[SYSETUP] Implement the CriticalDeviceCoInstaller
[reactos.git] / dll / win32 / syssetup / classinst.c
1 /*
2 * PROJECT: ReactOS system libraries
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/syssetup/classinst.c
5 * PURPOSE: Class installers
6 * PROGRAMMERS: Copyright 2006 Hervé Poussineau (hpoussin@reactos.org)
7 */
8
9 #include "precomp.h"
10
11 #define NDEBUG
12 #include <debug.h>
13
14 /*
15 * @unimplemented
16 */
17 DWORD
18 WINAPI
19 ComputerClassInstaller(
20 IN DI_FUNCTION InstallFunction,
21 IN HDEVINFO DeviceInfoSet,
22 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
23 {
24 switch (InstallFunction)
25 {
26 default:
27 DPRINT1("Install function %u ignored\n", InstallFunction);
28 return ERROR_DI_DO_DEFAULT;
29 }
30 }
31
32
33 /*
34 * @implemented
35 */
36 DWORD
37 WINAPI
38 CriticalDeviceCoInstaller(
39 IN DI_FUNCTION InstallFunction,
40 IN HDEVINFO DeviceInfoSet,
41 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
42 IN OUT PCOINSTALLER_CONTEXT_DATA Context)
43 {
44 WCHAR szDeviceId[256];
45 WCHAR szServiceName[256];
46 WCHAR szClassGUID[64];
47 DWORD dwRequiredSize;
48 HKEY hDriverKey = NULL;
49 HKEY hDatabaseKey = NULL, hDeviceKey = NULL;
50 DWORD dwDisposition;
51 PWSTR Ptr;
52 DWORD dwError = ERROR_SUCCESS;
53
54 DPRINT("CriticalDeviceCoInstaller(%lu %p %p %p)\n",
55 InstallFunction, DeviceInfoSet, DeviceInfoData, Context);
56
57 if (InstallFunction != DIF_INSTALLDEVICE)
58 return ERROR_SUCCESS;
59
60 /* Get the MatchingDeviceId property */
61 hDriverKey = SetupDiOpenDevRegKey(DeviceInfoSet,
62 DeviceInfoData,
63 DICS_FLAG_GLOBAL,
64 0,
65 DIREG_DRV,
66 KEY_READ);
67 if (hDriverKey == INVALID_HANDLE_VALUE)
68 {
69 if (Context->PostProcessing)
70 {
71 dwError = GetLastError();
72 DPRINT1("Failed to open the driver key! (Error %lu)\n", dwError);
73 goto done;
74 }
75 else
76 {
77 DPRINT("Failed to open the driver key! Postprocessing required!\n");
78 return ERROR_DI_POSTPROCESSING_REQUIRED;
79 }
80 }
81
82 dwRequiredSize = sizeof(szDeviceId);
83 dwError = RegQueryValueExW(hDriverKey,
84 L"MatchingDeviceId",
85 NULL,
86 NULL,
87 (PBYTE)szDeviceId,
88 &dwRequiredSize);
89 RegCloseKey(hDriverKey);
90 if (dwError != ERROR_SUCCESS)
91 {
92 if (Context->PostProcessing)
93 {
94 dwError = GetLastError();
95 DPRINT1("Failed to read the MatchingDeviceId value! (Error %lu)\n", dwError);
96 goto done;
97 }
98 else
99 {
100 DPRINT("Failed to read the MatchingDeviceId value! Postprocessing required!\n");
101 return ERROR_DI_POSTPROCESSING_REQUIRED;
102 }
103 }
104
105 DPRINT("MatchingDeviceId: %S\n", szDeviceId);
106
107 /* Get the ClassGUID property */
108 dwRequiredSize = 0;
109 if (!SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet,
110 DeviceInfoData,
111 SPDRP_CLASSGUID,
112 NULL,
113 (PBYTE)szClassGUID,
114 sizeof(szClassGUID),
115 &dwRequiredSize))
116 {
117 if (Context->PostProcessing)
118 {
119 dwError = GetLastError();
120 DPRINT1("Failed to read the ClassGUID! (Error %lu)\n", dwError);
121 goto done;
122 }
123 else
124 {
125 DPRINT("Failed to read the ClassGUID! Postprocessing required!\n");
126 return ERROR_DI_POSTPROCESSING_REQUIRED;
127 }
128 }
129
130 DPRINT("ClassGUID %S\n", szClassGUID);
131
132 /* Get the Service property (optional) */
133 dwRequiredSize = 0;
134 if (!SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet,
135 DeviceInfoData,
136 SPDRP_SERVICE,
137 NULL,
138 (PBYTE)szServiceName,
139 sizeof(szServiceName),
140 &dwRequiredSize))
141 {
142 if (Context->PostProcessing)
143 {
144 dwError = GetLastError();
145 if (dwError != ERROR_FILE_NOT_FOUND)
146 {
147 DPRINT1("Failed to read the Service name! (Error %lu)\n", dwError);
148 goto done;
149 }
150 else
151 {
152 szServiceName[0] = UNICODE_NULL;
153 dwError = ERROR_SUCCESS;
154 }
155 }
156 else
157 {
158 DPRINT("Failed to read the Service name! Postprocessing required!\n");
159 return ERROR_DI_POSTPROCESSING_REQUIRED;
160 }
161 }
162
163 DPRINT("Service %S\n", szServiceName);
164
165 /* Replace the first backslash by a number sign */
166 Ptr = wcschr(szDeviceId, L'\\');
167 if (Ptr != NULL)
168 {
169 *Ptr = L'#';
170
171 /* Terminate the device id at the second backslash */
172 Ptr = wcschr(Ptr, L'\\');
173 if (Ptr != NULL)
174 *Ptr = UNICODE_NULL;
175 }
176
177 DPRINT("DeviceId: %S\n", szDeviceId);
178
179 /* Open the critical device database key */
180 dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
181 L"SYSTEM\\CurrentControlSet\\Control\\CriticalDeviceDatabase",
182 0,
183 KEY_WRITE,
184 &hDatabaseKey);
185 if (dwError != ERROR_SUCCESS)
186 {
187 DPRINT1("RegOpenKeyExW failed (Error %lu)\n", dwError);
188 goto done;
189 }
190
191 /* Create a new key for the device */
192 dwError = RegCreateKeyExW(hDatabaseKey,
193 szDeviceId,
194 0,
195 NULL,
196 REG_OPTION_NON_VOLATILE,
197 KEY_WRITE,
198 NULL,
199 &hDeviceKey,
200 &dwDisposition);
201 if (dwError != ERROR_SUCCESS)
202 {
203 DPRINT1("RegCreateKeyExW failed (Error %lu)\n", dwError);
204 goto done;
205 }
206
207 /* Set the ClassGUID value */
208 dwError = RegSetValueExW(hDeviceKey,
209 L"ClassGUID",
210 0,
211 REG_SZ,
212 (PBYTE)szClassGUID,
213 (wcslen(szClassGUID) + 1) * sizeof(WCHAR));
214 if (dwError != ERROR_SUCCESS)
215 {
216 DPRINT1("RegSetValueExW failed (Error %lu)\n", dwError);
217 goto done;
218 }
219
220 /* If available, set the Service value */
221 if (szServiceName[0] != UNICODE_NULL)
222 {
223 dwError = RegSetValueExW(hDeviceKey,
224 L"Service",
225 0,
226 REG_SZ,
227 (PBYTE)szServiceName,
228 (wcslen(szServiceName) + 1) * sizeof(WCHAR));
229 if (dwError != ERROR_SUCCESS)
230 {
231 DPRINT1("RegSetValueExW failed (Error %lu)\n", dwError);
232 goto done;
233 }
234 }
235
236 done:
237 if (hDeviceKey != NULL)
238 RegCloseKey(hDeviceKey);
239
240 if (hDatabaseKey != NULL)
241 RegCloseKey(hDatabaseKey);
242
243 DPRINT("CriticalDeviceCoInstaller() done (Error %lu)\n", dwError);
244
245 return dwError;
246 }
247
248
249 /*
250 * @unimplemented
251 */
252 DWORD
253 WINAPI
254 DeviceBayClassInstaller(
255 IN DI_FUNCTION InstallFunction,
256 IN HDEVINFO DeviceInfoSet,
257 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
258 {
259 switch (InstallFunction)
260 {
261 default:
262 DPRINT("Install function %u ignored\n", InstallFunction);
263 return ERROR_DI_DO_DEFAULT;
264 }
265 }
266
267
268 /*
269 * @unimplemented
270 */
271 DWORD
272 WINAPI
273 EisaUpHalCoInstaller(
274 IN DI_FUNCTION InstallFunction,
275 IN HDEVINFO DeviceInfoSet,
276 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
277 IN OUT PCOINSTALLER_CONTEXT_DATA Context)
278 {
279 switch (InstallFunction)
280 {
281 default:
282 DPRINT1("Install function %u ignored\n", InstallFunction);
283 return ERROR_SUCCESS;
284 }
285 }
286
287
288 /*
289 * @implemented
290 */
291 DWORD
292 WINAPI
293 HdcClassInstaller(
294 IN DI_FUNCTION InstallFunction,
295 IN HDEVINFO DeviceInfoSet,
296 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
297 {
298 DPRINT("HdcClassInstaller()\n");
299 return ERROR_DI_DO_DEFAULT;
300 }
301
302
303 /*
304 * @unimplemented
305 */
306 DWORD
307 WINAPI
308 KeyboardClassInstaller(
309 IN DI_FUNCTION InstallFunction,
310 IN HDEVINFO DeviceInfoSet,
311 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
312 {
313 switch (InstallFunction)
314 {
315 default:
316 DPRINT("Install function %u ignored\n", InstallFunction);
317 return ERROR_DI_DO_DEFAULT;
318 }
319 }
320
321
322 /*
323 * @unimplemented
324 */
325 DWORD
326 WINAPI
327 MouseClassInstaller(
328 IN DI_FUNCTION InstallFunction,
329 IN HDEVINFO DeviceInfoSet,
330 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
331 {
332 switch (InstallFunction)
333 {
334 default:
335 DPRINT("Install function %u ignored\n", InstallFunction);
336 return ERROR_DI_DO_DEFAULT;
337 }
338 }
339
340
341 /*
342 * @unimplemented
343 */
344 DWORD
345 WINAPI
346 NtApmClassInstaller(
347 IN DI_FUNCTION InstallFunction,
348 IN HDEVINFO DeviceInfoSet,
349 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
350 {
351 switch (InstallFunction)
352 {
353 default:
354 DPRINT("Install function %u ignored\n", InstallFunction);
355 return ERROR_DI_DO_DEFAULT;
356 }
357 }
358
359
360 /*
361 * @unimplemented
362 */
363 DWORD
364 WINAPI
365 ScsiClassInstaller(
366 IN DI_FUNCTION InstallFunction,
367 IN HDEVINFO DeviceInfoSet,
368 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
369 {
370 switch (InstallFunction)
371 {
372 default:
373 DPRINT("Install function %u ignored\n", InstallFunction);
374 return ERROR_DI_DO_DEFAULT;
375 }
376 }
377
378
379 /*
380 * @unimplemented
381 */
382 DWORD
383 WINAPI
384 StorageCoInstaller(
385 IN DI_FUNCTION InstallFunction,
386 IN HDEVINFO DeviceInfoSet,
387 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
388 IN OUT PCOINSTALLER_CONTEXT_DATA Context)
389 {
390 switch (InstallFunction)
391 {
392 default:
393 DPRINT1("Install function %u ignored\n", InstallFunction);
394 return ERROR_SUCCESS;
395 }
396 }
397
398
399 /*
400 * @implemented
401 */
402 DWORD
403 WINAPI
404 TapeClassInstaller(
405 IN DI_FUNCTION InstallFunction,
406 IN HDEVINFO DeviceInfoSet,
407 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
408 {
409 DPRINT("TapeClassInstaller()\n");
410 return ERROR_DI_DO_DEFAULT;
411 }
412
413
414 /*
415 * @implemented
416 */
417 DWORD
418 WINAPI
419 VolumeClassInstaller(
420 IN DI_FUNCTION InstallFunction,
421 IN HDEVINFO DeviceInfoSet,
422 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
423 {
424 DPRINT("VolumeClassInstaller()\n");
425 return ERROR_DI_DO_DEFAULT;
426 }
427
428 /* EOF */