ReactOS 0.4.16-dev-1142-g8029339
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 1853 of file devaction.c.

1854{
1857 PDEVICE_RELATIONS DeviceRelations;
1859
1861
1862 Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
1863
1867 &Stack);
1868 if (!NT_SUCCESS(Status))
1869 {
1870 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
1871 DeviceRelations = NULL;
1872 }
1873 else
1874 {
1875 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
1876 }
1877
1878 if (DeviceRelations)
1879 IopCancelRemoveDeviceRelations(DeviceRelations);
1880}
LONG NTSTATUS
Definition: precomp.h:26
static VOID IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1835
static VOID NTAPI IopCancelRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1802
#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 1812 of file devaction.c.

1813{
1814 PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1815 KIRQL OldIrql;
1816
1818 ChildDeviceNode = ParentDeviceNode->Child;
1819 while (ChildDeviceNode != NULL)
1820 {
1821 NextDeviceNode = ChildDeviceNode->Sibling;
1823
1825
1826 ChildDeviceNode = NextDeviceNode;
1827
1829 }
1831}
static VOID IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1853
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:994
struct _DEVICE_NODE * Child
Definition: iotypes.h:995
PDEVICE_OBJECT PhysicalDeviceObject
Definition: iotypes.h:1010
_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 1802 of file devaction.c.

1803{
1804 /* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
1806
1807 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_CANCELLED, DeviceObject, NULL);
1808}
static NTSTATUS PiIrpSendRemoveCheckVpb(_In_ PDEVICE_OBJECT DeviceObject, _In_ UCHAR MinorFunction)
Sends one of the remove IRPs to the device stack.
Definition: devaction.c:1654
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 1835 of file devaction.c.

1836{
1837 /* This function DOES dereference the device objects in all cases */
1838
1839 ULONG i;
1840
1841 for (i = 0; i < DeviceRelations->Count; i++)
1842 {
1843 IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1844 ObDereferenceObject(DeviceRelations->Objects[i]);
1845 DeviceRelations->Objects[i] = NULL;
1846 }
1847
1848 ExFreePool(DeviceRelations);
1849}
#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
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
NTSTATUS IopGetParentIdPrefix(PDEVICE_NODE DeviceNode, PUNICODE_STRING ParentIdPrefix)
Definition: pnpmgr.c:760
NTSTATUS NTAPI IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, PDEVICE_CAPABILITIES DeviceCaps)
Definition: devaction.c:857
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_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:79
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 2006 of file devaction.c.

2007{
2011 PDEVICE_RELATIONS DeviceRelations;
2013
2014 if ((DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE) && !Force)
2015 {
2016 DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath);
2017 return STATUS_UNSUCCESSFUL;
2018 }
2019
2021 {
2022 DPRINT1("Removal vetoed by failing the query remove request\n");
2023
2025
2026 return STATUS_UNSUCCESSFUL;
2027 }
2028
2029 Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
2030
2034 &Stack);
2035 if (!NT_SUCCESS(Status))
2036 {
2037 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2038 DeviceRelations = NULL;
2039 }
2040 else
2041 {
2042 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2043 }
2044
2045 if (DeviceRelations)
2046 {
2047 Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
2048 if (!NT_SUCCESS(Status))
2049 return Status;
2050 }
2051
2053 if (!NT_SUCCESS(Status))
2054 {
2055 if (DeviceRelations)
2056 IopCancelRemoveDeviceRelations(DeviceRelations);
2057 return Status;
2058 }
2059
2060 if (DeviceRelations)
2061 IopSendRemoveDeviceRelations(DeviceRelations);
2063
2064 return STATUS_SUCCESS;
2065}
_Inout_ PVCB _In_ BOOLEAN Force
Definition: cdprocs.h:1417
static NTSTATUS IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations, BOOLEAN Force)
Definition: devaction.c:1965
static VOID IopSendRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
Definition: devaction.c:1768
static VOID IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
Definition: devaction.c:1751
static NTSTATUS NTAPI IopQueryRemoveDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: devaction.c:1885
static NTSTATUS IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode, BOOLEAN Force)
Definition: devaction.c:1911
#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 1025 of file devaction.c.

1027{
1030 PWSTR Ptr;
1034 BOOLEAN IsValidID;
1035
1036 DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
1037
1038 RtlZeroMemory(&Stack, sizeof(Stack));
1039 Stack.Parameters.QueryId.IdType = BusQueryCompatibleIDs;
1040 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1043 &Stack);
1045 {
1047
1048 if (!IsValidID)
1049 {
1050 DPRINT1("Invalid CompatibleIDs. DeviceNode - %p\n", DeviceNode);
1051 }
1052
1053 TotalLength = 0;
1054
1056 DPRINT("Compatible IDs:\n");
1057 while (*Ptr)
1058 {
1059 DPRINT(" %S\n", Ptr);
1060 Length = (ULONG)wcslen(Ptr) + 1;
1061
1062 Ptr += Length;
1064 }
1065 DPRINT("TotalLength: %hu\n", TotalLength);
1066 DPRINT("\n");
1067
1068 RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
1069 Status = ZwSetValueKey(InstanceKey,
1070 &ValueName,
1071 0,
1074 (TotalLength + 1) * sizeof(WCHAR));
1075 if (!NT_SUCCESS(Status))
1076 {
1077 DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status);
1078 }
1079 }
1080 else
1081 {
1082 DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
1083 }
1084
1085 return Status;
1086}
_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 857 of file devaction.c.

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

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

Referenced by PiInitializeDevNode(), and PiStartDeviceFinal().

◆ IopQueryRemoveChildDevices()

static NTSTATUS IopQueryRemoveChildDevices ( PDEVICE_NODE  ParentDeviceNode,
BOOLEAN  Force 
)
static

Definition at line 1911 of file devaction.c.

1912{
1913 PDEVICE_NODE ChildDeviceNode, NextDeviceNode, FailedRemoveDevice;
1915 KIRQL OldIrql;
1916
1918 ChildDeviceNode = ParentDeviceNode->Child;
1919 while (ChildDeviceNode != NULL)
1920 {
1921 NextDeviceNode = ChildDeviceNode->Sibling;
1924
1926 if (!NT_SUCCESS(Status))
1927 {
1928 FailedRemoveDevice = ChildDeviceNode;
1929 goto cleanup;
1930 }
1931
1933 ChildDeviceNode = NextDeviceNode;
1934 }
1936
1937 return STATUS_SUCCESS;
1938
1939cleanup:
1941 ChildDeviceNode = ParentDeviceNode->Child;
1942 while (ChildDeviceNode != NULL)
1943 {
1944 NextDeviceNode = ChildDeviceNode->Sibling;
1946
1948
1949 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1950 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1951 if (ChildDeviceNode == FailedRemoveDevice)
1952 return Status;
1953
1954 ChildDeviceNode = NextDeviceNode;
1955
1957 }
1959
1960 return Status;
1961}
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 1885 of file devaction.c.

