ReactOS  0.4.15-dev-1397-g19779b3
devnode.c File Reference
#include <ntoskrnl.h>
#include <debug.h>
Include dependency graph for devnode.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

PDEVICE_NODE FASTCALL IopGetDeviceNode (_In_ PDEVICE_OBJECT DeviceObject)
 
PDEVICE_NODE NTAPI PipAllocateDeviceNode (_In_opt_ PDEVICE_OBJECT PhysicalDeviceObject)
 
NTSTATUS IopCreateDeviceNode (_In_ PDEVICE_NODE ParentNode, _In_opt_ PDEVICE_OBJECT PhysicalDeviceObject, _In_opt_ PUNICODE_STRING ServiceName, _Out_ PDEVICE_NODE *DeviceNode)
 Creates a device node. More...
 
NTSTATUS IopFreeDeviceNode (_In_ PDEVICE_NODE DeviceNode)
 
static NTSTATUS IopFindNextDeviceNodeForTraversal (_In_ PDEVICETREE_TRAVERSE_CONTEXT Context)
 
NTSTATUS IopTraverseDeviceTree (_In_ PDEVICETREE_TRAVERSE_CONTEXT Context)
 

Variables

PDEVICE_NODE IopRootDeviceNode
 
KSPIN_LOCK IopDeviceTreeLock
 
LONG IopNumberDeviceNodes
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file devnode.c.

Function Documentation

◆ IopCreateDeviceNode()

NTSTATUS IopCreateDeviceNode ( _In_ PDEVICE_NODE  ParentNode,
_In_opt_ PDEVICE_OBJECT  PhysicalDeviceObject,
_In_opt_ PUNICODE_STRING  ServiceName,
_Out_ PDEVICE_NODE DeviceNode 
)

Creates a device node.

Parameters
[in]ParentNodePointer to parent device node
[in]PhysicalDeviceObjectPointer to PDO for device object. Pass NULL to have the root device node create one (eg. for legacy drivers)
[in]ServiceNameThe service (driver) name for a node. Pass NULL to set UNKNOWN as a service
[out]DeviceNodePointer to storage for created device node
Returns
Status, indicating the result of an operation

Definition at line 89 of file devnode.c.

