00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
#include "iop.h"
00030
#pragma hdrstop
00031
#include <stddef.h>
00032
#include <wdmguid.h>
00033
#include <pnpmgr.h>
00034
#include <pnpsetup.h>
00035
#include "..\pnp\pnpi.h"
00036
00037
#ifdef POOL_TAGGING
00038
#undef ExAllocatePool
00039
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'oipP')
00040
#endif
00041
00042 #define PNP_DEVICE_EVENT_ENTRY_TAG 'EEpP'
00043
00044
00045
00046
00047
00048
00049 typedef struct _DEVICE_WORK_ITEM {
00050 WORK_QUEUE_ITEM WorkItem;
00051 PDEVICE_OBJECT DeviceObject;
00052 PVOID
Context;
00053 }
DEVICE_WORK_ITEM, *
PDEVICE_WORK_ITEM;
00054
00055 typedef struct _ASYNC_TDC_WORK_ITEM {
00056 WORK_QUEUE_ITEM WorkItem;
00057 PDEVICE_OBJECT DeviceObject;
00058 PDEVICE_CHANGE_COMPLETE_CALLBACK Callback;
00059 PVOID
Context;
00060 PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure;
00061 }
ASYNC_TDC_WORK_ITEM, *
PASYNC_TDC_WORK_ITEM;
00062
00063 typedef struct _NOTIFICATION_CALLBACK_PARAM_BLOCK {
00064 PDRIVER_NOTIFICATION_CALLBACK_ROUTINE Callout;
00065 PVOID
NotificationStructure;
00066 PVOID
Context;
00067 }
NOTIFICATION_CALLBACK_PARAM_BLOCK, *
PNOTIFICATION_CALLBACK_PARAM_BLOCK;
00068
00069
NTSTATUS
00070
IopQueueDeviceWorkItem(
00071 IN
PDEVICE_OBJECT PhysicalDeviceObject,
00072 IN PVOID WorkerRoutine,
00073 IN PVOID Context
00074 );
00075
00076
VOID
00077
IopInvalidateDeviceStateWorker(
00078 PVOID Context
00079 );
00080
00081
VOID
00082
IopReportTargetDeviceChangeAsyncWorker(
00083 PVOID Context
00084 );
00085
00086
VOID
00087
IopRequestDeviceEjectWorker(
00088 PVOID Context
00089 );
00090
00091 BOOLEAN
00092
IopIsReportedAlready(
00093 IN HANDLE Handle,
00094 IN PUNICODE_STRING ServiceName,
00095 IN PCM_RESOURCE_LIST ResourceList
00096 );
00097
00098
NTSTATUS
00099
IopSetupDeviceObjectFromDeviceClass(
00100 IN
PDEVICE_OBJECT Pdo,
00101 IN HANDLE InterfaceClassKey
00102 );
00103
00104
NTSTATUS
00105
IopSetSecurityObjectFromRegistry(
00106 IN PVOID Object,
00107 IN HANDLE Key
00108 );
00109
00110
00111
NTSTATUS
00112
IopPnPHydraCallback (
00113 PVOID CallbackParams
00114 );
00115
00116
00117
00118
00119 #define PATH_CURRENTCONTROLSET_HW_PROFILE_CURRENT TEXT("\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet")
00120 #define PATH_CURRENTCONTROLSET TEXT("\\Registry\\Machine\\System\\CurrentControlSet")
00121 #define PATH_ENUM TEXT("Enum\\")
00122 #define PATH_CONTROL_CLASS TEXT("Control\\Class\\")
00123 #define MAX_RESTPATH_BUF_LEN 512
00124
00125
00126
00127
00128
00129 #define INITIAL_INFO_BUFFER_SIZE 512
00130 #define INFO_BUFFER_GROW_SIZE 64
00131 #define INITIAL_SYMLINK_BUFFER_SIZE 1024
00132 #define SYMLINK_BUFFER_GROW_SIZE 128
00133 #define INITIAL_RETURN_BUFFER_SIZE 4096
00134 #define RETURN_BUFFER_GROW_SIZE 512
00135
00136
00137
00138
00139 #define INITIAL_DEVNODE_NAME_BUFFER_SIZE (FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) + (200 * sizeof(WCHAR)))
00140
00141
00142
00143
00144
00145 #define KEY_STRING_PREFIX TEXT("##?#")
00146 #define KEY_STRING_PREFIX_SIZE ( sizeof(KEY_STRING_PREFIX) - sizeof(UNICODE_NULL) )
00147 #define KEY_STRING_PREFIX_LENGTH ( KEY_STRING_PREFIX_SIZE / sizeof(WCHAR) )
00148
00149
00150
00151
00152
00153
00154
00155 #define SEPERATOR_STRING TEXT("\\")
00156 #define SEPERATOR_CHAR (L'\\')
00157 #define ALT_SEPERATOR_CHAR (L'/')
00158 #define REPLACED_SEPERATOR_STRING TEXT("#")
00159 #define REPLACED_SEPERATOR_CHAR (L'#')
00160 #define USER_SYMLINK_STRING_PREFIX TEXT("\\\\?\\")
00161 #define USER_SYMLINK_STRING_PREFIX_LENGTH (( sizeof(USER_SYMLINK_STRING_PREFIX) - sizeof(UNICODE_NULL) ) / sizeof(WCHAR) )
00162 #define KERNEL_SYMLINK_STRING_PREFIX TEXT("\\??\\")
00163 #define KERNEL_SYMLINK_STRING_PREFIX_LENGTH (( sizeof(KERNEL_SYMLINK_STRING_PREFIX) - sizeof(UNICODE_NULL) ) / sizeof(WCHAR) )
00164 #define REFSTRING_PREFIX_CHAR (L'#')
00165
00166
00167
00168
00169
00170 #define LEGACY_COMPATIBLE_ID_BASE TEXT("DETECTED")
00171
00172
00173
00174
00175
00176 #define GUID_STRING_LENGTH 38
00177 #define GUID_STRING_SIZE GUID_STRING_LENGTH * sizeof(WCHAR)
00178
00179
00180
00181
00182
00183 LIST_ENTRY
IopDeviceClassNotifyList[
NOTIFY_DEVICE_CLASS_HASH_BUCKETS];
00184 FAST_MUTEX IopDeviceClassNotifyLock;
00185 PSETUP_NOTIFY_DATA IopSetupNotifyData =
NULL;
00186 FAST_MUTEX IopTargetDeviceNotifyLock;
00187 LIST_ENTRY
IopProfileNotifyList;
00188 FAST_MUTEX IopHwProfileNotifyLock;
00189 extern BOOLEAN
PiNotificationInProgress;
00190 extern FAST_MUTEX PiNotificationInProgressLock;
00191
extern NTSTATUS PiNotifyUserMode(
00192 PPNP_DEVICE_EVENT_ENTRY DeviceEvent
00193 );
00194
00195 typedef struct _DEFERRED_REGISTRATION_ENTRY {
00196 LIST_ENTRY
ListEntry;
00197 PNOTIFY_ENTRY_HEADER NotifyEntry;
00198 }
DEFERRED_REGISTRATION_ENTRY, *
PDEFERRED_REGISTRATION_ENTRY;
00199 LIST_ENTRY
IopDeferredRegistrationList;
00200 FAST_MUTEX IopDeferredRegistrationLock;
00201
00202
00203
00204
00205
NTSTATUS
00206
IopAppendBuffer(
00207 IN
PBUFFER_INFO Info,
00208 IN PVOID Data,
00209 IN ULONG DataSize
00210 );
00211
00212
NTSTATUS
00213
IopOverwriteBuffer(
00214 IN
PBUFFER_INFO Info,
00215 IN PVOID Data,
00216 IN ULONG DataSize
00217 );
00218
00219
NTSTATUS
00220
IopRealloc(
00221 IN OUT PVOID *Buffer,
00222 IN ULONG OldSize,
00223 IN ULONG NewSize
00224 );
00225
00226
NTSTATUS
00227
IopDeviceInterfaceKeysFromSymbolicLink(
00228 IN PUNICODE_STRING SymbolicLinkName,
00229 IN ACCESS_MASK DesiredAccess,
00230 OUT PHANDLE DeviceInterfaceClassKey OPTIONAL,
00231 OUT PHANDLE DeviceInterfaceKey OPTIONAL,
00232 OUT PHANDLE DeviceInterfaceInstanceKey OPTIONAL
00233 );
00234
00235
NTSTATUS
00236
IopBuildSymbolicLinkStrings(
00237 IN PUNICODE_STRING DeviceString,
00238 IN PUNICODE_STRING GuidString,
00239 IN PUNICODE_STRING ReferenceString OPTIONAL,
00240 OUT PUNICODE_STRING UserString,
00241 OUT PUNICODE_STRING KernelString
00242 );
00243
00244
NTSTATUS
00245
IopReplaceSeperatorWithPound(
00246 OUT PUNICODE_STRING OutString,
00247 IN PUNICODE_STRING InString
00248 );
00249
00250
NTSTATUS
00251
IopDropReferenceString(
00252 OUT PUNICODE_STRING OutString,
00253 IN PUNICODE_STRING InString
00254 );
00255
00256
NTSTATUS
00257
IopParseSymbolicLinkName(
00258 IN PUNICODE_STRING SymbolicLinkName,
00259 OUT PUNICODE_STRING PrefixString OPTIONAL,
00260 OUT PUNICODE_STRING MungedPathString OPTIONAL,
00261 OUT PUNICODE_STRING GuidString OPTIONAL,
00262 OUT PUNICODE_STRING RefString OPTIONAL,
00263 OUT PBOOLEAN RefStringPresent OPTIONAL,
00264 OUT LPGUID Guid OPTIONAL
00265 );
00266
00267
NTSTATUS
00268
IopSetRegistryStringValue(
00269 IN HANDLE KeyHandle,
00270 IN PUNICODE_STRING ValueName,
00271 IN PUNICODE_STRING ValueData
00272 );
00273
00274
VOID
00275
IopInitializePlugPlayNotification(
00276 VOID
00277 );
00278
00279
VOID
00280
IopReferenceNotify(
00281
PNOTIFY_ENTRY_HEADER notify
00282 );
00283
00284
VOID
00285
IopDereferenceNotify(
00286
PNOTIFY_ENTRY_HEADER Notify
00287 );
00288
00289
NTSTATUS
00290
IopRegisterTargetDeviceNotification(
00291 IN ULONG Flags,
00292 IN
PFILE_OBJECT FileObject,
00293 IN
PDRIVER_OBJECT DriverObject,
00294 IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine,
00295 IN PVOID Context,
00296 IN BOOLEAN AddLast,
00297 OUT PVOID *NotificationEntry
00298 );
00299
00300
NTSTATUS
00301
IopOpenOrCreateDeviceInterfaceSubKeys(
00302 OUT PHANDLE InterfaceKeyHandle OPTIONAL,
00303 OUT PULONG InterfaceKeyDisposition OPTIONAL,
00304 OUT PHANDLE InterfaceInstanceKeyHandle OPTIONAL,
00305 OUT PULONG InterfaceInstanceDisposition OPTIONAL,
00306 IN HANDLE InterfaceClassKeyHandle,
00307 IN PUNICODE_STRING DeviceInterfaceName,
00308 IN ACCESS_MASK DesiredAccess,
00309 IN BOOLEAN Create
00310 );
00311
00312
NTSTATUS
00313
PpCreateLegacyDeviceIds(
00314 IN
PDEVICE_OBJECT DeviceObject,
00315 IN PUNICODE_STRING DriverName,
00316 IN PCM_RESOURCE_LIST Resources
00317 );
00318
00319
#ifdef ALLOC_PRAGMA
00320
#pragma alloc_text(PAGE, IopIsReportedAlready)
00321
#pragma alloc_text(PAGE, IoCreateDriver)
00322
#pragma alloc_text(PAGE, IoDeleteDriver)
00323
#pragma alloc_text(PAGE, IoReportDetectedDevice)
00324
#pragma alloc_text(PAGE, IoOpenDeviceRegistryKey)
00325
#pragma alloc_text(PAGE, IoGetDeviceProperty)
00326
#pragma alloc_text(PAGE, IoRegisterPlugPlayNotification)
00327
#pragma alloc_text(PAGE, IoUnregisterPlugPlayNotification)
00328
#pragma alloc_text(PAGE, IoGetDeviceInterfaces)
00329
#pragma alloc_text(PAGE, IopGetDeviceInterfaces)
00330
#pragma alloc_text(PAGE, IoSetDeviceInterfaceState)
00331
#pragma alloc_text(PAGE, IoRegisterDeviceInterface)
00332
#pragma alloc_text(PAGE, IopRegisterDeviceInterface)
00333
#pragma alloc_text(PAGE, IopUnregisterDeviceInterface)
00334
#pragma alloc_text(PAGE, IopRemoveDeviceInterfaces)
00335
#pragma alloc_text(PAGE, IoOpenDeviceInterfaceRegistryKey)
00336
#pragma alloc_text(PAGE, IoGetDeviceInterfaceAlias)
00337
#pragma alloc_text(PAGE, IopDeviceInterfaceKeysFromSymbolicLink)
00338
#pragma alloc_text(PAGE, IopBuildSymbolicLinkStrings)
00339
#pragma alloc_text(PAGE, IopReplaceSeperatorWithPound)
00340
#pragma alloc_text(PAGE, IopAllocateUnicodeString)
00341
#pragma alloc_text(PAGE, IopFreeAllocatedUnicodeString)
00342
#pragma alloc_text(PAGE, IopDropReferenceString)
00343
#pragma alloc_text(PAGE, IopRealloc)
00344
#pragma alloc_text(PAGE, IopSetRegistryStringValue)
00345
#pragma alloc_text(PAGE, IopRegisterTargetDeviceNotification)
00346
#pragma alloc_text(PAGE, IopNotifyDeviceClassChange)
00347
#pragma alloc_text(PAGE, IopNotifyTargetDeviceChange)
00348
#pragma alloc_text(PAGE, IopNotifyHwProfileChange)
00349
#pragma alloc_text(PAGE, IopNotifySetupDeviceArrival)
00350
#pragma alloc_text(PAGE, IopRequestHwProfileChangeNotification)
00351
#pragma alloc_text(PAGE, IoNotifyPowerOperationVetoed)
00352
#pragma alloc_text(PAGE, IopDereferenceNotify)
00353
#pragma alloc_text(PAGE, IopReferenceNotify)
00354
#pragma alloc_text(PAGE, IopInitializePlugPlayNotification)
00355
#pragma alloc_text(PAGE, IoSynchronousInvalidateDeviceRelations)
00356
#pragma alloc_text(PAGE, IopParseSymbolicLinkName)
00357
#pragma alloc_text(PAGE, IopOverwriteBuffer)
00358
#pragma alloc_text(PAGE, IopAppendBuffer)
00359
#pragma alloc_text(PAGE, IopFreeBuffer)
00360
#pragma alloc_text(PAGE, IopResizeBuffer)
00361
#pragma alloc_text(PAGE, IopAllocateBuffer)
00362
#pragma alloc_text(PAGE, IopOpenOrCreateDeviceInterfaceSubKeys)
00363
#pragma alloc_text(PAGE, IoIsWdmVersionAvailable)
00364
#pragma alloc_text(PAGE, IoGetDmaAdapter)
00365
#pragma alloc_text(PAGE, IopGetRelatedTargetDevice)
00366
#pragma alloc_text(PAGE, IoGetRelatedTargetDevice)
00367
#pragma alloc_text(PAGE, IopResourceRequirementsChanged)
00368
#pragma alloc_text(PAGE, PpCreateLegacyDeviceIds)
00369
#pragma alloc_text(PAGE, IopPnPHydraCallback)
00370
#endif // ALLOC_PRAGMA
00371
00372
NTSTATUS
00373 IoGetDeviceProperty(
00374 IN
PDEVICE_OBJECT DeviceObject,
00375 IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
00376 IN ULONG BufferLength,
00377 OUT PVOID PropertyBuffer,
00378 OUT PULONG ResultLength
00379 )
00380
00381
00382
00383
00384
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
00411
00412 {
00413
PDEVICE_NODE deviceNode;
00414
DEVICE_CAPABILITIES capabilities;
00415
NTSTATUS status;
00416 HANDLE handle;
00417 PWSTR valueName, keyName =
NULL;
00418 PKEY_VALUE_FULL_INFORMATION keyValueInformation;
00419 ULONG valueType;
00420 ULONG length;
00421 POBJECT_NAME_INFORMATION deviceObjectName;
00422 PWSTR deviceInstanceName;
00423 PWCHAR enumeratorNameEnd;
00424
00425
PAGED_CODE();
00426
00427
ASSERT_PDO(DeviceObject);
00428
00429
00430
00431
00432
00433 *ResultLength = 0;
00434
00435
00436
00437
00438
00439
switch (DeviceProperty) {
00440
00441
case DevicePropertyDeviceDescription:
00442 valueName = REGSTR_VALUE_DEVICE_DESC;
00443 valueType = REG_SZ;
00444
break;
00445
00446
case DevicePropertyHardwareID:
00447 valueName = REGSTR_VAL_HARDWAREID;
00448 valueType = REG_MULTI_SZ;
00449
break;
00450
00451
case DevicePropertyCompatibleIDs:
00452 valueName = REGSTR_VAL_COMPATIBLEIDS;
00453 valueType = REG_MULTI_SZ;
00454
break;
00455
00456
case DevicePropertyBootConfiguration:
00457 keyName = REGSTR_KEY_LOG_CONF;
00458 valueName = REGSTR_VAL_BOOTCONFIG;
00459 valueType = REG_RESOURCE_LIST;
00460
break;
00461
00462
case DevicePropertyBootConfigurationTranslated:
00463
00464
00465
00466
return STATUS_NOT_SUPPORTED;
00467
break;
00468
00469
case DevicePropertyClassName:
00470 valueName = REGSTR_VALUE_CLASS;
00471 valueType = REG_SZ;
00472
break;
00473
00474
case DevicePropertyClassGuid:
00475 valueName = REGSTR_VALUE_CLASSGUID;
00476 valueType = REG_SZ;
00477
break;
00478
00479
case DevicePropertyDriverKeyName:
00480 valueName = REGSTR_VALUE_DRIVER;
00481 valueType = REG_SZ;
00482
break;
00483
00484
case DevicePropertyManufacturer:
00485 valueName = REGSTR_VAL_MFG;
00486 valueType = REG_SZ;
00487
break;
00488
00489
case DevicePropertyFriendlyName:
00490 valueName = REGSTR_VALUE_FRIENDLYNAME;
00491 valueType = REG_SZ;
00492
break;
00493
00494
case DevicePropertyLocationInformation:
00495 valueName = REGSTR_VAL_LOCATION_INFORMATION;
00496 valueType = REG_SZ;
00497
break;
00498
00499
case DevicePropertyUINumber:
00500 valueName = REGSTR_VAL_UI_NUMBER;
00501 valueType = REG_DWORD;
00502
break;
00503
00504
case DevicePropertyPhysicalDeviceObjectName:
00505
00506
ASSERT (0 == (1 & BufferLength));
00507
00508
00509
00510
00511 length = BufferLength +
sizeof (OBJECT_NAME_INFORMATION);
00512
00513 deviceObjectName = (POBJECT_NAME_INFORMATION)
00514
ExAllocatePool(
PagedPool, length);
00515
00516
if (
NULL == deviceObjectName) {
00517
return STATUS_INSUFFICIENT_RESOURCES;
00518 }
00519
00520 status =
ObQueryNameString (DeviceObject,
00521 deviceObjectName,
00522 length,
00523 ResultLength);
00524
00525
if (STATUS_INFO_LENGTH_MISMATCH == status) {
00526 status = STATUS_BUFFER_TOO_SMALL;
00527 }
00528
00529
if (
NT_SUCCESS (status)) {
00530
00531
if (deviceObjectName->Name.Length == 0) {
00532
00533
00534
00535
00536 *ResultLength = 0;
00537
00538 }
else {
00539
00540 *ResultLength = deviceObjectName->Name.Length +
sizeof(UNICODE_NULL);
00541
if (*ResultLength > BufferLength) {
00542 status = STATUS_BUFFER_TOO_SMALL;
00543 }
else {
00544
00545 RtlCopyMemory(PropertyBuffer,
00546 deviceObjectName->Name.Buffer,
00547 deviceObjectName->Name.Length);
00548 *(PWCHAR) (((PUCHAR) PropertyBuffer) + deviceObjectName->Name.Length) =
L'\0';
00549 }
00550 }
00551 }
else {
00552 *ResultLength -=
sizeof(OBJECT_NAME_INFORMATION);
00553 }
00554
00555
ExFreePool (deviceObjectName);
00556
return status;
00557
00558
00559
case DevicePropertyBusTypeGuid:
00560
00561 deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
00562
if (deviceNode->
ChildBusTypeIndex != 0xffff
00563 && deviceNode->
ChildBusTypeIndex <
IopBusTypeGuidList->
Count) {
00564
00565 *ResultLength =
sizeof(GUID);
00566
00567
if(*ResultLength <= BufferLength) {
00568
00569 RtlCopyMemory(PropertyBuffer,
00570 &(
IopBusTypeGuidList->
Guid[deviceNode->
ChildBusTypeIndex]),
00571
sizeof(GUID));
00572
00573 status = STATUS_SUCCESS;
00574
00575 }
else {
00576
00577 status = STATUS_BUFFER_TOO_SMALL;
00578
00579 }
00580
00581 }
else {
00582 status = STATUS_OBJECT_NAME_NOT_FOUND;
00583 }
00584
00585
return status;
00586
00587
case DevicePropertyLegacyBusType:
00588
00589 deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
00590
if (deviceNode->
ChildInterfaceType != InterfaceTypeUndefined) {
00591
00592 *ResultLength =
sizeof(INTERFACE_TYPE);
00593
00594
if(*ResultLength <= BufferLength) {
00595
00596 *(PINTERFACE_TYPE)PropertyBuffer = deviceNode->
ChildInterfaceType;
00597 status = STATUS_SUCCESS;
00598
00599 }
else {
00600 status = STATUS_BUFFER_TOO_SMALL;
00601 }
00602
00603 }
else {
00604 status = STATUS_OBJECT_NAME_NOT_FOUND;
00605 }
00606
00607
return status;
00608
00609
case DevicePropertyBusNumber:
00610
00611
00612
00613
00614
00615 deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
00616
if ((deviceNode->
ChildBusNumber & 0x80000000) != 0x80000000) {
00617
00618 *ResultLength =
sizeof(ULONG);
00619
00620
if(*ResultLength <= BufferLength) {
00621
00622 *(PULONG)PropertyBuffer = deviceNode->
ChildBusNumber;
00623 status = STATUS_SUCCESS;
00624
00625 }
else {
00626 status = STATUS_BUFFER_TOO_SMALL;
00627 }
00628
00629 }
else {
00630 status = STATUS_OBJECT_NAME_NOT_FOUND;
00631 }
00632
00633
return status;
00634
00635
case DevicePropertyEnumeratorName:
00636
00637
ASSERT (0 == (1 & BufferLength));
00638
00639 deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
00640 deviceInstanceName = deviceNode->
InstancePath.Buffer;
00641
00642
00643
00644
00645
00646
00647
ASSERT (deviceInstanceName);
00648
00649
00650
00651
00652
00653
00654 enumeratorNameEnd = wcschr(deviceInstanceName, OBJ_NAME_PATH_SEPARATOR);
00655
ASSERT (enumeratorNameEnd);
00656
00657
00658
00659
00660 length = (ULONG)((PUCHAR)enumeratorNameEnd - (PUCHAR)deviceInstanceName);
00661
00662
00663
00664
00665 *ResultLength = length +
sizeof(UNICODE_NULL);
00666
00667
if(*ResultLength > BufferLength) {
00668 status = STATUS_BUFFER_TOO_SMALL;
00669 }
else {
00670 memcpy((PUCHAR)PropertyBuffer, (PUCHAR)deviceInstanceName, length);
00671 *(PWCHAR)((PUCHAR)PropertyBuffer + length) = UNICODE_NULL;
00672 status = STATUS_SUCCESS;
00673 }
00674
00675
return status;
00676
00677
case DevicePropertyAddress:
00678
00679 deviceNode = (
PDEVICE_NODE)DeviceObject->DeviceObjectExtension->DeviceNode;
00680
00681 status =
IopQueryDeviceCapabilities(deviceNode, &capabilities);
00682
00683
if (
NT_SUCCESS(status) && (capabilities.
Address != 0xFFFFFFFF)) {
00684
00685 *ResultLength =
sizeof(ULONG);
00686
00687
if(*ResultLength <= BufferLength) {
00688
00689 *(PULONG)PropertyBuffer = capabilities.
Address;
00690 status = STATUS_SUCCESS;
00691
00692 }
else {
00693 status = STATUS_BUFFER_TOO_SMALL;
00694 }
00695
00696 }
else {
00697 status = STATUS_OBJECT_NAME_NOT_FOUND;
00698 }
00699
00700
return status;
00701
00702
default:
00703 status = STATUS_INVALID_PARAMETER_2;
00704
goto clean0;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
KeEnterCriticalRegion();
00717
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
00718
00719
00720
00721
00722
00723
00724 status =
IopDeviceObjectToDeviceInstance(DeviceObject, &handle, KEY_READ);
00725
if (!
NT_SUCCESS(status)) {
00726
goto clean1;
00727 }
00728
00729
00730
00731
00732
00733
if (keyName) {
00734 HANDLE subKeyHandle;
00735 UNICODE_STRING unicodeKey;
00736
00737
RtlInitUnicodeString(&unicodeKey, keyName);
00738 status =
IopOpenRegistryKeyEx( &subKeyHandle,
00739 handle,
00740 &unicodeKey,
00741 KEY_READ
00742 );
00743
00744
if(
NT_SUCCESS(status)){
00745 ZwClose(handle);
00746 handle = subKeyHandle;
00747 }
else {
00748
goto clean2;
00749 }
00750
00751 }
00752
00753
00754
00755
00756
00757 status =
IopGetRegistryValue (handle,
00758 valueName,
00759 &keyValueInformation);
00760
00761
00762
00763
00764
00765
00766 clean2:
00767 ZwClose(handle);
00768 clean1:
00769
ExReleaseResource(&
PpRegistryDeviceResource);
00770
KeLeaveCriticalRegion();
00771
00772
00773
00774
00775
00776
if (
NT_SUCCESS(status)) {
00777
00778
00779
00780
00781
00782 *ResultLength = keyValueInformation->DataLength;
00783
00784
00785
00786
00787
00788
00789
if (keyValueInformation->DataLength <= BufferLength) {
00790
if (keyValueInformation->Type == valueType) {
00791 RtlCopyMemory(PropertyBuffer,
00792
KEY_VALUE_DATA(keyValueInformation),
00793 keyValueInformation->DataLength);
00794
00795 }
else {
00796 status = STATUS_INVALID_PARAMETER_2;
00797 }
00798 }
else {
00799 status = STATUS_BUFFER_TOO_SMALL;
00800 }
00801
00802
ExFreePool(keyValueInformation);
00803 }
00804
00805 clean0:
00806
return status;
00807 }
00808
00809
NTSTATUS
00810 IoOpenDeviceRegistryKey(
00811 IN
PDEVICE_OBJECT PhysicalDeviceObject,
00812 IN ULONG DevInstKeyType,
00813 IN ACCESS_MASK DesiredAccess,
00814 OUT PHANDLE DevInstRegKey
00815 )
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863 {
00864
00865
NTSTATUS status, appendStatus;
00866 HANDLE hBasePath;
00867 UNICODE_STRING unicodeBasePath, unicodeRestPath;
00868
00869
PAGED_CODE();
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881 *DevInstRegKey =
NULL;
00882
00883
00884
00885
00886
00887
if(!(unicodeRestPath.Buffer =
ExAllocatePool(
PagedPool,
MAX_RESTPATH_BUF_LEN))) {
00888 status = STATUS_INSUFFICIENT_RESOURCES;
00889
goto clean0;
00890 }
00891
00892 unicodeRestPath.Length=0;
00893 unicodeRestPath.MaximumLength=
MAX_RESTPATH_BUF_LEN;
00894
00895
00896
00897
00898
00899
00900
if(DevInstKeyType &
PLUGPLAY_REGKEY_CURRENT_HWPROFILE) {
00901 PiWstrToUnicodeString(&unicodeBasePath,
PATH_CURRENTCONTROLSET_HW_PROFILE_CURRENT);
00902
00903 }
else {
00904 PiWstrToUnicodeString(&unicodeBasePath,
PATH_CURRENTCONTROLSET);
00905 }
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
KeEnterCriticalRegion();
00917
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
00918
00919
00920
00921
00922
00923 status =
IopOpenRegistryKeyEx( &hBasePath,
00924
NULL,
00925 &unicodeBasePath,
00926 KEY_READ
00927 );
00928
00929
if(!
NT_SUCCESS(status)) {
00930
goto clean1;
00931 }
00932
00933
00934
00935
00936
00937
switch (DevInstKeyType) {
00938
00939
case PLUGPLAY_REGKEY_DEVICE:
00940
case PLUGPLAY_REGKEY_DEVICE +
PLUGPLAY_REGKEY_CURRENT_HWPROFILE:
00941 {
00942
PDEVICE_NODE pDeviceNode;
00943
00944
00945
00946
00947
00948 appendStatus =
RtlAppendUnicodeToString(&unicodeRestPath,
PATH_ENUM);
00949
ASSERT(
NT_SUCCESS( appendStatus ));
00950
00951
00952
00953
00954 pDeviceNode = (
PDEVICE_NODE) PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
00955
00956
00957
00958
00959
00960
if (pDeviceNode) {
00961 appendStatus =
RtlAppendUnicodeStringToString(&unicodeRestPath, &(pDeviceNode->
InstancePath));
00962
ASSERT(
NT_SUCCESS( appendStatus ));
00963 }
else {
00964 status = STATUS_INVALID_DEVICE_REQUEST;
00965 }
00966
00967
break;
00968 }
00969
00970
case PLUGPLAY_REGKEY_DRIVER:
00971
case PLUGPLAY_REGKEY_DRIVER +
PLUGPLAY_REGKEY_CURRENT_HWPROFILE:
00972 {
00973
00974 HANDLE hDeviceKey;
00975 PKEY_VALUE_FULL_INFORMATION pDriverKeyInfo;
00976
00977
00978
00979
00980
00981 appendStatus =
RtlAppendUnicodeToString(&unicodeRestPath,
PATH_CONTROL_CLASS);
00982
ASSERT(
NT_SUCCESS( appendStatus ));
00983
00984
00985
00986
00987
00988 status =
IopDeviceObjectToDeviceInstance(PhysicalDeviceObject, &hDeviceKey, KEY_READ);
00989
00990
if(!
NT_SUCCESS(status)){
00991
goto clean1;
00992 }
00993
00994
00995
00996
00997
00998 status =
IopGetRegistryValue(hDeviceKey, REGSTR_VALUE_DRIVER, &pDriverKeyInfo );
00999
01000
if(
NT_SUCCESS(status)){
01001
01002
if(pDriverKeyInfo->Type == REG_SZ) {
01003
01004
01005
01006
01007
01008 appendStatus =
RtlAppendUnicodeToString(&unicodeRestPath, (PWSTR)
KEY_VALUE_DATA(pDriverKeyInfo));
01009
ASSERT(
NT_SUCCESS( appendStatus ));
01010
01011 }
else {
01012
01013
01014
01015
01016 status = STATUS_INVALID_PARAMETER_1;
01017 }
01018
01019
ExFreePool(pDriverKeyInfo);
01020 }
01021
01022 ZwClose(hDeviceKey);
01023
01024
break;
01025 }
01026
default:
01027 status = STATUS_INVALID_PARAMETER_3;
01028
goto clean2;
01029 }
01030
01031
01032
01033
01034
01035
01036
if (
NT_SUCCESS(status)){
01037
if (DevInstKeyType ==
PLUGPLAY_REGKEY_DEVICE) {
01038
01039 status =
IopOpenDeviceParametersSubkey(DevInstRegKey,
01040 hBasePath,
01041 &unicodeRestPath,
01042 DesiredAccess);
01043 }
else {
01044
01045 status =
IopCreateRegistryKeyEx( DevInstRegKey,
01046 hBasePath,
01047 &unicodeRestPath,
01048 DesiredAccess,
01049 REG_OPTION_NON_VOLATILE,
01050
NULL
01051 );
01052 }
01053 }
01054
01055
01056
01057
01058
01059 clean2:
01060 ZwClose(hBasePath);
01061 clean1:
01062
ExReleaseResource(&
PpRegistryDeviceResource);
01063
KeLeaveCriticalRegion();
01064
ExFreePool(unicodeRestPath.Buffer);
01065 clean0:
01066
return status;
01067
01068 }
01069
01070
NTSTATUS
01071 IoCreateDriver(
01072 IN PUNICODE_STRING DriverName OPTIONAL,
01073 IN PDRIVER_INITIALIZE InitializationFunction
01074 )
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098 {
01099 OBJECT_ATTRIBUTES objectAttributes;
01100
NTSTATUS status;
01101
PDRIVER_OBJECT driverObject;
01102 HANDLE driverHandle;
01103 ULONG objectSize;
01104
USHORT length;
01105 UNICODE_STRING driverName, serviceName;
01106 WCHAR buffer[60];
01107 ULONG i;
01108
01109
PAGED_CODE();
01110
01111
if (DriverName ==
NULL) {
01112
01113
01114
01115
01116
01117 length = (
USHORT) _snwprintf(buffer,
sizeof(buffer) /
sizeof(WCHAR),
L"\\Driver\\%08u",
KeTickCount);
01118 driverName.Length = length *
sizeof(WCHAR);
01119 driverName.MaximumLength = driverName.Length +
sizeof(UNICODE_NULL);
01120 driverName.Buffer = buffer; \
01121 }
else {
01122 driverName = *DriverName;
01123 }
01124
01125
01126
01127
01128
01129 InitializeObjectAttributes( &objectAttributes,
01130 &driverName,
01131 OBJ_PERMANENT | OBJ_CASE_INSENSITIVE,
01132
NULL,
01133
NULL );
01134
01135 objectSize =
sizeof(
DRIVER_OBJECT ) +
sizeof(
DRIVER_EXTENSION );
01136 status =
ObCreateObject(
KernelMode,
01137
IoDriverObjectType,
01138 &objectAttributes,
01139
KernelMode,
01140
NULL,
01141 objectSize,
01142 0,
01143 0,
01144 &driverObject );
01145
01146
if( !
NT_SUCCESS( status )){
01147
01148
01149
01150
01151
01152
return status;
01153 }
01154
01155
01156
01157
01158
01159 RtlZeroMemory( driverObject, objectSize );
01160 driverObject->
DriverExtension = (
PDRIVER_EXTENSION)(driverObject + 1);
01161 driverObject->
DriverExtension->
DriverObject = driverObject;
01162 driverObject->
Type =
IO_TYPE_DRIVER;
01163 driverObject->
Size =
sizeof(
DRIVER_OBJECT );
01164 driverObject->
Flags =
DRVO_BUILTIN_DRIVER;
01165
for (i = 0; i <=
IRP_MJ_MAXIMUM_FUNCTION; i++)
01166 driverObject->
MajorFunction[i] =
IopInvalidDeviceRequest;
01167 driverObject->
DriverInit = InitializationFunction;
01168
01169 serviceName.Buffer = (PWSTR)
ExAllocatePool(
PagedPool, driverName.Length +
sizeof(WCHAR));
01170
if (serviceName.Buffer) {
01171 serviceName.MaximumLength = driverName.Length +
sizeof(WCHAR);
01172 serviceName.Length = driverName.Length;
01173 RtlMoveMemory(serviceName.Buffer, driverName.Buffer, driverName.Length);
01174 serviceName.Buffer[serviceName.Length /
sizeof(WCHAR)] = UNICODE_NULL;
01175 driverObject->
DriverExtension->
ServiceKeyName = serviceName;
01176 }
else {
01177 status = STATUS_INSUFFICIENT_RESOURCES;
01178
goto errorFreeDriverObject;
01179 }
01180
01181
01182
01183
01184
01185 status =
ObInsertObject( driverObject,
01186
NULL,
01187 FILE_READ_DATA,
01188 0,
01189
NULL,
01190 &driverHandle );
01191
01192
if( !
NT_SUCCESS( status )){
01193
01194
01195
01196
01197
01198
01199
goto errorReturn;
01200 }
01201
01202
01203
01204
01205
01206
01207 status =
ObReferenceObjectByHandle( driverHandle,
01208 0,
01209
IoDriverObjectType,
01210
KernelMode,
01211 (PVOID *) &driverObject,
01212 (
POBJECT_HANDLE_INFORMATION)
NULL );
01213
if( !
NT_SUCCESS( status )) {
01214
01215
01216
01217
01218 ZwMakeTemporaryObject( driverHandle );
01219 ZwClose( driverHandle );
01220
goto errorReturn;
01221 }
01222
01223 ZwClose( driverHandle );
01224
01225
01226
01227
01228
01229
01230 driverObject->DriverName.Buffer =
ExAllocatePool(
PagedPool,
01231 driverName.MaximumLength );
01232
if (driverObject->DriverName.Buffer) {
01233 driverObject->DriverName.MaximumLength = driverName.MaximumLength;
01234 driverObject->DriverName.Length = driverName.Length;
01235
01236 RtlCopyMemory( driverObject->DriverName.Buffer,
01237 driverName.Buffer,
01238 driverName.MaximumLength );
01239 }
01240
01241
01242
01243
01244
01245 status = (*InitializationFunction)(driverObject,
NULL);
01246
01247
if( !
NT_SUCCESS( status )){
01248
01249 errorFreeDriverObject:
01250
01251
01252
01253
01254
01255
01256
ObMakeTemporaryObject( driverObject );
01257
ObDereferenceObject( driverObject );
01258 }
01259 errorReturn:
01260
return status;
01261 }
01262
01263
VOID
01264 IoDeleteDriver(
01265 IN
PDRIVER_OBJECT DriverObject
01266 )
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285 {
01286
01287
ObDereferenceObject(DriverObject);
01288 }
01289
01290
NTSTATUS
01291 IoSynchronousInvalidateDeviceRelations(
01292
PDEVICE_OBJECT DeviceObject,
01293 DEVICE_RELATION_TYPE Type
01294 )
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324 {
01325
PDEVICE_NODE deviceNode;
01326
NTSTATUS status = STATUS_SUCCESS;
01327
KEVENT completionEvent;
01328
01329
PAGED_CODE();
01330
01331
ASSERT_PDO(DeviceObject);
01332
01333
switch (Type) {
01334
case BusRelations:
01335
01336
if (
PnPInitialized) {
01337
01338 deviceNode = (
PDEVICE_NODE)DeviceObject->
DeviceObjectExtension->
DeviceNode;
01339
01340
if (deviceNode->
Flags &
DNF_STARTED) {
01341
01342
KeInitializeEvent( &completionEvent, NotificationEvent,
FALSE );
01343
01344 status =
IopRequestDeviceAction( DeviceObject,
01345
ReenumerateDeviceTree,
01346 &completionEvent,
01347
NULL );
01348
01349
if (
NT_SUCCESS(status)) {
01350
01351 status =
KeWaitForSingleObject( &completionEvent,
01352
Executive,
01353
KernelMode,
01354
FALSE,
01355
NULL);
01356 }
01357 }
else {
01358 status = STATUS_UNSUCCESSFUL;
01359 }
01360 }
else {
01361
01362
01363
01364
01365 status = STATUS_UNSUCCESSFUL;
01366 }
01367
01368
01369
break;
01370
01371
case EjectionRelations:
01372
01373
01374
01375
01376
01377
01378
01379 status = STATUS_NOT_SUPPORTED;
01380
break;
01381
01382
case PowerRelations:
01383
01384
01385
01386
01387
01388
PoInvalidateDevicePowerRelations(DeviceObject);
01389
break;
01390 }
01391
return status;
01392 }
01393
01394
VOID
01395 IoInvalidateDeviceRelations(
01396
PDEVICE_OBJECT DeviceObject,
01397 DEVICE_RELATION_TYPE Type
01398 )
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423 {
01424
01425
PDEVICE_NODE deviceNode;
01426 KIRQL oldIrql;
01427
01428
ASSERT_PDO(DeviceObject);
01429
01430
switch (Type) {
01431
case BusRelations:
01432
01433
01434
01435
01436
01437
01438
01439 deviceNode = (
PDEVICE_NODE) DeviceObject->
DeviceObjectExtension->
DeviceNode;
01440
if (deviceNode) {
01441
01442 ExAcquireSpinLock(&
IopPnPSpinLock, &oldIrql);
01443
if (deviceNode->
Flags &
DNF_BEING_ENUMERATED) {
01444 deviceNode->
Flags |=
DNF_IO_INVALIDATE_DEVICE_RELATIONS_PENDING;
01445 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01446 }
else if ((deviceNode->
Flags &
DNF_STARTED) &&
01447 !(deviceNode->
Flags &
DNF_ENUMERATION_REQUEST_QUEUED)) {
01448 deviceNode->
Flags |=
DNF_ENUMERATION_REQUEST_QUEUED;
01449 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01450
01451
IopRequestDeviceAction( DeviceObject,
01452
ReenumerateDeviceTree,
01453
NULL,
01454
NULL );
01455 }
else {
01456 ExReleaseSpinLock(&
IopPnPSpinLock, oldIrql);
01457 }
01458 }
01459
break;
01460
01461
case EjectionRelations:
01462
01463
01464
01465
01466
01467
01468
break;
01469
01470
case PowerRelations:
01471
01472
01473
01474
01475
PoInvalidateDevicePowerRelations(DeviceObject);
01476
break;
01477 }
01478 }
01479
01480
VOID
01481 IoRequestDeviceEject(
01482
PDEVICE_OBJECT DeviceObject
01483 )
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513 {
01514
ASSERT_PDO(DeviceObject);
01515
01516
IopQueueDeviceWorkItem(DeviceObject,
IopRequestDeviceEjectWorker,
NULL);
01517 }
01518
01519
VOID
01520 IopRequestDeviceEjectWorker(
01521 PVOID Context
01522 )
01523 {
01524
PDEVICE_WORK_ITEM deviceWorkItem = (
PDEVICE_WORK_ITEM)Context;
01525
PDEVICE_OBJECT deviceObject = deviceWorkItem->
DeviceObject;
01526
01527
ExFreePool(deviceWorkItem);
01528
01529
01530
01531
01532
01533
PpSetTargetDeviceRemove( deviceObject,
01534
TRUE,
01535
TRUE,
01536
TRUE,
01537 CM_PROB_DEVICE_NOT_THERE,
01538
NULL,
01539
NULL,
01540
NULL,
01541
NULL);
01542
01543
ObDereferenceObject(deviceObject);
01544 }
01545
01546
01547
NTSTATUS
01548 IoReportDetectedDevice(
01549 IN
PDRIVER_OBJECT DriverObject,
01550 IN INTERFACE_TYPE LegacyBusType,
01551 IN ULONG BusNumber,
01552 IN ULONG SlotNumber,
01553 IN PCM_RESOURCE_LIST ResourceList,
01554 IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL,
01555 IN BOOLEAN ResourceAssigned,
01556 IN OUT
PDEVICE_OBJECT *DeviceObject
01557 )
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
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 WCHAR buffer[60];
01603
NTSTATUS status;
01604 UNICODE_STRING deviceName, instanceName, unicodeName, *serviceName, driverName;
01605
PDEVICE_NODE deviceNode;
01606 ULONG length, i = 0, disposition, tmpValue, listSize = 0;
01607 HANDLE handle, handle1, logConfHandle, controlHandle, hTreeHandle, enumHandle;
01608 PCM_RESOURCE_LIST cmResource;
01609 PWSTR p;
01610 LARGE_INTEGER tickCount;
01611
PDEVICE_OBJECT deviceObject;
01612 BOOLEAN newlyCreated =
FALSE;
01613
01614
PAGED_CODE();
01615
01616
if (*DeviceObject) {
01617
01618 deviceObject = *DeviceObject;
01619
01620
01621
01622
01623
01624 deviceNode = (
PDEVICE_NODE)(*DeviceObject)->DeviceObjectExtension->DeviceNode;
01625
if (!deviceNode) {
01626
return STATUS_NO_SUCH_DEVICE;
01627 }
01628
01629
KeEnterCriticalRegion();
01630
ExAcquireResourceShared(&
PpRegistryDeviceResource,
TRUE);
01631
01632
01633
01634
01635
01636 status =
IopDeviceObjectToDeviceInstance (*DeviceObject,
01637 &handle,
01638 KEY_ALL_ACCESS
01639 );
01640
if (!
NT_SUCCESS(status)) {
01641
ExReleaseResource(&
PpRegistryDeviceResource);
01642
KeLeaveCriticalRegion();
01643
return status;
01644 }
01645
if (ResourceAssigned) {
01646
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_NO_RESOURCE_AT_INIT);
01647 tmpValue = 1;
01648 ZwSetValueKey(handle,
01649 &unicodeName,
01650
TITLE_INDEX_VALUE,
01651 REG_DWORD,
01652 &tmpValue,
01653
sizeof(tmpValue)
01654 );
01655 }
01656
RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
01657 status =
IopCreateRegistryKeyEx( &logConfHandle,
01658 handle,
01659 &unicodeName,
01660 KEY_ALL_ACCESS,
01661 REG_OPTION_NON_VOLATILE,
01662
NULL
01663 );
01664 ZwClose(handle);
01665
if (
NT_SUCCESS(status)) {
01666
01667
01668
01669
01670
01671
01672
if (ResourceList) {
01673
RtlInitUnicodeString(&unicodeName, REGSTR_VAL_BOOTCONFIG);
01674 ZwSetValueKey(
01675 logConfHandle,
01676 &unicodeName,
01677
TITLE_INDEX_VALUE,
01678 REG_RESOURCE_LIST,
01679 ResourceList,
01680 listSize =
IopDetermineResourceListSize(ResourceList)
01681 );
01682 }
01683
if (ResourceRequirements) {
01684
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_BASIC_CONFIG_VECTOR);
01685 ZwSetValueKey(
01686 logConfHandle,
01687 &unicodeName,
01688
TITLE_INDEX_VALUE,
01689 REG_RESOURCE_REQUIREMENTS_LIST,
01690 ResourceRequirements,
01691 ResourceRequirements->ListSize
01692 );
01693 }
01694 ZwClose(logConfHandle);
01695 }
01696
ExReleaseResource(&
PpRegistryDeviceResource);
01697
KeLeaveCriticalRegion();
01698
if (
NT_SUCCESS(status)) {
01699
goto checkResource;
01700 }
else {
01701
return status;
01702 }
01703 }
01704
01705
01706
01707
01708
01709 *DeviceObject =
NULL;
01710 serviceName = &DriverObject->DriverExtension->ServiceKeyName;
01711
01712
01713
01714
01715
01716
01717
01718
01719
if (DriverObject->Flags &
DRVO_BUILTIN_DRIVER) {
01720 p = serviceName->Buffer + (serviceName->Length /
sizeof(WCHAR)) - 1;
01721 driverName.Length = 0;
01722
while (*p !=
'\\' && (p != serviceName->Buffer)) {
01723 p--;
01724 driverName.Length +=
sizeof(WCHAR);
01725 }
01726
if (p == serviceName->Buffer) {
01727
return STATUS_UNSUCCESSFUL;
01728 }
else {
01729 p++;
01730 driverName.Buffer = p;
01731 driverName.MaximumLength = driverName.Length +
sizeof(WCHAR);
01732 }
01733 }
else {
01734
01735
01736
01737
01738
01739 status =
IopDuplicateDetection(
01740 LegacyBusType,
01741
BusNumber,
01742 SlotNumber,
01743 &deviceNode
01744 );
01745
01746
if (
NT_SUCCESS(status) && deviceNode) {
01747 deviceObject = deviceNode->
PhysicalDeviceObject;
01748
if ((deviceNode->
Flags &
DNF_ADDED) ||
01749 (
IopDoesDevNodeHaveProblem(deviceNode) &&
01750 deviceNode->
Problem != CM_PROB_NOT_CONFIGURED &&
01751 deviceNode->
Problem != CM_PROB_REINSTALL &&
01752 deviceNode->
Problem != CM_PROB_FAILED_INSTALL)) {
01753
01754
01755
01756
01757
01758
ObDereferenceObject(deviceObject);
01759
01760
return STATUS_NO_SUCH_DEVICE;
01761 }
01762
01763 deviceNode->
Flags &= ~
DNF_HAS_PROBLEM;
01764 deviceNode->
Problem = 0;
01765
01766
IopDeleteLegacyKey(DriverObject);
01767
goto checkResource;
01768 }
01769
01770 }
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
KeQueryTickCount(&tickCount);
01781 length = _snwprintf(buffer,
sizeof(buffer) /
sizeof(WCHAR),
L"\\Device\\%04u%x",
IopNumberDeviceNodes, tickCount.LowPart);
01782 deviceName.MaximumLength =
sizeof(buffer);
01783 deviceName.Length = (
USHORT)(length *
sizeof(WCHAR));
01784 deviceName.Buffer = buffer; \
01785
01786 status =
IoCreateDevice(
IoPnpDriverObject,
01787
sizeof(
IOPNP_DEVICE_EXTENSION),
01788 &deviceName,
01789 FILE_DEVICE_CONTROLLER,
01790 0,
01791
FALSE,
01792 &deviceObject );
01793
01794
if (
NT_SUCCESS(status)) {
01795 deviceObject->
Flags |=
DO_BUS_ENUMERATED_DEVICE;
01796 deviceNode =
IopAllocateDeviceNode(deviceObject);
01797
if (deviceNode) {
01798
01799
01800
01801
01802
01803
if (!(DriverObject->Flags &
DRVO_BUILTIN_DRIVER)) {
01804
IopDeleteLegacyKey(DriverObject);
01805 }
01806
01807
01808
01809
01810
01811 status =
PpCreateLegacyDeviceIds(
01812 deviceObject,
01813 ((DriverObject->Flags &
DRVO_BUILTIN_DRIVER) ?
01814 &driverName : serviceName),
01815 ResourceList);
01816
01817
if(!
NT_SUCCESS(status)) {
01818
goto exit;
01819 }
01820
01821
01822
01823
01824
01825
01826
if (DriverObject->Flags &
DRVO_BUILTIN_DRIVER) {
01827 length = _snwprintf(buffer,
sizeof(buffer) /
sizeof(WCHAR),
L"ROOT\\%s", driverName.Buffer);
01828 }
else {
01829 length = _snwprintf(buffer,
sizeof(buffer) /
sizeof(WCHAR),
L"ROOT\\%s", serviceName->Buffer);
01830 }
01831 deviceName.MaximumLength =
sizeof(buffer);
01832
ASSERT(length <=
sizeof(buffer) - 10);
01833 deviceName.Length = (
USHORT)(length *
sizeof(WCHAR));
01834 deviceName.Buffer = buffer;
01835
01836
KeEnterCriticalRegion();
01837
ExAcquireResourceShared(&
PpRegistryDeviceResource,
TRUE);
01838
01839 status =
IopOpenRegistryKeyEx( &enumHandle,
01840
NULL,
01841 &
CmRegistryMachineSystemCurrentControlSetEnumName,
01842 KEY_ALL_ACCESS
01843 );
01844
if (!
NT_SUCCESS(status)) {
01845
goto exit;
01846 }
01847
01848 status =
IopCreateRegistryKeyEx( &handle1,
01849 enumHandle,
01850 &deviceName,
01851 KEY_ALL_ACCESS,
01852 REG_OPTION_NON_VOLATILE,
01853 &disposition
01854 );
01855
01856
if (
NT_SUCCESS(status)) {
01857 deviceName.Buffer[deviceName.Length /
sizeof(WCHAR)] =
01858 OBJ_NAME_PATH_SEPARATOR;
01859 deviceName.Length +=
sizeof(WCHAR);
01860
if (disposition != REG_CREATED_NEW_KEY) {
01861
while (
TRUE) {
01862 PiUlongToInstanceKeyUnicodeString(&instanceName,
01863 buffer + deviceName.Length /
sizeof(WCHAR),
01864
sizeof(buffer) - deviceName.Length,
01865 i
01866 );
01867 status =
IopCreateRegistryKeyEx( &handle,
01868 handle1,
01869 &instanceName,
01870 KEY_ALL_ACCESS,
01871 REG_OPTION_NON_VOLATILE,
01872 &disposition
01873 );
01874
if (
NT_SUCCESS(status)) {
01875
if (disposition == REG_CREATED_NEW_KEY) {
01876 ZwClose(handle1);
01877
break;
01878 }
else {
01879
if (
IopIsReportedAlready(handle, serviceName, ResourceList)) {
01880
01881
01882
01883
01884
01885
RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
01886 status =
IopCreateRegistryKeyEx( &logConfHandle,
01887 handle,
01888 &unicodeName,
01889 KEY_ALL_ACCESS,
01890 REG_OPTION_NON_VOLATILE,
01891
NULL
01892 );
01893
if (
NT_SUCCESS(status)) {
01894
01895
01896
01897
01898
01899
if (ResourceList) {
01900
RtlInitUnicodeString(&unicodeName, REGSTR_VAL_BOOTCONFIG);
01901 ZwSetValueKey(
01902 logConfHandle,
01903 &unicodeName,
01904
TITLE_INDEX_VALUE,
01905 REG_RESOURCE_LIST,
01906 ResourceList,
01907 listSize =
IopDetermineResourceListSize(ResourceList)
01908 );
01909 }
01910
if (ResourceRequirements) {
01911
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_BASIC_CONFIG_VECTOR);
01912 ZwSetValueKey(
01913 logConfHandle,
01914 &unicodeName,
01915
TITLE_INDEX_VALUE,
01916 REG_RESOURCE_REQUIREMENTS_LIST,
01917 ResourceRequirements,
01918 ResourceRequirements->ListSize
01919 );
01920 }
01921 ZwClose(logConfHandle);
01922 }
01923
01924
ExReleaseResource(&
PpRegistryDeviceResource);
01925
KeLeaveCriticalRegion();
01926
IoDeleteDevice(deviceObject);
01927 ZwClose(handle1);
01928 deviceObject =
IopDeviceObjectFromDeviceInstance (
01929 handle,
NULL);
01930 ZwClose(handle);
01931 ZwClose(enumHandle);
01932
ASSERT(deviceObject);
01933
if (deviceObject ==
NULL) {
01934 status = STATUS_UNSUCCESSFUL;
01935
return status;
01936 }
01937 deviceNode = (
PDEVICE_NODE)
01938 deviceObject->
DeviceObjectExtension->
DeviceNode;
01939
goto checkResource;
01940 }
else {
01941 i++;
01942 ZwClose(handle);
01943
continue;
01944 }
01945 }
01946 }
else {
01947 ZwClose(handle1);
01948 ZwClose(enumHandle);
01949
goto exit;
01950 }
01951 }
01952 }
else {
01953
01954
01955
01956
01957
01958 PiUlongToInstanceKeyUnicodeString(&instanceName,
01959 buffer + deviceName.Length /
sizeof(WCHAR),
01960
sizeof(buffer) - deviceName.Length,
01961 i
01962 );
01963 status =
IopCreateRegistryKeyEx( &handle,
01964 handle1,
01965 &instanceName,
01966 KEY_ALL_ACCESS,
01967 REG_OPTION_NON_VOLATILE,
01968 &disposition
01969 );
01970 ZwClose(handle1);
01971
if (!
NT_SUCCESS(status)) {
01972 ZwClose(enumHandle);
01973
goto exit;
01974 }
01975
ASSERT(disposition == REG_CREATED_NEW_KEY);
01976 }
01977 }
else {
01978 ZwClose(enumHandle);
01979
goto exit;
01980 }
01981
01982 deviceName.Length += instanceName.Length;
01983
ASSERT(disposition == REG_CREATED_NEW_KEY);
01984 newlyCreated =
TRUE;
01985
01986
01987
01988
01989
01990
if (ResourceAssigned) {
01991
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_NO_RESOURCE_AT_INIT);
01992 tmpValue = 1;
01993 ZwSetValueKey(handle,
01994 &unicodeName,
01995
TITLE_INDEX_VALUE,
01996 REG_DWORD,
01997 &tmpValue,
01998
sizeof(tmpValue)
01999 );
02000 }
02001
RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
02002 logConfHandle =
NULL;
02003 status =
IopCreateRegistryKeyEx( &logConfHandle,
02004 handle,
02005 &unicodeName,
02006 KEY_ALL_ACCESS,
02007 REG_OPTION_NON_VOLATILE,
02008
NULL
02009 );
02010
02011
ASSERT(status == STATUS_SUCCESS);
02012
02013
if (
NT_SUCCESS(status)) {
02014
02015
02016
02017
02018
02019
02020
if (ResourceList) {
02021
RtlInitUnicodeString(&unicodeName, REGSTR_VAL_BOOTCONFIG);
02022 ZwSetValueKey(
02023 logConfHandle,
02024 &unicodeName,
02025
TITLE_INDEX_VALUE,
02026 REG_RESOURCE_LIST,
02027 ResourceList,
02028 listSize =
IopDetermineResourceListSize(ResourceList)
02029 );
02030 }
02031
if (ResourceRequirements) {
02032
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_BASIC_CONFIG_VECTOR);
02033 ZwSetValueKey(
02034 logConfHandle,
02035 &unicodeName,
02036
TITLE_INDEX_VALUE,
02037 REG_RESOURCE_REQUIREMENTS_LIST,
02038 ResourceRequirements,
02039 ResourceRequirements->ListSize
02040 );
02041 }
02042
02043 }
02044
02045
RtlInitUnicodeString(&unicodeName, REGSTR_VALUE_CONFIG_FLAGS);
02046 tmpValue = CONFIGFLAG_FINISH_INSTALL;
02047 ZwSetValueKey(handle,
02048 &unicodeName,
02049
TITLE_INDEX_VALUE,
02050 REG_DWORD,
02051 &tmpValue,
02052
sizeof(tmpValue)
02053 );
02054
02055 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_LEGACY);
02056 tmpValue = 0;
02057 ZwSetValueKey(
02058 handle,
02059 &unicodeName,
02060
TITLE_INDEX_VALUE,
02061 REG_DWORD,
02062 &tmpValue,
02063
sizeof(ULONG)
02064 );
02065
02066
RtlInitUnicodeString(&unicodeName, REGSTR_KEY_CONTROL);
02067 controlHandle =
NULL;
02068
IopCreateRegistryKeyEx( &controlHandle,
02069 handle,
02070 &unicodeName,
02071 KEY_ALL_ACCESS,
02072 REG_OPTION_VOLATILE,
02073
NULL
02074 );
02075
02076
ASSERT(status == STATUS_SUCCESS);
02077
02078
if (
NT_SUCCESS(status)) {
02079
02080
02081
02082
02083
02084 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_DEVICE_REFERENCE);
02085 status = ZwSetValueKey(controlHandle,
02086 &unicodeName,
02087
TITLE_INDEX_VALUE,
02088 REG_DWORD,
02089 (PULONG_PTR)&deviceObject,
02090
sizeof(ULONG_PTR)
02091 );
02092 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_DEVICE_REPORTED);
02093 tmpValue = 1;
02094 status = ZwSetValueKey(controlHandle,
02095 &unicodeName,
02096
TITLE_INDEX_VALUE,
02097 REG_DWORD,
02098 &tmpValue,
02099
sizeof(ULONG)
02100 );
02101 status = ZwSetValueKey(handle,
02102 &unicodeName,
02103
TITLE_INDEX_VALUE,
02104 REG_DWORD,
02105 &tmpValue,
02106
sizeof(ULONG)
02107 );
02108
02109
02110 }
02111
02112 ZwClose(enumHandle);
02113
02114
02115
02116
02117
02118
02119 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_SERVICE);
02120 p = (PWSTR)
ExAllocatePool(
PagedPool, serviceName->Length +
sizeof(UNICODE_NULL));
02121
if (!p) {
02122
goto CleanupRegistry;
02123 }
02124 RtlMoveMemory(p, serviceName->Buffer, serviceName->Length);
02125 p[serviceName->Length /
sizeof (WCHAR)] = UNICODE_NULL;
02126 ZwSetValueKey(
02127 handle,
02128 &unicodeName,
02129
TITLE_INDEX_VALUE,
02130 REG_SZ,
02131 p,
02132 serviceName->Length +
sizeof(UNICODE_NULL)
02133 );
02134
if (DriverObject->Flags &
DRVO_BUILTIN_DRIVER) {
02135 deviceNode->
ServiceName = *serviceName;
02136 }
else {
02137
ExFreePool(p);
02138 }
02139
02140
ExReleaseResource(&
PpRegistryDeviceResource);
02141
KeLeaveCriticalRegion();
02142
02143
02144
02145
02146
02147
02148
02149
02150
02151
if (!(DriverObject->Flags &
DRVO_BUILTIN_DRIVER)) {
02152
PpDeviceRegistration( &deviceName,
02153
TRUE,
02154 &deviceNode->
ServiceName
02155 );
02156 }
02157
02158
IopConcatenateUnicodeStrings(&deviceNode->
InstancePath, &deviceName,
NULL);
02159
02160 deviceNode->
Flags =
DNF_MADEUP +
DNF_ENUMERATED +
DNF_PROCESSED;
02161
02162
IopInsertTreeDeviceNode(
IopRootDeviceNode, deviceNode);
02163
02164
02165
02166
02167
02168
ObReferenceObject(deviceObject);
02169
02170
IopNotifySetupDeviceArrival(deviceObject,
NULL,
FALSE);
02171
02172
goto checkResource;
02173 }
else {
02174
IoDeleteDevice(deviceObject);
02175 status = STATUS_INSUFFICIENT_RESOURCES;
02176 }
02177 }
02178
return status;
02179 checkResource:
02180
02181
02182
02183
02184
02185
02186
02187
if (ResourceAssigned) {
02188
02189
02190
02191
02192
02193
02194
02195
02196 deviceNode->
Flags |=
DNF_NO_RESOURCE_REQUIRED;
02197
if (ResourceList) {
02198
02199
02200
02201
02202
02203 listSize =
IopDetermineResourceListSize(ResourceList);
02204
IopWriteAllocatedResourcesToRegistry (deviceNode, ResourceList, listSize);
02205 }
02206 }
else {
02207 BOOLEAN conflict;
02208
02209
if (ResourceList && ResourceList->Count && ResourceList->List[0].PartialResourceList.Count) {
02210
if (listSize == 0) {
02211 listSize =
IopDetermineResourceListSize(ResourceList);
02212 }
02213 cmResource = (PCM_RESOURCE_LIST)
ExAllocatePool(
PagedPool, listSize);
02214
if (cmResource) {
02215 RtlCopyMemory(cmResource, ResourceList, listSize);
02216
RtlInitUnicodeString(&unicodeName, PNPMGR_STR_PNP_MANAGER);
02217 status =
IoReportResourceUsageInternal(
02218
ArbiterRequestLegacyReported,
02219 &unicodeName,
02220
IoPnpDriverObject,
02221
NULL,
02222 0,
02223 deviceNode->
PhysicalDeviceObject,
02224
02225 cmResource,
02226 listSize,
02227
FALSE,
02228 &conflict
02229 );
02230
ExFreePool(cmResource);
02231
if (!
NT_SUCCESS(status) || conflict) {
02232 status = STATUS_CONFLICTING_ADDRESSES;
02233
IopSetDevNodeProblem(deviceNode, CM_PROB_NORMAL_CONFLICT);
02234 }
02235 }
else {
02236 status = STATUS_INSUFFICIENT_RESOURCES;
02237
IopSetDevNodeProblem(deviceNode, CM_PROB_OUT_OF_MEMORY);
02238 }
02239 }
else {
02240
ASSERT(ResourceRequirements ==
NULL);
02241 deviceNode->
Flags |=
DNF_NO_RESOURCE_REQUIRED;
02242 }
02243 }
02244
02245
if (
NT_SUCCESS(status)) {
02246
02247
IopDoDeferredSetInterfaceState(deviceNode);
02248
02249 deviceNode->
Flags |=
DNF_STARTED |
DNF_ADDED |
DNF_NEED_ENUMERATION_ONLY |
DNF_NEED_QUERY_IDS;
02250 *DeviceObject = deviceObject;
02251
if (newlyCreated) {
02252
if (controlHandle) {
02253 ZwClose(controlHandle);
02254 }
02255
if (logConfHandle) {
02256 ZwClose(logConfHandle);
02257 }
02258 ZwClose(handle);
02259 }
02260
return status;
02261
02262 }
02263 CleanupRegistry:
02264
IopReleaseDeviceResources(deviceNode,
FALSE);
02265
if (newlyCreated) {
02266
IoDeleteDevice(deviceObject);
02267
if (controlHandle) {
02268 ZwDeleteKey(controlHandle);
02269 }
02270
if (logConfHandle) {
02271 ZwDeleteKey(logConfHandle);
02272 }
02273
if (handle) {
02274 ZwDeleteKey(handle);
02275 }
02276 }
02277
return status;
02278
exit:
02279
ExReleaseResource(&
PpRegistryDeviceResource);
02280
KeLeaveCriticalRegion();
02281
IoDeleteDevice(*DeviceObject);
02282
return status;
02283 }
02284
02285 BOOLEAN
02286 IopIsReportedAlready(
02287 IN HANDLE Handle,
02288 IN PUNICODE_STRING ServiceName,
02289 IN PCM_RESOURCE_LIST ResourceList
02290 )
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313 {
02314 PKEY_VALUE_FULL_INFORMATION keyValueInfo1 =
NULL, keyValueInfo2 =
NULL;
02315
NTSTATUS status;
02316 UNICODE_STRING unicodeName;
02317 HANDLE logConfHandle, controlHandle =
NULL;
02318 BOOLEAN returnValue =
FALSE;
02319 PCM_RESOURCE_LIST cmResource =
NULL;
02320 ULONG tmpValue;
02321
02322
PAGED_CODE();
02323
02324
02325
02326
02327
02328
02329
RtlInitUnicodeString(&unicodeName, REGSTR_KEY_CONTROL);
02330 status =
IopOpenRegistryKeyEx( &controlHandle,
02331
Handle,
02332 &unicodeName,
02333 KEY_ALL_ACCESS
02334 );
02335
if (
NT_SUCCESS(status)) {
02336 status =
IopGetRegistryValue(controlHandle,
02337 REGSTR_VALUE_DEVICE_REPORTED,
02338 &keyValueInfo1);
02339
if (
NT_SUCCESS(status)) {
02340
goto exit;
02341 }
02342
02343
02344
02345
02346
02347 status =
IopGetRegistryValue(
Handle, REGSTR_VALUE_SERVICE, &keyValueInfo1);
02348
if (
NT_SUCCESS(status)) {
02349
if ((keyValueInfo1->Type == REG_SZ) &&
02350 (keyValueInfo1->DataLength != 0)) {
02351 unicodeName.Buffer = (PWSTR)
KEY_VALUE_DATA(keyValueInfo1);
02352 unicodeName.MaximumLength = unicodeName.Length = (
USHORT)keyValueInfo1->DataLength;
02353
if (unicodeName.Buffer[(keyValueInfo1->DataLength /
sizeof(WCHAR)) - 1] == UNICODE_NULL) {
02354 unicodeName.Length -=
sizeof(WCHAR);
02355 }
02356
if (
RtlEqualUnicodeString(ServiceName, &unicodeName,
TRUE)) {
02357
02358
02359
02360
02361
02362
RtlInitUnicodeString(&unicodeName, REGSTR_KEY_LOG_CONF);
02363 status =
IopOpenRegistryKeyEx( &logConfHandle,
02364
Handle,
02365 &unicodeName,
02366 KEY_READ
02367 );
02368
if (
NT_SUCCESS(status)) {
02369 status =
IopGetRegistryValue(logConfHandle,
02370 REGSTR_VAL_BOOTCONFIG,
02371 &keyValueInfo2);
02372 ZwClose(logConfHandle);
02373
if (
NT_SUCCESS(status)) {
02374
if ((keyValueInfo2->Type == REG_RESOURCE_LIST) &&
02375 (keyValueInfo2->DataLength != 0)) {
02376 cmResource = (PCM_RESOURCE_LIST)
KEY_VALUE_DATA(keyValueInfo2);
02377
if (ResourceList && cmResource &&
02378
IopIsDuplicatedDevices(ResourceList, cmResource,
NULL,
NULL)) {
02379 returnValue =
TRUE;
02380 }
02381 }
02382 }
02383 }
02384
if (!ResourceList && !cmResource) {
02385 returnValue =
TRUE;
02386 }
02387 }
02388 }
02389 }
02390
if (returnValue ==
TRUE) {
02391
02392
02393
02394
02395
02396 PiWstrToUnicodeString(&unicodeName, REGSTR_VALUE_DEVICE_REPORTED);
02397 tmpValue = 1;
02398 status = ZwSetValueKey(controlHandle,
02399 &unicodeName,
02400
TITLE_INDEX_VALUE,
02401 REG_DWORD,
02402 &tmpValue,
02403
sizeof(ULONG)
02404 );
02405
if (!
NT_SUCCESS(status)) {
02406 returnValue =
FALSE;
02407 }
02408 }
02409 }
02410
02411
exit:
02412
if (controlHandle) {
02413 ZwClose(controlHandle);
02414 }
02415
02416
if (keyValueInfo1) {
02417
ExFreePool(keyValueInfo1);
02418 }
02419
if (keyValueInfo2) {
02420
ExFreePool(keyValueInfo2);
02421 }
02422
return returnValue;
02423 }
02424
02425
02426
NTSTATUS
02427 IopAllocateBuffer(
02428 IN
PBUFFER_INFO Info,
02429 IN ULONG Size
02430 )
02431
02432
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448
02449
02450
02451
02452 {
02453
ASSERT(Info);
02454
02455
if (!(Info->Buffer =
ExAllocatePool(
PagedPool,
Size))) {
02456
return STATUS_INSUFFICIENT_RESOURCES;
02457 }
02458
02459 Info->Current = Info->Buffer;
02460 Info->MaxSize =
Size;
02461
02462
return STATUS_SUCCESS;
02463 }
02464
02465
02466
NTSTATUS
02467 IopResizeBuffer(
02468 IN
PBUFFER_INFO Info,
02469 IN ULONG NewSize,
02470 IN BOOLEAN CopyContents
02471 )
02472
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489
02490
02491
02492
02493
02494
02495
02496 {
02497 ULONG used;
02498 PCHAR newBuffer;
02499
02500
ASSERT(Info);
02501
02502 used = (ULONG)(Info->Current - Info->Buffer);
02503
02504
if (!(newBuffer =
ExAllocatePool(
PagedPool, NewSize))) {
02505
return STATUS_INSUFFICIENT_RESOURCES;
02506 }
02507
02508
if (CopyContents) {
02509
02510
02511
02512
02513
02514
ASSERT(used < NewSize);
02515
02516 RtlCopyMemory(newBuffer,
02517 Info->Buffer,
02518 used);
02519
02520 Info->Current = newBuffer + used;
02521
02522 }
else {
02523
02524 Info->Current = newBuffer;
02525 }
02526
02527
ExFreePool(Info->Buffer);
02528
02529 Info->Buffer = newBuffer;
02530 Info->MaxSize = NewSize;
02531
02532
return STATUS_SUCCESS;
02533 }
02534
02535
VOID
02536 IopFreeBuffer(
02537 IN
PBUFFER_INFO Info
02538 )
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555
02556 {
02557
ASSERT(Info);
02558
02559
02560
02561
02562
02563
ExFreePool(Info->Buffer);
02564
02565
02566
02567
02568
02569 Info->Buffer =
NULL;
02570 Info->Current =
NULL;
02571 Info->MaxSize = 0;
02572 }
02573
02574
NTSTATUS
02575 IopAppendBuffer(
02576 IN
PBUFFER_INFO Info,
02577 IN PVOID Data,
02578 IN ULONG DataSize
02579 )
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597
02598
02599
02600
02601 {
02602
02603
NTSTATUS status = STATUS_SUCCESS;
02604 ULONG free, used;
02605
02606
ASSERT(Info);
02607
02608 used = (ULONG)(Info->Current - Info->Buffer);
02609 free = Info->MaxSize - used;
02610
02611
if (free < DataSize) {
02612 status =
IopResizeBuffer(Info, used + DataSize,
TRUE);
02613
02614
if (!
NT_SUCCESS(status)) {
02615
goto clean0;
02616 }
02617
02618 }
02619
02620
02621
02622
02623
02624 RtlCopyMemory(Info->Current,
02625 Data,
02626 DataSize);
02627
02628
02629
02630
02631
02632 Info->Current += DataSize;
02633
02634 clean0:
02635
return status;
02636
02637 }
02638
02639
NTSTATUS
02640 IopOverwriteBuffer(
02641 IN
PBUFFER_INFO Info,
02642 IN PVOID Data,
02643 IN ULONG DataSize
02644 )
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656
02657
02658
02659
02660
02661
02662
02663
02664
02665
02666
02667
02668 {
02669
NTSTATUS status = STATUS_SUCCESS;
02670 ULONG free;
02671
02672
ASSERT(Info);
02673
02674 free = Info->MaxSize;
02675
02676
02677
if (free < DataSize) {
02678 status =
IopResizeBuffer(Info, DataSize,
FALSE);
02679
02680
if (!
NT_SUCCESS(status)) {
02681
goto clean0;
02682 }
02683
02684 }
02685
02686
02687
02688
02689
02690 RtlCopyMemory(Info->Buffer,
02691 Data,
02692 DataSize);
02693
02694
02695
02696
02697
02698 Info->Current += DataSize;
02699
02700 clean0:
02701
return status;
02702 }
02703
02704 #define DBG_GET_ASSOC 0
02705
02706
NTSTATUS
02707 IopGetDeviceInterfaces(
02708 IN CONST GUID *InterfaceClassGuid,
02709 IN PUNICODE_STRING DevicePath OPTIONAL,
02710 IN ULONG Flags,
02711 IN BOOLEAN UserModeFormat,
02712 OUT PWSTR *SymbolicLinkList,
02713 OUT PULONG SymbolicLinkListSize OPTIONAL
02714 )
02715
02716
02717
02718
02719
02720
02721
02722
02723
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754 {
02755
NTSTATUS status;
02756 UNICODE_STRING guidString, tempString, defaultString, symLinkString, devnodeString;
02757
BUFFER_INFO returnBuffer, infoBuffer, symLinkBuffer, devnodeNameBuffer;
02758 PKEY_VALUE_FULL_INFORMATION pDefaultInfo;
02759 ULONG tempLong, keyIndex, instanceKeyIndex, resultSize;
02760 HANDLE hDeviceClasses, hClass, hKey, hInstanceKey, hControl;
02761 BOOLEAN defaultPresent =
FALSE;
02762
02763
PAGED_CODE();
02764
02765
02766
02767
02768
02769 *SymbolicLinkList =
NULL;
02770
02771
02772
02773
02774
02775 status =
RtlStringFromGUID(InterfaceClassGuid, &guidString);
02776
if(!
NT_SUCCESS(status)) {
02777
goto finalClean;
02778 }
02779
02780
#if DBG_GET_ASSOC
02781
DbgPrint(
"Getting associations for class %wZ\n", &guidString);
02782
#endif
02783
02784
02785
02786
02787
02788 status =
IopAllocateBuffer(&returnBuffer,
02789
INITIAL_RETURN_BUFFER_SIZE
02790 );
02791
02792
if (!
NT_SUCCESS(status)) {
02793
goto clean0;
02794 }
02795
02796 status =
IopAllocateBuffer(&infoBuffer,
02797
INITIAL_INFO_BUFFER_SIZE
02798 );
02799
02800
if (!
NT_SUCCESS(status)) {
02801
goto clean1;
02802 }
02803
02804 status =
IopAllocateBuffer(&symLinkBuffer,
02805
INITIAL_SYMLINK_BUFFER_SIZE
02806 );
02807
02808
if (!
NT_SUCCESS(status)) {
02809
goto clean2;
02810 }
02811
02812 status =
IopAllocateBuffer(&devnodeNameBuffer,
02813
INITIAL_DEVNODE_NAME_BUFFER_SIZE
02814 );
02815
02816
if (!
NT_SUCCESS(status)) {
02817
goto clean2a;
02818 }
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
KeEnterCriticalRegion();
02830
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
02831
02832
02833
02834
02835
02836 PiWstrToUnicodeString(&tempString, REGSTR_FULL_PATH_DEVICE_CLASSES);
02837 status =
IopCreateRegistryKeyEx( &hDeviceClasses,
02838
NULL,
02839 &tempString,
02840 KEY_ALL_ACCESS,
02841 REG_OPTION_NON_VOLATILE,
02842
NULL
02843 );
02844
02845
if (!
NT_SUCCESS(status)) {
02846
goto clean3;
02847 }
02848
02849
02850
02851
02852
02853 status =
IopOpenRegistryKeyEx( &hClass,
02854 hDeviceClasses,
02855 &guidString,
02856 KEY_ALL_ACCESS
02857 );
02858 ZwClose(hDeviceClasses);
02859
02860
if(status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND) {
02861
02862
02863
02864
02865
02866 status = STATUS_SUCCESS;
02867
goto clean5;
02868 }
else if (!
NT_SUCCESS(status)) {
02869
goto clean3;
02870 }
02871
02872
02873
02874
02875
02876 status =
IopGetRegistryValue(hClass,
02877 REGSTR_VAL_DEFAULT,
02878 &pDefaultInfo
02879 );
02880
02881
02882
if (
NT_SUCCESS(status)
02883 && pDefaultInfo->Type == REG_SZ
02884 && pDefaultInfo->DataLength >=
sizeof(WCHAR)) {
02885
02886
02887
02888
02889
02890 defaultPresent =
TRUE;
02891 defaultString.Buffer = (PWSTR)
KEY_VALUE_DATA(pDefaultInfo);
02892 defaultString.Length = (
USHORT) pDefaultInfo->DataLength -
sizeof(UNICODE_NULL);
02893 defaultString.MaximumLength = defaultString.Length;
02894
02895
#if DBG_GET_ASSOC
02896
DbgPrint(
"Class default: %wZ\n", &defaultString);
02897
#endif
02898
02899
02900
02901
02902 status =
IopOpenOrCreateDeviceInterfaceSubKeys(
NULL,
02903
NULL,
02904 &hKey,
02905
NULL,
02906 hClass,
02907 &defaultString,
02908 KEY_READ,
02909
FALSE
02910 );
02911
02912
if (!
NT_SUCCESS(status)) {
02913 defaultPresent =
FALSE;
02914
ExFreePool(pDefaultInfo);
02915
02916
02917
02918
#if DBG_GET_ASSOC
02919
DbgPrint(
"WDM Warning: Default entry for class %zW is invalid\n", &guidString);
02920
#endif
02921
}
else {
02922
02923
02924
02925
02926
02927
02928
if (!(Flags &
DEVICE_INTERFACE_INCLUDE_NONACTIVE)) {
02929
02930 defaultPresent =
FALSE;
02931
02932
02933
02934
02935
02936 PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
02937 status =
IopOpenRegistryKeyEx( &hControl,
02938 hKey,
02939 &tempString,
02940 KEY_ALL_ACCESS
02941 );
02942
02943
if (
NT_SUCCESS(status)) {
02944
02945
02946
02947
02948 PiWstrToUnicodeString(&tempString, REGSTR_VAL_LINKED);
02949 status = ZwQueryValueKey(hControl,
02950 &tempString,
02951 KeyValuePartialInformation,
02952 (PVOID) infoBuffer.
Buffer,
02953 infoBuffer.
MaxSize,
02954 &resultSize
02955 );
02956
02957 ZwClose(hControl);
02958
02959
02960
02961
02962
02963
02964
if (
NT_SUCCESS(status)
02965 && (((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.
Buffer))->Type == REG_DWORD)
02966 && (((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.
Buffer))->DataLength ==
sizeof(ULONG))) {
02967
02968 defaultPresent = *(PULONG)(((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.
Buffer))->Data)
02969 ?
TRUE
02970 :
FALSE;
02971 }
02972 }
02973 }
02974
02975 ZwClose(hKey);
02976
02977
if(defaultPresent) {
02978
02979
02980
02981 status =
IopAppendBuffer(&returnBuffer,
02982 defaultString.
Buffer,
02983 defaultString.Length +
sizeof(UNICODE_NULL)
02984 );
02985
02986
if (!UserModeFormat) {
02987
02988 RtlCopyMemory(returnBuffer.
Buffer,
02989
KERNEL_SYMLINK_STRING_PREFIX,
02990
KERNEL_SYMLINK_STRING_PREFIX_LENGTH
02991 );
02992 }
02993
02994 }
else {
02995
02996
02997
02998
ExFreePool(pDefaultInfo);
02999 }
03000 }
03001
03002 }
else if (status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND) {
03003
03004
03005
03006 }
else {
03007
03008
03009
03010
if (
NT_SUCCESS(status)) {
03011
03012
ExFreePool(pDefaultInfo);
03013 status = STATUS_UNSUCCESSFUL;
03014 }
03015
03016 ZwClose(hClass);
03017
goto clean4;
03018 }
03019
03020
03021
03022
03023
03024 keyIndex = 0;
03025
03026
while((status = ZwEnumerateKey(hClass,
03027 keyIndex,
03028 KeyBasicInformation,
03029 (PVOID) infoBuffer.
Buffer,
03030 infoBuffer.
MaxSize,
03031 &resultSize
03032 )) != STATUS_NO_MORE_ENTRIES)
03033 {
03034
03035
if (status == STATUS_BUFFER_TOO_SMALL) {
03036
03037 status =
IopResizeBuffer(&infoBuffer, resultSize,
FALSE);
03038
03039
continue;
03040
03041 }
else if (!
NT_SUCCESS(status)) {
03042 ZwClose(hClass);
03043
goto clean4;
03044 }
03045
03046
03047
03048
03049 tempString.Length = (
USHORT) ((PKEY_BASIC_INFORMATION)(infoBuffer.
Buffer))->NameLength;
03050 tempString.MaximumLength = tempString.Length;
03051 tempString.Buffer = ((PKEY_BASIC_INFORMATION)(infoBuffer.
Buffer))->Name;
03052
03053
#if DBG_GET_ASSOC
03054
DbgPrint(
"Key %u enumerated %wZ\n", keyIndex, &tempString);
03055
#endif
03056
03057
03058
03059
03060
03061 status =
IopOpenRegistryKeyEx( &hKey,
03062 hClass,
03063 &tempString,
03064 KEY_READ
03065 );
03066
03067
if (!
NT_SUCCESS(status)) {
03068
03069
03070
03071
#if DBG_GET_ASSOC
03072
DbgPrint(
"\tCouldn't open interface key!\n");
03073
#endif
03074
keyIndex++;
03075
continue;
03076 }
03077
03078
03079
03080
03081
03082 PiWstrToUnicodeString(&tempString, REGSTR_VAL_DEVICE_INSTANCE);
03083
while ((status = ZwQueryValueKey(hKey,
03084 &tempString,
03085 KeyValuePartialInformation,
03086 devnodeNameBuffer.
Buffer,
03087 devnodeNameBuffer.
MaxSize,
03088 &resultSize
03089 )) == STATUS_BUFFER_TOO_SMALL ) {
03090
03091 status =
IopResizeBuffer(&devnodeNameBuffer, resultSize,
FALSE);
03092
03093
if (!
NT_SUCCESS(status)) {
03094 ZwClose(hKey);
03095 ZwClose(hClass);
03096
goto clean4;
03097 }
03098 }
03099
03100
if (!(
NT_SUCCESS(status)
03101 && ((PKEY_VALUE_PARTIAL_INFORMATION)(devnodeNameBuffer.
Buffer))->Type == REG_SZ
03102 && ((PKEY_VALUE_PARTIAL_INFORMATION)(devnodeNameBuffer.
Buffer))->DataLength >
sizeof(WCHAR) ) ) {
03103
#if DBG_GET_ASSOC
03104
DbgPrint(
"\tDevice instance entry corrupt\n");
03105
#endif
03106
goto CloseInterfaceKeyAndContinue;
03107 }
03108
03109
03110
03111
03112
03113 devnodeString.Length = (
USHORT) ((PKEY_VALUE_PARTIAL_INFORMATION)(devnodeNameBuffer.
Buffer))->DataLength -
sizeof(UNICODE_NULL);
03114 devnodeString.MaximumLength = tempString.Length;
03115 devnodeString.Buffer = (PWSTR) ((PKEY_VALUE_PARTIAL_INFORMATION)(devnodeNameBuffer.
Buffer))->Data;
03116
03117
03118
03119
03120 instanceKeyIndex = 0;
03121
03122
while((status = ZwEnumerateKey(hKey,
03123 instanceKeyIndex,
03124 KeyBasicInformation,
03125 (PVOID) infoBuffer.
Buffer,
03126 infoBuffer.
MaxSize,
03127 &resultSize
03128 )) != STATUS_NO_MORE_ENTRIES)
03129 {
03130
03131
if (status == STATUS_BUFFER_TOO_SMALL) {
03132
03133 status =
IopResizeBuffer(&infoBuffer, resultSize,
FALSE);
03134
03135
continue;
03136
03137 }
else if (!
NT_SUCCESS(status)) {
03138 ZwClose(hKey);
03139 ZwClose(hClass);
03140
goto clean4;
03141 }
03142
03143
03144
03145
03146 tempString.Length = (
USHORT) ((PKEY_BASIC_INFORMATION)(infoBuffer.
Buffer))->NameLength;
03147 tempString.MaximumLength = tempString.Length;
03148 tempString.Buffer = ((PKEY_BASIC_INFORMATION)(infoBuffer.
Buffer))->Name;
03149
03150
#if DBG_GET_ASSOC
03151
DbgPrint(
"Instance key %u enumerated %wZ\n", instanceKeyIndex, &tempString);
03152
#endif
03153
03154
03155
03156
03157
03158 status =
IopOpenRegistryKeyEx( &hInstanceKey,
03159 hKey,
03160 &tempString,
03161 KEY_READ
03162 );
03163
03164
if (!
NT_SUCCESS(status)) {
03165
03166
03167
03168
#if DBG_GET_ASSOC
03169
DbgPrint(
"\tCouldn't open interface key!\n");
03170
#endif
03171
instanceKeyIndex++;
03172
continue;
03173 }
03174
03175
if (!(Flags &
DEVICE_INTERFACE_INCLUDE_NONACTIVE)) {
03176
03177
03178
03179
03180
03181 PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
03182 status =
IopOpenRegistryKeyEx( &hControl,
03183 hInstanceKey,
03184 &tempString,
03185 KEY_READ
03186 );
03187
03188
if (!
NT_SUCCESS(status)) {
03189
03190
03191
03192
03193
03194
03195
#if DBG_GET_ASSOC
03196
DbgPrint(
"\tNo control subkey\n");
03197
#endif
03198
goto CloseInterfaceInstanceKeyAndContinue;
03199 }
03200
03201
03202
03203
03204
03205 PiWstrToUnicodeString(&tempString, REGSTR_VAL_LINKED);
03206 status = ZwQueryValueKey(hControl,
03207 &tempString,
03208 KeyValuePartialInformation,
03209 (PVOID) infoBuffer.
Buffer,
03210 infoBuffer.
MaxSize,
03211 &resultSize
03212 );
03213
03214 ZwClose(hControl);
03215
03216
03217
03218
03219
03220
03221
if (!
NT_SUCCESS(status)
03222 || (((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.
Buffer))->Type != REG_DWORD)
03223 || (((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.
Buffer))->DataLength !=
sizeof(ULONG))
03224 || !*(PULONG)(((PKEY_VALUE_PARTIAL_INFORMATION)(infoBuffer.
Buffer))->Data)) {
03225
03226
03227
03228
03229
03230
#if DBG_GET_ASSOC
03231
DbgPrint(
"\tNot Linked\n");
03232
#endif
03233
goto CloseInterfaceInstanceKeyAndContinue;
03234 }
03235 }
03236
03237
03238
03239
03240
03241 PiWstrToUnicodeString(&tempString, REGSTR_VAL_SYMBOLIC_LINK);
03242
while ((status = ZwQueryValueKey(hInstanceKey,
03243 &tempString,
03244 KeyValuePartialInformation,
03245 symLinkBuffer.
Buffer,
03246 symLinkBuffer.
MaxSize,
03247 &resultSize
03248 )) == STATUS_BUFFER_TOO_SMALL ) {
03249
03250 status =
IopResizeBuffer(&symLinkBuffer, resultSize,
FALSE);
03251
03252
if (!
NT_SUCCESS(status)) {
03253 ZwClose(hInstanceKey);
03254 ZwClose(hKey);
03255 ZwClose(hClass);
03256
goto clean4;
03257 }
03258 }
03259
03260
if (!(
NT_SUCCESS(status)
03261 && ((PKEY_VALUE_PARTIAL_INFORMATION)(symLinkBuffer.
Buffer))->Type == REG_SZ
03262 && ((PKEY_VALUE_PARTIAL_INFORMATION)(symLinkBuffer.
Buffer))->DataLength >
sizeof(WCHAR) ) ) {
03263
#if DBG_GET_ASSOC
03264
DbgPrint(
"\tSymbolic link entry corrupt\n");
03265
#endif
03266
goto CloseInterfaceInstanceKeyAndContinue;
03267 }
03268
03269
03270
03271
03272
03273 symLinkString.Length = (
USHORT) ((PKEY_VALUE_PARTIAL_INFORMATION)(symLinkBuffer.
Buffer))->DataLength -
sizeof(UNICODE_NULL);
03274 symLinkString.MaximumLength = symLinkString.Length;
03275 symLinkString.Buffer = (PWSTR) ((PKEY_VALUE_PARTIAL_INFORMATION)(symLinkBuffer.
Buffer))->Data;
03276
03277
03278
03279
03280
03281
if (defaultPresent) {
03282
03283
if (
RtlCompareUnicodeString(&defaultString, &symLinkString,
TRUE) == 0) {
03284
03285
03286
03287
03288
03289
#if DBG_GET_ASSOC
03290
DbgPrint(
"\tDefault entry skipped\n");
03291
#endif
03292
goto CloseInterfaceInstanceKeyAndContinue;
03293 }
03294 }
03295
03296
03297
03298
03299
03300
if (ARGUMENT_PRESENT(DevicePath)) {
03301
03302
03303
03304
if (
RtlCompareUnicodeString(DevicePath, &devnodeString,
TRUE) != 0) {
03305
03306
03307
03308
#if DBG_GET_ASSOC
03309
DbgPrint(
"\tNot from the correct PDO\n");
03310
#endif
03311
goto CloseInterfaceInstanceKeyAndContinue;
03312 }
03313 }
03314
03315
03316
03317
03318
03319 status =
IopAppendBuffer(&returnBuffer,
03320 symLinkString.
Buffer,
03321 symLinkString.Length +
sizeof(UNICODE_NULL)
03322 );
03323
03324
ASSERT(((PWSTR) returnBuffer.
Current)[-1] == UNICODE_NULL);
03325
03326
#if DBG_GET_ASSOC
03327
DbgPrint(
"\tAdded to return buffer\n");
03328
#endif
03329
03330
03331
03332
03333
03334
if (!UserModeFormat) {
03335
03336 RtlCopyMemory(returnBuffer.
Current - (symLinkString.Length +
sizeof(UNICODE_NULL)),
03337
KERNEL_SYMLINK_STRING_PREFIX,
03338
KERNEL_SYMLINK_STRING_PREFIX_LENGTH
03339 );
03340 }
03341
03342 CloseInterfaceInstanceKeyAndContinue:
03343 ZwClose(hInstanceKey);
03344 instanceKeyIndex++;
03345 }
03346
03347 CloseInterfaceKeyAndContinue:
03348 ZwClose(hKey);
03349 keyIndex++;
03350 }
03351
03352 ZwClose(hClass);
03353
03354 clean5:
03355
03356
03357
03358
03359 status =
IopResizeBuffer(&returnBuffer,
03360 (ULONG) (returnBuffer.
Current - returnBuffer.
Buffer +
sizeof(UNICODE_NULL)),
03361
TRUE
03362 );
03363
03364
if (
NT_SUCCESS(status)) {
03365
03366
03367
03368
03369 *((PWSTR) returnBuffer.
Current) = UNICODE_NULL;
03370 }
03371
03372 clean4:
03373
if (defaultPresent) {
03374
ExFreePool(pDefaultInfo);
03375 }
03376
03377 clean3:
03378
ExReleaseResource(&
PpRegistryDeviceResource);
03379
KeLeaveCriticalRegion();
03380
IopFreeBuffer(&devnodeNameBuffer);
03381
03382 clean2a:
03383
IopFreeBuffer(&symLinkBuffer);
03384
03385 clean2:
03386
IopFreeBuffer(&infoBuffer);
03387
03388 clean1:
03389
if (!
NT_SUCCESS(status)) {
03390
IopFreeBuffer(&returnBuffer);
03391 }
03392
03393 clean0:
03394
RtlFreeUnicodeString(&guidString);
03395
03396 finalClean:
03397
if (
NT_SUCCESS(status)) {
03398
03399 *SymbolicLinkList = (PWSTR) returnBuffer.
Buffer;
03400
03401
if (ARGUMENT_PRESENT(SymbolicLinkListSize)) {
03402 *SymbolicLinkListSize = returnBuffer.
MaxSize;
03403 }
03404
03405 }
else {
03406
03407 *SymbolicLinkList =
NULL;
03408
03409
if (ARGUMENT_PRESENT(SymbolicLinkListSize)) {
03410 *SymbolicLinkListSize = 0;
03411 }
03412
03413 }
03414
03415
return status;
03416 }
03417
03418
NTSTATUS
03419 IoGetDeviceInterfaces(
03420 IN CONST GUID *InterfaceClassGuid,
03421 IN
PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
03422 IN ULONG Flags,
03423 OUT PWSTR *SymbolicLinkList
03424 )
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461 {
03462
NTSTATUS status;
03463 PUNICODE_STRING pDeviceName =
NULL;
03464
PDEVICE_NODE pDeviceNode;
03465
03466
PAGED_CODE();
03467
03468
03469
03470
03471
03472
if (ARGUMENT_PRESENT(PhysicalDeviceObject)) {
03473
03474
ASSERT_PDO(PhysicalDeviceObject);
03475 pDeviceNode = (
PDEVICE_NODE) PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
03476 pDeviceName = &pDeviceNode->
InstancePath;
03477 }
03478
03479 status =
IopGetDeviceInterfaces(InterfaceClassGuid,
03480 pDeviceName,
03481 Flags,
03482
FALSE,
03483 SymbolicLinkList,
03484
NULL
03485 );
03486
return status;
03487 }
03488
03489
03490
NTSTATUS
03491 IopRealloc(
03492 IN OUT PVOID *Buffer,
03493 IN ULONG OldSize,
03494 IN ULONG NewSize
03495 )
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521 {
03522
03523 PVOID newBuffer;
03524
03525
PAGED_CODE();
03526
03527
ASSERT(*
Buffer);
03528
03529
03530
03531
03532
03533
if (!(newBuffer =
ExAllocatePool(
PagedPool, NewSize))) {
03534
return STATUS_INSUFFICIENT_RESOURCES;
03535 }
03536
03537
03538
03539
03540
03541
if(OldSize <= NewSize) {
03542 RtlCopyMemory(newBuffer, *
Buffer , OldSize);
03543 }
else {
03544 RtlCopyMemory(newBuffer, *
Buffer , NewSize);
03545 }
03546
03547
03548
03549
03550
ExFreePool(*
Buffer);
03551
03552
03553
03554
03555
03556 *
Buffer = newBuffer;
03557
03558
return STATUS_SUCCESS;
03559
03560 }
03561
03562
NTSTATUS
03563 IoSetDeviceInterfaceState(
03564 IN PUNICODE_STRING SymbolicLinkName,
03565 IN BOOLEAN Enable
03566 )
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577
03578
03579
03580
03581
03582
03583
03584
03585
03586
03587
03588
03589
03590 {
03591
NTSTATUS status;
03592
03593
PAGED_CODE();
03594
03595
03596
03597
03598
03599
03600
03601
03602
03603
03604
KeEnterCriticalRegion();
03605
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
03606
03607 status =
IopProcessSetInterfaceState(SymbolicLinkName, Enable,
TRUE);
03608
03609
ExReleaseResource(&
PpRegistryDeviceResource);
03610
KeLeaveCriticalRegion();
03611
03612
if (!
NT_SUCCESS(status) && !Enable) {
03613
03614
03615
03616
03617 status = STATUS_SUCCESS;
03618 }
03619
03620
return status;
03621 }
03622
03623
NTSTATUS
03624 IoOpenDeviceInterfaceRegistryKey(
03625 IN PUNICODE_STRING SymbolicLinkName,
03626 IN ACCESS_MASK DesiredAccess,
03627 OUT PHANDLE DeviceInterfaceKey
03628 )
03629
03630
03631
03632
03633
03634
03635
03636
03637
03638
03639
03640
03641
03642
03643
03644
03645
03646
03647
03648
03649
03650
03651
03652
03653 {
03654
NTSTATUS status;
03655 HANDLE hKey;
03656 UNICODE_STRING unicodeString;
03657
03658
PAGED_CODE();
03659
03660
03661
03662
03663
03664
03665
03666
03667
03668
03669
KeEnterCriticalRegion();
03670
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
03671
03672
03673
03674
03675
03676 status =
IopDeviceInterfaceKeysFromSymbolicLink(SymbolicLinkName,
03677 KEY_READ,
03678
NULL,
03679
NULL,
03680 &hKey
03681 );
03682
if(!
NT_SUCCESS(status)) {
03683
goto clean0;
03684 }
03685
03686
03687
03688
03689
03690 PiWstrToUnicodeString(&unicodeString, REGSTR_KEY_DEVICEPARAMETERS);
03691 status =
IopCreateRegistryKeyEx( DeviceInterfaceKey,
03692 hKey,
03693 &unicodeString,
03694 DesiredAccess,
03695 REG_OPTION_NON_VOLATILE,
03696
NULL
03697 );
03698 ZwClose(hKey);
03699
03700 clean0:
03701
ExReleaseResource(&
PpRegistryDeviceResource);
03702
KeLeaveCriticalRegion();
03703
03704
return status;
03705 }
03706
03707
NTSTATUS
03708 IopDeviceInterfaceKeysFromSymbolicLink(
03709 IN PUNICODE_STRING SymbolicLinkName,
03710 IN ACCESS_MASK DesiredAccess,
03711 OUT PHANDLE DeviceInterfaceClassKey OPTIONAL,
03712 OUT PHANDLE DeviceInterfaceKey OPTIONAL,
03713 OUT PHANDLE DeviceInterfaceInstanceKey OPTIONAL
03714 )
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730
03731
03732
03733
03734
03735
03736
03737
03738
03739
03740
03741
03742
03743
03744
03745
03746
03747
03748 {
03749
NTSTATUS status;
03750 UNICODE_STRING guidString, tempString;
03751 HANDLE hDeviceClasses, hFunctionClass;
03752
03753
PAGED_CODE();
03754
03755
03756
03757
03758 status =
IopParseSymbolicLinkName(SymbolicLinkName,
NULL,
NULL, &guidString,
NULL,
NULL,
NULL);
03759
03760
if(!
NT_SUCCESS(status)){
03761
goto clean0;
03762 }
03763
03764
03765
03766
03767
03768
03769
03770
03771
03772
03773
KeEnterCriticalRegion();
03774
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
03775
03776
03777
03778
03779
03780 PiWstrToUnicodeString(&tempString, REGSTR_FULL_PATH_DEVICE_CLASSES);
03781 status =
IopOpenRegistryKeyEx( &hDeviceClasses,
03782
NULL,
03783 &tempString,
03784 KEY_READ
03785 );
03786
03787
if( !
NT_SUCCESS(status) ){
03788
goto clean1;
03789 }
03790
03791
03792
03793
03794
03795 status =
IopOpenRegistryKeyEx( &hFunctionClass,
03796 hDeviceClasses,
03797 &guidString,
03798 KEY_READ
03799 );
03800
03801
if( !
NT_SUCCESS(status) ){
03802
goto clean2;
03803 }
03804
03805
03806
03807
03808 status =
IopOpenOrCreateDeviceInterfaceSubKeys(DeviceInterfaceKey,
03809
NULL,
03810 DeviceInterfaceInstanceKey,
03811
NULL,
03812 hFunctionClass,
03813 SymbolicLinkName,
03814 DesiredAccess,
03815
FALSE
03816 );
03817
03818
if((!
NT_SUCCESS(status)) || (!ARGUMENT_PRESENT(DeviceInterfaceClassKey))) {
03819 ZwClose(hFunctionClass);
03820 }
else {
03821 *DeviceInterfaceClassKey = hFunctionClass;
03822 }
03823
03824 clean2:
03825 ZwClose(hDeviceClasses);
03826 clean1:
03827
ExReleaseResource(&
PpRegistryDeviceResource);
03828
KeLeaveCriticalRegion();
03829 clean0:
03830
return status;
03831
03832 }
03833
03834
NTSTATUS
03835 IoRegisterDeviceInterface(
03836 IN
PDEVICE_OBJECT PhysicalDeviceObject,
03837 IN CONST GUID *InterfaceClassGuid,
03838 IN PUNICODE_STRING ReferenceString OPTIONAL,
03839 OUT PUNICODE_STRING SymbolicLinkName
03840 )
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869 {
03870
PDEVICE_NODE pDeviceNode;
03871 PUNICODE_STRING pDeviceString;
03872
NTSTATUS status;
03873 PWSTR pRefString;
03874
USHORT count;
03875
03876
PAGED_CODE();
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888 pDeviceNode = (
PDEVICE_NODE) PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
03889
if (pDeviceNode) {
03890
03891
03892
03893
03894 pDeviceString = &pDeviceNode->
InstancePath;
03895
03896
if (pDeviceNode->
InstancePath.Length == 0) {
03897
return STATUS_INVALID_DEVICE_REQUEST;
03898 }
03899
03900
03901
03902
03903
if (ReferenceString) {
03904 pRefString = ReferenceString->Buffer;
03905 count = ReferenceString->Length /
sizeof(WCHAR);
03906
while (count--) {
03907
if((*pRefString ==
SEPERATOR_CHAR) || (*pRefString ==
ALT_SEPERATOR_CHAR)) {
03908 status = STATUS_INVALID_DEVICE_REQUEST;
03909 KdPrint((
"IoRegisterDeviceInterface: Invalid RefString!! failed with status = %8.8X\n", status));
03910
return status;
03911 }
03912 pRefString++;
03913 }
03914 }
03915
03916
return IopRegisterDeviceInterface(pDeviceString,
03917 InterfaceClassGuid,
03918 ReferenceString,
03919
FALSE,
03920 SymbolicLinkName
03921 );
03922 }
else {
03923
03924
return STATUS_INVALID_DEVICE_REQUEST;
03925 }
03926 }
03927
03928
NTSTATUS
03929 IopRegisterDeviceInterface(
03930 IN PUNICODE_STRING DeviceInstanceName,
03931 IN CONST GUID *InterfaceClassGuid,
03932 IN PUNICODE_STRING ReferenceString OPTIONAL,
03933 IN BOOLEAN UserModeFormat,
03934 OUT PUNICODE_STRING SymbolicLinkName
03935 )
03936
03937
03938
03939
03940
03941
03942
03943
03944
03945
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966
03967
03968
03969
03970
03971
03972 {
03973
NTSTATUS status;
03974 UNICODE_STRING tempString, guidString, otherString;
03975 PUNICODE_STRING pUserString, pKernelString;
03976 HANDLE hTemp1, hTemp2, hInterfaceInstanceKey;
03977 ULONG InterfaceDisposition, InterfaceInstanceDisposition;
03978
03979
PAGED_CODE();
03980
03981
03982
03983
03984
03985 status =
RtlStringFromGUID(InterfaceClassGuid, &guidString);
03986
if( !
NT_SUCCESS(status) ){
03987
goto clean0;
03988 }
03989
03990
03991
03992
03993
03994
03995
03996
if(UserModeFormat) {
03997 pUserString = SymbolicLinkName;
03998 pKernelString = &otherString;
03999 }
else {
04000 pKernelString = SymbolicLinkName;
04001 pUserString = &otherString;
04002 }
04003
04004 status =
IopBuildSymbolicLinkStrings(DeviceInstanceName,
04005 &guidString,
04006 ReferenceString,
04007 pUserString,
04008 pKernelString
04009 );
04010
if (!
NT_SUCCESS(status)) {
04011
goto clean1;
04012 }
04013
04014
04015
04016
04017
04018
04019
04020
04021
04022
04023
KeEnterCriticalRegion();
04024
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
04025
04026
04027
04028
04029
04030 PiWstrToUnicodeString(&tempString, REGSTR_FULL_PATH_DEVICE_CLASSES);
04031 status =
IopCreateRegistryKeyEx( &hTemp1,
04032
NULL,
04033 &tempString,
04034 KEY_CREATE_SUB_KEY,
04035 REG_OPTION_NON_VOLATILE,
04036
NULL
04037 );
04038
04039
if( !
NT_SUCCESS(status) ){
04040
goto clean2;
04041 }
04042
04043
04044
04045
04046
04047 status =
IopCreateRegistryKeyEx( &hTemp2,
04048 hTemp1,
04049 &guidString,
04050 KEY_CREATE_SUB_KEY,
04051 REG_OPTION_NON_VOLATILE,
04052
NULL
04053 );
04054 ZwClose(hTemp1);
04055
04056
if( !
NT_SUCCESS(status) ){
04057
goto clean2;
04058 }
04059
04060
04061
04062
04063
04064 status =
IopOpenOrCreateDeviceInterfaceSubKeys(&hTemp1,
04065 &InterfaceDisposition,
04066 &hInterfaceInstanceKey,
04067 &InterfaceInstanceDisposition,
04068 hTemp2,
04069 pUserString,
04070 KEY_WRITE | DELETE,
04071
TRUE
04072 );
04073
04074 ZwClose(hTemp2);
04075
04076
if(!
NT_SUCCESS(status)) {
04077
goto clean2;
04078 }
04079
04080
04081
04082
04083
04084 PiWstrToUnicodeString(&tempString, REGSTR_VAL_DEVICE_INSTANCE);
04085 status =
IopSetRegistryStringValue(hTemp1,
04086 &tempString,
04087 DeviceInstanceName
04088 );
04089
if(!
NT_SUCCESS(status)) {
04090
goto clean3;
04091 }
04092
04093
04094
04095
04096
04097 PiWstrToUnicodeString(&tempString, REGSTR_VAL_SYMBOLIC_LINK);
04098 status =
IopSetRegistryStringValue(hInterfaceInstanceKey,
04099 &tempString,
04100 pUserString
04101 );
04102
04103 clean3:
04104
if (!
NT_SUCCESS(status)) {
04105
04106
04107
04108
04109
if(InterfaceInstanceDisposition == REG_CREATED_NEW_KEY) {
04110 ZwDeleteKey(hInterfaceInstanceKey);
04111 }
else {
04112 ZwClose(hInterfaceInstanceKey);
04113 }
04114
04115
if(InterfaceDisposition == REG_CREATED_NEW_KEY) {
04116 ZwDeleteKey(hTemp1);
04117 }
else {
04118 ZwClose(hTemp1);
04119 }
04120 }
else {
04121 ZwClose(hInterfaceInstanceKey);
04122 ZwClose(hTemp1);
04123 }
04124
04125 clean2:
04126
ExReleaseResource(&
PpRegistryDeviceResource);
04127
KeLeaveCriticalRegion();
04128
IopFreeAllocatedUnicodeString(&otherString);
04129
if (!
NT_SUCCESS(status)) {
04130
IopFreeAllocatedUnicodeString(SymbolicLinkName);
04131 }
04132
04133 clean1:
04134
RtlFreeUnicodeString(&guidString);
04135 clean0:
04136
return status;
04137 }
04138
04139
NTSTATUS
04140 IopUnregisterDeviceInterface(
04141 IN PUNICODE_STRING SymbolicLinkName
04142 )
04143
04144
04145
04146
04147
04148
04149
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166 {
04167
NTSTATUS status = STATUS_SUCCESS, context;
04168 HANDLE hInterfaceClassKey=
NULL, hInterfaceKey=
NULL,
04169 hInterfaceInstanceKey=
NULL, hControl=
NULL;
04170 UNICODE_STRING tempString, mungedPathString, guidString, refString;
04171 BOOLEAN refStringPresent;
04172 GUID guid;
04173 UNICODE_STRING interfaceKeyName, instanceKeyName;
04174 ULONG linked, remainingSubKeys;
04175
USHORT length;
04176 PKEY_VALUE_FULL_INFORMATION keyValueInformation;
04177 PKEY_FULL_INFORMATION keyInformation;
04178
04179
04180
PAGED_CODE();
04181
04182
04183
04184
04185
if ( (!ARGUMENT_PRESENT(SymbolicLinkName)) ||
04186 (!
NT_SUCCESS(
IopParseSymbolicLinkName(SymbolicLinkName,
04187
NULL,
04188 &mungedPathString,
04189 &guidString,
04190 &refString,
04191 &refStringPresent,
04192 &guid))) ) {
04193 status = STATUS_INVALID_PARAMETER;
04194
goto clean0;
04195 }
04196
04197
04198
04199
04200
04201 length =
sizeof(WCHAR) + refString.Length;
04202 status =
IopAllocateUnicodeString(&instanceKeyName,
04203 length);
04204
if(!
NT_SUCCESS(status)) {
04205
goto clean0;
04206 }
04207
04208
04209
04210
04211
04212 *instanceKeyName.Buffer =
REFSTRING_PREFIX_CHAR;
04213 instanceKeyName.Length =
sizeof(WCHAR);
04214 instanceKeyName.MaximumLength = length +
sizeof(UNICODE_NULL);
04215
04216
04217
04218
04219
if (refStringPresent) {
04220
RtlAppendUnicodeStringToString(&instanceKeyName, &refString);
04221 }
04222
04223 instanceKeyName.Buffer[instanceKeyName.Length/
sizeof(WCHAR)] = UNICODE_NULL;
04224
04225
04226
04227
04228
04229
04230 length =
IopConstStringSize(
KEY_STRING_PREFIX) + mungedPathString.Length +
04231
sizeof(WCHAR) + guidString.Length;
04232
04233 status =
IopAllocateUnicodeString(&interfaceKeyName,
04234 length);
04235
if(!
NT_SUCCESS(status)) {
04236
goto clean1;
04237 }
04238
04239 interfaceKeyName.MaximumLength = length +
sizeof(UNICODE_NULL);
04240
04241
04242
04243
04244 RtlCopyMemory(interfaceKeyName.Buffer, SymbolicLinkName->Buffer, length);
04245 interfaceKeyName.Length = length;
04246 interfaceKeyName.Buffer[interfaceKeyName.Length/
sizeof(WCHAR)] = UNICODE_NULL;
04247
04248
04249
04250
04251 RtlCopyMemory(interfaceKeyName.Buffer,
04252
KEY_STRING_PREFIX,
04253
IopConstStringSize(
KEY_STRING_PREFIX));
04254
04255
04256
04257
04258
04259
04260
04261
04262
04263
04264
KeEnterCriticalRegion();
04265
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
04266
04267
04268
04269
04270 status =
IopDeviceInterfaceKeysFromSymbolicLink(SymbolicLinkName,
04271 KEY_ALL_ACCESS,
04272 &hInterfaceClassKey,
04273 &hInterfaceKey,
04274 &hInterfaceInstanceKey
04275 );
04276
if (!
NT_SUCCESS(status)) {
04277
goto clean2;
04278 }
04279
04280
04281
04282
04283 linked = 0;
04284 PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
04285 status =
IopOpenRegistryKeyEx( &hControl,
04286 hInterfaceInstanceKey,
04287 &tempString,
04288 KEY_ALL_ACCESS
04289 );
04290
if (
NT_SUCCESS(status)) {
04291
04292
04293
04294
04295 keyValueInformation=
NULL;
04296 status =
IopGetRegistryValue(hControl,
04297 REGSTR_VAL_LINKED,
04298 &keyValueInformation);
04299
04300
if(
NT_SUCCESS(status)) {
04301
if (keyValueInformation->Type == REG_DWORD &&
04302 keyValueInformation->DataLength ==
sizeof(ULONG)) {
04303
04304 linked = *((PULONG)
KEY_VALUE_DATA(keyValueInformation));
04305
ExFreePool(keyValueInformation);
04306 }
04307 }
04308
04309 ZwClose(hControl);
04310 hControl =
NULL;
04311 }
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325
04326 status = STATUS_SUCCESS;
04327
04328
if (linked) {
04329
04330
04331
04332
04333
IoSetDeviceInterfaceState(SymbolicLinkName,
FALSE);
04334 }
04335
04336
04337
04338
04339 ZwClose(hInterfaceInstanceKey);
04340 hInterfaceInstanceKey =
NULL;
04341
IopDeleteKeyRecursive (hInterfaceKey, instanceKeyName.Buffer);
04342
04343
04344
04345
04346 status =
IopGetRegistryKeyInformation(hInterfaceKey,
04347 &keyInformation);
04348
if (!
NT_SUCCESS(status)) {
04349
goto clean3;
04350 }
04351
04352 remainingSubKeys = keyInformation->SubKeys;
04353
04354
ExFreePool(keyInformation);
04355
04356
04357
04358
04359 PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
04360 status =
IopOpenRegistryKeyEx( &hControl,
04361 hInterfaceKey,
04362 &tempString,
04363 KEY_READ
04364 );
04365
if (
NT_SUCCESS(status)) {
04366 ZwClose(hControl);
04367 hControl =
NULL;
04368 }
04369
if ((remainingSubKeys==0) ||
04370 ((remainingSubKeys==1) && (
NT_SUCCESS(status)))) {
04371
04372
04373
04374
04375
04376
04377 ZwClose(hInterfaceKey);
04378 hInterfaceKey =
NULL;
04379
04380
IopDeleteKeyRecursive (hInterfaceClassKey, interfaceKeyName.Buffer);
04381 }
04382
04383 status = STATUS_SUCCESS;
04384
04385
04386 clean3:
04387
if (hControl) {
04388 ZwClose(hControl);
04389 }
04390
if (hInterfaceInstanceKey) {
04391 ZwClose(hInterfaceInstanceKey);
04392 }
04393
if (hInterfaceKey) {
04394 ZwClose(hInterfaceKey);
04395 }
04396
if (hInterfaceClassKey) {
04397 ZwClose(hInterfaceClassKey);
04398 }
04399
04400 clean2:
04401
ExReleaseResource(&
PpRegistryDeviceResource);
04402
KeLeaveCriticalRegion();
04403
04404
IopFreeAllocatedUnicodeString(&interfaceKeyName);
04405
04406 clean1:
04407
IopFreeAllocatedUnicodeString(&instanceKeyName);
04408
04409 clean0:
04410
return status;
04411 }
04412
04413
NTSTATUS
04414 IopRemoveDeviceInterfaces(
04415 IN PUNICODE_STRING DeviceInstancePath
04416 )
04417
04418
04419
04420
04421
04422
04423
04424
04425
04426
04427
04428
04429
04430
04431
04432
04433
04434
04435
04436
04437
04438
04439
04440
04441
04442
04443
04444 {
04445
NTSTATUS status, context;
04446 HANDLE hDeviceClasses=
NULL, hClassGUID=
NULL, hInterface=
NULL;
04447 UNICODE_STRING tempString, guidString, interfaceString, deviceInstanceString;
04448 ULONG resultSize, classIndex, interfaceIndex;
04449 ULONG symbolicLinkListSize;
04450 PWCHAR symbolicLinkList, symLink;
04451
BUFFER_INFO classInfoBuffer, interfaceInfoBuffer;
04452 PKEY_VALUE_FULL_INFORMATION deviceInstanceInfo;
04453 BOOLEAN deletedInterface;
04454 GUID classGUID;
04455
04456
PAGED_CODE();
04457
04458
04459
04460
04461 status =
IopAllocateBuffer(&classInfoBuffer,
04462
INITIAL_INFO_BUFFER_SIZE);
04463
if (!
NT_SUCCESS(status)) {
04464
goto clean0;
04465 }
04466
04467 status =
IopAllocateBuffer(&interfaceInfoBuffer,
04468
INITIAL_INFO_BUFFER_SIZE);
04469
if (!
NT_SUCCESS(status)) {
04470
IopFreeBuffer(&classInfoBuffer);
04471
goto clean0;
04472 }
04473
04474
04475
04476
04477 PiWstrToUnicodeString(&tempString, REGSTR_FULL_PATH_DEVICE_CLASSES);
04478 status =
IopOpenRegistryKeyEx( &hDeviceClasses,
04479
NULL,
04480 &tempString,
04481 KEY_READ
04482 );
04483
if(!
NT_SUCCESS(status)){
04484
goto clean1;
04485 }
04486
04487
04488
04489
04490 classIndex = 0;
04491
04492
while((status = ZwEnumerateKey(hDeviceClasses,
04493 classIndex,
04494 KeyBasicInformation,
04495 (PVOID) classInfoBuffer.
Buffer,
04496 classInfoBuffer.
MaxSize,
04497 &resultSize)) != STATUS_NO_MORE_ENTRIES) {
04498
04499
if (status == STATUS_BUFFER_TOO_SMALL) {
04500 status =
IopResizeBuffer(&classInfoBuffer, resultSize,
FALSE);
04501
continue;
04502 }
else if (!
NT_SUCCESS(status)) {
04503
goto clean1;
04504 }
04505
04506
04507
04508
04509 guidString.Length = (
USHORT)((PKEY_BASIC_INFORMATION)(classInfoBuffer.
Buffer))->NameLength;
04510 guidString.MaximumLength = guidString.Length;
04511 guidString.Buffer = ((PKEY_BASIC_INFORMATION)(classInfoBuffer.
Buffer))->Name;
04512
04513
04514
04515
04516 status =
IopOpenRegistryKeyEx( &hClassGUID,
04517 hDeviceClasses,
04518 &guidString,
04519 KEY_ALL_ACCESS
04520 );
04521
if (!
NT_SUCCESS(status)) {
04522
04523
04524
04525
goto CloseClassKeyAndContinue;
04526 }
04527
04528
04529
04530
04531 interfaceIndex = 0;
04532
04533
while((status = ZwEnumerateKey(hClassGUID,
04534 interfaceIndex,
04535 KeyBasicInformation,
04536 (PVOID) interfaceInfoBuffer.
Buffer,
04537 interfaceInfoBuffer.
MaxSize,
04538 &resultSize)) != STATUS_NO_MORE_ENTRIES) {
04539
04540
if (status == STATUS_BUFFER_TOO_SMALL) {
04541 status =
IopResizeBuffer(&interfaceInfoBuffer, resultSize,
FALSE);
04542
continue;
04543 }
else if (!
NT_SUCCESS(status)) {
04544
goto clean1;
04545 }
04546
04547
04548
04549
04550 deletedInterface =
FALSE;
04551
04552
04553
04554
04555 status =
IopAllocateUnicodeString(&interfaceString,
04556 (
USHORT)((PKEY_BASIC_INFORMATION)(interfaceInfoBuffer.
Buffer))->NameLength);
04557
04558
if (!
NT_SUCCESS(status)) {
04559
goto clean1;
04560 }
04561
04562 interfaceString.Length = (
USHORT)((PKEY_BASIC_INFORMATION)(interfaceInfoBuffer.
Buffer))->NameLength;
04563 interfaceString.MaximumLength = interfaceString.Length +
sizeof(UNICODE_NULL);
04564 RtlCopyMemory(interfaceString.Buffer,
04565 ((PKEY_BASIC_INFORMATION)(interfaceInfoBuffer.
Buffer))->Name,
04566 interfaceString.Length);
04567 interfaceString.Buffer[interfaceString.Length/
sizeof(WCHAR)] = UNICODE_NULL;
04568
04569
04570
04571
04572 status =
IopOpenRegistryKeyEx( &hInterface,
04573 hClassGUID,
04574 &interfaceString,
04575 KEY_ALL_ACCESS
04576 );
04577
if (!
NT_SUCCESS(status)) {
04578
04579
04580
04581 hInterface =
NULL;
04582
goto CloseInterfaceKeyAndContinue;
04583 }
04584
04585
04586
04587
04588 status =
IopGetRegistryValue(hInterface,
04589 REGSTR_VAL_DEVICE_INSTANCE,
04590 &deviceInstanceInfo);
04591
04592
if(!
NT_SUCCESS(status)) {
04593
04594
04595
04596
04597
goto CloseInterfaceKeyAndContinue;
04598 }
04599
04600
if((deviceInstanceInfo->Type == REG_SZ) &&
04601 (deviceInstanceInfo->DataLength != 0)) {
04602
04603
IopRegistryDataToUnicodeString(&deviceInstanceString,
04604 (PWSTR)
KEY_VALUE_DATA(deviceInstanceInfo),
04605 deviceInstanceInfo->DataLength);
04606
04607 }
else {
04608
04609
04610
04611
ExFreePool(deviceInstanceInfo);
04612
goto CloseInterfaceKeyAndContinue;
04613
04614 }
04615
04616
04617
04618
04619
if (
RtlEqualUnicodeString(&deviceInstanceString, DeviceInstancePath,
TRUE)) {
04620
04621 ZwClose(hInterface);
04622 hInterface =
NULL;
04623
04624
04625
04626
04627
04628
RtlGUIDFromString(&guidString, &classGUID);
04629
04630 status =
IopGetDeviceInterfaces(&classGUID,
04631 DeviceInstancePath,
04632
DEVICE_INTERFACE_INCLUDE_NONACTIVE,
04633
FALSE,
04634 &symbolicLinkList,
04635 &symbolicLinkListSize);
04636
04637
if (
NT_SUCCESS(status)) {
04638
04639
04640
04641
04642 symLink = symbolicLinkList;
04643
while(*symLink != UNICODE_NULL) {
04644
04645
RtlInitUnicodeString(&tempString, symLink);
04646
04647
04648
04649
04650
04651
04652
04653
IopUnregisterDeviceInterface(&tempString);
04654
04655 symLink += ((tempString.Length +
sizeof(UNICODE_NULL)) /
sizeof(WCHAR));
04656 }
04657
ExFreePool(symbolicLinkList);
04658 }
04659
04660
04661
04662
04663
04664
04665
04666
04667
04668
04669 status =
IopOpenRegistryKeyEx( &hInterface,
04670 hClassGUID,
04671 &interfaceString,
04672 KEY_READ
04673 );
04674
if(
NT_SUCCESS(status)){
04675
if (
NT_SUCCESS(
IopDeleteKeyRecursive(hClassGUID,
04676 interfaceString.Buffer))) {
04677 deletedInterface =
TRUE;
04678 }
04679 ZwDeleteKey(hInterface);
04680 ZwClose(hInterface);
04681 hInterface =
NULL;
04682 }
else if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
04683
04684
04685
04686 deletedInterface =
TRUE;
04687 }
04688 }
04689
04690
04691
04692
04693
ExFreePool(deviceInstanceInfo);
04694
04695 CloseInterfaceKeyAndContinue:
04696
04697
if (hInterface !=
NULL) {
04698 ZwClose(hInterface);
04699 hInterface =
NULL;
04700 }
04701
04702
IopFreeAllocatedUnicodeString(&interfaceString);
04703
04704
04705
04706
04707
if (!deletedInterface) {
04708 interfaceIndex++;
04709 }
04710
04711 }
04712
04713 CloseClassKeyAndContinue:
04714
04715
if (hClassGUID !=
NULL) {
04716 ZwClose(hClassGUID);
04717 hClassGUID =
NULL;
04718 }
04719 classIndex++;
04720 }
04721
04722 clean1:
04723
if (hInterface) {
04724 ZwClose(hInterface);
04725 }
04726
if (hClassGUID) {
04727 ZwClose(hClassGUID);
04728 }
04729
if (hDeviceClasses) {
04730 ZwClose(hDeviceClasses);
04731 }
04732
04733
IopFreeBuffer(&interfaceInfoBuffer);
04734
IopFreeBuffer(&classInfoBuffer);
04735
04736 clean0:
04737
return status;
04738 }
04739
04740
NTSTATUS
04741 IopOpenOrCreateDeviceInterfaceSubKeys(
04742 OUT PHANDLE InterfaceKeyHandle OPTIONAL,
04743 OUT PULONG InterfaceKeyDisposition OPTIONAL,
04744 OUT PHANDLE InterfaceInstanceKeyHandle OPTIONAL,
04745 OUT PULONG InterfaceInstanceDisposition OPTIONAL,
04746 IN HANDLE InterfaceClassKeyHandle,
04747 IN PUNICODE_STRING DeviceInterfaceName,
04748 IN ACCESS_MASK DesiredAccess,
04749 IN BOOLEAN Create
04750 )
04751
04752
04753
04754
04755
04756
04757
04758
04759
04760
04761
04762
04763
04764
04765
04766
04767
04768
04769
04770
04771
04772
04773
04774
04775
04776
04777
04778
04779
04780
04781
04782
04783
04784
04785
04786
04787
04788
04789
04790
04791
04792
04793
04794
04795 {
04796
NTSTATUS status;
04797 UNICODE_STRING TempString, RefString;
04798 WCHAR PoundCharBuffer;
04799 HANDLE hTempInterface, hTempInterfaceInstance;
04800 ULONG TempInterfaceDisposition;
04801 BOOLEAN RefStringPresent=
FALSE;
04802
04803
PAGED_CODE();
04804
04805
04806
04807
04808 status =
IopAllocateUnicodeString(&TempString, DeviceInterfaceName->Length);
04809
04810
if(!
NT_SUCCESS(status)) {
04811
goto clean0;
04812 }
04813
04814
RtlCopyUnicodeString(&TempString, DeviceInterfaceName);
04815
04816
04817
04818
04819 status =
IopParseSymbolicLinkName(&TempString,
04820
NULL,
04821
NULL,
04822
NULL,
04823 &RefString,
04824 &RefStringPresent,
04825
NULL
04826 );
04827
ASSERT(
NT_SUCCESS(status));
04828
04829
if(RefStringPresent) {
04830
04831
04832
04833 RefString.Buffer--;
04834 RefString.Length +=
sizeof(WCHAR);
04835 RefString.MaximumLength +=
sizeof(WCHAR);
04836 TempString.MaximumLength = TempString.Length = (
USHORT)((PUCHAR)RefString.Buffer - (PUCHAR)TempString.Buffer);
04837 }
else {
04838
04839
04840
04841
04842 RefString.Buffer = &PoundCharBuffer;
04843 RefString.Length = RefString.MaximumLength =
sizeof(PoundCharBuffer);
04844 }
04845
04846
04847
04848
04849 RtlCopyMemory(TempString.Buffer,
KEY_STRING_PREFIX,
IopConstStringSize(
KEY_STRING_PREFIX));
04850
04851
04852
04853
04854
IopReplaceSeperatorWithPound(&TempString, &TempString);
04855
04856
04857
04858
04859
04860
if (
Create) {
04861 status =
IopCreateRegistryKeyEx( &hTempInterface,
04862 InterfaceClassKeyHandle,
04863 &TempString,
04864 DesiredAccess,
04865 REG_OPTION_NON_VOLATILE,
04866 &TempInterfaceDisposition
04867 );
04868 }
else {
04869 status =
IopOpenRegistryKeyEx( &hTempInterface,
04870 InterfaceClassKeyHandle,
04871 &TempString,
04872 DesiredAccess
04873 );
04874 }
04875
04876
if(!
NT_SUCCESS(status)) {
04877
goto clean1;
04878 }
04879
04880
04881
04882
04883
04884 *RefString.Buffer =
REFSTRING_PREFIX_CHAR;
04885
04886
04887
04888
04889
04890
04891
if (
Create) {
04892 status =
IopCreateRegistryKeyEx( &hTempInterfaceInstance,
04893 hTempInterface,
04894 &RefString,
04895 DesiredAccess,
04896 REG_OPTION_NON_VOLATILE,
04897 InterfaceInstanceDisposition
04898 );
04899 }
else {
04900 status =
IopOpenRegistryKeyEx( &hTempInterfaceInstance,
04901 hTempInterface,
04902 &RefString,
04903 DesiredAccess
04904 );
04905 }
04906
04907
if(
NT_SUCCESS(status)) {
04908
04909
04910
04911
if(InterfaceKeyHandle) {
04912 *InterfaceKeyHandle = hTempInterface;
04913 }
else {
04914 ZwClose(hTempInterface);
04915 }
04916
if(InterfaceKeyDisposition) {
04917 *InterfaceKeyDisposition = TempInterfaceDisposition;
04918 }
04919
if(InterfaceInstanceKeyHandle) {
04920 *InterfaceInstanceKeyHandle = hTempInterfaceInstance;
04921 }
else {
04922 ZwClose(hTempInterfaceInstance);
04923 }
04924
04925
04926
04927 }
else {
04928
04929
04930
04931
if(TempInterfaceDisposition == REG_CREATED_NEW_KEY) {
04932 ZwDeleteKey(hTempInterface);
04933 }
else {
04934 ZwClose(hTempInterface);
04935 }
04936 }
04937
04938 clean1:
04939
IopFreeAllocatedUnicodeString(&TempString);
04940
04941 clean0:
04942
return status;
04943 }
04944
04945
NTSTATUS
04946 IoGetDeviceInterfaceAlias(
04947 IN PUNICODE_STRING SymbolicLinkName,
04948 IN CONST GUID *AliasInterfaceClassGuid,
04949 OUT PUNICODE_STRING AliasSymbolicLinkName
04950 )
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981
04982
04983
04984
04985
04986
04987 {
04988
NTSTATUS status;
04989 HANDLE hKey;
04990 PKEY_VALUE_FULL_INFORMATION pDeviceInstanceInfo;
04991 UNICODE_STRING deviceInstanceString, refString, guidString, otherString;
04992 PUNICODE_STRING pUserString, pKernelString;
04993 BOOLEAN refStringPresent, userModeFormat;
04994
04995
PAGED_CODE();
04996
04997
04998
04999
05000
05001 status =
RtlStringFromGUID(AliasInterfaceClassGuid, &guidString);
05002
if( !
NT_SUCCESS(status) ){
05003
goto clean0;
05004 }
05005
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
KeEnterCriticalRegion();
05016
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
05017
05018
05019
05020
05021
05022 status =
IopDeviceInterfaceKeysFromSymbolicLink(SymbolicLinkName,
05023 KEY_READ,
05024
NULL,
05025 &hKey,
05026
NULL
05027 );
05028
if(!
NT_SUCCESS(status)) {
05029
goto clean1;
05030 }
05031
05032
05033
05034
05035
05036 status =
IopGetRegistryValue(hKey, REGSTR_VAL_DEVICE_INSTANCE, &pDeviceInstanceInfo);
05037
05038 ZwClose(hKey);
05039
05040
if(!
NT_SUCCESS(status)) {
05041
goto clean1;
05042 }
05043
05044
if(pDeviceInstanceInfo->Type == REG_SZ) {
05045
05046
IopRegistryDataToUnicodeString(&deviceInstanceString,
05047 (PWSTR)
KEY_VALUE_DATA(pDeviceInstanceInfo),
05048 pDeviceInstanceInfo->DataLength
05049 );
05050
05051 }
else {
05052
05053 status = STATUS_INVALID_PARAMETER_1;
05054
goto clean2;
05055
05056 }
05057
05058
05059
05060
05061
05062
05063
05064
05065
05066
IopParseSymbolicLinkName(SymbolicLinkName,
05067
NULL,
05068
NULL,
05069
NULL,
05070 &refString,
05071 &refStringPresent,
05072
NULL
05073 );
05074
05075
05076
05077
05078 userModeFormat = (
IopConstStringSize(
USER_SYMLINK_STRING_PREFIX) ==
05079 RtlCompareMemory(SymbolicLinkName->Buffer,
05080
USER_SYMLINK_STRING_PREFIX,
05081
IopConstStringSize(
USER_SYMLINK_STRING_PREFIX)
05082 ));
05083
05084
if(userModeFormat) {
05085 pUserString = AliasSymbolicLinkName;
05086 pKernelString = &otherString;
05087 }
else {
05088 pKernelString = AliasSymbolicLinkName;
05089 pUserString = &otherString;
05090 }
05091
05092 status =
IopBuildSymbolicLinkStrings(&deviceInstanceString,
05093 &guidString,
05094 refStringPresent ? &refString :
NULL,
05095 pUserString,
05096 pKernelString
05097 );
05098
if (!
NT_SUCCESS(status)) {
05099
goto clean2;
05100 }
05101
05102
05103
05104
05105
05106 status =
IopDeviceInterfaceKeysFromSymbolicLink(AliasSymbolicLinkName,
05107 KEY_READ,
05108
NULL,
05109
NULL,
05110 &hKey
05111 );
05112
05113
if(
NT_SUCCESS(status)) {
05114
05115
05116
05117 ZwClose(hKey);
05118 }
else {
05119
IopFreeAllocatedUnicodeString(AliasSymbolicLinkName);
05120 }
05121
05122
IopFreeAllocatedUnicodeString(&otherString);
05123
05124 clean2:
05125
ExFreePool(pDeviceInstanceInfo);
05126
05127 clean1:
05128
ExReleaseResource(&
PpRegistryDeviceResource);
05129
KeLeaveCriticalRegion();
05130
RtlFreeUnicodeString(&guidString);
05131
05132 clean0:
05133
return status;
05134 }
05135
05136
NTSTATUS
05137 IopBuildSymbolicLinkStrings(
05138 IN PUNICODE_STRING DeviceString,
05139 IN PUNICODE_STRING GuidString,
05140 IN PUNICODE_STRING ReferenceString OPTIONAL,
05141 OUT PUNICODE_STRING UserString,
05142 OUT PUNICODE_STRING KernelString
05143 )
05144
05145
05146
05147
05148
05149
05150
05151
05152
05153
05154
05155
05156
05157
05158
05159
05160
05161
05162
05163
05164
05165
05166
05167
05168
05169
05170
05171
05172
05173
05174
05175
05176
05177
05178
05179 {
05180
NTSTATUS status;
05181
USHORT length, count;
05182 UNICODE_STRING mungedDeviceString;
05183
05184
PAGED_CODE();
05185
05186
05187
05188
05189
05190
05191
ASSERT(
IopConstStringSize(
KERNEL_SYMLINK_STRING_PREFIX) ==
IopConstStringSize(
USER_SYMLINK_STRING_PREFIX));
05192
05193
05194
05195
05196
05197 length =
IopConstStringSize(
KERNEL_SYMLINK_STRING_PREFIX) + DeviceString->Length +
05198
IopConstStringSize(
REPLACED_SEPERATOR_STRING) + GuidString->Length;
05199
05200
if(ARGUMENT_PRESENT(ReferenceString)) {
05201 length +=
IopConstStringSize(
SEPERATOR_STRING) + ReferenceString->Length;
05202 }
05203
05204
05205
05206
05207
05208 status =
IopAllocateUnicodeString(KernelString, length);
05209
if (!
NT_SUCCESS(status)) {
05210
goto clean0;
05211 }
05212
05213 status =
IopAllocateUnicodeString(UserString, length);
05214
if (!
NT_SUCCESS(status)) {
05215
goto clean1;
05216 }
05217
05218
05219
05220
05221
05222 status =
IopAllocateUnicodeString(&mungedDeviceString, DeviceString->Length);
05223
if (!
NT_SUCCESS(status)) {
05224
goto clean2;
05225 }
05226
05227
05228
05229
05230
05231 status =
IopReplaceSeperatorWithPound(&mungedDeviceString, DeviceString);
05232
if (!
NT_SUCCESS(status)) {
05233
goto clean3;
05234 }
05235
05236
05237
05238
05239
05240
RtlAppendUnicodeToString(UserString,
USER_SYMLINK_STRING_PREFIX);
05241
RtlAppendUnicodeStringToString(UserString, &mungedDeviceString);
05242
RtlAppendUnicodeToString(UserString,
REPLACED_SEPERATOR_STRING);
05243
RtlAppendUnicodeStringToString(UserString, GuidString);
05244
05245
if (ARGUMENT_PRESENT(ReferenceString)) {
05246
RtlAppendUnicodeToString(UserString,
SEPERATOR_STRING);
05247
RtlAppendUnicodeStringToString(UserString, ReferenceString);
05248 }
05249
05250
ASSERT( UserString->Length == length );
05251
05252
05253
05254
05255
05256
RtlCopyUnicodeString(KernelString, UserString);
05257 RtlCopyMemory(KernelString->Buffer,
05258
KERNEL_SYMLINK_STRING_PREFIX,
05259
IopConstStringSize(
KERNEL_SYMLINK_STRING_PREFIX)
05260 );
05261
05262 clean3:
05263
IopFreeAllocatedUnicodeString(&mungedDeviceString);
05264
05265 clean2:
05266
if (!
NT_SUCCESS(status)) {
05267
IopFreeAllocatedUnicodeString(UserString);
05268 }
05269
05270 clean1:
05271
if (!
NT_SUCCESS(status)) {
05272
IopFreeAllocatedUnicodeString(KernelString);
05273 }
05274
05275 clean0:
05276
return status;
05277 }
05278
05279
NTSTATUS
05280 IopReplaceSeperatorWithPound(
05281 OUT PUNICODE_STRING OutString,
05282 IN PUNICODE_STRING InString
05283 )
05284
05285
05286
05287
05288
05289
05290
05291
05292
05293
05294
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304
05305
05306
05307
05308
05309
05310 {
05311 PWSTR pInPosition, pOutPosition;
05312
USHORT count;
05313
05314
PAGED_CODE();
05315
05316
ASSERT(InString);
05317
ASSERT(OutString);
05318
05319
05320
05321
05322
05323
if(InString->Length > OutString->MaximumLength) {
05324
return STATUS_BUFFER_TOO_SMALL;
05325 }
05326
05327 pInPosition = InString->Buffer;
05328 pOutPosition = OutString->Buffer;
05329 count = InString->Length /
sizeof(WCHAR);
05330
05331
05332
05333
05334
05335
05336
while (count--) {
05337
if((*pInPosition ==
SEPERATOR_CHAR) || (*pInPosition ==
ALT_SEPERATOR_CHAR)) {
05338 *pOutPosition =
REPLACED_SEPERATOR_CHAR;
05339 }
else {
05340 *pOutPosition = *pInPosition;
05341 }
05342 pInPosition++;
05343 pOutPosition++;
05344 }
05345
05346 OutString->Length = InString->Length;
05347
05348
return STATUS_SUCCESS;
05349
05350 }
05351
05352
NTSTATUS
05353 IopDropReferenceString(
05354 OUT PUNICODE_STRING OutString,
05355 IN PUNICODE_STRING InString
05356 )
05357
05358
05359
05360
05361
05362
05363
05364
05365
05366
05367
05368
05369
05370
05371
05372
05373
05374
05375
05376
05377
05378
05379
05380
05381
05382
05383
05384
05385
05386 {
05387 UNICODE_STRING refString;
05388
NTSTATUS status;
05389 BOOLEAN refStringPresent;
05390
05391
PAGED_CODE();
05392
05393
ASSERT(InString);
05394
ASSERT(OutString);
05395
05396 OutString->Buffer = InString->Buffer;
05397
05398 status =
IopParseSymbolicLinkName(InString,
NULL,
NULL,
NULL, &refString, &refStringPresent,
NULL);
05399
05400
if (
NT_SUCCESS(status)) {
05401
05402
05403
05404
if (refStringPresent) {
05405 OutString->Length = InString->Length - (refString.Length +
sizeof(WCHAR));
05406 }
else {
05407 OutString->Length = InString->Length;
05408 }
05409
05410 }
else {
05411
05412
05413
05414 OutString->Buffer =
NULL;
05415 OutString->Length = 0;
05416 }
05417
05418 OutString->MaximumLength = OutString->Length;
05419
05420
return status;
05421 }
05422
05423
NTSTATUS
05424 IopParseSymbolicLinkName(
05425 IN PUNICODE_STRING SymbolicLinkName,
05426 OUT PUNICODE_STRING PrefixString OPTIONAL,
05427 OUT PUNICODE_STRING MungedPathString OPTIONAL,
05428 OUT PUNICODE_STRING GuidString OPTIONAL,
05429 OUT PUNICODE_STRING RefString OPTIONAL,
05430 OUT PBOOLEAN RefStringPresent OPTIONAL,
05431 OUT LPGUID Guid OPTIONAL
05432 )
05433
05434
05435
05436
05437
05438
05439
05440
05441
05442
05443
05444
05445
05446
05447
05448
05449
05450
05451
05452
05453
05454
05455
05456
05457
05458
05459
05460
05461
05462
05463
05464
05465
05466
05467
05468
05469
05470
05471 {
05472
NTSTATUS status = STATUS_SUCCESS;
05473 PWSTR pCurrent;
05474
USHORT last, current,
path, guid, reference = 0;
05475 UNICODE_STRING tempString;
05476 GUID tempGuid;
05477 BOOLEAN haveRefString;
05478
05479
PAGED_CODE();
05480
05481
ASSERT(
IopConstStringSize(
USER_SYMLINK_STRING_PREFIX) ==
IopConstStringSize(
KERNEL_SYMLINK_STRING_PREFIX));
05482
05483
05484
05485
05486
05487
if (!(RtlCompareMemory(SymbolicLinkName->Buffer,
05488
USER_SYMLINK_STRING_PREFIX,
05489
IopConstStringSize(
USER_SYMLINK_STRING_PREFIX)
05490 ) !=
IopConstStringSize(
USER_SYMLINK_STRING_PREFIX)
05491 || RtlCompareMemory(SymbolicLinkName->Buffer,
05492
KERNEL_SYMLINK_STRING_PREFIX,
05493
IopConstStringSize(
KERNEL_SYMLINK_STRING_PREFIX)
05494 ) !=
IopConstStringSize(
KERNEL_SYMLINK_STRING_PREFIX)
05495 )) {
05496
05497 status = STATUS_INVALID_PARAMETER;
05498
goto clean0;
05499 }
05500
05501
05502
05503
05504
05505
if (SymbolicLinkName->Length <(
IopConstStringLength(
KERNEL_SYMLINK_STRING_PREFIX)+
GUID_STRING_SIZE+1)) {
05506 status = STATUS_INVALID_PARAMETER;
05507
goto clean0;
05508
05509 }
05510
05511
05512
05513
05514
05515
path =
IopConstStringSize(
USER_SYMLINK_STRING_PREFIX) + 1;
05516
05517
05518
05519
05520
05521 pCurrent = SymbolicLinkName->Buffer +
IopConstStringLength(
KERNEL_SYMLINK_STRING_PREFIX);
05522
05523
for (current = 0;
05524 current < (SymbolicLinkName->Length /
sizeof(WCHAR)) -
IopConstStringLength(
KERNEL_SYMLINK_STRING_PREFIX);
05525 current++, pCurrent++) {
05526
05527
if(*pCurrent ==
SEPERATOR_CHAR) {
05528 reference = current + 1 +
IopConstStringLength(
KERNEL_SYMLINK_STRING_PREFIX);
05529
break;
05530 }
05531
05532 }
05533
05534
05535
05536
05537
05538
if (reference == 0) {
05539 haveRefString =
FALSE;
05540 reference = SymbolicLinkName->Length /
sizeof(WCHAR) + 1;
05541
05542 }
else {
05543 haveRefString =
TRUE;
05544 }
05545
05546
05547
05548
05549
05550 tempString.Length =
GUID_STRING_SIZE;
05551 tempString.MaximumLength =
GUID_STRING_SIZE;
05552 tempString.Buffer = SymbolicLinkName->Buffer + reference -
GUID_STRING_LENGTH - 1;
05553
05554
if (!
NT_SUCCESS(
RtlGUIDFromString(&tempString, &tempGuid) )) {
05555 status = STATUS_INVALID_PARAMETER;
05556
goto clean0;
05557 }
05558
05559 guid = reference -
GUID_STRING_LENGTH - 1;
05560
05561
05562
05563
05564
05565
if (ARGUMENT_PRESENT(PrefixString)) {
05566 PrefixString->Length =
IopConstStringSize(
KERNEL_SYMLINK_STRING_PREFIX);
05567 PrefixString->MaximumLength = PrefixString->Length;
05568 PrefixString->Buffer = SymbolicLinkName->Buffer;
05569 }
05570
05571
if (ARGUMENT_PRESENT(MungedPathString)) {
05572 MungedPathString->Length = (reference - 1 -
GUID_STRING_LENGTH - 1 -
05573
IopConstStringLength(
KERNEL_SYMLINK_STRING_PREFIX)) *
05574
sizeof(WCHAR);
05575 MungedPathString->MaximumLength = MungedPathString->Length;
05576 MungedPathString->Buffer = SymbolicLinkName->Buffer +
05577
IopConstStringLength(
KERNEL_SYMLINK_STRING_PREFIX);
05578
05579 }
05580
05581
if (ARGUMENT_PRESENT(GuidString)) {
05582 GuidString->Length =
GUID_STRING_SIZE;
05583 GuidString->MaximumLength = GuidString->Length;
05584 GuidString->Buffer = SymbolicLinkName->Buffer + reference -
05585
GUID_STRING_LENGTH - 1;
05586 }
05587
05588
if (ARGUMENT_PRESENT(RefString)) {
05589
05590
05591
05592
if (haveRefString) {
05593 RefString->Length = SymbolicLinkName->Length -
05594 (reference *
sizeof(WCHAR));
05595 RefString->MaximumLength = RefString->Length;
05596 RefString->Buffer = SymbolicLinkName->Buffer + reference;
05597 }
else {
05598 RefString->Length = 0;
05599 RefString->MaximumLength = 0;
05600 RefString->Buffer =
NULL;
05601 }
05602 }
05603
05604
if (ARGUMENT_PRESENT(RefStringPresent)) {
05605 *RefStringPresent = haveRefString;
05606 }
05607
05608
if(ARGUMENT_PRESENT(Guid)) {
05609 *Guid = tempGuid;
05610 }
05611
05612 clean0:
05613
05614
return status;
05615
05616 }
05617
05618
NTSTATUS
05619 IopAllocateUnicodeString(
05620 IN OUT PUNICODE_STRING String,
05621 IN USHORT Length
05622 )
05623
05624
05625
05626
05627
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651
05652
05653
05654 {
05655
PAGED_CODE();
05656
05657
String->Length = 0;
05658
String->MaximumLength = Length +
sizeof(UNICODE_NULL);
05659
05660
if(!(
String->Buffer =
ExAllocatePool(
PagedPool, Length +
sizeof(UNICODE_NULL)))) {
05661
return STATUS_INSUFFICIENT_RESOURCES;
05662 }
else {
05663
return STATUS_SUCCESS;
05664 }
05665 }
05666
05667
VOID
05668 IopFreeAllocatedUnicodeString(
05669 PUNICODE_STRING String
05670 )
05671
05672
05673
05674
05675
05676
05677
05678
05679
05680
05681
05682
05683
05684
05685
05686
05687
05688 {
05689
PAGED_CODE();
05690
05691
ASSERT(
String);
05692
05693
05694
05695
05696
05697
if(
String->Buffer) {
05698
05699
ExFreePool(
String->Buffer);
05700
05701 }
05702
05703
05704
05705
05706
05707
String->Buffer =
NULL;
05708
String->Length = 0;
05709
String->MaximumLength = 0;
05710
05711 }
05712
05713
NTSTATUS
05714 IopSetRegistryStringValue(
05715 IN HANDLE KeyHandle,
05716 IN PUNICODE_STRING ValueName,
05717 IN PUNICODE_STRING ValueData
05718 )
05719
05720
05721
05722
05723
05724
05725
05726
05727
05728
05729
05730
05731
05732
05733
05734
05735
05736
05737
05738
05739
05740
05741 {
05742
NTSTATUS status;
05743
05744
PAGED_CODE();
05745
05746
ASSERT(
ValueName);
05747
ASSERT(ValueData);
05748
ASSERT(
ValueName->Buffer);
05749
ASSERT(ValueData->Buffer);
05750
05751
05752
05753
05754
05755
if ((ValueData->MaximumLength - ValueData->Length) >=
sizeof(UNICODE_NULL)) {
05756
05757
05758
05759
05760
05761 ValueData->Buffer[(ValueData->Length /
sizeof(WCHAR))] = UNICODE_NULL;
05762
05763
05764
05765
05766
05767 status = ZwSetValueKey(KeyHandle,
05768
ValueName,
05769 0,
05770 REG_SZ,
05771 (PVOID) ValueData->Buffer,
05772 ValueData->Length +
sizeof(UNICODE_NULL)
05773 );
05774
05775 }
else {
05776
05777 UNICODE_STRING tempString;
05778
05779
05780
05781
05782
05783
05784 status =
IopAllocateUnicodeString(&tempString, ValueData->Length);
05785
05786
if (!
NT_SUCCESS(status)) {
05787
goto clean0;
05788 }
05789
05790
05791
05792
05793
05794 tempString.Length = ValueData->Length;
05795 RtlCopyMemory(tempString.Buffer, ValueData->Buffer, ValueData->Length);
05796
05797
05798
05799
05800
05801 tempString.Buffer[tempString.Length /
sizeof(WCHAR)] = UNICODE_NULL;
05802
05803
05804
05805
05806
05807 status = ZwSetValueKey(KeyHandle,
05808
ValueName,
05809 0,
05810 REG_SZ,
05811 (PVOID) tempString.Buffer,
05812 tempString.Length +
sizeof(UNICODE_NULL)
05813 );
05814
05815
05816
05817
05818
05819
IopFreeAllocatedUnicodeString(&tempString);
05820
05821 }
05822
05823 clean0:
05824
return status;
05825
05826 }
05827
05828
NTSTATUS
05829 IoUnregisterPlugPlayNotification(
05830 IN PVOID NotificationEntry
05831 )
05832
05833
05834
05835
05836
05837
05838
05839
05840
05841
05842
05843
05844
05845
05846
05847
05848
05849
05850
05851
05852 {
05853
PNOTIFY_ENTRY_HEADER entry;
05854
PFAST_MUTEX lock;
05855 BOOLEAN wasDeferred =
FALSE;
05856
05857
PAGED_CODE();
05858
05859
ASSERT(NotificationEntry);
05860
05861 entry = (
PNOTIFY_ENTRY_HEADER)NotificationEntry;
05862
05863 lock = entry->
Lock;
05864
05865 ExAcquireFastMutex(&
PiNotificationInProgressLock);
05866
if (
PiNotificationInProgress) {
05867
05868
05869
05870
05871
IopAcquireNotifyLock(&
IopDeferredRegistrationLock);
05872
05873
if (!IsListEmpty(&
IopDeferredRegistrationList)) {
05874
05875 PLIST_ENTRY link;
05876
PDEFERRED_REGISTRATION_ENTRY deferredNode;
05877
05878 link =
IopDeferredRegistrationList.Flink;
05879 deferredNode = (
PDEFERRED_REGISTRATION_ENTRY)link;
05880
05881
while (link != (PLIST_ENTRY)&
IopDeferredRegistrationList) {
05882
ASSERT(deferredNode->
NotifyEntry->
Unregistered);
05883
if (deferredNode->
NotifyEntry == entry) {
05884 wasDeferred =
TRUE;
05885
if (lock) {
05886
IopAcquireNotifyLock(lock);
05887 }
05888 link = link->Flink;
05889 RemoveEntryList((PLIST_ENTRY)deferredNode);
05890
IopDereferenceNotify((
PNOTIFY_ENTRY_HEADER)deferredNode->NotifyEntry);
05891
if (lock) {
05892
IopReleaseNotifyLock(lock);
05893 }
05894
ExFreePool(deferredNode);
05895 deferredNode = (
PDEFERRED_REGISTRATION_ENTRY)link;
05896 }
else {
05897 link = link->Flink;
05898 deferredNode = (
PDEFERRED_REGISTRATION_ENTRY)link;
05899 }
05900 }
05901 }
05902
05903
IopReleaseNotifyLock(&
IopDeferredRegistrationLock);
05904 }
else {
05905
05906
05907
05908
05909
ASSERT(IsListEmpty(&
IopDeferredRegistrationList));
05910 }
05911 ExReleaseFastMutex(&
PiNotificationInProgressLock);
05912
05913
05914
05915
05916
if (lock) {
05917
IopAcquireNotifyLock(lock);
05918 }
05919
05920
ASSERT(wasDeferred == entry->
Unregistered);
05921
05922
if (!entry->
Unregistered || wasDeferred) {
05923
05924
05925
05926
05927
05928
05929
05930
05931
05932 entry->
Unregistered =
TRUE;
05933
05934
05935
05936
05937
05938
IopDereferenceNotify(entry);
05939 }
05940
05941
05942
05943
05944
05945
if (lock) {
05946
IopReleaseNotifyLock(lock);
05947 }
05948
05949
return STATUS_SUCCESS;
05950
05951 }
05952
05953
VOID
05954 IopProcessDeferredRegistrations(
05955 VOID
05956 )
05957
05958
05959
05960
05961
05962
05963
05964
05965
05966
05967
05968
05969
05970
05971
05972
05973 {
05974
PDEFERRED_REGISTRATION_ENTRY deferredNode;
05975
PFAST_MUTEX lock;
05976
05977
IopAcquireNotifyLock(&
IopDeferredRegistrationLock);
05978
05979
while (!IsListEmpty(&
IopDeferredRegistrationList)) {
05980
05981 deferredNode = (
PDEFERRED_REGISTRATION_ENTRY)RemoveHeadList(&
IopDeferredRegistrationList);
05982
05983
05984
05985
05986 lock = deferredNode->
NotifyEntry->
Lock;
05987
if (lock) {
05988
IopAcquireNotifyLock(lock);
05989 }
05990
05991
05992
05993
05994 deferredNode->
NotifyEntry->
Unregistered =
FALSE;
05995
05996
05997
05998
05999
06000
IopDereferenceNotify((
PNOTIFY_ENTRY_HEADER)deferredNode->
NotifyEntry);
06001
ExFreePool(deferredNode);
06002
06003
06004
06005
06006
if (lock) {
06007
IopReleaseNotifyLock(lock);
06008 lock =
NULL;
06009 }
06010 }
06011
06012
IopReleaseNotifyLock(&
IopDeferredRegistrationLock);
06013 }
06014
06015
06016
NTSTATUS
06017 IoReportTargetDeviceChange(
06018 IN
PDEVICE_OBJECT PhysicalDeviceObject,
06019 IN PVOID NotificationStructure
06020 )
06021
06022
06023
06024
06025
06026
06027
06028
06029
06030
06031
06032
06033
06034
06035
06036
06037
06038
06039
06040
06041
06042
06043
06044
06045
06046
06047
06048
06049
06050
06051
06052 {
06053
06054
NTSTATUS status = STATUS_SUCCESS;
06055
KEVENT completionEvent;
06056
NTSTATUS completionStatus;
06057
PTARGET_DEVICE_CUSTOM_NOTIFICATION notifyStruct;
06058 LONG dataSize;
06059
06060
PAGED_CODE();
06061
06062 notifyStruct = (
PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure;
06063
06064
ASSERT(notifyStruct);
06065
06066
ASSERT_PDO(PhysicalDeviceObject);
06067
06068
ASSERT(
NULL == notifyStruct->
FileObject);
06069
06070
06071
if (
IopCompareGuid(¬ifyStruct->
Event, &GUID_TARGET_DEVICE_QUERY_REMOVE) ||
06072
IopCompareGuid(¬ifyStruct->
Event, &GUID_TARGET_DEVICE_REMOVE_CANCELLED) ||
06073
IopCompareGuid(¬ifyStruct->
Event, &GUID_TARGET_DEVICE_REMOVE_COMPLETE)) {
06074
06075
06076
06077
06078
06079
#if DBG
06080
DbgPrint(
"Illegal Event type passed as custom notification\n");
06081
#endif
06082
return STATUS_INVALID_DEVICE_REQUEST;
06083
06084 }
06085
06086
if (notifyStruct->
Size < FIELD_OFFSET(
TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer)) {
06087
06088
return STATUS_INVALID_DEVICE_REQUEST;
06089 }
06090
06091 dataSize = notifyStruct->
Size - FIELD_OFFSET(
TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer);
06092
06093
if (notifyStruct->
NameBufferOffset != -1 && notifyStruct->
NameBufferOffset > dataSize) {
06094
06095
return STATUS_INVALID_DEVICE_REQUEST;
06096 }
06097
06098
KeInitializeEvent(&completionEvent, NotificationEvent,
FALSE);
06099
06100 status =
PpSetCustomTargetEvent( PhysicalDeviceObject,
06101 &completionEvent,
06102 &completionStatus,
06103
NULL,
06104
NULL,
06105 notifyStruct);
06106
06107
if (
NT_SUCCESS(status)) {
06108
06109
KeWaitForSingleObject( &completionEvent,
Executive,
KernelMode,
FALSE,
NULL );
06110
06111 status = completionStatus;
06112 }
06113
06114
return status;
06115 }
06116
06117
NTSTATUS
06118 IoReportTargetDeviceChangeAsynchronous(
06119 IN
PDEVICE_OBJECT PhysicalDeviceObject,
06120 IN PVOID NotificationStructure,
06121 IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL,
06122 IN PVOID Context OPTIONAL
06123 )
06124
06125
06126
06127
06128
06129
06130
06131
06132
06133
06134
06135
06136
06137
06138
06139
06140
06141
06142
06143
06144
06145
06146
06147
06148
06149
06150
06151
06152
06153
06154
06155 {
06156
PASYNC_TDC_WORK_ITEM asyncWorkItem;
06157
PWORK_QUEUE_ITEM workItem;
06158
NTSTATUS status;
06159 LONG dataSize;
06160
06161
PTARGET_DEVICE_CUSTOM_NOTIFICATION notifyStruct;
06162
06163 notifyStruct = (
PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure;
06164
06165
ASSERT(notifyStruct);
06166
06167
ASSERT_PDO(PhysicalDeviceObject);
06168
06169
ASSERT(
NULL == notifyStruct->
FileObject);
06170
06171
if (
IopCompareGuid(¬ifyStruct->
Event, &GUID_TARGET_DEVICE_QUERY_REMOVE) ||
06172
IopCompareGuid(¬ifyStruct->
Event, &GUID_TARGET_DEVICE_REMOVE_CANCELLED) ||
06173
IopCompareGuid(¬ifyStruct->
Event, &GUID_TARGET_DEVICE_REMOVE_COMPLETE)) {
06174
06175
06176
06177
06178
06179
#if DBG
06180
DbgPrint(
"Illegal Event type passed as custom notification\n");
06181
#endif
06182
return STATUS_INVALID_DEVICE_REQUEST;
06183
06184 }
06185
06186
if (notifyStruct->
Size < FIELD_OFFSET(
TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer)) {
06187
06188
return STATUS_INVALID_DEVICE_REQUEST;
06189 }
06190
06191 dataSize = notifyStruct->
Size - FIELD_OFFSET(
TARGET_DEVICE_CUSTOM_NOTIFICATION, CustomDataBuffer);
06192
06193
if (notifyStruct->
NameBufferOffset != -1 && notifyStruct->
NameBufferOffset > dataSize) {
06194
06195
return STATUS_INVALID_DEVICE_REQUEST;
06196 }
06197
06198
06199
06200
06201
06202
06203 asyncWorkItem =
ExAllocatePool(
NonPagedPool,
06204
sizeof(
ASYNC_TDC_WORK_ITEM) + notifyStruct->
Size);
06205
06206
if (asyncWorkItem !=
NULL) {
06207
06208
ObReferenceObject(PhysicalDeviceObject);
06209
06210 asyncWorkItem->
DeviceObject = PhysicalDeviceObject;
06211 asyncWorkItem->
NotificationStructure =
06212 (
PTARGET_DEVICE_CUSTOM_NOTIFICATION)((PUCHAR)asyncWorkItem +
sizeof(
ASYNC_TDC_WORK_ITEM));
06213
06214 RtlCopyMemory( asyncWorkItem->
NotificationStructure,
06215 notifyStruct,
06216 notifyStruct->
Size);
06217
06218 asyncWorkItem->
Callback = Callback;
06219 asyncWorkItem->
Context = Context;
06220 workItem = &asyncWorkItem->
WorkItem;
06221
06222
ExInitializeWorkItem(workItem,
IopReportTargetDeviceChangeAsyncWorker, asyncWorkItem);
06223
06224
06225
06226
06227
06228
ExQueueWorkItem(workItem,
DelayedWorkQueue);
06229 status = STATUS_PENDING;
06230 }
else {
06231
06232
06233
06234
06235 status = STATUS_INSUFFICIENT_RESOURCES;
06236 }
06237
06238
return status;
06239 }
06240
06241
VOID
06242 IopReportTargetDeviceChangeAsyncWorker(
06243 PVOID Context
06244 )
06245
06246
06247
06248
06249
06250
06251
06252
06253
06254
06255
06256
06257
06258
06259
06260
06261
06262
06263
06264 {
06265
PASYNC_TDC_WORK_ITEM asyncWorkItem = (
PASYNC_TDC_WORK_ITEM)Context;
06266
06267
PpSetCustomTargetEvent( asyncWorkItem->
DeviceObject,
06268
NULL,
06269
NULL,
06270 asyncWorkItem->
Callback,
06271 asyncWorkItem->
Context,
06272 asyncWorkItem->
NotificationStructure);
06273
06274
ObDereferenceObject(asyncWorkItem->
DeviceObject);
06275
ExFreePool(asyncWorkItem);
06276 }
06277
06278
06279
06280
VOID
06281 IoInvalidateDeviceState(
06282 IN
PDEVICE_OBJECT PhysicalDeviceObject
06283 )
06284
06285
06286
06287
06288
06289
06290
06291
06292
06293
06294
06295
06296
06297
06298
06299
06300
06301 {
06302
PDEVICE_NODE deviceNode;
06303
06304
ASSERT_PDO(PhysicalDeviceObject);
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314 deviceNode = (
PDEVICE_NODE)PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
06315
06316
if ((deviceNode->
Flags & (
DNF_STARTED |
DNF_REMOVE_PENDING_CLOSES)) !=
DNF_STARTED) {
06317
return;
06318 }
06319
06320
IopQueueDeviceWorkItem( PhysicalDeviceObject,
06321
IopInvalidateDeviceStateWorker,
06322
NULL);
06323 }
06324
06325
06326
NTSTATUS
06327 IopQueueDeviceWorkItem(
06328 IN
PDEVICE_OBJECT PhysicalDeviceObject,
06329 IN PVOID WorkerRoutine,
06330 IN PVOID Context
06331 )
06332
06333
06334
06335
06336
06337
06338
06339
06340
06341
06342
06343
06344
06345
06346
06347
06348
06349
06350
06351 {
06352
PDEVICE_WORK_ITEM deviceWorkItem;
06353
06354
06355
06356
06357
06358
06359 deviceWorkItem =
ExAllocatePool(
NonPagedPool,
sizeof(
DEVICE_WORK_ITEM));
06360
if (deviceWorkItem ==
NULL) {
06361
06362
06363
06364
06365
06366
return STATUS_INSUFFICIENT_RESOURCES;
06367 }
06368
06369
ObReferenceObject(PhysicalDeviceObject);
06370 deviceWorkItem->
DeviceObject = PhysicalDeviceObject;
06371 deviceWorkItem->
Context = Context;
06372
06373
ExInitializeWorkItem( &deviceWorkItem->
WorkItem,
06374 WorkerRoutine,
06375 deviceWorkItem);
06376
06377
06378
06379
06380
06381
ExQueueWorkItem( &deviceWorkItem->
WorkItem,
DelayedWorkQueue );
06382
06383
return STATUS_SUCCESS;
06384 }
06385
06386
VOID
06387 IopInvalidateDeviceStateWorker(
06388 PVOID Context
06389 )
06390
06391
06392
06393
06394
06395
06396
06397
06398
06399
06400
06401
06402
06403
06404
06405
06406
06407
06408
06409 {
06410
PDEVICE_WORK_ITEM deviceWorkItem = (
PDEVICE_WORK_ITEM)Context;
06411
PDEVICE_OBJECT deviceObject = deviceWorkItem->
DeviceObject;
06412
PDEVICE_NODE deviceNode;
06413
06414
ExFreePool(deviceWorkItem);
06415
06416
06417
06418
06419
06420
06421 deviceNode = (
PDEVICE_NODE)deviceObject->
DeviceObjectExtension->
DeviceNode;
06422
06423
if ((deviceNode->
Flags & (
DNF_STARTED |
DNF_REMOVE_PENDING_CLOSES)) ==
DNF_STARTED) {
06424
06425
IopQueryDeviceState(deviceObject);
06426
06427
06428
06429
06430
IopUncacheInterfaceInformation(deviceObject);
06431 }
06432
06433
ObDereferenceObject(deviceObject);
06434 }
06435
06436
06437
06438
VOID
06439 IopResourceRequirementsChanged(
06440 IN
PDEVICE_OBJECT PhysicalDeviceObject,
06441 IN BOOLEAN StopRequired
06442 )
06443
06444
06445
06446
06447
06448
06449
06450
06451
06452
06453
06454
06455
06456
06457
06458
06459
06460
06461
06462
06463 {
06464
PDEVICE_NODE deviceNode;
06465
PDEVICE_OBJECT device =
NULL;
06466
06467
PAGED_CODE();
06468
06469 deviceNode = (
PDEVICE_NODE)PhysicalDeviceObject->DeviceObjectExtension->DeviceNode;
06470
06471
06472
06473
06474
06475 deviceNode->
Flags &= ~
DNF_NO_RESOURCE_REQUIRED;
06476
06477
06478
06479
06480
06481
06482
06483
06484 deviceNode->
Flags |=
DNF_RESOURCE_REQUIREMENTS_CHANGED;
06485
06486
IopClearDevNodeProblem(deviceNode);
06487
06488
06489
06490
06491
06492
06493
if (deviceNode->
Flags &
DNF_STARTED) {
06494 device = PhysicalDeviceObject;
06495
if (StopRequired ==
FALSE) {
06496 deviceNode->
Flags |=
DNF_NON_STOPPED_REBALANCE;
06497 }
else {
06498
06499
06500
06501
06502
06503 deviceNode->
Flags &= ~
DNF_NON_STOPPED_REBALANCE;
06504 }
06505 }
06506
06507
IopRequestDeviceAction( device,
ResourceRequirementsChanged,
NULL,
NULL );
06508 }
06509
06510
VOID
06511 IopInitializePlugPlayNotification(
06512 VOID
06513 )
06514
06515
06516
06517
06518
06519
06520
06521
06522
06523
06524
06525
06526
06527
06528
06529
06530
06531
06532 {
06533 ULONG count;
06534
06535
PAGED_CODE();
06536
06537
06538
06539
06540
06541
for (count = 0; count <
NOTIFY_DEVICE_CLASS_HASH_BUCKETS; count++) {
06542
06543 InitializeListHead(&
IopDeviceClassNotifyList[count]);
06544
06545 }
06546
06547
06548
06549
06550 InitializeListHead(&
IopProfileNotifyList);
06551
06552
06553
06554
06555 InitializeListHead(&
IopDeferredRegistrationList);
06556
06557
ExInitializeFastMutex(&
IopDeviceClassNotifyLock);
06558
ExInitializeFastMutex(&
IopTargetDeviceNotifyLock);
06559
ExInitializeFastMutex(&
IopHwProfileNotifyLock);
06560
ExInitializeFastMutex(&
IopDeferredRegistrationLock);
06561 }
06562
06563
VOID
06564 IopReferenceNotify(
06565
PNOTIFY_ENTRY_HEADER Notify
06566 )
06567
06568
06569
06570
06571
06572
06573
06574
06575
06576
06577
06578
06579
06580
06581
06582
06583
06584
06585
06586
06587
06588
06589 {
06590
PAGED_CODE();
06591
06592
ASSERT(Notify);
06593
ASSERT(Notify->
RefCount > 0);
06594
06595 Notify->
RefCount++;
06596
06597 }
06598
06599
VOID
06600 IopDereferenceNotify(
06601
PNOTIFY_ENTRY_HEADER Notify
06602 )
06603
06604
06605
06606
06607
06608
06609
06610
06611
06612
06613
06614
06615
06616
06617
06618
06619
06620
06621
06622
06623
06624
06625
06626
06627 {
06628
PAGED_CODE();
06629
06630
ASSERT(Notify);
06631
ASSERT(Notify->
RefCount > 0);
06632
06633 Notify->
RefCount--;
06634
06635
if (Notify->
RefCount == 0) {
06636
06637
06638
06639
06640
06641
06642
ASSERT(Notify->
Unregistered);
06643
06644
06645
06646
06647
06648
ObDereferenceObject(Notify->
DriverObject);
06649
06650
06651
06652
06653
06654
06655
if (Notify->
EventCategory ==
EventCategoryTargetDeviceChange) {
06656
PTARGET_DEVICE_NOTIFY_ENTRY entry = (
PTARGET_DEVICE_NOTIFY_ENTRY)Notify;
06657
06658
if (entry->
PhysicalDeviceObject) {
06659
ObDereferenceObject(entry->
PhysicalDeviceObject);
06660 entry->
PhysicalDeviceObject =
NULL;
06661 }
06662 }
06663
06664 RemoveEntryList((PLIST_ENTRY)Notify);
06665
06666
ExFreePool(Notify);
06667
06668 }
06669 }
06670
06671
NTSTATUS
06672 IopRequestHwProfileChangeNotification(
06673 IN LPGUID EventGuid,
06674 IN PROFILE_NOTIFICATION_TIME NotificationTime,
06675 OUT PPNP_VETO_TYPE VetoType OPTIONAL,
06676 OUT PUNICODE_STRING VetoName OPTIONAL
06677 )
06678
06679
06680
06681
06682
06683
06684
06685
06686
06687
06688
06689
06690
06691
06692
06693
06694
06695
06696
06697
06698
06699
06700
06701
06702
06703
06704
06705
06706
06707
06708
06709
06710
06711
06712
06713
06714
06715
06716
06717 {
06718
NTSTATUS status=STATUS_SUCCESS,completionStatus;
06719
KEVENT completionEvent;
06720 ULONG dataSize,totalSize;
06721 PPNP_DEVICE_EVENT_ENTRY deviceEvent;
06722
06723
PAGED_CODE();
06724
06725
if (
06726 (!
IopCompareGuid(EventGuid,
06727 (LPGUID)&GUID_HWPROFILE_QUERY_CHANGE)) &&
06728 (!
IopCompareGuid(EventGuid,
06729 (LPGUID)&GUID_HWPROFILE_CHANGE_CANCELLED)) &&
06730 (!
IopCompareGuid(EventGuid,
06731 (LPGUID)&GUID_HWPROFILE_CHANGE_COMPLETE)) ) {
06732
06733
06734
06735
06736
06737
#if DBG
06738
DbgPrint (
"Illegal Event type passed as profile notification\n");
06739
#endif
06740
return STATUS_INVALID_DEVICE_REQUEST;
06741 }
06742
06743
06744
06745
06746
06747
06748
ASSERT((!
IopCompareGuid(EventGuid, (LPGUID)&GUID_HWPROFILE_QUERY_CHANGE))||
06749 (NotificationTime !=
PROFILE_PERHAPS_IN_PNPEVENT)) ;
06750
06751
if (!
IopCompareGuid(EventGuid, (LPGUID)&GUID_HWPROFILE_QUERY_CHANGE) ) {
06752
06753
06754
06755
06756
ASSERT(!ARGUMENT_PRESENT(VetoName));
06757
ASSERT(!ARGUMENT_PRESENT(VetoType));
06758
06759
return PpSetHwProfileChangeEvent( EventGuid,
06760
NULL,
06761
NULL,
06762
NULL,
06763
NULL
06764 );
06765 }
06766
06767
06768
06769
06770
06771
06772
if (NotificationTime ==
PROFILE_NOT_IN_PNPEVENT) {
06773
06774
06775
06776
06777
KeInitializeEvent(&completionEvent, NotificationEvent,
FALSE);
06778
06779 status =
PpSetHwProfileChangeEvent( EventGuid,
06780 &completionEvent,
06781 &completionStatus,
06782 VetoType,
06783 VetoName
06784 );
06785
06786
if (
NT_SUCCESS(status)) {
06787
06788
KeWaitForSingleObject( &completionEvent,
Executive,
KernelMode,
FALSE,
NULL );
06789
06790 status = completionStatus;
06791 }
06792
06793
return status ;
06794 }
06795
06796
06797
06798
06799
06800
06801
06802
06803
06804
ASSERT(
PiNotificationInProgress ==
TRUE);
06805
06806 dataSize =
sizeof(PLUGPLAY_EVENT_BLOCK);
06807
06808 totalSize = dataSize + FIELD_OFFSET (PNP_DEVICE_EVENT_ENTRY,Data);
06809
06810 deviceEvent =
ExAllocatePoolWithTag (
PagedPool,
06811 totalSize,
06812
PNP_DEVICE_EVENT_ENTRY_TAG);
06813
06814
if (
NULL == deviceEvent) {
06815
return STATUS_INSUFFICIENT_RESOURCES;
06816 }
06817
06818
06819
06820
06821 RtlZeroMemory ((PVOID)deviceEvent,totalSize);
06822 deviceEvent->Data.EventCategory = HardwareProfileChangeEvent;
06823 RtlCopyMemory(&deviceEvent->Data.EventGuid, EventGuid,
sizeof(GUID));
06824 deviceEvent->Data.TotalSize = dataSize;
06825 deviceEvent->CallerEvent = &completionEvent;
06826 deviceEvent->Data.Result = &completionStatus;
06827 deviceEvent->VetoType = VetoType;
06828 deviceEvent->VetoName = VetoName;
06829
06830
06831
06832
06833 status =
IopNotifyHwProfileChange(&deviceEvent->Data.EventGuid,
06834 VetoType,
06835 VetoName);
06836
06837
if (!
NT_SUCCESS(status)) {
06838
return status;
06839 }
06840
06841
06842
06843
06844 status =
PiNotifyUserMode(deviceEvent);
06845
06846
if (!
NT_SUCCESS(status)) {
06847
06848
06849
06850
IopNotifyHwProfileChange((LPGUID)&GUID_HWPROFILE_CHANGE_CANCELLED,
06851
NULL,
06852
NULL);
06853 }
06854
return status;
06855 }
06856
06857
NTSTATUS
06858 IopNotifyHwProfileChange(
06859 IN LPGUID EventGuid,
06860 OUT PPNP_VETO_TYPE VetoType OPTIONAL,
06861 OUT PUNICODE_STRING VetoName OPTIONAL
06862 )
06863
06864
06865
06866
06867
06868
06869
06870
06871
06872
06873
06874
06875
06876
06877
06878
06879
06880
06881
06882
06883
06884
06885
06886
06887 {
06888
NTSTATUS status=STATUS_SUCCESS;
06889
PHWPROFILE_NOTIFY_ENTRY pNotifyList;
06890 PLIST_ENTRY link;
06891
#if DBG
06892
ULONG originalApcDisable;
06893
#endif
06894
06895
06896
PAGED_CODE();
06897
06898
06899
IopAcquireNotifyLock (&
IopHwProfileNotifyLock);
06900
06901
06902
06903
06904 link =
IopProfileNotifyList.Flink;
06905 pNotifyList=(
PHWPROFILE_NOTIFY_ENTRY)link;
06906
06907
06908
06909
06910
while (link != (PLIST_ENTRY)&
IopProfileNotifyList) {
06911
if (!pNotifyList->
Unregistered) {
06912
06913
HWPROFILE_CHANGE_NOTIFICATION notification;
06914
06915
NOTIFICATION_CALLBACK_PARAM_BLOCK callparams;
06916 ULONG Console=0;
06917
06918
06919
06920
06921
06922
IopReferenceNotify((
PNOTIFY_ENTRY_HEADER)pNotifyList);
06923
IopReleaseNotifyLock(&
IopHwProfileNotifyLock);
06924
06925
06926
06927
06928
06929 notification.
Version =
PNP_NOTIFICATION_VERSION;
06930 notification.
Size =
sizeof(
HWPROFILE_CHANGE_NOTIFICATION);
06931 notification.
Event = *EventGuid;
06932
06933
#if DBG
06934
originalApcDisable =
KeGetCurrentThread()->KernelApcDisable;
06935
#endif
06936
06937
06938
06939 callparams.
Callout=(pNotifyList->
Callback);
06940 callparams.
NotificationStructure=¬ification;
06941 callparams.
Context=pNotifyList->
Context;
06942
06943
06944
06945
06946
06947
06948
06949
06950
06951
06952
06953 status =
MmDispatchWin32Callout ((
PKWIN32_CALLOUT)callparams.
Callout,&
IopPnPHydraCallback,&callparams,&Console);
06954
#if DBG
06955
if (originalApcDisable !=
KeGetCurrentThread()->KernelApcDisable) {
06956
DbgPrint(
"IopNotifyHwProfileChange: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
06957 &pNotifyList->
DriverObject->
DriverName, pNotifyList->
Callback,
KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
06958 DbgBreakPoint();
06959 }
06960
#endif
06961
06962
06963
06964
06965
06966
06967
06968
if (!
NT_SUCCESS(status) &&
06969
IopCompareGuid(EventGuid, (LPGUID)&GUID_HWPROFILE_QUERY_CHANGE)) {
06970
06971
if (VetoType) {
06972 *VetoType = PNP_VetoDriver;
06973 }
06974
if (VetoName) {
06975 VetoName->Length = 0;
06976
RtlCopyUnicodeString(VetoName, &pNotifyList->
DriverObject->
DriverName);
06977 }
06978
06979 notification.
Event = GUID_HWPROFILE_CHANGE_CANCELLED;
06980 notification.
Size =
sizeof(GUID_HWPROFILE_CHANGE_CANCELLED);
06981
06982
06983
06984
06985
IopAcquireNotifyLock(&
IopHwProfileNotifyLock);
06986
IopDereferenceNotify((
PNOTIFY_ENTRY_HEADER)pNotifyList);
06987
06988
do {
06989 pNotifyList = (
PHWPROFILE_NOTIFY_ENTRY)link;
06990
if (!pNotifyList->
Unregistered) {
06991
IopReferenceNotify((
PNOTIFY_ENTRY_HEADER)pNotifyList);
06992
IopReleaseNotifyLock(&
IopHwProfileNotifyLock);
06993
06994
#if DBG
06995
originalApcDisable =
KeGetCurrentThread()->KernelApcDisable;
06996
#endif
06997
callparams.
Callout=(pNotifyList->
Callback);
06998 callparams.
NotificationStructure=¬ification;
06999 callparams.
Context=pNotifyList->
Context;
07000
07001
MmDispatchWin32Callout ((
PKWIN32_CALLOUT)callparams.
Callout,&
IopPnPHydraCallback,&callparams,&Console);
07002
#if DBG
07003
if (originalApcDisable !=
KeGetCurrentThread()->KernelApcDisable) {
07004
DbgPrint(
"IopNotifyHwProfileChange: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
07005 &pNotifyList->
DriverObject->
DriverName, pNotifyList->
Callback,
KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
07006 DbgBreakPoint();
07007 }
07008
#endif
07009
07010
IopAcquireNotifyLock(&
IopHwProfileNotifyLock);
07011 link = link->Blink;
07012
IopDereferenceNotify((
PNOTIFY_ENTRY_HEADER)pNotifyList);
07013
07014 }
else {
07015 link = link->Blink;
07016 }
07017 }
while (link != (PLIST_ENTRY)&
IopProfileNotifyList);
07018
07019
goto Clean0;
07020 }
07021
07022
07023
07024
07025
IopAcquireNotifyLock (&
IopHwProfileNotifyLock);
07026 link = link->Flink;
07027
IopDereferenceNotify((
PNOTIFY_ENTRY_HEADER)pNotifyList);
07028 pNotifyList=(
PHWPROFILE_NOTIFY_ENTRY)link;
07029
07030 }
else {
07031
07032
07033
07034
if (pNotifyList) {
07035
07036
07037
07038 link = link->Flink;
07039 pNotifyList=(
PHWPROFILE_NOTIFY_ENTRY)link;
07040 }
07041 }
07042 }
07043
07044 Clean0:
07045
07046
07047
IopReleaseNotifyLock (&
IopHwProfileNotifyLock);
07048
07049
return status;
07050 }
07051
07052
07053
07054
NTSTATUS
07055 IopNotifyTargetDeviceChange(
07056 LPCGUID EventGuid,
07057
PDEVICE_OBJECT DeviceObject,
07058 PVOID NotificationStructure,
07059
PDRIVER_OBJECT *VetoingDriver
07060 )
07061
07062
07063
07064
07065
07066
07067
07068
07069
07070
07071
07072
07073
07074
07075
07076
07077
07078
07079
07080
07081
07082
07083
07084
07085
07086
07087
07088
07089
07090
07091 {
07092
NTSTATUS status = STATUS_SUCCESS;
07093 PLIST_ENTRY link, lastLink;
07094
PTARGET_DEVICE_NOTIFY_ENTRY entry;
07095
TARGET_DEVICE_REMOVAL_NOTIFICATION notification;
07096
PDEVICE_NODE deviceNode;
07097 BOOLEAN reverse;
07098
#if DBG
07099
KIRQL originalIrql;
07100 ULONG originalApcDisable;
07101
#endif
07102
07103
PAGED_CODE();
07104
07105
ASSERT(DeviceObject !=
NULL);
07106
ASSERT(EventGuid !=
NULL);
07107
07108
07109
07110
07111
ObReferenceObject(DeviceObject);
07112
07113 deviceNode = (
PDEVICE_NODE)DeviceObject->
DeviceObjectExtension->
DeviceNode;
07114
07115
ASSERT(deviceNode !=
NULL);
07116
07117
07118
if (NotificationStructure) {
07119
07120
07121
07122
07123 ((
PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure)->Version =
PNP_NOTIFICATION_VERSION;
07124
07125 }
else {
07126
07127
07128
07129
07130 notification.
Version =
PNP_NOTIFICATION_VERSION;
07131 notification.
Size =
sizeof(
TARGET_DEVICE_REMOVAL_NOTIFICATION);
07132 notification.
Event = *EventGuid;
07133 }
07134
07135
07136
07137
07138
07139
IopAcquireNotifyLock(&
IopTargetDeviceNotifyLock);
07140
07141
07142
07143
07144
07145 reverse =
IopCompareGuid(EventGuid, (LPGUID)&GUID_TARGET_DEVICE_REMOVE_CANCELLED);
07146
07147
if (reverse) {
07148 link = deviceNode->
TargetDeviceNotify.Blink;
07149 }
else {
07150 link = deviceNode->
TargetDeviceNotify.Flink;
07151 }
07152
07153
07154
07155
07156
07157
while (link != &deviceNode->
TargetDeviceNotify) {
07158
07159 entry = (
PTARGET_DEVICE_NOTIFY_ENTRY)link;
07160
07161
07162
07163
07164
07165
if (!entry->
Unregistered) {
07166
07167
NOTIFICATION_CALLBACK_PARAM_BLOCK callparams;
07168 ULONG Console=0;
07169
07170
07171
07172
07173
07174
07175
IopReferenceNotify((
PNOTIFY_ENTRY_HEADER)entry);
07176
IopReleaseNotifyLock(&
IopTargetDeviceNotifyLock);
07177
07178
#if DBG
07179
originalIrql = KeGetCurrentIrql();
07180 originalApcDisable =
KeGetCurrentThread()->KernelApcDisable;
07181
#endif
07182
07183
07184
07185
07186
07187
if (NotificationStructure) {
07188
TARGET_DEVICE_CUSTOM_NOTIFICATION *notificationStructure = NotificationStructure;
07189
07190 notificationStructure->
FileObject = entry->FileObject;
07191
07192 callparams.
Callout=(entry->
Callback);
07193 callparams.
NotificationStructure=NotificationStructure;
07194 callparams.
Context=entry->
Context;
07195
07196
07197
07198
07199
07200
07201
07202
07203
07204
07205
07206 status =
MmDispatchWin32Callout ((
PKWIN32_CALLOUT)callparams.
Callout,&
IopPnPHydraCallback,&callparams,&Console);
07207
07208
07209 }
else {
07210 notification.
FileObject = entry->FileObject;
07211
07212 callparams.
Callout=(entry->
Callback);
07213 callparams.
NotificationStructure=¬ification;
07214 callparams.
Context=entry->
Context;
07215
07216 status =
MmDispatchWin32Callout ((
PKWIN32_CALLOUT)callparams.
Callout,&
IopPnPHydraCallback,&callparams,&Console);
07217
07218 }
07219
07220
#if DBG
07221
if (originalIrql != KeGetCurrentIrql()) {
07222
DbgPrint(
"IopNotifyTargetDeviceChange: Driver %Z, notification handler @ 0x%p returned at raised IRQL = %d, original = %d\n",
07223 &entry->
DriverObject->
DriverName, entry->
Callback, KeGetCurrentIrql(), originalIrql);
07224 DbgBreakPoint();
07225 }
07226
if (originalApcDisable !=
KeGetCurrentThread()->KernelApcDisable) {
07227
DbgPrint(
"IopNotifyTargetDeviceChange: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
07228 &entry->
DriverObject->
DriverName, entry->
Callback,
KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
07229 DbgBreakPoint();
07230 }
07231
#endif
07232
07233
07234
07235
07236
07237
07238
07239
if (!
NT_SUCCESS(status) &&
07240
IopCompareGuid(EventGuid, (LPGUID)&GUID_TARGET_DEVICE_QUERY_REMOVE)) {
07241
07242
if (VetoingDriver !=
NULL) {
07243 *VetoingDriver = entry->
DriverObject;
07244 }
07245
07246 notification.
Event = GUID_TARGET_DEVICE_REMOVE_CANCELLED;
07247
07248
07249
07250
07251
IopAcquireNotifyLock(&
IopTargetDeviceNotifyLock);
07252
IopDereferenceNotify((
PNOTIFY_ENTRY_HEADER)entry);
07253
07254
do {
07255 entry = (
PTARGET_DEVICE_NOTIFY_ENTRY)link;
07256
if (!entry->
Unregistered) {
07257
IopReferenceNotify((
PNOTIFY_ENTRY_HEADER)entry);
07258
IopReleaseNotifyLock(&
IopTargetDeviceNotifyLock);
07259
07260 notification.
FileObject = entry->FileObject;
07261
#if DBG
07262
originalApcDisable =
KeGetCurrentThread()->KernelApcDisable;
07263
#endif
07264
07265 callparams.
Callout=(entry->
Callback);
07266 callparams.
NotificationStructure=¬ification;
07267 callparams.
Context=entry->
Context;
07268
07269
MmDispatchWin32Callout ((
PKWIN32_CALLOUT)callparams.
Callout,&
IopPnPHydraCallback,&callparams,&Console);
07270
07271
#if DBG
07272
if (originalApcDisable !=
KeGetCurrentThread()->KernelApcDisable) {
07273
DbgPrint(
"IopNotifyTargetDeviceChange: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
07274 &entry->
DriverObject->
DriverName, entry->
Callback,
KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
07275 DbgBreakPoint();
07276 }
07277
#endif
07278
07279
IopAcquireNotifyLock(&
IopTargetDeviceNotifyLock);
07280 link = link->Blink;
07281
IopDereferenceNotify( (
PNOTIFY_ENTRY_HEADER) entry );
07282
07283 }
else {
07284 link = link->Blink;
07285 }
07286 }
while (link != &deviceNode->
TargetDeviceNotify);
07287
07288
goto Clean0;
07289 }
07290
07291
07292
07293
07294
IopAcquireNotifyLock(&
IopTargetDeviceNotifyLock);
07295
if (reverse) {
07296 link = link->Blink;
07297 }
else {
07298 link = link->Flink;
07299 }
07300
IopDereferenceNotify((
PNOTIFY_ENTRY_HEADER)entry);
07301
07302 }
else {
07303
07304
07305
07306
07307
if (reverse) {
07308 link = link->Blink;
07309 }
else {
07310 link = link->Flink;
07311 }
07312 }
07313 }
07314
07315 Clean0:
07316
07317
07318
07319
07320
07321
IopReleaseNotifyLock(&
IopTargetDeviceNotifyLock);
07322
07323
ObDereferenceObject(DeviceObject);
07324
07325
return status;
07326 }
07327
07328
07329
NTSTATUS
07330 IopNotifyDeviceClassChange(
07331 LPGUID EventGuid,
07332 LPGUID ClassGuid,
07333 PUNICODE_STRING SymbolicLinkName
07334 )
07335
07336
07337
07338
07339
07340
07341
07342
07343
07344
07345
07346
07347
07348
07349
07350
07351
07352
07353
07354
07355
07356
07357
07358
07359
07360
07361
07362
07363
07364
07365
07366 {
07367
NTSTATUS status = STATUS_SUCCESS;
07368 PLIST_ENTRY link;
07369
PDEVICE_CLASS_NOTIFY_ENTRY entry;
07370
DEVICE_INTERFACE_CHANGE_NOTIFICATION notification;
07371 ULONG hash;
07372
#if DBG
07373
KIRQL originalIrql;
07374 ULONG originalApcDisable;
07375
#endif
07376
07377
PAGED_CODE();
07378
07379
07380
07381
07382
07383 notification.
Version =
PNP_NOTIFICATION_VERSION;
07384 notification.
Size =
sizeof(
DEVICE_INTERFACE_CHANGE_NOTIFICATION);
07385 notification.
Event = *EventGuid;
07386 notification.
InterfaceClassGuid = *ClassGuid;
07387 notification.
SymbolicLinkName = SymbolicLinkName;
07388
07389
07390
07391
07392
07393
IopAcquireNotifyLock(&
IopDeviceClassNotifyLock);
07394
07395
07396
07397
07398
07399 hash =
IopHashGuid(ClassGuid);
07400 link =
IopDeviceClassNotifyList[hash].Flink;
07401
07402
07403
07404
07405
07406
while (link != &
IopDeviceClassNotifyList[hash]) {
07407
07408 entry = (
PDEVICE_CLASS_NOTIFY_ENTRY) link;
07409
07410
07411
07412
07413
07414
if ( !entry->
Unregistered &&
IopCompareGuid(&(entry->
ClassGuid), ClassGuid) ) {
07415
07416
NOTIFICATION_CALLBACK_PARAM_BLOCK callparams;
07417 ULONG Console=0;
07418
07419
07420
07421
07422
07423
IopReferenceNotify( (
PNOTIFY_ENTRY_HEADER) entry );
07424
IopReleaseNotifyLock(&
IopDeviceClassNotifyLock);
07425
07426
#if DBG
07427
originalIrql = KeGetCurrentIrql();
07428 originalApcDisable =
KeGetCurrentThread()->KernelApcDisable;
07429
#endif
07430
07431
07432
07433
07434
07435
07436 callparams.
Callout=(entry->
Callback);
07437 callparams.
NotificationStructure=¬ification;
07438 callparams.
Context=entry->
Context;
07439
07440
07441
07442
07443
07444
07445
07446
07447
07448
07449
07450
MmDispatchWin32Callout ((
PKWIN32_CALLOUT)callparams.
Callout,&
IopPnPHydraCallback,&callparams,&Console);
07451
07452
07453
07454
#if DBG
07455
if (originalIrql != KeGetCurrentIrql()) {
07456
DbgPrint(
"IopNotifyDeviceClassChange: Driver %Z, notification handler @ 0x%p returned at raised IRQL = %d, original = %d\n",
07457 &entry->
DriverObject->
DriverName, entry->
Callback, KeGetCurrentIrql(), originalIrql);
07458 DbgBreakPoint();
07459 }
07460
if (originalApcDisable !=
KeGetCurrentThread()->KernelApcDisable) {
07461
DbgPrint(
"IopNotifyDeviceClassChange: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
07462 &entry->
DriverObject->
DriverName, entry->
Callback,
KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
07463 DbgBreakPoint();
07464 }
07465
#endif
07466
07467
07468
07469
07470
IopAcquireNotifyLock(&
IopDeviceClassNotifyLock);
07471 link = link->Flink;
07472
IopDereferenceNotify( (
PNOTIFY_ENTRY_HEADER) entry );
07473
07474 }
else {
07475
07476
07477
07478
07479
07480 link = link->Flink;
07481 }
07482 }
07483
07484
07485
07486
07487
07488
IopReleaseNotifyLock(&
IopDeviceClassNotifyLock);
07489
07490
return status;
07491 }
07492
07493
07494
NTSTATUS
07495 IoRegisterPlugPlayNotification(
07496 IN IO_NOTIFICATION_EVENT_CATEGORY EventCategory,
07497 IN ULONG EventCategoryFlags,
07498 IN PVOID EventCategoryData OPTIONAL,
07499 IN
PDRIVER_OBJECT DriverObject,
07500 IN PDRIVER_NOTIFICATION_CALLBACK_ROUTINE CallbackRoutine,
07501 IN PVOID Context,
07502 OUT PVOID *NotificationEntry
07503 )
07504
07505
07506
07507
07508
07509
07510
07511
07512
07513
07514
07515
07516
07517
07518
07519
07520
07521
07522
07523
07524
07525
07526
07527
07528
07529
07530
07531
07532
07533
07534
07535
07536
07537
07538
07539
07540
07541
07542
07543
07544
07545
07546
07547
07548
07549
07550
07551
07552
07553
07554
07555
07556
07557
07558
07559
07560
07561
07562
07563
07564
07565
07566
07567
07568
07569 {
07570
07571
NTSTATUS status = STATUS_SUCCESS;
07572
#if DBG
07573
ULONG originalApcDisable;
07574
#endif
07575
07576
PAGED_CODE();
07577
07578
ASSERT(NotificationEntry);
07579
07580
07581
07582
07583
07584 *NotificationEntry =
NULL;
07585
07586
07587
07588
07589
07590 status =
ObReferenceObjectByPointer(DriverObject,
07591 0,
07592
IoDriverObjectType,
07593
KernelMode
07594 );
07595
07596
if (!
NT_SUCCESS(status)) {
07597
return status;
07598 }
07599
07600
switch (EventCategory) {
07601
07602
case EventCategoryReserved:
07603 {
07604
07605
PSETUP_NOTIFY_DATA setupData;
07606
07607
07608
07609
07610
07611 setupData =
ExAllocatePool(
PagedPool,
sizeof(
SETUP_NOTIFY_DATA));
07612
if (!setupData) {
07613 status = STATUS_INSUFFICIENT_RESOURCES;
07614
goto clean0;
07615 }
07616
07617
07618
07619
07620 InitializeListHead(&(setupData->
ListEntry));
07621 setupData->
EventCategory = EventCategory;
07622 setupData->
Callback = CallbackRoutine;
07623 setupData->
Context = Context;
07624 setupData->
RefCount = 1;
07625 setupData->
Unregistered =
FALSE;
07626 setupData->
Lock =
NULL;
07627 setupData->
DriverObject = DriverObject;
07628
07629
07630
07631
07632
07633
IopSetupNotifyData = setupData;
07634
07635
07636
07637
07638
07639
07640 *NotificationEntry =
NULL;
07641
07642
break;
07643
07644 }
07645
07646
case EventCategoryHardwareProfileChange:
07647 {
07648
PHWPROFILE_NOTIFY_ENTRY entry;
07649
07650
07651
07652
07653 entry =
ExAllocatePool (
PagedPool,
sizeof (
HWPROFILE_NOTIFY_ENTRY));
07654
if (!entry) {
07655 status = STATUS_INSUFFICIENT_RESOURCES;
07656
goto clean0;
07657 }
07658
07659
07660
07661
07662
07663 entry->
EventCategory = EventCategory;
07664 entry->
Callback = CallbackRoutine;
07665 entry->
Context = Context;
07666 entry->
RefCount = 1;
07667 entry->
Unregistered =
FALSE;
07668 entry->
Lock = &
IopHwProfileNotifyLock;
07669 entry->
DriverObject = DriverObject;
07670
07671 ExAcquireFastMutex(&
PiNotificationInProgressLock);
07672
if (
PiNotificationInProgress) {
07673
07674
07675
07676
07677
07678
07679
PDEFERRED_REGISTRATION_ENTRY deferredNode;
07680
07681 deferredNode =
ExAllocatePool(
PagedPool,
sizeof(
DEFERRED_REGISTRATION_ENTRY));
07682
if (!deferredNode) {
07683 ExReleaseFastMutex(&
PiNotificationInProgressLock);
07684 status = STATUS_INSUFFICIENT_RESOURCES;
07685
goto clean0;
07686 }
07687
07688 deferredNode->
NotifyEntry = (
PNOTIFY_ENTRY_HEADER)entry;
07689
07690
07691
07692
07693
07694 entry->
Unregistered =
TRUE;
07695
07696
07697
07698
07699
07700
IopReferenceNotify((
PNOTIFY_ENTRY_HEADER)entry);
07701
07702
07703
07704
07705
IopAcquireNotifyLock(&
IopDeferredRegistrationLock);
07706 InsertTailList(&
IopDeferredRegistrationList, (PLIST_ENTRY)deferredNode);
07707
IopReleaseNotifyLock(&
IopDeferredRegistrationLock);
07708 }
else {
07709
07710
07711
07712
07713
ASSERT(IsListEmpty(&
IopDeferredRegistrationList));
07714 }
07715 ExReleaseFastMutex(&
PiNotificationInProgressLock);
07716
07717
07718
07719
07720
07721
IopAcquireNotifyLock(&
IopHwProfileNotifyLock);
07722 InsertTailList(&
IopProfileNotifyList, (PLIST_ENTRY)entry);
07723
IopReleaseNotifyLock(&
IopHwProfileNotifyLock);
07724
07725 *NotificationEntry = entry;
07726
07727
break;
07728 }
07729
case EventCategoryTargetDeviceChange:
07730 {
07731
PTARGET_DEVICE_NOTIFY_ENTRY entry;
07732
IO_STACK_LOCATION irpSp;
07733
PDEVICE_NODE deviceNode;
07734
07735
ASSERT(EventCategoryData);
07736
07737
07738
07739
07740
07741 entry =
ExAllocatePool(
PagedPool,
sizeof(
TARGET_DEVICE_NOTIFY_ENTRY));
07742
if (!entry) {
07743 status = STATUS_INSUFFICIENT_RESOURCES;
07744
goto clean0;
07745 }
07746
07747
07748
07749
07750 status =
IopGetRelatedTargetDevice((
PFILE_OBJECT)EventCategoryData,
07751 &deviceNode);
07752
if (!
NT_SUCCESS(status)) {
07753
ExFreePool(entry);
07754
goto clean0;
07755 }
07756
07757
07758
07759
07760
07761 entry->
EventCategory = EventCategory;
07762 entry->
Callback = CallbackRoutine;
07763 entry->
Context = Context;
07764 entry->
DriverObject = DriverObject;
07765 entry->
RefCount = 1;
07766 entry->
Unregistered =
FALSE;
07767 entry->
Lock = &
IopTargetDeviceNotifyLock;
07768 entry->
FileObject = (
PFILE_OBJECT)EventCategoryData;
07769
07770
07771
07772
07773
07774
07775
07776
07777
ASSERT(deviceNode->
PhysicalDeviceObject);
07778 entry->
PhysicalDeviceObject = deviceNode->
PhysicalDeviceObject;
07779
07780 ExAcquireFastMutex(&
PiNotificationInProgressLock);
07781
if (
PiNotificationInProgress) {
07782
07783
07784
07785
07786
07787
07788
PDEFERRED_REGISTRATION_ENTRY deferredNode;
07789
07790 deferredNode =
ExAllocatePool(
PagedPool,
sizeof(
DEFERRED_REGISTRATION_ENTRY));
07791
if (!deferredNode) {
07792 ExReleaseFastMutex(&
PiNotificationInProgressLock);
07793 status = STATUS_INSUFFICIENT_RESOURCES;
07794
goto clean0;
07795 }
07796
07797 deferredNode->
NotifyEntry = (
PNOTIFY_ENTRY_HEADER)entry;
07798
07799
07800
07801
07802
07803 entry->
Unregistered =
TRUE;
07804
07805
07806
07807
07808
07809
IopReferenceNotify((
PNOTIFY_ENTRY_HEADER)entry);
07810
07811
07812
07813
07814
IopAcquireNotifyLock(&
IopDeferredRegistrationLock);
07815 InsertTailList(&
IopDeferredRegistrationList, (PLIST_ENTRY)deferredNode);
07816
IopReleaseNotifyLock(&
IopDeferredRegistrationLock);
07817 }
else {
07818
07819
07820
07821
07822
ASSERT(IsListEmpty(&
IopDeferredRegistrationList));
07823 }
07824 ExReleaseFastMutex(&
PiNotificationInProgressLock);
07825
07826
07827
07828
07829
07830
IopAcquireNotifyLock(&
IopTargetDeviceNotifyLock);
07831 InsertTailList(&deviceNode->
TargetDeviceNotify, (PLIST_ENTRY)entry);
07832
IopReleaseNotifyLock(&
IopTargetDeviceNotifyLock);
07833
07834 *NotificationEntry = entry;
07835
break;
07836 }
07837
07838
case EventCategoryDeviceInterfaceChange:
07839 {
07840
PDEVICE_CLASS_NOTIFY_ENTRY entry;
07841
07842
ASSERT(EventCategoryData);
07843
07844
07845
07846
07847
07848 entry =
ExAllocatePool(
PagedPool,
sizeof(
DEVICE_CLASS_NOTIFY_ENTRY));
07849
if (!entry) {
07850 status = STATUS_INSUFFICIENT_RESOURCES;
07851
goto clean0;
07852 }
07853
07854
07855
07856
07857
07858 entry->
EventCategory = EventCategory;
07859 entry->
Callback = CallbackRoutine;
07860 entry->
Context = Context;
07861 entry->
ClassGuid = *((LPGUID) EventCategoryData);
07862 entry->
RefCount = 1;
07863 entry->
Unregistered =
FALSE;
07864 entry->
Lock = &
IopDeviceClassNotifyLock;
07865 entry->
DriverObject = DriverObject;
07866
07867 ExAcquireFastMutex(&
PiNotificationInProgressLock);
07868
if (
PiNotificationInProgress) {
07869
07870
07871
07872
07873
07874
07875
PDEFERRED_REGISTRATION_ENTRY deferredNode;
07876
07877 deferredNode =
ExAllocatePool(
PagedPool,
sizeof(
DEFERRED_REGISTRATION_ENTRY));
07878
if (!deferredNode) {
07879 ExReleaseFastMutex(&
PiNotificationInProgressLock);
07880 status = STATUS_INSUFFICIENT_RESOURCES;
07881
goto clean0;
07882 }
07883
07884 deferredNode->
NotifyEntry = (
PNOTIFY_ENTRY_HEADER)entry;
07885
07886
07887
07888
07889
07890 entry->
Unregistered =
TRUE;
07891
07892
07893
07894
07895
07896
IopReferenceNotify((
PNOTIFY_ENTRY_HEADER)entry);
07897
07898
07899
07900
07901
IopAcquireNotifyLock(&
IopDeferredRegistrationLock);
07902 InsertTailList(&
IopDeferredRegistrationList, (PLIST_ENTRY)deferredNode);
07903
IopReleaseNotifyLock(&
IopDeferredRegistrationLock);
07904 }
else {
07905
07906
07907
07908
07909
ASSERT(IsListEmpty(&
IopDeferredRegistrationList));
07910 }
07911 ExReleaseFastMutex(&
PiNotificationInProgressLock);
07912
07913
07914
07915
07916
07917
IopAcquireNotifyLock(&
IopDeviceClassNotifyLock);
07918
07919
07920
07921
07922
07923 InsertTailList( (PLIST_ENTRY) &(
IopDeviceClassNotifyList[
IopHashGuid(&(entry->
ClassGuid)) ]),
07924 (PLIST_ENTRY) entry
07925 );
07926
07927
07928
07929
07930
07931
IopReleaseNotifyLock(&
IopDeviceClassNotifyLock);
07932
07933
07934
07935
07936
07937
if (EventCategoryFlags &
PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES) {
07938
07939 PWCHAR pSymbolicLinks, pCurrent;
07940
DEVICE_INTERFACE_CHANGE_NOTIFICATION notification;
07941 UNICODE_STRING unicodeString;
07942
07943
07944
07945
07946
07947 notification.
Version =
PNP_NOTIFICATION_VERSION;
07948 notification.
Size =
sizeof(
DEVICE_INTERFACE_CHANGE_NOTIFICATION);
07949 notification.
Event = GUID_DEVICE_INTERFACE_ARRIVAL;
07950 notification.
InterfaceClassGuid = entry->ClassGuid;
07951
07952
07953
07954
07955
07956
07957 status =
IoGetDeviceInterfaces(&(entry->ClassGuid),
07958
NULL,
07959 0,
07960 &pSymbolicLinks
07961 );
07962
if (!
NT_SUCCESS(status)) {
07963
07964
07965
07966
goto clean0;
07967 }
07968
07969
07970
07971
07972
07973 pCurrent = pSymbolicLinks;
07974
while(*pCurrent != UNICODE_NULL) {
07975
NOTIFICATION_CALLBACK_PARAM_BLOCK callparams;
07976 ULONG Console=0;
07977
07978
RtlInitUnicodeString(&unicodeString, pCurrent);
07979 notification.
SymbolicLinkName = &unicodeString;
07980
07981
#if DBG
07982
originalApcDisable =
KeGetCurrentThread()->KernelApcDisable;
07983
#endif
07984
07985
07986
07987 callparams.
Callout=(*CallbackRoutine);
07988 callparams.
NotificationStructure=¬ification;
07989 callparams.
Context=Context;
07990
07991
07992
07993
07994
07995
07996
07997
07998
07999
08000
08001
MmDispatchWin32Callout ((
PKWIN32_CALLOUT)callparams.
Callout,&
IopPnPHydraCallback,&callparams,&Console);
08002
08003
#if DBG
08004
if (originalApcDisable !=
KeGetCurrentThread()->KernelApcDisable) {
08005
DbgPrint(
"IoRegisterPlugPlayNotification: Driver %Z, notification handler @ 0x%p returned with different KernelApcDisable = %d, original = %d\n",
08006 &entry->DriverObject->DriverName, entry->Callback,
KeGetCurrentThread()->KernelApcDisable, originalApcDisable);
08007 DbgBreakPoint();
08008 }
08009
#endif
08010
08011 pCurrent += (unicodeString.Length /
sizeof(WCHAR)) + 1;
08012
08013 }
08014
08015
ExFreePool(pSymbolicLinks);
08016
08017 }
08018
08019 *NotificationEntry = entry;
08020 }
08021
08022
break;
08023 }
08024
08025 clean0:
08026
08027
if (!
NT_SUCCESS(status)) {
08028
ObDereferenceObject(DriverObject);
08029 }
08030
08031
return status;
08032 }
08033
08034
08035
NTSTATUS
08036 IopGetRelatedTargetDevice(
08037 IN
PFILE_OBJECT FileObject,
08038 OUT
PDEVICE_NODE *DeviceNode
08039 )
08040
08041
08042
08043
08044
08045
08046
08047
08048
08049
08050
08051
08052
08053
08054
08055
08056
08057
08058
08059
08060
08061
08062
08063
08064
08065 {
08066
NTSTATUS status;
08067
IO_STACK_LOCATION irpSp;
08068
PDEVICE_OBJECT deviceObject;
08069
PDEVICE_RELATIONS deviceRelations;
08070
08071
ASSERT(FileObject);
08072
08073
08074
08075
08076
08077 deviceObject =
IoGetRelatedDeviceObject(FileObject);
08078
if (!deviceObject) {
08079
return STATUS_NO_SUCH_DEVICE;
08080 }
08081
08082
08083
08084
08085
08086
08087
08088
08089 RtlZeroMemory(&irpSp,
sizeof(
IO_STACK_LOCATION));
08090 irpSp.
MajorFunction =
IRP_MJ_PNP;
08091 irpSp.
MinorFunction =
IRP_MN_QUERY_DEVICE_RELATIONS;
08092 irpSp.
Parameters.QueryDeviceRelations.Type =
TargetDeviceRelation;
08093 irpSp.
DeviceObject = deviceObject;
08094 irpSp.
FileObject = FileObject;
08095
08096 status =
IopSynchronousCall(deviceObject, &irpSp, &deviceRelations);
08097
if (!
NT_SUCCESS(status)) {
08098
#if 0
08099
DbgPrint(
"PnpMgr: Contact dev owner for %WZ, which may not correctly support\n",
08100 &deviceObject->
DriverObject->
DriverExtension->
ServiceKeyName);
08101
DbgPrint(
" IRP_MN_QUERY_DEVICE_RELATIONS:TargetDeviceRelation\n");
08102
08103
#endif
08104
return status;
08105 }
08106
08107
ASSERT(deviceRelations);
08108
ASSERT(deviceRelations->
Count == 1);
08109
08110 *DeviceNode = (
PDEVICE_NODE)deviceRelations->
Objects[0]->
DeviceObjectExtension->
DeviceNode;
08111
if (!*DeviceNode) {
08112 status = STATUS_NO_SUCH_DEVICE;
08113 }
08114
08115
ExFreePool(deviceRelations);
08116
return status;
08117 }
08118
08119
NTSTATUS
08120 IoGetRelatedTargetDevice(
08121 IN
PFILE_OBJECT FileObject,
08122 OUT
PDEVICE_OBJECT *DeviceObject
08123 )
08124
08125
08126
08127
08128
08129
08130
08131
08132
08133
08134
08135
08136
08137
08138
08139
08140
08141
08142
08143
08144
08145
08146
08147
08148
08149 {
08150
NTSTATUS status;
08151
PDEVICE_NODE deviceNode =
NULL;
08152
08153 status =
IopGetRelatedTargetDevice( FileObject, &deviceNode );
08154
if (
NT_SUCCESS(status) && deviceNode !=
NULL) {
08155 *DeviceObject = deviceNode->
PhysicalDeviceObject;
08156 }
08157
return status;
08158 }
08159
08160
08161
NTSTATUS
08162 IopNotifySetupDeviceArrival(
08163
PDEVICE_OBJECT PhysicalDeviceObject,
08164 HANDLE EnumEntryKey,
08165 BOOLEAN InstallDriver
08166 )
08167
08168
08169
08170
08171
08172
08173
08174
08175
08176
08177
08178
08179
08180
08181
08182
08183
08184
08185
08186
08187
08188
08189
08190
08191
08192
08193
08194
08195
08196
08197
08198
08199
08200
08201
08202
08203 {
08204
PAGED_CODE();
08205
08206
08207
08208
08209
08210
if (
IopSetupNotifyData) {
08211
08212
NTSTATUS status;
08213
SETUP_DEVICE_ARRIVAL_NOTIFICATION notification;
08214
NOTIFICATION_CALLBACK_PARAM_BLOCK callparams;
08215 ULONG Console=0;
08216
PDEVICE_NODE deviceNode;
08217 HANDLE enumKey =
NULL;
08218
08219
08220
08221
08222
08223
if (!EnumEntryKey) {
08224 status =
IopDeviceObjectToDeviceInstance(PhysicalDeviceObject,
08225 &enumKey,
08226 KEY_WRITE);
08227
if (!
NT_SUCCESS(status)) {
08228
return status;
08229 }
08230 EnumEntryKey = enumKey;
08231 }
08232
08233 notification.
Version =
PNP_NOTIFICATION_VERSION;
08234 notification.
Size =
sizeof(
SETUP_DEVICE_ARRIVAL_NOTIFICATION);
08235 notification.
Event = GUID_SETUP_DEVICE_ARRIVAL;
08236 notification.
PhysicalDeviceObject = PhysicalDeviceObject;
08237 notification.
EnumEntryKey = EnumEntryKey;
08238 deviceNode = (
PDEVICE_NODE) PhysicalDeviceObject->
DeviceObjectExtension->
DeviceNode;
08239 notification.
EnumPath = &deviceNode->
InstancePath;
08240 notification.
InstallDriver = InstallDriver;
08241
08242
08243
08244
08245
08246 callparams.
Callout=(
IopSetupNotifyData->
Callback);
08247 callparams.
NotificationStructure=¬ification;
08248 callparams.
Context=
IopSetupNotifyData->
Context;
08249
08250
08251
08252
08253
08254
08255
08256
08257
08258
08259
08260 status =
MmDispatchWin32Callout ((
PKWIN32_CALLOUT)callparams.
Callout,&
IopPnPHydraCallback,&callparams,&Console);
08261
if (enumKey) {
08262 ZwClose(enumKey);
08263 }
08264
08265
return status;
08266
08267 }
else {
08268
08269
return STATUS_OBJECT_NAME_NOT_FOUND;
08270
08271 }
08272 }
08273
08274 BOOLEAN
08275 IoIsWdmVersionAvailable(
08276 IN UCHAR MajorVersion,
08277 IN UCHAR MinorVersion
08278 )
08279
08280
08281
08282
08283
08284
08285
08286
08287
08288
08289
08290
08291
08292
08293
08294
08295
08296
08297
08298
08299
08300 {
08301
return ((MajorVersion <
WDM_MAJORVERSION) ||
08302 ((MajorVersion ==
WDM_MAJORVERSION) && (MinorVersion <=
WDM_MINORVERSION)));
08303 }
08304
08305
NTKERNELAPI
08306
PDMA_ADAPTER
08307 IoGetDmaAdapter(
08308 IN
PDEVICE_OBJECT PhysicalDeviceObject OPTIONAL,
08309 IN
PDEVICE_DESCRIPTION DeviceDescription,
08310 IN OUT PULONG NumberOfMapRegisters
08311 )
08312
08313
08314
08315
08316
08317
08318
08319
08320
08321
08322
08323
08324
08325
08326
08327
08328
08329
08330
08331
08332
08333
08334
08335
08336
08337
08338
08339
08340 {
08341
KEVENT event;
08342
NTSTATUS status;
08343
PIRP irp;
08344 IO_STATUS_BLOCK ioStatusBlock;
08345
PIO_STACK_LOCATION irpStack;
08346
BUS_INTERFACE_STANDARD busInterface;
08347
PDMA_ADAPTER dmaAdapter =
NULL;
08348
PDEVICE_DESCRIPTION deviceDescriptionToUse;
08349
DEVICE_DESCRIPTION privateDeviceDescription;
08350 ULONG resultLength;
08351
PDEVICE_OBJECT targetDevice;
08352
08353
PAGED_CODE();
08354
08355
if (PhysicalDeviceObject !=
NULL) {
08356
08357
ASSERT_PDO(PhysicalDeviceObject);
08358
08359
08360
08361
08362
08363
08364
08365
08366
if ((DeviceDescription->InterfaceType == InterfaceTypeUndefined) ||
08367 (DeviceDescription->InterfaceType == PNPBus)) {
08368
08369
08370
08371
08372 RtlCopyMemory(&privateDeviceDescription,
08373 DeviceDescription,
08374
sizeof(
DEVICE_DESCRIPTION)
08375 );
08376
08377 status =
IoGetDeviceProperty(PhysicalDeviceObject,
08378
DevicePropertyLegacyBusType,
08379
sizeof(privateDeviceDescription.
InterfaceType),
08380 (PVOID)&(privateDeviceDescription.
InterfaceType),
08381 &resultLength
08382 );
08383
08384
if (!
NT_SUCCESS(status)) {
08385
08386
ASSERT(status == STATUS_OBJECT_NAME_NOT_FOUND);
08387
08388
08389
08390
08391
08392
08393
08394 privateDeviceDescription.
InterfaceType =
PnpDefaultInterfaceType;
08395 }
08396
08397
08398
08399
08400 deviceDescriptionToUse = &privateDeviceDescription;
08401
08402 }
else {
08403
08404
08405
08406 deviceDescriptionToUse = DeviceDescription;
08407 }
08408
08409
08410
08411
08412
KeInitializeEvent( &event, NotificationEvent,
FALSE );
08413
08414 targetDevice =
IoGetAttachedDeviceReference(PhysicalDeviceObject);
08415
08416 irp =
IoBuildSynchronousFsdRequest(
IRP_MJ_PNP,
08417 targetDevice,
08418
NULL,
08419 0,
08420
NULL,
08421 &event,
08422 &ioStatusBlock );
08423
08424
if (irp ==
NULL) {
08425
return NULL;
08426 }
08427
08428 RtlZeroMemory( &busInterface,
sizeof(
BUS_INTERFACE_STANDARD ));
08429
08430 irpStack =
IoGetNextIrpStackLocation( irp );
08431 irpStack->
MinorFunction =
IRP_MN_QUERY_INTERFACE;
08432 irpStack->
Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_BUS_INTERFACE_STANDARD;
08433 irpStack->
Parameters.QueryInterface.Size =
sizeof(
BUS_INTERFACE_STANDARD );
08434 irpStack->
Parameters.QueryInterface.Version = 1;
08435 irpStack->
Parameters.QueryInterface.Interface = (
PINTERFACE) &busInterface;
08436 irpStack->
Parameters.QueryInterface.InterfaceSpecificData =
NULL;
08437
08438
08439
08440
08441
08442
08443 irp->
IoStatus.Status = STATUS_NOT_SUPPORTED;
08444
08445 status =
IoCallDriver(targetDevice, irp);
08446
08447
if (status == STATUS_PENDING) {
08448
08449
KeWaitForSingleObject( &event,
Executive,
KernelMode,
FALSE,
NULL );
08450 status = ioStatusBlock.Status;
08451
08452 }
08453
08454
ObDereferenceObject(targetDevice);
08455
08456
if (
NT_SUCCESS( status)) {
08457
08458
if (busInterface.
GetDmaAdapter !=
NULL) {
08459
08460
08461 dmaAdapter = busInterface.
GetDmaAdapter( busInterface.
Context,
08462 deviceDescriptionToUse,
08463 NumberOfMapRegisters );
08464
08465 }
08466
08467
08468
08469
08470
08471 busInterface.
InterfaceDereference( busInterface.
Context );
08472 }
08473
08474 }
else {
08475
08476
08477
08478
08479
08480 deviceDescriptionToUse = DeviceDescription;
08481 }
08482
08483
#if !defined(NO_LEGACY_DRIVERS)
08484
08485
08486
08487
08488
if (dmaAdapter ==
NULL) {
08489
08490 dmaAdapter =
HalGetDmaAdapter( PhysicalDeviceObject,
08491 deviceDescriptionToUse,
08492 NumberOfMapRegisters );
08493
08494 }
08495
#endif // NO_LEGACY_DRIVERS
08496
08497
return( dmaAdapter );
08498 }
08499
08500
NTSTATUS
08501 IopOpenDeviceParametersSubkey(
08502 OUT HANDLE *ParamKeyHandle,
08503 IN HANDLE ParentKeyHandle,
08504 IN PUNICODE_STRING SubKeyString,
08505 IN ACCESS_MASK DesiredAccess
08506 )
08507
08508
08509
08510
08511
08512
08513
08514
08515
08516
08517
08518
08519
08520
08521
08522
08523
08524
08525
08526
08527
08528 {
08529
NTSTATUS status;
08530 ULONG disposition;
08531 ULONG lengthSD;
08532 PSECURITY_DESCRIPTOR oldSD =
NULL;
08533 SECURITY_DESCRIPTOR newSD;
08534 ACL_SIZE_INFORMATION aclSizeInfo;
08535 PACL oldDacl;
08536 PACL newDacl =
NULL;
08537 ULONG sizeDacl;
08538 BOOLEAN daclPresent, daclDefaulted;
08539 PACCESS_ALLOWED_ACE ace;
08540 ULONG aceIndex;
08541 HANDLE deviceKeyHandle;
08542 UNICODE_STRING deviceParamString;
08543
08544
08545
08546
08547 status =
IopOpenRegistryKeyEx( &deviceKeyHandle,
08548 ParentKeyHandle,
08549 SubKeyString,
08550 KEY_WRITE
08551 );
08552
08553
if (!
NT_SUCCESS(status)) {
08554
return status;
08555 }
08556
08557
RtlInitUnicodeString(&deviceParamString, REGSTR_KEY_DEVICEPARAMETERS);
08558
08559 status =
IopCreateRegistryKeyEx( ParamKeyHandle,
08560 deviceKeyHandle,
08561 &deviceParamString,
08562 DesiredAccess | READ_CONTROL | WRITE_DAC,
08563 REG_OPTION_NON_VOLATILE,
08564 &disposition
08565 );
08566
08567 ZwClose(deviceKeyHandle);
08568
08569
if (!
NT_SUCCESS(status)) {
08570 KdPrint((
"IopOpenDeviceParametersSubkey: IopCreateRegistryKeyEx failed, status = %8.8X\n", status));
08571
return status;
08572 }
08573
08574
if (disposition == REG_CREATED_NEW_KEY) {
08575
08576
08577
08578
08579
08580
08581
08582
08583 status = ZwQuerySecurityObject(*ParamKeyHandle,
08584 DACL_SECURITY_INFORMATION,
08585
NULL,
08586 0,
08587 &lengthSD);
08588
08589
if (status == STATUS_BUFFER_TOO_SMALL) {
08590 oldSD =
ExAllocatePool(
PagedPool, lengthSD );
08591
08592
if (oldSD !=
NULL) {
08593
08594 status = ZwQuerySecurityObject(*ParamKeyHandle,
08595 DACL_SECURITY_INFORMATION,
08596 oldSD,
08597 lengthSD,
08598 &lengthSD);
08599
if (!
NT_SUCCESS(status)) {
08600 KdPrint((
"IopOpenDeviceParametersSubkey: ZwQuerySecurityObject failed, status = %8.8X\n", status));
08601
goto Cleanup0;
08602 }
08603 }
else {
08604
08605 KdPrint((
"IopOpenDeviceParametersSubkey: Failed to allocate memory, status = %8.8X\n", status));
08606 status = STATUS_NO_MEMORY;
08607
goto Cleanup0;
08608 }
08609 }
else {
08610 KdPrint((
"IopOpenDeviceParametersSubkey: ZwQuerySecurityObject failed %8.8X\n",status));
08611 status = STATUS_UNSUCCESSFUL;
08612
goto Cleanup0;
08613 }
08614
08615 status =
RtlCreateSecurityDescriptor( (PSECURITY_DESCRIPTOR) &newSD,
08616 SECURITY_DESCRIPTOR_REVISION );
08617
ASSERT(
NT_SUCCESS( status ) );
08618
08619
if (!
NT_SUCCESS(status)) {
08620
08621 KdPrint((
"IopOpenDeviceParametersSubkey: RtlCreateSecurityDescriptor failed, status = %8.8X\n", status));
08622
goto Cleanup0;
08623 }
08624
08625
08626
08627 status =
RtlGetDaclSecurityDescriptor(oldSD, &daclPresent, &oldDacl, &daclDefaulted);
08628
08629
ASSERT(
NT_SUCCESS( status ) );
08630
08631
08632
08633
08634
08635
if (daclPresent) {
08636
08637 status =
RtlQueryInformationAcl( oldDacl,
08638 &aclSizeInfo,
08639
sizeof(ACL_SIZE_INFORMATION),
08640 AclSizeInformation);
08641
08642
08643
if (!
NT_SUCCESS(status)) {
08644
08645 KdPrint((
"IopOpenDeviceParametersSubkey: RtlQueryInformationAcl failed, status = %8.8X\n", status));
08646
goto Cleanup0;
08647 }
08648
08649 sizeDacl = aclSizeInfo.AclBytesInUse;
08650 }
else {
08651 sizeDacl =
sizeof(ACL);
08652 }
08653
08654 sizeDacl +=
sizeof(ACCESS_ALLOWED_ACE) +
RtlLengthSid(
SeAliasAdminsSid) -
sizeof(ULONG);
08655
08656
08657
08658
08659 newDacl =
ExAllocatePool(
PagedPool, sizeDacl);
08660
08661
if (newDacl ==
NULL) {
08662
08663 KdPrint((
"IopOpenDeviceParametersSubkey: ExAllocatePool failed\n"));
08664
goto Cleanup0;
08665 }
08666
08667 status =
RtlCreateAcl(newDacl, sizeDacl, ACL_REVISION);
08668
08669
if (!
NT_SUCCESS(status)) {
08670
08671 KdPrint((
"IopOpenDeviceParametersSubkey: RtlCreateAcl failed, status = %8.8X\n", status));
08672
goto Cleanup0;
08673 }
08674
08675
08676
08677
08678
if (daclPresent) {
08679
08680
for (aceIndex = 0; aceIndex < aclSizeInfo.AceCount; aceIndex++) {
08681
08682 status =
RtlGetAce(oldDacl, aceIndex, (PVOID *)&ace);
08683
08684
if (!
NT_SUCCESS(status)) {
08685
08686 KdPrint((
"IopOpenDeviceParametersSubkey: RtlGetAce failed, status = %8.8X\n", status));
08687
goto Cleanup0;
08688 }
08689
08690
08691
08692
08693
08694
if ((ace->Header.AceType != ACCESS_ALLOWED_ACE_TYPE &&
08695 ace->Header.AceType != ACCESS_DENIED_ACE_TYPE) ||
08696 !
RtlEqualSid((PSID)&ace->SidStart,
SeAliasAdminsSid)) {
08697
08698 status =
RtlAddAce( newDacl,
08699 ACL_REVISION,
08700 ~0U,
08701 ace,
08702 ace->Header.AceSize
08703 );
08704
08705
if (!
NT_SUCCESS(status)) {
08706
08707 KdPrint((
"IopOpenDeviceParametersSubkey: RtlAddAce failed, status = %8.8X\n", status));
08708
goto Cleanup0;
08709 }
08710 }
08711 }
08712 }
08713
08714
08715
08716
08717 status =
RtlAddAccessAllowedAceEx( newDacl,
08718 ACL_REVISION,
08719 CONTAINER_INHERIT_ACE,
08720 KEY_ALL_ACCESS,
08721
SeAliasAdminsSid
08722 );
08723
if (!
NT_SUCCESS(status)) {
08724
08725 KdPrint((
"IopOpenDeviceParametersSubkey: RtlAddAccessAllowedAceEx failed, status = %8.8X\n", status));
08726
goto Cleanup0;
08727 }
08728
08729
08730
08731
08732 status =
RtlSetDaclSecurityDescriptor( (PSECURITY_DESCRIPTOR) &newSD,
08733
TRUE,
08734 newDacl,
08735
FALSE
08736 );
08737
08738
if (!
NT_SUCCESS(status)) {
08739
08740 KdPrint((
"IopOpenDeviceParametersSubkey: RtlSetDaclSecurityDescriptor failed, status = %8.8X\n", status));
08741
goto Cleanup0;
08742 }
08743
08744
08745
08746
08747 status =
RtlValidSecurityDescriptor(&newSD);
08748
08749
if (!
NT_SUCCESS(status)) {
08750
08751 KdPrint((
"IopOpenDeviceParametersSubkey: RtlValidSecurityDescriptor failed, status = %8.8X\n", status));
08752
goto Cleanup0;
08753 }
08754
08755
08756 status = ZwSetSecurityObject( *ParamKeyHandle,
08757 DACL_SECURITY_INFORMATION,
08758 &newSD
08759 );
08760
if (!
NT_SUCCESS(status)) {
08761
08762 KdPrint((
"IopOpenDeviceParametersSubkey: ZwSetSecurityObject failed, status = %8.8X\n", status));
08763
goto Cleanup0;
08764 }
08765 }
08766
08767
08768
08769
08770
08771 Cleanup0:
08772
08773
if (oldSD !=
NULL) {
08774
ExFreePool(oldSD);
08775 }
08776
08777
if (newDacl !=
NULL) {
08778
ExFreePool(newDacl);
08779 }
08780
08781
return STATUS_SUCCESS;
08782 }
08783
08784
#if 0
08785
08786
NTSTATUS
08787
IopSetupDeviceObjectFromDeviceClass(
08788 IN
PDEVICE_OBJECT PhysicalDeviceObject,
08789 IN HANDLE DeviceClassKey
08790 )
08791
08792
08793
08794
08795
08796
08797
08798
08799
08800
08801
08802
08803
08804
08805
08806
08807
08808
08809
08810
08811
08812
08813
08814
08815
08816
08817
08818
08819
08820
08821
08822
08823 {
08824
PDEVICE_OBJECT topOfStack =
IoGetAttachedDevice(PhysicalDeviceObject);
08825 UNICODE_STRING valueName;
08826
08827 DEVICE_TYPE deviceType = PhysicalDeviceObject->DeviceType;
08828 ULONG characteristics = PhysicalDeviceObject->Characteristics;
08829
08830 BOOLEAN deviceTypeChanged;
08831
08832 PKEY_VALUE_FULL_INFORMATION info;
08833 PUCHAR data;
08834
08835
NTSTATUS status;
08836
08837
08838
08839
08840
08841
08842
RtlInitUnicodeString(&valueName, REGSTR_VAL_DEVICE_TYPE);
08843 status =
IopGetRegistryValue(DeviceClassKey,
08844 valueName.Buffer,
08845 &info);
08846
08847
if(
NT_SUCCESS(status)) {
08848 data = ((PUCHAR) info) + info->DataOffset;
08849 deviceType = *((PULONG) data);
08850
ExFreePool(info);
08851 }
08852
08853
RtlInitUnicodeString(&valueName, REGSTR_VAL_DEVICE_CHARACTERISTICS);
08854 status =
IopGetRegistryValue(DeviceClassKey,
08855 valueName.Buffer,
08856 &info);
08857
08858
if(
NT_SUCCESS(status)) {
08859 data = ((PUCHAR) info) + info->DataOffset;
08860 characteristics = *((PULONG) data);
08861
08862
ExFreePool(info);
08863 }
08864
08865
08866
08867
08868
08869
08870
08871
08872
08873
08874
ASSERT((PhysicalDeviceObject->DeviceType == FILE_DEVICE_PNP_WITH_INTERFACE) ||
08875 (PhysicalDeviceObject->DeviceType == deviceType));
08876
08877
if(PhysicalDeviceObject->DeviceType != deviceType) {
08878 deviceTypeChanged =
TRUE;
08879 }
08880
08881 PhysicalDeviceObject->DeviceType = deviceType;
08882 PhysicalDeviceObject->Characteristics |= characteristics;
08883
08884
08885
08886
08887
08888 topOfStack->
DeviceType = deviceType;
08889 topOfStack->
Characteristics |= characteristics;
08890
08891
08892
08893
08894
08895
if(deviceTypeChanged) {
08896
08897 status =
IopSetSecurityObjectFromRegistry(PhysicalDeviceObject,
08898 DeviceClassKey);
08899
08900
if(!
NT_SUCCESS(status)) {
08901
08902 BOOLEAN hasName;
08903
CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
08904 PSECURITY_DESCRIPTOR securityDescriptor;
08905 SECURITY_INFORMATION securityInformation = 0;
08906
08907
08908
08909
08910
08911
08912 hasName = ((PhysicalDeviceObject->Flags &
DO_DEVICE_HAS_NAME) ==
08913
DO_DEVICE_HAS_NAME);
08914
08915 securityDescriptor =
08916
IopCreateDefaultDeviceSecurityDescriptor(
08917 deviceType,
08918 PhysicalDeviceObject->Characteristics,
08919 hasName,
08920 buffer,
08921 &securityInformation
08922 );
08923
08924
if(securityDescriptor !=
NULL) {
08925
08926 SECURITY_INFORMATION securityInformation = 0;
08927
08928
08929 status =
ObSetSecurityObjectByPointer(PhysicalDeviceObject,
08930 securityInformation,
08931 securityDescriptor);
08932 }
08933 }
08934
08935
08936
08937
08938
08939
08940
if((deviceType == FILE_DEVICE_DISK) ||
08941 (deviceType == FILE_DEVICE_CD_ROM) ||
08942 (deviceType == FILE_DEVICE_TAPE) ||
08943 (deviceType == FILE_DEVICE_VIRTUAL_DISK)) {
08944
08945
IopCreateVpb(PhysicalDeviceObject);
08946
KeInitializeEvent( &PhysicalDeviceObject->DeviceLock,
08947 SynchronizationEvent,
08948 TRUE );
08949
PoVolumeDevice(PhysicalDeviceObject);
08950 }
08951 }
08952
08953
return status;
08954 }
08955
#endif
08956
08957
08958
NTSTATUS
08959 IopSetSecurityObjectFromRegistry(
08960 IN PVOID Object,
08961 IN HANDLE Key
08962 )
08963
08964
08965
08966
08967
08968
08969
08970
08971
08972
08973
08974
08975
08976
08977
08978
08979
08980
08981
08982
08983
08984 {
08985 UNICODE_STRING valueName;
08986
08987 PKEY_VALUE_FULL_INFORMATION info =
NULL;
08988
08989 PSECURITY_DESCRIPTOR descriptor;
08990 PSECURITY_DESCRIPTOR capturedDescriptor;
08991
08992
NTSTATUS status;
08993
08994
RtlInitUnicodeString(&valueName, REGSTR_VAL_DEVICE_SECURITY_DESCRIPTOR);
08995
08996 status =
IopGetRegistryValue(
Key,
08997 valueName.Buffer,
08998 &info);
08999
09000
if(!
NT_SUCCESS(status)) {
09001
return status;
09002 }
09003
09004 descriptor = (((PUCHAR) info) + info->DataOffset);
09005
09006 status =
SeCaptureSecurityDescriptor(descriptor,
09007
UserMode,
09008
PagedPool,
09009
FALSE,
09010 &capturedDescriptor);
09011
09012
ExFreePool(descriptor);
09013
09014
if(!
NT_SUCCESS(status)) {
09015
return status;
09016 }
09017
09018
try {
09019
09020 SECURITY_INFORMATION securityInformation;
09021
09022 PSID sid;
09023 PACL acl;
09024 BOOLEAN present, tmp;
09025
09026 RtlZeroMemory(&securityInformation,
sizeof(securityInformation));
09027
09028
09029
09030
09031
09032
09033 status =
RtlGetOwnerSecurityDescriptor(capturedDescriptor, &sid, &tmp);
09034
09035
if(
NT_SUCCESS(status) && (sid !=
NULL)) {
09036 securityInformation |= OWNER_SECURITY_INFORMATION;
09037 }
09038
09039 status =
RtlGetGroupSecurityDescriptor(capturedDescriptor, &sid, &tmp);
09040
09041
if(
NT_SUCCESS(status) && (sid !=
NULL)) {
09042 securityInformation |= GROUP_SECURITY_INFORMATION;
09043 }
09044
09045 status =
RtlGetSaclSecurityDescriptor(capturedDescriptor,
09046 &present,
09047 &acl,
09048 &tmp);
09049
09050
if(
NT_SUCCESS(status) && (present)) {
09051 securityInformation |= SACL_SECURITY_INFORMATION;
09052 }
09053
09054 status =
RtlGetDaclSecurityDescriptor(capturedDescriptor,
09055 &present,
09056 &acl,
09057 &tmp);
09058
09059
if(
NT_SUCCESS(status) && (present)) {
09060 securityInformation |= DACL_SECURITY_INFORMATION;
09061 }
09062
09063 status =
ObSetSecurityObjectByPointer(Object,
09064 securityInformation,
09065 capturedDescriptor);
09066 } finally {
09067
SeReleaseSecurityDescriptor(capturedDescriptor,
09068
UserMode,
09069
FALSE);
09070 }
09071
09072
return status;
09073 }
09074
09075
09076
NTSTATUS
09077 PpCreateLegacyDeviceIds(
09078 IN
PDEVICE_OBJECT DeviceObject,
09079 IN PUNICODE_STRING DriverName,
09080 IN PCM_RESOURCE_LIST Resources
09081 )
09082 {
09083
PIOPNP_DEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
09084 PWCHAR buffer;
09085
09086 ULONG length = 0;
09087
09088 INTERFACE_TYPE interface;
09089 PWCHAR interfaceNames[] ={
L"",
09090
L"Internal",
09091
L"Isa",
09092
L"Eisa",
09093
L"MicroChannel",
09094
L"TurboChannel",
09095
L"PCIBus",
09096
L"VMEBus",
09097
L"NuBus",
09098
L"PCMCIABus",
09099
L"CBus",
09100
L"MPIBus",
09101
L"MPSABus",
09102
L"ProcessorInternal",
09103
L"InternalPowerBus",
09104
L"PNPISABus",
09105
L"PNPBus",
09106
L"Other",
09107
L"Root"};
09108
09109
09110
PAGED_CODE();
09111
09112
if(Resources !=
NULL) {
09113
09114 interface = Resources->List[0].InterfaceType;
09115
09116
if((interface > MaximumInterfaceType) ||
09117 (interface < InterfaceTypeUndefined)) {
09118 interface = MaximumInterfaceType;
09119 }
09120 }
else {
09121 interface = Internal;
09122 }
09123
09124 interface++;
09125
09126
09127
09128
09129
09130
09131 length = wcslen(
LEGACY_COMPATIBLE_ID_BASE) *
sizeof(WCHAR);
09132 length += wcslen(interfaceNames[interface]) *
sizeof(WCHAR);
09133 length +=
sizeof(
L'\\');
09134 length += DriverName->Length;
09135 length +=
sizeof(UNICODE_NULL);
09136
09137 length += wcslen(
LEGACY_COMPATIBLE_ID_BASE) *
sizeof(WCHAR);
09138 length +=
sizeof(
L'\\');
09139 length += DriverName->Length;
09140 length +=
sizeof(UNICODE_NULL) * 2;
09141
09142 buffer =
ExAllocatePool(
PagedPool, length);
09143 deviceExtension->
CompatibleIdList = buffer;
09144
09145
if(buffer ==
NULL) {
09146
return STATUS_INSUFFICIENT_RESOURCES;
09147 }
09148
09149 RtlZeroMemory(buffer, length);
09150
09151 swprintf(buffer,
L"%ws%ws\\%wZ",
LEGACY_COMPATIBLE_ID_BASE,
09152 interfaceNames[interface],
09153 DriverName);
09154
09155
09156
09157
09158
09159
09160 buffer += wcslen(buffer) + 1;
09161
09162 swprintf(buffer,
L"%ws\\%wZ",
LEGACY_COMPATIBLE_ID_BASE, DriverName);
09163
09164 deviceExtension->
CompatibleIdListSize = length;
09165
09166
return STATUS_SUCCESS;
09167 }
09168
09169
09170
NTSTATUS
09171 IoNotifyPowerOperationVetoed(
09172 IN POWER_ACTION VetoedPowerOperation,
09173 IN
PDEVICE_OBJECT TargetedDeviceObject OPTIONAL,
09174 IN
PDEVICE_OBJECT VetoingDeviceObject
09175 )
09176
09177
09178
09179 {
09180
PDEVICE_NODE deviceNode, vetoingDeviceNode;
09181
PDEVICE_OBJECT deviceObject;
09182
09183
PAGED_CODE();
09184
09185
09186
09187
09188
09189
09190
09191
if (TargetedDeviceObject) {
09192
09193 deviceObject = TargetedDeviceObject;
09194
09195 }
else {
09196
09197 deviceObject =
IopRootDeviceNode->
PhysicalDeviceObject;
09198 }
09199
09200 deviceNode = (
PDEVICE_NODE)deviceObject->
DeviceObjectExtension->
DeviceNode;
09201
if (!deviceNode) {
09202
return STATUS_INVALID_PARAMETER_2;
09203 }
09204
09205 vetoingDeviceNode = (
PDEVICE_NODE)VetoingDeviceObject->DeviceObjectExtension->DeviceNode;
09206
if (!vetoingDeviceNode) {
09207
return STATUS_INVALID_PARAMETER_3;
09208 }
09209
09210
return PpSetPowerVetoEvent(
09211 VetoedPowerOperation,
09212
NULL,
09213
NULL,
09214 deviceObject,
09215 PNP_VetoDevice,
09216 &vetoingDeviceNode->
InstancePath
09217 );
09218 }
09219
09220 ULONG
09221 IoPnPDeliverServicePowerNotification(
09222 ULONG PwrNotification,
09223 BOOLEAN Synchronous
09224 )
09225 {
09226
09227
NTSTATUS status = STATUS_SUCCESS;
09228
KEVENT completionEvent;
09229
NTSTATUS completionStatus=STATUS_SUCCESS;
09230 PNP_VETO_TYPE vetoType = PNP_VetoTypeUnknown;
09231 UNICODE_STRING vetoName;
09232
09233
PAGED_CODE();
09234
09235
#define MAX_VETO_NAME_LENGTH 512 //From Revent.c make it common
09236
09237
if (Synchronous) {
09238
09239
09240
09241 vetoName.Buffer =
ExAllocatePool (
PagedPool,
MAX_VETO_NAME_LENGTH*
sizeof (WCHAR));
09242
09243
if (vetoName.Buffer) {
09244 vetoName.MaximumLength =
MAX_VETO_NAME_LENGTH;
09245 }
else {
09246 vetoName.MaximumLength = 0;
09247 }
09248 vetoName.Length = 0;
09249
09250
KeInitializeEvent(&completionEvent, NotificationEvent,
FALSE);
09251
09252 status =
PpSetPowerEvent(
09253 PwrNotification,
09254 &completionEvent,
09255 &completionStatus,
09256 &vetoType,&vetoName
09257 );
09258
09259
if (
NT_SUCCESS(status)) {
09260
09261
KeWaitForSingleObject( &completionEvent,
Executive,
KernelMode,
FALSE,
NULL );
09262 status = completionStatus;
09263
09264
if (vetoType == PNP_VetoWindowsService) {
09265
IoRaiseInformationalHardError (STATUS_DRIVER_FAILED_SLEEP,&vetoName,
NULL);
09266 }
09267
09268 }
09269
if (vetoName.Buffer) {
09270
ExFreePool (vetoName.Buffer);
09271 }
09272
09273 }
else {
09274 status =
PpSetPowerEvent(
09275 PwrNotification,
09276
NULL,
09277
NULL,
09278
NULL,
09279
NULL
09280 );
09281 }
09282
09283
ASSERT ((completionStatus == STATUS_SUCCESS) ||
09284 (completionStatus == STATUS_UNSUCCESSFUL));
09285
09286
09287
09288
09289
return (completionStatus != STATUS_UNSUCCESSFUL);
09290
09291 }
09292
09293
09294
09295
09296
09297
09298
09299
09300
VOID
09301 IopOrphanNotification(
09302 IN
PDEVICE_NODE TargetNode
09303 )
09304 {
09305
PTARGET_DEVICE_NOTIFY_ENTRY entry;
09306
PFAST_MUTEX lock;
09307
09308
IopAcquireNotifyLock(&
IopTargetDeviceNotifyLock);
09309
09310
while (!IsListEmpty(&TargetNode->TargetDeviceNotify)) {
09311 entry = (
PTARGET_DEVICE_NOTIFY_ENTRY)RemoveHeadList(&TargetNode->TargetDeviceNotify);
09312
if (entry->
EventCategory ==
EventCategoryTargetDeviceChange) {
09313
09314
if (entry->
PhysicalDeviceObject) {
09315
ObDereferenceObject(entry->
PhysicalDeviceObject);
09316 entry->
PhysicalDeviceObject =
NULL;
09317 }
09318 }
09319 }
09320
09321
IopReleaseNotifyLock(&
IopTargetDeviceNotifyLock);
09322 }
09323
09324
09325
09326
09327
09328
09329
09330
09331
09332
NTSTATUS
09333 IopPnPHydraCallback (
09334 PVOID CallbackParams
09335 )
09336 {
09337
PNOTIFICATION_CALLBACK_PARAM_BLOCK params=(
PNOTIFICATION_CALLBACK_PARAM_BLOCK)CallbackParams;
09338
NTSTATUS status;
09339
09340 status = (params->
Callout)(params->
NotificationStructure,params->
Context);
09341
09342
return status;
09343 }
09344
09345
09346
09347
09348
09349 typedef struct {
09350 PWSTR * VetoList;
09351 ULONG VetoListLength;
09352 PPNP_VETO_TYPE VetoType;
09353 NTSTATUS *
Status;
09354 }
IO_GET_LEGACY_VETO_LIST_CONTEXT, *
PIO_GET_LEGACY_VETO_LIST_CONTEXT;
09355
09356 BOOLEAN
09357 IopAppendLegacyVeto(
09358 IN PIO_GET_LEGACY_VETO_LIST_CONTEXT Context,
09359 IN PUNICODE_STRING VetoName
09360 )
09361
09362
09363
09364
09365
09366
09367
09368
09369
09370
09371
09372
09373
09374
09375
09376
09377
09378
09379 {
09380 ULONG Length;
09381 PWSTR
Buffer;
09382
09383
09384
09385
09386
09387
09388
09389 Length = Context->VetoListLength + VetoName->Length +
sizeof (WCHAR);
09390
09391
09392
09393
09394
09395
Buffer =
ExAllocatePool(
09396
NonPagedPool,
09397 Length
09398 );
09399
09400
09401
09402
09403
09404
09405
09406
09407
09408
if (
Buffer !=
NULL) {
09409
09410
if (*Context->VetoList !=
NULL) {
09411
09412 RtlMoveMemory(
09413
Buffer,
09414 *Context->VetoList,
09415 Context->VetoListLength
09416 );
09417
09418
ExFreePool(*Context->VetoList);
09419
09420 }
09421
09422 RtlMoveMemory(
09423 &
Buffer[Context->VetoListLength / sizeof (WCHAR)],
09424 VetoName->Buffer,
09425 VetoName->Length
09426 );
09427
09428
Buffer[Length /
sizeof (WCHAR) - 1] =
L'\0';
09429
09430 *Context->VetoList =
Buffer;
09431 Context->VetoListLength = Length;
09432
09433
return TRUE;
09434
09435 }
else {
09436
09437 *Context->Status = STATUS_INSUFFICIENT_RESOURCES;
09438
09439
return FALSE;
09440
09441 }
09442 }
09443
09444 BOOLEAN
09445 IopGetLegacyVetoListDevice(
09446 IN
PDEVICE_NODE DeviceNode,
09447 IN PIO_GET_LEGACY_VETO_LIST_CONTEXT Context
09448 )
09449
09450
09451
09452
09453
09454
09455
09456
09457
09458
09459
09460
09461
09462
09463
09464
09465
09466
09467
09468 {
09469
PDEVICE_CAPABILITIES DeviceCapabilities;
09470
09471
09472
09473
09474
09475
09476 DeviceCapabilities =
IopDeviceNodeFlagsToCapabilities(DeviceNode);
09477
09478
if (DeviceCapabilities->
NonDynamic) {
09479
09480
09481
09482
09483
09484
09485
09486 *Context->VetoType = PNP_VetoLegacyDevice;
09487
09488
if (Context->VetoList !=
NULL) {
09489
09490
if (!
IopAppendLegacyVeto(Context, &DeviceNode->InstancePath)) {
09491
return FALSE;
09492 }
09493
09494 }
else {
09495
09496
return FALSE;
09497
09498 }
09499
09500 }
09501
09502
return TRUE;
09503 }
09504
09505 BOOLEAN
09506 IopGetLegacyVetoListDeviceNode(
09507 IN
PDEVICE_NODE DeviceNode,
09508 IN PIO_GET_LEGACY_VETO_LIST_CONTEXT Context
09509 )
09510
09511
09512
09513
09514
09515
09516
09517
09518
09519
09520
09521
09522
09523
09524
09525
09526
09527
09528
09529
09530
09531 {
09532
PDEVICE_NODE Child;
09533
09534
09535
09536
09537
09538
09539
09540
09541
if (!
IopGetLegacyVetoListDevice(DeviceNode, Context)) {
09542
return FALSE;
09543 }
09544
09545
09546
09547
09548
09549
09550
09551
for (Child = DeviceNode->
Child;
09552 Child !=
NULL;
09553 Child = Child->
Sibling) {
09554
09555
if (!
IopGetLegacyVetoListDeviceNode(Child, Context)) {
09556
return FALSE;
09557 }
09558
09559 }
09560
09561
return TRUE;
09562 }
09563
09564
VOID
09565 IopGetLegacyVetoListDrivers(
09566 IN PIO_GET_LEGACY_VETO_LIST_CONTEXT Context
09567 )
09568 {
09569
PDRIVER_OBJECT driverObject;
09570 OBJECT_ATTRIBUTES attributes;
09571 UNICODE_STRING driverString;
09572 POBJECT_DIRECTORY_INFORMATION dirInfo;
09573 HANDLE directoryHandle;
09574 ULONG dirInfoLength, neededLength, dirContext;
09575
NTSTATUS status;
09576 BOOLEAN restartScan;
09577
09578 dirInfoLength = 0;
09579 dirInfo =
NULL;
09580 restartScan =
TRUE;
09581
09582
09583
09584
09585
09586
RtlInitUnicodeString(&driverString,
L"\\Driver");
09587
09588 InitializeObjectAttributes(&attributes,
09589 &driverString,
09590 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
09591
NULL,
09592
NULL
09593 );
09594
09595 status = ZwOpenDirectoryObject(&directoryHandle,
09596 DIRECTORY_QUERY,
09597 &attributes
09598 );
09599
if (!
NT_SUCCESS(status)) {
09600 *Context->Status = status;
09601
return;
09602 }
09603
09604
for (;;) {
09605
09606
09607
09608
09609
09610
09611
09612 status = ZwQueryDirectoryObject(directoryHandle,
09613 dirInfo,
09614 dirInfoLength,
09615
TRUE,
09616 restartScan,
09617 &dirContext,
09618 &neededLength);
09619
if (status == STATUS_BUFFER_TOO_SMALL) {
09620 dirInfoLength = neededLength;
09621
if (dirInfo !=
NULL) {
09622
ExFreePool(dirInfo);
09623 }
09624 dirInfo =
ExAllocatePool(
PagedPool, dirInfoLength);
09625
if (dirInfo ==
NULL) {
09626 *Context->Status = STATUS_INSUFFICIENT_RESOURCES;
09627
break;
09628 }
09629 status = ZwQueryDirectoryObject(directoryHandle,
09630 dirInfo,
09631 dirInfoLength,
09632
TRUE,
09633 restartScan,
09634 &dirContext,
09635 &neededLength);
09636 }
09637 restartScan =
FALSE;
09638
09639
if (!
NT_SUCCESS(status)) {
09640
break;
09641 }
09642
09643
09644
09645
09646
09647
09648
09649 driverString.MaximumLength =
sizeof(
L"\\Driver\\") +
09650 dirInfo->Name.Length;
09651 driverString.Length = driverString.MaximumLength -
sizeof(WCHAR);
09652 driverString.Buffer =
ExAllocatePool(
PagedPool,
09653 driverString.MaximumLength);
09654
if (driverString.Buffer ==
NULL) {
09655 *Context->Status = STATUS_INSUFFICIENT_RESOURCES;
09656
break;
09657 }
09658
09659 swprintf(driverString.Buffer,
L"\\Driver\\%ws", dirInfo->Name.Buffer);
09660 status =
ObReferenceObjectByName(&driverString,
09661 OBJ_CASE_INSENSITIVE,
09662
NULL,
09663 0,
09664
IoDriverObjectType,
09665
KernelMode,
09666
NULL,
09667 &driverObject);
09668
09669
ExFreePool(driverString.Buffer);
09670
09671
if (
NT_SUCCESS(status)) {
09672
ASSERT(driverObject->
Type ==
IO_TYPE_DRIVER);
09673
if (driverObject->
Flags &
DRVO_LEGACY_RESOURCES) {
09674
09675
09676
09677
09678
09679
09680
09681
09682
09683
09684
09685 *Context->VetoType = PNP_VetoLegacyDriver;
09686
09687
if (Context->VetoList !=
NULL) {
09688
IopAppendLegacyVeto(Context, &dirInfo->Name);
09689 }
09690 }
09691
ObDereferenceObject(driverObject);
09692
09693
09694
09695
09696
09697
if (((*Context->VetoType == PNP_VetoLegacyDriver) &&
09698 (Context->VetoList ==
NULL)) ||
09699 !
NT_SUCCESS(*Context->Status)) {
09700
break;
09701 }
09702 }
09703 }
09704
if (dirInfo !=
NULL) {
09705
ExFreePool(dirInfo);
09706 }
09707
09708 ZwClose(directoryHandle);
09709 }
09710
09711
NTSTATUS
09712 IoGetLegacyVetoList(
09713 OUT PWSTR *VetoList OPTIONAL,
09714 OUT PPNP_VETO_TYPE VetoType
09715 )
09716
09717
09718
09719
09720
09721
09722
09723
09724
09725
09726
09727
09728
09729
09730
09731
09732
09733
09734
09735
09736
09737
09738
09739
09740
09741
09742
09743
09744
09745 {
09746
NTSTATUS Status;
09747
IO_GET_LEGACY_VETO_LIST_CONTEXT Context;
09748 UNICODE_STRING UnicodeString;
09749
09750
09751
09752
09753
09754
if (VetoList !=
NULL) {
09755 *VetoList =
NULL;
09756 }
09757
09758
09759
09760
09761
09762
ASSERT(VetoType !=
NULL);
09763
09764 *VetoType = PNP_VetoTypeUnknown;
09765
09766
09767
09768
09769
09770
Status = STATUS_SUCCESS;
09771
09772
if (
PnPInitialized ==
FALSE) {
09773
09774
09775
09776
09777
return Status;
09778 }
09779
09780
09781
09782
09783
09784 Context.
VetoList = VetoList;
09785 Context.
VetoListLength = 0;
09786 Context.
VetoType = VetoType;
09787 Context.
Status = &
Status;
09788
09789
09790
09791
09792
09793
09794
09795
IopGetLegacyVetoListDrivers(&Context);
09796
09797
09798
09799
09800
09801
09802
09803
if (
NT_SUCCESS(
Status)) {
09804
09805
if (*VetoType == PNP_VetoTypeUnknown) {
09806
09807
IopAcquireEnumerationLock(
NULL);
09808
09809
IopGetLegacyVetoListDeviceNode(
09810
IopRootDeviceNode,
09811 &Context
09812 );
09813
09814
IopReleaseEnumerationLock(
NULL);
09815
09816 }
09817
09818 }
09819
09820
09821
09822
09823
09824
09825
09826
if (
NT_SUCCESS(
Status)) {
09827
09828
if (*VetoType != PNP_VetoTypeUnknown) {
09829
09830
if (VetoList !=
NULL) {
09831
09832
RtlInitUnicodeString(
09833 &UnicodeString,
09834
L""
09835 );
09836
09837
IopAppendLegacyVeto(
09838 &Context,
09839 &UnicodeString
09840 );
09841
09842 }
09843
09844 }
09845
09846 }
09847
09848
09849
09850
09851
09852
09853
if (!
NT_SUCCESS(
Status)) {
09854
09855
if (VetoList !=
NULL && *VetoList !=
NULL) {
09856
ExFreePool(*VetoList);
09857 *VetoList =
NULL;
09858 }
09859
09860 }
09861
09862
return Status;
09863 }
09864
09865
NTSTATUS
09866 IopDoDeferredSetInterfaceState(
09867 IN
PDEVICE_NODE DeviceNode
09868 )
09869
09870
09871
09872
09873
09874
09875
09876
09877
09878
09879
09880
09881
09882
09883
09884 {
09885 KIRQL irql;
09886
PDEVICE_OBJECT attachedDevice;
09887
09888
KeEnterCriticalRegion();
09889
ExAcquireResourceExclusive(&
PpRegistryDeviceResource,
TRUE);
09890
09891 ExAcquireFastLock( &
IopDatabaseLock, &irql );
09892
09893
for (attachedDevice = DeviceNode->PhysicalDeviceObject;
09894 attachedDevice;
09895 attachedDevice = attachedDevice->
AttachedDevice) {
09896
09897 attachedDevice->
DeviceObjectExtension->
ExtensionFlags &= ~
DOE_START_PENDING;
09898 }
09899
09900 ExReleaseFastLock( &
IopDatabaseLock, irql );
09901
09902
while (!IsListEmpty(&DeviceNode->PendedSetInterfaceState)) {
09903
09904
PPENDING_SET_INTERFACE_STATE entry;
09905
09906 entry = (
PPENDING_SET_INTERFACE_STATE)RemoveHeadList(&DeviceNode->PendedSetInterfaceState);
09907
09908
IopProcessSetInterfaceState(&entry->
LinkName,
TRUE,
FALSE);
09909
09910
ExFreePool(entry->
LinkName.Buffer);
09911
09912
ExFreePool(entry);
09913 }
09914
09915
ExReleaseResource(&
PpRegistryDeviceResource);
09916
KeLeaveCriticalRegion();
09917
09918
return STATUS_SUCCESS;
09919 }
09920
09921
NTSTATUS
09922 IopProcessSetInterfaceState(
09923 IN PUNICODE_STRING SymbolicLinkName,
09924 IN BOOLEAN Enable,
09925 IN BOOLEAN DeferNotStarted
09926 )
09927
09928
09929
09930
09931
09932
09933
09934
09935
09936
09937
09938
09939
09940
09941
09942
09943
09944
09945
09946
09947
09948
09949
09950
09951
09952
09953 {
09954
NTSTATUS status;
09955 HANDLE hInterfaceClassKey =
NULL;
09956 HANDLE hInterfaceParentKey=
NULL, hInterfaceInstanceKey =
NULL;
09957 HANDLE hInterfaceParentControl =
NULL, hInterfaceInstanceControl =
NULL;
09958 UNICODE_STRING tempString, actualSymbolicLinkName, deviceNameString;
09959 PKEY_VALUE_FULL_INFORMATION pKeyValueInfo;
09960 ULONG linked, refcount;
09961 GUID guid;
09962
PDEVICE_OBJECT physicalDeviceObject;
09963 PWCHAR deviceNameBuffer =
NULL;
09964 ULONG deviceNameBufferLength;
09965
09966
PAGED_CODE();
09967
09968
09969
09970
09971
09972 status =
IopDropReferenceString(&actualSymbolicLinkName, SymbolicLinkName);
09973
if (!
NT_SUCCESS(status)) {
09974
goto clean0;
09975 }
09976
09977
09978
09979
09980
09981 status =
IopParseSymbolicLinkName(SymbolicLinkName,
NULL,
NULL,
NULL,
NULL,
NULL, &guid);
09982
09983
09984
09985
09986
09987 status =
IopDeviceInterfaceKeysFromSymbolicLink(SymbolicLinkName,
09988 KEY_READ | KEY_WRITE,
09989 &hInterfaceClassKey,
09990 &hInterfaceParentKey,
09991 &hInterfaceInstanceKey
09992 );
09993
09994
if (!
NT_SUCCESS(status)) {
09995
goto clean1;
09996 }
09997
09998
09999
10000
10001 PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
10002 status =
IopCreateRegistryKeyEx( &hInterfaceParentControl,
10003 hInterfaceParentKey,
10004 &tempString,
10005 KEY_READ,
10006 REG_OPTION_VOLATILE,
10007
NULL
10008 );
10009
if (!
NT_SUCCESS(status)) {
10010
goto clean1;
10011 }
10012
10013
10014
10015
10016
10017 status =
IopGetRegistryValue(hInterfaceParentKey,
10018 REGSTR_VAL_DEVICE_INSTANCE,
10019 &pKeyValueInfo
10020 );
10021
10022
if(
NT_SUCCESS(status)) {
10023
10024
10025
10026 PiWstrToUnicodeString(&tempString, REGSTR_KEY_CONTROL);
10027 status =
IopCreateRegistryKeyEx( &hInterfaceInstanceControl,
10028 hInterfaceInstanceKey,
10029 &tempString,
10030 KEY_READ,
10031 REG_OPTION_VOLATILE,
10032
NULL
10033 );
10034
if(!
NT_SUCCESS(status)) {
10035
ExFreePool(pKeyValueInfo);
10036 hInterfaceInstanceControl =
NULL;
10037 }
10038 }
10039
10040
if (!
NT_SUCCESS(status)) {
10041
goto clean2;
10042 }
10043
10044
10045
10046
10047
if (pKeyValueInfo->Type == REG_SZ) {
10048
10049
IopRegistryDataToUnicodeString(&tempString,
10050 (PWSTR)
KEY_VALUE_DATA(pKeyValueInfo),
10051 pKeyValueInfo->DataLength
10052 );
10053
10054 physicalDeviceObject =
IopDeviceObjectFromDeviceInstance(
NULL, &tempString);
10055
10056
if (physicalDeviceObject) {
10057
10058
10059
10060
10061
10062
10063
10064
10065
if (DeferNotStarted) {
10066
10067
if (physicalDeviceObject->
DeviceObjectExtension->
ExtensionFlags &
DOE_START_PENDING) {
10068
10069
PDEVICE_NODE deviceNode;
10070
PPENDING_SET_INTERFACE_STATE pendingSetState;
10071
10072
10073
10074
10075
10076 deviceNode = (
PDEVICE_NODE)physicalDeviceObject->
DeviceObjectExtension->
DeviceNode;
10077
10078
if (Enable) {
10079
10080 pendingSetState =
ExAllocatePool(
PagedPool,
10081
sizeof(
PENDING_SET_INTERFACE_STATE));
10082
10083
if (pendingSetState !=
NULL) {
10084
10085 pendingSetState->
LinkName.Buffer =
ExAllocatePool(
PagedPool,
10086 SymbolicLinkName->Length);
10087
10088
if (pendingSetState->
LinkName.Buffer !=
NULL) {
10089
10090
10091
10092
10093
10094
10095 pendingSetState->
LinkName.MaximumLength = SymbolicLinkName->Length;
10096 pendingSetState->
LinkName.Length = SymbolicLinkName->Length;
10097 RtlCopyMemory( pendingSetState->
LinkName.Buffer,
10098 SymbolicLinkName->Buffer,
10099 SymbolicLinkName->Length);
10100 InsertTailList( &deviceNode->
PendedSetInterfaceState,
10101 &pendingSetState->
List);
10102
10103
ExFreePool(pKeyValueInfo);
10104
10105
ObDereferenceObject(physicalDeviceObject);
10106
10107 status = STATUS_SUCCESS;
10108
goto clean2;
10109
10110 }
else {
10111
10112
10113
10114
10115
10116
ExFreePool(pendingSetState);
10117 status = STATUS_INSUFFICIENT_RESOURCES;
10118 }
10119
10120 }
else {
10121
10122
10123
10124
10125
10126
10127 status = STATUS_INSUFFICIENT_RESOURCES;
10128 }
10129
10130 }
else {
10131
10132 PLIST_ENTRY entry;
10133
10134
10135
10136
10137
10138
10139
10140
10141
for (entry = deviceNode->
PendedSetInterfaceState.Flink;
10142 entry != &deviceNode->
PendedSetInterfaceState;
10143 entry = entry->Flink) {
10144
10145 pendingSetState = CONTAINING_RECORD( entry,
10146
PENDING_SET_INTERFACE_STATE,
10147
List );
10148
10149
if (
RtlEqualUnicodeString( &pendingSetState->
LinkName,
10150 SymbolicLinkName,
10151
TRUE)) {
10152
10153
10154
10155
10156
10157 RemoveEntryList(&pendingSetState->
List);
10158
10159
ExFreePool(pendingSetState->
LinkName.Buffer);
10160
ExFreePool(pendingSetState);
10161
10162
break;
10163 }
10164 }
10165
10166
#if 0
10167
10168
10169
10170
10171
10172
10173
10174
if (entry == &deviceNode->
PendedSetInterfaceState) {
10175 PIDBGMSG(PIDBG_ERROR,
10176 (
"IopProcessSetInterfaceState: Disable couldn't find deferred enable, DeviceNode = 0x%p, SymbolicLink = \"%Z\"\n",
10177 deviceNode,
10178 SymbolicLinkName));
10179 }
10180
10181
ASSERT(entry != &deviceNode->
PendedSetInterfaceState);
10182
#endif
10183
ExFreePool(pKeyValueInfo);
10184
10185
ObDereferenceObject(physicalDeviceObject);
10186
10187 status = STATUS_SUCCESS;
10188
goto clean2;
10189 }
10190 }
10191 }
10192
10193
if (!Enable || !
NT_SUCCESS(status)) {
10194
ObDereferenceObject(physicalDeviceObject);
10195 }
10196 }
else {
10197
10198 status = STATUS_INVALID_DEVICE_REQUEST;
10199 }
10200
10201 }
else {
10202
10203
10204
10205 physicalDeviceObject =
NULL;
10206 status = STATUS_INVALID_DEVICE_REQUEST;
10207 }
10208
10209
if (!Enable) {
10210
10211
10212
10213
10214
10215
10216
10217 status = STATUS_SUCCESS;
10218 }
10219
10220
ExFreePool(pKeyValueInfo);
10221
10222
if (!
NT_SUCCESS(status)) {
10223
goto clean2;
10224 }
10225
10226
if (Enable) {
10227
10228
10229
10230
10231 deviceNameBufferLength = 256 *
sizeof(WCHAR);
10232
10233
while (
TRUE) {
10234
10235 deviceNameBuffer =
ExAllocatePool(
PagedPool, deviceNameBufferLength);
10236
if (!deviceNameBuffer) {
10237 status = STATUS_INSUFFICIENT_RESOURCES;
10238
break;
10239 }
10240
10241 status =
IoGetDeviceProperty( physicalDeviceObject,
10242
DevicePropertyPhysicalDeviceObjectName,
10243 deviceNameBufferLength,
10244 deviceNameBuffer,
10245 &deviceNameBufferLength
10246 );
10247
10248
if (
NT_SUCCESS(status)) {
10249
break;
10250 }
else {
10251
10252
10253
10254
ExFreePool(deviceNameBuffer);
10255
10256
if (status != STATUS_BUFFER_TOO_SMALL) {
10257
10258
10259
10260
break;
10261 }
10262
10263
10264
10265
10266 }
10267 }
10268
10269
10270
10271
10272
ObDereferenceObject(physicalDeviceObject);
10273
10274
if (!
NT_SUCCESS(status)) {
10275
goto clean2;
10276 }
10277
10278
10279
10280
10281
10282
RtlInitUnicodeString(&deviceNameString, deviceNameBuffer);
10283 }
10284
10285
10286
10287
10288 pKeyValueInfo=
NULL;
10289 status =
IopGetRegistryValue(hInterfaceInstanceControl, REGSTR_VAL_LINKED, &pKeyValueInfo);
10290
10291
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
10292
10293
10294
10295
10296
10297 linked = 0;
10298
10299 }
else {
10300
if (!
NT_SUCCESS(status)) {
10301
10302
10303
10304
goto clean3;
10305 }
10306
10307
10308
10309
10310
10311
if(pKeyValueInfo->Type == REG_DWORD && pKeyValueInfo->DataLength ==
sizeof(ULONG)) {
10312
10313 linked = *((PULONG)
KEY_VALUE_DATA(pKeyValueInfo));
10314
10315 }
else {
10316
10317
10318
10319
10320
10321
10322 linked = 0;
10323
10324 }
10325
10326 }
10327
if (pKeyValueInfo) {
10328
ExFreePool (pKeyValueInfo);
10329 }
10330
10331
10332
10333
10334
10335
RtlInitUnicodeString(&tempString, REGSTR_VAL_REFERENCECOUNT);
10336 status =
IopGetRegistryValue(hInterfaceParentControl,
10337 tempString.Buffer,
10338 &pKeyValueInfo
10339 );
10340
10341
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
10342
10343
10344
10345
10346
10347 refcount = 0;
10348
10349 }
else {
10350
if (!
NT_SUCCESS(status)) {
10351
goto clean3;
10352 }
10353
10354
10355
10356
10357
10358
if(pKeyValueInfo->Type == REG_DWORD && pKeyValueInfo->DataLength ==
sizeof(ULONG)) {
10359
10360 refcount = *((PULONG)
KEY_VALUE_DATA(pKeyValueInfo));
10361
10362 }
else {
10363
10364
10365
10366
10367
10368
10369 refcount = 0;
10370
10371 }
10372
10373
ExFreePool(pKeyValueInfo);
10374 }
10375
10376
10377
if (Enable) {
10378
10379
if (!linked) {
10380
10381
10382
10383
10384
if (refcount > 0) {
10385
10386
10387
10388
10389 refcount += 1;
10390 }
else {
10391
10392
10393
10394
10395
10396 refcount = 1;
10397 status =
IoCreateSymbolicLink(&actualSymbolicLinkName, &deviceNameString);
10398
10399
if (status == STATUS_OBJECT_NAME_COLLISION) {
10400
10401
10402
10403 KdPrint((
"IoSetDeviceInterfaceState: symbolic link for %ws already exists! status = %8.8X\n",
10404 actualSymbolicLinkName.Buffer, status));
10405 status = STATUS_SUCCESS;
10406 }
10407
10408 }
10409
10410 linked = 1;
10411
10412
#if 0
10413
IopSetupDeviceObjectFromDeviceClass(physicalDeviceObject,
10414 hInterfaceClassKey);
10415
#endif
10416
10417 }
else {
10418
10419
10420
10421
10422
10423 status = STATUS_OBJECT_NAME_EXISTS;
10424
goto clean3;
10425
10426 }
10427 }
else {
10428
10429
if (linked) {
10430
10431
10432
10433
10434
10435
if (refcount > 1) {
10436
10437
10438
10439
10440 refcount -= 1;
10441 }
else {
10442
10443
10444
10445
10446 refcount = 0;
10447 status =
IoDeleteSymbolicLink(&actualSymbolicLinkName);
10448
10449
if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
10450
10451
10452
10453 KdPrint((
"IoSetDeviceInterfaceState: no symbolic link for %ws to delete! status = %8.8X\n",
10454 actualSymbolicLinkName.Buffer, status));
10455 status = STATUS_SUCCESS;
10456 }
10457
10458 }
10459
10460 linked = 0;
10461
10462 }
else {
10463
10464
10465
10466
10467
10468 status = STATUS_OBJECT_NAME_NOT_FOUND;
10469 }
10470 }
10471
10472
if (!
NT_SUCCESS(status)) {
10473
goto clean3;
10474 }
10475
10476
10477
10478
10479
10480 PiWstrToUnicodeString(&tempString, REGSTR_VAL_LINKED);
10481 status = ZwSetValueKey(hInterfaceInstanceControl,
10482 &tempString,
10483 0,
10484 REG_DWORD,
10485 &linked,
10486
sizeof(linked)
10487 );
10488
10489
10490
10491
10492
10493
RtlInitUnicodeString(&tempString, REGSTR_VAL_REFERENCECOUNT);
10494 status = ZwSetValueKey(hInterfaceParentControl,
10495 &tempString,
10496 0,
10497 REG_DWORD,
10498 &refcount,
10499
sizeof(refcount)
10500 );
10501
10502
10503
10504
10505
10506
10507
if (linked) {
10508
10509
PpSetDeviceClassChange( (LPGUID) &GUID_DEVICE_INTERFACE_ARRIVAL, &guid, SymbolicLinkName);
10510
10511 }
else {
10512
10513
PpSetDeviceClassChange( (LPGUID) &GUID_DEVICE_INTERFACE_REMOVAL, &guid, SymbolicLinkName);
10514
10515 }
10516
10517 clean3:
10518
if (deviceNameBuffer !=
NULL) {
10519
ExFreePool(deviceNameBuffer);
10520 }
10521
10522 clean2:
10523
if (hInterfaceParentControl) {
10524 ZwClose(hInterfaceParentControl);
10525 }
10526
if (hInterfaceInstanceControl) {
10527 ZwClose(hInterfaceInstanceControl);
10528 }
10529
10530 clean1:
10531
if (hInterfaceParentKey) {
10532 ZwClose(hInterfaceParentKey);
10533 }
10534
if (hInterfaceInstanceKey) {
10535 ZwClose(hInterfaceInstanceKey);
10536 }
10537
if(hInterfaceClassKey !=
NULL) {
10538 ZwClose(hInterfaceClassKey);
10539 }
10540
10541 clean0:
10542
if (!
NT_SUCCESS(status) && !Enable) {
10543
10544
10545
10546
10547 status = STATUS_SUCCESS;
10548 }
10549
10550
return status;
10551 }