1886{
1889
1891
1892 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING,
1893 &DeviceNode->InstancePath);
1894
1896
1897 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_QUERY_REMOVE, DeviceObject, NULL);
1898
1899 if (!NT_SUCCESS(Status))
1900 {
1901 DPRINT1("Removal vetoed by %wZ\n", &DeviceNode->InstancePath);
1902 IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVAL_VETOED,
1903 &DeviceNode->InstancePath);
1904 }
1905
1906 return Status;
1907}
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 1965 of file devaction.c.

1966{
1967 /* This function DOES NOT dereference the device objects on SUCCESS
1968 * but it DOES dereference device objects on FAILURE */
1969
1970 ULONG i, j;
1972
1973 for (i = 0; i < DeviceRelations->Count; i++)
1974 {
1975 Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i], Force);
1976 if (!NT_SUCCESS(Status))
1977 {
1978 j = i;
1979 goto cleanup;
1980 }
1981 }
1982
1983 return STATUS_SUCCESS;
1984
1985cleanup:
1986 /* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
1987 * that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
1988 for (i = 0; i <= j; i++)
1989 {
1990 IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
1991 ObDereferenceObject(DeviceRelations->Objects[i]);
1992 DeviceRelations->Objects[i] = NULL;
1993 }
1994 for (; i < DeviceRelations->Count; i++)
1995 {
1996 ObDereferenceObject(DeviceRelations->Objects[i]);
1997 DeviceRelations->Objects[i] = NULL;
1998 }
1999 ExFreePool(DeviceRelations);
2000
2001 return Status;
2002}
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 2069 of file devaction.c.

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

Referenced by PiDevNodeStateMachine().

◆ IopSendEject()

static NTSTATUS NTAPI IopSendEject ( IN PDEVICE_OBJECT  DeviceObject)
static

Definition at line 2195 of file devaction.c.

2196{
2198 PVOID Dummy;
2199
2201 Stack.MajorFunction = IRP_MJ_PNP;
2202 Stack.MinorFunction = IRP_MN_EJECT;
2203
2204 return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
2205}
#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 1768 of file devaction.c.

1769{
1770 PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
1771 KIRQL OldIrql;
1772
1774 ChildDeviceNode = ParentDeviceNode->Child;
1775 while (ChildDeviceNode != NULL)
1776 {
1777 NextDeviceNode = ChildDeviceNode->Sibling;
1779
1780 IopSendRemoveDevice(ChildDeviceNode->PhysicalDeviceObject);
1781
1782 ChildDeviceNode = NextDeviceNode;
1783
1785 }
1787}

Referenced by IopPrepareDeviceForRemoval(), and IoRequestDeviceEject().

◆ IopSendRemoveDevice()

static VOID NTAPI IopSendRemoveDevice ( IN PDEVICE_OBJECT  DeviceObject)
static

Definition at line 1721 of file devaction.c.

1722{
1724
1726
1727 /* Drivers should never fail a IRP_MN_REMOVE_DEVICE request */
1729
1730 /* Start of HACK: update resources stored in registry, so IopDetectResourceConflict works */
1731 if (DeviceNode->ResourceList)
1732 {
1733 ASSERT(DeviceNode->ResourceListTranslated);
1734 DeviceNode->ResourceList->Count = 0;
1735 DeviceNode->ResourceListTranslated->Count = 0;
1737 }
1738 /* End of HACK */
1739
1741 PiNotifyTargetDeviceChange(&GUID_TARGET_DEVICE_REMOVE_COMPLETE, DeviceObject, NULL);
1743 if (refCount != 0)
1744 {
1745 DPRINT1("Leaking device %wZ, refCount = %d\n", &DeviceNode->InstancePath, (INT32)refCount);
1746 }
1747}
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 1751 of file devaction.c.

1752{
1753 /* This function DOES dereference the device objects in all cases */
1754
1755 ULONG i;
1756
1757 for (i = 0; i < DeviceRelations->Count; i++)
1758 {
1759 IopSendRemoveDevice(DeviceRelations->Objects[i]);
1760 DeviceRelations->Objects[i] = NULL;
1761 }
1762
1763 ExFreePool(DeviceRelations);
1764}

Referenced by IopPrepareDeviceForRemoval(), and IoRequestDeviceEject().

◆ IopSendSurpriseRemoval()

static VOID NTAPI IopSendSurpriseRemoval ( IN PDEVICE_OBJECT  DeviceObject)
static

Definition at line 1792 of file devaction.c.

