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