예제 #1
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;
}
예제 #2
0
파일: devinst.c 프로젝트: Moteesh/reactos
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;
}