ReactOS 0.4.16-dev-106-g10b08aa
devaction.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for devaction.c:

Go to the source code of this file.

Classes

struct  _DEVICE_ACTION_REQUEST
 
struct  _ADD_DEV_DRIVERS_LIST
 
struct  _ATTACH_FILTER_DRIVERS_CONTEXT
 

Macros

#define NDEBUG
 
#define MAX_DEVICE_ID_LEN   200
 
#define MAX_SEPARATORS_INSTANCEID   0
 
#define MAX_SEPARATORS_DEVICEID   1
 

Typedefs

typedef struct _DEVICE_ACTION_REQUEST DEVICE_ACTION_REQUEST
 
typedef struct _DEVICE_ACTION_REQUESTPDEVICE_ACTION_REQUEST
 
typedef enum _ADD_DEV_DRIVER_TYPE ADD_DEV_DRIVER_TYPE
 
typedef struct _ADD_DEV_DRIVERS_LIST ADD_DEV_DRIVERS_LIST
 
typedef struct _ADD_DEV_DRIVERS_LISTPADD_DEV_DRIVERS_LIST
 
typedef struct _ATTACH_FILTER_DRIVERS_CONTEXT ATTACH_FILTER_DRIVERS_CONTEXT
 
typedef struct _ATTACH_FILTER_DRIVERS_CONTEXTPATTACH_FILTER_DRIVERS_CONTEXT
 

Enumerations

enum  _ADD_DEV_DRIVER_TYPE {
  LowerFilter , LowerClassFilter , DeviceDriver , UpperFilter ,
  UpperClassFilter
}
 

Functions

PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance (PUNICODE_STRING DeviceInstance)
 
NTSTATUS IopGetParentIdPrefix (PDEVICE_NODE DeviceNode, PUNICODE_STRING ParentIdPrefix)
 
USHORT NTAPI IopGetBusTypeGuidIndex (LPGUID BusTypeGuid)
 
NTSTATUS IopSetDeviceInstanceData (HANDLE InstanceKey, PDEVICE_NODE DeviceNode)
 
VOID NTAPI IopInstallCriticalDevice (PDEVICE_NODE DeviceNode)
 
static VOID IopCancelPrepareDeviceForRemoval (PDEVICE_OBJECT DeviceObject)
 
static NTSTATUS IopPrepareDeviceForRemoval (PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
 
static NTSTATUS IopSetServiceEnumData (_In_ PDEVICE_NODE DeviceNode, _In_ HANDLE InstanceHandle)
 
static BOOLEAN IopValidateID (_In_ PWCHAR Id, _In_ BUS_QUERY_ID_TYPE QueryType)
 
static NTSTATUS IopCreateDeviceInstancePath (_In_ PDEVICE_NODE DeviceNode, _Out_ PUNICODE_STRING InstancePath)
 
static NTSTATUS NTAPI PiAttachFilterDriversCallback (PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Ctx, PVOID EntryContext)
 Loads and/or returns the driver associated with the registry entry if the driver is enabled. In case of an error, sets up a corresponding Problem to the DeviceNode.
 
static NTSTATUS PiAttachFilterDrivers (PLIST_ENTRY DriversListHead, PDEVICE_NODE DeviceNode, HANDLE EnumSubKey, HANDLE ClassKey, BOOLEAN Lower, BOOLEAN LoadDrivers)
 Calls PiAttachFilterDriversCallback for filter drivers (if any)
 
static NTSTATUS PiCallDriverAddDevice (_In_ PDEVICE_NODE DeviceNode, _In_ BOOLEAN LoadDrivers)
 Loads all drivers for a device node (actual service and filters) and calls their AddDevice routine.
 
NTSTATUS NTAPI IopQueryDeviceCapabilities (PDEVICE_NODE DeviceNode, PDEVICE_CAPABILITIES DeviceCaps)
 
static NTSTATUS IopQueryHardwareIds (PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
 
static NTSTATUS IopQueryCompatibleIds (PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
 
VOID PiSetDevNodeText (_In_ PDEVICE_NODE DeviceNode, _In_ HANDLE InstanceKey)
 Sets the DeviceNode's DeviceDesc and LocationInformation registry values.
 
static NTSTATUS PiInitializeDevNode (_In_ PDEVICE_NODE DeviceNode)
 
static NTSTATUS PiUpdateDeviceState (_In_ PDEVICE_NODE DeviceNode)
 Processes the IoInvalidateDeviceState request.
 
static NTSTATUS PiStartDeviceFinal (_In_ PDEVICE_NODE DeviceNode)
 
static NTSTATUS PiIrpSendRemoveCheckVpb (_In_ PDEVICE_OBJECT DeviceObject, _In_ UCHAR MinorFunction)
 Sends one of the remove IRPs to the device stack.
 
NTSTATUS IopUpdateResourceMapForPnPDevice (IN PDEVICE_NODE DeviceNode)
 
static VOID NTAPI IopSendRemoveDevice (IN PDEVICE_OBJECT DeviceObject)
 
static VOID IopSendRemoveDeviceRelations (PDEVICE_RELATIONS DeviceRelations)
 
static VOID IopSendRemoveChildDevices (PDEVICE_NODE ParentDeviceNode)
 
static VOID NTAPI IopSendSurpriseRemoval (IN PDEVICE_OBJECT DeviceObject)
 
static VOID NTAPI IopCancelRemoveDevice (IN PDEVICE_OBJECT DeviceObject)
 
static VOID IopCancelRemoveChildDevices (PDEVICE_NODE ParentDeviceNode)
 
static VOID IopCancelRemoveDeviceRelations (PDEVICE_RELATIONS DeviceRelations)
 
static NTSTATUS NTAPI IopQueryRemoveDevice (IN PDEVICE_OBJECT DeviceObject)
 
static NTSTATUS IopQueryRemoveChildDevices (PDEVICE_NODE ParentDeviceNode, BOOLEAN Force)
 
static NTSTATUS IopQueryRemoveDeviceRelations (PDEVICE_RELATIONS DeviceRelations, BOOLEAN Force)
 
static NTSTATUS IopPrepareDeviceForRemoval (IN PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
 
static NTSTATUS IopRemoveDevice (PDEVICE_NODE DeviceNode)
 
static NTSTATUS PiEnumerateDevice (_In_ PDEVICE_NODE DeviceNode)
 
static NTSTATUS NTAPI IopSendEject (IN PDEVICE_OBJECT DeviceObject)
 
VOID NTAPI IoRequestDeviceEject (IN PDEVICE_OBJECT PhysicalDeviceObject)
 
static VOID PiFakeResourceRebalance (_In_ PDEVICE_NODE DeviceNode)
 
static VOID PiDevNodeStateMachine (_In_ PDEVICE_NODE RootNode)
 
static VOID NTAPI PipDeviceActionWorker (_In_opt_ PVOID Context)
 
VOID PiQueueDeviceAction (_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action, _In_opt_ PKEVENT CompletionEvent, _Out_opt_ NTSTATUS *CompletionStatus)
 Queue a device operation to a worker thread.
 
NTSTATUS PiPerformSyncDeviceAction (_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action)
 Perfom a device operation synchronously via PiQueueDeviceAction.
 

Variables

ERESOURCE IopDriverLoadResource
 
BOOLEAN PnpSystemInit
 
PDEVICE_NODE IopRootDeviceNode
 
BOOLEAN PnPBootDriversLoaded
 
BOOLEAN PnPBootDriversInitialized
 
LIST_ENTRY IopDeviceActionRequestList
 
WORK_QUEUE_ITEM IopDeviceActionWorkItem
 
BOOLEAN IopDeviceActionInProgress
 
KSPIN_LOCK IopDeviceActionLock
 
KEVENT PiEnumerationFinished
 
static const WCHAR ServicesKeyName [] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
 

Macro Definition Documentation

◆ MAX_DEVICE_ID_LEN

#define MAX_DEVICE_ID_LEN   200

Definition at line 40 of file devaction.c.

◆ MAX_SEPARATORS_DEVICEID

#define MAX_SEPARATORS_DEVICEID   1

Definition at line 42 of file devaction.c.

◆ MAX_SEPARATORS_INSTANCEID

#define MAX_SEPARATORS_INSTANCEID   0

Definition at line 41 of file devaction.c.

◆ NDEBUG

#define NDEBUG

Definition at line 29 of file devaction.c.

Typedef Documentation

◆ ADD_DEV_DRIVER_TYPE

◆ ADD_DEV_DRIVERS_LIST

◆ ATTACH_FILTER_DRIVERS_CONTEXT

◆ DEVICE_ACTION_REQUEST

◆ PADD_DEV_DRIVERS_LIST

◆ PATTACH_FILTER_DRIVERS_CONTEXT

◆ PDEVICE_ACTION_REQUEST

Enumeration Type Documentation

◆ _ADD_DEV_DRIVER_TYPE

Enumerator
LowerFilter 
LowerClassFilter 
DeviceDriver 
UpperFilter 
UpperClassFilter 

Definition at line 64 of file devaction.c.

65{
@ UpperFilter
Definition: devaction.c:69
@ LowerFilter
Definition: devaction.c:66
@ LowerClassFilter
Definition: devaction.c:67
@ DeviceDriver
Definition: devaction.c:68
@ UpperClassFilter
Definition: devaction.c:70
enum _ADD_DEV_DRIVER_TYPE ADD_DEV_DRIVER_TYPE

Function Documentation

◆ IopCancelPrepareDeviceForRemoval()

static VOID IopCancelPrepareDeviceForRemoval ( PDEVICE_OBJECT  DeviceObject)
static

Definition at line 1844 of file devaction.c.

1845{
1848 PDEVICE_RELATIONS DeviceRelations;
1850
1852
1853 Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
1854
1858 &Stack);
1859 if (!NT_SUCCESS(Status))
1860 {
1861 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
1862 DeviceRelations = NULL;
1863 }
1864 else
1865 {
1866 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1867 }
1868
1869 if (DeviceRelations)
1870 IopCancelRemoveDeviceRelations(DeviceRelations);
1871}
LONG NTSTATUS
Definition: precomp.h:26
static VOID IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1826
static VOID NTAPI IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1793
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
Status
Definition: gdiplustypes.h:25
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
NTSTATUS NTAPI IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject, IN PIO_STATUS_BLOCK IoStatusBlock, IN UCHAR MinorFunction, IN PIO_STACK_LOCATION Stack)
#define DPRINT
Definition: sndvol32.h:73
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ PIO_STACK_LOCATION Stack
Definition: wdfrequest.h:639
@ RemovalRelations
Definition: iotypes.h:2155
struct _DEVICE_RELATIONS * PDEVICE_RELATIONS
#define IRP_MN_QUERY_DEVICE_RELATIONS

Referenced by IopCancelRemoveChildDevices(), IopCancelRemoveDeviceRelations(), IopQueryRemoveChildDevices(), and IopQueryRemoveDeviceRelations().

◆ IopCancelRemoveChildDevices()

static VOID IopCancelRemoveChildDevices ( PDEVICE_NODE  ParentDeviceNode)
static

Definition at line 1803 of file devaction.c.

1804{
1805 PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1806 KIRQL OldIrql;
1807
1809 ChildDeviceNode = ParentDeviceNode->Child;
1810 while (ChildDeviceNode != NULL)
1811 {
1812 NextDeviceNode = ChildDeviceNode->Sibling;
1814
1816
1817 ChildDeviceNode = NextDeviceNode;
1818
1820 }
1822}
static VOID IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1844
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
KSPIN_LOCK IopDeviceTreeLock
Definition: devnode.c:19
struct _DEVICE_NODE * Sibling
Definition: iotypes.h:989
struct _DEVICE_NODE * Child
Definition: iotypes.h:990
PDEVICE_OBJECT PhysicalDeviceObject
Definition: iotypes.h:1005
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:778

Referenced by IoRequestDeviceEject().

◆ IopCancelRemoveDevice()

static VOID NTAPI IopCancelRemoveDevice ( IN PDEVICE_OBJECT  DeviceObject)
static

Definition at line 1793 of file devaction.c.

1794{
1795 /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
1797
1798 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_CANCELLED, DeviceObject, NULL);
1799}
static NTSTATUS PiIrpSendRemoveCheckVpb(_In_ PDEVICE_OBJECT DeviceObject, _In_ UCHAR MinorFunction)
Sends one of the remove IRPs to the device stack.
Definition: devaction.c:1645
VOID PiNotifyTargetDeviceChange(_In_ LPCGUID Event, _In_ PDEVICE_OBJECT DeviceObject, _In_opt_ PTARGET_DEVICE_CUSTOM_NOTIFICATION CustomNotification)
Delivers the event to all drivers subscribed to EventCategoryTargetDeviceChange PnP event.
Definition: pnpnotify.c:258
#define IRP_MN_CANCEL_REMOVE_DEVICE

Referenced by IopCancelPrepareDeviceForRemoval(), and IopPrepareDeviceForRemoval().

◆ IopCancelRemoveDeviceRelations()

static VOID IopCancelRemoveDeviceRelations ( PDEVICE_RELATIONS  DeviceRelations)
static

Definition at line 1826 of file devaction.c.

1827{
1828 /* This function DOES dereference the device objects in all cases */
1829
1830 ULONG i;
1831
1832 for (i = 0; i < DeviceRelations->Count; i++)
1833 {
1834 IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1835 ObDereferenceObject(DeviceRelations->Objects[i]);
1836 DeviceRelations->Objects[i] = NULL;
1837 }
1838
1839 ExFreePool(DeviceRelations);
1840}
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2163
uint32_t ULONG
Definition: typedefs.h:59
#define ObDereferenceObject
Definition: obfuncs.h:203

Referenced by IopCancelPrepareDeviceForRemoval(), IopPrepareDeviceForRemoval(), and IoRequestDeviceEject().

◆ IopCreateDeviceInstancePath()

static NTSTATUS IopCreateDeviceInstancePath ( _In_ PDEVICE_NODE  DeviceNode,
_Out_ PUNICODE_STRING  InstancePath 
)
static

Definition at line 213 of file devaction.c.

216{
218 UNICODE_STRING DeviceId;
222 UNICODE_STRING ParentIdPrefix = { 0, 0, NULL };
224 BOOLEAN IsValidID;
225
226 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
227
228 Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
229 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
232 &Stack);
233 if (!NT_SUCCESS(Status))
234 {
235 DPRINT1("IopInitiatePnpIrp(BusQueryDeviceID) failed (Status %x)\n", Status);
236 return Status;
237 }
238
240
241 if (!IsValidID)
242 {
243 DPRINT1("Invalid DeviceID. DeviceNode - %p\n", DeviceNode);
244 }
245
246 /* Save the device id string */
248
249 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
250
252 if (!NT_SUCCESS(Status))
253 {
255 {
256 DPRINT1("IopQueryDeviceCapabilities() failed (Status 0x%08lx)\n", Status);
257 }
258 RtlFreeUnicodeString(&DeviceId);
259 return Status;
260 }
261
262 /* This bit is only check after enumeration */
263 if (DeviceCapabilities.HardwareDisabled)
264 {
265 /* FIXME: Cleanup device */
266 RtlFreeUnicodeString(&DeviceId);
268 }
269
270 if (!DeviceCapabilities.UniqueID)
271 {
272 /* Device has not a unique ID. We need to prepend parent bus unique identifier */
273 DPRINT("Instance ID is not unique\n");
274 Status = IopGetParentIdPrefix(DeviceNode, &ParentIdPrefix);
275 if (!NT_SUCCESS(Status))
276 {
277 DPRINT1("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status);
278 RtlFreeUnicodeString(&DeviceId);
279 return Status;
280 }
281 }
282
283 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
284
285 Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
286 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
289 &Stack);
290 if (!NT_SUCCESS(Status))
291 {
292 DPRINT("IopInitiatePnpIrp(BusQueryInstanceID) failed (Status %lx)\n", Status);
294 }
295
297 {
299
300 if (!IsValidID)
301 {
302 DPRINT1("Invalid InstanceID. DeviceNode - %p\n", DeviceNode);
303 }
304 }
305
308
309 InstancePath->Length = 0;
310 InstancePath->MaximumLength = DeviceId.Length + sizeof(WCHAR) +
311 ParentIdPrefix.Length +
312 InstanceId.Length +
313 sizeof(UNICODE_NULL);
314 if (ParentIdPrefix.Length && InstanceId.Length)
315 {
316 InstancePath->MaximumLength += sizeof(WCHAR);
317 }
318
319 InstancePath->Buffer = ExAllocatePoolWithTag(PagedPool,
320 InstancePath->MaximumLength,
321 TAG_IO);
322 if (!InstancePath->Buffer)
323 {
325 RtlFreeUnicodeString(&ParentIdPrefix);
326 RtlFreeUnicodeString(&DeviceId);
328 }
329
330 /* Start with the device id */
331 RtlCopyUnicodeString(InstancePath, &DeviceId);
332 RtlAppendUnicodeToString(InstancePath, L"\\");
333
334 /* Add information from parent bus device to InstancePath */
335 RtlAppendUnicodeStringToString(InstancePath, &ParentIdPrefix);
336 if (ParentIdPrefix.Length && InstanceId.Length)
337 {
338 RtlAppendUnicodeToString(InstancePath, L"&");
339 }
340
341 /* Finally, add the id returned by the driver stack */
343
344 /*
345 * FIXME: Check for valid characters, if there is invalid characters
346 * then bugcheck
347 */
348
350 RtlFreeUnicodeString(&DeviceId);
351 RtlFreeUnicodeString(&ParentIdPrefix);
352
353 return STATUS_SUCCESS;
354}
@ DeviceNode
Definition: Node.h:9
unsigned char BOOLEAN
#define DPRINT1
Definition: precomp.h:8
NTSTATUS IopGetParentIdPrefix(PDEVICE_NODE DeviceNode, PUNICODE_STRING ParentIdPrefix)
Definition: pnpmgr.c:760
NTSTATUS NTAPI IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, PDEVICE_CAPABILITIES DeviceCaps)
Definition: devaction.c:854
static BOOLEAN IopValidateID(_In_ PWCHAR Id, _In_ BUS_QUERY_ID_TYPE QueryType)
Definition: devaction.c:122
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define PagedPool
Definition: env_spec_w32.h:308
_Must_inspect_result_ _In_opt_ PVOID _In_opt_ PVOID InstanceId
Definition: fsrtlfuncs.h:908
#define ASSERT(a)
Definition: mode.c:44
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define UNICODE_NULL
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
#define STATUS_PLUGPLAY_NO_DEVICE
Definition: ntstatus.h:731
#define L(x)
Definition: ntvdm.h:50
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TAG_IO
Definition: tag.h:80
uint16_t * PWSTR
Definition: typedefs.h:56
uint16_t * PWCHAR
Definition: typedefs.h:56
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define DeviceCapabilities
Definition: wingdi.h:4449
DEVICE_CAPABILITIES
Definition: iotypes.h:965
#define IRP_MN_QUERY_ID
@ BusQueryInstanceID
Definition: iotypes.h:2939
@ BusQueryDeviceID
Definition: iotypes.h:2936
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by PiInitializeDevNode().