94 {
97  KIRQL OldIrql;
98  UNICODE_STRING FullServiceName;
99  UNICODE_STRING LegacyPrefix = RTL_CONSTANT_STRING(L"LEGACY_");
100  UNICODE_STRING UnknownDeviceName = RTL_CONSTANT_STRING(L"UNKNOWN");
101  UNICODE_STRING KeyName, ClassName;
102  PUNICODE_STRING ServiceName1;
103  ULONG LegacyValue;
105  HANDLE InstanceHandle;
106 
107  DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
108  ParentNode, PhysicalDeviceObject, ServiceName);
109 
111  if (!Node)
112  {
114  }
115 
116  RtlZeroMemory(Node, sizeof(DEVICE_NODE));
117 
118  if (!ServiceName)
119  ServiceName1 = &UnknownDeviceName;
120  else
121  ServiceName1 = ServiceName;
122 
124  {
125  FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName1->Length + sizeof(UNICODE_NULL);
126  FullServiceName.Length = 0;
127  FullServiceName.Buffer = ExAllocatePool(PagedPool, FullServiceName.MaximumLength);
128  if (!FullServiceName.Buffer)
129  {
132  }
133 
134  RtlAppendUnicodeStringToString(&FullServiceName, &LegacyPrefix);
135  RtlAppendUnicodeStringToString(&FullServiceName, ServiceName1);
136  RtlUpcaseUnicodeString(&FullServiceName, &FullServiceName, FALSE);
137 
138  Status = PnpRootCreateDevice(&FullServiceName, NULL, &PhysicalDeviceObject, &Node->InstancePath);
139  if (!NT_SUCCESS(Status))
140  {
141  DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status);
142  ExFreePool(FullServiceName.Buffer);
144  return Status;
145  }
146 
147  /* Create the device key for legacy drivers */
148  Status = IopCreateDeviceKeyPath(&Node->InstancePath, REG_OPTION_VOLATILE, &InstanceHandle);
149  if (!NT_SUCCESS(Status))
150  {
151  ExFreePool(FullServiceName.Buffer);
153  return Status;
154  }
155 
156  Node->ServiceName.MaximumLength = ServiceName1->Length + sizeof(UNICODE_NULL);
157  Node->ServiceName.Length = 0;
158  Node->ServiceName.Buffer = ExAllocatePool(PagedPool, Node->ServiceName.MaximumLength);
159  if (!Node->ServiceName.Buffer)
160  {
161  ZwClose(InstanceHandle);
162  ExFreePool(FullServiceName.Buffer);
164  return Status;
165  }
166 
167  RtlCopyUnicodeString(&Node->ServiceName, ServiceName1);
168 
169  if (ServiceName)
170  {
171  RtlInitUnicodeString(&KeyName, L"Service");
172  Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName->Buffer, ServiceName->Length + sizeof(UNICODE_NULL));
173  }
174 
175  if (NT_SUCCESS(Status))
176  {
177  RtlInitUnicodeString(&KeyName, L"Legacy");
178  LegacyValue = 1;
179  Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
180 
181  RtlInitUnicodeString(&KeyName, L"ConfigFlags");
182  LegacyValue = 0;
183  ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
184 
185  if (NT_SUCCESS(Status))
186  {
187  RtlInitUnicodeString(&KeyName, L"Class");
188  RtlInitUnicodeString(&ClassName, L"LegacyDriver");
189  Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassName.Buffer, ClassName.Length + sizeof(UNICODE_NULL));
190  if (NT_SUCCESS(Status))
191  {
192  RtlInitUnicodeString(&KeyName, L"ClassGUID");
193  RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
194  Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassGUID.Buffer, ClassGUID.Length + sizeof(UNICODE_NULL));
195  if (NT_SUCCESS(Status))
196  {
197  // FIXME: Retrieve the real "description" by looking at the "DisplayName" string
198  // of the corresponding CurrentControlSet\Services\xxx entry for this driver.
199  RtlInitUnicodeString(&KeyName, L"DeviceDesc");
200  Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName1->Buffer, ServiceName1->Length + sizeof(UNICODE_NULL));
201  }
202  }
203  }
204  }
205 
206  ZwClose(InstanceHandle);
207  ExFreePool(FullServiceName.Buffer);
208 
209  if (!NT_SUCCESS(Status))
210  {
211  ExFreePool(Node->ServiceName.Buffer);
213  return Status;
214  }
215 
220  }
221 
222  Node->PhysicalDeviceObject = PhysicalDeviceObject;
223 
224  ((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode = Node;
225 
226  if (ParentNode)
227  {
229  Node->Parent = ParentNode;
230  Node->Sibling = NULL;
231  if (ParentNode->LastChild == NULL)
232  {
233  ParentNode->Child = Node;
234  ParentNode->LastChild = Node;
235  }
236  else
237  {
238  ParentNode->LastChild->Sibling = Node;
239  ParentNode->LastChild = Node;
240  }
242  Node->Level = ParentNode->Level + 1;
243  }
244 
246 
247  *DeviceNode = Node;
248 
249  return STATUS_SUCCESS;
250 }
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define DNF_PROCESSED
Definition: iotypes.h:167
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
NTSTATUS RtlUpcaseUnicodeString(PUNICODE_STRING dst, PUNICODE_STRING src, BOOLEAN Alloc)
Definition: string_lib.cpp:46
#define TAG_IO_DEVNODE
Definition: tag.h:89
USHORT MaximumLength
Definition: env_spec_w32.h:370
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
KSPIN_LOCK IopDeviceTreeLock
Definition: devnode.c:19
NTSTATUS NTAPI IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, IN ULONG CreateOptions, OUT PHANDLE Handle)
Definition: pnpmgr.c:666
LONG NTSTATUS
Definition: precomp.h:26
struct _EXTENDED_DEVOBJ_EXTENSION * PEXTENDED_DEVOBJ_EXTENSION
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1155
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
union node Node
Definition: types.h:1255
#define IopDeviceNodeSetFlag(DeviceNode, Flag)
Definition: io.h:142
void DPRINT(...)
Definition: polytest.cpp:61
static const WCHAR ClassGUID[]
Definition: devclass.c:30
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2697
#define DNF_STARTED
Definition: iotypes.h:168
Status
Definition: gdiplustypes.h:24
LPTSTR ServiceName
Definition: ServiceMain.c:15
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
Definition: Node.h:9
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
static const WCHAR L[]
Definition: oid.c:1250
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
#define DNF_LEGACY_DRIVER
Definition: iotypes.h:181
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define NULL
Definition: types.h:112
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define DPRINT1
Definition: precomp.h:8
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define STATUS_SUCCESS
Definition: shellext.h:65
#define REG_OPTION_VOLATILE
Definition: nt_native.h:1060
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define DNF_ADDED
Definition: iotypes.h:179
#define REG_DWORD
Definition: sdbapi.c:596
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
NTSTATUS PnpRootCreateDevice(IN PUNICODE_STRING ServiceName, IN OPTIONAL PDRIVER_OBJECT DriverObject, OUT PDEVICE_OBJECT *PhysicalDeviceObject, OUT OPTIONAL PUNICODE_STRING FullInstancePath)
Definition: pnproot.c:185
Definition: dlist.c:348
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#define REG_SZ
Definition: layer.c:22

