PGENERIC_LIST CreateDisplayDriverList(HINF InfFile) { CHAR Buffer[128]; PGENERIC_LIST List; INFCONTEXT Context; PWCHAR KeyName; PWCHAR KeyValue; PWCHAR UserData; WCHAR DisplayIdentifier[128]; WCHAR DisplayKey[32]; /* Get the display identification */ if (!GetDisplayIdentifier(DisplayIdentifier, 128)) { DisplayIdentifier[0] = 0; } DPRINT("Display identifier: '%S'\n", DisplayIdentifier); /* Search for matching device identifier */ if (!SetupFindFirstLineW(InfFile, L"Map.Display", NULL, &Context)) { /* FIXME: error message */ return NULL; } do { if (!INF_GetDataField(&Context, 1, &KeyValue)) { /* FIXME: Handle error! */ DPRINT("INF_GetDataField() failed\n"); return NULL; } DPRINT("KeyValue: %S\n", KeyValue); if (wcsstr(DisplayIdentifier, KeyValue)) { if (!INF_GetDataField(&Context, 0, &KeyName)) { /* FIXME: Handle error! */ DPRINT("INF_GetDataField() failed\n"); return NULL; } DPRINT("Display key: %S\n", KeyName); wcscpy(DisplayKey, KeyName); } } while (SetupFindNextLine(&Context, &Context)); List = CreateGenericList(); if (List == NULL) return NULL; if (!SetupFindFirstLineW (InfFile, L"Display", NULL, &Context)) { DestroyGenericList(List, FALSE); return NULL; } do { if (!INF_GetDataField(&Context, 0, &KeyName)) { DPRINT1("INF_GetDataField() failed\n"); break; } if (!INF_GetDataField(&Context, 1, &KeyValue)) { DPRINT1("INF_GetDataField() failed\n"); break; } UserData = (WCHAR*) RtlAllocateHeap(ProcessHeap, 0, (wcslen(KeyName) + 1) * sizeof(WCHAR)); if (UserData == NULL) { DPRINT1("RtlAllocateHeap() failed\n"); DestroyGenericList(List, TRUE); return NULL; } wcscpy(UserData, KeyName); sprintf(Buffer, "%S", KeyValue); AppendGenericListEntry(List, Buffer, UserData, _wcsicmp(KeyName, DisplayKey) ? FALSE : TRUE); } while (SetupFindNextLine(&Context, &Context)); #if 0 AppendGenericListEntry(List, "Other display driver", NULL, TRUE); #endif return List; }
BOOLEAN ProcessDisplayRegistry(HINF InfFile, PGENERIC_LIST List) { PGENERIC_LIST_ENTRY Entry; INFCONTEXT Context; PWCHAR ServiceName; ULONG StartValue; NTSTATUS Status; WCHAR RegPath [255]; PWCHAR Buffer; ULONG Width, Height, Bpp; DPRINT("ProcessDisplayRegistry() called\n"); Entry = GetCurrentListEntry(List); if (Entry == NULL) { DPRINT("GetCurrentListEntry() failed\n"); return FALSE; } if (!SetupFindFirstLineW(InfFile, L"Display", (WCHAR*)GetListEntryUserData(Entry), &Context)) { DPRINT("SetupFindFirstLineW() failed\n"); return FALSE; } /* Enable the right driver */ if (!INF_GetDataField(&Context, 3, &ServiceName)) { DPRINT("INF_GetDataField() failed\n"); return FALSE; } ASSERT(wcslen(ServiceName) < 10); DPRINT("Service name: %S\n", ServiceName); StartValue = 1; Status = RtlWriteRegistryValue(RTL_REGISTRY_SERVICES, ServiceName, L"Start", REG_DWORD, &StartValue, sizeof(ULONG)); if (!NT_SUCCESS(Status)) { DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status); return FALSE; } /* Set the resolution */ swprintf(RegPath, L"\\Registry\\Machine\\System\\CurrentControlSet\\Hardware Profiles\\Current\\System\\CurrentControlSet\\Services\\%s\\Device0", ServiceName); if (!INF_GetDataField(&Context, 4, &Buffer)) { DPRINT("INF_GetDataField() failed\n"); return FALSE; } Width = wcstoul(Buffer, NULL, 10); Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, RegPath, L"DefaultSettings.XResolution", REG_DWORD, &Width, sizeof(ULONG)); if (!NT_SUCCESS(Status)) { DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status); return FALSE; } if (!INF_GetDataField(&Context, 5, &Buffer)) { DPRINT("INF_GetDataField() failed\n"); return FALSE; } Height = wcstoul(Buffer, 0, 0); Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, RegPath, L"DefaultSettings.YResolution", REG_DWORD, &Height, sizeof(ULONG)); if (!NT_SUCCESS(Status)) { DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status); return FALSE; } if (!INF_GetDataField(&Context, 6, &Buffer)) { DPRINT("INF_GetDataField() failed\n"); return FALSE; } Bpp = wcstoul(Buffer, 0, 0); Status = RtlWriteRegistryValue(RTL_REGISTRY_ABSOLUTE, RegPath, L"DefaultSettings.BitsPerPel", REG_DWORD, &Bpp, sizeof(ULONG)); if (!NT_SUCCESS(Status)) { DPRINT("RtlWriteRegistryValue() failed (Status %lx)\n", Status); return FALSE; } DPRINT("ProcessDisplayRegistry() done\n"); return TRUE; }
BOOLEAN InstallDriver( IN HINF hInf, IN HANDLE hServices, IN HANDLE hDeviceKey, IN LPCWSTR DeviceId, IN LPCWSTR HardwareId) { UNICODE_STRING PathPrefix = RTL_CONSTANT_STRING(L"System32\\DRIVERS\\"); UNICODE_STRING ServiceU = RTL_CONSTANT_STRING(L"Service"); UNICODE_STRING ErrorControlU = RTL_CONSTANT_STRING(L"ErrorControl"); UNICODE_STRING ImagePathU = RTL_CONSTANT_STRING(L"ImagePath"); UNICODE_STRING StartU = RTL_CONSTANT_STRING(L"Start"); UNICODE_STRING TypeU = RTL_CONSTANT_STRING(L"Type"); UNICODE_STRING StringU; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE hService; INFCONTEXT Context; LPWSTR Driver, ClassGuid, ImagePath, FullImagePath; ULONG dwValue; ULONG Disposition; NTSTATUS Status; BOOLEAN deviceInstalled = FALSE; UNICODE_STRING UpperFiltersU = RTL_CONSTANT_STRING(L"UpperFilters"); LPWSTR keyboardClass = L"kbdclass\0"; /* Check if we know the hardware */ if (!SetupFindFirstLineW(hInf, L"HardwareIdsDatabase", HardwareId, &Context)) return FALSE; if (!INF_GetDataField(&Context, 1, &Driver)) return FALSE; /* Get associated class GUID (if any) */ if (!INF_GetDataField(&Context, 2, &ClassGuid)) ClassGuid = NULL; /* Find associated driver name */ /* FIXME: check in other sections too! */ if (!SetupFindFirstLineW(hInf, L"BootBusExtenders.Load", Driver, &Context) && !SetupFindFirstLineW(hInf, L"BusExtenders.Load", Driver, &Context) && !SetupFindFirstLineW(hInf, L"SCSI.Load", Driver, &Context) && !SetupFindFirstLineW(hInf, L"InputDevicesSupport.Load", Driver, &Context) && !SetupFindFirstLineW(hInf, L"Keyboard.Load", Driver, &Context)) { return FALSE; } if (!INF_GetDataField(&Context, 1, &ImagePath)) return FALSE; /* Prepare full driver path */ dwValue = PathPrefix.MaximumLength + wcslen(ImagePath) * sizeof(WCHAR); FullImagePath = (LPWSTR)RtlAllocateHeap(ProcessHeap, 0, dwValue); if (!FullImagePath) { DPRINT1("RtlAllocateHeap() failed\n"); return FALSE; } RtlCopyMemory(FullImagePath, PathPrefix.Buffer, PathPrefix.MaximumLength); wcscat(FullImagePath, ImagePath); DPRINT1("Using driver '%S' for device '%S'\n", ImagePath, DeviceId); /* Create service key */ RtlInitUnicodeString(&StringU, Driver); InitializeObjectAttributes(&ObjectAttributes, &StringU, 0, hServices, NULL); Status = NtCreateKey(&hService, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, 0, &Disposition); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateKey('%wZ') failed with status 0x%08x\n", &StringU, Status); RtlFreeHeap(ProcessHeap, 0, FullImagePath); return FALSE; } /* Fill service key */ if (Disposition == REG_CREATED_NEW_KEY) { dwValue = 0; NtSetValueKey( hService, &ErrorControlU, 0, REG_DWORD, &dwValue, sizeof(dwValue)); dwValue = 0; NtSetValueKey( hService, &StartU, 0, REG_DWORD, &dwValue, sizeof(dwValue)); dwValue = SERVICE_KERNEL_DRIVER; NtSetValueKey( hService, &TypeU, 0, REG_DWORD, &dwValue, sizeof(dwValue)); } /* HACK: don't put any path in registry */ NtSetValueKey( hService, &ImagePathU, 0, REG_SZ, ImagePath, (wcslen(ImagePath) + 1) * sizeof(WCHAR)); if (ClassGuid &&_wcsicmp(ClassGuid, L"{4D36E96B-E325-11CE-BFC1-08002BE10318}") == 0) { DPRINT1("Installing keyboard class driver for '%S'\n", DeviceId); NtSetValueKey(hDeviceKey, &UpperFiltersU, 0, REG_MULTI_SZ, keyboardClass, (wcslen(keyboardClass) + 2) * sizeof(WCHAR)); } /* Associate device with the service we just filled */ Status = NtSetValueKey( hDeviceKey, &ServiceU, 0, REG_SZ, Driver, (wcslen(Driver) + 1) * sizeof(WCHAR)); if (NT_SUCCESS(Status)) { /* Restart the device, so it will use the driver we registered */ deviceInstalled = ResetDevice(DeviceId); } /* HACK: Update driver path */ NtSetValueKey( hService, &ImagePathU, 0, REG_SZ, FullImagePath, (wcslen(FullImagePath) + 1) * sizeof(WCHAR)); RtlFreeHeap(ProcessHeap, 0, FullImagePath); NtClose(hService); return deviceInstalled; }