◆ IopGetBusTypeGuidIndex()

USHORT NTAPI IopGetBusTypeGuidIndex ( LPGUID  BusTypeGuid)

Definition at line 411 of file pnpmgr.c.

412{
413 USHORT i = 0, FoundIndex = 0xFFFF;
415 PVOID NewList;
416
417 /* Acquire the lock */
419
420 /* Loop all entries */
421 while (i < PnpBusTypeGuidList->GuidCount)
422 {
423 /* Try to find a match */
424 if (RtlCompareMemory(BusTypeGuid,
426 sizeof(GUID)) == sizeof(GUID))
427 {
428 /* Found it */
429 FoundIndex = i;
430 goto Quickie;
431 }
432 i++;
433 }
434
435 /* Check if we have to grow the list */
437 {
438 /* Calculate the new size */
440 (sizeof(GUID) * PnpBusTypeGuidList->GuidCount);
441
442 /* Allocate the new copy */
443 NewList = ExAllocatePool(PagedPool, NewSize);
444
445 if (!NewList)
446 {
447 /* Fail */
449 goto Quickie;
450 }
451
452 /* Now copy them, decrease the size too */
453 NewSize -= sizeof(GUID);
455
456 /* Free the old list */
458
459 /* Use the new buffer */
460 PnpBusTypeGuidList = NewList;
461 }
462
463 /* Copy the new GUID */
465 BusTypeGuid,
466 sizeof(GUID));
467
468 /* The new entry is the index */
469 FoundIndex = (USHORT)PnpBusTypeGuidList->GuidCount;
471
472Quickie:
474 return FoundIndex;
475}
#define RtlCompareMemory(s1, s2, l)
Definition: env_spec_w32.h:465
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
_Must_inspect_result_ _In_ USHORT NewSize
Definition: fltkernel.h:975
VOID FASTCALL ExAcquireFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:23
VOID FASTCALL ExReleaseFastMutex(IN PFAST_MUTEX FastMutex)
Definition: fmutex.c:31
struct _IO_BUS_TYPE_GUID_LIST IO_BUS_TYPE_GUID_LIST
unsigned short USHORT
Definition: pedump.c:61
PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList
Definition: pnpmgr.c:27
GUID Guids[1]
Definition: io.h:420
FAST_MUTEX Lock
Definition: io.h:419
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263

Referenced by PiInitializeDevNode().

◆ IopGetDeviceObjectFromDeviceInstance()

PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance ( PUNICODE_STRING  DeviceInstance)

Definition at line 206 of file plugplay.c.

207{
209 IOP_FIND_DEVICE_INSTANCE_TRAVERSE_CONTEXT DeviceInstanceContext;
210
211 if (IopRootDeviceNode == NULL)
212 return NULL;
213
214 if (DeviceInstance == NULL ||
215 DeviceInstance->Length == 0)
216 {
218 {
221 }
222 else
223 return NULL;
224 }
225
226 /* Traverse the device tree to find the matching device node */
227 DeviceInstanceContext.InstancePath = DeviceInstance;
228 DeviceInstanceContext.DeviceObject = NULL;
232 &DeviceInstanceContext);
234
235 /* In case of error or instance not found, this will still be NULL from above. */
236 return DeviceInstanceContext.DeviceObject;
237}
static const WCHAR DeviceInstance[]
Definition: interface.c:28
#define IopInitDeviceTreeTraverseContext( _DeviceTreeTraverseContext, _DeviceNode, _Action, _Context)
Definition: io.h:229
NTSTATUS IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context)
PDEVICE_NODE IopRootDeviceNode
Definition: devnode.c:18
NTSTATUS IopFindDeviceInstanceTraverse(_In_ PDEVICE_NODE DeviceNode, _Inout_ PVOID Context)
Definition: plugplay.c:186
#define ObReferenceObject
Definition: obfuncs.h:204

Referenced by IopDeviceStatus(), IopGetDeviceDepth(), IopGetDeviceProperty(), IopGetDeviceRelations(), IopGetInterfaceDeviceList(), IopGetRelatedDevice(), PiControlInitializeDevice(), PiControlQueryRemoveDevice(), PiControlSyncDeviceAction(), and PiInitializeDevNode().

◆ IopGetParentIdPrefix()

NTSTATUS IopGetParentIdPrefix ( PDEVICE_NODE  DeviceNode,
PUNICODE_STRING  ParentIdPrefix 
)

Definition at line 760 of file pnpmgr.c.

762{
763 const UNICODE_STRING EnumKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
764 ULONG KeyNameBufferLength;
765 PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL;
766 UNICODE_STRING KeyName = {0, 0, NULL};
767 UNICODE_STRING KeyValue;
769 HANDLE hKey = NULL;
770 ULONG crc32;
772
773 /* HACK: As long as some devices have a NULL device
774 * instance path, the following test is required :(
775 */
776 if (DeviceNode->Parent->InstancePath.Length == 0)
777 {
778 DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
779 &DeviceNode->InstancePath);
780 return STATUS_UNSUCCESSFUL;
781 }
782
783 /* 1. Try to retrieve ParentIdPrefix from registry */
784 KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + sizeof(L"12345678&12345678");
785 ParentIdPrefixInformation = ExAllocatePoolWithTag(PagedPool,
786 KeyNameBufferLength + sizeof(UNICODE_NULL),
787 TAG_IO);
788 if (!ParentIdPrefixInformation)
789 {
791 }
792
793 KeyName.Length = 0;
794 KeyName.MaximumLength = EnumKeyPath.Length +
795 DeviceNode->Parent->InstancePath.Length +
796 sizeof(UNICODE_NULL);
798 KeyName.MaximumLength,
799 TAG_IO);
800 if (!KeyName.Buffer)
801 {
803 goto cleanup;
804 }
805
806 RtlCopyUnicodeString(&KeyName, &EnumKeyPath);
807 RtlAppendUnicodeStringToString(&KeyName, &DeviceNode->Parent->InstancePath);
808
810 if (!NT_SUCCESS(Status))
811 {
812 goto cleanup;
813 }
814 RtlInitUnicodeString(&ValueName, L"ParentIdPrefix");
815 Status = ZwQueryValueKey(hKey,
816 &ValueName,
818 ParentIdPrefixInformation,
819 KeyNameBufferLength,
820 &KeyNameBufferLength);
821 if (NT_SUCCESS(Status))
822 {
823 if (ParentIdPrefixInformation->Type != REG_SZ)
824 {
826 }
827 else
828 {
829 KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
830 KeyValue.Length = KeyValue.MaximumLength - sizeof(UNICODE_NULL);
831 KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
832 ASSERT(KeyValue.Buffer[KeyValue.Length / sizeof(WCHAR)] == UNICODE_NULL);
833 }
834 goto cleanup;
835 }
837 {
838 /* FIXME how do we get here and why is ParentIdPrefixInformation valid? */
839 KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
840 KeyValue.Length = KeyValue.MaximumLength - sizeof(UNICODE_NULL);
841 KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
842 ASSERT(KeyValue.Buffer[KeyValue.Length / sizeof(WCHAR)] == UNICODE_NULL);
843 goto cleanup;
844 }
845
846 /* 2. Create the ParentIdPrefix value */
848 (PUCHAR)DeviceNode->Parent->InstancePath.Buffer,
849 DeviceNode->Parent->InstancePath.Length);
850
851 RtlStringCbPrintfW((PWSTR)ParentIdPrefixInformation,
852 KeyNameBufferLength,
853 L"%lx&%lx",
854 DeviceNode->Parent->Level,
855 crc32);
856 RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation);
857
858 /* 3. Try to write the ParentIdPrefix to registry */
859 Status = ZwSetValueKey(hKey,
860 &ValueName,
861 0,
862 REG_SZ,
863 KeyValue.Buffer,
864 ((ULONG)wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR));
865
866cleanup:
867 if (NT_SUCCESS(Status))
868 {
869 /* Duplicate the string to return it */
871 &KeyValue,
872 ParentIdPrefix);
873 }
874 ExFreePoolWithTag(ParentIdPrefixInformation, TAG_IO);
876 if (hKey != NULL)
877 {
878 ZwClose(hKey);
879 }
880 return Status;
881}
#define RtlComputeCrc32
Definition: compat.h:810
#define crc32(crc, buf, len)
Definition: inflate.c:1081
static void cleanup(void)
Definition: main.c:1335
FxAutoRegKey hKey
#define RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE
Definition: green.h:15
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
NTSYSAPI NTSTATUS WINAPI RtlDuplicateUnicodeString(int, const UNICODE_STRING *, UNICODE_STRING *)
#define REG_SZ
Definition: layer.c:22
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
@ KeyValuePartialInformation
Definition: nt_native.h:1182
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define KEY_SET_VALUE
Definition: nt_native.h:1017
NTSTRSAFEVAPI RtlStringCbPrintfW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1173
NTSTATUS NTAPI IopOpenRegistryKeyEx(PHANDLE KeyHandle, HANDLE ParentKey, PUNICODE_STRING Name, ACCESS_MASK DesiredAccess)
Definition: pnpmgr.c:885
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PUCHAR
Definition: typedefs.h:53
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243

Referenced by IopCreateDeviceInstancePath().

◆ IopInstallCriticalDevice()

VOID NTAPI IopInstallCriticalDevice ( PDEVICE_NODE  DeviceNode)

Definition at line 45 of file pnpmgr.c.

46{
48 HANDLE CriticalDeviceKey, InstanceKey;
50 UNICODE_STRING CriticalDeviceKeyU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\CriticalDeviceDatabase");
51 UNICODE_STRING CompatibleIdU = RTL_CONSTANT_STRING(L"CompatibleIDs");
52 UNICODE_STRING HardwareIdU = RTL_CONSTANT_STRING(L"HardwareID");
53 UNICODE_STRING ServiceU = RTL_CONSTANT_STRING(L"Service");
54 UNICODE_STRING ClassGuidU = RTL_CONSTANT_STRING(L"ClassGUID");
56 ULONG HidLength = 0, CidLength = 0, BufferLength;
57 PWCHAR IdBuffer, OriginalIdBuffer;
58
59 /* Open the device instance key */
60 Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
62 return;
63
64 Status = ZwQueryValueKey(InstanceKey,
65 &HardwareIdU,
67 NULL,
68 0,
69 &HidLength);
71 {
72 ZwClose(InstanceKey);
73 return;
74 }
75
76 Status = ZwQueryValueKey(InstanceKey,
77 &CompatibleIdU,
79 NULL,
80 0,
81 &CidLength);
83 {
84 CidLength = 0;
85 }
86
87 BufferLength = HidLength + CidLength;
88 BufferLength -= (((CidLength != 0) ? 2 : 1) * FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data));
89
90 /* Allocate a buffer to hold data from both */
91 OriginalIdBuffer = IdBuffer = ExAllocatePool(PagedPool, BufferLength);
92 if (!IdBuffer)
93 {
94 ZwClose(InstanceKey);
95 return;
96 }
97
98 /* Compute the buffer size */
99 if (HidLength > CidLength)
100 BufferLength = HidLength;
101 else
102 BufferLength = CidLength;
103
104 PartialInfo = ExAllocatePool(PagedPool, BufferLength);
105 if (!PartialInfo)
106 {
107 ZwClose(InstanceKey);
108 ExFreePool(OriginalIdBuffer);
109 return;
110 }
111
112 Status = ZwQueryValueKey(InstanceKey,
113 &HardwareIdU,
115 PartialInfo,
116 HidLength,
117 &HidLength);
118 if (Status != STATUS_SUCCESS)
119 {
120 ExFreePool(PartialInfo);
121 ExFreePool(OriginalIdBuffer);
122 ZwClose(InstanceKey);
123 return;
124 }
125
126 /* Copy in HID info first (without 2nd terminating NULL if CID is present) */
127 HidLength = PartialInfo->DataLength - ((CidLength != 0) ? sizeof(WCHAR) : 0);
128 RtlCopyMemory(IdBuffer, PartialInfo->Data, HidLength);
129
130 if (CidLength != 0)
131 {
132 Status = ZwQueryValueKey(InstanceKey,
133 &CompatibleIdU,
135 PartialInfo,
136 CidLength,
137 &CidLength);
138 if (Status != STATUS_SUCCESS)
139 {
140 ExFreePool(PartialInfo);
141 ExFreePool(OriginalIdBuffer);
142 ZwClose(InstanceKey);
143 return;
144 }
145
146 /* Copy CID next */
147 CidLength = PartialInfo->DataLength;
148 RtlCopyMemory(((PUCHAR)IdBuffer) + HidLength, PartialInfo->Data, CidLength);
149 }
150
151 /* Free our temp buffer */
152 ExFreePool(PartialInfo);
153
155 &CriticalDeviceKeyU,
157 NULL,
158 NULL);
159 Status = ZwOpenKey(&CriticalDeviceKey,
162 if (!NT_SUCCESS(Status))
163 {
164 /* The critical device database doesn't exist because
165 * we're probably in 1st stage setup, but it's ok */
166 ExFreePool(OriginalIdBuffer);
167 ZwClose(InstanceKey);
168 return;
169 }
170
171 while (*IdBuffer)
172 {
173 USHORT StringLength = (USHORT)wcslen(IdBuffer) + 1, Index;
174
175 IopFixupDeviceId(IdBuffer);
176
177 /* Look through all subkeys for a match */
178 for (Index = 0; TRUE; Index++)
179 {
180 ULONG NeededLength;
181 PKEY_BASIC_INFORMATION BasicInfo;
182
183 Status = ZwEnumerateKey(CriticalDeviceKey,
184 Index,
186 NULL,
187 0,
188 &NeededLength);
190 break;
192 {
193 UNICODE_STRING ChildIdNameU, RegKeyNameU;
194
195 BasicInfo = ExAllocatePool(PagedPool, NeededLength);
196 if (!BasicInfo)
197 {
198 /* No memory */
199 ExFreePool(OriginalIdBuffer);
200 ZwClose(CriticalDeviceKey);
201 ZwClose(InstanceKey);
202 return;
203 }
204
205 Status = ZwEnumerateKey(CriticalDeviceKey,
206 Index,
208 BasicInfo,
209 NeededLength,
210 &NeededLength);
211 if (Status != STATUS_SUCCESS)
212 {
213 /* This shouldn't happen */
214 ExFreePool(BasicInfo);
215 continue;
216 }
217
218 ChildIdNameU.Buffer = IdBuffer;
219 ChildIdNameU.MaximumLength = ChildIdNameU.Length = (StringLength - 1) * sizeof(WCHAR);
220 RegKeyNameU.Buffer = BasicInfo->Name;
221 RegKeyNameU.MaximumLength = RegKeyNameU.Length = (USHORT)BasicInfo->NameLength;
222
223 if (RtlEqualUnicodeString(&ChildIdNameU, &RegKeyNameU, TRUE))
224 {
225 HANDLE ChildKeyHandle;
226
228 &ChildIdNameU,
230 CriticalDeviceKey,
231 NULL);
232
233 Status = ZwOpenKey(&ChildKeyHandle,
236 if (Status != STATUS_SUCCESS)
237 {
238 ExFreePool(BasicInfo);
239 continue;
240 }
241
242 /* Check if there's already a driver installed */
243 Status = ZwQueryValueKey(InstanceKey,
244 &ClassGuidU,
246 NULL,
247 0,
248 &NeededLength);
250 {
251 ExFreePool(BasicInfo);
252 continue;
253 }
254
255 Status = ZwQueryValueKey(ChildKeyHandle,
256 &ClassGuidU,
258 NULL,
259 0,
260 &NeededLength);
262 {
263 ExFreePool(BasicInfo);
264 continue;
265 }
266
267 PartialInfo = ExAllocatePool(PagedPool, NeededLength);
268 if (!PartialInfo)
269 {
270 ExFreePool(OriginalIdBuffer);
271 ExFreePool(BasicInfo);
272 ZwClose(InstanceKey);
273 ZwClose(ChildKeyHandle);
274 ZwClose(CriticalDeviceKey);
275 return;
276 }
277
278 /* Read ClassGUID entry in the CDDB */
279 Status = ZwQueryValueKey(ChildKeyHandle,
280 &ClassGuidU,
282 PartialInfo,
283 NeededLength,
284 &NeededLength);
285 if (Status != STATUS_SUCCESS)
286 {
287 ExFreePool(BasicInfo);
288 continue;
289 }
290
291 /* Write it to the ENUM key */
292 Status = ZwSetValueKey(InstanceKey,
293 &ClassGuidU,
294 0,
295 REG_SZ,
296 PartialInfo->Data,
297 PartialInfo->DataLength);
298 if (Status != STATUS_SUCCESS)
299 {
300 ExFreePool(BasicInfo);
301 ExFreePool(PartialInfo);
302 ZwClose(ChildKeyHandle);
303 continue;
304 }
305
306 Status = ZwQueryValueKey(ChildKeyHandle,
307 &ServiceU,
309 NULL,
310 0,
311 &NeededLength);
313 {
314 ExFreePool(PartialInfo);
315 PartialInfo = ExAllocatePool(PagedPool, NeededLength);
316 if (!PartialInfo)
317 {
318 ExFreePool(OriginalIdBuffer);
319 ExFreePool(BasicInfo);
320 ZwClose(InstanceKey);
321 ZwClose(ChildKeyHandle);
322 ZwClose(CriticalDeviceKey);
323 return;
324 }
325
326 /* Read the service entry from the CDDB */
327 Status = ZwQueryValueKey(ChildKeyHandle,
328 &ServiceU,
330 PartialInfo,
331 NeededLength,
332 &NeededLength);
333 if (Status != STATUS_SUCCESS)
334 {
335 ExFreePool(BasicInfo);
336 ExFreePool(PartialInfo);
337 ZwClose(ChildKeyHandle);
338 continue;
339 }
340
341 /* Write it to the ENUM key */
342 Status = ZwSetValueKey(InstanceKey,
343 &ServiceU,
344 0,
345 REG_SZ,
346 PartialInfo->Data,
347 PartialInfo->DataLength);
348 if (Status != STATUS_SUCCESS)
349 {
350 ExFreePool(BasicInfo);
351 ExFreePool(PartialInfo);
352 ZwClose(ChildKeyHandle);
353 continue;
354 }
355
356 DPRINT("Installed service '%S' for critical device '%wZ'\n", PartialInfo->Data, &ChildIdNameU);
357 }
358 else
359 {
360 DPRINT1("Installed NULL service for critical device '%wZ'\n", &ChildIdNameU);
361 }
362
363 ExFreePool(OriginalIdBuffer);
364 ExFreePool(PartialInfo);
365 ExFreePool(BasicInfo);
366 ZwClose(InstanceKey);
367 ZwClose(ChildKeyHandle);
368 ZwClose(CriticalDeviceKey);
369
370 /* That's it */
371 return;
372 }
373
374 ExFreePool(BasicInfo);
375 }
376 else
377 {
378 /* Umm, not sure what happened here */
379 continue;
380 }
381 }
382
383 /* Advance to the next ID */
384 IdBuffer += StringLength;
385 }
386
387 ExFreePool(OriginalIdBuffer);
388 ZwClose(InstanceKey);
389 ZwClose(CriticalDeviceKey);
390}
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define TRUE
Definition: types.h:120
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
if(dx< 0)
Definition: linetemp.h:194
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
@ KeyBasicInformation
Definition: nt_native.h:1131
NTSYSAPI BOOLEAN NTAPI RtlEqualUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive)
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
NTSTATUS NTAPI IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, IN ULONG CreateOptions, OUT PHANDLE Handle)
Definition: pnpmgr.c:522
VOID IopFixupDeviceId(PWCHAR String)
Definition: pnpmgr.c:32
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771

