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
#pragma hdrstop
00023
00024
#if DBG_SCOPE
00025
00026 #define PnpIrpStatusTracking(Status, IrpCode, Device) \
00027
if (PnpIrpMask & (1 << IrpCode)) { \
00028
if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) { \
00029
DbgPrint(" ++ %s Driver ( %wZ ) return status %08lx\n", \
00030
IrpName[IrpCode], \
00031
&Device->DriverObject->DriverName, \
00032
Status); \
00033
} \
00034
}
00035
00036 ULONG
PnpIrpMask;
00037 PCHAR
IrpName[] = {
00038
"IRP_MN_START_DEVICE - ",
00039
"IRP_MN_QUERY_REMOVE_DEVICE - ",
00040
"IRP_MN_REMOVE_DEVICE - ",
00041
"IRP_MN_CANCEL_REMOVE_DEVICE - ",
00042
"IRP_MN_STOP_DEVICE - ",
00043
"IRP_MN_QUERY_STOP_DEVICE - ",
00044
"IRP_MN_CANCEL_STOP_DEVICE - ",
00045
"IRP_MN_QUERY_DEVICE_RELATIONS - ",
00046
"IRP_MN_QUERY_INTERFACE - ",
00047
"IRP_MN_QUERY_CAPABILITIES - ",
00048
"IRP_MN_QUERY_RESOURCES - ",
00049
"IRP_MN_QUERY_RESOURCE_REQUIREMENTS - ",
00050
"IRP_MN_QUERY_DEVICE_TEXT - ",
00051
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS - ",
00052
"INVALID_IRP_CODE - ",
00053
"IRP_MN_READ_CONFIG - ",
00054
"IRP_MN_WRITE_CONFIG - ",
00055
"IRP_MN_EJECT - ",
00056
"IRP_MN_SET_LOCK - ",
00057
"IRP_MN_QUERY_ID - ",
00058
"IRP_MN_QUERY_PNP_DEVICE_STATE - ",
00059
"IRP_MN_QUERY_BUS_INFORMATION - ",
00060
"IRP_MN_DEVICE_USAGE_NOTIFICATION - ",
00061
NULL
00062 };
00063
#else
00064
#define PnpIrpStatusTracking(Status, IrpCode, Device)
00065
#endif
00066
00067
00068
00069
00070
00071
00072 #define HASH_UNICODE_STRING( _pustr, _phash ) { \
00073
PWCHAR _p = (_pustr)->Buffer; \
00074
PWCHAR _ep = _p + ((_pustr)->Length/sizeof(WCHAR)); \
00075
ULONG _chHolder =0; \
00076
\
00077
while( _p < _ep ) { \
00078
_chHolder = 37 * _chHolder + (unsigned int) (*_p++); \
00079
} \
00080
\
00081
*(_phash) = abs(314159269 * _chHolder) % 1000000007; \
00082
}
00083
00084
00085 #define MAX_PARENT_PREFIX (8 + 8 + 8 + 2)
00086
00087
00088
00089
00090
00091 typedef struct _DEVICE_COMPLETION_CONTEXT {
00092 PDEVICE_NODE DeviceNode;
00093 ERESOURCE_THREAD Thread;
00094 ULONG
IrpMinorCode;
00095
#if DBG
00096
PVOID Id;
00097
#endif
00098
}
DEVICE_COMPLETION_CONTEXT, *
PDEVICE_COMPLETION_CONTEXT;
00099
00100 typedef struct _LOCK_MOUNTABLE_DEVICE_CONTEXT{
00101 PDEVICE_OBJECT MountedDevice;
00102 }
LOCK_MOUNTABLE_DEVICE_CONTEXT, *
PLOCK_MOUNTABLE_DEVICE_CONTEXT;
00103
00104
00105
00106
00107
00108
NTSTATUS
00109
IopAsynchronousCall(
00110 IN
PDEVICE_OBJECT DeviceObject,
00111 IN
PIO_STACK_LOCATION TopStackLocation,
00112 IN PDEVICE_COMPLETION_CONTEXT CompletionContext,
00113 IN PVOID CompletionRoutine
00114 );
00115
00116
NTSTATUS
00117
IopDeviceEjectComplete (
00118 IN
PDEVICE_OBJECT DeviceObject,
00119 IN
PIRP Irp,
00120 IN PVOID Context
00121 );
00122
00123
NTSTATUS
00124
IopDeviceStartComplete (
00125 IN
PDEVICE_OBJECT DeviceObject,
00126 IN
PIRP Irp,
00127 IN PVOID Context
00128 );
00129
00130
NTSTATUS
00131
IopDeviceRelationsComplete (
00132 IN
PDEVICE_OBJECT DeviceObject,
00133 IN
PIRP Irp,
00134 IN PVOID Context
00135 );
00136
00137
PDEVICE_OBJECT
00138
IopFindMountableDevice(
00139 IN
PDEVICE_OBJECT DeviceObject
00140 );
00141
00142
PDEVICE_OBJECT
00143
IopLockMountedDeviceForRemove(
00144 IN
PDEVICE_OBJECT DeviceObject,
00145 IN ULONG IrpMinorCode,
00146 OUT PLOCK_MOUNTABLE_DEVICE_CONTEXT Context
00147 );
00148
00149
VOID
00150
IopUnlockMountedDeviceForRemove(
00151 IN
PDEVICE_OBJECT DeviceObject,
00152 IN ULONG IrpMinorCode,
00153 IN PLOCK_MOUNTABLE_DEVICE_CONTEXT Context
00154 );
00155
00156
NTSTATUS
00157
IopFilterResourceRequirementsCall(
00158 IN
PDEVICE_OBJECT DeviceObject,
00159 IN PIO_RESOURCE_REQUIREMENTS_LIST ResReqList,
00160 OUT PVOID *Information
00161 );
00162
00163
00164
00165
00166
00167
#ifdef ALLOC_PRAGMA
00168
#pragma alloc_text(PAGE, IopAsynchronousCall)
00169
#pragma alloc_text(PAGE, IopSynchronousCall)
00170
00171
#pragma alloc_text(PAGE, IopEjectDevice)
00172
#pragma alloc_text(PAGE, IopRemoveDevice)
00173
00174
#pragma alloc_text(PAGE, IopQueryDeviceId)
00175
#pragma alloc_text(PAGE, IopQueryUniqueId)
00176
#pragma alloc_text(PAGE, IopQueryCompatibleIds)
00177
#pragma alloc_text(PAGE, IopQueryDeviceResources)
00178
#pragma alloc_text(PAGE, IopQueryDockRemovalInterface)
00179
#pragma alloc_text(PAGE, IopQueryLegacyBusInformation)
00180
#pragma alloc_text(PAGE, IopQueryPnpBusInformation)
00181
#pragma alloc_text(PAGE, IopQueryResourceHandlerInterface)
00182
#pragma alloc_text(PAGE, IopQueryReconfiguration)
00183
#pragma alloc_text(PAGE, IopUncacheInterfaceInformation)
00184
#pragma alloc_text(PAGE, IopFindMountableDevice)
00185
#pragma alloc_text(PAGE, IopFilterResourceRequirementsCall)
00186
#pragma alloc_text(PAGE, IopMakeGloballyUniqueId)
00187
00188
#endif // ALLOC_PRAGMA
00189
00190
VOID
00191 IopUncacheInterfaceInformation(
00192 IN
PDEVICE_OBJECT DeviceObject
00193 )
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 {
00213
PDEVICE_NODE deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
00214 PLIST_ENTRY listHead, nextEntry, entry;
00215
PPI_RESOURCE_TRANSLATOR_ENTRY handlerEntry;
00216
PINTERFACE interface;
00217
00218
00219
00220
00221
00222 listHead = &deviceNode->
DeviceArbiterList;
00223 nextEntry = listHead->Flink;
00224
while (nextEntry != listHead) {
00225 entry = nextEntry;
00226 nextEntry = nextEntry->Flink;
00227 handlerEntry = CONTAINING_RECORD(entry,
PI_RESOURCE_TRANSLATOR_ENTRY, DeviceTranslatorList);
00228
if (interface = (
PINTERFACE)handlerEntry->
TranslatorInterface) {
00229 (interface->
InterfaceDereference)(interface->
Context);
00230
ExFreePool(interface);
00231 }
00232
ExFreePool(entry);
00233 }
00234 InitializeListHead(&deviceNode->
DeviceArbiterList);
00235
00236
00237
00238
00239
00240 listHead = &deviceNode->
DeviceTranslatorList;
00241 nextEntry = listHead->Flink;
00242
while (nextEntry != listHead) {
00243 entry = nextEntry;
00244 nextEntry = nextEntry->Flink;
00245 handlerEntry = CONTAINING_RECORD(entry,
PI_RESOURCE_TRANSLATOR_ENTRY, DeviceTranslatorList);
00246
if (interface = (
PINTERFACE)handlerEntry->
TranslatorInterface) {
00247 (interface->
InterfaceDereference)(interface->
Context);
00248
ExFreePool(interface);
00249 }
00250
ExFreePool(entry);
00251 }
00252
00253 InitializeListHead(&deviceNode->
DeviceTranslatorList);
00254
00255 deviceNode->
NoArbiterMask = 0;
00256 deviceNode->
QueryArbiterMask = 0;
00257 deviceNode->
NoTranslatorMask = 0;
00258 deviceNode->
QueryTranslatorMask = 0;
00259 }
00260
00261
NTSTATUS
00262 IopAsynchronousCall(
00263 IN
PDEVICE_OBJECT TargetDevice,
00264 IN
PIO_STACK_LOCATION TopStackLocation,
00265 IN PDEVICE_COMPLETION_CONTEXT CompletionContext,
00266 IN PVOID CompletionRoutine
00267 )
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 {
00293
PDEVICE_OBJECT deviceObject;
00294
PIRP irp;
00295
PIO_STACK_LOCATION irpSp;
00296
NTSTATUS status;
00297
00298
PAGED_CODE();
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
if ((TargetDevice->Vpb !=
NULL) && (TargetDevice->Vpb->Flags &
VPB_MOUNTED)) {
00311 deviceObject = TargetDevice->
Vpb->
DeviceObject;
00312 }
else {
00313 deviceObject = TargetDevice;
00314 }
00315
00316
ASSERT(deviceObject !=
NULL);
00317
00318
00319
00320
00321
00322
00323 deviceObject =
IoGetAttachedDevice(deviceObject);
00324
00325
00326
00327
00328
00329 irp =
IoAllocateIrp( (CCHAR) (deviceObject->
StackSize),
FALSE );
00330
if (!irp) {
00331
return STATUS_INSUFFICIENT_RESOURCES;
00332 }
00333
00334
SPECIALIRP_WATERMARK_IRP(irp,
IRP_SYSTEM_RESTRICTED);
00335
00336
00337
00338
00339
00340 irp->
IoStatus.Status = STATUS_NOT_SUPPORTED;
00341 irp->
IoStatus.Information = 0;
00342
00343
00344
00345
00346
00347
00348
00349 irpSp =
IoGetNextIrpStackLocation (irp);
00350
00351
00352
00353
00354
00355 irp->
Tail.Overlay.Thread =
PsGetCurrentThread();
00356 irp->
RequestorMode =
KernelMode;
00357 irp->
UserIosb =
NULL;
00358 irp->
UserEvent =
NULL;
00359
00360
00361
00362
00363
00364 *irpSp = *TopStackLocation;
00365
#if DBG
00366
CompletionContext->Id = irp;
00367
#endif
00368
IoSetCompletionRoutine(irp,
00369 CompletionRoutine,
00370 CompletionContext,
00371
TRUE,
00372
TRUE,
00373
TRUE
00374 );
00375
00376 status =
IoCallDriver( deviceObject, irp );
00377
return status;
00378 }
00379
00380
NTSTATUS
00381 IopSynchronousCall(
00382 IN
PDEVICE_OBJECT DeviceObject,
00383 IN
PIO_STACK_LOCATION TopStackLocation,
00384 OUT PVOID *Information
00385 )
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 {
00410
PIRP irp;
00411
PIO_STACK_LOCATION irpSp;
00412 IO_STATUS_BLOCK statusBlock;
00413
KEVENT event;
00414
NTSTATUS status;
00415 PULONG_PTR returnInfo = (PULONG_PTR)Information;
00416
PDEVICE_OBJECT deviceObject;
00417
00418
PAGED_CODE();
00419
00420
00421
00422
00423
00424
00425 deviceObject =
IoGetAttachedDevice(DeviceObject);
00426
00427
00428
00429
00430
00431
00432 irp =
IoAllocateIrp(deviceObject->
StackSize,
FALSE);
00433
if (irp ==
NULL){
00434
00435
return STATUS_INSUFFICIENT_RESOURCES;
00436 }
00437
00438
SPECIALIRP_WATERMARK_IRP(irp,
IRP_SYSTEM_RESTRICTED);
00439
00440
00441
00442
00443
00444 irp->
IoStatus.Status = statusBlock.Status = STATUS_NOT_SUPPORTED;
00445 irp->
IoStatus.Information = statusBlock.Information = 0;
00446
00447
00448
00449
00450
00451
KeInitializeEvent( &event,
00452 SynchronizationEvent,
00453
FALSE );
00454
00455 irp->
UserIosb = &statusBlock;
00456 irp->
UserEvent = &event;
00457
00458
00459
00460
00461
00462 irp->
Tail.Overlay.Thread =
PsGetCurrentThread();
00463
00464
00465
00466
00467
00468
IopQueueThreadIrp(irp);
00469
00470
00471
00472
00473
00474
00475 irpSp =
IoGetNextIrpStackLocation(irp);
00476
00477
00478
00479
00480
00481 *irpSp = *TopStackLocation;
00482
00483
00484
00485
00486
00487 status =
IoCallDriver(deviceObject, irp);
00488
00489
PnpIrpStatusTracking(status, TopStackLocation->MinorFunction, deviceObject);
00490
00491
00492
00493
00494
00495
if (status == STATUS_PENDING) {
00496 (
VOID)
KeWaitForSingleObject( &event,
00497
Executive,
00498
KernelMode,
00499
FALSE,
00500 (PLARGE_INTEGER)
NULL );
00501 status = statusBlock.Status;
00502 }
00503
00504 *returnInfo = (ULONG_PTR) statusBlock.Information;
00505
00506
return status;
00507 }
00508
00509
VOID
00510 IopStartDevice(
00511 IN
PDEVICE_OBJECT DeviceObject
00512 )
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532 {
00533
IO_STACK_LOCATION irpSp;
00534 PVOID
dummy;
00535
PDEVICE_NODE deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
00536
PDEVICE_COMPLETION_CONTEXT completionContext;
00537
NTSTATUS status;
00538 PNP_VETO_TYPE vetoType;
00539
00540
00541
00542
00543
00544
00545
00546 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
00547
00548
00549
00550
00551
00552 irpSp.
MajorFunction =
IRP_MJ_PNP;
00553 irpSp.
MinorFunction =
IRP_MN_START_DEVICE;
00554
00555
00556
00557
00558
00559
if (!(deviceNode->
Flags &
DNF_RESOURCE_REPORTED)) {
00560 irpSp.
Parameters.StartDevice.AllocatedResources = deviceNode->
ResourceList;
00561 irpSp.
Parameters.StartDevice.AllocatedResourcesTranslated = deviceNode->
ResourceListTranslated;
00562 }
00563
00564
if (!(deviceNode->
Flags &
DNF_STOPPED)) {
00565
IopUncacheInterfaceInformation(DeviceObject);
00566 }
00567
00568
if (
PnpAsyncOk) {
00569
00570
00571
00572
00573
00574
00575
00576
ASSERT(0);
00577 completionContext = (
PDEVICE_COMPLETION_CONTEXT)
ExAllocatePool(
00578
NonPagedPool,
00579
sizeof(
DEVICE_COMPLETION_CONTEXT));
00580
if (completionContext ==
NULL) {
00581
return;
00582 }
00583
00584 completionContext->
DeviceNode = deviceNode;
00585 completionContext->
IrpMinorCode =
IRP_MN_START_DEVICE;
00586 completionContext->
Thread =
ExGetCurrentResourceThread();
00587
00588
00589
00590
00591
00592
IopAcquireEnumerationLock(
NULL);
00593 status =
IopAsynchronousCall(DeviceObject, &irpSp, completionContext,
IopDeviceStartComplete);
00594
if (status == STATUS_PENDING) {
00595
00596 KIRQL oldIrql;
00597
00598
00599
00600
00601
00602
00603 ExAcquireSpinLock(&
IopPnPSpinLock, &oldIrql);
00604
00605
if (!(
IopDoesDevNodeHaveProblem(deviceNode) || (deviceNode->
Flags &
DNF_STARTED))) {
00606 deviceNode->
Flags |=
DNF_START_REQUEST_PENDING;
00607 }
00608 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
00609 }
00610 }
else {
00611
00612
if ((deviceNode->
Flags &
DNF_STOPPED)||
00613 (deviceNode->
DockInfo.DockStatus ==
DOCK_NOTDOCKDEVICE)) {
00614
00615
00616
00617
00618
00619
00620
00621 status =
IopSynchronousCall(DeviceObject, &irpSp, &
dummy);
00622
00623 }
else {
00624
00625
00626
00627
00628
00629
00630
IopHardwareProfileBeginTransition(
FALSE);
00631
00632
00633
00634
00635
00636
IopHardwareProfileMarkDock(deviceNode,
DOCK_ARRIVING);
00637
00638
00639
00640
00641
00642
00643
00644
00645 status =
IopHardwareProfileQueryChange(
00646
FALSE,
00647
PROFILE_PERHAPS_IN_PNPEVENT,
00648 &vetoType,
00649
NULL
00650 );
00651
00652
if (
NT_SUCCESS(status)) {
00653
00654 status =
IopSynchronousCall(DeviceObject, &irpSp, &
dummy);
00655 }
00656
00657
if (
NT_SUCCESS(status)) {
00658
00659
00660
00661
00662
IopHardwareProfileCommitStartedDock(deviceNode);
00663
00664 }
else {
00665
00666
IopHardwareProfileCancelTransition();
00667 }
00668 }
00669
00670
if (!
NT_SUCCESS(status)) {
00671 ULONG Problem = CM_PROB_FAILED_START;
00672
00673
SAVE_FAILURE_INFO(deviceNode, status);
00674
00675
00676
00677
00678
switch (status) {
00679
case STATUS_PNP_REBOOT_REQUIRED:
00680 Problem = CM_PROB_NEED_RESTART;
00681
break;
00682
00683
default:
00684 Problem = CM_PROB_FAILED_START;
00685 }
00686
IopSetDevNodeProblem(deviceNode, Problem);
00687
00688
if (deviceNode->
DockInfo.DockStatus ==
DOCK_NOTDOCKDEVICE) {
00689
00690
IopRequestDeviceRemoval(deviceNode->
PhysicalDeviceObject, CM_PROB_FAILED_START);
00691 }
else {
00692
00693
ASSERT(deviceNode->
DockInfo.DockStatus ==
DOCK_QUIESCENT);
00694
00695
PpSetTargetDeviceRemove( deviceNode->
PhysicalDeviceObject,
00696
FALSE,
00697
TRUE,
00698
TRUE,
00699 CM_PROB_DEVICE_NOT_THERE,
00700
NULL,
00701
NULL,
00702
NULL,
00703
NULL);
00704 }
00705
00706 }
else {
00707
00708
IopDoDeferredSetInterfaceState(deviceNode);
00709
00710 deviceNode->
Flags |=
DNF_STARTED;
00711
00712
if (deviceNode->
Flags &
DNF_STOPPED) {
00713
00714
00715
00716
00717
00718 deviceNode->
Flags &= ~
DNF_STOPPED;
00719
00720 }
else {
00721
00722 deviceNode->
Flags |=
DNF_NEED_ENUMERATION_ONLY;
00723
00724 }
00725 }
00726 }
00727 }
00728
00729
NTSTATUS
00730 IopEjectDevice(
00731 IN
PDEVICE_OBJECT DeviceObject,
00732 IN OUT
PPENDING_RELATIONS_LIST_ENTRY PendingEntry
00733 )
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 {
00754
PIO_STACK_LOCATION irpSp;
00755
NTSTATUS status;
00756
PDEVICE_NODE deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
00757
PDEVICE_OBJECT deviceObject;
00758
PIRP irp;
00759
00760
PAGED_CODE();
00761
00762
if (PendingEntry->LightestSleepState != PowerSystemWorking) {
00763
00764
00765
00766
00767
if (PendingEntry->DockInterface) {
00768
00769 PendingEntry->DockInterface->ProfileDepartureSetMode(
00770 PendingEntry->DockInterface->Context,
00771 PDS_UPDATE_ON_EJECT
00772 );
00773 }
00774
00775 PendingEntry->EjectIrp =
NULL;
00776
00777 InitializeListHead( &PendingEntry->Link );
00778
00779
IopQueuePendingEject(PendingEntry);
00780
00781
ExInitializeWorkItem( &PendingEntry->WorkItem,
00782
IopProcessCompletedEject,
00783 PendingEntry);
00784
00785
ExQueueWorkItem( &PendingEntry->WorkItem,
DelayedWorkQueue );
00786
return STATUS_SUCCESS;
00787 }
00788
00789
if (PendingEntry->DockInterface) {
00790
00791
00792
00793
00794 PendingEntry->DockInterface->ProfileDepartureSetMode(
00795 PendingEntry->DockInterface->Context,
00796 PDS_UPDATE_ON_INTERFACE
00797 );
00798
00799 PendingEntry->DockInterface->ProfileDepartureUpdate(
00800 PendingEntry->DockInterface->Context
00801 );
00802
00803
if (PendingEntry->DisplaySafeRemovalDialog) {
00804
00805
PpNotifyUserModeRemovalSafe(DeviceObject);
00806 PendingEntry->DisplaySafeRemovalDialog =
FALSE;
00807 }
00808 }
00809
00810
00811
00812
00813
00814
00815 deviceObject =
IoGetAttachedDevice(DeviceObject);
00816
00817
00818
00819
00820
00821 irp =
IoAllocateIrp( (CCHAR) (deviceObject->
StackSize),
FALSE );
00822
if (!irp) {
00823
00824 PendingEntry->EjectIrp =
NULL;
00825
00826 InitializeListHead( &PendingEntry->Link );
00827
00828
IopQueuePendingEject(PendingEntry);
00829
00830
ExInitializeWorkItem( &PendingEntry->WorkItem,
00831
IopProcessCompletedEject,
00832 PendingEntry);
00833
00834
ExQueueWorkItem( &PendingEntry->WorkItem,
DelayedWorkQueue );
00835
00836
return STATUS_INSUFFICIENT_RESOURCES;
00837 }
00838
00839
SPECIALIRP_WATERMARK_IRP(irp,
IRP_SYSTEM_RESTRICTED);
00840
00841
00842
00843
00844
00845 irp->
IoStatus.Status = STATUS_NOT_SUPPORTED;
00846 irp->
IoStatus.Information = 0;
00847
00848
00849
00850
00851
00852
00853
00854 irpSp =
IoGetNextIrpStackLocation(irp);
00855
00856
00857
00858
00859
00860 RtlZeroMemory(irpSp,
sizeof(
IO_STACK_LOCATION));
00861
00862
00863
00864
00865
00866 irpSp->
MajorFunction =
IRP_MJ_PNP;
00867 irpSp->
MinorFunction =
IRP_MN_EJECT;
00868
00869
00870
00871
00872
00873 irp->
Tail.Overlay.Thread =
PsGetCurrentThread();
00874 irp->
RequestorMode =
KernelMode;
00875 irp->
UserIosb =
NULL;
00876 irp->
UserEvent =
NULL;
00877
00878 PendingEntry->EjectIrp = irp;
00879
00880
IopQueuePendingEject(PendingEntry);
00881
00882
IoSetCompletionRoutine(irp,
00883
IopDeviceEjectComplete,
00884 PendingEntry,
00885
TRUE,
00886
TRUE,
00887
TRUE
00888 );
00889
00890 status =
IoCallDriver( deviceObject, irp );
00891
00892
return status;
00893 }
00894
00895
NTSTATUS
00896 IopDeviceEjectComplete (
00897 IN
PDEVICE_OBJECT DeviceObject,
00898 IN
PIRP Irp,
00899 IN PVOID Context
00900 )
00901 {
00902
PPENDING_RELATIONS_LIST_ENTRY entry = (
PPENDING_RELATIONS_LIST_ENTRY)Context;
00903
PIRP ejectIrp;
00904
00905 ejectIrp = InterlockedExchangePointer(&entry->
EjectIrp,
NULL);
00906
00907
ASSERT(ejectIrp ==
NULL || ejectIrp ==
Irp);
00908
00909
00910
00911
00912
00913
00914
ExInitializeWorkItem( &entry->
WorkItem,
00915
IopProcessCompletedEject,
00916 entry);
00917
00918
ExQueueWorkItem( &entry->
WorkItem,
DelayedWorkQueue );
00919
00920
IoFreeIrp(
Irp );
00921
00922
return STATUS_MORE_PROCESSING_REQUIRED;
00923
00924 }
00925
00926
NTSTATUS
00927 IopRemoveDevice (
00928 IN
PDEVICE_OBJECT TargetDevice,
00929 IN ULONG IrpMinorCode
00930 )
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958 {
00959
PDEVICE_OBJECT deviceObject;
00960
PIRP irp;
00961
IO_STACK_LOCATION irpSp;
00962
NTSTATUS status;
00963
00964 BOOLEAN isMountable =
FALSE;
00965
PDEVICE_OBJECT mountedDevice;
00966
00967 PVOID
dummy;
00968
LOCK_MOUNTABLE_DEVICE_CONTEXT lockContext;
00969
00970
PAGED_CODE();
00971
00972
ASSERT(IrpMinorCode ==
IRP_MN_QUERY_REMOVE_DEVICE ||
00973 IrpMinorCode ==
IRP_MN_CANCEL_REMOVE_DEVICE ||
00974 IrpMinorCode ==
IRP_MN_REMOVE_DEVICE ||
00975 IrpMinorCode ==
IRP_MN_SURPRISE_REMOVAL ||
00976 IrpMinorCode ==
IRP_MN_EJECT);
00977
00978
if (IrpMinorCode ==
IRP_MN_REMOVE_DEVICE ||
00979 IrpMinorCode ==
IRP_MN_QUERY_REMOVE_DEVICE) {
00980
IopUncacheInterfaceInformation(TargetDevice);
00981 }
00982
00983
00984
00985
00986
00987 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
00988
00989 irpSp.
MajorFunction =
IRP_MJ_PNP;
00990 irpSp.
MinorFunction = (UCHAR)IrpMinorCode;
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004 mountedDevice =
IopFindMountableDevice(TargetDevice);
01005
01006
if (mountedDevice !=
NULL) {
01007
01008
01009
01010
01011
01012
01013 mountedDevice =
IopLockMountedDeviceForRemove(TargetDevice,
01014 IrpMinorCode,
01015 &lockContext);
01016
01017 isMountable =
TRUE;
01018
01019 }
else {
01020
ASSERTMSG(
"Mass storage device does not have VPB - this is odd",
01021 !((TargetDevice->Type == FILE_DEVICE_DISK) ||
01022 (TargetDevice->Type == FILE_DEVICE_CD_ROM) ||
01023 (TargetDevice->Type == FILE_DEVICE_TAPE) ||
01024 (TargetDevice->Type == FILE_DEVICE_VIRTUAL_DISK)));
01025
01026 mountedDevice = TargetDevice;
01027 }
01028
01029
01030
01031
01032
01033
if (IrpMinorCode ==
IRP_MN_SURPRISE_REMOVAL || IrpMinorCode ==
IRP_MN_REMOVE_DEVICE) {
01034
01035
01036
01037
01038
PDEVICE_NODE deviceNode = TargetDevice->
DeviceObjectExtension->
DeviceNode;
01039
01040
if (deviceNode->
UserFlags &
DNUF_NOT_DISABLEABLE) {
01041
01042
01043
01044
01045
01046 deviceNode->
UserFlags &= ~
DNUF_NOT_DISABLEABLE;
01047
IopDecDisableableDepends(deviceNode);
01048 }
01049 }
01050
01051 status =
IopSynchronousCall(mountedDevice, &irpSp, &
dummy);
01052
01053
if (isMountable) {
01054
01055
IopUnlockMountedDeviceForRemove(TargetDevice,
01056 IrpMinorCode,
01057 &lockContext);
01058
01059
01060
01061
01062
01063
01064
if (IrpMinorCode ==
IRP_MN_QUERY_REMOVE_DEVICE &&
NT_SUCCESS( status )) {
01065
01066 status =
IopInvalidateVolumesForDevice( TargetDevice );
01067 }
01068 }
01069
01070
if (IrpMinorCode ==
IRP_MN_REMOVE_DEVICE) {
01071 ((
PDEVICE_NODE)TargetDevice->DeviceObjectExtension->DeviceNode)->Flags &=
01072 ~(
DNF_ADDED |
DNF_STARTED |
DNF_LEGACY_DRIVER |
DNF_NEED_QUERY_IDS |
DNF_NEED_ENUMERATION_ONLY);
01073 }
01074
01075
return status;
01076 }
01077
01078
01079
PDEVICE_OBJECT
01080 IopLockMountedDeviceForRemove(
01081 IN
PDEVICE_OBJECT DeviceObject,
01082 IN ULONG IrpMinorCode,
01083 OUT PLOCK_MOUNTABLE_DEVICE_CONTEXT Context
01084 )
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116 {
01117
PVPB vpb;
01118
01119
PDEVICE_OBJECT device = DeviceObject;
01120
PDEVICE_OBJECT fsDevice =
NULL;
01121
01122 BOOLEAN isRemovePendingSet;
01123 KIRQL oldIrql;
01124
01125 RtlZeroMemory(Context,
sizeof(
LOCK_MOUNTABLE_DEVICE_CONTEXT));
01126 Context->MountedDevice = DeviceObject;
01127
01128
do {
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
if(device->
Vpb !=
NULL) {
01143
01144
01145
01146
01147
01148
01149
KeWaitForSingleObject(&(device->
DeviceLock),
01150
Executive,
01151
KernelMode,
01152
FALSE,
01153
NULL);
01154
01155
01156
01157
01158
01159
01160
01161
01162
IoAcquireVpbSpinLock(&oldIrql);
01163
01164 vpb = device->
Vpb;
01165
01166
ASSERT(vpb !=
NULL);
01167
01168
switch(IrpMinorCode) {
01169
01170
case IRP_MN_QUERY_REMOVE_DEVICE:
01171
case IRP_MN_SURPRISE_REMOVAL:
01172
case IRP_MN_REMOVE_DEVICE: {
01173
01174 vpb->
Flags |=
VPB_REMOVE_PENDING;
01175
break;
01176 }
01177
01178
case IRP_MN_CANCEL_REMOVE_DEVICE: {
01179
01180 vpb->
Flags &= ~
VPB_REMOVE_PENDING;
01181
break;
01182 }
01183
01184
default:
01185
break;
01186 }
01187
01188
01189
01190
01191
01192
01193
01194
01195
if(vpb->
Flags &
VPB_MOUNTED) {
01196
01197 Context->MountedDevice = device;
01198 fsDevice = vpb->
DeviceObject;
01199 }
01200
01201
IoReleaseVpbSpinLock(oldIrql);
01202
KeSetEvent(&(device->
DeviceLock),
IO_NO_INCREMENT,
FALSE);
01203
01204
01205
01206
01207
01208
if (Context->MountedDevice !=
NULL) {
01209
01210
01211
01212
01213
01214
break;
01215 }
01216 }
01217
01218 ExAcquireFastLock( &
IopDatabaseLock, &oldIrql );
01219 device = device->
AttachedDevice;
01220 ExReleaseFastLock( &
IopDatabaseLock, oldIrql );
01221
01222 }
while (device !=
NULL);
01223
01224
if(fsDevice !=
NULL) {
01225
01226
return fsDevice;
01227 }
01228
01229
return Context->MountedDevice;
01230 }
01231
01232
VOID
01233 IopUnlockMountedDeviceForRemove(
01234 IN
PDEVICE_OBJECT DeviceObject,
01235 IN ULONG IrpMinorCode,
01236 IN PLOCK_MOUNTABLE_DEVICE_CONTEXT Context
01237 )
01238 {
01239
PVPB vpb;
01240 BOOLEAN removePendingSet;
01241
01242
PDEVICE_OBJECT device = DeviceObject;
01243
01244
do {
01245
01246 KIRQL oldIrql;
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
if (device->
Vpb !=
NULL) {
01261
01262
01263
01264
01265
01266
01267
01268
KeWaitForSingleObject(&(device->
DeviceLock),
01269
Executive,
01270
KernelMode,
01271
FALSE,
01272
NULL);
01273
01274
01275
01276
01277
01278
01279
01280
01281
IoAcquireVpbSpinLock(&oldIrql);
01282
01283
if (IrpMinorCode ==
IRP_MN_REMOVE_DEVICE) {
01284
01285 device->
Vpb->
Flags &= ~
VPB_REMOVE_PENDING;
01286 }
01287
01288
IoReleaseVpbSpinLock(oldIrql);
01289
01290
KeSetEvent(&(device->
DeviceLock),
IO_NO_INCREMENT,
FALSE);
01291 }
01292
01293
01294
01295
01296
01297
01298
if (Context->MountedDevice == device) {
01299
01300
break;
01301
01302 }
else {
01303
01304 ExAcquireFastLock( &
IopDatabaseLock, &oldIrql );
01305 device = device->
AttachedDevice;
01306 ExReleaseFastLock( &
IopDatabaseLock, oldIrql );
01307 }
01308
01309 }
while (device !=
NULL);
01310
01311
return;
01312 }
01313
01314
01315
PDEVICE_OBJECT
01316 IopFindMountableDevice(
01317 IN
PDEVICE_OBJECT DeviceObject
01318 )
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349 {
01350
PVPB vpb;
01351
01352
PDEVICE_OBJECT mountableDevice = DeviceObject;
01353
01354
while (mountableDevice !=
NULL) {
01355
01356
if ((mountableDevice->
Flags &
DO_DEVICE_HAS_NAME) &&
01357 (mountableDevice->
Vpb !=
NULL)) {
01358
01359
return mountableDevice;
01360 }
01361
01362 mountableDevice = mountableDevice->
AttachedDevice;
01363 }
01364
01365
return NULL;
01366 }
01367
01368
01369
NTSTATUS
01370 IopDeviceStartComplete (
01371 IN
PDEVICE_OBJECT DeviceObject,
01372 IN
PIRP Irp,
01373 IN PVOID Context
01374 )
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395 {
01396
PDEVICE_NODE deviceNode = ((
PDEVICE_COMPLETION_CONTEXT)Context)->DeviceNode;
01397
ERESOURCE_THREAD LockingThread = ((
PDEVICE_COMPLETION_CONTEXT)Context)->Thread;
01398 ULONG oldFlags;
01399 KIRQL oldIrql;
01400
01401
01402
01403
01404
01405
#if DBG
01406
if (((
PDEVICE_COMPLETION_CONTEXT)Context)->Id != (PVOID)
Irp) {
01407
ASSERT(0);
01408
IoFreeIrp (
Irp);
01409
ExFreePool(Context);
01410
01411
return STATUS_MORE_PROCESSING_REQUIRED;
01412 }
01413
#endif
01414
01415
PnpIrpStatusTracking(
Irp->
IoStatus.Status,
IRP_MN_START_DEVICE, deviceNode->
PhysicalDeviceObject);
01416 ExAcquireSpinLock(&
IopPnPSpinLock, &oldIrql);
01417
01418 oldFlags = deviceNode->
Flags;
01419 deviceNode->
Flags &= ~
DNF_START_REQUEST_PENDING;
01420
if (
NT_SUCCESS(
Irp->
IoStatus.Status)) {
01421
01422
if (deviceNode->
Flags &
DNF_STOPPED) {
01423
01424
01425
01426
01427
01428 deviceNode->
Flags &= ~
DNF_STOPPED;
01429 deviceNode->
Flags |=
DNF_STARTED;
01430
01431 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01432 }
else {
01433
01434
01435
01436
01437
01438
01439
01440 deviceNode->
Flags |=
DNF_NEED_ENUMERATION_ONLY +
DNF_STARTED;
01441
01442 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01443
01444
if (oldFlags &
DNF_START_REQUEST_PENDING) {
01445
IopRequestDeviceAction( deviceNode->
PhysicalDeviceObject,
01446
ReenumerateDeviceTree,
01447
NULL,
01448
NULL );
01449 }
01450 }
01451
01452 }
else {
01453
01454
01455
01456
01457
01458 deviceNode->
Flags &= ~(
DNF_STOPPED |
DNF_STARTED);
01459
01460 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01461
SAVE_FAILURE_INFO(deviceNode,
Irp->
IoStatus.Status);
01462
01463
IopSetDevNodeProblem(deviceNode, CM_PROB_FAILED_START);
01464
01465
if (deviceNode->
DockInfo.DockStatus ==
DOCK_NOTDOCKDEVICE) {
01466
01467
IopRequestDeviceRemoval(deviceNode->
PhysicalDeviceObject, CM_PROB_FAILED_START);
01468 }
else {
01469
01470
ASSERT(deviceNode->
DockInfo.DockStatus ==
DOCK_ARRIVING);
01471
01472
01473
01474
01475
01476
01477
01478
ASSERT(0);
01479
IoRequestDeviceEject(deviceNode->
PhysicalDeviceObject);
01480 }
01481 }
01482
IopReleaseEnumerationLockForThread(
NULL, LockingThread);
01483
01484
01485
01486
01487
01488
01489
01490
IoFreeIrp (
Irp);
01491
ExFreePool(Context);
01492
return STATUS_MORE_PROCESSING_REQUIRED;
01493 }
01494
01495
NTSTATUS
01496 IopDeviceRelationsComplete (
01497 IN
PDEVICE_OBJECT DeviceObject,
01498 IN
PIRP Irp,
01499 IN PVOID Context
01500 )
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521 {
01522
PDEVICE_NODE deviceNode = ((
PDEVICE_COMPLETION_CONTEXT)Context)->DeviceNode;
01523
ERESOURCE_THREAD LockingThread = ((
PDEVICE_COMPLETION_CONTEXT)Context)->Thread;
01524 KIRQL oldIrql;
01525 BOOLEAN requestEnumeration =
FALSE;
01526
01527
#if DBG
01528
if (((
PDEVICE_COMPLETION_CONTEXT)Context)->Id != (PVOID)
Irp) {
01529
ASSERT(0);
01530
IoFreeIrp (
Irp);
01531
ExFreePool(Context);
01532
return STATUS_MORE_PROCESSING_REQUIRED;
01533 }
01534
#endif
01535
01536
PnpIrpStatusTracking(
Irp->
IoStatus.Status,
IRP_MN_QUERY_DEVICE_RELATIONS, deviceNode->
PhysicalDeviceObject);
01537 ExAcquireSpinLock(&
IopPnPSpinLock, &oldIrql);
01538 deviceNode->
Flags &= ~
DNF_BEING_ENUMERATED;
01539
01540
01541
01542
01543
01544
if (
NT_SUCCESS(
Irp->
IoStatus.Status) && (
Irp->
IoStatus.Information)) {
01545
01546
01547
01548
01549
01550
01551
ASSERT(deviceNode->
OverUsed1.PendingDeviceRelations ==
NULL);
01552 deviceNode->
OverUsed1.PendingDeviceRelations = (
PDEVICE_RELATIONS)
Irp->
IoStatus.Information;
01553 }
01554
01555
if (deviceNode->
Flags &
DNF_ENUMERATION_REQUEST_PENDING) {
01556 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01557
01558
if (deviceNode->
OverUsed1.PendingDeviceRelations) {
01559
01560
01561
01562
01563
01564
01565
IopRequestDeviceAction( deviceNode->
PhysicalDeviceObject,
01566
RestartEnumeration,
01567
NULL,
01568
NULL );
01569 }
else {
01570 deviceNode->
Flags &= ~
DNF_ENUMERATION_REQUEST_PENDING;
01571 }
01572 }
else {
01573 deviceNode->
Flags |=
DNF_ENUMERATION_REQUEST_PENDING;
01574 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01575 }
01576
01577
IopReleaseEnumerationLockForThread(
NULL, LockingThread);
01578
01579
01580
01581
01582
01583
01584
01585
IoFreeIrp (
Irp);
01586
ExFreePool(Context);
01587
01588 ExAcquireSpinLock(&
IopPnPSpinLock, &oldIrql);
01589
if (deviceNode->
Flags &
DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING) {
01590 deviceNode->
Flags &= ~
DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING;
01591 requestEnumeration =
TRUE;
01592 }
01593 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01594
if (requestEnumeration) {
01595
IopRequestDeviceAction( DeviceObject,
01596
ReenumerateDeviceTree,
01597
NULL,
01598
NULL );
01599 }
01600
return STATUS_MORE_PROCESSING_REQUIRED;
01601 }
01602
01603
NTSTATUS
01604 IopQueryDeviceRelations(
01605 IN DEVICE_RELATION_TYPE Relations,
01606 IN
PDEVICE_OBJECT DeviceObject,
01607 IN BOOLEAN AsyncOk,
01608 OUT
PDEVICE_RELATIONS *DeviceRelations
01609 )
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634 {
01635
IO_STACK_LOCATION irpSp;
01636
NTSTATUS status;
01637
PDEVICE_RELATIONS deviceRelations;
01638
PDEVICE_NODE deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
01639
PDEVICE_COMPLETION_CONTEXT completionContext;
01640 BOOLEAN requestEnumeration =
FALSE;
01641 KIRQL oldIrql;
01642
01643
01644
01645
01646
01647
if (Relations ==
BusRelations) {
01648 ExAcquireSpinLock(&
IopPnPSpinLock, &oldIrql);
01649
if (deviceNode->
Flags &
DNF_BEING_ENUMERATED) {
01650 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01651
return STATUS_UNSUCCESSFUL;
01652 }
01653 deviceNode->
Flags &= ~
DNF_ENUMERATION_REQUEST_QUEUED;
01654 deviceNode->
Flags |=
DNF_BEING_ENUMERATED;
01655 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01656 }
01657
01658
01659
01660
01661
01662 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
01663
01664
01665
01666
01667
01668 irpSp.
MajorFunction =
IRP_MJ_PNP;
01669 irpSp.
MinorFunction =
IRP_MN_QUERY_DEVICE_RELATIONS;
01670
01671
01672
01673
01674
01675 irpSp.
Parameters.QueryDeviceRelations.Type = Relations;
01676
01677
01678
01679
01680
01681
if (AsyncOk && Relations ==
BusRelations) {
01682 completionContext = (
PDEVICE_COMPLETION_CONTEXT)
ExAllocatePool(
01683
NonPagedPool,
01684
sizeof(
DEVICE_COMPLETION_CONTEXT));
01685
if (completionContext ==
NULL) {
01686
return STATUS_INSUFFICIENT_RESOURCES;
01687 }
01688
01689 completionContext->
DeviceNode = deviceNode;
01690 completionContext->
IrpMinorCode =
IRP_MN_QUERY_DEVICE_RELATIONS;
01691 completionContext->
Thread =
ExGetCurrentResourceThread();
01692
01693
01694
01695
01696
01697
IopAcquireEnumerationLock(
NULL);
01698 status =
IopAsynchronousCall(DeviceObject, &irpSp, completionContext,
IopDeviceRelationsComplete);
01699
if (status == STATUS_PENDING) {
01700 KIRQL oldIrql;
01701
01702 ExAcquireSpinLock(&
IopPnPSpinLock, &oldIrql);
01703
01704
01705
01706
01707
01708
01709
if (deviceNode->
Flags &
DNF_ENUMERATION_REQUEST_PENDING) {
01710 deviceNode->
Flags &= ~
DNF_ENUMERATION_REQUEST_PENDING;
01711 *DeviceRelations = deviceNode->
OverUsed1.PendingDeviceRelations;
01712 deviceNode->
OverUsed1.PendingDeviceRelations =
NULL;
01713 status = STATUS_SUCCESS;
01714 }
else {
01715
01716
01717
01718
01719
01720
01721 deviceNode->
Flags |=
DNF_ENUMERATION_REQUEST_PENDING;
01722 }
01723
01724 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01725 }
else {
01726 deviceNode->
Flags &= ~
DNF_ENUMERATION_REQUEST_PENDING;
01727 *DeviceRelations = deviceNode->
OverUsed1.PendingDeviceRelations;
01728 deviceNode->
OverUsed1.PendingDeviceRelations =
NULL;
01729 }
01730
return status;
01731 }
else {
01732 status =
IopSynchronousCall(DeviceObject, &irpSp, DeviceRelations);
01733
01734
01735
01736
01737
01738
01739
01740
01741
if (Relations ==
BusRelations) {
01742 ExAcquireSpinLock(&
IopPnPSpinLock, &oldIrql);
01743 deviceNode->
Flags &= ~
DNF_BEING_ENUMERATED;
01744
if (deviceNode->
Flags &
DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING) {
01745 deviceNode->
Flags &= ~
DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING;
01746 requestEnumeration =
TRUE;
01747 }
01748 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01749
if (requestEnumeration) {
01750
IopRequestDeviceAction( DeviceObject,
01751
ReenumerateDeviceTree,
01752
NULL,
01753
NULL );
01754 }
01755 }
01756 }
01757
01758
return status;
01759 }
01760
01761
NTSTATUS
01762 IopQueryDeviceId (
01763 IN
PDEVICE_OBJECT DeviceObject,
01764 OUT PWCHAR *DeviceId
01765 )
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785 {
01786
IO_STACK_LOCATION irpSp;
01787
NTSTATUS status;
01788
01789
PAGED_CODE();
01790
01791
01792
01793
01794
01795 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
01796
01797
01798
01799
01800
01801 irpSp.
MajorFunction =
IRP_MJ_PNP;
01802 irpSp.
MinorFunction =
IRP_MN_QUERY_ID;
01803
01804
01805
01806
01807
01808 irpSp.
Parameters.QueryId.IdType =
BusQueryDeviceID;
01809
01810
01811
01812
01813
01814 status =
IopSynchronousCall(DeviceObject, &irpSp, DeviceId);
01815
01816
return status;
01817 }
01818
01819
NTSTATUS
01820 IopQueryUniqueId (
01821 IN
PDEVICE_OBJECT DeviceObject,
01822 OUT PWCHAR *UniqueId
01823 )
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846 {
01847
IO_STACK_LOCATION irpSp;
01848
NTSTATUS status;
01849
01850
PAGED_CODE();
01851
01852 *UniqueId =
NULL;
01853
01854
01855
01856
01857
01858
01859
01860
01861 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
01862
01863
01864
01865
01866
01867 irpSp.
MajorFunction =
IRP_MJ_PNP;
01868 irpSp.
MinorFunction =
IRP_MN_QUERY_ID;
01869
01870
01871
01872
01873
01874 irpSp.
Parameters.QueryId.IdType =
BusQueryInstanceID;
01875
01876
01877
01878
01879
01880 status =
IopSynchronousCall(DeviceObject, &irpSp, UniqueId);
01881
01882
if (!
NT_SUCCESS(status)) {
01883 *UniqueId =
NULL;
01884 }
01885
01886
return status;
01887
01888 }
01889
01890
NTSTATUS
01891 IopMakeGloballyUniqueId(
01892 IN
PDEVICE_OBJECT DeviceObject,
01893 IN PWCHAR UniqueId,
01894 OUT PWCHAR *GloballyUniqueId
01895 )
01896 {
01897
NTSTATUS status;
01898 ULONG length;
01899 PWSTR
id, Prefix =
NULL;
01900 HANDLE enumKey;
01901 HANDLE instanceKey;
01902 UCHAR keyBuffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) +
sizeof(ULONG)];
01903 PKEY_VALUE_PARTIAL_INFORMATION keyValue, stringValueBuffer =
NULL;
01904 UNICODE_STRING valueName;
01905 ULONG uniqueIdValue, Hash, hashInstance;
01906
PDEVICE_NODE parentNode;
01907
01908
PAGED_CODE();
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920
01921
01922
01923
01924
KeEnterCriticalRegion();
01925
ExAcquireResourceShared(&
PpRegistryDeviceResource,
TRUE);
01926
01927 parentNode = ((
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode)->
Parent;
01928
01929 status =
IopOpenRegistryKeyEx( &enumKey,
01930
NULL,
01931 &
CmRegistryMachineSystemCurrentControlSetEnumName,
01932 KEY_READ | KEY_WRITE
01933 );
01934
01935
if (!
NT_SUCCESS(status)) {
01936
DbgPrint(
"IopQueryUniqueId:\tUnable to open HKLM\\SYSTEM\\CCS\\ENUM (status %08lx)\n",
01937 status
01938 );
01939
goto clean0;
01940 }
01941
01942
01943
01944
01945 status =
IopOpenRegistryKeyEx( &instanceKey,
01946 enumKey,
01947 &parentNode->
InstancePath,
01948 KEY_READ | KEY_WRITE
01949 );
01950
01951
if (!
NT_SUCCESS(status)) {
01952
DbgPrint(
"IopQueryUniqueId:\tUnable to open registry key for %wZ (status %08lx)\n",
01953 &parentNode->
InstancePath,
01954 status
01955 );
01956
goto clean1;
01957 }
01958
01959
01960
01961
01962
01963 keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)keyBuffer;
01964 PiWstrToUnicodeString(&valueName, REGSTR_VALUE_UNIQUE_PARENT_ID);
01965
01966 status = ZwQueryValueKey(instanceKey,
01967 &valueName,
01968 KeyValuePartialInformation,
01969 keyValue,
01970
sizeof(keyBuffer),
01971 &length
01972 );
01973
01974
if (
NT_SUCCESS(status)) {
01975
ASSERT(keyValue->Type == REG_DWORD);
01976
ASSERT(keyValue->DataLength ==
sizeof(ULONG));
01977
if ((keyValue->Type != REG_DWORD) ||
01978 (keyValue->DataLength !=
sizeof(ULONG))) {
01979 status = STATUS_INVALID_PARAMETER;
01980
goto clean2;
01981 }
01982
01983 uniqueIdValue = *(PULONG)(keyValue->Data);
01984
01985
01986
01987
01988 Prefix = (PWSTR)
ExAllocatePool(
PagedPool, 9 *
sizeof(WCHAR));
01989
if (!Prefix) {
01990 status = STATUS_INSUFFICIENT_RESOURCES;
01991
goto clean2;
01992 }
01993 swprintf(Prefix,
L"%x", uniqueIdValue);
01994 }
else {
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007 PiWstrToUnicodeString(&valueName, REGSTR_VALUE_PARENT_ID_PREFIX);
02008 length = (
MAX_PARENT_PREFIX + 1) *
sizeof(WCHAR) +
02009 FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
02010 stringValueBuffer =
ExAllocatePool(
PagedPool,
02011 length);
02012
if (stringValueBuffer) {
02013 status = ZwQueryValueKey(instanceKey,
02014 &valueName,
02015 KeyValuePartialInformation,
02016 stringValueBuffer,
02017 length,
02018 &length);
02019 }
02020
else {
02021 status = STATUS_INSUFFICIENT_RESOURCES;
02022
goto clean2;
02023 }
02024
02025
if (
NT_SUCCESS(status)) {
02026
02027
ASSERT(stringValueBuffer->Type == REG_SZ);
02028
if (stringValueBuffer->Type != REG_SZ) {
02029 status = STATUS_INVALID_PARAMETER;
02030
goto clean2;
02031 }
02032
02033
02034
02035
02036
02037 Prefix = (PWSTR)
ExAllocatePool(
PagedPool,
02038 stringValueBuffer->DataLength);
02039
if (!Prefix)
02040 {
02041 status = STATUS_INSUFFICIENT_RESOURCES;
02042
goto clean2;
02043 }
02044 wcscpy(Prefix, (PWSTR) stringValueBuffer->Data);
02045 }
02046
else
02047 {
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062 length =
max(wcslen(REGSTR_VALUE_NEXT_PARENT_ID) + 2 + 8 + 8,
02063
MAX_PARENT_PREFIX) + 1;
02064
02065
02066
02067 status =
RtlUpcaseUnicodeString(&valueName,
02068 &parentNode->
InstancePath,
02069
TRUE);
02070
if (!
NT_SUCCESS(status))
02071 {
02072
goto clean2;
02073 }
02074
HASH_UNICODE_STRING(&valueName, &Hash);
02075
RtlFreeUnicodeString(&valueName);
02076
02077 Prefix = (PWSTR)
ExAllocatePool(
PagedPool,
02078 length *
sizeof(WCHAR));
02079
if (!Prefix) {
02080 status = STATUS_INSUFFICIENT_RESOURCES;
02081
goto clean2;
02082 }
02083
02084
02085 swprintf(Prefix,
L"%s.%x.%x", REGSTR_VALUE_NEXT_PARENT_ID,
02086 Hash, parentNode->
Level);
02087
RtlInitUnicodeString(&valueName, Prefix);
02088 keyValue = (PKEY_VALUE_PARTIAL_INFORMATION)keyBuffer;
02089 status = ZwQueryValueKey(enumKey,
02090 &valueName,
02091 KeyValuePartialInformation,
02092 keyValue,
02093
sizeof(keyBuffer),
02094 &length
02095 );
02096
if (
NT_SUCCESS(status) && (keyValue->Type == REG_DWORD) &&
02097 (keyValue->DataLength ==
sizeof(ULONG))) {
02098 hashInstance = *(PULONG)(keyValue->Data);
02099 }
02100
else {
02101 hashInstance = 0;
02102 }
02103
02104 hashInstance++;
02105
02106 status = ZwSetValueKey(enumKey,
02107 &valueName,
02108
TITLE_INDEX_VALUE,
02109 REG_DWORD,
02110 &hashInstance,
02111
sizeof(hashInstance)
02112 );
02113
02114
if (!
NT_SUCCESS(status)) {
02115
goto clean2;
02116 }
02117
02118 hashInstance--;
02119
02120
02121 PiWstrToUnicodeString(&valueName, REGSTR_VALUE_PARENT_ID_PREFIX);
02122 length = swprintf(Prefix,
L"%x&%x&%x", parentNode->
Level,
02123 Hash, hashInstance) + 1;
02124 status = ZwSetValueKey(instanceKey,
02125 &valueName,
02126
TITLE_INDEX_VALUE,
02127 REG_SZ,
02128 Prefix,
02129 length *
sizeof(WCHAR)
02130 );
02131
if (!
NT_SUCCESS(status))
02132 {
02133
goto clean2;
02134 }
02135 }
02136 }
02137
02138
02139
02140 length = wcslen(Prefix) + (UniqueId ? wcslen(UniqueId) : 0) + 2;
02141
id = (PWSTR)
ExAllocatePool(
PagedPool, length *
sizeof(WCHAR));
02142
if (!
id) {
02143 status = STATUS_INSUFFICIENT_RESOURCES;
02144 }
else if (UniqueId) {
02145 swprintf(
id,
L"%s&%s", Prefix, UniqueId);
02146 }
else {
02147 wcscpy(
id, Prefix);
02148 }
02149
02150 clean2:
02151 ZwClose(instanceKey);
02152
02153 clean1:
02154 ZwClose(enumKey);
02155
02156 clean0:
02157
ExReleaseResource(&
PpRegistryDeviceResource);
02158
KeLeaveCriticalRegion();
02159
02160
if (stringValueBuffer) {
02161
ExFreePool(stringValueBuffer);
02162 }
02163
02164
if (Prefix) {
02165
ExFreePool(Prefix);
02166 }
02167
02168 *GloballyUniqueId =
id;
02169
return status;
02170 }
02171
02172
NTSTATUS
02173 IopQueryCompatibleIds (
02174 IN
PDEVICE_OBJECT DeviceObject,
02175 IN BUS_QUERY_ID_TYPE IdType,
02176 OUT PWCHAR *CompatibleIds,
02177 OUT ULONG *Length
02178 )
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204 {
02205
IO_STACK_LOCATION irpSp;
02206
NTSTATUS status;
02207
02208
PAGED_CODE();
02209
02210 *Length = 0;
02211
if ((IdType !=
BusQueryHardwareIDs) && (IdType !=
BusQueryCompatibleIDs)) {
02212
return STATUS_INVALID_PARAMETER_2;
02213 }
02214
02215
02216
02217
02218
02219 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
02220
02221
02222
02223
02224
02225 irpSp.
MajorFunction =
IRP_MJ_PNP;
02226 irpSp.
MinorFunction =
IRP_MN_QUERY_ID;
02227
02228
02229
02230
02231
02232 irpSp.
Parameters.QueryId.IdType = IdType;
02233
02234
02235
02236
02237
02238 status =
IopSynchronousCall(DeviceObject, &irpSp, CompatibleIds);
02239
02240
if (
NT_SUCCESS(status) && *CompatibleIds) {
02241
02242
02243
02244
02245
02246
02247 PWCHAR wp;
02248
02249
for (wp = *CompatibleIds;
02250 (*wp != UNICODE_NULL) || (*(wp + 1) != UNICODE_NULL);
02251 wp++) {
02252
02253 *Length += 2;
02254 }
02255 *Length += 4;
02256 }
02257
02258
return status;
02259 }
02260
02261
NTSTATUS
02262 IopQueryDeviceResources (
02263 IN
PDEVICE_OBJECT DeviceObject,
02264 IN ULONG ResourceType,
02265 OUT PVOID *Resource,
02266 OUT ULONG *Length
02267 )
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295 {
02296
IO_STACK_LOCATION irpSp;
02297
PDEVICE_NODE deviceNode;
02298
NTSTATUS status;
02299 PIO_RESOURCE_REQUIREMENTS_LIST resReqList, newResources;
02300 ULONG junk;
02301 PCM_RESOURCE_LIST cmList;
02302 PIO_RESOURCE_REQUIREMENTS_LIST filteredList, mergedList;
02303 BOOLEAN exactMatch;
02304
02305
PAGED_CODE();
02306
02307
#if DBG
02308
02309
if ((ResourceType !=
QUERY_RESOURCE_LIST) &&
02310 (ResourceType !=
QUERY_RESOURCE_REQUIREMENTS)) {
02311
return STATUS_INVALID_PARAMETER_2;
02312 }
02313
#endif
02314
02315 *
Resource =
NULL;
02316 *Length = 0;
02317
02318
02319
02320
02321
02322 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
02323
02324 deviceNode = (
PDEVICE_NODE) DeviceObject->DeviceObjectExtension->DeviceNode;
02325
02326
if (ResourceType ==
QUERY_RESOURCE_LIST) {
02327
02328
02329
02330
02331
02332
02333
if (deviceNode->
Flags &
DNF_MADEUP) {
02334
02335 status =
IopGetDeviceResourcesFromRegistry(
02336 DeviceObject,
02337 ResourceType,
02338
REGISTRY_ALLOC_CONFIG +
REGISTRY_FORCED_CONFIG +
REGISTRY_BOOT_CONFIG,
02339
Resource,
02340 Length);
02341
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
02342 status = STATUS_SUCCESS;
02343 }
02344
return status;
02345 }
else {
02346 irpSp.
MinorFunction =
IRP_MN_QUERY_RESOURCES;
02347 irpSp.
MajorFunction =
IRP_MJ_PNP;
02348 status =
IopSynchronousCall(DeviceObject, &irpSp,
Resource);
02349
if (status == STATUS_NOT_SUPPORTED) {
02350
02351
02352
02353
02354
02355
02356 *
Resource =
NULL;
02357 status = STATUS_SUCCESS;
02358 }
02359
if (
NT_SUCCESS(status)) {
02360 *Length =
IopDetermineResourceListSize((PCM_RESOURCE_LIST)*
Resource);
02361 }
02362
return status;
02363 }
02364 }
else {
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375
02376
02377 status =
IopGetDeviceResourcesFromRegistry(
02378 DeviceObject,
02379
QUERY_RESOURCE_LIST,
02380
REGISTRY_FORCED_CONFIG,
02381
Resource,
02382 &junk);
02383
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
02384 status =
IopGetDeviceResourcesFromRegistry(
02385 DeviceObject,
02386
QUERY_RESOURCE_REQUIREMENTS,
02387
REGISTRY_OVERRIDE_CONFIGVECTOR,
02388 &resReqList,
02389 &junk);
02390
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
02391
if (deviceNode->
Flags &
DNF_MADEUP) {
02392 status =
IopGetDeviceResourcesFromRegistry(
02393 DeviceObject,
02394
QUERY_RESOURCE_REQUIREMENTS,
02395
REGISTRY_BASIC_CONFIGVECTOR,
02396 &resReqList,
02397 &junk);
02398
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
02399 status = STATUS_SUCCESS;
02400 resReqList =
NULL;
02401 }
02402 }
else {
02403
02404
02405
02406
02407
02408
if (deviceNode->
ResourceRequirements) {
02409
ASSERT(deviceNode->
Flags &
DNF_RESOURCE_REQUIREMENTS_NEED_FILTERED);
02410 resReqList =
ExAllocatePool(
PagedPool, deviceNode->
ResourceRequirements->ListSize);
02411
if (resReqList) {
02412 RtlMoveMemory(resReqList,
02413 deviceNode->
ResourceRequirements,
02414 deviceNode->
ResourceRequirements->ListSize
02415 );
02416 status = STATUS_SUCCESS;
02417 }
else {
02418
return STATUS_NO_MEMORY;
02419 }
02420 }
else {
02421 irpSp.
MinorFunction =
IRP_MN_QUERY_RESOURCE_REQUIREMENTS;
02422 irpSp.
MajorFunction =
IRP_MJ_PNP;
02423 status =
IopSynchronousCall(DeviceObject, &irpSp, &resReqList);
02424
if (status == STATUS_NOT_SUPPORTED) {
02425
02426
02427
02428
02429
02430
02431 status = STATUS_SUCCESS;
02432 resReqList =
NULL;
02433
02434 }
02435 }
02436 }
02437
if (!
NT_SUCCESS(status)) {
02438
return status;
02439 }
02440 }
02441
02442
02443
02444
02445
02446
02447 status =
IopGetDeviceResourcesFromRegistry(
02448 DeviceObject,
02449
QUERY_RESOURCE_LIST,
02450
REGISTRY_BOOT_CONFIG,
02451 &cmList,
02452 &junk);
02453
if (
NT_SUCCESS(status) &&
02454 (!cmList || cmList->Count == 0 || cmList->List[0].InterfaceType != PCIBus)) {
02455 status =
IopFilterResourceRequirementsList (
02456 resReqList,
02457 cmList,
02458 &filteredList,
02459 &exactMatch);
02460
if (cmList) {
02461
ExFreePool(cmList);
02462 }
02463
if (!
NT_SUCCESS(status)) {
02464
if (resReqList) {
02465
ExFreePool(resReqList);
02466 }
02467
return status;
02468 }
else {
02469
02470
02471
02472
02473
02474
02475
02476
if (!(deviceNode->
Flags &
DNF_MADEUP) &&
02477 (exactMatch ==
FALSE || resReqList->AlternativeLists > 1)) {
02478 status =
IopMergeFilteredResourceRequirementsList (
02479 filteredList,
02480 resReqList,
02481 &mergedList
02482 );
02483
if (resReqList) {
02484
ExFreePool(resReqList);
02485 }
02486
if (filteredList) {
02487
ExFreePool(filteredList);
02488 }
02489
if (
NT_SUCCESS(status)) {
02490 resReqList = mergedList;
02491 }
else {
02492
return status;
02493 }
02494 }
else {
02495
if (resReqList) {
02496
ExFreePool(resReqList);
02497 }
02498 resReqList = filteredList;
02499 }
02500 }
02501 }
02502
02503 }
else {
02504
ASSERT(
NT_SUCCESS(status));
02505
02506
02507
02508
02509
02510
if (*Resource) {
02511 resReqList =
IopCmResourcesToIoResources (0, (PCM_RESOURCE_LIST)*
Resource, LCPRI_FORCECONFIG);
02512
ExFreePool(*
Resource);
02513
if (resReqList) {
02514 *
Resource = (PVOID)resReqList;
02515 *Length = resReqList->ListSize;
02516 }
else {
02517 *
Resource =
NULL;
02518 *Length = 0;
02519 status = STATUS_INSUFFICIENT_RESOURCES;
02520
return status;
02521 }
02522 }
else {
02523 resReqList =
NULL;
02524 }
02525 }
02526
02527
02528
02529
02530
02531
02532 status =
IopFilterResourceRequirementsCall(
02533 DeviceObject,
02534 resReqList,
02535 &newResources
02536 );
02537
02538
if (
NT_SUCCESS(status)) {
02539 UNICODE_STRING unicodeName;
02540 HANDLE handle, handlex;
02541
02542
#if DBG
02543
if (newResources ==
NULL && resReqList) {
02544
DbgPrint(
"PnpMgr: Non-NULL resource requirements list filtered to NULL\n");
02545 }
02546
#endif
02547
if (newResources) {
02548
02549 *Length = newResources->ListSize;
02550
ASSERT(*Length);
02551
02552
02553
02554
02555
02556
02557
02558 *
Resource = (PVOID)
ExAllocatePool(
PagedPool, *Length);
02559
if (*
Resource ==
NULL) {
02560
02561
ExFreePool(newResources);
02562
return STATUS_INSUFFICIENT_RESOURCES;
02563 }
02564
02565 RtlCopyMemory(*
Resource, newResources, *Length);
02566
ExFreePool(newResources);
02567
02568 }
else {
02569 *Length = 0;
02570 *
Resource =
NULL;
02571 }
02572
02573
02574
02575
02576
02577 status =
IopDeviceObjectToDeviceInstance(DeviceObject, &handlex, KEY_ALL_ACCESS);
02578
if (
NT_SUCCESS(status)) {
02579 PiWstrToUnicodeString(&unicodeName, REGSTR_KEY_CONTROL);
02580 status =
IopOpenRegistryKeyEx( &handle,
02581 handlex,
02582 &unicodeName,
02583 KEY_READ
02584 );
02585
if (
NT_SUCCESS(status)) {
02586 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_FILTERED_CONFIG_VECTOR);
02587 ZwSetValueKey(handle,
02588 &unicodeName,
02589
TITLE_INDEX_VALUE,
02590 REG_RESOURCE_REQUIREMENTS_LIST,
02591 *
Resource,
02592 *Length
02593 );
02594 ZwClose(handle);
02595 ZwClose(handlex);
02596 }
02597 }
02598 }
else {
02599
02600
02601
02602
02603
02604
02605 *
Resource = resReqList;
02606
if (resReqList) {
02607 *Length = resReqList->ListSize;
02608 }
else {
02609 *Length = 0;
02610 }
02611 }
02612
return STATUS_SUCCESS;
02613 }
02614 }
02615
02616
NTSTATUS
02617 IopQueryResourceHandlerInterface(
02618 IN RESOURCE_HANDLER_TYPE HandlerType,
02619 IN
PDEVICE_OBJECT DeviceObject,
02620 IN UCHAR ResourceType,
02621 IN OUT PVOID *Interface
02622 )
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646 {
02647
IO_STACK_LOCATION irpSp;
02648
NTSTATUS status;
02649 PVOID
dummy;
02650
PINTERFACE interface;
02651
USHORT size;
02652 GUID interfaceType;
02653
PDEVICE_NODE deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
02654
02655
PAGED_CODE();
02656
02657
02658
02659
02660
02661
02662
if ((deviceNode->
DuplicatePDO == (
PDEVICE_OBJECT) DeviceObject->
DriverObject) ||
02663 !(DeviceObject->Flags &
DO_BUS_ENUMERATED_DEVICE)) {
02664
return STATUS_NOT_SUPPORTED;
02665 }
02666
02667
switch (HandlerType) {
02668
case ResourceTranslator:
02669 size =
sizeof(
TRANSLATOR_INTERFACE) + 4;
02670
02671 interfaceType = GUID_TRANSLATOR_INTERFACE_STANDARD;
02672
break;
02673
02674
case ResourceArbiter:
02675 size =
sizeof(
ARBITER_INTERFACE);
02676 interfaceType = GUID_ARBITER_INTERFACE_STANDARD;
02677
break;
02678
02679
case ResourceLegacyDeviceDetection:
02680 size =
sizeof(
LEGACY_DEVICE_DETECTION_INTERFACE);
02681 interfaceType = GUID_LEGACY_DEVICE_DETECTION_STANDARD;
02682
break;
02683
02684
default:
02685
return STATUS_INVALID_PARAMETER;
02686 }
02687
02688 interface = (
PINTERFACE)
ExAllocatePool(
PagedPool, size);
02689
if (interface ==
NULL) {
02690
return STATUS_INSUFFICIENT_RESOURCES;
02691 }
02692
02693 RtlZeroMemory(interface, size);
02694 interface->
Size = size;
02695
02696
02697
02698
02699
02700 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
02701
02702
02703
02704
02705
02706 irpSp.
MajorFunction =
IRP_MJ_PNP;
02707 irpSp.
MinorFunction =
IRP_MN_QUERY_INTERFACE;
02708
02709
02710
02711
02712
02713 irpSp.
Parameters.QueryInterface.InterfaceType = &interfaceType;
02714 irpSp.
Parameters.QueryInterface.Size = interface->
Size;
02715 irpSp.
Parameters.QueryInterface.Version = interface->
Version = 0;
02716 irpSp.
Parameters.QueryInterface.Interface = interface;
02717 irpSp.
Parameters.QueryInterface.InterfaceSpecificData = (PVOID) ResourceType;
02718
02719
02720
02721
02722
02723 status =
IopSynchronousCall(DeviceObject, &irpSp, &
dummy);
02724
if (
NT_SUCCESS(status)) {
02725 *Interface = interface;
02726 }
else {
02727
ExFreePool(interface);
02728 }
02729
return status;
02730 }
02731
02732
NTSTATUS
02733 IopQueryReconfiguration(
02734 IN UCHAR Request,
02735 IN
PDEVICE_OBJECT DeviceObject
02736 )
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760 {
02761
IO_STACK_LOCATION irpSp;
02762
NTSTATUS status;
02763 PVOID
dummy;
02764
02765
PAGED_CODE();
02766
02767
ASSERT (
Request ==
IRP_MN_QUERY_STOP_DEVICE ||
02768
Request ==
IRP_MN_STOP_DEVICE ||
02769
Request ==
IRP_MN_CANCEL_STOP_DEVICE);
02770
02771
02772
02773
02774
02775 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
02776
02777
02778
02779
02780
02781 irpSp.
MajorFunction =
IRP_MJ_PNP;
02782 irpSp.
MinorFunction =
Request;
02783
02784
02785
02786
02787
02788 status =
IopSynchronousCall(DeviceObject, &irpSp, &
dummy);
02789
return status;
02790 }
02791
02792
NTSTATUS
02793 IopQueryLegacyBusInformation (
02794 IN
PDEVICE_OBJECT DeviceObject,
02795 OUT LPGUID InterfaceGuid, OPTIONAL
02796 OUT INTERFACE_TYPE *InterfaceType, OPTIONAL
02797 OUT ULONG *BusNumber OPTIONAL
02798 )
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821
02822
02823 {
02824
IO_STACK_LOCATION irpSp;
02825
NTSTATUS status;
02826
PLEGACY_BUS_INFORMATION busInfo;
02827
02828
PAGED_CODE();
02829
02830
02831
02832
02833
02834 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
02835
02836
02837
02838
02839
02840 irpSp.
MajorFunction =
IRP_MJ_PNP;
02841 irpSp.
MinorFunction =
IRP_MN_QUERY_LEGACY_BUS_INFORMATION;
02842
02843
02844
02845
02846
02847 status =
IopSynchronousCall(DeviceObject, &irpSp, &busInfo);
02848
if (
NT_SUCCESS(status)) {
02849
02850
if (busInfo ==
NULL) {
02851
02852
02853
02854
02855
02856
PDEVICE_NODE deviceNode;
02857
02858 deviceNode = DeviceObject->DeviceObjectExtension->DeviceNode;
02859
02860
if (deviceNode && deviceNode->
ServiceName.Buffer) {
02861
02862
DbgPrint(
"*** IopQueryLegacyBusInformation - Driver %wZ returned STATUS_SUCCESS\n", &deviceNode->
ServiceName);
02863
DbgPrint(
" for IRP_MN_QUERY_LEGACY_BUS_INFORMATION, and a NULL POINTER.\n");
02864 }
02865
02866
ASSERT(busInfo !=
NULL);
02867
02868 }
else {
02869
if (ARGUMENT_PRESENT(InterfaceGuid)) {
02870 *InterfaceGuid = busInfo->
BusTypeGuid;
02871 }
02872
if (ARGUMENT_PRESENT(
InterfaceType)) {
02873 *
InterfaceType = busInfo->
LegacyBusType;
02874 }
02875
if (ARGUMENT_PRESENT(
BusNumber)) {
02876 *
BusNumber = busInfo->
BusNumber;
02877 }
02878
ExFreePool(busInfo);
02879 }
02880 }
02881
return status;
02882 }
02883
02884
NTSTATUS
02885 IopQueryPnpBusInformation (
02886 IN
PDEVICE_OBJECT DeviceObject,
02887 OUT LPGUID InterfaceGuid, OPTIONAL
02888 OUT INTERFACE_TYPE *InterfaceType, OPTIONAL
02889 OUT ULONG *BusNumber OPTIONAL
02890 )
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914 {
02915
IO_STACK_LOCATION irpSp;
02916
NTSTATUS status;
02917
PPNP_BUS_INFORMATION busInfo;
02918
02919
PAGED_CODE();
02920
02921
02922
02923
02924
02925 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
02926
02927
02928
02929
02930
02931 irpSp.
MajorFunction =
IRP_MJ_PNP;
02932 irpSp.
MinorFunction =
IRP_MN_QUERY_BUS_INFORMATION;
02933
02934
02935
02936
02937
02938 status =
IopSynchronousCall(DeviceObject, &irpSp, &busInfo);
02939
if (
NT_SUCCESS(status)) {
02940
02941
if (busInfo ==
NULL) {
02942
02943
02944
02945
02946
02947
PDEVICE_NODE deviceNode;
02948
02949 deviceNode = DeviceObject->DeviceObjectExtension->DeviceNode;
02950
02951
if (deviceNode && deviceNode->
ServiceName.Buffer) {
02952
02953
DbgPrint(
"*** IopQueryPnpBusInformation - Driver %wZ returned STATUS_SUCCESS\n", &deviceNode->
ServiceName);
02954
DbgPrint(
" for IRP_MN_QUERY_BUS_INFORMATION, and a NULL POINTER.\n");
02955 }
02956
02957
ASSERT(busInfo !=
NULL);
02958
02959 }
else {
02960
if (ARGUMENT_PRESENT(InterfaceGuid)) {
02961 *InterfaceGuid = busInfo->
BusTypeGuid;
02962 }
02963
if (ARGUMENT_PRESENT(
InterfaceType)) {
02964 *
InterfaceType = busInfo->
LegacyBusType;
02965 }
02966
if (ARGUMENT_PRESENT(
BusNumber)) {
02967 *
BusNumber = busInfo->
BusNumber;
02968 }
02969
ExFreePool(busInfo);
02970 }
02971 }
02972
return status;
02973 }
02974
02975
NTSTATUS
02976 IopQueryDeviceState(
02977 IN
PDEVICE_OBJECT DeviceObject
02978 )
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996 {
02997
IO_STACK_LOCATION irpSp;
02998
PDEVICE_NODE deviceNode;
02999
PNP_DEVICE_STATE deviceState;
03000
PDEVICE_RELATIONS deviceRelations;
03001
KEVENT userEvent;
03002 ULONG eventResult;
03003
NTSTATUS status;
03004
03005
PAGED_CODE();
03006
03007
03008
03009
03010
03011 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
03012
03013
03014
03015
03016
03017 irpSp.
MajorFunction =
IRP_MJ_PNP;
03018 irpSp.
MinorFunction =
IRP_MN_QUERY_PNP_DEVICE_STATE;
03019
03020
03021
03022
03023
03024 status =
IopSynchronousCall(DeviceObject, &irpSp, (PVOID *)&deviceState);
03025
03026
03027
03028
03029
03030
if (
NT_SUCCESS(status)) {
03031
03032 deviceNode = DeviceObject->DeviceObjectExtension->DeviceNode;
03033
03034
if (deviceState != 0) {
03035
03036
03037
03038
03039
03040
if (deviceState &
PNP_DEVICE_DONT_DISPLAY_IN_UI) {
03041
03042 deviceNode->
UserFlags |=
DNUF_DONT_SHOW_IN_UI;
03043 }
03044
03045
if (deviceState &
PNP_DEVICE_NOT_DISABLEABLE) {
03046
03047
if ((deviceNode->
UserFlags &
DNUF_NOT_DISABLEABLE)==0) {
03048
03049
03050
03051 deviceNode->
UserFlags |=
DNUF_NOT_DISABLEABLE;
03052
03053
03054
03055
IopIncDisableableDepends(deviceNode);
03056
03057 }
03058 }
03059
03060
if (deviceState & (
PNP_DEVICE_DISABLED |
PNP_DEVICE_REMOVED)) {
03061
03062
IopRequestDeviceRemoval( DeviceObject,
03063 (deviceState &
PNP_DEVICE_DISABLED) ?
03064 CM_PROB_HARDWARE_DISABLED : CM_PROB_DEVICE_NOT_THERE
03065 );
03066
03067 }
else if (deviceState &
PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED) {
03068
03069
if (deviceState &
PNP_DEVICE_FAILED) {
03070
03071
IopResourceRequirementsChanged(DeviceObject,
TRUE);
03072
03073 }
else {
03074
03075
IopResourceRequirementsChanged(DeviceObject,
FALSE);
03076
03077 }
03078 }
else if (deviceState &
PNP_DEVICE_FAILED) {
03079
03080 deviceNode->
Flags |=
DNF_HAS_PRIVATE_PROBLEM;
03081
03082
IopRequestDeviceRemoval(DeviceObject, 0);
03083 }
03084 }
else {
03085
03086
03087
03088
03089
03090
if (deviceNode->
UserFlags &
DNUF_NOT_DISABLEABLE) {
03091
03092
03093
03094
03095
03096
03097
IopDecDisableableDepends(deviceNode);
03098 }
03099
03100 deviceNode->
UserFlags &= ~(
DNUF_DONT_SHOW_IN_UI |
DNUF_NOT_DISABLEABLE);
03101 }
03102 }
03103
03104
return status;
03105 }
03106
03107
03108
VOID
03109 IopIncDisableableDepends(
03110 IN OUT
PDEVICE_NODE DeviceNode
03111 )
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130 {
03131
03132
while (DeviceNode !=
NULL) {
03133
03134 LONG newval;
03135
03136 newval = InterlockedIncrement(& DeviceNode->DisableableDepends);
03137
if (newval != 1) {
03138
03139
03140
03141
break;
03142 }
03143
03144 DeviceNode = DeviceNode ->Parent;
03145
03146 }
03147
03148 }
03149
03150
03151
VOID
03152 IopDecDisableableDepends(
03153 IN OUT
PDEVICE_NODE DeviceNode
03154 )
03155
03156
03157
03158
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173 {
03174
03175
while (DeviceNode !=
NULL) {
03176
03177 LONG newval;
03178
03179 newval = InterlockedDecrement(& DeviceNode->DisableableDepends);
03180
if (newval != 0) {
03181
03182
03183
03184
break;
03185 }
03186
03187 DeviceNode = DeviceNode ->Parent;
03188
03189 }
03190
03191 }
03192
03193
03194
NTSTATUS
03195 IopQueryDeviceSerialNumber (
03196 IN
PDEVICE_OBJECT DeviceObject,
03197 OUT PWCHAR *SerialNumber
03198 )
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219 {
03220
IO_STACK_LOCATION irpSp;
03221
NTSTATUS status;
03222
03223
PAGED_CODE();
03224
03225 *SerialNumber =
NULL;
03226
03227
03228
03229
03230
03231 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
03232
03233
03234
03235
03236
03237 irpSp.
MajorFunction =
IRP_MJ_PNP;
03238 irpSp.
MinorFunction =
IRP_MN_QUERY_ID;
03239 irpSp.
Parameters.QueryId.IdType =
BusQueryDeviceSerialNumber;
03240
03241
03242
03243
03244
03245 status =
IopSynchronousCall(DeviceObject, &irpSp, SerialNumber);
03246
03247
ASSERT(
NT_SUCCESS(status) || (*SerialNumber ==
NULL));
03248
if (!
NT_SUCCESS(status)) {
03249 *SerialNumber =
NULL;
03250 }
03251
return status;
03252 }
03253
03254
NTSTATUS
03255 IopFilterResourceRequirementsCall(
03256 IN
PDEVICE_OBJECT DeviceObject,
03257 IN PIO_RESOURCE_REQUIREMENTS_LIST ResReqList OPTIONAL,
03258 OUT PVOID *Information
03259 )
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278
03279
03280
03281
03282
03283
03284 {
03285
PIRP irp;
03286
PIO_STACK_LOCATION irpSp;
03287 IO_STATUS_BLOCK statusBlock;
03288
KEVENT event;
03289
NTSTATUS status;
03290 PULONG_PTR returnInfo = (PULONG_PTR)Information;
03291
PDEVICE_OBJECT deviceObject;
03292
03293
PAGED_CODE();
03294
03295
03296
03297
03298
03299
03300 deviceObject =
IoGetAttachedDevice(DeviceObject);
03301
03302
03303
03304
03305
03306
03307 irp =
IoAllocateIrp(deviceObject->
StackSize,
FALSE);
03308
if (irp ==
NULL){
03309
03310
return STATUS_INSUFFICIENT_RESOURCES;
03311 }
03312
03313
SPECIALIRP_WATERMARK_IRP(irp,
IRP_SYSTEM_RESTRICTED);
03314
03315
03316
03317
03318
03319
03320
if (ResReqList) {
03321
03322 irp->
IoStatus.Status = statusBlock.Status = STATUS_SUCCESS;
03323 irp->
IoStatus.Information = statusBlock.Information = (ULONG_PTR) ResReqList;
03324
03325 }
else {
03326
03327 irp->
IoStatus.Status = statusBlock.Status = STATUS_NOT_SUPPORTED;
03328 }
03329
03330
03331
03332
03333
03334
KeInitializeEvent( &event,
03335 SynchronizationEvent,
03336
FALSE );
03337
03338 irp->
UserIosb = &statusBlock;
03339 irp->
UserEvent = &event;
03340
03341
03342
03343
03344
03345 irp->
Tail.Overlay.Thread =
PsGetCurrentThread();
03346
03347
03348
03349
03350
03351
IopQueueThreadIrp(irp);
03352
03353
03354
03355
03356
03357
03358 irpSp =
IoGetNextIrpStackLocation(irp);
03359
03360
03361
03362
03363
03364 irpSp->
MinorFunction =
IRP_MN_FILTER_RESOURCE_REQUIREMENTS;
03365 irpSp->
MajorFunction =
IRP_MJ_PNP;
03366 irpSp->
Parameters.FilterResourceRequirements.IoResourceRequirementList = ResReqList;
03367
03368
03369
03370
03371
03372 status =
IoCallDriver(deviceObject, irp);
03373
03374
PnpIrpStatusTracking(status,
IRP_MN_FILTER_RESOURCE_REQUIREMENTS, deviceObject);
03375
03376
03377
03378
03379
03380
if (status == STATUS_PENDING) {
03381 (
VOID)
KeWaitForSingleObject( &event,
03382
Executive,
03383
KernelMode,
03384
FALSE,
03385 (PLARGE_INTEGER)
NULL );
03386 status = statusBlock.Status;
03387 }
03388
03389 *returnInfo = (ULONG_PTR) statusBlock.Information;
03390
03391
return status;
03392 }
03393
03394
NTSTATUS
03395 IopQueryDockRemovalInterface(
03396 IN
PDEVICE_OBJECT DeviceObject,
03397 IN OUT PDOCK_INTERFACE *DockInterface
03398 )
03399
03400
03401
03402
03403
03404
03405
03406
03407
03408
03409
03410
03411
03412
03413
03414
03415
03416
03417
03418
03419 {
03420
IO_STACK_LOCATION irpSp;
03421
NTSTATUS status;
03422 PVOID
dummy;
03423
PINTERFACE interface;
03424
USHORT size;
03425 GUID interfaceType;
03426
03427
PAGED_CODE();
03428
03429 size =
sizeof(DOCK_INTERFACE);
03430 interfaceType = GUID_DOCK_INTERFACE;
03431 interface = (
PINTERFACE)
ExAllocatePool(
PagedPool, size);
03432
if (interface ==
NULL) {
03433
return STATUS_INSUFFICIENT_RESOURCES;
03434 }
03435
03436 RtlZeroMemory(interface, size);
03437 interface->
Size = size;
03438
03439
03440
03441
03442
03443 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
03444
03445
03446
03447
03448
03449 irpSp.
MajorFunction =
IRP_MJ_PNP;
03450 irpSp.
MinorFunction =
IRP_MN_QUERY_INTERFACE;
03451
03452
03453
03454
03455
03456 irpSp.
Parameters.QueryInterface.InterfaceType = &interfaceType;
03457 irpSp.
Parameters.QueryInterface.Size = interface->
Size;
03458 irpSp.
Parameters.QueryInterface.Version = interface->
Version = 0;
03459 irpSp.
Parameters.QueryInterface.Interface = interface;
03460 irpSp.
Parameters.QueryInterface.InterfaceSpecificData =
NULL;
03461
03462
03463
03464
03465
03466 status =
IopSynchronousCall(DeviceObject, &irpSp, &
dummy);
03467
if (
NT_SUCCESS(status)) {
03468 *DockInterface = (PDOCK_INTERFACE) interface;
03469 }
else {
03470
ExFreePool(interface);
03471 }
03472
return status;
03473 }
03474