00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "iop.h"
00022
#include "wdmguid.h"
00023
00024
#ifdef POOL_TAGGING
00025
#undef ExAllocatePool
00026
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'edpP')
00027
#endif
00028
00029
00030
00031
00032
00033
NTSTATUS
00034
IopCancelPendingEject(
00035 IN
PPENDING_RELATIONS_LIST_ENTRY EjectEntry
00036 );
00037
00038
VOID
00039
IopDelayedRemoveWorker(
00040 IN PVOID Context
00041 );
00042
00043 BOOLEAN
00044
IopDeleteLockedDeviceNode(
00045 IN
PDEVICE_NODE DeviceNode,
00046 IN ULONG IrpCode,
00047 IN
PRELATION_LIST RelationsList,
00048 IN BOOLEAN IsKernelInitiated,
00049 IN ULONG Problem
00050 );
00051
00052
NTSTATUS
00053
IopProcessRelation(
00054 IN
PDEVICE_OBJECT DeviceObject,
00055 IN PLUGPLAY_DEVICE_DELETE_TYPE OperationCode,
00056 IN
PRELATION_LIST RelationsList,
00057 IN BOOLEAN IsKernelInitiated,
00058 IN BOOLEAN IsDirectDescendant
00059 );
00060
00061
NTSTATUS
00062
IopUnloadAttachedDriver(
00063 IN
PDRIVER_OBJECT DriverObject
00064 );
00065
00066 WORK_QUEUE_ITEM IopDeviceRemovalWorkItem;
00067
00068
#ifdef ALLOC_PRAGMA
00069
#pragma alloc_text(PAGE, IopChainDereferenceComplete)
00070
#pragma alloc_text(PAGE, IopDelayedRemoveWorker)
00071
#pragma alloc_text(PAGE, IopDeleteLockedDeviceNode)
00072
#pragma alloc_text(PAGE, IopDeleteLockedDeviceNodes)
00073
#pragma alloc_text(PAGE, IopLockDeviceRemovalRelations)
00074
#pragma alloc_text(PAGE, IopProcessCompletedEject)
00075
#pragma alloc_text(PAGE, IopProcessRelation)
00076
#pragma alloc_text(PAGE, IopQueuePendingEject)
00077
#pragma alloc_text(PAGE, IopQueuePendingSurpriseRemoval)
00078
#pragma alloc_text(PAGE, IopRequestDeviceRemoval)
00079
#pragma alloc_text(PAGE, IopUnloadAttachedDriver)
00080
#pragma alloc_text(PAGE, IopUnlockDeviceRemovalRelations)
00081
#endif
00082
00083
VOID
00084 IopChainDereferenceComplete(
00085 IN
PDEVICE_OBJECT PhysicalDeviceObject
00086 )
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 {
00109
PPENDING_RELATIONS_LIST_ENTRY entry;
00110 PLIST_ENTRY link;
00111 ULONG count;
00112 ULONG taggedCount;
00113
NTSTATUS status;
00114
00115
PAGED_CODE();
00116
00117
00118
00119
00120
00121
IopAcquireDeviceTreeLock();
00122
00123
00124
00125
00126
for (link =
IopPendingSurpriseRemovals.Flink;
00127 link != &
IopPendingSurpriseRemovals;
00128 link = link->Flink) {
00129
00130 entry = CONTAINING_RECORD(link,
PENDING_RELATIONS_LIST_ENTRY, Link);
00131
00132
00133
00134
00135 status =
IopSetRelationsTag( entry->
RelationsList, PhysicalDeviceObject,
TRUE );
00136
00137
if (
NT_SUCCESS(status)) {
00138 taggedCount =
IopGetRelationsTaggedCount( entry->
RelationsList );
00139 count =
IopGetRelationsCount( entry->
RelationsList );
00140
00141
if (taggedCount == count) {
00142
00143
00144
00145 RemoveEntryList( link );
00146
00147
IopReleaseDeviceTreeLock();
00148
00149
if (
PsGetCurrentProcess() !=
PsInitialSystemProcess) {
00150
00151
00152
00153
00154
00155
00156
00157
ExInitializeWorkItem( &entry->
WorkItem,
00158
IopDelayedRemoveWorker,
00159 entry);
00160
00161
ExQueueWorkItem(&entry->
WorkItem,
DelayedWorkQueue);
00162
00163 }
else {
00164
00165
00166
00167
00168
00169
00170
IopDelayedRemoveWorker( entry );
00171
00172 }
00173
00174
return;
00175 }
00176
00177
break;
00178 }
00179 }
00180
00181
IopReleaseDeviceTreeLock();
00182
00183
ASSERT(link != &
IopPendingSurpriseRemovals);
00184 }
00185
00186
VOID
00187 IopDelayedRemoveWorker(
00188 IN PVOID Context
00189 )
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210 {
00211
PPENDING_RELATIONS_LIST_ENTRY entry = (
PPENDING_RELATIONS_LIST_ENTRY)Context;
00212
00213
PAGED_CODE();
00214
00215
IopSetAllRelationsTags( entry->
RelationsList,
FALSE );
00216
00217
IopDeleteLockedDeviceNodes( entry->
DeviceObject,
00218 entry->
RelationsList,
00219 RemoveDevice,
00220
TRUE,
00221
FALSE,
00222 entry->
Problem,
00223
NULL);
00224
00225
IopFreeRelationList( entry->
RelationsList );
00226
00227
ExFreePool( entry );
00228 }
00229
00230
00231 BOOLEAN
00232 IopDeleteLockedDeviceNode(
00233 IN
PDEVICE_NODE DeviceNode,
00234 IN ULONG IrpCode,
00235 IN
PRELATION_LIST RelationsList,
00236 IN BOOLEAN IsKernelInitiated,
00237 IN ULONG Problem
00238 )
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 {
00258
PDEVICE_OBJECT deviceObject = DeviceNode->PhysicalDeviceObject;
00259
PDEVICE_OBJECT *attachedDevices, device1, *device2;
00260
PDRIVER_OBJECT *attachedDrivers, *driver;
00261 ULONG length = 0;
00262 BOOLEAN success =
TRUE;
00263
NTSTATUS status;
00264
00265
PAGED_CODE();
00266
00267 PIDBGMSG( PIDBG_REMOVAL,
00268 (
"IopDeleteLockedDeviceNode: Entered\n DeviceNode = 0x%p\n IrpCode = 0x%08X\n RelationsList = 0x%p\n IsKernelInitiated = %d\n Problem = %d\n",
00269 DeviceNode,
00270 IrpCode,
00271 RelationsList,
00272 IsKernelInitiated,
00273 Problem));
00274
00275
00276
00277
00278
00279
if (!IsKernelInitiated && !(DeviceNode->Flags &
DNF_ADDED)) {
00280 PIDBGMSG(PIDBG_REMOVAL, (
"IopDeleteLockedDeviceNode: Device already deleted\n"));
00281
if (IrpCode ==
IRP_MN_REMOVE_DEVICE) {
00282
while (deviceObject) {
00283 deviceObject->
DeviceObjectExtension->
ExtensionFlags &= ~(
DOE_REMOVE_PENDING |
DOE_REMOVE_PROCESSED);
00284 deviceObject->
DeviceObjectExtension->
ExtensionFlags |=
DOE_START_PENDING;
00285 deviceObject = deviceObject->
AttachedDevice;
00286 }
00287 }
00288
return TRUE;
00289 }
00290
00291
if (IrpCode ==
IRP_MN_SURPRISE_REMOVAL) {
00292
00293
00294
00295
00296
00297 PIDBGMSG( PIDBG_REMOVAL,
00298 (
"IopDeleteLockedDeviceNode: Sending surprise remove irp to device = 0x%p\n",
00299 deviceObject));
00300
00301 status =
IopRemoveDevice(deviceObject,
IRP_MN_SURPRISE_REMOVAL);
00302
00303
if (
NT_SUCCESS(status)) {
00304
00305 PIDBGMSG(PIDBG_REMOVAL, (
"IopDeleteLockedDeviceNode: Releasing devices resources\n"));
00306
00307
IopReleaseDeviceResources(DeviceNode,
FALSE);
00308
00309 }
else if (!(DeviceNode->Flags &
DNF_NO_RESOURCE_REQUIRED)) {
00310 success =
FALSE;
00311 }
00312
00313
ASSERT(DeviceNode->DockInfo.DockStatus !=
DOCK_ARRIVING);
00314
00315 }
else if (IrpCode ==
IRP_MN_REMOVE_DEVICE) {
00316
00317
PDEVICE_NODE child, nextChild, parent;
00318
PDEVICE_OBJECT childPDO;
00319
00320
00321
00322
00323
00324 child = DeviceNode->
Child;
00325
while (child) {
00326
if (child->
Flags &
DNF_ENUMERATED) {
00327 child->
Flags &= ~
DNF_ENUMERATED;
00328 }
00329
00330
ASSERT(!(child->
Flags &
DNF_ADDED));
00331
00332
if (child->
Flags & (
DNF_HAS_RESOURCE |
DNF_RESOURCE_REPORTED |
DNF_HAS_BOOT_CONFIG)) {
00333
00334
00335
00336
00337
00338 PIDBGMSG( PIDBG_REMOVAL,
00339 (
"IopDeleteLockedDeviceNode: Sending remove irp to orphaned child device = 0x%p\n",
00340 child->
PhysicalDeviceObject));
00341
00342
IopRemoveDevice(child->
PhysicalDeviceObject,
IRP_MN_REMOVE_DEVICE);
00343
00344 PIDBGMSG(PIDBG_REMOVAL,
00345 (
"IopDeleteLockedDeviceNode: Releasing resources for child device = 0x%p\n",
00346 child->
PhysicalDeviceObject));
00347
00348
IopReleaseDeviceResources(child,
FALSE);
00349
00350
00351
00352
00353 }
00354
00355
00356
00357 nextChild = child->
Sibling;
00358 parent = child->
Parent;
00359
00360 PIDBGMSG( PIDBG_REMOVAL,
00361 (
"IopDeleteLockedDeviceNode: Cleaning up registry values, instance = %wZ\n",
00362 &child->
InstancePath));
00363
00364
KeEnterCriticalRegion();
00365
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
00366
00367
IopCleanupDeviceRegistryValues(&child->
InstancePath,
FALSE);
00368
00369 PIDBGMSG( PIDBG_REMOVAL,
00370 (
"IopDeleteLockedDeviceNode: Removing DevNode tree, DevNode = 0x%p\n",
00371 child));
00372
00373 childPDO = child->
PhysicalDeviceObject;
00374
IopRemoveTreeDeviceNode(child);
00375
IopRemoveRelationFromList(RelationsList, childPDO);
00376
ObDereferenceObject(childPDO);
00377
00378
ExReleaseResource(&
PpRegistryDeviceResource);
00379
KeLeaveCriticalRegion();
00380
00381
if (child->
LockCount != 0) {
00382
00383
ASSERT(child->
LockCount == 1);
00384
00385 child->
LockCount = 0;
00386
00387
KeSetEvent(&child->
EnumerationMutex, 0,
FALSE);
00388
ObDereferenceObject(childPDO);
00389
00390
ASSERT(parent->
LockCount > 0);
00391
00392
if (--parent->
LockCount == 0) {
00393
KeSetEvent(&parent->
EnumerationMutex, 0,
FALSE);
00394
ObDereferenceObject(parent->
PhysicalDeviceObject);
00395 }
00396 }
00397
00398 child = nextChild;
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408 device1 = deviceObject->
AttachedDevice;
00409
while (device1) {
00410 length++;
00411 device1 = device1->
AttachedDevice;
00412 }
00413
00414 attachedDevices =
NULL;
00415 attachedDrivers =
NULL;
00416
if (length != 0) {
00417 length = (length + 2) *
sizeof(
PDEVICE_OBJECT);
00418 attachedDevices = (
PDEVICE_OBJECT *)
ExAllocatePool (
PagedPool, length);
00419
if (!attachedDevices) {
00420
return FALSE;
00421 }
00422 attachedDrivers = (
PDRIVER_OBJECT *)
ExAllocatePool (
PagedPool, length);
00423
if (!attachedDrivers) {
00424
ExFreePool(attachedDevices);
00425
return FALSE;
00426 }
00427 RtlZeroMemory(attachedDevices, length);
00428 RtlZeroMemory(attachedDrivers, length);
00429 device1 = deviceObject->
AttachedDevice;
00430 device2 = attachedDevices;
00431 driver = attachedDrivers;
00432
while (device1) {
00433
ObReferenceObject(device1);
00434 *device2++ = device1;
00435 *driver++ = device1->DriverObject;
00436 device1 = device1->AttachedDevice;
00437 }
00438 }
00439
00440
00441
00442
00443
00444 PIDBGMSG( PIDBG_REMOVAL,
00445 (
"IopDeleteLockedDeviceNode: Sending remove irp to device = 0x%p\n",
00446 deviceObject));
00447
00448
IopRemoveDevice(deviceObject,
IRP_MN_REMOVE_DEVICE);
00449
00450 PIDBGMSG(PIDBG_REMOVAL, (
"IopDeleteLockedDeviceNode: Releasing devices resources\n"));
00451
00452
IopReleaseDeviceResources(DeviceNode, (BOOLEAN)!(DeviceNode->Flags &
DNF_DEVICE_GONE));
00453
00454
if (!(DeviceNode->Flags &
DNF_ENUMERATED)) {
00455
00456
00457
00458
00459
ASSERT(DeviceNode->DockInfo.DockStatus !=
DOCK_ARRIVING) ;
00460
if ((DeviceNode->DockInfo.DockStatus ==
DOCK_DEPARTING)||
00461 (DeviceNode->DockInfo.DockStatus ==
DOCK_EJECTIRP_COMPLETED)) {
00462
IopHardwareProfileCommitRemovedDock(DeviceNode);
00463 }
00464 }
00465
00466
00467
00468
00469
00470
00471
if (device2 = attachedDevices) {
00472 driver = attachedDrivers;
00473
while (*device2) {
00474 (*device2)->DeviceObjectExtension->ExtensionFlags &= ~(
DOE_REMOVE_PENDING |
DOE_REMOVE_PROCESSED);
00475 (*device2)->DeviceObjectExtension->ExtensionFlags |=
DOE_START_PENDING;
00476
IopUnloadAttachedDriver(*driver);
00477
ObDereferenceObject(*device2);
00478 device2++;
00479 driver++;
00480 }
00481
ExFreePool(attachedDevices);
00482
ExFreePool(attachedDrivers);
00483 }
00484
00485
00486
00487
00488
00489
if (!(DeviceNode->Flags &
DNF_HAS_PRIVATE_PROBLEM)) {
00490
00491
ASSERT(!
IopDoesDevNodeHaveProblem(DeviceNode) ||
00492
IopIsDevNodeProblem(DeviceNode, Problem) ||
00493 Problem == CM_PROB_DEVICE_NOT_THERE ||
00494 Problem == CM_PROB_DISABLED);
00495
00496
IopClearDevNodeProblem(DeviceNode);
00497
IopSetDevNodeProblem(DeviceNode, Problem);
00498 }
00499
00500 deviceObject->
DeviceObjectExtension->
ExtensionFlags &= ~(
DOE_REMOVE_PENDING |
DOE_REMOVE_PROCESSED);
00501 deviceObject->
DeviceObjectExtension->
ExtensionFlags |=
DOE_START_PENDING;
00502
00503
if (DeviceNode->Flags &
DNF_REMOVE_PENDING_CLOSES) {
00504
00505
ASSERT(DeviceNode->LockCount == 0);
00506
00507 DeviceNode->Flags &= ~
DNF_REMOVE_PENDING_CLOSES;
00508
00509
if ((DeviceNode->Flags &
DNF_DEVICE_GONE) && DeviceNode->Parent !=
NULL) {
00510
00511
ASSERT(DeviceNode->Child ==
NULL);
00512
00513 PIDBGMSG( PIDBG_REMOVAL,
00514 (
"IopDeleteLockedDeviceNode: Cleaning up registry values, instance = %wZ\n",
00515 &DeviceNode->InstancePath));
00516
00517
KeEnterCriticalRegion();
00518
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
00519
00520
IopCleanupDeviceRegistryValues(&DeviceNode->InstancePath,
FALSE);
00521
00522
ExReleaseResource(&
PpRegistryDeviceResource);
00523
KeLeaveCriticalRegion();
00524
00525 PIDBGMSG( PIDBG_REMOVAL,
00526 (
"IopDeleteLockedDeviceNode: Removing DevNode tree, DevNode = 0x%p\n",
00527 DeviceNode));
00528
00529
IopRemoveTreeDeviceNode(DeviceNode);
00530
ObDereferenceObject(deviceObject);
00531 }
00532 }
00533
00534 }
else {
00535
00536
00537
00538
00539
00540 PIDBGMSG( PIDBG_REMOVAL,
00541 (
"IopDeleteLockedDeviceNode: Sending QueryRemove/CancelRemove irp to device = 0x%p\n",
00542 deviceObject));
00543
00544 status =
IopRemoveDevice(deviceObject, IrpCode);
00545
if (!
NT_SUCCESS(status) && IrpCode ==
IRP_MN_QUERY_REMOVE_DEVICE) {
00546 PIDBGMSG( PIDBG_REMOVAL,
00547 (
"IopDeleteLockedDeviceNode: QueryRemove vetoed by device = 0x%p\n",
00548 deviceObject));
00549
00550 success =
FALSE;
00551 }
00552 }
00553
return success;
00554 }
00555
00556
NTSTATUS
00557 IopDeleteLockedDeviceNodes(
00558 IN
PDEVICE_OBJECT DeviceObject,
00559 IN
PRELATION_LIST RelationsList,
00560 IN PLUGPLAY_DEVICE_DELETE_TYPE OperationCode,
00561 IN BOOLEAN IsKernelInitiated,
00562 IN BOOLEAN ProcessIndirectDescendants,
00563 IN ULONG Problem,
00564 OUT
PDEVICE_OBJECT *VetoingDevice OPTIONAL
00565 )
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588 {
00589
NTSTATUS status = STATUS_SUCCESS;
00590
PDEVICE_NODE deviceNode;
00591
PDEVICE_OBJECT deviceObject, relatedDeviceObject;
00592 ULONG i;
00593 ULONG marker;
00594 ULONG irpCode;
00595 BOOLEAN tagged, directDescendant;
00596
00597
PAGED_CODE();
00598
00599 PIDBGMSG( PIDBG_REMOVAL,
00600 (
"IopDeleteLockedDeviceNodes: Entered\n DeviceObject = 0x%p\n RelationsList = 0x%p\n OperationCode = %d\n",
00601 DeviceObject,
00602 RelationsList,
00603 OperationCode));
00604
00605 deviceNode = (
PDEVICE_NODE) DeviceObject->DeviceObjectExtension->DeviceNode;
00606
00607
switch (OperationCode) {
00608
case QueryRemoveDevice:
00609 irpCode =
IRP_MN_QUERY_REMOVE_DEVICE;
00610
break;
00611
00612
case CancelRemoveDevice:
00613 irpCode =
IRP_MN_CANCEL_REMOVE_DEVICE;
00614
break;
00615
00616
case RemoveDevice:
00617 irpCode =
IRP_MN_REMOVE_DEVICE;
00618
break;
00619
00620
case SurpriseRemoveDevice:
00621 irpCode =
IRP_MN_SURPRISE_REMOVAL;
00622
break;
00623
00624
case EjectDevice:
00625
default:
00626
ASSERT(0);
00627
return STATUS_INVALID_PARAMETER;
00628 }
00629
00630 marker = 0;
00631
while (
IopEnumerateRelations( RelationsList,
00632 &marker,
00633 &deviceObject,
00634 &directDescendant,
00635 &tagged,
00636
TRUE)) {
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
if (!tagged && (directDescendant || ProcessIndirectDescendants)) {
00651 deviceNode = (
PDEVICE_NODE)deviceObject->
DeviceObjectExtension->
DeviceNode;
00652
00653
if (OperationCode == SurpriseRemoveDevice) {
00654 deviceNode->
Flags |=
DNF_REMOVE_PENDING_CLOSES;
00655 }
00656
00657
if (OperationCode == QueryRemoveDevice && !(deviceNode->
Flags &
DNF_STARTED)) {
00658
00659
00660
00661
continue;
00662 }
00663
00664
if (!
IopDeleteLockedDeviceNode( deviceNode,
00665 irpCode,
00666 RelationsList,
00667 IsKernelInitiated,
00668 Problem)) {
00669
00670
if (OperationCode == QueryRemoveDevice) {
00671
00672
if (VetoingDevice !=
NULL) {
00673 *VetoingDevice = deviceObject;
00674 }
00675
00676
IopDeleteLockedDeviceNode( deviceNode,
00677
IRP_MN_CANCEL_REMOVE_DEVICE,
00678 RelationsList,
00679 IsKernelInitiated,
00680 Problem);
00681
00682
while (
IopEnumerateRelations( RelationsList,
00683 &marker,
00684 &deviceObject,
00685
NULL,
00686 &tagged,
00687
FALSE)) {
00688
00689
if (!tagged) {
00690
00691 deviceNode = (
PDEVICE_NODE)deviceObject->
DeviceObjectExtension->
DeviceNode;
00692
00693
IopDeleteLockedDeviceNode( deviceNode,
00694
IRP_MN_CANCEL_REMOVE_DEVICE,
00695 RelationsList,
00696 IsKernelInitiated,
00697 Problem);
00698 }
00699 }
00700
00701 status = STATUS_UNSUCCESSFUL;
00702
goto exit;
00703 }
00704 }
00705 }
00706 }
00707
00708
00709
00710
00711
00712
00713
if (OperationCode == RemoveDevice) {
00714 PIDBGMSG( PIDBG_REMOVAL,
00715 (
"IopDeleteLockedDeviceNodes: Calling IopRequestDeviceEnumeration\n"));
00716
00717
IopRequestDeviceAction(
NULL,
AssignResources,
NULL,
NULL);
00718 }
00719
00720
exit:
00721
return status;
00722 }
00723
00724
NTSTATUS
00725 IopLockDeviceRemovalRelations(
00726 IN
PDEVICE_OBJECT DeviceObject,
00727 IN PLUGPLAY_DEVICE_DELETE_TYPE OperationCode,
00728 OUT
PRELATION_LIST *RelationsList,
00729 IN BOOLEAN IsKernelInitiated
00730 )
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757 {
00758
NTSTATUS status;
00759
PDEVICE_OBJECT deviceObject;
00760
PDEVICE_NODE deviceNode, parent;
00761
PRELATION_LIST relationsList;
00762 ULONG marker;
00763 BOOLEAN tagged;
00764
00765
PAGED_CODE();
00766
00767 *RelationsList =
NULL;
00768
00769 deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
00770
00771
if (!IsKernelInitiated && !(deviceNode->
Flags &
DNF_ADDED) && OperationCode != EjectDevice) {
00772
00773
return STATUS_SUCCESS;
00774 }
00775
00776
00777
00778
00779
00780
ASSERT(DeviceObject !=
IopRootDeviceNode->
PhysicalDeviceObject);
00781
00782
00783
00784
00785
00786
IopAcquireDeviceTreeLock();
00787
00788
if (IsKernelInitiated) {
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 }
00801
00802
if ((relationsList =
IopAllocateRelationList()) ==
NULL) {
00803
00804
IopReleaseDeviceTreeLock();
00805
return STATUS_INSUFFICIENT_RESOURCES;
00806 }
00807
00808
00809
00810
00811 status =
IopProcessRelation( DeviceObject,
00812 OperationCode,
00813 relationsList,
00814 IsKernelInitiated,
00815
TRUE);
00816
00817
ASSERT(status != STATUS_INVALID_DEVICE_REQUEST);
00818
00819 marker = 0;
00820
while (
IopEnumerateRelations( relationsList,
00821 &marker,
00822 &deviceObject,
00823
NULL,
00824 &tagged,
00825
FALSE)) {
00826
00827 deviceNode = (
PDEVICE_NODE)deviceObject->
DeviceObjectExtension->
DeviceNode;
00828
00829
00830
00831
00832
00833
00834
00835
if (
NT_SUCCESS(status)) {
00836
00837
00838
00839
00840
00841
if (tagged) {
00842
00843
00844
00845
00846
00847
00848
00849
if (deviceNode->
LockCount++ == 0) {
00850
ObReferenceObject(deviceNode->
PhysicalDeviceObject);
00851
KeClearEvent(&deviceNode->
EnumerationMutex);
00852 }
00853 }
00854
00855 parent = deviceNode->
Parent;
00856
00857
if (parent->
LockCount++ == 0) {
00858
ObReferenceObject(parent->
PhysicalDeviceObject);
00859
KeClearEvent(&parent->
EnumerationMutex);
00860 }
00861
00862 }
else {
00863
00864
if (!tagged) {
00865
00866
00867
00868
00869
00870
00871
00872
ASSERT(deviceNode->
LockCount > 0);
00873
00874
if (--deviceNode->
LockCount == 0) {
00875
KeSetEvent(&deviceNode->
EnumerationMutex, 0,
FALSE);
00876
ObDereferenceObject(deviceObject);
00877 }
00878 }
00879 }
00880 }
00881
00882
00883
00884
00885
00886
IopReleaseDeviceTreeLock();
00887
00888
if (
NT_SUCCESS(status)) {
00889
IopCompressRelationList(&relationsList);
00890 *RelationsList = relationsList;
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909 }
else {
00910
IopFreeRelationList(relationsList);
00911 }
00912
00913
return status;
00914 }
00915
00916
NTSTATUS
00917 IopProcessRelation(
00918 IN
PDEVICE_OBJECT DeviceObject,
00919 IN PLUGPLAY_DEVICE_DELETE_TYPE OperationCode,
00920 IN
PRELATION_LIST RelationsList,
00921 IN BOOLEAN IsKernelInitiated,
00922 IN BOOLEAN IsDirectDescendant
00923 )
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942 {
00943
PDEVICE_NODE deviceNode, relatedDeviceNode;
00944
PDEVICE_OBJECT relatedDeviceObject;
00945
PDEVICE_RELATIONS deviceRelations;
00946 PLIST_ENTRY ejectLink;
00947
PPENDING_RELATIONS_LIST_ENTRY ejectEntry;
00948
PRELATION_LIST pendingRelationList;
00949
PIRP pendingIrp;
00950
NTSTATUS status;
00951 ULONG i;
00952
00953
PAGED_CODE();
00954
00955 deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
00956
00957
if (deviceNode ==
NULL || deviceNode->
Parent ==
NULL) {
00958
ASSERT(deviceNode !=
NULL);
00959
00960
00961
00962
00963
return STATUS_UNSUCCESSFUL;
00964 }
00965
00966
if ((OperationCode == QueryRemoveDevice || OperationCode == EjectDevice) &&
00967 (deviceNode->
Flags &
DNF_REMOVE_PENDING_CLOSES)) {
00968
00969
00970
00971
00972
return STATUS_UNSUCCESSFUL;
00973 }
00974
00975 status =
IopAddRelationToList( RelationsList,
00976 DeviceObject,
00977 IsDirectDescendant,
00978
FALSE);
00979
00980
if (status == STATUS_SUCCESS) {
00981
00982
ASSERT(deviceNode->
LockCount == 0);
00983
00984
if (!(deviceNode->
Flags &
DNF_LOCKED_FOR_EJECT)) {
00985
ObReferenceObject(DeviceObject);
00986
00987
KeClearEvent(&deviceNode->
EnumerationMutex);
00988
00989 deviceNode->
LockCount++;
00990
00991
00992
00993
00994
for (relatedDeviceNode = deviceNode->
Child;
00995 relatedDeviceNode !=
NULL;
00996 ) {
00997
00998 relatedDeviceObject = relatedDeviceNode->
PhysicalDeviceObject;
00999
01000 relatedDeviceNode = relatedDeviceNode->
Sibling;
01001
01002 status =
IopProcessRelation( relatedDeviceObject,
01003 OperationCode,
01004 RelationsList,
01005 IsKernelInitiated,
01006 IsDirectDescendant
01007 );
01008
01009
ASSERT(status == STATUS_SUCCESS || status == STATUS_UNSUCCESSFUL);
01010
01011
if (status == STATUS_INSUFFICIENT_RESOURCES ||
01012 status == STATUS_INVALID_DEVICE_REQUEST) {
01013
return status;
01014 }
01015 }
01016
01017
01018
01019
01020
01021
01022
if (deviceNode->
Flags &
DNF_STARTED) {
01023 status =
IopQueryDeviceRelations(
RemovalRelations,
01024 DeviceObject,
01025
FALSE,
01026 &deviceRelations);
01027
01028
if (
NT_SUCCESS(status) && deviceRelations) {
01029
01030
for (i = 0; i < deviceRelations->
Count; i++) {
01031
01032 relatedDeviceObject = deviceRelations->
Objects[i];
01033
01034 status =
IopProcessRelation( relatedDeviceObject,
01035 OperationCode,
01036 RelationsList,
01037 IsKernelInitiated,
01038
FALSE);
01039
01040
01041
ObDereferenceObject( relatedDeviceObject );
01042
01043
ASSERT(status == STATUS_SUCCESS ||
01044 status == STATUS_UNSUCCESSFUL);
01045
01046
if (status == STATUS_INSUFFICIENT_RESOURCES ||
01047 status == STATUS_INVALID_DEVICE_REQUEST) {
01048
01049
ExFreePool(deviceRelations);
01050
01051
return status;
01052 }
01053 }
01054
01055
ExFreePool(deviceRelations);
01056 }
else {
01057
if (status != STATUS_NOT_SUPPORTED) {
01058 PIDBGMSG( PIDBG_WARNING,
01059 (
"IopProcessRelation: IopQueryDeviceRelations failed, DeviceObject = 0x%p, status = 0x%08X\n",
01060 DeviceObject, status));
01061 }
01062 }
01063 }
01064
01065
01066
01067
01068
01069
if (OperationCode != QueryRemoveDevice &&
01070 OperationCode != RemoveFailedDevice &&
01071 OperationCode != RemoveUnstartedFailedDevice) {
01072 status =
IopQueryDeviceRelations(
EjectionRelations,
01073 DeviceObject,
01074
FALSE,
01075 &deviceRelations);
01076
01077
if (
NT_SUCCESS(status) && deviceRelations) {
01078
01079
for (i = 0; i < deviceRelations->
Count; i++) {
01080
01081 relatedDeviceObject = deviceRelations->
Objects[i];
01082
01083 status =
IopProcessRelation( relatedDeviceObject,
01084 OperationCode,
01085 RelationsList,
01086 IsKernelInitiated,
01087
FALSE);
01088
01089
ObDereferenceObject( relatedDeviceObject );
01090
01091
ASSERT(status == STATUS_SUCCESS ||
01092 status == STATUS_UNSUCCESSFUL);
01093
01094
if (status == STATUS_INSUFFICIENT_RESOURCES ||
01095 status == STATUS_INVALID_DEVICE_REQUEST) {
01096
01097
ExFreePool(deviceRelations);
01098
01099
return status;
01100 }
01101 }
01102
01103
ExFreePool(deviceRelations);
01104 }
else {
01105
if (status != STATUS_NOT_SUPPORTED) {
01106 PIDBGMSG( PIDBG_WARNING,
01107 (
"IopProcessRelation: IopQueryDeviceRelations failed, DeviceObject = 0x%p, status = 0x%08X\n",
01108 DeviceObject, status));
01109 }
01110 }
01111 }
01112
01113 status = STATUS_SUCCESS;
01114
01115 }
else {
01116
01117
01118
01119
01120
01121
01122
01123
01124
for (ejectLink =
IopPendingEjects.Flink;
01125 ejectLink != &
IopPendingEjects;
01126 ejectLink = ejectLink->Flink) {
01127
01128 ejectEntry = CONTAINING_RECORD( ejectLink,
01129
PENDING_RELATIONS_LIST_ENTRY,
01130 Link);
01131
01132
if (ejectEntry->
RelationsList !=
NULL &&
01133
IopIsRelationInList(ejectEntry->
RelationsList, DeviceObject)) {
01134
01135
01136
if (OperationCode == EjectDevice) {
01137
01138 status =
IopRemoveRelationFromList(RelationsList, DeviceObject);
01139
01140
ASSERT(
NT_SUCCESS(status));
01141
01142 pendingIrp = InterlockedExchangePointer(&ejectEntry->
EjectIrp,
NULL);
01143 pendingRelationList = ejectEntry->
RelationsList;
01144 ejectEntry->
RelationsList =
NULL;
01145
01146
if (pendingIrp !=
NULL) {
01147
IoCancelIrp(pendingIrp);
01148 }
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
IopMergeRelationLists(RelationsList, pendingRelationList,
TRUE);
01160
01161
IopFreeRelationList(pendingRelationList);
01162
01163
if (IsDirectDescendant) {
01164
01165
01166
01167
01168
01169
01170
01171
IopAddRelationToList( RelationsList,
01172 DeviceObject,
01173
TRUE,
01174
FALSE);
01175 }
01176 }
else if (OperationCode == RemoveDevice) {
01177
01178
01179
01180
01181
01182
01183
01184 status =
IopRemoveRelationFromList( ejectEntry->
RelationsList,
01185 DeviceObject);
01186
01187 deviceNode->
Flags &= ~
DNF_LOCKED_FOR_EJECT;
01188
01189
ASSERT(
NT_SUCCESS(status));
01190
01191
ObReferenceObject(DeviceObject);
01192
01193
KeClearEvent(&deviceNode->
EnumerationMutex);
01194
01195 deviceNode->
LockCount++;
01196 }
else {
01197
01198
ASSERT(0);
01199
01200
return STATUS_INVALID_DEVICE_REQUEST;
01201 }
01202
break;
01203 }
01204 }
01205
01206
ASSERT(ejectLink != &
IopPendingEjects);
01207
01208
if (ejectLink == &
IopPendingEjects) {
01209
KeBugCheckEx( PNP_DETECTED_FATAL_ERROR,
01210
PNP_ERR_DEVICE_MISSING_FROM_EJECT_LIST,
01211 (ULONG_PTR)DeviceObject,
01212 0,
01213 0);
01214 }
01215 }
01216 }
else if (status == STATUS_OBJECT_NAME_COLLISION) {
01217 PIDBGMSG( PIDBG_INFORMATION,
01218 (
"IopProcessRelation: Duplicate relation, DeviceObject = 0x%p\n",
01219 DeviceObject));
01220
01221 status = STATUS_SUCCESS;
01222 }
else if (status != STATUS_INSUFFICIENT_RESOURCES) {
01223
KeBugCheckEx( PNP_DETECTED_FATAL_ERROR,
01224
PNP_ERR_UNEXPECTED_ADD_RELATION_ERR,
01225 (ULONG_PTR)DeviceObject,
01226 (ULONG_PTR)RelationsList,
01227 status);
01228 }
01229
01230
return status;
01231 }
01232
01233 BOOLEAN
01234 IopQueuePendingEject(
01235
PPENDING_RELATIONS_LIST_ENTRY Entry
01236 )
01237 {
01238
PAGED_CODE();
01239
01240
IopAcquireDeviceTreeLock();
01241
01242 InsertTailList(&
IopPendingEjects, &Entry->
Link);
01243
01244
IopReleaseDeviceTreeLock();
01245
01246
return TRUE;
01247 }
01248
01249
NTSTATUS
01250 IopInvalidateRelationsInList(
01251
PRELATION_LIST RelationsList,
01252 BOOLEAN OnlyIndirectDescendants,
01253 BOOLEAN UnlockDevNode,
01254 BOOLEAN RestartDevNode
01255 )
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294 {
01295
PRELATION_LIST parentsList;
01296
PDEVICE_OBJECT deviceObject, parentObject;
01297
PDEVICE_NODE deviceNode, parentNode;
01298 ULONG marker;
01299 BOOLEAN directDescendant, tagged;
01300
01301
PAGED_CODE();
01302
01303 parentsList =
IopAllocateRelationList();
01304
01305
if (parentsList ==
NULL) {
01306
return STATUS_INSUFFICIENT_RESOURCES;
01307 }
01308
01309
IopSetAllRelationsTags( RelationsList,
FALSE );
01310
01311
01312
01313
01314
01315
01316 marker = 0;
01317
01318
while (
IopEnumerateRelations( RelationsList,
01319 &marker,
01320 &deviceObject,
01321 &directDescendant,
01322 &tagged,
01323
TRUE)) {
01324
01325
if (!OnlyIndirectDescendants || !directDescendant) {
01326
01327
if (!tagged) {
01328
01329 parentObject = deviceObject;
01330
01331
while (
IopSetRelationsTag( RelationsList, parentObject,
TRUE ) == STATUS_SUCCESS) {
01332
01333 deviceNode = parentObject->
DeviceObjectExtension->
DeviceNode;
01334
01335
if (RestartDevNode) {
01336
01337 deviceNode->
Flags &= ~
DNF_LOCKED_FOR_EJECT;
01338
01339
if ((deviceNode->
Flags & (
DNF_PROCESSED |
DNF_ENUMERATED)) ==
01340 (
DNF_PROCESSED |
DNF_ENUMERATED)) {
01341
01342
ASSERT(deviceNode->
Child ==
NULL);
01343
ASSERT(!(deviceNode->
Flags &
DNF_ADDED));
01344
01345
IopClearDevNodeProblem( deviceNode );
01346
IopRestartDeviceNode( deviceNode );
01347 }
01348 }
01349
01350
if (UnlockDevNode) {
01351 parentNode = deviceNode->
Parent;
01352
01353
ASSERT(parentNode !=
NULL);
01354
01355
ASSERT(deviceNode->
LockCount > 0);
01356
01357
if (--deviceNode->
LockCount == 0) {
01358
KeSetEvent(&deviceNode->
EnumerationMutex, 0,
FALSE);
01359
ObDereferenceObject(deviceNode->
PhysicalDeviceObject);
01360 }
01361
01362
ASSERT(parentNode->
LockCount > 0);
01363
01364
if (--parentNode->
LockCount == 0) {
01365
KeSetEvent(&parentNode->
EnumerationMutex, 0,
FALSE);
01366
ObDereferenceObject(parentNode->
PhysicalDeviceObject);
01367 }
01368 }
01369
01370
if (deviceNode->
Parent !=
NULL) {
01371
01372 parentObject = deviceNode->
Parent->
PhysicalDeviceObject;
01373
01374 }
else {
01375 parentObject =
NULL;
01376
break;
01377 }
01378 }
01379
01380
if (parentObject !=
NULL) {
01381
IopAddRelationToList( parentsList, parentObject,
FALSE,
FALSE );
01382 }
01383 }
01384
01385 }
01386 }
01387
01388
01389
01390
01391
01392 marker = 0;
01393
01394
while (
IopEnumerateRelations( parentsList,
01395 &marker,
01396 &deviceObject,
01397
NULL,
01398
NULL,
01399
FALSE)) {
01400
01401
IopRequestDeviceAction( deviceObject,
01402
ReenumerateDeviceTree,
01403
NULL,
01404
NULL );
01405 }
01406
01407
01408
01409
01410
01411
IopFreeRelationList( parentsList );
01412
01413
return STATUS_SUCCESS;
01414 }
01415
01416
VOID
01417 IopProcessCompletedEject(
01418 IN PVOID Context
01419 )
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440 {
01441
PPENDING_RELATIONS_LIST_ENTRY entry = (
PPENDING_RELATIONS_LIST_ENTRY)Context;
01442
NTSTATUS status = STATUS_SUCCESS;
01443
01444
PAGED_CODE();
01445
01446
if ((entry->
LightestSleepState != PowerSystemWorking) &&
01447 (entry->
LightestSleepState != PowerSystemUnspecified)) {
01448
01449
01450
01451
01452
01453
01454 entry->
DisplaySafeRemovalDialog =
FALSE;
01455
01456
01457
01458
01459 status =
IopWarmEjectDevice(entry->
DeviceObject, entry->
LightestSleepState);
01460
01461
01462
01463
01464 }
01465
01466
if (entry->
DockInterface) {
01467
01468 entry->
DockInterface->ProfileDepartureSetMode(
01469 entry->
DockInterface->Context,
01470 PDS_UPDATE_DEFAULT
01471 );
01472
01473 entry->
DockInterface->InterfaceDereference(
01474 entry->
DockInterface->Context
01475 );
01476 }
01477
01478
IopAcquireDeviceTreeLock();
01479
01480 RemoveEntryList( &entry->
Link );
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
if (entry->
RelationsList !=
NULL) {
01502
01503
if (entry->
ProfileChangingEject) {
01504
01505
IopHardwareProfileSetMarkedDocksEjected();
01506 }
01507
01508
IopInvalidateRelationsInList( entry->
RelationsList,
FALSE,
FALSE,
TRUE );
01509
01510
01511
01512
01513
01514
IopFreeRelationList( entry->
RelationsList );
01515
01516 }
else {
01517
01518 entry->
DisplaySafeRemovalDialog =
FALSE;
01519 }
01520
01521
IopReleaseDeviceTreeLock();
01522
01523
01524
01525
01526
if (entry->
DeviceEvent !=
NULL ) {
01527
01528 PpCompleteDeviceEvent( entry->
DeviceEvent, status );
01529 }
01530
01531
if (entry->
DisplaySafeRemovalDialog) {
01532
01533
PpSetDeviceRemovalSafe(entry->
DeviceObject,
NULL,
NULL);
01534 }
01535
01536
ExFreePool( entry );
01537 }
01538
01539 BOOLEAN
01540 IopQueuePendingSurpriseRemoval(
01541 IN
PDEVICE_OBJECT DeviceObject,
01542 IN
PRELATION_LIST List,
01543 IN ULONG Problem
01544 )
01545 {
01546
PPENDING_RELATIONS_LIST_ENTRY entry;
01547
01548
PAGED_CODE();
01549
01550 entry =
ExAllocatePool(
NonPagedPool,
sizeof(
PENDING_RELATIONS_LIST_ENTRY) );
01551
01552
if (entry !=
NULL) {
01553
01554 entry->
DeviceObject = DeviceObject;
01555 entry->
RelationsList =
List;
01556 entry->
Problem = Problem;
01557 entry->
ProfileChangingEject =
FALSE ;
01558
01559
IopAcquireDeviceTreeLock();
01560
01561 InsertTailList(&
IopPendingSurpriseRemovals, &entry->
Link);
01562
01563
IopReleaseDeviceTreeLock();
01564
01565
return TRUE;
01566 }
01567
01568
return FALSE;
01569 }
01570
01571
NTSTATUS
01572 IopUnlockDeviceRemovalRelations(
01573 IN
PDEVICE_OBJECT DeviceObject,
01574 IN
PRELATION_LIST RelationsList,
01575 IN
UNLOCK_UNLINK_ACTION UnlinkAction
01576 )
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613 {
01614
NTSTATUS status;
01615
PDEVICE_NODE deviceNode, parent;
01616
PDEVICE_OBJECT deviceObject, relatedDeviceObject;
01617 ULONG i;
01618 ULONG marker;
01619
01620
PAGED_CODE();
01621
01622
KeEnterCriticalRegion();
01623
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
01624
01625
if (ARGUMENT_PRESENT(RelationsList)) {
01626 marker = 0;
01627
while (
IopEnumerateRelations( RelationsList,
01628 &marker,
01629 &deviceObject,
01630
NULL,
01631
NULL,
01632
TRUE)) {
01633
01634 deviceNode = (
PDEVICE_NODE)deviceObject->
DeviceObjectExtension->
DeviceNode;
01635 parent = deviceNode->
Parent;
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
if ((!(deviceNode->
Flags & (
DNF_ENUMERATED |
DNF_REMOVE_PENDING_CLOSES)) &&
01656
IopDoesDevNodeHaveProblem(deviceNode)) ||
01657 (UnlinkAction !=
UnlinkRemovedDeviceNodes &&
01658 (deviceNode->
Flags &
DNF_REMOVE_PENDING_CLOSES) &&
01659 !(deviceNode->
Flags &
DNF_RESOURCE_ASSIGNED) &&
01660 deviceNode->
Child ==
NULL &&
01661 (UnlinkAction ==
UnlinkAllDeviceNodesPendingClose ||
01662 deviceObject != DeviceObject))) {
01663
01664 PIDBGMSG( PIDBG_REMOVAL,
01665 (
"IopUnlockDeviceRemovalRelations: Cleaning up registry values, instance = %wZ\n",
01666 &deviceNode->
InstancePath));
01667
01668
IopCleanupDeviceRegistryValues(&deviceNode->
InstancePath,
FALSE);
01669
01670 PIDBGMSG( PIDBG_REMOVAL,
01671 (
"IopUnlockDeviceRemovalRelations: Removing DevNode tree, DevNode = 0x%p\n",
01672 deviceNode));
01673
01674
IopRemoveTreeDeviceNode(deviceNode);
01675
01676
if (!(deviceNode->
Flags &
DNF_REMOVE_PENDING_CLOSES)) {
01677
IopRemoveRelationFromList(RelationsList, deviceObject);
01678 }
01679
ObDereferenceObject(deviceObject);
01680 }
01681
01682
ASSERT(deviceNode->
LockCount > 0);
01683
01684
if (--deviceNode->
LockCount == 0) {
01685
KeSetEvent(&deviceNode->
EnumerationMutex, 0,
FALSE);
01686
ObDereferenceObject(deviceObject);
01687 }
01688
01689
ASSERT(parent->
LockCount > 0);
01690
01691
if (--parent->
LockCount == 0) {
01692
KeSetEvent(&parent->
EnumerationMutex, 0,
FALSE);
01693
ObDereferenceObject(parent->
PhysicalDeviceObject);
01694 }
01695 }
01696 }
01697
01698
ExReleaseResource(&
PpRegistryDeviceResource);
01699
KeLeaveCriticalRegion();
01700
01701
return STATUS_SUCCESS;
01702 }
01703
01704
01705
01706
01707
NTSTATUS
01708 IopRequestDeviceRemoval(
01709 IN
PDEVICE_OBJECT DeviceObject,
01710 IN ULONG Problem
01711 )
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732 {
01733
PAGED_CODE();
01734
01735
ASSERT(DeviceObject->DeviceObjectExtension->DeviceNode !=
NULL);
01736
01737
ASSERT(((
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode)->InstancePath.Length != 0);
01738
01739
01740
01741
01742
01743
return PpSetTargetDeviceRemove( DeviceObject,
01744
TRUE,
01745
TRUE,
01746
FALSE,
01747 Problem,
01748
NULL,
01749
NULL,
01750
NULL,
01751
NULL);
01752 }
01753
01754
NTSTATUS
01755 IopUnloadAttachedDriver(
01756 IN
PDRIVER_OBJECT DriverObject
01757 )
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776 {
01777
NTSTATUS status;
01778 PWCHAR buffer;
01779 UNICODE_STRING unicodeName;
01780 PUNICODE_STRING serviceName = &DriverObject->DriverExtension->ServiceKeyName;
01781
01782
PAGED_CODE();
01783
01784
if (DriverObject->DriverSection !=
NULL) {
01785
if (DriverObject->DeviceObject ==
NULL) {
01786 buffer = (PWCHAR)
ExAllocatePool(
01787
PagedPool,
01788
CmRegistryMachineSystemCurrentControlSetServices.Length +
01789 serviceName->Length +
sizeof(WCHAR) +
01790
sizeof(
L"\\"));
01791
if (!buffer) {
01792
return STATUS_INSUFFICIENT_RESOURCES;
01793 }
01794 swprintf(buffer,
01795
L"%s\\%s",
01796
CmRegistryMachineSystemCurrentControlSetServices.Buffer,
01797 serviceName->Buffer);
01798
RtlInitUnicodeString(&unicodeName, buffer);
01799 status = ZwUnloadDriver(&unicodeName);
01800
#if DBG
01801
if (
NT_SUCCESS(status)) {
01802
DbgPrint(
"****** Unloaded driver (%wZ)\n", serviceName);
01803 }
else {
01804
DbgPrint(
"****** Error unloading driver (%wZ), status = 0x%08X\n", serviceName, status);
01805 }
01806
#endif
01807
ExFreePool(unicodeName.Buffer);
01808 }
01809
#if DBG
01810
else {
01811
DbgPrint(
"****** Skipping unload of driver (%wZ), DriverObject->DeviceObject != NULL\n", serviceName);
01812 }
01813
#endif
01814
}
01815
#if DBG
01816
else {
01817
01818
01819
01820
DbgPrint(
"****** Skipping unload of boot driver (%wZ)\n", serviceName);
01821 }
01822
#endif
01823
return STATUS_SUCCESS;
01824 }