Merge from amd64-branch:
[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
1413 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet, DeviceInfoData, Scope,
1414 HwProfile, KeyType, InfHandle, debugstr_w(InfSectionName));
1415
1416 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1417 {
1418 SetLastError(ERROR_INVALID_HANDLE);
1419 return INVALID_HANDLE_VALUE;
1420 }
1421 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1422 {
1423 SetLastError(ERROR_INVALID_HANDLE);
1424 return INVALID_HANDLE_VALUE;
1425 }
1426 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1427 || !DeviceInfoData->Reserved)
1428 {
1429 SetLastError(ERROR_INVALID_PARAMETER);
1430 return INVALID_HANDLE_VALUE;
1431 }
1432 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
1433 {
1434 SetLastError(ERROR_INVALID_FLAGS);
1435 return INVALID_HANDLE_VALUE;
1436 }
1437 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
1438 {
1439 SetLastError(ERROR_INVALID_FLAGS);
1440 return INVALID_HANDLE_VALUE;
1441 }
1442 if (InfHandle && !InfSectionName)
1443 {
1444 SetLastError(ERROR_INVALID_PARAMETER);
1445 return INVALID_HANDLE_VALUE;
1446 }
1447 if (!InfHandle && InfSectionName)
1448 {
1449 SetLastError(ERROR_INVALID_PARAMETER);
1450 return INVALID_HANDLE_VALUE;
1451 }
1452
1453 LPWSTR lpGuidString = NULL;
1454 LPWSTR DriverKey = NULL; /* {GUID}\Index */
1455 LPWSTR pDeviceInstance; /* Points into DriverKey, on the Index field */
1456 DWORD Index; /* Index used in the DriverKey name */
1457 DWORD rc;
1458 HKEY hHWProfileKey = INVALID_HANDLE_VALUE;
1459 HKEY hEnumKey = NULL;
1460 HKEY hClassKey = NULL;
1461 HKEY hDeviceKey = INVALID_HANDLE_VALUE;
1462 HKEY hKey = NULL;
1463 HKEY RootKey;
1464
1465 if (Scope == DICS_FLAG_GLOBAL)
1466 RootKey = set->HKLM;
1467 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1468 {
1469 hHWProfileKey = OpenHardwareProfileKey(set->HKLM, HwProfile, KEY_CREATE_SUB_KEY);
1470 if (hHWProfileKey == INVALID_HANDLE_VALUE)
1471 goto cleanup;
1472 RootKey = hHWProfileKey;
1473 }
1474
1475 if (KeyType == DIREG_DEV)
1476 {
1477 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1478
1479 rc = RegCreateKeyExW(
1480 RootKey,
1481 REGSTR_PATH_SYSTEMENUM,
1482 0,
1483 NULL,
1484 REG_OPTION_NON_VOLATILE,
1485 KEY_CREATE_SUB_KEY,
1486 NULL,
1487 &hEnumKey,
1488 NULL);
1489 if (rc != ERROR_SUCCESS)
1490 {
1491 SetLastError(rc);
1492 goto cleanup;
1493 }
1494 rc = RegCreateKeyExW(
1495 hEnumKey,
1496 deviceInfo->instanceId,
1497 0,
1498 NULL,
1499 REG_OPTION_NON_VOLATILE,
1500 #if _WIN32_WINNT >= 0x502
1501 KEY_READ | KEY_WRITE,
1502 #else
1503 KEY_ALL_ACCESS,
1504 #endif
1505 NULL,
1506 &hKey,
1507 NULL);
1508 if (rc != ERROR_SUCCESS)
1509 {
1510 SetLastError(rc);
1511 goto cleanup;
1512 }
1513 }
1514 else /* KeyType == DIREG_DRV */
1515 {
1516 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) != RPC_S_OK)
1517 goto cleanup;
1518 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1519 DriverKey = HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString) + 7) * sizeof(WCHAR) + sizeof(UNICODE_NULL));
1520 if (!DriverKey)
1521 {
1522 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1523 goto cleanup;
1524 }
1525 DriverKey[0] = '{';
1526 strcpyW(&DriverKey[1], lpGuidString);
1527 pDeviceInstance = &DriverKey[strlenW(DriverKey)];
1528 *pDeviceInstance++ = '}';
1529 *pDeviceInstance++ = '\\';
1530 rc = RegOpenKeyExW(RootKey,
1531 REGSTR_PATH_CLASS_NT,
1532 0,
1533 KEY_CREATE_SUB_KEY,
1534 &hClassKey);
1535 if (rc != ERROR_SUCCESS)
1536 {
1537 SetLastError(rc);
1538 goto cleanup;
1539 }
1540
1541 /* Try all values for Index between 0 and 9999 */
1542 Index = 0;
1543 while (Index <= 9999)
1544 {
1545 DWORD Disposition;
1546 sprintfW(pDeviceInstance, InstanceKeyFormat, Index);
1547 rc = RegCreateKeyExW(hClassKey,
1548 DriverKey,
1549 0,
1550 NULL,
1551 REG_OPTION_NON_VOLATILE,
1552 #if _WIN32_WINNT >= 0x502
1553 KEY_READ | KEY_WRITE,
1554 #else
1555 KEY_ALL_ACCESS,
1556 #endif
1557 NULL,
1558 &hKey,
1559 &Disposition);
1560 if (rc != ERROR_SUCCESS)
1561 {
1562 SetLastError(rc);
1563 goto cleanup;
1564 }
1565 if (Disposition == REG_CREATED_NEW_KEY)
1566 break;
1567 RegCloseKey(hKey);
1568 hKey = NULL;
1569 Index++;
1570 }
1571 if (Index > 9999)
1572 {
1573 /* Unable to create more than 9999 devices within the same class */
1574 SetLastError(ERROR_GEN_FAILURE);
1575 goto cleanup;
1576 }
1577
1578 /* Open device key, to write Driver value */
1579 hDeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, Scope, HwProfile, DIREG_DEV, KEY_SET_VALUE);
1580 if (hDeviceKey == INVALID_HANDLE_VALUE)
1581 goto cleanup;
1582 rc = RegSetValueExW(hDeviceKey, REGSTR_VAL_DRIVER, 0, REG_SZ, (const BYTE *)DriverKey, (strlenW(DriverKey) + 1) * sizeof(WCHAR));
1583 if (rc != ERROR_SUCCESS)
1584 {
1585 SetLastError(rc);
1586 goto cleanup;
1587 }
1588 }
1589
1590 /* Do installation of the specified section */
1591 if (InfHandle)
1592 {
1593 FIXME("Need to install section %s in file %p\n",
1594 debugstr_w(InfSectionName), InfHandle);
1595 }
1596 key = hKey;
1597
1598 cleanup:
1599 if (lpGuidString)
1600 RpcStringFreeW(&lpGuidString);
1601 HeapFree(GetProcessHeap(), 0, DriverKey);
1602 if (hHWProfileKey != INVALID_HANDLE_VALUE)
1603 RegCloseKey(hHWProfileKey);
1604 if (hEnumKey != NULL)
1605 RegCloseKey(hEnumKey);
1606 if (hClassKey != NULL)
1607 RegCloseKey(hClassKey);
1608 if (hDeviceKey != INVALID_HANDLE_VALUE)
1609 RegCloseKey(hDeviceKey);
1610 if (hKey != NULL && hKey != key)
1611 RegCloseKey(hKey);
1612
1613 TRACE("Returning 0x%p\n", key);
1614 return key;
1615 }
1616
1617 /***********************************************************************
1618 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1619 */
1620 BOOL WINAPI SetupDiCreateDeviceInfoA(
1621 HDEVINFO DeviceInfoSet,
1622 PCSTR DeviceName,
1623 CONST GUID *ClassGuid,
1624 PCSTR DeviceDescription,
1625 HWND hwndParent,
1626 DWORD CreationFlags,
1627 PSP_DEVINFO_DATA DeviceInfoData)
1628 {
1629 BOOL ret;
1630 LPWSTR DeviceNameW = NULL;
1631 LPWSTR DeviceDescriptionW = NULL;
1632
1633 TRACE("\n");
1634
1635 if (DeviceName)
1636 {
1637 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
1638 if (DeviceNameW == NULL) return FALSE;
1639 }
1640 if (DeviceDescription)
1641 {
1642 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
1643 if (DeviceDescriptionW == NULL)
1644 {
1645 MyFree(DeviceNameW);
1646 return FALSE;
1647 }
1648 }
1649
1650 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
1651 hwndParent, CreationFlags, DeviceInfoData);
1652
1653 MyFree(DeviceNameW);
1654 MyFree(DeviceDescriptionW);
1655
1656 return ret;
1657 }
1658
1659 /***********************************************************************
1660 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1661 */
1662 BOOL WINAPI SetupDiCreateDeviceInfoW(
1663 HDEVINFO DeviceInfoSet,
1664 PCWSTR DeviceName,
1665 CONST GUID *ClassGuid,
1666 PCWSTR DeviceDescription,
1667 HWND hwndParent,
1668 DWORD CreationFlags,
1669 PSP_DEVINFO_DATA DeviceInfoData)
1670 {
1671 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1672 BOOL ret = FALSE;
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 SP_DEVINFO_DATA DevInfo;
1712
1713 if (CreationFlags & DICD_GENERATE_ID)
1714 {
1715 /* Generate a new unique ID for this device */
1716 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1717 FIXME("not implemented\n");
1718 }
1719 else
1720 {
1721 /* Device name is fully qualified. Try to open it */
1722 BOOL rc;
1723
1724 DevInfo.cbSize = sizeof(SP_DEVINFO_DATA);
1725 rc = SetupDiOpenDeviceInfoW(
1726 DeviceInfoSet,
1727 DeviceName,
1728 NULL, /* hwndParent */
1729 CreationFlags & DICD_INHERIT_CLASSDRVS ? DIOD_INHERIT_CLASSDRVS : 0,
1730 &DevInfo);
1731
1732 if (rc)
1733 {
1734 /* SetupDiOpenDeviceInfoW has already added
1735 * the device info to the device info set
1736 */
1737 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1738 }
1739 else if (GetLastError() == ERROR_FILE_NOT_FOUND)
1740 {
1741 struct DeviceInfo *deviceInfo;
1742
1743 if (CreateDeviceInfo(set, DeviceName, ClassGuid, &deviceInfo))
1744 {
1745 InsertTailList(&set->ListHead, &deviceInfo->ListEntry);
1746
1747 if (!DeviceInfoData)
1748 ret = TRUE;
1749 else
1750 {
1751 if (DeviceInfoData->cbSize != sizeof(PSP_DEVINFO_DATA))
1752 {
1753 SetLastError(ERROR_INVALID_USER_BUFFER);
1754 }
1755 else
1756 {
1757 memcpy(&DeviceInfoData->ClassGuid, ClassGuid, sizeof(GUID));
1758 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
1759 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
1760 ret = TRUE;
1761 }
1762 }
1763 }
1764 }
1765 }
1766
1767 TRACE("Returning %d\n", ret);
1768 return ret;
1769 }
1770
1771 /***********************************************************************
1772 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1773 */
1774 BOOL WINAPI SetupDiRegisterDeviceInfo(
1775 HDEVINFO DeviceInfoSet,
1776 PSP_DEVINFO_DATA DeviceInfoData,
1777 DWORD Flags,
1778 PSP_DETSIG_CMPPROC CompareProc,
1779 PVOID CompareContext,
1780 PSP_DEVINFO_DATA DupDeviceInfoData)
1781 {
1782 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1783
1784 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1785 CompareProc, CompareContext, DupDeviceInfoData);
1786
1787 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1788 {
1789 SetLastError(ERROR_INVALID_HANDLE);
1790 return FALSE;
1791 }
1792 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1793 {
1794 SetLastError(ERROR_INVALID_HANDLE);
1795 return FALSE;
1796 }
1797 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1798 || !DeviceInfoData->Reserved)
1799 {
1800 SetLastError(ERROR_INVALID_PARAMETER);
1801 return FALSE;
1802 }
1803 FIXME("Stub %p %p 0x%lx %p %p %p\n", DeviceInfoSet, DeviceInfoData, Flags,
1804 CompareProc, CompareContext, DupDeviceInfoData);
1805 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1806 return FALSE;
1807 }
1808
1809 /***********************************************************************
1810 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1811 */
1812 BOOL WINAPI SetupDiEnumDeviceInfo(
1813 HDEVINFO devinfo,
1814 DWORD index,
1815 PSP_DEVINFO_DATA info)
1816 {
1817 BOOL ret = FALSE;
1818
1819 TRACE("%p %d %p\n", devinfo, index, info);
1820
1821 if(info==NULL)
1822 {
1823 SetLastError(ERROR_INVALID_PARAMETER);
1824 return FALSE;
1825 }
1826 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
1827 {
1828 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1829 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1830 {
1831 if (info->cbSize != sizeof(SP_DEVINFO_DATA))
1832 SetLastError(ERROR_INVALID_USER_BUFFER);
1833 else
1834 {
1835 PLIST_ENTRY ItemList = list->ListHead.Flink;
1836 while (ItemList != &list->ListHead && index-- > 0)
1837 ItemList = ItemList->Flink;
1838 if (ItemList == &list->ListHead)
1839 SetLastError(ERROR_NO_MORE_ITEMS);
1840 else
1841 {
1842 struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
1843 memcpy(&info->ClassGuid,
1844 &DevInfo->ClassGuid,
1845 sizeof(GUID));
1846 info->DevInst = DevInfo->dnDevInst;
1847 info->Reserved = (ULONG_PTR)DevInfo;
1848 ret = TRUE;
1849 }
1850 }
1851 }
1852 else
1853 SetLastError(ERROR_INVALID_HANDLE);
1854 }
1855 else
1856 SetLastError(ERROR_INVALID_HANDLE);
1857 return ret;
1858 }
1859
1860 /***********************************************************************
1861 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1862 */
1863 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1864 HDEVINFO DeviceInfoSet,
1865 PSP_DEVINFO_DATA DeviceInfoData,
1866 PSTR DeviceInstanceId,
1867 DWORD DeviceInstanceIdSize,
1868 PDWORD RequiredSize)
1869 {
1870 BOOL ret = FALSE;
1871 DWORD size;
1872 PWSTR instanceId;
1873
1874 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1875 DeviceInstanceIdSize, RequiredSize);
1876
1877 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1878 {
1879 SetLastError(ERROR_INVALID_PARAMETER);
1880 return FALSE;
1881 }
1882
1883 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1884 DeviceInfoData,
1885 NULL,
1886 0,
1887 &size);
1888 if (!ret && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1889 return FALSE;
1890 instanceId = MyMalloc(size * sizeof(WCHAR));
1891 if (instanceId)
1892 {
1893 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1894 DeviceInfoData,
1895 instanceId,
1896 size,
1897 &size);
1898 if (ret)
1899 {
1900 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1901 DeviceInstanceId,
1902 DeviceInstanceIdSize, NULL, NULL);
1903
1904 if (!len)
1905 ret = FALSE;
1906 else
1907 {
1908 if (len > DeviceInstanceIdSize)
1909 {
1910 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1911 ret = FALSE;
1912 }
1913 if (RequiredSize)
1914 *RequiredSize = len;
1915 }
1916 }
1917 MyFree(instanceId);
1918 }
1919 else
1920 {
1921 if (RequiredSize)
1922 *RequiredSize = size;
1923 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1924 ret = FALSE;
1925 }
1926 return ret;
1927 }
1928
1929 /***********************************************************************
1930 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1931 */
1932 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1933 HDEVINFO DeviceInfoSet,
1934 PSP_DEVINFO_DATA DeviceInfoData,
1935 PWSTR DeviceInstanceId,
1936 DWORD DeviceInstanceIdSize,
1937 PDWORD RequiredSize)
1938 {
1939 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1940 struct DeviceInfo *devInfo;
1941
1942 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1943 DeviceInstanceIdSize, RequiredSize);
1944
1945 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1946 {
1947 SetLastError(ERROR_INVALID_HANDLE);
1948 return FALSE;
1949 }
1950 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1951 {
1952 SetLastError(ERROR_INVALID_HANDLE);
1953 return FALSE;
1954 }
1955 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1956 || !DeviceInfoData->Reserved)
1957 {
1958 SetLastError(ERROR_INVALID_PARAMETER);
1959 return FALSE;
1960 }
1961 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1962 if (!DeviceInstanceId && DeviceInstanceIdSize > 0)
1963 {
1964 SetLastError(ERROR_INVALID_PARAMETER);
1965 return FALSE;
1966 }
1967 if (DeviceInstanceId && DeviceInstanceIdSize == 0)
1968 {
1969 SetLastError(ERROR_INVALID_PARAMETER);
1970 return FALSE;
1971 }
1972 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1973 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1974 {
1975 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1976 if (RequiredSize)
1977 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1978 return FALSE;
1979 }
1980 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1981 if (RequiredSize)
1982 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1983 return TRUE;
1984 }
1985
1986 /***********************************************************************
1987 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1988 */
1989 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1990 HINF InfHandle,
1991 PCSTR InfSectionName,
1992 PSTR InfSectionWithExt,
1993 DWORD InfSectionWithExtSize,
1994 PDWORD RequiredSize,
1995 PSTR *Extension)
1996 {
1997 return SetupDiGetActualSectionToInstallExA(InfHandle, InfSectionName,
1998 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
1999 Extension, NULL);
2000 }
2001
2002 /***********************************************************************
2003 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2004 */
2005 BOOL WINAPI SetupDiGetActualSectionToInstallW(
2006 HINF InfHandle,
2007 PCWSTR InfSectionName,
2008 PWSTR InfSectionWithExt,
2009 DWORD InfSectionWithExtSize,
2010 PDWORD RequiredSize,
2011 PWSTR *Extension)
2012 {
2013 return SetupDiGetActualSectionToInstallExW(InfHandle, InfSectionName,
2014 NULL, InfSectionWithExt, InfSectionWithExtSize, RequiredSize,
2015 Extension, NULL);
2016 }
2017
2018 /***********************************************************************
2019 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2020 */
2021 BOOL WINAPI
2022 SetupDiGetActualSectionToInstallExA(
2023 IN HINF InfHandle,
2024 IN PCSTR InfSectionName,
2025 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL,
2026 OUT PSTR InfSectionWithExt OPTIONAL,
2027 IN DWORD InfSectionWithExtSize,
2028 OUT PDWORD RequiredSize OPTIONAL,
2029 OUT PSTR* Extension OPTIONAL,
2030 IN PVOID Reserved)
2031 {
2032 LPWSTR InfSectionNameW = NULL;
2033 LPWSTR InfSectionWithExtW = NULL;
2034 PWSTR ExtensionW;
2035 BOOL bResult = FALSE;
2036
2037 TRACE("\n");
2038
2039 if (InfSectionName)
2040 {
2041 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2042 if (InfSectionNameW == NULL)
2043 goto cleanup;
2044 }
2045 if (InfSectionWithExt)
2046 {
2047 InfSectionWithExtW = MyMalloc(InfSectionWithExtSize * sizeof(WCHAR));
2048 if (InfSectionWithExtW == NULL)
2049 goto cleanup;
2050 }
2051
2052 bResult = SetupDiGetActualSectionToInstallExW(
2053 InfHandle, InfSectionNameW, AlternatePlatformInfo,
2054 InfSectionWithExt ? InfSectionWithExtW : NULL,
2055 InfSectionWithExtSize,
2056 RequiredSize,
2057 Extension ? &ExtensionW : NULL,
2058 Reserved);
2059
2060 if (bResult && InfSectionWithExt)
2061 {
2062 bResult = WideCharToMultiByte(CP_ACP, 0, InfSectionWithExtW, -1, InfSectionWithExt,
2063 InfSectionWithExtSize, NULL, NULL) != 0;
2064 }
2065 if (bResult && Extension)
2066 {
2067 if (ExtensionW == NULL)
2068 *Extension = NULL;
2069 else
2070 *Extension = &InfSectionWithExt[ExtensionW - InfSectionWithExtW];
2071 }
2072
2073 cleanup:
2074 MyFree(InfSectionNameW);
2075 MyFree(InfSectionWithExtW);
2076
2077 return bResult;
2078 }
2079
2080 /***********************************************************************
2081 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2082 */
2083 BOOL WINAPI SetupDiGetClassDescriptionA(
2084 const GUID* ClassGuid,
2085 PSTR ClassDescription,
2086 DWORD ClassDescriptionSize,
2087 PDWORD RequiredSize)
2088 {
2089 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
2090 ClassDescriptionSize,
2091 RequiredSize, NULL, NULL);
2092 }
2093
2094 /***********************************************************************
2095 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2096 */
2097 BOOL WINAPI SetupDiGetClassDescriptionW(
2098 const GUID* ClassGuid,
2099 PWSTR ClassDescription,
2100 DWORD ClassDescriptionSize,
2101 PDWORD RequiredSize)
2102 {
2103 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
2104 ClassDescriptionSize,
2105 RequiredSize, NULL, NULL);
2106 }
2107
2108 /***********************************************************************
2109 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2110 */
2111 BOOL WINAPI SetupDiGetClassDescriptionExA(
2112 const GUID* ClassGuid,
2113 PSTR ClassDescription,
2114 DWORD ClassDescriptionSize,
2115 PDWORD RequiredSize,
2116 PCSTR MachineName,
2117 PVOID Reserved)
2118 {
2119 PWCHAR ClassDescriptionW = NULL;
2120 LPWSTR MachineNameW = NULL;
2121 BOOL ret = FALSE;
2122
2123 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2124 ClassDescriptionSize, RequiredSize, debugstr_a(MachineName), Reserved);
2125
2126 if (ClassDescriptionSize > 0)
2127 {
2128 ClassDescriptionW = MyMalloc(ClassDescriptionSize * sizeof(WCHAR));
2129 if (!ClassDescriptionW)
2130 {
2131 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2132 goto cleanup;
2133 }
2134 }
2135
2136 if (MachineName)
2137 {
2138 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2139 if (!MachineNameW)
2140 {
2141 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2142 goto cleanup;
2143 }
2144 }
2145
2146 ret = SetupDiGetClassDescriptionExW(ClassGuid, ClassDescriptionW,
2147 ClassDescriptionSize * sizeof(WCHAR), RequiredSize, MachineNameW, Reserved);
2148 if (ret)
2149 {
2150 DWORD len = (DWORD)WideCharToMultiByte(CP_ACP, 0, ClassDescriptionW, -1, ClassDescription,
2151 ClassDescriptionSize, NULL, NULL);
2152 if (len == 0 || len > ClassDescriptionSize)
2153 {
2154 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2155 ret = FALSE;
2156 }
2157 }
2158
2159 cleanup:
2160 MyFree(ClassDescriptionW);
2161 MyFree(MachineNameW);
2162 return ret;
2163 }
2164
2165 /***********************************************************************
2166 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2167 */
2168 BOOL WINAPI SetupDiGetClassDescriptionExW(
2169 const GUID* ClassGuid,
2170 PWSTR ClassDescription,
2171 DWORD ClassDescriptionSize,
2172 PDWORD RequiredSize,
2173 PCWSTR MachineName,
2174 PVOID Reserved)
2175 {
2176 HKEY hKey;
2177 DWORD dwLength;
2178 DWORD dwRegType;
2179 LONG rc;
2180
2181 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid), ClassDescription,
2182 ClassDescriptionSize, RequiredSize, debugstr_w(MachineName), Reserved);
2183
2184 if (!ClassGuid)
2185 {
2186 SetLastError(ERROR_INVALID_PARAMETER);
2187 return FALSE;
2188 }
2189 else if (!ClassDescription && ClassDescriptionSize > 0)
2190 {
2191 SetLastError(ERROR_INVALID_PARAMETER);
2192 return FALSE;
2193 }
2194
2195 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
2196 KEY_QUERY_VALUE,
2197 DIOCR_INSTALLER,
2198 MachineName,
2199 Reserved);
2200 if (hKey == INVALID_HANDLE_VALUE)
2201 {
2202 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
2203 return FALSE;
2204 }
2205
2206 if (ClassDescriptionSize < sizeof(UNICODE_NULL) || !ClassDescription)
2207 dwLength = 0;
2208 else
2209 dwLength = ClassDescriptionSize * sizeof(WCHAR) - sizeof(UNICODE_NULL);
2210
2211 rc = RegQueryValueExW(hKey,
2212 NULL,
2213 NULL,
2214 &dwRegType,
2215 (LPBYTE)ClassDescription,
2216 &dwLength);
2217 RegCloseKey(hKey);
2218 if (rc != ERROR_MORE_DATA && rc != ERROR_SUCCESS)
2219 {
2220 SetLastError(rc);
2221 return FALSE;
2222 }
2223 else if (dwRegType != REG_SZ)
2224 {
2225 SetLastError(ERROR_GEN_FAILURE);
2226 return FALSE;
2227 }
2228
2229 if (RequiredSize)
2230 *RequiredSize = dwLength / sizeof(WCHAR) + 1;
2231
2232 if (ClassDescriptionSize * sizeof(WCHAR) >= dwLength + sizeof(UNICODE_NULL))
2233 {
2234 if (ClassDescriptionSize > sizeof(UNICODE_NULL))
2235 ClassDescription[ClassDescriptionSize / sizeof(WCHAR)] = UNICODE_NULL;
2236 return TRUE;
2237 }
2238 else
2239 {
2240 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2241 return FALSE;
2242 }
2243 }
2244
2245 /***********************************************************************
2246 * SetupDiGetClassDevsA (SETUPAPI.@)
2247 */
2248 HDEVINFO WINAPI SetupDiGetClassDevsA(
2249 CONST GUID *class,
2250 LPCSTR enumstr,
2251 HWND parent,
2252 DWORD flags)
2253 {
2254 return SetupDiGetClassDevsExA(class, enumstr, parent,
2255 flags, NULL, NULL, NULL);
2256 }
2257
2258 /***********************************************************************
2259 * SetupDiGetClassDevsExA (SETUPAPI.@)
2260 */
2261 HDEVINFO WINAPI SetupDiGetClassDevsExA(
2262 const GUID *class,
2263 PCSTR enumstr,
2264 HWND parent,
2265 DWORD flags,
2266 HDEVINFO deviceset,
2267 PCSTR machine,
2268 PVOID reserved)
2269 {
2270 HDEVINFO ret;
2271 LPWSTR enumstrW = NULL, machineW = NULL;
2272
2273 if (enumstr)
2274 {
2275 enumstrW = MultiByteToUnicode(enumstr, CP_ACP);
2276 if (!enumstrW)
2277 {
2278 ret = INVALID_HANDLE_VALUE;
2279 goto end;
2280 }
2281 }
2282 if (machine)
2283 {
2284 machineW = MultiByteToUnicode(machine, CP_ACP);
2285 if (!machineW)
2286 {
2287 MyFree(enumstrW);
2288 ret = INVALID_HANDLE_VALUE;
2289 goto end;
2290 }
2291 }
2292 ret = SetupDiGetClassDevsExW(class, enumstrW, parent, flags, deviceset,
2293 machineW, reserved);
2294 MyFree(enumstrW);
2295 MyFree(machineW);
2296
2297 end:
2298 return ret;
2299 }
2300
2301 /***********************************************************************
2302 * SetupDiGetClassDevsW (SETUPAPI.@)
2303 */
2304 HDEVINFO WINAPI SetupDiGetClassDevsW(
2305 CONST GUID *class,
2306 LPCWSTR enumstr,
2307 HWND parent,
2308 DWORD flags)
2309 {
2310 return SetupDiGetClassDevsExW(class, enumstr, parent, flags, NULL, NULL,
2311 NULL);
2312 }
2313
2314 /***********************************************************************
2315 * SetupDiGetClassDevsExW (SETUPAPI.@)
2316 */
2317 HDEVINFO WINAPI SetupDiGetClassDevsExW(
2318 CONST GUID *class,
2319 PCWSTR enumstr,
2320 HWND parent,
2321 DWORD flags,
2322 HDEVINFO deviceset,
2323 PCWSTR machine,
2324 PVOID reserved)
2325 {
2326 HDEVINFO hDeviceInfo = INVALID_HANDLE_VALUE;
2327 struct DeviceInfoSet *list;
2328 CONST GUID *pClassGuid;
2329 LONG rc;
2330 HDEVINFO set = INVALID_HANDLE_VALUE;
2331
2332 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2333 debugstr_w(enumstr), parent, flags, deviceset, debugstr_w(machine),
2334 reserved);
2335
2336 if (!(flags & DIGCF_ALLCLASSES) && !class)
2337 {
2338 SetLastError(ERROR_INVALID_PARAMETER);
2339 return NULL;
2340 }
2341
2342 /* Create the deviceset if not set */
2343 if (deviceset)
2344 {
2345 list = (struct DeviceInfoSet *)deviceset;
2346 if (list->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2347 {
2348 SetLastError(ERROR_INVALID_HANDLE);
2349 goto cleanup;
2350 }
2351 hDeviceInfo = deviceset;
2352 }
2353 else
2354 {
2355 hDeviceInfo = SetupDiCreateDeviceInfoListExW(
2356 flags & (DIGCF_DEVICEINTERFACE | DIGCF_ALLCLASSES) ? NULL : class,
2357 NULL, machine, NULL);
2358 if (hDeviceInfo == INVALID_HANDLE_VALUE)
2359 goto cleanup;
2360 list = (struct DeviceInfoSet *)hDeviceInfo;
2361 }
2362
2363 if (flags & DIGCF_PROFILE)
2364 FIXME(": flag DIGCF_PROFILE ignored\n");
2365
2366 if (flags & DIGCF_DEVICEINTERFACE)
2367 {
2368 if (!class)
2369 {
2370 SetLastError(ERROR_INVALID_PARAMETER);
2371 goto cleanup;
2372 }
2373 rc = SETUP_CreateInterfaceList(list, machine, class, enumstr, flags & DIGCF_PRESENT);
2374 }
2375 else
2376 {
2377 /* Determine which class(es) should be included in the deviceset */
2378 if (flags & DIGCF_ALLCLASSES)
2379 {
2380 /* The caller wants all classes. Check if
2381 * the deviceset limits us to one class */
2382 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2383 pClassGuid = NULL;
2384 else
2385 pClassGuid = &list->ClassGuid;
2386 }
2387 else if (class)
2388 {
2389 /* The caller wants one class. Check if it matches deviceset class */
2390 if (IsEqualIID(&list->ClassGuid, class)
2391 || IsEqualIID(&list->ClassGuid, &GUID_NULL))
2392 {
2393 pClassGuid = class;
2394 }
2395 else
2396 {
2397 SetLastError(ERROR_INVALID_PARAMETER);
2398 goto cleanup;
2399 }
2400 }
2401 else if (!IsEqualIID(&list->ClassGuid, &GUID_NULL))
2402 {
2403 /* No class specified. Try to use the one of the deviceset */
2404 if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
2405 pClassGuid = &list->ClassGuid;
2406 else
2407 {
2408 SetLastError(ERROR_INVALID_PARAMETER);
2409 goto cleanup;
2410 }
2411 }
2412 else
2413 {
2414 SetLastError(ERROR_INVALID_PARAMETER);
2415 goto cleanup;
2416 }
2417 rc = SETUP_CreateDevicesList(list, machine, pClassGuid, enumstr);
2418 }
2419 if (rc != ERROR_SUCCESS)
2420 {
2421 SetLastError(rc);
2422 goto cleanup;
2423 }
2424 set = hDeviceInfo;
2425
2426 cleanup:
2427 if (!deviceset && hDeviceInfo != INVALID_HANDLE_VALUE && hDeviceInfo != set)
2428 SetupDiDestroyDeviceInfoList(hDeviceInfo);
2429 return set;
2430 }
2431
2432 /***********************************************************************
2433 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2434 */
2435 BOOL WINAPI SetupDiGetDeviceInfoListDetailA(
2436 HDEVINFO DeviceInfoSet,
2437 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData )
2438 {
2439 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2440
2441 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2442
2443 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2444 {
2445 SetLastError(ERROR_INVALID_HANDLE);
2446 return FALSE;
2447 }
2448 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2449 {
2450 SetLastError(ERROR_INVALID_HANDLE);
2451 return FALSE;
2452 }
2453 if (!DevInfoData ||
2454 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A))
2455 {
2456 SetLastError(ERROR_INVALID_PARAMETER);
2457 return FALSE;
2458 }
2459 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2460 DevInfoData->RemoteMachineHandle = set->hMachine;
2461 if (set->MachineName)
2462 {
2463 FIXME("Stub\n");
2464 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2465 return FALSE;
2466 }
2467 else
2468 DevInfoData->RemoteMachineName[0] = 0;
2469
2470 return TRUE;
2471 }
2472
2473 /***********************************************************************
2474 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2475 */
2476 BOOL WINAPI SetupDiGetDeviceInfoListDetailW(
2477 HDEVINFO DeviceInfoSet,
2478 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData )
2479 {
2480 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2481
2482 TRACE("%p %p\n", DeviceInfoSet, DevInfoData);
2483
2484 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2485 {
2486 SetLastError(ERROR_INVALID_HANDLE);
2487 return FALSE;
2488 }
2489 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2490 {
2491 SetLastError(ERROR_INVALID_HANDLE);
2492 return FALSE;
2493 }
2494 if (!DevInfoData ||
2495 DevInfoData->cbSize != sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W))
2496 {
2497 SetLastError(ERROR_INVALID_PARAMETER);
2498 return FALSE;
2499 }
2500 memcpy(&DevInfoData->ClassGuid, &set->ClassGuid, sizeof(GUID));
2501 DevInfoData->RemoteMachineHandle = set->hMachine;
2502 if (set->MachineName)
2503 strcpyW(DevInfoData->RemoteMachineName, set->MachineName + 2);
2504 else
2505 DevInfoData->RemoteMachineName[0] = 0;
2506
2507 return TRUE;
2508 }
2509
2510 /***********************************************************************
2511 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2512 */
2513 BOOL WINAPI SetupDiCreateDeviceInterfaceA(
2514 HDEVINFO DeviceInfoSet,
2515 PSP_DEVINFO_DATA DeviceInfoData,
2516 const GUID *InterfaceClassGuid,
2517 PCSTR ReferenceString,
2518 DWORD CreationFlags,
2519 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2520 {
2521 BOOL ret;
2522 LPWSTR ReferenceStringW = NULL;
2523
2524 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2525 debugstr_guid(InterfaceClassGuid), debugstr_a(ReferenceString),
2526 CreationFlags, DeviceInterfaceData);
2527
2528 if (ReferenceString)
2529 {
2530 ReferenceStringW = MultiByteToUnicode(ReferenceString, CP_ACP);
2531 if (ReferenceStringW == NULL) return FALSE;
2532 }
2533
2534 ret = SetupDiCreateDeviceInterfaceW(DeviceInfoSet, DeviceInfoData,
2535 InterfaceClassGuid, ReferenceStringW, CreationFlags,
2536 DeviceInterfaceData);
2537
2538 MyFree(ReferenceStringW);
2539
2540 return ret;
2541 }
2542
2543 /***********************************************************************
2544 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2545 */
2546 BOOL WINAPI SetupDiCreateDeviceInterfaceW(
2547 HDEVINFO DeviceInfoSet,
2548 PSP_DEVINFO_DATA DeviceInfoData,
2549 const GUID *InterfaceClassGuid,
2550 PCWSTR ReferenceString,
2551 DWORD CreationFlags,
2552 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2553 {
2554 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2555 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2556 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2557 CreationFlags, DeviceInterfaceData);
2558
2559 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
2560 {
2561 SetLastError(ERROR_INVALID_HANDLE);
2562 return FALSE;
2563 }
2564 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2565 {
2566 SetLastError(ERROR_INVALID_HANDLE);
2567 return FALSE;
2568 }
2569 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
2570 || !DeviceInfoData->Reserved)
2571 {
2572 SetLastError(ERROR_INVALID_PARAMETER);
2573 return FALSE;
2574 }
2575 if (!InterfaceClassGuid)
2576 {
2577 SetLastError(ERROR_INVALID_USER_BUFFER);
2578 return FALSE;
2579 }
2580
2581 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet, DeviceInfoData,
2582 debugstr_guid(InterfaceClassGuid), debugstr_w(ReferenceString),
2583 CreationFlags, DeviceInterfaceData);
2584 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2585 return FALSE;
2586 }
2587
2588 /***********************************************************************
2589 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2590 */
2591 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyA(
2592 HDEVINFO DeviceInfoSet,
2593 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2594 DWORD Reserved,
2595 REGSAM samDesired,
2596 HINF InfHandle,
2597 PCSTR InfSectionName)
2598 {
2599 HKEY key;
2600 PWSTR InfSectionNameW = NULL;
2601
2602 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2603 samDesired, InfHandle, InfSectionName);
2604 if (InfHandle)
2605 {
2606 if (!InfSectionName)
2607 {
2608 SetLastError(ERROR_INVALID_PARAMETER);
2609 return INVALID_HANDLE_VALUE;
2610 }
2611 InfSectionNameW = MultiByteToUnicode(InfSectionName, CP_ACP);
2612 if (!InfSectionNameW)
2613 return INVALID_HANDLE_VALUE;
2614 }
2615 key = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet,
2616 DeviceInterfaceData, Reserved, samDesired, InfHandle,
2617 InfSectionNameW);
2618 MyFree(InfSectionNameW);
2619 return key;
2620 }
2621
2622 /***********************************************************************
2623 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2624 */
2625 HKEY WINAPI SetupDiCreateDeviceInterfaceRegKeyW(
2626 HDEVINFO DeviceInfoSet,
2627 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2628 DWORD Reserved,
2629 REGSAM samDesired,
2630 HINF InfHandle,
2631 PCWSTR InfSectionName)
2632 {
2633 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2634 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2635 samDesired, InfHandle, InfSectionName);
2636
2637 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2638 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2639 {
2640 SetLastError(ERROR_INVALID_HANDLE);
2641 return INVALID_HANDLE_VALUE;
2642 }
2643 if (!DeviceInterfaceData ||
2644 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2645 !DeviceInterfaceData->Reserved)
2646 {
2647 SetLastError(ERROR_INVALID_PARAMETER);
2648 return INVALID_HANDLE_VALUE;
2649 }
2650 if (InfHandle && !InfSectionName)
2651 {
2652 SetLastError(ERROR_INVALID_PARAMETER);
2653 return INVALID_HANDLE_VALUE;
2654 }
2655
2656 FIXME("%p %p %d %08x %p %p\n", DeviceInfoSet, DeviceInterfaceData, Reserved,
2657 samDesired, InfHandle, InfSectionName);
2658 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2659 return INVALID_HANDLE_VALUE;
2660 }
2661
2662 /***********************************************************************
2663 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2664 */
2665 BOOL WINAPI SetupDiDeleteDeviceInterfaceRegKey(
2666 HDEVINFO DeviceInfoSet,
2667 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2668 DWORD Reserved)
2669 {
2670 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2671 BOOL ret = FALSE;
2672
2673 TRACE("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2674
2675 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2676 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2677 {
2678 SetLastError(ERROR_INVALID_HANDLE);
2679 return FALSE;
2680 }
2681 if (!DeviceInterfaceData ||
2682 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2683 !DeviceInterfaceData->Reserved)
2684 {
2685 SetLastError(ERROR_INVALID_PARAMETER);
2686 return FALSE;
2687 }
2688
2689 FIXME("%p %p %d\n", DeviceInfoSet, DeviceInterfaceData, Reserved);
2690 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2691 return ret;
2692 }
2693
2694 /***********************************************************************
2695 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2696 *
2697 * PARAMS
2698 * DeviceInfoSet [I] Set of devices from which to enumerate
2699 * interfaces
2700 * DeviceInfoData [I] (Optional) If specified, a specific device
2701 * instance from which to enumerate interfaces.
2702 * If it isn't specified, all interfaces for all
2703 * devices in the set are enumerated.
2704 * InterfaceClassGuid [I] The interface class to enumerate.
2705 * MemberIndex [I] An index of the interface instance to enumerate.
2706 * A caller should start with MemberIndex set to 0,
2707 * and continue until the function fails with
2708 * ERROR_NO_MORE_ITEMS.
2709 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2710 * member must be set to
2711 * sizeof(SP_DEVICE_INTERFACE_DATA).
2712 *
2713 * RETURNS
2714 * Success: non-zero value.
2715 * Failure: FALSE. Call GetLastError() for more info.
2716 */
2717 BOOL WINAPI SetupDiEnumDeviceInterfaces(
2718 HDEVINFO DeviceInfoSet,
2719 PSP_DEVINFO_DATA DeviceInfoData,
2720 CONST GUID * InterfaceClassGuid,
2721 DWORD MemberIndex,
2722 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2723 {
2724 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2725 BOOL ret = FALSE;
2726
2727 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet, DeviceInfoData,
2728 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
2729
2730 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2731 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2732 {
2733 SetLastError(ERROR_INVALID_HANDLE);
2734 return FALSE;
2735 }
2736 if (DeviceInfoData && (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA) ||
2737 !DeviceInfoData->Reserved))
2738 {
2739 SetLastError(ERROR_INVALID_PARAMETER);
2740 return FALSE;
2741 }
2742 if (!DeviceInterfaceData ||
2743 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
2744 {
2745 SetLastError(ERROR_INVALID_PARAMETER);
2746 return FALSE;
2747 }
2748 if (DeviceInfoData)
2749 {
2750 struct DeviceInfo *devInfo =
2751 (struct DeviceInfo *)DeviceInfoData->Reserved;
2752 BOOL found = FALSE;
2753 PLIST_ENTRY InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2754 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2755 {
2756 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2757 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2758 {
2759 InterfaceListEntry = InterfaceListEntry->Flink;
2760 continue;
2761 }
2762 if (MemberIndex-- == 0)
2763 {
2764 /* return this item */
2765 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2766 &DevItf->InterfaceClassGuid,
2767 sizeof(GUID));
2768 DeviceInterfaceData->Flags = DevItf->Flags;
2769 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2770 found = TRUE;
2771 ret = TRUE;
2772 }
2773 InterfaceListEntry = InterfaceListEntry->Flink;
2774 }
2775 if (!found)
2776 SetLastError(ERROR_NO_MORE_ITEMS);
2777 }
2778 else
2779 {
2780 BOOL found = FALSE;
2781 PLIST_ENTRY ItemList = set->ListHead.Flink;
2782 while (ItemList != &set->ListHead && !found)
2783 {
2784 PLIST_ENTRY InterfaceListEntry;
2785 struct DeviceInfo *devInfo =
2786 CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
2787 InterfaceListEntry = devInfo->InterfaceListHead.Flink;
2788 while (InterfaceListEntry != &devInfo->InterfaceListHead && !found)
2789 {
2790 struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
2791 if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
2792 {
2793 InterfaceListEntry = InterfaceListEntry->Flink;
2794 continue;
2795 }
2796 if (MemberIndex-- == 0)
2797 {
2798 /* return this item */
2799 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
2800 &DevItf->InterfaceClassGuid,
2801 sizeof(GUID));
2802 DeviceInterfaceData->Flags = DevItf->Flags;
2803 DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
2804 found = TRUE;
2805 ret = TRUE;
2806 }
2807 InterfaceListEntry = InterfaceListEntry->Flink;
2808 }
2809 ItemList = ItemList->Flink;
2810
2811 }
2812 if (!found)
2813 SetLastError(ERROR_NO_MORE_ITEMS);
2814 }
2815 return ret;
2816 }
2817
2818 /***********************************************************************
2819 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2820 *
2821 * Destroy a DeviceInfoList and free all used memory of the list.
2822 *
2823 * PARAMS
2824 * devinfo [I] DeviceInfoList pointer to list to destroy
2825 *
2826 * RETURNS
2827 * Success: non zero value.
2828 * Failure: zero value.
2829 */
2830 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
2831 {
2832 BOOL ret = FALSE;
2833
2834 TRACE("%p\n", devinfo);
2835 if (devinfo && devinfo != INVALID_HANDLE_VALUE)
2836 {
2837 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
2838
2839 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
2840 {
2841 ret = DestroyDeviceInfoSet(list);
2842 }
2843 }
2844
2845 if (ret == FALSE)
2846 SetLastError(ERROR_INVALID_HANDLE);
2847
2848 return ret;
2849 }
2850
2851 /***********************************************************************
2852 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2853 */
2854 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
2855 HDEVINFO DeviceInfoSet,
2856 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2857 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
2858 DWORD DeviceInterfaceDetailDataSize,
2859 PDWORD RequiredSize,
2860 PSP_DEVINFO_DATA DeviceInfoData)
2861 {
2862 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2863 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
2864 DWORD sizeW = 0, bytesNeeded;
2865 BOOL ret = FALSE;
2866
2867 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2868 DeviceInterfaceData, DeviceInterfaceDetailData,
2869 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2870
2871 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2872 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2873 {
2874 SetLastError(ERROR_INVALID_HANDLE);
2875 return FALSE;
2876 }
2877 if (!DeviceInterfaceData ||
2878 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2879 !DeviceInterfaceData->Reserved)
2880 {
2881 SetLastError(ERROR_INVALID_PARAMETER);
2882 return FALSE;
2883 }
2884 if (DeviceInterfaceDetailData && (DeviceInterfaceDetailData->cbSize <
2885 FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1 ||
2886 DeviceInterfaceDetailData->cbSize > sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A)))
2887 {
2888 SetLastError(ERROR_INVALID_USER_BUFFER);
2889 return FALSE;
2890 }
2891 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2892 {
2893 SetLastError(ERROR_INVALID_USER_BUFFER);
2894 return FALSE;
2895 }
2896
2897
2898 if (DeviceInterfaceDetailData != NULL)
2899 {
2900 sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
2901 + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
2902 DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)MyMalloc(sizeW);
2903 if (!DeviceInterfaceDetailDataW)
2904 {
2905 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2906 }
2907 }
2908 if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
2909 {
2910 DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
2911 ret = SetupDiGetDeviceInterfaceDetailW(
2912 DeviceInfoSet,
2913 DeviceInterfaceData,
2914 DeviceInterfaceDetailDataW,
2915 sizeW,
2916 &sizeW,
2917 DeviceInfoData);
2918 bytesNeeded = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
2919 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
2920 if (RequiredSize)
2921 *RequiredSize = bytesNeeded;
2922 if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= bytesNeeded)
2923 {
2924 if (!WideCharToMultiByte(
2925 CP_ACP, 0,
2926 DeviceInterfaceDetailDataW->DevicePath, -1,
2927 DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
2928 NULL, NULL))
2929 {
2930 ret = FALSE;
2931 }
2932 }
2933 }
2934 MyFree(DeviceInterfaceDetailDataW);
2935
2936 return ret;
2937 }
2938
2939 /***********************************************************************
2940 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2941 */
2942 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
2943 HDEVINFO DeviceInfoSet,
2944 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
2945 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
2946 DWORD DeviceInterfaceDetailDataSize,
2947 PDWORD RequiredSize,
2948 PSP_DEVINFO_DATA DeviceInfoData)
2949 {
2950 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
2951 BOOL ret = FALSE;
2952
2953 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
2954 DeviceInterfaceData, DeviceInterfaceDetailData,
2955 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
2956
2957 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE ||
2958 set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
2959 {
2960 SetLastError(ERROR_INVALID_HANDLE);
2961 return FALSE;
2962 }
2963 if (!DeviceInterfaceData ||
2964 DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA) ||
2965 !DeviceInterfaceData->Reserved)
2966 {
2967 SetLastError(ERROR_INVALID_PARAMETER);
2968 return FALSE;
2969 }
2970 if (DeviceInterfaceDetailData && DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
2971 {
2972 SetLastError(ERROR_INVALID_USER_BUFFER);
2973 return FALSE;
2974 }
2975 if (!DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize)
2976 {
2977 SetLastError(ERROR_INVALID_USER_BUFFER);
2978 return FALSE;
2979 }
2980 if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
2981 {
2982 SetLastError(ERROR_INVALID_PARAMETER);
2983 return FALSE;
2984 }
2985 if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR))
2986 {
2987 SetLastError(ERROR_INVALID_PARAMETER);
2988 return FALSE;
2989 }
2990 else
2991 {
2992 struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
2993 LPCWSTR devName = deviceInterface->SymbolicLink;
2994 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
2995 (lstrlenW(devName) + 1) * sizeof(WCHAR);
2996
2997 if (sizeRequired > DeviceInterfaceDetailDataSize)
2998 {
2999 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3000 if (RequiredSize)
3001 *RequiredSize = sizeRequired;
3002 }
3003 else
3004 {
3005 strcpyW(DeviceInterfaceDetailData->DevicePath, devName);
3006 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
3007 if (DeviceInfoData)
3008 {
3009 memcpy(&DeviceInfoData->ClassGuid,
3010 &deviceInterface->DeviceInfo->ClassGuid,
3011 sizeof(GUID));
3012 DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
3013 DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
3014 }
3015 ret = TRUE;
3016 }
3017 }
3018 return ret;
3019 }
3020
3021 struct PropertyMapEntry
3022 {
3023 DWORD regType;
3024 LPCSTR nameA;
3025 LPCWSTR nameW;
3026 };
3027
3028 static struct PropertyMapEntry PropertyMap[] = {
3029 { REG_SZ, "DeviceDesc", REGSTR_VAL_DEVDESC },
3030 { REG_MULTI_SZ, "HardwareId", REGSTR_VAL_HARDWAREID },
3031 { REG_MULTI_SZ, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS },
3032 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
3033 { REG_SZ, "Service", REGSTR_VAL_SERVICE },
3034 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
3035 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
3036 { REG_SZ, "Class", REGSTR_VAL_CLASS },
3037 { REG_SZ, "ClassGUID", REGSTR_VAL_CLASSGUID },
3038 { REG_SZ, "Driver", REGSTR_VAL_DRIVER },
3039 { REG_DWORD, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS },
3040 { REG_SZ, "Mfg", REGSTR_VAL_MFG },
3041 { REG_SZ, "FriendlyName", REGSTR_VAL_FRIENDLYNAME },
3042 { REG_SZ, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION },
3043 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3044 { REG_DWORD, "Capabilities", REGSTR_VAL_CAPABILITIES },
3045 { REG_DWORD, "UINumber", REGSTR_VAL_UI_NUMBER },
3046 { REG_MULTI_SZ, "UpperFilters", REGSTR_VAL_UPPERFILTERS },
3047 { REG_MULTI_SZ, "LowerFilters", REGSTR_VAL_LOWERFILTERS },
3048 { 0, NULL, NULL }, /* SPDRP_BUSTYPEGUID */
3049 { 0, NULL, NULL }, /* SPDRP_LEGACYBUSTYPE */
3050 { 0, NULL, NULL }, /* SPDRP_BUSNUMBER */
3051 { 0, NULL, NULL }, /* SPDRP_ENUMERATOR_NAME */
3052 { REG_BINARY, "Security", REGSTR_SECURITY },
3053 { 0, NULL, NULL }, /* SPDRP_SECURITY_SDS */
3054 { 0, NULL, NULL }, /* SPDRP_DEVTYPE */
3055 { 0, NULL, NULL }, /* SPDRP_EXCLUSIVE */
3056 { 0, NULL, NULL }, /* SPDRP_CHARACTERISTICS */
3057 { 0, NULL, NULL }, /* SPDRP_ADDRESS */
3058 { REG_SZ, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT },
3059 { 0, NULL, NULL }, /* SPDRP_DEVICE_POWER_DATA */
3060 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY */
3061 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3062 { 0, NULL, NULL }, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3063 { 0, NULL, NULL }, /* SPDRP_INSTALL_STATE */
3064 };
3065
3066 /***********************************************************************
3067 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3068 */
3069 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
3070 HDEVINFO DeviceInfoSet,
3071 PSP_DEVINFO_DATA DeviceInfoData,
3072 DWORD Property,
3073 PDWORD PropertyRegDataType,
3074 PBYTE PropertyBuffer,
3075 DWORD PropertyBufferSize,
3076 PDWORD RequiredSize)
3077 {
3078 BOOL ret;
3079 BOOL bIsStringProperty;
3080 DWORD RegType;
3081 DWORD RequiredSizeA, RequiredSizeW;
3082 DWORD PropertyBufferSizeW = 0;
3083 PBYTE PropertyBufferW = NULL;
3084
3085 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3086 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3087 RequiredSize);
3088
3089 if (PropertyBufferSize != 0)
3090 {
3091 PropertyBufferSizeW = PropertyBufferSize * 2;
3092 PropertyBufferW = HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW);
3093 if (!PropertyBufferW)
3094 {
3095 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3096 return FALSE;
3097 }
3098 }
3099
3100 ret = SetupDiGetDeviceRegistryPropertyW(
3101 DeviceInfoSet,
3102 DeviceInfoData,
3103 Property,
3104 &RegType,
3105 PropertyBufferW,
3106 PropertyBufferSizeW,
3107 &RequiredSizeW);
3108
3109 if (ret || GetLastError() == ERROR_INSUFFICIENT_BUFFER)
3110 {
3111 bIsStringProperty = (RegType == REG_SZ || RegType == REG_MULTI_SZ || RegType == REG_EXPAND_SZ);
3112
3113 if (bIsStringProperty)
3114 RequiredSizeA = RequiredSizeW / sizeof(WCHAR);
3115 else
3116 RequiredSizeA = RequiredSizeW;
3117 if (RequiredSize)
3118 *RequiredSize = RequiredSizeA;
3119 if (PropertyRegDataType)
3120 *PropertyRegDataType = RegType;
3121 }
3122
3123 if (!ret)
3124 {
3125 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3126 return ret;
3127 }
3128
3129 if (RequiredSizeA <= PropertyBufferSize)
3130 {
3131 if (bIsStringProperty && PropertyBufferSize > 0)
3132 {
3133 if (WideCharToMultiByte(CP_ACP, 0, (LPWSTR)PropertyBufferW, RequiredSizeW / sizeof(WCHAR), (LPSTR)PropertyBuffer, PropertyBufferSize, NULL, NULL) == 0)
3134 {
3135 /* Last error is already set by WideCharToMultiByte */
3136 ret = FALSE;
3137 }
3138 }
3139 else
3140 memcpy(PropertyBuffer, PropertyBufferW, RequiredSizeA);
3141 }
3142 else
3143 {
3144 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3145 ret = FALSE;
3146 }
3147
3148 HeapFree(GetProcessHeap(), 0, PropertyBufferW);
3149 return ret;
3150 }
3151
3152 /***********************************************************************
3153 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3154 */
3155 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
3156 HDEVINFO DeviceInfoSet,
3157 PSP_DEVINFO_DATA DeviceInfoData,
3158 DWORD Property,
3159 PDWORD PropertyRegDataType,
3160 PBYTE PropertyBuffer,
3161 DWORD PropertyBufferSize,
3162 PDWORD RequiredSize)
3163 {
3164 BOOL ret = FALSE;
3165 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3166 struct DeviceInfo *devInfo;
3167
3168 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet, DeviceInfoData,
3169 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
3170 RequiredSize);
3171
3172 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3173 {
3174 SetLastError(ERROR_INVALID_HANDLE);
3175 return FALSE;
3176 }
3177 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3178 {
3179 SetLastError(ERROR_INVALID_HANDLE);
3180 return FALSE;
3181 }
3182 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3183 || !DeviceInfoData->Reserved)
3184 {
3185 SetLastError(ERROR_INVALID_PARAMETER);
3186 return FALSE;
3187 }
3188 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
3189 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3190 && PropertyMap[Property].nameW)
3191 {
3192 DWORD size = PropertyBufferSize;
3193 HKEY hKey;
3194 LONG l;
3195 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE);
3196 if (hKey == INVALID_HANDLE_VALUE)
3197 return FALSE;
3198 l = RegQueryValueExW(hKey, PropertyMap[Property].nameW,
3199 NULL, PropertyRegDataType, PropertyBuffer, &size);
3200 RegCloseKey(hKey);
3201
3202 if (RequiredSize)
3203 *RequiredSize = size;
3204 switch(l) {
3205 case ERROR_SUCCESS:
3206 if (PropertyBuffer != NULL || size == 0)
3207 ret = TRUE;
3208 else
3209 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3210 break;
3211 case ERROR_MORE_DATA:
3212 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3213 break;
3214 default:
3215 SetLastError(l);
3216 }
3217 }
3218 else if (Property == SPDRP_PHYSICAL_DEVICE_OBJECT_NAME)
3219 {
3220 DWORD required = (strlenW(devInfo->Data) + 1) * sizeof(WCHAR);
3221
3222 if (PropertyRegDataType)
3223 *PropertyRegDataType = REG_SZ;
3224 if (RequiredSize)
3225 *RequiredSize = required;
3226 if (PropertyBufferSize >= required)
3227 {
3228 strcpyW((LPWSTR)PropertyBuffer, devInfo->Data);
3229 ret = TRUE;
3230 }
3231 else
3232 SetLastError(ERROR_INSUFFICIENT_BUFFER);
3233 }
3234 else
3235 {
3236 ERR("Property 0x%lx not implemented\n", Property);
3237 SetLastError(ERROR_NOT_SUPPORTED);
3238 }
3239 return ret;
3240 }
3241
3242 /***********************************************************************
3243 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3244 */
3245 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
3246 HDEVINFO DeviceInfoSet,
3247 PSP_DEVINFO_DATA DeviceInfoData,
3248 DWORD Property,
3249 const BYTE *PropertyBuffer,
3250 DWORD PropertyBufferSize)
3251 {
3252 BOOL ret = FALSE;
3253 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3254
3255 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3256 PropertyBuffer, PropertyBufferSize);
3257
3258 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3259 {
3260 SetLastError(ERROR_INVALID_HANDLE);
3261 return FALSE;
3262 }
3263 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3264 {
3265 SetLastError(ERROR_INVALID_HANDLE);
3266 return FALSE;
3267 }
3268 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3269 || !DeviceInfoData->Reserved)
3270 {
3271 SetLastError(ERROR_INVALID_PARAMETER);
3272 return FALSE;
3273 }
3274
3275 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet, DeviceInfoData,
3276 Property, PropertyBuffer, PropertyBufferSize);
3277 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
3278 return ret;
3279 }
3280
3281 /***********************************************************************
3282 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3283 */
3284 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
3285 HDEVINFO DeviceInfoSet,
3286 PSP_DEVINFO_DATA DeviceInfoData,
3287 DWORD Property,
3288 const BYTE *PropertyBuffer,
3289 DWORD PropertyBufferSize)
3290 {
3291 BOOL ret = FALSE;
3292 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
3293
3294 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
3295 PropertyBuffer, PropertyBufferSize);
3296
3297 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
3298 {
3299 SetLastError(ERROR_INVALID_HANDLE);
3300 return FALSE;
3301 }
3302 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3303 {
3304 SetLastError(ERROR_INVALID_HANDLE);
3305 return FALSE;
3306 }
3307 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
3308 || !DeviceInfoData->Reserved)
3309 {
3310 SetLastError(ERROR_INVALID_PARAMETER);
3311 return FALSE;
3312 }
3313 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
3314 && PropertyMap[Property].nameW)
3315 {
3316 HKEY hKey;
3317 LONG l;
3318 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
3319 if (hKey == INVALID_HANDLE_VALUE)
3320 return FALSE;
3321 /* Write new data */
3322 l = RegSetValueExW(
3323 hKey, PropertyMap[Property].nameW, 0,
3324 PropertyMap[Property].regType, PropertyBuffer,
3325 PropertyBufferSize);
3326 if (!l)
3327 ret = TRUE;
3328 else
3329 SetLastError(l);
3330 RegCloseKey(hKey);
3331 }
3332 else
3333 {
3334 ERR("Property 0x%lx not implemented\n", Property);
3335 SetLastError(ERROR_NOT_SUPPORTED);
3336 }
3337
3338 TRACE("Returning %d\n", ret);
3339 return ret;
3340 }
3341
3342 /***********************************************************************
3343 * SetupDiInstallClassA (SETUPAPI.@)
3344 */
3345 BOOL WINAPI SetupDiInstallClassA(
3346 HWND hwndParent,
3347 PCSTR InfFileName,
3348 DWORD Flags,
3349 HSPFILEQ FileQueue)
3350 {
3351 return SetupDiInstallClassExA(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3352 }
3353
3354 /***********************************************************************
3355 * SetupDiInstallClassExA (SETUPAPI.@)
3356 */
3357 BOOL WINAPI
3358 SetupDiInstallClassExA(
3359 IN HWND hwndParent OPTIONAL,
3360 IN PCSTR InfFileName OPTIONAL,
3361 IN DWORD Flags,
3362 IN HSPFILEQ FileQueue OPTIONAL,
3363 IN CONST GUID *InterfaceClassGuid OPTIONAL,
3364 IN PVOID Reserved1,
3365 IN PVOID Reserved2)
3366 {
3367 PWSTR InfFileNameW = NULL;
3368 BOOL Result;
3369
3370 if (!InfFileName)
3371 {
3372 SetLastError(ERROR_INVALID_PARAMETER);
3373 return FALSE;
3374 }
3375 else
3376 {
3377 InfFileNameW = MultiByteToUnicode(InfFileName, CP_ACP);
3378 if (InfFileNameW == NULL)
3379 {
3380 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3381 return FALSE;
3382 }
3383 }
3384
3385 Result = SetupDiInstallClassExW(hwndParent, InfFileNameW, Flags,
3386 FileQueue, InterfaceClassGuid, Reserved1, Reserved2);
3387
3388 MyFree(InfFileNameW);
3389
3390 return Result;
3391 }
3392
3393 HKEY SETUP_CreateClassKey(HINF hInf)
3394 {
3395 static const WCHAR slash[] = { '\\',0 };
3396 WCHAR FullBuffer[MAX_PATH];
3397 WCHAR Buffer[MAX_PATH];
3398 DWORD RequiredSize;
3399 HKEY hClassKey;
3400
3401 if (!SetupGetLineTextW(NULL,
3402 hInf,
3403 Version,
3404 ClassGUID,
3405 Buffer,
3406 MAX_PATH,
3407 &RequiredSize))
3408 {
3409 return INVALID_HANDLE_VALUE;
3410 }
3411
3412 lstrcpyW(FullBuffer, REGSTR_PATH_CLASS_NT);
3413 lstrcatW(FullBuffer, slash);
3414 lstrcatW(FullBuffer, Buffer);
3415
3416 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
3417 FullBuffer,
3418 0,
3419 KEY_SET_VALUE,
3420 &hClassKey))
3421 {
3422 if (!SetupGetLineTextW(NULL,
3423 hInf,
3424 Version,
3425 Class,
3426 Buffer,
3427 MAX_PATH,
3428 &RequiredSize))
3429 {
3430 return INVALID_HANDLE_VALUE;
3431 }
3432
3433 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
3434 FullBuffer,
3435 0,
3436 NULL,
3437 REG_OPTION_NON_VOLATILE,
3438 KEY_SET_VALUE,
3439 NULL,
3440 &hClassKey,
3441 NULL))
3442 {
3443 return INVALID_HANDLE_VALUE;
3444 }
3445
3446 }
3447
3448 if (RegSetValueExW(hClassKey,
3449 Class,
3450 0,
3451 REG_SZ,
3452 (LPBYTE)Buffer,
3453 RequiredSize * sizeof(WCHAR)))
3454 {
3455 RegCloseKey(hClassKey);
3456 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
3457 FullBuffer);
3458 return INVALID_HANDLE_VALUE;
3459 }
3460
3461 return hClassKey;
3462 }
3463
3464 /***********************************************************************
3465 * SetupDiInstallClassW (SETUPAPI.@)
3466 */
3467 BOOL WINAPI SetupDiInstallClassW(
3468 HWND hwndParent,
3469 PCWSTR InfFileName,
3470 DWORD Flags,
3471 HSPFILEQ FileQueue)
3472 {
3473 return SetupDiInstallClassExW(hwndParent, InfFileName, Flags, FileQueue, NULL, NULL, NULL);
3474 }
3475
3476
3477 /***********************************************************************
3478 * SetupDiOpenClassRegKey (SETUPAPI.@)
3479 */
3480 HKEY WINAPI SetupDiOpenClassRegKey(
3481 const GUID* ClassGuid,
3482 REGSAM samDesired)
3483 {
3484 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3485 DIOCR_INSTALLER, NULL, NULL);
3486 }
3487
3488
3489 /***********************************************************************
3490 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3491 */
3492 HKEY WINAPI SetupDiOpenClassRegKeyExA(
3493 const GUID* ClassGuid,
3494 REGSAM samDesired,
3495 DWORD Flags,
3496 PCSTR MachineName,
3497 PVOID Reserved)
3498 {
3499 PWSTR MachineNameW = NULL;
3500 HKEY hKey;
3501
3502 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
3503 Flags, debugstr_a(MachineName), Reserved);
3504
3505 if (MachineName)
3506 {
3507 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
3508 if (MachineNameW == NULL)
3509 return INVALID_HANDLE_VALUE;
3510 }
3511
3512 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
3513 Flags, MachineNameW, Reserved);
3514
3515 MyFree(MachineNameW);
3516
3517 return hKey;
3518 }
3519
3520
3521 /***********************************************************************
3522 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3523 */
3524 HKEY WINAPI SetupDiOpenClassRegKeyExW(
3525 const GUID* ClassGuid,
3526 REGSAM samDesired,
3527 DWORD Flags,
3528 PCWSTR MachineName,
3529 PVOID Reserved)
3530 {
3531 HKEY HKLM;
3532 HKEY hClassesKey;
3533 HKEY key;
3534 LPCWSTR lpKeyName;
3535 LONG l;
3536
3537 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid), samDesired,
3538 Flags, debugstr_w(MachineName), Reserved);
3539
3540 if (MachineName != NULL)
3541 {
3542 l = RegConnectRegistryW(MachineName, HKEY_LOCAL_MACHINE, &HKLM);
3543 if (l != ERROR_SUCCESS)
3544 {
3545 SetLastError(l);
3546 return INVALID_HANDLE_VALUE;
3547 }
3548 }
3549 else
3550 HKLM = HKEY_LOCAL_MACHINE;
3551
3552 if (Flags == DIOCR_INSTALLER)
3553 {
3554 lpKeyName = REGSTR_PATH_CLASS_NT;
3555 }
3556 else if (Flags == DIOCR_INTERFACE)
3557 {
3558 lpKeyName = REGSTR_PATH_DEVICE_CLASSES;
3559 }
3560 else
3561 {
3562 ERR("Invalid Flags parameter!\n");
3563 SetLastError(ERROR_INVALID_PARAMETER);
3564 if (MachineName != NULL) RegCloseKey(HKLM);
3565 return INVALID_HANDLE_VALUE;
3566 }
3567
3568 if (!ClassGuid)
3569 {
3570 if ((l = RegOpenKeyExW(HKLM,
3571 lpKeyName,
3572 0,
3573 samDesired,
3574 &hClassesKey)))
3575 {
3576 SetLastError(l);
3577 hClassesKey = INVALID_HANDLE_VALUE;
3578 }
3579 if (MachineName != NULL)
3580 RegCloseKey(HKLM);
3581 key = hClassesKey;
3582 }
3583 else
3584 {
3585 WCHAR bracedGuidString[39];
3586
3587 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
3588
3589 if (!(l = RegOpenKeyExW(HKLM,
3590 lpKeyName,
3591 0,
3592 0,
3593 &hClassesKey)))
3594 {
3595 if (MachineName != NULL)
3596 RegCloseKey(HKLM);
3597
3598 if ((l = RegOpenKeyExW(hClassesKey,
3599 bracedGuidString,
3600 0,
3601 samDesired,
3602 &key)))
3603 {
3604 SetLastError(l);
3605 key = INVALID_HANDLE_VALUE;
3606 }
3607 RegCloseKey(hClassesKey);
3608 }
3609 else
3610 {
3611 if (MachineName != NULL) RegCloseKey(HKLM);
3612 SetLastError(l);
3613 key = INVALID_HANDLE_VALUE;
3614 }
3615 }
3616 return key;
3617 }
3618
3619 /***********************************************************************
3620 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3621 */
3622 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
3623 HDEVINFO DeviceInfoSet,
3624 PCWSTR DevicePath,
3625 DWORD OpenFlags,
3626 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3627 {
3628 FIXME("%p %s %08x %p\n",
3629 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
3630 return FALSE;
3631 }
3632
3633 /***********************************************************************
3634 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3635 */
3636 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
3637 HDEVINFO DeviceInfoSet,
3638 PCSTR DevicePath,
3639 DWORD OpenFlags,
3640 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
3641 {
3642 LPWSTR DevicePathW = NULL;
3643 BOOL bResult;
3644
3645 TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
3646
3647 DevicePathW = MultiByteToUnicode(DevicePath, CP_ACP);
3648 if (DevicePathW == NULL)
3649 return FALSE;
3650
3651 bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet,
3652 DevicePathW, OpenFlags, DeviceInterfaceData);
3653
3654 MyFree(DevicePathW);
3655
3656 return bResult;
3657 }
3658
3659 /***********************************************************************
3660 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3661 */
3662 BOOL WINAPI SetupDiSetClassInstallParamsA(
3663 HDEVINFO DeviceInfoSet,
3664 PSP_DEVINFO_DATA DeviceInfoData,
3665 PSP_CLASSINSTALL_HEADER ClassInstallParams,
3666 DWORD ClassInstallParamsSize)
3667 {
3668 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
3669 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
3670 return FALSE;
3671 }
3672
3673 static BOOL WINAPI
3674 IntSetupDiRegisterDeviceInfo(
3675 IN HDEVINFO DeviceInfoSet,
3676 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
3677 {
3678 return SetupDiRegisterDeviceInfo(DeviceInfoSet, DeviceInfoData, 0, NULL, NULL, NULL);
3679 }
3680
3681 /***********************************************************************
3682 * SetupDiCallClassInstaller (SETUPAPI.@)
3683 */
3684 BOOL WINAPI SetupDiCallClassInstaller(
3685 DI_FUNCTION InstallFunction,
3686 HDEVINFO DeviceInfoSet,
3687 PSP_DEVINFO_DATA DeviceInfoData)
3688 {
3689 BOOL ret = FALSE;
3690
3691 TRACE("%u %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
3692
3693 if (!DeviceInfoSet)
3694 SetLastError(ERROR_INVALID_PARAMETER);
3695 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
3696 SetLastError(ERROR_INVALID_HANDLE);
3697 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
3698 SetLastError(ERROR_INVALID_HANDLE);
3699 else if (((struct DeviceInfoSet *)DeviceInfoSet)->HKLM != HKEY_LOCAL_MACHINE)
3700 SetLastError(ERROR_INVALID_HANDLE);
3701 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
3702 SetLastError(ERROR_INVALID_USER_BUFFER);
3703 else
3704 {
3705 SP_DEVINSTALL_PARAMS_W InstallParams;
3706 #define CLASS_COINSTALLER 0x1
3707 #define DEVICE_COINSTALLER 0x2
3708 #define CLASS_INSTALLER 0x4
3709 UCHAR CanHandle = 0;
3710 DEFAULT_CLASS_INSTALL_PROC DefaultHandler = NULL;
3711
3712 switch (InstallFunction)
3713 {
3714 case DIF_ADDPROPERTYPAGE_ADVANCED:
3715 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3716 break;
3717 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED:
3718 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3719 break;
3720 case DIF_ALLOW_INSTALL:
3721 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3722 break;
3723 case DIF_DETECT:
3724 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3725 break;
3726 case DIF_DESTROYPRIVATEDATA:
3727 CanHandle = CLASS_INSTALLER;
3728 break;
3729 case DIF_INSTALLDEVICE:
3730 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3731 DefaultHandler = SetupDiInstallDevice;
3732 break;
3733 case DIF_INSTALLDEVICEFILES:
3734 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3735 DefaultHandler = SetupDiInstallDriverFiles;
3736 break;
3737 case DIF_INSTALLINTERFACES:
3738 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3739 DefaultHandler = SetupDiInstallDeviceInterfaces;
3740 break;
3741 case DIF_NEWDEVICEWIZARD_FINISHINSTALL:
3742 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3743 break;
3744 case DIF_NEWDEVICEWIZARD_POSTANALYZE:
3745 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3746 break;
3747 case DIF_NEWDEVICEWIZARD_PREANALYZE:
3748 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3749 break;
3750 case DIF_NEWDEVICEWIZARD_PRESELECT:
3751 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3752 break;
3753 case DIF_NEWDEVICEWIZARD_SELECT:
3754 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3755 break;
3756 case DIF_POWERMESSAGEWAKE:
3757 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3758 break;
3759 case DIF_PROPERTYCHANGE:
3760 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3761 DefaultHandler = SetupDiChangeState;
3762 break;
3763 case DIF_REGISTER_COINSTALLERS:
3764 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3765 DefaultHandler = SetupDiRegisterCoDeviceInstallers;
3766 break;
3767 case DIF_REGISTERDEVICE:
3768 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3769 DefaultHandler = IntSetupDiRegisterDeviceInfo;
3770 break;
3771 case DIF_REMOVE:
3772 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3773 DefaultHandler = SetupDiRemoveDevice;
3774 break;
3775 case DIF_SELECTBESTCOMPATDRV:
3776 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3777 DefaultHandler = SetupDiSelectBestCompatDrv;
3778 break;
3779 case DIF_SELECTDEVICE:
3780 CanHandle = CLASS_COINSTALLER | CLASS_INSTALLER;
3781 DefaultHandler = SetupDiSelectDevice;
3782 break;
3783 case DIF_TROUBLESHOOTER:
3784 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3785 break;
3786 case DIF_UNREMOVE:
3787 CanHandle = CLASS_COINSTALLER | DEVICE_COINSTALLER | CLASS_INSTALLER;
3788 DefaultHandler = SetupDiUnremoveDevice;
3789 break;
3790 default:
3791 ERR("Install function %u not supported\n", InstallFunction);
3792 SetLastError(ERROR_NOT_SUPPORTED);
3793 }
3794
3795 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
3796 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams))
3797 /* Don't process this call, as a parameter is invalid */
3798 CanHandle = 0;
3799
3800 if (CanHandle != 0)
3801 {
3802 LIST_ENTRY ClassCoInstallersListHead;
3803 LIST_ENTRY DeviceCoInstallersListHead;
3804 HMODULE ClassInstallerLibrary = NULL;
3805 CLASS_INSTALL_PROC ClassInstaller = NULL;
3806 COINSTALLER_CONTEXT_DATA Context;
3807 PLIST_ENTRY ListEntry;
3808 HKEY hKey;
3809 DWORD dwRegType, dwLength;
3810 DWORD rc = NO_ERROR;
3811
3812 InitializeListHead(&ClassCoInstallersListHead);
3813 InitializeListHead(&DeviceCoInstallersListHead);
3814
3815 if (CanHandle & DEVICE_COINSTALLER)
3816 {
3817 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE);
3818 if (hKey != INVALID_HANDLE_VALUE)
3819 {
3820 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, &dwRegType, NULL, &dwLength);
3821 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
3822 {
3823 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3824 if (KeyBuffer != NULL)
3825 {
3826 rc = RegQueryValueExW(hKey, REGSTR_VAL_COINSTALLERS_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3827 if (rc == ERROR_SUCCESS)
3828 {
3829 LPWSTR ptr;
3830 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
3831 {
3832 /* Add coinstaller to DeviceCoInstallersListHead list */
3833 struct CoInstallerElement *coinstaller;
3834 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr));
3835 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
3836 if (!coinstaller)
3837 continue;
3838 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
3839 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
3840 InsertTailList(&DeviceCoInstallersListHead, &coinstaller->ListEntry);
3841 else
3842 HeapFree(GetProcessHeap(), 0, coinstaller);
3843 }
3844 }
3845 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3846 }
3847 }
3848 RegCloseKey(hKey);
3849 }
3850 }
3851 if (CanHandle & CLASS_COINSTALLER)
3852 {
3853 rc = RegOpenKeyExW(
3854 HKEY_LOCAL_MACHINE,
3855 REGSTR_PATH_CODEVICEINSTALLERS,
3856 0, /* Options */
3857 KEY_QUERY_VALUE,
3858 &hKey);
3859 if (rc == ERROR_SUCCESS)
3860 {
3861 LPWSTR lpGuidString;
3862 if (UuidToStringW((UUID*)&DeviceInfoData->ClassGuid, &lpGuidString) == RPC_S_OK)
3863 {
3864 rc = RegQueryValueExW(hKey, lpGuidString, NULL, &dwRegType, NULL, &dwLength);
3865 if (rc == ERROR_SUCCESS && dwRegType == REG_MULTI_SZ)
3866 {
3867 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3868 if (KeyBuffer != NULL)
3869 {
3870 rc = RegQueryValueExW(hKey, lpGuidString, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3871 if (rc == ERROR_SUCCESS)
3872 {
3873 LPWSTR ptr;
3874 for (ptr = KeyBuffer; *ptr; ptr += strlenW(ptr) + 1)
3875 {
3876 /* Add coinstaller to ClassCoInstallersListHead list */
3877 struct CoInstallerElement *coinstaller;
3878 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr));
3879 coinstaller = HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement));
3880 if (!coinstaller)
3881 continue;
3882 ZeroMemory(coinstaller, sizeof(struct CoInstallerElement));
3883 if (GetFunctionPointer(ptr, &coinstaller->Module, (PVOID*)&coinstaller->Function) == ERROR_SUCCESS)
3884 InsertTailList(&ClassCoInstallersListHead, &coinstaller->ListEntry);
3885 else
3886 HeapFree(GetProcessHeap(), 0, coinstaller);
3887 }
3888 }
3889 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3890 }
3891 }
3892 RpcStringFreeW(&lpGuidString);
3893 }
3894 RegCloseKey(hKey);
3895 }
3896 }
3897 if ((CanHandle & CLASS_INSTALLER) && !(InstallParams.FlagsEx & DI_FLAGSEX_CI_FAILED))
3898 {
3899 hKey = SetupDiOpenClassRegKey(&DeviceInfoData->ClassGuid, KEY_QUERY_VALUE);
3900 if (hKey != INVALID_HANDLE_VALUE)
3901 {
3902 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, &dwRegType, NULL, &dwLength);
3903 if (rc == ERROR_SUCCESS && dwRegType == REG_SZ)
3904 {
3905 LPWSTR KeyBuffer = HeapAlloc(GetProcessHeap(), 0, dwLength);
3906 if (KeyBuffer != NULL)
3907 {
3908 rc = RegQueryValueExW(hKey, REGSTR_VAL_INSTALLER_32, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength);
3909 if (rc == ERROR_SUCCESS)
3910 {
3911 /* Get ClassInstaller function pointer */
3912 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer));
3913 if (GetFunctionPointer(KeyBuffer, &ClassInstallerLibrary, (PVOID*)&ClassInstaller) != ERROR_SUCCESS)
3914 {
3915 InstallParams.FlagsEx |= DI_FLAGSEX_CI_FAILED;
3916 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
3917 }
3918 }
3919 HeapFree(GetProcessHeap(), 0, KeyBuffer);
3920 }
3921 }
3922 RegCloseKey(hKey);
3923 }
3924 }
3925
3926 /* Call Class co-installers */
3927 Context.PostProcessing = FALSE;
3928 rc = NO_ERROR;
3929 ListEntry = ClassCoInstallersListHead.Flink;
3930 while (rc == NO_ERROR && ListEntry != &ClassCoInstallersListHead)
3931 {
3932 struct CoInstallerElement *coinstaller;
3933 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
3934 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3935 coinstaller->PrivateData = Context.PrivateData;
3936 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
3937 {
3938 coinstaller->DoPostProcessing = TRUE;
3939 rc = NO_ERROR;
3940 }
3941 ListEntry = ListEntry->Flink;
3942 }
3943
3944 /* Call Device co-installers */
3945 ListEntry = DeviceCoInstallersListHead.Flink;
3946 while (rc == NO_ERROR && ListEntry != &DeviceCoInstallersListHead)
3947 {
3948 struct CoInstallerElement *coinstaller;
3949 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
3950 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3951 coinstaller->PrivateData = Context.PrivateData;
3952 if (rc == ERROR_DI_POSTPROCESSING_REQUIRED)
3953 {
3954 coinstaller->DoPostProcessing = TRUE;
3955 rc = NO_ERROR;
3956 }
3957 ListEntry = ListEntry->Flink;
3958 }
3959
3960 /* Call Class installer */
3961 if (ClassInstaller)
3962 {
3963 rc = (*ClassInstaller)(InstallFunction, DeviceInfoSet, DeviceInfoData);
3964 FreeFunctionPointer(ClassInstallerLibrary, ClassInstaller);
3965 }
3966 else
3967 rc = ERROR_DI_DO_DEFAULT;
3968
3969 /* Call default handler */
3970 if (rc == ERROR_DI_DO_DEFAULT)
3971 {
3972 if (DefaultHandler && !(InstallParams.Flags & DI_NODI_DEFAULTACTION))
3973 {
3974 if ((*DefaultHandler)(DeviceInfoSet, DeviceInfoData))
3975 rc = NO_ERROR;
3976 else
3977 rc = GetLastError();
3978 }
3979 else
3980 rc = NO_ERROR;
3981 }
3982
3983 /* Call Class co-installers that required postprocessing */
3984 Context.PostProcessing = TRUE;
3985 ListEntry = ClassCoInstallersListHead.Flink;
3986 while (ListEntry != &ClassCoInstallersListHead)
3987 {
3988 struct CoInstallerElement *coinstaller;
3989 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
3990 if (coinstaller->DoPostProcessing)
3991 {
3992 Context.InstallResult = rc;
3993 Context.PrivateData = coinstaller->PrivateData;
3994 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
3995 }
3996 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
3997 ListEntry = ListEntry->Flink;
3998 }
3999
4000 /* Call Device co-installers that required postprocessing */
4001 ListEntry = DeviceCoInstallersListHead.Flink;
4002 while (ListEntry != &DeviceCoInstallersListHead)
4003 {
4004 struct CoInstallerElement *coinstaller;
4005 coinstaller = CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry);
4006 if (coinstaller->DoPostProcessing)
4007 {
4008 Context.InstallResult = rc;
4009 Context.PrivateData = coinstaller->PrivateData;
4010 rc = (*coinstaller->Function)(InstallFunction, DeviceInfoSet, DeviceInfoData, &Context);
4011 }
4012 FreeFunctionPointer(coinstaller->Module, coinstaller->Function);
4013 ListEntry = ListEntry->Flink;
4014 }
4015
4016 /* Free allocated memory */
4017 while (!IsListEmpty(&ClassCoInstallersListHead))
4018 {
4019 ListEntry = RemoveHeadList(&ClassCoInstallersListHead);
4020 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
4021 }
4022 while (!IsListEmpty(&DeviceCoInstallersListHead))
4023 {
4024 ListEntry = RemoveHeadList(&DeviceCoInstallersListHead);
4025 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry, struct CoInstallerElement, ListEntry));
4026 }
4027
4028 ret = (rc == NO_ERROR);
4029 }
4030 }
4031
4032 TRACE("Returning %d\n", ret);
4033 return ret;
4034 }
4035
4036 /***********************************************************************
4037 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4038 */
4039 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
4040 HDEVINFO DeviceInfoSet,
4041 PSP_DEVINFO_DATA DeviceInfoData,
4042 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
4043 {
4044 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
4045 BOOL ret = FALSE;
4046
4047 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4048
4049 if (DeviceInstallParams == NULL)
4050 SetLastError(ERROR_INVALID_PARAMETER);
4051 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_A))
4052 SetLastError(ERROR_INVALID_USER_BUFFER);
4053 else
4054 {
4055 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4056 ret = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
4057
4058 if (ret)
4059 {
4060 /* Do W->A conversion */
4061 memcpy(
4062 DeviceInstallParams,
4063 &deviceInstallParamsW,
4064 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W, DriverPath));
4065 if (WideCharToMultiByte(CP_ACP, 0, deviceInstallParamsW.DriverPath, -1,
4066 DeviceInstallParams->DriverPath, MAX_PATH, NULL, NULL) == 0)
4067 {
4068 DeviceInstallParams->DriverPath[0] = '\0';
4069 ret = FALSE;
4070 }
4071 }
4072 }
4073
4074 TRACE("Returning %d\n", ret);
4075 return ret;
4076 }
4077
4078 /***********************************************************************
4079 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4080 */
4081 BOOL WINAPI
4082 SetupDiGetDeviceInfoListClass(
4083 IN HDEVINFO DeviceInfoSet,
4084 OUT LPGUID ClassGuid)
4085 {
4086 struct DeviceInfoSet *list;
4087 BOOL ret = FALSE;
4088
4089 TRACE("%p %p\n", DeviceInfoSet, ClassGuid);
4090
4091 if (!DeviceInfoSet)
4092 SetLastError(ERROR_INVALID_HANDLE);
4093 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4094 SetLastError(ERROR_INVALID_HANDLE);
4095 else if (IsEqualIID(&list->ClassGuid, &GUID_NULL))
4096 SetLastError(ERROR_NO_ASSOCIATED_CLASS);
4097 else
4098 {
4099 memcpy(&ClassGuid, &list->ClassGuid, sizeof(GUID));
4100
4101 ret = TRUE;
4102 }
4103
4104 TRACE("Returning %d\n", ret);
4105 return ret;
4106 }
4107
4108 /***********************************************************************
4109 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4110 */
4111 BOOL WINAPI
4112 SetupDiGetDeviceInstallParamsW(
4113 IN HDEVINFO DeviceInfoSet,
4114 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4115 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4116 {
4117 struct DeviceInfoSet *list;
4118 BOOL ret = FALSE;
4119
4120 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4121
4122 if (!DeviceInfoSet)
4123 SetLastError(ERROR_INVALID_HANDLE);
4124 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4125 SetLastError(ERROR_INVALID_HANDLE);
4126 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4127 SetLastError(ERROR_INVALID_USER_BUFFER);
4128 else if (!DeviceInstallParams)
4129 SetLastError(ERROR_INVALID_PARAMETER);
4130 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
4131 SetLastError(ERROR_INVALID_USER_BUFFER);
4132 else
4133 {
4134 PSP_DEVINSTALL_PARAMS_W Source;
4135
4136 if (DeviceInfoData)
4137 Source = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
4138 else
4139 Source = &list->InstallParams;
4140 memcpy(DeviceInstallParams, Source, Source->cbSize);
4141 ret = TRUE;
4142 }
4143
4144 TRACE("Returning %d\n", ret);
4145 return ret;
4146 }
4147
4148 static BOOL
4149 CheckDeviceInstallParameters(
4150 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4151 {
4152 DWORD SupportedFlags =
4153 DI_NOVCP | /* 0x00000008 */
4154 DI_DIDCOMPAT | /* 0x00000010 */
4155 DI_DIDCLASS | /* 0x00000020 */
4156 DI_NEEDRESTART | /* 0x00000080 */
4157 DI_NEEDREBOOT | /* 0x00000100 */
4158 DI_RESOURCEPAGE_ADDED | /* 0x00002000 */
4159 DI_PROPERTIES_CHANGE | /* 0x00004000 */
4160 DI_ENUMSINGLEINF | /* 0x00010000 */
4161 DI_DONOTCALLCONFIGMG | /* 0x00020000 */
4162 DI_CLASSINSTALLPARAMS | /* 0x00100000 */
4163 DI_NODI_DEFAULTACTION | /* 0x00200000 */
4164 DI_QUIETINSTALL | /* 0x00800000 */
4165 DI_NOFILECOPY | /* 0x01000000 */
4166 DI_DRIVERPAGE_ADDED; /* 0x04000000 */
4167 DWORD SupportedFlagsEx =
4168 DI_FLAGSEX_CI_FAILED | /* 0x00000004 */
4169 DI_FLAGSEX_DIDINFOLIST | /* 0x00000010 */
4170 DI_FLAGSEX_DIDCOMPATINFO | /* 0x00000020 */
4171 DI_FLAGSEX_ALLOWEXCLUDEDDRVS | /* 0x00000800 */
4172 DI_FLAGSEX_NO_DRVREG_MODIFY | /* 0x00008000 */
4173 DI_FLAGSEX_INSTALLEDDRIVER; /* 0x04000000 */
4174 BOOL ret = FALSE;
4175
4176 /* FIXME: add support for more flags */
4177
4178 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4179 * It should be checked before accessing to other values
4180 * of the SP_DEVINSTALL_PARAMS structure */
4181
4182 if (DeviceInstallParams->Flags & ~SupportedFlags)
4183 {
4184 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams->Flags & ~SupportedFlags);
4185 SetLastError(ERROR_INVALID_FLAGS);
4186 }
4187 else if (DeviceInstallParams->FlagsEx & ~SupportedFlagsEx)
4188 {
4189 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams->FlagsEx & ~SupportedFlagsEx);
4190 SetLastError(ERROR_INVALID_FLAGS);
4191 }
4192 else if ((DeviceInstallParams->Flags & DI_NOVCP)
4193 && (DeviceInstallParams->FileQueue == NULL || DeviceInstallParams->FileQueue == (HSPFILEQ)INVALID_HANDLE_VALUE))
4194 SetLastError(ERROR_INVALID_USER_BUFFER);
4195 else
4196 {
4197 /* FIXME: check Reserved field */
4198 ret = TRUE;
4199 }
4200
4201 return ret;
4202 }
4203
4204 /***********************************************************************
4205 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4206 */
4207 BOOL WINAPI
4208 SetupDiSetDeviceInstallParamsW(
4209 IN HDEVINFO DeviceInfoSet,
4210 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
4211 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams)
4212 {
4213 struct DeviceInfoSet *list;
4214 BOOL ret = FALSE;
4215
4216 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4217
4218 if (!DeviceInfoSet)
4219 SetLastError(ERROR_INVALID_HANDLE);
4220 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4221 SetLastError(ERROR_INVALID_HANDLE);
4222 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4223 SetLastError(ERROR_INVALID_USER_BUFFER);
4224 else if (!DeviceInstallParams)
4225 SetLastError(ERROR_INVALID_PARAMETER);
4226 else if (DeviceInstallParams->cbSize != sizeof(SP_DEVINSTALL_PARAMS_W))
4227 SetLastError(ERROR_INVALID_USER_BUFFER);
4228 else if (CheckDeviceInstallParameters(DeviceInstallParams))
4229 {
4230 PSP_DEVINSTALL_PARAMS_W Destination;
4231
4232 if (DeviceInfoData)
4233 Destination = &((struct DeviceInfo *)DeviceInfoData->Reserved)->InstallParams;
4234 else
4235 Destination = &list->InstallParams;
4236 memcpy(Destination, DeviceInstallParams, DeviceInstallParams->cbSize);
4237 ret = TRUE;
4238 }
4239
4240 TRACE("Returning %d\n", ret);
4241 return ret;
4242 }
4243
4244 BOOL WINAPI SetupDiSetDeviceInstallParamsA(
4245 HDEVINFO DeviceInfoSet,
4246 PSP_DEVINFO_DATA DeviceInfoData,
4247 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
4248 {
4249 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW;
4250 int len = 0;
4251 BOOL ret = FALSE;
4252
4253 TRACE("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
4254
4255 if (DeviceInstallParams == NULL)
4256 SetLastError(ERROR_INVALID_PARAMETER);
4257 else if (DeviceInstallParams->cbSize < sizeof(SP_DEVINSTALL_PARAMS_A))
4258 SetLastError(ERROR_INVALID_USER_BUFFER);
4259 else
4260 {
4261 memcpy(&deviceInstallParamsW, DeviceInstallParams, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A, DriverPath));
4262 deviceInstallParamsW.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4263 len = MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, NULL, 0);
4264 if (!len)
4265 {
4266 ERR("DrivePath is NULL\n");
4267 ret = FALSE;
4268 }
4269 else
4270 {
4271 MultiByteToWideChar(CP_ACP, 0, DeviceInstallParams->DriverPath, -1, deviceInstallParamsW.DriverPath, len);
4272 ret = SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &deviceInstallParamsW);
4273 }
4274 }
4275
4276 TRACE("Returning %d\n", ret);
4277 return ret;
4278 }
4279
4280 static HKEY
4281 OpenHardwareProfileKey(
4282 IN HKEY HKLM,
4283 IN DWORD HwProfile,
4284 IN DWORD samDesired)
4285 {
4286 HKEY hHWProfilesKey = NULL;
4287 HKEY hHWProfileKey = NULL;
4288 HKEY ret = INVALID_HANDLE_VALUE;
4289 LONG rc;
4290
4291 rc = RegOpenKeyExW(HKLM,
4292 REGSTR_PATH_HWPROFILES,
4293 0,
4294 0,
4295 &hHWProfilesKey);
4296 if (rc != ERROR_SUCCESS)
4297 {
4298 SetLastError(rc);
4299 goto cleanup;
4300 }
4301 if (HwProfile == 0)
4302 {
4303 rc = RegOpenKeyExW(
4304 hHWProfilesKey,
4305 REGSTR_KEY_CURRENT,
4306 0,
4307 KEY_CREATE_SUB_KEY,
4308 &hHWProfileKey);
4309 }
4310 else
4311 {
4312 WCHAR subKey[5];
4313 snprintfW(subKey, 4, InstanceKeyFormat, HwProfile);
4314 subKey[4] = '\0';
4315 rc = RegOpenKeyExW(
4316 hHWProfilesKey,
4317 subKey,
4318 0,
4319 KEY_CREATE_SUB_KEY,
4320 &hHWProfileKey);
4321 }
4322 if (rc != ERROR_SUCCESS)
4323 {
4324 SetLastError(rc);
4325 goto cleanup;
4326 }
4327 ret = hHWProfileKey;
4328
4329 cleanup:
4330 if (hHWProfilesKey != NULL)
4331 RegCloseKey(hHWProfilesKey);
4332 if (hHWProfileKey != NULL && hHWProfileKey != ret)
4333 RegCloseKey(hHWProfileKey);
4334 return ret;
4335 }
4336
4337 /***********************************************************************
4338 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4339 */
4340 BOOL WINAPI
4341 SetupDiDeleteDeviceInfo(
4342 IN HDEVINFO DeviceInfoSet,
4343 IN PSP_DEVINFO_DATA DeviceInfoData)
4344 {
4345 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4346
4347 FIXME("not implemented\n");
4348 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4349 return FALSE;
4350 }
4351
4352
4353 /***********************************************************************
4354 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4355 */
4356 BOOL WINAPI
4357 SetupDiOpenDeviceInfoA(
4358 IN HDEVINFO DeviceInfoSet,
4359 IN PCSTR DeviceInstanceId,
4360 IN HWND hwndParent OPTIONAL,
4361 IN DWORD OpenFlags,
4362 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4363 {
4364 LPWSTR DeviceInstanceIdW = NULL;
4365 BOOL bResult;
4366
4367 TRACE("%p %s %p %lx %p\n", DeviceInfoSet, DeviceInstanceId, hwndParent, OpenFlags, DeviceInfoData);
4368
4369 DeviceInstanceIdW = MultiByteToUnicode(DeviceInstanceId, CP_ACP);
4370 if (DeviceInstanceIdW == NULL)
4371 return FALSE;
4372
4373 bResult = SetupDiOpenDeviceInfoW(DeviceInfoSet,
4374 DeviceInstanceIdW, hwndParent, OpenFlags, DeviceInfoData);
4375
4376 MyFree(DeviceInstanceIdW);
4377
4378 return bResult;
4379 }
4380
4381
4382 /***********************************************************************
4383 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4384 */
4385 BOOL WINAPI
4386 SetupDiOpenDeviceInfoW(
4387 IN HDEVINFO DeviceInfoSet,
4388 IN PCWSTR DeviceInstanceId,
4389 IN HWND hwndParent OPTIONAL,
4390 IN DWORD OpenFlags,
4391 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4392 {
4393 struct DeviceInfoSet *list;
4394 HKEY hEnumKey, hKey = NULL;
4395 DWORD rc, dwSize;
4396 BOOL ret = FALSE;
4397
4398 TRACE("%p %s %p %lx %p\n",
4399 DeviceInfoSet, debugstr_w(DeviceInstanceId),
4400 hwndParent, OpenFlags, DeviceInfoData);
4401
4402 if (OpenFlags & DIOD_CANCEL_REMOVE)
4403 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4404
4405 if (!DeviceInfoSet)
4406 SetLastError(ERROR_INVALID_HANDLE);
4407 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4408 SetLastError(ERROR_INVALID_HANDLE);
4409 else if (!DeviceInstanceId)
4410 SetLastError(ERROR_INVALID_PARAMETER);
4411 else if (OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS))
4412 {
4413 TRACE("Unknown flags: 0x%08lx\n", OpenFlags & ~(DIOD_CANCEL_REMOVE | DIOD_INHERIT_CLASSDRVS));
4414 SetLastError(ERROR_INVALID_FLAGS);
4415 }
4416 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4417 SetLastError(ERROR_INVALID_USER_BUFFER);
4418 else
4419 {
4420 struct DeviceInfo *deviceInfo = NULL;
4421 /* Search if device already exists in DeviceInfoSet.
4422 * If yes, return the existing element
4423 * If no, create a new element using information in registry
4424 */
4425 PLIST_ENTRY ItemList = list->ListHead.Flink;
4426 while (ItemList != &list->ListHead)
4427 {
4428 // TODO
4429 //if (good one)
4430 // break;
4431 FIXME("not implemented\n");
4432 ItemList = ItemList->Flink;
4433 }
4434
4435 if (deviceInfo)
4436 {
4437 /* good one found */
4438 ret = TRUE;
4439 }
4440 else
4441 {
4442 GUID ClassGUID;
4443 WCHAR szClassGuid[MAX_GUID_STRING_LEN];
4444
4445 /* Open supposed registry key */
4446 rc = RegOpenKeyExW(
4447 list->HKLM,
4448 REGSTR_PATH_SYSTEMENUM,
4449 0, /* Options */
4450 0,
4451 &hEnumKey);
4452 if (rc != ERROR_SUCCESS)
4453 {
4454 SetLastError(rc);
4455 goto cleanup;
4456 }
4457 rc = RegOpenKeyExW(
4458 hEnumKey,
4459 DeviceInstanceId,
4460 0, /* Options */
4461 KEY_QUERY_VALUE,
4462 &hKey);
4463 RegCloseKey(hEnumKey);
4464 if (rc != ERROR_SUCCESS)
4465 {
4466 if (rc == ERROR_FILE_NOT_FOUND)
4467 rc = ERROR_NO_SUCH_DEVINST;
4468 SetLastError(rc);
4469 goto cleanup;
4470 }
4471
4472 ClassGUID = GUID_NULL;
4473 dwSize = MAX_GUID_STRING_LEN * sizeof(WCHAR);
4474
4475 if (RegQueryValueExW(hKey,
4476 REGSTR_VAL_CLASSGUID,
4477 NULL,
4478 NULL,
4479 (LPBYTE)szClassGuid,
4480 &dwSize) == ERROR_SUCCESS)
4481 {
4482 szClassGuid[MAX_GUID_STRING_LEN - 2] = UNICODE_NULL;
4483
4484 /* Convert a string to a ClassGuid */
4485 UuidFromStringW(&szClassGuid[1], &ClassGUID);
4486 }
4487
4488 if (!CreateDeviceInfo(list, DeviceInstanceId, &ClassGUID, &deviceInfo))
4489 goto cleanup;
4490
4491 InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
4492
4493 ret = TRUE;
4494 }
4495
4496 if (ret && deviceInfo && DeviceInfoData)
4497 {
4498 memcpy(&DeviceInfoData->ClassGuid, &deviceInfo->ClassGuid, sizeof(GUID));
4499 DeviceInfoData->DevInst = deviceInfo->dnDevInst;
4500 DeviceInfoData->Reserved = (ULONG_PTR)deviceInfo;
4501 }
4502 }
4503
4504 cleanup:
4505 if (hKey != NULL)
4506 RegCloseKey(hKey);
4507 return ret;
4508 }
4509
4510
4511 /***********************************************************************
4512 * SetupDiGetSelectedDevice (SETUPAPI.@)
4513 */
4514 BOOL WINAPI
4515 SetupDiGetSelectedDevice(
4516 IN HDEVINFO DeviceInfoSet,
4517 OUT PSP_DEVINFO_DATA DeviceInfoData)
4518 {
4519 struct DeviceInfoSet *list;
4520 BOOL ret = FALSE;
4521
4522 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4523
4524 if (!DeviceInfoSet)
4525 SetLastError(ERROR_INVALID_HANDLE);
4526 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4527 SetLastError(ERROR_INVALID_HANDLE);
4528 else if (list->SelectedDevice == NULL)
4529 SetLastError(ERROR_NO_DEVICE_SELECTED);
4530 else if (!DeviceInfoData)
4531 SetLastError(ERROR_INVALID_PARAMETER);
4532 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4533 SetLastError(ERROR_INVALID_USER_BUFFER);
4534 else
4535 {
4536 memcpy(&DeviceInfoData->ClassGuid,
4537 &list->SelectedDevice->ClassGuid,
4538 sizeof(GUID));
4539 DeviceInfoData->DevInst = list->SelectedDevice->dnDevInst;
4540 DeviceInfoData->Reserved = (ULONG_PTR)list->SelectedDevice;
4541 ret = TRUE;
4542 }
4543
4544 TRACE("Returning %d\n", ret);
4545 return ret;
4546 }
4547
4548
4549 /***********************************************************************
4550 * SetupDiSetSelectedDevice (SETUPAPI.@)
4551 */
4552 BOOL WINAPI
4553 SetupDiSetSelectedDevice(
4554 IN HDEVINFO DeviceInfoSet,
4555 IN PSP_DEVINFO_DATA DeviceInfoData)
4556 {
4557 struct DeviceInfoSet *list;
4558 BOOL ret = FALSE;
4559
4560 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4561
4562 if (!DeviceInfoSet)
4563 SetLastError(ERROR_INVALID_HANDLE);
4564 else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4565 SetLastError(ERROR_INVALID_HANDLE);
4566 else if (!DeviceInfoData)
4567 SetLastError(ERROR_INVALID_PARAMETER);
4568 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4569 SetLastError(ERROR_INVALID_USER_BUFFER);
4570 else if (DeviceInfoData->Reserved == 0)
4571 SetLastError(ERROR_INVALID_USER_BUFFER);
4572 else
4573 {
4574 list->SelectedDevice = (struct DeviceInfo *)DeviceInfoData->Reserved;
4575 ret = TRUE;
4576 }
4577
4578 TRACE("Returning %d\n", ret);
4579 return ret;
4580 }
4581
4582
4583 /* Return the current hardware profile id, or -1 if error */
4584 static DWORD
4585 SETUPAPI_GetCurrentHwProfile(
4586 IN HDEVINFO DeviceInfoSet)
4587 {
4588 HKEY hKey = NULL;
4589 DWORD dwRegType, dwLength;
4590 DWORD hwProfile;
4591 LONG rc;
4592 DWORD ret = (DWORD)-1;
4593
4594 rc = RegOpenKeyExW(
4595 ((struct DeviceInfoSet *)DeviceInfoSet)->HKLM,
4596 REGSTR_PATH_IDCONFIGDB,
4597 0, /* Options */
4598 KEY_QUERY_VALUE,
4599 &hKey);
4600 if (rc != ERROR_SUCCESS)
4601 {
4602 SetLastError(rc);
4603 goto cleanup;
4604 }
4605
4606 dwLength = sizeof(DWORD);
4607 rc = RegQueryValueExW(
4608 hKey,
4609 REGSTR_VAL_CURRENTCONFIG,
4610 NULL,
4611 &dwRegType,
4612 (LPBYTE)&hwProfile, &dwLength);
4613 if (rc != ERROR_SUCCESS)
4614 {
4615 SetLastError(rc);
4616 goto cleanup;
4617 }
4618 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
4619 {
4620 SetLastError(ERROR_GEN_FAILURE);
4621 goto cleanup;
4622 }
4623
4624 ret = hwProfile;
4625
4626 cleanup:
4627 if (hKey != NULL)
4628 RegCloseKey(hKey);
4629
4630 return ret;
4631 }
4632
4633 static BOOL
4634 ResetDevice(
4635 IN HDEVINFO DeviceInfoSet,
4636 IN PSP_DEVINFO_DATA DeviceInfoData)
4637 {
4638 #ifndef __WINESRC__
4639 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
4640 struct DeviceInfo *deviceInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
4641 CONFIGRET cr;
4642
4643 cr = CM_Enable_DevNode_Ex(deviceInfo->dnDevInst, 0, set->hMachine);
4644 if (cr != CR_SUCCESS)
4645 {
4646 SetLastError(GetErrorCodeFromCrCode(cr));
4647 return FALSE;
4648 }
4649
4650 return TRUE;
4651 #else
4652 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
4653 return TRUE;
4654 #endif
4655 }
4656
4657 static BOOL StopDevice(
4658 IN HDEVINFO DeviceInfoSet,
4659 IN PSP_DEVINFO_DATA DeviceInfoData)
4660 {
4661 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet, DeviceInfoData);
4662 return TRUE;
4663 }
4664
4665 /***********************************************************************
4666 * SetupDiChangeState (SETUPAPI.@)
4667 */
4668 BOOL WINAPI
4669 SetupDiChangeState(
4670 IN HDEVINFO DeviceInfoSet,
4671 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
4672 {
4673 PSP_PROPCHANGE_PARAMS PropChange;
4674 HKEY hKey = INVALID_HANDLE_VALUE;
4675 LPCWSTR RegistryValueName;
4676 DWORD dwConfigFlags, dwLength, dwRegType;
4677 LONG rc;
4678 BOOL ret = FALSE;
4679
4680 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4681
4682 if (!DeviceInfoData)
4683 PropChange = ((struct DeviceInfoSet *)DeviceInfoSet)->ClassInstallParams.PropChangeParams;
4684 else
4685 PropChange = ((struct DeviceInfo *)DeviceInfoData->Reserved)->ClassInstallParams.PropChangeParams;
4686 if (!PropChange)
4687 {
4688 SetLastError(ERROR_INVALID_PARAMETER);
4689 goto cleanup;
4690 }
4691
4692 if (PropChange->Scope == DICS_FLAG_GLOBAL)
4693 RegistryValueName = REGSTR_VAL_CONFIGFLAGS;
4694 else
4695 RegistryValueName = REGSTR_VAL_CSCONFIGFLAGS;
4696
4697 switch (PropChange->StateChange)
4698 {
4699 case DICS_ENABLE:
4700 case DICS_DISABLE:
4701 {
4702 /* Enable/disable device in registry */
4703 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, KEY_QUERY_VALUE | KEY_SET_VALUE);
4704 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
4705 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, PropChange->Scope, PropChange->HwProfile, DIREG_DEV, NULL, NULL);
4706 if (hKey == INVALID_HANDLE_VALUE)
4707 break;
4708 dwLength = sizeof(DWORD);
4709 rc = RegQueryValueExW(
4710 hKey,
4711 RegistryValueName,
4712 NULL,
4713 &dwRegType,
4714 (LPBYTE)&dwConfigFlags, &dwLength);
4715 if (rc == ERROR_FILE_NOT_FOUND)
4716 dwConfigFlags = 0;
4717 else if (rc != ERROR_SUCCESS)
4718 {
4719 SetLastError(rc);
4720 goto cleanup;
4721 }
4722 else if (dwRegType != REG_DWORD || dwLength != sizeof(DWORD))
4723 {
4724 SetLastError(ERROR_GEN_FAILURE);
4725 goto cleanup;
4726 }
4727 if (PropChange->StateChange == DICS_ENABLE)
4728 dwConfigFlags &= ~(PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
4729 else
4730 dwConfigFlags |= (PropChange->Scope == DICS_FLAG_GLOBAL ? CONFIGFLAG_DISABLED : CSCONFIGFLAG_DISABLED);
4731 rc = RegSetValueExW(
4732 hKey,
4733 RegistryValueName,
4734 0,
4735 REG_DWORD,
4736 (LPBYTE)&dwConfigFlags, sizeof(DWORD));
4737 if (rc != ERROR_SUCCESS)
4738 {
4739 SetLastError(rc);
4740 goto cleanup;
4741 }
4742
4743 /* Enable/disable device if needed */
4744 if (PropChange->Scope == DICS_FLAG_GLOBAL
4745 || PropChange->HwProfile == 0
4746 || PropChange->HwProfile == SETUPAPI_GetCurrentHwProfile(DeviceInfoSet))
4747 {
4748 if (PropChange->StateChange == DICS_ENABLE)
4749 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
4750 else
4751 ret = StopDevice(DeviceInfoSet, DeviceInfoData);
4752 }
4753 else
4754 ret = TRUE;
4755 break;
4756 }
4757 case DICS_PROPCHANGE:
4758 {
4759 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
4760 break;
4761 }
4762 default:
4763 {
4764 ERR("Unknown StateChange 0x%lx\n", PropChange->StateChange);
4765 SetLastError(ERROR_NOT_SUPPORTED);
4766 }
4767 }
4768
4769 cleanup:
4770 if (hKey != INVALID_HANDLE_VALUE)
4771 RegCloseKey(hKey);
4772
4773 TRACE("Returning %d\n", ret);
4774 return ret;
4775 }
4776
4777 /***********************************************************************
4778 * SetupDiSelectDevice (SETUPAPI.@)
4779 */
4780 BOOL WINAPI
4781 SetupDiSelectDevice(
4782 IN HDEVINFO DeviceInfoSet,
4783 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
4784 {
4785 FIXME("%p %p\n", DeviceInfoSet, DeviceInfoData);
4786 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
4787 return FALSE;
4788 }
4789
4790
4791 /***********************************************************************
4792 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
4793 */
4794 BOOL WINAPI
4795 SetupDiRegisterCoDeviceInstallers(
4796 IN HDEVINFO DeviceInfoSet,
4797 IN PSP_DEVINFO_DATA DeviceInfoData)
4798 {
4799 BOOL ret = FALSE; /* Return value */
4800
4801 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4802
4803 if (!DeviceInfoSet)
4804 SetLastError(ERROR_INVALID_PARAMETER);
4805 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
4806 SetLastError(ERROR_INVALID_HANDLE);
4807 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4808 SetLastError(ERROR_INVALID_HANDLE);
4809 else if (!DeviceInfoData)
4810 SetLastError(ERROR_INVALID_PARAMETER);
4811 else if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4812 SetLastError(ERROR_INVALID_USER_BUFFER);
4813 else
4814 {
4815 SP_DEVINSTALL_PARAMS_W InstallParams;
4816 struct DriverInfoElement *SelectedDriver;
4817 BOOL Result;
4818 DWORD DoAction;
4819 WCHAR SectionName[MAX_PATH];
4820 DWORD SectionNameLength = 0;
4821 HKEY hKey = INVALID_HANDLE_VALUE;
4822 PVOID Context = NULL;
4823
4824 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4825 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4826 if (!Result)
4827 goto cleanup;
4828
4829 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
4830 if (SelectedDriver == NULL)
4831 {
4832 SetLastError(ERROR_NO_DRIVER_SELECTED);
4833 goto cleanup;
4834 }
4835
4836 /* Get .CoInstallers section name */
4837 Result = SetupDiGetActualSectionToInstallW(
4838 SelectedDriver->InfFileDetails->hInf,
4839 SelectedDriver->Details.SectionName,
4840 SectionName, MAX_PATH, &SectionNameLength, NULL);
4841 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotCoInstallers) - 1)
4842 goto cleanup;
4843 lstrcatW(SectionName, DotCoInstallers);
4844
4845 /* Open/Create driver key information */
4846 #if _WIN32_WINNT >= 0x502
4847 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
4848 #else
4849 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
4850 #endif
4851 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
4852 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
4853 if (hKey == INVALID_HANDLE_VALUE)
4854 goto cleanup;
4855
4856 /* Install .CoInstallers section */
4857 DoAction = SPINST_REGISTRY;
4858 if (!(InstallParams.Flags & DI_NOFILECOPY))
4859 {
4860 DoAction |= SPINST_FILES;
4861 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
4862 if (!Context)
4863 goto cleanup;
4864 }
4865 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
4866 SelectedDriver->InfFileDetails->hInf, SectionName,
4867 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
4868 SetupDefaultQueueCallbackW, Context,
4869 DeviceInfoSet, DeviceInfoData);
4870 if (!Result)
4871 goto cleanup;
4872
4873 ret = TRUE;
4874
4875 cleanup:
4876 if (Context)
4877 SetupTermDefaultQueueCallback(Context);
4878 if (hKey != INVALID_HANDLE_VALUE)
4879 RegCloseKey(hKey);
4880 }
4881
4882 TRACE("Returning %d\n", ret);
4883 return ret;
4884 }
4885
4886 static BOOL
4887 InfIsFromOEMLocation(
4888 IN PCWSTR FullName,
4889 OUT LPBOOL IsOEMLocation)
4890 {
4891 PWCHAR last;
4892
4893 last = strrchrW(FullName, '\\');
4894 if (!last)
4895 {
4896 /* No directory specified */
4897 *IsOEMLocation = FALSE;
4898 }
4899 else
4900 {
4901 LPWSTR Windir;
4902 UINT ret;
4903
4904 Windir = MyMalloc((MAX_PATH + 1 + strlenW(InfDirectory)) * sizeof(WCHAR));
4905 if (!Windir)
4906 {
4907 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
4908 return FALSE;
4909 }
4910
4911 ret = GetSystemWindowsDirectoryW(Windir, MAX_PATH);
4912 if (ret == 0 || ret > MAX_PATH)
4913 {
4914 MyFree(Windir);
4915 SetLastError(ERROR_GEN_FAILURE);
4916 return FALSE;
4917 }
4918 if (*Windir && Windir[strlenW(Windir) - 1] != '\\')
4919 strcatW(Windir, BackSlash);
4920 strcatW(Windir, InfDirectory);
4921
4922 if (strncmpiW(FullName, Windir, last - FullName) == 0)
4923 {
4924 /* The path is %SYSTEMROOT%\Inf */
4925 *IsOEMLocation = FALSE;
4926 }
4927 else
4928 {
4929 /* The file is in another place */
4930 *IsOEMLocation = TRUE;
4931 }
4932 MyFree(Windir);
4933 }
4934 return TRUE;
4935 }
4936
4937 /***********************************************************************
4938 * SetupDiInstallDevice (SETUPAPI.@)
4939 */
4940 BOOL WINAPI
4941 SetupDiInstallDevice(
4942 IN HDEVINFO DeviceInfoSet,
4943 IN OUT PSP_DEVINFO_DATA DeviceInfoData)
4944 {
4945 SP_DEVINSTALL_PARAMS_W InstallParams;
4946 struct DriverInfoElement *SelectedDriver;
4947 SYSTEMTIME DriverDate;
4948 WCHAR SectionName[MAX_PATH];
4949 WCHAR Buffer[32];
4950 DWORD SectionNameLength = 0;
4951 BOOL Result = FALSE;
4952 ULONG DoAction;
4953 DWORD RequiredSize;
4954 LPWSTR pSectionName = NULL;
4955 WCHAR ClassName[MAX_CLASS_NAME_LEN];
4956 GUID ClassGuid;
4957 LPWSTR lpGuidString = NULL, lpFullGuidString = NULL;
4958 BOOL RebootRequired = FALSE;
4959 HKEY hKey = INVALID_HANDLE_VALUE;
4960 BOOL NeedtoCopyFile;
4961 LARGE_INTEGER fullVersion;
4962 LONG rc;
4963 PVOID Context = NULL;
4964 BOOL ret = FALSE; /* Return value */
4965
4966 TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
4967
4968 if (!DeviceInfoSet)
4969 SetLastError(ERROR_INVALID_PARAMETER);
4970 else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
4971 SetLastError(ERROR_INVALID_HANDLE);
4972 else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
4973 SetLastError(ERROR_INVALID_HANDLE);
4974 else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
4975 SetLastError(ERROR_INVALID_USER_BUFFER);
4976 else
4977 Result = TRUE;
4978
4979 if (!Result)
4980 {
4981 /* One parameter is bad */
4982 goto cleanup;
4983 }
4984
4985 InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
4986 Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
4987 if (!Result)
4988 goto cleanup;
4989
4990 if (InstallParams.FlagsEx & DI_FLAGSEX_SETFAILEDINSTALL)
4991 {
4992 /* Set FAILEDINSTALL in ConfigFlags registry value */
4993 DWORD ConfigFlags, regType;
4994 Result = SetupDiGetDeviceRegistryPropertyW(
4995 DeviceInfoSet,
4996 DeviceInfoData,
4997 SPDRP_CONFIGFLAGS,
4998 &regType,
4999 (PBYTE)&ConfigFlags,
5000 sizeof(ConfigFlags),
5001 NULL);
5002 if (!Result || regType != REG_DWORD)
5003 {
5004 SetLastError(ERROR_GEN_FAILURE);
5005 goto cleanup;
5006 }
5007 ConfigFlags |= DNF_DISABLED;
5008 Result = SetupDiSetDeviceRegistryPropertyW(
5009 DeviceInfoSet,
5010 DeviceInfoData,
5011 SPDRP_CONFIGFLAGS,
5012 (PBYTE)&ConfigFlags,
5013 sizeof(ConfigFlags));
5014 if (!Result)
5015 {
5016 SetLastError(ERROR_GEN_FAILURE);
5017 goto cleanup;
5018 }
5019
5020 ret = TRUE;
5021 goto cleanup;
5022 }
5023
5024 SelectedDriver = (struct DriverInfoElement *)InstallParams.Reserved;
5025 if (SelectedDriver == NULL)
5026 {
5027 SetLastError(ERROR_NO_DRIVER_SELECTED);
5028 goto cleanup;
5029 }
5030
5031 FileTimeToSystemTime(&SelectedDriver->Info.DriverDate, &DriverDate);
5032
5033 Result = SetupDiGetActualSectionToInstallW(
5034 SelectedDriver->InfFileDetails->hInf,
5035 SelectedDriver->Details.SectionName,
5036 SectionName, MAX_PATH, &SectionNameLength, NULL);
5037 if (!Result || SectionNameLength > MAX_PATH - strlenW(DotServices))
5038 goto cleanup;
5039 pSectionName = &SectionName[strlenW(SectionName)];
5040
5041 /* Get information from [Version] section */
5042 if (!SetupDiGetINFClassW(SelectedDriver->Details.InfFileName, &ClassGuid, ClassName, MAX_CLASS_NAME_LEN, &RequiredSize))
5043 goto cleanup;
5044 /* Format ClassGuid to a string */
5045 if (UuidToStringW((UUID*)&ClassGuid, &lpGuidString) != RPC_S_OK)
5046 goto cleanup;
5047 RequiredSize = lstrlenW(lpGuidString);
5048 lpFullGuidString = HeapAlloc(GetProcessHeap(), 0, (RequiredSize + 3) * sizeof(WCHAR));
5049 if (!lpFullGuidString)
5050 {
5051 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5052 goto cleanup;
5053 }
5054 lpFullGuidString[0] = '{';
5055 memcpy(&lpFullGuidString[1], lpGuidString, RequiredSize * sizeof(WCHAR));
5056 lpFullGuidString[RequiredSize + 1] = '}';
5057 lpFullGuidString[RequiredSize + 2] = '\0';
5058
5059 /* Copy .inf file to Inf\ directory (if needed) */
5060 Result = InfIsFromOEMLocation(SelectedDriver->Details.InfFileName, &NeedtoCopyFile);
5061 if (!Result)
5062 goto cleanup;
5063 if (NeedtoCopyFile)
5064 {
5065 WCHAR NewFileName[MAX_PATH];
5066 struct InfFileDetails *newInfFileDetails;
5067 Result = SetupCopyOEMInfW(
5068 SelectedDriver->Details.InfFileName,
5069 NULL,
5070 SPOST_NONE,
5071 SP_COPY_NOOVERWRITE,
5072 NewFileName, MAX_PATH,
5073 NULL,
5074 NULL);
5075 if (!Result)
5076 goto cleanup;
5077 /* Create a new struct InfFileDetails, and set it to
5078 * SelectedDriver->InfFileDetails, to release use of
5079 * current InfFile */
5080 newInfFileDetails = CreateInfFileDetails(NewFileName);
5081 if (!newInfFileDetails)
5082 goto cleanup;
5083 DereferenceInfFile(SelectedDriver->InfFileDetails);
5084 SelectedDriver->InfFileDetails = newInfFileDetails;
5085 strcpyW(SelectedDriver->Details.InfFileName, NewFileName);
5086 }
5087
5088 /* Open/Create driver key information */
5089 #if _WIN32_WINNT >= 0x502
5090 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_READ | KEY_WRITE);
5091 #else
5092 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_ALL_ACCESS);
5093 #endif
5094 if (hKey == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND)
5095 hKey = SetupDiCreateDevRegKeyW(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, NULL, NULL);
5096 if (hKey == INVALID_HANDLE_VALUE)
5097 goto cleanup;
5098
5099 /* Install main section */
5100 DoAction = 0;
5101 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
5102 DoAction |= SPINST_REGISTRY;
5103 if (!(InstallParams.Flags & DI_NOFILECOPY))
5104 {
5105 DoAction |= SPINST_FILES;
5106 Context = SetupInitDefaultQueueCallback(InstallParams.hwndParent);
5107 if (!Context)
5108 goto cleanup;
5109 }
5110 *pSectionName = '\0';
5111 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5112 SelectedDriver->InfFileDetails->hInf, SectionName,
5113 DoAction, hKey, SelectedDriver->InfFileDetails->DirectoryName, SP_COPY_NEWER,
5114 SetupDefaultQueueCallbackW, Context,
5115 DeviceInfoSet, DeviceInfoData);
5116 if (!Result)
5117 goto cleanup;
5118 InstallParams.Flags |= DI_NOFILECOPY;
5119 SetupDiSetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
5120
5121 /* Write information to driver key */
5122 *pSectionName = UNICODE_NULL;
5123 memcpy(&fullVersion, &SelectedDriver->Info.DriverVersion, sizeof(LARGE_INTEGER));
5124 TRACE("Write information to driver key\n");
5125 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
5126 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
5127 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
5128 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver->InfFileDetails->FileName));
5129 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver->Details.SectionName));
5130 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName[strlenW(SelectedDriver->Details.SectionName)]));
5131 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver->MatchingId));
5132 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver->Info.ProviderName));
5133 sprintfW(Buffer, DateFormat, DriverDate.wMonth, DriverDate.wDay, DriverDate.wYear);
5134 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
5135 if (rc == ERROR_SUCCESS)
5136 rc = RegSetValueExW(hKey, REGSTR_DRIVER_DATE_DATA, 0, REG_BINARY, (const BYTE *)&SelectedDriver->Info.DriverDate, sizeof(FILETIME));
5137 if (rc == ERROR_SUCCESS)
5138 rc = RegSetValueExW(hKey, REGSTR_VAL_DRVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
5139 if (rc == ERROR_SUCCESS)
5140 {
5141 sprintfW(Buffer, VersionFormat, fullVersion.HighPart >> 16, fullVersion.HighPart & 0xffff, fullVersion.LowPart >> 16, fullVersion.LowPart & 0xffff);
5142 rc = RegSetValueExW(hKey, REGSTR_DRIVER_VERSION, 0, REG_SZ, (const BYTE *)Buffer, (strlenW(Buffer) + 1) * sizeof(WCHAR));
5143 }
5144 if (rc == ERROR_SUCCESS)
5145 rc = RegSetValueExW(hKey, REGSTR_VAL_INFPATH, 0, REG_SZ, (const BYTE *)SelectedDriver->InfFileDetails->FileName, (strlenW(SelectedDriver->InfFileDetails->FileName) + 1) * sizeof(WCHAR));
5146 if (rc == ERROR_SUCCESS)
5147 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTION, 0, REG_SZ, (const BYTE *)SelectedDriver->Details.SectionName, (strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
5148 if (rc == ERROR_SUCCESS)
5149 rc = RegSetValueExW(hKey, REGSTR_VAL_INFSECTIONEXT, 0, REG_SZ, (const BYTE *)&SectionName[strlenW(SelectedDriver->Details.SectionName)], (strlenW(SectionName) - strlenW(SelectedDriver->Details.SectionName) + 1) * sizeof(WCHAR));
5150 if (rc == ERROR_SUCCESS)
5151 rc = RegSetValueExW(hKey, REGSTR_VAL_MATCHINGDEVID, 0, REG_SZ, (const BYTE *)SelectedDriver->MatchingId, (strlenW(SelectedDriver->MatchingId) + 1) * sizeof(WCHAR));
5152 if (rc == ERROR_SUCCESS)
5153 rc = RegSetValueExW(hKey, REGSTR_VAL_PROVIDER_NAME, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.ProviderName, (strlenW(SelectedDriver->Info.ProviderName) + 1) * sizeof(WCHAR));
5154 if (rc != ERROR_SUCCESS)
5155 {
5156 SetLastError(rc);
5157 goto cleanup;
5158 }
5159 RegCloseKey(hKey);
5160 hKey = INVALID_HANDLE_VALUE;
5161
5162 /* FIXME: Process .LogConfigOverride section */
5163
5164 /* Install .Services section */
5165 strcpyW(pSectionName, DotServices);
5166 Result = SetupInstallServicesFromInfSectionExW(
5167 SelectedDriver->InfFileDetails->hInf,
5168 SectionName,
5169 0,
5170 DeviceInfoSet,
5171 DeviceInfoData,
5172 NULL,
5173 NULL);
5174 if (!Result)
5175 goto cleanup;
5176 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED)
5177 RebootRequired = TRUE;
5178
5179 /* Open device registry key */
5180 hKey = SetupDiOpenDevRegKey(DeviceInfoSet, DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_SET_VALUE);
5181 if (hKey == INVALID_HANDLE_VALUE)
5182 goto cleanup;
5183
5184 /* Install .HW section */
5185 DoAction = 0;
5186 if (!(InstallParams.FlagsEx & DI_FLAGSEX_NO_DRVREG_MODIFY))
5187 DoAction |= SPINST_REGISTRY;
5188 strcpyW(pSectionName, DotHW);
5189 Result = SetupInstallFromInfSectionW(InstallParams.hwndParent,
5190 SelectedDriver->InfFileDetails->hInf, SectionName,
5191 DoAction, hKey, NULL, 0,
5192 NULL, NULL,
5193 DeviceInfoSet, DeviceInfoData);
5194 if (!Result)
5195 goto cleanup;
5196
5197 /* Write information to enum key */
5198 TRACE("Write information to enum key\n");
5199 TRACE("Class : '%s'\n", debugstr_w(ClassName));
5200 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString));
5201 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver->Info.Description));
5202 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver->Info.MfgName));
5203 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASS, 0, REG_SZ, (const BYTE *)ClassName, (strlenW(ClassName) + 1) * sizeof(WCHAR));
5204 if (rc == ERROR_SUCCESS)
5205 rc = RegSetValueExW(hKey, REGSTR_VAL_CLASSGUID, 0, REG_SZ, (const BYTE *)lpFullGuidString, (strlenW(lpFullGuidString) + 1) * sizeof(WCHAR));
5206 if (rc == ERROR_SUCCESS)
5207 rc = RegSetValueExW(hKey, REGSTR_VAL_DEVDESC, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.Description, (strlenW(SelectedDriver->Info.Description) + 1) * sizeof(WCHAR));
5208 if (rc == ERROR_SUCCESS)
5209 rc = RegSetValueExW(hKey, REGSTR_VAL_MFG, 0, REG_SZ, (const BYTE *)SelectedDriver->Info.MfgName, (strlenW(SelectedDriver->Info.MfgName) + 1) * sizeof(WCHAR));
5210 if (rc != ERROR_SUCCESS)
5211 {
5212 SetLastError(rc);
5213 goto cleanup;
5214 }
5215
5216 /* Start the device */
5217 if (!RebootRequired && !(InstallParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT | DI_DONOTCALLCONFIGMG)))
5218 ret = ResetDevice(DeviceInfoSet, DeviceInfoData);
5219 else
5220 ret = TRUE;
5221
5222 cleanup:
5223 /* End of installation */
5224 if (hKey != INVALID_HANDLE_VALUE)
5225 RegCloseKey(hKey);
5226 if (lpGuidString)
5227 RpcStringFreeW(&lpGuidString);
5228 HeapFree(GetProcessHeap(), 0, lpFullGuidString);
5229 if (Context)
5230 SetupTermDefaultQueueCallback(Context);
5231 TRACE("Returning %d\n", ret);
5232 return ret;
5233 }
5234
5235 static HKEY SETUPDI_OpenDevKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired)
5236 {
5237 HKEY enumKey, key = INVALID_HANDLE_VALUE;
5238 LONG l;
5239
5240 l = RegOpenKeyExW(RootKey, REGSTR_PATH_SYSTEMENUM, 0, 0, &enumKey);
5241 if (!l)
5242 {
5243 l = RegOpenKeyExW(enumKey, devInfo->instanceId, 0, samDesired, &key);
5244 RegCloseKey(enumKey);
5245 }
5246 if (l)
5247 SetLastError(l);
5248 return key;
5249 }
5250
5251 static HKEY SETUPDI_OpenDrvKey(HKEY RootKey, struct DeviceInfo *devInfo, REGSAM samDesired)
5252 {
5253 LPWSTR DriverKey = NULL;
5254 DWORD dwLength = 0;
5255 DWORD dwRegType;
5256 DWORD rc;
5257 HKEY hEnumKey = NULL;
5258 HKEY hKey = NULL;
5259 HKEY key = INVALID_HANDLE_VALUE;
5260
5261 hKey = SETUPDI_OpenDevKey(RootKey, devInfo, KEY_QUERY_VALUE);
5262 if (hKey == INVALID_HANDLE_VALUE)
5263 goto cleanup;
5264 /* Read the 'Driver' key */
5265 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, NULL, &dwLength);
5266 if (rc != ERROR_SUCCESS)
5267 {
5268 SetLastError(rc);
5269 goto cleanup;
5270 }
5271 else if (dwRegType != REG_SZ)
5272 {
5273 SetLastError(ERROR_GEN_FAILURE);
5274 goto cleanup;
5275 }
5276 DriverKey = HeapAlloc(GetProcessHeap(), 0, dwLength);
5277 if (!DriverKey)
5278 {
5279 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
5280 goto cleanup;
5281 }
5282 rc = RegQueryValueExW(hKey, REGSTR_VAL_DRIVER, NULL, &dwRegType, (LPBYTE)DriverKey, &dwLength);
5283 if (rc != ERROR_SUCCESS)
5284 {
5285 SetLastError(rc);
5286 goto cleanup;
5287 }
5288 RegCloseKey(hKey);
5289 hKey = NULL;
5290 /* Need to open the driver key */
5291 rc = RegOpenKeyExW(
5292 RootKey,
5293 REGSTR_PATH_CLASS_NT,
5294 0, /* Options */
5295 0,
5296 &hEnumKey);
5297 if (rc != ERROR_SUCCESS)
5298 {
5299 SetLastError(rc);
5300 goto cleanup;
5301 }
5302 rc = RegOpenKeyExW(
5303 hEnumKey,
5304 DriverKey,
5305 0, /* Options */
5306 samDesired,
5307 &hKey);
5308 if (rc != ERROR_SUCCESS)
5309 {
5310 SetLastError(rc);
5311 goto cleanup;
5312 }
5313 key = hKey;
5314
5315 cleanup:
5316 if (hEnumKey != NULL)
5317 RegCloseKey(hEnumKey);
5318 if (hKey != NULL && hKey != key)
5319 RegCloseKey(hKey);
5320 return key;
5321 }
5322
5323 /***********************************************************************
5324 * SetupDiOpenDevRegKey (SETUPAPI.@)
5325 */
5326 HKEY WINAPI SetupDiOpenDevRegKey(
5327 HDEVINFO DeviceInfoSet,
5328 PSP_DEVINFO_DATA DeviceInfoData,
5329 DWORD Scope,
5330 DWORD HwProfile,
5331 DWORD KeyType,
5332 REGSAM samDesired)
5333 {
5334 struct DeviceInfoSet *set = DeviceInfoSet;
5335 struct DeviceInfo *devInfo;
5336 HKEY key = INVALID_HANDLE_VALUE;
5337 HKEY RootKey;
5338
5339 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
5340 Scope, HwProfile, KeyType, samDesired);
5341
5342 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
5343 {
5344 SetLastError(ERROR_INVALID_HANDLE);
5345 return INVALID_HANDLE_VALUE;
5346 }
5347 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5348 {
5349 SetLastError(ERROR_INVALID_HANDLE);
5350 return INVALID_HANDLE_VALUE;
5351 }
5352 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
5353 || !DeviceInfoData->Reserved)
5354 {
5355 SetLastError(ERROR_INVALID_PARAMETER);
5356 return INVALID_HANDLE_VALUE;
5357 }
5358 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
5359 {
5360 SetLastError(ERROR_INVALID_FLAGS);
5361 return INVALID_HANDLE_VALUE;
5362 }
5363 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV)
5364 {
5365 SetLastError(ERROR_INVALID_FLAGS);
5366 return INVALID_HANDLE_VALUE;
5367 }
5368 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
5369 if (devInfo->set != set)
5370 {
5371 SetLastError(ERROR_INVALID_PARAMETER);
5372 return INVALID_HANDLE_VALUE;
5373 }
5374 if (Scope != DICS_FLAG_GLOBAL)
5375 {
5376 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0);
5377 if (RootKey == INVALID_HANDLE_VALUE)
5378 return INVALID_HANDLE_VALUE;
5379 }
5380 else
5381 RootKey = set->HKLM;
5382 switch (KeyType)
5383 {
5384 case DIREG_DEV:
5385 key = SETUPDI_OpenDevKey(RootKey, devInfo, samDesired);
5386 break;
5387 case DIREG_DRV:
5388 key = SETUPDI_OpenDrvKey(RootKey, devInfo, samDesired);
5389 break;
5390 default:
5391 WARN("unknown KeyType %d\n", KeyType);
5392 }
5393 if (RootKey != set->HKLM)
5394 RegCloseKey(RootKey);
5395 return key;
5396 }
5397
5398 static BOOL SETUPDI_DeleteDevKey(HKEY RootKey, struct DeviceInfo *devInfo)
5399 {
5400 FIXME("\n");
5401 return FALSE;
5402 }
5403
5404 static BOOL SETUPDI_DeleteDrvKey(HKEY RootKey, struct DeviceInfo *devInfo)
5405 {
5406 FIXME("\n");
5407 return FALSE;
5408 }
5409
5410 /***********************************************************************
5411 * SetupDiDeleteDevRegKey (SETUPAPI.@)
5412 */
5413 BOOL WINAPI SetupDiDeleteDevRegKey(
5414 HDEVINFO DeviceInfoSet,
5415 PSP_DEVINFO_DATA DeviceInfoData,
5416 DWORD Scope,
5417 DWORD HwProfile,
5418 DWORD KeyType)
5419 {
5420 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
5421 struct DeviceInfo *devInfo;
5422 BOOL ret = FALSE;
5423 HKEY RootKey;
5424
5425 TRACE("%p %p %d %d %d\n", DeviceInfoSet, DeviceInfoData, Scope, HwProfile,
5426 KeyType);
5427
5428 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
5429 {
5430 SetLastError(ERROR_INVALID_HANDLE);
5431 return FALSE;
5432 }
5433 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
5434 {
5435 SetLastError(ERROR_INVALID_HANDLE);
5436 return FALSE;
5437 }
5438 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
5439 || !DeviceInfoData->Reserved)
5440 {
5441 SetLastError(ERROR_INVALID_PARAMETER);
5442 return FALSE;
5443 }
5444 if (Scope != DICS_FLAG_GLOBAL && Scope != DICS_FLAG_CONFIGSPECIFIC)
5445 {
5446 SetLastError(ERROR_INVALID_FLAGS);
5447 return FALSE;
5448 }
5449 if (KeyType != DIREG_DEV && KeyType != DIREG_DRV && KeyType != DIREG_BOTH)
5450 {
5451 SetLastError(ERROR_INVALID_FLAGS);
5452 return FALSE;
5453 }
5454 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
5455 if (devInfo->set != set)
5456 {
5457 SetLastError(ERROR_INVALID_PARAMETER);
5458 return FALSE;
5459 }
5460 if (Scope != DICS_FLAG_GLOBAL)
5461 {
5462 RootKey = OpenHardwareProfileKey(set->HKLM, HwProfile, 0);
5463 if (RootKey == INVALID_HANDLE_VALUE)
5464 return FALSE;
5465 }
5466 else
5467 RootKey = set->HKLM;
5468 switch (KeyType)
5469 {
5470 case DIREG_DEV:
5471 ret = SETUPDI_DeleteDevKey(RootKey, devInfo);
5472 break;
5473 case DIREG_DRV:
5474 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo);
5475 break;
5476 case DIREG_BOTH:
5477 ret = SETUPDI_DeleteDevKey(RootKey, devInfo);
5478 if (ret)
5479 ret = SETUPDI_DeleteDrvKey(RootKey, devInfo);
5480 break;
5481 default:
5482 WARN("unknown KeyType %d\n", KeyType);
5483 }
5484 if (RootKey != set->HKLM)
5485 RegCloseKey(RootKey);
5486 return ret;
5487 }