◆ IopFindNextDeviceNodeForTraversal()

static NTSTATUS IopFindNextDeviceNodeForTraversal ( _In_ PDEVICETREE_TRAVERSE_CONTEXT  Context)
static

Definition at line 324 of file devnode.c.

326 {
327  /* If we have a child, simply go down the tree */
328  if (Context->DeviceNode->Child != NULL)
329  {
330  ASSERT(Context->DeviceNode->Child->Parent == Context->DeviceNode);
331  Context->DeviceNode = Context->DeviceNode->Child;
332  return STATUS_SUCCESS;
333  }
334 
335  while (Context->DeviceNode != Context->FirstDeviceNode)
336  {
337  /* All children processed -- go sideways */
338  if (Context->DeviceNode->Sibling != NULL)
339  {
340  ASSERT(Context->DeviceNode->Sibling->Parent == Context->DeviceNode->Parent);
341  Context->DeviceNode = Context->DeviceNode->Sibling;
342  return STATUS_SUCCESS;
343  }
344 
345  /* We're the last sibling -- go back up */
346  ASSERT(Context->DeviceNode->Parent->LastChild == Context->DeviceNode);
347  Context->DeviceNode = Context->DeviceNode->Parent;
348 
349  /* We already visited the parent and all its children, so keep looking */
350  }
351 
352  /* Done with all children of the start node -- stop enumeration */
353  return STATUS_UNSUCCESSFUL;
354 }
#define ASSERT(a)
Definition: mode.c:45
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define NULL
Definition: types.h:112
#define STATUS_SUCCESS
Definition: shellext.h:65

Referenced by IopTraverseDeviceTree().

◆ IopFreeDeviceNode()

NTSTATUS IopFreeDeviceNode ( _In_ PDEVICE_NODE  DeviceNode)

Definition at line 253 of file devnode.c.

255 {
256  KIRQL OldIrql;
257  PDEVICE_NODE PrevSibling = NULL;
258 
259  /* All children must be deleted before a parent is deleted */
260  ASSERT(!DeviceNode->Child);
261  ASSERT(DeviceNode->PhysicalDeviceObject);
262 
264 
265  /* Get previous sibling */
266  if (DeviceNode->Parent && DeviceNode->Parent->Child != DeviceNode)
267  {
268  PrevSibling = DeviceNode->Parent->Child;
269  while (PrevSibling->Sibling != DeviceNode)
270  PrevSibling = PrevSibling->Sibling;
271  }
272 
273  /* Unlink from parent if it exists */
274  if (DeviceNode->Parent)
275  {
276  if (DeviceNode->Parent->LastChild == DeviceNode)
277  {
278  DeviceNode->Parent->LastChild = PrevSibling;
279  if (PrevSibling)
280  PrevSibling->Sibling = NULL;
281  }
282  if (DeviceNode->Parent->Child == DeviceNode)
283  DeviceNode->Parent->Child = DeviceNode->Sibling;
284  }
285 
286  /* Unlink from sibling list */
287  if (PrevSibling)
288  PrevSibling->Sibling = DeviceNode->Sibling;
289 
291 
292  RtlFreeUnicodeString(&DeviceNode->InstancePath);
293 
294  RtlFreeUnicodeString(&DeviceNode->ServiceName);
295 
296  if (DeviceNode->ResourceList)
297  {
298  ExFreePool(DeviceNode->ResourceList);
299  }
300 
301  if (DeviceNode->ResourceListTranslated)
302  {
303  ExFreePool(DeviceNode->ResourceListTranslated);
304  }
305 
306  if (DeviceNode->ResourceRequirements)
307  {
308  ExFreePool(DeviceNode->ResourceRequirements);
309  }
310 
311  if (DeviceNode->BootResources)
312  {
313  ExFreePool(DeviceNode->BootResources);
314  }
315 
316  ((PEXTENDED_DEVOBJ_EXTENSION)DeviceNode->PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode = NULL;
318 
319  return STATUS_SUCCESS;
320 }
#define TAG_IO_DEVNODE
Definition: tag.h:89
KSPIN_LOCK IopDeviceTreeLock
Definition: devnode.c:19
struct _EXTENDED_DEVOBJ_EXTENSION * PEXTENDED_DEVOBJ_EXTENSION
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define ASSERT(a)
Definition: mode.c:45
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
Definition: Node.h:9
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#define NULL
Definition: types.h:112
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
struct _DEVICE_NODE * Sibling
Definition: iotypes.h:823
#define STATUS_SUCCESS
Definition: shellext.h:65
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define ExFreePool(addr)
Definition: env_spec_w32.h:352

◆ IopGetDeviceNode()

PDEVICE_NODE FASTCALL IopGetDeviceNode ( _In_ PDEVICE_OBJECT  DeviceObject)

Definition at line 27 of file devnode.c.

29 {
30  return ((PEXTENDED_DEVOBJ_EXTENSION)DeviceObject->DeviceObjectExtension)->DeviceNode;
31 }
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055

◆ IopTraverseDeviceTree()

NTSTATUS IopTraverseDeviceTree ( _In_ PDEVICETREE_TRAVERSE_CONTEXT  Context)

Definition at line 357 of file devnode.c.

359 {
362 
363  DPRINT("Context 0x%p\n", Context);
364 
365  DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %p Context 0x%p)\n",
366  Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context);
367 
368  /* Start from the specified device node */
369  Context->DeviceNode = Context->FirstDeviceNode;
370 
371  /* Traverse the device tree */
372  do
373  {
374  DeviceNode = Context->DeviceNode;
375 
376  /* HACK: Keep a reference to the PDO so we can keep traversing the tree
377  * if the device is deleted. In a perfect world, children would have to be
378  * deleted before their parents, and we'd restart the traversal after
379  * deleting a device node. */
380  ObReferenceObject(DeviceNode->PhysicalDeviceObject);
381 
382  /* Call the action routine */
383  Status = (Context->Action)(DeviceNode, Context->Context);
384  if (NT_SUCCESS(Status))
385  {
386  /* Find next device node */
387  ASSERT(Context->DeviceNode == DeviceNode);
389  }
390 
391  /* We need to either abort or make progress */
392  ASSERT(!NT_SUCCESS(Status) || Context->DeviceNode != DeviceNode);
393 
394  ObDereferenceObject(DeviceNode->PhysicalDeviceObject);
395  } while (NT_SUCCESS(Status));
396 
398  {
399  /* The action routine just wanted to terminate the traversal with status
400  code STATUS_SUCCESS */
402  }
403 
404  return Status;
405 }
LONG NTSTATUS
Definition: precomp.h:26
void DPRINT(...)
Definition: polytest.cpp:61
static NTSTATUS IopFindNextDeviceNodeForTraversal(_In_ PDEVICETREE_TRAVERSE_CONTEXT Context)
Definition: devnode.c:324
Status
Definition: gdiplustypes.h:24
#define ASSERT(a)
Definition: mode.c:45
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define ObDereferenceObject
Definition: obfuncs.h:203
Definition: Node.h:9
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ObReferenceObject
Definition: obfuncs.h:204
#define STATUS_SUCCESS
Definition: shellext.h:65