Referenced by PiInitializeDevNode().

◆ IopPrepareDeviceForRemoval() [1/2]

static NTSTATUS IopPrepareDeviceForRemoval ( IN PDEVICE_OBJECT  DeviceObject,
BOOLEAN  Force 
)
static

Definition at line 1997 of file devaction.c.

1998{
2002 PDEVICE_RELATIONS DeviceRelations;
2004
2005 if ((DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE) && !Force)
2006 {
2007 DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath);
2008 return STATUS_UNSUCCESSFUL;
2009 }
2010
2012 {
2013 DPRINT1("Removal vetoed by failing the query remove request\n");
2014
2016
2017 return STATUS_UNSUCCESSFUL;
2018 }
2019
2020 Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
2021
2025 &Stack);
2026 if (!NT_SUCCESS(Status))
2027 {
2028 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2029 DeviceRelations = NULL;
2030 }
2031 else
2032 {
2033 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2034 }
2035
2036 if (DeviceRelations)
2037 {
2038 Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
2039 if (!NT_SUCCESS(Status))
2040 return Status;
2041 }
2042
2044 if (!NT_SUCCESS(Status))
2045 {
2046 if (DeviceRelations)
2047 IopCancelRemoveDeviceRelations(DeviceRelations);
2048 return Status;
2049 }
2050
2051 if (DeviceRelations)
2052 IopSendRemoveDeviceRelations(DeviceRelations);
2054
2055 return STATUS_SUCCESS;
2056}
_Inout_ PVCB _In_ BOOLEAN Force
Definition: cdprocs.h:1417
static NTSTATUS IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations, BOOLEAN Force)
Definition: devaction.c:1956
static VOID IopSendRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
Definition: devaction.c:1759
static VOID IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1742
static NTSTATUS NTAPI IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1876
static NTSTATUS IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode, BOOLEAN Force)
Definition: devaction.c:1902
#define DNUF_NOT_DISABLEABLE
Definition: iotypes.h:211
PDEVICE_NODE FASTCALL IopGetDeviceNode(IN PDEVICE_OBJECT DeviceObject)

◆ IopPrepareDeviceForRemoval() [2/2]

static NTSTATUS IopPrepareDeviceForRemoval ( PDEVICE_OBJECT  DeviceObject,
BOOLEAN  Force 
)
static

◆ IopQueryCompatibleIds()

static NTSTATUS IopQueryCompatibleIds ( PDEVICE_NODE  DeviceNode,
HANDLE  InstanceKey 
)
static

Definition at line 1022 of file devaction.c.

1024{
1027 PWSTR Ptr;
1031 BOOLEAN IsValidID;
1032
1033 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1034
1035 RtlZeroMemory(&Stack, sizeof(Stack));
1036 Stack.Parameters.QueryId.IdType = BusQueryCompatibleIDs;
1037 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1040 &Stack);
1042 {
1044
1045 if (!IsValidID)
1046 {
1047 DPRINT1("Invalid CompatibleIDs. DeviceNode - %p\n", DeviceNode);
1048 }
1049
1050 TotalLength = 0;
1051
1053 DPRINT("Compatible IDs:\n");
1054 while (*Ptr)
1055 {
1056 DPRINT(" %S\n", Ptr);
1057 Length = (ULONG)wcslen(Ptr) + 1;
1058
1059 Ptr += Length;
1061 }
1062 DPRINT("TotalLength: %hu\n", TotalLength);
1063 DPRINT("\n");
1064
1065 RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
1066 Status = ZwSetValueKey(InstanceKey,
1067 &ValueName,
1068 0,
1071 (TotalLength + 1) * sizeof(WCHAR));
1072 if (!NT_SUCCESS(Status))
1073 {
1074 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status);
1075 }
1076 }
1077 else
1078 {
1079 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1080 }
1081
1082 return Status;
1083}
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
#define REG_MULTI_SZ
Definition: nt_native.h:1501
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
_In_ ULONG TotalLength
Definition: usbdlib.h:158
@ BusQueryCompatibleIDs
Definition: iotypes.h:2938

Referenced by PiInitializeDevNode(), and PiStartDeviceFinal().

◆ IopQueryDeviceCapabilities()

NTSTATUS NTAPI IopQueryDeviceCapabilities ( PDEVICE_NODE  DeviceNode,
PDEVICE_CAPABILITIES  DeviceCaps 
)

Definition at line 854 of file devaction.c.

856{
857 IO_STATUS_BLOCK StatusBlock;
860 HANDLE InstanceKey;
862
863 /* Set up the Header */
864 RtlZeroMemory(DeviceCaps, sizeof(DEVICE_CAPABILITIES));
865 DeviceCaps->Size = sizeof(DEVICE_CAPABILITIES);
866 DeviceCaps->Version = 1;
867 DeviceCaps->Address = -1;
868 DeviceCaps->UINumber = -1;
869
870 /* Set up the Stack */
872 Stack.Parameters.DeviceCapabilities.Capabilities = DeviceCaps;
873
874 /* Send the IRP */
875 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
876 &StatusBlock,
878 &Stack);
879 if (!NT_SUCCESS(Status))
880 {
882 {
883 DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%lx\n", Status);
884 }
885 return Status;
886 }
887
888 /* Map device capabilities to capability flags */
889 DeviceNode->CapabilityFlags = 0;
890 if (DeviceCaps->LockSupported)
891 DeviceNode->CapabilityFlags |= 0x00000001; // CM_DEVCAP_LOCKSUPPORTED
892
893 if (DeviceCaps->EjectSupported)
894 DeviceNode->CapabilityFlags |= 0x00000002; // CM_DEVCAP_EJECTSUPPORTED
895
896 if (DeviceCaps->Removable)
897 DeviceNode->CapabilityFlags |= 0x00000004; // CM_DEVCAP_REMOVABLE
898
899 if (DeviceCaps->DockDevice)
900 DeviceNode->CapabilityFlags |= 0x00000008; // CM_DEVCAP_DOCKDEVICE
901
902 if (DeviceCaps->UniqueID)
903 DeviceNode->CapabilityFlags |= 0x00000010; // CM_DEVCAP_UNIQUEID
904
905 if (DeviceCaps->SilentInstall)
906 DeviceNode->CapabilityFlags |= 0x00000020; // CM_DEVCAP_SILENTINSTALL
907
908 if (DeviceCaps->RawDeviceOK)
909 DeviceNode->CapabilityFlags |= 0x00000040; // CM_DEVCAP_RAWDEVICEOK
910
911 if (DeviceCaps->SurpriseRemovalOK)
912 DeviceNode->CapabilityFlags |= 0x00000080; // CM_DEVCAP_SURPRISEREMOVALOK
913
914 if (DeviceCaps->HardwareDisabled)
915 DeviceNode->CapabilityFlags |= 0x00000100; // CM_DEVCAP_HARDWAREDISABLED
916
917 if (DeviceCaps->NonDynamic)
918 DeviceNode->CapabilityFlags |= 0x00000200; // CM_DEVCAP_NONDYNAMIC
919
920 if (DeviceCaps->NoDisplayInUI)
921 DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
922 else
923 DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
924
925 Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
926 if (NT_SUCCESS(Status))
927 {
928 /* Set 'Capabilities' value */
929 RtlInitUnicodeString(&ValueName, L"Capabilities");
930 Status = ZwSetValueKey(InstanceKey,
931 &ValueName,
932 0,
933 REG_DWORD,
934 &DeviceNode->CapabilityFlags,
935 sizeof(ULONG));
936
937 /* Set 'UINumber' value */
938 if (DeviceCaps->UINumber != MAXULONG)
939 {
940 RtlInitUnicodeString(&ValueName, L"UINumber");
941 Status = ZwSetValueKey(InstanceKey,
942 &ValueName,
943 0,
944 REG_DWORD,
945 &DeviceCaps->UINumber,
946 sizeof(ULONG));
947 }
948
949 ZwClose(InstanceKey);
950 }
951
952 return Status;
953}
#define DNUF_DONT_SHOW_IN_UI
Definition: iotypes.h:209
NTSTATUS NTAPI IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, IN ULONG CreateOptions, OUT PHANDLE Handle)
Definition: pnpmgr.c:522
#define REG_DWORD
Definition: sdbapi.c:596
#define MAXULONG
Definition: typedefs.h:251
#define IRP_MN_QUERY_CAPABILITIES

Referenced by IoGetDeviceProperty(), IopCreateDeviceInstancePath(), IoRequestDeviceEject(), and PiStartDeviceFinal().

◆ IopQueryHardwareIds()

static NTSTATUS IopQueryHardwareIds ( PDEVICE_NODE  DeviceNode,
HANDLE  InstanceKey 
)
static

Definition at line 957 of file devaction.c.

959{
962 PWSTR Ptr;
966 BOOLEAN IsValidID;
967
968 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
969
970 RtlZeroMemory(&Stack, sizeof(Stack));
971 Stack.Parameters.QueryId.IdType = BusQueryHardwareIDs;
972 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
975 &Stack);
976 if (NT_SUCCESS(Status))
977 {
979
980 if (!IsValidID)
981 {
982 DPRINT1("Invalid HardwareIDs. DeviceNode - %p\n", DeviceNode);
983 }
984
985 TotalLength = 0;
986
988 DPRINT("Hardware IDs:\n");
989 while (*Ptr)
990 {
991 DPRINT(" %S\n", Ptr);
992 Length = (ULONG)wcslen(Ptr) + 1;
993
994 Ptr += Length;
996 }
997 DPRINT("TotalLength: %hu\n", TotalLength);
998 DPRINT("\n");
999
1000 RtlInitUnicodeString(&ValueName, L"HardwareID");
1001 Status = ZwSetValueKey(InstanceKey,
1002 &ValueName,
1003 0,
1006 (TotalLength + 1) * sizeof(WCHAR));
1007 if (!NT_SUCCESS(Status))
1008 {
1009 DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
1010 }
1011 }
1012 else
1013 {
1014 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1015 }
1016
1017 return Status;
1018}
@ BusQueryHardwareIDs
Definition: iotypes.h:2937

Referenced by PiInitializeDevNode(), and PiStartDeviceFinal().

◆ IopQueryRemoveChildDevices()

static NTSTATUS IopQueryRemoveChildDevices ( PDEVICE_NODE  ParentDeviceNode,
BOOLEAN  Force 
)
static

Definition at line 1902 of file devaction.c.

1903{
1904 PDEVICE_NODE ChildDeviceNode, NextDeviceNode, FailedRemoveDevice;
1906 KIRQL OldIrql;
1907
1909 ChildDeviceNode = ParentDeviceNode->Child;
1910 while (ChildDeviceNode != NULL)
1911 {
1912 NextDeviceNode = ChildDeviceNode->Sibling;
1915
1917 if (!NT_SUCCESS(Status))
1918 {
1919 FailedRemoveDevice = ChildDeviceNode;
1920 goto cleanup;
1921 }
1922
1924 ChildDeviceNode = NextDeviceNode;
1925 }
1927
1928 return STATUS_SUCCESS;
1929
1930cleanup:
1932 ChildDeviceNode = ParentDeviceNode->Child;
1933 while (ChildDeviceNode != NULL)
1934 {
1935 NextDeviceNode = ChildDeviceNode->Sibling;
1937
1939
1940 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1941 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1942 if (ChildDeviceNode == FailedRemoveDevice)
1943 return Status;
1944
1945 ChildDeviceNode = NextDeviceNode;
1946
1948 }
1950
1951 return Status;
1952}
static NTSTATUS IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
@ DeviceNodeAwaitingQueuedRemoval
Definition: iotypes.h:549
PNP_DEVNODE_STATE PiSetDevNodeState(_In_ PDEVICE_NODE DeviceNode, _In_ PNP_DEVNODE_STATE NewState)
Definition: devnode.c:108

Referenced by IopPrepareDeviceForRemoval(), and IoRequestDeviceEject().

◆ IopQueryRemoveDevice()

static NTSTATUS NTAPI IopQueryRemoveDevice ( IN PDEVICE_OBJECT  DeviceObject)
static

Definition at line 1876 of file devaction.c.

1877{
1880
1882
1883 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING,
1884 &DeviceNode->InstancePath);
1885
1887
1888 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_QUERY_REMOVE, DeviceObject, NULL);
1889
1890 if (!NT_SUCCESS(Status))
1891 {
1892 DPRINT1("Removal vetoed by %wZ\n", &DeviceNode->InstancePath);
1893 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED,
1894 &DeviceNode->InstancePath);
1895 }
1896
1897 return Status;
1898}
NTSTATUS IopQueueTargetDeviceEvent(_In_ const GUID *Guid, _In_ PUNICODE_STRING DeviceIds)
#define IRP_MN_QUERY_REMOVE_DEVICE

Referenced by IopPrepareDeviceForRemoval().

◆ IopQueryRemoveDeviceRelations()

static NTSTATUS IopQueryRemoveDeviceRelations ( PDEVICE_RELATIONS  DeviceRelations,
BOOLEAN  Force 
)
static

Definition at line 1956 of file devaction.c.

