/* Loop to install all queued devices installations */ static ULONG NTAPI DeviceInstallThread(IN PVOID Parameter) { HINF hSetupInf = *(HINF*)Parameter; PSLIST_ENTRY ListEntry; DeviceInstallParams* Params; LARGE_INTEGER Timeout; for (;;) { ListEntry = RtlInterlockedPopEntrySList(&DeviceInstallListHead); if (ListEntry == NULL) { /* * The list is now empty, but there may be a new enumerated device * that is going to be added to the list soon. In order to avoid * setting the hNoPendingInstalls event to release it soon after, * we wait for maximum 1 second for no PnP enumeration event being * received before declaring that no pending installations are * taking place and setting the corresponding event. */ Timeout.QuadPart = -10000000LL; /* Wait for 1 second */ if (NtWaitForSingleObject(hDeviceInstallListNotEmpty, FALSE, &Timeout) == STATUS_TIMEOUT) { /* We timed out: set the event and do the actual wait */ NtSetEvent(hNoPendingInstalls, NULL); NtWaitForSingleObject(hDeviceInstallListNotEmpty, FALSE, NULL); } } else { NtResetEvent(hNoPendingInstalls, NULL); Params = CONTAINING_RECORD(ListEntry, DeviceInstallParams, ListEntry); InstallDevice(hSetupInf, hEnumKey, hServicesKey, Params->DeviceIds); RtlFreeHeap(ProcessHeap, 0, Params); } } return 0; }
NTSTATUS EventThread(IN LPVOID lpParameter) { UNICODE_STRING EnumU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum"); UNICODE_STRING ServicesU = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services"); PPLUGPLAY_EVENT_BLOCK PnpEvent; OBJECT_ATTRIBUTES ObjectAttributes; ULONG PnpEventSize; HINF hInf; HANDLE hEnum, hServices; NTSTATUS Status; hInf = *(HINF *)lpParameter; InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenKey(&hEnum, KEY_QUERY_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT1("NtOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU, Status); return Status; } InitializeObjectAttributes(&ObjectAttributes, &ServicesU, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtCreateKey(&hServices, KEY_ALL_ACCESS, &ObjectAttributes, 0, NULL, 0, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateKey('%wZ') failed with status 0x%08lx\n", &ServicesU, Status); NtClose(hEnum); return Status; } PnpEventSize = 0x1000; PnpEvent = (PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap, 0, PnpEventSize); if (PnpEvent == NULL) { NtClose(hEnum); NtClose(hServices); return STATUS_NO_MEMORY; } for (;;) { DPRINT("Calling NtGetPlugPlayEvent()\n"); /* Wait for the next pnp event */ Status = NtGetPlugPlayEvent(0, 0, PnpEvent, PnpEventSize); /* Resize the buffer for the PnP event if it's too small. */ if (Status == STATUS_BUFFER_TOO_SMALL) { PnpEventSize += 0x400; RtlFreeHeap(ProcessHeap, 0, PnpEvent); PnpEvent = (PPLUGPLAY_EVENT_BLOCK)RtlAllocateHeap(ProcessHeap, 0, PnpEventSize); if (PnpEvent == NULL) { NtClose(hEnum); NtClose(hServices); return STATUS_NO_MEMORY; } continue; } if (!NT_SUCCESS(Status)) { DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status); break; } /* Process the pnp event */ DPRINT("Received PnP Event\n"); if (IsEqualIID(&PnpEvent->EventGuid, (REFGUID)&GUID_DEVICE_ENUMERATED)) { DPRINT("Device arrival event: %S\n", PnpEvent->TargetDevice.DeviceIds); InstallDevice(hInf, hEnum, hServices, PnpEvent->TargetDevice.DeviceIds); } else { DPRINT("Unknown event\n"); } /* Dequeue the current pnp event and signal the next one */ NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0); } RtlFreeHeap(ProcessHeap, 0, PnpEvent); NtClose(hEnum); NtClose(hServices); return STATUS_SUCCESS; }