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 /* Unicode constants */
25 static const WCHAR BackSlash
[] = {'\\',0};
26 static const WCHAR DateFormat
[] = {'%','u','-','%','u','-','%','u',0};
27 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
28 static const WCHAR DotHW
[] = {'.','H','W',0};
29 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
30 static const WCHAR InfDirectory
[] = {'i','n','f','\\',0};
31 static const WCHAR InstanceKeyFormat
[] = {'%','0','4','l','u',0};
32 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
33 static const WCHAR VersionFormat
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
35 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
36 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
37 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
38 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
39 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT
[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
42 (CALLBACK
* CLASS_INSTALL_PROC
) (
43 IN DI_FUNCTION InstallFunction
,
44 IN HDEVINFO DeviceInfoSet
,
45 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
47 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
48 IN HDEVINFO DeviceInfoSet
,
49 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
51 (CALLBACK
* COINSTALLER_PROC
) (
52 IN DI_FUNCTION InstallFunction
,
53 IN HDEVINFO DeviceInfoSet
,
54 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
55 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
57 struct CoInstallerElement
62 COINSTALLER_PROC Function
;
63 BOOL DoPostProcessing
;
67 struct GetSectionCallbackInfo
69 PSP_ALTPLATFORM_INFO PlatformInfo
;
73 WCHAR BestSection
[LINE_LEN
+ 1];
74 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
79 static void SETUPDI_GuidToString(const GUID
*guid
, LPWSTR guidStr
)
81 static const WCHAR fmt
[] = {'{','%','0','8','X','-','%','0','4','X','-',
82 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
83 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
86 sprintfW(guidStr
, fmt
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
87 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
88 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
92 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
96 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
97 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
98 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
99 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
100 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
101 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
102 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
103 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
104 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
105 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
106 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
107 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
108 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
109 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
110 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
111 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
112 case CR_ALREADY_SUCH_DEVINST
: return ERROR_DEVINST_ALREADY_EXISTS
;
113 case CR_SUCCESS
: return ERROR_SUCCESS
;
114 default: return ERROR_GEN_FAILURE
;
117 /* Does not happen */
120 /* Lower scores are best ones */
123 IN LPCWSTR SectionName
,
124 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
127 OUT PDWORD ScorePlatform
,
128 OUT PDWORD ScoreMajorVersion
,
129 OUT PDWORD ScoreMinorVersion
,
130 OUT PDWORD ScoreProductType
,
131 OUT PDWORD ScoreSuiteMask
)
133 LPWSTR Section
= NULL
;
134 //LPCWSTR pExtensionPlatform;
135 LPCWSTR pExtensionArchitecture
;
140 //static const WCHAR ExtensionPlatformNone[] = {'.',0};
141 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
142 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
144 static const WCHAR ExtensionArchitectureNone
[] = {0};
145 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
146 static const WCHAR ExtensionArchitectureamd64
[] = {'A','M','D','6','4',0};
147 static const WCHAR ExtensionArchitectureia64
[] = {'I','A','6','4',0};
148 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
149 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
150 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
152 TRACE("%s %p 0x%x 0x%x\n",
153 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
155 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
157 Section
= pSetupDuplicateString(SectionName
);
160 TRACE("pSetupDuplicateString() failed\n");
164 /* Set various extensions values */
165 switch (PlatformInfo
->Platform
)
167 case VER_PLATFORM_WIN32_WINDOWS
:
168 //pExtensionPlatform = ExtensionPlatformWindows;
170 case VER_PLATFORM_WIN32_NT
:
171 //pExtensionPlatform = ExtensionPlatformNT;
174 ERR("Unknown platform 0x%lx\n", PlatformInfo
->Platform
);
175 //pExtensionPlatform = ExtensionPlatformNone;
178 switch (PlatformInfo
->ProcessorArchitecture
)
180 case PROCESSOR_ARCHITECTURE_ALPHA
:
181 pExtensionArchitecture
= ExtensionArchitecturealpha
;
183 case PROCESSOR_ARCHITECTURE_AMD64
:
184 pExtensionArchitecture
= ExtensionArchitectureamd64
;
186 case PROCESSOR_ARCHITECTURE_IA64
:
187 pExtensionArchitecture
= ExtensionArchitectureia64
;
189 case PROCESSOR_ARCHITECTURE_INTEL
:
190 pExtensionArchitecture
= ExtensionArchitecturex86
;
192 case PROCESSOR_ARCHITECTURE_MIPS
:
193 pExtensionArchitecture
= ExtensionArchitecturemips
;
195 case PROCESSOR_ARCHITECTURE_PPC
:
196 pExtensionArchitecture
= ExtensionArchitectureppc
;
199 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
200 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
201 pExtensionArchitecture
= ExtensionArchitectureNone
;
207 * Field[1] Architecture
208 * Field[2] Major version
209 * Field[3] Minor version
210 * Field[4] Product type
211 * Field[5] Suite mask
212 * Remark: these fields may be NULL if the information is not provided
215 if (Fields
[0] == NULL
)
217 TRACE("No extension found\n");
218 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
222 Fields
[1] = Fields
[0] + 1;
223 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
224 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
226 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
230 *(Fields
[i
] - 1) = UNICODE_NULL
;
233 /* Take care of first 2 fields */
234 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
236 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
238 TRACE("Mismatch on platform field\n");
241 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
243 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
245 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
247 TRACE("Mismatch on platform field\n");
250 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
254 /* No platform specified */
255 *ScorePlatform
|= 0x02;
257 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
259 /* No architecture specified */
260 *ScorePlatform
|= 0x01;
262 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
264 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
265 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
269 /* Check if informations are matching */
270 if (Fields
[2] && *Fields
[2])
272 DWORD MajorVersion
, MinorVersion
= 0;
273 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
274 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
275 (errno
== ERANGE
|| errno
== EINVAL
))
277 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
280 if (Fields
[3] && *Fields
[3])
282 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
283 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
284 (errno
== ERANGE
|| errno
== EINVAL
))
286 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
290 if (PlatformInfo
->MajorVersion
< MajorVersion
||
291 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
293 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
294 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
297 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
298 if (MajorVersion
== PlatformInfo
->MajorVersion
)
299 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
301 *ScoreMinorVersion
= MinorVersion
;
303 else if (Fields
[3] && *Fields
[3])
305 TRACE("Minor version found without major version\n");
310 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
311 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
314 if (Fields
[4] && *Fields
[4])
316 DWORD CurrentProductType
;
317 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
318 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
319 (errno
== ERANGE
|| errno
== EINVAL
))
321 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
324 if (CurrentProductType
!= ProductType
)
326 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
327 CurrentProductType
, ProductType
);
332 *ScoreProductType
= 1;
334 if (Fields
[5] && *Fields
[5])
336 DWORD CurrentSuiteMask
;
337 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
338 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
339 (errno
== ERANGE
|| errno
== EINVAL
))
341 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
344 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
346 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
347 CurrentSuiteMask
, SuiteMask
);
350 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
353 *ScoreSuiteMask
= SuiteMask
;
364 IN LPCWSTR SectionName
,
367 struct GetSectionCallbackInfo
*info
= Context
;
368 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
371 if (SectionName
[info
->PrefixLength
] != '.')
374 ret
= CheckSectionValid(
375 &SectionName
[info
->PrefixLength
],
379 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
382 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
385 if (Score1
> info
->BestScore1
) goto done
;
386 if (Score1
< info
->BestScore1
) goto bettersection
;
387 if (Score2
> info
->BestScore2
) goto done
;
388 if (Score2
< info
->BestScore2
) goto bettersection
;
389 if (Score3
> info
->BestScore3
) goto done
;
390 if (Score3
< info
->BestScore3
) goto bettersection
;
391 if (Score4
> info
->BestScore4
) goto done
;
392 if (Score4
< info
->BestScore4
) goto bettersection
;
393 if (Score5
> info
->BestScore5
) goto done
;
394 if (Score5
< info
->BestScore5
) goto bettersection
;
398 strcpyW(info
->BestSection
, SectionName
);
399 info
->BestScore1
= Score1
;
400 info
->BestScore2
= Score2
;
401 info
->BestScore3
= Score3
;
402 info
->BestScore4
= Score4
;
403 info
->BestScore5
= Score5
;
409 /***********************************************************************
410 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
413 SetupDiGetActualSectionToInstallExW(
415 IN PCWSTR InfSectionName
,
416 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
417 OUT PWSTR InfSectionWithExt OPTIONAL
,
418 IN DWORD InfSectionWithExtSize
,
419 OUT PDWORD RequiredSize OPTIONAL
,
420 OUT PWSTR
* Extension OPTIONAL
,
425 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
426 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
427 RequiredSize
, Extension
, Reserved
);
429 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
430 SetLastError(ERROR_INVALID_HANDLE
);
431 else if (!InfSectionName
)
432 SetLastError(ERROR_INVALID_PARAMETER
);
433 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
434 SetLastError(ERROR_INVALID_USER_BUFFER
);
435 else if (Reserved
!= NULL
)
436 SetLastError(ERROR_INVALID_PARAMETER
);
439 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
440 static BYTE CurrentProductType
= 0;
441 static WORD CurrentSuiteMask
= 0;
442 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
443 struct GetSectionCallbackInfo CallbackInfo
;
448 /* Fill platform info if needed */
449 if (AlternatePlatformInfo
)
451 pPlatformInfo
= AlternatePlatformInfo
;
457 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
459 /* That's the first time we go here. We need to fill in the structure */
460 SYSTEM_INFO SystemInfo
;
461 GetSystemInfo(&SystemInfo
);
462 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
463 CurrentPlatform
.Platform
= OsVersionInfo
.dwPlatformId
;
464 CurrentPlatform
.MajorVersion
= OsVersionInfo
.dwMajorVersion
;
465 CurrentPlatform
.MinorVersion
= OsVersionInfo
.dwMinorVersion
;
466 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
467 CurrentPlatform
.Reserved
= 0;
468 CurrentProductType
= OsVersionInfo
.wProductType
;
469 CurrentSuiteMask
= OsVersionInfo
.wSuiteMask
;
471 ProductType
= CurrentProductType
;
472 SuiteMask
= CurrentSuiteMask
;
475 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
476 CallbackInfo
.ProductType
= ProductType
;
477 CallbackInfo
.SuiteMask
= SuiteMask
;
478 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
479 CallbackInfo
.BestScore1
= ULONG_MAX
;
480 CallbackInfo
.BestScore2
= ULONG_MAX
;
481 CallbackInfo
.BestScore3
= ULONG_MAX
;
482 CallbackInfo
.BestScore4
= ULONG_MAX
;
483 CallbackInfo
.BestScore5
= ULONG_MAX
;
484 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
485 TRACE("EnumerateSectionsStartingWith(InfSectionName = %S)\n", InfSectionName
);
486 if (!EnumerateSectionsStartingWith(
492 SetLastError(ERROR_GEN_FAILURE
);
495 TRACE("CallbackInfo.BestSection = %S\n", CallbackInfo
.BestSection
);
497 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
498 if (RequiredSize
!= NULL
)
499 *RequiredSize
= dwFullLength
+ 1;
501 if (InfSectionWithExtSize
> 0)
503 if (InfSectionWithExtSize
< dwFullLength
+ 1)
505 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
508 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
511 DWORD dwLength
= lstrlenW(InfSectionName
);
512 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
520 TRACE("Returning %d\n", ret
);
527 IN
struct DeviceInfoSet
*list
,
528 IN LPCWSTR InstancePath
,
529 IN LPCGUID pClassGuid
,
530 OUT
struct DeviceInfo
**pDeviceInfo
)
534 struct DeviceInfo
*deviceInfo
;
538 size
= FIELD_OFFSET(struct DeviceInfo
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
539 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
542 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
545 ZeroMemory(deviceInfo
, size
);
547 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
548 if (cr
!= CR_SUCCESS
)
550 SetLastError(GetErrorCodeFromCrCode(cr
));
554 deviceInfo
->set
= list
;
555 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
556 strcpyW(deviceInfo
->Data
, InstancePath
);
557 deviceInfo
->instanceId
= deviceInfo
->Data
;
558 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
559 deviceInfo
->DeviceDescription
= NULL
;
560 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
561 deviceInfo
->CreationFlags
= 0;
562 InitializeListHead(&deviceInfo
->DriverListHead
);
563 InitializeListHead(&deviceInfo
->InterfaceListHead
);
565 *pDeviceInfo
= deviceInfo
;
571 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
573 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
574 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
579 DestroyDeviceInfo(struct DeviceInfo
*deviceInfo
)
581 PLIST_ENTRY ListEntry
;
582 struct DriverInfoElement
*driverInfo
;
583 struct DeviceInterface
*deviceInterface
;
585 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
587 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
588 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
589 if (!DestroyDriverInfoElement(driverInfo
))
592 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
594 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
595 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
596 if (!DestroyDeviceInterface(deviceInterface
))
599 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
600 if (deviceInfo
->hmodDevicePropPageProvider
)
601 FreeLibrary(deviceInfo
->hmodDevicePropPageProvider
);
602 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
606 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
608 PLIST_ENTRY ListEntry
;
609 struct DeviceInfo
*deviceInfo
;
611 while (!IsListEmpty(&list
->ListHead
))
613 ListEntry
= RemoveHeadList(&list
->ListHead
);
614 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
);
615 if (!DestroyDeviceInfo(deviceInfo
))
618 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
619 RegCloseKey(list
->HKLM
);
620 CM_Disconnect_Machine(list
->hMachine
);
621 DestroyClassInstallParams(&list
->ClassInstallParams
);
622 if (list
->hmodClassPropPageProvider
)
623 FreeLibrary(list
->hmodClassPropPageProvider
);
624 return HeapFree(GetProcessHeap(), 0, list
);
627 /***********************************************************************
628 * SetupDiBuildClassInfoList (SETUPAPI.@)
630 * Returns a list of setup class GUIDs that identify the classes
631 * that are installed on a local machine.
634 * Flags [I] control exclusion of classes from the list.
635 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
636 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
637 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
643 BOOL WINAPI
SetupDiBuildClassInfoList(
645 LPGUID ClassGuidList
,
646 DWORD ClassGuidListSize
,
650 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
651 ClassGuidListSize
, RequiredSize
,
655 /***********************************************************************
656 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
658 * Returns a list of setup class GUIDs that identify the classes
659 * that are installed on a local or remote machine.
662 * Flags [I] control exclusion of classes from the list.
663 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
664 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
665 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
666 * MachineName [I] name of a remote machine.
667 * Reserved [I] must be NULL.
673 BOOL WINAPI
SetupDiBuildClassInfoListExA(
675 LPGUID ClassGuidList
,
676 DWORD ClassGuidListSize
,
681 LPWSTR MachineNameW
= NULL
;
684 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
685 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
689 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
690 if (MachineNameW
== NULL
) return FALSE
;
693 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
694 ClassGuidListSize
, RequiredSize
,
695 MachineNameW
, Reserved
);
697 MyFree(MachineNameW
);
702 /***********************************************************************
703 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
705 * Returns a list of setup class GUIDs that identify the classes
706 * that are installed on a local or remote machine.
709 * Flags [I] control exclusion of classes from the list.
710 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
711 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
712 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
713 * MachineName [I] name of a remote machine.
714 * Reserved [I] must be NULL.
720 BOOL WINAPI
SetupDiBuildClassInfoListExW(
722 LPGUID ClassGuidList
,
723 DWORD ClassGuidListSize
,
729 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
734 DWORD dwGuidListIndex
= 0;
736 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
737 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
741 SetLastError(ERROR_INVALID_PARAMETER
);
744 else if (!ClassGuidList
&& ClassGuidListSize
> 0)
746 SetLastError(ERROR_INVALID_PARAMETER
);
750 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
751 KEY_ENUMERATE_SUB_KEYS
,
755 if (hClassesKey
== INVALID_HANDLE_VALUE
)
760 for (dwIndex
= 0; ; dwIndex
++)
763 lError
= RegEnumKeyExW(hClassesKey
,
771 TRACE("RegEnumKeyExW() returns %d\n", lError
);
772 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
774 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
776 if (RegOpenKeyExW(hClassesKey
,
782 RegCloseKey(hClassesKey
);
786 if (!RegQueryValueExW(hClassKey
,
787 REGSTR_VAL_NOUSECLASS
,
793 TRACE("'NoUseClass' value found!\n");
794 RegCloseKey(hClassKey
);
798 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
799 (!RegQueryValueExW(hClassKey
,
800 REGSTR_VAL_NOINSTALLCLASS
,
806 TRACE("'NoInstallClass' value found!\n");
807 RegCloseKey(hClassKey
);
811 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
812 (!RegQueryValueExW(hClassKey
,
813 REGSTR_VAL_NODISPLAYCLASS
,
819 TRACE("'NoDisplayClass' value found!\n");
820 RegCloseKey(hClassKey
);
824 RegCloseKey(hClassKey
);
826 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
827 if (dwGuidListIndex
< ClassGuidListSize
)
829 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
833 TRACE("Guid: %p\n", &szKeyName
[1]);
835 UuidFromStringW(&szKeyName
[1],
836 &ClassGuidList
[dwGuidListIndex
]);
842 if (lError
!= ERROR_SUCCESS
)
846 RegCloseKey(hClassesKey
);
848 if (RequiredSize
!= NULL
)
849 *RequiredSize
= dwGuidListIndex
;
851 if (ClassGuidListSize
< dwGuidListIndex
)
853 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
860 /***********************************************************************
861 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
863 BOOL WINAPI
SetupDiClassGuidsFromNameA(
865 LPGUID ClassGuidList
,
866 DWORD ClassGuidListSize
,
869 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
870 ClassGuidListSize
, RequiredSize
,
874 /***********************************************************************
875 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
877 BOOL WINAPI
SetupDiClassGuidsFromNameW(
879 LPGUID ClassGuidList
,
880 DWORD ClassGuidListSize
,
883 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
884 ClassGuidListSize
, RequiredSize
,
888 /***********************************************************************
889 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
891 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
893 LPGUID ClassGuidList
,
894 DWORD ClassGuidListSize
,
899 LPWSTR ClassNameW
= NULL
;
900 LPWSTR MachineNameW
= NULL
;
903 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName
), ClassGuidList
,
904 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
908 SetLastError(ERROR_INVALID_PARAMETER
);
912 ClassNameW
= pSetupMultiByteToUnicode(ClassName
, CP_ACP
);
913 if (ClassNameW
== NULL
)
918 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
919 if (MachineNameW
== NULL
)
926 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
927 ClassGuidListSize
, RequiredSize
,
928 MachineNameW
, Reserved
);
930 MyFree(MachineNameW
);
936 /***********************************************************************
937 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
939 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
941 LPGUID ClassGuidList
,
942 DWORD ClassGuidListSize
,
948 WCHAR szClassName
[MAX_CLASS_NAME_LEN
];
954 DWORD dwGuidListIndex
= 0;
956 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
957 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
959 if (!ClassName
|| !RequiredSize
)
961 SetLastError(ERROR_INVALID_PARAMETER
);
964 if (!ClassGuidList
&& ClassGuidListSize
> 0)
966 SetLastError(ERROR_INVALID_PARAMETER
);
971 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
972 KEY_ENUMERATE_SUB_KEYS
,
976 if (hClassesKey
== INVALID_HANDLE_VALUE
)
981 for (dwIndex
= 0; ; dwIndex
++)
984 lError
= RegEnumKeyExW(hClassesKey
,
992 TRACE("RegEnumKeyExW() returns %d\n", lError
);
993 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
995 TRACE("Key name: %p\n", szKeyName
);
997 if (RegOpenKeyExW(hClassesKey
,
1003 RegCloseKey(hClassesKey
);
1007 dwLength
= MAX_CLASS_NAME_LEN
* sizeof(WCHAR
);
1008 if (!RegQueryValueExW(hClassKey
,
1012 (LPBYTE
)szClassName
,
1015 TRACE("Class name: %p\n", szClassName
);
1017 if (strcmpiW(szClassName
, ClassName
) == 0)
1019 TRACE("Found matching class name\n");
1021 TRACE("Guid: %p\n", szKeyName
);
1022 if (dwGuidListIndex
< ClassGuidListSize
)
1024 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
1028 TRACE("Guid: %p\n", &szKeyName
[1]);
1030 UuidFromStringW(&szKeyName
[1],
1031 &ClassGuidList
[dwGuidListIndex
]);
1038 RegCloseKey(hClassKey
);
1041 if (lError
!= ERROR_SUCCESS
)
1045 RegCloseKey(hClassesKey
);
1047 if (RequiredSize
!= NULL
)
1048 *RequiredSize
= dwGuidListIndex
;
1050 if (ClassGuidListSize
< dwGuidListIndex
)
1052 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1059 /***********************************************************************
1060 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1062 BOOL WINAPI
SetupDiClassNameFromGuidA(
1063 const GUID
* ClassGuid
,
1065 DWORD ClassNameSize
,
1066 PDWORD RequiredSize
)
1068 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
1069 ClassNameSize
, RequiredSize
,
1073 /***********************************************************************
1074 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1076 BOOL WINAPI
SetupDiClassNameFromGuidW(
1077 const GUID
* ClassGuid
,
1079 DWORD ClassNameSize
,
1080 PDWORD RequiredSize
)
1082 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
1083 ClassNameSize
, RequiredSize
,
1087 /***********************************************************************
1088 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1090 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1091 const GUID
* ClassGuid
,
1093 DWORD ClassNameSize
,
1094 PDWORD RequiredSize
,
1098 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1099 LPWSTR MachineNameW
= NULL
;
1103 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1104 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1105 RequiredSize
, MachineNameW
, Reserved
);
1108 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1109 ClassNameSize
, NULL
, NULL
);
1110 if (len
== 0 || len
> ClassNameSize
)
1112 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1116 MyFree(MachineNameW
);
1120 /***********************************************************************
1121 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1123 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1124 const GUID
* ClassGuid
,
1126 DWORD ClassNameSize
,
1127 PDWORD RequiredSize
,
1137 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
1138 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1140 /* Make sure there's a GUID */
1141 if (ClassGuid
== NULL
)
1143 SetLastError(ERROR_INVALID_CLASS
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1147 /* Make sure there's a real buffer when there's a size */
1148 if ((ClassNameSize
> 0) && (ClassName
== NULL
))
1150 SetLastError(ERROR_INVALID_PARAMETER
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1154 /* Open the key for the GUID */
1155 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INSTALLER
, MachineName
, Reserved
);
1157 if (hKey
== INVALID_HANDLE_VALUE
)
1160 /* Retrieve the class name data and close the key */
1161 rc
= QueryRegistryValue(hKey
, REGSTR_VAL_CLASS
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
1164 /* Make sure we got the data */
1165 if (rc
!= ERROR_SUCCESS
)
1171 /* Make sure the data is a string */
1172 if (dwRegType
!= REG_SZ
)
1175 SetLastError(ERROR_GEN_FAILURE
);
1179 /* Determine the length of the class name */
1180 dwLength
/= sizeof(WCHAR
);
1182 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
1183 /* Count the null-terminator */
1186 /* Inform the caller about the class name */
1187 if ((ClassName
!= NULL
) && (dwLength
<= ClassNameSize
))
1189 memcpy(ClassName
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
1190 ClassName
[dwLength
- 1] = UNICODE_NULL
;
1193 /* Inform the caller about the required size */
1194 if (RequiredSize
!= NULL
)
1195 *RequiredSize
= dwLength
;
1197 /* Clean up the buffer */
1200 /* Make sure the buffer was large enough */
1201 if ((ClassName
== NULL
) || (dwLength
> ClassNameSize
))
1203 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1210 /***********************************************************************
1211 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1214 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1217 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1220 /***********************************************************************
1221 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1224 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1229 LPWSTR MachineNameW
= NULL
;
1232 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1233 debugstr_a(MachineName
), Reserved
);
1237 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1238 if (MachineNameW
== NULL
)
1239 return INVALID_HANDLE_VALUE
;
1242 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1243 MachineNameW
, Reserved
);
1245 MyFree(MachineNameW
);
1250 /***********************************************************************
1251 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1253 * Create an empty DeviceInfoSet list.
1256 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1258 * hwndParent [I] hwnd needed for interface related actions.
1259 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1260 * local registry will be used.
1261 * Reserved [I] must be NULL
1264 * Success: empty list.
1265 * Failure: INVALID_HANDLE_VALUE.
1268 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1273 struct DeviceInfoSet
*list
= NULL
;
1274 DWORD size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
1277 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1279 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1280 debugstr_w(MachineName
), Reserved
);
1282 if (MachineName
!= NULL
)
1284 SIZE_T len
= strlenW(MachineName
);
1285 if (len
>= SP_MAX_MACHINENAME_LENGTH
- 4)
1287 SetLastError(ERROR_INVALID_MACHINENAME
);
1291 size
+= (len
+ 3) * sizeof(WCHAR
);
1296 if (Reserved
!= NULL
)
1298 SetLastError(ERROR_INVALID_PARAMETER
);
1299 return INVALID_HANDLE_VALUE
;
1302 list
= MyMalloc(size
);
1305 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1306 return INVALID_HANDLE_VALUE
;
1308 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
1310 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1311 memcpy(&list
->ClassGuid
,
1312 ClassGuid
? ClassGuid
: &GUID_NULL
,
1313 sizeof(list
->ClassGuid
));
1314 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1315 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1316 list
->InstallParams
.hwndParent
= hwndParent
;
1319 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
1320 if (rc
!= ERROR_SUCCESS
)
1322 SetLastError(ERROR_INVALID_MACHINENAME
);
1326 list
->szData
[0] = list
->szData
[1] = '\\';
1327 strcpyW(list
->szData
+ 2, MachineName
);
1328 list
->MachineName
= list
->szData
;
1332 list
->HKLM
= HKEY_LOCAL_MACHINE
;
1333 list
->MachineName
= NULL
;
1335 cr
= CM_Connect_MachineW(list
->MachineName
, &list
->hMachine
);
1336 if (cr
!= CR_SUCCESS
)
1338 SetLastError(GetErrorCodeFromCrCode(cr
));
1341 InitializeListHead(&list
->DriverListHead
);
1342 InitializeListHead(&list
->ListHead
);
1344 return (HDEVINFO
)list
;
1347 if (ret
== INVALID_HANDLE_VALUE
)
1351 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1352 RegCloseKey(list
->HKLM
);
1359 /***********************************************************************
1360 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1362 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1363 HDEVINFO DeviceInfoSet
,
1364 PSP_DEVINFO_DATA DeviceInfoData
,
1369 PCSTR InfSectionName
)
1371 PWSTR InfSectionNameW
= NULL
;
1374 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1375 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1379 if (!InfSectionName
)
1381 SetLastError(ERROR_INVALID_PARAMETER
);
1382 return INVALID_HANDLE_VALUE
;
1386 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
1387 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1390 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1391 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1392 MyFree(InfSectionNameW
);
1397 OpenHardwareProfileKey(
1400 IN DWORD samDesired
);
1402 /***********************************************************************
1403 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1405 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1406 HDEVINFO DeviceInfoSet
,
1407 PSP_DEVINFO_DATA DeviceInfoData
,
1412 PCWSTR InfSectionName
)
1414 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1415 struct DeviceInfo
*deviceInfo
;
1416 HKEY key
= INVALID_HANDLE_VALUE
;
1418 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
1422 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1423 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1425 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1427 SetLastError(ERROR_INVALID_HANDLE
);
1428 return INVALID_HANDLE_VALUE
;
1430 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1432 SetLastError(ERROR_INVALID_HANDLE
);
1433 return INVALID_HANDLE_VALUE
;
1435 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1436 || !DeviceInfoData
->Reserved
)
1438 SetLastError(ERROR_INVALID_PARAMETER
);
1439 return INVALID_HANDLE_VALUE
;
1441 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1443 SetLastError(ERROR_INVALID_FLAGS
);
1444 return INVALID_HANDLE_VALUE
;
1446 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1448 SetLastError(ERROR_INVALID_FLAGS
);
1449 return INVALID_HANDLE_VALUE
;
1451 if (InfHandle
&& !InfSectionName
)
1453 SetLastError(ERROR_INVALID_PARAMETER
);
1454 return INVALID_HANDLE_VALUE
;
1456 if (!InfHandle
&& InfSectionName
)
1458 SetLastError(ERROR_INVALID_PARAMETER
);
1459 return INVALID_HANDLE_VALUE
;
1462 deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1464 if (Scope
== DICS_FLAG_GLOBAL
)
1465 RootKey
= set
->HKLM
;
1466 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1468 hHWProfileKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
1469 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
1471 RootKey
= hHWProfileKey
;
1474 if (KeyType
== DIREG_DEV
)
1476 #if _WIN32_WINNT >= 0x502
1477 hKey
= SETUPDI_CreateDevKey(RootKey
, deviceInfo
, KEY_READ
| KEY_WRITE
);
1479 hKey
= SETUPDI_CreateDevKey(RootKey
, deviceInfo
, KEY_ALL_ACCESS
);
1481 if (hKey
== INVALID_HANDLE_VALUE
)
1484 if (Scope
== DICS_FLAG_GLOBAL
)
1486 HKEY hTempKey
= hKey
;
1488 rc
= RegCreateKeyExW(hTempKey
,
1489 L
"Device Parameters",
1492 REG_OPTION_NON_VOLATILE
,
1493 #if _WIN32_WINNT >= 0x502
1494 KEY_READ
| KEY_WRITE
,
1501 if (rc
== ERROR_SUCCESS
)
1502 RegCloseKey(hTempKey
);
1505 else /* KeyType == DIREG_DRV */
1507 #if _WIN32_WINNT >= 0x502
1508 hKey
= SETUPDI_CreateDrvKey(RootKey
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_READ
| KEY_WRITE
);
1510 hKey
= SETUPDI_CreateDrvKey(RootKey
, deviceInfo
, (UUID
*)&DeviceInfoData
->ClassGuid
, KEY_ALL_ACCESS
);
1512 if (hKey
== INVALID_HANDLE_VALUE
)
1516 /* Do installation of the specified section */
1519 FIXME("Need to install section %s in file %p\n",
1520 debugstr_w(InfSectionName
), InfHandle
);
1525 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
1526 RegCloseKey(hHWProfileKey
);
1527 if (hKey
!= NULL
&& hKey
!= key
)
1530 TRACE("Returning 0x%p\n", key
);
1534 /***********************************************************************
1535 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1537 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1538 HDEVINFO DeviceInfoSet
,
1540 CONST GUID
*ClassGuid
,
1541 PCSTR DeviceDescription
,
1543 DWORD CreationFlags
,
1544 PSP_DEVINFO_DATA DeviceInfoData
)
1547 LPWSTR DeviceNameW
= NULL
;
1548 LPWSTR DeviceDescriptionW
= NULL
;
1554 DeviceNameW
= pSetupMultiByteToUnicode(DeviceName
, CP_ACP
);
1555 if (DeviceNameW
== NULL
) return FALSE
;
1557 if (DeviceDescription
)
1559 DeviceDescriptionW
= pSetupMultiByteToUnicode(DeviceDescription
, CP_ACP
);
1560 if (DeviceDescriptionW
== NULL
)
1562 MyFree(DeviceNameW
);
1567 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1568 hwndParent
, CreationFlags
, DeviceInfoData
);
1570 MyFree(DeviceNameW
);
1571 MyFree(DeviceDescriptionW
);
1576 /***********************************************************************
1577 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1579 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1580 HDEVINFO DeviceInfoSet
,
1582 CONST GUID
*ClassGuid
,
1583 PCWSTR DeviceDescription
,
1585 DWORD CreationFlags
,
1586 PSP_DEVINFO_DATA DeviceInfoData
)
1588 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1589 struct DeviceInfo
*deviceInfo
= NULL
;
1592 DEVINST RootDevInst
;
1594 WCHAR GenInstanceId
[MAX_DEVICE_ID_LEN
];
1596 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
1597 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1598 hwndParent
, CreationFlags
, DeviceInfoData
);
1602 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1605 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1607 SetLastError(ERROR_INVALID_HANDLE
);
1612 SetLastError(ERROR_INVALID_PARAMETER
);
1615 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1617 SetLastError(ERROR_INVALID_HANDLE
);
1620 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1621 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1623 SetLastError(ERROR_CLASS_MISMATCH
);
1626 if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
1628 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
1629 SetLastError(ERROR_INVALID_FLAGS
);
1633 /* Get the root device instance */
1634 cr
= CM_Locate_DevInst_ExW(&RootDevInst
,
1636 CM_LOCATE_DEVINST_NORMAL
,
1638 if (cr
!= CR_SUCCESS
)
1640 SetLastError(ERROR_INVALID_DATA
);
1644 /* Create the new device instance */
1645 cr
= CM_Create_DevInst_ExW(&DevInst
,
1646 (DEVINSTID
)DeviceName
,
1648 (CreationFlags
& DICD_GENERATE_ID
) ?
1649 CM_CREATE_DEVINST_GENERATE_ID
: 0,
1651 if (cr
!= CR_SUCCESS
)
1653 SetLastError(GetErrorCodeFromCrCode(cr
));
1657 if (CreationFlags
& DICD_GENERATE_ID
)
1659 /* Grab the actual instance ID that was created */
1660 cr
= CM_Get_Device_ID_Ex(DevInst
,
1665 if (cr
!= CR_SUCCESS
)
1667 SetLastError(GetErrorCodeFromCrCode(cr
));
1671 DeviceName
= GenInstanceId
;
1672 TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName
));
1675 if (CreateDeviceInfo(set
, DeviceName
, ClassGuid
, &deviceInfo
))
1677 InsertTailList(&set
->ListHead
, &deviceInfo
->ListEntry
);
1679 if (!DeviceInfoData
)
1683 if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1685 SetLastError(ERROR_INVALID_USER_BUFFER
);
1689 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
1690 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
1691 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
1699 if (deviceInfo
!= NULL
)
1701 /* Remove deviceInfo from List */
1702 RemoveEntryList(&deviceInfo
->ListEntry
);
1704 /* Destroy deviceInfo */
1705 DestroyDeviceInfo(deviceInfo
);
1709 TRACE("Returning %d\n", ret
);
1713 /***********************************************************************
1714 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1716 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1717 HDEVINFO DeviceInfoSet
,
1718 PSP_DEVINFO_DATA DeviceInfoData
,
1720 PSP_DETSIG_CMPPROC CompareProc
,
1721 PVOID CompareContext
,
1722 PSP_DEVINFO_DATA DupDeviceInfoData
)
1724 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1725 WCHAR DevInstId
[MAX_DEVICE_ID_LEN
];
1726 DEVINST ParentDevInst
;
1728 DWORD dwError
= ERROR_SUCCESS
;
1730 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1731 CompareProc
, CompareContext
, DupDeviceInfoData
);
1733 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1735 SetLastError(ERROR_INVALID_HANDLE
);
1738 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1740 SetLastError(ERROR_INVALID_HANDLE
);
1743 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1744 || !DeviceInfoData
->Reserved
)
1746 SetLastError(ERROR_INVALID_PARAMETER
);
1750 if (Flags
& ~SPRDI_FIND_DUPS
)
1752 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~SPRDI_FIND_DUPS
);
1753 SetLastError(ERROR_INVALID_FLAGS
);
1757 if (Flags
& SPRDI_FIND_DUPS
)
1759 FIXME("Unimplemented codepath!\n");
1762 CM_Get_Device_ID_Ex(DeviceInfoData
->DevInst
,
1768 CM_Get_Parent_Ex(&ParentDevInst
,
1769 DeviceInfoData
->DevInst
,
1773 cr
= CM_Create_DevInst_Ex(&DeviceInfoData
->DevInst
,
1776 CM_CREATE_DEVINST_NORMAL
| CM_CREATE_DEVINST_DO_NOT_INSTALL
,
1778 if (cr
!= CR_SUCCESS
&&
1779 cr
!= CR_ALREADY_SUCH_DEVINST
)
1781 dwError
= ERROR_NO_SUCH_DEVINST
;
1784 SetLastError(dwError
);
1786 return (dwError
== ERROR_SUCCESS
);
1789 /***********************************************************************
1790 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1792 BOOL WINAPI
SetupDiEnumDeviceInfo(
1795 PSP_DEVINFO_DATA info
)
1799 TRACE("%p %d %p\n", devinfo
, index
, info
);
1803 SetLastError(ERROR_INVALID_PARAMETER
);
1806 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1808 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1809 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1811 if (info
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1812 SetLastError(ERROR_INVALID_USER_BUFFER
);
1815 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1816 while (ItemList
!= &list
->ListHead
&& index
-- > 0)
1817 ItemList
= ItemList
->Flink
;
1818 if (ItemList
== &list
->ListHead
)
1819 SetLastError(ERROR_NO_MORE_ITEMS
);
1822 struct DeviceInfo
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
1823 memcpy(&info
->ClassGuid
,
1824 &DevInfo
->ClassGuid
,
1826 info
->DevInst
= DevInfo
->dnDevInst
;
1827 info
->Reserved
= (ULONG_PTR
)DevInfo
;
1833 SetLastError(ERROR_INVALID_HANDLE
);
1836 SetLastError(ERROR_INVALID_HANDLE
);
1840 /***********************************************************************
1841 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1843 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1844 HDEVINFO DeviceInfoSet
,
1845 PSP_DEVINFO_DATA DeviceInfoData
,
1846 PSTR DeviceInstanceId
,
1847 DWORD DeviceInstanceIdSize
,
1848 PDWORD RequiredSize
)
1854 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1855 DeviceInstanceIdSize
, RequiredSize
);
1857 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1859 SetLastError(ERROR_INVALID_PARAMETER
);
1863 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1868 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1870 instanceId
= MyMalloc(size
* sizeof(WCHAR
));
1873 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1880 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
1882 DeviceInstanceIdSize
, NULL
, NULL
);
1888 if (len
> DeviceInstanceIdSize
)
1890 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1894 *RequiredSize
= len
;
1902 *RequiredSize
= size
;
1903 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1909 /***********************************************************************
1910 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1912 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
1913 HDEVINFO DeviceInfoSet
,
1914 PSP_DEVINFO_DATA DeviceInfoData
,
1915 PWSTR DeviceInstanceId
,
1916 DWORD DeviceInstanceIdSize
,
1917 PDWORD RequiredSize
)
1919 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1920 struct DeviceInfo
*devInfo
;
1922 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1923 DeviceInstanceIdSize
, RequiredSize
);
1925 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1927 SetLastError(ERROR_INVALID_HANDLE
);
1930 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1932 SetLastError(ERROR_INVALID_HANDLE
);
1935 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1936 || !DeviceInfoData
->Reserved
)
1938 SetLastError(ERROR_INVALID_PARAMETER
);
1941 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1942 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1944 SetLastError(ERROR_INVALID_PARAMETER
);
1947 if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
1949 SetLastError(ERROR_INVALID_PARAMETER
);
1952 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
1953 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
1955 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1957 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1960 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
1962 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
1966 /***********************************************************************
1967 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1969 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
1971 PCSTR InfSectionName
,
1972 PSTR InfSectionWithExt
,
1973 DWORD InfSectionWithExtSize
,
1974 PDWORD RequiredSize
,
1977 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
1978 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
1982 /***********************************************************************
1983 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1985 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
1987 PCWSTR InfSectionName
,
1988 PWSTR InfSectionWithExt
,
1989 DWORD InfSectionWithExtSize
,
1990 PDWORD RequiredSize
,
1993 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
1994 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
1998 /***********************************************************************
1999 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2002 SetupDiGetActualSectionToInstallExA(
2004 IN PCSTR InfSectionName
,
2005 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
2006 OUT PSTR InfSectionWithExt OPTIONAL
,
2007 IN DWORD InfSectionWithExtSize
,
2008 OUT PDWORD RequiredSize OPTIONAL
,
2009 OUT PSTR
* Extension OPTIONAL
,
2012 LPWSTR InfSectionNameW
= NULL
;
2013 LPWSTR InfSectionWithExtW
= NULL
;
2015 BOOL bResult
= FALSE
;
2021 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2022 if (InfSectionNameW
== NULL
)
2025 if (InfSectionWithExt
)
2027 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
2028 if (InfSectionWithExtW
== NULL
)
2032 bResult
= SetupDiGetActualSectionToInstallExW(
2033 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
2034 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
2035 InfSectionWithExtSize
,
2037 Extension
? &ExtensionW
: NULL
,
2040 if (bResult
&& InfSectionWithExt
)
2042 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
2043 InfSectionWithExtSize
, NULL
, NULL
) != 0;
2045 if (bResult
&& Extension
)
2047 if (ExtensionW
== NULL
)
2050 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
2054 MyFree(InfSectionNameW
);
2055 MyFree(InfSectionWithExtW
);
2060 /***********************************************************************
2061 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2063 BOOL WINAPI
SetupDiGetClassDescriptionA(
2064 const GUID
* ClassGuid
,
2065 PSTR ClassDescription
,
2066 DWORD ClassDescriptionSize
,
2067 PDWORD RequiredSize
)
2069 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
2070 ClassDescriptionSize
,
2071 RequiredSize
, NULL
, NULL
);
2074 /***********************************************************************
2075 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2077 BOOL WINAPI
SetupDiGetClassDescriptionW(
2078 const GUID
* ClassGuid
,
2079 PWSTR ClassDescription
,
2080 DWORD ClassDescriptionSize
,
2081 PDWORD RequiredSize
)
2083 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
2084 ClassDescriptionSize
,
2085 RequiredSize
, NULL
, NULL
);
2088 /***********************************************************************
2089 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2091 BOOL WINAPI
SetupDiGetClassDescriptionExA(
2092 const GUID
* ClassGuid
,
2093 PSTR ClassDescription
,
2094 DWORD ClassDescriptionSize
,
2095 PDWORD RequiredSize
,
2099 PWCHAR ClassDescriptionW
= NULL
;
2100 LPWSTR MachineNameW
= NULL
;
2103 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2104 ClassDescriptionSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
2106 if (ClassDescriptionSize
> 0)
2108 ClassDescriptionW
= MyMalloc(ClassDescriptionSize
* sizeof(WCHAR
));
2109 if (!ClassDescriptionW
)
2111 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2118 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
2121 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2126 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
,
2127 ClassDescriptionSize
* sizeof(WCHAR
), RequiredSize
, MachineNameW
, Reserved
);
2130 DWORD len
= (DWORD
)WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
2131 ClassDescriptionSize
, NULL
, NULL
);
2132 if (len
== 0 || len
> ClassDescriptionSize
)
2134 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2140 MyFree(ClassDescriptionW
);
2141 MyFree(MachineNameW
);
2145 /***********************************************************************
2146 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2148 BOOL WINAPI
SetupDiGetClassDescriptionExW(
2149 const GUID
* ClassGuid
,
2150 PWSTR ClassDescription
,
2151 DWORD ClassDescriptionSize
,
2152 PDWORD RequiredSize
,
2162 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2163 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
2165 /* Make sure there's a GUID */
2168 SetLastError(ERROR_INVALID_PARAMETER
);
2172 /* Make sure there's a real buffer when there's a size */
2173 if (!ClassDescription
&& ClassDescriptionSize
> 0)
2175 SetLastError(ERROR_INVALID_PARAMETER
);
2179 /* Open the key for the GUID */
2180 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
2185 if (hKey
== INVALID_HANDLE_VALUE
)
2188 /* Retrieve the class description data and close the key */
2189 rc
= QueryRegistryValue(hKey
, NULL
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
2192 /* Make sure we got the data */
2193 if (rc
!= ERROR_SUCCESS
)
2199 /* Make sure the data is a string */
2200 if (dwRegType
!= REG_SZ
)
2203 SetLastError(ERROR_GEN_FAILURE
);
2207 /* Determine the length of the class description */
2208 dwLength
/= sizeof(WCHAR
);
2210 /* Count the null-terminator if none is present */
2211 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
2214 /* Inform the caller about the class description */
2215 if ((ClassDescription
!= NULL
) && (dwLength
<= ClassDescriptionSize
))
2217 memcpy(ClassDescription
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
2218 ClassDescription
[dwLength
- 1] = UNICODE_NULL
;
2221 /* Inform the caller about the required size */
2222 if (RequiredSize
!= NULL
)
2223 *RequiredSize
= dwLength
;
2225 /* Clean up the buffer */
2228 /* Make sure the buffer was large enough */
2229 if ((ClassDescription
== NULL
) || (dwLength
> ClassDescriptionSize
))
2231 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2238 /***********************************************************************
2239 * SetupDiGetClassDevsA (SETUPAPI.@)
2241 HDEVINFO WINAPI
SetupDiGetClassDevsA(
2247 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
2248 flags
, NULL
, NULL
, NULL
);
2251 /***********************************************************************
2252 * SetupDiGetClassDevsExA (SETUPAPI.@)
2254 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
2264 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
2268 enumstrW
= pSetupMultiByteToUnicode(enumstr
, CP_ACP
);
2271 ret
= INVALID_HANDLE_VALUE
;
2277 machineW
= pSetupMultiByteToUnicode(machine
, CP_ACP
);
2281 ret
= INVALID_HANDLE_VALUE
;
2285 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
2286 machineW
, reserved
);
2294 /***********************************************************************
2295 * SetupDiGetClassDevsW (SETUPAPI.@)
2297 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2303 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2307 /***********************************************************************
2308 * SetupDiGetClassDevsExW (SETUPAPI.@)
2310 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2319 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2320 struct DeviceInfoSet
*list
;
2321 CONST GUID
*pClassGuid
;
2323 HDEVINFO set
= INVALID_HANDLE_VALUE
;
2325 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2326 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2329 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2331 SetLastError(ERROR_INVALID_PARAMETER
);
2332 return INVALID_HANDLE_VALUE
;
2335 /* Create the deviceset if not set */
2338 list
= (struct DeviceInfoSet
*)deviceset
;
2339 if (list
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2341 SetLastError(ERROR_INVALID_HANDLE
);
2344 hDeviceInfo
= deviceset
;
2348 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2349 flags
& (DIGCF_DEVICEINTERFACE
| DIGCF_ALLCLASSES
) ? NULL
: class,
2350 NULL
, machine
, NULL
);
2351 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2353 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2356 if (flags
& DIGCF_PROFILE
)
2357 FIXME(": flag DIGCF_PROFILE ignored\n");
2359 if (flags
& DIGCF_DEVICEINTERFACE
)
2363 SetLastError(ERROR_INVALID_PARAMETER
);
2366 rc
= SETUP_CreateInterfaceList(list
, machine
, class, enumstr
, flags
& DIGCF_PRESENT
);
2370 /* Determine which class(es) should be included in the deviceset */
2371 if (flags
& DIGCF_ALLCLASSES
)
2373 /* The caller wants all classes. Check if
2374 * the deviceset limits us to one class */
2375 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2378 pClassGuid
= &list
->ClassGuid
;
2382 /* The caller wants one class. Check if it matches deviceset class */
2383 if (IsEqualIID(&list
->ClassGuid
, class)
2384 || IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2390 SetLastError(ERROR_INVALID_PARAMETER
);
2394 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2396 /* No class specified. Try to use the one of the deviceset */
2397 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2398 pClassGuid
= &list
->ClassGuid
;
2401 SetLastError(ERROR_INVALID_PARAMETER
);
2407 SetLastError(ERROR_INVALID_PARAMETER
);
2410 rc
= SETUP_CreateDevicesList(list
, machine
, pClassGuid
, enumstr
);
2412 if (rc
!= ERROR_SUCCESS
)
2420 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= set
)
2421 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2425 /***********************************************************************
2426 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2428 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2429 HDEVINFO DeviceInfoSet
,
2430 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2432 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2434 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2436 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2438 SetLastError(ERROR_INVALID_HANDLE
);
2441 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2443 SetLastError(ERROR_INVALID_HANDLE
);
2447 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2449 SetLastError(ERROR_INVALID_PARAMETER
);
2452 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2453 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2454 if (set
->MachineName
)
2457 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2461 DevInfoData
->RemoteMachineName
[0] = 0;
2466 /***********************************************************************
2467 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2469 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2470 HDEVINFO DeviceInfoSet
,
2471 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2473 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2475 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2477 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2479 SetLastError(ERROR_INVALID_HANDLE
);
2482 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2484 SetLastError(ERROR_INVALID_HANDLE
);
2488 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2490 SetLastError(ERROR_INVALID_PARAMETER
);
2493 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2494 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2495 if (set
->MachineName
)
2496 strcpyW(DevInfoData
->RemoteMachineName
, set
->MachineName
+ 2);
2498 DevInfoData
->RemoteMachineName
[0] = 0;
2503 /***********************************************************************
2504 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2506 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2507 HDEVINFO DeviceInfoSet
,
2508 PSP_DEVINFO_DATA DeviceInfoData
,
2509 const GUID
*InterfaceClassGuid
,
2510 PCSTR ReferenceString
,
2511 DWORD CreationFlags
,
2512 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2515 LPWSTR ReferenceStringW
= NULL
;
2517 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2518 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2519 CreationFlags
, DeviceInterfaceData
);
2521 if (ReferenceString
)
2523 ReferenceStringW
= pSetupMultiByteToUnicode(ReferenceString
, CP_ACP
);
2524 if (ReferenceStringW
== NULL
) return FALSE
;
2527 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2528 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2529 DeviceInterfaceData
);
2531 MyFree(ReferenceStringW
);
2536 /***********************************************************************
2537 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2539 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2540 HDEVINFO DeviceInfoSet
,
2541 PSP_DEVINFO_DATA DeviceInfoData
,
2542 const GUID
*InterfaceClassGuid
,
2543 PCWSTR ReferenceString
,
2544 DWORD CreationFlags
,
2545 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2547 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2548 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2549 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2550 CreationFlags
, DeviceInterfaceData
);
2552 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2554 SetLastError(ERROR_INVALID_HANDLE
);
2557 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2559 SetLastError(ERROR_INVALID_HANDLE
);
2562 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2563 || !DeviceInfoData
->Reserved
)
2565 SetLastError(ERROR_INVALID_PARAMETER
);
2568 if (!InterfaceClassGuid
)
2570 SetLastError(ERROR_INVALID_USER_BUFFER
);
2574 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2575 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2576 CreationFlags
, DeviceInterfaceData
);
2577 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2581 /***********************************************************************
2582 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2584 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2585 HDEVINFO DeviceInfoSet
,
2586 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2590 PCSTR InfSectionName
)
2593 PWSTR InfSectionNameW
= NULL
;
2595 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2596 samDesired
, InfHandle
, InfSectionName
);
2599 if (!InfSectionName
)
2601 SetLastError(ERROR_INVALID_PARAMETER
);
2602 return INVALID_HANDLE_VALUE
;
2604 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2605 if (!InfSectionNameW
)
2606 return INVALID_HANDLE_VALUE
;
2608 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2609 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2611 MyFree(InfSectionNameW
);
2615 /***********************************************************************
2616 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2618 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2619 HDEVINFO DeviceInfoSet
,
2620 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2624 PCWSTR InfSectionName
)
2627 LPWSTR SymbolicLink
;
2628 DWORD Length
, Index
;
2630 WCHAR bracedGuidString
[39];
2631 struct DeviceInterface
*DevItf
;
2632 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2634 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2635 samDesired
, InfHandle
, InfSectionName
);
2637 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2638 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2640 SetLastError(ERROR_INVALID_HANDLE
);
2641 return INVALID_HANDLE_VALUE
;
2643 if (!DeviceInterfaceData
||
2644 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2645 !DeviceInterfaceData
->Reserved
)
2647 SetLastError(ERROR_INVALID_PARAMETER
);
2648 return INVALID_HANDLE_VALUE
;
2650 if (InfHandle
&& !InfSectionName
)
2652 SetLastError(ERROR_INVALID_PARAMETER
);
2653 return INVALID_HANDLE_VALUE
;
2656 hKey
= SetupDiOpenClassRegKeyExW(&DeviceInterfaceData
->InterfaceClassGuid
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2657 if (hKey
== INVALID_HANDLE_VALUE
)
2659 hKey
= SetupDiOpenClassRegKeyExW(NULL
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2660 if (hKey
== INVALID_HANDLE_VALUE
)
2662 SetLastError(ERROR_INVALID_PARAMETER
);
2663 return INVALID_HANDLE_VALUE
;
2665 SETUPDI_GuidToString(&DeviceInterfaceData
->InterfaceClassGuid
, bracedGuidString
);
2667 if (RegCreateKeyExW(hKey
, bracedGuidString
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
) != ERROR_SUCCESS
)
2669 SetLastError(ERROR_INVALID_PARAMETER
);
2670 return INVALID_HANDLE_VALUE
;
2676 DevItf
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2678 Length
= (wcslen(DevItf
->SymbolicLink
)+1) * sizeof(WCHAR
);
2679 SymbolicLink
= HeapAlloc(GetProcessHeap(), 0, Length
);
2683 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2684 return INVALID_HANDLE_VALUE
;
2687 wcscpy(SymbolicLink
, DevItf
->SymbolicLink
);
2690 while(SymbolicLink
[Index
])
2692 if (SymbolicLink
[Index
] == L
'\\')
2694 SymbolicLink
[Index
] = L
'#';
2699 rc
= RegCreateKeyExW(hKey
, SymbolicLink
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
);
2702 HeapFree(GetProcessHeap(), 0, SymbolicLink
);
2704 if (rc
== ERROR_SUCCESS
)
2706 if (InfHandle
&& InfSectionName
)
2708 if (!SetupInstallFromInfSection(NULL
/*FIXME */,
2711 SPINST_INIFILES
| SPINST_REGISTRY
| SPINST_INI2REG
| SPINST_FILES
| SPINST_BITREG
| SPINST_REGSVR
| SPINST_UNREGSVR
| SPINST_PROFILEITEMS
| SPINST_COPYINF
,
2715 set
->SelectedDevice
->InstallParams
.InstallMsgHandler
,
2716 set
->SelectedDevice
->InstallParams
.InstallMsgHandlerContext
,
2717 INVALID_HANDLE_VALUE
,
2720 RegCloseKey(hDevKey
);
2721 return INVALID_HANDLE_VALUE
;
2730 /***********************************************************************
2731 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2733 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2734 HDEVINFO DeviceInfoSet
,
2735 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2738 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2741 TRACE("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2743 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2744 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2746 SetLastError(ERROR_INVALID_HANDLE
);
2749 if (!DeviceInterfaceData
||
2750 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2751 !DeviceInterfaceData
->Reserved
)
2753 SetLastError(ERROR_INVALID_PARAMETER
);
2757 FIXME("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2758 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2762 /***********************************************************************
2763 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2766 * DeviceInfoSet [I] Set of devices from which to enumerate
2768 * DeviceInfoData [I] (Optional) If specified, a specific device
2769 * instance from which to enumerate interfaces.
2770 * If it isn't specified, all interfaces for all
2771 * devices in the set are enumerated.
2772 * InterfaceClassGuid [I] The interface class to enumerate.
2773 * MemberIndex [I] An index of the interface instance to enumerate.
2774 * A caller should start with MemberIndex set to 0,
2775 * and continue until the function fails with
2776 * ERROR_NO_MORE_ITEMS.
2777 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2778 * member must be set to
2779 * sizeof(SP_DEVICE_INTERFACE_DATA).
2782 * Success: non-zero value.
2783 * Failure: FALSE. Call GetLastError() for more info.
2785 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2786 HDEVINFO DeviceInfoSet
,
2787 PSP_DEVINFO_DATA DeviceInfoData
,
2788 CONST GUID
* InterfaceClassGuid
,
2790 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2792 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2795 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet
, DeviceInfoData
,
2796 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2798 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2799 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2801 SetLastError(ERROR_INVALID_HANDLE
);
2804 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2805 !DeviceInfoData
->Reserved
))
2807 SetLastError(ERROR_INVALID_PARAMETER
);
2810 if (!DeviceInterfaceData
||
2811 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2813 SetLastError(ERROR_INVALID_PARAMETER
);
2818 struct DeviceInfo
*devInfo
=
2819 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2821 PLIST_ENTRY InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2822 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2824 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2825 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2827 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2830 if (MemberIndex
-- == 0)
2832 /* return this item */
2833 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2834 &DevItf
->InterfaceClassGuid
,
2836 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2837 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2841 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2844 SetLastError(ERROR_NO_MORE_ITEMS
);
2849 PLIST_ENTRY ItemList
= set
->ListHead
.Flink
;
2850 while (ItemList
!= &set
->ListHead
&& !found
)
2852 PLIST_ENTRY InterfaceListEntry
;
2853 struct DeviceInfo
*devInfo
=
2854 CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
2855 InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2856 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2858 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2859 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2861 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2864 if (MemberIndex
-- == 0)
2866 /* return this item */
2867 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2868 &DevItf
->InterfaceClassGuid
,
2870 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2871 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2875 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2877 ItemList
= ItemList
->Flink
;
2881 SetLastError(ERROR_NO_MORE_ITEMS
);
2886 /***********************************************************************
2887 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2889 * Destroy a DeviceInfoList and free all used memory of the list.
2892 * devinfo [I] DeviceInfoList pointer to list to destroy
2895 * Success: non zero value.
2896 * Failure: zero value.
2898 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2902 TRACE("%p\n", devinfo
);
2903 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
2905 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2907 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
2909 ret
= DestroyDeviceInfoSet(list
);
2914 SetLastError(ERROR_INVALID_HANDLE
);
2919 /***********************************************************************
2920 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2922 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2923 HDEVINFO DeviceInfoSet
,
2924 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2925 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2926 DWORD DeviceInterfaceDetailDataSize
,
2927 PDWORD RequiredSize
,
2928 PSP_DEVINFO_DATA DeviceInfoData
)
2930 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2931 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2932 DWORD sizeW
= 0, bytesNeeded
;
2935 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
2936 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2937 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2939 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2940 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2942 SetLastError(ERROR_INVALID_HANDLE
);
2945 if (!DeviceInterfaceData
||
2946 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2947 !DeviceInterfaceData
->Reserved
)
2949 SetLastError(ERROR_INVALID_PARAMETER
);
2952 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
2954 SetLastError(ERROR_INVALID_USER_BUFFER
);
2958 if((DeviceInterfaceDetailDataSize
!= 0) &&
2959 (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + sizeof(CHAR
))))
2961 SetLastError(ERROR_INVALID_USER_BUFFER
);
2965 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
2967 SetLastError(ERROR_INVALID_USER_BUFFER
);
2972 if (DeviceInterfaceDetailData
!= NULL
)
2974 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2975 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2976 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)MyMalloc(sizeW
);
2977 if (!DeviceInterfaceDetailDataW
)
2979 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2981 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2983 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2985 ret
= SetupDiGetDeviceInterfaceDetailW(
2987 DeviceInterfaceData
,
2988 DeviceInterfaceDetailDataW
,
2992 bytesNeeded
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2993 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2995 *RequiredSize
= bytesNeeded
;
2996 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
>= bytesNeeded
)
2998 if (!WideCharToMultiByte(
3000 DeviceInterfaceDetailDataW
->DevicePath
, -1,
3001 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
3008 MyFree(DeviceInterfaceDetailDataW
);
3013 /***********************************************************************
3014 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3016 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
3017 HDEVINFO DeviceInfoSet
,
3018 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3019 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
3020 DWORD DeviceInterfaceDetailDataSize
,
3021 PDWORD RequiredSize
,
3022 PSP_DEVINFO_DATA DeviceInfoData
)
3024 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3027 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3028 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3029 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3031 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3032 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3034 SetLastError(ERROR_INVALID_HANDLE
);
3037 if (!DeviceInterfaceData
||
3038 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3039 !DeviceInterfaceData
->Reserved
)
3041 SetLastError(ERROR_INVALID_PARAMETER
);
3044 if (DeviceInterfaceDetailData
&& DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
3046 SetLastError(ERROR_INVALID_USER_BUFFER
);
3049 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3051 SetLastError(ERROR_INVALID_USER_BUFFER
);
3054 if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3056 SetLastError(ERROR_INVALID_PARAMETER
);
3059 if ((DeviceInterfaceDetailData
!= NULL
)
3060 && (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) + sizeof(WCHAR
)))
3062 SetLastError(ERROR_INVALID_PARAMETER
);
3067 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
3068 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
3069 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
3070 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
3072 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
3074 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3076 *RequiredSize
= sizeRequired
;
3080 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
3081 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
3084 memcpy(&DeviceInfoData
->ClassGuid
,
3085 &deviceInterface
->DeviceInfo
->ClassGuid
,
3087 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
3088 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
3096 struct PropertyMapEntry
3103 static struct PropertyMapEntry PropertyMap
[] = {
3104 { REG_SZ
, "DeviceDesc", REGSTR_VAL_DEVDESC
},
3105 { REG_MULTI_SZ
, "HardwareId", REGSTR_VAL_HARDWAREID
},
3106 { REG_MULTI_SZ
, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS
},
3107 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3108 { REG_SZ
, "Service", REGSTR_VAL_SERVICE
},
3109 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3110 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3111 { REG_SZ
, "Class", REGSTR_VAL_CLASS
},
3112 { REG_SZ
, "ClassGUID", REGSTR_VAL_CLASSGUID
},
3113 { REG_SZ
, "Driver", REGSTR_VAL_DRIVER
},
3114 { REG_DWORD
, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS
},
3115 { REG_SZ
, "Mfg", REGSTR_VAL_MFG
},
3116 { REG_SZ
, "FriendlyName", REGSTR_VAL_FRIENDLYNAME
},
3117 { REG_SZ
, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION
},
3118 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3119 { REG_DWORD
, "Capabilities", REGSTR_VAL_CAPABILITIES
},
3120 { REG_DWORD
, "UINumber", REGSTR_VAL_UI_NUMBER
},
3121 { REG_MULTI_SZ
, "UpperFilters", REGSTR_VAL_UPPERFILTERS
},
3122 { REG_MULTI_SZ
, "LowerFilters", REGSTR_VAL_LOWERFILTERS
},
3123 { 0, NULL
, NULL
}, /* SPDRP_BUSTYPEGUID */
3124 { 0, NULL
, NULL
}, /* SPDRP_LEGACYBUSTYPE */
3125 { 0, NULL
, NULL
}, /* SPDRP_BUSNUMBER */
3126 { 0, NULL
, NULL
}, /* SPDRP_ENUMERATOR_NAME */
3127 { REG_BINARY
, "Security", REGSTR_SECURITY
},
3128 { 0, NULL
, NULL
}, /* SPDRP_SECURITY_SDS */
3129 { 0, NULL
, NULL
}, /* SPDRP_DEVTYPE */
3130 { 0, NULL
, NULL
}, /* SPDRP_EXCLUSIVE */
3131 { 0, NULL
, NULL
}, /* SPDRP_CHARACTERISTICS */
3132 { 0, NULL
, NULL
}, /* SPDRP_ADDRESS */
3133 { REG_SZ
, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT
},
3134 { 0, NULL
, NULL
}, /* SPDRP_DEVICE_POWER_DATA */
3135 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY */
3136 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3137 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3138 { 0, NULL
, NULL
}, /* SPDRP_INSTALL_STATE */
3141 /***********************************************************************
3142 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3144 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3145 HDEVINFO DeviceInfoSet
,
3146 PSP_DEVINFO_DATA DeviceInfoData
,
3148 PDWORD PropertyRegDataType
,
3149 PBYTE PropertyBuffer
,
3150 DWORD PropertyBufferSize
,
3151 PDWORD RequiredSize
)
3154 BOOL bIsStringProperty
;
3156 DWORD RequiredSizeA
, RequiredSizeW
;
3157 DWORD PropertyBufferSizeW
= 0;
3158 PBYTE PropertyBufferW
= NULL
;
3160 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3161 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3164 if (PropertyBufferSize
!= 0)
3166 PropertyBufferSizeW
= PropertyBufferSize
* 2;
3167 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
3168 if (!PropertyBufferW
)
3170 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3175 ret
= SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
3180 PropertyBufferSizeW
,
3183 if (ret
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3185 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
3187 if (bIsStringProperty
)
3188 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
3190 RequiredSizeA
= RequiredSizeW
;
3192 *RequiredSize
= RequiredSizeA
;
3193 if (PropertyRegDataType
)
3194 *PropertyRegDataType
= RegType
;
3199 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3203 if (RequiredSizeA
<= PropertyBufferSize
)
3205 if (bIsStringProperty
&& PropertyBufferSize
> 0)
3207 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
3209 /* Last error is already set by WideCharToMultiByte */
3214 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
3218 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3222 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3226 /***********************************************************************
3227 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3229 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3230 HDEVINFO DeviceInfoSet
,
3231 PSP_DEVINFO_DATA DeviceInfoData
,
3233 PDWORD PropertyRegDataType
,
3234 PBYTE PropertyBuffer
,
3235 DWORD PropertyBufferSize
,
3236 PDWORD RequiredSize
)
3238 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3239 struct DeviceInfo
*devInfo
;
3241 LONG lError
= ERROR_SUCCESS
;
3244 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3245 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3248 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3250 SetLastError(ERROR_INVALID_HANDLE
);
3253 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3255 SetLastError(ERROR_INVALID_HANDLE
);
3258 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3259 || !DeviceInfoData
->Reserved
)
3261 SetLastError(ERROR_INVALID_PARAMETER
);
3265 if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
3267 SetLastError(ERROR_INVALID_REG_PROPERTY
);
3271 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3273 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3274 && PropertyMap
[Property
].nameW
)
3277 size
= PropertyBufferSize
;
3278 hKey
= SETUPDI_OpenDevKey(set
->HKLM
, devInfo
, KEY_QUERY_VALUE
);
3279 if (hKey
== INVALID_HANDLE_VALUE
)
3281 lError
= RegQueryValueExW(hKey
, PropertyMap
[Property
].nameW
,
3282 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3286 *RequiredSize
= size
;