91356c3f5438d5fa6c254f3c3967417ef7f9e25a
[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