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