1957{
1958 /* This function DOES NOT dereference the device objects on SUCCESS
1959 * but it DOES dereference device objects on FAILURE */
1960
1961 ULONG i, j;
1963
1964 for (i = 0; i < DeviceRelations->Count; i++)
1965 {
1966 Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i], Force);
1967 if (!NT_SUCCESS(Status))
1968 {
1969 j = i;
1970 goto cleanup;
1971 }
1972 }
1973
1974 return STATUS_SUCCESS;
1975
1976cleanup:
1977 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1978 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1979 for (i = 0; i <= j; i++)
1980 {
1981 IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1982 ObDereferenceObject(DeviceRelations->Objects[i]);
1983 DeviceRelations->Objects[i] = NULL;
1984 }
1985 for (; i < DeviceRelations->Count; i++)
1986 {
1987 ObDereferenceObject(DeviceRelations->Objects[i]);
1988 DeviceRelations->Objects[i] = NULL;
1989 }
1990 ExFreePool(DeviceRelations);
1991
1992 return Status;
1993}
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250

Referenced by IopPrepareDeviceForRemoval(), and IoRequestDeviceEject().

◆ IopRemoveDevice()

static NTSTATUS IopRemoveDevice ( PDEVICE_NODE  DeviceNode)
static

Definition at line 2060 of file devaction.c.

2061{
2063
2064 // This function removes the device subtree, with the root in DeviceNode
2065 // atm everyting is in fact done inside this function, which is completely wrong.
2066 // The right implementation should have a separate removal worker thread and
2067 // properly do device node state transitions
2068
2069 DPRINT("Removing device: %wZ\n", &DeviceNode->InstancePath);
2070
2071 BOOLEAN surpriseRemoval = (_Bool)(DeviceNode->Flags & DNF_DEVICE_GONE);
2072
2073 Status = IopPrepareDeviceForRemoval(DeviceNode->PhysicalDeviceObject, surpriseRemoval);
2074
2075 if (surpriseRemoval)
2076 {
2077 IopSendSurpriseRemoval(DeviceNode->PhysicalDeviceObject);
2078 IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL, &DeviceNode->InstancePath);
2079 }
2080
2081 if (NT_SUCCESS(Status))
2082 {
2083 IopSendRemoveDevice(DeviceNode->PhysicalDeviceObject);
2084 if (surpriseRemoval)
2085 {
2086 IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL, &DeviceNode->InstancePath);
2087 }
2088 return STATUS_SUCCESS;
2089 }
2090
2091 return Status;
2092}
static VOID NTAPI IopSendSurpriseRemoval(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1783
static VOID NTAPI IopSendRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1712
#define DNF_DEVICE_GONE
Definition: iotypes.h:186

Referenced by PiDevNodeStateMachine().

◆ IopSendEject()

static NTSTATUS NTAPI IopSendEject ( IN PDEVICE_OBJECT  DeviceObject)
static

Definition at line 2186 of file devaction.c.

2187{
2189 PVOID Dummy;
2190
2192 Stack.MajorFunction = IRP_MJ_PNP;
2193 Stack.MinorFunction = IRP_MN_EJECT;
2194
2195 return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
2196}
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
NTSTATUS IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject, IN PIO_STACK_LOCATION IoStackLocation, OUT PVOID *Information)
#define IRP_MN_EJECT

Referenced by IoRequestDeviceEject().

◆ IopSendRemoveChildDevices()

static VOID IopSendRemoveChildDevices ( PDEVICE_NODE  ParentDeviceNode)
static

Definition at line 1759 of file devaction.c.

1760{
1761 PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1762 KIRQL OldIrql;
1763
1765 ChildDeviceNode = ParentDeviceNode->Child;
1766 while (ChildDeviceNode != NULL)
1767 {
1768 NextDeviceNode = ChildDeviceNode->Sibling;
1770
1771 IopSendRemoveDevice(ChildDeviceNode->PhysicalDeviceObject);
1772
1773 ChildDeviceNode = NextDeviceNode;
1774
1776 }
1778}

Referenced by IopPrepareDeviceForRemoval(), and IoRequestDeviceEject().

◆ IopSendRemoveDevice()

static VOID NTAPI IopSendRemoveDevice ( IN PDEVICE_OBJECT  DeviceObject)
static

Definition at line 1712 of file devaction.c.

1713{
1715
1717
1718 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
1720
1721 /* Start of HACK: update resources stored in registry, so IopDetectResourceConflict works */
1722 if (DeviceNode->ResourceList)
1723 {
1724 ASSERT(DeviceNode->ResourceListTranslated);
1725 DeviceNode->ResourceList->Count = 0;
1726 DeviceNode->ResourceListTranslated->Count = 0;
1728 }
1729 /* End of HACK */
1730
1732 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_COMPLETE, DeviceObject, NULL);
1734 if (refCount != 0)
1735 {
1736 DPRINT1("Leaking device %wZ, refCount = %d\n", &DeviceNode->InstancePath, (INT32)refCount);
1737 }
1738}
signed int INT32
NTSTATUS IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode)
Definition: pnpres.c:961
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
@ DeviceNodeRemoved
Definition: iotypes.h:552
#define IRP_MN_REMOVE_DEVICE

Referenced by IopRemoveDevice(), IopSendRemoveChildDevices(), and IopSendRemoveDeviceRelations().

◆ IopSendRemoveDeviceRelations()

static VOID IopSendRemoveDeviceRelations ( PDEVICE_RELATIONS  DeviceRelations)
static

Definition at line 1742 of file devaction.c.

1743{
1744 /* This function DOES dereference the device objects in all cases */
1745
1746 ULONG i;
1747
1748 for (i = 0; i < DeviceRelations->Count; i++)
1749 {
1750 IopSendRemoveDevice(DeviceRelations->Objects[i]);
1751 DeviceRelations->Objects[i] = NULL;
1752 }
1753
1754 ExFreePool(DeviceRelations);
1755}

Referenced by IopPrepareDeviceForRemoval(), and IoRequestDeviceEject().

◆ IopSendSurpriseRemoval()

static VOID NTAPI IopSendSurpriseRemoval ( IN PDEVICE_OBJECT  DeviceObject)
static

Definition at line 1783 of file devaction.c.

1784{
1786 /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
1788}
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408

Referenced by IopRemoveDevice().

◆ IopSetDeviceInstanceData()

NTSTATUS IopSetDeviceInstanceData ( HANDLE  InstanceKey,
PDEVICE_NODE  DeviceNode 
)

Definition at line 606 of file pnpmgr.c.

608{
611 HANDLE LogConfKey, ControlKey, DeviceParamsKey;
612 ULONG ResCount;
615
616 DPRINT("IopSetDeviceInstanceData() called\n");
617
618 /* Create the 'LogConf' key */
619 RtlInitUnicodeString(&KeyName, L"LogConf");
621 &KeyName,
623 InstanceKey,
624 NULL);
625 Status = ZwCreateKey(&LogConfKey,
628 0,
629 NULL,
630 // FIXME? In r53694 it was silently turned from non-volatile into this,
631 // without any extra warning. Is this still needed??
633 NULL);
634 if (NT_SUCCESS(Status))
635 {
636 /* Set 'BootConfig' value */
637 if (DeviceNode->BootResources != NULL)
638 {
639 ResCount = DeviceNode->BootResources->Count;
640 if (ResCount != 0)
641 {
642 RtlInitUnicodeString(&KeyName, L"BootConfig");
643 Status = ZwSetValueKey(LogConfKey,
644 &KeyName,
645 0,
647 DeviceNode->BootResources,
649 }
650 }
651
652 /* Set 'BasicConfigVector' value */
653 if (DeviceNode->ResourceRequirements != NULL &&
654 DeviceNode->ResourceRequirements->ListSize != 0)
655 {
656 RtlInitUnicodeString(&KeyName, L"BasicConfigVector");
657 Status = ZwSetValueKey(LogConfKey,
658 &KeyName,
659 0,
661 DeviceNode->ResourceRequirements,
662 DeviceNode->ResourceRequirements->ListSize);
663 }
664
665 ZwClose(LogConfKey);
666 }
667
668 /* Set the 'ConfigFlags' value */
669 RtlInitUnicodeString(&KeyName, L"ConfigFlags");
670 Status = ZwQueryValueKey(InstanceKey,
671 &KeyName,
673 NULL,
674 0,
675 &ResultLength);
677 {
678 /* Write the default value */
679 ULONG DefaultConfigFlags = 0;
680 Status = ZwSetValueKey(InstanceKey,
681 &KeyName,
682 0,
683 REG_DWORD,
684 &DefaultConfigFlags,
685 sizeof(DefaultConfigFlags));
686 }
687
688 /* Create the 'Control' key */
689 RtlInitUnicodeString(&KeyName, L"Control");
691 &KeyName,
693 InstanceKey,
694 NULL);
695 Status = ZwCreateKey(&ControlKey,
696 0,
698 0,
699 NULL,
701 NULL);
702 if (NT_SUCCESS(Status))
703 ZwClose(ControlKey);
704
705 /* Create the 'Device Parameters' key and set the 'FirmwareIdentified' value for all ACPI-enumerated devices */
706 if (_wcsnicmp(DeviceNode->InstancePath.Buffer, L"ACPI\\", 5) == 0)
707 {
708 RtlInitUnicodeString(&KeyName, L"Device Parameters");
710 &KeyName,
712 InstanceKey,
713 NULL);
714 Status = ZwCreateKey(&DeviceParamsKey,
715 0,
717 0,
718 NULL,
720 NULL);
721 if (NT_SUCCESS(Status))
722 {
723 ULONG FirmwareIdentified = 1;
724 RtlInitUnicodeString(&KeyName, L"FirmwareIdentified");
725 Status = ZwSetValueKey(DeviceParamsKey,
726 &KeyName,
727 0,
728 REG_DWORD,
729 &FirmwareIdentified,
730 sizeof(FirmwareIdentified));
731
732 ZwClose(DeviceParamsKey);
733 }
734 }
735
736 DPRINT("IopSetDeviceInstanceData() done\n");
737
738 return Status;
739}
@ KeyValueBasicInformation
Definition: nt_native.h:1180
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define REG_RESOURCE_LIST
Definition: nt_native.h:1502
#define REG_RESOURCE_REQUIREMENTS_LIST
Definition: nt_native.h:1504
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
ULONG NTAPI PnpDetermineResourceListSize(IN PCM_RESOURCE_LIST ResourceList)
Definition: pnpmgr.c:1237
_Check_return_ _CRTIMP int __cdecl _wcsnicmp(_In_reads_or_z_(_MaxCount) const wchar_t *_Str1, _In_reads_or_z_(_MaxCount) const wchar_t *_Str2, _In_ size_t _MaxCount)
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776

Referenced by PiInitializeDevNode().

◆ IopSetServiceEnumData()

static NTSTATUS IopSetServiceEnumData ( _In_ PDEVICE_NODE  DeviceNode,
_In_ HANDLE  InstanceHandle 
)
static

Definition at line 1343 of file devaction.c.

1346{
1347 UNICODE_STRING ServicesKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
1348 UNICODE_STRING ServiceKeyName;
1349 UNICODE_STRING EnumKeyName;
1352 PKEY_VALUE_FULL_INFORMATION KeyValueInformation, kvInfo2;
1353 HANDLE ServiceKey = NULL, ServiceEnumKey = NULL;
1355 ULONG Count = 0, NextInstance = 0;
1356 WCHAR ValueBuffer[6];
1358
1359 // obtain the device node's ServiceName
1360 Status = IopGetRegistryValue(InstanceHandle, L"Service", &kvInfo2);
1361 if (!NT_SUCCESS(Status))
1362 {
1363 return Status;
1364 }
1365
1366 if (kvInfo2->Type != REG_SZ || kvInfo2->DataLength <= sizeof(WCHAR))
1367 {
1368 ExFreePool(kvInfo2);
1369 return STATUS_UNSUCCESSFUL;
1370 }
1371
1372 ServiceName.MaximumLength = kvInfo2->DataLength;
1373 ServiceName.Length = kvInfo2->DataLength - sizeof(UNICODE_NULL);
1374 ServiceName.Buffer = (PVOID)((ULONG_PTR)kvInfo2 + kvInfo2->DataOffset);
1375
1376 DPRINT("IopSetServiceEnumData(%p)\n", DeviceNode);
1377 DPRINT("Instance: %wZ\n", &DeviceNode->InstancePath);
1378 DPRINT("Service: %wZ\n", &ServiceName);
1379
1380 ServiceKeyName.MaximumLength = ServicesKeyPath.Length + ServiceName.Length + sizeof(UNICODE_NULL);
1381 ServiceKeyName.Length = 0;
1382 ServiceKeyName.Buffer = ExAllocatePool(PagedPool, ServiceKeyName.MaximumLength);
1383 if (ServiceKeyName.Buffer == NULL)
1384 {
1385 DPRINT1("No ServiceKeyName.Buffer!\n");
1387 }
1388
1389 RtlAppendUnicodeStringToString(&ServiceKeyName, &ServicesKeyPath);
1391
1392 DPRINT("ServiceKeyName: %wZ\n", &ServiceKeyName);
1393
1394 Status = IopOpenRegistryKeyEx(&ServiceKey, NULL, &ServiceKeyName, KEY_CREATE_SUB_KEY);
1395 if (!NT_SUCCESS(Status))
1396 {
1397 goto done;
1398 }
1399
1401 &ServiceName,
1402 &DeviceNode->ServiceName);
1403 if (!NT_SUCCESS(Status))
1404 {
1405 goto done;
1406 }
1407
1408 RtlInitUnicodeString(&EnumKeyName, L"Enum");
1409 Status = IopCreateRegistryKeyEx(&ServiceEnumKey,
1410 ServiceKey,
1411 &EnumKeyName,
1414 &Disposition);
1415 if (NT_SUCCESS(Status))
1416 {
1418 {
1419 /* Read the NextInstance value */
1420 Status = IopGetRegistryValue(ServiceEnumKey,
1421 L"Count",
1422 &KeyValueInformation);
1423 if (!NT_SUCCESS(Status))
1424 goto done;
1425
1426 if ((KeyValueInformation->Type == REG_DWORD) &&
1427 (KeyValueInformation->DataLength))
1428 {
1429 /* Read it */
1430 Count = *(PULONG)((ULONG_PTR)KeyValueInformation +
1431 KeyValueInformation->DataOffset);
1432 }
1433
1434 ExFreePool(KeyValueInformation);
1435 KeyValueInformation = NULL;
1436
1437 /* Read the NextInstance value */
1438 Status = IopGetRegistryValue(ServiceEnumKey,
1439 L"NextInstance",
1440 &KeyValueInformation);
1441 if (!NT_SUCCESS(Status))
1442 goto done;
1443
1444 if ((KeyValueInformation->Type == REG_DWORD) &&
1445 (KeyValueInformation->DataLength))
1446 {
1447 NextInstance = *(PULONG)((ULONG_PTR)KeyValueInformation +
1448 KeyValueInformation->DataOffset);
1449 }
1450
1451 ExFreePool(KeyValueInformation);
1452 KeyValueInformation = NULL;
1453 }
1454
1455 /* Set the instance path */
1456 swprintf(ValueBuffer, L"%lu", NextInstance);
1457 RtlInitUnicodeString(&ValueName, ValueBuffer);
1458 Status = ZwSetValueKey(ServiceEnumKey,
1459 &ValueName,
1460 0,
1461 REG_SZ,
1462 DeviceNode->InstancePath.Buffer,
1463 DeviceNode->InstancePath.MaximumLength);
1464 if (!NT_SUCCESS(Status))
1465 goto done;
1466
1467 /* Increment Count and NextInstance */
1468 Count++;
1469 NextInstance++;
1470
1471 /* Set the new Count value */
1473 Status = ZwSetValueKey(ServiceEnumKey,
1474 &ValueName,
1475 0,
1476 REG_DWORD,
1477 &Count,
1478 sizeof(Count));
1479 if (!NT_SUCCESS(Status))
1480 goto done;
1481
1482 /* Set the new NextInstance value */
1483 RtlInitUnicodeString(&ValueName, L"NextInstance");
1484 Status = ZwSetValueKey(ServiceEnumKey,
1485 &ValueName,
1486 0,
1487 REG_DWORD,
1488 &NextInstance,
1489 sizeof(NextInstance));
1490 }
1491
1492done:
1493 if (ServiceEnumKey != NULL)
1494 ZwClose(ServiceEnumKey);
1495
1496 if (ServiceKey != NULL)
1497 ZwClose(ServiceKey);
1498
1499 ExFreePool(ServiceKeyName.Buffer);
1500 ExFreePool(kvInfo2);
1501
1502 return Status;
1503}
static WCHAR ServiceName[]
Definition: browser.c:19
#define swprintf
Definition: precomp.h:40
#define RTL_DUPLICATE_UNICODE_STRING_ALLOCATE_NULL_STRING
Definition: green.h:16
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:56
int Count
Definition: noreturn.cpp:7
#define KEY_CREATE_SUB_KEY
Definition: nt_native.h:1018
#define REG_OPENED_EXISTING_KEY
Definition: nt_native.h:1085
NTSTATUS NTAPI IopOpenRegistryKeyEx(PHANDLE KeyHandle, HANDLE ParentKey, PUNICODE_STRING Name, ACCESS_MASK DesiredAccess)
Definition: pnpmgr.c:885
NTSTATUS NTAPI IopGetRegistryValue(IN HANDLE Handle, IN PWSTR ValueName, OUT PKEY_VALUE_FULL_INFORMATION *Information)
Definition: pnpmgr.c:1036
NTSTATUS NTAPI IopCreateRegistryKeyEx(OUT PHANDLE Handle, IN HANDLE BaseHandle OPTIONAL, IN PUNICODE_STRING KeyName, IN ACCESS_MASK DesiredAccess, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
uint32_t * PULONG
Definition: typedefs.h:59
void * PVOID
Definition: typedefs.h:50
uint32_t ULONG_PTR
Definition: typedefs.h:65

Referenced by PiInitializeDevNode().

◆ IopUpdateResourceMapForPnPDevice()

NTSTATUS IopUpdateResourceMapForPnPDevice ( IN PDEVICE_NODE  DeviceNode)

Definition at line 961 of file pnpres.c.

963{
964 return IopUpdateResourceMap(DeviceNode, L"PnP Manager", L"PnpManager");
965}
NTSTATUS IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2Key)
Definition: pnpres.c:802