1793{
1795 /* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
1797}
#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 1346 of file devaction.c.

1349{
1350 UNICODE_STRING ServicesKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
1351 UNICODE_STRING ServiceKeyName;
1352 UNICODE_STRING EnumKeyName;
1355 PKEY_VALUE_FULL_INFORMATION KeyValueInformation, kvInfo2;
1356 HANDLE ServiceKey = NULL, ServiceEnumKey = NULL;
1358 ULONG Count = 0, NextInstance = 0;
1359 WCHAR ValueBuffer[6];
1361
1362 // obtain the device node's ServiceName
1363 Status = IopGetRegistryValue(InstanceHandle, L"Service", &kvInfo2);
1364 if (!NT_SUCCESS(Status))
1365 {
1366 return Status;
1367 }
1368
1369 if ((kvInfo2->Type != REG_SZ) ||
1370 (kvInfo2->DataLength <= sizeof(UNICODE_NULL)) ||
1371 (kvInfo2->DataLength > UNICODE_STRING_MAX_BYTES) ||
1372 ((kvInfo2->DataLength % sizeof(WCHAR)) != 0))
1373 {
1374 DPRINT1("ObjectName invalid (Type = %lu, DataLength = %lu)\n",
1375 kvInfo2->Type,
1376 kvInfo2->DataLength);
1377 ExFreePool(kvInfo2);
1378 return STATUS_UNSUCCESSFUL;
1379 }
1380
1381 ServiceName.MaximumLength = kvInfo2->DataLength;
1382 ServiceName.Length = (USHORT)(kvInfo2->DataLength - sizeof(UNICODE_NULL));
1383 ServiceName.Buffer = (PVOID)((ULONG_PTR)kvInfo2 + kvInfo2->DataOffset);
1384
1385 DPRINT("IopSetServiceEnumData(%p)\n", DeviceNode);
1386 DPRINT("Instance: %wZ\n", &DeviceNode->InstancePath);
1387 DPRINT("Service: %wZ\n", &ServiceName);
1388
1389 ServiceKeyName.MaximumLength = ServicesKeyPath.Length + ServiceName.Length + sizeof(UNICODE_NULL);
1390 ServiceKeyName.Length = 0;
1391 ServiceKeyName.Buffer = ExAllocatePool(PagedPool, ServiceKeyName.MaximumLength);
1392 if (ServiceKeyName.Buffer == NULL)
1393 {
1394 DPRINT1("No ServiceKeyName.Buffer!\n");
1396 }
1397
1398 RtlAppendUnicodeStringToString(&ServiceKeyName, &ServicesKeyPath);
1400
1401 DPRINT("ServiceKeyName: %wZ\n", &ServiceKeyName);
1402
1403 Status = IopOpenRegistryKeyEx(&ServiceKey, NULL, &ServiceKeyName, KEY_CREATE_SUB_KEY);
1404 if (!NT_SUCCESS(Status))
1405 {
1406 goto done;
1407 }
1408
1410 &ServiceName,
1411 &DeviceNode->ServiceName);
1412 if (!NT_SUCCESS(Status))
1413 {
1414 goto done;
1415 }
1416
1417 RtlInitUnicodeString(&EnumKeyName, L"Enum");
1418 Status = IopCreateRegistryKeyEx(&ServiceEnumKey,
1419 ServiceKey,
1420 &EnumKeyName,
1423 &Disposition);
1424 if (NT_SUCCESS(Status))
1425 {
1427 {
1428 /* Read the NextInstance value */
1429 Status = IopGetRegistryValue(ServiceEnumKey,
1430 L"Count",
1431 &KeyValueInformation);
1432 if (!NT_SUCCESS(Status))
1433 goto done;
1434
1435 if ((KeyValueInformation->Type == REG_DWORD) &&
1436 (KeyValueInformation->DataLength))
1437 {
1438 /* Read it */
1439 Count = *(PULONG)((ULONG_PTR)KeyValueInformation +
1440 KeyValueInformation->DataOffset);
1441 }
1442
1443 ExFreePool(KeyValueInformation);
1444 KeyValueInformation = NULL;
1445
1446 /* Read the NextInstance value */
1447 Status = IopGetRegistryValue(ServiceEnumKey,
1448 L"NextInstance",
1449 &KeyValueInformation);
1450 if (!NT_SUCCESS(Status))
1451 goto done;
1452
1453 if ((KeyValueInformation->Type == REG_DWORD) &&
1454 (KeyValueInformation->DataLength))
1455 {
1456 NextInstance = *(PULONG)((ULONG_PTR)KeyValueInformation +
1457 KeyValueInformation->DataOffset);
1458 }
1459
1460 ExFreePool(KeyValueInformation);
1461 KeyValueInformation = NULL;
1462 }
1463
1464 /* Set the instance path */
1465 swprintf(ValueBuffer, L"%lu", NextInstance);
1466 RtlInitUnicodeString(&ValueName, ValueBuffer);
1467 Status = ZwSetValueKey(ServiceEnumKey,
1468 &ValueName,
1469 0,
1470 REG_SZ,
1471 DeviceNode->InstancePath.Buffer,
1472 DeviceNode->InstancePath.MaximumLength);
1473 if (!NT_SUCCESS(Status))
1474 goto done;
1475
1476 /* Increment Count and NextInstance */
1477 Count++;
1478 NextInstance++;
1479
1480 /* Set the new Count value */
1482 Status = ZwSetValueKey(ServiceEnumKey,
1483 &ValueName,
1484 0,
1485 REG_DWORD,
1486 &Count,
1487 sizeof(Count));
1488 if (!NT_SUCCESS(Status))
1489 goto done;
1490
1491 /* Set the new NextInstance value */
1492 RtlInitUnicodeString(&ValueName, L"NextInstance");
1493 Status = ZwSetValueKey(ServiceEnumKey,
1494 &ValueName,
1495 0,
1496 REG_DWORD,
1497 &NextInstance,
1498 sizeof(NextInstance));
1499 }
1500
1501done:
1502 if (ServiceEnumKey != NULL)
1503 ZwClose(ServiceEnumKey);
1504
1505 if (ServiceKey != NULL)
1506 ZwClose(ServiceKey);
1507
1508 ExFreePool(ServiceKeyName.Buffer);
1509 ExFreePool(kvInfo2);
1510
1511 return Status;
1512}
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
#define UNICODE_STRING_MAX_BYTES
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 2212 of file devaction.c.

