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_ALREADY_SUCH_DEVINST
: return ERROR_DEVINST_ALREADY_EXISTS
;
117 case CR_SUCCESS
: return ERROR_SUCCESS
;
118 default: return ERROR_GEN_FAILURE
;
121 /* Does not happen */
124 /* Lower scores are best ones */
127 IN LPCWSTR SectionName
,
128 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
131 OUT PDWORD ScorePlatform
,
132 OUT PDWORD ScoreMajorVersion
,
133 OUT PDWORD ScoreMinorVersion
,
134 OUT PDWORD ScoreProductType
,
135 OUT PDWORD ScoreSuiteMask
)
137 LPWSTR Section
= NULL
;
138 //LPCWSTR pExtensionPlatform;
139 LPCWSTR pExtensionArchitecture
;
144 //static const WCHAR ExtensionPlatformNone[] = {'.',0};
145 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
146 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
148 static const WCHAR ExtensionArchitectureNone
[] = {0};
149 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
150 static const WCHAR ExtensionArchitectureamd64
[] = {'A','M','D','6','4',0};
151 static const WCHAR ExtensionArchitectureia64
[] = {'I','A','6','4',0};
152 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
153 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
154 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
156 TRACE("%s %p 0x%x 0x%x\n",
157 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
159 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
161 Section
= pSetupDuplicateString(SectionName
);
164 TRACE("pSetupDuplicateString() failed\n");
168 /* Set various extensions values */
169 switch (PlatformInfo
->Platform
)
171 case VER_PLATFORM_WIN32_WINDOWS
:
172 //pExtensionPlatform = ExtensionPlatformWindows;
174 case VER_PLATFORM_WIN32_NT
:
175 //pExtensionPlatform = ExtensionPlatformNT;
178 ERR("Unknown platform 0x%lx\n", PlatformInfo
->Platform
);
179 //pExtensionPlatform = ExtensionPlatformNone;
182 switch (PlatformInfo
->ProcessorArchitecture
)
184 case PROCESSOR_ARCHITECTURE_ALPHA
:
185 pExtensionArchitecture
= ExtensionArchitecturealpha
;
187 case PROCESSOR_ARCHITECTURE_AMD64
:
188 pExtensionArchitecture
= ExtensionArchitectureamd64
;
190 case PROCESSOR_ARCHITECTURE_IA64
:
191 pExtensionArchitecture
= ExtensionArchitectureia64
;
193 case PROCESSOR_ARCHITECTURE_INTEL
:
194 pExtensionArchitecture
= ExtensionArchitecturex86
;
196 case PROCESSOR_ARCHITECTURE_MIPS
:
197 pExtensionArchitecture
= ExtensionArchitecturemips
;
199 case PROCESSOR_ARCHITECTURE_PPC
:
200 pExtensionArchitecture
= ExtensionArchitectureppc
;
203 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
204 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
205 pExtensionArchitecture
= ExtensionArchitectureNone
;
211 * Field[1] Architecture
212 * Field[2] Major version
213 * Field[3] Minor version
214 * Field[4] Product type
215 * Field[5] Suite mask
216 * Remark: lastests fields may be NULL if the information is not provided
219 if (Fields
[0] == NULL
)
221 TRACE("No extension found\n");
222 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
226 Fields
[1] = Fields
[0] + 1;
227 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
228 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
230 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
234 *(Fields
[i
] - 1) = UNICODE_NULL
;
237 /* Take care of first 2 fields */
238 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
240 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
242 TRACE("Mismatch on platform field\n");
245 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
247 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
249 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
251 TRACE("Mismatch on platform field\n");
254 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
258 /* No platform specified */
259 *ScorePlatform
|= 0x02;
261 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
263 /* No architecture specified */
264 *ScorePlatform
|= 0x01;
266 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
268 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
269 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
273 /* Check if informations are matching */
274 if (Fields
[2] && *Fields
[2])
276 DWORD MajorVersion
, MinorVersion
= 0;
277 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
278 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
279 (errno
== ERANGE
|| errno
== EINVAL
))
281 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
284 if (Fields
[3] && *Fields
[3])
286 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
287 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
288 (errno
== ERANGE
|| errno
== EINVAL
))
290 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
294 if (PlatformInfo
->MajorVersion
< MajorVersion
||
295 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
297 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
298 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
301 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
302 if (MajorVersion
== PlatformInfo
->MajorVersion
)
303 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
305 *ScoreMinorVersion
= MinorVersion
;
307 else if (Fields
[3] && *Fields
[3])
309 TRACE("Minor version found without major version\n");
314 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
315 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
318 if (Fields
[4] && *Fields
[4])
320 DWORD CurrentProductType
;
321 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
322 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
323 (errno
== ERANGE
|| errno
== EINVAL
))
325 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
328 if (CurrentProductType
!= ProductType
)
330 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
331 CurrentProductType
, ProductType
);
336 *ScoreProductType
= 1;
338 if (Fields
[5] && *Fields
[5])
340 DWORD CurrentSuiteMask
;
341 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
342 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
343 (errno
== ERANGE
|| errno
== EINVAL
))
345 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
348 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
350 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
351 CurrentSuiteMask
, SuiteMask
);
354 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
357 *ScoreSuiteMask
= SuiteMask
;
368 IN LPCWSTR SectionName
,
371 struct GetSectionCallbackInfo
*info
= Context
;
372 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
375 if (SectionName
[info
->PrefixLength
] != '.')
378 ret
= CheckSectionValid(
379 &SectionName
[info
->PrefixLength
],
383 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
386 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
389 if (Score1
> info
->BestScore1
) goto done
;
390 if (Score1
< info
->BestScore1
) goto bettersection
;
391 if (Score2
> info
->BestScore2
) goto done
;
392 if (Score2
< info
->BestScore2
) goto bettersection
;
393 if (Score3
> info
->BestScore3
) goto done
;
394 if (Score3
< info
->BestScore3
) goto bettersection
;
395 if (Score4
> info
->BestScore4
) goto done
;
396 if (Score4
< info
->BestScore4
) goto bettersection
;
397 if (Score5
> info
->BestScore5
) goto done
;
398 if (Score5
< info
->BestScore5
) goto bettersection
;
402 strcpyW(info
->BestSection
, SectionName
);
403 info
->BestScore1
= Score1
;
404 info
->BestScore2
= Score2
;
405 info
->BestScore3
= Score3
;
406 info
->BestScore4
= Score4
;
407 info
->BestScore5
= Score5
;
413 /***********************************************************************
414 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
417 SetupDiGetActualSectionToInstallExW(
419 IN PCWSTR InfSectionName
,
420 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
421 OUT PWSTR InfSectionWithExt OPTIONAL
,
422 IN DWORD InfSectionWithExtSize
,
423 OUT PDWORD RequiredSize OPTIONAL
,
424 OUT PWSTR
* Extension OPTIONAL
,
429 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
430 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
431 RequiredSize
, Extension
, Reserved
);
433 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
434 SetLastError(ERROR_INVALID_HANDLE
);
435 else if (!InfSectionName
)
436 SetLastError(ERROR_INVALID_PARAMETER
);
437 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
438 SetLastError(ERROR_INVALID_USER_BUFFER
);
439 else if (Reserved
!= NULL
)
440 SetLastError(ERROR_INVALID_PARAMETER
);
443 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
444 static BYTE CurrentProductType
= 0;
445 static WORD CurrentSuiteMask
= 0;
446 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
447 struct GetSectionCallbackInfo CallbackInfo
;
452 /* Fill platform info if needed */
453 if (AlternatePlatformInfo
)
455 pPlatformInfo
= AlternatePlatformInfo
;
461 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
463 /* That's the first time we go here. We need to fill in the structure */
464 OSVERSIONINFOEX VersionInfo
;
465 SYSTEM_INFO SystemInfo
;
466 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
467 ret
= GetVersionExW((OSVERSIONINFO
*)&VersionInfo
);
470 GetSystemInfo(&SystemInfo
);
471 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
472 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
473 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
474 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
475 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
476 CurrentPlatform
.Reserved
= 0;
477 CurrentProductType
= VersionInfo
.wProductType
;
478 CurrentSuiteMask
= VersionInfo
.wSuiteMask
;
480 ProductType
= CurrentProductType
;
481 SuiteMask
= CurrentSuiteMask
;
484 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
485 CallbackInfo
.ProductType
= ProductType
;
486 CallbackInfo
.SuiteMask
= SuiteMask
;
487 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
488 CallbackInfo
.BestScore1
= ULONG_MAX
;
489 CallbackInfo
.BestScore2
= ULONG_MAX
;
490 CallbackInfo
.BestScore3
= ULONG_MAX
;
491 CallbackInfo
.BestScore4
= ULONG_MAX
;
492 CallbackInfo
.BestScore5
= ULONG_MAX
;
493 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
494 if (!EnumerateSectionsStartingWith(
500 SetLastError(ERROR_GEN_FAILURE
);
504 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
505 if (RequiredSize
!= NULL
)
506 *RequiredSize
= dwFullLength
+ 1;
508 if (InfSectionWithExtSize
> 0)
510 if (InfSectionWithExtSize
< dwFullLength
+ 1)
512 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
515 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
518 DWORD dwLength
= lstrlenW(InfSectionName
);
519 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
527 TRACE("Returning %d\n", ret
);
534 IN
struct DeviceInfoSet
*list
,
535 IN LPCWSTR InstancePath
,
536 IN LPCGUID pClassGuid
,
537 OUT
struct DeviceInfo
**pDeviceInfo
)
541 struct DeviceInfo
*deviceInfo
;
545 size
= FIELD_OFFSET(struct DeviceInfo
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
546 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
549 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
552 ZeroMemory(deviceInfo
, size
);
554 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
555 if (cr
!= CR_SUCCESS
)
557 SetLastError(GetErrorCodeFromCrCode(cr
));
561 deviceInfo
->set
= list
;
562 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
563 strcpyW(deviceInfo
->Data
, InstancePath
);
564 deviceInfo
->instanceId
= deviceInfo
->Data
;
565 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
566 deviceInfo
->DeviceDescription
= NULL
;
567 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
568 deviceInfo
->CreationFlags
= 0;
569 InitializeListHead(&deviceInfo
->DriverListHead
);
570 InitializeListHead(&deviceInfo
->InterfaceListHead
);
572 *pDeviceInfo
= deviceInfo
;
578 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
580 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
581 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
586 DestroyDeviceInfo(struct DeviceInfo
*deviceInfo
)
588 PLIST_ENTRY ListEntry
;
589 struct DriverInfoElement
*driverInfo
;
590 struct DeviceInterface
*deviceInterface
;
592 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
594 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
595 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
596 if (!DestroyDriverInfoElement(driverInfo
))
599 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
601 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
602 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
603 if (!DestroyDeviceInterface(deviceInterface
))
606 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
607 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
611 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
613 PLIST_ENTRY ListEntry
;
614 struct DeviceInfo
*deviceInfo
;
616 while (!IsListEmpty(&list
->ListHead
))
618 ListEntry
= RemoveHeadList(&list
->ListHead
);
619 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
);
620 if (!DestroyDeviceInfo(deviceInfo
))
623 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
624 RegCloseKey(list
->HKLM
);
625 CM_Disconnect_Machine(list
->hMachine
);
626 DestroyClassInstallParams(&list
->ClassInstallParams
);
627 return HeapFree(GetProcessHeap(), 0, list
);
630 /***********************************************************************
631 * SetupDiBuildClassInfoList (SETUPAPI.@)
633 * Returns a list of setup class GUIDs that identify the classes
634 * that are installed on a local machine.
637 * Flags [I] control exclusion of classes from the list.
638 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
639 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
640 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
646 BOOL WINAPI
SetupDiBuildClassInfoList(
648 LPGUID ClassGuidList
,
649 DWORD ClassGuidListSize
,
653 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
654 ClassGuidListSize
, RequiredSize
,
658 /***********************************************************************
659 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
661 * Returns a list of setup class GUIDs that identify the classes
662 * that are installed on a local or remote macine.
665 * Flags [I] control exclusion of classes from the list.
666 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
667 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
668 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
669 * MachineName [I] name of a remote machine.
670 * Reserved [I] must be NULL.
676 BOOL WINAPI
SetupDiBuildClassInfoListExA(
678 LPGUID ClassGuidList
,
679 DWORD ClassGuidListSize
,
684 LPWSTR MachineNameW
= NULL
;
687 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
688 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
692 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
693 if (MachineNameW
== NULL
) return FALSE
;
696 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
697 ClassGuidListSize
, RequiredSize
,
698 MachineNameW
, Reserved
);
700 MyFree(MachineNameW
);
705 /***********************************************************************
706 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
708 * Returns a list of setup class GUIDs that identify the classes
709 * that are installed on a local or remote macine.
712 * Flags [I] control exclusion of classes from the list.
713 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
714 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
715 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
716 * MachineName [I] name of a remote machine.
717 * Reserved [I] must be NULL.
723 BOOL WINAPI
SetupDiBuildClassInfoListExW(
725 LPGUID ClassGuidList
,
726 DWORD ClassGuidListSize
,
732 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
737 DWORD dwGuidListIndex
= 0;
739 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
740 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
744 SetLastError(ERROR_INVALID_PARAMETER
);
747 else if (!ClassGuidList
&& ClassGuidListSize
> 0)
749 SetLastError(ERROR_INVALID_PARAMETER
);
753 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
754 KEY_ENUMERATE_SUB_KEYS
,
758 if (hClassesKey
== INVALID_HANDLE_VALUE
)
763 for (dwIndex
= 0; ; dwIndex
++)
766 lError
= RegEnumKeyExW(hClassesKey
,
774 TRACE("RegEnumKeyExW() returns %d\n", lError
);
775 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
777 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
779 if (RegOpenKeyExW(hClassesKey
,
785 RegCloseKey(hClassesKey
);
789 if (!RegQueryValueExW(hClassKey
,
790 REGSTR_VAL_NOUSECLASS
,
796 TRACE("'NoUseClass' value found!\n");
797 RegCloseKey(hClassKey
);
801 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
802 (!RegQueryValueExW(hClassKey
,
803 REGSTR_VAL_NOINSTALLCLASS
,
809 TRACE("'NoInstallClass' value found!\n");
810 RegCloseKey(hClassKey
);
814 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
815 (!RegQueryValueExW(hClassKey
,
816 REGSTR_VAL_NODISPLAYCLASS
,
822 TRACE("'NoDisplayClass' value found!\n");
823 RegCloseKey(hClassKey
);
827 RegCloseKey(hClassKey
);
829 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
830 if (dwGuidListIndex
< ClassGuidListSize
)
832 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
836 TRACE("Guid: %p\n", &szKeyName
[1]);
838 UuidFromStringW(&szKeyName
[1],
839 &ClassGuidList
[dwGuidListIndex
]);
845 if (lError
!= ERROR_SUCCESS
)
849 RegCloseKey(hClassesKey
);
851 if (RequiredSize
!= NULL
)
852 *RequiredSize
= dwGuidListIndex
;
854 if (ClassGuidListSize
< dwGuidListIndex
)
856 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
863 /***********************************************************************
864 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
866 BOOL WINAPI
SetupDiClassGuidsFromNameA(
868 LPGUID ClassGuidList
,
869 DWORD ClassGuidListSize
,
872 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
873 ClassGuidListSize
, RequiredSize
,
877 /***********************************************************************
878 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
880 BOOL WINAPI
SetupDiClassGuidsFromNameW(
882 LPGUID ClassGuidList
,
883 DWORD ClassGuidListSize
,
886 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
887 ClassGuidListSize
, RequiredSize
,
891 /***********************************************************************
892 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
894 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
896 LPGUID ClassGuidList
,
897 DWORD ClassGuidListSize
,
902 LPWSTR ClassNameW
= NULL
;
903 LPWSTR MachineNameW
= NULL
;
906 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName
), ClassGuidList
,
907 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
911 SetLastError(ERROR_INVALID_PARAMETER
);
915 ClassNameW
= pSetupMultiByteToUnicode(ClassName
, CP_ACP
);
916 if (ClassNameW
== NULL
)
921 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
922 if (MachineNameW
== NULL
)
929 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
930 ClassGuidListSize
, RequiredSize
,
931 MachineNameW
, Reserved
);
933 MyFree(MachineNameW
);
939 /***********************************************************************
940 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
942 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
944 LPGUID ClassGuidList
,
945 DWORD ClassGuidListSize
,
951 WCHAR szClassName
[MAX_CLASS_NAME_LEN
];
957 DWORD dwGuidListIndex
= 0;
959 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
960 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
962 if (!ClassName
|| !RequiredSize
)
964 SetLastError(ERROR_INVALID_PARAMETER
);
967 if (!ClassGuidList
&& ClassGuidListSize
> 0)
969 SetLastError(ERROR_INVALID_PARAMETER
);
974 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
975 KEY_ENUMERATE_SUB_KEYS
,
979 if (hClassesKey
== INVALID_HANDLE_VALUE
)
984 for (dwIndex
= 0; ; dwIndex
++)
987 lError
= RegEnumKeyExW(hClassesKey
,
995 TRACE("RegEnumKeyExW() returns %d\n", lError
);
996 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
998 TRACE("Key name: %p\n", szKeyName
);
1000 if (RegOpenKeyExW(hClassesKey
,
1006 RegCloseKey(hClassesKey
);
1010 dwLength
= MAX_CLASS_NAME_LEN
* sizeof(WCHAR
);
1011 if (!RegQueryValueExW(hClassKey
,
1015 (LPBYTE
)szClassName
,
1018 TRACE("Class name: %p\n", szClassName
);
1020 if (strcmpiW(szClassName
, ClassName
) == 0)
1022 TRACE("Found matching class name\n");
1024 TRACE("Guid: %p\n", szKeyName
);
1025 if (dwGuidListIndex
< ClassGuidListSize
)
1027 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
1031 TRACE("Guid: %p\n", &szKeyName
[1]);
1033 UuidFromStringW(&szKeyName
[1],
1034 &ClassGuidList
[dwGuidListIndex
]);
1041 RegCloseKey(hClassKey
);
1044 if (lError
!= ERROR_SUCCESS
)
1048 RegCloseKey(hClassesKey
);
1050 if (RequiredSize
!= NULL
)
1051 *RequiredSize
= dwGuidListIndex
;
1053 if (ClassGuidListSize
< dwGuidListIndex
)
1055 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1062 /***********************************************************************
1063 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1065 BOOL WINAPI
SetupDiClassNameFromGuidA(
1066 const GUID
* ClassGuid
,
1068 DWORD ClassNameSize
,
1069 PDWORD RequiredSize
)
1071 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
1072 ClassNameSize
, RequiredSize
,
1076 /***********************************************************************
1077 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1079 BOOL WINAPI
SetupDiClassNameFromGuidW(
1080 const GUID
* ClassGuid
,
1082 DWORD ClassNameSize
,
1083 PDWORD RequiredSize
)
1085 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
1086 ClassNameSize
, RequiredSize
,
1090 /***********************************************************************
1091 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1093 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1094 const GUID
* ClassGuid
,
1096 DWORD ClassNameSize
,
1097 PDWORD RequiredSize
,
1101 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1102 LPWSTR MachineNameW
= NULL
;
1106 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1107 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1108 RequiredSize
, MachineNameW
, Reserved
);
1111 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1112 ClassNameSize
, NULL
, NULL
);
1113 if (len
== 0 || len
> ClassNameSize
)
1115 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1119 MyFree(MachineNameW
);
1123 /***********************************************************************
1124 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1126 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1127 const GUID
* ClassGuid
,
1129 DWORD ClassNameSize
,
1130 PDWORD RequiredSize
,
1140 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
1141 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1143 /* Make sure there's a GUID */
1144 if (ClassGuid
== NULL
)
1146 SetLastError(ERROR_INVALID_CLASS
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1150 /* Make sure there's a real buffer when there's a size */
1151 if ((ClassNameSize
> 0) && (ClassName
== NULL
))
1153 SetLastError(ERROR_INVALID_PARAMETER
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1157 /* Open the key for the GUID */
1158 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INSTALLER
, MachineName
, Reserved
);
1160 if (hKey
== INVALID_HANDLE_VALUE
)
1163 /* Retrieve the class name data and close the key */
1164 rc
= QueryRegistryValue(hKey
, Class
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
1167 /* Make sure we got the data */
1168 if (rc
!= ERROR_SUCCESS
)
1174 /* Make sure the data is a string */
1175 if (dwRegType
!= REG_SZ
)
1178 SetLastError(ERROR_GEN_FAILURE
);
1182 /* Determine the length of the class name */
1183 dwLength
/= sizeof(WCHAR
);
1185 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
1186 /* Count the null-terminator */
1189 /* Inform the caller about the class name */
1190 if ((ClassName
!= NULL
) && (dwLength
<= ClassNameSize
))
1192 memcpy(ClassName
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
1193 ClassName
[dwLength
- 1] = UNICODE_NULL
;
1196 /* Inform the caller about the required size */
1197 if (RequiredSize
!= NULL
)
1198 *RequiredSize
= dwLength
;
1200 /* Clean up the buffer */
1203 /* Make sure the buffer was large enough */
1204 if ((ClassName
== NULL
) || (dwLength
> ClassNameSize
))
1206 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1213 /***********************************************************************
1214 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1217 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1220 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1223 /***********************************************************************
1224 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1227 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1232 LPWSTR MachineNameW
= NULL
;
1235 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1236 debugstr_a(MachineName
), Reserved
);
1240 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1241 if (MachineNameW
== NULL
)
1242 return INVALID_HANDLE_VALUE
;
1245 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1246 MachineNameW
, Reserved
);
1248 MyFree(MachineNameW
);
1253 /***********************************************************************
1254 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1256 * Create an empty DeviceInfoSet list.
1259 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1261 * hwndParent [I] hwnd needed for interface related actions.
1262 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1263 * local registry will be used.
1264 * Reserved [I] must be NULL
1267 * Success: empty list.
1268 * Failure: INVALID_HANDLE_VALUE.
1271 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1276 struct DeviceInfoSet
*list
= NULL
;
1277 DWORD size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
1280 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1282 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1283 debugstr_w(MachineName
), Reserved
);
1285 if (MachineName
!= NULL
)
1287 SIZE_T len
= strlenW(MachineName
);
1288 if (len
>= SP_MAX_MACHINENAME_LENGTH
- 4)
1290 SetLastError(ERROR_INVALID_MACHINENAME
);
1294 size
+= (len
+ 3) * sizeof(WCHAR
);
1299 if (Reserved
!= NULL
)
1301 SetLastError(ERROR_INVALID_PARAMETER
);
1302 return INVALID_HANDLE_VALUE
;
1305 list
= MyMalloc(size
);
1308 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1309 return INVALID_HANDLE_VALUE
;
1311 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
1313 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1314 memcpy(&list
->ClassGuid
,
1315 ClassGuid
? ClassGuid
: &GUID_NULL
,
1316 sizeof(list
->ClassGuid
));
1317 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1318 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1319 list
->InstallParams
.hwndParent
= hwndParent
;
1322 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
1323 if (rc
!= ERROR_SUCCESS
)
1325 SetLastError(ERROR_INVALID_MACHINENAME
);
1329 list
->szData
[0] = list
->szData
[1] = '\\';
1330 strcpyW(list
->szData
+ 2, MachineName
);
1331 list
->MachineName
= list
->szData
;
1335 list
->HKLM
= HKEY_LOCAL_MACHINE
;
1336 list
->MachineName
= NULL
;
1338 cr
= CM_Connect_MachineW(list
->MachineName
, &list
->hMachine
);
1339 if (cr
!= CR_SUCCESS
)
1341 SetLastError(GetErrorCodeFromCrCode(cr
));
1344 InitializeListHead(&list
->DriverListHead
);
1345 InitializeListHead(&list
->ListHead
);
1347 return (HDEVINFO
)list
;
1350 if (ret
== INVALID_HANDLE_VALUE
)
1354 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1355 RegCloseKey(list
->HKLM
);
1362 /***********************************************************************
1363 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1365 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1366 HDEVINFO DeviceInfoSet
,
1367 PSP_DEVINFO_DATA DeviceInfoData
,
1372 PCSTR InfSectionName
)
1374 PWSTR InfSectionNameW
= NULL
;
1377 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1378 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1382 if (!InfSectionName
)
1384 SetLastError(ERROR_INVALID_PARAMETER
);
1385 return INVALID_HANDLE_VALUE
;
1389 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
1390 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1393 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1394 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1395 MyFree(InfSectionNameW
);
1400 OpenHardwareProfileKey(
1403 IN DWORD samDesired
);
1405 /***********************************************************************
1406 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1408 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1409 HDEVINFO DeviceInfoSet
,
1410 PSP_DEVINFO_DATA DeviceInfoData
,
1415 PCWSTR InfSectionName
)
1417 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1418 HKEY key
= INVALID_HANDLE_VALUE
;
1419 LPWSTR lpGuidString
= NULL
;
1420 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
1421 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
1422 DWORD Index
; /* Index used in the DriverKey name */
1426 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
1427 HKEY hEnumKey
= NULL
;
1428 HKEY hClassKey
= NULL
;
1429 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
1433 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1434 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1436 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1438 SetLastError(ERROR_INVALID_HANDLE
);
1439 return INVALID_HANDLE_VALUE
;
1441 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1443 SetLastError(ERROR_INVALID_HANDLE
);
1444 return INVALID_HANDLE_VALUE
;
1446 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1447 || !DeviceInfoData
->Reserved
)
1449 SetLastError(ERROR_INVALID_PARAMETER
);
1450 return INVALID_HANDLE_VALUE
;
1452 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1454 SetLastError(ERROR_INVALID_FLAGS
);
1455 return INVALID_HANDLE_VALUE
;
1457 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1459 SetLastError(ERROR_INVALID_FLAGS
);
1460 return INVALID_HANDLE_VALUE
;
1462 if (InfHandle
&& !InfSectionName
)
1464 SetLastError(ERROR_INVALID_PARAMETER
);
1465 return INVALID_HANDLE_VALUE
;
1467 if (!InfHandle
&& InfSectionName
)
1469 SetLastError(ERROR_INVALID_PARAMETER
);
1470 return INVALID_HANDLE_VALUE
;
1473 if (Scope
== DICS_FLAG_GLOBAL
)
1474 RootKey
= set
->HKLM
;
1475 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1477 hHWProfileKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
1478 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
1480 RootKey
= hHWProfileKey
;
1483 if (KeyType
== DIREG_DEV
)
1485 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1487 rc
= RegCreateKeyExW(
1489 REGSTR_PATH_SYSTEMENUM
,
1492 REG_OPTION_NON_VOLATILE
,
1497 if (rc
!= ERROR_SUCCESS
)
1502 rc
= RegCreateKeyExW(
1504 deviceInfo
->instanceId
,
1507 REG_OPTION_NON_VOLATILE
,
1508 #if _WIN32_WINNT >= 0x502
1509 KEY_READ
| KEY_WRITE
,
1516 if (rc
!= ERROR_SUCCESS
)
1522 else /* KeyType == DIREG_DRV */
1524 /* Open device key, to read Driver value */
1525 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1526 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
1529 rc
= RegOpenKeyExW(RootKey
, REGSTR_PATH_CLASS_NT
, 0, KEY_CREATE_SUB_KEY
, &hClassKey
);
1530 if (rc
!= ERROR_SUCCESS
)
1536 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, NULL
, &dwSize
);
1537 if (rc
!= ERROR_SUCCESS
)
1539 /* Create a new driver key */
1541 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
1544 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1545 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
1548 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1553 strcpyW(&DriverKey
[1], lpGuidString
);
1554 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
1555 *pDeviceInstance
++ = '}';
1556 *pDeviceInstance
++ = '\\';
1558 /* Try all values for Index between 0 and 9999 */
1560 while (Index
<= 9999)
1562 sprintfW(pDeviceInstance
, InstanceKeyFormat
, Index
);
1563 rc
= RegCreateKeyExW(hClassKey
,
1567 REG_OPTION_NON_VOLATILE
,
1568 #if _WIN32_WINNT >= 0x502
1569 KEY_READ
| KEY_WRITE
,
1576 if (rc
!= ERROR_SUCCESS
)
1581 if (Disposition
== REG_CREATED_NEW_KEY
)
1590 /* Unable to create more than 9999 devices within the same class */
1591 SetLastError(ERROR_GEN_FAILURE
);
1595 /* Write the new Driver value */
1596 rc
= RegSetValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
1597 if (rc
!= ERROR_SUCCESS
)
1606 /* Open the existing driver key */
1608 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
1611 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1615 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, (LPBYTE
)DriverKey
, &dwSize
);
1616 if (rc
!= ERROR_SUCCESS
)
1622 rc
= RegCreateKeyExW(hClassKey
,
1626 REG_OPTION_NON_VOLATILE
,
1627 #if _WIN32_WINNT >= 0x502
1628 KEY_READ
| KEY_WRITE
,
1635 if (rc
!= ERROR_SUCCESS
)
1643 /* Do installation of the specified section */
1646 FIXME("Need to install section %s in file %p\n",
1647 debugstr_w(InfSectionName
), InfHandle
);
1653 RpcStringFreeW(&lpGuidString
);
1654 HeapFree(GetProcessHeap(), 0, DriverKey
);
1655 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
1656 RegCloseKey(hHWProfileKey
);
1657 if (hEnumKey
!= NULL
)
1658 RegCloseKey(hEnumKey
);
1659 if (hClassKey
!= NULL
)
1660 RegCloseKey(hClassKey
);
1661 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
1662 RegCloseKey(hDeviceKey
);
1663 if (hKey
!= NULL
&& hKey
!= key
)
1666 TRACE("Returning 0x%p\n", key
);
1670 /***********************************************************************
1671 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1673 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1674 HDEVINFO DeviceInfoSet
,
1676 CONST GUID
*ClassGuid
,
1677 PCSTR DeviceDescription
,
1679 DWORD CreationFlags
,
1680 PSP_DEVINFO_DATA DeviceInfoData
)
1683 LPWSTR DeviceNameW
= NULL
;
1684 LPWSTR DeviceDescriptionW
= NULL
;
1690 DeviceNameW
= pSetupMultiByteToUnicode(DeviceName
, CP_ACP
);
1691 if (DeviceNameW
== NULL
) return FALSE
;
1693 if (DeviceDescription
)
1695 DeviceDescriptionW
= pSetupMultiByteToUnicode(DeviceDescription
, CP_ACP
);
1696 if (DeviceDescriptionW
== NULL
)
1698 MyFree(DeviceNameW
);
1703 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1704 hwndParent
, CreationFlags
, DeviceInfoData
);
1706 MyFree(DeviceNameW
);
1707 MyFree(DeviceDescriptionW
);
1712 /***********************************************************************
1713 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1715 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1716 HDEVINFO DeviceInfoSet
,
1718 CONST GUID
*ClassGuid
,
1719 PCWSTR DeviceDescription
,
1721 DWORD CreationFlags
,
1722 PSP_DEVINFO_DATA DeviceInfoData
)
1724 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1725 struct DeviceInfo
*deviceInfo
= NULL
;
1728 DEVINST RootDevInst
;
1730 WCHAR GenInstanceId
[MAX_DEVICE_ID_LEN
];
1732 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
1733 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1734 hwndParent
, CreationFlags
, DeviceInfoData
);
1738 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1741 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1743 SetLastError(ERROR_INVALID_HANDLE
);
1748 SetLastError(ERROR_INVALID_PARAMETER
);
1751 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1753 SetLastError(ERROR_INVALID_HANDLE
);
1756 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1757 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1759 SetLastError(ERROR_CLASS_MISMATCH
);
1762 if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
1764 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
1765 SetLastError(ERROR_INVALID_FLAGS
);
1769 /* Get the root device instance */
1770 cr
= CM_Locate_DevInst_ExW(&RootDevInst
,
1772 CM_LOCATE_DEVINST_NORMAL
,
1774 if (cr
!= CR_SUCCESS
)
1776 SetLastError(ERROR_INVALID_DATA
);
1780 /* Create the new device instance */
1781 cr
= CM_Create_DevInst_ExW(&DevInst
,
1782 (DEVINSTID
)DeviceName
,
1784 (CreationFlags
& DICD_GENERATE_ID
) ?
1785 CM_CREATE_DEVINST_GENERATE_ID
: 0,
1787 if (cr
!= CR_SUCCESS
)
1789 SetLastError(GetErrorCodeFromCrCode(cr
));
1793 if (CreationFlags
& DICD_GENERATE_ID
)
1795 /* Grab the actual instance ID that was created */
1796 cr
= CM_Get_Device_ID_Ex(DevInst
,
1801 if (cr
!= CR_SUCCESS
)
1803 SetLastError(GetErrorCodeFromCrCode(cr
));
1807 DeviceName
= GenInstanceId
;
1808 TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName
));
1811 if (CreateDeviceInfo(set
, DeviceName
, ClassGuid
, &deviceInfo
))
1813 InsertTailList(&set
->ListHead
, &deviceInfo
->ListEntry
);
1815 if (!DeviceInfoData
)
1819 if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1821 SetLastError(ERROR_INVALID_USER_BUFFER
);
1825 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
1826 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
1827 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
1835 if (deviceInfo
!= NULL
)
1837 /* Remove deviceInfo from List */
1838 RemoveEntryList(&deviceInfo
->ListEntry
);
1840 /* Destroy deviceInfo */
1841 DestroyDeviceInfo(deviceInfo
);
1845 TRACE("Returning %d\n", ret
);
1849 /***********************************************************************
1850 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1852 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1853 HDEVINFO DeviceInfoSet
,
1854 PSP_DEVINFO_DATA DeviceInfoData
,
1856 PSP_DETSIG_CMPPROC CompareProc
,
1857 PVOID CompareContext
,
1858 PSP_DEVINFO_DATA DupDeviceInfoData
)
1860 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1861 WCHAR DevInstId
[MAX_DEVICE_ID_LEN
];
1862 DEVINST ParentDevInst
;
1864 DWORD dwError
= ERROR_SUCCESS
;
1866 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1867 CompareProc
, CompareContext
, DupDeviceInfoData
);
1869 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1871 SetLastError(ERROR_INVALID_HANDLE
);
1874 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1876 SetLastError(ERROR_INVALID_HANDLE
);
1879 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1880 || !DeviceInfoData
->Reserved
)
1882 SetLastError(ERROR_INVALID_PARAMETER
);
1886 if (Flags
& ~SPRDI_FIND_DUPS
)
1888 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~SPRDI_FIND_DUPS
);
1889 SetLastError(ERROR_INVALID_FLAGS
);
1893 if (Flags
& SPRDI_FIND_DUPS
)
1895 FIXME("Unimplemented codepath!\n");
1898 CM_Get_Device_ID_Ex(DeviceInfoData
->DevInst
,
1904 CM_Get_Parent_Ex(&ParentDevInst
,
1905 DeviceInfoData
->DevInst
,
1909 cr
= CM_Create_DevInst_Ex(&DeviceInfoData
->DevInst
,
1912 CM_CREATE_DEVINST_NORMAL
| CM_CREATE_DEVINST_DO_NOT_INSTALL
,
1914 if (cr
!= CR_SUCCESS
)
1916 dwError
= ERROR_NO_SUCH_DEVINST
;
1919 SetLastError(dwError
);
1921 return (dwError
== ERROR_SUCCESS
);
1924 /***********************************************************************
1925 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1927 BOOL WINAPI
SetupDiEnumDeviceInfo(
1930 PSP_DEVINFO_DATA info
)
1934 TRACE("%p %d %p\n", devinfo
, index
, info
);
1938 SetLastError(ERROR_INVALID_PARAMETER
);
1941 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1943 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1944 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1946 if (info
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1947 SetLastError(ERROR_INVALID_USER_BUFFER
);
1950 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1951 while (ItemList
!= &list
->ListHead
&& index
-- > 0)
1952 ItemList
= ItemList
->Flink
;
1953 if (ItemList
== &list
->ListHead
)
1954 SetLastError(ERROR_NO_MORE_ITEMS
);
1957 struct DeviceInfo
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
1958 memcpy(&info
->ClassGuid
,
1959 &DevInfo
->ClassGuid
,
1961 info
->DevInst
= DevInfo
->dnDevInst
;
1962 info
->Reserved
= (ULONG_PTR
)DevInfo
;
1968 SetLastError(ERROR_INVALID_HANDLE
);
1971 SetLastError(ERROR_INVALID_HANDLE
);
1975 /***********************************************************************
1976 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1978 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1979 HDEVINFO DeviceInfoSet
,
1980 PSP_DEVINFO_DATA DeviceInfoData
,
1981 PSTR DeviceInstanceId
,
1982 DWORD DeviceInstanceIdSize
,
1983 PDWORD RequiredSize
)
1989 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1990 DeviceInstanceIdSize
, RequiredSize
);
1992 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1994 SetLastError(ERROR_INVALID_PARAMETER
);
1998 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
2003 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
2005 instanceId
= MyMalloc(size
* sizeof(WCHAR
));
2008 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
2015 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
2017 DeviceInstanceIdSize
, NULL
, NULL
);
2023 if (len
> DeviceInstanceIdSize
)
2025 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2029 *RequiredSize
= len
;
2037 *RequiredSize
= size
;
2038 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2044 /***********************************************************************
2045 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
2047 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
2048 HDEVINFO DeviceInfoSet
,
2049 PSP_DEVINFO_DATA DeviceInfoData
,
2050 PWSTR DeviceInstanceId
,
2051 DWORD DeviceInstanceIdSize
,
2052 PDWORD RequiredSize
)
2054 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2055 struct DeviceInfo
*devInfo
;
2057 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
2058 DeviceInstanceIdSize
, RequiredSize
);
2060 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2062 SetLastError(ERROR_INVALID_HANDLE
);
2065 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2067 SetLastError(ERROR_INVALID_HANDLE
);
2070 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2071 || !DeviceInfoData
->Reserved
)
2073 SetLastError(ERROR_INVALID_PARAMETER
);
2076 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2077 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
2079 SetLastError(ERROR_INVALID_PARAMETER
);
2082 if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
2084 SetLastError(ERROR_INVALID_PARAMETER
);
2087 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
2088 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
2090 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2092 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
2095 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
2097 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
2101 /***********************************************************************
2102 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
2104 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
2106 PCSTR InfSectionName
,
2107 PSTR InfSectionWithExt
,
2108 DWORD InfSectionWithExtSize
,
2109 PDWORD RequiredSize
,
2112 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
2113 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2117 /***********************************************************************
2118 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2120 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
2122 PCWSTR InfSectionName
,
2123 PWSTR InfSectionWithExt
,
2124 DWORD InfSectionWithExtSize
,
2125 PDWORD RequiredSize
,
2128 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
2129 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2133 /***********************************************************************
2134 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2137 SetupDiGetActualSectionToInstallExA(
2139 IN PCSTR InfSectionName
,
2140 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
2141 OUT PSTR InfSectionWithExt OPTIONAL
,
2142 IN DWORD InfSectionWithExtSize
,
2143 OUT PDWORD RequiredSize OPTIONAL
,
2144 OUT PSTR
* Extension OPTIONAL
,
2147 LPWSTR InfSectionNameW
= NULL
;
2148 LPWSTR InfSectionWithExtW
= NULL
;
2150 BOOL bResult
= FALSE
;
2156 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2157 if (InfSectionNameW
== NULL
)
2160 if (InfSectionWithExt
)
2162 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
2163 if (InfSectionWithExtW
== NULL
)
2167 bResult
= SetupDiGetActualSectionToInstallExW(
2168 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
2169 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
2170 InfSectionWithExtSize
,
2172 Extension
? &ExtensionW
: NULL
,
2175 if (bResult
&& InfSectionWithExt
)
2177 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
2178 InfSectionWithExtSize
, NULL
, NULL
) != 0;
2180 if (bResult
&& Extension
)
2182 if (ExtensionW
== NULL
)
2185 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
2189 MyFree(InfSectionNameW
);
2190 MyFree(InfSectionWithExtW
);
2195 /***********************************************************************
2196 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2198 BOOL WINAPI
SetupDiGetClassDescriptionA(
2199 const GUID
* ClassGuid
,
2200 PSTR ClassDescription
,
2201 DWORD ClassDescriptionSize
,
2202 PDWORD RequiredSize
)
2204 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
2205 ClassDescriptionSize
,
2206 RequiredSize
, NULL
, NULL
);
2209 /***********************************************************************
2210 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2212 BOOL WINAPI
SetupDiGetClassDescriptionW(
2213 const GUID
* ClassGuid
,
2214 PWSTR ClassDescription
,
2215 DWORD ClassDescriptionSize
,
2216 PDWORD RequiredSize
)
2218 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
2219 ClassDescriptionSize
,
2220 RequiredSize
, NULL
, NULL
);
2223 /***********************************************************************
2224 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2226 BOOL WINAPI
SetupDiGetClassDescriptionExA(
2227 const GUID
* ClassGuid
,
2228 PSTR ClassDescription
,
2229 DWORD ClassDescriptionSize
,
2230 PDWORD RequiredSize
,
2234 PWCHAR ClassDescriptionW
= NULL
;
2235 LPWSTR MachineNameW
= NULL
;
2238 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2239 ClassDescriptionSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
2241 if (ClassDescriptionSize
> 0)
2243 ClassDescriptionW
= MyMalloc(ClassDescriptionSize
* sizeof(WCHAR
));
2244 if (!ClassDescriptionW
)
2246 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2253 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
2256 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2261 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
,
2262 ClassDescriptionSize
* sizeof(WCHAR
), RequiredSize
, MachineNameW
, Reserved
);
2265 DWORD len
= (DWORD
)WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
2266 ClassDescriptionSize
, NULL
, NULL
);
2267 if (len
== 0 || len
> ClassDescriptionSize
)
2269 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2275 MyFree(ClassDescriptionW
);
2276 MyFree(MachineNameW
);
2280 /***********************************************************************
2281 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2283 BOOL WINAPI
SetupDiGetClassDescriptionExW(
2284 const GUID
* ClassGuid
,
2285 PWSTR ClassDescription
,
2286 DWORD ClassDescriptionSize
,
2287 PDWORD RequiredSize
,
2297 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2298 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
2300 /* Make sure there's a GUID */
2303 SetLastError(ERROR_INVALID_PARAMETER
);
2307 /* Make sure there's a real buffer when there's a size */
2308 if (!ClassDescription
&& ClassDescriptionSize
> 0)
2310 SetLastError(ERROR_INVALID_PARAMETER
);
2314 /* Open the key for the GUID */
2315 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
2320 if (hKey
== INVALID_HANDLE_VALUE
)
2323 /* Retrieve the class description data and close the key */
2324 rc
= QueryRegistryValue(hKey
, NULL
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
2327 /* Make sure we got the data */
2328 if (rc
!= ERROR_SUCCESS
)
2334 /* Make sure the data is a string */
2335 if (dwRegType
!= REG_SZ
)
2338 SetLastError(ERROR_GEN_FAILURE
);
2342 /* Determine the length of the class description */
2343 dwLength
/= sizeof(WCHAR
);
2345 /* Count the null-terminator if none is present */
2346 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
2349 /* Inform the caller about the class description */
2350 if ((ClassDescription
!= NULL
) && (dwLength
<= ClassDescriptionSize
))
2352 memcpy(ClassDescription
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
2353 ClassDescription
[dwLength
- 1] = UNICODE_NULL
;
2356 /* Inform the caller about the required size */
2357 if (RequiredSize
!= NULL
)
2358 *RequiredSize
= dwLength
;
2360 /* Clean up the buffer */
2363 /* Make sure the buffer was large enough */
2364 if ((ClassDescription
== NULL
) || (dwLength
> ClassDescriptionSize
))
2366 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2373 /***********************************************************************
2374 * SetupDiGetClassDevsA (SETUPAPI.@)
2376 HDEVINFO WINAPI
SetupDiGetClassDevsA(
2382 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
2383 flags
, NULL
, NULL
, NULL
);
2386 /***********************************************************************
2387 * SetupDiGetClassDevsExA (SETUPAPI.@)
2389 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
2399 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
2403 enumstrW
= pSetupMultiByteToUnicode(enumstr
, CP_ACP
);
2406 ret
= INVALID_HANDLE_VALUE
;
2412 machineW
= pSetupMultiByteToUnicode(machine
, CP_ACP
);
2416 ret
= INVALID_HANDLE_VALUE
;
2420 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
2421 machineW
, reserved
);
2429 /***********************************************************************
2430 * SetupDiGetClassDevsW (SETUPAPI.@)
2432 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2438 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2442 /***********************************************************************
2443 * SetupDiGetClassDevsExW (SETUPAPI.@)
2445 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2454 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2455 struct DeviceInfoSet
*list
;
2456 CONST GUID
*pClassGuid
;
2458 HDEVINFO set
= INVALID_HANDLE_VALUE
;
2460 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2461 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2464 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2466 SetLastError(ERROR_INVALID_PARAMETER
);
2467 return INVALID_HANDLE_VALUE
;
2470 /* Create the deviceset if not set */
2473 list
= (struct DeviceInfoSet
*)deviceset
;
2474 if (list
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2476 SetLastError(ERROR_INVALID_HANDLE
);
2479 hDeviceInfo
= deviceset
;
2483 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2484 flags
& (DIGCF_DEVICEINTERFACE
| DIGCF_ALLCLASSES
) ? NULL
: class,
2485 NULL
, machine
, NULL
);
2486 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2488 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2491 if (flags
& DIGCF_PROFILE
)
2492 FIXME(": flag DIGCF_PROFILE ignored\n");
2494 if (flags
& DIGCF_DEVICEINTERFACE
)
2498 SetLastError(ERROR_INVALID_PARAMETER
);
2501 rc
= SETUP_CreateInterfaceList(list
, machine
, class, enumstr
, flags
& DIGCF_PRESENT
);
2505 /* Determine which class(es) should be included in the deviceset */
2506 if (flags
& DIGCF_ALLCLASSES
)
2508 /* The caller wants all classes. Check if
2509 * the deviceset limits us to one class */
2510 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2513 pClassGuid
= &list
->ClassGuid
;
2517 /* The caller wants one class. Check if it matches deviceset class */
2518 if (IsEqualIID(&list
->ClassGuid
, class)
2519 || IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2525 SetLastError(ERROR_INVALID_PARAMETER
);
2529 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2531 /* No class specified. Try to use the one of the deviceset */
2532 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2533 pClassGuid
= &list
->ClassGuid
;
2536 SetLastError(ERROR_INVALID_PARAMETER
);
2542 SetLastError(ERROR_INVALID_PARAMETER
);
2545 rc
= SETUP_CreateDevicesList(list
, machine
, pClassGuid
, enumstr
);
2547 if (rc
!= ERROR_SUCCESS
)
2555 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= set
)
2556 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2560 /***********************************************************************
2561 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2563 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2564 HDEVINFO DeviceInfoSet
,
2565 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2567 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2569 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2571 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2573 SetLastError(ERROR_INVALID_HANDLE
);
2576 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2578 SetLastError(ERROR_INVALID_HANDLE
);
2582 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2584 SetLastError(ERROR_INVALID_PARAMETER
);
2587 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2588 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2589 if (set
->MachineName
)
2592 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2596 DevInfoData
->RemoteMachineName
[0] = 0;
2601 /***********************************************************************
2602 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2604 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2605 HDEVINFO DeviceInfoSet
,
2606 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2608 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2610 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2612 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2614 SetLastError(ERROR_INVALID_HANDLE
);
2617 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2619 SetLastError(ERROR_INVALID_HANDLE
);
2623 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2625 SetLastError(ERROR_INVALID_PARAMETER
);
2628 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2629 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2630 if (set
->MachineName
)
2631 strcpyW(DevInfoData
->RemoteMachineName
, set
->MachineName
+ 2);
2633 DevInfoData
->RemoteMachineName
[0] = 0;
2638 /***********************************************************************
2639 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2641 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2642 HDEVINFO DeviceInfoSet
,
2643 PSP_DEVINFO_DATA DeviceInfoData
,
2644 const GUID
*InterfaceClassGuid
,
2645 PCSTR ReferenceString
,
2646 DWORD CreationFlags
,
2647 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2650 LPWSTR ReferenceStringW
= NULL
;
2652 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2653 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2654 CreationFlags
, DeviceInterfaceData
);
2656 if (ReferenceString
)
2658 ReferenceStringW
= pSetupMultiByteToUnicode(ReferenceString
, CP_ACP
);
2659 if (ReferenceStringW
== NULL
) return FALSE
;
2662 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2663 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2664 DeviceInterfaceData
);
2666 MyFree(ReferenceStringW
);
2671 /***********************************************************************
2672 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2674 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2675 HDEVINFO DeviceInfoSet
,
2676 PSP_DEVINFO_DATA DeviceInfoData
,
2677 const GUID
*InterfaceClassGuid
,
2678 PCWSTR ReferenceString
,
2679 DWORD CreationFlags
,
2680 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2682 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2683 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2684 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2685 CreationFlags
, DeviceInterfaceData
);
2687 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2689 SetLastError(ERROR_INVALID_HANDLE
);
2692 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2694 SetLastError(ERROR_INVALID_HANDLE
);
2697 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2698 || !DeviceInfoData
->Reserved
)
2700 SetLastError(ERROR_INVALID_PARAMETER
);
2703 if (!InterfaceClassGuid
)
2705 SetLastError(ERROR_INVALID_USER_BUFFER
);
2709 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2710 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2711 CreationFlags
, DeviceInterfaceData
);
2712 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2716 /***********************************************************************
2717 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2719 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2720 HDEVINFO DeviceInfoSet
,
2721 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2725 PCSTR InfSectionName
)
2728 PWSTR InfSectionNameW
= NULL
;
2730 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2731 samDesired
, InfHandle
, InfSectionName
);
2734 if (!InfSectionName
)
2736 SetLastError(ERROR_INVALID_PARAMETER
);
2737 return INVALID_HANDLE_VALUE
;
2739 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2740 if (!InfSectionNameW
)
2741 return INVALID_HANDLE_VALUE
;
2743 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2744 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2746 MyFree(InfSectionNameW
);
2750 /***********************************************************************
2751 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2753 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2754 HDEVINFO DeviceInfoSet
,
2755 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2759 PCWSTR InfSectionName
)
2762 LPWSTR SymbolicLink
;
2763 DWORD Length
, Index
;
2765 WCHAR bracedGuidString
[39];
2766 struct DeviceInterface
*DevItf
;
2767 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2769 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2770 samDesired
, InfHandle
, InfSectionName
);
2772 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2773 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2775 SetLastError(ERROR_INVALID_HANDLE
);
2776 return INVALID_HANDLE_VALUE
;
2778 if (!DeviceInterfaceData
||
2779 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2780 !DeviceInterfaceData
->Reserved
)
2782 SetLastError(ERROR_INVALID_PARAMETER
);
2783 return INVALID_HANDLE_VALUE
;
2785 if (InfHandle
&& !InfSectionName
)
2787 SetLastError(ERROR_INVALID_PARAMETER
);
2788 return INVALID_HANDLE_VALUE
;
2791 hKey
= SetupDiOpenClassRegKeyExW(&DeviceInterfaceData
->InterfaceClassGuid
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2792 if (hKey
== INVALID_HANDLE_VALUE
)
2794 hKey
= SetupDiOpenClassRegKeyExW(NULL
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2795 if (hKey
== INVALID_HANDLE_VALUE
)
2797 SetLastError(ERROR_INVALID_PARAMETER
);
2798 return INVALID_HANDLE_VALUE
;
2800 SETUPDI_GuidToString(&DeviceInterfaceData
->InterfaceClassGuid
, bracedGuidString
);
2802 if (RegCreateKeyExW(hKey
, bracedGuidString
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
) != ERROR_SUCCESS
)
2804 SetLastError(ERROR_INVALID_PARAMETER
);
2805 return INVALID_HANDLE_VALUE
;
2811 DevItf
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2813 Length
= (wcslen(DevItf
->SymbolicLink
)+1) * sizeof(WCHAR
);
2814 SymbolicLink
= HeapAlloc(GetProcessHeap(), 0, Length
);
2818 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2819 return INVALID_HANDLE_VALUE
;
2822 wcscpy(SymbolicLink
, DevItf
->SymbolicLink
);
2825 while(SymbolicLink
[Index
])
2827 if (SymbolicLink
[Index
] == L
'\\')
2829 SymbolicLink
[Index
] = L
'#';
2834 rc
= RegCreateKeyExW(hKey
, SymbolicLink
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
);
2837 HeapFree(GetProcessHeap(), 0, SymbolicLink
);
2839 if (rc
== ERROR_SUCCESS
)
2841 if (InfHandle
&& InfSectionName
)
2843 if (!SetupInstallFromInfSection(NULL
/*FIXME */,
2846 SPINST_INIFILES
| SPINST_REGISTRY
| SPINST_INI2REG
| SPINST_FILES
| SPINST_BITREG
| SPINST_REGSVR
| SPINST_UNREGSVR
| SPINST_PROFILEITEMS
| SPINST_COPYINF
,
2850 set
->SelectedDevice
->InstallParams
.InstallMsgHandler
,
2851 set
->SelectedDevice
->InstallParams
.InstallMsgHandlerContext
,
2852 INVALID_HANDLE_VALUE
,
2855 RegCloseKey(hDevKey
);
2856 return INVALID_HANDLE_VALUE
;
2865 /***********************************************************************
2866 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2868 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2869 HDEVINFO DeviceInfoSet
,
2870 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2873 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2876 TRACE("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2878 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2879 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2881 SetLastError(ERROR_INVALID_HANDLE
);
2884 if (!DeviceInterfaceData
||
2885 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2886 !DeviceInterfaceData
->Reserved
)
2888 SetLastError(ERROR_INVALID_PARAMETER
);
2892 FIXME("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2893 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2897 /***********************************************************************
2898 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2901 * DeviceInfoSet [I] Set of devices from which to enumerate
2903 * DeviceInfoData [I] (Optional) If specified, a specific device
2904 * instance from which to enumerate interfaces.
2905 * If it isn't specified, all interfaces for all
2906 * devices in the set are enumerated.
2907 * InterfaceClassGuid [I] The interface class to enumerate.
2908 * MemberIndex [I] An index of the interface instance to enumerate.
2909 * A caller should start with MemberIndex set to 0,
2910 * and continue until the function fails with
2911 * ERROR_NO_MORE_ITEMS.
2912 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2913 * member must be set to
2914 * sizeof(SP_DEVICE_INTERFACE_DATA).
2917 * Success: non-zero value.
2918 * Failure: FALSE. Call GetLastError() for more info.
2920 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2921 HDEVINFO DeviceInfoSet
,
2922 PSP_DEVINFO_DATA DeviceInfoData
,
2923 CONST GUID
* InterfaceClassGuid
,
2925 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2927 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2930 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet
, DeviceInfoData
,
2931 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2933 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2934 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2936 SetLastError(ERROR_INVALID_HANDLE
);
2939 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2940 !DeviceInfoData
->Reserved
))
2942 SetLastError(ERROR_INVALID_PARAMETER
);
2945 if (!DeviceInterfaceData
||
2946 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2948 SetLastError(ERROR_INVALID_PARAMETER
);
2953 struct DeviceInfo
*devInfo
=
2954 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2956 PLIST_ENTRY InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2957 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2959 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2960 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2962 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2965 if (MemberIndex
-- == 0)
2967 /* return this item */
2968 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2969 &DevItf
->InterfaceClassGuid
,
2971 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2972 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2976 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2979 SetLastError(ERROR_NO_MORE_ITEMS
);
2984 PLIST_ENTRY ItemList
= set
->ListHead
.Flink
;
2985 while (ItemList
!= &set
->ListHead
&& !found
)
2987 PLIST_ENTRY InterfaceListEntry
;
2988 struct DeviceInfo
*devInfo
=
2989 CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
2990 InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2991 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2993 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2994 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2996 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2999 if (MemberIndex
-- == 0)
3001 /* return this item */
3002 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
3003 &DevItf
->InterfaceClassGuid
,
3005 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
3006 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
3010 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3012 ItemList
= ItemList
->Flink
;
3016 SetLastError(ERROR_NO_MORE_ITEMS
);
3021 /***********************************************************************
3022 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
3024 * Destroy a DeviceInfoList and free all used memory of the list.
3027 * devinfo [I] DeviceInfoList pointer to list to destroy
3030 * Success: non zero value.
3031 * Failure: zero value.
3033 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
3037 TRACE("%p\n", devinfo
);
3038 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
3040 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
3042 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
3044 ret
= DestroyDeviceInfoSet(list
);
3049 SetLastError(ERROR_INVALID_HANDLE
);
3054 /***********************************************************************
3055 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
3057 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
3058 HDEVINFO DeviceInfoSet
,
3059 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3060 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
3061 DWORD DeviceInterfaceDetailDataSize
,
3062 PDWORD RequiredSize
,
3063 PSP_DEVINFO_DATA DeviceInfoData
)
3065 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3066 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
3067 DWORD sizeW
= 0, bytesNeeded
;
3070 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3071 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3072 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3074 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3075 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3077 SetLastError(ERROR_INVALID_HANDLE
);
3080 if (!DeviceInterfaceData
||
3081 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3082 !DeviceInterfaceData
->Reserved
)
3084 SetLastError(ERROR_INVALID_PARAMETER
);
3087 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
3089 SetLastError(ERROR_INVALID_USER_BUFFER
);
3093 if((DeviceInterfaceDetailDataSize
!= 0) &&
3094 (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + sizeof(CHAR
))))
3096 SetLastError(ERROR_INVALID_USER_BUFFER
);
3100 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3102 SetLastError(ERROR_INVALID_USER_BUFFER
);
3107 if (DeviceInterfaceDetailData
!= NULL
)
3109 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
3110 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
3111 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)MyMalloc(sizeW
);
3112 if (!DeviceInterfaceDetailDataW
)
3114 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3116 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
3118 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
3120 ret
= SetupDiGetDeviceInterfaceDetailW(
3122 DeviceInterfaceData
,
3123 DeviceInterfaceDetailDataW
,
3127 bytesNeeded
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
3128 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
3130 *RequiredSize
= bytesNeeded
;
3131 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
>= bytesNeeded
)
3133 if (!WideCharToMultiByte(
3135 DeviceInterfaceDetailDataW
->DevicePath
, -1,
3136 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
3143 MyFree(DeviceInterfaceDetailDataW
);
3148 /***********************************************************************
3149 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3151 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
3152 HDEVINFO DeviceInfoSet
,
3153 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3154 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
3155 DWORD DeviceInterfaceDetailDataSize
,
3156 PDWORD RequiredSize
,
3157 PSP_DEVINFO_DATA DeviceInfoData
)
3159 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3162 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3163 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3164 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3166 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3167 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3169 SetLastError(ERROR_INVALID_HANDLE
);
3172 if (!DeviceInterfaceData
||
3173 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3174 !DeviceInterfaceData
->Reserved
)
3176 SetLastError(ERROR_INVALID_PARAMETER
);
3179 if (DeviceInterfaceDetailData
&& DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
3181 SetLastError(ERROR_INVALID_USER_BUFFER
);
3184 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3186 SetLastError(ERROR_INVALID_USER_BUFFER
);
3189 if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3191 SetLastError(ERROR_INVALID_PARAMETER
);
3194 if ((DeviceInterfaceDetailData
!= NULL
)
3195 && (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) + sizeof(WCHAR
)))
3197 SetLastError(ERROR_INVALID_PARAMETER
);
3202 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
3203 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
3204 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
3205 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
3207 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
3209 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3211 *RequiredSize
= sizeRequired
;
3215 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
3216 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
3219 memcpy(&DeviceInfoData
->ClassGuid
,
3220 &deviceInterface
->DeviceInfo
->ClassGuid
,
3222 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
3223 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
3231 struct PropertyMapEntry
3238 static struct PropertyMapEntry PropertyMap
[] = {
3239 { REG_SZ
, "DeviceDesc", REGSTR_VAL_DEVDESC
},
3240 { REG_MULTI_SZ
, "HardwareId", REGSTR_VAL_HARDWAREID
},
3241 { REG_MULTI_SZ
, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS
},
3242 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3243 { REG_SZ
, "Service", REGSTR_VAL_SERVICE
},
3244 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3245 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3246 { REG_SZ
, "Class", REGSTR_VAL_CLASS
},
3247 { REG_SZ
, "ClassGUID", REGSTR_VAL_CLASSGUID
},
3248 { REG_SZ
, "Driver", REGSTR_VAL_DRIVER
},
3249 { REG_DWORD
, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS
},
3250 { REG_SZ
, "Mfg", REGSTR_VAL_MFG
},
3251 { REG_SZ
, "FriendlyName", REGSTR_VAL_FRIENDLYNAME
},
3252 { REG_SZ
, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION
},
3253 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3254 { REG_DWORD
, "Capabilities", REGSTR_VAL_CAPABILITIES
},
3255 { REG_DWORD
, "UINumber", REGSTR_VAL_UI_NUMBER
},
3256 { REG_MULTI_SZ
, "UpperFilters", REGSTR_VAL_UPPERFILTERS
},
3257 { REG_MULTI_SZ
, "LowerFilters", REGSTR_VAL_LOWERFILTERS
},
3258 { 0, NULL
, NULL
}, /* SPDRP_BUSTYPEGUID */
3259 { 0, NULL
, NULL
}, /* SPDRP_LEGACYBUSTYPE */
3260 { 0, NULL
, NULL
}, /* SPDRP_BUSNUMBER */
3261 { 0, NULL
, NULL
}, /* SPDRP_ENUMERATOR_NAME */
3262 { REG_BINARY
, "Security", REGSTR_SECURITY
},
3263 { 0, NULL
, NULL
}, /* SPDRP_SECURITY_SDS */
3264 { 0, NULL
, NULL
}, /* SPDRP_DEVTYPE */
3265 { 0, NULL
, NULL
}, /* SPDRP_EXCLUSIVE */
3266 { 0, NULL
, NULL
}, /* SPDRP_CHARACTERISTICS */
3267 { 0, NULL
, NULL
}, /* SPDRP_ADDRESS */
3268 { REG_SZ
, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT
},
3269 { 0, NULL
, NULL
}, /* SPDRP_DEVICE_POWER_DATA */
3270 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY */
3271 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3272 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3273 { 0, NULL
, NULL
}, /* SPDRP_INSTALL_STATE */
3276 /***********************************************************************
3277 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3279 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3280 HDEVINFO DeviceInfoSet
,
3281 PSP_DEVINFO_DATA DeviceInfoData
,
3283 PDWORD PropertyRegDataType
,
3284 PBYTE PropertyBuffer
,
3285 DWORD PropertyBufferSize
,
3286 PDWORD RequiredSize
)
3289 BOOL bIsStringProperty
;
3291 DWORD RequiredSizeA
, RequiredSizeW
;
3292 DWORD PropertyBufferSizeW
= 0;
3293 PBYTE PropertyBufferW
= NULL
;
3295 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3296 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3299 if (PropertyBufferSize
!= 0)
3301 PropertyBufferSizeW
= PropertyBufferSize
* 2;
3302 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
3303 if (!PropertyBufferW
)
3305 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3310 ret
= SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
3315 PropertyBufferSizeW
,
3318 if (ret
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3320 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
3322 if (bIsStringProperty
)
3323 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
3325 RequiredSizeA
= RequiredSizeW
;
3327 *RequiredSize
= RequiredSizeA
;
3328 if (PropertyRegDataType
)
3329 *PropertyRegDataType
= RegType
;
3334 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3338 if (RequiredSizeA
<= PropertyBufferSize
)
3340 if (bIsStringProperty
&& PropertyBufferSize
> 0)
3342 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
3344 /* Last error is already set by WideCharToMultiByte */
3349 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
3353 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3357 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3361 /***********************************************************************
3362 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3364 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3365 HDEVINFO DeviceInfoSet
,
3366 PSP_DEVINFO_DATA DeviceInfoData
,
3368 PDWORD PropertyRegDataType
,
3369 PBYTE PropertyBuffer
,
3370 DWORD PropertyBufferSize
,
3371 PDWORD RequiredSize
)
3374 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3375 struct DeviceInfo
*devInfo
;
3377 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3378 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3381 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3383 SetLastError(ERROR_INVALID_HANDLE
);
3386 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3388 SetLastError(ERROR_INVALID_HANDLE
);
3391 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3392 || !DeviceInfoData
->Reserved
)
3394 SetLastError(ERROR_INVALID_PARAMETER
);
3397 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3398 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3399 && PropertyMap
[Property
].nameW
)
3401 DWORD size
= PropertyBufferSize
;
3404 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_QUERY_VALUE
);
3405 if (hKey
== INVALID_HANDLE_VALUE
)
3407 l
= RegQueryValueExW(hKey
, PropertyMap
[Property
].nameW
,
3408 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3412 *RequiredSize
= size
;
3415 if (PropertyBuffer
!= NULL
|| size
== 0)
3418 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3420 case ERROR_MORE_DATA
:
3421 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3427 else if (Property
== SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
)
3429 DWORD required
= (strlenW(devInfo
->Data
) + 1) * sizeof(WCHAR
);
3431 if (PropertyRegDataType
)
3432 *PropertyRegDataType
= REG_SZ
;
3434 *RequiredSize
= required
;
3435 if (PropertyBufferSize
>= required
)
3437 strcpyW((LPWSTR
)PropertyBuffer
, devInfo
->Data
);
3441 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3445 ERR("Property 0x%lx not implemented\n", Property
);
3446 SetLastError(ERROR_NOT_SUPPORTED
);
3451 /***********************************************************************
3452 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3454 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
3455 HDEVINFO DeviceInfoSet
,
3456 PSP_DEVINFO_DATA DeviceInfoData
,
3458 const BYTE
*PropertyBuffer
,
3459 DWORD PropertyBufferSize
)
3462 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3464 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3465 PropertyBuffer
, PropertyBufferSize
);
3467 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3469 SetLastError(ERROR_INVALID_HANDLE
);
3472 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3474 SetLastError(ERROR_INVALID_HANDLE
);
3477 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3478 || !DeviceInfoData
->Reserved
)
3480 SetLastError(ERROR_INVALID_PARAMETER
);
3484 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3485 Property
, PropertyBuffer
, PropertyBufferSize
);
3486 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3490 /***********************************************************************
3491 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3493 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
3494 HDEVINFO DeviceInfoSet
,
3495 PSP_DEVINFO_DATA DeviceInfoData
,
3497 const BYTE
*PropertyBuffer
,
3498 DWORD PropertyBufferSize
)
3501 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3503 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3504 PropertyBuffer
, PropertyBufferSize
);
3506 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3508 SetLastError(ERROR_INVALID_HANDLE
);
3511 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3513 SetLastError(ERROR_INVALID_HANDLE
);
3516 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3517 || !DeviceInfoData
->Reserved
)
3519 SetLastError(ERROR_INVALID_PARAMETER
);
3522 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3523 && PropertyMap
[Property
].nameW
)
3527 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3528 if (hKey
== INVALID_HANDLE_VALUE
)
3530 /* Write new data */
3532 hKey
, PropertyMap
[Property
].nameW
, 0,
3533 PropertyMap
[Property
].regType
, PropertyBuffer
,
3534 PropertyBufferSize
);
3543 ERR("Property 0x%lx not implemented\n", Property
);
3544 SetLastError(ERROR_NOT_SUPPORTED
);
3547 TRACE("Returning %d\n", ret
);
3551 /***********************************************************************
3552 * SetupDiInstallClassA (SETUPAPI.@)
3554 BOOL WINAPI
SetupDiInstallClassA(
3560 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3563 /***********************************************************************
3564 * SetupDiInstallClassExA (SETUPAPI.@)
3567 SetupDiInstallClassExA(
3568 IN HWND hwndParent OPTIONAL
,
3569 IN PCSTR InfFileName OPTIONAL
,
3571 IN HSPFILEQ FileQueue OPTIONAL
,
3572 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3576 PWSTR InfFileNameW
= NULL
;
3581 SetLastError(ERROR_INVALID_PARAMETER
);
3586 InfFileNameW
= pSetupMultiByteToUnicode(InfFileName
, CP_ACP
);
3587 if (InfFileNameW
== NULL
)
3589 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3594 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3595 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3597 MyFree(InfFileNameW
);
3602 HKEY
SETUP_CreateClassKey(HINF hInf
)
3604 static const WCHAR slash
[] = { '\\',0 };
3605 WCHAR FullBuffer
[MAX_PATH
];
3606 WCHAR Buffer
[MAX_PATH
];
3610 if (!SetupGetLineTextW(NULL
,
3618 return INVALID_HANDLE_VALUE
;
3621 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3622 lstrcatW(FullBuffer
, slash
);
3623 lstrcatW(FullBuffer
, Buffer
);
3625 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3631 if (!SetupGetLineTextW(NULL
,
3639 return INVALID_HANDLE_VALUE
;
3642 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3646 REG_OPTION_NON_VOLATILE
,
3652 return INVALID_HANDLE_VALUE
;
3656 if (RegSetValueExW(hClassKey
,
3661 RequiredSize
* sizeof(WCHAR
)))
3663 RegCloseKey(hClassKey
);
3664 RegDeleteKeyW(HKEY_LOCAL_MACHINE
,
3666 return INVALID_HANDLE_VALUE
;
3672 /***********************************************************************
3673 * SetupDiInstallClassW (SETUPAPI.@)
3675 BOOL WINAPI
SetupDiInstallClassW(
3681 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3685 /***********************************************************************
3686 * SetupDiOpenClassRegKey (SETUPAPI.@)
3688 HKEY WINAPI
SetupDiOpenClassRegKey(
3689 const GUID
* ClassGuid
,
3692 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3693 DIOCR_INSTALLER
, NULL
, NULL
);
3697 /***********************************************************************
3698 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3700 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3701 const GUID
* ClassGuid
,
3707 PWSTR MachineNameW
= NULL
;
3710 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3711 Flags
, debugstr_a(MachineName
), Reserved
);
3715 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
3716 if (MachineNameW
== NULL
)
3717 return INVALID_HANDLE_VALUE
;
3720 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3721 Flags
, MachineNameW
, Reserved
);
3723 MyFree(MachineNameW
);
3729 /***********************************************************************
3730 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3732 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3733 const GUID
* ClassGuid
,
3745 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3746 Flags
, debugstr_w(MachineName
), Reserved
);
3748 if (MachineName
!= NULL
)
3750 l
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3751 if (l
!= ERROR_SUCCESS
)
3754 return INVALID_HANDLE_VALUE
;
3758 HKLM
= HKEY_LOCAL_MACHINE
;
3760 if (Flags
== DIOCR_INSTALLER
)
3762 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3764 else if (Flags
== DIOCR_INTERFACE
)
3766 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3770 ERR("Invalid Flags parameter!\n");
3771 SetLastError(ERROR_INVALID_FLAGS
);
3772 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3773 return INVALID_HANDLE_VALUE
;
3778 if ((l
= RegOpenKeyExW(HKLM
,
3784 SetLastError(ERROR_INVALID_CLASS
);
3785 hClassesKey
= INVALID_HANDLE_VALUE
;
3787 if (MachineName
!= NULL
)
3793 WCHAR bracedGuidString
[39];
3795 SETUPDI_GuidToString(ClassGuid
, bracedGuidString
);
3797 if (!(l
= RegOpenKeyExW(HKLM
,
3803 if (MachineName
!= NULL
)
3806 if ((l
= RegOpenKeyExW(hClassesKey
,
3813 key
= INVALID_HANDLE_VALUE
;
3815 RegCloseKey(hClassesKey
);
3819 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3821 key
= INVALID_HANDLE_VALUE
;
3828 /***********************************************************************
3829 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3831 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3832 HDEVINFO DeviceInfoSet
,
3835 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3837 struct DeviceInfoSet
* list
;
3839 DWORD dwLength
, dwError
, dwIndex
, dwKeyName
, dwSubIndex
;
3841 WCHAR Buffer
[MAX_PATH
+ 1];
3842 WCHAR SymBuffer
[MAX_PATH
+ 1];
3843 WCHAR InstancePath
[MAX_PATH
+ 1];
3844 HKEY hKey
, hDevKey
, hSymKey
;
3845 struct DeviceInfo
* deviceInfo
;
3846 struct DeviceInterface
*deviceInterface
;
3848 PLIST_ENTRY ItemList
;
3849 PLIST_ENTRY InterfaceListEntry
;
3851 TRACE("%p %s %08x %p\n",
3852 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3855 if (DeviceInterfaceData
&& DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
3857 SetLastError(ERROR_INVALID_PARAMETER
);
3861 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3863 SetLastError(ERROR_INVALID_HANDLE
);
3867 list
= (struct DeviceInfoSet
* )DeviceInfoSet
;
3869 dwLength
= wcslen(DevicePath
);
3872 /* path must be at least a guid length + L'\0' */
3873 SetLastError(ERROR_BAD_PATHNAME
);
3877 if (DevicePath
[0] != L
'\\' ||
3878 DevicePath
[1] != L
'\\' ||
3879 (DevicePath
[2] != L
'?' && DevicePath
[2] != L
'.') ||
3880 DevicePath
[3] != L
'\\')
3882 /* invalid formatted path */
3883 SetLastError(ERROR_BAD_PATHNAME
);
3887 /* check for reference strings */
3888 pEnd
= wcschr(&DevicePath
[4], L
'\\');
3891 /* no reference string */
3892 pEnd
= DevicePath
+ dwLength
;
3896 wcscpy(Buffer
, pEnd
- 37);
3899 dwError
= UuidFromStringW(Buffer
, &ClassId
);
3900 if (dwError
!= NOERROR
)
3902 /* invalid formatted path */
3903 SetLastError(ERROR_BAD_PATHNAME
);
3907 hKey
= SetupDiOpenClassRegKeyExW(&ClassId
, KEY_READ
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
3909 if (hKey
== INVALID_HANDLE_VALUE
)
3911 /* invalid device class */
3915 ItemList
= list
->ListHead
.Flink
;
3916 while (ItemList
!= &list
->ListHead
)
3918 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
3919 InterfaceListEntry
= deviceInfo
->InterfaceListHead
.Flink
;
3920 while (InterfaceListEntry
!= &deviceInfo
->InterfaceListHead
)
3922 deviceInterface
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
3923 if (!IsEqualIID(&deviceInterface
->InterfaceClassGuid
, &ClassId
))
3925 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3929 if (!wcsicmp(deviceInterface
->SymbolicLink
, DevicePath
))
3931 if (DeviceInterfaceData
)
3933 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
3934 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
3935 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3949 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3950 dwError
= RegEnumKeyExW(hKey
, dwIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3952 if (dwError
!= ERROR_SUCCESS
)
3955 if (RegOpenKeyExW(hKey
, Buffer
, 0, KEY_READ
, &hDevKey
) != ERROR_SUCCESS
)
3959 InstancePath
[0] = 0;
3960 dwKeyName
= sizeof(InstancePath
);
3962 dwError
= RegQueryValueExW(hDevKey
, L
"DeviceInstance", NULL
, NULL
, (LPBYTE
)InstancePath
, &dwKeyName
);
3967 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3968 dwError
= RegEnumKeyExW(hDevKey
, dwSubIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3970 if (dwError
!= ERROR_SUCCESS
)
3973 dwError
= RegOpenKeyExW(hDevKey
, Buffer
, 0, KEY_READ
, &hSymKey
);
3974 if (dwError
!= ERROR_SUCCESS
)
3977 /* query for symbolic link */
3978 dwKeyName
= sizeof(SymBuffer
);
3979 SymBuffer
[0] = L
'\0';
3980 dwError
= RegQueryValueExW(hSymKey
, L
"SymbolicLink", NULL
, NULL
, (LPBYTE
)SymBuffer
, &dwKeyName
);
3982 if (dwError
!= ERROR_SUCCESS
)
3984 RegCloseKey(hSymKey
);
3988 if (!wcsicmp(SymBuffer
, DevicePath
))
3990 Ret
= CreateDeviceInfo(list
, InstancePath
, &ClassId
, &deviceInfo
);
3991 RegCloseKey(hSymKey
);
3992 RegCloseKey(hDevKey
);
3997 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymBuffer
) + 1) * sizeof(WCHAR
));
3998 if (deviceInterface
)
4001 CopyMemory(&deviceInterface
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
4002 deviceInterface
->DeviceInfo
= deviceInfo
;
4003 deviceInterface
->Flags
= SPINT_ACTIVE
; //FIXME
4005 wcscpy(deviceInterface
->SymbolicLink
, SymBuffer
);
4007 InsertTailList(&deviceInfo
->InterfaceListHead
, &deviceInterface
->ListEntry
);
4008 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4011 if (DeviceInterfaceData
)
4013 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
4014 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
4015 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
4020 SetLastError(ERROR_INVALID_USER_BUFFER
);
4026 HeapFree(GetProcessHeap(), 0, deviceInfo
);
4031 RegCloseKey(hSymKey
);
4035 RegCloseKey(hDevKey
);
4043 /***********************************************************************
4044 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
4046 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
4047 HDEVINFO DeviceInfoSet
,
4050 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
4052 LPWSTR DevicePathW
= NULL
;
4055 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
4057 DevicePathW
= pSetupMultiByteToUnicode(DevicePath
, CP_ACP
);
4058 if (DevicePathW
== NULL
)
4061 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
4062 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
4064 MyFree(DevicePathW
);
4069 /***********************************************************************
4070 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
4072 BOOL WINAPI
SetupDiSetClassInstallParamsA(
4073 HDEVINFO DeviceInfoSet
,
4074 PSP_DEVINFO_DATA DeviceInfoData
,
4075 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
4076 DWORD ClassInstallParamsSize
)
4078 FIXME("%p %p %x %u\n",DeviceInfoSet
, DeviceInfoData
,
4079 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
4084 IntSetupDiRegisterDeviceInfo(
4085 IN HDEVINFO DeviceInfoSet
,
4086 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
4088 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
4091 /***********************************************************************
4092 * SetupDiCallClassInstaller (SETUPAPI.@)
4094 BOOL WINAPI
SetupDiCallClassInstaller(
4095 DI_FUNCTION InstallFunction
,
4096 HDEVINFO DeviceInfoSet
,
4097 PSP_DEVINFO_DATA DeviceInfoData
)
4101 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4104 SetLastError(ERROR_INVALID_PARAMETER
);
4105 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4106 SetLastError(ERROR_INVALID_HANDLE
);
4107 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4108 SetLastError(ERROR_INVALID_HANDLE
);
4109 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
4110 SetLastError(ERROR_INVALID_HANDLE
);
4111 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4112 SetLastError(ERROR_INVALID_USER_BUFFER
);
4115 SP_DEVINSTALL_PARAMS_W InstallParams
;
4116 #define CLASS_COINSTALLER 0x1
4117 #define DEVICE_COINSTALLER 0x2
4118 #define CLASS_INSTALLER 0x4
4119 UCHAR CanHandle
= 0;
4120 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
4122 switch (InstallFunction
)
4124 case DIF_ADDPROPERTYPAGE_ADVANCED
:
4125 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4127 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
4128 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4130 case DIF_ALLOW_INSTALL
:
4131 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4134 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4136 case DIF_DESTROYPRIVATEDATA
:
4137 CanHandle
= CLASS_INSTALLER
;
4139 case DIF_INSTALLDEVICE
:
4140 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4141 DefaultHandler
= SetupDiInstallDevice
;
4143 case DIF_INSTALLDEVICEFILES
:
4144 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4145 DefaultHandler
= SetupDiInstallDriverFiles
;
4147 case DIF_INSTALLINTERFACES
:
4148 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4149 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
4151 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
4152 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4154 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
4155 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4157 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
4158 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4160 case DIF_NEWDEVICEWIZARD_PRESELECT
:
4161 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4163 case DIF_NEWDEVICEWIZARD_SELECT
:
4164 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4166 case DIF_POWERMESSAGEWAKE
:
4167 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4169 case DIF_PROPERTYCHANGE
:
4170 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4171 DefaultHandler
= SetupDiChangeState
;
4173 case DIF_REGISTER_COINSTALLERS
:
4174 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4175 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
4177 case DIF_REGISTERDEVICE
:
4178 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4179 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
4182 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4183 DefaultHandler
= SetupDiRemoveDevice
;
4185 case DIF_SELECTBESTCOMPATDRV
:
4186 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4187 DefaultHandler
= SetupDiSelectBestCompatDrv
;
4189 case DIF_SELECTDEVICE
:
4190 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4191 DefaultHandler
= SetupDiSelectDevice
;
4193 case DIF_TROUBLESHOOTER
:
4194 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4197 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4198 DefaultHandler
= SetupDiUnremoveDevice
;
4201 ERR("Install function %u not supported\n", InstallFunction
);
4202 SetLastError(ERROR_NOT_SUPPORTED
);
4205 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4206 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4207 /* Don't process this call, as a parameter is invalid */
4212 LIST_ENTRY ClassCoInstallersListHead
;
4213 LIST_ENTRY DeviceCoInstallersListHead
;
4214 HMODULE ClassInstallerLibrary
= NULL
;
4215 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
4216 COINSTALLER_CONTEXT_DATA Context
;
4217 PLIST_ENTRY ListEntry
;
4219 DWORD dwRegType
, dwLength
;
4220 DWORD rc
= NO_ERROR
;
4222 InitializeListHead(&ClassCoInstallersListHead
);
4223 InitializeListHead(&DeviceCoInstallersListHead
);
4225 if (CanHandle
& DEVICE_COINSTALLER
)
4227 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4228 if (hKey
!= INVALID_HANDLE_VALUE
)
4230 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4231 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4233 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4234 if (KeyBuffer
!= NULL
)
4236 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4237 if (rc
== ERROR_SUCCESS
)
4240 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4242 /* Add coinstaller to DeviceCoInstallersListHead list */
4243 struct CoInstallerElement
*coinstaller
;
4244 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
4245 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4248 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4249 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4250 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
4252 HeapFree(GetProcessHeap(), 0, coinstaller
);
4255 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4261 if (CanHandle
& CLASS_COINSTALLER
)
4265 REGSTR_PATH_CODEVICEINSTALLERS
,
4269 if (rc
== ERROR_SUCCESS
)
4271 LPWSTR lpGuidString
;
4272 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
4274 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
4275 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4277 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4278 if (KeyBuffer
!= NULL
)
4280 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4281 if (rc
== ERROR_SUCCESS
)
4284 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4286 /* Add coinstaller to ClassCoInstallersListHead list */
4287 struct CoInstallerElement
*coinstaller
;
4288 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
4289 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4292 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4293 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4294 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
4296 HeapFree(GetProcessHeap(), 0, coinstaller
);
4299 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4302 RpcStringFreeW(&lpGuidString
);
4307 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
4309 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
4310 if (hKey
!= INVALID_HANDLE_VALUE
)
4312 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4313 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
4315 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4316 if (KeyBuffer
!= NULL
)
4318 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4319 if (rc
== ERROR_SUCCESS
)
4321 /* Get ClassInstaller function pointer */
4322 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
4323 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
4325 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
4326 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4329 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4336 /* Call Class co-installers */
4337 Context
.PostProcessing
= FALSE
;
4339 ListEntry
= ClassCoInstallersListHead
.Flink
;
4340 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4342 struct CoInstallerElement
*coinstaller
;
4343 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4344 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4345 coinstaller
->PrivateData
= Context
.PrivateData
;
4346 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4348 coinstaller
->DoPostProcessing
= TRUE
;
4351 ListEntry
= ListEntry
->Flink
;
4354 /* Call Device co-installers */
4355 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4356 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4358 struct CoInstallerElement
*coinstaller
;
4359 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4360 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4361 coinstaller
->PrivateData
= Context
.PrivateData
;
4362 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4364 coinstaller
->DoPostProcessing
= TRUE
;
4367 ListEntry
= ListEntry
->Flink
;
4370 /* Call Class installer */
4373 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4374 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4377 rc
= ERROR_DI_DO_DEFAULT
;
4379 /* Call default handler */
4380 if (rc
== ERROR_DI_DO_DEFAULT
)
4382 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4384 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4387 rc
= GetLastError();
4393 /* Call Class co-installers that required postprocessing */
4394 Context
.PostProcessing
= TRUE
;
4395 ListEntry
= ClassCoInstallersListHead
.Flink
;
4396 while (ListEntry
!= &ClassCoInstallersListHead
)
4398 struct CoInstallerElement
*coinstaller
;
4399 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4400 if (coinstaller
->DoPostProcessing
)
4402 Context
.InstallResult
= rc
;
4403 Context
.PrivateData
= coinstaller
->PrivateData
;
4404 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4406 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4407 ListEntry
= ListEntry
->Flink
;
4410 /* Call Device co-installers that required postprocessing */
4411 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4412 while (ListEntry
!= &DeviceCoInstallersListHead
)
4414 struct CoInstallerElement
*coinstaller
;
4415 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4416 if (coinstaller
->DoPostProcessing
)
4418 Context
.InstallResult
= rc
;
4419 Context
.PrivateData
= coinstaller
->PrivateData
;
4420 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4422 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4423 ListEntry
= ListEntry
->Flink
;
4426 /* Free allocated memory */
4427 while (!IsListEmpty(&ClassCoInstallersListHead
))
4429 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4430 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4432 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4434 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4435 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4438 ret
= (rc
== NO_ERROR
);
4442 TRACE("Returning %d\n", ret
);
4446 /***********************************************************************
4447 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4449 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4450 HDEVINFO DeviceInfoSet
,
4451 PSP_DEVINFO_DATA DeviceInfoData
,
4452 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4454 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4457 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4459 if (DeviceInstallParams
== NULL
)
4460 SetLastError(ERROR_INVALID_PARAMETER
);
4461 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4462 SetLastError(ERROR_INVALID_USER_BUFFER
);
4465 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4466 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4470 /* Do W->A conversion */
4472 DeviceInstallParams
,
4473 &deviceInstallParamsW
,
4474 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4475 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4476 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4478 DeviceInstallParams
->DriverPath
[0] = '\0';
4484 TRACE("Returning %d\n", ret
);
4488 /***********************************************************************
4489 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4492 SetupDiGetDeviceInfoListClass(
4493 IN HDEVINFO DeviceInfoSet
,
4494 OUT LPGUID ClassGuid
)
4496 struct DeviceInfoSet
*list
;
4499 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4502 SetLastError(ERROR_INVALID_HANDLE
);
4503 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4504 SetLastError(ERROR_INVALID_HANDLE
);
4505 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4506 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4509 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4514 TRACE("Returning %d\n", ret
);
4518 /***********************************************************************
4519 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4522 SetupDiGetDeviceInstallParamsW(
4523 IN HDEVINFO DeviceInfoSet
,
4524 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4525 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4527 struct DeviceInfoSet
*list
;
4530 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4533 SetLastError(ERROR_INVALID_HANDLE
);
4534 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4535 SetLastError(ERROR_INVALID_HANDLE
);
4536 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4537 SetLastError(ERROR_INVALID_USER_BUFFER
);
4538 else if (!DeviceInstallParams
)
4539 SetLastError(ERROR_INVALID_PARAMETER
);
4540 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4541 SetLastError(ERROR_INVALID_USER_BUFFER
);
4544 PSP_DEVINSTALL_PARAMS_W Source
;
4547 Source
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4549 Source
= &list
->InstallParams
;
4555 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4557 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4559 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
4565 TRACE("Returning %d\n", ret
);
4570 CheckDeviceInstallParameters(
4571 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4573 DWORD SupportedFlags
=
4574 DI_NOVCP
| /* 0x00000008 */
4575 DI_DIDCOMPAT
| /* 0x00000010 */
4576 DI_DIDCLASS
| /* 0x00000020 */
4577 DI_NEEDRESTART
| /* 0x00000080 */
4578 DI_NEEDREBOOT
| /* 0x00000100 */
4579 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4580 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4581 DI_ENUMSINGLEINF
| /* 0x00010000 */
4582 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
4583 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4584 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4585 DI_QUIETINSTALL
| /* 0x00800000 */
4586 DI_NOFILECOPY
| /* 0x01000000 */
4587 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4588 DWORD SupportedFlagsEx
=
4589 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4590 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4591 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4592 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4593 DI_FLAGSEX_NO_DRVREG_MODIFY
| /* 0x00008000 */
4594 DI_FLAGSEX_INSTALLEDDRIVER
; /* 0x04000000 */
4597 /* FIXME: add support for more flags */
4599 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4600 * It should be checked before accessing to other values
4601 * of the SP_DEVINSTALL_PARAMS structure */
4603 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4605 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4606 SetLastError(ERROR_INVALID_FLAGS
);
4608 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4610 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4611 SetLastError(ERROR_INVALID_FLAGS
);
4613 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4614 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4615 SetLastError(ERROR_INVALID_USER_BUFFER
);
4618 /* FIXME: check Reserved field */
4625 /***********************************************************************
4626 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4629 SetupDiSetDeviceInstallParamsW(
4630 IN HDEVINFO DeviceInfoSet
,
4631 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4632 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4634 struct DeviceInfoSet
*list
;
4637 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4640 SetLastError(ERROR_INVALID_HANDLE
);
4641 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4642 SetLastError(ERROR_INVALID_HANDLE
);
4643 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4644 SetLastError(ERROR_INVALID_USER_BUFFER
);
4645 else if (!DeviceInstallParams
)
4646 SetLastError(ERROR_INVALID_PARAMETER
);
4647 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4648 SetLastError(ERROR_INVALID_USER_BUFFER
);
4649 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4651 PSP_DEVINSTALL_PARAMS_W Destination
;
4654 Destination
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4656 Destination
= &list
->InstallParams
;
4657 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4661 TRACE("Returning %d\n", ret
);
4665 /***********************************************************************
4666 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4669 SetupDiSetDeviceInstallParamsA(
4670 HDEVINFO DeviceInfoSet
,
4671 PSP_DEVINFO_DATA DeviceInfoData
,
4672 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4674 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4678 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4680 if (DeviceInstallParams
== NULL
)
4681 SetLastError(ERROR_INVALID_PARAMETER
);
4682 else if (DeviceInstallParams
->cbSize
< sizeof(SP_DEVINSTALL_PARAMS_A
))
4683 SetLastError(ERROR_INVALID_USER_BUFFER
);
4686 memcpy(&deviceInstallParamsW
, DeviceInstallParams
, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A
, DriverPath
));
4687 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4688 len
= MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, NULL
, 0);
4691 ERR("DrivePath is NULL\n");
4696 MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, deviceInstallParamsW
.DriverPath
, len
);
4697 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4701 TRACE("Returning %d\n", ret
);
4706 OpenHardwareProfileKey(
4709 IN DWORD samDesired
)
4711 HKEY hHWProfilesKey
= NULL
;
4712 HKEY hHWProfileKey
= NULL
;
4713 HKEY ret
= INVALID_HANDLE_VALUE
;
4716 rc
= RegOpenKeyExW(HKLM
,
4717 REGSTR_PATH_HWPROFILES
,
4721 if (rc
!= ERROR_SUCCESS
)
4728 rc
= RegOpenKeyExW(hHWProfilesKey
,
4737 snprintfW(subKey
, 4, InstanceKeyFormat
, HwProfile
);
4739 rc
= RegOpenKeyExW(hHWProfilesKey
,
4745 if (rc
!= ERROR_SUCCESS
)
4750 ret
= hHWProfileKey
;
4753 if (hHWProfilesKey
!= NULL
)
4754 RegCloseKey(hHWProfilesKey
);
4755 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4756 RegCloseKey(hHWProfileKey
);
4761 IsDeviceInfoInDeviceInfoSet(
4762 struct DeviceInfoSet
*deviceInfoSet
,
4763 struct DeviceInfo
*deviceInfo
)
4765 PLIST_ENTRY ListEntry
;
4767 ListEntry
= deviceInfoSet
->ListHead
.Flink
;
4768 while (ListEntry
!= &deviceInfoSet
->ListHead
)
4770 if (deviceInfo
== CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
))
4773 ListEntry
= ListEntry
->Flink
;
4779 /***********************************************************************
4780 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4783 SetupDiDeleteDeviceInfo(
4784 IN HDEVINFO DeviceInfoSet
,
4785 IN PSP_DEVINFO_DATA DeviceInfoData
)
4787 struct DeviceInfoSet
*deviceInfoSet
;
4788 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
;
4791 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4794 SetLastError(ERROR_INVALID_HANDLE
);
4795 else if ((deviceInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4796 SetLastError(ERROR_INVALID_HANDLE
);
4797 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4798 SetLastError(ERROR_INVALID_USER_BUFFER
);
4799 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet
, deviceInfo
))
4800 SetLastError(ERROR_INVALID_PARAMETER
);
4803 RemoveEntryList(&deviceInfo
->ListEntry
);
4804 DestroyDeviceInfo(deviceInfo
);
4812 /***********************************************************************
4813 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4816 SetupDiOpenDeviceInfoA(
4817 IN HDEVINFO DeviceInfoSet
,
4818 IN PCSTR DeviceInstanceId
,
4819 IN HWND hwndParent OPTIONAL
,
4821 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4823 LPWSTR DeviceInstanceIdW
= NULL
;
4826 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4828 DeviceInstanceIdW
= pSetupMultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4829 if (DeviceInstanceIdW
== NULL
)
4832 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4833 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4835 MyFree(DeviceInstanceIdW
);
4841 /***********************************************************************
4842 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4845 SetupDiOpenDeviceInfoW(
4846 IN HDEVINFO DeviceInfoSet
,
4847 IN PCWSTR DeviceInstanceId
,
4848 IN HWND hwndParent OPTIONAL
,
4850 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4852 struct DeviceInfoSet
*list
;
4853 HKEY hEnumKey
, hKey
= NULL
;
4857 TRACE("%p %s %p %lx %p\n",
4858 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
4859 hwndParent
, OpenFlags
, DeviceInfoData
);
4861 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4862 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4865 SetLastError(ERROR_INVALID_HANDLE
);
4866 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4867 SetLastError(ERROR_INVALID_HANDLE
);
4868 else if (!DeviceInstanceId
)
4869 SetLastError(ERROR_INVALID_PARAMETER
);
4870 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4872 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4873 SetLastError(ERROR_INVALID_FLAGS
);
4875 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4876 SetLastError(ERROR_INVALID_USER_BUFFER
);
4879 struct DeviceInfo
*deviceInfo
= NULL
;
4880 /* Search if device already exists in DeviceInfoSet.
4881 * If yes, return the existing element
4882 * If no, create a new element using information in registry
4884 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4885 while (ItemList
!= &list
->ListHead
)
4887 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
4888 if (!wcscmp(deviceInfo
->instanceId
, DeviceInstanceId
))
4891 ItemList
= ItemList
->Flink
;
4896 /* good one found */
4902 WCHAR szClassGuid
[MAX_GUID_STRING_LEN
];
4904 /* Open supposed registry key */
4907 REGSTR_PATH_SYSTEMENUM
,
4911 if (rc
!= ERROR_SUCCESS
)
4922 RegCloseKey(hEnumKey
);
4923 if (rc
!= ERROR_SUCCESS
)
4925 if (rc
== ERROR_FILE_NOT_FOUND
)
4926 rc
= ERROR_NO_SUCH_DEVINST
;
4931 ClassGUID
= GUID_NULL
;
4932 dwSize
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
4934 if (RegQueryValueExW(hKey
,
4935 REGSTR_VAL_CLASSGUID
,
4938 (LPBYTE
)szClassGuid
,
4939 &dwSize
) == ERROR_SUCCESS
)
4941 szClassGuid
[MAX_GUID_STRING_LEN
- 2] = UNICODE_NULL
;
4943 /* Convert a string to a ClassGuid */
4944 UuidFromStringW(&szClassGuid
[1], &ClassGUID
);
4947 if (!CreateDeviceInfo(list
, DeviceInstanceId
, &ClassGUID
, &deviceInfo
))
4950 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4955 if (ret
&& deviceInfo
&& DeviceInfoData
)
4957 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4958 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4959 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4970 /***********************************************************************
4971 * SetupDiGetSelectedDevice (SETUPAPI.@)
4974 SetupDiGetSelectedDevice(
4975 IN HDEVINFO DeviceInfoSet
,
4976 OUT PSP_DEVINFO_DATA DeviceInfoData
)
4978 struct DeviceInfoSet
*list
;
4981 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4984 SetLastError(ERROR_INVALID_HANDLE
);
4985 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4986 SetLastError(ERROR_INVALID_HANDLE
);
4987 else if (list
->SelectedDevice
== NULL
)
4988 SetLastError(ERROR_NO_DEVICE_SELECTED
);
4989 else if (!DeviceInfoData
)
4990 SetLastError(ERROR_INVALID_PARAMETER
);
4991 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4992 SetLastError(ERROR_INVALID_USER_BUFFER
);
4995 memcpy(&DeviceInfoData
->ClassGuid
,
4996 &list
->SelectedDevice
->ClassGuid
,
4998 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
4999 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
5003 TRACE("Returning %d\n", ret
);
5008 /***********************************************************************
5009 * SetupDiSetSelectedDevice (SETUPAPI.@)
5012 SetupDiSetSelectedDevice(
5013 IN HDEVINFO DeviceInfoSet
,
5014 IN PSP_DEVINFO_DATA DeviceInfoData
)
5016 struct DeviceInfoSet
*list
;
5019 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5022 SetLastError(ERROR_INVALID_HANDLE
);
5023 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5024 SetLastError(ERROR_INVALID_HANDLE
);
5025 else if (!DeviceInfoData
)
5026 SetLastError(ERROR_INVALID_PARAMETER
);
5027 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5028 SetLastError(ERROR_INVALID_USER_BUFFER
);
5029 else if (DeviceInfoData
->Reserved
== 0)
5030 SetLastError(ERROR_INVALID_USER_BUFFER
);
5033 list
->SelectedDevice
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5037 TRACE("Returning %d\n", ret
);
5042 /* Return the current hardware profile id, or -1 if error */
5044 SETUPAPI_GetCurrentHwProfile(
5045 IN HDEVINFO DeviceInfoSet
)
5048 DWORD dwRegType
, dwLength
;
5051 DWORD ret
= (DWORD
)-1;
5053 rc
= RegOpenKeyExW(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
5054 REGSTR_PATH_IDCONFIGDB
,
5058 if (rc
!= ERROR_SUCCESS
)
5064 dwLength
= sizeof(DWORD
);
5065 rc
= RegQueryValueExW(hKey
,
5066 REGSTR_VAL_CURRENTCONFIG
,
5069 (LPBYTE
)&hwProfile
, &dwLength
);
5070 if (rc
!= ERROR_SUCCESS
)
5075 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5077 SetLastError(ERROR_GEN_FAILURE
);
5092 IN HDEVINFO DeviceInfoSet
,
5093 IN PSP_DEVINFO_DATA DeviceInfoData
)
5096 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5097 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5100 cr
= CM_Enable_DevNode_Ex(deviceInfo
->dnDevInst
, 0, set
->hMachine
);
5101 if (cr
!= CR_SUCCESS
)
5103 SetLastError(GetErrorCodeFromCrCode(cr
));
5109 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5114 static BOOL
StopDevice(
5115 IN HDEVINFO DeviceInfoSet
,
5116 IN PSP_DEVINFO_DATA DeviceInfoData
)
5118 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5122 /***********************************************************************
5123 * SetupDiChangeState (SETUPAPI.@)
5127 IN HDEVINFO DeviceInfoSet
,
5128 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5130 PSP_PROPCHANGE_PARAMS PropChange
;
5131 HKEY hKey
= INVALID_HANDLE_VALUE
;
5132 LPCWSTR RegistryValueName
;
5133 DWORD dwConfigFlags
, dwLength
, dwRegType
;
5137 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5139 if (!DeviceInfoData
)
5140 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChangeParams
;
5142 PropChange
= ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChangeParams
;
5145 SetLastError(ERROR_INVALID_PARAMETER
);
5149 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
5150 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
5152 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
5154 switch (PropChange
->StateChange
)
5159 /* Enable/disable device in registry */
5160 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5161 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5162 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
5163 if (hKey
== INVALID_HANDLE_VALUE
)
5165 dwLength
= sizeof(DWORD
);
5166 rc
= RegQueryValueExW(
5171 (LPBYTE
)&dwConfigFlags
, &dwLength
);
5172 if (rc
== ERROR_FILE_NOT_FOUND
)
5174 else if (rc
!= ERROR_SUCCESS
)
5179 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5181 SetLastError(ERROR_GEN_FAILURE
);
5184 if (PropChange
->StateChange
== DICS_ENABLE
)
5185 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5187 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5188 rc
= RegSetValueExW(
5193 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
5194 if (rc
!= ERROR_SUCCESS
)
5200 /* Enable/disable device if needed */
5201 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
5202 || PropChange
->HwProfile
== 0
5203 || PropChange
->HwProfile
== SETUPAPI_GetCurrentHwProfile(DeviceInfoSet
))
5205 if (PropChange
->StateChange
== DICS_ENABLE
)
5206 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5208 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
5214 case DICS_PROPCHANGE
:
5216 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5221 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
5222 SetLastError(ERROR_NOT_SUPPORTED
);
5227 if (hKey
!= INVALID_HANDLE_VALUE
)
5230 TRACE("Returning %d\n", ret
);
5234 /***********************************************************************
5235 * SetupDiSelectDevice (SETUPAPI.@)
5238 SetupDiSelectDevice(
5239 IN HDEVINFO DeviceInfoSet
,
5240 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5242 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5243 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5248 /***********************************************************************
5249 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5252 SetupDiRegisterCoDeviceInstallers(
5253 IN HDEVINFO DeviceInfoSet
,
5254 IN PSP_DEVINFO_DATA DeviceInfoData
)
5256 BOOL ret
= FALSE
; /* Return value */
5258 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5261 SetLastError(ERROR_INVALID_PARAMETER
);
5262 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5263 SetLastError(ERROR_INVALID_HANDLE
);
5264 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5265 SetLastError(ERROR_INVALID_HANDLE
);
5266 else if (!DeviceInfoData
)
5267 SetLastError(ERROR_INVALID_PARAMETER
);
5268 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5269 SetLastError(ERROR_INVALID_USER_BUFFER
);
5272 SP_DEVINSTALL_PARAMS_W InstallParams
;
5273 struct DriverInfoElement
*SelectedDriver
;
5276 WCHAR SectionName
[MAX_PATH
];
5277 DWORD SectionNameLength
= 0;
5278 HKEY hKey
= INVALID_HANDLE_VALUE
;
5279 PVOID Context
= NULL
;
5281 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5282 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5286 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5287 if (SelectedDriver
== NULL
)
5289 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5293 /* Get .CoInstallers section name */
5294 Result
= SetupDiGetActualSectionToInstallW(
5295 SelectedDriver
->InfFileDetails
->hInf
,
5296 SelectedDriver
->Details
.SectionName
,
5297 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5298 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
5300 lstrcatW(SectionName
, DotCoInstallers
);
5302 /* Open/Create driver key information */
5303 #if _WIN32_WINNT >= 0x502
5304 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5306 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5308 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5309 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5310 if (hKey
== INVALID_HANDLE_VALUE
)
5313 /* Install .CoInstallers section */
5314 DoAction
= SPINST_REGISTRY
;
5315 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5317 DoAction
|= SPINST_FILES
;
5318 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5322 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5323 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5324 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5325 SetupDefaultQueueCallbackW
, Context
,
5326 DeviceInfoSet
, DeviceInfoData
);
5334 SetupTermDefaultQueueCallback(Context
);
5335 if (hKey
!= INVALID_HANDLE_VALUE
)
5339 TRACE("Returning %d\n", ret
);
5344 InfIsFromOEMLocation(
5346 OUT LPBOOL IsOEMLocation
)
5350 last
= strrchrW(FullName
, '\\');
5353 /* No directory specified */
5354 *IsOEMLocation
= FALSE
;
5361 Windir
= MyMalloc((MAX_PATH
+ 1 + strlenW(InfDirectory
)) * sizeof(WCHAR
));
5364 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5368 ret
= GetSystemWindowsDirectoryW(Windir
, MAX_PATH
);
5369 if (ret
== 0 || ret
> MAX_PATH
)
5372 SetLastError(ERROR_GEN_FAILURE
);
5375 if (*Windir
&& Windir
[strlenW(Windir
) - 1] != '\\')
5376 strcatW(Windir
, BackSlash
);
5377 strcatW(Windir
, InfDirectory
);
5379 if (strncmpiW(FullName
, Windir
, last
- FullName
) == 0)
5381 /* The path is %SYSTEMROOT%\Inf */
5382 *IsOEMLocation
= FALSE
;
5386 /* The file is in another place */
5387 *IsOEMLocation
= TRUE
;
5394 /***********************************************************************
5395 * SetupDiInstallDevice (SETUPAPI.@)
5398 SetupDiInstallDevice(
5399 IN HDEVINFO DeviceInfoSet
,
5400 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5402 SP_DEVINSTALL_PARAMS_W InstallParams
;
5403 struct DriverInfoElement
*SelectedDriver
;
5404 SYSTEMTIME DriverDate
;
5405 WCHAR SectionName
[MAX_PATH
];
5407 DWORD SectionNameLength
= 0;
5408 BOOL Result
= FALSE
;
5411 LPWSTR pSectionName
= NULL
;
5412 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5414 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5415 BOOL RebootRequired
= FALSE
;
5416 HKEY hKey
= INVALID_HANDLE_VALUE
;
5417 BOOL NeedtoCopyFile
;
5418 LARGE_INTEGER fullVersion
;
5420 PVOID Context
= NULL
;
5421 BOOL ret
= FALSE
; /* Return value */
5423 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5426 SetLastError(ERROR_INVALID_PARAMETER
);
5427 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5428 SetLastError(ERROR_INVALID_HANDLE
);
5429 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5430 SetLastError(ERROR_INVALID_HANDLE
);
5431 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5432 SetLastError(ERROR_INVALID_USER_BUFFER
);
5438 /* One parameter is bad */
5442 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5443 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5447 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5449 /* Set FAILEDINSTALL in ConfigFlags registry value */
5450 DWORD ConfigFlags
, regType
;
5451 Result
= SetupDiGetDeviceRegistryPropertyW(
5456 (PBYTE
)&ConfigFlags
,
5457 sizeof(ConfigFlags
),
5459 if (!Result
|| regType
!= REG_DWORD
)
5461 SetLastError(ERROR_GEN_FAILURE
);
5464 ConfigFlags
|= DNF_DISABLED
;
5465 Result
= SetupDiSetDeviceRegistryPropertyW(
5469 (PBYTE
)&ConfigFlags
,
5470 sizeof(ConfigFlags
));
5473 SetLastError(ERROR_GEN_FAILURE
);
5481 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5482 if (SelectedDriver
== NULL
)
5484 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5488 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5490 Result
= SetupDiGetActualSectionToInstallW(
5491 SelectedDriver
->InfFileDetails
->hInf
,
5492 SelectedDriver
->Details
.SectionName
,
5493 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5494 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
5496 pSectionName
= &SectionName
[strlenW(SectionName
)];
5498 /* Get information from [Version] section */
5499 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5501 /* Format ClassGuid to a string */
5502 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5504 RequiredSize
= lstrlenW(lpGuidString
);
5505 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5506 if (!lpFullGuidString
)
5508 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5511 lpFullGuidString
[0] = '{';
5512 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5513 lpFullGuidString
[RequiredSize
+ 1] = '}';
5514 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5516 /* Copy .inf file to Inf\ directory (if needed) */
5517 Result
= InfIsFromOEMLocation(SelectedDriver
->Details
.InfFileName
, &NeedtoCopyFile
);
5522 WCHAR NewFileName
[MAX_PATH
];
5523 struct InfFileDetails
*newInfFileDetails
;
5524 Result
= SetupCopyOEMInfW(
5525 SelectedDriver
->Details
.InfFileName
,
5528 SP_COPY_NOOVERWRITE
,
5529 NewFileName
, MAX_PATH
,
5532 if (!Result
&& GetLastError() != ERROR_FILE_EXISTS
)
5534 /* Create a new struct InfFileDetails, and set it to
5535 * SelectedDriver->InfFileDetails, to release use of
5536 * current InfFile */
5537 newInfFileDetails
= CreateInfFileDetails(NewFileName
);
5538 if (!newInfFileDetails
)
5540 DereferenceInfFile(SelectedDriver
->InfFileDetails
);
5541 SelectedDriver
->InfFileDetails
= newInfFileDetails
;
5542 strcpyW(SelectedDriver
->Details
.InfFileName
, NewFileName
);
5545 /* Open/Create driver key information */
5546 #if _WIN32_WINNT >= 0x502
5547 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5549 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5551 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5552 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5553 if (hKey
== INVALID_HANDLE_VALUE
)
5556 /* Install main section */
5558 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5559 DoAction
|= SPINST_REGISTRY
;
5560 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5562 DoAction
|= SPINST_FILES
;
5563 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5567 *pSectionName
= '\0';
5568 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5569 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5570 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5571 SetupDefaultQueueCallbackW
, Context
,
5572 DeviceInfoSet
, DeviceInfoData
);
5575 InstallParams
.Flags
|= DI_NOFILECOPY
;
5576 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5578 /* Write information to driver key */
5579 *pSectionName
= UNICODE_NULL
;
5580 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
5581 TRACE("Write information to driver key\n");
5582 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5583 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5584 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5585 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->InfFileDetails
->FileName
));
5586 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
5587 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
5588 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
5589 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
5590 sprintfW(Buffer
, DateFormat
, DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5591 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5592 if (rc
== ERROR_SUCCESS
)
5593 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5594 if (rc
== ERROR_SUCCESS
)
5595 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5596 if (rc
== ERROR_SUCCESS
)
5598 sprintfW(Buffer
, VersionFormat
, fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5599 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5601 if (rc
== ERROR_SUCCESS
)
5602 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->InfFileDetails
->FileName
, (strlenW(SelectedDriver
->InfFileDetails
->FileName
) + 1) * sizeof(WCHAR
));
5603 if (rc
== ERROR_SUCCESS
)
5604 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5605 if (rc
== ERROR_SUCCESS
)
5606 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFSECTIONEXT
, 0, REG_SZ
, (const BYTE
*)&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)], (strlenW(SectionName
) - strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5607 if (rc
== ERROR_SUCCESS
)
5608 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5609 if (rc
== ERROR_SUCCESS
)
5610 rc
= RegSetValueExW(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5611 if (rc
!= ERROR_SUCCESS
)
5617 hKey
= INVALID_HANDLE_VALUE
;
5619 /* FIXME: Process .LogConfigOverride section */
5621 /* Install .Services section */
5622 strcpyW(pSectionName
, DotServices
);
5623 Result
= SetupInstallServicesFromInfSectionExW(
5624 SelectedDriver
->InfFileDetails
->hInf
,
5633 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5634 RebootRequired
= TRUE
;
5636 /* Open device registry key */
5637 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5638 if (hKey
== INVALID_HANDLE_VALUE
)
5641 /* Install .HW section */
5643 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5644 DoAction
|= SPINST_REGISTRY
;
5645 strcpyW(pSectionName
, DotHW
);
5646 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5647 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5648 DoAction
, hKey
, NULL
, 0,
5650 DeviceInfoSet
, DeviceInfoData
);
5654 /* Write information to enum key */
5655 TRACE("Write information to enum key\n");
5656 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
5657 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
5658 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5659 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
5660 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
5661 if (rc
== ERROR_SUCCESS
)
5662 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5663 if (rc
== ERROR_SUCCESS
)
5664 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5665 if (rc
== ERROR_SUCCESS
)
5666 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5667 if (rc
!= ERROR_SUCCESS
)
5673 /* Start the device */
5674 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5675 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5680 /* End of installation */
5681 if (hKey
!= INVALID_HANDLE_VALUE
)
5684 RpcStringFreeW(&lpGuidString
);
5685 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
5687 SetupTermDefaultQueueCallback(Context
);
5688 TRACE("Returning %d\n", ret
);
5692 static HKEY
SETUPDI_OpenDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5694 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
5697 l
= RegOpenKeyExW(RootKey
, REGSTR_PATH_SYSTEMENUM
, 0, 0, &enumKey
);
5700 l
= RegOpenKeyExW(enumKey
, devInfo
->instanceId
, 0, samDesired
, &key
);
5701 RegCloseKey(enumKey
);
5708 static HKEY
SETUPDI_OpenDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5710 LPWSTR DriverKey
= NULL
;
5714 HKEY hEnumKey
= NULL
;
5716 HKEY key
= INVALID_HANDLE_VALUE
;
5718 hKey
= SETUPDI_OpenDevKey(RootKey
, devInfo
, KEY_QUERY_VALUE
);
5719 if (hKey
== INVALID_HANDLE_VALUE
)
5721 /* Read the 'Driver' key */
5722 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5723 if (rc
!= ERROR_SUCCESS
)
5728 else if (dwRegType
!= REG_SZ
)
5730 SetLastError(ERROR_GEN_FAILURE
);
5733 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5736 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5739 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5740 if (rc
!= ERROR_SUCCESS
)
5747 /* Need to open the driver key */
5750 REGSTR_PATH_CLASS_NT
,
5754 if (rc
!= ERROR_SUCCESS
)
5765 if (rc
!= ERROR_SUCCESS
)
5773 if (hEnumKey
!= NULL
)
5774 RegCloseKey(hEnumKey
);
5775 if (hKey
!= NULL
&& hKey
!= key
)
5780 /***********************************************************************
5781 * SetupDiOpenDevRegKey (SETUPAPI.@)
5783 HKEY WINAPI
SetupDiOpenDevRegKey(
5784 HDEVINFO DeviceInfoSet
,
5785 PSP_DEVINFO_DATA DeviceInfoData
,
5791 struct DeviceInfoSet
*set
= DeviceInfoSet
;
5792 struct DeviceInfo
*devInfo
;
5793 HKEY key
= INVALID_HANDLE_VALUE
;
5796 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet
, DeviceInfoData
,
5797 Scope
, HwProfile
, KeyType
, samDesired
);
5799 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5801 SetLastError(ERROR_INVALID_HANDLE
);
5802 return INVALID_HANDLE_VALUE
;
5804 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5806 SetLastError(ERROR_INVALID_HANDLE
);
5807 return INVALID_HANDLE_VALUE
;
5809 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5810 || !DeviceInfoData
->Reserved
)
5812 SetLastError(ERROR_INVALID_PARAMETER
);
5813 return INVALID_HANDLE_VALUE
;
5815 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5817 SetLastError(ERROR_INVALID_FLAGS
);
5818 return INVALID_HANDLE_VALUE
;
5820 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
5822 SetLastError(ERROR_INVALID_FLAGS
);
5823 return INVALID_HANDLE_VALUE
;
5825 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5826 if (devInfo
->set
!= set
)
5828 SetLastError(ERROR_INVALID_PARAMETER
);
5829 return INVALID_HANDLE_VALUE
;
5831 if (Scope
!= DICS_FLAG_GLOBAL
)
5833 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5834 if (RootKey
== INVALID_HANDLE_VALUE
)
5835 return INVALID_HANDLE_VALUE
;
5838 RootKey
= set
->HKLM
;
5842 key
= SETUPDI_OpenDevKey(RootKey
, devInfo
, samDesired
);
5845 key
= SETUPDI_OpenDrvKey(RootKey
, devInfo
, samDesired
);
5848 WARN("unknown KeyType %d\n", KeyType
);
5850 if (RootKey
!= set
->HKLM
)
5851 RegCloseKey(RootKey
);
5855 static BOOL
SETUPDI_DeleteDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5861 static BOOL
SETUPDI_DeleteDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5867 /***********************************************************************
5868 * SetupDiDeleteDevRegKey (SETUPAPI.@)
5870 BOOL WINAPI
SetupDiDeleteDevRegKey(
5871 HDEVINFO DeviceInfoSet
,
5872 PSP_DEVINFO_DATA DeviceInfoData
,
5877 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5878 struct DeviceInfo
*devInfo
;
5882 TRACE("%p %p %d %d %d\n", DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
,
5885 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5887 SetLastError(ERROR_INVALID_HANDLE
);
5890 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5892 SetLastError(ERROR_INVALID_HANDLE
);
5895 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5896 || !DeviceInfoData
->Reserved
)
5898 SetLastError(ERROR_INVALID_PARAMETER
);
5901 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5903 SetLastError(ERROR_INVALID_FLAGS
);
5906 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
&& KeyType
!= DIREG_BOTH
)
5908 SetLastError(ERROR_INVALID_FLAGS
);
5911 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5912 if (devInfo
->set
!= set
)
5914 SetLastError(ERROR_INVALID_PARAMETER
);
5917 if (Scope
!= DICS_FLAG_GLOBAL
)
5919 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5920 if (RootKey
== INVALID_HANDLE_VALUE
)
5924 RootKey
= set
->HKLM
;
5928 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
5931 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
5934 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
5936 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
5939 WARN("unknown KeyType %d\n", KeyType
);
5941 if (RootKey
!= set
->HKLM
)
5942 RegCloseKey(RootKey
);