2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS text-mode setup
4 * FILE: subsys/system/usetup/interface/devinst.c
5 * PURPOSE: Device installation
6 * PROGRAMMER: Hervé Poussineau (hpoussin@reactos.org)
16 #include <libs/umpnpmgr/sysguid.h>
22 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
25 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DeviceId
);
26 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
27 if (!NT_SUCCESS(Status
))
29 DPRINT1("NtPlugPlayControl() failed with status 0x%08x\n", Status
);
41 IN LPCWSTR HardwareId
)
43 UNICODE_STRING PathPrefix
= RTL_CONSTANT_STRING(L
"System32\\DRIVERS\\");
44 UNICODE_STRING ServiceU
= RTL_CONSTANT_STRING(L
"Service");
45 UNICODE_STRING ErrorControlU
= RTL_CONSTANT_STRING(L
"ErrorControl");
46 UNICODE_STRING ImagePathU
= RTL_CONSTANT_STRING(L
"ImagePath");
47 UNICODE_STRING StartU
= RTL_CONSTANT_STRING(L
"Start");
48 UNICODE_STRING TypeU
= RTL_CONSTANT_STRING(L
"Type");
49 UNICODE_STRING StringU
;
50 OBJECT_ATTRIBUTES ObjectAttributes
;
53 LPWSTR Driver
, ImagePath
, FullImagePath
;
57 BOOLEAN deviceInstalled
= FALSE
;
58 UNICODE_STRING UpperFiltersU
= RTL_CONSTANT_STRING(L
"UpperFilters");
59 LPWSTR keyboardClass
= L
"kbdclass\0";
60 BOOLEAN keyboardDevice
= FALSE
;
62 /* Check if we know the hardware */
63 if (!SetupFindFirstLineW(hInf
, L
"HardwareIdsDatabase", HardwareId
, &Context
))
65 if (!INF_GetDataField(&Context
, 1, &Driver
))
68 /* Find associated driver name */
69 /* FIXME: check in other sections too! */
70 if (!SetupFindFirstLineW(hInf
, L
"BootBusExtenders.Load", Driver
, &Context
)
71 && !SetupFindFirstLineW(hInf
, L
"BusExtenders.Load", Driver
, &Context
)
72 && !SetupFindFirstLineW(hInf
, L
"SCSI.Load", Driver
, &Context
)
73 && !SetupFindFirstLineW(hInf
, L
"InputDevicesSupport.Load", Driver
, &Context
))
75 if (!SetupFindFirstLineW(hInf
, L
"Keyboard.Load", Driver
, &Context
))
78 keyboardDevice
= TRUE
;
81 if (!INF_GetDataField(&Context
, 1, &ImagePath
))
84 /* Prepare full driver path */
85 dwValue
= PathPrefix
.MaximumLength
+ wcslen(ImagePath
) * sizeof(WCHAR
);
86 FullImagePath
= (LPWSTR
)RtlAllocateHeap(ProcessHeap
, 0, dwValue
);
89 DPRINT1("RtlAllocateHeap() failed\n");
92 RtlCopyMemory(FullImagePath
, PathPrefix
.Buffer
, PathPrefix
.MaximumLength
);
93 wcscat(FullImagePath
, ImagePath
);
95 DPRINT1("Using driver '%S' for device '%S'\n", ImagePath
, DeviceId
);
97 /* Create service key */
98 RtlInitUnicodeString(&StringU
, Driver
);
99 InitializeObjectAttributes(&ObjectAttributes
, &StringU
, 0, hServices
, NULL
);
100 Status
= NtCreateKey(&hService
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, 0, &Disposition
);
101 if (!NT_SUCCESS(Status
))
103 DPRINT1("NtCreateKey('%wZ') failed with status 0x%08x\n", &StringU
, Status
);
104 RtlFreeHeap(ProcessHeap
, 0, FullImagePath
);
108 /* Fill service key */
109 if (Disposition
== REG_CREATED_NEW_KEY
)
127 dwValue
= SERVICE_KERNEL_DRIVER
;
136 /* HACK: don't put any path in registry */
143 (wcslen(ImagePath
) + 1) * sizeof(WCHAR
));
147 DPRINT1("Installing keyboard class driver for '%S'\n", DeviceId
);
148 NtSetValueKey(hDeviceKey
,
153 (wcslen(keyboardClass
) + 2) * sizeof(WCHAR
));
156 /* Associate device with the service we just filled */
157 Status
= NtSetValueKey(
163 (wcslen(Driver
) + 1) * sizeof(WCHAR
));
164 if (NT_SUCCESS(Status
))
166 /* Restart the device, so it will use the driver we registred */
167 deviceInstalled
= ResetDevice(DeviceId
);
170 /* HACK: Update driver path */
177 (wcslen(FullImagePath
) + 1) * sizeof(WCHAR
));
178 RtlFreeHeap(ProcessHeap
, 0, FullImagePath
);
181 return deviceInstalled
;
191 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
192 UNICODE_STRING CompatibleIDsU
= RTL_CONSTANT_STRING(L
"CompatibleIDs");
193 UNICODE_STRING DeviceIdU
;
194 OBJECT_ATTRIBUTES ObjectAttributes
;
196 PKEY_VALUE_PARTIAL_INFORMATION pPartialInformation
= NULL
;
199 BOOLEAN bDriverInstalled
= FALSE
;
202 RtlInitUnicodeString(&DeviceIdU
, DeviceId
);
203 InitializeObjectAttributes(&ObjectAttributes
, &DeviceIdU
, 0, hEnum
, NULL
);
204 Status
= NtOpenKey(&hDeviceKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
205 if (!NT_SUCCESS(Status
))
207 DPRINT("Unable to open subkey '%S'\n", DeviceId
);
211 Status
= NtQueryValueKey(
214 KeyValuePartialInformation
,
218 if (Status
== STATUS_BUFFER_TOO_SMALL
)
220 pPartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)RtlAllocateHeap(ProcessHeap
, 0, ulRequired
);
221 if (!pPartialInformation
)
223 DPRINT1("RtlAllocateHeap() failed\n");
227 Status
= NtQueryValueKey(
230 KeyValuePartialInformation
,
235 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
239 else if (!NT_SUCCESS(Status
))
241 DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status
);
242 if (pPartialInformation
)
243 RtlFreeHeap(ProcessHeap
, 0, pPartialInformation
);
247 else if (pPartialInformation
)
249 for (HardwareID
= (LPCWSTR
)pPartialInformation
->Data
;
250 (PUCHAR
)HardwareID
< pPartialInformation
->Data
+ pPartialInformation
->DataLength
252 && !bDriverInstalled
;
253 HardwareID
+= wcslen(HardwareID
) + 1)
255 bDriverInstalled
= InstallDriver(hInf
, hServices
,hDeviceKey
, DeviceId
, HardwareID
);
259 if (!bDriverInstalled
)
261 if (pPartialInformation
)
263 RtlFreeHeap(ProcessHeap
, 0, pPartialInformation
);
264 pPartialInformation
= NULL
;
266 Status
= NtQueryValueKey(
269 KeyValuePartialInformation
,
273 if (Status
== STATUS_BUFFER_TOO_SMALL
)
275 pPartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)RtlAllocateHeap(ProcessHeap
, 0, ulRequired
);
276 if (!pPartialInformation
)
278 DPRINT("RtlAllocateHeap() failed\n");
282 Status
= NtQueryValueKey(
285 KeyValuePartialInformation
,
290 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
294 else if (!NT_SUCCESS(Status
))
296 if (pPartialInformation
)
297 RtlFreeHeap(ProcessHeap
, 0, pPartialInformation
);
299 DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status
);
302 else if (pPartialInformation
)
304 for (HardwareID
= (LPCWSTR
)pPartialInformation
->Data
;
305 (PUCHAR
)HardwareID
< pPartialInformation
->Data
+ pPartialInformation
->DataLength
307 && !bDriverInstalled
;
308 HardwareID
+= wcslen(HardwareID
) + 1)
310 bDriverInstalled
= InstallDriver(hInf
, hServices
,hDeviceKey
, DeviceId
, HardwareID
);
314 if (!bDriverInstalled
)
315 DPRINT("No driver available for %S\n", DeviceId
);
317 RtlFreeHeap(ProcessHeap
, 0, pPartialInformation
);
322 EventThread(IN LPVOID lpParameter
)
324 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
325 UNICODE_STRING ServicesU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
326 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
327 OBJECT_ATTRIBUTES ObjectAttributes
;
330 HANDLE hEnum
, hServices
;
333 hInf
= *(HINF
*)lpParameter
;
335 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
336 Status
= NtOpenKey(&hEnum
, KEY_QUERY_VALUE
, &ObjectAttributes
);
337 if (!NT_SUCCESS(Status
))
339 DPRINT1("NtOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
343 InitializeObjectAttributes(&ObjectAttributes
, &ServicesU
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
344 Status
= NtCreateKey(&hServices
, 0, &ObjectAttributes
, 0, NULL
, 0, NULL
);
345 if (!NT_SUCCESS(Status
))
347 DPRINT1("NtCreateKey('%wZ') failed with status 0x%08lx\n", &ServicesU
, Status
);
352 PnpEventSize
= 0x1000;
353 PnpEvent
= (PPLUGPLAY_EVENT_BLOCK
)RtlAllocateHeap(ProcessHeap
, 0, PnpEventSize
);
354 if (PnpEvent
== NULL
)
358 return STATUS_NO_MEMORY
;
363 DPRINT("Calling NtGetPlugPlayEvent()\n");
365 /* Wait for the next pnp event */
366 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
368 /* Resize the buffer for the PnP event if it's too small. */
369 if (Status
== STATUS_BUFFER_TOO_SMALL
)
371 PnpEventSize
+= 0x400;
372 RtlFreeHeap(ProcessHeap
, 0, PnpEvent
);
373 PnpEvent
= (PPLUGPLAY_EVENT_BLOCK
)RtlAllocateHeap(ProcessHeap
, 0, PnpEventSize
);
374 if (PnpEvent
== NULL
)
378 return STATUS_NO_MEMORY
;
383 if (!NT_SUCCESS(Status
))
385 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status
);
389 /* Process the pnp event */
390 DPRINT("Received PnP Event\n");
391 if (IsEqualIID(&PnpEvent
->EventGuid
, (REFGUID
)&GUID_DEVICE_ENUMERATED
))
393 DPRINT("Device arrival event: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
394 InstallDevice(hInf
, hEnum
, hServices
, PnpEvent
->TargetDevice
.DeviceIds
);
398 DPRINT("Unknown event\n");
401 /* Dequeue the current pnp event and signal the next one */
402 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
405 RtlFreeHeap(ProcessHeap
, 0, PnpEvent
);
409 return STATUS_SUCCESS
;
413 PnpEventThread(IN LPVOID lpParameter
)
416 Status
= EventThread(lpParameter
);
417 NtTerminateThread(NtCurrentThread(), Status
);