2213{
2215 PDEVICE_RELATIONS DeviceRelations;
2220
2221 IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT,
2222 &DeviceNode->InstancePath);
2223
2225 {
2226 goto cleanup;
2227 }
2228
2229 Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations;
2230
2234 &Stack);
2235 if (!NT_SUCCESS(Status))
2236 {
2237 DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
2238 DeviceRelations = NULL;
2239 }
2240 else
2241 {
2242 DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
2243 }
2244
2245 if (DeviceRelations)
2246 {
2247 Status = IopQueryRemoveDeviceRelations(DeviceRelations, FALSE);
2248 if (!NT_SUCCESS(Status))
2249 goto cleanup;
2250 }
2251
2253 if (!NT_SUCCESS(Status))
2254 {
2255 if (DeviceRelations)
2256 IopCancelRemoveDeviceRelations(DeviceRelations);
2257 goto cleanup;
2258 }
2259
2261 {
2262 if (DeviceRelations)
2263 IopCancelRemoveDeviceRelations(DeviceRelations);
2265 goto cleanup;
2266 }
2267
2268 if (DeviceRelations)
2269 IopSendRemoveDeviceRelations(DeviceRelations);
2271
2273 if (Capabilities.EjectSupported)
2274 {
2276 {
2277 goto cleanup;
2278 }
2279 }
2280 else
2281 {
2282 // DeviceNode->Flags |= DNF_DISABLED;
2283 }
2284
2285 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT,
2286 &DeviceNode->InstancePath);
2287
2288 return;
2289
2290cleanup:
2291 IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED,
2292 &DeviceNode->InstancePath);
2293}
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:2195
static VOID IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
Definition: devaction.c:1812
_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:4203
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:38
#define DNF_HAS_PROBLEM
Definition: iotypes.h:183
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4202
#define KEY_READ
Definition: nt_native.h:1023
NTSTATUS IopLoadDriver(_In_ HANDLE ServiceHandle, _Out_ PDRIVER_OBJECT *DriverObject)
Definition: driver.c:1950
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:96
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) &&
632 (kvInfo->DataLength > sizeof(UNICODE_NULL)) &&
634 ((kvInfo->DataLength % sizeof(WCHAR)) == 0))
635 {
636 UNICODE_STRING classGUID = {
637 .MaximumLength = kvInfo->DataLength,
638 .Length = (USHORT)(kvInfo->DataLength - sizeof(UNICODE_NULL)),
639 .Buffer = (PVOID)((ULONG_PTR)kvInfo + kvInfo->DataOffset)
640 };
641 HANDLE ccsControlHandle;
642
643 Status = IopOpenRegistryKeyEx(&ccsControlHandle, NULL, &ccsControlClass, KEY_READ);
644 if (!NT_SUCCESS(Status))
645 {
646 DPRINT1("IopOpenRegistryKeyEx() failed for \"%wZ\" (status %x)\n",
647 &ccsControlClass, Status);
648 }
649 else
650 {
651 // open the CCS\Control\Class<ClassGUID> key
652 Status = IopOpenRegistryKeyEx(&ClassKey, ccsControlHandle, &classGUID, KEY_READ);
653 ZwClose(ccsControlHandle);
654 if (!NT_SUCCESS(Status))
655 {
656 DPRINT1("Failed to open class key \"%wZ\" (status %x)\n", &classGUID, Status);
657 }
658 }
659
660 if (ClassKey)
661 {
662 // Check the Properties key of a class too
663 // Windows fills some device properties from this key (which is protected)
664 // TODO: add the device properties from this key
665
667 HANDLE propertiesHandle;
668
669 Status = IopOpenRegistryKeyEx(&propertiesHandle, ClassKey, &properties, KEY_READ);
670 if (!NT_SUCCESS(Status))
671 {
672 DPRINT("Properties key failed to open for \"%wZ\" (status %x)\n",
673 &classGUID, Status);
674 }
675 else
676 {
677 ZwClose(propertiesHandle);
678 }
679 }
680 }
681
682 ExFreePool(kvInfo);
683 }
684
685 // the driver loading order:
686 // 1. LowerFilters
687 // 2. LowerClassFilters
688 // 3. Device driver (only one service!)
689 // 4. UpperFilters
690 // 5. UpperClassFilters
691
692 LIST_ENTRY drvListHead;
693 InitializeListHead(&drvListHead);
694
695 // lower (class) filters
696 Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, TRUE, LoadDrivers);
697 if (!NT_SUCCESS(Status))
698 {
699 goto Cleanup;
700 }
701
702 ATTACH_FILTER_DRIVERS_CONTEXT routineContext = {
703 .DriversListHead = &drvListHead,
704 .DriverType = DeviceDriver,
705 .DeviceNode = DeviceNode
706 };
707
708 RTL_QUERY_REGISTRY_TABLE queryTable[2] = {{
710 .Name = L"Service",
712 .DefaultType = REG_SZ, // REG_MULTI_SZ is not allowed here
713 .DefaultData = L"",
714 .EntryContext = (PVOID)(ULONG_PTR)LoadDrivers
715 },};
716
717 // device driver
719 (PWSTR)SubKey,
720 queryTable,
721 &routineContext,
722 NULL);
723 if (NT_SUCCESS(Status))
724 {
725 // do nothing
726 }
727 // if a driver is not found, but a device allows raw access -> proceed
729 (DeviceNode->CapabilityFlags & 0x00000040)) // CM_DEVCAP_RAWDEVICEOK
730 {
731 // add a dummy entry to the drivers list (need for later processing)
733 sizeof(*driverEntry),
735 driverEntry->DriverType = DeviceDriver;
736 InsertTailList(&drvListHead, &driverEntry->ListEntry);
737 DPRINT("No service for \"%wZ\" (RawDeviceOK)\n", &DeviceNode->InstancePath);
738 }
739 else
740 {
742 {
744 }
745 DPRINT("No service for \"%wZ\" (loadDrv: %u)\n", &DeviceNode->InstancePath, LoadDrivers);
746 goto Cleanup;
747 }
748
749 // upper (class) filters
750 Status = PiAttachFilterDrivers(&drvListHead, DeviceNode, SubKey, ClassKey, FALSE, LoadDrivers);
751 if (!NT_SUCCESS(Status))
752 {
753 goto Cleanup;
754 }
755
756 // finally loop through the stack and call AddDevice for every driver
757 for (PLIST_ENTRY listEntry = drvListHead.Flink;
758 listEntry != &drvListHead;
759 listEntry = listEntry->Flink)
760 {
761 PADD_DEV_DRIVERS_LIST driverEntry;
762 driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry);
763 PDRIVER_OBJECT driverObject = driverEntry->DriverObject;
764
765 // FIXME: ReactOS is not quite ready for this assert
766 // (legacy drivers should not have AddDevice routine)
767 // ASSERT(!(DriverObject->Flags & DRVO_LEGACY_DRIVER));
768
769 if (driverObject && driverObject->DriverExtension->AddDevice)
770 {
771 Status = driverObject->DriverExtension->AddDevice(driverEntry->DriverObject,
772 DeviceNode->PhysicalDeviceObject);
773 }
774 else if (driverObject == NULL)
775 {
776 // valid only for DeviceDriver
777 ASSERT(driverEntry->DriverType == DeviceDriver);
778 ASSERT(DeviceNode->CapabilityFlags & 0x00000040); // CM_DEVCAP_RAWDEVICEOK
780 }
781 else
782 {
783 // HACK: the driver doesn't have a AddDevice routine. We shouldn't be here,
784 // but ReactOS' PnP stack is not that correct yet
787 }
788
789 // for filter drivers we don't care about the AddDevice result
790 if (driverEntry->DriverType == DeviceDriver)
791 {
792 if (NT_SUCCESS(Status))
793 {
794 PDEVICE_OBJECT fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
795
796 // HACK: Check if we have a ACPI device (needed for power management)
797 if (fdo->DeviceType == FILE_DEVICE_ACPI)
798 {
799 static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
800
801 // There can be only one system power device
802 if (!SystemPowerDeviceNodeCreated)
803 {
806 SystemPowerDeviceNodeCreated = TRUE;
807 }
808 }
809
812 }
813 else
814 {
815 // lower filters (if already started) will be removed upon this request
818 break;
819 }
820 }
821
822#if DBG
823 PDEVICE_OBJECT attachedDO = IoGetAttachedDevice(DeviceNode->PhysicalDeviceObject);
824 if (attachedDO->Flags & DO_DEVICE_INITIALIZING)
825 {
826 DPRINT1("DO_DEVICE_INITIALIZING is not cleared on a device 0x%p!\n", attachedDO);
827 }
828#endif
829 }
830
831Cleanup:
832 while (!IsListEmpty(&drvListHead))
833 {
834 PLIST_ENTRY listEntry = RemoveHeadList(&drvListHead);
835 PADD_DEV_DRIVERS_LIST driverEntry;
836 driverEntry = CONTAINING_RECORD(listEntry, ADD_DEV_DRIVERS_LIST, ListEntry);
837
838 // drivers which don't have any devices (in case of failure) will be cleaned up
839 if (driverEntry->DriverObject)
840 {
841 ObDereferenceObject(driverEntry->DriverObject);
842 }
844 }
845
846 ZwClose(SubKey);
847 if (ClassKey != NULL)
848 {
849 ZwClose(ClassKey);
850 }
851
852 return Status;
853}
#define CM_PROB_REGISTRY
Definition: cfg.h:49
#define CM_PROB_FAILED_ADD
Definition: cfg.h:61
Definition: bufpool.h:45
#define STATUS_OBJECT_TYPE_MISMATCH
Definition: d3dkmdt.h:46
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
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 2321 of file devaction.c.

