Author: cgutman
Date: Sat Apr 10 06:11:45 2010
New Revision: 46808
URL:
http://svn.reactos.org/svn/reactos?rev=46808&view=rev
Log:
[NTOSKRNL]
- Cache the next instance value in the the registry so we don't have to go searching
for an unused instance number every time we add a new device
Modified:
trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c
Modified: trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/pnpmgr/pnproot…
==============================================================================
--- trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/io/pnpmgr/pnproot.c [iso-8859-1] Sat Apr 10 06:11:45 2010
@@ -139,29 +139,19 @@
WCHAR InstancePath[5];
PPNPROOT_DEVICE Device = NULL;
NTSTATUS Status;
- ULONG i;
UNICODE_STRING PathSep = RTL_CONSTANT_STRING(L"\\");
+ ULONG NextInstance;
+ UNICODE_STRING EnumKeyName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\"
REGSTR_PATH_SYSTEMENUM);
+ HANDLE EnumHandle, DeviceKeyHandle = INVALID_HANDLE_VALUE;
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ OBJECT_ATTRIBUTES ObjectAttributes;
DeviceExtension = PnpRootDeviceObject->DeviceExtension;
KeAcquireGuardedMutex(&DeviceExtension->DeviceListLock);
DPRINT("Creating a PnP root device for service '%wZ'\n",
ServiceName);
- /* Search for a free instance ID */
_snwprintf(DevicePath, sizeof(DevicePath) / sizeof(WCHAR), L"%s\\%wZ",
REGSTR_KEY_ROOTENUM, ServiceName);
- for (i = 0; i < 9999; i++)
- {
- _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR),
L"%04lu", i);
- Status = LocateChildDevice(DeviceExtension, DevicePath, InstancePath,
&Device);
- if (Status == STATUS_NO_SUCH_DEVICE)
- break;
- }
- if (i == 9999)
- {
- DPRINT1("Too much legacy devices reported for service '%wZ'\n",
ServiceName);
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto cleanup;
- }
/* Initialize a PNPROOT_DEVICE structure */
Device = ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
@@ -177,6 +167,74 @@
Status = STATUS_NO_MEMORY;
goto cleanup;
}
+
+ Status = IopOpenRegistryKeyEx(&EnumHandle, NULL, &EnumKeyName, KEY_READ);
+ if (NT_SUCCESS(Status))
+ {
+ InitializeObjectAttributes(&ObjectAttributes, &Device->DeviceID,
OBJ_CASE_INSENSITIVE, EnumHandle, NULL);
+ Status = ZwCreateKey(&DeviceKeyHandle, KEY_SET_VALUE, &ObjectAttributes,
0, NULL, 0, NULL);
+ ZwClose(EnumHandle);
+ }
+
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to open registry key\n");
+ goto cleanup;
+ }
+
+tryagain:
+ RtlZeroMemory(QueryTable, sizeof(QueryTable));
+ QueryTable[0].Name = L"NextInstance";
+ QueryTable[0].EntryContext = &NextInstance;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE,
+ (PWSTR)DeviceKeyHandle,
+ QueryTable,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ for (NextInstance = 0; NextInstance <= 9999; NextInstance++)
+ {
+ _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR),
L"%04lu", NextInstance);
+ Status = LocateChildDevice(DeviceExtension, DevicePath, InstancePath,
&Device);
+ if (Status == STATUS_NO_SUCH_DEVICE)
+ break;
+ }
+
+ if (NextInstance > 9999)
+ {
+ DPRINT1("Too many legacy devices reported for service
'%wZ'\n", ServiceName);
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto cleanup;
+ }
+ }
+
+ _snwprintf(InstancePath, sizeof(InstancePath) / sizeof(WCHAR), L"%04lu",
NextInstance);
+ Status = LocateChildDevice(DeviceExtension, DevicePath, InstancePath, &Device);
+ if (Status != STATUS_NO_SUCH_DEVICE || NextInstance > 9999)
+ {
+ DPRINT1("NextInstance value is corrupt! (%d)\n", NextInstance);
+ RtlDeleteRegistryValue(RTL_REGISTRY_HANDLE,
+ (PWSTR)DeviceKeyHandle,
+ L"NextInstance");
+ goto tryagain;
+ }
+
+ NextInstance++;
+ Status = RtlWriteRegistryValue(RTL_REGISTRY_HANDLE,
+ (PWSTR)DeviceKeyHandle,
+ L"NextInstance",
+ REG_DWORD,
+ &NextInstance,
+ sizeof(NextInstance));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to write new NextInstance value! (0x%x)\n", Status);
+ goto cleanup;
+ }
+
if (!RtlCreateUnicodeString(&Device->InstanceID, InstancePath))
{
Status = STATUS_NO_MEMORY;
@@ -243,6 +301,8 @@
RtlFreeUnicodeString(&Device->InstanceID);
ExFreePoolWithTag(Device, TAG_PNP_ROOT);
}
+ if (DeviceKeyHandle != INVALID_HANDLE_VALUE)
+ ZwClose(DeviceKeyHandle);
return Status;
}