2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
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.
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.
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
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
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};
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};
46 (CALLBACK
* CLASS_INSTALL_PROC
) (
47 IN DI_FUNCTION InstallFunction
,
48 IN HDEVINFO DeviceInfoSet
,
49 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
51 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
52 IN HDEVINFO DeviceInfoSet
,
53 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
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
);
61 struct CoInstallerElement
66 COINSTALLER_PROC Function
;
67 BOOL DoPostProcessing
;
71 struct GetSectionCallbackInfo
73 PSP_ALTPLATFORM_INFO PlatformInfo
;
77 WCHAR BestSection
[LINE_LEN
+ 1];
78 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
83 static void SETUPDI_GuidToString(const GUID
*guid
, LPWSTR guidStr
)
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','%',
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]);
96 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
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
;
120 /* Does not happen */
123 /* Lower scores are best ones */
126 IN LPCWSTR SectionName
,
127 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
130 OUT PDWORD ScorePlatform
,
131 OUT PDWORD ScoreMajorVersion
,
132 OUT PDWORD ScoreMinorVersion
,
133 OUT PDWORD ScoreProductType
,
134 OUT PDWORD ScoreSuiteMask
)
136 LPWSTR Section
= NULL
;
137 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
142 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
143 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
144 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
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};
154 TRACE("%s %p 0x%x 0x%x\n",
155 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
157 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
159 Section
= pSetupDuplicateString(SectionName
);
162 TRACE("pSetupDuplicateString() failed\n");
166 /* Set various extensions values */
167 switch (PlatformInfo
->Platform
)
169 case VER_PLATFORM_WIN32_WINDOWS
:
170 pExtensionPlatform
= ExtensionPlatformWindows
;
172 case VER_PLATFORM_WIN32_NT
:
173 pExtensionPlatform
= ExtensionPlatformNT
;
176 ERR("Unknown platform 0x%lx\n", PlatformInfo
->Platform
);
177 pExtensionPlatform
= ExtensionPlatformNone
;
180 switch (PlatformInfo
->ProcessorArchitecture
)
182 case PROCESSOR_ARCHITECTURE_ALPHA
:
183 pExtensionArchitecture
= ExtensionArchitecturealpha
;
185 case PROCESSOR_ARCHITECTURE_AMD64
:
186 pExtensionArchitecture
= ExtensionArchitectureamd64
;
188 case PROCESSOR_ARCHITECTURE_IA64
:
189 pExtensionArchitecture
= ExtensionArchitectureia64
;
191 case PROCESSOR_ARCHITECTURE_INTEL
:
192 pExtensionArchitecture
= ExtensionArchitecturex86
;
194 case PROCESSOR_ARCHITECTURE_MIPS
:
195 pExtensionArchitecture
= ExtensionArchitecturemips
;
197 case PROCESSOR_ARCHITECTURE_PPC
:
198 pExtensionArchitecture
= ExtensionArchitectureppc
;
201 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
202 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
203 pExtensionArchitecture
= ExtensionArchitectureNone
;
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
217 if (Fields
[0] == NULL
)
219 TRACE("No extension found\n");
220 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
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
++)
228 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
232 *(Fields
[i
] - 1) = UNICODE_NULL
;
235 /* Take care of first 2 fields */
236 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
238 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
240 TRACE("Mismatch on platform field\n");
243 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
245 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
247 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
249 TRACE("Mismatch on platform field\n");
252 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
256 /* No platform specified */
257 *ScorePlatform
|= 0x02;
259 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
261 /* No architecture specified */
262 *ScorePlatform
|= 0x01;
264 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
266 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
267 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
271 /* Check if informations are matching */
272 if (Fields
[2] && *Fields
[2])
274 DWORD MajorVersion
, MinorVersion
= 0;
275 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
276 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
277 (errno
== ERANGE
|| errno
== EINVAL
))
279 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
282 if (Fields
[3] && *Fields
[3])
284 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
285 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
286 (errno
== ERANGE
|| errno
== EINVAL
))
288 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
292 if (PlatformInfo
->MajorVersion
< MajorVersion
||
293 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
295 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
296 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
299 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
300 if (MajorVersion
== PlatformInfo
->MajorVersion
)
301 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
303 *ScoreMinorVersion
= MinorVersion
;
305 else if (Fields
[3] && *Fields
[3])
307 TRACE("Minor version found without major version\n");
312 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
313 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
316 if (Fields
[4] && *Fields
[4])
318 DWORD CurrentProductType
;
319 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
320 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
321 (errno
== ERANGE
|| errno
== EINVAL
))
323 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
326 if (CurrentProductType
!= ProductType
)
328 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
329 CurrentProductType
, ProductType
);
334 *ScoreProductType
= 1;
336 if (Fields
[5] && *Fields
[5])
338 DWORD CurrentSuiteMask
;
339 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
340 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
341 (errno
== ERANGE
|| errno
== EINVAL
))
343 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
346 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
348 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
349 CurrentSuiteMask
, SuiteMask
);
352 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
355 *ScoreSuiteMask
= SuiteMask
;
366 IN LPCWSTR SectionName
,
369 struct GetSectionCallbackInfo
*info
= Context
;
370 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
373 if (SectionName
[info
->PrefixLength
] != '.')
376 ret
= CheckSectionValid(
377 &SectionName
[info
->PrefixLength
],
381 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
384 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
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
;
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
;
411 /***********************************************************************
412 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
415 SetupDiGetActualSectionToInstallExW(
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
,
427 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
428 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
429 RequiredSize
, Extension
, Reserved
);
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
);
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
;
450 /* Fill platform info if needed */
451 if (AlternatePlatformInfo
)
453 pPlatformInfo
= AlternatePlatformInfo
;
459 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
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
);
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
;
478 ProductType
= CurrentProductType
;
479 SuiteMask
= CurrentSuiteMask
;
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(
498 SetLastError(ERROR_GEN_FAILURE
);
502 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
503 if (RequiredSize
!= NULL
)
504 *RequiredSize
= dwFullLength
+ 1;
506 if (InfSectionWithExtSize
> 0)
508 if (InfSectionWithExtSize
< dwFullLength
+ 1)
510 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
513 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
516 DWORD dwLength
= lstrlenW(InfSectionName
);
517 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
525 TRACE("Returning %d\n", ret
);
532 IN
struct DeviceInfoSet
*list
,
533 IN LPCWSTR InstancePath
,
534 IN LPCGUID pClassGuid
,
535 OUT
struct DeviceInfo
**pDeviceInfo
)
539 struct DeviceInfo
*deviceInfo
;
543 size
= FIELD_OFFSET(struct DeviceInfo
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
544 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
547 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
550 ZeroMemory(deviceInfo
, size
);
552 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
553 if (cr
!= CR_SUCCESS
)
555 SetLastError(GetErrorCodeFromCrCode(cr
));
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
);
570 *pDeviceInfo
= deviceInfo
;
576 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
578 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
579 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
584 DestroyDeviceInfo(struct DeviceInfo
*deviceInfo
)
586 PLIST_ENTRY ListEntry
;
587 struct DriverInfoElement
*driverInfo
;
588 struct DeviceInterface
*deviceInterface
;
590 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
592 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
593 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
594 if (!DestroyDriverInfoElement(driverInfo
))
597 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
599 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
600 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
601 if (!DestroyDeviceInterface(deviceInterface
))
604 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
605 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
609 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
611 PLIST_ENTRY ListEntry
;
612 struct DeviceInfo
*deviceInfo
;
614 while (!IsListEmpty(&list
->ListHead
))
616 ListEntry
= RemoveHeadList(&list
->ListHead
);
617 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
);
618 if (!DestroyDeviceInfo(deviceInfo
))
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
);
628 /***********************************************************************
629 * SetupDiBuildClassInfoList (SETUPAPI.@)
631 * Returns a list of setup class GUIDs that identify the classes
632 * that are installed on a local machine.
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.
644 BOOL WINAPI
SetupDiBuildClassInfoList(
646 LPGUID ClassGuidList
,
647 DWORD ClassGuidListSize
,
651 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
652 ClassGuidListSize
, RequiredSize
,
656 /***********************************************************************
657 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
659 * Returns a list of setup class GUIDs that identify the classes
660 * that are installed on a local or remote macine.
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.
674 BOOL WINAPI
SetupDiBuildClassInfoListExA(
676 LPGUID ClassGuidList
,
677 DWORD ClassGuidListSize
,
682 LPWSTR MachineNameW
= NULL
;
685 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
686 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
690 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
691 if (MachineNameW
== NULL
) return FALSE
;
694 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
695 ClassGuidListSize
, RequiredSize
,
696 MachineNameW
, Reserved
);
698 MyFree(MachineNameW
);
703 /***********************************************************************
704 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
706 * Returns a list of setup class GUIDs that identify the classes
707 * that are installed on a local or remote macine.
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.
721 BOOL WINAPI
SetupDiBuildClassInfoListExW(
723 LPGUID ClassGuidList
,
724 DWORD ClassGuidListSize
,
730 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
735 DWORD dwGuidListIndex
= 0;
737 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
738 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
742 SetLastError(ERROR_INVALID_PARAMETER
);
745 else if (!ClassGuidList
&& ClassGuidListSize
> 0)
747 SetLastError(ERROR_INVALID_PARAMETER
);
751 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
752 KEY_ENUMERATE_SUB_KEYS
,
756 if (hClassesKey
== INVALID_HANDLE_VALUE
)
761 for (dwIndex
= 0; ; dwIndex
++)
764 lError
= RegEnumKeyExW(hClassesKey
,
772 TRACE("RegEnumKeyExW() returns %d\n", lError
);
773 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
775 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
777 if (RegOpenKeyExW(hClassesKey
,
783 RegCloseKey(hClassesKey
);
787 if (!RegQueryValueExW(hClassKey
,
788 REGSTR_VAL_NOUSECLASS
,
794 TRACE("'NoUseClass' value found!\n");
795 RegCloseKey(hClassKey
);
799 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
800 (!RegQueryValueExW(hClassKey
,
801 REGSTR_VAL_NOINSTALLCLASS
,
807 TRACE("'NoInstallClass' value found!\n");
808 RegCloseKey(hClassKey
);
812 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
813 (!RegQueryValueExW(hClassKey
,
814 REGSTR_VAL_NODISPLAYCLASS
,
820 TRACE("'NoDisplayClass' value found!\n");
821 RegCloseKey(hClassKey
);
825 RegCloseKey(hClassKey
);
827 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
828 if (dwGuidListIndex
< ClassGuidListSize
)
830 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
834 TRACE("Guid: %p\n", &szKeyName
[1]);
836 UuidFromStringW(&szKeyName
[1],
837 &ClassGuidList
[dwGuidListIndex
]);
843 if (lError
!= ERROR_SUCCESS
)
847 RegCloseKey(hClassesKey
);
849 if (RequiredSize
!= NULL
)
850 *RequiredSize
= dwGuidListIndex
;
852 if (ClassGuidListSize
< dwGuidListIndex
)
854 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
861 /***********************************************************************
862 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
864 BOOL WINAPI
SetupDiClassGuidsFromNameA(
866 LPGUID ClassGuidList
,
867 DWORD ClassGuidListSize
,
870 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
871 ClassGuidListSize
, RequiredSize
,
875 /***********************************************************************
876 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
878 BOOL WINAPI
SetupDiClassGuidsFromNameW(
880 LPGUID ClassGuidList
,
881 DWORD ClassGuidListSize
,
884 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
885 ClassGuidListSize
, RequiredSize
,
889 /***********************************************************************
890 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
892 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
894 LPGUID ClassGuidList
,
895 DWORD ClassGuidListSize
,
900 LPWSTR ClassNameW
= NULL
;
901 LPWSTR MachineNameW
= NULL
;
904 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName
), ClassGuidList
,
905 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
909 SetLastError(ERROR_INVALID_PARAMETER
);
913 ClassNameW
= pSetupMultiByteToUnicode(ClassName
, CP_ACP
);
914 if (ClassNameW
== NULL
)
919 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
920 if (MachineNameW
== NULL
)
927 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
928 ClassGuidListSize
, RequiredSize
,
929 MachineNameW
, Reserved
);
931 MyFree(MachineNameW
);
937 /***********************************************************************
938 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
940 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
942 LPGUID ClassGuidList
,
943 DWORD ClassGuidListSize
,
949 WCHAR szClassName
[MAX_CLASS_NAME_LEN
];
955 DWORD dwGuidListIndex
= 0;
957 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
958 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
960 if (!ClassName
|| !RequiredSize
)
962 SetLastError(ERROR_INVALID_PARAMETER
);
965 if (!ClassGuidList
&& ClassGuidListSize
> 0)
967 SetLastError(ERROR_INVALID_PARAMETER
);
972 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
973 KEY_ENUMERATE_SUB_KEYS
,
977 if (hClassesKey
== INVALID_HANDLE_VALUE
)
982 for (dwIndex
= 0; ; dwIndex
++)
985 lError
= RegEnumKeyExW(hClassesKey
,
993 TRACE("RegEnumKeyExW() returns %d\n", lError
);
994 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
996 TRACE("Key name: %p\n", szKeyName
);
998 if (RegOpenKeyExW(hClassesKey
,
1004 RegCloseKey(hClassesKey
);
1008 dwLength
= MAX_CLASS_NAME_LEN
* sizeof(WCHAR
);
1009 if (!RegQueryValueExW(hClassKey
,
1013 (LPBYTE
)szClassName
,
1016 TRACE("Class name: %p\n", szClassName
);
1018 if (strcmpiW(szClassName
, ClassName
) == 0)
1020 TRACE("Found matching class name\n");
1022 TRACE("Guid: %p\n", szKeyName
);
1023 if (dwGuidListIndex
< ClassGuidListSize
)
1025 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
1029 TRACE("Guid: %p\n", &szKeyName
[1]);
1031 UuidFromStringW(&szKeyName
[1],
1032 &ClassGuidList
[dwGuidListIndex
]);
1039 RegCloseKey(hClassKey
);
1042 if (lError
!= ERROR_SUCCESS
)
1046 RegCloseKey(hClassesKey
);
1048 if (RequiredSize
!= NULL
)
1049 *RequiredSize
= dwGuidListIndex
;
1051 if (ClassGuidListSize
< dwGuidListIndex
)
1053 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1060 /***********************************************************************
1061 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1063 BOOL WINAPI
SetupDiClassNameFromGuidA(
1064 const GUID
* ClassGuid
,
1066 DWORD ClassNameSize
,
1067 PDWORD RequiredSize
)
1069 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
1070 ClassNameSize
, RequiredSize
,
1074 /***********************************************************************
1075 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1077 BOOL WINAPI
SetupDiClassNameFromGuidW(
1078 const GUID
* ClassGuid
,
1080 DWORD ClassNameSize
,
1081 PDWORD RequiredSize
)
1083 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
1084 ClassNameSize
, RequiredSize
,
1088 /***********************************************************************
1089 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1091 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1092 const GUID
* ClassGuid
,
1094 DWORD ClassNameSize
,
1095 PDWORD RequiredSize
,
1099 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1100 LPWSTR MachineNameW
= NULL
;
1104 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1105 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1106 RequiredSize
, MachineNameW
, Reserved
);
1109 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1110 ClassNameSize
, NULL
, NULL
);
1111 if (len
== 0 || len
> ClassNameSize
)
1113 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1117 MyFree(MachineNameW
);
1121 /***********************************************************************
1122 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1124 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1125 const GUID
* ClassGuid
,
1127 DWORD ClassNameSize
,
1128 PDWORD RequiredSize
,
1138 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
1139 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1141 /* Make sure there's a GUID */
1142 if (ClassGuid
== NULL
)
1144 SetLastError(ERROR_INVALID_CLASS
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1148 /* Make sure there's a real buffer when there's a size */
1149 if ((ClassNameSize
> 0) && (ClassName
== NULL
))
1151 SetLastError(ERROR_INVALID_PARAMETER
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1155 /* Open the key for the GUID */
1156 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INSTALLER
, MachineName
, Reserved
);
1158 if (hKey
== INVALID_HANDLE_VALUE
)
1161 /* Retrieve the class name data and close the key */
1162 rc
= QueryRegistryValue(hKey
, Class
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
1165 /* Make sure we got the data */
1166 if (rc
!= ERROR_SUCCESS
)
1172 /* Make sure the data is a string */
1173 if (dwRegType
!= REG_SZ
)
1176 SetLastError(ERROR_GEN_FAILURE
);
1180 /* Determine the length of the class name */
1181 dwLength
/= sizeof(WCHAR
);
1183 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
1184 /* Count the null-terminator */
1187 /* Inform the caller about the class name */
1188 if ((ClassName
!= NULL
) && (dwLength
<= ClassNameSize
))
1190 memcpy(ClassName
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
1191 ClassName
[dwLength
- 1] = UNICODE_NULL
;
1194 /* Inform the caller about the required size */
1195 if (RequiredSize
!= NULL
)
1196 *RequiredSize
= dwLength
;
1198 /* Clean up the buffer */
1201 /* Make sure the buffer was large enough */
1202 if ((ClassName
== NULL
) || (dwLength
> ClassNameSize
))
1204 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1211 /***********************************************************************
1212 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1215 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1218 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1221 /***********************************************************************
1222 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1225 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1230 LPWSTR MachineNameW
= NULL
;
1233 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1234 debugstr_a(MachineName
), Reserved
);
1238 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1239 if (MachineNameW
== NULL
)
1240 return INVALID_HANDLE_VALUE
;
1243 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1244 MachineNameW
, Reserved
);
1246 MyFree(MachineNameW
);
1251 /***********************************************************************
1252 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1254 * Create an empty DeviceInfoSet list.
1257 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1259 * hwndParent [I] hwnd needed for interface related actions.
1260 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1261 * local registry will be used.
1262 * Reserved [I] must be NULL
1265 * Success: empty list.
1266 * Failure: INVALID_HANDLE_VALUE.
1269 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1274 struct DeviceInfoSet
*list
= NULL
;
1275 DWORD size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
1278 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1280 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1281 debugstr_w(MachineName
), Reserved
);
1283 if (MachineName
!= NULL
)
1285 SIZE_T len
= strlenW(MachineName
);
1286 if (len
>= SP_MAX_MACHINENAME_LENGTH
- 4)
1288 SetLastError(ERROR_INVALID_MACHINENAME
);
1291 size
+= (len
+ 3) * sizeof(WCHAR
);
1294 if (Reserved
!= NULL
)
1296 SetLastError(ERROR_INVALID_PARAMETER
);
1297 return INVALID_HANDLE_VALUE
;
1300 list
= MyMalloc(size
);
1303 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1304 return INVALID_HANDLE_VALUE
;
1306 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
1308 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1309 memcpy(&list
->ClassGuid
,
1310 ClassGuid
? ClassGuid
: &GUID_NULL
,
1311 sizeof(list
->ClassGuid
));
1312 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1313 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1314 list
->InstallParams
.hwndParent
= hwndParent
;
1317 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
1318 if (rc
!= ERROR_SUCCESS
)
1320 SetLastError(ERROR_INVALID_MACHINENAME
);
1324 list
->szData
[0] = list
->szData
[1] = '\\';
1325 strcpyW(list
->szData
+ 2, MachineName
);
1326 list
->MachineName
= list
->szData
;
1330 list
->HKLM
= HKEY_LOCAL_MACHINE
;
1331 list
->MachineName
= NULL
;
1333 cr
= CM_Connect_MachineW(list
->MachineName
, &list
->hMachine
);
1334 if (cr
!= CR_SUCCESS
)
1336 SetLastError(GetErrorCodeFromCrCode(cr
));
1339 InitializeListHead(&list
->DriverListHead
);
1340 InitializeListHead(&list
->ListHead
);
1342 return (HDEVINFO
)list
;
1345 if (ret
== INVALID_HANDLE_VALUE
)
1349 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1350 RegCloseKey(list
->HKLM
);
1357 /***********************************************************************
1358 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1360 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1361 HDEVINFO DeviceInfoSet
,
1362 PSP_DEVINFO_DATA DeviceInfoData
,
1367 PCSTR InfSectionName
)
1369 PWSTR InfSectionNameW
= NULL
;
1372 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1373 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1377 if (!InfSectionName
)
1379 SetLastError(ERROR_INVALID_PARAMETER
);
1380 return INVALID_HANDLE_VALUE
;
1384 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
1385 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1388 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1389 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1390 MyFree(InfSectionNameW
);
1395 OpenHardwareProfileKey(
1398 IN DWORD samDesired
);
1400 /***********************************************************************
1401 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1403 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1404 HDEVINFO DeviceInfoSet
,
1405 PSP_DEVINFO_DATA DeviceInfoData
,
1410 PCWSTR InfSectionName
)
1412 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1413 HKEY key
= INVALID_HANDLE_VALUE
;
1414 LPWSTR lpGuidString
= NULL
;
1415 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
1416 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
1417 DWORD Index
; /* Index used in the DriverKey name */
1419 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
1420 HKEY hEnumKey
= NULL
;
1421 HKEY hClassKey
= NULL
;
1422 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
1426 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1427 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1429 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1431 SetLastError(ERROR_INVALID_HANDLE
);
1432 return INVALID_HANDLE_VALUE
;
1434 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1436 SetLastError(ERROR_INVALID_HANDLE
);
1437 return INVALID_HANDLE_VALUE
;
1439 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1440 || !DeviceInfoData
->Reserved
)
1442 SetLastError(ERROR_INVALID_PARAMETER
);
1443 return INVALID_HANDLE_VALUE
;
1445 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1447 SetLastError(ERROR_INVALID_FLAGS
);
1448 return INVALID_HANDLE_VALUE
;
1450 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1452 SetLastError(ERROR_INVALID_FLAGS
);
1453 return INVALID_HANDLE_VALUE
;
1455 if (InfHandle
&& !InfSectionName
)
1457 SetLastError(ERROR_INVALID_PARAMETER
);
1458 return INVALID_HANDLE_VALUE
;
1460 if (!InfHandle
&& InfSectionName
)
1462 SetLastError(ERROR_INVALID_PARAMETER
);
1463 return INVALID_HANDLE_VALUE
;
1466 if (Scope
== DICS_FLAG_GLOBAL
)
1467 RootKey
= set
->HKLM
;
1468 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1470 hHWProfileKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
1471 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
1473 RootKey
= hHWProfileKey
;
1476 if (KeyType
== DIREG_DEV
)
1478 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1480 rc
= RegCreateKeyExW(
1482 REGSTR_PATH_SYSTEMENUM
,
1485 REG_OPTION_NON_VOLATILE
,
1490 if (rc
!= ERROR_SUCCESS
)
1495 rc
= RegCreateKeyExW(
1497 deviceInfo
->instanceId
,
1500 REG_OPTION_NON_VOLATILE
,
1501 #if _WIN32_WINNT >= 0x502
1502 KEY_READ
| KEY_WRITE
,
1509 if (rc
!= ERROR_SUCCESS
)
1515 else /* KeyType == DIREG_DRV */
1517 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
1519 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1520 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
1523 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1527 strcpyW(&DriverKey
[1], lpGuidString
);
1528 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
1529 *pDeviceInstance
++ = '}';
1530 *pDeviceInstance
++ = '\\';
1531 rc
= RegOpenKeyExW(RootKey
,
1532 REGSTR_PATH_CLASS_NT
,
1536 if (rc
!= ERROR_SUCCESS
)
1542 /* Try all values for Index between 0 and 9999 */
1544 while (Index
<= 9999)
1547 sprintfW(pDeviceInstance
, InstanceKeyFormat
, Index
);
1548 rc
= RegCreateKeyExW(hClassKey
,
1552 REG_OPTION_NON_VOLATILE
,
1553 #if _WIN32_WINNT >= 0x502
1554 KEY_READ
| KEY_WRITE
,
1561 if (rc
!= ERROR_SUCCESS
)
1566 if (Disposition
== REG_CREATED_NEW_KEY
)
1574 /* Unable to create more than 9999 devices within the same class */
1575 SetLastError(ERROR_GEN_FAILURE
);
1579 /* Open device key, to write Driver value */
1580 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
1581 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
1583 rc
= RegSetValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
1584 if (rc
!= ERROR_SUCCESS
)
1591 /* Do installation of the specified section */
1594 FIXME("Need to install section %s in file %p\n",
1595 debugstr_w(InfSectionName
), InfHandle
);
1601 RpcStringFreeW(&lpGuidString
);
1602 HeapFree(GetProcessHeap(), 0, DriverKey
);
1603 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
1604 RegCloseKey(hHWProfileKey
);
1605 if (hEnumKey
!= NULL
)
1606 RegCloseKey(hEnumKey
);
1607 if (hClassKey
!= NULL
)
1608 RegCloseKey(hClassKey
);
1609 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
1610 RegCloseKey(hDeviceKey
);
1611 if (hKey
!= NULL
&& hKey
!= key
)
1614 TRACE("Returning 0x%p\n", key
);
1618 /***********************************************************************
1619 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1621 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1622 HDEVINFO DeviceInfoSet
,
1624 CONST GUID
*ClassGuid
,
1625 PCSTR DeviceDescription
,
1627 DWORD CreationFlags
,
1628 PSP_DEVINFO_DATA DeviceInfoData
)
1631 LPWSTR DeviceNameW
= NULL
;
1632 LPWSTR DeviceDescriptionW
= NULL
;
1638 DeviceNameW
= pSetupMultiByteToUnicode(DeviceName
, CP_ACP
);
1639 if (DeviceNameW
== NULL
) return FALSE
;
1641 if (DeviceDescription
)
1643 DeviceDescriptionW
= pSetupMultiByteToUnicode(DeviceDescription
, CP_ACP
);
1644 if (DeviceDescriptionW
== NULL
)
1646 MyFree(DeviceNameW
);
1651 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1652 hwndParent
, CreationFlags
, DeviceInfoData
);
1654 MyFree(DeviceNameW
);
1655 MyFree(DeviceDescriptionW
);
1660 /***********************************************************************
1661 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1663 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1664 HDEVINFO DeviceInfoSet
,
1666 CONST GUID
*ClassGuid
,
1667 PCWSTR DeviceDescription
,
1669 DWORD CreationFlags
,
1670 PSP_DEVINFO_DATA DeviceInfoData
)
1672 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1674 SP_DEVINFO_DATA DevInfo
;
1676 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
1677 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1678 hwndParent
, CreationFlags
, DeviceInfoData
);
1682 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1685 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1687 SetLastError(ERROR_INVALID_HANDLE
);
1692 SetLastError(ERROR_INVALID_PARAMETER
);
1695 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1697 SetLastError(ERROR_INVALID_HANDLE
);
1700 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1701 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1703 SetLastError(ERROR_CLASS_MISMATCH
);
1706 if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
1708 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
1709 SetLastError(ERROR_INVALID_FLAGS
);
1713 if (CreationFlags
& DICD_GENERATE_ID
)
1715 /* Generate a new unique ID for this device */
1716 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1717 FIXME("not implemented\n");
1721 /* Device name is fully qualified. Try to open it */
1724 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
1725 rc
= SetupDiOpenDeviceInfoW(
1728 NULL
, /* hwndParent */
1729 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
1734 /* SetupDiOpenDeviceInfoW has already added
1735 * the device info to the device info set
1737 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
1739 else if (GetLastError() == ERROR_NO_SUCH_DEVINST
)
1741 struct DeviceInfo
*deviceInfo
;
1743 if (CreateDeviceInfo(set
, DeviceName
, ClassGuid
, &deviceInfo
))
1745 InsertTailList(&set
->ListHead
, &deviceInfo
->ListEntry
);
1747 if (!DeviceInfoData
)
1751 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
1753 SetLastError(ERROR_INVALID_USER_BUFFER
);
1757 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
1758 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
1759 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
1767 TRACE("Returning %d\n", ret
);
1771 /***********************************************************************
1772 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1774 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1775 HDEVINFO DeviceInfoSet
,
1776 PSP_DEVINFO_DATA DeviceInfoData
,
1778 PSP_DETSIG_CMPPROC CompareProc
,
1779 PVOID CompareContext
,
1780 PSP_DEVINFO_DATA DupDeviceInfoData
)
1782 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1784 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1785 CompareProc
, CompareContext
, DupDeviceInfoData
);
1787 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1789 SetLastError(ERROR_INVALID_HANDLE
);
1792 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1794 SetLastError(ERROR_INVALID_HANDLE
);
1797 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1798 || !DeviceInfoData
->Reserved
)
1800 SetLastError(ERROR_INVALID_PARAMETER
);
1803 FIXME("Stub %p %p 0x%lx %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1804 CompareProc
, CompareContext
, DupDeviceInfoData
);
1805 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1809 /***********************************************************************
1810 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1812 BOOL WINAPI
SetupDiEnumDeviceInfo(
1815 PSP_DEVINFO_DATA info
)
1819 TRACE("%p %d %p\n", devinfo
, index
, info
);
1823 SetLastError(ERROR_INVALID_PARAMETER
);
1826 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1828 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1829 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1831 if (info
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1832 SetLastError(ERROR_INVALID_USER_BUFFER
);
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
);
1842 struct DeviceInfo
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
1843 memcpy(&info
->ClassGuid
,
1844 &DevInfo
->ClassGuid
,
1846 info
->DevInst
= DevInfo
->dnDevInst
;
1847 info
->Reserved
= (ULONG_PTR
)DevInfo
;
1853 SetLastError(ERROR_INVALID_HANDLE
);
1856 SetLastError(ERROR_INVALID_HANDLE
);
1860 /***********************************************************************
1861 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1863 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1864 HDEVINFO DeviceInfoSet
,
1865 PSP_DEVINFO_DATA DeviceInfoData
,
1866 PSTR DeviceInstanceId
,
1867 DWORD DeviceInstanceIdSize
,
1868 PDWORD RequiredSize
)
1874 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1875 DeviceInstanceIdSize
, RequiredSize
);
1877 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1879 SetLastError(ERROR_INVALID_PARAMETER
);
1883 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1888 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1890 instanceId
= MyMalloc(size
* sizeof(WCHAR
));
1893 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1900 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
1902 DeviceInstanceIdSize
, NULL
, NULL
);
1908 if (len
> DeviceInstanceIdSize
)
1910 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1914 *RequiredSize
= len
;
1922 *RequiredSize
= size
;
1923 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1929 /***********************************************************************
1930 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1932 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
1933 HDEVINFO DeviceInfoSet
,
1934 PSP_DEVINFO_DATA DeviceInfoData
,
1935 PWSTR DeviceInstanceId
,
1936 DWORD DeviceInstanceIdSize
,
1937 PDWORD RequiredSize
)
1939 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1940 struct DeviceInfo
*devInfo
;
1942 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1943 DeviceInstanceIdSize
, RequiredSize
);
1945 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1947 SetLastError(ERROR_INVALID_HANDLE
);
1950 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1952 SetLastError(ERROR_INVALID_HANDLE
);
1955 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1956 || !DeviceInfoData
->Reserved
)
1958 SetLastError(ERROR_INVALID_PARAMETER
);
1961 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1962 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1964 SetLastError(ERROR_INVALID_PARAMETER
);
1967 if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
1969 SetLastError(ERROR_INVALID_PARAMETER
);
1972 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
1973 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
1975 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1977 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1980 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
1982 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1986 /***********************************************************************
1987 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1989 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
1991 PCSTR InfSectionName
,
1992 PSTR InfSectionWithExt
,
1993 DWORD InfSectionWithExtSize
,
1994 PDWORD RequiredSize
,
1997 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
1998 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2002 /***********************************************************************
2003 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2005 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
2007 PCWSTR InfSectionName
,
2008 PWSTR InfSectionWithExt
,
2009 DWORD InfSectionWithExtSize
,
2010 PDWORD RequiredSize
,
2013 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
2014 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2018 /***********************************************************************
2019 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2022 SetupDiGetActualSectionToInstallExA(
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
,
2032 LPWSTR InfSectionNameW
= NULL
;
2033 LPWSTR InfSectionWithExtW
= NULL
;
2035 BOOL bResult
= FALSE
;
2041 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2042 if (InfSectionNameW
== NULL
)
2045 if (InfSectionWithExt
)
2047 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
2048 if (InfSectionWithExtW
== NULL
)
2052 bResult
= SetupDiGetActualSectionToInstallExW(
2053 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
2054 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
2055 InfSectionWithExtSize
,
2057 Extension
? &ExtensionW
: NULL
,
2060 if (bResult
&& InfSectionWithExt
)
2062 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
2063 InfSectionWithExtSize
, NULL
, NULL
) != 0;
2065 if (bResult
&& Extension
)
2067 if (ExtensionW
== NULL
)
2070 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
2074 MyFree(InfSectionNameW
);
2075 MyFree(InfSectionWithExtW
);
2080 /***********************************************************************
2081 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2083 BOOL WINAPI
SetupDiGetClassDescriptionA(
2084 const GUID
* ClassGuid
,
2085 PSTR ClassDescription
,
2086 DWORD ClassDescriptionSize
,
2087 PDWORD RequiredSize
)
2089 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
2090 ClassDescriptionSize
,
2091 RequiredSize
, NULL
, NULL
);
2094 /***********************************************************************
2095 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2097 BOOL WINAPI
SetupDiGetClassDescriptionW(
2098 const GUID
* ClassGuid
,
2099 PWSTR ClassDescription
,
2100 DWORD ClassDescriptionSize
,
2101 PDWORD RequiredSize
)
2103 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
2104 ClassDescriptionSize
,
2105 RequiredSize
, NULL
, NULL
);
2108 /***********************************************************************
2109 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2111 BOOL WINAPI
SetupDiGetClassDescriptionExA(
2112 const GUID
* ClassGuid
,
2113 PSTR ClassDescription
,
2114 DWORD ClassDescriptionSize
,
2115 PDWORD RequiredSize
,
2119 PWCHAR ClassDescriptionW
= NULL
;
2120 LPWSTR MachineNameW
= NULL
;
2123 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2124 ClassDescriptionSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
2126 if (ClassDescriptionSize
> 0)
2128 ClassDescriptionW
= MyMalloc(ClassDescriptionSize
* sizeof(WCHAR
));
2129 if (!ClassDescriptionW
)
2131 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2138 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
2141 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2146 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
,
2147 ClassDescriptionSize
* sizeof(WCHAR
), RequiredSize
, MachineNameW
, Reserved
);
2150 DWORD len
= (DWORD
)WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
2151 ClassDescriptionSize
, NULL
, NULL
);
2152 if (len
== 0 || len
> ClassDescriptionSize
)
2154 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2160 MyFree(ClassDescriptionW
);
2161 MyFree(MachineNameW
);
2165 /***********************************************************************
2166 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2168 BOOL WINAPI
SetupDiGetClassDescriptionExW(
2169 const GUID
* ClassGuid
,
2170 PWSTR ClassDescription
,
2171 DWORD ClassDescriptionSize
,
2172 PDWORD RequiredSize
,
2182 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2183 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
2185 /* Make sure there's a GUID */
2188 SetLastError(ERROR_INVALID_PARAMETER
);
2192 /* Make sure there's a real buffer when there's a size */
2193 if (!ClassDescription
&& ClassDescriptionSize
> 0)
2195 SetLastError(ERROR_INVALID_PARAMETER
);
2199 /* Open the key for the GUID */
2200 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
2205 if (hKey
== INVALID_HANDLE_VALUE
)
2208 /* Retrieve the class description data and close the key */
2209 rc
= QueryRegistryValue(hKey
, NULL
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
2212 /* Make sure we got the data */
2213 if (rc
!= ERROR_SUCCESS
)
2219 /* Make sure the data is a string */
2220 if (dwRegType
!= REG_SZ
)
2223 SetLastError(ERROR_GEN_FAILURE
);
2227 /* Determine the length of the class description */
2228 dwLength
/= sizeof(WCHAR
);
2230 /* Count the null-terminator if none is present */
2231 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
2234 /* Inform the caller about the class description */
2235 if ((ClassDescription
!= NULL
) && (dwLength
<= ClassDescriptionSize
))
2237 memcpy(ClassDescription
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
2238 ClassDescription
[dwLength
- 1] = UNICODE_NULL
;
2241 /* Inform the caller about the required size */
2242 if (RequiredSize
!= NULL
)
2243 *RequiredSize
= dwLength
;
2245 /* Clean up the buffer */
2248 /* Make sure the buffer was large enough */
2249 if ((ClassDescription
== NULL
) || (dwLength
> ClassDescriptionSize
))
2251 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2258 /***********************************************************************
2259 * SetupDiGetClassDevsA (SETUPAPI.@)
2261 HDEVINFO WINAPI
SetupDiGetClassDevsA(
2267 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
2268 flags
, NULL
, NULL
, NULL
);
2271 /***********************************************************************
2272 * SetupDiGetClassDevsExA (SETUPAPI.@)
2274 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
2284 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
2288 enumstrW
= pSetupMultiByteToUnicode(enumstr
, CP_ACP
);
2291 ret
= INVALID_HANDLE_VALUE
;
2297 machineW
= pSetupMultiByteToUnicode(machine
, CP_ACP
);
2301 ret
= INVALID_HANDLE_VALUE
;
2305 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
2306 machineW
, reserved
);
2314 /***********************************************************************
2315 * SetupDiGetClassDevsW (SETUPAPI.@)
2317 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2323 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2327 /***********************************************************************
2328 * SetupDiGetClassDevsExW (SETUPAPI.@)
2330 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2339 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2340 struct DeviceInfoSet
*list
;
2341 CONST GUID
*pClassGuid
;
2343 HDEVINFO set
= INVALID_HANDLE_VALUE
;
2345 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2346 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2349 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2351 SetLastError(ERROR_INVALID_PARAMETER
);
2352 return INVALID_HANDLE_VALUE
;
2355 /* Create the deviceset if not set */
2358 list
= (struct DeviceInfoSet
*)deviceset
;
2359 if (list
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2361 SetLastError(ERROR_INVALID_HANDLE
);
2364 hDeviceInfo
= deviceset
;
2368 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2369 flags
& (DIGCF_DEVICEINTERFACE
| DIGCF_ALLCLASSES
) ? NULL
: class,
2370 NULL
, machine
, NULL
);
2371 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2373 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2376 if (flags
& DIGCF_PROFILE
)
2377 FIXME(": flag DIGCF_PROFILE ignored\n");
2379 if (flags
& DIGCF_DEVICEINTERFACE
)
2383 SetLastError(ERROR_INVALID_PARAMETER
);
2386 rc
= SETUP_CreateInterfaceList(list
, machine
, class, enumstr
, flags
& DIGCF_PRESENT
);
2390 /* Determine which class(es) should be included in the deviceset */
2391 if (flags
& DIGCF_ALLCLASSES
)
2393 /* The caller wants all classes. Check if
2394 * the deviceset limits us to one class */
2395 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2398 pClassGuid
= &list
->ClassGuid
;
2402 /* The caller wants one class. Check if it matches deviceset class */
2403 if (IsEqualIID(&list
->ClassGuid
, class)
2404 || IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2410 SetLastError(ERROR_INVALID_PARAMETER
);
2414 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2416 /* No class specified. Try to use the one of the deviceset */
2417 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2418 pClassGuid
= &list
->ClassGuid
;
2421 SetLastError(ERROR_INVALID_PARAMETER
);
2427 SetLastError(ERROR_INVALID_PARAMETER
);
2430 rc
= SETUP_CreateDevicesList(list
, machine
, pClassGuid
, enumstr
);
2432 if (rc
!= ERROR_SUCCESS
)
2440 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= set
)
2441 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2445 /***********************************************************************
2446 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2448 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2449 HDEVINFO DeviceInfoSet
,
2450 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2452 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2454 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2456 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2458 SetLastError(ERROR_INVALID_HANDLE
);
2461 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2463 SetLastError(ERROR_INVALID_HANDLE
);
2467 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2469 SetLastError(ERROR_INVALID_PARAMETER
);
2472 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2473 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2474 if (set
->MachineName
)
2477 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2481 DevInfoData
->RemoteMachineName
[0] = 0;
2486 /***********************************************************************
2487 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2489 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2490 HDEVINFO DeviceInfoSet
,
2491 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2493 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2495 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2497 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2499 SetLastError(ERROR_INVALID_HANDLE
);
2502 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2504 SetLastError(ERROR_INVALID_HANDLE
);
2508 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2510 SetLastError(ERROR_INVALID_PARAMETER
);
2513 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2514 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2515 if (set
->MachineName
)
2516 strcpyW(DevInfoData
->RemoteMachineName
, set
->MachineName
+ 2);
2518 DevInfoData
->RemoteMachineName
[0] = 0;
2523 /***********************************************************************
2524 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2526 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2527 HDEVINFO DeviceInfoSet
,
2528 PSP_DEVINFO_DATA DeviceInfoData
,
2529 const GUID
*InterfaceClassGuid
,
2530 PCSTR ReferenceString
,
2531 DWORD CreationFlags
,
2532 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2535 LPWSTR ReferenceStringW
= NULL
;
2537 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2538 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2539 CreationFlags
, DeviceInterfaceData
);
2541 if (ReferenceString
)
2543 ReferenceStringW
= pSetupMultiByteToUnicode(ReferenceString
, CP_ACP
);
2544 if (ReferenceStringW
== NULL
) return FALSE
;
2547 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2548 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2549 DeviceInterfaceData
);
2551 MyFree(ReferenceStringW
);
2556 /***********************************************************************
2557 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2559 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2560 HDEVINFO DeviceInfoSet
,
2561 PSP_DEVINFO_DATA DeviceInfoData
,
2562 const GUID
*InterfaceClassGuid
,
2563 PCWSTR ReferenceString
,
2564 DWORD CreationFlags
,
2565 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2567 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2568 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2569 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2570 CreationFlags
, DeviceInterfaceData
);
2572 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2574 SetLastError(ERROR_INVALID_HANDLE
);
2577 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2579 SetLastError(ERROR_INVALID_HANDLE
);
2582 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2583 || !DeviceInfoData
->Reserved
)
2585 SetLastError(ERROR_INVALID_PARAMETER
);
2588 if (!InterfaceClassGuid
)
2590 SetLastError(ERROR_INVALID_USER_BUFFER
);
2594 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2595 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2596 CreationFlags
, DeviceInterfaceData
);
2597 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2601 /***********************************************************************
2602 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2604 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2605 HDEVINFO DeviceInfoSet
,
2606 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2610 PCSTR InfSectionName
)
2613 PWSTR InfSectionNameW
= NULL
;
2615 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2616 samDesired
, InfHandle
, InfSectionName
);
2619 if (!InfSectionName
)
2621 SetLastError(ERROR_INVALID_PARAMETER
);
2622 return INVALID_HANDLE_VALUE
;
2624 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2625 if (!InfSectionNameW
)
2626 return INVALID_HANDLE_VALUE
;
2628 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2629 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2631 MyFree(InfSectionNameW
);
2635 /***********************************************************************
2636 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2638 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2639 HDEVINFO DeviceInfoSet
,
2640 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2644 PCWSTR InfSectionName
)
2647 LPWSTR SymbolicLink
;
2648 DWORD Length
, Index
;
2650 WCHAR bracedGuidString
[39];
2651 struct DeviceInterface
*DevItf
;
2652 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2654 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2655 samDesired
, InfHandle
, InfSectionName
);
2657 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2658 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2660 SetLastError(ERROR_INVALID_HANDLE
);
2661 return INVALID_HANDLE_VALUE
;
2663 if (!DeviceInterfaceData
||
2664 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2665 !DeviceInterfaceData
->Reserved
)
2667 SetLastError(ERROR_INVALID_PARAMETER
);
2668 return INVALID_HANDLE_VALUE
;
2670 if (InfHandle
&& !InfSectionName
)
2672 SetLastError(ERROR_INVALID_PARAMETER
);
2673 return INVALID_HANDLE_VALUE
;
2676 hKey
= SetupDiOpenClassRegKeyExW(&DeviceInterfaceData
->InterfaceClassGuid
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2677 if (hKey
== INVALID_HANDLE_VALUE
)
2679 hKey
= SetupDiOpenClassRegKeyExW(NULL
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2680 if (hKey
== INVALID_HANDLE_VALUE
)
2682 SetLastError(ERROR_INVALID_PARAMETER
);
2683 return INVALID_HANDLE_VALUE
;
2685 SETUPDI_GuidToString(&DeviceInterfaceData
->InterfaceClassGuid
, bracedGuidString
);
2687 if (RegCreateKeyExW(hKey
, bracedGuidString
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
) != ERROR_SUCCESS
)
2689 SetLastError(ERROR_INVALID_PARAMETER
);
2690 return INVALID_HANDLE_VALUE
;
2696 DevItf
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2698 Length
= (wcslen(DevItf
->SymbolicLink
)+1) * sizeof(WCHAR
);
2699 SymbolicLink
= HeapAlloc(GetProcessHeap(), 0, Length
);
2703 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2704 return INVALID_HANDLE_VALUE
;
2707 wcscpy(SymbolicLink
, DevItf
->SymbolicLink
);
2710 while(SymbolicLink
[Index
])
2712 if (SymbolicLink
[Index
] == L
'\\')
2714 SymbolicLink
[Index
] = L
'#';
2719 rc
= RegCreateKeyExW(hKey
, SymbolicLink
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
);
2722 HeapFree(GetProcessHeap(), 0, SymbolicLink
);
2724 if (rc
== ERROR_SUCCESS
)
2726 if (InfHandle
&& InfSectionName
)
2728 if (!SetupInstallFromInfSection(NULL
/*FIXME */,
2731 SPINST_INIFILES
| SPINST_REGISTRY
| SPINST_INI2REG
| SPINST_FILES
| SPINST_BITREG
| SPINST_REGSVR
| SPINST_UNREGSVR
| SPINST_PROFILEITEMS
| SPINST_COPYINF
,
2735 set
->SelectedDevice
->InstallParams
.InstallMsgHandler
,
2736 set
->SelectedDevice
->InstallParams
.InstallMsgHandlerContext
,
2737 INVALID_HANDLE_VALUE
,
2740 RegCloseKey(hDevKey
);
2741 return INVALID_HANDLE_VALUE
;
2750 /***********************************************************************
2751 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2753 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2754 HDEVINFO DeviceInfoSet
,
2755 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2758 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2761 TRACE("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2763 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2764 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2766 SetLastError(ERROR_INVALID_HANDLE
);
2769 if (!DeviceInterfaceData
||
2770 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2771 !DeviceInterfaceData
->Reserved
)
2773 SetLastError(ERROR_INVALID_PARAMETER
);
2777 FIXME("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2778 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2782 /***********************************************************************
2783 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2786 * DeviceInfoSet [I] Set of devices from which to enumerate
2788 * DeviceInfoData [I] (Optional) If specified, a specific device
2789 * instance from which to enumerate interfaces.
2790 * If it isn't specified, all interfaces for all
2791 * devices in the set are enumerated.
2792 * InterfaceClassGuid [I] The interface class to enumerate.
2793 * MemberIndex [I] An index of the interface instance to enumerate.
2794 * A caller should start with MemberIndex set to 0,
2795 * and continue until the function fails with
2796 * ERROR_NO_MORE_ITEMS.
2797 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2798 * member must be set to
2799 * sizeof(SP_DEVICE_INTERFACE_DATA).
2802 * Success: non-zero value.
2803 * Failure: FALSE. Call GetLastError() for more info.
2805 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2806 HDEVINFO DeviceInfoSet
,
2807 PSP_DEVINFO_DATA DeviceInfoData
,
2808 CONST GUID
* InterfaceClassGuid
,
2810 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2812 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2815 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet
, DeviceInfoData
,
2816 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2818 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2819 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2821 SetLastError(ERROR_INVALID_HANDLE
);
2824 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2825 !DeviceInfoData
->Reserved
))
2827 SetLastError(ERROR_INVALID_PARAMETER
);
2830 if (!DeviceInterfaceData
||
2831 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2833 SetLastError(ERROR_INVALID_PARAMETER
);
2838 struct DeviceInfo
*devInfo
=
2839 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2841 PLIST_ENTRY InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2842 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2844 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2845 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2847 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2850 if (MemberIndex
-- == 0)
2852 /* return this item */
2853 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2854 &DevItf
->InterfaceClassGuid
,
2856 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2857 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2861 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2864 SetLastError(ERROR_NO_MORE_ITEMS
);
2869 PLIST_ENTRY ItemList
= set
->ListHead
.Flink
;
2870 while (ItemList
!= &set
->ListHead
&& !found
)
2872 PLIST_ENTRY InterfaceListEntry
;
2873 struct DeviceInfo
*devInfo
=
2874 CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
2875 InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2876 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2878 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2879 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2881 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2884 if (MemberIndex
-- == 0)
2886 /* return this item */
2887 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2888 &DevItf
->InterfaceClassGuid
,
2890 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2891 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2895 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2897 ItemList
= ItemList
->Flink
;
2901 SetLastError(ERROR_NO_MORE_ITEMS
);
2906 /***********************************************************************
2907 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2909 * Destroy a DeviceInfoList and free all used memory of the list.
2912 * devinfo [I] DeviceInfoList pointer to list to destroy
2915 * Success: non zero value.
2916 * Failure: zero value.
2918 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2922 TRACE("%p\n", devinfo
);
2923 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
2925 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2927 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
2929 ret
= DestroyDeviceInfoSet(list
);
2934 SetLastError(ERROR_INVALID_HANDLE
);
2939 /***********************************************************************
2940 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2942 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2943 HDEVINFO DeviceInfoSet
,
2944 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2945 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2946 DWORD DeviceInterfaceDetailDataSize
,
2947 PDWORD RequiredSize
,
2948 PSP_DEVINFO_DATA DeviceInfoData
)
2950 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2951 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2952 DWORD sizeW
= 0, bytesNeeded
;
2955 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
2956 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2957 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2959 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2960 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2962 SetLastError(ERROR_INVALID_HANDLE
);
2965 if (!DeviceInterfaceData
||
2966 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2967 !DeviceInterfaceData
->Reserved
)
2969 SetLastError(ERROR_INVALID_PARAMETER
);
2972 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
<
2973 FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1 ||
2974 DeviceInterfaceDetailData
->cbSize
> sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
2976 SetLastError(ERROR_INVALID_USER_BUFFER
);
2979 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
2981 SetLastError(ERROR_INVALID_USER_BUFFER
);
2986 if (DeviceInterfaceDetailData
!= NULL
)
2988 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2989 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2990 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)MyMalloc(sizeW
);
2991 if (!DeviceInterfaceDetailDataW
)
2993 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2996 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2998 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2999 ret
= SetupDiGetDeviceInterfaceDetailW(
3001 DeviceInterfaceData
,
3002 DeviceInterfaceDetailDataW
,
3006 bytesNeeded
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
3007 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
3009 *RequiredSize
= bytesNeeded
;
3010 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= bytesNeeded
)
3012 if (!WideCharToMultiByte(
3014 DeviceInterfaceDetailDataW
->DevicePath
, -1,
3015 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
3022 MyFree(DeviceInterfaceDetailDataW
);
3027 /***********************************************************************
3028 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3030 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
3031 HDEVINFO DeviceInfoSet
,
3032 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3033 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
3034 DWORD DeviceInterfaceDetailDataSize
,
3035 PDWORD RequiredSize
,
3036 PSP_DEVINFO_DATA DeviceInfoData
)
3038 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3041 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3042 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3043 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3045 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3046 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3048 SetLastError(ERROR_INVALID_HANDLE
);
3051 if (!DeviceInterfaceData
||
3052 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3053 !DeviceInterfaceData
->Reserved
)
3055 SetLastError(ERROR_INVALID_PARAMETER
);
3058 if (DeviceInterfaceDetailData
&& DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
3060 SetLastError(ERROR_INVALID_USER_BUFFER
);
3063 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3065 SetLastError(ERROR_INVALID_USER_BUFFER
);
3068 if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3070 SetLastError(ERROR_INVALID_PARAMETER
);
3073 if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
3075 SetLastError(ERROR_INVALID_PARAMETER
);
3080 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
3081 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
3082 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
3083 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
3085 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
3087 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3089 *RequiredSize
= sizeRequired
;
3093 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
3094 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
3097 memcpy(&DeviceInfoData
->ClassGuid
,
3098 &deviceInterface
->DeviceInfo
->ClassGuid
,
3100 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
3101 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
3109 struct PropertyMapEntry
3116 static struct PropertyMapEntry PropertyMap
[] = {
3117 { REG_SZ
, "DeviceDesc", REGSTR_VAL_DEVDESC
},
3118 { REG_MULTI_SZ
, "HardwareId", REGSTR_VAL_HARDWAREID
},
3119 { REG_MULTI_SZ
, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS
},
3120 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3121 { REG_SZ
, "Service", REGSTR_VAL_SERVICE
},
3122 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3123 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3124 { REG_SZ
, "Class", REGSTR_VAL_CLASS
},
3125 { REG_SZ
, "ClassGUID", REGSTR_VAL_CLASSGUID
},
3126 { REG_SZ
, "Driver", REGSTR_VAL_DRIVER
},
3127 { REG_DWORD
, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS
},
3128 { REG_SZ
, "Mfg", REGSTR_VAL_MFG
},
3129 { REG_SZ
, "FriendlyName", REGSTR_VAL_FRIENDLYNAME
},
3130 { REG_SZ
, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION
},
3131 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3132 { REG_DWORD
, "Capabilities", REGSTR_VAL_CAPABILITIES
},
3133 { REG_DWORD
, "UINumber", REGSTR_VAL_UI_NUMBER
},
3134 { REG_MULTI_SZ
, "UpperFilters", REGSTR_VAL_UPPERFILTERS
},
3135 { REG_MULTI_SZ
, "LowerFilters", REGSTR_VAL_LOWERFILTERS
},
3136 { 0, NULL
, NULL
}, /* SPDRP_BUSTYPEGUID */
3137 { 0, NULL
, NULL
}, /* SPDRP_LEGACYBUSTYPE */
3138 { 0, NULL
, NULL
}, /* SPDRP_BUSNUMBER */
3139 { 0, NULL
, NULL
}, /* SPDRP_ENUMERATOR_NAME */
3140 { REG_BINARY
, "Security", REGSTR_SECURITY
},
3141 { 0, NULL
, NULL
}, /* SPDRP_SECURITY_SDS */
3142 { 0, NULL
, NULL
}, /* SPDRP_DEVTYPE */
3143 { 0, NULL
, NULL
}, /* SPDRP_EXCLUSIVE */
3144 { 0, NULL
, NULL
}, /* SPDRP_CHARACTERISTICS */
3145 { 0, NULL
, NULL
}, /* SPDRP_ADDRESS */
3146 { REG_SZ
, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT
},
3147 { 0, NULL
, NULL
}, /* SPDRP_DEVICE_POWER_DATA */
3148 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY */
3149 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3150 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3151 { 0, NULL
, NULL
}, /* SPDRP_INSTALL_STATE */
3154 /***********************************************************************
3155 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3157 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3158 HDEVINFO DeviceInfoSet
,
3159 PSP_DEVINFO_DATA DeviceInfoData
,
3161 PDWORD PropertyRegDataType
,
3162 PBYTE PropertyBuffer
,
3163 DWORD PropertyBufferSize
,
3164 PDWORD RequiredSize
)
3167 BOOL bIsStringProperty
;
3169 DWORD RequiredSizeA
, RequiredSizeW
;
3170 DWORD PropertyBufferSizeW
= 0;
3171 PBYTE PropertyBufferW
= NULL
;
3173 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3174 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3177 if (PropertyBufferSize
!= 0)
3179 PropertyBufferSizeW
= PropertyBufferSize
* 2;
3180 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
3181 if (!PropertyBufferW
)
3183 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3188 ret
= SetupDiGetDeviceRegistryPropertyW(
3194 PropertyBufferSizeW
,
3197 if (ret
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)