2323{
2325 BOOLEAN doProcessAgain;
2326 PDEVICE_NODE currentNode = RootNode;
2327 PDEVICE_OBJECT referencedObject;
2328
2329 do
2330 {
2331 doProcessAgain = FALSE;
2332
2333 // The device can be removed during processing, but we still need its Parent and Sibling
2334 // links to continue the tree traversal. So keep the link till the and of a cycle
2335 referencedObject = currentNode->PhysicalDeviceObject;
2336 ObReferenceObject(referencedObject);
2337
2338 // Devices with problems are skipped (unless they are not being removed)
2339 if (currentNode->Flags & DNF_HAS_PROBLEM &&
2340 currentNode->State != DeviceNodeAwaitingQueuedRemoval)
2341 {
2342 goto skipEnum;
2343 }
2344
2345 switch (currentNode->State)
2346 {
2347 case DeviceNodeUnspecified: // this state is not used
2348 break;
2350 DPRINT("DeviceNodeUninitialized %wZ\n", &currentNode->InstancePath);
2351 status = PiInitializeDevNode(currentNode);
2352 doProcessAgain = NT_SUCCESS(status);
2353 break;
2355 DPRINT("DeviceNodeInitialized %wZ\n", &currentNode->InstancePath);
2357 doProcessAgain = NT_SUCCESS(status);
2358 break;
2360 DPRINT("DeviceNodeDriversAdded %wZ\n", &currentNode->InstancePath);
2361 status = IopAssignDeviceResources(currentNode);
2362 doProcessAgain = NT_SUCCESS(status);
2363 break;
2365 DPRINT("DeviceNodeResourcesAssigned %wZ\n", &currentNode->InstancePath);
2366 // send IRP_MN_START_DEVICE
2367 PiIrpStartDevice(currentNode);
2368
2369 // skip DeviceNodeStartPending, it is probably used for an async IRP_MN_START_DEVICE
2371 doProcessAgain = TRUE;
2372 break;
2373 case DeviceNodeStartPending: // skipped on XP/2003
2374 break;
2376 DPRINT("DeviceNodeStartCompletion %wZ\n", &currentNode->InstancePath);
2377 status = currentNode->CompletionStatus;
2378 doProcessAgain = TRUE;
2379 if (!NT_SUCCESS(status))
2380 {
2384
2385 PiSetDevNodeProblem(currentNode, problem);
2387 }
2388 else
2389 {
2390 // TODO: IopDoDeferredSetInterfaceState and IopAllocateLegacyBootResources
2391 // are called here too
2392
2394 }
2395 break;
2397 DPRINT("DeviceNodeStartPostWork %wZ\n", &currentNode->InstancePath);
2398 // TODO: inspect the status
2399 status = PiStartDeviceFinal(currentNode);
2400 doProcessAgain = TRUE;
2401 break;
2402 case DeviceNodeStarted:
2403 if (currentNode->Flags & DNF_REENUMERATE)
2404 {
2405 DPRINT("DeviceNodeStarted REENUMERATE %wZ\n", &currentNode->InstancePath);
2406 currentNode->Flags &= ~DNF_REENUMERATE;
2408
2409 // again, skip DeviceNodeEnumeratePending as with the starting sequence
2411 doProcessAgain = TRUE;
2412 }
2413 else if (currentNode->Flags & DNF_RESOURCE_REQUIREMENTS_CHANGED)
2414 {
2415 if (currentNode->Flags & DNF_NON_STOPPED_REBALANCE)
2416 {
2417 PiFakeResourceRebalance(currentNode);
2418 currentNode->Flags &= ~DNF_NON_STOPPED_REBALANCE;
2419 }
2420 else
2421 {
2422 PiIrpQueryStopDevice(currentNode);
2424 }
2425
2426 doProcessAgain = TRUE;
2427 }
2428 break;
2430 // we're here after sending IRP_MN_QUERY_STOP_DEVICE
2431 status = currentNode->CompletionStatus;
2432 if (NT_SUCCESS(status))
2433 {
2434 PiIrpStopDevice(currentNode);
2436 }
2437 else
2438 {
2439 PiIrpCancelStopDevice(currentNode);
2441 }
2442 doProcessAgain = TRUE;
2443 break;
2444 case DeviceNodeStopped:
2445 // TODO: do resource rebalance (not implemented)
2446 PiFakeResourceRebalance(currentNode);
2447
2449 doProcessAgain = TRUE;
2450 break;
2452 break;
2453 case DeviceNodeEnumeratePending: // skipped on XP/2003
2454 break;
2456 DPRINT("DeviceNodeEnumerateCompletion %wZ\n", &currentNode->InstancePath);
2457 status = PiEnumerateDevice(currentNode);
2458 doProcessAgain = TRUE;
2459 break;
2461 break;
2463 DPRINT("DeviceNodeAwaitingQueuedRemoval %wZ\n", &currentNode->InstancePath);
2464 status = IopRemoveDevice(currentNode);
2465 break;
2467 break;
2469 break;
2470 case DeviceNodeRemoved:
2471 break;
2473 break;
2474 case DeviceNodeDeleted:
2475 break;
2476 default:
2477 break;
2478 }
2479
2480skipEnum:
2481 if (!doProcessAgain)
2482 {
2483 KIRQL OldIrql;
2485 /* If we have a child, simply go down the tree */
2486 if (currentNode->State != DeviceNodeRemoved && currentNode->Child != NULL)
2487 {
2488 ASSERT(currentNode->Child->Parent == currentNode);
2489 currentNode = currentNode->Child;
2490 }
2491 else
2492 {
2493 while (currentNode != RootNode)
2494 {
2495 /* All children processed -- go sideways */
2496 if (currentNode->Sibling != NULL)
2497 {
2498 ASSERT(currentNode->Sibling->Parent == currentNode->Parent);
2499 currentNode = currentNode->Sibling;
2500 break;
2501 }
2502 else
2503 {
2504 /* We're the last sibling -- go back up */
2505 ASSERT(currentNode->Parent->LastChild == currentNode);
2506 currentNode = currentNode->Parent;
2507 }
2508 /* We already visited the parent and all its children, so keep looking */
2509 }
2510 }
2512 }
2513 ObDereferenceObject(referencedObject);
2514 } while (doProcessAgain || currentNode != RootNode);
2515}
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:2105
static NTSTATUS IopRemoveDevice(PDEVICE_NODE DeviceNode)
Definition: devaction.c:2069
static NTSTATUS PiStartDeviceFinal(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:1582
static VOID PiFakeResourceRebalance(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:2297
static NTSTATUS PiInitializeDevNode(_In_ PDEVICE_NODE DeviceNode)
Definition: devaction.c:1193
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:1005
PNP_DEVNODE_STATE State
Definition: iotypes.h:1001
ULONG Flags
Definition: iotypes.h:1007
struct _DEVICE_NODE * Parent
Definition: iotypes.h:996
UNICODE_STRING InstancePath
Definition: iotypes.h:1013
Definition: ps.c:97
@ BusRelations
Definition: iotypes.h:2152

Referenced by PipDeviceActionWorker().

◆ PiEnumerateDevice()

static NTSTATUS PiEnumerateDevice ( _In_ PDEVICE_NODE  DeviceNode)
static

Definition at line 2105 of file devaction.c.

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

2299{
2301
2302 PCM_RESOURCE_LIST bootConfig = NULL;
2303 PIO_RESOURCE_REQUIREMENTS_LIST resourceRequirements = NULL;
2304
2305 PiIrpQueryResources(DeviceNode, &bootConfig);
2306 PiIrpQueryResourceRequirements(DeviceNode, &resourceRequirements);
2307
2308 DeviceNode->BootResources = bootConfig;
2309 DeviceNode->ResourceRequirements = resourceRequirements;
2310
2311 if (bootConfig)
2312 {
2314 }
2315
2316 DeviceNode->Flags &= ~DNF_RESOURCE_REQUIREMENTS_CHANGED;
2317}
#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 1193 of file devaction.c.

1195{
1198 HANDLE InstanceKey = NULL;
1199 UNICODE_STRING InstancePathU;
1200 PDEVICE_OBJECT OldDeviceObject;
1201
1202 DPRINT("PiProcessNewDevNode(%p)\n", DeviceNode);
1203 DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject);
1204
1205 /*
1206 * FIXME: For critical errors, cleanup and disable device, but always
1207 * return STATUS_SUCCESS.
1208 */
1209
1211 if (!NT_SUCCESS(Status))
1212 {
1214 {
1215 DPRINT1("IopCreateDeviceInstancePath() failed with status 0x%lx\n", Status);
1216 }
1217 return Status;
1218 }
1219
1220 /* Verify that this is not a duplicate */
1221 OldDeviceObject = IopGetDeviceObjectFromDeviceInstance(&InstancePathU);
1222 if (OldDeviceObject != NULL)
1223 {
1224 PDEVICE_NODE OldDeviceNode = IopGetDeviceNode(OldDeviceObject);
1225
1226 DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU);
1227 DPRINT1("Current instance parent: '%wZ'\n", &DeviceNode->Parent->InstancePath);
1228 DPRINT1("Old instance parent: '%wZ'\n", &OldDeviceNode->Parent->InstancePath);
1229
1230 KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
1231 0x01,
1232 (ULONG_PTR)DeviceNode->PhysicalDeviceObject,
1233 (ULONG_PTR)OldDeviceObject,
1234 0);
1235 }
1236
1237 DeviceNode->InstancePath = InstancePathU;
1238
1239 DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
1240
1241 /*
1242 * Create registry key for the instance id, if it doesn't exist yet
1243 */
1244 Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
1245 if (!NT_SUCCESS(Status))
1246 {
1247 DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
1248
1249 /* We have to return success otherwise we abort the traverse operation */
1250 return STATUS_SUCCESS;
1251 }
1252
1253 IopQueryHardwareIds(DeviceNode, InstanceKey);
1254
1255 IopQueryCompatibleIds(DeviceNode, InstanceKey);
1256
1257 DeviceNode->Flags |= DNF_IDS_QUERIED;
1258
1259 // Set the device's DeviceDesc and LocationInformation fields
1260 PiSetDevNodeText(DeviceNode, InstanceKey);
1261
1262 DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
1263
1264 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1267 NULL);
1269 {
1271
1272 DeviceNode->ChildBusNumber = BusInformation->BusNumber;
1273 DeviceNode->ChildInterfaceType = BusInformation->LegacyBusType;
1274 DeviceNode->ChildBusTypeIndex = IopGetBusTypeGuidIndex(&BusInformation->BusTypeGuid);
1276 }
1277 else
1278 {
1279 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
1280
1281 DeviceNode->ChildBusNumber = 0xFFFFFFF0;
1282 DeviceNode->ChildInterfaceType = InterfaceTypeUndefined;
1283 DeviceNode->ChildBusTypeIndex = -1;
1284 }
1285
1286 DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
1287
1288 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1291 NULL);
1293 {
1296 }
1297 else
1298 {
1299 DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
1300 DeviceNode->BootResources = NULL;
1301 }
1302
1303 DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
1304
1305 Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
1308 NULL);
1309 if (NT_SUCCESS(Status))
1310 {
1312 }
1313 else
1314 {
1315 DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
1316 DeviceNode->ResourceRequirements = NULL;
1317 }
1318
1319 if (InstanceKey != NULL)
1320 {
1322 }
1323
1324 // Try installing a critical device, so its Service key is populated
1325 // then call IopSetServiceEnumData to populate service's Enum key.
1326 // That allows us to start devices during an early boot
1328 IopSetServiceEnumData(DeviceNode, InstanceKey);
1329
1330 ZwClose(InstanceKey);
1331
1333
1335 {
1336 /* Report the device to the user-mode pnp manager */
1337 IopQueueDeviceInstallEvent(&GUID_DEVICE_ENUMERATED,
1338 &DeviceNode->InstancePath);
1339 }
1340
1341 return STATUS_SUCCESS;
1342}
static NTSTATUS IopQueryCompatibleIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:1025
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:1092
static NTSTATUS IopSetServiceEnumData(_In_ PDEVICE_NODE DeviceNode, _In_ HANDLE InstanceHandle)
Definition: devaction.c:1346
static NTSTATUS IopQueryHardwareIds(PDEVICE_NODE DeviceNode, HANDLE InstanceKey)
Definition: devaction.c:960
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 1654 of file devaction.c.

