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