[SETUPAPI] SetupDiCreateDevRegKeyW / SetupDiOpenDevRegKey: Create or open the 'Device...
[reactos.git] / dll / win32 / setupapi / devinst.c
1 /*
2 * SetupAPI device installer
3 *
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "setupapi_private.h"
23
24 /* Unicode constants */
25 static const WCHAR BackSlash[] = {'\\',0};
26 static const WCHAR DateFormat[] = {'%','u','-','%','u','-','%','u',0};
27 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
28 static const WCHAR DotHW[] = {'.','H','W',0};
29 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
30 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
31 static const WCHAR InstanceKeyFormat[] = {'%','0','4','l','u',0};
32 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
33 static const WCHAR VersionFormat[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
34
35 static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0};
36 static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
37 static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
38 static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0};
39 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
40
41 typedef DWORD
42 (CALLBACK* CLASS_INSTALL_PROC) (
43 IN DI_FUNCTION InstallFunction,
44 IN HDEVINFO DeviceInfoSet,
45 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL);
46 typedef BOOL
47 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
48 IN HDEVINFO DeviceInfoSet,
49 IN OUT PSP_DEVINFO_DATA DeviceInfoData);
50 typedef DWORD
51 (CALLBACK* COINSTALLER_PROC) (
52 IN DI_FUNCTION InstallFunction,
53 IN HDEVINFO DeviceInfoSet,
54 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
55 IN OUT PCOINSTALLER_CONTEXT_DATA Context);
56
57 struct CoInstallerElement
58 {
59 LIST_ENTRY ListEntry;
60
61 HMODULE Module;
62 COINSTALLER_PROC Function;
63 BOOL DoPostProcessing;
64 PVOID PrivateData;
65 };
66
67 struct GetSectionCallbackInfo
68 {
69 PSP_ALTPLATFORM_INFO PlatformInfo;
70 BYTE ProductType;
71 WORD SuiteMask;
72 DWORD PrefixLength;
73 WCHAR BestSection[LINE_LEN + 1];
74 DWORD BestScore1, BestScore2, BestScore3, BestScore4, BestScore5;
75 };
76
77
78
79 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
80 {
81 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
82 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
83 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
84 '0','2','X','}',0};
85
86 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
87 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
88 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
89 }
90
91 static DWORD
92 GetErrorCodeFromCrCode(const IN CONFIGRET cr)
93 {
94 switch (cr)
95 {
96 case CR_ACCESS_DENIED: return ERROR_ACCESS_DENIED;
97 case CR_BUFFER_SMALL: return ERROR_INSUFFICIENT_BUFFER;
98 case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED;
99 case CR_FAILURE: return ERROR_GEN_FAILURE;
100 case CR_INVALID_DATA: return ERROR_INVALID_USER_BUFFER;
101 case CR_INVALID_DEVICE_ID: return ERROR_INVALID_PARAMETER;
102 case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
103 case CR_INVALID_DEVNODE: return ERROR_INVALID_PARAMETER;
104 case CR_INVALID_FLAG: return ERROR_INVALID_FLAGS;
105 case CR_INVALID_POINTER: return ERROR_INVALID_PARAMETER;
106 case CR_INVALID_PROPERTY: return ERROR_INVALID_PARAMETER;
107 case CR_NO_SUCH_DEVNODE: return ERROR_FILE_NOT_FOUND;
108 case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND;
109 case CR_NO_SUCH_VALUE: return ERROR_FILE_NOT_FOUND;
110 case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
111 case CR_REGISTRY_ERROR: return ERROR_GEN_FAILURE;
112 case CR_ALREADY_SUCH_DEVINST: return ERROR_DEVINST_ALREADY_EXISTS;
113 case CR_SUCCESS: return ERROR_SUCCESS;
114 default: return ERROR_GEN_FAILURE;
115 }
116
117 /* Does not happen */
118 }
119
120 /* Lower scores are best ones */
121 static BOOL
122 CheckSectionValid(
123 IN LPCWSTR SectionName,
124 IN PSP_ALTPLATFORM_INFO PlatformInfo,
125 IN BYTE ProductType,
126 IN WORD SuiteMask,
127 OUT PDWORD ScorePlatform,
128 OUT PDWORD ScoreMajorVersion,
129 OUT PDWORD ScoreMinorVersion,
130 OUT PDWORD ScoreProductType,
131 OUT PDWORD ScoreSuiteMask)
132 {
133 LPWSTR Section = NULL;
134 //LPCWSTR pExtensionPlatform;
135 LPCWSTR pExtensionArchitecture;
136 LPWSTR Fields[6];
137 DWORD i;
138 BOOL ret = FALSE;
139
140 //static const WCHAR ExtensionPlatformNone[] = {'.',0};
141 static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
142 static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
143
144 static const WCHAR ExtensionArchitectureNone[] = {0};
145 static const WCHAR ExtensionArchitecturealpha[] = {'a','l','p','h','a',0};
146 static const WCHAR ExtensionArchitectureamd64[] = {'A','M','D','6','4',0};
147 static const WCHAR ExtensionArchitectureia64[] = {'I','A','6','4',0};
148 static const WCHAR ExtensionArchitecturemips[] = {'m','i','p','s',0};
149 static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
150 static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
151
152 TRACE("%s %p 0x%x 0x%x\n",
153 debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask);
154
155 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0;
156
157 Section = pSetupDuplicateString(SectionName);
158 if (!Section)
159 {
160 TRACE("pSetupDuplicateString() failed\n");
161 goto cleanup;
162 }
163
164 /* Set various extensions values */
165 switch (PlatformInfo->Platform)
166 {
167 case VER_PLATFORM_WIN32_WINDOWS:
168 //pExtensionPlatform = ExtensionPlatformWindows;
169 break;
170 case VER_PLATFORM_WIN32_NT:
171 //pExtensionPlatform = ExtensionPlatformNT;
172 break;
173 default:
174 ERR("Unknown platform 0x%lx\n", PlatformInfo->Platform);
175 //pExtensionPlatform = ExtensionPlatformNone;
176 break;
177 }
178 switch (PlatformInfo->ProcessorArchitecture)
179 {
180 case PROCESSOR_ARCHITECTURE_ALPHA:
181 pExtensionArchitecture = ExtensionArchitecturealpha;
182 break;
183 case PROCESSOR_ARCHITECTURE_AMD64:
184 pExtensionArchitecture = ExtensionArchitectureamd64;
185 break;
186 case PROCESSOR_ARCHITECTURE_IA64:
187 pExtensionArchitecture = ExtensionArchitectureia64;
188 break;
189 case PROCESSOR_ARCHITECTURE_INTEL:
190 pExtensionArchitecture = ExtensionArchitecturex86;
191 break;
192 case PROCESSOR_ARCHITECTURE_MIPS:
193 pExtensionArchitecture = ExtensionArchitecturemips;
194 break;
195 case PROCESSOR_ARCHITECTURE_PPC:
196 pExtensionArchitecture = ExtensionArchitectureppc;
197 break;
198 default:
199 ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture);
200 case PROCESSOR_ARCHITECTURE_UNKNOWN:
201 pExtensionArchitecture = ExtensionArchitectureNone;
202 break;
203 }
204
205 /*
206 * Field[0] Platform
207 * Field[1] Architecture
208 * Field[2] Major version
209 * Field[3] Minor version
210 * Field[4] Product type
211 * Field[5] Suite mask
212 * Remark: these fields may be NULL if the information is not provided
213 */
214 Fields[0] = Section;
215 if (Fields[0] == NULL)
216 {
217 TRACE("No extension found\n");
218 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX;
219 ret = TRUE;
220 goto cleanup;
221 }
222 Fields[1] = Fields[0] + 1;
223 Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL;
224 for (i = 2; Fields[i - 1] != NULL && i < 6; i++)
225 {
226 Fields[i] = wcschr(Fields[i - 1], '.');
227 if (Fields[i])
228 {
229 Fields[i]++;
230 *(Fields[i] - 1) = UNICODE_NULL;
231 }
232 }
233 /* Take care of first 2 fields */
234 if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0)
235 {
236 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS)
237 {
238 TRACE("Mismatch on platform field\n");
239 goto cleanup;
240 }
241 Fields[1] += wcslen(ExtensionPlatformWindows) - 1;
242 }
243 else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0)
244 {
245 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT)
246 {
247 TRACE("Mismatch on platform field\n");
248 goto cleanup;
249 }
250 Fields[1] += wcslen(ExtensionPlatformNT) - 1;
251 }
252 else
253 {
254 /* No platform specified */
255 *ScorePlatform |= 0x02;
256 }
257 if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0)
258 {
259 /* No architecture specified */
260 *ScorePlatform |= 0x01;
261 }
262 else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0)
263 {
264 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
265 debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture));
266 goto cleanup;
267 }
268
269 /* Check if informations are matching */
270 if (Fields[2] && *Fields[2])
271 {
272 DWORD MajorVersion, MinorVersion = 0;
273 MajorVersion = strtoulW(Fields[2], NULL, 0);
274 if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) &&
275 (errno == ERANGE || errno == EINVAL))
276 {
277 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2]));
278 goto cleanup;
279 }
280 if (Fields[3] && *Fields[3])
281 {
282 MinorVersion = strtoulW(Fields[3], NULL, 0);
283 if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) &&
284 (errno == ERANGE || errno == EINVAL))
285 {
286 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3]));
287 goto cleanup;
288 }
289 }
290 if (PlatformInfo->MajorVersion < MajorVersion ||
291 (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion))
292 {
293 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
294 MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion);
295 goto cleanup;
296 }
297 *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion;
298 if (MajorVersion == PlatformInfo->MajorVersion)
299 *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion;
300 else
301 *ScoreMinorVersion = MinorVersion;
302 }
303 else if (Fields[3] && *Fields[3])
304 {
305 TRACE("Minor version found without major version\n");
306 goto cleanup;
307 }
308 else
309 {
310 *ScoreMajorVersion = PlatformInfo->MajorVersion;
311 *ScoreMinorVersion = PlatformInfo->MinorVersion;
312 }
313
314 if (Fields[4] && *Fields[4])
315 {
316 DWORD CurrentProductType;
317 CurrentProductType = strtoulW(Fields[4], NULL, 0);
318 if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) &&
319 (errno == ERANGE || errno == EINVAL))
320 {
321 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4]));
322 goto cleanup;
323 }
324 if (CurrentProductType != ProductType)
325 {
326 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
327 CurrentProductType, ProductType);
328 goto cleanup;
329 }
330 }
331 else
332 *ScoreProductType = 1;
333
334 if (Fields[5] && *Fields[5])
335 {
336 DWORD CurrentSuiteMask;
337 CurrentSuiteMask = strtoulW(Fields[5], NULL, 0);
338 if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) &&
339 (errno == ERANGE || errno == EINVAL))
340 {
341 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5]));
342 goto cleanup;
343 }
344 if ((CurrentSuiteMask & ~SuiteMask) != 0)
345 {
346 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
347 CurrentSuiteMask, SuiteMask);
348 goto cleanup;
349 }
350 *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask;
351 }
352 else
353 *ScoreSuiteMask = SuiteMask;
354
355 ret = TRUE;
356
357 cleanup:
358 MyFree(Section);
359 return ret;
360 }
361
362 static BOOL
363 GetSectionCallback(
364 IN LPCWSTR SectionName,
365 IN PVOID Context)
366 {
367 struct GetSectionCallbackInfo *info = Context;
368 DWORD Score1, Score2, Score3, Score4, Score5;
369 BOOL ret;
370
371 if (SectionName[info->PrefixLength] != '.')
372 return TRUE;
373
374 ret = CheckSectionValid(
375 &SectionName[info->PrefixLength],
376 info->PlatformInfo,
377 info->ProductType,
378 info->SuiteMask,
379 &Score1, &Score2, &Score3, &Score4, &Score5);
380 if (!ret)
381 {
382 TRACE("Section %s not compatible\n", debugstr_w(SectionName));
383 return TRUE;
384 }
385 if (Score1 > info->BestScore1) goto done;
386 if (Score1 < info->BestScore1) goto bettersection;
387 if (Score2 > info->BestScore2) goto done;
388 if (Score2 < info->BestScore2) goto bettersection;
389 if (Score3 > info->BestScore3) goto done;
390 if (Score3 < info->BestScore3) goto bettersection;
391 if (Score4 > info->BestScore4) goto done;
392 if (Score4 < info->BestScore4) goto bettersection;
393 if (Score5 > info->BestScore5) goto done;
394 if (Score5 < info->BestScore5) goto bettersection;
395 goto done;
396
397 bettersection:
398 strcpyW(info->BestSection, SectionName);
399 info->BestScore1 = Score1;
400 info->BestScore2 = Score2;
401 info->BestScore3 = Score3;
402 info->BestScore4 = Score4;
403 info->BestScore5 = Score5;
404
405 done:
406 return TRUE;
407 }
408
409 /***********************************************************************
410 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
411 */
412 BOOL WINAPI
413 SetupDiGetActualSectionToInstallExW(
414 IN HINF InfHandle,
415 IN PCWSTR InfSectionName,
416 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
417 OUT PWSTR InfSectionWithExt OPTIONAL,
418 IN DWORD InfSectionWithExtSize,
419 OUT PDWORD RequiredSize OPTIONAL,
420 OUT PWSTR* Extension OPTIONAL,
421 IN PVOID Reserved)
422 {
423 BOOL ret = FALSE;
424
425 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName),
426 AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
427 RequiredSize, Extension, Reserved);
428
429 if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
430 SetLastError(ERROR_INVALID_HANDLE);
431 else if (!InfSectionName)
432 SetLastError(ERROR_INVALID_PARAMETER);
433 else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
434 SetLastError(ERROR_INVALID_USER_BUFFER);
435 else if (Reserved != NULL)
436 SetLastError(ERROR_INVALID_PARAMETER);
437 else
438 {
439 static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
440 static BYTE CurrentProductType = 0;
441 static WORD CurrentSuiteMask = 0;
442 PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
443 struct GetSectionCallbackInfo CallbackInfo;
444 DWORD dwFullLength;
445 BYTE ProductType;
446 WORD SuiteMask;
447
448 /* Fill platform info if needed */
449 if (AlternatePlatformInfo)
450 {
451 pPlatformInfo = AlternatePlatformInfo;
452 ProductType = 0;
453 SuiteMask = 0;
454 }
455 else
456 {
457 if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
458 {
459 /* That's the first time we go here. We need to fill in the structure */
460 SYSTEM_INFO SystemInfo;
461 GetSystemInfo(&SystemInfo);
462 CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
463 CurrentPlatform.Platform = OsVersionInfo.dwPlatformId;
464 CurrentPlatform.MajorVersion = OsVersionInfo.dwMajorVersion;
465 CurrentPlatform.MinorVersion = OsVersionInfo.dwMinorVersion;
466 CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
467 CurrentPlatform.Reserved = 0;
468 CurrentProductType = OsVersionInfo.wProductType;
469 CurrentSuiteMask = OsVersionInfo.wSuiteMask;
470 }
471 ProductType = CurrentProductType;
472 SuiteMask = CurrentSuiteMask;
473 }
474
475 CallbackInfo.PlatformInfo = pPlatformInfo;
476 CallbackInfo.ProductType = ProductType;
477 CallbackInfo.SuiteMask = SuiteMask;
478 CallbackInfo.PrefixLength = strlenW(InfSectionName);
479 CallbackInfo.BestScore1 = ULONG_MAX;
480 CallbackInfo.BestScore2 = ULONG_MAX;
481 CallbackInfo.BestScore3 = ULONG_MAX;
482 CallbackInfo.BestScore4 = ULONG_MAX;
483 CallbackInfo.BestScore5 = ULONG_MAX;
484 strcpyW(CallbackInfo.BestSection, InfSectionName);
485 TRACE("EnumerateSectionsStartingWith(InfSectionName = %S)\n", InfSectionName);
486 if (!EnumerateSectionsStartingWith(
487 InfHandle,
488 InfSectionName,
489 GetSectionCallback,
490 &CallbackInfo))
491 {
492 SetLastError(ERROR_GEN_FAILURE);
493 goto done;
494 }
495 TRACE("CallbackInfo.BestSection = %S\n", CallbackInfo.BestSection);
496
497 dwFullLength = lstrlenW(CallbackInfo.BestSection);
498 if (RequiredSize != NULL)
499 *RequiredSize = dwFullLength + 1;
500
501 if (InfSectionWithExtSize > 0)
502 {
503 if (InfSectionWithExtSize < dwFullLength + 1)
504 {
505 SetLastError(ERROR_INSUFFICIENT_BUFFER);
506 goto done;
507 }
508 strcpyW(InfSectionWithExt, CallbackInfo.BestSection);
509 if (Extension)
510 {
511 DWORD dwLength = lstrlenW(InfSectionName);
512 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
513 }
514 }
515
516 ret = TRUE;
517 }
518
519 done:
520 TRACE("Returning %d\n", ret);
521 return ret;
522 }
523
524
525 BOOL
526 CreateDeviceInfo(
527 IN struct DeviceInfoSet *list,
528 IN LPCWSTR InstancePath,
529 IN LPCGUID pClassGuid,
530 OUT struct DeviceInfo **pDeviceInfo)
531 {
532 DWORD size;
533 CONFIGRET cr;
534 struct DeviceInfo *deviceInfo;
535
536 *pDeviceInfo = NULL;
537
538 size = FIELD_OFFSET(struct DeviceInfo, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR);
539 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
540 if (!deviceInfo)
541 {
542 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
543 return FALSE;
544 }
545 ZeroMemory(deviceInfo, size);
546
547 cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
548 if (cr != CR_SUCCESS)
549 {
550 SetLastError(GetErrorCodeFromCrCode(cr));
551 return FALSE;
552 }
553
554 deviceInfo->set = list;
555 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
556 strcpyW(deviceInfo->Data, InstancePath);
557 deviceInfo->instanceId = deviceInfo->Data;
558 deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\');
559 deviceInfo->DeviceDescription = NULL;
560 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
561 deviceInfo->CreationFlags = 0;
562 InitializeListHead(&deviceInfo->DriverListHead);
563 InitializeListHead(&deviceInfo->InterfaceListHead);
564
565 *pDeviceInfo = deviceInfo;
566 return TRUE;
567 }
568
569
570 static BOOL
571 DestroyClassInstallParams(struct ClassInstallParams* installParams)
572 {
573 HeapFree(GetProcessHeap(), 0, installParams->PropChangeParams);
574 HeapFree(GetProcessHeap(), 0, installParams->AddPropertyPageData);
575 return TRUE;
576 }
577
578 static BOOL
579 DestroyDeviceInfo(struct DeviceInfo *deviceInfo)
580 {
581 PLIST_ENTRY ListEntry;
582 struct DriverInfoElement *driverInfo;
583 struct DeviceInterface *deviceInterface;
584
585 while (!IsListEmpty(&deviceInfo->DriverListHead))
586 {
587 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
588 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
589 if (!DestroyDriverInfoElement(driverInfo))
590 return FALSE;
591 }
592 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
593 {
594 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
595 deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry);
596 if (!DestroyDeviceInterface(deviceInterface))
597 return FALSE;
598 }
599 DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
600 if (deviceInfo->hmodDevicePropPageProvider)
601 FreeLibrary(deviceInfo->hmodDevicePropPageProvider);
602 return HeapFree(GetProcessHeap(), 0, deviceInfo);
603 }
604
605 static BOOL
606 DestroyDeviceInfoSet(struct DeviceInfoSet* list)
607 {
608 PLIST_ENTRY ListEntry;
609 struct DeviceInfo *deviceInfo;
610
611 while (!IsListEmpty(&list->ListHead))
612 {
613 ListEntry = RemoveHeadList(&list->ListHead);
614 deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry);
615 if (!DestroyDeviceInfo(deviceInfo))
616 return FALSE;
617 }
618 if (list->HKLM != HKEY_LOCAL_MACHINE)
619 RegCloseKey(list->HKLM);
620 CM_Disconnect_Machine(list->hMachine);
621 DestroyClassInstallParams(&list->ClassInstallParams);
622 if (list->hmodClassPropPageProvider)
623 FreeLibrary(list->hmodClassPropPageProvider);
624 return HeapFree(GetProcessHeap(), 0, list);
625 }
626
627 /***********************************************************************
628 * SetupDiBuildClassInfoList (SETUPAPI.@)
629 *
630 * Returns a list of setup class GUIDs that identify the classes
631 * that are installed on a local machine.
632 *
633 * PARAMS
634 * Flags [I] control exclusion of classes from the list.
635 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
636 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
637 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
638 *
639 * RETURNS
640 * Success: TRUE.
641 * Failure: FALSE.
642 */
643 BOOL WINAPI SetupDiBuildClassInfoList(
644 DWORD Flags,
645 LPGUID ClassGuidList,
646 DWORD ClassGuidListSize,
647 PDWORD RequiredSize)
648 {
649 TRACE("\n");
650 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
651 ClassGuidListSize, RequiredSize,
652 NULL, NULL);
653 }
654
655 /***********************************************************************
656 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
657 *
658 * Returns a list of setup class GUIDs that identify the classes
659 * that are installed on a local or remote machine.
660 *
661 * PARAMS
662 * Flags [I] control exclusion of classes from the list.
663 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
664 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
665 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
666 * MachineName [I] name of a remote machine.
667 * Reserved [I] must be NULL.
668 *
669 * RETURNS
670 * Success: TRUE.
671 * Failure: FALSE.
672 */
673 BOOL WINAPI SetupDiBuildClassInfoListExA(
674 DWORD Flags,
675 LPGUID ClassGuidList,
676 DWORD ClassGuidListSize,
677 PDWORD RequiredSize,
678 LPCSTR MachineName,
679 PVOID Reserved)
680 {
681 LPWSTR MachineNameW = NULL;
682 BOOL bResult;
683
684 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
685 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved);
686
687 if (MachineName)
688 {
689 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
690 if (MachineNameW == NULL) return FALSE;
691 }
692
693 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
694 ClassGuidListSize, RequiredSize,
695 MachineNameW, Reserved);
696
697 MyFree(MachineNameW);
698
699 return bResult;
700 }
701
702 /***********************************************************************
703 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
704 *
705 * Returns a list of setup class GUIDs that identify the classes
706 * that are installed on a local or remote machine.
707 *
708 * PARAMS
709 * Flags [I] control exclusion of classes from the list.
710 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
711 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
712 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
713 * MachineName [I] name of a remote machine.
714 * Reserved [I] must be NULL.
715 *
716 * RETURNS
717 * Success: TRUE.
718 * Failure: FALSE.
719 */
720 BOOL WINAPI SetupDiBuildClassInfoListExW(
721 DWORD Flags,
722 LPGUID ClassGuidList,
723 DWORD ClassGuidListSize,
724 PDWORD RequiredSize,
725 LPCWSTR MachineName,
726 PVOID Reserved)
727 {
728 WCHAR szKeyName[40];
729 HKEY hClassesKey = INVALID_HANDLE_VALUE;
730 HKEY hClassKey;
731 DWORD dwLength;
732 DWORD dwIndex;
733 LONG lError;
734 DWORD dwGuidListIndex = 0;
735
736 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
737 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
738
739 if (!RequiredSize)
740 {
741 SetLastError(ERROR_INVALID_PARAMETER);
742 return FALSE;
743 }
744 else if (!ClassGuidList && ClassGuidListSize > 0)
745 {
746 SetLastError(ERROR_INVALID_PARAMETER);
747 return FALSE;
748 }
749
750 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
751 KEY_ENUMERATE_SUB_KEYS,
752 DIOCR_INSTALLER,
753 MachineName,
754 Reserved);
755 if (hClassesKey == INVALID_HANDLE_VALUE)
756 {
757 return FALSE;
758 }
759
760 for (dwIndex = 0; ; dwIndex++)
761 {
762 dwLength = 40;
763 lError = RegEnumKeyExW(hClassesKey,
764 dwIndex,
765 szKeyName,
766 &dwLength,
767 NULL,
768 NULL,
769 NULL,
770 NULL);
771 TRACE("RegEnumKeyExW() returns %d\n", lError);
772 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
773 {
774 TRACE("Key name: %s\n", debugstr_w(szKeyName));
775
776 if (RegOpenKeyExW(hClassesKey,
777 szKeyName,
778 0,
779 KEY_QUERY_VALUE,
780 &hClassKey))
781 {
782 RegCloseKey(hClassesKey);
783 return FALSE;
784 }
785
786 if (!RegQueryValueExW(hClassKey,
787 REGSTR_VAL_NOUSECLASS,
788 NULL,
789 NULL,
790 NULL,
791 NULL))
792 {
793 TRACE("'NoUseClass' value found!\n");
794 RegCloseKey(hClassKey);
795 continue;
796 }
797
798 if ((Flags & DIBCI_NOINSTALLCLASS) &&
799 (!RegQueryValueExW(hClassKey,
800 REGSTR_VAL_NOINSTALLCLASS,
801 NULL,
802 NULL,
803 NULL,
804 NULL)))
805 {
806 TRACE("'NoInstallClass' value found!\n");
807 RegCloseKey(hClassKey);
808 continue;
809 }
810
811 if ((Flags & DIBCI_NODISPLAYCLASS) &&
812 (!RegQueryValueExW(hClassKey,
813 REGSTR_VAL_NODISPLAYCLASS,
814 NULL,
815 NULL,
816 NULL,
817 NULL)))
818 {
819 TRACE("'NoDisplayClass' value found!\n");
820 RegCloseKey(hClassKey);
821 continue;
822 }
823
824 RegCloseKey(hClassKey);
825
826 TRACE("Guid: %s\n", debugstr_w(szKeyName));
827 if (dwGuidListIndex < ClassGuidListSize)
828 {
829 if (szKeyName[0] == '{' && szKeyName[37] == '}')
830 {
831 szKeyName[37] = 0;
832 }
833 TRACE("Guid: %p\n", &szKeyName[1]);
834
835 UuidFromStringW(&szKeyName[1],
836 &ClassGuidList[dwGuidListIndex]);
837 }
838
839 dwGuidListIndex++;
840 }
841
842 if (lError != ERROR_SUCCESS)
843 break;
844 }
845
846 RegCloseKey(hClassesKey);
847
848 if (RequiredSize != NULL)
849 *RequiredSize = dwGuidListIndex;
850
851 if (ClassGuidListSize < dwGuidListIndex)
852 {
853 SetLastError(ERROR_INSUFFICIENT_BUFFER);
854 return FALSE;
855 }
856
857 return TRUE;
858 }
859
860 /***********************************************************************
861 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
862 */
863 BOOL WINAPI SetupDiClassGuidsFromNameA(
864 LPCSTR ClassName,
865 LPGUID ClassGuidList,
866 DWORD ClassGuidListSize,
867 PDWORD RequiredSize)
868 {
869 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
870 ClassGuidListSize, RequiredSize,
871 NULL, NULL);
872 }
873
874 /***********************************************************************
875 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
876 */
877 BOOL WINAPI SetupDiClassGuidsFromNameW(
878 LPCWSTR ClassName,
879 LPGUID ClassGuidList,
880 DWORD ClassGuidListSize,
881 PDWORD RequiredSize)
882 {
883 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
884 ClassGuidListSize, RequiredSize,
885 NULL, NULL);
886 }
887
888 /***********************************************************************
889 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
890 */
891 BOOL WINAPI SetupDiClassGuidsFromNameExA(
892 LPCSTR ClassName,
893 LPGUID ClassGuidList,
894 DWORD ClassGuidListSize,
895 PDWORD RequiredSize,
896 LPCSTR MachineName,
897 PVOID Reserved)
898 {
899 LPWSTR ClassNameW = NULL;
900 LPWSTR MachineNameW = NULL;
901 BOOL bResult;
902
903 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName), ClassGuidList,
904 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved);
905
906 if (!ClassName)
907 {
908 SetLastError(ERROR_INVALID_PARAMETER);
909 return FALSE;
910 }
911
912 ClassNameW = pSetupMultiByteToUnicode(ClassName, CP_ACP);
913 if (ClassNameW == NULL)
914 return FALSE;
915
916 if (MachineName)
917 {
918 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
919 if (MachineNameW == NULL)
920 {
921 MyFree(ClassNameW);
922 return FALSE;
923 }
924 }
925
926 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
927 ClassGuidListSize, RequiredSize,
928 MachineNameW, Reserved);
929
930 MyFree(MachineNameW);
931 MyFree(ClassNameW);
932
933 return bResult;
934 }
935
936 /***********************************************************************
937 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
938 */
939 BOOL WINAPI SetupDiClassGuidsFromNameExW(
940 LPCWSTR ClassName,
941 LPGUID ClassGuidList,
942 DWORD ClassGuidListSize,
943 PDWORD RequiredSize,
944 LPCWSTR MachineName,
945 PVOID Reserved)
946 {
947 WCHAR szKeyName[40];
948 WCHAR szClassName[MAX_CLASS_NAME_LEN];
949 HKEY hClassesKey;
950 HKEY hClassKey;
951 DWORD dwLength;
952 DWORD dwIndex;
953 LONG lError;
954 DWORD dwGuidListIndex = 0;
955
956 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
957 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
958
959 if (!ClassName || !RequiredSize)
960 {
961 SetLastError(ERROR_INVALID_PARAMETER);
962 return FALSE;
963 }
964 if (!ClassGuidList && ClassGuidListSize > 0)
965 {
966 SetLastError(ERROR_INVALID_PARAMETER);
967 return FALSE;
968 }
969 *RequiredSize = 0;
970
971 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
972 KEY_ENUMERATE_SUB_KEYS,
973 DIOCR_INSTALLER,
974 MachineName,
975 Reserved);
976 if (hClassesKey == INVALID_HANDLE_VALUE)
977 {
978 return FALSE;
979 }
980
981 for (dwIndex = 0; ; dwIndex++)
982 {
983 dwLength = 40;
984 lError = RegEnumKeyExW(hClassesKey,
985 dwIndex,
986 szKeyName,
987 &dwLength,
988 NULL,
989 NULL,
990 NULL,
991 NULL);
992 TRACE("RegEnumKeyExW() returns %d\n", lError);
993 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
994 {
995 TRACE("Key name: %p\n", szKeyName);
996
997 if (RegOpenKeyExW(hClassesKey,
998 szKeyName,
999 0,
1000 KEY_QUERY_VALUE,
1001 &hClassKey))
1002 {
1003 RegCloseKey(hClassesKey);
1004 return FALSE;
1005 }
1006
1007 dwLength = MAX_CLASS_NAME_LEN * sizeof(WCHAR);
1008 if (!RegQueryValueExW(hClassKey,
1009 REGSTR_VAL_CLASS,
1010 NULL,
1011 NULL,
1012 (LPBYTE)szClassName,
1013 &dwLength))
1014 {
1015 TRACE("Class name: %p\n", szClassName);
1016
1017 if (strcmpiW(szClassName, ClassName) == 0)
1018 {
1019 TRACE("Found matching class name\n");
1020
1021 TRACE("Guid: %p\n", szKeyName);
1022 if (dwGuidListIndex < ClassGuidListSize)
1023 {
1024 if (szKeyName[0] == '{' && szKeyName[37] == '}')
1025 {
1026 szKeyName[37] = 0;
1027 }
1028 TRACE("Guid: %p\n", &szKeyName[1]);
1029
1030 UuidFromStringW(&szKeyName[1],
1031 &ClassGuidList[dwGuidListIndex]);
1032 }
1033
1034 dwGuidListIndex++;
1035 }
1036 }
1037
1038 RegCloseKey(hClassKey);
1039 }
1040
1041 if (lError != ERROR_SUCCESS)
1042 break;
1043 }
1044
1045 RegCloseKey(hClassesKey);
1046
1047 if (RequiredSize != NULL)
1048 *RequiredSize = dwGuidListIndex;
1049
1050 if (ClassGuidListSize < dwGuidListIndex)
1051 {
1052 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1053 return FALSE;
1054 }
1055
1056 return TRUE;
1057 }
1058
1059 /***********************************************************************
1060 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1061 */
1062 BOOL WINAPI SetupDiClassNameFromGuidA(
1063 const GUID* ClassGuid,
1064 PSTR ClassName,
1065 DWORD ClassNameSize,
1066 PDWORD RequiredSize)
1067 {
1068 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
1069 ClassNameSize, RequiredSize,
1070 NULL, NULL);
1071 }
1072
1073 /***********************************************************************
1074 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1075 */
1076 BOOL WINAPI SetupDiClassNameFromGuidW(
1077 const GUID* ClassGuid,
1078 PWSTR ClassName,
1079 DWORD ClassNameSize,
1080 PDWORD RequiredSize)
1081 {
1082 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
1083 ClassNameSize, RequiredSize,
1084 NULL, NULL);
1085 }
1086
1087 /***********************************************************************
1088 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1089 */
1090 BOOL WINAPI SetupDiClassNameFromGuidExA(
1091 const GUID* ClassGuid,
1092 PSTR ClassName,
1093 DWORD ClassNameSize,
1094 PDWORD RequiredSize,
1095 PCSTR MachineName,
1096 PVOID Reserved)
1097 {
1098 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
1099 LPWSTR MachineNameW = NULL;
1100 BOOL ret;
1101
1102 if (MachineName)
1103 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
1104 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
1105 RequiredSize, MachineNameW, Reserved);
1106 if (ret)
1107 {
1108 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
1109 ClassNameSize, NULL, NULL);
1110 if (len == 0 || len > ClassNameSize)
1111 {
1112 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1113 ret = FALSE;
1114 }
1115 }
1116 MyFree(MachineNameW);
1117 return ret;
1118 }
1119
1120 /***********************************************************************
1121 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1122 */
1123 BOOL WINAPI SetupDiClassNameFromGuidExW(
1124 const GUID* ClassGuid,
1125 PWSTR ClassName,
1126 DWORD ClassNameSize,
1127 PDWORD RequiredSize,
1128 PCWSTR MachineName,
1129 PVOID Reserved)
1130 {
1131 HKEY hKey;
1132 DWORD dwLength;
1133 DWORD dwRegType;
1134 LONG rc;
1135 PWSTR Buffer;
1136
1137 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
1138 ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
1139
1140 /* Make sure there's a GUID */
1141 if (ClassGuid == NULL)
1142 {
1143 SetLastError(ERROR_INVALID_CLASS); /* On Vista: ERROR_INVALID_USER_BUFFER */
1144 return FALSE;
1145 }
1146
1147 /* Make sure there's a real buffer when there's a size */
1148 if ((ClassNameSize > 0) && (ClassName == NULL))
1149 {
1150 SetLastError(ERROR_INVALID_PARAMETER); /* On Vista: ERROR_INVALID_USER_BUFFER */
1151 return FALSE;
1152 }
1153
1154 /* Open the key for the GUID */
1155 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, KEY_QUERY_VALUE, DIOCR_INSTALLER, MachineName, Reserved);
1156
1157 if (hKey == INVALID_HANDLE_VALUE)
1158 return FALSE;
1159
1160 /* Retrieve the class name data and close the key */
1161 rc = QueryRegistryValue(hKey, REGSTR_VAL_CLASS, (LPBYTE *) &Buffer, &dwRegType, &dwLength);
1162 RegCloseKey(hKey);
1163
1164 /* Make sure we got the data */
1165 if (rc != ERROR_SUCCESS)
1166 {
1167 SetLastError(rc);
1168 return FALSE;
1169 }
1170
1171 /* Make sure the data is a string */
1172 if (dwRegType != REG_SZ)
1173 {
1174 MyFree(Buffer);
1175 SetLastError(ERROR_GEN_FAILURE);
1176 return FALSE;
1177 }
1178
1179 /* Determine the length of the class name */
1180 dwLength /= sizeof(WCHAR);
1181
1182 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
1183 /* Count the null-terminator */
1184 dwLength++;
1185
1186 /* Inform the caller about the class name */
1187 if ((ClassName != NULL) && (dwLength <= ClassNameSize))
1188 {
1189 memcpy(ClassName, Buffer, (dwLength - 1) * sizeof(WCHAR));
1190 ClassName[dwLength - 1] = UNICODE_NULL;
1191 }
1192
1193 /* Inform the caller about the required size */
1194 if (RequiredSize != NULL)
1195 *RequiredSize = dwLength;
1196
1197 /* Clean up the buffer */
1198 MyFree(Buffer);
1199
1200 /* Make sure the buffer was large enough */
1201 if ((ClassName == NULL) || (dwLength > ClassNameSize))
1202 {
1203 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1204 return FALSE;
1205 }
1206
1207 return TRUE;
1208 }
1209
1210 /***********************************************************************
1211 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1212 */
1213 HDEVINFO WINAPI
1214 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1215 HWND hwndParent)
1216 {
1217 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1218 }
1219
1220 /***********************************************************************
1221 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1222 */
1223 HDEVINFO WINAPI
1224 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1225 HWND hwndParent,
1226 PCSTR MachineName,
1227 PVOID Reserved)
1228 {
1229 LPWSTR MachineNameW = NULL;
1230 HDEVINFO hDevInfo;
1231
1232 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1233 debugstr_a(MachineName), Reserved);
1234
1235 if (MachineName)
1236 {
1237 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
1238 if (MachineNameW == NULL)
1239 return INVALID_HANDLE_VALUE;
1240 }
1241
1242 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1243 MachineNameW, Reserved);
1244
1245 MyFree(MachineNameW);
1246
1247 return hDevInfo;
1248 }
1249
1250 /***********************************************************************
1251 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1252 *
1253 * Create an empty DeviceInfoSet list.
1254 *
1255 * PARAMS
1256 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1257 * with this list.
1258 * hwndParent [I] hwnd needed for interface related actions.
1259 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1260 * local registry will be used.
1261 * Reserved [I] must be NULL
1262 *
1263 * RETURNS
1264 * Success: empty list.
1265 * Failure: INVALID_HANDLE_VALUE.
1266 */
1267 HDEVINFO WINAPI
1268 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1269 HWND hwndParent,
1270 PCWSTR MachineName,
1271 PVOID Reserved)
1272 {
1273 struct DeviceInfoSet *list = NULL;
1274 DWORD size = FIELD_OFFSET(struct DeviceInfoSet, szData);
1275 DWORD rc;
1276 CONFIGRET cr;
1277 HDEVINFO ret = INVALID_HANDLE_VALUE;
1278
1279 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1280 debugstr_w(MachineName), Reserved);
1281
1282 if (MachineName != NULL)
1283 {
1284 SIZE_T len = strlenW(MachineName);
1285 if (len >= SP_MAX_MACHINENAME_LENGTH - 4)
1286 {
1287 SetLastError(ERROR_INVALID_MACHINENAME);
1288 goto cleanup;
1289 }
1290 if(len > 0)
1291 size += (len + 3) * sizeof(WCHAR);
1292 else
1293 MachineName = NULL;
1294 }
1295
1296 if (Reserved != NULL)
1297 {
1298 SetLastError(ERROR_INVALID_PARAMETER);
1299 return INVALID_HANDLE_VALUE;
1300 }
1301
1302 list = MyMalloc(size);
1303 if (!list)
1304 {
1305 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1306 return INVALID_HANDLE_VALUE;
1307 }
1308 ZeroMemory(list, FIELD_OFFSET(struct DeviceInfoSet, szData));
1309
1310 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1311 memcpy(&list->ClassGuid,
1312 ClassGuid ? ClassGuid : &GUID_NULL,
1313 sizeof(list->ClassGuid));
1314 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1315 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
1316 list->InstallParams.hwndParent = hwndParent;
1317 if (MachineName)
1318 {
1319 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
1320 if (rc != ERROR_SUCCESS)
1321 {
1322 SetLastError(ERROR_INVALID_MACHINENAME);
1323 goto cleanup;
1324 }
1325
1326 list->szData[0] = list->szData[1] = '\\';
1327 strcpyW(list->szData + 2, MachineName);
1328 list->MachineName = list->szData;
1329 }
1330 else
1331 {
1332 list->HKLM = HKEY_LOCAL_MACHINE;
1333 list->MachineName = NULL;
1334 }
1335 cr = CM_Connect_MachineW(list->MachineName, &list->hMachine);
1336 if (cr != CR_SUCCESS)
1337 {
1338 SetLastError(GetErrorCodeFromCrCode(cr));
1339 goto cleanup;
1340 }
1341 InitializeListHead(&list->DriverListHead);
1342 InitializeListHead(&list->ListHead);
1343
1344 return (HDEVINFO)list;
1345
1346 cleanup:
1347 if (ret == INVALID_HANDLE_VALUE)
1348 {
1349 if (list)
1350 {
1351 if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE)
1352 RegCloseKey(list->HKLM);
1353 MyFree(list);
1354 }
1355 }
1356 return ret;
1357 }
1358
1359 /***********************************************************************
1360 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1361 */
1362 HKEY WINAPI SetupDiCreateDevRegKeyA(
1363 HDEVINFO DeviceInfoSet,
1364 PSP_DEVINFO_DATA DeviceInfoData,
1365 DWORD Scope,
1366 DWORD HwProfile,
1367 DWORD KeyType,
1368 HINF InfHandle,
1369 PCSTR InfSectionName)
1370 {
1371 PWSTR InfSectionNameW = NULL;
1372 HKEY key;
1373
1374 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1375 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1376
1377 if (InfHandle)
1378 {
1379 if (!InfSectionName)
1380 {
1381 SetLastError(ERROR_INVALID_PARAMETER);
1382 return INVALID_HANDLE_VALUE;
1383 }
1384 else
1385 {
1386 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
1387 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1388 }
1389 }
1390 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
1391 HwProfile, KeyType, InfHandle, InfSectionNameW);
1392 MyFree(InfSectionNameW);
1393 return key;
1394 }
1395
1396 static HKEY
1397 OpenHardwareProfileKey(
1398 IN HKEY HKLM,
1399 IN DWORD HwProfile,
1400 IN DWORD samDesired);
1401
1402 /***********************************************************************
1403 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1404 */
1405 HKEY WINAPI SetupDiCreateDevRegKeyW(
1406 HDEVINFO DeviceInfoSet,
1407 PSP_DEVINFO_DATA DeviceInfoData,
1408 DWORD Scope,
1409 DWORD HwProfile,
1410 DWORD KeyType,
1411 HINF InfHandle,
1412 PCWSTR InfSectionName)
1413 {
1414 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1415 HKEY key = INVALID_HANDLE_VALUE;
1416 LPWSTR lpGuidString = NULL;
1417 LPWSTR DriverKey = NULL; /* {GUID}\Index */
1418 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
1419 DWORD Index; /* Index used in the DriverKey name */
1420 DWORD dwSize;
1421 DWORD Disposition;
1422 DWORD rc;
1423 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
1424 HKEY hEnumKey = NULL;
1425 HKEY hClassKey = NULL;
1426 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
1427 HKEY hKey = NULL;
1428 HKEY RootKey;
1429
1430 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1431 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1432
1433 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1434 {
1435 SetLastError(ERROR_INVALID_HANDLE);
1436 return INVALID_HANDLE_VALUE;
1437 }
1438 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1439 {
1440 SetLastError(ERROR_INVALID_HANDLE);
1441 return INVALID_HANDLE_VALUE;
1442 }
1443 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1444 || !DeviceInfoData->Reserved)
1445 {
1446 SetLastError(ERROR_INVALID_PARAMETER);
1447 return INVALID_HANDLE_VALUE;
1448 }
1449 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
1450 {
1451 SetLastError(ERROR_INVALID_FLAGS);
1452 return INVALID_HANDLE_VALUE;
1453 }
1454 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
1455 {
1456 SetLastError(ERROR_INVALID_FLAGS);
1457 return INVALID_HANDLE_VALUE;
1458 }
1459 if (InfHandle && !InfSectionName)
1460 {
1461 SetLastError(ERROR_INVALID_PARAMETER);
1462 return INVALID_HANDLE_VALUE;
1463 }
1464 if (!InfHandle && InfSectionName)
1465 {
1466 SetLastError(ERROR_INVALID_PARAMETER);
1467 return INVALID_HANDLE_VALUE;
1468 }
1469
1470 if (Scope == DICS_FLAG_GLOBAL)
1471 RootKey = set->HKLM;
1472 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1473 {
1474 hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
1475 if (hHWProfileKey == INVALID_HANDLE_VALUE)
1476 goto cleanup;
1477 RootKey = hHWProfileKey;
1478 }
1479
1480 if (KeyType == DIREG_DEV)
1481 {
1482 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1483
1484 rc = RegCreateKeyExW(
1485 RootKey,
1486 REGSTR_PATH_SYSTEMENUM,
1487 0,
1488 NULL,
1489 REG_OPTION_NON_VOLATILE,
1490 KEY_CREATE_SUB_KEY,
1491 NULL,
1492 &hEnumKey,
1493 NULL);
1494 if (rc != ERROR_SUCCESS)
1495 {
1496 SetLastError(rc);
1497 goto cleanup;
1498 }
1499 rc = RegCreateKeyExW(
1500 hEnumKey,
1501 deviceInfo->instanceId,
1502 0,
1503 NULL,
1504 REG_OPTION_NON_VOLATILE,
1505 #if _WIN32_WINNT >= 0x502
1506 KEY_READ | KEY_WRITE,
1507 #else
1508 KEY_ALL_ACCESS,
1509 #endif
1510 NULL,
1511 &hKey,
1512 NULL);
1513 if (rc != ERROR_SUCCESS)
1514 {
1515 SetLastError(rc);
1516 goto cleanup;
1517 }
1518
1519 if (Scope == DICS_FLAG_GLOBAL)
1520 {
1521 HKEY hTempKey = hKey;
1522
1523 rc = RegCreateKeyExW(hTempKey,
1524 L"Device Parameters",
1525 0,
1526 NULL,
1527 REG_OPTION_NON_VOLATILE,
1528 #if _WIN32_WINNT >= 0x502
1529 KEY_READ | KEY_WRITE,
1530 #else
1531 KEY_ALL_ACCESS,
1532 #endif
1533 NULL,
1534 &hKey,
1535 NULL);
1536 if (rc == ERROR_SUCCESS)
1537 RegCloseKey(hTempKey);
1538 }
1539 }
1540 else /* KeyType == DIREG_DRV */
1541 {
1542 /* Open device key, to read Driver value */
1543 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE);
1544 if (hDeviceKey == INVALID_HANDLE_VALUE)
1545 goto cleanup;
1546
1547 rc = RegOpenKeyExW(RootKey, REGSTR_PATH_CLASS_NT, 0, KEY_CREATE_SUB_KEY, &hClassKey);
1548 if (rc != ERROR_SUCCESS)
1549 {
1550 SetLastError(rc);
1551 goto cleanup;
1552 }
1553
1554 rc = RegQueryValueExW(hDeviceKey, REGSTR_VAL_DRIVER, NULL, NULL, NULL, &dwSize);
1555 if (rc != ERROR_SUCCESS)
1556 {
1557 /* Create a new driver key */
1558
1559 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
1560 goto cleanup;
1561
1562 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1563 DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1564 if (!DriverKey)
1565 {
1566 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1567 goto cleanup;
1568 }
1569
1570 DriverKey[0] = '{';
1571 strcpyW(&DriverKey[1], lpGuidString);
1572 pDeviceInstance = &DriverKey[strlenW(DriverKey)];
1573 *pDeviceInstance++ = '}';
1574 *pDeviceInstance++ = '\\';
1575
1576 /* Try all values for Index between 0 and 9999 */
1577 Index = 0;
1578 while (Index <= 9999)
1579 {
1580 sprintfW(pDeviceInstance, InstanceKeyFormat, Index);
1581 rc = RegCreateKeyExW(hClassKey,
1582 DriverKey,
1583 0,
1584 NULL,
1585 REG_OPTION_NON_VOLATILE,
1586 #if _WIN32_WINNT >= 0x502
1587 KEY_READ | KEY_WRITE,
1588 #else
1589 KEY_ALL_ACCESS,
1590 #endif
1591 NULL,
1592 &hKey,
1593 &Disposition);
1594 if (rc != ERROR_SUCCESS)
1595 {
1596 SetLastError(rc);
1597 goto cleanup;
1598 }
1599 if (Disposition == REG_CREATED_NEW_KEY)
1600 break;
1601 RegCloseKey(hKey);
1602 hKey = NULL;
1603 Index++;
1604 }
1605
1606 if (Index > 9999)
1607 {
1608 /* Unable to create more than 9999 devices within the same class */
1609 SetLastError(ERROR_GEN_FAILURE);
1610 goto cleanup;
1611 }
1612
1613 /* Write the new Driver value */
1614 rc = RegSetValueExW(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR));
1615 if (rc != ERROR_SUCCESS)
1616 {
1617 SetLastError(rc);
1618 goto cleanup;
1619 }
1620
1621 }
1622 else
1623 {
1624 /* Open the existing driver key */
1625
1626 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwSize);
1627 if (!DriverKey)
1628 {
1629 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1630 goto cleanup;
1631 }
1632
1633 rc = RegQueryValueExW(hDeviceKey, REGSTR_VAL_DRIVER, NULL, NULL, (LPBYTE)DriverKey, &dwSize);
1634 if (rc != ERROR_SUCCESS)
1635 {
1636 SetLastError(rc);
1637 goto cleanup;
1638 }
1639
1640 rc = RegCreateKeyExW(hClassKey,
1641 DriverKey,
1642 0,
1643 NULL,
1644 REG_OPTION_NON_VOLATILE,
1645 #if _WIN32_WINNT >= 0x502
1646 KEY_READ | KEY_WRITE,
1647 #else
1648 KEY_ALL_ACCESS,
1649 #endif
1650 NULL,
1651 &hKey,
1652 &Disposition);
1653 if (rc != ERROR_SUCCESS)
1654 {
1655 SetLastError(rc);
1656 goto cleanup;
1657 }
1658 }
1659 }
1660
1661 /* Do installation of the specified section */
1662 if (InfHandle)
1663 {
1664 FIXME("Need to install section %s in file %p\n",
1665 debugstr_w(InfSectionName), InfHandle);
1666 }
1667 key = hKey;
1668
1669 cleanup:
1670 if (lpGuidString)
1671 RpcStringFreeW(&lpGuidString);
1672 HeapFree(GetProcessHeap(), 0, DriverKey);
1673 if (hHWProfileKey != INVALID_HANDLE_VALUE)
1674 RegCloseKey(hHWProfileKey);
1675 if (hEnumKey != NULL)
1676 RegCloseKey(hEnumKey);
1677 if (hClassKey != NULL)
1678 RegCloseKey(hClassKey);
1679 if (hDeviceKey != INVALID_HANDLE_VALUE)
1680 RegCloseKey(hDeviceKey);
1681 if (hKey != NULL && hKey != key)
1682 RegCloseKey(hKey);
1683
1684 TRACE("Returning 0x%p\n", key);
1685 return key;
1686 }
1687
1688 /***********************************************************************
1689 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1690 */
1691 BOOL WINAPI SetupDiCreateDeviceInfoA(
1692 HDEVINFO DeviceInfoSet,
1693 PCSTR DeviceName,
1694 CONST GUID *ClassGuid,
1695 PCSTR DeviceDescription,
1696 HWND hwndParent,
1697 DWORD CreationFlags,
1698 PSP_DEVINFO_DATA DeviceInfoData)
1699 {
1700 BOOL ret;
1701 LPWSTR DeviceNameW = NULL;
1702 LPWSTR DeviceDescriptionW = NULL;
1703
1704 TRACE("\n");
1705
1706 if (DeviceName)
1707 {
1708 DeviceNameW = pSetupMultiByteToUnicode(DeviceName, CP_ACP);
1709 if (DeviceNameW == NULL) return FALSE;
1710 }
1711 if (DeviceDescription)
1712 {
1713 DeviceDescriptionW = pSetupMultiByteToUnicode(DeviceDescription, CP_ACP);
1714 if (DeviceDescriptionW == NULL)
1715 {
1716 MyFree(DeviceNameW);
1717 return FALSE;
1718 }
1719 }
1720
1721 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1722 hwndParent, CreationFlags, DeviceInfoData);
1723
1724 MyFree(DeviceNameW);
1725 MyFree(DeviceDescriptionW);
1726
1727 return ret;
1728 }
1729
1730 /***********************************************************************
1731 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1732 */
1733 BOOL WINAPI SetupDiCreateDeviceInfoW(
1734 HDEVINFO DeviceInfoSet,
1735 PCWSTR DeviceName,
1736 CONST GUID *ClassGuid,
1737 PCWSTR DeviceDescription,
1738 HWND hwndParent,
1739 DWORD CreationFlags,
1740 PSP_DEVINFO_DATA DeviceInfoData)
1741 {
1742 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1743 struct DeviceInfo *deviceInfo = NULL;
1744 BOOL ret = FALSE;
1745 CONFIGRET cr;
1746 DEVINST RootDevInst;
1747 DEVINST DevInst;
1748 WCHAR GenInstanceId[MAX_DEVICE_ID_LEN];
1749
1750 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1751 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1752 hwndParent, CreationFlags, DeviceInfoData);
1753
1754 if (!DeviceName)
1755 {
1756 SetLastError(ERROR_INVALID_DEVINST_NAME);
1757 return FALSE;
1758 }
1759 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1760 {
1761 SetLastError(ERROR_INVALID_HANDLE);
1762 return FALSE;
1763 }
1764 if (!ClassGuid)
1765 {
1766 SetLastError(ERROR_INVALID_PARAMETER);
1767 return FALSE;
1768 }
1769 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1770 {
1771 SetLastError(ERROR_INVALID_HANDLE);
1772 return FALSE;
1773 }
1774 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1775 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1776 {
1777 SetLastError(ERROR_CLASS_MISMATCH);
1778 return FALSE;
1779 }
1780 if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
1781 {
1782 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
1783 SetLastError(ERROR_INVALID_FLAGS);
1784 return FALSE;
1785 }
1786
1787 /* Get the root device instance */
1788 cr = CM_Locate_DevInst_ExW(&RootDevInst,
1789 NULL,
1790 CM_LOCATE_DEVINST_NORMAL,
1791 set->hMachine);
1792 if (cr != CR_SUCCESS)
1793 {
1794 SetLastError(ERROR_INVALID_DATA);
1795 return FALSE;
1796 }
1797
1798 /* Create the new device instance */
1799 cr = CM_Create_DevInst_ExW(&DevInst,
1800 (DEVINSTID)DeviceName,
1801 RootDevInst,
1802 (CreationFlags & DICD_GENERATE_ID) ?
1803 CM_CREATE_DEVINST_GENERATE_ID : 0,
1804 set->hMachine);
1805 if (cr != CR_SUCCESS)
1806 {
1807 SetLastError(GetErrorCodeFromCrCode(cr));
1808 return FALSE;
1809 }
1810
1811 if (CreationFlags & DICD_GENERATE_ID)
1812 {
1813 /* Grab the actual instance ID that was created */
1814 cr = CM_Get_Device_ID_Ex(DevInst,
1815 GenInstanceId,
1816 MAX_DEVICE_ID_LEN,
1817 0,
1818 set->hMachine);
1819 if (cr != CR_SUCCESS)
1820 {
1821 SetLastError(GetErrorCodeFromCrCode(cr));
1822 return FALSE;
1823 }
1824
1825 DeviceName = GenInstanceId;
1826 TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName));
1827 }
1828
1829 if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo))
1830 {
1831 InsertTailList(&set->ListHead, &deviceInfo->ListEntry);
1832
1833 if (!DeviceInfoData)
1834 ret = TRUE;
1835 else
1836 {
1837 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1838 {
1839 SetLastError(ERROR_INVALID_USER_BUFFER);
1840 }
1841 else
1842 {
1843 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
1844 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
1845 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
1846 ret = TRUE;
1847 }
1848 }
1849 }
1850
1851 if (ret == FALSE)
1852 {
1853 if (deviceInfo != NULL)
1854 {
1855 /* Remove deviceInfo from List */
1856 RemoveEntryList(&deviceInfo->ListEntry);
1857
1858 /* Destroy deviceInfo */
1859 DestroyDeviceInfo(deviceInfo);
1860 }
1861 }
1862
1863 TRACE("Returning %d\n", ret);
1864 return ret;
1865 }
1866
1867 /***********************************************************************
1868 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1869 */
1870 BOOL WINAPI SetupDiRegisterDeviceInfo(
1871 HDEVINFO DeviceInfoSet,
1872 PSP_DEVINFO_DATA DeviceInfoData,
1873 DWORD Flags,
1874 PSP_DETSIG_CMPPROC CompareProc,
1875 PVOID CompareContext,
1876 PSP_DEVINFO_DATA DupDeviceInfoData)
1877 {
1878 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1879 WCHAR DevInstId[MAX_DEVICE_ID_LEN];
1880 DEVINST ParentDevInst;
1881 CONFIGRET cr;
1882 DWORD dwError = ERROR_SUCCESS;
1883
1884 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1885 CompareProc, CompareContext, DupDeviceInfoData);
1886
1887 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1888 {
1889 SetLastError(ERROR_INVALID_HANDLE);
1890 return FALSE;
1891 }
1892 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1893 {
1894 SetLastError(ERROR_INVALID_HANDLE);
1895 return FALSE;
1896 }
1897 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1898 || !DeviceInfoData->Reserved)
1899 {
1900 SetLastError(ERROR_INVALID_PARAMETER);
1901 return FALSE;
1902 }
1903
1904 if (Flags & ~SPRDI_FIND_DUPS)
1905 {
1906 TRACE("Unknown flags: 0x%08lx\n", Flags & ~SPRDI_FIND_DUPS);
1907 SetLastError(ERROR_INVALID_FLAGS);
1908 return FALSE;
1909 }
1910
1911 if (Flags & SPRDI_FIND_DUPS)
1912 {
1913 FIXME("Unimplemented codepath!\n");
1914 }
1915
1916 CM_Get_Device_ID_Ex(DeviceInfoData->DevInst,
1917 DevInstId,
1918 MAX_DEVICE_ID_LEN,
1919 0,
1920 set->hMachine);
1921
1922 CM_Get_Parent_Ex(&ParentDevInst,
1923 DeviceInfoData->DevInst,
1924 0,
1925 set->hMachine);
1926
1927 cr = CM_Create_DevInst_Ex(&DeviceInfoData->DevInst,
1928 DevInstId,
1929 ParentDevInst,
1930 CM_CREATE_DEVINST_NORMAL | CM_CREATE_DEVINST_DO_NOT_INSTALL,
1931 set->hMachine);
1932 if (cr != CR_SUCCESS &&
1933 cr != CR_ALREADY_SUCH_DEVINST)
1934 {
1935 dwError = ERROR_NO_SUCH_DEVINST;
1936 }
1937
1938 SetLastError(dwError);
1939
1940 return (dwError == ERROR_SUCCESS);
1941 }
1942
1943 /***********************************************************************
1944 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1945 */
1946 BOOL WINAPI SetupDiEnumDeviceInfo(
1947 HDEVINFO devinfo,
1948 DWORD index,
1949 PSP_DEVINFO_DATA info)
1950 {
1951 BOOL ret = FALSE;
1952
1953 TRACE("%p %d %p\n", devinfo, index, info);
1954
1955 if(info==NULL)
1956 {
1957 SetLastError(ERROR_INVALID_PARAMETER);
1958 return FALSE;
1959 }
1960 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
1961 {
1962 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1963 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1964 {
1965 if (info->cbSize != sizeof(SP_DEVINFO_DATA))
1966 SetLastError(ERROR_INVALID_USER_BUFFER);
1967 else
1968 {
1969 PLIST_ENTRY ItemList = list->ListHead.Flink;
1970 while (ItemList != &list->ListHead && index-- > 0)
1971 ItemList = ItemList->Flink;
1972 if (ItemList == &list->ListHead)
1973 SetLastError(ERROR_NO_MORE_ITEMS);
1974 else
1975 {
1976 struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
1977 memcpy(&info->ClassGuid,
1978 &DevInfo->ClassGuid,
1979 sizeof(GUID));
1980 info->DevInst = DevInfo->dnDevInst;
1981 info->Reserved = (ULONG_PTR)DevInfo;
1982 ret = TRUE;
1983 }
1984 }
1985 }
1986 else
1987 SetLastError(ERROR_INVALID_HANDLE);
1988 }
1989 else
1990 SetLastError(ERROR_INVALID_HANDLE);
1991 return ret;
1992 }
1993
1994 /***********************************************************************
1995 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1996 */
1997 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1998 HDEVINFO DeviceInfoSet,
1999 PSP_DEVINFO_DATA DeviceInfoData,
2000 PSTR DeviceInstanceId,
2001 DWORD DeviceInstanceIdSize,
2002 PDWORD RequiredSize)
2003 {
2004 BOOL ret = FALSE;
2005 DWORD size;
2006 PWSTR instanceId;
2007
2008 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
2009 DeviceInstanceIdSize, RequiredSize);
2010
2011 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
2012 {
2013 SetLastError(ERROR_INVALID_PARAMETER);
2014 return FALSE;
2015 }
2016
2017 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
2018 DeviceInfoData,
2019 NULL,
2020 0,
2021 &size);
2022 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
2023 return FALSE;
2024 instanceId = MyMalloc(size * sizeof(WCHAR));
2025 if (instanceId)
2026 {
2027 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
2028 DeviceInfoData,
2029 instanceId,
2030 size,
2031 &size);
2032 if (ret)
2033 {
2034 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
2035 DeviceInstanceId,
2036 DeviceInstanceIdSize, NULL, NULL);
2037
2038 if (!len)
2039 ret = FALSE;
2040 else
2041 {
2042 if (len > DeviceInstanceIdSize)
2043 {
2044 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2045 ret = FALSE;
2046 }
2047 if (RequiredSize)
2048 *RequiredSize = len;
2049 }
2050 }
2051 MyFree(instanceId);
2052 }
2053 else
2054 {
2055 if (RequiredSize)
2056 *RequiredSize = size;
2057 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2058 ret = FALSE;
2059 }
2060 return ret;
2061 }
2062
2063 /***********************************************************************
2064 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
2065 */
2066 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
2067 HDEVINFO DeviceInfoSet,
2068 PSP_DEVINFO_DATA DeviceInfoData,
2069 PWSTR DeviceInstanceId,
2070 DWORD DeviceInstanceIdSize,
2071 PDWORD RequiredSize)
2072 {
2073 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2074 struct DeviceInfo *devInfo;
2075
2076 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
2077 DeviceInstanceIdSize, RequiredSize);
2078
2079 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2080 {
2081 SetLastError(ERROR_INVALID_HANDLE);
2082 return FALSE;
2083 }
2084 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2085 {
2086 SetLastError(ERROR_INVALID_HANDLE);
2087 return FALSE;
2088 }
2089 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2090 || !DeviceInfoData->Reserved)
2091 {
2092 SetLastError(ERROR_INVALID_PARAMETER);
2093 return FALSE;
2094 }
2095 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
2096 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
2097 {
2098 SetLastError(ERROR_INVALID_PARAMETER);
2099 return FALSE;
2100 }
2101 if (DeviceInstanceId && DeviceInstanceIdSize == 0)
2102 {
2103 SetLastError(ERROR_INVALID_PARAMETER);
2104 return FALSE;
2105 }
2106 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
2107 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
2108 {
2109 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2110 if (RequiredSize)
2111 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
2112 return FALSE;
2113 }
2114 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
2115 if (RequiredSize)
2116 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
2117 return TRUE;
2118 }
2119
2120 /***********************************************************************
2121 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
2122 */
2123 BOOL WINAPI SetupDiGetActualSectionToInstallA(
2124 HINF InfHandle,
2125 PCSTR InfSectionName,
2126 PSTR InfSectionWithExt,
2127 DWORD InfSectionWithExtSize,
2128 PDWORD RequiredSize,
2129 PSTR *Extension)
2130 {
2131 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
2132 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
2133 Extension, NULL);
2134 }
2135
2136 /***********************************************************************
2137 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2138 */
2139 BOOL WINAPI SetupDiGetActualSectionToInstallW(
2140 HINF InfHandle,
2141 PCWSTR InfSectionName,
2142 PWSTR InfSectionWithExt,
2143 DWORD InfSectionWithExtSize,
2144 PDWORD RequiredSize,
2145 PWSTR *Extension)
2146 {
2147 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
2148 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
2149 Extension, NULL);
2150 }
2151
2152 /***********************************************************************
2153 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2154 */
2155 BOOL WINAPI
2156 SetupDiGetActualSectionToInstallExA(
2157 IN HINF InfHandle,
2158 IN PCSTR InfSectionName,
2159 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
2160 OUT PSTR InfSectionWithExt OPTIONAL,
2161 IN DWORD InfSectionWithExtSize,
2162 OUT PDWORD RequiredSize OPTIONAL,
2163 OUT PSTR* Extension OPTIONAL,
2164 IN PVOID Reserved)
2165 {
2166 LPWSTR InfSectionNameW = NULL;
2167 LPWSTR InfSectionWithExtW = NULL;
2168 PWSTR ExtensionW;
2169 BOOL bResult = FALSE;
2170
2171 TRACE("\n");
2172
2173 if (InfSectionName)
2174 {
2175 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
2176 if (InfSectionNameW == NULL)
2177 goto cleanup;
2178 }
2179 if (InfSectionWithExt)
2180 {
2181 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
2182 if (InfSectionWithExtW == NULL)
2183 goto cleanup;
2184 }
2185
2186 bResult = SetupDiGetActualSectionToInstallExW(
2187 InfHandle, InfSectionNameW, AlternatePlatformInfo,
2188 InfSectionWithExt ? InfSectionWithExtW : NULL,
2189 InfSectionWithExtSize,
2190 RequiredSize,
2191 Extension ? &ExtensionW : NULL,
2192 Reserved);
2193
2194 if (bResult && InfSectionWithExt)
2195 {
2196 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
2197 InfSectionWithExtSize, NULL, NULL) != 0;
2198 }
2199 if (bResult && Extension)
2200 {
2201 if (ExtensionW == NULL)
2202 *Extension = NULL;
2203 else
2204 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
2205 }
2206
2207 cleanup:
2208 MyFree(InfSectionNameW);
2209 MyFree(InfSectionWithExtW);
2210
2211 return bResult;
2212 }
2213
2214 /***********************************************************************
2215 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2216 */
2217 BOOL WINAPI SetupDiGetClassDescriptionA(
2218 const GUID* ClassGuid,
2219 PSTR ClassDescription,
2220 DWORD ClassDescriptionSize,
2221 PDWORD RequiredSize)
2222 {
2223 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
2224 ClassDescriptionSize,
2225 RequiredSize, NULL, NULL);
2226 }
2227
2228 /***********************************************************************
2229 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2230 */
2231 BOOL WINAPI SetupDiGetClassDescriptionW(
2232 const GUID* ClassGuid,
2233 PWSTR ClassDescription,
2234 DWORD ClassDescriptionSize,
2235 PDWORD RequiredSize)
2236 {
2237 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
2238 ClassDescriptionSize,
2239 RequiredSize, NULL, NULL);
2240 }
2241
2242 /***********************************************************************
2243 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2244 */
2245 BOOL WINAPI SetupDiGetClassDescriptionExA(
2246 const GUID* ClassGuid,
2247 PSTR ClassDescription,
2248 DWORD ClassDescriptionSize,
2249 PDWORD RequiredSize,
2250 PCSTR MachineName,
2251 PVOID Reserved)
2252 {
2253 PWCHAR ClassDescriptionW = NULL;
2254 LPWSTR MachineNameW = NULL;
2255 BOOL ret = FALSE;
2256
2257 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2258 ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved);
2259
2260 if (ClassDescriptionSize > 0)
2261 {
2262 ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR));
2263 if (!ClassDescriptionW)
2264 {
2265 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2266 goto cleanup;
2267 }
2268 }
2269
2270 if (MachineName)
2271 {
2272 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
2273 if (!MachineNameW)
2274 {
2275 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2276 goto cleanup;
2277 }
2278 }
2279
2280 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW,
2281 ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved);
2282 if (ret)
2283 {
2284 DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
2285 ClassDescriptionSize, NULL, NULL);
2286 if (len == 0 || len > ClassDescriptionSize)
2287 {
2288 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2289 ret = FALSE;
2290 }
2291 }
2292
2293 cleanup:
2294 MyFree(ClassDescriptionW);
2295 MyFree(MachineNameW);
2296 return ret;
2297 }
2298
2299 /***********************************************************************
2300 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2301 */
2302 BOOL WINAPI SetupDiGetClassDescriptionExW(
2303 const GUID* ClassGuid,
2304 PWSTR ClassDescription,
2305 DWORD ClassDescriptionSize,
2306 PDWORD RequiredSize,
2307 PCWSTR MachineName,
2308 PVOID Reserved)
2309 {
2310 HKEY hKey;
2311 DWORD dwLength;
2312 DWORD dwRegType;
2313 LONG rc;
2314 PWSTR Buffer;
2315
2316 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2317 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
2318
2319 /* Make sure there's a GUID */
2320 if (!ClassGuid)
2321 {
2322 SetLastError(ERROR_INVALID_PARAMETER);
2323 return FALSE;
2324 }
2325
2326 /* Make sure there's a real buffer when there's a size */
2327 if (!ClassDescription && ClassDescriptionSize > 0)
2328 {
2329 SetLastError(ERROR_INVALID_PARAMETER);
2330 return FALSE;
2331 }
2332
2333 /* Open the key for the GUID */
2334 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
2335 KEY_QUERY_VALUE,
2336 DIOCR_INSTALLER,
2337 MachineName,
2338 Reserved);
2339 if (hKey == INVALID_HANDLE_VALUE)
2340 return FALSE;
2341
2342 /* Retrieve the class description data and close the key */
2343 rc = QueryRegistryValue(hKey, NULL, (LPBYTE *) &Buffer, &dwRegType, &dwLength);
2344 RegCloseKey(hKey);
2345
2346 /* Make sure we got the data */
2347 if (rc != ERROR_SUCCESS)
2348 {
2349 SetLastError(rc);
2350 return FALSE;
2351 }
2352
2353 /* Make sure the data is a string */
2354 if (dwRegType != REG_SZ)
2355 {
2356 MyFree(Buffer);
2357 SetLastError(ERROR_GEN_FAILURE);
2358 return FALSE;
2359 }
2360
2361 /* Determine the length of the class description */
2362 dwLength /= sizeof(WCHAR);
2363
2364 /* Count the null-terminator if none is present */
2365 if ((dwLength == 0) || (Buffer[dwLength - 1] != UNICODE_NULL))
2366 dwLength++;
2367
2368 /* Inform the caller about the class description */
2369 if ((ClassDescription != NULL) && (dwLength <= ClassDescriptionSize))
2370 {
2371 memcpy(ClassDescription, Buffer, (dwLength - 1) * sizeof(WCHAR));
2372 ClassDescription[dwLength - 1] = UNICODE_NULL;
2373 }
2374
2375 /* Inform the caller about the required size */
2376 if (RequiredSize != NULL)
2377 *RequiredSize = dwLength;
2378
2379 /* Clean up the buffer */
2380 MyFree(Buffer);
2381
2382 /* Make sure the buffer was large enough */
2383 if ((ClassDescription == NULL) || (dwLength > ClassDescriptionSize))
2384 {
2385 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2386 return FALSE;
2387 }
2388
2389 return TRUE;
2390 }
2391
2392 /***********************************************************************
2393 * SetupDiGetClassDevsA (SETUPAPI.@)
2394 */
2395 HDEVINFO WINAPI SetupDiGetClassDevsA(
2396 CONST GUID *class,
2397 LPCSTR enumstr,
2398 HWND parent,
2399 DWORD flags)
2400 {
2401 return SetupDiGetClassDevsExA(class, enumstr, parent,
2402 flags, NULL, NULL, NULL);
2403 }
2404
2405 /***********************************************************************
2406 * SetupDiGetClassDevsExA (SETUPAPI.@)
2407 */
2408 HDEVINFO WINAPI SetupDiGetClassDevsExA(
2409 const GUID *class,
2410 PCSTR enumstr,
2411 HWND parent,
2412 DWORD flags,
2413 HDEVINFO deviceset,
2414 PCSTR machine,
2415 PVOID reserved)
2416 {
2417 HDEVINFO ret;
2418 LPWSTR enumstrW = NULL, machineW = NULL;
2419
2420 if (enumstr)
2421 {
2422 enumstrW = pSetupMultiByteToUnicode(enumstr, CP_ACP);
2423 if (!enumstrW)
2424 {
2425 ret = INVALID_HANDLE_VALUE;
2426 goto end;
2427 }
2428 }
2429 if (machine)
2430 {
2431 machineW = pSetupMultiByteToUnicode(machine, CP_ACP);
2432 if (!machineW)
2433 {
2434 MyFree(enumstrW);
2435 ret = INVALID_HANDLE_VALUE;
2436 goto end;
2437 }
2438 }
2439 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
2440 machineW, reserved);
2441 MyFree(enumstrW);
2442 MyFree(machineW);
2443
2444 end:
2445 return ret;
2446 }
2447
2448 /***********************************************************************
2449 * SetupDiGetClassDevsW (SETUPAPI.@)
2450 */
2451 HDEVINFO WINAPI SetupDiGetClassDevsW(
2452 CONST GUID *class,
2453 LPCWSTR enumstr,
2454 HWND parent,
2455 DWORD flags)
2456 {
2457 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2458 NULL);
2459 }
2460
2461 /***********************************************************************
2462 * SetupDiGetClassDevsExW (SETUPAPI.@)
2463 */
2464 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2465 CONST GUID *class,
2466 PCWSTR enumstr,
2467 HWND parent,
2468 DWORD flags,
2469 HDEVINFO deviceset,
2470 PCWSTR machine,
2471 PVOID reserved)
2472 {
2473 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2474 struct DeviceInfoSet *list;
2475 CONST GUID *pClassGuid;
2476 LONG rc;
2477 HDEVINFO set = INVALID_HANDLE_VALUE;
2478
2479 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2480 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2481 reserved);
2482
2483 if (!(flags & DIGCF_ALLCLASSES) && !class)
2484 {
2485 SetLastError(ERROR_INVALID_PARAMETER);
2486 return INVALID_HANDLE_VALUE;
2487 }
2488
2489 /* Create the deviceset if not set */
2490 if (deviceset)
2491 {
2492 list = (struct DeviceInfoSet *)deviceset;
2493 if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2494 {
2495 SetLastError(ERROR_INVALID_HANDLE);
2496 goto cleanup;
2497 }
2498 hDeviceInfo = deviceset;
2499 }
2500 else
2501 {
2502 hDeviceInfo = SetupDiCreateDeviceInfoListExW(
2503 flags & (DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES) ? NULL : class,
2504 NULL, machine, NULL);
2505 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2506 goto cleanup;
2507 list = (struct DeviceInfoSet *)hDeviceInfo;
2508 }
2509
2510 if (flags & DIGCF_PROFILE)
2511 FIXME(": flag DIGCF_PROFILE ignored\n");
2512
2513 if (flags & DIGCF_DEVICEINTERFACE)
2514 {
2515 if (!class)
2516 {
2517 SetLastError(ERROR_INVALID_PARAMETER);
2518 goto cleanup;
2519 }
2520 rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT);
2521 }
2522 else
2523 {
2524 /* Determine which class(es) should be included in the deviceset */
2525 if (flags & DIGCF_ALLCLASSES)
2526 {
2527 /* The caller wants all classes. Check if
2528 * the deviceset limits us to one class */
2529 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2530 pClassGuid = NULL;
2531 else
2532 pClassGuid = &list->ClassGuid;
2533 }
2534 else if (class)
2535 {
2536 /* The caller wants one class. Check if it matches deviceset class */
2537 if (IsEqualIID(&list->ClassGuid, class)
2538 || IsEqualIID(&list->ClassGuid, &GUID_NULL))
2539 {
2540 pClassGuid = class;
2541 }
2542 else
2543 {
2544 SetLastError(ERROR_INVALID_PARAMETER);
2545 goto cleanup;
2546 }
2547 }
2548 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL))
2549 {
2550 /* No class specified. Try to use the one of the deviceset */
2551 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2552 pClassGuid = &list->ClassGuid;
2553 else
2554 {
2555 SetLastError(ERROR_INVALID_PARAMETER);
2556 goto cleanup;
2557 }
2558 }
2559 else
2560 {
2561 SetLastError(ERROR_INVALID_PARAMETER);
2562 goto cleanup;
2563 }
2564 rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr);
2565 }
2566 if (rc != ERROR_SUCCESS)
2567 {
2568 SetLastError(rc);
2569 goto cleanup;
2570 }
2571 set = hDeviceInfo;
2572
2573 cleanup:
2574 if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set)
2575 SetupDiDestroyDeviceInfoList(hDeviceInfo);
2576 return set;
2577 }
2578
2579 /***********************************************************************
2580 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2581 */
2582 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2583 HDEVINFO DeviceInfoSet,
2584 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2585 {
2586 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2587
2588 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2589
2590 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2591 {
2592 SetLastError(ERROR_INVALID_HANDLE);
2593 return FALSE;
2594 }
2595 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2596 {
2597 SetLastError(ERROR_INVALID_HANDLE);
2598 return FALSE;
2599 }
2600 if (!DevInfoData ||
2601 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2602 {
2603 SetLastError(ERROR_INVALID_PARAMETER);
2604 return FALSE;
2605 }
2606 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2607 DevInfoData->RemoteMachineHandle = set->hMachine;
2608 if (set->MachineName)
2609 {
2610 FIXME("Stub\n");
2611 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2612 return FALSE;
2613 }
2614 else
2615 DevInfoData->RemoteMachineName[0] = 0;
2616
2617 return TRUE;
2618 }
2619
2620 /***********************************************************************
2621 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2622 */
2623 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2624 HDEVINFO DeviceInfoSet,
2625 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2626 {
2627 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2628
2629 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2630
2631 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2632 {
2633 SetLastError(ERROR_INVALID_HANDLE);
2634 return FALSE;
2635 }
2636 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2637 {
2638 SetLastError(ERROR_INVALID_HANDLE);
2639 return FALSE;
2640 }
2641 if (!DevInfoData ||
2642 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2643 {
2644 SetLastError(ERROR_INVALID_PARAMETER);
2645 return FALSE;
2646 }
2647 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2648 DevInfoData->RemoteMachineHandle = set->hMachine;
2649 if (set->MachineName)
2650 strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2);
2651 else
2652 DevInfoData->RemoteMachineName[0] = 0;
2653
2654 return TRUE;
2655 }
2656
2657 /***********************************************************************
2658 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2659 */
2660 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2661 HDEVINFO DeviceInfoSet,
2662 PSP_DEVINFO_DATA DeviceInfoData,
2663 const GUID *InterfaceClassGuid,
2664 PCSTR ReferenceString,
2665 DWORD CreationFlags,
2666 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2667 {
2668 BOOL ret;
2669 LPWSTR ReferenceStringW = NULL;
2670
2671 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2672 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2673 CreationFlags, DeviceInterfaceData);
2674
2675 if (ReferenceString)
2676 {
2677 ReferenceStringW = pSetupMultiByteToUnicode(ReferenceString, CP_ACP);
2678 if (ReferenceStringW == NULL) return FALSE;
2679 }
2680
2681 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2682 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2683 DeviceInterfaceData);
2684
2685 MyFree(ReferenceStringW);
2686
2687 return ret;
2688 }
2689
2690 /***********************************************************************
2691 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2692 */
2693 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2694 HDEVINFO DeviceInfoSet,
2695 PSP_DEVINFO_DATA DeviceInfoData,
2696 const GUID *InterfaceClassGuid,
2697 PCWSTR ReferenceString,
2698 DWORD CreationFlags,
2699 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2700 {
2701 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2702 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2703 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2704 CreationFlags, DeviceInterfaceData);
2705
2706 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2707 {
2708 SetLastError(ERROR_INVALID_HANDLE);
2709 return FALSE;
2710 }
2711 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2712 {
2713 SetLastError(ERROR_INVALID_HANDLE);
2714 return FALSE;
2715 }
2716 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2717 || !DeviceInfoData->Reserved)
2718 {
2719 SetLastError(ERROR_INVALID_PARAMETER);
2720 return FALSE;
2721 }
2722 if (!InterfaceClassGuid)
2723 {
2724 SetLastError(ERROR_INVALID_USER_BUFFER);
2725 return FALSE;
2726 }
2727
2728 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2729 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2730 CreationFlags, DeviceInterfaceData);
2731 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2732 return FALSE;
2733 }
2734
2735 /***********************************************************************
2736 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2737 */
2738 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2739 HDEVINFO DeviceInfoSet,
2740 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2741 DWORD Reserved,
2742 REGSAM samDesired,
2743 HINF InfHandle,
2744 PCSTR InfSectionName)
2745 {
2746 HKEY key;
2747 PWSTR InfSectionNameW = NULL;
2748
2749 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2750 samDesired, InfHandle, InfSectionName);
2751 if (InfHandle)
2752 {
2753 if (!InfSectionName)
2754 {
2755 SetLastError(ERROR_INVALID_PARAMETER);
2756 return INVALID_HANDLE_VALUE;
2757 }
2758 InfSectionNameW = pSetupMultiByteToUnicode(InfSectionName, CP_ACP);
2759 if (!InfSectionNameW)
2760 return INVALID_HANDLE_VALUE;
2761 }
2762 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2763 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2764 InfSectionNameW);
2765 MyFree(InfSectionNameW);
2766 return key;
2767 }
2768
2769 /***********************************************************************
2770 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2771 */
2772 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2773 HDEVINFO DeviceInfoSet,
2774 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2775 DWORD Reserved,
2776 REGSAM samDesired,
2777 HINF InfHandle,
2778 PCWSTR InfSectionName)
2779 {
2780 HKEY hKey, hDevKey;
2781 LPWSTR SymbolicLink;
2782 DWORD Length, Index;
2783 LONG rc;
2784 WCHAR bracedGuidString[39];
2785 struct DeviceInterface *DevItf;
2786 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2787
2788 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2789 samDesired, InfHandle, InfSectionName);
2790
2791 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2792 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2793 {
2794 SetLastError(ERROR_INVALID_HANDLE);
2795 return INVALID_HANDLE_VALUE;
2796 }
2797 if (!DeviceInterfaceData ||
2798 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2799 !DeviceInterfaceData->Reserved)
2800 {
2801 SetLastError(ERROR_INVALID_PARAMETER);
2802 return INVALID_HANDLE_VALUE;
2803 }
2804 if (InfHandle && !InfSectionName)
2805 {
2806 SetLastError(ERROR_INVALID_PARAMETER);
2807 return INVALID_HANDLE_VALUE;
2808 }
2809
2810 hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL);
2811 if (hKey == INVALID_HANDLE_VALUE)
2812 {
2813 hKey = SetupDiOpenClassRegKeyExW(NULL, samDesired, DIOCR_INTERFACE, NULL, NULL);
2814 if (hKey == INVALID_HANDLE_VALUE)
2815 {
2816 SetLastError(ERROR_INVALID_PARAMETER);
2817 return INVALID_HANDLE_VALUE;
2818 }
2819 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, bracedGuidString);
2820
2821 if (RegCreateKeyExW(hKey, bracedGuidString, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL) != ERROR_SUCCESS)
2822 {
2823 SetLastError(ERROR_INVALID_PARAMETER);
2824 return INVALID_HANDLE_VALUE;
2825 }
2826 RegCloseKey(hKey);
2827 hKey = hDevKey;
2828 }
2829
2830 DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2831
2832 Length = (wcslen(DevItf->SymbolicLink)+1) * sizeof(WCHAR);
2833 SymbolicLink = HeapAlloc(GetProcessHeap(), 0, Length);
2834 if (!SymbolicLink)
2835 {
2836 RegCloseKey(hKey);
2837 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2838 return INVALID_HANDLE_VALUE;
2839 }
2840
2841 wcscpy(SymbolicLink, DevItf->SymbolicLink);
2842
2843 Index = 0;
2844 while(SymbolicLink[Index])
2845 {
2846 if (SymbolicLink[Index] == L'\\')
2847 {
2848 SymbolicLink[Index] = L'#';
2849 }
2850 Index++;
2851 }
2852
2853 rc = RegCreateKeyExW(hKey, SymbolicLink, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL);
2854
2855 RegCloseKey(hKey);
2856 HeapFree(GetProcessHeap(), 0, SymbolicLink);
2857
2858 if (rc == ERROR_SUCCESS)
2859 {
2860 if (InfHandle && InfSectionName)
2861 {
2862 if (!SetupInstallFromInfSection(NULL /*FIXME */,
2863 InfHandle,
2864 InfSectionName,
2865 SPINST_INIFILES | SPINST_REGISTRY | SPINST_INI2REG | SPINST_FILES | SPINST_BITREG | SPINST_REGSVR | SPINST_UNREGSVR | SPINST_PROFILEITEMS | SPINST_COPYINF,
2866 hDevKey,
2867 NULL,
2868 0,
2869 set->SelectedDevice->InstallParams.InstallMsgHandler,
2870 set->SelectedDevice->InstallParams.InstallMsgHandlerContext,
2871 INVALID_HANDLE_VALUE,
2872 NULL))
2873 {
2874 RegCloseKey(hDevKey);
2875 return INVALID_HANDLE_VALUE;
2876 }
2877 }
2878 }
2879
2880 SetLastError(rc);
2881 return hDevKey;
2882 }
2883
2884 /***********************************************************************
2885 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2886 */
2887 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
2888 HDEVINFO DeviceInfoSet,
2889 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2890 DWORD Reserved)
2891 {
2892 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2893 BOOL ret = FALSE;
2894
2895 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2896
2897 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2898 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2899 {
2900 SetLastError(ERROR_INVALID_HANDLE);
2901 return FALSE;
2902 }
2903 if (!DeviceInterfaceData ||
2904 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2905 !DeviceInterfaceData->Reserved)
2906 {
2907 SetLastError(ERROR_INVALID_PARAMETER);
2908 return FALSE;
2909 }
2910
2911 FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2912 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2913 return ret;
2914 }
2915
2916 /***********************************************************************
2917 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2918 *
2919 * PARAMS
2920 * DeviceInfoSet [I] Set of devices from which to enumerate
2921 * interfaces
2922 * DeviceInfoData [I] (Optional) If specified, a specific device
2923 * instance from which to enumerate interfaces.
2924 * If it isn't specified, all interfaces for all
2925 * devices in the set are enumerated.
2926 * InterfaceClassGuid [I] The interface class to enumerate.
2927 * MemberIndex [I] An index of the interface instance to enumerate.
2928 * A caller should start with MemberIndex set to 0,
2929 * and continue until the function fails with
2930 * ERROR_NO_MORE_ITEMS.
2931 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2932 * member must be set to
2933 * sizeof(SP_DEVICE_INTERFACE_DATA).
2934 *
2935 * RETURNS
2936 * Success: non-zero value.
2937 * Failure: FALSE. Call GetLastError() for more info.
2938 */
2939 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2940 HDEVINFO DeviceInfoSet,
2941 PSP_DEVINFO_DATA DeviceInfoData,
2942 CONST GUID * InterfaceClassGuid,
2943 DWORD MemberIndex,
2944 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2945 {
2946 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2947 BOOL ret = FALSE;
2948
2949 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2950 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2951
2952 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2953 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2954 {
2955 SetLastError(ERROR_INVALID_HANDLE);
2956 return FALSE;
2957 }
2958 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2959 !DeviceInfoData->Reserved))
2960 {
2961 SetLastError(ERROR_INVALID_PARAMETER);
2962 return FALSE;
2963 }
2964 if (!DeviceInterfaceData ||
2965 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2966 {
2967 SetLastError(ERROR_INVALID_PARAMETER);
2968 return FALSE;
2969 }
2970 if (DeviceInfoData)
2971 {
2972 struct DeviceInfo *devInfo =
2973 (struct DeviceInfo *)DeviceInfoData->Reserved;
2974 BOOL found = FALSE;
2975 PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2976 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2977 {
2978 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2979 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2980 {
2981 InterfaceListEntry = InterfaceListEntry->Flink;
2982 continue;
2983 }
2984 if (MemberIndex-- == 0)
2985 {
2986 /* return this item */
2987 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2988 &DevItf->InterfaceClassGuid,
2989 sizeof(GUID));
2990 DeviceInterfaceData->Flags = DevItf->Flags;
2991 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2992 found = TRUE;
2993 ret = TRUE;
2994 }
2995 InterfaceListEntry = InterfaceListEntry->Flink;
2996 }
2997 if (!found)
2998 SetLastError(ERROR_NO_MORE_ITEMS);
2999 }
3000 else
3001 {
3002 BOOL found = FALSE;
3003 PLIST_ENTRY ItemList = set->ListHead.Flink;
3004 while (ItemList != &set->ListHead && !found)
3005 {
3006 PLIST_ENTRY InterfaceListEntry;
3007 struct DeviceInfo *devInfo =
3008 CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
3009 InterfaceListEntry = devInfo->InterfaceListHead.Flink;
3010 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
3011 {
3012 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
3013 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
3014 {
3015 InterfaceListEntry = InterfaceListEntry->Flink;
3016 continue;
3017 }
3018 if (MemberIndex-- == 0)
3019 {
3020 /* return this item */
3021 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
3022 &DevItf->InterfaceClassGuid,
3023 sizeof(GUID));
3024 DeviceInterfaceData->Flags = DevItf->Flags;
3025 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
3026 found = TRUE;
3027 ret = TRUE;
3028 }
3029 InterfaceListEntry = InterfaceListEntry->Flink;
3030 }
3031 ItemList = ItemList->Flink;
3032
3033 }
3034 if (!found)
3035 SetLastError(ERROR_NO_MORE_ITEMS);
3036 }
3037 return ret;
3038 }
3039
3040 /***********************************************************************
3041 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
3042 *
3043 * Destroy a DeviceInfoList and free all used memory of the list.
3044 *
3045 * PARAMS
3046 * devinfo [I] DeviceInfoList pointer to list to destroy
3047 *
3048 * RETURNS
3049 * Success: non zero value.
3050 * Failure: zero value.
3051 */
3052 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
3053 {
3054 BOOL ret = FALSE;
3055
3056 TRACE("%p\n", devinfo);
3057 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
3058 {
3059 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
3060
3061 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
3062 {
3063 ret = DestroyDeviceInfoSet(list);
3064 }
3065 }
3066
3067 if (ret == FALSE)
3068 SetLastError(ERROR_INVALID_HANDLE);
3069
3070 return ret;
3071 }
3072
3073 /***********************************************************************
3074 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
3075 */
3076 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
3077 HDEVINFO DeviceInfoSet,
3078 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
3079 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
3080 DWORD DeviceInterfaceDetailDataSize,
3081 PDWORD RequiredSize,
3082 PSP_DEVINFO_DATA DeviceInfoData)
3083 {
3084 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3085 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
3086 DWORD sizeW = 0, bytesNeeded;
3087 BOOL ret = FALSE;
3088
3089 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
3090 DeviceInterfaceData, DeviceInterfaceDetailData,
3091 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
3092
3093 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
3094 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3095 {
3096 SetLastError(ERROR_INVALID_HANDLE);
3097 return FALSE;
3098 }
3099 if (!DeviceInterfaceData ||
3100 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
3101 !DeviceInterfaceData->Reserved)
3102 {
3103 SetLastError(ERROR_INVALID_PARAMETER);
3104 return FALSE;
3105 }
3106 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
3107 {
3108 SetLastError(ERROR_INVALID_USER_BUFFER);
3109 return FALSE;
3110 }
3111
3112 if((DeviceInterfaceDetailDataSize != 0) &&
3113 (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + sizeof(CHAR))))
3114 {
3115 SetLastError(ERROR_INVALID_USER_BUFFER);
3116 return FALSE;
3117 }
3118
3119 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
3120 {
3121 SetLastError(ERROR_INVALID_USER_BUFFER);
3122 return FALSE;
3123 }
3124
3125
3126 if (DeviceInterfaceDetailData != NULL)
3127 {
3128 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
3129 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
3130 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW);
3131 if (!DeviceInterfaceDetailDataW)
3132 {
3133 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3134 }
3135 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
3136 }
3137 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
3138 {
3139 ret = SetupDiGetDeviceInterfaceDetailW(
3140 DeviceInfoSet,
3141 DeviceInterfaceData,
3142 DeviceInterfaceDetailDataW,
3143 sizeW,
3144 &sizeW,
3145 DeviceInfoData);
3146 bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
3147 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
3148 if (RequiredSize)
3149 *RequiredSize = bytesNeeded;
3150 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize >= bytesNeeded)
3151 {
3152 if (!WideCharToMultiByte(
3153 CP_ACP, 0,
3154 DeviceInterfaceDetailDataW->DevicePath, -1,
3155 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
3156 NULL, NULL))
3157 {
3158 ret = FALSE;
3159 }
3160 }
3161 }
3162 MyFree(DeviceInterfaceDetailDataW);
3163
3164 return ret;
3165 }
3166
3167 /***********************************************************************
3168 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3169 */
3170 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
3171 HDEVINFO DeviceInfoSet,
3172 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
3173 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
3174 DWORD DeviceInterfaceDetailDataSize,
3175 PDWORD RequiredSize,
3176 PSP_DEVINFO_DATA DeviceInfoData)
3177 {
3178 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3179 BOOL ret = FALSE;
3180
3181 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
3182 DeviceInterfaceData, DeviceInterfaceDetailData,
3183 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
3184
3185 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
3186 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3187 {
3188 SetLastError(ERROR_INVALID_HANDLE);
3189 return FALSE;
3190 }
3191 if (!DeviceInterfaceData ||
3192 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
3193 !DeviceInterfaceData->Reserved)
3194 {
3195 SetLastError(ERROR_INVALID_PARAMETER);
3196 return FALSE;
3197 }
3198 if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
3199 {
3200 SetLastError(ERROR_INVALID_USER_BUFFER);
3201 return FALSE;
3202 }
3203 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
3204 {
3205 SetLastError(ERROR_INVALID_USER_BUFFER);
3206 return FALSE;
3207 }
3208 if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3209 {
3210 SetLastError(ERROR_INVALID_PARAMETER);
3211 return FALSE;
3212 }
3213 if ((DeviceInterfaceDetailData != NULL)
3214 && (DeviceInterfaceDetailDataSize < (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) + sizeof(WCHAR)))
3215 {
3216 SetLastError(ERROR_INVALID_PARAMETER);
3217 return FALSE;
3218 }
3219 else
3220 {
3221 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
3222 LPCWSTR devName = deviceInterface->SymbolicLink;
3223 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
3224 (lstrlenW(devName) + 1) * sizeof(WCHAR);
3225
3226 if (sizeRequired > DeviceInterfaceDetailDataSize)
3227 {
3228 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3229 if (RequiredSize)
3230 *RequiredSize = sizeRequired;
3231 }
3232 else
3233 {
3234 strcpyW(DeviceInterfaceDetailData->DevicePath, devName);
3235 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
3236 if (DeviceInfoData)
3237 {
3238 memcpy(&DeviceInfoData->ClassGuid,
3239 &deviceInterface->DeviceInfo->ClassGuid,
3240 sizeof(GUID));
3241 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
3242 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
3243 }
3244 ret = TRUE;
3245 }
3246 }
3247 return ret;
3248 }
3249
3250 struct PropertyMapEntry
3251 {
3252 DWORD regType;
3253 LPCSTR nameA;
3254 LPCWSTR nameW;
3255 };
3256
3257 static struct PropertyMapEntry PropertyMap[] = {
3258 { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC },
3259 { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID },
3260 { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS },
3261 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
3262 { REG_SZ, "Service", REGSTR_VAL_SERVICE },
3263 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
3264 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
3265 { REG_SZ, "Class", REGSTR_VAL_CLASS },
3266 { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID },
3267 { REG_SZ, "Driver", REGSTR_VAL_DRIVER },
3268 { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS },
3269 { REG_SZ, "Mfg", REGSTR_VAL_MFG },
3270 { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME },
3271 { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION },
3272 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3273 { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES },
3274 { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER },
3275 { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS },
3276 { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS },
3277 { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */
3278 { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */
3279 { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */
3280 { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */
3281 { REG_BINARY, "Security", REGSTR_SECURITY },
3282 { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */
3283 { 0, NULL, NULL }, /* SPDRP_DEVTYPE */
3284 { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */
3285 { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */
3286 { 0, NULL, NULL }, /* SPDRP_ADDRESS */
3287 { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT },
3288 { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */
3289 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */
3290 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3291 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3292 { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */
3293 };
3294
3295 /***********************************************************************
3296 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3297 */
3298 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
3299 HDEVINFO DeviceInfoSet,
3300 PSP_DEVINFO_DATA DeviceInfoData,
3301 DWORD Property,
3302 PDWORD PropertyRegDataType,
3303 PBYTE PropertyBuffer,
3304 DWORD PropertyBufferSize,
3305 PDWORD RequiredSize)
3306 {
3307 BOOL ret;
3308 BOOL bIsStringProperty;
3309 DWORD RegType;
3310 DWORD RequiredSizeA, RequiredSizeW;
3311 DWORD PropertyBufferSizeW = 0;
3312 PBYTE PropertyBufferW = NULL;
3313
3314 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3315 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3316 RequiredSize);
3317
3318 if (PropertyBufferSize != 0)
3319 {
3320 PropertyBufferSizeW = PropertyBufferSize * 2;
3321 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
3322 if (!PropertyBufferW)
3323 {
3324 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3325 return FALSE;
3326 }
3327 }
3328
3329 ret = SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet,
3330 DeviceInfoData,
3331 Property,
3332 &RegType,
3333 PropertyBufferW,
3334 PropertyBufferSizeW,
3335 &RequiredSizeW);
3336
3337 if (ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3338 {
3339 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
3340
3341 if (bIsStringProperty)
3342 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
3343 else
3344 RequiredSizeA = RequiredSizeW;
3345 if (RequiredSize)
3346 *RequiredSize = RequiredSizeA;
3347 if (PropertyRegDataType)
3348 *PropertyRegDataType = RegType;
3349 }
3350
3351 if (!ret)
3352 {
3353 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3354 return ret;
3355 }
3356
3357 if (RequiredSizeA <= PropertyBufferSize)
3358 {
3359 if (bIsStringProperty && PropertyBufferSize > 0)
3360 {
3361 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
3362 {
3363 /* Last error is already set by WideCharToMultiByte */
3364 ret = FALSE;
3365 }
3366 }
3367 else
3368 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
3369 }
3370 else
3371 {
3372 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3373 ret = FALSE;
3374 }
3375
3376 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3377 return ret;
3378 }
3379
3380 /***********************************************************************
3381 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3382 */
3383 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
3384 HDEVINFO DeviceInfoSet,
3385 PSP_DEVINFO_DATA DeviceInfoData,
3386 DWORD Property,
3387 PDWORD PropertyRegDataType,
3388 PBYTE PropertyBuffer,
3389 DWORD PropertyBufferSize,
3390 PDWORD RequiredSize)
3391 {
3392 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3393 struct DeviceInfo *devInfo;
3394 CONFIGRET cr;
3395 LONG lError = ERROR_SUCCESS;
3396 DWORD size;
3397
3398 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3399 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3400 RequiredSize);
3401
3402 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3403 {
3404 SetLastError(ERROR_INVALID_HANDLE);
3405 return FALSE;
3406 }
3407 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3408 {
3409 SetLastError(ERROR_INVALID_HANDLE);
3410 return FALSE;
3411 }
3412 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3413 || !DeviceInfoData->Reserved)
3414 {
3415 SetLastError(ERROR_INVALID_PARAMETER);
3416 return FALSE;
3417 }
3418
3419 if (Property >= SPDRP_MAXIMUM_PROPERTY)
3420 {
3421 SetLastError(ERROR_INVALID_REG_PROPERTY);
3422 return FALSE;
3423 }
3424
3425 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3426
3427 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3428 && PropertyMap[Property].nameW)
3429 {
3430 HKEY hKey;
3431 size = PropertyBufferSize;
3432 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
3433 if (hKey == INVALID_HANDLE_VALUE)
3434 return FALSE;
3435 lError = RegQueryValueExW(hKey, PropertyMap[Property].nameW,
3436 NULL, PropertyRegDataType, PropertyBuffer, &size);
3437 RegCloseKey(hKey);
3438
3439 if (RequiredSize)
3440 *RequiredSize = size;
3441
3442 switch (lError)
3443 {
3444 case ERROR_SUCCESS:
3445 if (PropertyBuffer == NULL && size != 0)
3446 lError = ERROR_INSUFFICIENT_BUFFER;
3447 break;
3448 case ERROR_MORE_DATA:
3449 lError = ERROR_INSUFFICIENT_BUFFER;
3450 break;
3451 default:
3452 break;
3453 }
3454 }
3455 else if (Property == SPDRP_PHYSICAL_DEVICE_OBJECT_NAME)
3456 {
3457 size = (strlenW(devInfo->Data) + 1) * sizeof(WCHAR);
3458
3459 if (PropertyRegDataType)
3460 *PropertyRegDataType = REG_SZ;
3461 if (RequiredSize)
3462 *RequiredSize = size;
3463 if (PropertyBufferSize >= size)
3464 {
3465 strcpyW((LPWSTR)PropertyBuffer, devInfo->Data);
3466 }
3467 else
3468 lError = ERROR_INSUFFICIENT_BUFFER;
3469 }
3470 else
3471 {
3472 size = PropertyBufferSize;
3473
3474 cr = CM_Get_DevNode_Registry_Property_ExW(devInfo->dnDevInst,
3475 Property + (CM_DRP_DEVICEDESC - SPDRP_DEVICEDESC),
3476 PropertyRegDataType,
3477 PropertyBuffer,
3478 &size,
3479 0,
3480 set->hMachine);
3481 if ((cr == CR_SUCCESS) || (cr == CR_BUFFER_SMALL))
3482 {
3483 if (RequiredSize)
3484 *RequiredSize = size;
3485 }
3486
3487 if (cr != CR_SUCCESS)
3488 {
3489 switch (cr)
3490 {
3491 case CR_INVALID_DEVINST:
3492 lError = ERROR_NO_SUCH_DEVINST;
3493 break;
3494
3495 case CR_INVALID_PROPERTY:
3496 lError = ERROR_INVALID_REG_PROPERTY;
3497 break;
3498
3499 case CR_BUFFER_SMALL:
3500 lError = ERROR_INSUFFICIENT_BUFFER;
3501 break;
3502
3503 default :
3504 lError = ERROR_INVALID_DATA;
3505 break;
3506 }
3507 }
3508 }
3509
3510 SetLastError(lError);
3511 return (lError == ERROR_SUCCESS);
3512 }
3513
3514 /***********************************************************************
3515 * Internal for SetupDiSetDeviceRegistryPropertyA/W
3516 */
3517 BOOL WINAPI IntSetupDiSetDeviceRegistryPropertyAW(
3518 HDEVINFO DeviceInfoSet,
3519 PSP_DEVINFO_DATA DeviceInfoData,
3520 DWORD Property,
3521 const BYTE *PropertyBuffer,
3522 DWORD PropertyBufferSize,
3523 BOOL isAnsi)
3524 {
3525 BOOL ret = FALSE;
3526 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3527
3528 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3529 PropertyBuffer, PropertyBufferSize);
3530
3531 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3532 {
3533 SetLastError(ERROR_INVALID_HANDLE);
3534 return FALSE;
3535 }
3536 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3537 {
3538 SetLastError(ERROR_INVALID_HANDLE);
3539 return FALSE;
3540 }
3541 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3542 || !DeviceInfoData->Reserved)
3543 {
3544 SetLastError(ERROR_INVALID_PARAMETER);
3545 return FALSE;
3546 }
3547 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3548 && PropertyMap[Property].nameW
3549 && PropertyMap[Property].nameA)
3550 {
3551 HKEY hKey;
3552 LONG l;
3553 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
3554 if (hKey == INVALID_HANDLE_VALUE)
3555 return FALSE;
3556 /* Write new data */
3557 if (isAnsi)
3558 {
3559 l = RegSetValueExA(
3560 hKey, PropertyMap[Property].nameA, 0,
3561 PropertyMap[Property].regType, PropertyBuffer,
3562 PropertyBufferSize);
3563 }
3564 else
3565 {
3566 l = RegSetValueExW(
3567 hKey, PropertyMap[Property].nameW, 0,
3568 PropertyMap[Property].regType, PropertyBuffer,
3569 PropertyBufferSize);
3570 }
3571 if (!l)
3572 ret = TRUE;
3573 else
3574 SetLastError(l);
3575 RegCloseKey(hKey);
3576 }
3577 else
3578 {
3579 ERR("Property 0x%lx not implemented\n", Property);
3580 SetLastError(ERROR_NOT_SUPPORTED);
3581 }
3582
3583 TRACE("Returning %d\n", ret);
3584 return ret;
3585 }
3586 /***********************************************************************
3587 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3588 */
3589 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
3590 HDEVINFO DeviceInfoSet,
3591 PSP_DEVINFO_DATA DeviceInfoData,
3592 DWORD Property,
3593 const BYTE *PropertyBuffer,
3594 DWORD PropertyBufferSize)
3595 {
3596 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet,
3597 DeviceInfoData,
3598 Property,
3599 PropertyBuffer,
3600 PropertyBufferSize,
3601 TRUE);
3602 }
3603
3604 /***********************************************************************
3605 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3606 */
3607 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
3608 HDEVINFO DeviceInfoSet,
3609 PSP_DEVINFO_DATA DeviceInfoData,
3610 DWORD Property,
3611 const BYTE *PropertyBuffer,
3612 DWORD PropertyBufferSize)
3613 {
3614 return IntSetupDiSetDeviceRegistryPropertyAW(DeviceInfoSet,
3615 DeviceInfoData,
3616 Property,
3617 PropertyBuffer,
3618 PropertyBufferSize,
3619 FALSE);
3620 }
3621
3622 /***********************************************************************
3623 * SetupDiInstallClassA (SETUPAPI.@)
3624 */
3625 BOOL WINAPI SetupDiInstallClassA(
3626 HWND hwndParent,
3627 PCSTR InfFileName,
3628 DWORD Flags,
3629 HSPFILEQ FileQueue)
3630 {
3631 return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3632 }
3633
3634 /***********************************************************************
3635 * SetupDiInstallClassExA (SETUPAPI.@)
3636 */
3637 BOOL WINAPI
3638 SetupDiInstallClassExA(
3639 IN HWND hwndParent OPTIONAL,
3640 IN PCSTR InfFileName OPTIONAL,
3641 IN DWORD Flags,
3642 IN HSPFILEQ FileQueue OPTIONAL,
3643 IN CONST GUID *InterfaceClassGuid OPTIONAL,
3644 IN PVOID Reserved1,
3645 IN PVOID Reserved2)
3646 {
3647 PWSTR InfFileNameW = NULL;
3648 BOOL Result;
3649
3650 if (!InfFileName)
3651 {
3652 SetLastError(ERROR_INVALID_PARAMETER);
3653 return FALSE;
3654 }
3655 else
3656 {
3657 InfFileNameW = pSetupMultiByteToUnicode(InfFileName, CP_ACP);
3658 if (InfFileNameW == NULL)
3659 {
3660 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3661 return FALSE;
3662 }
3663 }
3664
3665 Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags,
3666 FileQueue, InterfaceClassGuid, Reserved1, Reserved2);
3667
3668 MyFree(InfFileNameW);
3669
3670 return Result;
3671 }
3672
3673 HKEY SETUP_CreateClassKey(HINF hInf)
3674 {
3675 WCHAR FullBuffer[MAX_PATH];
3676 WCHAR Buffer[MAX_PATH];
3677 DWORD RequiredSize;
3678 HKEY hClassKey;
3679 DWORD Disposition;
3680
3681 /* Obtain the Class GUID for this class */
3682 if (!SetupGetLineTextW(NULL,
3683 hInf,
3684 Version,
3685 REGSTR_VAL_CLASSGUID,
3686 Buffer,
3687 sizeof(Buffer) / sizeof(WCHAR),
3688 &RequiredSize))
3689 {
3690 return INVALID_HANDLE_VALUE;
3691 }
3692
3693 /* Build the corresponding registry key name */
3694 lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
3695 lstrcatW(FullBuffer, BackSlash);
3696 lstrcatW(FullBuffer, Buffer);
3697
3698 /* Obtain the Class name for this class */
3699 if (!SetupGetLineTextW(NULL,
3700 hInf,
3701 Version,
3702 REGSTR_VAL_CLASS,
3703 Buffer,
3704 sizeof(Buffer) / sizeof(WCHAR),
3705 &RequiredSize))
3706 {
3707 return INVALID_HANDLE_VALUE;
3708 }
3709
3710 /* Try to open or create the registry key */
3711 TRACE("Opening class key %s\n", debugstr_w(FullBuffer));
3712 #if 0 // I keep this for reference...
3713 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3714 FullBuffer,
3715 0,
3716 KEY_SET_VALUE,
3717 &hClassKey))
3718 {
3719 /* Use RegCreateKeyExW */
3720 }
3721 #endif
3722 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3723 FullBuffer,
3724 0,
3725 NULL,
3726 REG_OPTION_NON_VOLATILE,
3727 KEY_SET_VALUE,
3728 NULL,
3729 &hClassKey,
3730 &Disposition))
3731 {
3732 ERR("RegCreateKeyExW(%s) failed\n", debugstr_w(FullBuffer));
3733 return INVALID_HANDLE_VALUE;
3734 }
3735 if (Disposition == REG_CREATED_NEW_KEY)
3736 TRACE("The class key %s was successfully created\n", debugstr_w(FullBuffer));
3737 else
3738 TRACE("The class key %s was successfully opened\n", debugstr_w(FullBuffer));
3739
3740 TRACE( "setting value %s to %s\n", debugstr_w(REGSTR_VAL_CLASS), debugstr_w(Buffer) );
3741 if (RegSetValueExW(hClassKey,
3742 REGSTR_VAL_CLASS,
3743 0,
3744 REG_SZ,
3745 (LPBYTE)Buffer,
3746 RequiredSize * sizeof(WCHAR)))
3747 {
3748 RegCloseKey(hClassKey);
3749 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
3750 FullBuffer);
3751 return INVALID_HANDLE_VALUE;
3752 }
3753
3754 return hClassKey;
3755 }
3756
3757 /***********************************************************************
3758 * SetupDiInstallClassW (SETUPAPI.@)
3759 */
3760 BOOL WINAPI SetupDiInstallClassW(
3761 HWND hwndParent,
3762 PCWSTR InfFileName,
3763 DWORD Flags,
3764 HSPFILEQ FileQueue)
3765 {
3766 return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3767 }
3768
3769
3770 /***********************************************************************
3771 * SetupDiOpenClassRegKey (SETUPAPI.@)
3772 */
3773 HKEY WINAPI SetupDiOpenClassRegKey(
3774 const GUID* ClassGuid,
3775 REGSAM samDesired)
3776 {
3777 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3778 DIOCR_INSTALLER, NULL, NULL);
3779 }
3780
3781
3782 /***********************************************************************
3783 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3784 */
3785 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3786 const GUID* ClassGuid,
3787 REGSAM samDesired,
3788 DWORD Flags,
3789 PCSTR MachineName,
3790 PVOID Reserved)
3791 {
3792 PWSTR MachineNameW = NULL;
3793 HKEY hKey;
3794
3795 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
3796 Flags, debugstr_a(MachineName), Reserved);
3797
3798 if (MachineName)
3799 {
3800 MachineNameW = pSetupMultiByteToUnicode(MachineName, CP_ACP);
3801 if (MachineNameW == NULL)
3802 return INVALID_HANDLE_VALUE;
3803 }
3804
3805 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3806 Flags, MachineNameW, Reserved);
3807
3808 MyFree(MachineNameW);
3809
3810 return hKey;
3811 }
3812
3813
3814 /***********************************************************************
3815 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3816 */
3817 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3818 const GUID* ClassGuid,
3819 REGSAM samDesired,
3820 DWORD Flags,
3821 PCWSTR MachineName,
3822 PVOID Reserved)
3823 {
3824 HKEY HKLM;
3825 HKEY hClassesKey;
3826 HKEY key;
3827 LPCWSTR lpKeyName;
3828 LONG l;
3829
3830 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
3831 Flags, debugstr_w(MachineName), Reserved);
3832
3833 if (MachineName != NULL)
3834 {
3835 l = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
3836 if (l != ERROR_SUCCESS)
3837 {
3838 SetLastError(l);
3839 return INVALID_HANDLE_VALUE;
3840 }
3841 }
3842 else
3843 HKLM = HKEY_LOCAL_MACHINE;
3844
3845 if (Flags == DIOCR_INSTALLER)
3846 {
3847 lpKeyName = REGSTR_PATH_CLASS_NT;
3848 }
3849 else if (Flags == DIOCR_INTERFACE)
3850 {
3851 lpKeyName = REGSTR_PATH_DEVICE_CLASSES;
3852 }
3853 else
3854 {
3855 ERR("Invalid Flags parameter!\n");
3856 SetLastError(ERROR_INVALID_FLAGS);
3857 if (MachineName != NULL) RegCloseKey(HKLM);
3858 return INVALID_HANDLE_VALUE;
3859 }
3860
3861 if (!ClassGuid)
3862 {
3863 if ((l = RegOpenKeyExW(HKLM,
3864 lpKeyName,
3865 0,
3866 samDesired,
3867 &hClassesKey)))
3868 {
3869 SetLastError(ERROR_INVALID_CLASS);
3870 hClassesKey = INVALID_HANDLE_VALUE;
3871 }
3872 if (MachineName != NULL)
3873 RegCloseKey(HKLM);
3874 key = hClassesKey;
3875 }
3876 else
3877 {
3878 WCHAR bracedGuidString[39];
3879
3880 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3881
3882 if (!(l = RegOpenKeyExW(HKLM,
3883 lpKeyName,
3884 0,
3885 samDesired,
3886 &hClassesKey)))
3887 {
3888 if (MachineName != NULL)
3889 RegCloseKey(HKLM);
3890
3891 if ((l = RegOpenKeyExW(hClassesKey,
3892 bracedGuidString,
3893 0,
3894 samDesired,
3895 &key)))
3896 {
3897 SetLastError(l);
3898 key = INVALID_HANDLE_VALUE;
3899 }
3900 RegCloseKey(hClassesKey);
3901 }
3902 else
3903 {
3904 if (MachineName != NULL) RegCloseKey(HKLM);
3905 SetLastError(l);
3906 key = INVALID_HANDLE_VALUE;
3907 }
3908 }
3909
3910 return key;
3911 }
3912
3913 /***********************************************************************
3914 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3915 */
3916 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3917 HDEVINFO DeviceInfoSet,
3918 PCWSTR DevicePath,
3919 DWORD OpenFlags,
3920 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3921 {
3922 struct DeviceInfoSet * list;
3923 PCWSTR pEnd;
3924 DWORD dwLength, dwError, dwIndex, dwKeyName, dwSubIndex;
3925 CLSID ClassId;
3926 WCHAR Buffer[MAX_PATH + 1];
3927 WCHAR SymBuffer[MAX_PATH + 1];
3928 WCHAR InstancePath[MAX_PATH + 1];
3929 HKEY hKey, hDevKey, hSymKey;
3930 struct DeviceInfo * deviceInfo;
3931 struct DeviceInterface *deviceInterface;
3932 BOOL Ret;
3933 PLIST_ENTRY ItemList;
3934 PLIST_ENTRY InterfaceListEntry;
3935
3936 TRACE("%p %s %08x %p\n",
3937 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3938
3939
3940 if (DeviceInterfaceData && DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
3941 {
3942 SetLastError(ERROR_INVALID_PARAMETER);
3943 return FALSE;
3944 }
3945
3946 if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3947 {
3948 SetLastError(ERROR_INVALID_HANDLE);
3949 return FALSE;
3950 }
3951
3952 list = (struct DeviceInfoSet * )DeviceInfoSet;
3953
3954 dwLength = wcslen(DevicePath);
3955 if (dwLength < 39)
3956 {
3957 /* path must be at least a guid length + L'\0' */
3958 SetLastError(ERROR_BAD_PATHNAME);
3959 return FALSE;
3960 }
3961
3962 if (DevicePath[0] != L'\\' ||
3963 DevicePath[1] != L'\\' ||
3964 (DevicePath[2] != L'?' && DevicePath[2] != L'.') ||
3965 DevicePath[3] != L'\\')
3966 {
3967 /* invalid formatted path */
3968 SetLastError(ERROR_BAD_PATHNAME);
3969 return FALSE;
3970 }
3971
3972 /* check for reference strings */
3973 pEnd = wcschr(&DevicePath[4], L'\\');
3974 if (!pEnd)
3975 {
3976 /* no reference string */
3977 pEnd = DevicePath + dwLength;
3978 }
3979
3980 /* copy guid */
3981 wcscpy(Buffer, pEnd - 37);
3982 Buffer[36] = L'\0';
3983
3984 dwError = UuidFromStringW(Buffer, &ClassId);
3985 if (dwError != NOERROR)
3986 {
3987 /* invalid formatted path */
3988 SetLastError(ERROR_BAD_PATHNAME);
3989 return FALSE;
3990 }
3991
3992 hKey = SetupDiOpenClassRegKeyExW(&ClassId, KEY_READ, DIOCR_INTERFACE, list->MachineName, NULL);
3993
3994 if (hKey == INVALID_HANDLE_VALUE)
3995 {
3996 /* invalid device class */
3997 return FALSE;
3998 }
3999
4000 ItemList = list->ListHead.Flink;
4001 while (ItemList != &list->ListHead)
4002 {
4003 deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
4004 InterfaceListEntry = deviceInfo->InterfaceListHead.Flink;
4005 while (InterfaceListEntry != &deviceInfo->InterfaceListHead)
4006 {
4007 deviceInterface = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
4008 if (!IsEqualIID(&deviceInterface->InterfaceClassGuid, &ClassId))
4009 {
4010 InterfaceListEntry = InterfaceListEntry->Flink;
4011 continue;
4012 }
4013
4014 if (!wcsicmp(deviceInterface->SymbolicLink, DevicePath))
4015 {
4016 if (DeviceInterfaceData)
4017 {
4018 DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface;
4019 DeviceInterfaceData->Flags = deviceInterface->Flags;
4020 CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID));
4021 }
4022
4023 return TRUE;
4024 }
4025
4026 }
4027 }
4028
4029
4030 dwIndex = 0;
4031 do
4032 {
4033 Buffer[0] = 0;
4034 dwKeyName = sizeof(Buffer) / sizeof(WCHAR);
4035 dwError = RegEnumKeyExW(hKey, dwIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL);
4036
4037 if (dwError != ERROR_SUCCESS)
4038 break;
4039
4040 if (RegOpenKeyExW(hKey, Buffer, 0, KEY_READ, &hDevKey) != ERROR_SUCCESS)
4041 break;
4042
4043 dwSubIndex = 0;
4044 InstancePath[0] = 0;
4045 dwKeyName = sizeof(InstancePath);
4046
4047 dwError = RegQueryValueExW(hDevKey, L"DeviceInstance", NULL, NULL, (LPBYTE)InstancePath, &dwKeyName);
4048
4049 while(TRUE)
4050 {
4051 Buffer[0] = 0;
4052 dwKeyName = sizeof(Buffer) / sizeof(WCHAR);
4053 dwError = RegEnumKeyExW(hDevKey, dwSubIndex, Buffer, &dwKeyName, NULL, NULL, NULL, NULL);
4054
4055 if (dwError != ERROR_SUCCESS)
4056 break;
4057
4058 dwError = RegOpenKeyExW(hDevKey, Buffer, 0, KEY_READ, &hSymKey);
4059 if (dwError != ERROR_SUCCESS)
4060 break;
4061
4062 /* query for symbolic link */
4063 dwKeyName = sizeof(SymBuffer);
4064 SymBuffer[0] = L'\0';
4065 dwError = RegQueryValueExW(hSymKey, L"SymbolicLink", NULL, NULL, (LPBYTE)SymBuffer, &dwKeyName);
4066
4067 if (dwError != ERROR_SUCCESS)
4068 {
4069 RegCloseKey(hSymKey);
4070 break;
4071 }
4072
4073 if (!wcsicmp(SymBuffer, DevicePath))
4074 {
4075 Ret = CreateDeviceInfo(list, InstancePath, &ClassId, &deviceInfo);
4076 RegCloseKey(hSymKey);
4077 RegCloseKey(hDevKey);
4078 RegCloseKey(hKey);
4079
4080 if (Ret)
4081 {
4082 deviceInterface = HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface) + (wcslen(SymBuffer) + 1) * sizeof(WCHAR));
4083 if (deviceInterface)
4084 {
4085
4086 CopyMemory(&deviceInterface->InterfaceClassGuid, &ClassId, sizeof(GUID));
4087 deviceInterface->DeviceInfo = deviceInfo;
4088 deviceInterface->Flags = SPINT_ACTIVE; //FIXME
4089
4090 wcscpy(deviceInterface->SymbolicLink, SymBuffer);
4091
4092 InsertTailList(&deviceInfo->InterfaceListHead, &deviceInterface->ListEntry);
4093 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
4094
4095
4096 if (DeviceInterfaceData)
4097 {
4098 DeviceInterfaceData->Reserved = (ULONG_PTR)deviceInterface;
4099 DeviceInterfaceData->Flags = deviceInterface->Flags;
4100 CopyMemory(&DeviceInterfaceData->InterfaceClassGuid, &ClassId, sizeof(GUID));
4101 }
4102 else
4103 {
4104 Ret = FALSE;
4105 SetLastError(ERROR_INVALID_USER_BUFFER);
4106 }
4107 }
4108 }
4109 else
4110 {
4111 HeapFree(GetProcessHeap(), 0, deviceInfo);
4112 Ret = FALSE;
4113 }
4114 return Ret;
4115 }
4116 RegCloseKey(hSymKey);
4117 dwSubIndex++;
4118 }
4119
4120 RegCloseKey(hDevKey);
4121 dwIndex++;
4122 } while(TRUE);
4123
4124 RegCloseKey(hKey);
4125 return FALSE;
4126 }
4127
4128 /***********************************************************************
4129 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
4130 */
4131 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
4132 HDEVINFO DeviceInfoSet,
4133 PCSTR DevicePath,
4134 DWORD OpenFlags,
4135 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
4136 {
4137 LPWSTR DevicePathW = NULL;
4138 BOOL bResult;
4139
4140 TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
4141
4142 DevicePathW = pSetupMultiByteToUnicode(DevicePath, CP_ACP);
4143 if (DevicePathW == NULL)
4144 return FALSE;
4145
4146 bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet,
4147 DevicePathW, OpenFlags, DeviceInterfaceData);
4148
4149 MyFree(DevicePathW);
4150
4151 return bResult;
4152 }
4153
4154 /***********************************************************************
4155 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
4156 */
4157 BOOL WINAPI SetupDiSetClassInstallParamsA(
4158 HDEVINFO DeviceInfoSet,
4159 PSP_DEVINFO_DATA DeviceInfoData,
4160 PSP_CLASSINSTALL_HEADER ClassInstallParams,
4161 DWORD ClassInstallParamsSize)
4162 {
4163 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
4164 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
4165 return FALSE;
4166 }
4167
4168 static BOOL WINAPI
4169 IntSetupDiRegisterDeviceInfo(
4170 IN HDEVINFO DeviceInfoSet,
4171 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
4172 {
4173 return SetupDiRegisterDeviceInfo(DeviceInfoSet, DeviceInfoData, 0, NULL, NULL, NULL);
4174 }
4175
4176 /***********************************************************************
4177 * SetupDiCallClassInstaller (SETUPAPI.@)
4178 */
4179 BOOL WINAPI SetupDiCallClassInstaller(
4180 DI_FUNCTION InstallFunction,
4181 HDEVINFO DeviceInfoSet,
4182 PSP_DEVINFO_DATA DeviceInfoData)
4183 {
4184 BOOL ret = FALSE;
4185
4186 TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
4187
4188 if (!DeviceInfoSet)
4189 SetLastError(ERROR_INVALID_PARAMETER);
4190 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
4191 SetLastError(ERROR_INVALID_HANDLE);
4192 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4193 SetLastError(ERROR_INVALID_HANDLE);
4194 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
4195 SetLastError(ERROR_INVALID_HANDLE);
4196 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4197 SetLastError(ERROR_INVALID_USER_BUFFER);
4198 else
4199 {
4200 SP_DEVINSTALL_PARAMS_W InstallParams;
4201 #define CLASS_COINSTALLER 0x1
4202 #define DEVICE_COINSTALLER 0x2
4203 #define CLASS_INSTALLER 0x4
4204 UCHAR CanHandle = 0;
4205 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
4206
4207 switch (InstallFunction)
4208 {
4209 case DIF_ADDPROPERTYPAGE_ADVANCED:
4210 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4211 break;
4212 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED:
4213 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4214 break;
4215 case DIF_ALLOW_INSTALL:
4216 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4217 break;
4218 case DIF_DETECT:
4219 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4220 break;
4221 case DIF_DESTROYPRIVATEDATA:
4222 CanHandle = CLASS_INSTALLER;
4223 break;
4224 case DIF_INSTALLDEVICE:
4225 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4226 DefaultHandler = SetupDiInstallDevice;
4227 break;
4228 case DIF_INSTALLDEVICEFILES:
4229 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4230 DefaultHandler = SetupDiInstallDriverFiles;
4231 break;
4232 case DIF_INSTALLINTERFACES:
4233 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4234 DefaultHandler = SetupDiInstallDeviceInterfaces;
4235 break;
4236 case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
4237 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4238 break;
4239 case DIF_NEWDEVICEWIZARD_POSTANALYZE:
4240 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4241 break;
4242 case DIF_NEWDEVICEWIZARD_PREANALYZE:
4243 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4244 break;
4245 case DIF_NEWDEVICEWIZARD_PRESELECT:
4246 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4247 break;
4248 case DIF_NEWDEVICEWIZARD_SELECT:
4249 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4250 break;
4251 case DIF_POWERMESSAGEWAKE:
4252 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4253 break;
4254 case DIF_PROPERTYCHANGE:
4255 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4256 DefaultHandler = SetupDiChangeState;
4257 break;
4258 case DIF_REGISTER_COINSTALLERS:
4259 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4260 DefaultHandler = SetupDiRegisterCoDeviceInstallers;
4261 break;
4262 case DIF_REGISTERDEVICE:
4263 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4264 DefaultHandler = IntSetupDiRegisterDeviceInfo;
4265 break;
4266 case DIF_REMOVE:
4267 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4268 DefaultHandler = SetupDiRemoveDevice;
4269 break;
4270 case DIF_SELECTBESTCOMPATDRV:
4271 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4272 DefaultHandler = SetupDiSelectBestCompatDrv;
4273 break;
4274 case DIF_SELECTDEVICE:
4275 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
4276 DefaultHandler = SetupDiSelectDevice;
4277 break;
4278 case DIF_TROUBLESHOOTER:
4279 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4280 break;
4281 case DIF_UNREMOVE:
4282 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
4283 DefaultHandler = SetupDiUnremoveDevice;
4284 break;
4285 default:
4286 ERR("Install function %u not supported\n", InstallFunction);
4287 SetLastError(ERROR_NOT_SUPPORTED);
4288 }
4289
4290 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4291 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
4292 /* Don't process this call, as a parameter is invalid */
4293 CanHandle = 0;
4294
4295 if (CanHandle != 0)
4296 {
4297 LIST_ENTRY ClassCoInstallersListHead;
4298 LIST_ENTRY DeviceCoInstallersListHead;
4299 HMODULE ClassInstallerLibrary = NULL;
4300 CLASS_INSTALL_PROC ClassInstaller = NULL;
4301 COINSTALLER_CONTEXT_DATA Context;
4302 PLIST_ENTRY ListEntry;
4303 HKEY hKey;
4304 DWORD dwRegType, dwLength;
4305 DWORD rc = NO_ERROR;
4306
4307 InitializeListHead(&ClassCoInstallersListHead);
4308 InitializeListHead(&DeviceCoInstallersListHead);
4309
4310 if (CanHandle & DEVICE_COINSTALLER)
4311 {
4312 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
4313 if (hKey != INVALID_HANDLE_VALUE)
4314 {
4315 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength);
4316 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
4317 {
4318 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4319 if (KeyBuffer != NULL)
4320 {
4321 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4322 if (rc == ERROR_SUCCESS)
4323 {
4324 LPWSTR ptr;
4325 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
4326 {
4327 /* Add coinstaller to DeviceCoInstallersListHead list */
4328 struct CoInstallerElement *coinstaller;
4329 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
4330 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
4331 if (!coinstaller)
4332 continue;
4333 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
4334 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
4335 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
4336 else
4337 HeapFree(GetProcessHeap(), 0, coinstaller);
4338 }
4339 }
4340 HeapFree(GetProcessHeap(), 0, KeyBuffer);
4341 }
4342 }
4343 RegCloseKey(hKey);
4344 }
4345 }
4346 if (CanHandle & CLASS_COINSTALLER)
4347 {
4348 rc = RegOpenKeyExW(
4349 HKEY_LOCAL_MACHINE,
4350 REGSTR_PATH_CODEVICEINSTALLERS,
4351 0, /* Options */
4352 KEY_QUERY_VALUE,
4353 &hKey);
4354 if (rc == ERROR_SUCCESS)
4355 {
4356 WCHAR szGuidString[40];
4357 if (pSetupStringFromGuid(&DeviceInfoData->ClassGuid, szGuidString, ARRAYSIZE(szGuidString)) == ERROR_SUCCESS)
4358 {
4359 rc = RegQueryValueExW(hKey, szGuidString, NULL, &dwRegType, NULL, &dwLength);
4360 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
4361 {
4362 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4363 if (KeyBuffer != NULL)
4364 {
4365 rc = RegQueryValueExW(hKey, szGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4366 if (rc == ERROR_SUCCESS)
4367 {
4368 LPWSTR ptr;
4369 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
4370 {
4371 /* Add coinstaller to ClassCoInstallersListHead list */
4372 struct CoInstallerElement *coinstaller;
4373 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
4374 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
4375 if (!coinstaller)
4376 continue;
4377 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
4378 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
4379 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
4380 else
4381 HeapFree(GetProcessHeap(), 0, coinstaller);
4382 }
4383 }
4384 HeapFree(GetProcessHeap(), 0, KeyBuffer);
4385 }
4386 }
4387 }
4388 RegCloseKey(hKey);
4389 }
4390 }
4391 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
4392 {
4393 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
4394 if (hKey != INVALID_HANDLE_VALUE)
4395 {
4396 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
4397 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
4398 {
4399 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
4400 if (KeyBuffer != NULL)
4401 {
4402 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
4403 if (rc == ERROR_SUCCESS)
4404 {
4405 /* Get ClassInstaller function pointer */
4406 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
4407 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
4408 {
4409 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
4410 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4411 }
4412 }
4413 HeapFree(GetProcessHeap(), 0, KeyBuffer);
4414 }
4415 }
4416 RegCloseKey(hKey);
4417 }
4418 }
4419
4420 /* Call Class co-installers */
4421 Context.PostProcessing = FALSE;
4422 rc = NO_ERROR;
4423 ListEntry = ClassCoInstallersListHead.Flink;
4424 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
4425 {
4426 struct CoInstallerElement *coinstaller;
4427 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4428 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4429 coinstaller->PrivateData = Context.PrivateData;
4430 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
4431 {
4432 coinstaller->DoPostProcessing = TRUE;
4433 rc = NO_ERROR;
4434 }
4435 ListEntry = ListEntry->Flink;
4436 }
4437
4438 /* Call Device co-installers */
4439 ListEntry = DeviceCoInstallersListHead.Flink;
4440 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
4441 {
4442 struct CoInstallerElement *coinstaller;
4443 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4444 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4445 coinstaller->PrivateData = Context.PrivateData;
4446 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
4447 {
4448 coinstaller->DoPostProcessing = TRUE;
4449 rc = NO_ERROR;
4450 }
4451 ListEntry = ListEntry->Flink;
4452 }
4453
4454 /* Call Class installer */
4455 if (ClassInstaller)
4456 {
4457 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
4458 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
4459 }
4460 else
4461 rc = ERROR_DI_DO_DEFAULT;
4462
4463 /* Call default handler */
4464 if (rc == ERROR_DI_DO_DEFAULT)
4465 {
4466 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
4467 {
4468 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
4469 rc = NO_ERROR;
4470 else
4471 rc = GetLastError();
4472 }
4473 else
4474 rc = NO_ERROR;
4475 }
4476
4477 /* Call Class co-installers that required postprocessing */
4478 Context.PostProcessing = TRUE;
4479 ListEntry = ClassCoInstallersListHead.Flink;
4480 while (ListEntry != &ClassCoInstallersListHead)
4481 {
4482 struct CoInstallerElement *coinstaller;
4483 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4484 if (coinstaller->DoPostProcessing)
4485 {
4486 Context.InstallResult = rc;
4487 Context.PrivateData = coinstaller->PrivateData;
4488 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4489 }
4490 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4491 ListEntry = ListEntry->Flink;
4492 }
4493
4494 /* Call Device co-installers that required postprocessing */
4495 ListEntry = DeviceCoInstallersListHead.Flink;
4496 while (ListEntry != &DeviceCoInstallersListHead)
4497 {
4498 struct CoInstallerElement *coinstaller;
4499 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4500 if (coinstaller->DoPostProcessing)
4501 {
4502 Context.InstallResult = rc;
4503 Context.PrivateData = coinstaller->PrivateData;
4504 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4505 }
4506 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4507 ListEntry = ListEntry->Flink;
4508 }
4509
4510 /* Free allocated memory */
4511 while (!IsListEmpty(&ClassCoInstallersListHead))
4512 {
4513 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
4514 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
4515 }
4516 while (!IsListEmpty(&DeviceCoInstallersListHead))
4517 {
4518 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
4519 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
4520 }
4521
4522 ret = (rc == NO_ERROR);
4523 }
4524 }
4525
4526 TRACE("Returning %d\n", ret);
4527 return ret;
4528 }
4529
4530 /***********************************************************************
4531 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4532 */
4533 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
4534 HDEVINFO DeviceInfoSet,
4535 PSP_DEVINFO_DATA DeviceInfoData,
4536 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
4537 {
4538 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
4539 BOOL ret = FALSE;
4540
4541 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4542
4543 if (DeviceInstallParams == NULL)
4544 SetLastError(ERROR_INVALID_PARAMETER);
4545 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
4546 SetLastError(ERROR_INVALID_USER_BUFFER);
4547 else
4548 {
4549 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4550 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
4551
4552 if (ret)
4553 {
4554 /* Do W->A conversion */
4555 memcpy(
4556 DeviceInstallParams,
4557 &deviceInstallParamsW,
4558 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
4559 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
4560 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
4561 {
4562 DeviceInstallParams->DriverPath[0] = '\0';
4563 ret = FALSE;
4564 }
4565 }
4566 }
4567
4568 TRACE("Returning %d\n", ret);
4569 return ret;
4570 }
4571
4572 /***********************************************************************
4573 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4574 */
4575 BOOL WINAPI
4576 SetupDiGetDeviceInfoListClass(
4577 IN HDEVINFO DeviceInfoSet,
4578 OUT LPGUID ClassGuid)
4579 {
4580 struct DeviceInfoSet *list;
4581 BOOL ret = FALSE;
4582
4583 TRACE("%p %p\n", DeviceInfoSet, ClassGuid);
4584
4585 if (!DeviceInfoSet)
4586 SetLastError(ERROR_INVALID_HANDLE);
4587 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4588 SetLastError(ERROR_INVALID_HANDLE);
4589 else if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
4590 SetLastError(ERROR_NO_ASSOCIATED_CLASS);
4591 else
4592 {
4593 memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID));
4594
4595 ret = TRUE;
4596 }
4597
4598 TRACE("Returning %d\n", ret);
4599 return ret;
4600 }
4601
4602 /***********************************************************************
4603 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4604 */
4605 BOOL WINAPI
4606 SetupDiGetDeviceInstallParamsW(
4607 IN HDEVINFO DeviceInfoSet,
4608 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4609 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4610 {
4611 struct DeviceInfoSet *list;
4612 BOOL ret = FALSE;
4613
4614 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4615
4616 if (!DeviceInfoSet)
4617 SetLastError(ERROR_INVALID_HANDLE);
4618 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4619 SetLastError(ERROR_INVALID_HANDLE);
4620 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4621 SetLastError(ERROR_INVALID_USER_BUFFER);
4622 else if (!DeviceInstallParams)
4623 SetLastError(ERROR_INVALID_PARAMETER);
4624 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
4625 SetLastError(ERROR_INVALID_USER_BUFFER);
4626 else
4627 {
4628 PSP_DEVINSTALL_PARAMS_W Source;
4629
4630 if (DeviceInfoData)
4631 Source = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
4632 else
4633 Source = &list->InstallParams;
4634
4635 ret = TRUE;
4636
4637 _SEH2_TRY
4638 {
4639 memcpy(DeviceInstallParams, Source, Source->cbSize);
4640 }
4641 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
4642 {
4643 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
4644 ret = FALSE;
4645 }
4646 _SEH2_END;
4647 }
4648
4649 TRACE("Returning %d\n", ret);
4650 return ret;
4651 }
4652
4653 static BOOL
4654 CheckDeviceInstallParameters(
4655 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4656 {
4657 DWORD SupportedFlags =
4658 DI_NOVCP | /* 0x00000008 */
4659 DI_DIDCOMPAT | /* 0x00000010 */
4660 DI_DIDCLASS | /* 0x00000020 */
4661 DI_NEEDRESTART | /* 0x00000080 */
4662 DI_NEEDREBOOT | /* 0x00000100 */
4663 DI_RESOURCEPAGE_ADDED | /* 0x00002000 */
4664 DI_PROPERTIES_CHANGE | /* 0x00004000 */
4665 DI_ENUMSINGLEINF | /* 0x00010000 */
4666 DI_DONOTCALLCONFIGMG | /* 0x00020000 */
4667 DI_CLASSINSTALLPARAMS | /* 0x00100000 */
4668 DI_NODI_DEFAULTACTION | /* 0x00200000 */
4669 DI_QUIETINSTALL | /* 0x00800000 */
4670 DI_NOFILECOPY | /* 0x01000000 */
4671 DI_DRIVERPAGE_ADDED; /* 0x04000000 */
4672 DWORD SupportedFlagsEx =
4673 DI_FLAGSEX_CI_FAILED | /* 0x00000004 */
4674 DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */
4675 DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */
4676 DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */
4677 DI_FLAGSEX_NO_DRVREG_MODIFY | /* 0x00008000 */
4678 DI_FLAGSEX_INSTALLEDDRIVER; /* 0x04000000 */
4679 BOOL ret = FALSE;
4680
4681 /* FIXME: add support for more flags */
4682
4683 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4684 * It should be checked before accessing to other values
4685 * of the SP_DEVINSTALL_PARAMS structure */
4686
4687 if (DeviceInstallParams->Flags & ~SupportedFlags)
4688 {
4689 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags);
4690 SetLastError(ERROR_INVALID_FLAGS);
4691 }
4692 else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx)
4693 {
4694 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx);
4695 SetLastError(ERROR_INVALID_FLAGS);
4696 }
4697 else if ((DeviceInstallParams->Flags & DI_NOVCP)
4698 && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE))
4699 SetLastError(ERROR_INVALID_USER_BUFFER);
4700 else
4701 {
4702 /* FIXME: check Reserved field */
4703 ret = TRUE;
4704 }
4705
4706 return ret;
4707 }
4708
4709 /***********************************************************************
4710 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4711 */
4712 BOOL WINAPI
4713 SetupDiSetDeviceInstallParamsW(
4714 IN HDEVINFO DeviceInfoSet,
4715 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4716 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4717 {
4718 struct DeviceInfoSet *list;
4719 BOOL ret = FALSE;
4720
4721 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4722
4723 if (!DeviceInfoSet)
4724 SetLastError(ERROR_INVALID_HANDLE);
4725 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4726 SetLastError(ERROR_INVALID_HANDLE);
4727 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4728 SetLastError(ERROR_INVALID_USER_BUFFER);
4729 else if (!DeviceInstallParams)
4730 SetLastError(ERROR_INVALID_PARAMETER);
4731 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
4732 SetLastError(ERROR_INVALID_USER_BUFFER);
4733 else if (CheckDeviceInstallParameters(DeviceInstallParams))
4734 {
4735 PSP_DEVINSTALL_PARAMS_W Destination;
4736
4737 if (DeviceInfoData)
4738 Destination = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
4739 else
4740 Destination = &list->InstallParams;
4741 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
4742 ret = TRUE;
4743 }
4744
4745 TRACE("Returning %d\n", ret);
4746 return ret;
4747 }
4748
4749 /***********************************************************************
4750 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4751 */
4752 BOOL WINAPI
4753 SetupDiSetDeviceInstallParamsA(
4754 HDEVINFO DeviceInfoSet,
4755 PSP_DEVINFO_DATA DeviceInfoData,
4756 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
4757 {
4758 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
4759 int len = 0;
4760 BOOL ret = FALSE;
4761
4762 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4763
4764 if (DeviceInstallParams == NULL)
4765 SetLastError(ERROR_INVALID_PARAMETER);
4766 else if (DeviceInstallParams->cbSize < sizeof(SP_DEVINSTALL_PARAMS_A))
4767 SetLastError(ERROR_INVALID_USER_BUFFER);
4768 else
4769 {
4770 memcpy(&deviceInstallParamsW, DeviceInstallParams, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A, DriverPath));
4771 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4772 len = MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, NULL, 0);
4773 if (!len)
4774 {
4775 ERR("DrivePath is NULL\n");
4776 ret = FALSE;
4777 }
4778 else
4779 {
4780 MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, deviceInstallParamsW.DriverPath, len);
4781 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
4782 }
4783 }
4784
4785 TRACE("Returning %d\n", ret);
4786 return ret;
4787 }
4788
4789 static HKEY
4790 OpenHardwareProfileKey(
4791 IN HKEY HKLM,
4792 IN DWORD HwProfile,
4793 IN DWORD samDesired)
4794 {
4795 HKEY hHWProfilesKey = NULL;
4796 HKEY hHWProfileKey = NULL;
4797 HKEY ret = INVALID_HANDLE_VALUE;
4798 LONG rc;
4799
4800 rc = RegOpenKeyExW(HKLM,
4801 REGSTR_PATH_HWPROFILES,
4802 0,
4803 READ_CONTROL,
4804 &hHWProfilesKey);
4805 if (rc != ERROR_SUCCESS)
4806 {
4807 SetLastError(rc);
4808 goto cleanup;
4809 }
4810 if (HwProfile == 0)
4811 {
4812 rc = RegOpenKeyExW(hHWProfilesKey,
4813 REGSTR_KEY_CURRENT,
4814 0,
4815 KEY_CREATE_SUB_KEY,
4816 &hHWProfileKey);
4817 }
4818 else
4819 {
4820 WCHAR subKey[5];
4821 snprintfW(subKey, 4, InstanceKeyFormat, HwProfile);
4822 subKey[4] = '\0';
4823 rc = RegOpenKeyExW(hHWProfilesKey,
4824 subKey,
4825 0,
4826 KEY_CREATE_SUB_KEY,
4827 &hHWProfileKey);
4828 }
4829 if (rc != ERROR_SUCCESS)
4830 {
4831 SetLastError(rc);
4832 goto cleanup;
4833 }
4834 ret = hHWProfileKey;
4835
4836 cleanup:
4837 if (hHWProfilesKey != NULL)
4838 RegCloseKey(hHWProfilesKey);
4839 if (hHWProfileKey != NULL && hHWProfileKey != ret)
4840 RegCloseKey(hHWProfileKey);
4841 return ret;
4842 }
4843
4844 static BOOL
4845 IsDeviceInfoInDeviceInfoSet(
4846 struct DeviceInfoSet *deviceInfoSet,
4847 struct DeviceInfo *deviceInfo)
4848 {
4849 PLIST_ENTRY ListEntry;
4850
4851 ListEntry = deviceInfoSet->ListHead.Flink;
4852 while (ListEntry != &deviceInfoSet->ListHead)
4853 {
4854 if (deviceInfo == CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry))
4855 return TRUE;
4856
4857 ListEntry = ListEntry->Flink;
4858 }
4859
4860 return FALSE;
4861 }
4862
4863 /***********************************************************************
4864 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4865 */
4866 BOOL WINAPI
4867 SetupDiDeleteDeviceInfo(
4868 IN HDEVINFO DeviceInfoSet,
4869 IN PSP_DEVINFO_DATA DeviceInfoData)
4870 {
4871 struct DeviceInfoSet *deviceInfoSet;
4872 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData;
4873 BOOL ret = FALSE;
4874
4875 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4876
4877 if (!DeviceInfoSet)
4878 SetLastError(ERROR_INVALID_HANDLE);
4879 else if ((deviceInfoSet = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4880 SetLastError(ERROR_INVALID_HANDLE);
4881 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4882 SetLastError(ERROR_INVALID_USER_BUFFER);
4883 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet, deviceInfo))
4884 SetLastError(ERROR_INVALID_PARAMETER);
4885 else
4886 {
4887 RemoveEntryList(&deviceInfo->ListEntry);
4888 DestroyDeviceInfo(deviceInfo);
4889 ret = TRUE;
4890 }
4891
4892 return ret;
4893 }
4894
4895
4896 /***********************************************************************
4897 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4898 */
4899 BOOL WINAPI
4900 SetupDiOpenDeviceInfoA(
4901 IN HDEVINFO DeviceInfoSet,
4902 IN PCSTR DeviceInstanceId,
4903 IN HWND hwndParent OPTIONAL,
4904 IN DWORD OpenFlags,
4905 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4906 {
4907 LPWSTR DeviceInstanceIdW = NULL;
4908 BOOL bResult;
4909
4910 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
4911
4912 DeviceInstanceIdW = pSetupMultiByteToUnicode(DeviceInstanceId, CP_ACP);
4913 if (DeviceInstanceIdW == NULL)
4914 return FALSE;
4915
4916 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
4917 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
4918
4919 MyFree(DeviceInstanceIdW);
4920
4921 return bResult;
4922 }
4923
4924
4925 /***********************************************************************
4926 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4927 */
4928 BOOL WINAPI
4929 SetupDiOpenDeviceInfoW(
4930 IN HDEVINFO DeviceInfoSet,
4931 IN PCWSTR DeviceInstanceId,
4932 IN HWND hwndParent OPTIONAL,
4933 IN DWORD OpenFlags,
4934 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4935 {
4936 struct DeviceInfoSet *list;
4937 HKEY hEnumKey, hKey = NULL;
4938 DWORD rc, dwSize;
4939 BOOL ret = FALSE;
4940
4941 TRACE("%p %s %p %lx %p\n",
4942 DeviceInfoSet, debugstr_w(DeviceInstanceId),
4943 hwndParent, OpenFlags, DeviceInfoData);
4944
4945 if (OpenFlags & DIOD_CANCEL_REMOVE)
4946 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4947
4948 if (!DeviceInfoSet)
4949 SetLastError(ERROR_INVALID_HANDLE);
4950 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4951 SetLastError(ERROR_INVALID_HANDLE);
4952 else if (!DeviceInstanceId)
4953 SetLastError(ERROR_INVALID_PARAMETER);
4954 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
4955 {
4956 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
4957 SetLastError(ERROR_INVALID_FLAGS);
4958 }
4959 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4960 SetLastError(ERROR_INVALID_USER_BUFFER);
4961 else
4962 {
4963 struct DeviceInfo *deviceInfo = NULL;
4964 /* Search if device already exists in DeviceInfoSet.
4965 * If yes, return the existing element
4966 * If no, create a new element using information in registry
4967 */
4968 PLIST_ENTRY ItemList = list->ListHead.Flink;
4969 while (ItemList != &list->ListHead)
4970 {
4971 deviceInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
4972 if (!wcscmp(deviceInfo->instanceId, DeviceInstanceId))
4973 break;
4974 deviceInfo = NULL;
4975 ItemList = ItemList->Flink;
4976 }
4977
4978 if (deviceInfo)
4979 {
4980 /* good one found */
4981 ret = TRUE;
4982 }
4983 else
4984 {
4985 GUID ClassGUID;
4986 WCHAR szClassGuid[MAX_GUID_STRING_LEN];
4987
4988 /* Open supposed registry key */
4989 rc = RegOpenKeyExW(
4990 list->HKLM,
4991 REGSTR_PATH_SYSTEMENUM,
4992 0, /* Options */
4993 READ_CONTROL,
4994 &hEnumKey);
4995 if (rc != ERROR_SUCCESS)
4996 {
4997 SetLastError(rc);
4998 goto cleanup;
4999 }
5000 rc = RegOpenKeyExW(
5001 hEnumKey,
5002 DeviceInstanceId,
5003 0, /* Options */
5004 KEY_QUERY_VALUE,
5005 &hKey);
5006 RegCloseKey(hEnumKey);
5007 if (rc != ERROR_SUCCESS)
5008 {
5009 if (rc == ERROR_FILE_NOT_FOUND)
5010 rc = ERROR_NO_SUCH_DEVINST;
5011 SetLastError(rc);
5012 goto cleanup;
5013 }
5014
5015 ClassGUID = GUID_NULL;
5016 dwSize = MAX_GUID_STRING_LEN * sizeof(WCHAR);
5017
5018 if (RegQueryValueExW(hKey,
5019 REGSTR_VAL_CLASSGUID,
5020 NULL,
5021 NULL,
5022 (LPBYTE)szClassGuid,
5023 &dwSize) == ERROR_SUCCESS)
5024 {
5025 szClassGuid[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL;
5026
5027 /* Convert a string to a ClassGuid */
5028 UuidFromStringW(&szClassGuid[1], &ClassGUID);
5029 }
5030
5031 if (!CreateDeviceInfo(list, DeviceInstanceId, &ClassGUID, &deviceInfo))
5032 goto cleanup;
5033
5034 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
5035
5036 ret = TRUE;
5037 }
5038
5039 if (ret && deviceInfo && DeviceInfoData)
5040 {
5041 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
5042 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
5043 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
5044 }
5045 }
5046
5047 cleanup:
5048 if (hKey != NULL)
5049 RegCloseKey(hKey);
5050 return ret;
5051 }
5052
5053
5054 /***********************************************************************
5055 * SetupDiGetSelectedDevice (SETUPAPI.@)
5056 */
5057 BOOL WINAPI
5058 SetupDiGetSelectedDevice(
5059 IN HDEVINFO DeviceInfoSet,
5060 OUT PSP_DEVINFO_DATA DeviceInfoData)
5061 {
5062 struct DeviceInfoSet *list;
5063 BOOL ret = FALSE;
5064
5065 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5066
5067 if (!DeviceInfoSet)
5068 SetLastError(ERROR_INVALID_HANDLE);
5069 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5070 SetLastError(ERROR_INVALID_HANDLE);
5071 else if (list->SelectedDevice == NULL)
5072 SetLastError(ERROR_NO_DEVICE_SELECTED);
5073 else if (!DeviceInfoData)
5074 SetLastError(ERROR_INVALID_PARAMETER);
5075 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5076 SetLastError(ERROR_INVALID_USER_BUFFER);
5077 else
5078 {
5079 memcpy(&DeviceInfoData->ClassGuid,
5080 &list->SelectedDevice->ClassGuid,
5081 sizeof(GUID));
5082 DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst;
5083 DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice;
5084 ret = TRUE;
5085 }
5086
5087 TRACE("Returning %d\n", ret);
5088 return ret;
5089 }
5090
5091
5092 /***********************************************************************
5093 * SetupDiSetSelectedDevice (SETUPAPI.@)
5094 */
5095 BOOL WINAPI
5096 SetupDiSetSelectedDevice(
5097 IN HDEVINFO DeviceInfoSet,
5098 IN PSP_DEVINFO_DATA DeviceInfoData)
5099 {
5100 struct DeviceInfoSet *list;
5101 BOOL ret = FALSE;
5102
5103 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5104
5105 if (!DeviceInfoSet)
5106 SetLastError(ERROR_INVALID_HANDLE);
5107 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5108 SetLastError(ERROR_INVALID_HANDLE);
5109 else if (!DeviceInfoData)
5110 SetLastError(ERROR_INVALID_PARAMETER);
5111 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5112 SetLastError(ERROR_INVALID_USER_BUFFER);
5113 else if (DeviceInfoData->Reserved == 0)
5114 SetLastError(ERROR_INVALID_USER_BUFFER);
5115 else
5116 {
5117 list->SelectedDevice = (struct DeviceInfo *)DeviceInfoData->Reserved;
5118 ret = TRUE;
5119 }
5120
5121 TRACE("Returning %d\n", ret);
5122 return ret;
5123 }
5124
5125
5126 /* Return the current hardware profile id, or -1 if error */
5127 static DWORD
5128 SETUPAPI_GetCurrentHwProfile(
5129 IN HDEVINFO DeviceInfoSet)
5130 {
5131 HKEY hKey = NULL;
5132 DWORD dwRegType, dwLength;
5133 DWORD hwProfile;
5134 LONG rc;
5135 DWORD ret = (DWORD)-1;
5136
5137 rc = RegOpenKeyExW(((struct DeviceInfoSet *)DeviceInfoSet)->HKLM,
5138 REGSTR_PATH_IDCONFIGDB,
5139 0, /* Options */
5140 KEY_QUERY_VALUE,
5141 &hKey);
5142 if (rc != ERROR_SUCCESS)
5143 {
5144 SetLastError(rc);
5145 goto cleanup;
5146 }
5147
5148 dwLength = sizeof(DWORD);
5149 rc = RegQueryValueExW(hKey,
5150 REGSTR_VAL_CURRENTCONFIG,
5151 NULL,
5152 &dwRegType,
5153 (LPBYTE)&hwProfile, &dwLength);
5154 if (rc != ERROR_SUCCESS)
5155 {
5156 SetLastError(rc);
5157 goto cleanup;
5158 }
5159 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
5160 {
5161 SetLastError(ERROR_GEN_FAILURE);
5162 goto cleanup;
5163 }
5164
5165 ret = hwProfile;
5166
5167 cleanup:
5168 if (hKey != NULL)
5169 RegCloseKey(hKey);
5170
5171 return ret;
5172 }
5173
5174 static BOOL
5175 ResetDevice(
5176 IN HDEVINFO DeviceInfoSet,
5177 IN PSP_DEVINFO_DATA DeviceInfoData)
5178 {
5179 #ifndef __WINESRC__
5180 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
5181 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
5182 CONFIGRET cr;
5183
5184 cr = CM_Enable_DevNode_Ex(deviceInfo->dnDevInst, 0, set->hMachine);
5185 if (cr != CR_SUCCESS)
5186 {
5187 SetLastError(GetErrorCodeFromCrCode(cr));
5188 return FALSE;
5189 }
5190
5191 return TRUE;
5192 #else
5193 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
5194 return TRUE;
5195 #endif
5196 }
5197
5198 static BOOL StopDevice(
5199 IN HDEVINFO DeviceInfoSet,
5200 IN PSP_DEVINFO_DATA DeviceInfoData)
5201 {
5202 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
5203 return TRUE;
5204 }
5205
5206 /***********************************************************************
5207 * SetupDiChangeState (SETUPAPI.@)
5208 */
5209 BOOL WINAPI
5210 SetupDiChangeState(
5211 IN HDEVINFO DeviceInfoSet,
5212 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
5213 {
5214 PSP_PROPCHANGE_PARAMS PropChange;
5215 HKEY hKey = INVALID_HANDLE_VALUE;
5216 LPCWSTR RegistryValueName;
5217 DWORD dwConfigFlags, dwLength, dwRegType;
5218 LONG rc;
5219 BOOL ret = FALSE;
5220
5221 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5222
5223 if (!DeviceInfoData)
5224 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChangeParams;
5225 else
5226 PropChange = ((struct DeviceInfo *)DeviceInfoData->Reserved)->ClassInstallParams.PropChangeParams;
5227 if (!PropChange)
5228 {
5229 SetLastError(ERROR_INVALID_PARAMETER);
5230 goto cleanup;
5231 }
5232
5233 if (PropChange->Scope == DICS_FLAG_GLOBAL)
5234 RegistryValueName = REGSTR_VAL_CONFIGFLAGS;
5235 else
5236 RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS;
5237
5238 switch (PropChange->StateChange)
5239 {
5240 case DICS_ENABLE:
5241 case DICS_DISABLE:
5242 {
5243 /* Enable/disable device in registry */
5244 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE);
5245 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5246 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL);
5247 if (hKey == INVALID_HANDLE_VALUE)
5248 break;
5249 dwLength = sizeof(DWORD);
5250 rc = RegQueryValueExW(
5251 hKey,
5252 RegistryValueName,
5253 NULL,
5254 &dwRegType,
5255 (LPBYTE)&dwConfigFlags, &dwLength);
5256 if (rc == ERROR_FILE_NOT_FOUND)
5257 dwConfigFlags = 0;
5258 else if (rc != ERROR_SUCCESS)
5259 {
5260 SetLastError(rc);
5261 goto cleanup;
5262 }
5263 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
5264 {
5265 SetLastError(ERROR_GEN_FAILURE);
5266 goto cleanup;
5267 }
5268 if (PropChange->StateChange == DICS_ENABLE)
5269 dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
5270 else
5271 dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
5272 rc = RegSetValueExW(
5273 hKey,
5274 RegistryValueName,
5275 0,
5276 REG_DWORD,
5277 (LPBYTE)&dwConfigFlags, sizeof(DWORD));
5278 if (rc != ERROR_SUCCESS)
5279 {
5280 SetLastError(rc);
5281 goto cleanup;
5282 }
5283
5284 /* Enable/disable device if needed */
5285 if (PropChange->Scope == DICS_FLAG_GLOBAL
5286 || PropChange->HwProfile == 0
5287 || PropChange->HwProfile == SETUPAPI_GetCurrentHwProfile(DeviceInfoSet))
5288 {
5289 if (PropChange->StateChange == DICS_ENABLE)
5290 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
5291 else
5292 ret = StopDevice(DeviceInfoSet, DeviceInfoData);
5293 }
5294 else
5295 ret = TRUE;
5296 break;
5297 }
5298 case DICS_PROPCHANGE:
5299 {
5300 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
5301 break;
5302 }
5303 default:
5304 {
5305 ERR("Unknown StateChange 0x%lx\n", PropChange->StateChange);
5306 SetLastError(ERROR_NOT_SUPPORTED);
5307 }
5308 }
5309
5310 cleanup:
5311 if (hKey != INVALID_HANDLE_VALUE)
5312 RegCloseKey(hKey);
5313
5314 TRACE("Returning %d\n", ret);
5315 return ret;
5316 }
5317
5318 /***********************************************************************
5319 * SetupDiSelectDevice (SETUPAPI.@)
5320 */
5321 BOOL WINAPI
5322 SetupDiSelectDevice(
5323 IN HDEVINFO DeviceInfoSet,
5324 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
5325 {
5326 FIXME("%p %p\n", DeviceInfoSet, DeviceInfoData);
5327 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
5328 return FALSE;
5329 }
5330
5331
5332 /***********************************************************************
5333 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5334 */
5335 BOOL WINAPI
5336 SetupDiRegisterCoDeviceInstallers(
5337 IN HDEVINFO DeviceInfoSet,
5338 IN PSP_DEVINFO_DATA DeviceInfoData)
5339 {
5340 BOOL ret = FALSE; /* Return value */
5341
5342 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5343
5344 if (!DeviceInfoSet)
5345 SetLastError(ERROR_INVALID_PARAMETER);
5346 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5347 SetLastError(ERROR_INVALID_HANDLE);
5348 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5349 SetLastError(ERROR_INVALID_HANDLE);
5350 else if (!DeviceInfoData)
5351 SetLastError(ERROR_INVALID_PARAMETER);
5352 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5353 SetLastError(ERROR_INVALID_USER_BUFFER);
5354 else
5355 {
5356 SP_DEVINSTALL_PARAMS_W InstallParams;
5357 struct DriverInfoElement *SelectedDriver;
5358 BOOL Result;
5359 DWORD DoAction;
5360 WCHAR SectionName[MAX_PATH];
5361 DWORD SectionNameLength = 0;
5362 HKEY hKey = INVALID_HANDLE_VALUE;
5363 PVOID Context = NULL;
5364
5365 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5366 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5367 if (!Result)
5368 goto cleanup;
5369
5370 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5371 if (SelectedDriver == NULL)
5372 {
5373 SetLastError(ERROR_NO_DRIVER_SELECTED);
5374 goto cleanup;
5375 }
5376
5377 /* Get .CoInstallers section name */
5378 Result = SetupDiGetActualSectionToInstallW(
5379 SelectedDriver->InfFileDetails->hInf,
5380 SelectedDriver->Details.SectionName,
5381 SectionName, MAX_PATH, &SectionNameLength, NULL);
5382 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotCoInstallers) - 1)
5383 goto cleanup;
5384 lstrcatW(SectionName, DotCoInstallers);
5385
5386 /* Open/Create driver key information */
5387 #if _WIN32_WINNT >= 0x502
5388 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
5389 #else
5390 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
5391 #endif
5392 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5393 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
5394 if (hKey == INVALID_HANDLE_VALUE)
5395 goto cleanup;
5396
5397 /* Install .CoInstallers section */
5398 DoAction = SPINST_REGISTRY;
5399 if (!(InstallParams.Flags & DI_NOFILECOPY))
5400 {
5401 DoAction |= SPINST_FILES;
5402 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5403 if (!Context)
5404 goto cleanup;
5405 }
5406 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5407 SelectedDriver->InfFileDetails->hInf, SectionName,
5408 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
5409 SetupDefaultQueueCallbackW, Context,
5410 DeviceInfoSet, DeviceInfoData);
5411 if (!Result)
5412 goto cleanup;
5413
5414 ret = TRUE;
5415
5416 cleanup:
5417 if (Context)
5418 SetupTermDefaultQueueCallback(Context);
5419 if (hKey != INVALID_HANDLE_VALUE)
5420 RegCloseKey(hKey);
5421 }
5422
5423 TRACE("Returning %d\n", ret);
5424 return ret;
5425 }
5426
5427 static BOOL
5428 InfIsFromOEMLocation(
5429 IN PCWSTR FullName,
5430 OUT LPBOOL IsOEMLocation)
5431 {
5432 PWCHAR last;
5433
5434 last = strrchrW(FullName, '\\');
5435 if (!last)
5436 {
5437 /* No directory specified */
5438 *IsOEMLocation = FALSE;
5439 }
5440 else
5441 {
5442 LPWSTR Windir;
5443 UINT ret;
5444
5445 Windir = MyMalloc((MAX_PATH + 1 + strlenW(InfDirectory)) * sizeof(WCHAR));
5446 if (!Windir)
5447 {
5448 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5449 return FALSE;
5450 }
5451
5452 ret = GetSystemWindowsDirectoryW(Windir, MAX_PATH);
5453 if (ret == 0 || ret > MAX_PATH)
5454 {
5455 MyFree(Windir);
5456 SetLastError(ERROR_GEN_FAILURE);
5457 return FALSE;
5458 }
5459 if (*Windir && Windir[strlenW(Windir) - 1] != '\\')
5460 strcatW(Windir, BackSlash);
5461 strcatW(Windir, InfDirectory);
5462
5463 if (strncmpiW(FullName, Windir, last - FullName) == 0)
5464 {
5465 /* The path is %SYSTEMROOT%\Inf */
5466 *IsOEMLocation = FALSE;
5467 }
5468 else
5469 {
5470 /* The file is in another place */
5471 *IsOEMLocation = TRUE;
5472 }
5473 MyFree(Windir);
5474 }
5475 return TRUE;
5476 }
5477
5478 /***********************************************************************
5479 * SetupDiInstallDevice (SETUPAPI.@)
5480 */
5481 BOOL WINAPI
5482 SetupDiInstallDevice(
5483 IN HDEVINFO DeviceInfoSet,
5484 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
5485 {
5486 SP_DEVINSTALL_PARAMS_W InstallParams;
5487 struct DriverInfoElement *SelectedDriver;
5488 SYSTEMTIME DriverDate;
5489 WCHAR SectionName[MAX_PATH];
5490 WCHAR Buffer[32];
5491 DWORD SectionNameLength = 0;
5492 BOOL Result = FALSE;
5493 ULONG DoAction;
5494 DWORD RequiredSize;
5495 LPWSTR pSectionName = NULL;
5496 WCHAR ClassName[MAX_CLASS_NAME_LEN];
5497 GUID ClassGuid;
5498 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
5499 BOOL RebootRequired = FALSE;
5500 HKEY hKey = INVALID_HANDLE_VALUE;
5501 BOOL NeedtoCopyFile;
5502 LARGE_INTEGER fullVersion;
5503 LONG rc;
5504 PVOID Context = NULL;
5505 BOOL ret = FALSE; /* Return value */
5506
5507 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
5508
5509 if (!DeviceInfoSet)
5510 SetLastError(ERROR_INVALID_PARAMETER);
5511 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
5512 SetLastError(ERROR_INVALID_HANDLE);
5513 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5514 SetLastError(ERROR_INVALID_HANDLE);
5515 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
5516 SetLastError(ERROR_INVALID_USER_BUFFER);
5517 else
5518 Result = TRUE;
5519
5520 if (!Result)
5521 {
5522 /* One parameter is bad */
5523 goto cleanup;
5524 }
5525
5526 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
5527 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5528 if (!Result)
5529 goto cleanup;
5530
5531 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
5532 {
5533 /* Set FAILEDINSTALL in ConfigFlags registry value */
5534 DWORD ConfigFlags, regType;
5535 Result = SetupDiGetDeviceRegistryPropertyW(
5536 DeviceInfoSet,
5537 DeviceInfoData,
5538 SPDRP_CONFIGFLAGS,
5539 &regType,
5540 (PBYTE)&ConfigFlags,
5541 sizeof(ConfigFlags),
5542 NULL);
5543 if (!Result || regType != REG_DWORD)
5544 {
5545 SetLastError(ERROR_GEN_FAILURE);
5546 goto cleanup;
5547 }
5548 ConfigFlags |= DNF_DISABLED;
5549 Result = SetupDiSetDeviceRegistryPropertyW(
5550 DeviceInfoSet,
5551 DeviceInfoData,
5552 SPDRP_CONFIGFLAGS,
5553 (PBYTE)&ConfigFlags,
5554 sizeof(ConfigFlags));
5555 if (!Result)
5556 {
5557 SetLastError(ERROR_GEN_FAILURE);
5558 goto cleanup;
5559 }
5560
5561 ret = TRUE;
5562 goto cleanup;
5563 }
5564
5565 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5566 if (SelectedDriver == NULL)
5567 {
5568 SetLastError(ERROR_NO_DRIVER_SELECTED);
5569 goto cleanup;
5570 }
5571
5572 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
5573
5574 Result = SetupDiGetActualSectionToInstallW(
5575 SelectedDriver->InfFileDetails->hInf,
5576 SelectedDriver->Details.SectionName,
5577 SectionName, MAX_PATH, &SectionNameLength, NULL);
5578 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotServices))
5579 goto cleanup;
5580 pSectionName = &SectionName[strlenW(SectionName)];
5581
5582 /* Get information from [Version] section */
5583 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
5584 goto cleanup;
5585 /* Format ClassGuid to a string */
5586 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
5587 goto cleanup;
5588 RequiredSize = lstrlenW(lpGuidString);
5589 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
5590 if (!lpFullGuidString)
5591 {
5592 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5593 goto cleanup;
5594 }
5595 lpFullGuidString[0] = '{';
5596 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
5597 lpFullGuidString[RequiredSize + 1] = '}';
5598 lpFullGuidString[RequiredSize + 2] = '\0';
5599
5600 /* Copy .inf file to Inf\ directory (if needed) */
5601 Result = InfIsFromOEMLocation(SelectedDriver->Details.InfFileName, &NeedtoCopyFile);
5602 if (!Result)
5603 goto cleanup;
5604 if (NeedtoCopyFile)
5605 {
5606 WCHAR NewFileName[MAX_PATH];
5607 struct InfFileDetails *newInfFileDetails;
5608 Result = SetupCopyOEMInfW(
5609 SelectedDriver->Details.InfFileName,
5610 NULL,
5611 SPOST_NONE,
5612 SP_COPY_NOOVERWRITE,
5613 NewFileName, MAX_PATH,
5614 NULL,
5615 NULL);
5616 if (!Result && GetLastError() != ERROR_FILE_EXISTS)
5617 goto cleanup;
5618 /* Create a new struct InfFileDetails, and set it to
5619 * SelectedDriver->InfFileDetails, to release use of
5620 * current InfFile */
5621 newInfFileDetails = CreateInfFileDetails(NewFileName);
5622 if (!newInfFileDetails)
5623 goto cleanup;
5624 DereferenceInfFile(SelectedDriver->InfFileDetails);
5625 SelectedDriver->InfFileDetails = newInfFileDetails;
5626 strcpyW(SelectedDriver->Details.InfFileName, NewFileName);
5627 }
5628
5629 /* Open/Create driver key information */
5630 #if _WIN32_WINNT >= 0x502
5631 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
5632 #else
5633 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
5634 #endif
5635 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5636 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
5637 if (hKey == INVALID_HANDLE_VALUE)
5638 goto cleanup;
5639
5640 /* Install main section */
5641 DoAction = 0;
5642 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
5643 DoAction |= SPINST_REGISTRY;
5644 if (!(InstallParams.Flags & DI_NOFILECOPY))
5645 {
5646 DoAction |= SPINST_FILES;
5647 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5648 if (!Context)
5649 goto cleanup;
5650 }
5651 *pSectionName = '\0';
5652 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5653 SelectedDriver->InfFileDetails->hInf, SectionName,
5654 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
5655 SetupDefaultQueueCallbackW, Context,
5656 DeviceInfoSet, DeviceInfoData);
5657 if (!Result)
5658 goto cleanup;
5659 InstallParams.Flags |= DI_NOFILECOPY;
5660 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5661
5662 /* Write information to driver key */
5663 *pSectionName = UNICODE_NULL;
5664 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
5665 TRACE("Write information to driver key\n");
5666 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
5667 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
5668 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
5669 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver->InfFileDetails->FileName));
5670 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName));
5671 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)]));
5672 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId));
5673 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver->Info.ProviderName));
5674 sprintfW(Buffer, DateFormat, DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
5675 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
5676 if (rc == ERROR_SUCCESS)
5677 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
5678 if (rc == ERROR_SUCCESS)
5679 rc = RegSetValueExW(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
5680 if (rc == ERROR_SUCCESS)
5681 {
5682 sprintfW(Buffer, VersionFormat, fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
5683 rc = RegSetValueExW(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
5684 }
5685 if (rc == ERROR_SUCCESS)
5686 rc = RegSetValueExW(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->InfFileDetails->FileName, (strlenW(SelectedDriver->InfFileDetails->FileName) + 1) * sizeof(WCHAR));
5687 if (rc == ERROR_SUCCESS)
5688 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
5689 if (rc == ERROR_SUCCESS)
5690 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTIONEXT, 0, REG_SZ, (const BYTE *)&SectionName[strlenW(SelectedDriver->Details.SectionName)], (strlenW(SectionName) - strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
5691 if (rc == ERROR_SUCCESS)
5692 rc = RegSetValueExW(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
5693 if (rc == ERROR_SUCCESS)
5694 rc = RegSetValueExW(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (strlenW(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
5695 if (rc != ERROR_SUCCESS)
5696 {
5697 SetLastError(rc);
5698 goto cleanup;
5699 }
5700 RegCloseKey(hKey);
5701 hKey = INVALID_HANDLE_VALUE;
5702
5703 /* FIXME: Process .LogConfigOverride section */
5704
5705 /* Install .Services section */
5706 strcpyW(pSectionName, DotServices);
5707 Result = SetupInstallServicesFromInfSectionExW(
5708 SelectedDriver->InfFileDetails->hInf,
5709 SectionName,
5710 0,
5711 DeviceInfoSet,
5712 DeviceInfoData,
5713 NULL,
5714 NULL);
5715 if (!Result)
5716 goto cleanup;
5717 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
5718 RebootRequired = TRUE;
5719
5720 /* Open device registry key */
5721 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
5722 if (hKey == INVALID_HANDLE_VALUE)
5723 goto cleanup;
5724
5725 /* Install .HW section */
5726 DoAction = 0;
5727 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
5728 DoAction |= SPINST_REGISTRY;
5729 strcpyW(pSectionName, DotHW);
5730 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5731 SelectedDriver->InfFileDetails->hInf, SectionName,
5732 DoAction, hKey, NULL, 0,
5733 NULL, NULL,
5734 DeviceInfoSet, DeviceInfoData);
5735 if (!Result)
5736 goto cleanup;
5737
5738 /* Write information to enum key */
5739 TRACE("Write information to enum key\n");
5740 TRACE("Class : '%s'\n", debugstr_w(ClassName));
5741 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString));
5742 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
5743 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver->Info.MfgName));
5744 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR));
5745 if (rc == ERROR_SUCCESS)
5746 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR));
5747 if (rc == ERROR_SUCCESS)
5748 rc = RegSetValueExW(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
5749 if (rc == ERROR_SUCCESS)
5750 rc = RegSetValueExW(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (strlenW(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
5751 if (rc != ERROR_SUCCESS)
5752 {
5753 SetLastError(rc);
5754 goto cleanup;
5755 }
5756
5757 /* Start the device */
5758 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
5759 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
5760 else
5761 ret = TRUE;
5762
5763 cleanup:
5764 /* End of installation */
5765 if (hKey != INVALID_HANDLE_VALUE)
5766 RegCloseKey(hKey);
5767 if (lpGuidString)
5768 RpcStringFreeW(&lpGuidString);
5769 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
5770 if (Context)
5771 SetupTermDefaultQueueCallback(Context);
5772 TRACE("Returning %d\n", ret);
5773 return ret;
5774 }
5775
5776 static HKEY SETUPDI_OpenDevKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired)
5777 {
5778 HKEY enumKey, key = INVALID_HANDLE_VALUE;
5779 LONG l;
5780
5781 l = RegOpenKeyExW(RootKey, REGSTR_PATH_SYSTEMENUM, 0, READ_CONTROL, &enumKey);
5782 if (!l)
5783 {
5784 l = RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key);
5785 RegCloseKey(enumKey);
5786 }
5787 if (l)
5788 SetLastError(l);
5789 return key;
5790 }
5791
5792 static HKEY SETUPDI_OpenDrvKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired)
5793 {
5794 LPWSTR DriverKey = NULL;
5795 DWORD dwLength = 0;
5796 DWORD dwRegType;
5797 DWORD rc;
5798 HKEY hEnumKey = NULL;
5799 HKEY hKey = NULL;
5800 HKEY key = INVALID_HANDLE_VALUE;
5801
5802 hKey = SETUPDI_OpenDevKey(RootKey, devInfo, KEY_QUERY_VALUE);
5803 if (hKey == INVALID_HANDLE_VALUE)
5804 goto cleanup;
5805 /* Read the 'Driver' key */
5806 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength);
5807 if (rc != ERROR_SUCCESS)
5808 {
5809 SetLastError(rc);
5810 goto cleanup;
5811 }
5812 else if (dwRegType != REG_SZ)
5813 {
5814 SetLastError(ERROR_GEN_FAILURE);
5815 goto cleanup;
5816 }
5817 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
5818 if (!DriverKey)
5819 {
5820 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5821 goto cleanup;
5822 }
5823 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
5824 if (rc != ERROR_SUCCESS)
5825 {
5826 SetLastError(rc);
5827 goto cleanup;
5828 }
5829 RegCloseKey(hKey);
5830 hKey = NULL;
5831 /* Need to open the driver key */
5832 rc = RegOpenKeyExW(
5833 RootKey,
5834 REGSTR_PATH_CLASS_NT,
5835 0, /* Options */
5836 READ_CONTROL,
5837 &hEnumKey);
5838 if (rc != ERROR_SUCCESS)
5839 {
5840 SetLastError(rc);
5841 goto cleanup;
5842 }
5843 rc = RegOpenKeyExW(
5844 hEnumKey,
5845 DriverKey,
5846 0, /* Options */
5847 samDesired,
5848 &hKey);
5849 if (rc != ERROR_SUCCESS)
5850 {
5851 SetLastError(rc);
5852 goto cleanup;
5853 }
5854 key = hKey;
5855
5856 cleanup:
5857 if (hEnumKey != NULL)
5858 RegCloseKey(hEnumKey);
5859 if (hKey != NULL && hKey != key)
5860 RegCloseKey(hKey);
5861 if (DriverKey)
5862 HeapFree(GetProcessHeap(), 0, DriverKey);
5863 return key;
5864 }
5865
5866 /***********************************************************************
5867 * SetupDiOpenDevRegKey (SETUPAPI.@)
5868 */
5869 HKEY WINAPI SetupDiOpenDevRegKey(
5870 HDEVINFO DeviceInfoSet,
5871 PSP_DEVINFO_DATA DeviceInfoData,
5872 DWORD Scope,
5873 DWORD HwProfile,
5874 DWORD KeyType,
5875 REGSAM samDesired)
5876 {
5877 struct DeviceInfoSet *set = DeviceInfoSet;
5878 struct DeviceInfo *devInfo;
5879 HKEY key = INVALID_HANDLE_VALUE;
5880 HKEY RootKey;
5881
5882 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
5883 Scope, HwProfile, KeyType, samDesired);
5884
5885 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
5886 {
5887 SetLastError(ERROR_INVALID_HANDLE);
5888 return INVALID_HANDLE_VALUE;
5889 }
5890 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5891 {
5892 SetLastError(ERROR_INVALID_HANDLE);
5893 return INVALID_HANDLE_VALUE;
5894 }
5895 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
5896 || !DeviceInfoData->Reserved)
5897 {
5898 SetLastError(ERROR_INVALID_PARAMETER);
5899 return INVALID_HANDLE_VALUE;
5900 }
5901 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
5902 {
5903 SetLastError(ERROR_INVALID_FLAGS);
5904 return INVALID_HANDLE_VALUE;
5905 }
5906 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
5907 {
5908 SetLastError(ERROR_INVALID_FLAGS);
5909 return INVALID_HANDLE_VALUE;
5910 }
5911 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
5912 if (devInfo->set != set)
5913 {
5914 SetLastError(ERROR_INVALID_PARAMETER);
5915 return INVALID_HANDLE_VALUE;
5916 }
5917 if (Scope != DICS_FLAG_GLOBAL)
5918 {
5919 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0);
5920 if (RootKey == INVALID_HANDLE_VALUE)
5921 return INVALID_HANDLE_VALUE;
5922 }
5923 else
5924 RootKey = set->HKLM;
5925 switch (KeyType)
5926 {
5927 case DIREG_DEV:
5928 key = SETUPDI_OpenDevKey(RootKey, devInfo, samDesired);
5929 if (Scope == DICS_FLAG_GLOBAL)
5930 {
5931 LONG rc;
5932 HKEY hTempKey = key;
5933 rc = RegOpenKeyExW(hTempKey,
5934 L"Device Parameters",
5935 0,
5936 samDesired,
5937 &key);
5938 if (rc == ERROR_SUCCESS)
5939 RegCloseKey(hTempKey);
5940 }
5941 break;
5942 case DIREG_DRV:
5943 key = SETUPDI_OpenDrvKey(RootKey, devInfo, samDesired);
5944 break;
5945 default:
5946 WARN("unknown KeyType %d\n", KeyType);
5947 }
5948 if (RootKey != set->HKLM)
5949 RegCloseKey(RootKey);
5950 return key;
5951 }
5952
5953 static BOOL SETUPDI_DeleteDevKey(HKEY RootKey, struct DeviceInfo *devInfo)
5954 {
5955 FIXME("\n");
5956 return FALSE;
5957 }
5958
5959 static BOOL SETUPDI_DeleteDrvKey(HKEY RootKey, struct DeviceInfo *devInfo)
5960 {
5961 FIXME("\n");
5962 return FALSE;
5963 }
5964
5965 /***********************************************************************
5966 * SetupDiDeleteDevRegKey (SETUPAPI.@)
5967 */
5968 BOOL WINAPI SetupDiDeleteDevRegKey(
5969 HDEVINFO DeviceInfoSet,
5970 PSP_DEVINFO_DATA DeviceInfoData,
5971 DWORD Scope,
5972 DWORD HwProfile,
5973 DWORD KeyType)
5974 {
5975 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
5976 struct DeviceInfo *devInfo;
5977 BOOL ret = FALSE;
5978 HKEY RootKey;
5979
5980 TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile,
5981 KeyType);
5982
5983 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
5984 {
5985 SetLastError(ERROR_INVALID_HANDLE);
5986 return FALSE;
5987 }
5988 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5989 {
5990 SetLastError(ERROR_INVALID_HANDLE);
5991 return FALSE;
5992 }
5993 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
5994 || !DeviceInfoData->Reserved)
5995 {
5996 SetLastError(ERROR_INVALID_PARAMETER);
5997 return FALSE;
5998 }
5999 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
6000 {
6001 SetLastError(ERROR_INVALID_FLAGS);
6002 return FALSE;
6003 }
6004 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH)
6005 {
6006 SetLastError(ERROR_INVALID_FLAGS);
6007 return FALSE;
6008 }
6009 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
6010 if (devInfo->set != set)
6011 {
6012 SetLastError(ERROR_INVALID_PARAMETER);
6013 return FALSE;
6014 }
6015 if (Scope != DICS_FLAG_GLOBAL)
6016 {
6017 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0);
6018 if (RootKey == INVALID_HANDLE_VALUE)
6019 return FALSE;
6020 }
6021 else
6022 RootKey = set->HKLM;
6023 switch (KeyType)
6024 {
6025 case DIREG_DEV:
6026 ret = SETUPDI_DeleteDevKey(RootKey, devInfo);
6027 break;
6028 case DIREG_DRV:
6029 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo);
6030 break;
6031 case DIREG_BOTH:
6032 ret = SETUPDI_DeleteDevKey(RootKey, devInfo);
6033 if (ret)
6034 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo);
6035 break;
6036 default:
6037 WARN("unknown KeyType %d\n", KeyType);
6038 }
6039 if (RootKey != set->HKLM)
6040 RegCloseKey(RootKey);
6041 return ret;
6042 }