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)
18 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
21 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, DeviceId
);
22 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
23 if (!NT_SUCCESS(Status
))
25 DPRINT1("NtPlugPlayControl() failed with status 0x%08x\n", Status
);
37 IN LPCWSTR HardwareId
)
39 UNICODE_STRING PathPrefix
= RTL_CONSTANT_STRING(L
"System32\\DRIVERS\\");
40 UNICODE_STRING ServiceU
= RTL_CONSTANT_STRING(L
"Service");
41 UNICODE_STRING ErrorControlU
= RTL_CONSTANT_STRING(L
"ErrorControl");
42 UNICODE_STRING ImagePathU
= RTL_CONSTANT_STRING(L
"ImagePath");
43 UNICODE_STRING StartU
= RTL_CONSTANT_STRING(L
"Start");
44 UNICODE_STRING TypeU
= RTL_CONSTANT_STRING(L
"Type");
45 UNICODE_STRING StringU
;
46 OBJECT_ATTRIBUTES ObjectAttributes
;
49 LPWSTR Driver
, ImagePath
, FullImagePath
;
53 BOOLEAN deviceInstalled
= FALSE
;
55 /* Check if we know the hardware */
56 if (!SetupFindFirstLineW(hInf
, L
"HardwareIdsDatabase", HardwareId
, &Context
))
58 if (!INF_GetDataField(&Context
, 1, &Driver
))
61 /* Find associated driver name */
62 /* FIXME: check in other sections too! */
63 if (!SetupFindFirstLineW(hInf
, L
"BootBusExtenders.Load", Driver
, &Context
)
64 && !SetupFindFirstLineW(hInf
, L
"BusExtenders.Load", Driver
, &Context
)
65 && !SetupFindFirstLineW(hInf
, L
"SCSI.Load", Driver
, &Context
)
66 && !SetupFindFirstLineW(hInf
, L
"InputDevicesSupport.Load", Driver
, &Context
)
67 && !SetupFindFirstLineW(hInf
, L
"Keyboard.Load", Driver
, &Context
))
69 if (!INF_GetDataField(&Context
, 1, &ImagePath
))
72 /* Prepare full driver path */
73 dwValue
= PathPrefix
.MaximumLength
+ wcslen(ImagePath
) * sizeof(WCHAR
);
74 FullImagePath
= (LPWSTR
)RtlAllocateHeap(ProcessHeap
, 0, dwValue
);
77 DPRINT1("RtlAllocateHeap() failed\n");
80 RtlCopyMemory(FullImagePath
, PathPrefix
.Buffer
, PathPrefix
.MaximumLength
);
81 wcscat(FullImagePath
, ImagePath
);
83 DPRINT1("Using driver '%S' for device '%S'\n", ImagePath
, DeviceId
);
85 /* Create service key */
86 RtlInitUnicodeString(&StringU
, Driver
);
87 InitializeObjectAttributes(&ObjectAttributes
, &StringU
, 0, hServices
, NULL
);
88 Status
= NtCreateKey(&hService
, KEY_SET_VALUE
, &ObjectAttributes
, 0, NULL
, 0, &Disposition
);
89 if (!NT_SUCCESS(Status
))
91 DPRINT1("NtCreateKey('%wZ') failed with status 0x%08x\n", &StringU
, Status
);
92 RtlFreeHeap(ProcessHeap
, 0, FullImagePath
);
96 /* Fill service key */
97 if (Disposition
== REG_CREATED_NEW_KEY
)
115 dwValue
= SERVICE_KERNEL_DRIVER
;
124 /* HACK: don't put any path in registry */
131 (wcslen(ImagePath
) + 1) * sizeof(WCHAR
));
133 /* Associate device with the service we just filled */
134 Status
= NtSetValueKey(
140 (wcslen(Driver
) + 1) * sizeof(WCHAR
));
141 if (NT_SUCCESS(Status
))
143 /* Restart the device, so it will use the driver we registred */
144 deviceInstalled
= ResetDevice(DeviceId
);
147 /* HACK: Update driver path */
154 (wcslen(FullImagePath
) + 1) * sizeof(WCHAR
));
155 RtlFreeHeap(ProcessHeap
, 0, FullImagePath
);
158 return deviceInstalled
;
168 UNICODE_STRING HardwareIDU
= RTL_CONSTANT_STRING(L
"HardwareID");
169 UNICODE_STRING CompatibleIDsU
= RTL_CONSTANT_STRING(L
"CompatibleIDs");
170 UNICODE_STRING DeviceIdU
;
171 OBJECT_ATTRIBUTES ObjectAttributes
;
173 PKEY_VALUE_PARTIAL_INFORMATION pPartialInformation
= NULL
;
176 BOOLEAN bDriverInstalled
= FALSE
;
179 RtlInitUnicodeString(&DeviceIdU
, DeviceId
);
180 InitializeObjectAttributes(&ObjectAttributes
, &DeviceIdU
, 0, hEnum
, NULL
);
181 Status
= NtOpenKey(&hDeviceKey
, KEY_QUERY_VALUE
| KEY_SET_VALUE
, &ObjectAttributes
);
182 if (!NT_SUCCESS(Status
))
184 DPRINT("Unable to open subkey '%S'\n", DeviceId
);
188 Status
= NtQueryValueKey(
191 KeyValuePartialInformation
,
195 if (Status
== STATUS_BUFFER_TOO_SMALL
)
197 pPartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)RtlAllocateHeap(ProcessHeap
, 0, ulRequired
);
198 if (!pPartialInformation
)
200 DPRINT1("RtlAllocateHeap() failed\n");
204 Status
= NtQueryValueKey(
207 KeyValuePartialInformation
,
212 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
216 else if (!NT_SUCCESS(Status
))
218 DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status
);
219 if (pPartialInformation
)
220 RtlFreeHeap(ProcessHeap
, 0, pPartialInformation
);
224 else if (pPartialInformation
)
226 for (HardwareID
= (LPCWSTR
)pPartialInformation
->Data
;
227 (PUCHAR
)HardwareID
< pPartialInformation
->Data
+ pPartialInformation
->DataLength
229 && !bDriverInstalled
;
230 HardwareID
+= wcslen(HardwareID
) + 1)
232 bDriverInstalled
= InstallDriver(hInf
, hServices
,hDeviceKey
, DeviceId
, HardwareID
);
236 if (!bDriverInstalled
)
238 if (pPartialInformation
)
240 RtlFreeHeap(ProcessHeap
, 0, pPartialInformation
);
241 pPartialInformation
= NULL
;
243 Status
= NtQueryValueKey(
246 KeyValuePartialInformation
,
250 if (Status
== STATUS_BUFFER_TOO_SMALL
)
252 pPartialInformation
= (PKEY_VALUE_PARTIAL_INFORMATION
)RtlAllocateHeap(ProcessHeap
, 0, ulRequired
);
253 if (!pPartialInformation
)
255 DPRINT("RtlAllocateHeap() failed\n");
259 Status
= NtQueryValueKey(
262 KeyValuePartialInformation
,
267 if (Status
== STATUS_OBJECT_NAME_NOT_FOUND
)
271 else if (!NT_SUCCESS(Status
))
273 if (pPartialInformation
)
274 RtlFreeHeap(ProcessHeap
, 0, pPartialInformation
);
276 DPRINT1("NtQueryValueKey() failed with status 0x%08x\n", Status
);
279 else if (pPartialInformation
)
281 for (HardwareID
= (LPCWSTR
)pPartialInformation
->Data
;
282 (PUCHAR
)HardwareID
< pPartialInformation
->Data
+ pPartialInformation
->DataLength
284 && !bDriverInstalled
;
285 HardwareID
+= wcslen(HardwareID
) + 1)
287 bDriverInstalled
= InstallDriver(hInf
, hServices
,hDeviceKey
, DeviceId
, HardwareID
);
291 if (!bDriverInstalled
)
292 DPRINT("No driver available for %S\n", DeviceId
);
294 RtlFreeHeap(ProcessHeap
, 0, pPartialInformation
);
299 EventThread(IN LPVOID lpParameter
)
301 UNICODE_STRING EnumU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Enum");
302 UNICODE_STRING ServicesU
= RTL_CONSTANT_STRING(L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services");
303 PPLUGPLAY_EVENT_BLOCK PnpEvent
;
304 OBJECT_ATTRIBUTES ObjectAttributes
;
307 HANDLE hEnum
, hServices
;
310 hInf
= *(HINF
*)lpParameter
;
312 InitializeObjectAttributes(&ObjectAttributes
, &EnumU
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
313 Status
= NtOpenKey(&hEnum
, KEY_QUERY_VALUE
, &ObjectAttributes
);
314 if (!NT_SUCCESS(Status
))
316 DPRINT1("NtOpenKey('%wZ') failed with status 0x%08lx\n", &EnumU
, Status
);
320 InitializeObjectAttributes(&ObjectAttributes
, &ServicesU
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
321 Status
= NtCreateKey(&hServices
, 0, &ObjectAttributes
, 0, NULL
, 0, NULL
);
322 if (!NT_SUCCESS(Status
))
324 DPRINT1("NtCreateKey('%wZ') failed with status 0x%08lx\n", &ServicesU
, Status
);
329 PnpEventSize
= 0x1000;
330 PnpEvent
= (PPLUGPLAY_EVENT_BLOCK
)RtlAllocateHeap(ProcessHeap
, 0, PnpEventSize
);
331 if (PnpEvent
== NULL
)
335 return STATUS_NO_MEMORY
;
340 DPRINT("Calling NtGetPlugPlayEvent()\n");
342 /* Wait for the next pnp event */
343 Status
= NtGetPlugPlayEvent(0, 0, PnpEvent
, PnpEventSize
);
345 /* Resize the buffer for the PnP event if it's too small. */
346 if (Status
== STATUS_BUFFER_TOO_SMALL
)
348 PnpEventSize
+= 0x400;
349 RtlFreeHeap(ProcessHeap
, 0, PnpEvent
);
350 PnpEvent
= (PPLUGPLAY_EVENT_BLOCK
)RtlAllocateHeap(ProcessHeap
, 0, PnpEventSize
);
351 if (PnpEvent
== NULL
)
355 return STATUS_NO_MEMORY
;
360 if (!NT_SUCCESS(Status
))
362 DPRINT("NtPlugPlayEvent() failed (Status %lx)\n", Status
);
366 /* Process the pnp event */
367 DPRINT("Received PnP Event\n");
368 if (IsEqualIID(&PnpEvent
->EventGuid
, (REFGUID
)&GUID_DEVICE_ENUMERATED
))
370 DPRINT("Device arrival event: %S\n", PnpEvent
->TargetDevice
.DeviceIds
);
371 InstallDevice(hInf
, hEnum
, hServices
, PnpEvent
->TargetDevice
.DeviceIds
);
375 DPRINT("Unknown event\n");
378 /* Dequeue the current pnp event and signal the next one */
379 NtPlugPlayControl(PlugPlayControlUserResponse
, NULL
, 0);
382 RtlFreeHeap(ProcessHeap
, 0, PnpEvent
);
386 return STATUS_SUCCESS
;
390 PnpEventThread(IN LPVOID lpParameter
)
393 Status
= EventThread(lpParameter
);
394 NtTerminateThread(NtCurrentThread(), Status
);