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