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