1657{
1658 KIRQL oldIrql;
1659
1664
1665 PDEVICE_OBJECT vpbDevObj = DeviceObject, targetDevice = DeviceObject;
1666
1667 // walk the device stack down, stop on a first mounted device
1668 do
1669 {
1670 if (vpbDevObj->Vpb)
1671 {
1672 // two locks are needed here
1673 KeWaitForSingleObject(&vpbDevObj->DeviceLock, Executive, KernelMode, FALSE, NULL);
1674 IoAcquireVpbSpinLock(&oldIrql);
1675
1677 {
1678 vpbDevObj->Vpb->Flags &= ~VPB_REMOVE_PENDING;
1679 }
1680 else
1681 {
1682 vpbDevObj->Vpb->Flags |= VPB_REMOVE_PENDING;
1683 }
1684
1685 BOOLEAN isMounted = (_Bool)(vpbDevObj->Vpb->Flags & VPB_MOUNTED);
1686
1687 if (isMounted)
1688 {
1689 targetDevice = vpbDevObj->Vpb->DeviceObject;
1690 }
1691
1692 IoReleaseVpbSpinLock(oldIrql);
1693 KeSetEvent(&vpbDevObj->DeviceLock, IO_NO_INCREMENT, FALSE);
1694
1695 if (isMounted)
1696 {
1697 break;
1698 }
1699 }
1700
1702 vpbDevObj = vpbDevObj->AttachedDevice;
1704 } while (vpbDevObj);
1705
1706 ASSERT(targetDevice);
1707
1708 PVOID info;
1709 IO_STACK_LOCATION stack = {.MajorFunction = IRP_MJ_PNP, .MinorFunction = MinorFunction};
1710
1711 return IopSynchronousCall(targetDevice, &stack, &info);
1712}
#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 2546 of file devaction.c.