Referenced by IopAssignDeviceResources(), and IopSendRemoveDevice().

◆ IopValidateID()

static BOOLEAN IopValidateID ( _In_ PWCHAR  Id,
_In_ BUS_QUERY_ID_TYPE  QueryType 
)
static

Definition at line 122 of file devaction.c.

125{
126 PWCHAR PtrChar;
127 PWCHAR StringEnd;
128 WCHAR Char;
129 ULONG SeparatorsCount = 0;
130 PWCHAR PtrPrevChar = NULL;
131 ULONG MaxSeparators;
132 BOOLEAN IsMultiSz;
133
134 PAGED_CODE();
135
136 switch (QueryType)
137 {
138 case BusQueryDeviceID:
139 MaxSeparators = MAX_SEPARATORS_DEVICEID;
140 IsMultiSz = FALSE;
141 break;
143 MaxSeparators = MAX_SEPARATORS_INSTANCEID;
144 IsMultiSz = FALSE;
145 break;
146
149 MaxSeparators = MAX_SEPARATORS_DEVICEID;
150 IsMultiSz = TRUE;
151 break;
152
153 default:
154 DPRINT1("IopValidateID: Not handled QueryType - %x\n", QueryType);
155 return FALSE;
156 }
157
158 StringEnd = Id + MAX_DEVICE_ID_LEN;
159
160 for (PtrChar = Id; PtrChar < StringEnd; PtrChar++)
161 {
162 Char = *PtrChar;
163
164 if (Char == UNICODE_NULL)
165 {
166 if (!IsMultiSz || (PtrPrevChar && PtrChar == PtrPrevChar + 1))
167 {
168 if (MaxSeparators == SeparatorsCount || IsMultiSz)
169 {
170 return TRUE;
171 }
172
173 DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
174 SeparatorsCount, MaxSeparators);
175 goto ErrorExit;
176 }
177
178 StringEnd = PtrChar + MAX_DEVICE_ID_LEN + 1;
179 PtrPrevChar = PtrChar;
180 SeparatorsCount = 0;
181 }
182 else if (Char < ' ' || Char > 0x7F || Char == ',')
183 {
184 DPRINT1("IopValidateID: Invalid character - %04X\n", Char);
185 goto ErrorExit;
186 }
187 else if (Char == ' ')
188 {
189 *PtrChar = '_';
190 }
191 else if (Char == '\\')
192 {
193 SeparatorsCount++;
194
195 if (SeparatorsCount > MaxSeparators)
196 {
197 DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
198 SeparatorsCount, MaxSeparators);
199 goto ErrorExit;
200 }
201 }
202 }
203
204 DPRINT1("IopValidateID: Not terminated ID\n");
205
207 // FIXME logging
208 return FALSE;
209}
#define PAGED_CODE()
DWORD Id
#define MAX_DEVICE_ID_LEN
Definition: devaction.c:40
#define MAX_SEPARATORS_DEVICEID
Definition: devaction.c:42
#define MAX_SEPARATORS_INSTANCEID
Definition: devaction.c:41
#define FALSE
Definition: types.h:117
_Must_inspect_result_ _In_ KTMOBJECT_TYPE QueryType
Definition: nttmapi.h:404
static VOID ErrorExit(LPTSTR lpszMessage)
Definition: telnetd.c:647

Referenced by IopCreateDeviceInstancePath(), IopQueryCompatibleIds(), and IopQueryHardwareIds().

◆ IoRequestDeviceEject()

VOID NTAPI IoRequestDeviceEject ( IN PDEVICE_OBJECT  PhysicalDeviceObject)

Definition at line 2203 of file devaction.c.

2204{
2206 PDEVICE_RELATIONS DeviceRelations;
2211
2212 IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT,
2213 &DeviceNode->InstancePath);
2214
2216 {
2217 goto cleanup;
2218 }
2219
2220 Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations;
2221
2225 &Stack);
2226 if (!NT_SUCCESS(Status))
2227 {
2228 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2229 DeviceRelations = NULL;
2230 }
2231 else
2232 {
2233 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2234 }
2235
2236 if (DeviceRelations)
2237 {
2238 Status = IopQueryRemoveDeviceRelations(DeviceRelations, FALSE);
2239 if (!NT_SUCCESS(Status))
2240 goto cleanup;
2241 }
2242
2244 if (!NT_SUCCESS(Status))
2245 {
2246 if (DeviceRelations)
2247 IopCancelRemoveDeviceRelations(DeviceRelations);
2248 goto cleanup;
2249 }
2250
2252 {
2253 if (DeviceRelations)
2254 IopCancelRemoveDeviceRelations(DeviceRelations);
2256 goto cleanup;
2257 }
2258
2259 if (DeviceRelations)
2260 IopSendRemoveDeviceRelations(DeviceRelations);
2262
2264 if (Capabilities.EjectSupported)
2265 {
2267 {
2268 goto cleanup;
2269 }
2270 }
2271 else
2272 {
2273 // DeviceNode->Flags |= DNF_DISABLED;
2274 }
2275
2276 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT,
2277 &DeviceNode->InstancePath);
2278
2279 return;
2280
2281cleanup:
2282 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED,
2283 &DeviceNode->InstancePath);
2284}
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
#define CM_PROB_HELD_FOR_EJECT
Definition: cfg.h:77
static NTSTATUS NTAPI IopSendEject(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:2186
static VOID IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
Definition: devaction.c:1803
_Must_inspect_result_ typedef _Out_ PHIDP_CAPS Capabilities
Definition: hidclass.h:103
@ EjectionRelations
Definition: iotypes.h:2153

◆ PiAttachFilterDrivers()

static NTSTATUS PiAttachFilterDrivers ( PLIST_ENTRY  DriversListHead,
PDEVICE_NODE  DeviceNode,
HANDLE  EnumSubKey,
HANDLE  ClassKey,
BOOLEAN  Lower,
BOOLEAN  LoadDrivers 
)
static

Calls PiAttachFilterDriversCallback for filter drivers (if any)

Definition at line 532 of file devaction.c.

539{
540 RTL_QUERY_REGISTRY_TABLE QueryTable[2] = { { NULL, 0, NULL, NULL, 0, NULL, 0 }, };
541 ATTACH_FILTER_DRIVERS_CONTEXT routineContext;
543
544 PAGED_CODE();
545
546 routineContext.DriversListHead = DriversListHead;
547 routineContext.DeviceNode = DeviceNode;
548
549 // First add device filters
550 routineContext.DriverType = Lower ? LowerFilter : UpperFilter;
553 .Name = Lower ? L"LowerFilters" : L"UpperFilters",
554 .DefaultType = REG_NONE,
555 .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
556 };
557
559 (PWSTR)EnumSubKey,
561 &routineContext,
562 NULL);
563 if (ClassKey == NULL)
564 {
565 return Status;
566 }
567
568 // Then add device class filters
569 routineContext.DriverType = Lower ? LowerClassFilter : UpperClassFilter;
572 .Name = Lower ? L"LowerFilters" : L"UpperFilters",
573 .DefaultType = REG_NONE,
574 .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
575 };
576
578 (PWSTR)ClassKey,
580 &routineContext,
581 NULL);
582 return Status;
583}
static NTSTATUS NTAPI PiAttachFilterDriversCallback(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Ctx, PVOID EntryContext)
Loads and/or returns the driver associated with the registry entry if the driver is enabled....
Definition: devaction.c:363
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4220
struct _RTL_QUERY_REGISTRY_TABLE RTL_QUERY_REGISTRY_TABLE
#define REG_NONE
Definition: nt_native.h:1492
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
ADD_DEV_DRIVER_TYPE DriverType
Definition: devaction.c:82
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109

Referenced by PiCallDriverAddDevice().

◆ PiAttachFilterDriversCallback()

static NTSTATUS NTAPI PiAttachFilterDriversCallback ( PWSTR  ValueName,
ULONG  ValueType,
PVOID  ValueData,
ULONG  ValueLength,
PVOID  Ctx,
PVOID  EntryContext 
)
static

Loads and/or returns the driver associated with the registry entry if the driver is enabled. In case of an error, sets up a corresponding Problem to the DeviceNode.

Definition at line 363 of file devaction.c.

