[SETUPAPI]
[reactos.git] / reactos / 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 WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
25
26 /* Unicode constants */
27 static const WCHAR BackSlash[] = {'\\',0};
28 static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class[] = {'C','l','a','s','s',0};
30 static const WCHAR DateFormat[] = {'%','u','-','%','u','-','%','u',0};
31 static const WCHAR DotCoInstallers[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
32 static const WCHAR DotHW[] = {'.','H','W',0};
33 static const WCHAR DotServices[] = {'.','S','e','r','v','i','c','e','s',0};
34 static const WCHAR InfDirectory[] = {'i','n','f','\\',0};
35 static const WCHAR InstanceKeyFormat[] = {'%','0','4','l','u',0};
36 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
37 static const WCHAR VersionFormat[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
38
39 static const WCHAR REGSTR_DRIVER_DATE[] = {'D','r','i','v','e','r','D','a','t','e',0};
40 static const WCHAR REGSTR_DRIVER_DATE_DATA[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
41 static const WCHAR REGSTR_DRIVER_VERSION[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
42 static const WCHAR REGSTR_SECURITY[] = {'S','e','c','u','r','i','t','y',0};
43 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};
44
45 typedef DWORD
46 (CALLBACK* CLASS_INSTALL_PROC) (
47 IN DI_FUNCTION InstallFunction,
48 IN HDEVINFO DeviceInfoSet,
49 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL);
50 typedef BOOL
51 (WINAPI* DEFAULT_CLASS_INSTALL_PROC) (
52 IN HDEVINFO DeviceInfoSet,
53 IN OUT PSP_DEVINFO_DATA DeviceInfoData);
54 typedef DWORD
55 (CALLBACK* COINSTALLER_PROC) (
56 IN DI_FUNCTION InstallFunction,
57 IN HDEVINFO DeviceInfoSet,
58 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
59 IN OUT PCOINSTALLER_CONTEXT_DATA Context);
60
61 struct CoInstallerElement
62 {
63 LIST_ENTRY ListEntry;
64
65 HMODULE Module;
66 COINSTALLER_PROC Function;
67 BOOL DoPostProcessing;
68 PVOID PrivateData;
69 };
70
71 struct GetSectionCallbackInfo
72 {
73 PSP_ALTPLATFORM_INFO PlatformInfo;
74 BYTE ProductType;
75 WORD SuiteMask;
76 DWORD PrefixLength;
77 WCHAR BestSection[LINE_LEN + 1];
78 DWORD BestScore1, BestScore2, BestScore3, BestScore4, BestScore5;
79 };
80
81
82
83 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
84 {
85 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
86 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
87 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
88 '0','2','X','}',0};
89
90 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
91 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
92 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
93 }
94
95 static DWORD
96 GetErrorCodeFromCrCode(const IN CONFIGRET cr)
97 {
98 switch (cr)
99 {
100 case CR_ACCESS_DENIED: return ERROR_ACCESS_DENIED;
101 case CR_BUFFER_SMALL: return ERROR_INSUFFICIENT_BUFFER;
102 case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED;
103 case CR_FAILURE: return ERROR_GEN_FAILURE;
104 case CR_INVALID_DATA: return ERROR_INVALID_USER_BUFFER;
105 case CR_INVALID_DEVICE_ID: return ERROR_INVALID_PARAMETER;
106 case CR_INVALID_MACHINENAME: return ERROR_INVALID_COMPUTERNAME;
107 case CR_INVALID_DEVNODE: return ERROR_INVALID_PARAMETER;
108 case CR_INVALID_FLAG: return ERROR_INVALID_FLAGS;
109 case CR_INVALID_POINTER: return ERROR_INVALID_PARAMETER;
110 case CR_INVALID_PROPERTY: return ERROR_INVALID_PARAMETER;
111 case CR_NO_SUCH_DEVNODE: return ERROR_FILE_NOT_FOUND;
112 case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND;
113 case CR_NO_SUCH_VALUE: return ERROR_FILE_NOT_FOUND;
114 case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
115 case CR_REGISTRY_ERROR: return ERROR_GEN_FAILURE;
116 case CR_SUCCESS: return ERROR_SUCCESS;
117 default: return ERROR_GEN_FAILURE;
118 }
119
120 /* Does not happen */
121 }
122
123 /* Lower scores are best ones */
124 static BOOL
125 CheckSectionValid(
126 IN LPCWSTR SectionName,
127 IN PSP_ALTPLATFORM_INFO PlatformInfo,
128 IN BYTE ProductType,
129 IN WORD SuiteMask,
130 OUT PDWORD ScorePlatform,
131 OUT PDWORD ScoreMajorVersion,
132 OUT PDWORD ScoreMinorVersion,
133 OUT PDWORD ScoreProductType,
134 OUT PDWORD ScoreSuiteMask)
135 {
136 LPWSTR Section = NULL;
137 LPCWSTR pExtensionPlatform, pExtensionArchitecture;
138 LPWSTR Fields[6];
139 DWORD i;
140 BOOL ret = FALSE;
141
142 static const WCHAR ExtensionPlatformNone[] = {'.',0};
143 static const WCHAR ExtensionPlatformNT[] = {'.','N','T',0};
144 static const WCHAR ExtensionPlatformWindows[] = {'.','W','i','n',0};
145
146 static const WCHAR ExtensionArchitectureNone[] = {0};
147 static const WCHAR ExtensionArchitecturealpha[] = {'a','l','p','h','a',0};
148 static const WCHAR ExtensionArchitectureamd64[] = {'A','M','D','6','4',0};
149 static const WCHAR ExtensionArchitectureia64[] = {'I','A','6','4',0};
150 static const WCHAR ExtensionArchitecturemips[] = {'m','i','p','s',0};
151 static const WCHAR ExtensionArchitectureppc[] = {'p','p','c',0};
152 static const WCHAR ExtensionArchitecturex86[] = {'x','8','6',0};
153
154 TRACE("%s %p 0x%x 0x%x\n",
155 debugstr_w(SectionName), PlatformInfo, ProductType, SuiteMask);
156
157 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = 0;
158
159 Section = DuplicateString(SectionName);
160 if (!Section)
161 {
162 TRACE("DuplicateString() failed\n");
163 goto cleanup;
164 }
165
166 /* Set various extensions values */
167 switch (PlatformInfo->Platform)
168 {
169 case VER_PLATFORM_WIN32_WINDOWS:
170 pExtensionPlatform = ExtensionPlatformWindows;
171 break;
172 case VER_PLATFORM_WIN32_NT:
173 pExtensionPlatform = ExtensionPlatformNT;
174 break;
175 default:
176 ERR("Unknown platform 0x%lx\n", PlatformInfo->Platform);
177 pExtensionPlatform = ExtensionPlatformNone;
178 break;
179 }
180 switch (PlatformInfo->ProcessorArchitecture)
181 {
182 case PROCESSOR_ARCHITECTURE_ALPHA:
183 pExtensionArchitecture = ExtensionArchitecturealpha;
184 break;
185 case PROCESSOR_ARCHITECTURE_AMD64:
186 pExtensionArchitecture = ExtensionArchitectureamd64;
187 break;
188 case PROCESSOR_ARCHITECTURE_IA64:
189 pExtensionArchitecture = ExtensionArchitectureia64;
190 break;
191 case PROCESSOR_ARCHITECTURE_INTEL:
192 pExtensionArchitecture = ExtensionArchitecturex86;
193 break;
194 case PROCESSOR_ARCHITECTURE_MIPS:
195 pExtensionArchitecture = ExtensionArchitecturemips;
196 break;
197 case PROCESSOR_ARCHITECTURE_PPC:
198 pExtensionArchitecture = ExtensionArchitectureppc;
199 break;
200 default:
201 ERR("Unknown processor architecture 0x%x\n", PlatformInfo->ProcessorArchitecture);
202 case PROCESSOR_ARCHITECTURE_UNKNOWN:
203 pExtensionArchitecture = ExtensionArchitectureNone;
204 break;
205 }
206
207 /*
208 * Field[0] Platform
209 * Field[1] Architecture
210 * Field[2] Major version
211 * Field[3] Minor version
212 * Field[4] Product type
213 * Field[5] Suite mask
214 * Remark: lastests fields may be NULL if the information is not provided
215 */
216 Fields[0] = Section;
217 if (Fields[0] == NULL)
218 {
219 TRACE("No extension found\n");
220 *ScorePlatform = *ScoreMajorVersion = *ScoreMinorVersion = *ScoreProductType = *ScoreSuiteMask = ULONG_MAX;
221 ret = TRUE;
222 goto cleanup;
223 }
224 Fields[1] = Fields[0] + 1;
225 Fields[2] = Fields[3] = Fields[4] = Fields[5] = NULL;
226 for (i = 2; Fields[i - 1] != NULL && i < 6; i++)
227 {
228 Fields[i] = wcschr(Fields[i - 1], '.');
229 if (Fields[i])
230 {
231 Fields[i]++;
232 *(Fields[i] - 1) = UNICODE_NULL;
233 }
234 }
235 /* Take care of first 2 fields */
236 if (strncmpiW(Fields[0], ExtensionPlatformWindows, strlenW(ExtensionPlatformWindows)) == 0)
237 {
238 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_WINDOWS)
239 {
240 TRACE("Mismatch on platform field\n");
241 goto cleanup;
242 }
243 Fields[1] += wcslen(ExtensionPlatformWindows) - 1;
244 }
245 else if (strncmpiW(Fields[0], ExtensionPlatformNT, strlenW(ExtensionPlatformNT)) == 0)
246 {
247 if (PlatformInfo->Platform != VER_PLATFORM_WIN32_NT)
248 {
249 TRACE("Mismatch on platform field\n");
250 goto cleanup;
251 }
252 Fields[1] += wcslen(ExtensionPlatformNT) - 1;
253 }
254 else
255 {
256 /* No platform specified */
257 *ScorePlatform |= 0x02;
258 }
259 if (strcmpiW(Fields[1], ExtensionArchitectureNone) == 0)
260 {
261 /* No architecture specified */
262 *ScorePlatform |= 0x01;
263 }
264 else if (strcmpiW(Fields[1], pExtensionArchitecture) != 0)
265 {
266 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
267 debugstr_w(Fields[1]), debugstr_w(pExtensionArchitecture));
268 goto cleanup;
269 }
270
271 /* Check if informations are matching */
272 if (Fields[2] && *Fields[2])
273 {
274 DWORD MajorVersion, MinorVersion = 0;
275 MajorVersion = strtoulW(Fields[2], NULL, 0);
276 if ((MajorVersion == 0 || MajorVersion == ULONG_MAX) &&
277 (errno == ERANGE || errno == EINVAL))
278 {
279 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields[2]));
280 goto cleanup;
281 }
282 if (Fields[3] && *Fields[3])
283 {
284 MinorVersion = strtoulW(Fields[3], NULL, 0);
285 if ((MinorVersion == 0 || MinorVersion == ULONG_MAX) &&
286 (errno == ERANGE || errno == EINVAL))
287 {
288 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields[3]));
289 goto cleanup;
290 }
291 }
292 if (PlatformInfo->MajorVersion < MajorVersion ||
293 (PlatformInfo->MajorVersion == MajorVersion && PlatformInfo->MinorVersion < MinorVersion))
294 {
295 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
296 MajorVersion, MinorVersion, PlatformInfo->MajorVersion, PlatformInfo->MinorVersion);
297 goto cleanup;
298 }
299 *ScoreMajorVersion = MajorVersion - PlatformInfo->MajorVersion;
300 if (MajorVersion == PlatformInfo->MajorVersion)
301 *ScoreMinorVersion = MinorVersion - PlatformInfo->MinorVersion;
302 else
303 *ScoreMinorVersion = MinorVersion;
304 }
305 else if (Fields[3] && *Fields[3])
306 {
307 TRACE("Minor version found without major version\n");
308 goto cleanup;
309 }
310 else
311 {
312 *ScoreMajorVersion = PlatformInfo->MajorVersion;
313 *ScoreMinorVersion = PlatformInfo->MinorVersion;
314 }
315
316 if (Fields[4] && *Fields[4])
317 {
318 DWORD CurrentProductType;
319 CurrentProductType = strtoulW(Fields[4], NULL, 0);
320 if ((CurrentProductType == 0 || CurrentProductType == ULONG_MAX) &&
321 (errno == ERANGE || errno == EINVAL))
322 {
323 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields[4]));
324 goto cleanup;
325 }
326 if (CurrentProductType != ProductType)
327 {
328 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
329 CurrentProductType, ProductType);
330 goto cleanup;
331 }
332 }
333 else
334 *ScoreProductType = 1;
335
336 if (Fields[5] && *Fields[5])
337 {
338 DWORD CurrentSuiteMask;
339 CurrentSuiteMask = strtoulW(Fields[5], NULL, 0);
340 if ((CurrentSuiteMask == 0 || CurrentSuiteMask == ULONG_MAX) &&
341 (errno == ERANGE || errno == EINVAL))
342 {
343 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields[5]));
344 goto cleanup;
345 }
346 if ((CurrentSuiteMask & ~SuiteMask) != 0)
347 {
348 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
349 CurrentSuiteMask, SuiteMask);
350 goto cleanup;
351 }
352 *ScoreSuiteMask = SuiteMask & ~CurrentSuiteMask;
353 }
354 else
355 *ScoreSuiteMask = SuiteMask;
356
357 ret = TRUE;
358
359 cleanup:
360 MyFree(Section);
361 return ret;
362 }
363
364 static BOOL
365 GetSectionCallback(
366 IN LPCWSTR SectionName,
367 IN PVOID Context)
368 {
369 struct GetSectionCallbackInfo *info = Context;
370 DWORD Score1, Score2, Score3, Score4, Score5;
371 BOOL ret;
372
373 if (SectionName[info->PrefixLength] != '.')
374 return TRUE;
375
376 ret = CheckSectionValid(
377 &SectionName[info->PrefixLength],
378 info->PlatformInfo,
379 info->ProductType,
380 info->SuiteMask,
381 &Score1, &Score2, &Score3, &Score4, &Score5);
382 if (!ret)
383 {
384 TRACE("Section %s not compatible\n", debugstr_w(SectionName));
385 return TRUE;
386 }
387 if (Score1 > info->BestScore1) goto done;
388 if (Score1 < info->BestScore1) goto bettersection;
389 if (Score2 > info->BestScore2) goto done;
390 if (Score2 < info->BestScore2) goto bettersection;
391 if (Score3 > info->BestScore3) goto done;
392 if (Score3 < info->BestScore3) goto bettersection;
393 if (Score4 > info->BestScore4) goto done;
394 if (Score4 < info->BestScore4) goto bettersection;
395 if (Score5 > info->BestScore5) goto done;
396 if (Score5 < info->BestScore5) goto bettersection;
397 goto done;
398
399 bettersection:
400 strcpyW(info->BestSection, SectionName);
401 info->BestScore1 = Score1;
402 info->BestScore2 = Score2;
403 info->BestScore3 = Score3;
404 info->BestScore4 = Score4;
405 info->BestScore5 = Score5;
406
407 done:
408 return TRUE;
409 }
410
411 /***********************************************************************
412 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
413 */
414 BOOL WINAPI
415 SetupDiGetActualSectionToInstallExW(
416 IN HINF InfHandle,
417 IN PCWSTR InfSectionName,
418 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
419 OUT PWSTR InfSectionWithExt OPTIONAL,
420 IN DWORD InfSectionWithExtSize,
421 OUT PDWORD RequiredSize OPTIONAL,
422 OUT PWSTR* Extension OPTIONAL,
423 IN PVOID Reserved)
424 {
425 BOOL ret = FALSE;
426
427 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle, debugstr_w(InfSectionName),
428 AlternatePlatformInfo, InfSectionWithExt, InfSectionWithExtSize,
429 RequiredSize, Extension, Reserved);
430
431 if (!InfHandle || InfHandle == (HINF)INVALID_HANDLE_VALUE)
432 SetLastError(ERROR_INVALID_HANDLE);
433 else if (!InfSectionName)
434 SetLastError(ERROR_INVALID_PARAMETER);
435 else if (AlternatePlatformInfo && AlternatePlatformInfo->cbSize != sizeof(SP_ALTPLATFORM_INFO))
436 SetLastError(ERROR_INVALID_USER_BUFFER);
437 else if (Reserved != NULL)
438 SetLastError(ERROR_INVALID_PARAMETER);
439 else
440 {
441 static SP_ALTPLATFORM_INFO CurrentPlatform = { 0, };
442 static BYTE CurrentProductType = 0;
443 static WORD CurrentSuiteMask = 0;
444 PSP_ALTPLATFORM_INFO pPlatformInfo = &CurrentPlatform;
445 struct GetSectionCallbackInfo CallbackInfo;
446 DWORD dwFullLength;
447 BYTE ProductType;
448 WORD SuiteMask;
449
450 /* Fill platform info if needed */
451 if (AlternatePlatformInfo)
452 {
453 pPlatformInfo = AlternatePlatformInfo;
454 ProductType = 0;
455 SuiteMask = 0;
456 }
457 else
458 {
459 if (CurrentPlatform.cbSize != sizeof(SP_ALTPLATFORM_INFO))
460 {
461 /* That's the first time we go here. We need to fill in the structure */
462 OSVERSIONINFOEX VersionInfo;
463 SYSTEM_INFO SystemInfo;
464 VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
465 ret = GetVersionExW((OSVERSIONINFO*)&VersionInfo);
466 if (!ret)
467 goto done;
468 GetSystemInfo(&SystemInfo);
469 CurrentPlatform.cbSize = sizeof(SP_ALTPLATFORM_INFO);
470 CurrentPlatform.Platform = VersionInfo.dwPlatformId;
471 CurrentPlatform.MajorVersion = VersionInfo.dwMajorVersion;
472 CurrentPlatform.MinorVersion = VersionInfo.dwMinorVersion;
473 CurrentPlatform.ProcessorArchitecture = SystemInfo.wProcessorArchitecture;
474 CurrentPlatform.Reserved = 0;
475 CurrentProductType = VersionInfo.wProductType;
476 CurrentSuiteMask = VersionInfo.wSuiteMask;
477 }
478 ProductType = CurrentProductType;
479 SuiteMask = CurrentSuiteMask;
480 }
481
482 CallbackInfo.PlatformInfo = pPlatformInfo;
483 CallbackInfo.ProductType = ProductType;
484 CallbackInfo.SuiteMask = SuiteMask;
485 CallbackInfo.PrefixLength = strlenW(InfSectionName);
486 CallbackInfo.BestScore1 = ULONG_MAX;
487 CallbackInfo.BestScore2 = ULONG_MAX;
488 CallbackInfo.BestScore3 = ULONG_MAX;
489 CallbackInfo.BestScore4 = ULONG_MAX;
490 CallbackInfo.BestScore5 = ULONG_MAX;
491 strcpyW(CallbackInfo.BestSection, InfSectionName);
492 if (!EnumerateSectionsStartingWith(
493 InfHandle,
494 InfSectionName,
495 GetSectionCallback,
496 &CallbackInfo))
497 {
498 SetLastError(ERROR_GEN_FAILURE);
499 goto done;
500 }
501
502 dwFullLength = lstrlenW(CallbackInfo.BestSection);
503 if (RequiredSize != NULL)
504 *RequiredSize = dwFullLength + 1;
505
506 if (InfSectionWithExtSize > 0)
507 {
508 if (InfSectionWithExtSize < dwFullLength + 1)
509 {
510 SetLastError(ERROR_INSUFFICIENT_BUFFER);
511 goto done;
512 }
513 strcpyW(InfSectionWithExt, CallbackInfo.BestSection);
514 if (Extension)
515 {
516 DWORD dwLength = lstrlenW(InfSectionName);
517 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
518 }
519 }
520
521 ret = TRUE;
522 }
523
524 done:
525 TRACE("Returning %d\n", ret);
526 return ret;
527 }
528
529
530 BOOL
531 CreateDeviceInfo(
532 IN struct DeviceInfoSet *list,
533 IN LPCWSTR InstancePath,
534 IN LPCGUID pClassGuid,
535 OUT struct DeviceInfo **pDeviceInfo)
536 {
537 DWORD size;
538 CONFIGRET cr;
539 struct DeviceInfo *deviceInfo;
540
541 *pDeviceInfo = NULL;
542
543 size = FIELD_OFFSET(struct DeviceInfo, Data) + (strlenW(InstancePath) + 1) * sizeof(WCHAR);
544 deviceInfo = HeapAlloc(GetProcessHeap(), 0, size);
545 if (!deviceInfo)
546 {
547 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
548 return FALSE;
549 }
550 ZeroMemory(deviceInfo, size);
551
552 cr = CM_Locate_DevNode_ExW(&deviceInfo->dnDevInst, (DEVINSTID_W)InstancePath, CM_LOCATE_DEVNODE_PHANTOM, list->hMachine);
553 if (cr != CR_SUCCESS)
554 {
555 SetLastError(GetErrorCodeFromCrCode(cr));
556 return FALSE;
557 }
558
559 deviceInfo->set = list;
560 deviceInfo->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
561 strcpyW(deviceInfo->Data, InstancePath);
562 deviceInfo->instanceId = deviceInfo->Data;
563 deviceInfo->UniqueId = strrchrW(deviceInfo->Data, '\\');
564 deviceInfo->DeviceDescription = NULL;
565 memcpy(&deviceInfo->ClassGuid, pClassGuid, sizeof(GUID));
566 deviceInfo->CreationFlags = 0;
567 InitializeListHead(&deviceInfo->DriverListHead);
568 InitializeListHead(&deviceInfo->InterfaceListHead);
569
570 *pDeviceInfo = deviceInfo;
571 return TRUE;
572 }
573
574
575 static BOOL
576 DestroyClassInstallParams(struct ClassInstallParams* installParams)
577 {
578 HeapFree(GetProcessHeap(), 0, installParams->PropChangeParams);
579 HeapFree(GetProcessHeap(), 0, installParams->AddPropertyPageData);
580 return TRUE;
581 }
582
583 static BOOL
584 DestroyDeviceInfo(struct DeviceInfo *deviceInfo)
585 {
586 PLIST_ENTRY ListEntry;
587 struct DriverInfoElement *driverInfo;
588 struct DeviceInterface *deviceInterface;
589
590 while (!IsListEmpty(&deviceInfo->DriverListHead))
591 {
592 ListEntry = RemoveHeadList(&deviceInfo->DriverListHead);
593 driverInfo = CONTAINING_RECORD(ListEntry, struct DriverInfoElement, ListEntry);
594 if (!DestroyDriverInfoElement(driverInfo))
595 return FALSE;
596 }
597 while (!IsListEmpty(&deviceInfo->InterfaceListHead))
598 {
599 ListEntry = RemoveHeadList(&deviceInfo->InterfaceListHead);
600 deviceInterface = CONTAINING_RECORD(ListEntry, struct DeviceInterface, ListEntry);
601 if (!DestroyDeviceInterface(deviceInterface))
602 return FALSE;
603 }
604 DestroyClassInstallParams(&deviceInfo->ClassInstallParams);
605 return HeapFree(GetProcessHeap(), 0, deviceInfo);
606 }
607
608 static BOOL
609 DestroyDeviceInfoSet(struct DeviceInfoSet* list)
610 {
611 PLIST_ENTRY ListEntry;
612 struct DeviceInfo *deviceInfo;
613
614 while (!IsListEmpty(&list->ListHead))
615 {
616 ListEntry = RemoveHeadList(&list->ListHead);
617 deviceInfo = CONTAINING_RECORD(ListEntry, struct DeviceInfo, ListEntry);
618 if (!DestroyDeviceInfo(deviceInfo))
619 return FALSE;
620 }
621 if (list->HKLM != HKEY_LOCAL_MACHINE)
622 RegCloseKey(list->HKLM);
623 CM_Disconnect_Machine(list->hMachine);
624 DestroyClassInstallParams(&list->ClassInstallParams);
625 return HeapFree(GetProcessHeap(), 0, list);
626 }
627
628 /***********************************************************************
629 * SetupDiBuildClassInfoList (SETUPAPI.@)
630 *
631 * Returns a list of setup class GUIDs that identify the classes
632 * that are installed on a local machine.
633 *
634 * PARAMS
635 * Flags [I] control exclusion of classes from the list.
636 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
637 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
638 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
639 *
640 * RETURNS
641 * Success: TRUE.
642 * Failure: FALSE.
643 */
644 BOOL WINAPI SetupDiBuildClassInfoList(
645 DWORD Flags,
646 LPGUID ClassGuidList,
647 DWORD ClassGuidListSize,
648 PDWORD RequiredSize)
649 {
650 TRACE("\n");
651 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
652 ClassGuidListSize, RequiredSize,
653 NULL, NULL);
654 }
655
656 /***********************************************************************
657 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
658 *
659 * Returns a list of setup class GUIDs that identify the classes
660 * that are installed on a local or remote macine.
661 *
662 * PARAMS
663 * Flags [I] control exclusion of classes from the list.
664 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
665 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
666 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
667 * MachineName [I] name of a remote machine.
668 * Reserved [I] must be NULL.
669 *
670 * RETURNS
671 * Success: TRUE.
672 * Failure: FALSE.
673 */
674 BOOL WINAPI SetupDiBuildClassInfoListExA(
675 DWORD Flags,
676 LPGUID ClassGuidList,
677 DWORD ClassGuidListSize,
678 PDWORD RequiredSize,
679 LPCSTR MachineName,
680 PVOID Reserved)
681 {
682 LPWSTR MachineNameW = NULL;
683 BOOL bResult;
684
685 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
686 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved);
687
688 if (MachineName)
689 {
690 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
691 if (MachineNameW == NULL) return FALSE;
692 }
693
694 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
695 ClassGuidListSize, RequiredSize,
696 MachineNameW, Reserved);
697
698 MyFree(MachineNameW);
699
700 return bResult;
701 }
702
703 /***********************************************************************
704 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
705 *
706 * Returns a list of setup class GUIDs that identify the classes
707 * that are installed on a local or remote macine.
708 *
709 * PARAMS
710 * Flags [I] control exclusion of classes from the list.
711 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
712 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
713 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
714 * MachineName [I] name of a remote machine.
715 * Reserved [I] must be NULL.
716 *
717 * RETURNS
718 * Success: TRUE.
719 * Failure: FALSE.
720 */
721 BOOL WINAPI SetupDiBuildClassInfoListExW(
722 DWORD Flags,
723 LPGUID ClassGuidList,
724 DWORD ClassGuidListSize,
725 PDWORD RequiredSize,
726 LPCWSTR MachineName,
727 PVOID Reserved)
728 {
729 WCHAR szKeyName[40];
730 HKEY hClassesKey = INVALID_HANDLE_VALUE;
731 HKEY hClassKey;
732 DWORD dwLength;
733 DWORD dwIndex;
734 LONG lError;
735 DWORD dwGuidListIndex = 0;
736
737 TRACE("0x%lx %p %lu %p %s %p\n", Flags, ClassGuidList,
738 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
739
740 if (!RequiredSize)
741 {
742 SetLastError(ERROR_INVALID_PARAMETER);
743 return FALSE;
744 }
745 else if (!ClassGuidList && ClassGuidListSize > 0)
746 {
747 SetLastError(ERROR_INVALID_PARAMETER);
748 return FALSE;
749 }
750
751 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
752 KEY_ENUMERATE_SUB_KEYS,
753 DIOCR_INSTALLER,
754 MachineName,
755 Reserved);
756 if (hClassesKey == INVALID_HANDLE_VALUE)
757 {
758 return FALSE;
759 }
760
761 for (dwIndex = 0; ; dwIndex++)
762 {
763 dwLength = 40;
764 lError = RegEnumKeyExW(hClassesKey,
765 dwIndex,
766 szKeyName,
767 &dwLength,
768 NULL,
769 NULL,
770 NULL,
771 NULL);
772 TRACE("RegEnumKeyExW() returns %d\n", lError);
773 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
774 {
775 TRACE("Key name: %s\n", debugstr_w(szKeyName));
776
777 if (RegOpenKeyExW(hClassesKey,
778 szKeyName,
779 0,
780 KEY_QUERY_VALUE,
781 &hClassKey))
782 {
783 RegCloseKey(hClassesKey);
784 return FALSE;
785 }
786
787 if (!RegQueryValueExW(hClassKey,
788 REGSTR_VAL_NOUSECLASS,
789 NULL,
790 NULL,
791 NULL,
792 NULL))
793 {
794 TRACE("'NoUseClass' value found!\n");
795 RegCloseKey(hClassKey);
796 continue;
797 }
798
799 if ((Flags & DIBCI_NOINSTALLCLASS) &&
800 (!RegQueryValueExW(hClassKey,
801 REGSTR_VAL_NOINSTALLCLASS,
802 NULL,
803 NULL,
804 NULL,
805 NULL)))
806 {
807 TRACE("'NoInstallClass' value found!\n");
808 RegCloseKey(hClassKey);
809 continue;
810 }
811
812 if ((Flags & DIBCI_NODISPLAYCLASS) &&
813 (!RegQueryValueExW(hClassKey,
814 REGSTR_VAL_NODISPLAYCLASS,
815 NULL,
816 NULL,
817 NULL,
818 NULL)))
819 {
820 TRACE("'NoDisplayClass' value found!\n");
821 RegCloseKey(hClassKey);
822 continue;
823 }
824
825 RegCloseKey(hClassKey);
826
827 TRACE("Guid: %s\n", debugstr_w(szKeyName));
828 if (dwGuidListIndex < ClassGuidListSize)
829 {
830 if (szKeyName[0] == '{' && szKeyName[37] == '}')
831 {
832 szKeyName[37] = 0;
833 }
834 TRACE("Guid: %p\n", &szKeyName[1]);
835
836 UuidFromStringW(&szKeyName[1],
837 &ClassGuidList[dwGuidListIndex]);
838 }
839
840 dwGuidListIndex++;
841 }
842
843 if (lError != ERROR_SUCCESS)
844 break;
845 }
846
847 RegCloseKey(hClassesKey);
848
849 if (RequiredSize != NULL)
850 *RequiredSize = dwGuidListIndex;
851
852 if (ClassGuidListSize < dwGuidListIndex)
853 {
854 SetLastError(ERROR_INSUFFICIENT_BUFFER);
855 return FALSE;
856 }
857
858 return TRUE;
859 }
860
861 /***********************************************************************
862 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
863 */
864 BOOL WINAPI SetupDiClassGuidsFromNameA(
865 LPCSTR ClassName,
866 LPGUID ClassGuidList,
867 DWORD ClassGuidListSize,
868 PDWORD RequiredSize)
869 {
870 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
871 ClassGuidListSize, RequiredSize,
872 NULL, NULL);
873 }
874
875 /***********************************************************************
876 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
877 */
878 BOOL WINAPI SetupDiClassGuidsFromNameW(
879 LPCWSTR ClassName,
880 LPGUID ClassGuidList,
881 DWORD ClassGuidListSize,
882 PDWORD RequiredSize)
883 {
884 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
885 ClassGuidListSize, RequiredSize,
886 NULL, NULL);
887 }
888
889 /***********************************************************************
890 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
891 */
892 BOOL WINAPI SetupDiClassGuidsFromNameExA(
893 LPCSTR ClassName,
894 LPGUID ClassGuidList,
895 DWORD ClassGuidListSize,
896 PDWORD RequiredSize,
897 LPCSTR MachineName,
898 PVOID Reserved)
899 {
900 LPWSTR ClassNameW = NULL;
901 LPWSTR MachineNameW = NULL;
902 BOOL bResult;
903
904 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName), ClassGuidList,
905 ClassGuidListSize, RequiredSize, debugstr_a(MachineName), Reserved);
906
907 if (!ClassName)
908 {
909 SetLastError(ERROR_INVALID_PARAMETER);
910 return FALSE;
911 }
912
913 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
914 if (ClassNameW == NULL)
915 return FALSE;
916
917 if (MachineName)
918 {
919 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
920 if (MachineNameW == NULL)
921 {
922 MyFree(ClassNameW);
923 return FALSE;
924 }
925 }
926
927 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
928 ClassGuidListSize, RequiredSize,
929 MachineNameW, Reserved);
930
931 MyFree(MachineNameW);
932 MyFree(ClassNameW);
933
934 return bResult;
935 }
936
937 /***********************************************************************
938 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
939 */
940 BOOL WINAPI SetupDiClassGuidsFromNameExW(
941 LPCWSTR ClassName,
942 LPGUID ClassGuidList,
943 DWORD ClassGuidListSize,
944 PDWORD RequiredSize,
945 LPCWSTR MachineName,
946 PVOID Reserved)
947 {
948 WCHAR szKeyName[40];
949 WCHAR szClassName[MAX_CLASS_NAME_LEN];
950 HKEY hClassesKey;
951 HKEY hClassKey;
952 DWORD dwLength;
953 DWORD dwIndex;
954 LONG lError;
955 DWORD dwGuidListIndex = 0;
956
957 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName), ClassGuidList,
958 ClassGuidListSize, RequiredSize, debugstr_w(MachineName), Reserved);
959
960 if (!ClassName || !RequiredSize)
961 {
962 SetLastError(ERROR_INVALID_PARAMETER);
963 return FALSE;
964 }
965 if (!ClassGuidList && ClassGuidListSize > 0)
966 {
967 SetLastError(ERROR_INVALID_PARAMETER);
968 return FALSE;
969 }
970 *RequiredSize = 0;
971
972 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
973 KEY_ENUMERATE_SUB_KEYS,
974 DIOCR_INSTALLER,
975 MachineName,
976 Reserved);
977 if (hClassesKey == INVALID_HANDLE_VALUE)
978 {
979 return FALSE;
980 }
981
982 for (dwIndex = 0; ; dwIndex++)
983 {
984 dwLength = 40;
985 lError = RegEnumKeyExW(hClassesKey,
986 dwIndex,
987 szKeyName,
988 &dwLength,
989 NULL,
990 NULL,
991 NULL,
992 NULL);
993 TRACE("RegEnumKeyExW() returns %d\n", lError);
994 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
995 {
996 TRACE("Key name: %p\n", szKeyName);
997
998 if (RegOpenKeyExW(hClassesKey,
999 szKeyName,
1000 0,
1001 KEY_QUERY_VALUE,
1002 &hClassKey))
1003 {
1004 RegCloseKey(hClassesKey);
1005 return FALSE;
1006 }
1007
1008 dwLength = MAX_CLASS_NAME_LEN * sizeof(WCHAR);
1009 if (!RegQueryValueExW(hClassKey,
1010 Class,
1011 NULL,
1012 NULL,
1013 (LPBYTE)szClassName,
1014 &dwLength))
1015 {
1016 TRACE("Class name: %p\n", szClassName);
1017
1018 if (strcmpiW(szClassName, ClassName) == 0)
1019 {
1020 TRACE("Found matching class name\n");
1021
1022 TRACE("Guid: %p\n", szKeyName);
1023 if (dwGuidListIndex < ClassGuidListSize)
1024 {
1025 if (szKeyName[0] == '{' && szKeyName[37] == '}')
1026 {
1027 szKeyName[37] = 0;
1028 }
1029 TRACE("Guid: %p\n", &szKeyName[1]);
1030
1031 UuidFromStringW(&szKeyName[1],
1032 &ClassGuidList[dwGuidListIndex]);
1033 }
1034
1035 dwGuidListIndex++;
1036 }
1037 }
1038
1039 RegCloseKey(hClassKey);
1040 }
1041
1042 if (lError != ERROR_SUCCESS)
1043 break;
1044 }
1045
1046 RegCloseKey(hClassesKey);
1047
1048 if (RequiredSize != NULL)
1049 *RequiredSize = dwGuidListIndex;
1050
1051 if (ClassGuidListSize < dwGuidListIndex)
1052 {
1053 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1054 return FALSE;
1055 }
1056
1057 return TRUE;
1058 }
1059
1060 /***********************************************************************
1061 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1062 */
1063 BOOL WINAPI SetupDiClassNameFromGuidA(
1064 const GUID* ClassGuid,
1065 PSTR ClassName,
1066 DWORD ClassNameSize,
1067 PDWORD RequiredSize)
1068 {
1069 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
1070 ClassNameSize, RequiredSize,
1071 NULL, NULL);
1072 }
1073
1074 /***********************************************************************
1075 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1076 */
1077 BOOL WINAPI SetupDiClassNameFromGuidW(
1078 const GUID* ClassGuid,
1079 PWSTR ClassName,
1080 DWORD ClassNameSize,
1081 PDWORD RequiredSize)
1082 {
1083 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
1084 ClassNameSize, RequiredSize,
1085 NULL, NULL);
1086 }
1087
1088 /***********************************************************************
1089 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1090 */
1091 BOOL WINAPI SetupDiClassNameFromGuidExA(
1092 const GUID* ClassGuid,
1093 PSTR ClassName,
1094 DWORD ClassNameSize,
1095 PDWORD RequiredSize,
1096 PCSTR MachineName,
1097 PVOID Reserved)
1098 {
1099 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
1100 LPWSTR MachineNameW = NULL;
1101 BOOL ret;
1102
1103 if (MachineName)
1104 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1105 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
1106 NULL, MachineNameW, Reserved);
1107 if (ret)
1108 {
1109 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
1110 ClassNameSize, NULL, NULL);
1111 if (len == 0 || len > ClassNameSize)
1112 {
1113 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1114 ret = FALSE;
1115 }
1116 else if (RequiredSize)
1117 *RequiredSize = len;
1118 }
1119 MyFree(MachineNameW);
1120 return ret;
1121 }
1122
1123 /***********************************************************************
1124 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1125 */
1126 BOOL WINAPI SetupDiClassNameFromGuidExW(
1127 const GUID* ClassGuid,
1128 PWSTR ClassName,
1129 DWORD ClassNameSize,
1130 PDWORD RequiredSize,
1131 PCWSTR MachineName,
1132 PVOID Reserved)
1133 {
1134 HKEY hKey;
1135 DWORD dwLength;
1136 DWORD dwRegType;
1137 LONG rc;
1138
1139 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassName,
1140 ClassNameSize, RequiredSize, debugstr_w(MachineName), Reserved);
1141
1142 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1143 KEY_QUERY_VALUE,
1144 DIOCR_INSTALLER,
1145 MachineName,
1146 Reserved);
1147 if (hKey == INVALID_HANDLE_VALUE)
1148 {
1149 return FALSE;
1150 }
1151
1152 if (RequiredSize != NULL)
1153 {
1154 dwLength = 0;
1155 if (RegQueryValueExW(hKey,
1156 Class,
1157 NULL,
1158 NULL,
1159 NULL,
1160 &dwLength))
1161 {
1162 RegCloseKey(hKey);
1163 return FALSE;
1164 }
1165
1166 *RequiredSize = dwLength / sizeof(WCHAR) + 1;
1167 }
1168
1169 if (!ClassGuid)
1170 {
1171 SetLastError(ERROR_INVALID_CLASS);
1172 RegCloseKey(hKey);
1173 return FALSE;
1174 }
1175 if (!ClassName && ClassNameSize > 0)
1176 {
1177 SetLastError(ERROR_INVALID_PARAMETER);
1178 RegCloseKey(hKey);
1179 return FALSE;
1180 }
1181
1182 dwLength = ClassNameSize * sizeof(WCHAR) - sizeof(UNICODE_NULL);
1183 rc = RegQueryValueExW(hKey,
1184 Class,
1185 NULL,
1186 &dwRegType,
1187 (LPBYTE)ClassName,
1188 &dwLength);
1189 if (rc != ERROR_SUCCESS)
1190 {
1191 SetLastError(rc);
1192 RegCloseKey(hKey);
1193 return FALSE;
1194 }
1195 if (dwRegType != REG_SZ)
1196 {
1197 SetLastError(ERROR_GEN_FAILURE);
1198 RegCloseKey(hKey);
1199 return FALSE;
1200 }
1201
1202 if (ClassNameSize > 1)
1203 ClassName[ClassNameSize] = UNICODE_NULL;
1204 RegCloseKey(hKey);
1205
1206 return TRUE;
1207 }
1208
1209 /***********************************************************************
1210 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1211 */
1212 HDEVINFO WINAPI
1213 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
1214 HWND hwndParent)
1215 {
1216 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
1217 }
1218
1219 /***********************************************************************
1220 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1221 */
1222 HDEVINFO WINAPI
1223 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
1224 HWND hwndParent,
1225 PCSTR MachineName,
1226 PVOID Reserved)
1227 {
1228 LPWSTR MachineNameW = NULL;
1229 HDEVINFO hDevInfo;
1230
1231 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1232 debugstr_a(MachineName), Reserved);
1233
1234 if (MachineName)
1235 {
1236 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1237 if (MachineNameW == NULL)
1238 return INVALID_HANDLE_VALUE;
1239 }
1240
1241 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
1242 MachineNameW, Reserved);
1243
1244 MyFree(MachineNameW);
1245
1246 return hDevInfo;
1247 }
1248
1249 /***********************************************************************
1250 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1251 *
1252 * Create an empty DeviceInfoSet list.
1253 *
1254 * PARAMS
1255 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1256 * with this list.
1257 * hwndParent [I] hwnd needed for interface related actions.
1258 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1259 * local registry will be used.
1260 * Reserved [I] must be NULL
1261 *
1262 * RETURNS
1263 * Success: empty list.
1264 * Failure: INVALID_HANDLE_VALUE.
1265 */
1266 HDEVINFO WINAPI
1267 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
1268 HWND hwndParent,
1269 PCWSTR MachineName,
1270 PVOID Reserved)
1271 {
1272 struct DeviceInfoSet *list = NULL;
1273 DWORD size = FIELD_OFFSET(struct DeviceInfoSet, szData);
1274 DWORD rc;
1275 CONFIGRET cr;
1276 HDEVINFO ret = INVALID_HANDLE_VALUE;
1277
1278 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
1279 debugstr_w(MachineName), Reserved);
1280
1281 if (MachineName != NULL)
1282 {
1283 SIZE_T len = strlenW(MachineName);
1284 if (len >= SP_MAX_MACHINENAME_LENGTH - 4)
1285 {
1286 SetLastError(ERROR_INVALID_MACHINENAME);
1287 goto cleanup;
1288 }
1289 size += (len + 3) * sizeof(WCHAR);
1290 }
1291
1292 if (Reserved != NULL)
1293 {
1294 SetLastError(ERROR_INVALID_PARAMETER);
1295 return INVALID_HANDLE_VALUE;
1296 }
1297
1298 list = MyMalloc(size);
1299 if (!list)
1300 {
1301 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1302 return INVALID_HANDLE_VALUE;
1303 }
1304 ZeroMemory(list, FIELD_OFFSET(struct DeviceInfoSet, szData));
1305
1306 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
1307 memcpy(&list->ClassGuid,
1308 ClassGuid ? ClassGuid : &GUID_NULL,
1309 sizeof(list->ClassGuid));
1310 list->InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
1311 list->InstallParams.Flags |= DI_CLASSINSTALLPARAMS;
1312 list->InstallParams.hwndParent = hwndParent;
1313 if (MachineName)
1314 {
1315 rc = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &list->HKLM);
1316 if (rc != ERROR_SUCCESS)
1317 {
1318 SetLastError(ERROR_INVALID_MACHINENAME);
1319 goto cleanup;
1320 }
1321
1322 list->szData[0] = list->szData[1] = '\\';
1323 strcpyW(list->szData + 2, MachineName);
1324 list->MachineName = list->szData;
1325 }
1326 else
1327 {
1328 list->HKLM = HKEY_LOCAL_MACHINE;
1329 list->MachineName = NULL;
1330 }
1331 cr = CM_Connect_MachineW(list->MachineName, &list->hMachine);
1332 if (cr != CR_SUCCESS)
1333 {
1334 SetLastError(GetErrorCodeFromCrCode(cr));
1335 goto cleanup;
1336 }
1337 InitializeListHead(&list->DriverListHead);
1338 InitializeListHead(&list->ListHead);
1339
1340 return (HDEVINFO)list;
1341
1342 cleanup:
1343 if (ret == INVALID_HANDLE_VALUE)
1344 {
1345 if (list)
1346 {
1347 if (list->HKLM != NULL && list->HKLM != HKEY_LOCAL_MACHINE)
1348 RegCloseKey(list->HKLM);
1349 MyFree(list);
1350 }
1351 }
1352 return ret;
1353 }
1354
1355 /***********************************************************************
1356 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1357 */
1358 HKEY WINAPI SetupDiCreateDevRegKeyA(
1359 HDEVINFO DeviceInfoSet,
1360 PSP_DEVINFO_DATA DeviceInfoData,
1361 DWORD Scope,
1362 DWORD HwProfile,
1363 DWORD KeyType,
1364 HINF InfHandle,
1365 PCSTR InfSectionName)
1366 {
1367 PWSTR InfSectionNameW = NULL;
1368 HKEY key;
1369
1370 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1371 HwProfile, KeyType, InfHandle, debugstr_a(InfSectionName));
1372
1373 if (InfHandle)
1374 {
1375 if (!InfSectionName)
1376 {
1377 SetLastError(ERROR_INVALID_PARAMETER);
1378 return INVALID_HANDLE_VALUE;
1379 }
1380 else
1381 {
1382 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
1383 if (InfSectionNameW == NULL) return INVALID_HANDLE_VALUE;
1384 }
1385 }
1386 key = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, Scope,
1387 HwProfile, KeyType, InfHandle, InfSectionNameW);
1388 MyFree(InfSectionNameW);
1389 return key;
1390 }
1391
1392 static HKEY
1393 OpenHardwareProfileKey(
1394 IN HKEY HKLM,
1395 IN DWORD HwProfile,
1396 IN DWORD samDesired);
1397
1398 /***********************************************************************
1399 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1400 */
1401 HKEY WINAPI SetupDiCreateDevRegKeyW(
1402 HDEVINFO DeviceInfoSet,
1403 PSP_DEVINFO_DATA DeviceInfoData,
1404 DWORD Scope,
1405 DWORD HwProfile,
1406 DWORD KeyType,
1407 HINF InfHandle,
1408 PCWSTR InfSectionName)
1409 {
1410 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1411 HKEY key = INVALID_HANDLE_VALUE;
1412 LPWSTR lpGuidString = NULL;
1413 LPWSTR DriverKey = NULL; /* {GUID}\Index */
1414 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
1415 DWORD Index; /* Index used in the DriverKey name */
1416 DWORD rc;
1417 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
1418 HKEY hEnumKey = NULL;
1419 HKEY hClassKey = NULL;
1420 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
1421 HKEY hKey = NULL;
1422 HKEY RootKey;
1423
1424 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1425 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1426
1427 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1428 {
1429 SetLastError(ERROR_INVALID_HANDLE);
1430 return INVALID_HANDLE_VALUE;
1431 }
1432 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1433 {
1434 SetLastError(ERROR_INVALID_HANDLE);
1435 return INVALID_HANDLE_VALUE;
1436 }
1437 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1438 || !DeviceInfoData->Reserved)
1439 {
1440 SetLastError(ERROR_INVALID_PARAMETER);
1441 return INVALID_HANDLE_VALUE;
1442 }
1443 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
1444 {
1445 SetLastError(ERROR_INVALID_FLAGS);
1446 return INVALID_HANDLE_VALUE;
1447 }
1448 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
1449 {
1450 SetLastError(ERROR_INVALID_FLAGS);
1451 return INVALID_HANDLE_VALUE;
1452 }
1453 if (InfHandle && !InfSectionName)
1454 {
1455 SetLastError(ERROR_INVALID_PARAMETER);
1456 return INVALID_HANDLE_VALUE;
1457 }
1458 if (!InfHandle && InfSectionName)
1459 {
1460 SetLastError(ERROR_INVALID_PARAMETER);
1461 return INVALID_HANDLE_VALUE;
1462 }
1463
1464 if (Scope == DICS_FLAG_GLOBAL)
1465 RootKey = set->HKLM;
1466 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1467 {
1468 hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
1469 if (hHWProfileKey == INVALID_HANDLE_VALUE)
1470 goto cleanup;
1471 RootKey = hHWProfileKey;
1472 }
1473
1474 if (KeyType == DIREG_DEV)
1475 {
1476 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1477
1478 rc = RegCreateKeyExW(
1479 RootKey,
1480 REGSTR_PATH_SYSTEMENUM,
1481 0,
1482 NULL,
1483 REG_OPTION_NON_VOLATILE,
1484 KEY_CREATE_SUB_KEY,
1485 NULL,
1486 &hEnumKey,
1487 NULL);
1488 if (rc != ERROR_SUCCESS)
1489 {
1490 SetLastError(rc);
1491 goto cleanup;
1492 }
1493 rc = RegCreateKeyExW(
1494 hEnumKey,
1495 deviceInfo->instanceId,
1496 0,
1497 NULL,
1498 REG_OPTION_NON_VOLATILE,
1499 #if _WIN32_WINNT >= 0x502
1500 KEY_READ | KEY_WRITE,
1501 #else
1502 KEY_ALL_ACCESS,
1503 #endif
1504 NULL,
1505 &hKey,
1506 NULL);
1507 if (rc != ERROR_SUCCESS)
1508 {
1509 SetLastError(rc);
1510 goto cleanup;
1511 }
1512 }
1513 else /* KeyType == DIREG_DRV */
1514 {
1515 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
1516 goto cleanup;
1517 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1518 DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1519 if (!DriverKey)
1520 {
1521 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1522 goto cleanup;
1523 }
1524 DriverKey[0] = '{';
1525 strcpyW(&DriverKey[1], lpGuidString);
1526 pDeviceInstance = &DriverKey[strlenW(DriverKey)];
1527 *pDeviceInstance++ = '}';
1528 *pDeviceInstance++ = '\\';
1529 rc = RegOpenKeyExW(RootKey,
1530 REGSTR_PATH_CLASS_NT,
1531 0,
1532 KEY_CREATE_SUB_KEY,
1533 &hClassKey);
1534 if (rc != ERROR_SUCCESS)
1535 {
1536 SetLastError(rc);
1537 goto cleanup;
1538 }
1539
1540 /* Try all values for Index between 0 and 9999 */
1541 Index = 0;
1542 while (Index <= 9999)
1543 {
1544 DWORD Disposition;
1545 sprintfW(pDeviceInstance, InstanceKeyFormat, Index);
1546 rc = RegCreateKeyExW(hClassKey,
1547 DriverKey,
1548 0,
1549 NULL,
1550 REG_OPTION_NON_VOLATILE,
1551 #if _WIN32_WINNT >= 0x502
1552 KEY_READ | KEY_WRITE,
1553 #else
1554 KEY_ALL_ACCESS,
1555 #endif
1556 NULL,
1557 &hKey,
1558 &Disposition);
1559 if (rc != ERROR_SUCCESS)
1560 {
1561 SetLastError(rc);
1562 goto cleanup;
1563 }
1564 if (Disposition == REG_CREATED_NEW_KEY)
1565 break;
1566 RegCloseKey(hKey);
1567 hKey = NULL;
1568 Index++;
1569 }
1570 if (Index > 9999)
1571 {
1572 /* Unable to create more than 9999 devices within the same class */
1573 SetLastError(ERROR_GEN_FAILURE);
1574 goto cleanup;
1575 }
1576
1577 /* Open device key, to write Driver value */
1578 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
1579 if (hDeviceKey == INVALID_HANDLE_VALUE)
1580 goto cleanup;
1581 rc = RegSetValueExW(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR));
1582 if (rc != ERROR_SUCCESS)
1583 {
1584 SetLastError(rc);
1585 goto cleanup;
1586 }
1587 }
1588
1589 /* Do installation of the specified section */
1590 if (InfHandle)
1591 {
1592 FIXME("Need to install section %s in file %p\n",
1593 debugstr_w(InfSectionName), InfHandle);
1594 }
1595 key = hKey;
1596
1597 cleanup:
1598 if (lpGuidString)
1599 RpcStringFreeW(&lpGuidString);
1600 HeapFree(GetProcessHeap(), 0, DriverKey);
1601 if (hHWProfileKey != INVALID_HANDLE_VALUE)
1602 RegCloseKey(hHWProfileKey);
1603 if (hEnumKey != NULL)
1604 RegCloseKey(hEnumKey);
1605 if (hClassKey != NULL)
1606 RegCloseKey(hClassKey);
1607 if (hDeviceKey != INVALID_HANDLE_VALUE)
1608 RegCloseKey(hDeviceKey);
1609 if (hKey != NULL && hKey != key)
1610 RegCloseKey(hKey);
1611
1612 TRACE("Returning 0x%p\n", key);
1613 return key;
1614 }
1615
1616 /***********************************************************************
1617 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1618 */
1619 BOOL WINAPI SetupDiCreateDeviceInfoA(
1620 HDEVINFO DeviceInfoSet,
1621 PCSTR DeviceName,
1622 CONST GUID *ClassGuid,
1623 PCSTR DeviceDescription,
1624 HWND hwndParent,
1625 DWORD CreationFlags,
1626 PSP_DEVINFO_DATA DeviceInfoData)
1627 {
1628 BOOL ret;
1629 LPWSTR DeviceNameW = NULL;
1630 LPWSTR DeviceDescriptionW = NULL;
1631
1632 TRACE("\n");
1633
1634 if (DeviceName)
1635 {
1636 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1637 if (DeviceNameW == NULL) return FALSE;
1638 }
1639 if (DeviceDescription)
1640 {
1641 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1642 if (DeviceDescriptionW == NULL)
1643 {
1644 MyFree(DeviceNameW);
1645 return FALSE;
1646 }
1647 }
1648
1649 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1650 hwndParent, CreationFlags, DeviceInfoData);
1651
1652 MyFree(DeviceNameW);
1653 MyFree(DeviceDescriptionW);
1654
1655 return ret;
1656 }
1657
1658 /***********************************************************************
1659 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1660 */
1661 BOOL WINAPI SetupDiCreateDeviceInfoW(
1662 HDEVINFO DeviceInfoSet,
1663 PCWSTR DeviceName,
1664 CONST GUID *ClassGuid,
1665 PCWSTR DeviceDescription,
1666 HWND hwndParent,
1667 DWORD CreationFlags,
1668 PSP_DEVINFO_DATA DeviceInfoData)
1669 {
1670 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1671 BOOL ret = FALSE;
1672 SP_DEVINFO_DATA DevInfo;
1673
1674 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
1675 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
1676 hwndParent, CreationFlags, DeviceInfoData);
1677
1678 if (!DeviceName)
1679 {
1680 SetLastError(ERROR_INVALID_DEVINST_NAME);
1681 return FALSE;
1682 }
1683 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1684 {
1685 SetLastError(ERROR_INVALID_HANDLE);
1686 return FALSE;
1687 }
1688 if (!ClassGuid)
1689 {
1690 SetLastError(ERROR_INVALID_PARAMETER);
1691 return FALSE;
1692 }
1693 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1694 {
1695 SetLastError(ERROR_INVALID_HANDLE);
1696 return FALSE;
1697 }
1698 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
1699 !IsEqualGUID(ClassGuid, &set->ClassGuid))
1700 {
1701 SetLastError(ERROR_CLASS_MISMATCH);
1702 return FALSE;
1703 }
1704 if (CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS))
1705 {
1706 TRACE("Unknown flags: 0x%08lx\n", CreationFlags & ~(DICD_GENERATE_ID | DICD_INHERIT_CLASSDRVS));
1707 SetLastError(ERROR_INVALID_FLAGS);
1708 return FALSE;
1709 }
1710
1711 if (CreationFlags & DICD_GENERATE_ID)
1712 {
1713 /* Generate a new unique ID for this device */
1714 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1715 FIXME("not implemented\n");
1716 }
1717 else
1718 {
1719 /* Device name is fully qualified. Try to open it */
1720 BOOL rc;
1721
1722 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
1723 rc = SetupDiOpenDeviceInfoW(
1724 DeviceInfoSet,
1725 DeviceName,
1726 NULL, /* hwndParent */
1727 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
1728 &DevInfo);
1729
1730 if (rc)
1731 {
1732 /* SetupDiOpenDeviceInfoW has already added
1733 * the device info to the device info set
1734 */
1735 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1736 }
1737 else if (GetLastError() == ERROR_FILE_NOT_FOUND)
1738 {
1739 struct DeviceInfo *deviceInfo;
1740
1741 if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo))
1742 {
1743 InsertTailList(&set->ListHead, &deviceInfo->ListEntry);
1744
1745 if (!DeviceInfoData)
1746 ret = TRUE;
1747 else
1748 {
1749 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
1750 {
1751 SetLastError(ERROR_INVALID_USER_BUFFER);
1752 }
1753 else
1754 {
1755 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
1756 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
1757 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
1758 ret = TRUE;
1759 }
1760 }
1761 }
1762 }
1763 }
1764
1765 TRACE("Returning %d\n", ret);
1766 return ret;
1767 }
1768
1769 /***********************************************************************
1770 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1771 */
1772 BOOL WINAPI SetupDiRegisterDeviceInfo(
1773 HDEVINFO DeviceInfoSet,
1774 PSP_DEVINFO_DATA DeviceInfoData,
1775 DWORD Flags,
1776 PSP_DETSIG_CMPPROC CompareProc,
1777 PVOID CompareContext,
1778 PSP_DEVINFO_DATA DupDeviceInfoData)
1779 {
1780 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1781
1782 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1783 CompareProc, CompareContext, DupDeviceInfoData);
1784
1785 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1786 {
1787 SetLastError(ERROR_INVALID_HANDLE);
1788 return FALSE;
1789 }
1790 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1791 {
1792 SetLastError(ERROR_INVALID_HANDLE);
1793 return FALSE;
1794 }
1795 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1796 || !DeviceInfoData->Reserved)
1797 {
1798 SetLastError(ERROR_INVALID_PARAMETER);
1799 return FALSE;
1800 }
1801 FIXME("Stub %p %p 0x%lx %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1802 CompareProc, CompareContext, DupDeviceInfoData);
1803 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1804 return FALSE;
1805 }
1806
1807 /***********************************************************************
1808 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1809 */
1810 BOOL WINAPI SetupDiEnumDeviceInfo(
1811 HDEVINFO devinfo,
1812 DWORD index,
1813 PSP_DEVINFO_DATA info)
1814 {
1815 BOOL ret = FALSE;
1816
1817 TRACE("%p %d %p\n", devinfo, index, info);
1818
1819 if(info==NULL)
1820 {
1821 SetLastError(ERROR_INVALID_PARAMETER);
1822 return FALSE;
1823 }
1824 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
1825 {
1826 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1827 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1828 {
1829 if (info->cbSize != sizeof(SP_DEVINFO_DATA))
1830 SetLastError(ERROR_INVALID_USER_BUFFER);
1831 else
1832 {
1833 PLIST_ENTRY ItemList = list->ListHead.Flink;
1834 while (ItemList != &list->ListHead && index-- > 0)
1835 ItemList = ItemList->Flink;
1836 if (ItemList == &list->ListHead)
1837 SetLastError(ERROR_NO_MORE_ITEMS);
1838 else
1839 {
1840 struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
1841 memcpy(&info->ClassGuid,
1842 &DevInfo->ClassGuid,
1843 sizeof(GUID));
1844 info->DevInst = DevInfo->dnDevInst;
1845 info->Reserved = (ULONG_PTR)DevInfo;
1846 ret = TRUE;
1847 }
1848 }
1849 }
1850 else
1851 SetLastError(ERROR_INVALID_HANDLE);
1852 }
1853 else
1854 SetLastError(ERROR_INVALID_HANDLE);
1855 return ret;
1856 }
1857
1858 /***********************************************************************
1859 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1860 */
1861 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1862 HDEVINFO DeviceInfoSet,
1863 PSP_DEVINFO_DATA DeviceInfoData,
1864 PSTR DeviceInstanceId,
1865 DWORD DeviceInstanceIdSize,
1866 PDWORD RequiredSize)
1867 {
1868 BOOL ret = FALSE;
1869 DWORD size;
1870 PWSTR instanceId;
1871
1872 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1873 DeviceInstanceIdSize, RequiredSize);
1874
1875 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1876 {
1877 SetLastError(ERROR_INVALID_PARAMETER);
1878 return FALSE;
1879 }
1880
1881 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1882 DeviceInfoData,
1883 NULL,
1884 0,
1885 &size);
1886 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1887 return FALSE;
1888 instanceId = MyMalloc(size * sizeof(WCHAR));
1889 if (instanceId)
1890 {
1891 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1892 DeviceInfoData,
1893 instanceId,
1894 size,
1895 &size);
1896 if (ret)
1897 {
1898 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1899 DeviceInstanceId,
1900 DeviceInstanceIdSize, NULL, NULL);
1901
1902 if (!len)
1903 ret = FALSE;
1904 else
1905 {
1906 if (len > DeviceInstanceIdSize)
1907 {
1908 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1909 ret = FALSE;
1910 }
1911 if (RequiredSize)
1912 *RequiredSize = len;
1913 }
1914 }
1915 MyFree(instanceId);
1916 }
1917 else
1918 {
1919 if (RequiredSize)
1920 *RequiredSize = size;
1921 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1922 ret = FALSE;
1923 }
1924 return ret;
1925 }
1926
1927 /***********************************************************************
1928 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1929 */
1930 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1931 HDEVINFO DeviceInfoSet,
1932 PSP_DEVINFO_DATA DeviceInfoData,
1933 PWSTR DeviceInstanceId,
1934 DWORD DeviceInstanceIdSize,
1935 PDWORD RequiredSize)
1936 {
1937 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1938 struct DeviceInfo *devInfo;
1939
1940 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1941 DeviceInstanceIdSize, RequiredSize);
1942
1943 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1944 {
1945 SetLastError(ERROR_INVALID_HANDLE);
1946 return FALSE;
1947 }
1948 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1949 {
1950 SetLastError(ERROR_INVALID_HANDLE);
1951 return FALSE;
1952 }
1953 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1954 || !DeviceInfoData->Reserved)
1955 {
1956 SetLastError(ERROR_INVALID_PARAMETER);
1957 return FALSE;
1958 }
1959 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1960 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1961 {
1962 SetLastError(ERROR_INVALID_PARAMETER);
1963 return FALSE;
1964 }
1965 if (DeviceInstanceId && DeviceInstanceIdSize == 0)
1966 {
1967 SetLastError(ERROR_INVALID_PARAMETER);
1968 return FALSE;
1969 }
1970 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1971 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1972 {
1973 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1974 if (RequiredSize)
1975 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1976 return FALSE;
1977 }
1978 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1979 if (RequiredSize)
1980 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1981 return TRUE;
1982 }
1983
1984 /***********************************************************************
1985 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1986 */
1987 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1988 HINF InfHandle,
1989 PCSTR InfSectionName,
1990 PSTR InfSectionWithExt,
1991 DWORD InfSectionWithExtSize,
1992 PDWORD RequiredSize,
1993 PSTR *Extension)
1994 {
1995 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
1996 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
1997 Extension, NULL);
1998 }
1999
2000 /***********************************************************************
2001 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2002 */
2003 BOOL WINAPI SetupDiGetActualSectionToInstallW(
2004 HINF InfHandle,
2005 PCWSTR InfSectionName,
2006 PWSTR InfSectionWithExt,
2007 DWORD InfSectionWithExtSize,
2008 PDWORD RequiredSize,
2009 PWSTR *Extension)
2010 {
2011 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
2012 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
2013 Extension, NULL);
2014 }
2015
2016 /***********************************************************************
2017 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2018 */
2019 BOOL WINAPI
2020 SetupDiGetActualSectionToInstallExA(
2021 IN HINF InfHandle,
2022 IN PCSTR InfSectionName,
2023 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
2024 OUT PSTR InfSectionWithExt OPTIONAL,
2025 IN DWORD InfSectionWithExtSize,
2026 OUT PDWORD RequiredSize OPTIONAL,
2027 OUT PSTR* Extension OPTIONAL,
2028 IN PVOID Reserved)
2029 {
2030 LPWSTR InfSectionNameW = NULL;
2031 LPWSTR InfSectionWithExtW = NULL;
2032 PWSTR ExtensionW;
2033 BOOL bResult = FALSE;
2034
2035 TRACE("\n");
2036
2037 if (InfSectionName)
2038 {
2039 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2040 if (InfSectionNameW == NULL)
2041 goto cleanup;
2042 }
2043 if (InfSectionWithExt)
2044 {
2045 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
2046 if (InfSectionWithExtW == NULL)
2047 goto cleanup;
2048 }
2049
2050 bResult = SetupDiGetActualSectionToInstallExW(
2051 InfHandle, InfSectionNameW, AlternatePlatformInfo,
2052 InfSectionWithExt ? InfSectionWithExtW : NULL,
2053 InfSectionWithExtSize,
2054 RequiredSize,
2055 Extension ? &ExtensionW : NULL,
2056 Reserved);
2057
2058 if (bResult && InfSectionWithExt)
2059 {
2060 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
2061 InfSectionWithExtSize, NULL, NULL) != 0;
2062 }
2063 if (bResult && Extension)
2064 {
2065 if (ExtensionW == NULL)
2066 *Extension = NULL;
2067 else
2068 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
2069 }
2070
2071 cleanup:
2072 MyFree(InfSectionNameW);
2073 MyFree(InfSectionWithExtW);
2074
2075 return bResult;
2076 }
2077
2078 /***********************************************************************
2079 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2080 */
2081 BOOL WINAPI SetupDiGetClassDescriptionA(
2082 const GUID* ClassGuid,
2083 PSTR ClassDescription,
2084 DWORD ClassDescriptionSize,
2085 PDWORD RequiredSize)
2086 {
2087 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
2088 ClassDescriptionSize,
2089 RequiredSize, NULL, NULL);
2090 }
2091
2092 /***********************************************************************
2093 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2094 */
2095 BOOL WINAPI SetupDiGetClassDescriptionW(
2096 const GUID* ClassGuid,
2097 PWSTR ClassDescription,
2098 DWORD ClassDescriptionSize,
2099 PDWORD RequiredSize)
2100 {
2101 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
2102 ClassDescriptionSize,
2103 RequiredSize, NULL, NULL);
2104 }
2105
2106 /***********************************************************************
2107 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2108 */
2109 BOOL WINAPI SetupDiGetClassDescriptionExA(
2110 const GUID* ClassGuid,
2111 PSTR ClassDescription,
2112 DWORD ClassDescriptionSize,
2113 PDWORD RequiredSize,
2114 PCSTR MachineName,
2115 PVOID Reserved)
2116 {
2117 PWCHAR ClassDescriptionW = NULL;
2118 LPWSTR MachineNameW = NULL;
2119 BOOL ret = FALSE;
2120
2121 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2122 ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved);
2123
2124 if (ClassDescriptionSize > 0)
2125 {
2126 ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR));
2127 if (!ClassDescriptionW)
2128 {
2129 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2130 goto cleanup;
2131 }
2132 }
2133
2134 if (MachineName)
2135 {
2136 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2137 if (!MachineNameW)
2138 {
2139 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2140 goto cleanup;
2141 }
2142 }
2143
2144 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW,
2145 ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved);
2146 if (ret)
2147 {
2148 DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
2149 ClassDescriptionSize, NULL, NULL);
2150 if (len == 0 || len > ClassDescriptionSize)
2151 {
2152 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2153 ret = FALSE;
2154 }
2155 }
2156
2157 cleanup:
2158 MyFree(ClassDescriptionW);
2159 MyFree(MachineNameW);
2160 return ret;
2161 }
2162
2163 /***********************************************************************
2164 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2165 */
2166 BOOL WINAPI SetupDiGetClassDescriptionExW(
2167 const GUID* ClassGuid,
2168 PWSTR ClassDescription,
2169 DWORD ClassDescriptionSize,
2170 PDWORD RequiredSize,
2171 PCWSTR MachineName,
2172 PVOID Reserved)
2173 {
2174 HKEY hKey;
2175 DWORD dwLength;
2176 DWORD dwRegType;
2177 LONG rc;
2178
2179 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2180 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
2181
2182 if (!ClassGuid)
2183 {
2184 SetLastError(ERROR_INVALID_PARAMETER);
2185 return FALSE;
2186 }
2187 else if (!ClassDescription && ClassDescriptionSize > 0)
2188 {
2189 SetLastError(ERROR_INVALID_PARAMETER);
2190 return FALSE;
2191 }
2192
2193 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
2194 KEY_QUERY_VALUE,
2195 DIOCR_INSTALLER,
2196 MachineName,
2197 Reserved);
2198 if (hKey == INVALID_HANDLE_VALUE)
2199 {
2200 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
2201 return FALSE;
2202 }
2203
2204 if (ClassDescriptionSize < sizeof(UNICODE_NULL) || !ClassDescription)
2205 dwLength = 0;
2206 else
2207 dwLength = ClassDescriptionSize * sizeof(WCHAR) - sizeof(UNICODE_NULL);
2208
2209 rc = RegQueryValueExW(hKey,
2210 NULL,
2211 NULL,
2212 &dwRegType,
2213 (LPBYTE)ClassDescription,
2214 &dwLength);
2215 RegCloseKey(hKey);
2216 if (rc != ERROR_MORE_DATA && rc != ERROR_SUCCESS)
2217 {
2218 SetLastError(rc);
2219 return FALSE;
2220 }
2221 else if (dwRegType != REG_SZ)
2222 {
2223 SetLastError(ERROR_GEN_FAILURE);
2224 return FALSE;
2225 }
2226
2227 if (RequiredSize)
2228 *RequiredSize = dwLength / sizeof(WCHAR) + 1;
2229
2230 if (ClassDescriptionSize * sizeof(WCHAR) >= dwLength + sizeof(UNICODE_NULL))
2231 {
2232 if (ClassDescriptionSize > sizeof(UNICODE_NULL))
2233 ClassDescription[ClassDescriptionSize / sizeof(WCHAR)] = UNICODE_NULL;
2234 return TRUE;
2235 }
2236 else
2237 {
2238 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2239 return FALSE;
2240 }
2241 }
2242
2243 /***********************************************************************
2244 * SetupDiGetClassDevsA (SETUPAPI.@)
2245 */
2246 HDEVINFO WINAPI SetupDiGetClassDevsA(
2247 CONST GUID *class,
2248 LPCSTR enumstr,
2249 HWND parent,
2250 DWORD flags)
2251 {
2252 return SetupDiGetClassDevsExA(class, enumstr, parent,
2253 flags, NULL, NULL, NULL);
2254 }
2255
2256 /***********************************************************************
2257 * SetupDiGetClassDevsExA (SETUPAPI.@)
2258 */
2259 HDEVINFO WINAPI SetupDiGetClassDevsExA(
2260 const GUID *class,
2261 PCSTR enumstr,
2262 HWND parent,
2263 DWORD flags,
2264 HDEVINFO deviceset,
2265 PCSTR machine,
2266 PVOID reserved)
2267 {
2268 HDEVINFO ret;
2269 LPWSTR enumstrW = NULL, machineW = NULL;
2270
2271 if (enumstr)
2272 {
2273 enumstrW = MultiByteToUnicode(enumstr, CP_ACP);
2274 if (!enumstrW)
2275 {
2276 ret = INVALID_HANDLE_VALUE;
2277 goto end;
2278 }
2279 }
2280 if (machine)
2281 {
2282 machineW = MultiByteToUnicode(machine, CP_ACP);
2283 if (!machineW)
2284 {
2285 MyFree(enumstrW);
2286 ret = INVALID_HANDLE_VALUE;
2287 goto end;
2288 }
2289 }
2290 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
2291 machineW, reserved);
2292 MyFree(enumstrW);
2293 MyFree(machineW);
2294
2295 end:
2296 return ret;
2297 }
2298
2299 /***********************************************************************
2300 * SetupDiGetClassDevsW (SETUPAPI.@)
2301 */
2302 HDEVINFO WINAPI SetupDiGetClassDevsW(
2303 CONST GUID *class,
2304 LPCWSTR enumstr,
2305 HWND parent,
2306 DWORD flags)
2307 {
2308 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2309 NULL);
2310 }
2311
2312 /***********************************************************************
2313 * SetupDiGetClassDevsExW (SETUPAPI.@)
2314 */
2315 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2316 CONST GUID *class,
2317 PCWSTR enumstr,
2318 HWND parent,
2319 DWORD flags,
2320 HDEVINFO deviceset,
2321 PCWSTR machine,
2322 PVOID reserved)
2323 {
2324 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2325 struct DeviceInfoSet *list;
2326 CONST GUID *pClassGuid;
2327 LONG rc;
2328 HDEVINFO set = INVALID_HANDLE_VALUE;
2329
2330 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2331 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2332 reserved);
2333
2334 if (!(flags & DIGCF_ALLCLASSES) && !class)
2335 {
2336 SetLastError(ERROR_INVALID_PARAMETER);
2337 return NULL;
2338 }
2339
2340 /* Create the deviceset if not set */
2341 if (deviceset)
2342 {
2343 list = (struct DeviceInfoSet *)deviceset;
2344 if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2345 {
2346 SetLastError(ERROR_INVALID_HANDLE);
2347 goto cleanup;
2348 }
2349 hDeviceInfo = deviceset;
2350 }
2351 else
2352 {
2353 hDeviceInfo = SetupDiCreateDeviceInfoListExW(
2354 flags & (DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES) ? NULL : class,
2355 NULL, machine, NULL);
2356 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2357 goto cleanup;
2358 list = (struct DeviceInfoSet *)hDeviceInfo;
2359 }
2360
2361 if (flags & DIGCF_PROFILE)
2362 FIXME(": flag DIGCF_PROFILE ignored\n");
2363
2364 if (flags & DIGCF_DEVICEINTERFACE)
2365 {
2366 if (!class)
2367 {
2368 SetLastError(ERROR_INVALID_PARAMETER);
2369 goto cleanup;
2370 }
2371 rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT);
2372 }
2373 else
2374 {
2375 /* Determine which class(es) should be included in the deviceset */
2376 if (flags & DIGCF_ALLCLASSES)
2377 {
2378 /* The caller wants all classes. Check if
2379 * the deviceset limits us to one class */
2380 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2381 pClassGuid = NULL;
2382 else
2383 pClassGuid = &list->ClassGuid;
2384 }
2385 else if (class)
2386 {
2387 /* The caller wants one class. Check if it matches deviceset class */
2388 if (IsEqualIID(&list->ClassGuid, class)
2389 || IsEqualIID(&list->ClassGuid, &GUID_NULL))
2390 {
2391 pClassGuid = class;
2392 }
2393 else
2394 {
2395 SetLastError(ERROR_INVALID_PARAMETER);
2396 goto cleanup;
2397 }
2398 }
2399 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL))
2400 {
2401 /* No class specified. Try to use the one of the deviceset */
2402 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2403 pClassGuid = &list->ClassGuid;
2404 else
2405 {
2406 SetLastError(ERROR_INVALID_PARAMETER);
2407 goto cleanup;
2408 }
2409 }
2410 else
2411 {
2412 SetLastError(ERROR_INVALID_PARAMETER);
2413 goto cleanup;
2414 }
2415 rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr);
2416 }
2417 if (rc != ERROR_SUCCESS)
2418 {
2419 SetLastError(rc);
2420 goto cleanup;
2421 }
2422 set = hDeviceInfo;
2423
2424 cleanup:
2425 if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set)
2426 SetupDiDestroyDeviceInfoList(hDeviceInfo);
2427 return set;
2428 }
2429
2430 /***********************************************************************
2431 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2432 */
2433 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2434 HDEVINFO DeviceInfoSet,
2435 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2436 {
2437 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2438
2439 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2440
2441 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2442 {
2443 SetLastError(ERROR_INVALID_HANDLE);
2444 return FALSE;
2445 }
2446 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2447 {
2448 SetLastError(ERROR_INVALID_HANDLE);
2449 return FALSE;
2450 }
2451 if (!DevInfoData ||
2452 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2453 {
2454 SetLastError(ERROR_INVALID_PARAMETER);
2455 return FALSE;
2456 }
2457 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2458 DevInfoData->RemoteMachineHandle = set->hMachine;
2459 if (set->MachineName)
2460 {
2461 FIXME("Stub\n");
2462 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2463 return FALSE;
2464 }
2465 else
2466 DevInfoData->RemoteMachineName[0] = 0;
2467
2468 return TRUE;
2469 }
2470
2471 /***********************************************************************
2472 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2473 */
2474 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2475 HDEVINFO DeviceInfoSet,
2476 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2477 {
2478 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2479
2480 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2481
2482 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2483 {
2484 SetLastError(ERROR_INVALID_HANDLE);
2485 return FALSE;
2486 }
2487 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2488 {
2489 SetLastError(ERROR_INVALID_HANDLE);
2490 return FALSE;
2491 }
2492 if (!DevInfoData ||
2493 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2494 {
2495 SetLastError(ERROR_INVALID_PARAMETER);
2496 return FALSE;
2497 }
2498 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2499 DevInfoData->RemoteMachineHandle = set->hMachine;
2500 if (set->MachineName)
2501 strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2);
2502 else
2503 DevInfoData->RemoteMachineName[0] = 0;
2504
2505 return TRUE;
2506 }
2507
2508 /***********************************************************************
2509 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2510 */
2511 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2512 HDEVINFO DeviceInfoSet,
2513 PSP_DEVINFO_DATA DeviceInfoData,
2514 const GUID *InterfaceClassGuid,
2515 PCSTR ReferenceString,
2516 DWORD CreationFlags,
2517 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2518 {
2519 BOOL ret;
2520 LPWSTR ReferenceStringW = NULL;
2521
2522 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2523 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2524 CreationFlags, DeviceInterfaceData);
2525
2526 if (ReferenceString)
2527 {
2528 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2529 if (ReferenceStringW == NULL) return FALSE;
2530 }
2531
2532 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2533 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2534 DeviceInterfaceData);
2535
2536 MyFree(ReferenceStringW);
2537
2538 return ret;
2539 }
2540
2541 /***********************************************************************
2542 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2543 */
2544 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2545 HDEVINFO DeviceInfoSet,
2546 PSP_DEVINFO_DATA DeviceInfoData,
2547 const GUID *InterfaceClassGuid,
2548 PCWSTR ReferenceString,
2549 DWORD CreationFlags,
2550 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2551 {
2552 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2553 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2554 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2555 CreationFlags, DeviceInterfaceData);
2556
2557 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2558 {
2559 SetLastError(ERROR_INVALID_HANDLE);
2560 return FALSE;
2561 }
2562 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2563 {
2564 SetLastError(ERROR_INVALID_HANDLE);
2565 return FALSE;
2566 }
2567 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2568 || !DeviceInfoData->Reserved)
2569 {
2570 SetLastError(ERROR_INVALID_PARAMETER);
2571 return FALSE;
2572 }
2573 if (!InterfaceClassGuid)
2574 {
2575 SetLastError(ERROR_INVALID_USER_BUFFER);
2576 return FALSE;
2577 }
2578
2579 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2580 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2581 CreationFlags, DeviceInterfaceData);
2582 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2583 return FALSE;
2584 }
2585
2586 /***********************************************************************
2587 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2588 */
2589 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2590 HDEVINFO DeviceInfoSet,
2591 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2592 DWORD Reserved,
2593 REGSAM samDesired,
2594 HINF InfHandle,
2595 PCSTR InfSectionName)
2596 {
2597 HKEY key;
2598 PWSTR InfSectionNameW = NULL;
2599
2600 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2601 samDesired, InfHandle, InfSectionName);
2602 if (InfHandle)
2603 {
2604 if (!InfSectionName)
2605 {
2606 SetLastError(ERROR_INVALID_PARAMETER);
2607 return INVALID_HANDLE_VALUE;
2608 }
2609 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2610 if (!InfSectionNameW)
2611 return INVALID_HANDLE_VALUE;
2612 }
2613 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2614 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2615 InfSectionNameW);
2616 MyFree(InfSectionNameW);
2617 return key;
2618 }
2619
2620 /***********************************************************************
2621 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2622 */
2623 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2624 HDEVINFO DeviceInfoSet,
2625 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2626 DWORD Reserved,
2627 REGSAM samDesired,
2628 HINF InfHandle,
2629 PCWSTR InfSectionName)
2630 {
2631 HKEY hKey, hDevKey;
2632 LPWSTR SymbolicLink;
2633 DWORD Length, Index;
2634 LONG rc;
2635 WCHAR bracedGuidString[39];
2636 struct DeviceInterface *DevItf;
2637 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2638
2639 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2640 samDesired, InfHandle, InfSectionName);
2641
2642 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2643 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2644 {
2645 SetLastError(ERROR_INVALID_HANDLE);
2646 return INVALID_HANDLE_VALUE;
2647 }
2648 if (!DeviceInterfaceData ||
2649 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2650 !DeviceInterfaceData->Reserved)
2651 {
2652 SetLastError(ERROR_INVALID_PARAMETER);
2653 return INVALID_HANDLE_VALUE;
2654 }
2655 if (InfHandle && !InfSectionName)
2656 {
2657 SetLastError(ERROR_INVALID_PARAMETER);
2658 return INVALID_HANDLE_VALUE;
2659 }
2660
2661 hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL);
2662 if (hKey == INVALID_HANDLE_VALUE)
2663 {
2664 hKey = SetupDiOpenClassRegKeyExW(NULL, samDesired, DIOCR_INTERFACE, NULL, NULL);
2665 if (hKey == INVALID_HANDLE_VALUE)
2666 {
2667 SetLastError(ERROR_INVALID_PARAMETER);
2668 return INVALID_HANDLE_VALUE;
2669 }
2670 SETUPDI_GuidToString(&DeviceInterfaceData->InterfaceClassGuid, bracedGuidString);
2671
2672 if (RegCreateKeyExW(hKey, bracedGuidString, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL) != ERROR_SUCCESS)
2673 {
2674 SetLastError(ERROR_INVALID_PARAMETER);
2675 return INVALID_HANDLE_VALUE;
2676 }
2677 RegCloseKey(hKey);
2678 hKey = hDevKey;
2679 }
2680
2681 DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2682
2683 Length = (wcslen(DevItf->SymbolicLink)+1) * sizeof(WCHAR);
2684 SymbolicLink = HeapAlloc(GetProcessHeap(), 0, Length);
2685 if (!SymbolicLink)
2686 {
2687 RegCloseKey(hKey);
2688 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2689 return INVALID_HANDLE_VALUE;
2690 }
2691
2692 wcscpy(SymbolicLink, DevItf->SymbolicLink);
2693
2694 Index = 0;
2695 while(SymbolicLink[Index])
2696 {
2697 if (SymbolicLink[Index] == L'\\')
2698 {
2699 SymbolicLink[Index] = L'#';
2700 }
2701 Index++;
2702 }
2703
2704 rc = RegCreateKeyExW(hKey, SymbolicLink, 0, NULL, 0, samDesired, NULL, &hDevKey, NULL);
2705
2706 RegCloseKey(hKey);
2707 HeapFree(GetProcessHeap(), 0, SymbolicLink);
2708
2709 if (rc == ERROR_SUCCESS)
2710 {
2711 if (InfHandle && InfSectionName)
2712 {
2713 if (!SetupInstallFromInfSection(NULL /*FIXME */,
2714 InfHandle,
2715 InfSectionName,
2716 SPINST_INIFILES | SPINST_REGISTRY | SPINST_INI2REG | SPINST_FILES | SPINST_BITREG | SPINST_REGSVR | SPINST_UNREGSVR | SPINST_PROFILEITEMS | SPINST_COPYINF,
2717 hDevKey,
2718 NULL,
2719 0,
2720 set->SelectedDevice->InstallParams.InstallMsgHandler,
2721 set->SelectedDevice->InstallParams.InstallMsgHandlerContext,
2722 INVALID_HANDLE_VALUE,
2723 NULL))
2724 {
2725 RegCloseKey(hDevKey);
2726 return INVALID_HANDLE_VALUE;
2727 }
2728 }
2729 }
2730
2731 SetLastError(rc);
2732 return hDevKey;
2733 }
2734
2735 /***********************************************************************
2736 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2737 */
2738 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
2739 HDEVINFO DeviceInfoSet,
2740 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2741 DWORD Reserved)
2742 {
2743 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2744 BOOL ret = FALSE;
2745
2746 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2747
2748 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2749 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2750 {
2751 SetLastError(ERROR_INVALID_HANDLE);
2752 return FALSE;
2753 }
2754 if (!DeviceInterfaceData ||
2755 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2756 !DeviceInterfaceData->Reserved)
2757 {
2758 SetLastError(ERROR_INVALID_PARAMETER);
2759 return FALSE;
2760 }
2761
2762 FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2763 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2764 return ret;
2765 }
2766
2767 /***********************************************************************
2768 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2769 *
2770 * PARAMS
2771 * DeviceInfoSet [I] Set of devices from which to enumerate
2772 * interfaces
2773 * DeviceInfoData [I] (Optional) If specified, a specific device
2774 * instance from which to enumerate interfaces.
2775 * If it isn't specified, all interfaces for all
2776 * devices in the set are enumerated.
2777 * InterfaceClassGuid [I] The interface class to enumerate.
2778 * MemberIndex [I] An index of the interface instance to enumerate.
2779 * A caller should start with MemberIndex set to 0,
2780 * and continue until the function fails with
2781 * ERROR_NO_MORE_ITEMS.
2782 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2783 * member must be set to
2784 * sizeof(SP_DEVICE_INTERFACE_DATA).
2785 *
2786 * RETURNS
2787 * Success: non-zero value.
2788 * Failure: FALSE. Call GetLastError() for more info.
2789 */
2790 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2791 HDEVINFO DeviceInfoSet,
2792 PSP_DEVINFO_DATA DeviceInfoData,
2793 CONST GUID * InterfaceClassGuid,
2794 DWORD MemberIndex,
2795 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2796 {
2797 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2798 BOOL ret = FALSE;
2799
2800 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2801 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2802
2803 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2804 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2805 {
2806 SetLastError(ERROR_INVALID_HANDLE);
2807 return FALSE;
2808 }
2809 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2810 !DeviceInfoData->Reserved))
2811 {
2812 SetLastError(ERROR_INVALID_PARAMETER);
2813 return FALSE;
2814 }
2815 if (!DeviceInterfaceData ||
2816 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2817 {
2818 SetLastError(ERROR_INVALID_PARAMETER);
2819 return FALSE;
2820 }
2821 if (DeviceInfoData)
2822 {
2823 struct DeviceInfo *devInfo =
2824 (struct DeviceInfo *)DeviceInfoData->Reserved;
2825 BOOL found = FALSE;
2826 PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2827 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2828 {
2829 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2830 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2831 {
2832 InterfaceListEntry = InterfaceListEntry->Flink;
2833 continue;
2834 }
2835 if (MemberIndex-- == 0)
2836 {
2837 /* return this item */
2838 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2839 &DevItf->InterfaceClassGuid,
2840 sizeof(GUID));
2841 DeviceInterfaceData->Flags = DevItf->Flags;
2842 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2843 found = TRUE;
2844 ret = TRUE;
2845 }
2846 InterfaceListEntry = InterfaceListEntry->Flink;
2847 }
2848 if (!found)
2849 SetLastError(ERROR_NO_MORE_ITEMS);
2850 }
2851 else
2852 {
2853 BOOL found = FALSE;
2854 PLIST_ENTRY ItemList = set->ListHead.Flink;
2855 while (ItemList != &set->ListHead && !found)
2856 {
2857 PLIST_ENTRY InterfaceListEntry;
2858 struct DeviceInfo *devInfo =
2859 CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
2860 InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2861 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2862 {
2863 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2864 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2865 {
2866 InterfaceListEntry = InterfaceListEntry->Flink;
2867 continue;
2868 }
2869 if (MemberIndex-- == 0)
2870 {
2871 /* return this item */
2872 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2873 &DevItf->InterfaceClassGuid,
2874 sizeof(GUID));
2875 DeviceInterfaceData->Flags = DevItf->Flags;
2876 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2877 found = TRUE;
2878 ret = TRUE;
2879 }
2880 InterfaceListEntry = InterfaceListEntry->Flink;
2881 }
2882 ItemList = ItemList->Flink;
2883
2884 }
2885 if (!found)
2886 SetLastError(ERROR_NO_MORE_ITEMS);
2887 }
2888 return ret;
2889 }
2890
2891 /***********************************************************************
2892 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2893 *
2894 * Destroy a DeviceInfoList and free all used memory of the list.
2895 *
2896 * PARAMS
2897 * devinfo [I] DeviceInfoList pointer to list to destroy
2898 *
2899 * RETURNS
2900 * Success: non zero value.
2901 * Failure: zero value.
2902 */
2903 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2904 {
2905 BOOL ret = FALSE;
2906
2907 TRACE("%p\n", devinfo);
2908 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
2909 {
2910 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2911
2912 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2913 {
2914 ret = DestroyDeviceInfoSet(list);
2915 }
2916 }
2917
2918 if (ret == FALSE)
2919 SetLastError(ERROR_INVALID_HANDLE);
2920
2921 return ret;
2922 }
2923
2924 /***********************************************************************
2925 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2926 */
2927 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2928 HDEVINFO DeviceInfoSet,
2929 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2930 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2931 DWORD DeviceInterfaceDetailDataSize,
2932 PDWORD RequiredSize,
2933 PSP_DEVINFO_DATA DeviceInfoData)
2934 {
2935 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2936 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
2937 DWORD sizeW = 0, bytesNeeded;
2938 BOOL ret = FALSE;
2939
2940 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2941 DeviceInterfaceData, DeviceInterfaceDetailData,
2942 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2943
2944 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2945 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2946 {
2947 SetLastError(ERROR_INVALID_HANDLE);
2948 return FALSE;
2949 }
2950 if (!DeviceInterfaceData ||
2951 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2952 !DeviceInterfaceData->Reserved)
2953 {
2954 SetLastError(ERROR_INVALID_PARAMETER);
2955 return FALSE;
2956 }
2957 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2958 FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1 ||
2959 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2960 {
2961 SetLastError(ERROR_INVALID_USER_BUFFER);
2962 return FALSE;
2963 }
2964 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2965 {
2966 SetLastError(ERROR_INVALID_USER_BUFFER);
2967 return FALSE;
2968 }
2969
2970
2971 if (DeviceInterfaceDetailData != NULL)
2972 {
2973 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2974 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2975 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW);
2976 if (!DeviceInterfaceDetailDataW)
2977 {
2978 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2979 }
2980 }
2981 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2982 {
2983 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2984 ret = SetupDiGetDeviceInterfaceDetailW(
2985 DeviceInfoSet,
2986 DeviceInterfaceData,
2987 DeviceInterfaceDetailDataW,
2988 sizeW,
2989 &sizeW,
2990 DeviceInfoData);
2991 bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
2992 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
2993 if (RequiredSize)
2994 *RequiredSize = bytesNeeded;
2995 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= bytesNeeded)
2996 {
2997 if (!WideCharToMultiByte(
2998 CP_ACP, 0,
2999 DeviceInterfaceDetailDataW->DevicePath, -1,
3000 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
3001 NULL, NULL))
3002 {
3003 ret = FALSE;
3004 }
3005 }
3006 }
3007 MyFree(DeviceInterfaceDetailDataW);
3008
3009 return ret;
3010 }
3011
3012 /***********************************************************************
3013 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3014 */
3015 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
3016 HDEVINFO DeviceInfoSet,
3017 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
3018 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
3019 DWORD DeviceInterfaceDetailDataSize,
3020 PDWORD RequiredSize,
3021 PSP_DEVINFO_DATA DeviceInfoData)
3022 {
3023 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3024 BOOL ret = FALSE;
3025
3026 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
3027 DeviceInterfaceData, DeviceInterfaceDetailData,
3028 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
3029
3030 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
3031 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3032 {
3033 SetLastError(ERROR_INVALID_HANDLE);
3034 return FALSE;
3035 }
3036 if (!DeviceInterfaceData ||
3037 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
3038 !DeviceInterfaceData->Reserved)
3039 {
3040 SetLastError(ERROR_INVALID_PARAMETER);
3041 return FALSE;
3042 }
3043 if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
3044 {
3045 SetLastError(ERROR_INVALID_USER_BUFFER);
3046 return FALSE;
3047 }
3048 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
3049 {
3050 SetLastError(ERROR_INVALID_USER_BUFFER);
3051 return FALSE;
3052 }
3053 if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3054 {
3055 SetLastError(ERROR_INVALID_PARAMETER);
3056 return FALSE;
3057 }
3058 if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR))
3059 {
3060 SetLastError(ERROR_INVALID_PARAMETER);
3061 return FALSE;
3062 }
3063 else
3064 {
3065 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
3066 LPCWSTR devName = deviceInterface->SymbolicLink;
3067 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
3068 (lstrlenW(devName) + 1) * sizeof(WCHAR);
3069
3070 if (sizeRequired > DeviceInterfaceDetailDataSize)
3071 {
3072 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3073 if (RequiredSize)
3074 *RequiredSize = sizeRequired;
3075 }
3076 else
3077 {
3078 strcpyW(DeviceInterfaceDetailData->DevicePath, devName);
3079 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
3080 if (DeviceInfoData)
3081 {
3082 memcpy(&DeviceInfoData->ClassGuid,
3083 &deviceInterface->DeviceInfo->ClassGuid,
3084 sizeof(GUID));
3085 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
3086 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
3087 }
3088 ret = TRUE;
3089 }
3090 }
3091 return ret;
3092 }
3093
3094 struct PropertyMapEntry
3095 {
3096 DWORD regType;
3097 LPCSTR nameA;
3098 LPCWSTR nameW;
3099 };
3100
3101 static struct PropertyMapEntry PropertyMap[] = {
3102 { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC },
3103 { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID },
3104 { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS },
3105 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
3106 { REG_SZ, "Service", REGSTR_VAL_SERVICE },
3107 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
3108 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
3109 { REG_SZ, "Class", REGSTR_VAL_CLASS },
3110 { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID },
3111 { REG_SZ, "Driver", REGSTR_VAL_DRIVER },
3112 { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS },
3113 { REG_SZ, "Mfg", REGSTR_VAL_MFG },
3114 { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME },
3115 { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION },
3116 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3117 { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES },
3118 { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER },
3119 { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS },
3120 { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS },
3121 { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */
3122 { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */
3123 { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */
3124 { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */
3125 { REG_BINARY, "Security", REGSTR_SECURITY },
3126 { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */
3127 { 0, NULL, NULL }, /* SPDRP_DEVTYPE */
3128 { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */
3129 { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */
3130 { 0, NULL, NULL }, /* SPDRP_ADDRESS */
3131 { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT },
3132 { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */
3133 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */
3134 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3135 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3136 { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */
3137 };
3138
3139 /***********************************************************************
3140 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3141 */
3142 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
3143 HDEVINFO DeviceInfoSet,
3144 PSP_DEVINFO_DATA DeviceInfoData,
3145 DWORD Property,
3146 PDWORD PropertyRegDataType,
3147 PBYTE PropertyBuffer,
3148 DWORD PropertyBufferSize,
3149 PDWORD RequiredSize)
3150 {
3151 BOOL ret;
3152 BOOL bIsStringProperty;
3153 DWORD RegType;
3154 DWORD RequiredSizeA, RequiredSizeW;
3155 DWORD PropertyBufferSizeW = 0;
3156 PBYTE PropertyBufferW = NULL;
3157
3158 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3159 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3160 RequiredSize);
3161
3162 if (PropertyBufferSize != 0)
3163 {
3164 PropertyBufferSizeW = PropertyBufferSize * 2;
3165 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
3166 if (!PropertyBufferW)
3167 {
3168 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3169 return FALSE;
3170 }
3171 }
3172
3173 ret = SetupDiGetDeviceRegistryPropertyW(
3174 DeviceInfoSet,
3175 DeviceInfoData,
3176 Property,
3177 &RegType,
3178 PropertyBufferW,
3179 PropertyBufferSizeW,
3180 &RequiredSizeW);
3181
3182 if (ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3183 {
3184 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
3185
3186 if (bIsStringProperty)
3187 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
3188 else
3189 RequiredSizeA = RequiredSizeW;
3190 if (RequiredSize)
3191 *RequiredSize = RequiredSizeA;
3192 if (PropertyRegDataType)
3193 *PropertyRegDataType = RegType;
3194 }
3195