2548{
2549 PLIST_ENTRY ListEntry;
2551 KIRQL OldIrql;
2552 PDEVICE_NODE deviceNode;
2554
2557 {
2560 Request = CONTAINING_RECORD(ListEntry, DEVICE_ACTION_REQUEST, RequestListEntry);
2561
2562 ASSERT(Request->DeviceObject);
2563
2564 deviceNode = IopGetDeviceNode(Request->DeviceObject);
2565 ASSERT(deviceNode);
2566
2568
2569 DPRINT("Processing PnP request %p: DeviceObject - %p, Action - %s\n",
2570 Request, Request->DeviceObject, ActionToStr(Request->Action));
2571
2572 switch (Request->Action)
2573 {
2575 {
2576 if (deviceNode->State == DeviceNodeInitialized &&
2577 !(deviceNode->Flags & DNF_HAS_PROBLEM))
2578 {
2580 }
2581 break;
2582 }
2585 deviceNode->Flags |= DNF_REENUMERATE;
2586 PiDevNodeStateMachine(deviceNode);
2587 break;
2588
2590 // TODO: the operation is a no-op for everything except removed nodes
2591 // for removed nodes, it returns them back to DeviceNodeUninitialized
2592 if (deviceNode->State == DeviceNodeRemoved)
2593 {
2594 deviceNode->State = DeviceNodeUninitialized;
2595 }
2597 break;
2598
2600 // This action is triggered from usermode, when a driver is installed
2601 // for a non-critical PDO
2602 if (deviceNode->State == DeviceNodeInitialized &&
2603 !(deviceNode->Flags & DNF_HAS_PROBLEM))
2604 {
2605 PiDevNodeStateMachine(deviceNode);
2606 }
2607 else
2608 {
2609 DPRINT1("NOTE: attempt to start an already started/uninitialized device %wZ\n",
2610 &deviceNode->InstancePath);
2612 }
2613 break;
2614
2615 case PiActionQueryState:
2616 // This action is only valid for started devices. If the device is not yet
2617 // started, the PnP manager issues IRP_MN_QUERY_PNP_DEVICE_STATE by itself.
2618 if (deviceNode->State == DeviceNodeStarted)
2619 {
2620 // Issue a IRP_MN_QUERY_PNP_DEVICE_STATE request: it will update node's flags
2621 // and then do enumeration if something has changed
2622 status = PiUpdateDeviceState(deviceNode);
2623 if (NT_SUCCESS(status))
2624 {
2625 PiDevNodeStateMachine(deviceNode);
2626 }
2627 }
2628 // TODO: Windows may return STATUS_DELETE_PENDING here
2630 break;
2631
2632 default:
2633 DPRINT1("Unimplemented device action %u\n", Request->Action);
2635 break;
2636 }
2637
2638 if (Request->CompletionStatus)
2639 {
2640 *Request->CompletionStatus = status;
2641 }
2642
2643 if (Request->CompletionEvent)
2644 {
2645 KeSetEvent(Request->CompletionEvent, IO_NO_INCREMENT, FALSE);
2646 }
2647
2648 DPRINT("Finished processing PnP request %p\n", Request);
2649 ObDereferenceObject(Request->DeviceObject);
2652 }
2656}
#define STATUS_NOT_IMPLEMENTED
Definition: d3dkmdt.h:42
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:2321
BOOLEAN IopDeviceActionInProgress
Definition: devaction.c:48
static NTSTATUS PiUpdateDeviceState(_In_ PDEVICE_NODE DeviceNode)
Processes the IoInvalidateDeviceState request.
Definition: devaction.c:1525
@ 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
_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 2727 of file devaction.c.

