00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "iop.h"
00024
00025
00026
00027
00028
00029 typedef struct _ENUM_CONTEXT{
00030 PENUM_CALLBACK CallersCallback;
00031 PVOID
CallersContext;
00032 }
ENUM_CONTEXT, *
PENUM_CONTEXT;
00033
00034
00035
00036
00037
00038
NTSTATUS
00039
IopForAllDeviceNodesCallback(
00040 IN
PDEVICE_NODE DeviceNode,
00041 IN PVOID Context
00042 );
00043
00044
#ifdef ALLOC_PRAGMA
00045
#pragma alloc_text(PAGE, IopAllocateDeviceNode)
00046
#pragma alloc_text(PAGE, IopForAllDeviceNodes)
00047
#pragma alloc_text(PAGE, IopForAllChildDeviceNodes)
00048
#pragma alloc_text(PAGE, IopForAllDeviceNodesCallback)
00049
#pragma alloc_text(PAGE, IopDestroyDeviceNode)
00050
#pragma alloc_text(PAGE, IopInsertTreeDeviceNode)
00051
#pragma alloc_text(PAGE, IopRemoveTreeDeviceNode)
00052
#endif
00053
00054
00055
PDEVICE_NODE
00056 IopAllocateDeviceNode(
00057 IN
PDEVICE_OBJECT PhysicalDeviceObject
00058 )
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 {
00080
PDEVICE_NODE deviceNode;
00081
00082
PAGED_CODE();
00083
00084 deviceNode =
ExAllocatePoolWithTag(
00085
NonPagedPool,
00086
sizeof(
DEVICE_NODE),
00087
IOP_DNOD_TAG
00088 );
00089
00090
if (deviceNode ==
NULL ){
00091
return NULL;
00092 }
00093
00094 InterlockedIncrement (&
IopNumberDeviceNodes);
00095
00096 RtlZeroMemory(deviceNode,
sizeof(
DEVICE_NODE));
00097 deviceNode->
InterfaceType = InterfaceTypeUndefined;
00098 deviceNode->
BusNumber = (ULONG)-1;
00099 deviceNode->
ChildInterfaceType = InterfaceTypeUndefined;
00100 deviceNode->
ChildBusNumber = (ULONG)-1;
00101 deviceNode->
ChildBusTypeIndex = (
USHORT)-1;
00102
00103
KeInitializeEvent( &deviceNode->
EnumerationMutex,
00104 SynchronizationEvent,
00105
TRUE );
00106
00107 InitializeListHead(&deviceNode->
DeviceArbiterList);
00108 InitializeListHead(&deviceNode->
DeviceTranslatorList);
00109
00110
if (PhysicalDeviceObject){
00111
00112 deviceNode->
PhysicalDeviceObject = PhysicalDeviceObject;
00113 PhysicalDeviceObject->
DeviceObjectExtension->
DeviceNode = (PVOID)deviceNode;
00114 PhysicalDeviceObject->
Flags &= ~
DO_DEVICE_INITIALIZING;
00115 }
00116
00117 InitializeListHead(&deviceNode->
TargetDeviceNotify);
00118
00119 InitializeListHead(&deviceNode->
DockInfo.ListEntry);
00120
00121 InitializeListHead(&deviceNode->
PendedSetInterfaceState);
00122
00123
return deviceNode;
00124 }
00125
00126
NTSTATUS
00127 IopForAllDeviceNodes(
00128 IN
PENUM_CALLBACK Callback,
00129 IN PVOID Context
00130 )
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 {
00154
ENUM_CONTEXT enumContext;
00155
NTSTATUS status;
00156
00157
PAGED_CODE();
00158
00159 enumContext.
CallersCallback = Callback;
00160 enumContext.
CallersContext = Context;
00161
00162
00163
00164
00165
00166
00167
00168
IopAcquireEnumerationLock(
IopRootDeviceNode);
00169
00170 status =
IopForAllChildDeviceNodes(
IopRootDeviceNode,
00171
IopForAllDeviceNodesCallback,
00172 (PVOID)&enumContext );
00173
00174
IopReleaseEnumerationLock(
IopRootDeviceNode);
00175
return status;
00176 }
00177
00178
NTSTATUS
00179 IopForAllChildDeviceNodes(
00180 IN
PDEVICE_NODE Parent,
00181 IN PENUM_CALLBACK Callback,
00182 IN PVOID Context
00183 )
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 {
00211
PDEVICE_NODE nextChild = Parent->Child;
00212
PDEVICE_NODE child;
00213
NTSTATUS status = STATUS_SUCCESS;
00214
00215
PAGED_CODE();
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
while (nextChild &&
NT_SUCCESS(status)) {
00228 child = nextChild;
00229 nextChild = child->
Sibling;
00230 status = Callback(child, Context);
00231 }
00232
00233
return status;
00234 }
00235
00236
NTSTATUS
00237 IopForAllDeviceNodesCallback(
00238 IN
PDEVICE_NODE DeviceNode,
00239 IN PVOID Context
00240 )
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 {
00262
PENUM_CONTEXT enumContext;
00263
NTSTATUS status;
00264
00265
PAGED_CODE();
00266
00267 enumContext = (
PENUM_CONTEXT)Context;
00268
00269
00270
00271
00272
00273 status =
00274 enumContext->
CallersCallback(DeviceNode, enumContext->
CallersContext);
00275
00276
if (
NT_SUCCESS(status)) {
00277
00278
00279
00280
00281
00282
IopAcquireEnumerationLock(DeviceNode);
00283
00284
if( DeviceNode->Child) {
00285
00286 status =
IopForAllChildDeviceNodes(
00287 DeviceNode,
00288
IopForAllDeviceNodesCallback,
00289 Context);
00290 }
00291
IopReleaseEnumerationLock(DeviceNode);
00292 }
00293
00294
return status;
00295 }
00296
VOID
00297 IopDestroyDeviceNode(
00298 IN
PDEVICE_NODE DeviceNode
00299 )
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 {
00322 PLIST_ENTRY listHead, nextEntry, entry;
00323
PPI_RESOURCE_TRANSLATOR_ENTRY handlerEntry;
00324
PINTERFACE interface;
00325
00326
PAGED_CODE();
00327
00328
if (DeviceNode) {
00329
00330
if ((DeviceNode->PhysicalDeviceObject->Flags &
DO_BUS_ENUMERATED_DEVICE) &&
00331 DeviceNode->Parent !=
NULL) {
00332
00333
KeBugCheckEx( PNP_DETECTED_FATAL_ERROR,
00334
PNP_ERR_ACTIVE_PDO_FREED,
00335 (ULONG_PTR)DeviceNode->PhysicalDeviceObject,
00336 0,
00337 0);
00338 }
00339
00340
#if DBG
00341
00342
00343
00344
00345
00346
00347
00348
ASSERT(DeviceNode->Child ==
NULL &&
00349 DeviceNode->Sibling ==
NULL &&
00350 DeviceNode->LastChild ==
NULL
00351 );
00352
00353
ASSERT(DeviceNode->DockInfo.SerialNumber ==
NULL &&
00354 IsListEmpty(&DeviceNode->DockInfo.ListEntry));
00355
00356
if (DeviceNode->PhysicalDeviceObject->Flags &
DO_BUS_ENUMERATED_DEVICE) {
00357
ASSERT (DeviceNode->Parent == 0);
00358 }
00359
00360
if (DeviceNode->PreviousResourceList) {
00361
ExFreePool(DeviceNode->PreviousResourceList);
00362 }
00363
if (DeviceNode->PreviousResourceRequirements) {
00364
ExFreePool(DeviceNode->PreviousResourceRequirements);
00365 }
00366
00367
00368
00369
00370
00371
00372
ASSERT((DeviceNode->UserFlags &
DNUF_NOT_DISABLEABLE) == 0);
00373
ASSERT(DeviceNode->DisableableDepends == 0);
00374
00375
#endif
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
if (DeviceNode->Flags &
DNF_LEGACY_RESOURCE_DEVICENODE) {
00387
00388
PDEVICE_NODE resourceDeviceNode;
00389
00390
for ( resourceDeviceNode = (
PDEVICE_NODE)DeviceNode->
OverUsed1.LegacyDeviceNode;
00391 resourceDeviceNode;
00392 resourceDeviceNode = resourceDeviceNode->
OverUsed2.NextResourceDeviceNode) {
00393
00394
if (resourceDeviceNode->
OverUsed2.NextResourceDeviceNode == DeviceNode) {
00395
00396 resourceDeviceNode->
OverUsed2.NextResourceDeviceNode = DeviceNode->OverUsed2.NextResourceDeviceNode;
00397
break;
00398
00399 }
00400 }
00401 }
00402
00403
if (DeviceNode->DuplicatePDO) {
00404
ObDereferenceObject(DeviceNode->DuplicatePDO);
00405 }
00406
if (DeviceNode->ServiceName.Length != 0) {
00407
ExFreePool(DeviceNode->ServiceName.Buffer);
00408 }
00409
if (DeviceNode->InstancePath.Length != 0) {
00410
ExFreePool(DeviceNode->InstancePath.Buffer);
00411 }
00412
if (DeviceNode->ResourceRequirements) {
00413
ExFreePool(DeviceNode->ResourceRequirements);
00414 }
00415
00416
00417
00418
00419
IopUncacheInterfaceInformation(DeviceNode->PhysicalDeviceObject) ;
00420
00421
00422
00423
00424
00425
while (!IsListEmpty(&DeviceNode->PendedSetInterfaceState)) {
00426
00427
PPENDING_SET_INTERFACE_STATE entry;
00428
00429 entry = (
PPENDING_SET_INTERFACE_STATE)RemoveHeadList(&DeviceNode->PendedSetInterfaceState);
00430
00431
ExFreePool(entry->
LinkName.Buffer);
00432
00433
ExFreePool(entry);
00434 }
00435
00436 DeviceNode->PhysicalDeviceObject->DeviceObjectExtension->DeviceNode =
NULL;
00437
ExFreePool(DeviceNode);
00438
IopNumberDeviceNodes--;
00439 }
00440 }
00441
00442
00443
00444
00445
00446
VOID
00447 IopInsertTreeDeviceNode (
00448 IN
PDEVICE_NODE ParentNode,
00449 IN
PDEVICE_NODE DeviceNode
00450 )
00451
00452 {
00453
PDEVICE_NODE deviceNode;
00454 PLIST_ENTRY *p;
00455 LONG i;
00456
00457
00458
00459
00460
00461 DeviceNode->Parent = ParentNode;
00462
if (ParentNode->LastChild) {
00463
ASSERT(ParentNode->LastChild->Sibling ==
NULL);
00464 ParentNode->LastChild->Sibling = DeviceNode;
00465 ParentNode->LastChild = DeviceNode;
00466 }
else {
00467
ASSERT(ParentNode->Child ==
NULL);
00468 ParentNode->Child = ParentNode->LastChild = DeviceNode;
00469 }
00470
00471
00472
00473
00474
00475
for (deviceNode = DeviceNode;
00476 deviceNode !=
IopRootDeviceNode;
00477 deviceNode = deviceNode->
Parent) {
00478 DeviceNode->Level++;
00479 }
00480
00481
if (DeviceNode->Level >
IopMaxDeviceNodeLevel) {
00482
IopMaxDeviceNodeLevel = DeviceNode->Level;
00483 }
00484
00485
00486
00487
00488
00489
IoDeviceNodeTreeSequence += 1;
00490 }
00491
00492
00493
VOID
00494 IopRemoveTreeDeviceNode (
00495 IN
PDEVICE_NODE DeviceNode
00496 )
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 {
00514
PDEVICE_NODE *Node;
00515
00516
00517
00518
00519
00520
00521
00522 Node = &DeviceNode->
Parent->
Child;
00523
while (*Node != DeviceNode) {
00524 Node = &(*Node)->
Sibling;
00525 }
00526 *Node = DeviceNode->
Sibling;
00527
00528
if (DeviceNode->Parent->Child ==
NULL) {
00529 DeviceNode->
Parent->
LastChild =
NULL;
00530 }
else {
00531
while (*Node) {
00532 Node = &(*Node)->
Sibling;
00533 }
00534 DeviceNode->
Parent->
LastChild = CONTAINING_RECORD(Node,
DEVICE_NODE, Sibling);
00535 }
00536
00537
00538
00539
00540
00541
IopOrphanNotification(DeviceNode);
00542
00543
00544
00545
00546
00547 DeviceNode->Parent =
NULL;
00548 DeviceNode->Child =
NULL;
00549 DeviceNode->Sibling =
NULL;
00550 DeviceNode->LastChild =
NULL;
00551 }
00552
00553
#if DBG
00554
00555
VOID
00556 IopCheckForTargetDevice (
00557 IN
PDEVICE_OBJECT TargetDevice,
00558 IN
PDEVICE_OBJECT DeviceObject
00559 )
00560 {
00561
if (!TargetDevice || !DeviceObject) {
00562
return ;
00563 }
00564
00565
ASSERT (DeviceObject != TargetDevice);
00566
00567
while (DeviceObject->AttachedDevice) {
00568 DeviceObject = DeviceObject->AttachedDevice;
00569
ASSERT (DeviceObject != TargetDevice);
00570 }
00571 }
00572
00573
VOID
00574 IopCheckDeviceNodeTree (
00575 IN
PDEVICE_OBJECT TargetDevice OPTIONAL,
00576 IN
PDEVICE_NODE TargetNode OPTIONAL
00577 )
00578
00579
00580 {
00581 KIRQL OldIrql;
00582
PDEVICE_NODE Node;
00583
00584
return ;
00585
00586
IopAcquireDeviceTreeLock();
00587 ExAcquireSpinLock (&IopDatabaseLock, &OldIrql);
00588
00589
00590
00591
00592
00593 Node =
IopRootDeviceNode;
00594
while (Node->
Child) {
00595 Node = Node->
Child;
00596 }
00597
00598
00599
00600
00601
00602
while (Node !=
IopRootDeviceNode) {
00603
00604
00605
00606
00607
00608
ASSERT (Node != TargetNode);
00609
00610
00611
00612
00613
00614 IopCheckForTargetDevice (TargetDevice, Node->
PhysicalDeviceObject);
00615 IopCheckForTargetDevice (TargetDevice, Node->
DuplicatePDO);
00616
00617
00618
00619
00620
00621
if (Node->
Sibling) {
00622 Node = Node->
Sibling;
00623
while (Node->
Child) {
00624 Node = Node->
Child;
00625 }
00626 }
else {
00627 Node = Node->
Parent;
00628 }
00629 }
00630
00631 ExReleaseSpinLock (&IopDatabaseLock, OldIrql);
00632
IopReleaseDeviceTreeLock ();
00633
00634 }
00635
#endif
00636