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; }
static ULONG NTAPI PnpEventThread(IN PVOID Parameter) { NTSTATUS Status; PPLUGPLAY_EVENT_BLOCK PnpEvent, NewPnpEvent; ULONG PnpEventSize; UNREFERENCED_PARAMETER(Parameter); PnpEventSize = 0x1000; PnpEvent = RtlAllocateHeap(ProcessHeap, 0, PnpEventSize); if (PnpEvent == NULL) { Status = STATUS_NO_MEMORY; goto Quit; } 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; NewPnpEvent = RtlReAllocateHeap(ProcessHeap, 0, PnpEvent, PnpEventSize); if (NewPnpEvent == NULL) { Status = STATUS_NO_MEMORY; goto Quit; } PnpEvent = NewPnpEvent; continue; } if (!NT_SUCCESS(Status)) { DPRINT1("NtGetPlugPlayEvent() failed (Status 0x%08lx)\n", Status); goto Quit; } /* Process the PnP event */ DPRINT("Received PnP Event\n"); if (IsEqualGUID(&PnpEvent->EventGuid, &GUID_DEVICE_ENUMERATED)) { DeviceInstallParams* Params; ULONG len; ULONG DeviceIdLength; DPRINT("Device enumerated event: %S\n", PnpEvent->TargetDevice.DeviceIds); DeviceIdLength = wcslen(PnpEvent->TargetDevice.DeviceIds); if (DeviceIdLength) { /* Queue device install (will be dequeued by DeviceInstallThread) */ len = FIELD_OFFSET(DeviceInstallParams, DeviceIds) + (DeviceIdLength + 1) * sizeof(WCHAR); Params = RtlAllocateHeap(ProcessHeap, 0, len); if (Params) { wcscpy(Params->DeviceIds, PnpEvent->TargetDevice.DeviceIds); RtlInterlockedPushEntrySList(&DeviceInstallListHead, &Params->ListEntry); NtSetEvent(hDeviceInstallListNotEmpty, NULL); } else { DPRINT1("Not enough memory (size %lu)\n", len); } } } else { DPRINT("Unknown event, GUID {%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\n", PnpEvent->EventGuid.Data1, PnpEvent->EventGuid.Data2, PnpEvent->EventGuid.Data3, PnpEvent->EventGuid.Data4[0], PnpEvent->EventGuid.Data4[1], PnpEvent->EventGuid.Data4[2], PnpEvent->EventGuid.Data4[3], PnpEvent->EventGuid.Data4[4], PnpEvent->EventGuid.Data4[5], PnpEvent->EventGuid.Data4[6], PnpEvent->EventGuid.Data4[7]); } /* Dequeue the current PnP event and signal the next one */ NtPlugPlayControl(PlugPlayControlUserResponse, NULL, 0); } Status = STATUS_SUCCESS; Quit: if (PnpEvent) RtlFreeHeap(ProcessHeap, 0, PnpEvent); NtTerminateThread(NtCurrentThread(), Status); return Status; }