2730{
2731 KEVENT opFinished;
2733
2737
2738 return status;
2739}
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:2668
#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 2668 of file devaction.c.

2673{
2675 KIRQL OldIrql;
2676
2678
2679 DPRINT("PiQueueDeviceAction: DeviceObject - %p, Request - %p, Action - %s\n",
2680 DeviceObject, Request, ActionToStr(Action));
2681
2683
2684 Request->DeviceObject = DeviceObject;
2685 Request->Action = Action;
2686 Request->CompletionEvent = CompletionEvent;
2687 Request->CompletionStatus = CompletionStatus;
2688
2691
2693 {
2695
2699
2701 return;
2702 }
2703
2705 {
2707 return;
2708 }
2712
2715}
static VOID NTAPI PipDeviceActionWorker(_In_opt_ PVOID Context)
Definition: devaction.c:2546
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 1092 of file devaction.c.

1095{
1096 PAGED_CODE();
1097
1098 LCID localeId;
1099
1100 // Get the Locale ID
1102 if (!NT_SUCCESS(status))
1103 {
1104 DPRINT1("ZwQueryDefaultLocale() failed with status %x\n", status);
1105 return;
1106 }
1107
1108 // Step 1: Write the DeviceDesc value if does not exist
1109
1110 UNICODE_STRING valDeviceDesc = RTL_CONSTANT_STRING(L"DeviceDesc");
1111 ULONG len;
1112
1113 status = ZwQueryValueKey(InstanceKey, &valDeviceDesc, KeyValueBasicInformation, NULL, 0, &len);
1115 {
1116 PWSTR deviceDesc = NULL;
1118
1119 if (deviceDesc && deviceDesc[0] != UNICODE_NULL)
1120 {
1121 status = ZwSetValueKey(InstanceKey,
1122 &valDeviceDesc,
1123 0,
1124 REG_SZ,
1125 deviceDesc,
1126 ((ULONG)wcslen(deviceDesc) + 1) * sizeof(WCHAR));
1127
1128 if (!NT_SUCCESS(status))
1129 {
1130 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1131 }
1132 }
1133 else
1134 {
1135 // This key is mandatory, so even if the Irp fails, we still write it
1136 UNICODE_STRING unknownDeviceDesc = RTL_CONSTANT_STRING(L"Unknown device");
1137 DPRINT("Driver didn't return DeviceDesc (status %x)\n", status);
1138
1139 status = ZwSetValueKey(InstanceKey,
1140 &valDeviceDesc,
1141 0,
1142 REG_SZ,
1143 unknownDeviceDesc.Buffer,
1144 unknownDeviceDesc.MaximumLength);
1145 if (!NT_SUCCESS(status))
1146 {
1147 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1148 }
1149 }
1150
1151 if (deviceDesc)
1152 {
1153 ExFreePoolWithTag(deviceDesc, 0);
1154 }
1155 }
1156
1157 // Step 2: LocaltionInformation is overwritten unconditionally
1158
1159 PWSTR deviceLocationInfo = NULL;
1161 localeId,
1163 &deviceLocationInfo);
1164
1165 if (deviceLocationInfo && deviceLocationInfo[0] != UNICODE_NULL)
1166 {
1167 UNICODE_STRING valLocationInfo = RTL_CONSTANT_STRING(L"LocationInformation");
1168
1169 status = ZwSetValueKey(InstanceKey,
1170 &valLocationInfo,
1171 0,
1172 REG_SZ,
1173 deviceLocationInfo,
1174 ((ULONG)wcslen(deviceLocationInfo) + 1) * sizeof(WCHAR));
1175 if (!NT_SUCCESS(status))
1176 {
1177 DPRINT1("ZwSetValueKey() failed (Status %x)\n", status);
1178 }
1179 }
1180
1181 if (deviceLocationInfo)
1182 {
1183 ExFreePoolWithTag(deviceLocationInfo, 0);
1184 }
1185 else
1186 {
1187 DPRINT("Driver didn't return LocationInformation (status %x)\n", status);
1188 }
1189}
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 1582 of file devaction.c.

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

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 1525 of file devaction.c.

1527{
1528 PNP_DEVICE_STATE PnPFlags;
1530
1532 if (!NT_SUCCESS(Status))
1533 {
1534 return Status;
1535 }
1536
1537 if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE)
1538 DeviceNode->UserFlags |= DNUF_NOT_DISABLEABLE;
1539 else
1540 DeviceNode->UserFlags &= ~DNUF_NOT_DISABLEABLE;
1541
1542 if (PnPFlags & PNP_DEVICE_DONT_DISPLAY_IN_UI)
1543 DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
1544 else
1545 DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
1546
1547 if (PnPFlags & PNP_DEVICE_REMOVED || PnPFlags & PNP_DEVICE_DISABLED)
1548 {
1550 PnPFlags & PNP_DEVICE_DISABLED
1553
1555 }
1556 else if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
1557 {
1558 // Query resource rebalance
1559
1560 if (PnPFlags & PNP_DEVICE_FAILED)
1562 else
1564
1565 // Clear DNF_NO_RESOURCE_REQUIRED just in case (will be set back if needed)
1566 DeviceNode->Flags &= ~DNF_NO_RESOURCE_REQUIRED;
1567
1568 // This will be caught up later by enumeration
1570 }
1571 else if (PnPFlags & PNP_DEVICE_FAILED)
1572 {
1575 }
1576
1577 return STATUS_SUCCESS;
1578}
#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().