370{
374 BOOLEAN loadDrivers = (BOOLEAN)(ULONG_PTR)EntryContext;
375
376 PAGED_CODE();
377
378 // No filter value present
379 if (ValueType != REG_SZ)
380 return STATUS_SUCCESS;
381
382 if (ValueLength <= sizeof(WCHAR))
384
385 // open the service registry key
386 UNICODE_STRING serviceName = { .Length = 0 }, servicesKeyName;
388 RtlInitUnicodeString(&servicesKeyName, ServicesKeyName);
389
390 HANDLE ccsServicesHandle, serviceHandle = NULL;
391
392 Status = IopOpenRegistryKeyEx(&ccsServicesHandle, NULL, &servicesKeyName, KEY_READ);
393 if (!NT_SUCCESS(Status))
394 {
395 DPRINT1("Failed to open a registry key for \"%wZ\" (status %x)\n", &serviceName, Status);
396 return Status;
397 }
398
399 Status = IopOpenRegistryKeyEx(&serviceHandle, ccsServicesHandle, &serviceName, KEY_READ);
400 ZwClose(ccsServicesHandle);
401 if (!NT_SUCCESS(Status))
402 {
403 DPRINT1("Failed to open a registry key for \"%wZ\" (status %x)\n", &serviceName, Status);
404 return Status;
405 }
406
408 sizeof(*driverEntry),
410
411 if (!driverEntry)
412 {
413 DPRINT1("Failed to allocate driverEntry for \"%wZ\"\n", &serviceName);
414 ZwClose(serviceHandle);
416 }
417
418 // check if the driver is disabled
420 SERVICE_LOAD_TYPE startType = DisableLoad;
421
422 Status = IopGetRegistryValue(serviceHandle, L"Start", &kvInfo);
423 if (NT_SUCCESS(Status))
424 {
425 if (kvInfo->Type == REG_DWORD)
426 {
427 RtlMoveMemory(&startType,
428 (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset),
429 sizeof(startType));
430 }
431
432 ExFreePool(kvInfo);
433 }
434
435 // TODO: take into account other start types (like SERVICE_DEMAND_START)
436 if (startType >= DisableLoad)
437 {
438 if (!(context->DeviceNode->Flags & DNF_HAS_PROBLEM))
439 {
441 }
442
443 DPRINT("Service \"%wZ\" is disabled (start type %u)\n", &serviceName, startType);
445 goto Cleanup;
446 }
447
448 // check if the driver is already loaded
449 UNICODE_STRING driverName;
450 Status = IopGetDriverNames(serviceHandle, &driverName, NULL);
451 if (!NT_SUCCESS(Status))
452 {
453 DPRINT1("Unable to obtain the driver name for \"%wZ\"\n", &serviceName);
454 goto Cleanup;
455 }
456
457 // try to open it
458 Status = ObReferenceObjectByName(&driverName,
460 NULL, /* PassedAccessState */
461 0, /* DesiredAccess */
464 NULL, /* ParseContext */
466 RtlFreeUnicodeString(&driverName);
467
468 // the driver was not probably loaded, try to load
469 if (!NT_SUCCESS(Status))
470 {
471 if (loadDrivers)
472 {
473 Status = IopLoadDriver(serviceHandle, &DriverObject);
474 }
475 else
476 {
477 DPRINT("Service \"%wZ\" will not be loaded now\n", &serviceName);
478 // return failure, the driver will be loaded later (in a subsequent call)
480 goto Cleanup;
481 }
482 }
483
484 if (NT_SUCCESS(Status))
485 {
486 driverEntry->DriverObject = DriverObject;
487 driverEntry->DriverType = context->DriverType;
488 InsertTailList(context->DriversListHead, &driverEntry->ListEntry);
489 ZwClose(serviceHandle);
490 return STATUS_SUCCESS;
491 }
492 else
493 {
494 if (!(context->DeviceNode->Flags & DNF_HAS_PROBLEM))
495 {
496 switch (Status)
497 {
500 break;
503 break;
506 break;
507 default:
509 break;
510 }
511 }
512
513 DPRINT1("Failed to load driver \"%wZ\" for %wZ (status %x)\n",
514 &serviceName, &context->DeviceNode->InstancePath, Status);
515 }
516
517Cleanup:
519 if (serviceHandle)
520 {
521 ZwClose(serviceHandle);
522 }
523 return Status;
524}
#define CM_PROB_DRIVER_SERVICE_KEY_INVALID
Definition: cfg.h:70
#define CM_PROB_DRIVER_FAILED_LOAD
Definition: cfg.h:69
#define CM_PROB_OUT_OF_MEMORY
Definition: cfg.h:33
#define CM_PROB_FAILED_DRIVER_ENTRY
Definition: cfg.h:67
#define CM_PROB_DISABLED_SERVICE
Definition: cfg.h:62
static const WCHAR ServicesKeyName[]
Definition: devaction.c:51
static const WCHAR Cleanup[]
Definition: register.c:80
#define InsertTailList(ListHead, Entry)
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
#define OBJ_OPENIF
Definition: winternl.h:229
#define KernelMode
Definition: asm.h:34
#define DNF_HAS_PROBLEM
Definition: iotypes.h:183
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4219
#define KEY_READ
Definition: nt_native.h:1023
NTSTATUS IopLoadDriver(_In_ HANDLE ServiceHandle, _Out_ PDRIVER_OBJECT *DriverObject)
Definition: driver.c:1938
NTSTATUS IopGetDriverNames(_In_ HANDLE ServiceHandle, _Out_ PUNICODE_STRING DriverName, _Out_opt_ PUNICODE_STRING ServiceName)
Definition: driver.c:123
VOID PiSetDevNodeProblem(_In_ PDEVICE_NODE DeviceNode, _In_ UINT32 Problem)
Definition: devnode.c:132
POBJECT_TYPE IoDriverObjectType
Definition: driver.c:34
#define STATUS_FAILED_DRIVER_ENTRY
Definition: ntstatus.h:911
#define STATUS_ILL_FORMED_SERVICE_ENTRY
Definition: ntstatus.h:588
NTSTATUS NTAPI ObReferenceObjectByName(IN PUNICODE_STRING ObjectPath, IN ULONG Attributes, IN PACCESS_STATE PassedAccessState, IN ACCESS_MASK DesiredAccess, IN POBJECT_TYPE ObjectType, IN KPROCESSOR_MODE AccessMode, IN OUT PVOID ParseContext, OUT PVOID *ObjectPtr)
Definition: obref.c:409
#define BOOLEAN
Definition: pedump.c:73
PDRIVER_OBJECT DriverObject
Definition: devaction.c:76
ADD_DEV_DRIVER_TYPE DriverType
Definition: devaction.c:77
LIST_ENTRY ListEntry
Definition: devaction.c:75
Definition: http.c:7252
#define TAG_PNP_DEVACTION
Definition: tag.h:98
char serviceName[]
Definition: tftpd.cpp:34
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:282
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
enum _CM_SERVICE_LOAD_TYPE SERVICE_LOAD_TYPE
@ DisableLoad
Definition: cmtypes.h:1000

Referenced by PiAttachFilterDrivers(), and PiCallDriverAddDevice().

◆ PiCallDriverAddDevice()

static NTSTATUS PiCallDriverAddDevice ( _In_ PDEVICE_NODE  DeviceNode,
_In_ BOOLEAN  LoadDrivers 
)
static

Loads all drivers for a device node (actual service and filters) and calls their AddDevice routine.

Parameters
[in]DeviceNodeThe device node
[in]LoadDriversWhether to load drivers if they are not loaded yet (used when storage subsystem is not yet initialized)

Definition at line 595 of file devaction.c.

598{
600 HANDLE EnumRootKey, SubKey;
601 HANDLE ClassKey = NULL;
603 static UNICODE_STRING ccsControlClass =
604 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class");
606
607 PAGED_CODE();
608
609 // open the enumeration root key
610 Status = IopOpenRegistryKeyEx(&EnumRootKey, NULL, &EnumRoot, KEY_READ);
611 if (!NT_SUCCESS(Status))
612 {
613 DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n", &EnumRoot, Status);
614 return Status;
615 }
616
617 // open an instance subkey
618 Status = IopOpenRegistryKeyEx(&SubKey, EnumRootKey, &DeviceNode->InstancePath, KEY_READ);
619 ZwClose(EnumRootKey);
620 if (!NT_SUCCESS(Status))
621 {
622 DPRINT1("Failed to open a devnode instance key for \"%wZ\" (status %x)\n",
623 &DeviceNode->InstancePath, Status);
624 return Status;
625 }
626
627 // try to get the class GUID of an instance and its registry key
629 if (NT_SUCCESS(Status))
630 {
631 if (kvInfo->Type == REG_SZ && kvInfo->DataLength > sizeof(WCHAR))
632 {
633 UNICODE_STRING classGUID = {
634 .MaximumLength = kvInfo->DataLength,
635 .Length = kvInfo->DataLength - sizeof(UNICODE_NULL),
636 .Buffer = (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset)
637 };
638 HANDLE ccsControlHandle;
639
640 Status = IopOpenRegistryKeyEx(&ccsControlHandle, NULL, &ccsControlClass, KEY_READ);
641 if (!NT_SUCCESS(Status))
642 {
643 DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n",
644 &ccsControlClass, Status);
645 }
646 else
647 {
648 // open the CCS\Control\Class<ClassGUID> key
649 Status = IopOpenRegistryKeyEx(&ClassKey, ccsControlHandle, &classGUID, KEY_READ);
650 ZwClose(ccsControlHandle);
651 if (!NT_SUCCESS(Status))
652 {
653 DPRINT1("Failed to open class key \"%wZ\" (status %x)\n", &classGUID, Status);
654 }
655 }
656
657 if (ClassKey)
658 {
659 // Check the Properties key of a class too
660 // Windows fills some device properties from this key (which is protected)
661 // TODO: add the device properties from this key
662
664 HANDLE propertiesHandle;
665
666 Status = IopOpenRegistryKeyEx(&propertiesHandle, ClassKey, &properties, KEY_READ);
667 if (!NT_SUCCESS(Status))
668 {
669 DPRINT("Properties key failed to open for \"%wZ\" (status %x)\n",
670 &classGUID, Status);
671 }
672 else
673 {
674 ZwClose(propertiesHandle);
675 }
676 }
677 }
678
679 ExFreePool(kvInfo);
680 }
681
682 // the driver loading order:
683 // 1. LowerFilters
684 // 2. LowerClassFilters
685 // 3. Device driver (only one service!)
686 // 4. UpperFilters
687 // 5. UpperClassFilters
688
689 LIST_ENTRY drvListHead;
690 InitializeListHead(&drvListHead);
691
692 // lower (class) filters
693 Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, TRUE, LoadDrivers);
694 if (!NT_SUCCESS(Status))
695 {
696 goto Cleanup;
697 }
698
699 ATTACH_FILTER_DRIVERS_CONTEXT routineContext = {
700 .DriversListHead = &drvListHead,
701 .DriverType = DeviceDriver,
702 .DeviceNode = DeviceNode
703 };
704
705 RTL_QUERY_REGISTRY_TABLE queryTable[2] = {{
707 .Name = L"Service",
709 .DefaultType = REG_SZ, // REG_MULTI_SZ is not allowed here
710 .DefaultData = L"",
711 .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
712 },};
713
714 // device driver
716 (PWSTR)SubKey,
717 queryTable,
718 &routineContext,
719 NULL);
720 if (NT_SUCCESS(Status))
721 {
722 // do nothing
723 }
724 // if a driver is not found, but a device allows raw access -> proceed
726 (DeviceNode->CapabilityFlags & 0x00000040)) // CM_DEVCAP_RAWDEVICEOK
727 {
728 // add a dummy entry to the drivers list (need for later processing)
730 sizeof(*driverEntry),
732 driverEntry->DriverType = DeviceDriver;
733 InsertTailList(&drvListHead, &driverEntry->ListEntry);
734 DPRINT("No service for \"%wZ\" (RawDeviceOK)\n", &DeviceNode->InstancePath);
735 }
736 else
737 {
739 {
741 }
742 DPRINT("No service for \"%wZ\" (loadDrv: %u)\n", &DeviceNode->InstancePath, LoadDrivers);
743 goto Cleanup;
744 }
745
746 // upper (class) filters
747 Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, FALSE, LoadDrivers);
748 if (!NT_SUCCESS(Status))
749 {
750 goto Cleanup;
751 }
752
753 // finally loop through the stack and call AddDevice for every driver
754 for (PLIST_ENTRY listEntry = drvListHead.Flink;
755 listEntry != &drvListHead;
756 listEntry = listEntry->Flink)
757 {
758 PADD_DEV_DRIVERS_LIST driverEntry;
759 driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry);
760 PDRIVER_OBJECT driverObject = driverEntry->DriverObject;
761
762 // FIXME: ReactOS is not quite ready for this assert
763 // (legacy drivers should not have AddDevice routine)
764 // ASSERT(!(DriverObject->Flags & DRVO_LEGACY_DRIVER));
765
766 if (driverObject && driverObject->DriverExtension->AddDevice)
767 {
768 Status = driverObject->DriverExtension->AddDevice(driverEntry->DriverObject,
769 DeviceNode->PhysicalDeviceObject);
770 }
771 else if (driverObject == NULL)
772 {
773 // valid only for DeviceDriver
774 ASSERT(driverEntry->DriverType == DeviceDriver);
775 ASSERT(DeviceNode->CapabilityFlags & 0x00000040); // CM_DEVCAP_RAWDEVICEOK
777 }
778 else
779 {
780 // HACK: the driver doesn't have a AddDevice routine. We shouldn't be here,
781 // but ReactOS' PnP stack is not that correct yet
784 }
785
786 // for filter drivers we don't care about the AddDevice result
787 if (driverEntry->DriverType == DeviceDriver)
788 {
789 if (NT_SUCCESS(Status))
790 {
791 PDEVICE_OBJECT fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
792
793 // HACK: Check if we have a ACPI device (needed for power management)
794 if (fdo->DeviceType == FILE_DEVICE_ACPI)
795 {
796 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
797
798 // There can be only one system power device
799 if (!SystemPowerDeviceNodeCreated)
800 {
803 SystemPowerDeviceNodeCreated = TRUE;
804 }
805 }
806
809 }
810 else
811 {
812 // lower filters (if already started) will be removed upon this request
815 break;
816 }
817 }
818
819#if DBG
820 PDEVICE_OBJECT attachedDO = IoGetAttachedDevice(DeviceNode->PhysicalDeviceObject);
821 if (attachedDO->Flags & DO_DEVICE_INITIALIZING)
822 {
823 DPRINT1("DO_DEVICE_INITIALIZING is not cleared on a device 0x%p!\n", attachedDO);
824 }
825#endif
826 }
827
828Cleanup:
829 while (!IsListEmpty(&drvListHead))
830 {
831 PLIST_ENTRY listEntry = RemoveHeadList(&drvListHead);
832 PADD_DEV_DRIVERS_LIST driverEntry;
833 driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry);
834
835 // drivers which don't have any devices (in case of failure) will be cleaned up
836 if (driverEntry->DriverObject)
837 {
838 ObDereferenceObject(driverEntry->DriverObject);
839 }
841 }
842
843 ZwClose(SubKey);
844 if (ClassKey != NULL)
845 {
846 ZwClose(ClassKey);
847 }
848
849 return Status;
850}
#define CM_PROB_REGISTRY
Definition: cfg.h:49
#define CM_PROB_FAILED_ADD
Definition: cfg.h:61
Definition: bufpool.h:45
static NTSTATUS PiAttachFilterDrivers(PLIST_ENTRY DriversListHead, PDEVICE_NODE DeviceNode, HANDLE EnumSubKey, HANDLE ClassKey, BOOLEAN Lower, BOOLEAN LoadDrivers)
Calls PiAttachFilterDriversCallback for filter drivers (if any)
Definition: devaction.c:532
#define ULONG_PTR
Definition: config.h:101
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
FORCEINLINE PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define DNF_LEGACY_DRIVER
Definition: iotypes.h:182
@ DeviceNodeDriversAdded
Definition: iotypes.h:537
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define ENUM_ROOT
Definition: io.h:53
PDEVICE_OBJECT NTAPI IoGetAttachedDevice(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1385
PDEVICE_OBJECT NTAPI IoGetAttachedDeviceReference(PDEVICE_OBJECT DeviceObject)
Definition: device.c:1406
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: ntstatus.h:273
PDEVICE_NODE PopSystemPowerDeviceNode
Definition: power.c:25
#define FILE_DEVICE_ACPI
Definition: winioctl.h:95
#define REGSTR_KEY_DEVICE_PROPERTIES
Definition: regstr.h:752
#define REGSTR_VAL_CLASSGUID
Definition: regstr.h:422
PDRIVER_ADD_DEVICE AddDevice
Definition: iotypes.h:2220
PDRIVER_EXTENSION DriverExtension
Definition: iotypes.h:2282
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260

Referenced by PiDevNodeStateMachine(), and PipDeviceActionWorker().

◆ PiDevNodeStateMachine()

static VOID PiDevNodeStateMachine ( _In_ PDEVICE_NODE  RootNode)
static

Definition at line 2312 of file devaction.c.

2314{
2316 BOOLEAN doProcessAgain;
2317 PDEVICE_NODE currentNode = RootNode;
2318 PDEVICE_OBJECT referencedObject;
2319
2320 do
2321 {
2322 doProcessAgain = FALSE;
2323
2324 // The device can be removed during processing, but we still need its Parent and Sibling
2325 // links to continue the tree traversal. So keep the link till the and of a cycle
2326 referencedObject = currentNode->PhysicalDeviceObject;
2327 ObReferenceObject(referencedObject);
2328
2329 // Devices with problems are skipped (unless they are not being removed)
2330 if (currentNode->Flags & DNF_HAS_PROBLEM &&
2331 currentNode->State != DeviceNodeAwaitingQueuedRemoval)
2332 {
2333 goto skipEnum;
2334 }
2335
2336 switch (currentNode->State)
2337 {
2338 case DeviceNodeUnspecified: // this state is not used
2339 break;
2341 DPRINT("DeviceNodeUninitialized %wZ\n", &currentNode->InstancePath);
2342 status = PiInitializeDevNode(currentNode);
2343 doProcessAgain = NT_SUCCESS(status);
2344 break;
2346 DPRINT("DeviceNodeInitialized %wZ\n", &currentNode->InstancePath);
2348 doProcessAgain = NT_SUCCESS(status);
2349 break;
2351 DPRINT("DeviceNodeDriversAdded %wZ\n", &currentNode->InstancePath);
2352 status = IopAssignDeviceResources(currentNode);
2353 doProcessAgain = NT_SUCCESS(status);
2354 break;
2356 DPRINT("DeviceNodeResourcesAssigned %wZ\n", &currentNode->InstancePath);
2357 // send IRP_MN_START_DEVICE
2358 PiIrpStartDevice(currentNode);
2359
2360 // skip DeviceNodeStartPending, it is probably used for an async IRP_MN_START_DEVICE
2362 doProcessAgain = TRUE;
2363 break;
2364 case DeviceNodeStartPending: // skipped on XP/2003
2365 break;
2367 DPRINT("DeviceNodeStartCompletion %wZ\n", &currentNode->InstancePath);
2368 status = currentNode->CompletionStatus;
2369 doProcessAgain = TRUE;
2370 if (!NT_SUCCESS(status))
2371 {
2375
2376 PiSetDevNodeProblem(currentNode, problem);
2378 }
2379 else
2380 {
2381 // TODO: IopDoDeferredSetInterfaceState and IopAllocateLegacyBootResources
2382 // are called here too
2383
2385 }
2386 break;
2388 DPRINT("DeviceNodeStartPostWork %wZ\n", &currentNode->InstancePath);
2389 // TODO: inspect the status
2390 status = PiStartDeviceFinal(currentNode);
2391 doProcessAgain = TRUE;
2392 break;
2393 case DeviceNodeStarted:
2394 if (currentNode->Flags & DNF_REENUMERATE)
2395 {
2396 DPRINT("DeviceNodeStarted REENUMERATE %wZ\n", &currentNode->InstancePath);
2397 currentNode->Flags &= ~DNF_REENUMERATE;
2399
2400 // again, skip DeviceNodeEnumeratePending as with the starting sequence
2402 doProcessAgain = TRUE;
2403 }
2404 else if (currentNode->Flags & DNF_RESOURCE_REQUIREMENTS_CHANGED)
2405 {
2406 if (currentNode->Flags & DNF_NON_STOPPED_REBALANCE)
2407 {
2408 PiFakeResourceRebalance(currentNode);
2409 currentNode->Flags &= ~DNF_NON_STOPPED_REBALANCE;
2410 }
2411 else
2412 {
2413 PiIrpQueryStopDevice(currentNode);
2415 }
2416
2417 doProcessAgain = TRUE;
2418 }
2419 break;
2421 // we're here after sending IRP_MN_QUERY_STOP_DEVICE
2422 status = currentNode->CompletionStatus;
2423 if (NT_SUCCESS(status))
2424 {
2425 PiIrpStopDevice(currentNode);
2427 }
2428 else
2429 {
2430 PiIrpCancelStopDevice(currentNode);
2432 }
2433 doProcessAgain = TRUE;
2434 break;
2435 case DeviceNodeStopped:
2436 // TODO: do resource rebalance (not implemented)
2437 PiFakeResourceRebalance(currentNode);
2438
2440 doProcessAgain = TRUE;
2441 break;
2443 break;
2444 case DeviceNodeEnumeratePending: // skipped on XP/2003
2445 break;
2447 DPRINT("DeviceNodeEnumerateCompletion %wZ\n", &currentNode->InstancePath);
2448 status = PiEnumerateDevice(currentNode);
2449 doProcessAgain = TRUE;
2450 break;
2452 break;
2454 DPRINT("DeviceNodeAwaitingQueuedRemoval %wZ\n", &currentNode->InstancePath);
2455 status = IopRemoveDevice(currentNode);
2456 break;
2458 break;
2460 break;
2461 case DeviceNodeRemoved:
2462 break;
2464 break;
2465 case DeviceNodeDeleted:
2466 break;
2467 default:
2468 break;
2469 }
2470
2471skipEnum:
2472 if (!doProcessAgain)
2473 {
2474 KIRQL OldIrql;
2476 /* If we have a child, simply go down the tree */
2477 if (currentNode->State != DeviceNodeRemoved && currentNode->Child != NULL)
2478 {
2479 ASSERT(currentNode->Child->Parent == currentNode);
2480 currentNode = currentNode->Child;
2481 }
2482 else
2483 {
2484 while (currentNode != RootNode)
2485 {
2486 /* All children processed -- go sideways */
2487 if (currentNode->Sibling != NULL)
2488 {
2489 ASSERT(currentNode->Sibling->Parent == currentNode->Parent);
2490 currentNode = currentNode->Sibling;
2491 break;
2492 }
2493 else
2494 {
2495 /* We're the last sibling -- go back up */
2496 ASSERT(currentNode->Parent->LastChild == currentNode);
2497 currentNode = currentNode->Parent;
2498 }
2499 /* We already visited the parent and all its children, so keep looking */
2500 }
2501 }
2503 }
2504 ObDereferenceObject(referencedObject);
2505 } while (doProcessAgain || currentNode != RootNode);
2506}
unsigned int UINT32
#define CM_PROB_NEED_RESTART
Definition: cfg.h:44
#define CM_PROB_FAILED_START
Definition: cfg.h:40
BOOLEAN PnPBootDriversInitialized
Definition: pnpinit.c:21
static NTSTATUS PiEnumerateDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:2096
static NTSTATUS IopRemoveDevice(PDEVICE_NODE DeviceNode)
Definition: devaction.c:2060
static NTSTATUS PiStartDeviceFinal(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:1573
static VOID PiFakeResourceRebalance(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:2288
static NTSTATUS PiInitializeDevNode(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:1190
static NTSTATUS PiCallDriverAddDevice(_In_ PDEVICE_NODE DeviceNode, _In_ BOOLEAN LoadDrivers)
Loads all drivers for a device node (actual service and filters) and calls their AddDevice routine.
Definition: devaction.c:595
PCONFIGURATION_COMPONENT_DATA RootNode
Definition: macharm.c:19
#define DNF_REENUMERATE
Definition: iotypes.h:173
@ DeviceNodeRemovePendingCloses
Definition: iotypes.h:551
@ DeviceNodeStopped
Definition: iotypes.h:544
@ DeviceNodeRestartCompletion
Definition: iotypes.h:545
@ DeviceNodeInitialized
Definition: iotypes.h:536
@ DeviceNodeQueryRemoved
Definition: iotypes.h:550
@ DeviceNodeStartPostWork
Definition: iotypes.h:541
@ DeviceNodeStarted
Definition: iotypes.h:542
@ DeviceNodeStartCompletion
Definition: iotypes.h:540
@ DeviceNodeDeleted
Definition: iotypes.h:554
@ DeviceNodeEnumerateCompletion
Definition: iotypes.h:547
@ DeviceNodeAwaitingQueuedDeletion
Definition: iotypes.h:548
@ DeviceNodeEnumeratePending
Definition: iotypes.h:546
@ DeviceNodeResourcesAssigned
Definition: iotypes.h:538
@ DeviceNodeUninitialized
Definition: iotypes.h:535
@ DeviceNodeQueryStopped
Definition: iotypes.h:543
@ DeviceNodeStartPending
Definition: iotypes.h:539
@ DeviceNodeUnspecified
Definition: iotypes.h:534
@ DeviceNodeDeletePendingCloses
Definition: iotypes.h:553
#define DNF_NON_STOPPED_REBALANCE
Definition: iotypes.h:181
#define DNF_RESOURCE_REQUIREMENTS_CHANGED
Definition: iotypes.h:180
NTSTATUS PiIrpStartDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: pnpirp.c:87
NTSTATUS PiIrpCancelStopDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: pnpirp.c:154
NTSTATUS NTAPI IopAssignDeviceResources(IN PDEVICE_NODE DeviceNode)
Definition: pnpres.c:1116
NTSTATUS PiIrpQueryStopDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: pnpirp.c:133
NTSTATUS PiIrpStopDevice(_In_ PDEVICE_NODE DeviceNode)
Definition: pnpirp.c:111
NTSTATUS PiIrpQueryDeviceRelations(_In_ PDEVICE_NODE DeviceNode, _In_ DEVICE_RELATION_TYPE Type)
Definition: pnpirp.c:176
#define STATUS_PNP_REBOOT_REQUIRED
Definition: ntstatus.h:830
NTSTATUS CompletionStatus
Definition: iotypes.h:1000
PNP_DEVNODE_STATE State
Definition: iotypes.h:996
ULONG Flags
Definition: iotypes.h:1002
struct _DEVICE_NODE * Parent
Definition: iotypes.h:991
UNICODE_STRING InstancePath
Definition: iotypes.h:1008
Definition: ps.c:97
@ BusRelations
Definition: iotypes.h:2152

Referenced by PipDeviceActionWorker().

◆ PiEnumerateDevice()

static NTSTATUS PiEnumerateDevice ( _In_ PDEVICE_NODE  DeviceNode)
static

Definition at line 2096 of file devaction.c.

2098{
2099 PDEVICE_OBJECT ChildDeviceObject;
2100 PDEVICE_NODE ChildDeviceNode;
2101 ULONG i;
2102
2103 // bus relations are already obtained for this device node
2104
2105 if (!NT_SUCCESS(DeviceNode->CompletionStatus))
2106 {
2107 DPRINT("QDR request failed for %wZ, status %x\n",
2108 &DeviceNode->InstancePath, DeviceNode->CompletionStatus);
2109 // treat as if there are no child objects
2110 }
2111
2112 PDEVICE_RELATIONS DeviceRelations = DeviceNode->OverUsed1.PendingDeviceRelations;
2113 DeviceNode->OverUsed1.PendingDeviceRelations = NULL;
2114
2115 // it's acceptable not to have PDOs
2116 if (!DeviceRelations)
2117 {
2119 DPRINT("No PDOs\n");
2120 return STATUS_SUCCESS;
2121 }
2122
2123 // mark children nodes as non-present (those not returned in DR request will be removed)
2124 for (PDEVICE_NODE child = DeviceNode->Child; child != NULL; child = child->Sibling)
2125 {
2126 child->Flags &= ~DNF_ENUMERATED;
2127 }
2128
2129 DPRINT("PiEnumerateDevice: enumerating %u children\n", DeviceRelations->Count);
2130
2131 // create device nodes for all new children and set DNF_ENUMERATED back for old ones
2132 for (i = 0; i < DeviceRelations->Count; i++)
2133 {
2134 ChildDeviceObject = DeviceRelations->Objects[i];
2135 ASSERT((ChildDeviceObject->Flags & DO_DEVICE_INITIALIZING) == 0);
2136
2137 ChildDeviceNode = IopGetDeviceNode(ChildDeviceObject);
2138 if (!ChildDeviceNode)
2139 {
2140 /* One doesn't exist, create it */
2141 ChildDeviceNode = PipAllocateDeviceNode(ChildDeviceObject);
2142 if (ChildDeviceNode)
2143 {
2144 PiInsertDevNode(ChildDeviceNode, DeviceNode);
2145
2146 /* Mark the node as enumerated */
2147 ChildDeviceNode->Flags |= DNF_ENUMERATED;
2148
2149 /* Mark the DO as bus enumerated */
2150 ChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;
2151 }
2152 else
2153 {
2154 /* Ignore this DO */
2155 DPRINT1("PipAllocateDeviceNode() failed. Skipping PDO %u\n", i);
2156 ObDereferenceObject(ChildDeviceObject);
2157 }
2158 }
2159 else
2160 {
2161 /* Mark it as enumerated */
2162 ChildDeviceNode->Flags |= DNF_ENUMERATED;
2163 ObDereferenceObject(ChildDeviceObject);
2164 }
2165 }
2166 ExFreePool(DeviceRelations);
2167
2168 // time to remove non-reported devices
2169 for (PDEVICE_NODE child = DeviceNode->Child; child != NULL; child = child->Sibling)
2170 {
2171 if (!(child->Flags & (DNF_ENUMERATED|DNF_DEVICE_GONE)))
2172 {
2173 // this flag indicates that this is a surprise removal
2174 child->Flags |= DNF_DEVICE_GONE;
2176 }
2177 }
2178
2180 return STATUS_SUCCESS;
2181}
static HWND child
Definition: cursoricon.c:298
#define DNF_ENUMERATED
Definition: iotypes.h:174
VOID PiInsertDevNode(_In_ PDEVICE_NODE DeviceNode, _In_ PDEVICE_NODE ParentNode)
Definition: devnode.c:80
PDEVICE_NODE PipAllocateDeviceNode(IN PDEVICE_OBJECT PhysicalDeviceObject)
#define DO_BUS_ENUMERATED_DEVICE

Referenced by PiDevNodeStateMachine().

◆ PiFakeResourceRebalance()

static VOID PiFakeResourceRebalance ( _In_ PDEVICE_NODE  DeviceNode)
static

Definition at line 2288 of file devaction.c.

2290{
2292
2293 PCM_RESOURCE_LIST bootConfig = NULL;
2294 PIO_RESOURCE_REQUIREMENTS_LIST resourceRequirements = NULL;
2295
2296 PiIrpQueryResources(DeviceNode, &bootConfig);
2297 PiIrpQueryResourceRequirements(DeviceNode, &resourceRequirements);
2298
2299 DeviceNode->BootResources = bootConfig;
2300 DeviceNode->ResourceRequirements = resourceRequirements;
2301
2302 if (bootConfig)
2303 {
2305 }
2306
2307 DeviceNode->Flags &= ~DNF_RESOURCE_REQUIREMENTS_CHANGED;
2308}
#define DNF_HAS_BOOT_CONFIG
Definition: iotypes.h:176
NTSTATUS PiIrpQueryResources(_In_ PDEVICE_NODE DeviceNode, _Out_ PCM_RESOURCE_LIST *Resources)
Definition: pnpirp.c:201
NTSTATUS PiIrpQueryResourceRequirements(_In_ PDEVICE_NODE DeviceNode, _Out_ PIO_RESOURCE_REQUIREMENTS_LIST *Resources)
Definition: pnpirp.c:227

Referenced by PiDevNodeStateMachine().

◆ PiInitializeDevNode()

static NTSTATUS PiInitializeDevNode ( _In_ PDEVICE_NODE  DeviceNode)
static

Definition at line 1190 of file devaction.c.

1192{
1195 HANDLE InstanceKey = NULL;
1196 UNICODE_STRING InstancePathU;
1197 PDEVICE_OBJECT OldDeviceObject;
1198
1199 DPRINT("PiProcessNewDevNode(%p)\n", DeviceNode);
1200 DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject);
1201
1202 /*
1203 * FIXME: For critical errors, cleanup and disable device, but always
1204 * return STATUS_SUCCESS.
1205 */
1206
1208 if (!NT_SUCCESS(Status))
1209 {
1211 {
1212 DPRINT1("IopCreateDeviceInstancePath() failed with status 0x%lx\n", Status);
1213 }
1214 return Status;
1215 }
1216
1217 /* Verify that this is not a duplicate */
1218 OldDeviceObject = IopGetDeviceObjectFromDeviceInstance(&InstancePathU);
1219 if (OldDeviceObject != NULL)
1220 {
1221 PDEVICE_NODE OldDeviceNode = IopGetDeviceNode(OldDeviceObject);
1222
1223 DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU);
1224 DPRINT1("Current instance parent: '%wZ'\n", &DeviceNode->Parent->InstancePath);
1225 DPRINT1("Old instance parent: '%wZ'\n", &OldDeviceNode->Parent->InstancePath);
1226
1227 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
1228 0x01,
1229 (ULONG_PTR)DeviceNode->PhysicalDeviceObject,
1230 (ULONG_PTR)OldDeviceObject,
1231 0);
1232 }
1233
1234 DeviceNode->InstancePath = InstancePathU;
1235
1236 DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
1237
1238 /*
1239 * Create registry key for the instance id, if it doesn't exist yet
1240 */
1241 Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
1242 if (!NT_SUCCESS(Status))
1243 {
1244 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
1245
1246 /* We have to return success otherwise we abort the traverse operation */
1247 return STATUS_SUCCESS;
1248 }
1249
1250 IopQueryHardwareIds(DeviceNode, InstanceKey);
1251
1252 IopQueryCompatibleIds(DeviceNode, InstanceKey);
1253
1254 DeviceNode->Flags |= DNF_IDS_QUERIED;
1255
1256 // Set the device's DeviceDesc and LocationInformation fields
1257 PiSetDevNodeText(DeviceNode, InstanceKey);
1258
1259 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1260
1261 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1264 NULL);
1266 {
1268
1269 DeviceNode->ChildBusNumber = BusInformation->BusNumber;
1270 DeviceNode->ChildInterfaceType = BusInformation->LegacyBusType;
1271 DeviceNode->ChildBusTypeIndex = IopGetBusTypeGuidIndex(&BusInformation->BusTypeGuid);
1273 }
1274 else
1275 {
1276 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
1277
1278 DeviceNode->ChildBusNumber = 0xFFFFFFF0;
1279 DeviceNode->ChildInterfaceType = InterfaceTypeUndefined;
1280 DeviceNode->ChildBusTypeIndex = -1;
1281 }
1282
1283 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1284
1285 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1288 NULL);
1290 {
1293 }
1294 else
1295 {
1296 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
1297 DeviceNode->BootResources = NULL;
1298 }
1299
1300 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1301
1302 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1305 NULL);
1306 if (NT_SUCCESS(Status))
1307 {
1309 }
1310 else
1311 {
1312 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
1313 DeviceNode->ResourceRequirements = NULL;
1314 }
1315
1316 if (InstanceKey != NULL)
1317 {
1319 }
1320
1321 // Try installing a critical device, so its Service key is populated
1322 // then call IopSetServiceEnumData to populate service's Enum key.
1323 // That allows us to start devices during an early boot
1325 IopSetServiceEnumData(DeviceNode, InstanceKey);
1326
1327 ZwClose(InstanceKey);
1328
1330
1332 {
1333 /* Report the device to the user-mode pnp manager */
1334 IopQueueDeviceInstallEvent(&GUID_DEVICE_ENUMERATED,
1335 &DeviceNode->InstancePath);
1336 }
1337
1338 return STATUS_SUCCESS;
1339}
static NTSTATUS IopQueryCompatibleIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:1022
PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance)
Definition: plugplay.c:206
NTSTATUS IopSetDeviceInstanceData(HANDLE InstanceKey, PDEVICE_NODE DeviceNode)
Definition: pnpmgr.c:606
static NTSTATUS IopCreateDeviceInstancePath(_In_ PDEVICE_NODE DeviceNode, _Out_ PUNICODE_STRING InstancePath)
Definition: devaction.c:213
USHORT NTAPI IopGetBusTypeGuidIndex(LPGUID BusTypeGuid)
Definition: pnpmgr.c:411
VOID PiSetDevNodeText(_In_ PDEVICE_NODE DeviceNode, _In_ HANDLE InstanceKey)
Sets the DeviceNode's DeviceDesc and LocationInformation registry values.
Definition: devaction.c:1089
static NTSTATUS IopSetServiceEnumData(_In_ PDEVICE_NODE DeviceNode, _In_ HANDLE InstanceHandle)
Definition: devaction.c:1343
static NTSTATUS IopQueryHardwareIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:957
VOID NTAPI IopInstallCriticalDevice(PDEVICE_NODE DeviceNode)
Definition: pnpmgr.c:45
struct _CM_RESOURCE_LIST * PCM_RESOURCE_LIST
@ InterfaceTypeUndefined
Definition: hwresource.cpp:136
#define DNF_IDS_QUERIED
Definition: iotypes.h:175
#define IopDeviceNodeHasFlag(DeviceNode, Flag)
Definition: io.h:164
NTSTATUS IopQueueDeviceInstallEvent(_In_ const GUID *Guid, _In_ PUNICODE_STRING DeviceId)
Definition: plugplay.c:97
#define IopDeviceNodeSetFlag(DeviceNode, Flag)
Definition: io.h:146
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:108
_In_ WDFDEVICE _In_ PPNP_BUS_INFORMATION BusInformation
Definition: wdfdevice.h:3915
struct _PNP_BUS_INFORMATION * PPNP_BUS_INFORMATION
#define IRP_MN_QUERY_RESOURCE_REQUIREMENTS
#define IRP_MN_QUERY_RESOURCES
struct _IO_RESOURCE_REQUIREMENTS_LIST * PIO_RESOURCE_REQUIREMENTS_LIST
#define IRP_MN_QUERY_BUS_INFORMATION