◆ PipAllocateDeviceNode()

PDEVICE_NODE NTAPI PipAllocateDeviceNode ( _In_opt_ PDEVICE_OBJECT  PhysicalDeviceObject)

Definition at line 35 of file devnode.c.

37 {
39  PAGED_CODE();
40 
41  /* Allocate it */
43  if (!DeviceNode) return DeviceNode;
44 
45  /* Statistics */
47 
48  /* Set it up */
50  DeviceNode->InterfaceType = InterfaceTypeUndefined;
51  DeviceNode->BusNumber = -1;
52  DeviceNode->ChildInterfaceType = InterfaceTypeUndefined;
53  DeviceNode->ChildBusNumber = -1;
54  DeviceNode->ChildBusTypeIndex = -1;
55 // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE);
56  InitializeListHead(&DeviceNode->DeviceArbiterList);
57  InitializeListHead(&DeviceNode->DeviceTranslatorList);
58  InitializeListHead(&DeviceNode->TargetDeviceNotify);
59  InitializeListHead(&DeviceNode->DockInfo.ListEntry);
60  InitializeListHead(&DeviceNode->PendedSetInterfaceState);
61 
62  /* Check if there is a PDO */
64  {
65  /* Link it and remove the init flag */
66  DeviceNode->PhysicalDeviceObject = PhysicalDeviceObject;
67  ((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode = DeviceNode;
69  }
70 
71  /* Return the node */
72  return DeviceNode;
73 }
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
#define TAG_IO_DEVNODE
Definition: tag.h:89
struct _EXTENDED_DEVOBJ_EXTENSION * PEXTENDED_DEVOBJ_EXTENSION
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1155
LONG IopNumberDeviceNodes
Definition: devnode.c:21
Definition: Node.h:9
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define InterlockedIncrement
Definition: armddk.h:53
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define PAGED_CODE()

Variable Documentation

◆ IopDeviceTreeLock

◆ IopNumberDeviceNodes

LONG IopNumberDeviceNodes

Definition at line 21 of file devnode.c.

Referenced by PipAllocateDeviceNode().

◆ IopRootDeviceNode