ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pnproot.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.