Referenced by PiDevNodeStateMachine().

◆ PiIrpSendRemoveCheckVpb()

static NTSTATUS PiIrpSendRemoveCheckVpb ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ UCHAR  MinorFunction 
)
static

Sends one of the remove IRPs to the device stack.

If there is a mounted VPB attached to a one of the stack devices, the IRP should be send to a VPB's DeviceObject first (which belongs to a FS driver). FS driver will then forward it down to the volume device. While walking the device stack, the function sets (or unsets) VPB_REMOVE_PENDING flag thus blocking all further mounts on a soon-to-be-removed devices

Definition at line 1645 of file devaction.c.

1648{
1649 KIRQL oldIrql;
1650
1655
1656 PDEVICE_OBJECT vpbDevObj = DeviceObject, targetDevice = DeviceObject;
1657
1658 // walk the device stack down, stop on a first mounted device
1659 do
1660 {
1661 if (vpbDevObj->Vpb)
1662 {
1663 // two locks are needed here
1664 KeWaitForSingleObject(&vpbDevObj->DeviceLock, Executive, KernelMode, FALSE, NULL);
1665 IoAcquireVpbSpinLock(&oldIrql);
1666
1668 {
1669 vpbDevObj->Vpb->Flags &= ~VPB_REMOVE_PENDING;
1670 }
1671 else
1672 {
1673 vpbDevObj->Vpb->Flags |= VPB_REMOVE_PENDING;
1674 }
1675
1676 BOOLEAN isMounted = (_Bool)(vpbDevObj->Vpb->Flags & VPB_MOUNTED);
1677
1678 if (isMounted)
1679 {
1680 targetDevice = vpbDevObj->Vpb->DeviceObject;
1681 }
1682
1683 IoReleaseVpbSpinLock(oldIrql);
1684 KeSetEvent(&vpbDevObj->DeviceLock, IO_NO_INCREMENT, FALSE);
1685
1686 if (isMounted)
1687 {
1688 break;
1689 }
1690 }
1691
1693 vpbDevObj = vpbDevObj->AttachedDevice;
1695 } while (vpbDevObj);
1696
1697 ASSERT(targetDevice);
1698
1699 PVOID info;
1700 IO_STACK_LOCATION stack = {.MajorFunction = IRP_MJ_PNP, .MinorFunction = MinorFunction};
1701
1702 return IopSynchronousCall(targetDevice, &stack, &info);
1703}
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
static int isMounted
Definition: fatten.c:16
VOID FASTCALL KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, IN KIRQL OldIrql)
Definition: spinlock.c:154
KIRQL FASTCALL KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
Definition: spinlock.c:108
#define VPB_REMOVE_PENDING
Definition: ntifs_ex.h:428
VOID NTAPI IoReleaseVpbSpinLock(IN KIRQL Irql)
Definition: volume.c:1215
VOID NTAPI IoAcquireVpbSpinLock(OUT PKIRQL Irql)
Definition: volume.c:1204
Definition: format.c:80
_In_ UCHAR _In_ UCHAR MinorFunction
Definition: wdfdevice.h:1699
#define VPB_MOUNTED
Definition: iotypes.h:1807
#define IO_NO_INCREMENT
Definition: iotypes.h:598
@ Executive
Definition: ketypes.h:415
@ LockQueueIoDatabaseLock
Definition: ketypes.h:668

Referenced by IopCancelRemoveDevice(), IopQueryRemoveDevice(), IopSendRemoveDevice(), and IopSendSurpriseRemoval().

◆ PipDeviceActionWorker()

static VOID NTAPI PipDeviceActionWorker ( _In_opt_ PVOID  Context)
static

Definition at line 2537 of file devaction.c.

