Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpnproot.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS Kernel 00003 * COPYRIGHT: GPL - See COPYING in the top level directory 00004 * FILE: ntoskrnl/io/pnpmgr/pnproot.c 00005 * PURPOSE: PnP manager root device 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * Copyright 2007 Herv? Poussineau (hpoussin@reactos.org) 00008 */ 00009 00010 /* INCLUDES ******************************************************************/ 00011 00012 #include <ntoskrnl.h> 00013 #define NDEBUG 00014 #include <debug.h> 00015 00016 /* GLOBALS *******************************************************************/ 00017 00018 #define ENUM_NAME_ROOT L"Root" 00019 00020 /* DATA **********************************************************************/ 00021 00022 typedef struct _PNPROOT_DEVICE 00023 { 00024 // Entry on device list 00025 LIST_ENTRY ListEntry; 00026 // Physical Device Object of device 00027 PDEVICE_OBJECT Pdo; 00028 // Device ID 00029 UNICODE_STRING DeviceID; 00030 // Instance ID 00031 UNICODE_STRING InstanceID; 00032 // Device description 00033 UNICODE_STRING DeviceDescription; 00034 // Resource requirement list 00035 PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList; 00036 // Associated resource list 00037 PCM_RESOURCE_LIST ResourceList; 00038 ULONG ResourceListSize; 00039 } PNPROOT_DEVICE, *PPNPROOT_DEVICE; 00040 00041 typedef enum 00042 { 00043 dsStopped, 00044 dsStarted, 00045 dsPaused, 00046 dsRemoved, 00047 dsSurpriseRemoved 00048 } PNPROOT_DEVICE_STATE; 00049 00050 typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION 00051 { 00052 // Wether this device extension is for an FDO or PDO 00053 BOOLEAN IsFDO; 00054 } PNPROOT_COMMON_DEVICE_EXTENSION, *PPNPROOT_COMMON_DEVICE_EXTENSION; 00055 00056 /* Physical Device Object device extension for a child device */ 00057 typedef struct _PNPROOT_PDO_DEVICE_EXTENSION 00058 { 00059 // Common device data 00060 PNPROOT_COMMON_DEVICE_EXTENSION Common; 00061 // Informations about the device 00062 PPNPROOT_DEVICE DeviceInfo; 00063 } PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION; 00064 00065 /* Physical Device Object device extension for the Root bus device object */ 00066 typedef struct _PNPROOT_FDO_DEVICE_EXTENSION 00067 { 00068 // Common device data 00069 PNPROOT_COMMON_DEVICE_EXTENSION Common; 00070 // Lower device object 00071 PDEVICE_OBJECT Ldo; 00072 // Current state of the driver 00073 PNPROOT_DEVICE_STATE State; 00074 // Namespace device list 00075 LIST_ENTRY DeviceListHead; 00076 // Number of (not removed) devices in device list 00077 ULONG DeviceListCount; 00078 // Lock for namespace device list 00079 KGUARDED_MUTEX DeviceListLock; 00080 } PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION; 00081 00082 typedef struct _BUFFER 00083 { 00084 PVOID *Data; 00085 PULONG Length; 00086 } BUFFER, *PBUFFER; 00087 00088 static PDEVICE_OBJECT PnpRootDeviceObject = NULL; 00089 00090 /* FUNCTIONS *****************************************************************/ 00091 00092 static NTSTATUS 00093 LocateChildDevice( 00094 IN PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension, 00095 IN PCWSTR DeviceId, 00096 IN PCWSTR InstanceId, 00097 OUT PPNPROOT_DEVICE* ChildDevice) 00098 { 00099 PPNPROOT_DEVICE Device; 00100 UNICODE_STRING DeviceIdU, InstanceIdU; 00101 PLIST_ENTRY NextEntry; 00102 00103 /* Initialize the strings to compare */ 00104 RtlInitUnicodeString(&DeviceIdU, DeviceId); 00105 RtlInitUnicodeString(&InstanceIdU, InstanceId); 00106 00107 /* Start looping */ 00108 for (NextEntry = DeviceExtension->DeviceListHead.Flink; 00109 NextEntry != &DeviceExtension->DeviceListHead; 00110 NextEntry = NextEntry->Flink) 00111 { 00112 /* Get the entry */ 00113 Device = CONTAINING_RECORD(NextEntry, PNPROOT_DEVICE, ListEntry); 00114 00115 /* See if the strings match */ 00116 if (RtlEqualUnicodeString(&DeviceIdU, &Device->DeviceID, TRUE) && 00117 RtlEqualUnicodeString(&InstanceIdU, &Device->InstanceID, TRUE)) 00118 { 00119 /* They do, so set the pointer and return success */ 00120 *ChildDevice = Device; 00121 return STATUS_SUCCESS; 00122 } 00123 } 00124 00125 /* No device found */ 00126 return STATUS_NO_SUCH_DEVICE; 00127 } 00128 00129 NTSTATUS 00130 PnpRootRegisterDevice( 00131 IN PDEVICE_OBJECT DeviceObject) 00132 { 00133 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension = PnpRootDeviceObject->DeviceExtension; 00134 PPNPROOT_DEVICE Device; 00135 PDEVICE_NODE DeviceNode; 00136 PWSTR InstancePath; 00137 UNICODE_STRING InstancePathCopy; 00138 00139 Device = ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT); 00140 if (!Device) return STATUS_NO_MEMORY; 00141 00142 DeviceNode = IopGetDeviceNode(DeviceObject); 00143 if (!RtlCreateUnicodeString(&InstancePathCopy, DeviceNode->InstancePath.Buffer)) 00144 { 00145 ExFreePoolWithTag(Device, TAG_PNP_ROOT); 00146 return STATUS_NO_MEMORY; 00147 } 00148 00149 InstancePath = wcsrchr(InstancePathCopy.Buffer, L'\\'); 00150 ASSERT(InstancePath); 00151 00152 if (!RtlCreateUnicodeString(&Device->InstanceID, InstancePath + 1)) 00153 { 00154 RtlFreeUnicodeString(&InstancePathCopy); 00155 ExFreePoolWithTag(Device, TAG_PNP_ROOT); 00156 return STATUS_NO_MEMORY; 00157 } 00158 00159 InstancePath[0] = UNICODE_NULL; 00160 00161 if (!RtlCreateUnicodeString(&Device->DeviceID, InstancePathCopy.Buffer)) 00162 { 00163 RtlFreeUnicodeString(&InstancePathCopy); 00164 RtlFreeUnicodeString(&Device->InstanceID); 00165 ExFreePoolWithTag(Device, TAG_PNP_ROOT); 00166 return STATUS_NO_MEMORY; 00167 } 00168 00169 InstancePath[0] = L'\\'; 00170 00171 Device->Pdo = DeviceObject; 00172 00173 KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock); 00174 InsertTailList(&DeviceExtension->DeviceListHead, 00175 &Device->ListEntry); 00176 DeviceExtension->DeviceListCount++; 00177 KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock); 00178 00179 RtlFreeUnicodeString(&InstancePathCopy); 00180 00181 return STATUS_SUCCESS; 00182 } 00183 00184 /* Creates a new PnP device for a legacy driver */ 00185 NTSTATUS 00186 PnpRootCreateDevice( 00187 IN PUNICODE_STRING ServiceName, 00188 IN OPTIONAL PDRIVER_OBJECT DriverObject, 00189 OUT PDEVICE_OBJECT *PhysicalDeviceObject, 00190 OUT OPTIONAL PUNICODE_STRING FullInstancePath) 00191 { 00192 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; 00193 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension; 00194 WCHAR DevicePath[MAX_PATH + 1]; 00195 WCHAR InstancePath[5]; 00196 PPNPROOT_DEVICE Device = NULL; 00197 NTSTATUS Status; 00198 UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\\"); 00199 ULONG NextInstance; 00200 UNICODE_STRING EnumKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM); 00201 HANDLE EnumHandle, DeviceKeyHandle = INVALID_HANDLE_VALUE, InstanceKeyHandle; 00202 RTL_QUERY_REGISTRY_TABLE QueryTable[2]; 00203 OBJECT_ATTRIBUTES ObjectAttributes; 00204 00205 DeviceExtension = PnpRootDeviceObject->DeviceExtension; 00206 KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock); 00207 00208 DPRINT("Creating a PnP root device for service '%wZ'\n", ServiceName); 00209 00210 _snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\\%wZ", REGSTR_KEY_ROOTENUM, ServiceName); 00211 00212 /* Initialize a PNPROOT_DEVICE structure */ 00213 Device = ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT); 00214 if (!Device) 00215 { 00216 DPRINT("ExAllocatePoolWithTag() failed\n"); 00217 Status = STATUS_NO_MEMORY; 00218 goto cleanup; 00219 } 00220 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE)); 00221 if (!RtlCreateUnicodeString(&Device->DeviceID, DevicePath)) 00222 { 00223 Status = STATUS_NO_MEMORY; 00224 goto cleanup; 00225 } 00226 00227 Status = IopOpenRegistryKeyEx(&EnumHandle, NULL, &EnumKeyName, KEY_READ); 00228 if (NT_SUCCESS(Status)) 00229 { 00230 InitializeObjectAttributes(&ObjectAttributes, &Device->DeviceID, OBJ_CASE_INSENSITIVE, EnumHandle, NULL); 00231 Status = ZwCreateKey(&DeviceKeyHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); 00232 ZwClose(EnumHandle); 00233 } 00234 00235 if (!NT_SUCCESS(Status)) 00236 { 00237 DPRINT1("Failed to open registry key\n"); 00238 goto cleanup; 00239 } 00240 00241 tryagain: 00242 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 00243 QueryTable[0].Name = L"NextInstance"; 00244 QueryTable[0].EntryContext = &NextInstance; 00245 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; 00246 00247 Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, 00248 (PWSTR)DeviceKeyHandle, 00249 QueryTable, 00250 NULL, 00251 NULL); 00252 if (!NT_SUCCESS(Status)) 00253 { 00254 for (NextInstance = 0; NextInstance <= 9999; NextInstance++) 00255 { 00256 _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", NextInstance); 00257 Status = LocateChildDevice(DeviceExtension, DevicePath, InstancePath, &Device); 00258 if (Status == STATUS_NO_SUCH_DEVICE) 00259 break; 00260 } 00261 00262 if (NextInstance > 9999) 00263 { 00264 DPRINT1("Too many legacy devices reported for service '%wZ'\n", ServiceName); 00265 Status = STATUS_INSUFFICIENT_RESOURCES; 00266 goto cleanup; 00267 } 00268 } 00269 00270 _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu", NextInstance); 00271 Status = LocateChildDevice(DeviceExtension, DevicePath, InstancePath, &Device); 00272 if (Status != STATUS_NO_SUCH_DEVICE || NextInstance > 9999) 00273 { 00274 DPRINT1("NextInstance value is corrupt! (%d)\n", NextInstance); 00275 RtlDeleteRegistryValue(RTL_REGISTRY_HANDLE, 00276 (PWSTR)DeviceKeyHandle, 00277 L"NextInstance"); 00278 goto tryagain; 00279 } 00280 00281 NextInstance++; 00282 Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE, 00283 (PWSTR)DeviceKeyHandle, 00284 L"NextInstance", 00285 REG_DWORD, 00286 &NextInstance, 00287 sizeof(NextInstance)); 00288 if (!NT_SUCCESS(Status)) 00289 { 00290 DPRINT1("Failed to write new NextInstance value! (0x%x)\n", Status); 00291 goto cleanup; 00292 } 00293 00294 if (!RtlCreateUnicodeString(&Device->InstanceID, InstancePath)) 00295 { 00296 Status = STATUS_NO_MEMORY; 00297 goto cleanup; 00298 } 00299 00300 /* Finish creating the instance path in the registry */ 00301 InitializeObjectAttributes(&ObjectAttributes, &Device->InstanceID, OBJ_CASE_INSENSITIVE, DeviceKeyHandle, NULL); 00302 Status = ZwCreateKey(&InstanceKeyHandle, KEY_QUERY_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL); 00303 if (NT_SUCCESS(Status)) 00304 { 00305 DPRINT1("Failed to create instance path (0x%x)\n", Status); 00306 goto cleanup; 00307 } 00308 00309 /* Just close the handle */ 00310 ZwClose(InstanceKeyHandle); 00311 00312 if (FullInstancePath) 00313 { 00314 FullInstancePath->MaximumLength = Device->DeviceID.Length + PathSep.Length + Device->InstanceID.Length; 00315 FullInstancePath->Length = 0; 00316 FullInstancePath->Buffer = ExAllocatePool(PagedPool, FullInstancePath->MaximumLength); 00317 if (!FullInstancePath->Buffer) 00318 { 00319 Status = STATUS_NO_MEMORY; 00320 goto cleanup; 00321 } 00322 00323 RtlAppendUnicodeStringToString(FullInstancePath, &Device->DeviceID); 00324 RtlAppendUnicodeStringToString(FullInstancePath, &PathSep); 00325 RtlAppendUnicodeStringToString(FullInstancePath, &Device->InstanceID); 00326 } 00327 00328 /* Initialize a device object */ 00329 Status = IoCreateDevice( 00330 DriverObject ? DriverObject : PnpRootDeviceObject->DriverObject, 00331 sizeof(PNPROOT_PDO_DEVICE_EXTENSION), 00332 NULL, 00333 FILE_DEVICE_CONTROLLER, 00334 FILE_AUTOGENERATED_DEVICE_NAME, 00335 FALSE, 00336 &Device->Pdo); 00337 if (!NT_SUCCESS(Status)) 00338 { 00339 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status); 00340 Status = STATUS_NO_MEMORY; 00341 goto cleanup; 00342 } 00343 00344 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension; 00345 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION)); 00346 PdoDeviceExtension->Common.IsFDO = FALSE; 00347 PdoDeviceExtension->DeviceInfo = Device; 00348 00349 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; 00350 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; 00351 00352 InsertTailList( 00353 &DeviceExtension->DeviceListHead, 00354 &Device->ListEntry); 00355 DeviceExtension->DeviceListCount++; 00356 00357 *PhysicalDeviceObject = Device->Pdo; 00358 DPRINT("Created PDO %p (%wZ\\%wZ)\n", *PhysicalDeviceObject, &Device->DeviceID, &Device->InstanceID); 00359 Device = NULL; 00360 Status = STATUS_SUCCESS; 00361 00362 cleanup: 00363 KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock); 00364 if (Device) 00365 { 00366 if (Device->Pdo) 00367 IoDeleteDevice(Device->Pdo); 00368 RtlFreeUnicodeString(&Device->DeviceID); 00369 RtlFreeUnicodeString(&Device->InstanceID); 00370 ExFreePoolWithTag(Device, TAG_PNP_ROOT); 00371 } 00372 if (DeviceKeyHandle != INVALID_HANDLE_VALUE) 00373 ZwClose(DeviceKeyHandle); 00374 return Status; 00375 } 00376 00377 static NTSTATUS NTAPI 00378 QueryStringCallback( 00379 IN PWSTR ValueName, 00380 IN ULONG ValueType, 00381 IN PVOID ValueData, 00382 IN ULONG ValueLength, 00383 IN PVOID Context, 00384 IN PVOID EntryContext) 00385 { 00386 PUNICODE_STRING Destination = (PUNICODE_STRING)EntryContext; 00387 UNICODE_STRING Source; 00388 00389 if (ValueType != REG_SZ || ValueLength == 0 || ValueLength % sizeof(WCHAR) != 0) 00390 { 00391 Destination->Length = 0; 00392 Destination->MaximumLength = 0; 00393 Destination->Buffer = NULL; 00394 return STATUS_SUCCESS; 00395 } 00396 00397 Source.MaximumLength = Source.Length = (USHORT)ValueLength; 00398 Source.Buffer = ValueData; 00399 00400 return RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &Source, Destination); 00401 } 00402 00403 static NTSTATUS NTAPI 00404 QueryBinaryValueCallback( 00405 IN PWSTR ValueName, 00406 IN ULONG ValueType, 00407 IN PVOID ValueData, 00408 IN ULONG ValueLength, 00409 IN PVOID Context, 00410 IN PVOID EntryContext) 00411 { 00412 PBUFFER Buffer = (PBUFFER)EntryContext; 00413 PVOID BinaryValue; 00414 00415 if (ValueLength == 0) 00416 { 00417 *Buffer->Data = NULL; 00418 return STATUS_SUCCESS; 00419 } 00420 00421 BinaryValue = ExAllocatePoolWithTag(PagedPool, ValueLength, TAG_PNP_ROOT); 00422 if (BinaryValue == NULL) 00423 return STATUS_NO_MEMORY; 00424 RtlCopyMemory(BinaryValue, ValueData, ValueLength); 00425 *Buffer->Data = BinaryValue; 00426 if (Buffer->Length) *Buffer->Length = ValueLength; 00427 return STATUS_SUCCESS; 00428 } 00429 00430 static NTSTATUS 00431 EnumerateDevices( 00432 IN PDEVICE_OBJECT DeviceObject) 00433 { 00434 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; 00435 PKEY_BASIC_INFORMATION KeyInfo = NULL, SubKeyInfo = NULL; 00436 UNICODE_STRING LegacyU = RTL_CONSTANT_STRING(L"LEGACY_"); 00437 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\" REGSTR_PATH_SYSTEMENUM L"\\" REGSTR_KEY_ROOTENUM); 00438 UNICODE_STRING SubKeyName; 00439 WCHAR DevicePath[MAX_PATH + 1]; 00440 RTL_QUERY_REGISTRY_TABLE QueryTable[4]; 00441 PPNPROOT_DEVICE Device = NULL; 00442 HANDLE KeyHandle = INVALID_HANDLE_VALUE; 00443 HANDLE SubKeyHandle = INVALID_HANDLE_VALUE; 00444 HANDLE DeviceKeyHandle = INVALID_HANDLE_VALUE; 00445 ULONG BufferSize; 00446 ULONG ResultSize; 00447 ULONG Index1, Index2; 00448 BUFFER Buffer1, Buffer2; 00449 NTSTATUS Status = STATUS_UNSUCCESSFUL; 00450 00451 DPRINT("EnumerateDevices(FDO %p)\n", DeviceObject); 00452 00453 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00454 KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock); 00455 00456 BufferSize = sizeof(KEY_BASIC_INFORMATION) + (MAX_PATH + 1) * sizeof(WCHAR); 00457 KeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT); 00458 if (!KeyInfo) 00459 { 00460 DPRINT("ExAllocatePoolWithTag() failed\n"); 00461 Status = STATUS_NO_MEMORY; 00462 goto cleanup; 00463 } 00464 SubKeyInfo = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_PNP_ROOT); 00465 if (!SubKeyInfo) 00466 { 00467 DPRINT("ExAllocatePoolWithTag() failed\n"); 00468 Status = STATUS_NO_MEMORY; 00469 goto cleanup; 00470 } 00471 00472 Status = IopOpenRegistryKeyEx(&KeyHandle, NULL, &KeyName, KEY_ENUMERATE_SUB_KEYS); 00473 if (!NT_SUCCESS(Status)) 00474 { 00475 DPRINT("IopOpenRegistryKeyEx(%wZ) failed with status 0x%08lx\n", &KeyName, Status); 00476 goto cleanup; 00477 } 00478 00479 /* Devices are sub-sub-keys of 'KeyName'. KeyName is already opened as 00480 * KeyHandle. We'll first do a first enumeration to have first level keys, 00481 * and an inner one to have the real devices list. 00482 */ 00483 Index1 = 0; 00484 while (TRUE) 00485 { 00486 Status = ZwEnumerateKey( 00487 KeyHandle, 00488 Index1, 00489 KeyBasicInformation, 00490 KeyInfo, 00491 BufferSize, 00492 &ResultSize); 00493 if (Status == STATUS_NO_MORE_ENTRIES) 00494 { 00495 Status = STATUS_SUCCESS; 00496 break; 00497 } 00498 else if (!NT_SUCCESS(Status)) 00499 { 00500 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); 00501 goto cleanup; 00502 } 00503 00504 /* Terminate the string */ 00505 KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = 0; 00506 00507 /* Check if it is a legacy driver */ 00508 RtlInitUnicodeString(&SubKeyName, KeyInfo->Name); 00509 if (RtlPrefixUnicodeString(&LegacyU, &SubKeyName, FALSE)) 00510 { 00511 DPRINT("Ignoring legacy driver '%wZ'\n", &SubKeyName); 00512 Index1++; 00513 continue; 00514 } 00515 00516 /* Open the key */ 00517 Status = IopOpenRegistryKeyEx(&SubKeyHandle, KeyHandle, &SubKeyName, KEY_ENUMERATE_SUB_KEYS); 00518 if (!NT_SUCCESS(Status)) 00519 { 00520 DPRINT("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status); 00521 break; 00522 } 00523 00524 /* Enumerate the sub-keys */ 00525 Index2 = 0; 00526 while (TRUE) 00527 { 00528 Status = ZwEnumerateKey( 00529 SubKeyHandle, 00530 Index2, 00531 KeyBasicInformation, 00532 SubKeyInfo, 00533 BufferSize, 00534 &ResultSize); 00535 if (Status == STATUS_NO_MORE_ENTRIES) 00536 break; 00537 else if (!NT_SUCCESS(Status)) 00538 { 00539 DPRINT("ZwEnumerateKey() failed with status 0x%08lx\n", Status); 00540 break; 00541 } 00542 00543 /* Terminate the string */ 00544 SubKeyInfo->Name[SubKeyInfo->NameLength / sizeof(WCHAR)] = 0; 00545 00546 _snwprintf( 00547 DevicePath, 00548 sizeof(DevicePath) / sizeof(WCHAR), 00549 L"%s\\%s", REGSTR_KEY_ROOTENUM, KeyInfo->Name); 00550 DPRINT("Found device %S\\%s!\n", DevicePath, SubKeyInfo->Name); 00551 if (LocateChildDevice(DeviceExtension, DevicePath, SubKeyInfo->Name, &Device) == STATUS_NO_SUCH_DEVICE) 00552 { 00553 /* Create a PPNPROOT_DEVICE object, and add if in the list of known devices */ 00554 Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT); 00555 if (!Device) 00556 { 00557 DPRINT("ExAllocatePoolWithTag() failed\n"); 00558 Status = STATUS_NO_MEMORY; 00559 goto cleanup; 00560 } 00561 RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE)); 00562 00563 /* Fill device ID and instance ID */ 00564 if (!RtlCreateUnicodeString(&Device->DeviceID, DevicePath)) 00565 { 00566 DPRINT1("RtlCreateUnicodeString() failed\n"); 00567 Status = STATUS_NO_MEMORY; 00568 goto cleanup; 00569 } 00570 00571 if (!RtlCreateUnicodeString(&Device->InstanceID, SubKeyInfo->Name)) 00572 { 00573 DPRINT1("RtlCreateUnicodeString() failed\n"); 00574 Status = STATUS_NO_MEMORY; 00575 goto cleanup; 00576 } 00577 00578 /* Open registry key to fill other informations */ 00579 Status = IopOpenRegistryKeyEx(&DeviceKeyHandle, SubKeyHandle, &Device->InstanceID, KEY_READ); 00580 if (!NT_SUCCESS(Status)) 00581 { 00582 DPRINT1("IopOpenRegistryKeyEx() failed with status 0x%08lx\n", Status); 00583 break; 00584 } 00585 00586 /* Fill information from the device instance key */ 00587 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 00588 QueryTable[0].QueryRoutine = QueryStringCallback; 00589 QueryTable[0].Name = L"DeviceDesc"; 00590 QueryTable[0].EntryContext = &Device->DeviceDescription; 00591 00592 RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, 00593 (PCWSTR)DeviceKeyHandle, 00594 QueryTable, 00595 NULL, 00596 NULL); 00597 00598 /* Fill information from the LogConf subkey */ 00599 Buffer1.Data = (PVOID *)&Device->ResourceRequirementsList; 00600 Buffer1.Length = NULL; 00601 Buffer2.Data = (PVOID *)&Device->ResourceList; 00602 Buffer2.Length = &Device->ResourceListSize; 00603 RtlZeroMemory(QueryTable, sizeof(QueryTable)); 00604 QueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY; 00605 QueryTable[0].Name = L"LogConf"; 00606 QueryTable[1].QueryRoutine = QueryBinaryValueCallback; 00607 QueryTable[1].Name = L"BasicConfigVector"; 00608 QueryTable[1].EntryContext = &Buffer1; 00609 QueryTable[2].QueryRoutine = QueryBinaryValueCallback; 00610 QueryTable[2].Name = L"BootConfig"; 00611 QueryTable[2].EntryContext = &Buffer2; 00612 00613 if (!NT_SUCCESS(RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, 00614 (PCWSTR)DeviceKeyHandle, 00615 QueryTable, 00616 NULL, 00617 NULL))) 00618 { 00619 /* Non-fatal error */ 00620 DPRINT1("Failed to read the LogConf key for %S\\%S\n", DevicePath, SubKeyInfo->Name); 00621 } 00622 00623 ZwClose(DeviceKeyHandle); 00624 DeviceKeyHandle = INVALID_HANDLE_VALUE; 00625 00626 /* Insert the newly created device into the list */ 00627 InsertTailList( 00628 &DeviceExtension->DeviceListHead, 00629 &Device->ListEntry); 00630 DeviceExtension->DeviceListCount++; 00631 } 00632 Device = NULL; 00633 00634 Index2++; 00635 } 00636 00637 ZwClose(SubKeyHandle); 00638 SubKeyHandle = INVALID_HANDLE_VALUE; 00639 Index1++; 00640 } 00641 00642 cleanup: 00643 if (Device) 00644 { 00645 /* We have a device that has not been added to device list. We need to clean it up */ 00646 /* FIXME */ 00647 ExFreePoolWithTag(Device, TAG_PNP_ROOT); 00648 } 00649 if (DeviceKeyHandle != INVALID_HANDLE_VALUE) 00650 ZwClose(DeviceKeyHandle); 00651 if (SubKeyHandle != INVALID_HANDLE_VALUE) 00652 ZwClose(SubKeyHandle); 00653 if (KeyHandle != INVALID_HANDLE_VALUE) 00654 ZwClose(KeyHandle); 00655 if (KeyInfo) 00656 ExFreePoolWithTag(KeyInfo, TAG_PNP_ROOT); 00657 if (SubKeyInfo) 00658 ExFreePoolWithTag(SubKeyInfo, TAG_PNP_ROOT); 00659 KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock); 00660 return Status; 00661 } 00662 00663 /* FUNCTION: Handle IRP_MN_QUERY_DEVICE_RELATIONS IRPs for the root bus device object 00664 * ARGUMENTS: 00665 * DeviceObject = Pointer to functional device object of the root bus driver 00666 * Irp = Pointer to IRP that should be handled 00667 * RETURNS: 00668 * Status 00669 */ 00670 static NTSTATUS 00671 PnpRootQueryDeviceRelations( 00672 IN PDEVICE_OBJECT DeviceObject, 00673 IN PIRP Irp) 00674 { 00675 PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension; 00676 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; 00677 PDEVICE_RELATIONS Relations = NULL, OtherRelations = (PDEVICE_RELATIONS)Irp->IoStatus.Information; 00678 PPNPROOT_DEVICE Device = NULL; 00679 ULONG Size; 00680 NTSTATUS Status; 00681 PLIST_ENTRY NextEntry; 00682 00683 DPRINT("PnpRootQueryDeviceRelations(FDO %p, Irp %p)\n", DeviceObject, Irp); 00684 00685 Status = EnumerateDevices(DeviceObject); 00686 if (!NT_SUCCESS(Status)) 00687 { 00688 DPRINT("EnumerateDevices() failed with status 0x%08lx\n", Status); 00689 return Status; 00690 } 00691 00692 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00693 00694 Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) + sizeof(PDEVICE_OBJECT) * DeviceExtension->DeviceListCount; 00695 if (OtherRelations) 00696 { 00697 /* Another bus driver has already created a DEVICE_RELATIONS 00698 * structure so we must merge this structure with our own */ 00699 00700 Size += sizeof(PDEVICE_OBJECT) * OtherRelations->Count; 00701 } 00702 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size); 00703 if (!Relations) 00704 { 00705 DPRINT("ExAllocatePoolWithTag() failed\n"); 00706 Status = STATUS_NO_MEMORY; 00707 goto cleanup; 00708 } 00709 RtlZeroMemory(Relations, Size); 00710 if (OtherRelations) 00711 { 00712 Relations->Count = OtherRelations->Count; 00713 RtlCopyMemory(Relations->Objects, OtherRelations->Objects, sizeof(PDEVICE_OBJECT) * OtherRelations->Count); 00714 } 00715 00716 KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock); 00717 00718 /* Start looping */ 00719 for (NextEntry = DeviceExtension->DeviceListHead.Flink; 00720 NextEntry != &DeviceExtension->DeviceListHead; 00721 NextEntry = NextEntry->Flink) 00722 { 00723 /* Get the entry */ 00724 Device = CONTAINING_RECORD(NextEntry, PNPROOT_DEVICE, ListEntry); 00725 00726 if (!Device->Pdo) 00727 { 00728 /* Create a physical device object for the 00729 * device as it does not already have one */ 00730 Status = IoCreateDevice( 00731 DeviceObject->DriverObject, 00732 sizeof(PNPROOT_PDO_DEVICE_EXTENSION), 00733 NULL, 00734 FILE_DEVICE_CONTROLLER, 00735 FILE_AUTOGENERATED_DEVICE_NAME, 00736 FALSE, 00737 &Device->Pdo); 00738 if (!NT_SUCCESS(Status)) 00739 { 00740 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status); 00741 break; 00742 } 00743 00744 PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension; 00745 RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION)); 00746 PdoDeviceExtension->Common.IsFDO = FALSE; 00747 PdoDeviceExtension->DeviceInfo = Device; 00748 00749 Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE; 00750 Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING; 00751 } 00752 00753 /* Reference the physical device object. The PnP manager 00754 will dereference it again when it is no longer needed */ 00755 ObReferenceObject(Device->Pdo); 00756 00757 Relations->Objects[Relations->Count++] = Device->Pdo; 00758 } 00759 KeReleaseGuardedMutex(&DeviceExtension->DeviceListLock); 00760 00761 Irp->IoStatus.Information = (ULONG_PTR)Relations; 00762 00763 cleanup: 00764 if (!NT_SUCCESS(Status)) 00765 { 00766 if (OtherRelations) 00767 ExFreePool(OtherRelations); 00768 if (Relations) 00769 ExFreePool(Relations); 00770 if (Device && Device->Pdo) 00771 { 00772 IoDeleteDevice(Device->Pdo); 00773 Device->Pdo = NULL; 00774 } 00775 } 00776 00777 return Status; 00778 } 00779 00780 /* 00781 * FUNCTION: Handle Plug and Play IRPs for the root bus device object 00782 * ARGUMENTS: 00783 * DeviceObject = Pointer to functional device object of the root bus driver 00784 * Irp = Pointer to IRP that should be handled 00785 * RETURNS: 00786 * Status 00787 */ 00788 static NTSTATUS 00789 PnpRootFdoPnpControl( 00790 IN PDEVICE_OBJECT DeviceObject, 00791 IN PIRP Irp) 00792 { 00793 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; 00794 PIO_STACK_LOCATION IrpSp; 00795 NTSTATUS Status; 00796 00797 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00798 Status = Irp->IoStatus.Status; 00799 IrpSp = IoGetCurrentIrpStackLocation(Irp); 00800 00801 switch (IrpSp->MinorFunction) 00802 { 00803 case IRP_MN_QUERY_DEVICE_RELATIONS: 00804 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS\n"); 00805 Status = PnpRootQueryDeviceRelations(DeviceObject, Irp); 00806 break; 00807 00808 case IRP_MN_START_DEVICE: 00809 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); 00810 if (!IoForwardIrpSynchronously(DeviceExtension->Ldo, Irp)) 00811 Status = STATUS_UNSUCCESSFUL; 00812 else 00813 { 00814 Status = Irp->IoStatus.Status; 00815 if (NT_SUCCESS(Status)) 00816 DeviceExtension->State = dsStarted; 00817 } 00818 00819 Irp->IoStatus.Status = Status; 00820 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00821 return Status; 00822 00823 case IRP_MN_STOP_DEVICE: 00824 DPRINT("IRP_MJ_PNP / IRP_MN_STOP_DEVICE\n"); 00825 /* Root device cannot be stopped */ 00826 Irp->IoStatus.Status = Status = STATUS_INVALID_DEVICE_REQUEST; 00827 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00828 return Status; 00829 00830 default: 00831 DPRINT("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction); 00832 break; 00833 } 00834 00835 if (Status != STATUS_PENDING) 00836 { 00837 Irp->IoStatus.Status = Status; 00838 IoCompleteRequest(Irp, IO_NO_INCREMENT); 00839 } 00840 00841 return Status; 00842 } 00843 00844 static NTSTATUS 00845 PdoQueryDeviceRelations( 00846 IN PDEVICE_OBJECT DeviceObject, 00847 IN PIRP Irp, 00848 IN PIO_STACK_LOCATION IrpSp) 00849 { 00850 PDEVICE_RELATIONS Relations; 00851 NTSTATUS Status = Irp->IoStatus.Status; 00852 00853 if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) 00854 return Status; 00855 00856 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n"); 00857 Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS)); 00858 if (!Relations) 00859 { 00860 DPRINT("ExAllocatePoolWithTag() failed\n"); 00861 Status = STATUS_NO_MEMORY; 00862 } 00863 else 00864 { 00865 ObReferenceObject(DeviceObject); 00866 Relations->Count = 1; 00867 Relations->Objects[0] = DeviceObject; 00868 Status = STATUS_SUCCESS; 00869 Irp->IoStatus.Information = (ULONG_PTR)Relations; 00870 } 00871 00872 return Status; 00873 } 00874 00875 static NTSTATUS 00876 PdoQueryCapabilities( 00877 IN PDEVICE_OBJECT DeviceObject, 00878 IN PIRP Irp, 00879 IN PIO_STACK_LOCATION IrpSp) 00880 { 00881 PDEVICE_CAPABILITIES DeviceCapabilities; 00882 00883 DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities; 00884 00885 if (DeviceCapabilities->Version != 1) 00886 return STATUS_REVISION_MISMATCH; 00887 00888 DeviceCapabilities->UniqueID = TRUE; 00889 /* FIXME: Fill other fields */ 00890 00891 return STATUS_SUCCESS; 00892 } 00893 00894 static NTSTATUS 00895 PdoQueryResources( 00896 IN PDEVICE_OBJECT DeviceObject, 00897 IN PIRP Irp, 00898 IN PIO_STACK_LOCATION IrpSp) 00899 { 00900 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension; 00901 PCM_RESOURCE_LIST ResourceList; 00902 00903 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00904 00905 if (DeviceExtension->DeviceInfo->ResourceList) 00906 { 00907 /* Copy existing resource requirement list */ 00908 ResourceList = ExAllocatePool( 00909 PagedPool, 00910 DeviceExtension->DeviceInfo->ResourceListSize); 00911 if (!ResourceList) 00912 return STATUS_NO_MEMORY; 00913 00914 RtlCopyMemory( 00915 ResourceList, 00916 DeviceExtension->DeviceInfo->ResourceList, 00917 DeviceExtension->DeviceInfo->ResourceListSize); 00918 00919 Irp->IoStatus.Information = (ULONG_PTR)ResourceList; 00920 00921 return STATUS_SUCCESS; 00922 } 00923 else 00924 { 00925 /* No resources so just return without changing the status */ 00926 return Irp->IoStatus.Status; 00927 } 00928 } 00929 00930 static NTSTATUS 00931 PdoQueryResourceRequirements( 00932 IN PDEVICE_OBJECT DeviceObject, 00933 IN PIRP Irp, 00934 IN PIO_STACK_LOCATION IrpSp) 00935 { 00936 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension; 00937 PIO_RESOURCE_REQUIREMENTS_LIST ResourceList; 00938 00939 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00940 00941 if (DeviceExtension->DeviceInfo->ResourceRequirementsList) 00942 { 00943 /* Copy existing resource requirement list */ 00944 ResourceList = ExAllocatePool(PagedPool, DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize); 00945 if (!ResourceList) 00946 return STATUS_NO_MEMORY; 00947 00948 RtlCopyMemory( 00949 ResourceList, 00950 DeviceExtension->DeviceInfo->ResourceRequirementsList, 00951 DeviceExtension->DeviceInfo->ResourceRequirementsList->ListSize); 00952 00953 Irp->IoStatus.Information = (ULONG_PTR)ResourceList; 00954 00955 return STATUS_SUCCESS; 00956 } 00957 else 00958 { 00959 /* No resource requirements so just return without changing the status */ 00960 return Irp->IoStatus.Status; 00961 } 00962 } 00963 00964 static NTSTATUS 00965 PdoQueryDeviceText( 00966 IN PDEVICE_OBJECT DeviceObject, 00967 IN PIRP Irp, 00968 IN PIO_STACK_LOCATION IrpSp) 00969 { 00970 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension; 00971 DEVICE_TEXT_TYPE DeviceTextType; 00972 NTSTATUS Status = Irp->IoStatus.Status; 00973 00974 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 00975 DeviceTextType = IrpSp->Parameters.QueryDeviceText.DeviceTextType; 00976 00977 switch (DeviceTextType) 00978 { 00979 case DeviceTextDescription: 00980 { 00981 UNICODE_STRING String; 00982 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextDescription\n"); 00983 00984 if (DeviceExtension->DeviceInfo->DeviceDescription.Buffer != NULL) 00985 { 00986 Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 00987 &DeviceExtension->DeviceInfo->DeviceDescription, 00988 &String); 00989 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer; 00990 } 00991 break; 00992 } 00993 00994 case DeviceTextLocationInformation: 00995 { 00996 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / DeviceTextLocationInformation\n"); 00997 break; 00998 } 00999 01000 default: 01001 { 01002 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown query id type 0x%lx\n", DeviceTextType); 01003 } 01004 } 01005 01006 return Status; 01007 } 01008 01009 static NTSTATUS 01010 PdoQueryId( 01011 IN PDEVICE_OBJECT DeviceObject, 01012 IN PIRP Irp, 01013 IN PIO_STACK_LOCATION IrpSp) 01014 { 01015 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension; 01016 BUS_QUERY_ID_TYPE IdType; 01017 NTSTATUS Status = Irp->IoStatus.Status; 01018 01019 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 01020 IdType = IrpSp->Parameters.QueryId.IdType; 01021 01022 switch (IdType) 01023 { 01024 case BusQueryDeviceID: 01025 { 01026 UNICODE_STRING String; 01027 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n"); 01028 01029 Status = RtlDuplicateUnicodeString( 01030 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 01031 &DeviceExtension->DeviceInfo->DeviceID, 01032 &String); 01033 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer; 01034 break; 01035 } 01036 01037 case BusQueryHardwareIDs: 01038 case BusQueryCompatibleIDs: 01039 { 01040 /* Optional, do nothing */ 01041 break; 01042 } 01043 01044 case BusQueryInstanceID: 01045 { 01046 UNICODE_STRING String; 01047 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n"); 01048 01049 Status = RtlDuplicateUnicodeString( 01050 RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, 01051 &DeviceExtension->DeviceInfo->InstanceID, 01052 &String); 01053 Irp->IoStatus.Information = (ULONG_PTR)String.Buffer; 01054 break; 01055 } 01056 01057 default: 01058 { 01059 DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType); 01060 } 01061 } 01062 01063 return Status; 01064 } 01065 01066 static NTSTATUS 01067 PdoQueryBusInformation( 01068 IN PDEVICE_OBJECT DeviceObject, 01069 IN PIRP Irp, 01070 IN PIO_STACK_LOCATION IrpSp) 01071 { 01072 PPNP_BUS_INFORMATION BusInfo; 01073 NTSTATUS Status; 01074 01075 BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION), TAG_PNP_ROOT); 01076 if (!BusInfo) 01077 Status = STATUS_NO_MEMORY; 01078 else 01079 { 01080 RtlCopyMemory( 01081 &BusInfo->BusTypeGuid, 01082 &GUID_BUS_TYPE_INTERNAL, 01083 sizeof(BusInfo->BusTypeGuid)); 01084 BusInfo->LegacyBusType = PNPBus; 01085 /* We're the only root bus enumerator on the computer */ 01086 BusInfo->BusNumber = 0; 01087 Irp->IoStatus.Information = (ULONG_PTR)BusInfo; 01088 Status = STATUS_SUCCESS; 01089 } 01090 01091 return Status; 01092 } 01093 01094 /* 01095 * FUNCTION: Handle Plug and Play IRPs for the child device 01096 * ARGUMENTS: 01097 * DeviceObject = Pointer to physical device object of the child device 01098 * Irp = Pointer to IRP that should be handled 01099 * RETURNS: 01100 * Status 01101 */ 01102 static NTSTATUS 01103 PnpRootPdoPnpControl( 01104 IN PDEVICE_OBJECT DeviceObject, 01105 IN PIRP Irp) 01106 { 01107 PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension; 01108 PPNPROOT_FDO_DEVICE_EXTENSION FdoDeviceExtension; 01109 PIO_STACK_LOCATION IrpSp; 01110 NTSTATUS Status; 01111 01112 DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 01113 FdoDeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension; 01114 Status = Irp->IoStatus.Status; 01115 IrpSp = IoGetCurrentIrpStackLocation(Irp); 01116 01117 switch (IrpSp->MinorFunction) 01118 { 01119 case IRP_MN_START_DEVICE: /* 0x00 */ 01120 DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n"); 01121 Status = STATUS_SUCCESS; 01122 break; 01123 01124 case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */ 01125 Status = PdoQueryDeviceRelations(DeviceObject, Irp, IrpSp); 01126 break; 01127 01128 case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */ 01129 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n"); 01130 Status = PdoQueryCapabilities(DeviceObject, Irp, IrpSp); 01131 break; 01132 01133 case IRP_MN_QUERY_RESOURCES: /* 0x0a */ 01134 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCES\n"); 01135 Status = PdoQueryResources(DeviceObject, Irp, IrpSp); 01136 break; 01137 01138 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */ 01139 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); 01140 Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp); 01141 break; 01142 01143 case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */ 01144 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n"); 01145 Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp); 01146 break; 01147 01148 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */ 01149 DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n"); 01150 break; 01151 01152 case IRP_MN_REMOVE_DEVICE: 01153 /* Remove the device from the device list and decrement the device count*/ 01154 KeAcquireGuardedMutex(&FdoDeviceExtension->DeviceListLock); 01155 RemoveEntryList(&DeviceExtension->DeviceInfo->ListEntry); 01156 FdoDeviceExtension->DeviceListCount--; 01157 KeReleaseGuardedMutex(&FdoDeviceExtension->DeviceListLock); 01158 01159 /* Free some strings we created */ 01160 RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->DeviceDescription); 01161 RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->DeviceID); 01162 RtlFreeUnicodeString(&DeviceExtension->DeviceInfo->InstanceID); 01163 01164 /* Free the resource requirements list */ 01165 if (DeviceExtension->DeviceInfo->ResourceRequirementsList != NULL) 01166 ExFreePool(DeviceExtension->DeviceInfo->ResourceRequirementsList); 01167 01168 /* Free the boot resources list */ 01169 if (DeviceExtension->DeviceInfo->ResourceList != NULL) 01170 ExFreePool(DeviceExtension->DeviceInfo->ResourceList); 01171 01172 /* Free the device info */ 01173 ExFreePool(DeviceExtension->DeviceInfo); 01174 01175 /* Finally, delete the device object */ 01176 IoDeleteDevice(DeviceObject); 01177 01178 /* Return success */ 01179 Status = STATUS_SUCCESS; 01180 break; 01181 01182 case IRP_MN_QUERY_ID: /* 0x13 */ 01183 Status = PdoQueryId(DeviceObject, Irp, IrpSp); 01184 break; 01185 01186 case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */ 01187 DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n"); 01188 Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp); 01189 break; 01190 01191 default: 01192 DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", IrpSp->MinorFunction); 01193 break; 01194 } 01195 01196 if (Status != STATUS_PENDING) 01197 { 01198 Irp->IoStatus.Status = Status; 01199 IoCompleteRequest(Irp, IO_NO_INCREMENT); 01200 } 01201 01202 return Status; 01203 } 01204 01205 /* 01206 * FUNCTION: Handle Plug and Play IRPs 01207 * ARGUMENTS: 01208 * DeviceObject = Pointer to PDO or FDO 01209 * Irp = Pointer to IRP that should be handled 01210 * RETURNS: 01211 * Status 01212 */ 01213 static NTSTATUS NTAPI 01214 PnpRootPnpControl( 01215 IN PDEVICE_OBJECT DeviceObject, 01216 IN PIRP Irp) 01217 { 01218 PPNPROOT_COMMON_DEVICE_EXTENSION DeviceExtension; 01219 NTSTATUS Status; 01220 01221 DeviceExtension = (PPNPROOT_COMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 01222 01223 if (DeviceExtension->IsFDO) 01224 Status = PnpRootFdoPnpControl(DeviceObject, Irp); 01225 else 01226 Status = PnpRootPdoPnpControl(DeviceObject, Irp); 01227 01228 return Status; 01229 } 01230 01231 NTSTATUS 01232 NTAPI 01233 PnpRootAddDevice( 01234 IN PDRIVER_OBJECT DriverObject, 01235 IN PDEVICE_OBJECT PhysicalDeviceObject) 01236 { 01237 PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension; 01238 NTSTATUS Status; 01239 01240 DPRINT("PnpRootAddDevice(DriverObject %p, Pdo %p)\n", DriverObject, PhysicalDeviceObject); 01241 01242 if (!PhysicalDeviceObject) 01243 { 01244 DPRINT("PhysicalDeviceObject 0x%p\n", PhysicalDeviceObject); 01245 Status = STATUS_INSUFFICIENT_RESOURCES; 01246 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); 01247 } 01248 01249 Status = IoCreateDevice( 01250 DriverObject, 01251 sizeof(PNPROOT_FDO_DEVICE_EXTENSION), 01252 NULL, 01253 FILE_DEVICE_BUS_EXTENDER, 01254 FILE_DEVICE_SECURE_OPEN, 01255 TRUE, 01256 &PnpRootDeviceObject); 01257 if (!NT_SUCCESS(Status)) 01258 { 01259 DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status); 01260 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); 01261 } 01262 DPRINT("Created FDO %p\n", PnpRootDeviceObject); 01263 01264 DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension; 01265 RtlZeroMemory(DeviceExtension, sizeof(PNPROOT_FDO_DEVICE_EXTENSION)); 01266 01267 DeviceExtension->Common.IsFDO = TRUE; 01268 DeviceExtension->State = dsStopped; 01269 InitializeListHead(&DeviceExtension->DeviceListHead); 01270 DeviceExtension->DeviceListCount = 0; 01271 KeInitializeGuardedMutex(&DeviceExtension->DeviceListLock); 01272 01273 Status = IoAttachDeviceToDeviceStackSafe( 01274 PnpRootDeviceObject, 01275 PhysicalDeviceObject, 01276 &DeviceExtension->Ldo); 01277 if (!NT_SUCCESS(Status)) 01278 { 01279 DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status); 01280 KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); 01281 } 01282 01283 PnpRootDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 01284 01285 DPRINT("Done AddDevice()\n"); 01286 01287 return STATUS_SUCCESS; 01288 } 01289 01290 NTSTATUS NTAPI 01291 PnpRootDriverEntry( 01292 IN PDRIVER_OBJECT DriverObject, 01293 IN PUNICODE_STRING RegistryPath) 01294 { 01295 DPRINT("PnpRootDriverEntry(%p %wZ)\n", DriverObject, RegistryPath); 01296 01297 IopRootDriverObject = DriverObject; 01298 01299 DriverObject->DriverExtension->AddDevice = PnpRootAddDevice; 01300 01301 DriverObject->MajorFunction[IRP_MJ_PNP] = PnpRootPnpControl; 01302 //DriverObject->MajorFunction[IRP_MJ_POWER] = PnpRootPowerControl; 01303 01304 return STATUS_SUCCESS; 01305 } Generated on Sun May 27 2012 04:37:19 for ReactOS by
1.7.6.1
|