2539{
2540 PLIST_ENTRY ListEntry;
2542 KIRQL OldIrql;
2543 PDEVICE_NODE deviceNode;
2545
2548 {
2551 Request = CONTAINING_RECORD(ListEntry, DEVICE_ACTION_REQUEST, RequestListEntry);
2552
2553 ASSERT(Request->DeviceObject);
2554
2555 deviceNode = IopGetDeviceNode(Request->DeviceObject);
2556 ASSERT(deviceNode);
2557
2559
2560 DPRINT("Processing PnP request %p: DeviceObject - %p, Action - %s\n",
2561 Request, Request->DeviceObject, ActionToStr(Request->Action));
2562
2563 switch (Request->Action)
2564 {
2566 {
2567 if (deviceNode->State == DeviceNodeInitialized &&
2568 !(deviceNode->Flags & DNF_HAS_PROBLEM))
2569 {
2571 }
2572 break;
2573 }
2576 deviceNode->Flags |= DNF_REENUMERATE;
2577 PiDevNodeStateMachine(deviceNode);
2578 break;
2579
2581 // TODO: the operation is a no-op for everything except removed nodes
2582 // for removed nodes, it returns them back to DeviceNodeUninitialized
2583 if (deviceNode->State == DeviceNodeRemoved)
2584 {
2585 deviceNode->State = DeviceNodeUninitialized;
2586 }
2588 break;
2589
2591 // This action is triggered from usermode, when a driver is installed
2592 // for a non-critical PDO
2593 if (deviceNode->State == DeviceNodeInitialized &&
2594 !(deviceNode->Flags & DNF_HAS_PROBLEM))
2595 {
2596 PiDevNodeStateMachine(deviceNode);
2597 }
2598 else
2599 {
2600 DPRINT1("NOTE: attempt to start an already started/uninitialized device %wZ\n",
2601 &deviceNode->InstancePath);
2603 }
2604 break;
2605
2606 case PiActionQueryState:
2607 // This action is only valid for started devices. If the device is not yet
2608 // started, the PnP manager issues IRP_MN_QUERY_PNP_DEVICE_STATE by itself.
2609 if (deviceNode->State == DeviceNodeStarted)
2610 {
2611 // Issue a IRP_MN_QUERY_PNP_DEVICE_STATE request: it will update node's flags
2612 // and then do enumeration if something has changed
2613 status = PiUpdateDeviceState(deviceNode);
2614 if (NT_SUCCESS(status))
2615 {
2616 PiDevNodeStateMachine(deviceNode);
2617 }
2618 }
2619 // TODO: Windows may return STATUS_DELETE_PENDING here
2621 break;
2622
2623 default:
2624 DPRINT1("Unimplemented device action %u\n", Request->Action);
2626 break;
2627 }
2628
2629 if (Request->CompletionStatus)
2630 {
2631 *Request->CompletionStatus = status;
2632 }
2633
2634 if (Request->CompletionEvent)
2635 {
2636 KeSetEvent(Request->CompletionEvent, IO_NO_INCREMENT, FALSE);
2637 }
2638
2639 DPRINT("Finished processing PnP request %p\n", Request);
2640 ObDereferenceObject(Request->DeviceObject);
2643 }
2647}
LIST_ENTRY IopDeviceActionRequestList
Definition: devaction.c:46
KSPIN_LOCK IopDeviceActionLock
Definition: devaction.c:49
KEVENT PiEnumerationFinished
Definition: devaction.c:50
static VOID PiDevNodeStateMachine(_In_ PDEVICE_NODE RootNode)
Definition: devaction.c:2312
BOOLEAN IopDeviceActionInProgress
Definition: devaction.c:48
static NTSTATUS PiUpdateDeviceState(_In_ PDEVICE_NODE DeviceNode)
Processes the IoInvalidateDeviceState request.
Definition: devaction.c:1516
@ PiActionResetDevice
Definition: io.h:528
@ PiActionQueryState
Definition: io.h:531
@ PiActionAddBootDevices
Definition: io.h:529
@ PiActionStartDevice
Definition: io.h:530
@ PiActionEnumRootDevices
Definition: io.h:527
@ PiActionEnumDeviceTree
Definition: io.h:526
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547

Referenced by PiQueueDeviceAction().

◆ PiPerformSyncDeviceAction()

NTSTATUS PiPerformSyncDeviceAction ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ DEVICE_ACTION  Action 
)

Perfom a device operation synchronously via PiQueueDeviceAction.

Parameters
[in]DeviceObjectThe device object
[in]ActionThe action
Returns
Status of the operation

Definition at line 2718 of file devaction.c.

2721{
2722 KEVENT opFinished;
2724
2728
2729 return status;
2730}
VOID PiQueueDeviceAction(_In_ PDEVICE_OBJECT DeviceObject, _In_ DEVICE_ACTION Action, _In_opt_ PKEVENT CompletionEvent, _Out_opt_ NTSTATUS *CompletionStatus)
Queue a device operation to a worker thread.
Definition: devaction.c:2659
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
@ SynchronizationEvent
_In_ WDFIOTARGET _In_ _Strict_type_match_ WDF_IO_TARGET_SENT_IO_ACTION Action
Definition: wdfiotarget.h:510

Referenced by IopInitializeSystemDrivers(), IoSynchronousInvalidateDeviceRelations(), and PiControlSyncDeviceAction().

◆ PiQueueDeviceAction()

VOID PiQueueDeviceAction ( _In_ PDEVICE_OBJECT  DeviceObject,
_In_ DEVICE_ACTION  Action,
_In_opt_ PKEVENT  CompletionEvent,
_Out_opt_ NTSTATUS CompletionStatus 
)

Queue a device operation to a worker thread.

Parameters
[in]DeviceObjectThe device object
[in]ActionThe action
[in]CompletionEventThe completion event object (optional)
[out]CompletionStatusStatus returned be the action will be written here

Definition at line 2659 of file devaction.c.

2664{
2666 KIRQL OldIrql;
2667
2669
2670 DPRINT("PiQueueDeviceAction: DeviceObject - %p, Request - %p, Action - %s\n",
2671 DeviceObject, Request, ActionToStr(Action));
2672
2674
2675 Request->DeviceObject = DeviceObject;
2676 Request->Action = Action;
2677 Request->CompletionEvent = CompletionEvent;
2678 Request->CompletionStatus = CompletionStatus;
2679
2682
2684 {
2686
2690
2692 return;
2693 }
2694
2696 {
2698 return;
2699 }
2703
2706}
static VOID NTAPI PipDeviceActionWorker(_In_opt_ PVOID Context)
Definition: devaction.c:2537
WORK_QUEUE_ITEM IopDeviceActionWorkItem
Definition: devaction.c:47
BOOLEAN PnPBootDriversLoaded
Definition: pnpinit.c:20
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ DelayedWorkQueue
Definition: extypes.h:190
@ NonPagedPoolMustSucceed
Definition: ketypes.h:880

Referenced by IoInitSystem(), IoInvalidateDeviceRelations(), IoInvalidateDeviceState(), IopInitializeBootDrivers(), IopInitializeBuiltinDriver(), IopInitializePlugPlayServices(), IopInitializeSystemDrivers(), IoReportDetectedDevice(), and PiPerformSyncDeviceAction().

◆ PiSetDevNodeText()

VOID PiSetDevNodeText ( _In_ PDEVICE_NODE  DeviceNode,
_In_ HANDLE  InstanceKey 
)

Sets the DeviceNode's DeviceDesc and LocationInformation registry values.

Definition at line 1089 of file devaction.c.

1092{
1093 PAGED_CODE();
1094
1095 LCID localeId;
1096
1097 // Get the Locale ID
1099 if (!NT_SUCCESS(status))
1100 {
1101 DPRINT1("ZwQueryDefaultLocale() failed with status %x\n", status);
1102 return;
1103 }
1104
1105 // Step 1: Write the DeviceDesc value if does not exist
1106
1107 UNICODE_STRING valDeviceDesc = RTL_CONSTANT_STRING(L"DeviceDesc");
1108 ULONG len;
1109
1110 status = ZwQueryValueKey(InstanceKey, &valDeviceDesc, KeyValueBasicInformation, NULL, 0, &len);
1112 {
1113 PWSTR deviceDesc = NULL;
1115
1116 if (deviceDesc && deviceDesc[0] != UNICODE_NULL)
1117 {
1118 status = ZwSetValueKey(InstanceKey,
1119 &valDeviceDesc,
1120 0,
1121 REG_SZ,
1122 deviceDesc,
1123 ((ULONG)wcslen(deviceDesc) + 1) * sizeof(WCHAR));
1124
1125 if (!NT_SUCCESS(status))
1126 {
1127 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1128 }
1129 }
1130 else
1131 {
1132 // This key is mandatory, so even if the Irp fails, we still write it
1133 UNICODE_STRING unknownDeviceDesc = RTL_CONSTANT_STRING(L"Unknown device");
1134 DPRINT("Driver didn't return DeviceDesc (status %x)\n", status);
1135
1136 status = ZwSetValueKey(InstanceKey,
1137 &valDeviceDesc,
1138 0,
1139 REG_SZ,
1140 unknownDeviceDesc.Buffer,
1141 unknownDeviceDesc.MaximumLength);
1142 if (!NT_SUCCESS(status))
1143 {
1144 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1145 }
1146 }
1147
1148 if (deviceDesc)
1149 {
1150 ExFreePoolWithTag(deviceDesc, 0);
1151 }
1152 }
1153
1154 // Step 2: LocaltionInformation is overwritten unconditionally
1155
1156 PWSTR deviceLocationInfo = NULL;
1158 localeId,
1160 &deviceLocationInfo);
1161
1162 if (deviceLocationInfo && deviceLocationInfo[0] != UNICODE_NULL)
1163 {
1164 UNICODE_STRING valLocationInfo = RTL_CONSTANT_STRING(L"LocationInformation");
1165
1166 status = ZwSetValueKey(InstanceKey,
1167 &valLocationInfo,
1168 0,
1169 REG_SZ,
1170 deviceLocationInfo,
1171 ((ULONG)wcslen(deviceLocationInfo) + 1) * sizeof(WCHAR));
1172 if (!NT_SUCCESS(status))
1173 {
1174 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1175 }
1176 }
1177
1178 if (deviceLocationInfo)
1179 {
1180 ExFreePoolWithTag(deviceLocationInfo, 0);
1181 }
1182 else
1183 {
1184 DPRINT("Driver didn't return LocationInformation (status %x)\n", status);
1185 }
1186}
GLenum GLsizei len
Definition: glext.h:6722
NTSYSAPI NTSTATUS NTAPI ZwQueryDefaultLocale(_In_ BOOLEAN UserProfile, _Out_ PLCID DefaultLocaleId)
NTSTATUS PiIrpQueryDeviceText(_In_ PDEVICE_NODE DeviceNode, _In_ LCID LocaleId, _In_ DEVICE_TEXT_TYPE Type, _Out_ PWSTR *DeviceText)
Definition: pnpirp.c:253
DWORD LCID
Definition: nls.h:13
@ DeviceTextLocationInformation
Definition: iotypes.h:2946
@ DeviceTextDescription
Definition: iotypes.h:2945

Referenced by IoReportDetectedDevice(), and PiInitializeDevNode().

◆ PiStartDeviceFinal()

static NTSTATUS PiStartDeviceFinal ( _In_ PDEVICE_NODE  DeviceNode)
static

Definition at line 1573 of file devaction.c.

1575{
1578
1579 if (!(DeviceNode->Flags & DNF_IDS_QUERIED))
1580 {
1581 // query ids (for reported devices)
1583 HANDLE enumRootHandle, instanceHandle;
1584
1585 // open the enumeration root key
1586 Status = IopOpenRegistryKeyEx(&enumRootHandle, NULL, &enumRoot, KEY_READ);
1587 if (!NT_SUCCESS(Status))
1588 {
1589 DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n", &enumRoot, Status);
1590 return Status;
1591 }
1592
1593 // open an instance subkey
1594 Status = IopOpenRegistryKeyEx(&instanceHandle, enumRootHandle, &DeviceNode->InstancePath, KEY_READ);
1595 ZwClose(enumRootHandle);
1596 if (!NT_SUCCESS(Status))
1597 {
1598 DPRINT1("Failed to open a devnode instance key for \"%wZ\" (status %x)\n",
1599 &DeviceNode->InstancePath, Status);
1600 return Status;
1601 }
1602
1603 IopQueryHardwareIds(DeviceNode, instanceHandle);
1604 IopQueryCompatibleIds(DeviceNode, instanceHandle);
1605
1606 DeviceNode->Flags |= DNF_IDS_QUERIED;
1607 ZwClose(instanceHandle);
1608 }
1609
1610 // we're about to start - needs enumeration
1611 DeviceNode->Flags |= DNF_REENUMERATE;
1612
1613 DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
1614
1616 if (!NT_SUCCESS(Status))
1617 {
1618 DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
1619 }
1620
1621 // Query the device state (IRP_MN_QUERY_PNP_DEVICE_STATE)
1623
1624 DPRINT("Sending GUID_DEVICE_ARRIVAL %wZ\n", &DeviceNode->InstancePath);
1625 IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, &DeviceNode->InstancePath);
1626
1628
1629 return STATUS_SUCCESS;
1630}

Referenced by PiDevNodeStateMachine().

◆ PiUpdateDeviceState()

static NTSTATUS PiUpdateDeviceState ( _In_ PDEVICE_NODE  DeviceNode)
static

Processes the IoInvalidateDeviceState request.

Sends IRP_MN_QUERY_PNP_DEVICE_STATE request and sets device node's flags according to the result. Tree reenumeration should be started upon a successful return of the function.

Todo:
Do not return STATUS_SUCCESS if nothing is changed.

Definition at line 1516 of file devaction.c.

1518{
1519 PNP_DEVICE_STATE PnPFlags;
1521
1523 if (!NT_SUCCESS(Status))
1524 {
1525 return Status;
1526 }
1527
1528 if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
1529 DeviceNode->UserFlags |= DNUF_NOT_DISABLEABLE;
1530 else
1531 DeviceNode->UserFlags &= ~DNUF_NOT_DISABLEABLE;
1532
1533 if (PnPFlags & PNP_DEVICE_DONT_DISPLAY_IN_UI)
1534 DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
1535 else
1536 DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
1537
1538 if (PnPFlags & PNP_DEVICE_REMOVED || PnPFlags & PNP_DEVICE_DISABLED)
1539 {
1541 PnPFlags & PNP_DEVICE_DISABLED
1544
1546 }
1547 else if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
1548 {
1549 // Query resource rebalance
1550
1551 if (PnPFlags & PNP_DEVICE_FAILED)
1553 else
1555
1556 // Clear DNF_NO_RESOURCE_REQUIRED just in case (will be set back if needed)
1557 DeviceNode->Flags &= ~DNF_NO_RESOURCE_REQUIRED;
1558
1559 // This will be caught up later by enumeration
1561 }
1562 else if (PnPFlags & PNP_DEVICE_FAILED)
1563 {
1566 }
1567
1568 return STATUS_SUCCESS;
1569}
#define CM_PROB_HARDWARE_DISABLED
Definition: cfg.h:59
#define CM_PROB_DEVICE_NOT_THERE
Definition: cfg.h:54
#define CM_PROB_FAILED_POST_START
Definition: cfg.h:73
NTSTATUS PiIrpQueryPnPDeviceState(_In_ PDEVICE_NODE DeviceNode, _Out_ PPNP_DEVICE_STATE DeviceState)
Definition: pnpirp.c:284
#define PNP_DEVICE_NOT_DISABLEABLE
Definition: iotypes.h:1006
#define PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED
Definition: iotypes.h:1005
#define PNP_DEVICE_FAILED
Definition: iotypes.h:1003
ULONG PNP_DEVICE_STATE
Definition: iotypes.h:997
#define PNP_DEVICE_DONT_DISPLAY_IN_UI
Definition: iotypes.h:1002
#define PNP_DEVICE_DISABLED
Definition: iotypes.h:1001
#define PNP_DEVICE_REMOVED
Definition: iotypes.h:1004

Referenced by PipDeviceActionWorker(), and PiStartDeviceFinal().

Variable Documentation

◆ IopDeviceActionInProgress

BOOLEAN IopDeviceActionInProgress

Definition at line 48 of file devaction.c.

Referenced by PipDeviceActionWorker(), and PiQueueDeviceAction().

◆ IopDeviceActionLock

KSPIN_LOCK IopDeviceActionLock

◆ IopDeviceActionRequestList

LIST_ENTRY IopDeviceActionRequestList

◆ IopDeviceActionWorkItem

WORK_QUEUE_ITEM IopDeviceActionWorkItem

Definition at line 47 of file devaction.c.

Referenced by PiQueueDeviceAction().

◆ IopDriverLoadResource

ERESOURCE IopDriverLoadResource
extern

Definition at line 20 of file driver.c.

Referenced by IopLoadDriver().

◆ IopRootDeviceNode

PDEVICE_NODE IopRootDeviceNode
extern

Definition at line 18 of file devnode.c.

◆ PiEnumerationFinished

◆ PnPBootDriversInitialized

BOOLEAN PnPBootDriversInitialized
extern

Definition at line 21 of file pnpinit.c.

Referenced by PiDevNodeStateMachine(), and PipDeviceActionWorker().

◆ PnPBootDriversLoaded

BOOLEAN PnPBootDriversLoaded
extern

Definition at line 20 of file pnpinit.c.

Referenced by PiQueueDeviceAction().

◆ PnpSystemInit

BOOLEAN PnpSystemInit
extern

Definition at line 17 of file iomgr.c.

Referenced by IoInitSystem().

◆ ServicesKeyName

const WCHAR ServicesKeyName[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"
static

Definition at line 51 of file devaction.c.

Referenced by PiAttachFilterDriversCallback().