2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "setupapi_private.h"
24 /* Unicode constants */
25 static const WCHAR BackSlash
[] = {'\\',0};
26 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
27 static const WCHAR Class
[] = {'C','l','a','s','s',0};
28 static const WCHAR DateFormat
[] = {'%','u','-','%','u','-','%','u',0};
29 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
30 static const WCHAR DotHW
[] = {'.','H','W',0};
31 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
32 static const WCHAR InfDirectory
[] = {'i','n','f','\\',0};
33 static const WCHAR InstanceKeyFormat
[] = {'%','0','4','l','u',0};
34 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
35 static const WCHAR VersionFormat
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
37 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
38 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
39 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
40 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
41 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT
[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
44 (CALLBACK
* CLASS_INSTALL_PROC
) (
45 IN DI_FUNCTION InstallFunction
,
46 IN HDEVINFO DeviceInfoSet
,
47 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
49 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
50 IN HDEVINFO DeviceInfoSet
,
51 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
53 (CALLBACK
* COINSTALLER_PROC
) (
54 IN DI_FUNCTION InstallFunction
,
55 IN HDEVINFO DeviceInfoSet
,
56 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
57 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
59 struct CoInstallerElement
64 COINSTALLER_PROC Function
;
65 BOOL DoPostProcessing
;
69 struct GetSectionCallbackInfo
71 PSP_ALTPLATFORM_INFO PlatformInfo
;
75 WCHAR BestSection
[LINE_LEN
+ 1];
76 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
81 static void SETUPDI_GuidToString(const GUID
*guid
, LPWSTR guidStr
)
83 static const WCHAR fmt
[] = {'{','%','0','8','X','-','%','0','4','X','-',
84 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
85 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
88 sprintfW(guidStr
, fmt
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
89 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
90 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
94 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
98 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
99 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
100 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
101 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
102 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
103 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
104 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
105 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
106 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
107 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
108 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
109 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
110 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
111 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
112 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
113 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
114 case CR_ALREADY_SUCH_DEVINST
: return ERROR_DEVINST_ALREADY_EXISTS
;
115 case CR_SUCCESS
: return ERROR_SUCCESS
;
116 default: return ERROR_GEN_FAILURE
;
119 /* Does not happen */
122 /* Lower scores are best ones */
125 IN LPCWSTR SectionName
,
126 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
129 OUT PDWORD ScorePlatform
,
130 OUT PDWORD ScoreMajorVersion
,
131 OUT PDWORD ScoreMinorVersion
,
132 OUT PDWORD ScoreProductType
,
133 OUT PDWORD ScoreSuiteMask
)
135 LPWSTR Section
= NULL
;
136 //LPCWSTR pExtensionPlatform;
137 LPCWSTR pExtensionArchitecture
;
142 //static const WCHAR ExtensionPlatformNone[] = {'.',0};
143 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
144 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
146 static const WCHAR ExtensionArchitectureNone
[] = {0};
147 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
148 static const WCHAR ExtensionArchitectureamd64
[] = {'A','M','D','6','4',0};
149 static const WCHAR ExtensionArchitectureia64
[] = {'I','A','6','4',0};
150 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
151 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
152 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
154 TRACE("%s %p 0x%x 0x%x\n",
155 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
157 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
159 Section
= pSetupDuplicateString(SectionName
);
162 TRACE("pSetupDuplicateString() failed\n");
166 /* Set various extensions values */
167 switch (PlatformInfo
->Platform
)
169 case VER_PLATFORM_WIN32_WINDOWS
:
170 //pExtensionPlatform = ExtensionPlatformWindows;
172 case VER_PLATFORM_WIN32_NT
:
173 //pExtensionPlatform = ExtensionPlatformNT;
176 ERR("Unknown platform 0x%lx\n", PlatformInfo
->Platform
);
177 //pExtensionPlatform = ExtensionPlatformNone;
180 switch (PlatformInfo
->ProcessorArchitecture
)
182 case PROCESSOR_ARCHITECTURE_ALPHA
:
183 pExtensionArchitecture
= ExtensionArchitecturealpha
;
185 case PROCESSOR_ARCHITECTURE_AMD64
:
186 pExtensionArchitecture
= ExtensionArchitectureamd64
;
188 case PROCESSOR_ARCHITECTURE_IA64
:
189 pExtensionArchitecture
= ExtensionArchitectureia64
;
191 case PROCESSOR_ARCHITECTURE_INTEL
:
192 pExtensionArchitecture
= ExtensionArchitecturex86
;
194 case PROCESSOR_ARCHITECTURE_MIPS
:
195 pExtensionArchitecture
= ExtensionArchitecturemips
;
197 case PROCESSOR_ARCHITECTURE_PPC
:
198 pExtensionArchitecture
= ExtensionArchitectureppc
;
201 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
202 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
203 pExtensionArchitecture
= ExtensionArchitectureNone
;
209 * Field[1] Architecture
210 * Field[2] Major version
211 * Field[3] Minor version
212 * Field[4] Product type
213 * Field[5] Suite mask
214 * Remark: these fields may be NULL if the information is not provided
217 if (Fields
[0] == NULL
)
219 TRACE("No extension found\n");
220 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
224 Fields
[1] = Fields
[0] + 1;
225 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
226 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
228 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
232 *(Fields
[i
] - 1) = UNICODE_NULL
;
235 /* Take care of first 2 fields */
236 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
238 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
240 TRACE("Mismatch on platform field\n");
243 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
245 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
247 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
249 TRACE("Mismatch on platform field\n");
252 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
256 /* No platform specified */
257 *ScorePlatform
|= 0x02;
259 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
261 /* No architecture specified */
262 *ScorePlatform
|= 0x01;
264 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
266 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
267 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
271 /* Check if informations are matching */
272 if (Fields
[2] && *Fields
[2])
274 DWORD MajorVersion
, MinorVersion
= 0;
275 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
276 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
277 (errno
== ERANGE
|| errno
== EINVAL
))
279 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
282 if (Fields
[3] && *Fields
[3])
284 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
285 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
286 (errno
== ERANGE
|| errno
== EINVAL
))
288 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
292 if (PlatformInfo
->MajorVersion
< MajorVersion
||
293 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
295 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
296 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
299 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
300 if (MajorVersion
== PlatformInfo
->MajorVersion
)
301 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
303 *ScoreMinorVersion
= MinorVersion
;
305 else if (Fields
[3] && *Fields
[3])
307 TRACE("Minor version found without major version\n");
312 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
313 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
316 if (Fields
[4] && *Fields
[4])
318 DWORD CurrentProductType
;
319 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
320 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
321 (errno
== ERANGE
|| errno
== EINVAL
))
323 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
326 if (CurrentProductType
!= ProductType
)
328 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
329 CurrentProductType
, ProductType
);
334 *ScoreProductType
= 1;
336 if (Fields
[5] && *Fields
[5])
338 DWORD CurrentSuiteMask
;
339 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
340 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
341 (errno
== ERANGE
|| errno
== EINVAL
))
343 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
346 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
348 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
349 CurrentSuiteMask
, SuiteMask
);
352 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
355 *ScoreSuiteMask
= SuiteMask
;
366 IN LPCWSTR SectionName
,
369 struct GetSectionCallbackInfo
*info
= Context
;
370 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
373 if (SectionName
[info
->PrefixLength
] != '.')
376 ret
= CheckSectionValid(
377 &SectionName
[info
->PrefixLength
],
381 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
384 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
387 if (Score1
> info
->BestScore1
) goto done
;
388 if (Score1
< info
->BestScore1
) goto bettersection
;
389 if (Score2
> info
->BestScore2
) goto done
;
390 if (Score2
< info
->BestScore2
) goto bettersection
;
391 if (Score3
> info
->BestScore3
) goto done
;
392 if (Score3
< info
->BestScore3
) goto bettersection
;
393 if (Score4
> info
->BestScore4
) goto done
;
394 if (Score4
< info
->BestScore4
) goto bettersection
;
395 if (Score5
> info
->BestScore5
) goto done
;
396 if (Score5
< info
->BestScore5
) goto bettersection
;
400 strcpyW(info
->BestSection
, SectionName
);
401 info
->BestScore1
= Score1
;
402 info
->BestScore2
= Score2
;
403 info
->BestScore3
= Score3
;
404 info
->BestScore4
= Score4
;
405 info
->BestScore5
= Score5
;
411 /***********************************************************************
412 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
415 SetupDiGetActualSectionToInstallExW(
417 IN PCWSTR InfSectionName
,
418 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
419 OUT PWSTR InfSectionWithExt OPTIONAL
,
420 IN DWORD InfSectionWithExtSize
,
421 OUT PDWORD RequiredSize OPTIONAL
,
422 OUT PWSTR
* Extension OPTIONAL
,
427 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
428 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
429 RequiredSize
, Extension
, Reserved
);
431 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
432 SetLastError(ERROR_INVALID_HANDLE
);
433 else if (!InfSectionName
)
434 SetLastError(ERROR_INVALID_PARAMETER
);
435 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
436 SetLastError(ERROR_INVALID_USER_BUFFER
);
437 else if (Reserved
!= NULL
)
438 SetLastError(ERROR_INVALID_PARAMETER
);
441 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
442 static BYTE CurrentProductType
= 0;
443 static WORD CurrentSuiteMask
= 0;
444 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
445 struct GetSectionCallbackInfo CallbackInfo
;
450 /* Fill platform info if needed */
451 if (AlternatePlatformInfo
)
453 pPlatformInfo
= AlternatePlatformInfo
;
459 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
461 /* That's the first time we go here. We need to fill in the structure */
462 OSVERSIONINFOEX VersionInfo
;
463 SYSTEM_INFO SystemInfo
;
464 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
465 ret
= GetVersionExW((OSVERSIONINFO
*)&VersionInfo
);
468 GetSystemInfo(&SystemInfo
);
469 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
470 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
471 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
472 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
473 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
474 CurrentPlatform
.Reserved
= 0;
475 CurrentProductType
= VersionInfo
.wProductType
;
476 CurrentSuiteMask
= VersionInfo
.wSuiteMask
;
478 ProductType
= CurrentProductType
;
479 SuiteMask
= CurrentSuiteMask
;
482 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
483 CallbackInfo
.ProductType
= ProductType
;
484 CallbackInfo
.SuiteMask
= SuiteMask
;
485 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
486 CallbackInfo
.BestScore1
= ULONG_MAX
;
487 CallbackInfo
.BestScore2
= ULONG_MAX
;
488 CallbackInfo
.BestScore3
= ULONG_MAX
;
489 CallbackInfo
.BestScore4
= ULONG_MAX
;
490 CallbackInfo
.BestScore5
= ULONG_MAX
;
491 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
492 if (!EnumerateSectionsStartingWith(
498 SetLastError(ERROR_GEN_FAILURE
);
502 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
503 if (RequiredSize
!= NULL
)
504 *RequiredSize
= dwFullLength
+ 1;
506 if (InfSectionWithExtSize
> 0)
508 if (InfSectionWithExtSize
< dwFullLength
+ 1)
510 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
513 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
516 DWORD dwLength
= lstrlenW(InfSectionName
);
517 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
525 TRACE("Returning %d\n", ret
);
532 IN
struct DeviceInfoSet
*list
,
533 IN LPCWSTR InstancePath
,
534 IN LPCGUID pClassGuid
,
535 OUT
struct DeviceInfo
**pDeviceInfo
)
539 struct DeviceInfo
*deviceInfo
;
543 size
= FIELD_OFFSET(struct DeviceInfo
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
544 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
547 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
550 ZeroMemory(deviceInfo
, size
);
552 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
553 if (cr
!= CR_SUCCESS
)
555 SetLastError(GetErrorCodeFromCrCode(cr
));
559 deviceInfo
->set
= list
;
560 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
561 strcpyW(deviceInfo
->Data
, InstancePath
);
562 deviceInfo
->instanceId
= deviceInfo
->Data
;
563 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
564 deviceInfo
->DeviceDescription
= NULL
;
565 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
566 deviceInfo
->CreationFlags
= 0;
567 InitializeListHead(&deviceInfo
->DriverListHead
);
568 InitializeListHead(&deviceInfo
->InterfaceListHead
);
570 *pDeviceInfo
= deviceInfo
;
576 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
578 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
579 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
584 DestroyDeviceInfo(struct DeviceInfo
*deviceInfo
)
586 PLIST_ENTRY ListEntry
;
587 struct DriverInfoElement
*driverInfo
;
588 struct DeviceInterface
*deviceInterface
;
590 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
592 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
593 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
594 if (!DestroyDriverInfoElement(driverInfo
))
597 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
599 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
600 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
601 if (!DestroyDeviceInterface(deviceInterface
))
604 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
605 if (deviceInfo
->hmodDevicePropPageProvider
)
606 FreeLibrary(deviceInfo
->hmodDevicePropPageProvider
);
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 if (list
->hmodClassPropPageProvider
)
628 FreeLibrary(list
->hmodClassPropPageProvider
);
629 return HeapFree(GetProcessHeap(), 0, list
);
632 /***********************************************************************
633 * SetupDiBuildClassInfoList (SETUPAPI.@)
635 * Returns a list of setup class GUIDs that identify the classes
636 * that are installed on a local machine.
639 * Flags [I] control exclusion of classes from the list.
640 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
641 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
642 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
648 BOOL WINAPI
SetupDiBuildClassInfoList(
650 LPGUID ClassGuidList
,
651 DWORD ClassGuidListSize
,
655 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
656 ClassGuidListSize
, RequiredSize
,
660 /***********************************************************************
661 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
663 * Returns a list of setup class GUIDs that identify the classes
664 * that are installed on a local or remote machine.
667 * Flags [I] control exclusion of classes from the list.
668 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
669 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
670 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
671 * MachineName [I] name of a remote machine.
672 * Reserved [I] must be NULL.
678 BOOL WINAPI
SetupDiBuildClassInfoListExA(
680 LPGUID ClassGuidList
,
681 DWORD ClassGuidListSize
,
686 LPWSTR MachineNameW
= NULL
;
689 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
690 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
694 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
695 if (MachineNameW
== NULL
) return FALSE
;
698 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
699 ClassGuidListSize
, RequiredSize
,
700 MachineNameW
, Reserved
);
702 MyFree(MachineNameW
);
707 /***********************************************************************
708 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
710 * Returns a list of setup class GUIDs that identify the classes
711 * that are installed on a local or remote machine.
714 * Flags [I] control exclusion of classes from the list.
715 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
716 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
717 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
718 * MachineName [I] name of a remote machine.
719 * Reserved [I] must be NULL.
725 BOOL WINAPI
SetupDiBuildClassInfoListExW(
727 LPGUID ClassGuidList
,
728 DWORD ClassGuidListSize
,
734 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
739 DWORD dwGuidListIndex
= 0;
741 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
742 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
746 SetLastError(ERROR_INVALID_PARAMETER
);
749 else if (!ClassGuidList
&& ClassGuidListSize
> 0)
751 SetLastError(ERROR_INVALID_PARAMETER
);
755 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
756 KEY_ENUMERATE_SUB_KEYS
,
760 if (hClassesKey
== INVALID_HANDLE_VALUE
)
765 for (dwIndex
= 0; ; dwIndex
++)
768 lError
= RegEnumKeyExW(hClassesKey
,
776 TRACE("RegEnumKeyExW() returns %d\n", lError
);
777 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
779 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
781 if (RegOpenKeyExW(hClassesKey
,
787 RegCloseKey(hClassesKey
);
791 if (!RegQueryValueExW(hClassKey
,
792 REGSTR_VAL_NOUSECLASS
,
798 TRACE("'NoUseClass' value found!\n");
799 RegCloseKey(hClassKey
);
803 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
804 (!RegQueryValueExW(hClassKey
,
805 REGSTR_VAL_NOINSTALLCLASS
,
811 TRACE("'NoInstallClass' value found!\n");
812 RegCloseKey(hClassKey
);
816 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
817 (!RegQueryValueExW(hClassKey
,
818 REGSTR_VAL_NODISPLAYCLASS
,
824 TRACE("'NoDisplayClass' value found!\n");
825 RegCloseKey(hClassKey
);
829 RegCloseKey(hClassKey
);
831 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
832 if (dwGuidListIndex
< ClassGuidListSize
)
834 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
838 TRACE("Guid: %p\n", &szKeyName
[1]);
840 UuidFromStringW(&szKeyName
[1],
841 &ClassGuidList
[dwGuidListIndex
]);
847 if (lError
!= ERROR_SUCCESS
)
851 RegCloseKey(hClassesKey
);
853 if (RequiredSize
!= NULL
)
854 *RequiredSize
= dwGuidListIndex
;
856 if (ClassGuidListSize
< dwGuidListIndex
)
858 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
865 /***********************************************************************
866 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
868 BOOL WINAPI
SetupDiClassGuidsFromNameA(
870 LPGUID ClassGuidList
,
871 DWORD ClassGuidListSize
,
874 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
875 ClassGuidListSize
, RequiredSize
,
879 /***********************************************************************
880 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
882 BOOL WINAPI
SetupDiClassGuidsFromNameW(
884 LPGUID ClassGuidList
,
885 DWORD ClassGuidListSize
,
888 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
889 ClassGuidListSize
, RequiredSize
,
893 /***********************************************************************
894 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
896 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
898 LPGUID ClassGuidList
,
899 DWORD ClassGuidListSize
,
904 LPWSTR ClassNameW
= NULL
;
905 LPWSTR MachineNameW
= NULL
;
908 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName
), ClassGuidList
,
909 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
913 SetLastError(ERROR_INVALID_PARAMETER
);
917 ClassNameW
= pSetupMultiByteToUnicode(ClassName
, CP_ACP
);
918 if (ClassNameW
== NULL
)
923 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
924 if (MachineNameW
== NULL
)
931 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
932 ClassGuidListSize
, RequiredSize
,
933 MachineNameW
, Reserved
);
935 MyFree(MachineNameW
);
941 /***********************************************************************
942 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
944 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
946 LPGUID ClassGuidList
,
947 DWORD ClassGuidListSize
,
953 WCHAR szClassName
[MAX_CLASS_NAME_LEN
];
959 DWORD dwGuidListIndex
= 0;
961 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
962 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
964 if (!ClassName
|| !RequiredSize
)
966 SetLastError(ERROR_INVALID_PARAMETER
);
969 if (!ClassGuidList
&& ClassGuidListSize
> 0)
971 SetLastError(ERROR_INVALID_PARAMETER
);
976 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
977 KEY_ENUMERATE_SUB_KEYS
,
981 if (hClassesKey
== INVALID_HANDLE_VALUE
)
986 for (dwIndex
= 0; ; dwIndex
++)
989 lError
= RegEnumKeyExW(hClassesKey
,
997 TRACE("RegEnumKeyExW() returns %d\n", lError
);
998 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
1000 TRACE("Key name: %p\n", szKeyName
);
1002 if (RegOpenKeyExW(hClassesKey
,
1008 RegCloseKey(hClassesKey
);
1012 dwLength
= MAX_CLASS_NAME_LEN
* sizeof(WCHAR
);
1013 if (!RegQueryValueExW(hClassKey
,
1017 (LPBYTE
)szClassName
,
1020 TRACE("Class name: %p\n", szClassName
);
1022 if (strcmpiW(szClassName
, ClassName
) == 0)
1024 TRACE("Found matching class name\n");
1026 TRACE("Guid: %p\n", szKeyName
);
1027 if (dwGuidListIndex
< ClassGuidListSize
)
1029 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
1033 TRACE("Guid: %p\n", &szKeyName
[1]);
1035 UuidFromStringW(&szKeyName
[1],
1036 &ClassGuidList
[dwGuidListIndex
]);
1043 RegCloseKey(hClassKey
);
1046 if (lError
!= ERROR_SUCCESS
)
1050 RegCloseKey(hClassesKey
);
1052 if (RequiredSize
!= NULL
)
1053 *RequiredSize
= dwGuidListIndex
;
1055 if (ClassGuidListSize
< dwGuidListIndex
)
1057 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1064 /***********************************************************************
1065 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1067 BOOL WINAPI
SetupDiClassNameFromGuidA(
1068 const GUID
* ClassGuid
,
1070 DWORD ClassNameSize
,
1071 PDWORD RequiredSize
)
1073 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
1074 ClassNameSize
, RequiredSize
,
1078 /***********************************************************************
1079 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1081 BOOL WINAPI
SetupDiClassNameFromGuidW(
1082 const GUID
* ClassGuid
,
1084 DWORD ClassNameSize
,
1085 PDWORD RequiredSize
)
1087 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
1088 ClassNameSize
, RequiredSize
,
1092 /***********************************************************************
1093 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1095 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1096 const GUID
* ClassGuid
,
1098 DWORD ClassNameSize
,
1099 PDWORD RequiredSize
,
1103 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1104 LPWSTR MachineNameW
= NULL
;
1108 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1109 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1110 RequiredSize
, MachineNameW
, Reserved
);
1113 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1114 ClassNameSize
, NULL
, NULL
);
1115 if (len
== 0 || len
> ClassNameSize
)
1117 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1121 MyFree(MachineNameW
);
1125 /***********************************************************************
1126 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1128 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1129 const GUID
* ClassGuid
,
1131 DWORD ClassNameSize
,
1132 PDWORD RequiredSize
,
1142 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
1143 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1145 /* Make sure there's a GUID */
1146 if (ClassGuid
== NULL
)
1148 SetLastError(ERROR_INVALID_CLASS
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1152 /* Make sure there's a real buffer when there's a size */
1153 if ((ClassNameSize
> 0) && (ClassName
== NULL
))
1155 SetLastError(ERROR_INVALID_PARAMETER
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1159 /* Open the key for the GUID */
1160 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INSTALLER
, MachineName
, Reserved
);
1162 if (hKey
== INVALID_HANDLE_VALUE
)
1165 /* Retrieve the class name data and close the key */
1166 rc
= QueryRegistryValue(hKey
, Class
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
1169 /* Make sure we got the data */
1170 if (rc
!= ERROR_SUCCESS
)
1176 /* Make sure the data is a string */
1177 if (dwRegType
!= REG_SZ
)
1180 SetLastError(ERROR_GEN_FAILURE
);
1184 /* Determine the length of the class name */
1185 dwLength
/= sizeof(WCHAR
);
1187 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
1188 /* Count the null-terminator */
1191 /* Inform the caller about the class name */
1192 if ((ClassName
!= NULL
) && (dwLength
<= ClassNameSize
))
1194 memcpy(ClassName
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
1195 ClassName
[dwLength
- 1] = UNICODE_NULL
;
1198 /* Inform the caller about the required size */
1199 if (RequiredSize
!= NULL
)
1200 *RequiredSize
= dwLength
;
1202 /* Clean up the buffer */
1205 /* Make sure the buffer was large enough */
1206 if ((ClassName
== NULL
) || (dwLength
> ClassNameSize
))
1208 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1215 /***********************************************************************
1216 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1219 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1222 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1225 /***********************************************************************
1226 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1229 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1234 LPWSTR MachineNameW
= NULL
;
1237 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1238 debugstr_a(MachineName
), Reserved
);
1242 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1243 if (MachineNameW
== NULL
)
1244 return INVALID_HANDLE_VALUE
;
1247 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1248 MachineNameW
, Reserved
);
1250 MyFree(MachineNameW
);
1255 /***********************************************************************
1256 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1258 * Create an empty DeviceInfoSet list.
1261 * ClassGuid [I] if not NULL only devices with GUID ClassGuid are associated
1263 * hwndParent [I] hwnd needed for interface related actions.
1264 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1265 * local registry will be used.
1266 * Reserved [I] must be NULL
1269 * Success: empty list.
1270 * Failure: INVALID_HANDLE_VALUE.
1273 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1278 struct DeviceInfoSet
*list
= NULL
;
1279 DWORD size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
1282 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1284 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1285 debugstr_w(MachineName
), Reserved
);
1287 if (MachineName
!= NULL
)
1289 SIZE_T len
= strlenW(MachineName
);
1290 if (len
>= SP_MAX_MACHINENAME_LENGTH
- 4)
1292 SetLastError(ERROR_INVALID_MACHINENAME
);
1296 size
+= (len
+ 3) * sizeof(WCHAR
);
1301 if (Reserved
!= NULL
)
1303 SetLastError(ERROR_INVALID_PARAMETER
);
1304 return INVALID_HANDLE_VALUE
;
1307 list
= MyMalloc(size
);
1310 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1311 return INVALID_HANDLE_VALUE
;
1313 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
1315 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1316 memcpy(&list
->ClassGuid
,
1317 ClassGuid
? ClassGuid
: &GUID_NULL
,
1318 sizeof(list
->ClassGuid
));
1319 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1320 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1321 list
->InstallParams
.hwndParent
= hwndParent
;
1324 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
1325 if (rc
!= ERROR_SUCCESS
)
1327 SetLastError(ERROR_INVALID_MACHINENAME
);
1331 list
->szData
[0] = list
->szData
[1] = '\\';
1332 strcpyW(list
->szData
+ 2, MachineName
);
1333 list
->MachineName
= list
->szData
;
1337 list
->HKLM
= HKEY_LOCAL_MACHINE
;
1338 list
->MachineName
= NULL
;
1340 cr
= CM_Connect_MachineW(list
->MachineName
, &list
->hMachine
);
1341 if (cr
!= CR_SUCCESS
)
1343 SetLastError(GetErrorCodeFromCrCode(cr
));
1346 InitializeListHead(&list
->DriverListHead
);
1347 InitializeListHead(&list
->ListHead
);
1349 return (HDEVINFO
)list
;
1352 if (ret
== INVALID_HANDLE_VALUE
)
1356 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1357 RegCloseKey(list
->HKLM
);
1364 /***********************************************************************
1365 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1367 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1368 HDEVINFO DeviceInfoSet
,
1369 PSP_DEVINFO_DATA DeviceInfoData
,
1374 PCSTR InfSectionName
)
1376 PWSTR InfSectionNameW
= NULL
;
1379 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1380 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1384 if (!InfSectionName
)
1386 SetLastError(ERROR_INVALID_PARAMETER
);
1387 return INVALID_HANDLE_VALUE
;
1391 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
1392 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1395 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1396 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1397 MyFree(InfSectionNameW
);
1402 OpenHardwareProfileKey(
1405 IN DWORD samDesired
);
1407 /***********************************************************************
1408 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1410 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1411 HDEVINFO DeviceInfoSet
,
1412 PSP_DEVINFO_DATA DeviceInfoData
,
1417 PCWSTR InfSectionName
)
1419 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1420 HKEY key
= INVALID_HANDLE_VALUE
;
1421 LPWSTR lpGuidString
= NULL
;
1422 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
1423 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
1424 DWORD Index
; /* Index used in the DriverKey name */
1428 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
1429 HKEY hEnumKey
= NULL
;
1430 HKEY hClassKey
= NULL
;
1431 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
1435 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1436 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1438 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1440 SetLastError(ERROR_INVALID_HANDLE
);
1441 return INVALID_HANDLE_VALUE
;
1443 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1445 SetLastError(ERROR_INVALID_HANDLE
);
1446 return INVALID_HANDLE_VALUE
;
1448 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1449 || !DeviceInfoData
->Reserved
)
1451 SetLastError(ERROR_INVALID_PARAMETER
);
1452 return INVALID_HANDLE_VALUE
;
1454 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1456 SetLastError(ERROR_INVALID_FLAGS
);
1457 return INVALID_HANDLE_VALUE
;
1459 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1461 SetLastError(ERROR_INVALID_FLAGS
);
1462 return INVALID_HANDLE_VALUE
;
1464 if (InfHandle
&& !InfSectionName
)
1466 SetLastError(ERROR_INVALID_PARAMETER
);
1467 return INVALID_HANDLE_VALUE
;
1469 if (!InfHandle
&& InfSectionName
)
1471 SetLastError(ERROR_INVALID_PARAMETER
);
1472 return INVALID_HANDLE_VALUE
;
1475 if (Scope
== DICS_FLAG_GLOBAL
)
1476 RootKey
= set
->HKLM
;
1477 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1479 hHWProfileKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
1480 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
1482 RootKey
= hHWProfileKey
;
1485 if (KeyType
== DIREG_DEV
)
1487 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1489 rc
= RegCreateKeyExW(
1491 REGSTR_PATH_SYSTEMENUM
,
1494 REG_OPTION_NON_VOLATILE
,
1499 if (rc
!= ERROR_SUCCESS
)
1504 rc
= RegCreateKeyExW(
1506 deviceInfo
->instanceId
,
1509 REG_OPTION_NON_VOLATILE
,
1510 #if _WIN32_WINNT >= 0x502
1511 KEY_READ
| KEY_WRITE
,
1518 if (rc
!= ERROR_SUCCESS
)
1524 else /* KeyType == DIREG_DRV */
1526 /* Open device key, to read Driver value */
1527 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1528 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
1531 rc
= RegOpenKeyExW(RootKey
, REGSTR_PATH_CLASS_NT
, 0, KEY_CREATE_SUB_KEY
, &hClassKey
);
1532 if (rc
!= ERROR_SUCCESS
)
1538 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, NULL
, &dwSize
);
1539 if (rc
!= ERROR_SUCCESS
)
1541 /* Create a new driver key */
1543 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
1546 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1547 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
1550 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1555 strcpyW(&DriverKey
[1], lpGuidString
);
1556 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
1557 *pDeviceInstance
++ = '}';
1558 *pDeviceInstance
++ = '\\';
1560 /* Try all values for Index between 0 and 9999 */
1562 while (Index
<= 9999)
1564 sprintfW(pDeviceInstance
, InstanceKeyFormat
, Index
);
1565 rc
= RegCreateKeyExW(hClassKey
,
1569 REG_OPTION_NON_VOLATILE
,
1570 #if _WIN32_WINNT >= 0x502
1571 KEY_READ
| KEY_WRITE
,
1578 if (rc
!= ERROR_SUCCESS
)
1583 if (Disposition
== REG_CREATED_NEW_KEY
)
1592 /* Unable to create more than 9999 devices within the same class */
1593 SetLastError(ERROR_GEN_FAILURE
);
1597 /* Write the new Driver value */
1598 rc
= RegSetValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
1599 if (rc
!= ERROR_SUCCESS
)
1608 /* Open the existing driver key */
1610 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
1613 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1617 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, (LPBYTE
)DriverKey
, &dwSize
);
1618 if (rc
!= ERROR_SUCCESS
)
1624 rc
= RegCreateKeyExW(hClassKey
,
1628 REG_OPTION_NON_VOLATILE
,
1629 #if _WIN32_WINNT >= 0x502
1630 KEY_READ
| KEY_WRITE
,
1637 if (rc
!= ERROR_SUCCESS
)
1645 /* Do installation of the specified section */
1648 FIXME("Need to install section %s in file %p\n",
1649 debugstr_w(InfSectionName
), InfHandle
);
1655 RpcStringFreeW(&lpGuidString
);
1656 HeapFree(GetProcessHeap(), 0, DriverKey
);
1657 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
1658 RegCloseKey(hHWProfileKey
);
1659 if (hEnumKey
!= NULL
)
1660 RegCloseKey(hEnumKey
);
1661 if (hClassKey
!= NULL
)
1662 RegCloseKey(hClassKey
);
1663 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
1664 RegCloseKey(hDeviceKey
);
1665 if (hKey
!= NULL
&& hKey
!= key
)
1668 TRACE("Returning 0x%p\n", key
);
1672 /***********************************************************************
1673 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1675 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1676 HDEVINFO DeviceInfoSet
,
1678 CONST GUID
*ClassGuid
,
1679 PCSTR DeviceDescription
,
1681 DWORD CreationFlags
,
1682 PSP_DEVINFO_DATA DeviceInfoData
)
1685 LPWSTR DeviceNameW
= NULL
;
1686 LPWSTR DeviceDescriptionW
= NULL
;
1692 DeviceNameW
= pSetupMultiByteToUnicode(DeviceName
, CP_ACP
);
1693 if (DeviceNameW
== NULL
) return FALSE
;
1695 if (DeviceDescription
)
1697 DeviceDescriptionW
= pSetupMultiByteToUnicode(DeviceDescription
, CP_ACP
);
1698 if (DeviceDescriptionW
== NULL
)
1700 MyFree(DeviceNameW
);
1705 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1706 hwndParent
, CreationFlags
, DeviceInfoData
);
1708 MyFree(DeviceNameW
);
1709 MyFree(DeviceDescriptionW
);
1714 /***********************************************************************
1715 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1717 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1718 HDEVINFO DeviceInfoSet
,
1720 CONST GUID
*ClassGuid
,
1721 PCWSTR DeviceDescription
,
1723 DWORD CreationFlags
,
1724 PSP_DEVINFO_DATA DeviceInfoData
)
1726 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1727 struct DeviceInfo
*deviceInfo
= NULL
;
1730 DEVINST RootDevInst
;
1732 WCHAR GenInstanceId
[MAX_DEVICE_ID_LEN
];
1734 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
1735 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1736 hwndParent
, CreationFlags
, DeviceInfoData
);
1740 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1743 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1745 SetLastError(ERROR_INVALID_HANDLE
);
1750 SetLastError(ERROR_INVALID_PARAMETER
);
1753 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1755 SetLastError(ERROR_INVALID_HANDLE
);
1758 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1759 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1761 SetLastError(ERROR_CLASS_MISMATCH
);
1764 if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
1766 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
1767 SetLastError(ERROR_INVALID_FLAGS
);
1771 /* Get the root device instance */
1772 cr
= CM_Locate_DevInst_ExW(&RootDevInst
,
1774 CM_LOCATE_DEVINST_NORMAL
,
1776 if (cr
!= CR_SUCCESS
)
1778 SetLastError(ERROR_INVALID_DATA
);
1782 /* Create the new device instance */
1783 cr
= CM_Create_DevInst_ExW(&DevInst
,
1784 (DEVINSTID
)DeviceName
,
1786 (CreationFlags
& DICD_GENERATE_ID
) ?
1787 CM_CREATE_DEVINST_GENERATE_ID
: 0,
1789 if (cr
!= CR_SUCCESS
)
1791 SetLastError(GetErrorCodeFromCrCode(cr
));
1795 if (CreationFlags
& DICD_GENERATE_ID
)
1797 /* Grab the actual instance ID that was created */
1798 cr
= CM_Get_Device_ID_Ex(DevInst
,
1803 if (cr
!= CR_SUCCESS
)
1805 SetLastError(GetErrorCodeFromCrCode(cr
));
1809 DeviceName
= GenInstanceId
;
1810 TRACE("Using generated instance ID: %s\n", debugstr_w(DeviceName
));
1813 if (CreateDeviceInfo(set
, DeviceName
, ClassGuid
, &deviceInfo
))
1815 InsertTailList(&set
->ListHead
, &deviceInfo
->ListEntry
);
1817 if (!DeviceInfoData
)
1821 if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1823 SetLastError(ERROR_INVALID_USER_BUFFER
);
1827 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
1828 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
1829 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
1837 if (deviceInfo
!= NULL
)
1839 /* Remove deviceInfo from List */
1840 RemoveEntryList(&deviceInfo
->ListEntry
);
1842 /* Destroy deviceInfo */
1843 DestroyDeviceInfo(deviceInfo
);
1847 TRACE("Returning %d\n", ret
);
1851 /***********************************************************************
1852 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1854 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1855 HDEVINFO DeviceInfoSet
,
1856 PSP_DEVINFO_DATA DeviceInfoData
,
1858 PSP_DETSIG_CMPPROC CompareProc
,
1859 PVOID CompareContext
,
1860 PSP_DEVINFO_DATA DupDeviceInfoData
)
1862 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1863 WCHAR DevInstId
[MAX_DEVICE_ID_LEN
];
1864 DEVINST ParentDevInst
;
1866 DWORD dwError
= ERROR_SUCCESS
;
1868 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1869 CompareProc
, CompareContext
, DupDeviceInfoData
);
1871 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1873 SetLastError(ERROR_INVALID_HANDLE
);
1876 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1878 SetLastError(ERROR_INVALID_HANDLE
);
1881 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1882 || !DeviceInfoData
->Reserved
)
1884 SetLastError(ERROR_INVALID_PARAMETER
);
1888 if (Flags
& ~SPRDI_FIND_DUPS
)
1890 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~SPRDI_FIND_DUPS
);
1891 SetLastError(ERROR_INVALID_FLAGS
);
1895 if (Flags
& SPRDI_FIND_DUPS
)
1897 FIXME("Unimplemented codepath!\n");
1900 CM_Get_Device_ID_Ex(DeviceInfoData
->DevInst
,
1906 CM_Get_Parent_Ex(&ParentDevInst
,
1907 DeviceInfoData
->DevInst
,
1911 cr
= CM_Create_DevInst_Ex(&DeviceInfoData
->DevInst
,
1914 CM_CREATE_DEVINST_NORMAL
| CM_CREATE_DEVINST_DO_NOT_INSTALL
,
1916 if (cr
!= CR_SUCCESS
&&
1917 cr
!= CR_ALREADY_SUCH_DEVINST
)
1919 dwError
= ERROR_NO_SUCH_DEVINST
;
1922 SetLastError(dwError
);
1924 return (dwError
== ERROR_SUCCESS
);
1927 /***********************************************************************
1928 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1930 BOOL WINAPI
SetupDiEnumDeviceInfo(
1933 PSP_DEVINFO_DATA info
)
1937 TRACE("%p %d %p\n", devinfo
, index
, info
);
1941 SetLastError(ERROR_INVALID_PARAMETER
);
1944 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1946 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1947 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1949 if (info
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1950 SetLastError(ERROR_INVALID_USER_BUFFER
);
1953 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1954 while (ItemList
!= &list
->ListHead
&& index
-- > 0)
1955 ItemList
= ItemList
->Flink
;
1956 if (ItemList
== &list
->ListHead
)
1957 SetLastError(ERROR_NO_MORE_ITEMS
);
1960 struct DeviceInfo
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
1961 memcpy(&info
->ClassGuid
,
1962 &DevInfo
->ClassGuid
,
1964 info
->DevInst
= DevInfo
->dnDevInst
;
1965 info
->Reserved
= (ULONG_PTR
)DevInfo
;
1971 SetLastError(ERROR_INVALID_HANDLE
);
1974 SetLastError(ERROR_INVALID_HANDLE
);
1978 /***********************************************************************
1979 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1981 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1982 HDEVINFO DeviceInfoSet
,
1983 PSP_DEVINFO_DATA DeviceInfoData
,
1984 PSTR DeviceInstanceId
,
1985 DWORD DeviceInstanceIdSize
,
1986 PDWORD RequiredSize
)
1992 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1993 DeviceInstanceIdSize
, RequiredSize
);
1995 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1997 SetLastError(ERROR_INVALID_PARAMETER
);
2001 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
2006 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
2008 instanceId
= MyMalloc(size
* sizeof(WCHAR
));
2011 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
2018 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
2020 DeviceInstanceIdSize
, NULL
, NULL
);
2026 if (len
> DeviceInstanceIdSize
)
2028 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2032 *RequiredSize
= len
;
2040 *RequiredSize
= size
;
2041 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2047 /***********************************************************************
2048 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
2050 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
2051 HDEVINFO DeviceInfoSet
,
2052 PSP_DEVINFO_DATA DeviceInfoData
,
2053 PWSTR DeviceInstanceId
,
2054 DWORD DeviceInstanceIdSize
,
2055 PDWORD RequiredSize
)
2057 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2058 struct DeviceInfo
*devInfo
;
2060 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
2061 DeviceInstanceIdSize
, RequiredSize
);
2063 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2065 SetLastError(ERROR_INVALID_HANDLE
);
2068 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2070 SetLastError(ERROR_INVALID_HANDLE
);
2073 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2074 || !DeviceInfoData
->Reserved
)
2076 SetLastError(ERROR_INVALID_PARAMETER
);
2079 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2080 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
2082 SetLastError(ERROR_INVALID_PARAMETER
);
2085 if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
2087 SetLastError(ERROR_INVALID_PARAMETER
);
2090 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
2091 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
2093 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2095 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
2098 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
2100 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
2104 /***********************************************************************
2105 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
2107 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
2109 PCSTR InfSectionName
,
2110 PSTR InfSectionWithExt
,
2111 DWORD InfSectionWithExtSize
,
2112 PDWORD RequiredSize
,
2115 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
2116 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2120 /***********************************************************************
2121 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2123 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
2125 PCWSTR InfSectionName
,
2126 PWSTR InfSectionWithExt
,
2127 DWORD InfSectionWithExtSize
,
2128 PDWORD RequiredSize
,
2131 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
2132 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2136 /***********************************************************************
2137 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2140 SetupDiGetActualSectionToInstallExA(
2142 IN PCSTR InfSectionName
,
2143 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
2144 OUT PSTR InfSectionWithExt OPTIONAL
,
2145 IN DWORD InfSectionWithExtSize
,
2146 OUT PDWORD RequiredSize OPTIONAL
,
2147 OUT PSTR
* Extension OPTIONAL
,
2150 LPWSTR InfSectionNameW
= NULL
;
2151 LPWSTR InfSectionWithExtW
= NULL
;
2153 BOOL bResult
= FALSE
;
2159 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2160 if (InfSectionNameW
== NULL
)
2163 if (InfSectionWithExt
)
2165 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
2166 if (InfSectionWithExtW
== NULL
)
2170 bResult
= SetupDiGetActualSectionToInstallExW(
2171 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
2172 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
2173 InfSectionWithExtSize
,
2175 Extension
? &ExtensionW
: NULL
,
2178 if (bResult
&& InfSectionWithExt
)
2180 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
2181 InfSectionWithExtSize
, NULL
, NULL
) != 0;
2183 if (bResult
&& Extension
)
2185 if (ExtensionW
== NULL
)
2188 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
2192 MyFree(InfSectionNameW
);
2193 MyFree(InfSectionWithExtW
);
2198 /***********************************************************************
2199 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2201 BOOL WINAPI
SetupDiGetClassDescriptionA(
2202 const GUID
* ClassGuid
,
2203 PSTR ClassDescription
,
2204 DWORD ClassDescriptionSize
,
2205 PDWORD RequiredSize
)
2207 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
2208 ClassDescriptionSize
,
2209 RequiredSize
, NULL
, NULL
);
2212 /***********************************************************************
2213 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2215 BOOL WINAPI
SetupDiGetClassDescriptionW(
2216 const GUID
* ClassGuid
,
2217 PWSTR ClassDescription
,
2218 DWORD ClassDescriptionSize
,
2219 PDWORD RequiredSize
)
2221 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
2222 ClassDescriptionSize
,
2223 RequiredSize
, NULL
, NULL
);
2226 /***********************************************************************
2227 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2229 BOOL WINAPI
SetupDiGetClassDescriptionExA(
2230 const GUID
* ClassGuid
,
2231 PSTR ClassDescription
,
2232 DWORD ClassDescriptionSize
,
2233 PDWORD RequiredSize
,
2237 PWCHAR ClassDescriptionW
= NULL
;
2238 LPWSTR MachineNameW
= NULL
;
2241 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2242 ClassDescriptionSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
2244 if (ClassDescriptionSize
> 0)
2246 ClassDescriptionW
= MyMalloc(ClassDescriptionSize
* sizeof(WCHAR
));
2247 if (!ClassDescriptionW
)
2249 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2256 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
2259 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2264 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
,
2265 ClassDescriptionSize
* sizeof(WCHAR
), RequiredSize
, MachineNameW
, Reserved
);
2268 DWORD len
= (DWORD
)WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
2269 ClassDescriptionSize
, NULL
, NULL
);
2270 if (len
== 0 || len
> ClassDescriptionSize
)
2272 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2278 MyFree(ClassDescriptionW
);
2279 MyFree(MachineNameW
);
2283 /***********************************************************************
2284 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2286 BOOL WINAPI
SetupDiGetClassDescriptionExW(
2287 const GUID
* ClassGuid
,
2288 PWSTR ClassDescription
,
2289 DWORD ClassDescriptionSize
,
2290 PDWORD RequiredSize
,
2300 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2301 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
2303 /* Make sure there's a GUID */
2306 SetLastError(ERROR_INVALID_PARAMETER
);
2310 /* Make sure there's a real buffer when there's a size */
2311 if (!ClassDescription
&& ClassDescriptionSize
> 0)
2313 SetLastError(ERROR_INVALID_PARAMETER
);
2317 /* Open the key for the GUID */
2318 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
2323 if (hKey
== INVALID_HANDLE_VALUE
)
2326 /* Retrieve the class description data and close the key */
2327 rc
= QueryRegistryValue(hKey
, NULL
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
2330 /* Make sure we got the data */
2331 if (rc
!= ERROR_SUCCESS
)
2337 /* Make sure the data is a string */
2338 if (dwRegType
!= REG_SZ
)
2341 SetLastError(ERROR_GEN_FAILURE
);
2345 /* Determine the length of the class description */
2346 dwLength
/= sizeof(WCHAR
);
2348 /* Count the null-terminator if none is present */
2349 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
2352 /* Inform the caller about the class description */
2353 if ((ClassDescription
!= NULL
) && (dwLength
<= ClassDescriptionSize
))
2355 memcpy(ClassDescription
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
2356 ClassDescription
[dwLength
- 1] = UNICODE_NULL
;
2359 /* Inform the caller about the required size */
2360 if (RequiredSize
!= NULL
)
2361 *RequiredSize
= dwLength
;
2363 /* Clean up the buffer */
2366 /* Make sure the buffer was large enough */
2367 if ((ClassDescription
== NULL
) || (dwLength
> ClassDescriptionSize
))
2369 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2376 /***********************************************************************
2377 * SetupDiGetClassDevsA (SETUPAPI.@)
2379 HDEVINFO WINAPI
SetupDiGetClassDevsA(
2385 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
2386 flags
, NULL
, NULL
, NULL
);
2389 /***********************************************************************
2390 * SetupDiGetClassDevsExA (SETUPAPI.@)
2392 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
2402 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
2406 enumstrW
= pSetupMultiByteToUnicode(enumstr
, CP_ACP
);
2409 ret
= INVALID_HANDLE_VALUE
;
2415 machineW
= pSetupMultiByteToUnicode(machine
, CP_ACP
);
2419 ret
= INVALID_HANDLE_VALUE
;
2423 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
2424 machineW
, reserved
);
2432 /***********************************************************************
2433 * SetupDiGetClassDevsW (SETUPAPI.@)
2435 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2441 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2445 /***********************************************************************
2446 * SetupDiGetClassDevsExW (SETUPAPI.@)
2448 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2457 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2458 struct DeviceInfoSet
*list
;
2459 CONST GUID
*pClassGuid
;
2461 HDEVINFO set
= INVALID_HANDLE_VALUE
;
2463 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2464 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2467 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2469 SetLastError(ERROR_INVALID_PARAMETER
);
2470 return INVALID_HANDLE_VALUE
;
2473 /* Create the deviceset if not set */
2476 list
= (struct DeviceInfoSet
*)deviceset
;
2477 if (list
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2479 SetLastError(ERROR_INVALID_HANDLE
);
2482 hDeviceInfo
= deviceset
;
2486 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2487 flags
& (DIGCF_DEVICEINTERFACE
| DIGCF_ALLCLASSES
) ? NULL
: class,
2488 NULL
, machine
, NULL
);
2489 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2491 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2494 if (flags
& DIGCF_PROFILE
)
2495 FIXME(": flag DIGCF_PROFILE ignored\n");
2497 if (flags
& DIGCF_DEVICEINTERFACE
)
2501 SetLastError(ERROR_INVALID_PARAMETER
);
2504 rc
= SETUP_CreateInterfaceList(list
, machine
, class, enumstr
, flags
& DIGCF_PRESENT
);
2508 /* Determine which class(es) should be included in the deviceset */
2509 if (flags
& DIGCF_ALLCLASSES
)
2511 /* The caller wants all classes. Check if
2512 * the deviceset limits us to one class */
2513 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2516 pClassGuid
= &list
->ClassGuid
;
2520 /* The caller wants one class. Check if it matches deviceset class */
2521 if (IsEqualIID(&list
->ClassGuid
, class)
2522 || IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2528 SetLastError(ERROR_INVALID_PARAMETER
);
2532 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2534 /* No class specified. Try to use the one of the deviceset */
2535 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2536 pClassGuid
= &list
->ClassGuid
;
2539 SetLastError(ERROR_INVALID_PARAMETER
);
2545 SetLastError(ERROR_INVALID_PARAMETER
);
2548 rc
= SETUP_CreateDevicesList(list
, machine
, pClassGuid
, enumstr
);
2550 if (rc
!= ERROR_SUCCESS
)
2558 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= set
)
2559 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2563 /***********************************************************************
2564 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2566 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2567 HDEVINFO DeviceInfoSet
,
2568 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2570 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2572 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2574 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2576 SetLastError(ERROR_INVALID_HANDLE
);
2579 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2581 SetLastError(ERROR_INVALID_HANDLE
);
2585 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2587 SetLastError(ERROR_INVALID_PARAMETER
);
2590 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2591 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2592 if (set
->MachineName
)
2595 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2599 DevInfoData
->RemoteMachineName
[0] = 0;
2604 /***********************************************************************
2605 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2607 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2608 HDEVINFO DeviceInfoSet
,
2609 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2611 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2613 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2615 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2617 SetLastError(ERROR_INVALID_HANDLE
);
2620 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2622 SetLastError(ERROR_INVALID_HANDLE
);
2626 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2628 SetLastError(ERROR_INVALID_PARAMETER
);
2631 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2632 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2633 if (set
->MachineName
)
2634 strcpyW(DevInfoData
->RemoteMachineName
, set
->MachineName
+ 2);
2636 DevInfoData
->RemoteMachineName
[0] = 0;
2641 /***********************************************************************
2642 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2644 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2645 HDEVINFO DeviceInfoSet
,
2646 PSP_DEVINFO_DATA DeviceInfoData
,
2647 const GUID
*InterfaceClassGuid
,
2648 PCSTR ReferenceString
,
2649 DWORD CreationFlags
,
2650 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2653 LPWSTR ReferenceStringW
= NULL
;
2655 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2656 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2657 CreationFlags
, DeviceInterfaceData
);
2659 if (ReferenceString
)
2661 ReferenceStringW
= pSetupMultiByteToUnicode(ReferenceString
, CP_ACP
);
2662 if (ReferenceStringW
== NULL
) return FALSE
;
2665 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2666 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2667 DeviceInterfaceData
);
2669 MyFree(ReferenceStringW
);
2674 /***********************************************************************
2675 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2677 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2678 HDEVINFO DeviceInfoSet
,
2679 PSP_DEVINFO_DATA DeviceInfoData
,
2680 const GUID
*InterfaceClassGuid
,
2681 PCWSTR ReferenceString
,
2682 DWORD CreationFlags
,
2683 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2685 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2686 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2687 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2688 CreationFlags
, DeviceInterfaceData
);
2690 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2692 SetLastError(ERROR_INVALID_HANDLE
);
2695 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2697 SetLastError(ERROR_INVALID_HANDLE
);
2700 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2701 || !DeviceInfoData
->Reserved
)
2703 SetLastError(ERROR_INVALID_PARAMETER
);
2706 if (!InterfaceClassGuid
)
2708 SetLastError(ERROR_INVALID_USER_BUFFER
);
2712 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2713 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2714 CreationFlags
, DeviceInterfaceData
);
2715 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2719 /***********************************************************************
2720 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2722 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2723 HDEVINFO DeviceInfoSet
,
2724 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2728 PCSTR InfSectionName
)
2731 PWSTR InfSectionNameW
= NULL
;
2733 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2734 samDesired
, InfHandle
, InfSectionName
);
2737 if (!InfSectionName
)
2739 SetLastError(ERROR_INVALID_PARAMETER
);
2740 return INVALID_HANDLE_VALUE
;
2742 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2743 if (!InfSectionNameW
)
2744 return INVALID_HANDLE_VALUE
;
2746 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2747 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2749 MyFree(InfSectionNameW
);
2753 /***********************************************************************
2754 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2756 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2757 HDEVINFO DeviceInfoSet
,
2758 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2762 PCWSTR InfSectionName
)
2765 LPWSTR SymbolicLink
;
2766 DWORD Length
, Index
;
2768 WCHAR bracedGuidString
[39];
2769 struct DeviceInterface
*DevItf
;
2770 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2772 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2773 samDesired
, InfHandle
, InfSectionName
);
2775 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2776 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2778 SetLastError(ERROR_INVALID_HANDLE
);
2779 return INVALID_HANDLE_VALUE
;
2781 if (!DeviceInterfaceData
||
2782 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2783 !DeviceInterfaceData
->Reserved
)
2785 SetLastError(ERROR_INVALID_PARAMETER
);
2786 return INVALID_HANDLE_VALUE
;
2788 if (InfHandle
&& !InfSectionName
)
2790 SetLastError(ERROR_INVALID_PARAMETER
);
2791 return INVALID_HANDLE_VALUE
;
2794 hKey
= SetupDiOpenClassRegKeyExW(&DeviceInterfaceData
->InterfaceClassGuid
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2795 if (hKey
== INVALID_HANDLE_VALUE
)
2797 hKey
= SetupDiOpenClassRegKeyExW(NULL
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2798 if (hKey
== INVALID_HANDLE_VALUE
)
2800 SetLastError(ERROR_INVALID_PARAMETER
);
2801 return INVALID_HANDLE_VALUE
;
2803 SETUPDI_GuidToString(&DeviceInterfaceData
->InterfaceClassGuid
, bracedGuidString
);
2805 if (RegCreateKeyExW(hKey
, bracedGuidString
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
) != ERROR_SUCCESS
)
2807 SetLastError(ERROR_INVALID_PARAMETER
);
2808 return INVALID_HANDLE_VALUE
;
2814 DevItf
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2816 Length
= (wcslen(DevItf
->SymbolicLink
)+1) * sizeof(WCHAR
);
2817 SymbolicLink
= HeapAlloc(GetProcessHeap(), 0, Length
);
2821 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2822 return INVALID_HANDLE_VALUE
;
2825 wcscpy(SymbolicLink
, DevItf
->SymbolicLink
);
2828 while(SymbolicLink
[Index
])
2830 if (SymbolicLink
[Index
] == L
'\\')
2832 SymbolicLink
[Index
] = L
'#';
2837 rc
= RegCreateKeyExW(hKey
, SymbolicLink
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
);
2840 HeapFree(GetProcessHeap(), 0, SymbolicLink
);
2842 if (rc
== ERROR_SUCCESS
)
2844 if (InfHandle
&& InfSectionName
)
2846 if (!SetupInstallFromInfSection(NULL
/*FIXME */,
2849 SPINST_INIFILES
| SPINST_REGISTRY
| SPINST_INI2REG
| SPINST_FILES
| SPINST_BITREG
| SPINST_REGSVR
| SPINST_UNREGSVR
| SPINST_PROFILEITEMS
| SPINST_COPYINF
,
2853 set
->SelectedDevice
->InstallParams
.InstallMsgHandler
,
2854 set
->SelectedDevice
->InstallParams
.InstallMsgHandlerContext
,
2855 INVALID_HANDLE_VALUE
,
2858 RegCloseKey(hDevKey
);
2859 return INVALID_HANDLE_VALUE
;
2868 /***********************************************************************
2869 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2871 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2872 HDEVINFO DeviceInfoSet
,
2873 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2876 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2879 TRACE("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2881 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2882 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2884 SetLastError(ERROR_INVALID_HANDLE
);
2887 if (!DeviceInterfaceData
||
2888 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2889 !DeviceInterfaceData
->Reserved
)
2891 SetLastError(ERROR_INVALID_PARAMETER
);
2895 FIXME("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2896 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2900 /***********************************************************************
2901 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2904 * DeviceInfoSet [I] Set of devices from which to enumerate
2906 * DeviceInfoData [I] (Optional) If specified, a specific device
2907 * instance from which to enumerate interfaces.
2908 * If it isn't specified, all interfaces for all
2909 * devices in the set are enumerated.
2910 * InterfaceClassGuid [I] The interface class to enumerate.
2911 * MemberIndex [I] An index of the interface instance to enumerate.
2912 * A caller should start with MemberIndex set to 0,
2913 * and continue until the function fails with
2914 * ERROR_NO_MORE_ITEMS.
2915 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2916 * member must be set to
2917 * sizeof(SP_DEVICE_INTERFACE_DATA).
2920 * Success: non-zero value.
2921 * Failure: FALSE. Call GetLastError() for more info.
2923 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2924 HDEVINFO DeviceInfoSet
,
2925 PSP_DEVINFO_DATA DeviceInfoData
,
2926 CONST GUID
* InterfaceClassGuid
,
2928 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2930 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2933 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet
, DeviceInfoData
,
2934 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2936 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2937 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2939 SetLastError(ERROR_INVALID_HANDLE
);
2942 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2943 !DeviceInfoData
->Reserved
))
2945 SetLastError(ERROR_INVALID_PARAMETER
);
2948 if (!DeviceInterfaceData
||
2949 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2951 SetLastError(ERROR_INVALID_PARAMETER
);
2956 struct DeviceInfo
*devInfo
=
2957 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2959 PLIST_ENTRY InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2960 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2962 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2963 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2965 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2968 if (MemberIndex
-- == 0)
2970 /* return this item */
2971 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2972 &DevItf
->InterfaceClassGuid
,
2974 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2975 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2979 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2982 SetLastError(ERROR_NO_MORE_ITEMS
);
2987 PLIST_ENTRY ItemList
= set
->ListHead
.Flink
;
2988 while (ItemList
!= &set
->ListHead
&& !found
)
2990 PLIST_ENTRY InterfaceListEntry
;
2991 struct DeviceInfo
*devInfo
=
2992 CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
2993 InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2994 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2996 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2997 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2999 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3002 if (MemberIndex
-- == 0)
3004 /* return this item */
3005 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
3006 &DevItf
->InterfaceClassGuid
,
3008 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
3009 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
3013 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3015 ItemList
= ItemList
->Flink
;
3019 SetLastError(ERROR_NO_MORE_ITEMS
);
3024 /***********************************************************************
3025 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
3027 * Destroy a DeviceInfoList and free all used memory of the list.
3030 * devinfo [I] DeviceInfoList pointer to list to destroy
3033 * Success: non zero value.
3034 * Failure: zero value.
3036 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
3040 TRACE("%p\n", devinfo
);
3041 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
3043 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
3045 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
3047 ret
= DestroyDeviceInfoSet(list
);
3052 SetLastError(ERROR_INVALID_HANDLE
);
3057 /***********************************************************************
3058 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
3060 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
3061 HDEVINFO DeviceInfoSet
,
3062 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3063 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
3064 DWORD DeviceInterfaceDetailDataSize
,
3065 PDWORD RequiredSize
,
3066 PSP_DEVINFO_DATA DeviceInfoData
)
3068 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3069 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
3070 DWORD sizeW
= 0, bytesNeeded
;
3073 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3074 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3075 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3077 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3078 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3080 SetLastError(ERROR_INVALID_HANDLE
);
3083 if (!DeviceInterfaceData
||
3084 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3085 !DeviceInterfaceData
->Reserved
)
3087 SetLastError(ERROR_INVALID_PARAMETER
);
3090 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
3092 SetLastError(ERROR_INVALID_USER_BUFFER
);
3096 if((DeviceInterfaceDetailDataSize
!= 0) &&
3097 (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + sizeof(CHAR
))))
3099 SetLastError(ERROR_INVALID_USER_BUFFER
);
3103 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3105 SetLastError(ERROR_INVALID_USER_BUFFER
);
3110 if (DeviceInterfaceDetailData
!= NULL
)
3112 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
3113 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
3114 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)MyMalloc(sizeW
);
3115 if (!DeviceInterfaceDetailDataW
)
3117 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3119 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
3121 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
3123 ret
= SetupDiGetDeviceInterfaceDetailW(
3125 DeviceInterfaceData
,
3126 DeviceInterfaceDetailDataW
,
3130 bytesNeeded
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
3131 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
3133 *RequiredSize
= bytesNeeded
;
3134 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
>= bytesNeeded
)
3136 if (!WideCharToMultiByte(
3138 DeviceInterfaceDetailDataW
->DevicePath
, -1,
3139 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
3146 MyFree(DeviceInterfaceDetailDataW
);
3151 /***********************************************************************
3152 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3154 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
3155 HDEVINFO DeviceInfoSet
,
3156 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3157 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
3158 DWORD DeviceInterfaceDetailDataSize
,
3159 PDWORD RequiredSize
,
3160 PSP_DEVINFO_DATA DeviceInfoData
)
3162 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3165 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3166 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3167 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3169 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3170 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3172 SetLastError(ERROR_INVALID_HANDLE
);
3175 if (!DeviceInterfaceData
||
3176 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3177 !DeviceInterfaceData
->Reserved
)
3179 SetLastError(ERROR_INVALID_PARAMETER
);
3182 if (DeviceInterfaceDetailData
&& DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
3184 SetLastError(ERROR_INVALID_USER_BUFFER
);
3187 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3189 SetLastError(ERROR_INVALID_USER_BUFFER
);
3192 if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3194 SetLastError(ERROR_INVALID_PARAMETER
);
3197 if ((DeviceInterfaceDetailData
!= NULL
)
3198 && (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) + sizeof(WCHAR
)))
3200 SetLastError(ERROR_INVALID_PARAMETER
);
3205 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
3206 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
3207 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
3208 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
3210 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
3212 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3214 *RequiredSize
= sizeRequired
;
3218 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
3219 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
3222 memcpy(&DeviceInfoData
->ClassGuid
,
3223 &deviceInterface
->DeviceInfo
->ClassGuid
,
3225 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
3226 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
3234 struct PropertyMapEntry
3241 static struct PropertyMapEntry PropertyMap
[] = {
3242 { REG_SZ
, "DeviceDesc", REGSTR_VAL_DEVDESC
},
3243 { REG_MULTI_SZ
, "HardwareId", REGSTR_VAL_HARDWAREID
},
3244 { REG_MULTI_SZ
, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS
},
3245 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3246 { REG_SZ
, "Service", REGSTR_VAL_SERVICE
},
3247 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3248 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3249 { REG_SZ
, "Class", REGSTR_VAL_CLASS
},
3250 { REG_SZ
, "ClassGUID", REGSTR_VAL_CLASSGUID
},
3251 { REG_SZ
, "Driver", REGSTR_VAL_DRIVER
},
3252 { REG_DWORD
, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS
},
3253 { REG_SZ
, "Mfg", REGSTR_VAL_MFG
},
3254 { REG_SZ
, "FriendlyName", REGSTR_VAL_FRIENDLYNAME
},
3255 { REG_SZ
, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION
},
3256 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3257 { REG_DWORD
, "Capabilities", REGSTR_VAL_CAPABILITIES
},
3258 { REG_DWORD
, "UINumber", REGSTR_VAL_UI_NUMBER
},
3259 { REG_MULTI_SZ
, "UpperFilters", REGSTR_VAL_UPPERFILTERS
},
3260 { REG_MULTI_SZ
, "LowerFilters", REGSTR_VAL_LOWERFILTERS
},
3261 { 0, NULL
, NULL
}, /* SPDRP_BUSTYPEGUID */
3262 { 0, NULL
, NULL
}, /* SPDRP_LEGACYBUSTYPE */
3263 { 0, NULL
, NULL
}, /* SPDRP_BUSNUMBER */
3264 { 0, NULL
, NULL
}, /* SPDRP_ENUMERATOR_NAME */
3265 { REG_BINARY
, "Security", REGSTR_SECURITY
},
3266 { 0, NULL
, NULL
}, /* SPDRP_SECURITY_SDS */
3267 { 0, NULL
, NULL
}, /* SPDRP_DEVTYPE */
3268 { 0, NULL
, NULL
}, /* SPDRP_EXCLUSIVE */
3269 { 0, NULL
, NULL
}, /* SPDRP_CHARACTERISTICS */
3270 { 0, NULL
, NULL
}, /* SPDRP_ADDRESS */
3271 { REG_SZ
, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT
},
3272 { 0, NULL
, NULL
}, /* SPDRP_DEVICE_POWER_DATA */
3273 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY */
3274 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3275 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3276 { 0, NULL
, NULL
}, /* SPDRP_INSTALL_STATE */
3279 /***********************************************************************
3280 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3282 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3283 HDEVINFO DeviceInfoSet
,
3284 PSP_DEVINFO_DATA DeviceInfoData
,
3286 PDWORD PropertyRegDataType
,
3287 PBYTE PropertyBuffer
,
3288 DWORD PropertyBufferSize
,
3289 PDWORD RequiredSize
)
3292 BOOL bIsStringProperty
;
3294 DWORD RequiredSizeA
, RequiredSizeW
;
3295 DWORD PropertyBufferSizeW
= 0;
3296 PBYTE PropertyBufferW
= NULL
;
3298 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3299 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3302 if (PropertyBufferSize
!= 0)
3304 PropertyBufferSizeW
= PropertyBufferSize
* 2;
3305 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
3306 if (!PropertyBufferW
)
3308 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3313 ret
= SetupDiGetDeviceRegistryPropertyW(DeviceInfoSet
,
3318 PropertyBufferSizeW
,
3321 if (ret
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3323 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
3325 if (bIsStringProperty
)
3326 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
3328 RequiredSizeA
= RequiredSizeW
;
3330 *RequiredSize
= RequiredSizeA
;
3331 if (PropertyRegDataType
)
3332 *PropertyRegDataType
= RegType
;
3337 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3341 if (RequiredSizeA
<= PropertyBufferSize
)
3343 if (bIsStringProperty
&& PropertyBufferSize
> 0)
3345 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
3347 /* Last error is already set by WideCharToMultiByte */
3352 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
3356 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3360 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3364 /***********************************************************************
3365 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3367 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3368 HDEVINFO DeviceInfoSet
,
3369 PSP_DEVINFO_DATA DeviceInfoData
,
3371 PDWORD PropertyRegDataType
,
3372 PBYTE PropertyBuffer
,
3373 DWORD PropertyBufferSize
,
3374 PDWORD RequiredSize
)
3377 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3378 struct DeviceInfo
*devInfo
;
3380 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3381 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3384 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3386 SetLastError(ERROR_INVALID_HANDLE
);
3389 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3391 SetLastError(ERROR_INVALID_HANDLE
);
3394 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3395 || !DeviceInfoData
->Reserved
)
3397 SetLastError(ERROR_INVALID_PARAMETER
);
3400 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3401 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3402 && PropertyMap
[Property
].nameW
)
3404 DWORD size
= PropertyBufferSize
;
3407 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_QUERY_VALUE
);
3408 if (hKey
== INVALID_HANDLE_VALUE
)
3410 l
= RegQueryValueExW(hKey
, PropertyMap
[Property
].nameW
,
3411 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3415 *RequiredSize
= size
;
3418 if (PropertyBuffer
!= NULL
|| size
== 0)
3421 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3423 case ERROR_MORE_DATA
:
3424 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3430 else if (Property
== SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
)
3432 DWORD required
= (strlenW(devInfo
->Data
) + 1) * sizeof(WCHAR
);
3434 if (PropertyRegDataType
)
3435 *PropertyRegDataType
= REG_SZ
;
3437 *RequiredSize
= required
;
3438 if (PropertyBufferSize
>= required
)
3440 strcpyW((LPWSTR
)PropertyBuffer
, devInfo
->Data
);
3444 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3448 ERR("Property 0x%lx not implemented\n", Property
);
3449 SetLastError(ERROR_NOT_SUPPORTED
);
3454 /***********************************************************************
3455 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3457 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
3458 HDEVINFO DeviceInfoSet
,
3459 PSP_DEVINFO_DATA DeviceInfoData
,
3461 const BYTE
*PropertyBuffer
,
3462 DWORD PropertyBufferSize
)
3465 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3467 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3468 PropertyBuffer
, PropertyBufferSize
);
3470 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3472 SetLastError(ERROR_INVALID_HANDLE
);
3475 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3477 SetLastError(ERROR_INVALID_HANDLE
);
3480 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3481 || !DeviceInfoData
->Reserved
)
3483 SetLastError(ERROR_INVALID_PARAMETER
);
3487 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3488 Property
, PropertyBuffer
, PropertyBufferSize
);
3489 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3493 /***********************************************************************
3494 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3496 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
3497 HDEVINFO DeviceInfoSet
,
3498 PSP_DEVINFO_DATA DeviceInfoData
,
3500 const BYTE
*PropertyBuffer
,
3501 DWORD PropertyBufferSize
)
3504 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3506 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3507 PropertyBuffer
, PropertyBufferSize
);
3509 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3511 SetLastError(ERROR_INVALID_HANDLE
);
3514 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3516 SetLastError(ERROR_INVALID_HANDLE
);
3519 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3520 || !DeviceInfoData
->Reserved
)
3522 SetLastError(ERROR_INVALID_PARAMETER
);
3525 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3526 && PropertyMap
[Property
].nameW
)
3530 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3531 if (hKey
== INVALID_HANDLE_VALUE
)
3533 /* Write new data */
3535 hKey
, PropertyMap
[Property
].nameW
, 0,
3536 PropertyMap
[Property
].regType
, PropertyBuffer
,
3537 PropertyBufferSize
);
3546 ERR("Property 0x%lx not implemented\n", Property
);
3547 SetLastError(ERROR_NOT_SUPPORTED
);
3550 TRACE("Returning %d\n", ret
);
3554 /***********************************************************************
3555 * SetupDiInstallClassA (SETUPAPI.@)
3557 BOOL WINAPI
SetupDiInstallClassA(
3563 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3566 /***********************************************************************
3567 * SetupDiInstallClassExA (SETUPAPI.@)
3570 SetupDiInstallClassExA(
3571 IN HWND hwndParent OPTIONAL
,
3572 IN PCSTR InfFileName OPTIONAL
,
3574 IN HSPFILEQ FileQueue OPTIONAL
,
3575 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3579 PWSTR InfFileNameW
= NULL
;
3584 SetLastError(ERROR_INVALID_PARAMETER
);
3589 InfFileNameW
= pSetupMultiByteToUnicode(InfFileName
, CP_ACP
);
3590 if (InfFileNameW
== NULL
)
3592 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3597 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3598 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3600 MyFree(InfFileNameW
);
3605 HKEY
SETUP_CreateClassKey(HINF hInf
)
3607 static const WCHAR slash
[] = { '\\',0 };
3608 WCHAR FullBuffer
[MAX_PATH
];
3609 WCHAR Buffer
[MAX_PATH
];
3613 if (!SetupGetLineTextW(NULL
,
3621 return INVALID_HANDLE_VALUE
;
3624 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3625 lstrcatW(FullBuffer
, slash
);
3626 lstrcatW(FullBuffer
, Buffer
);
3628 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3634 if (!SetupGetLineTextW(NULL
,
3642 return INVALID_HANDLE_VALUE
;
3645 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3649 REG_OPTION_NON_VOLATILE
,
3655 return INVALID_HANDLE_VALUE
;
3659 if (RegSetValueExW(hClassKey
,
3664 RequiredSize
* sizeof(WCHAR
)))
3666 RegCloseKey(hClassKey
);
3667 RegDeleteKeyW(HKEY_LOCAL_MACHINE
,
3669 return INVALID_HANDLE_VALUE
;
3675 /***********************************************************************
3676 * SetupDiInstallClassW (SETUPAPI.@)
3678 BOOL WINAPI
SetupDiInstallClassW(
3684 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3688 /***********************************************************************
3689 * SetupDiOpenClassRegKey (SETUPAPI.@)
3691 HKEY WINAPI
SetupDiOpenClassRegKey(
3692 const GUID
* ClassGuid
,
3695 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3696 DIOCR_INSTALLER
, NULL
, NULL
);
3700 /***********************************************************************
3701 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3703 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3704 const GUID
* ClassGuid
,
3710 PWSTR MachineNameW
= NULL
;
3713 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3714 Flags
, debugstr_a(MachineName
), Reserved
);
3718 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
3719 if (MachineNameW
== NULL
)
3720 return INVALID_HANDLE_VALUE
;
3723 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3724 Flags
, MachineNameW
, Reserved
);
3726 MyFree(MachineNameW
);
3732 /***********************************************************************
3733 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3735 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3736 const GUID
* ClassGuid
,
3748 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3749 Flags
, debugstr_w(MachineName
), Reserved
);
3751 if (MachineName
!= NULL
)
3753 l
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3754 if (l
!= ERROR_SUCCESS
)
3757 return INVALID_HANDLE_VALUE
;
3761 HKLM
= HKEY_LOCAL_MACHINE
;
3763 if (Flags
== DIOCR_INSTALLER
)
3765 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3767 else if (Flags
== DIOCR_INTERFACE
)
3769 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3773 ERR("Invalid Flags parameter!\n");
3774 SetLastError(ERROR_INVALID_FLAGS
);
3775 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3776 return INVALID_HANDLE_VALUE
;
3781 if ((l
= RegOpenKeyExW(HKLM
,
3787 SetLastError(ERROR_INVALID_CLASS
);
3788 hClassesKey
= INVALID_HANDLE_VALUE
;
3790 if (MachineName
!= NULL
)
3796 WCHAR bracedGuidString
[39];
3798 SETUPDI_GuidToString(ClassGuid
, bracedGuidString
);
3800 if (!(l
= RegOpenKeyExW(HKLM
,
3806 if (MachineName
!= NULL
)
3809 if ((l
= RegOpenKeyExW(hClassesKey
,
3816 key
= INVALID_HANDLE_VALUE
;
3818 RegCloseKey(hClassesKey
);
3822 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3824 key
= INVALID_HANDLE_VALUE
;
3831 /***********************************************************************
3832 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3834 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3835 HDEVINFO DeviceInfoSet
,
3838 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3840 struct DeviceInfoSet
* list
;
3842 DWORD dwLength
, dwError
, dwIndex
, dwKeyName
, dwSubIndex
;
3844 WCHAR Buffer
[MAX_PATH
+ 1];
3845 WCHAR SymBuffer
[MAX_PATH
+ 1];
3846 WCHAR InstancePath
[MAX_PATH
+ 1];
3847 HKEY hKey
, hDevKey
, hSymKey
;
3848 struct DeviceInfo
* deviceInfo
;
3849 struct DeviceInterface
*deviceInterface
;
3851 PLIST_ENTRY ItemList
;
3852 PLIST_ENTRY InterfaceListEntry
;
3854 TRACE("%p %s %08x %p\n",
3855 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3858 if (DeviceInterfaceData
&& DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
3860 SetLastError(ERROR_INVALID_PARAMETER
);
3864 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3866 SetLastError(ERROR_INVALID_HANDLE
);
3870 list
= (struct DeviceInfoSet
* )DeviceInfoSet
;
3872 dwLength
= wcslen(DevicePath
);
3875 /* path must be at least a guid length + L'\0' */
3876 SetLastError(ERROR_BAD_PATHNAME
);
3880 if (DevicePath
[0] != L
'\\' ||
3881 DevicePath
[1] != L
'\\' ||
3882 (DevicePath
[2] != L
'?' && DevicePath
[2] != L
'.') ||
3883 DevicePath
[3] != L
'\\')
3885 /* invalid formatted path */
3886 SetLastError(ERROR_BAD_PATHNAME
);
3890 /* check for reference strings */
3891 pEnd
= wcschr(&DevicePath
[4], L
'\\');
3894 /* no reference string */
3895 pEnd
= DevicePath
+ dwLength
;
3899 wcscpy(Buffer
, pEnd
- 37);
3902 dwError
= UuidFromStringW(Buffer
, &ClassId
);
3903 if (dwError
!= NOERROR
)
3905 /* invalid formatted path */
3906 SetLastError(ERROR_BAD_PATHNAME
);
3910 hKey
= SetupDiOpenClassRegKeyExW(&ClassId
, KEY_READ
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
3912 if (hKey
== INVALID_HANDLE_VALUE
)
3914 /* invalid device class */
3918 ItemList
= list
->ListHead
.Flink
;
3919 while (ItemList
!= &list
->ListHead
)
3921 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
3922 InterfaceListEntry
= deviceInfo
->InterfaceListHead
.Flink
;
3923 while (InterfaceListEntry
!= &deviceInfo
->InterfaceListHead
)
3925 deviceInterface
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
3926 if (!IsEqualIID(&deviceInterface
->InterfaceClassGuid
, &ClassId
))
3928 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3932 if (!wcsicmp(deviceInterface
->SymbolicLink
, DevicePath
))
3934 if (DeviceInterfaceData
)
3936 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
3937 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
3938 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3952 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3953 dwError
= RegEnumKeyExW(hKey
, dwIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3955 if (dwError
!= ERROR_SUCCESS
)
3958 if (RegOpenKeyExW(hKey
, Buffer
, 0, KEY_READ
, &hDevKey
) != ERROR_SUCCESS
)
3962 InstancePath
[0] = 0;
3963 dwKeyName
= sizeof(InstancePath
);
3965 dwError
= RegQueryValueExW(hDevKey
, L
"DeviceInstance", NULL
, NULL
, (LPBYTE
)InstancePath
, &dwKeyName
);
3970 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3971 dwError
= RegEnumKeyExW(hDevKey
, dwSubIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3973 if (dwError
!= ERROR_SUCCESS
)
3976 dwError
= RegOpenKeyExW(hDevKey
, Buffer
, 0, KEY_READ
, &hSymKey
);
3977 if (dwError
!= ERROR_SUCCESS
)
3980 /* query for symbolic link */
3981 dwKeyName
= sizeof(SymBuffer
);
3982 SymBuffer
[0] = L
'\0';
3983 dwError
= RegQueryValueExW(hSymKey
, L
"SymbolicLink", NULL
, NULL
, (LPBYTE
)SymBuffer
, &dwKeyName
);
3985 if (dwError
!= ERROR_SUCCESS
)
3987 RegCloseKey(hSymKey
);
3991 if (!wcsicmp(SymBuffer
, DevicePath
))
3993 Ret
= CreateDeviceInfo(list
, InstancePath
, &ClassId
, &deviceInfo
);
3994 RegCloseKey(hSymKey
);
3995 RegCloseKey(hDevKey
);
4000 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymBuffer
) + 1) * sizeof(WCHAR
));
4001 if (deviceInterface
)
4004 CopyMemory(&deviceInterface
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
4005 deviceInterface
->DeviceInfo
= deviceInfo
;
4006 deviceInterface
->Flags
= SPINT_ACTIVE
; //FIXME
4008 wcscpy(deviceInterface
->SymbolicLink
, SymBuffer
);
4010 InsertTailList(&deviceInfo
->InterfaceListHead
, &deviceInterface
->ListEntry
);
4011 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4014 if (DeviceInterfaceData
)
4016 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
4017 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
4018 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
4023 SetLastError(ERROR_INVALID_USER_BUFFER
);
4029 HeapFree(GetProcessHeap(), 0, deviceInfo
);
4034 RegCloseKey(hSymKey
);
4038 RegCloseKey(hDevKey
);
4046 /***********************************************************************
4047 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
4049 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
4050 HDEVINFO DeviceInfoSet
,
4053 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
4055 LPWSTR DevicePathW
= NULL
;
4058 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
4060 DevicePathW
= pSetupMultiByteToUnicode(DevicePath
, CP_ACP
);
4061 if (DevicePathW
== NULL
)
4064 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
4065 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
4067 MyFree(DevicePathW
);
4072 /***********************************************************************
4073 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
4075 BOOL WINAPI
SetupDiSetClassInstallParamsA(
4076 HDEVINFO DeviceInfoSet
,
4077 PSP_DEVINFO_DATA DeviceInfoData
,
4078 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
4079 DWORD ClassInstallParamsSize
)
4081 FIXME("%p %p %x %u\n",DeviceInfoSet
, DeviceInfoData
,
4082 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
4087 IntSetupDiRegisterDeviceInfo(
4088 IN HDEVINFO DeviceInfoSet
,
4089 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
4091 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
4094 /***********************************************************************
4095 * SetupDiCallClassInstaller (SETUPAPI.@)
4097 BOOL WINAPI
SetupDiCallClassInstaller(
4098 DI_FUNCTION InstallFunction
,
4099 HDEVINFO DeviceInfoSet
,
4100 PSP_DEVINFO_DATA DeviceInfoData
)
4104 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4107 SetLastError(ERROR_INVALID_PARAMETER
);
4108 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4109 SetLastError(ERROR_INVALID_HANDLE
);
4110 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4111 SetLastError(ERROR_INVALID_HANDLE
);
4112 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
4113 SetLastError(ERROR_INVALID_HANDLE
);
4114 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4115 SetLastError(ERROR_INVALID_USER_BUFFER
);
4118 SP_DEVINSTALL_PARAMS_W InstallParams
;
4119 #define CLASS_COINSTALLER 0x1
4120 #define DEVICE_COINSTALLER 0x2
4121 #define CLASS_INSTALLER 0x4
4122 UCHAR CanHandle
= 0;
4123 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
4125 switch (InstallFunction
)
4127 case DIF_ADDPROPERTYPAGE_ADVANCED
:
4128 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4130 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
4131 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4133 case DIF_ALLOW_INSTALL
:
4134 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4137 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4139 case DIF_DESTROYPRIVATEDATA
:
4140 CanHandle
= CLASS_INSTALLER
;
4142 case DIF_INSTALLDEVICE
:
4143 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4144 DefaultHandler
= SetupDiInstallDevice
;
4146 case DIF_INSTALLDEVICEFILES
:
4147 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4148 DefaultHandler
= SetupDiInstallDriverFiles
;
4150 case DIF_INSTALLINTERFACES
:
4151 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4152 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
4154 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
4155 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4157 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
4158 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4160 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
4161 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4163 case DIF_NEWDEVICEWIZARD_PRESELECT
:
4164 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4166 case DIF_NEWDEVICEWIZARD_SELECT
:
4167 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4169 case DIF_POWERMESSAGEWAKE
:
4170 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4172 case DIF_PROPERTYCHANGE
:
4173 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4174 DefaultHandler
= SetupDiChangeState
;
4176 case DIF_REGISTER_COINSTALLERS
:
4177 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4178 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
4180 case DIF_REGISTERDEVICE
:
4181 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4182 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
4185 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4186 DefaultHandler
= SetupDiRemoveDevice
;
4188 case DIF_SELECTBESTCOMPATDRV
:
4189 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4190 DefaultHandler
= SetupDiSelectBestCompatDrv
;
4192 case DIF_SELECTDEVICE
:
4193 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4194 DefaultHandler
= SetupDiSelectDevice
;
4196 case DIF_TROUBLESHOOTER
:
4197 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4200 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4201 DefaultHandler
= SetupDiUnremoveDevice
;
4204 ERR("Install function %u not supported\n", InstallFunction
);
4205 SetLastError(ERROR_NOT_SUPPORTED
);
4208 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4209 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4210 /* Don't process this call, as a parameter is invalid */
4215 LIST_ENTRY ClassCoInstallersListHead
;
4216 LIST_ENTRY DeviceCoInstallersListHead
;
4217 HMODULE ClassInstallerLibrary
= NULL
;
4218 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
4219 COINSTALLER_CONTEXT_DATA Context
;
4220 PLIST_ENTRY ListEntry
;
4222 DWORD dwRegType
, dwLength
;
4223 DWORD rc
= NO_ERROR
;
4225 InitializeListHead(&ClassCoInstallersListHead
);
4226 InitializeListHead(&DeviceCoInstallersListHead
);
4228 if (CanHandle
& DEVICE_COINSTALLER
)
4230 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4231 if (hKey
!= INVALID_HANDLE_VALUE
)
4233 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4234 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4236 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4237 if (KeyBuffer
!= NULL
)
4239 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4240 if (rc
== ERROR_SUCCESS
)
4243 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4245 /* Add coinstaller to DeviceCoInstallersListHead list */
4246 struct CoInstallerElement
*coinstaller
;
4247 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
4248 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4251 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4252 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4253 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
4255 HeapFree(GetProcessHeap(), 0, coinstaller
);
4258 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4264 if (CanHandle
& CLASS_COINSTALLER
)
4268 REGSTR_PATH_CODEVICEINSTALLERS
,
4272 if (rc
== ERROR_SUCCESS
)
4274 LPWSTR lpGuidString
;
4275 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
4277 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
4278 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4280 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4281 if (KeyBuffer
!= NULL
)
4283 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4284 if (rc
== ERROR_SUCCESS
)
4287 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4289 /* Add coinstaller to ClassCoInstallersListHead list */
4290 struct CoInstallerElement
*coinstaller
;
4291 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
4292 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4295 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4296 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4297 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
4299 HeapFree(GetProcessHeap(), 0, coinstaller
);
4302 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4305 RpcStringFreeW(&lpGuidString
);
4310 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
4312 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
4313 if (hKey
!= INVALID_HANDLE_VALUE
)
4315 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4316 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
4318 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4319 if (KeyBuffer
!= NULL
)
4321 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4322 if (rc
== ERROR_SUCCESS
)
4324 /* Get ClassInstaller function pointer */
4325 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
4326 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
4328 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
4329 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4332 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4339 /* Call Class co-installers */
4340 Context
.PostProcessing
= FALSE
;
4342 ListEntry
= ClassCoInstallersListHead
.Flink
;
4343 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4345 struct CoInstallerElement
*coinstaller
;
4346 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4347 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4348 coinstaller
->PrivateData
= Context
.PrivateData
;
4349 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4351 coinstaller
->DoPostProcessing
= TRUE
;
4354 ListEntry
= ListEntry
->Flink
;
4357 /* Call Device co-installers */
4358 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4359 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4361 struct CoInstallerElement
*coinstaller
;
4362 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4363 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4364 coinstaller
->PrivateData
= Context
.PrivateData
;
4365 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4367 coinstaller
->DoPostProcessing
= TRUE
;
4370 ListEntry
= ListEntry
->Flink
;
4373 /* Call Class installer */
4376 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4377 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4380 rc
= ERROR_DI_DO_DEFAULT
;
4382 /* Call default handler */
4383 if (rc
== ERROR_DI_DO_DEFAULT
)
4385 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4387 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4390 rc
= GetLastError();
4396 /* Call Class co-installers that required postprocessing */
4397 Context
.PostProcessing
= TRUE
;
4398 ListEntry
= ClassCoInstallersListHead
.Flink
;
4399 while (ListEntry
!= &ClassCoInstallersListHead
)
4401 struct CoInstallerElement
*coinstaller
;
4402 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4403 if (coinstaller
->DoPostProcessing
)
4405 Context
.InstallResult
= rc
;
4406 Context
.PrivateData
= coinstaller
->PrivateData
;
4407 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4409 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4410 ListEntry
= ListEntry
->Flink
;
4413 /* Call Device co-installers that required postprocessing */
4414 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4415 while (ListEntry
!= &DeviceCoInstallersListHead
)
4417 struct CoInstallerElement
*coinstaller
;
4418 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4419 if (coinstaller
->DoPostProcessing
)
4421 Context
.InstallResult
= rc
;
4422 Context
.PrivateData
= coinstaller
->PrivateData
;
4423 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4425 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4426 ListEntry
= ListEntry
->Flink
;
4429 /* Free allocated memory */
4430 while (!IsListEmpty(&ClassCoInstallersListHead
))
4432 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4433 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4435 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4437 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4438 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4441 ret
= (rc
== NO_ERROR
);
4445 TRACE("Returning %d\n", ret
);
4449 /***********************************************************************
4450 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4452 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4453 HDEVINFO DeviceInfoSet
,
4454 PSP_DEVINFO_DATA DeviceInfoData
,
4455 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4457 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4460 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4462 if (DeviceInstallParams
== NULL
)
4463 SetLastError(ERROR_INVALID_PARAMETER
);
4464 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4465 SetLastError(ERROR_INVALID_USER_BUFFER
);
4468 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4469 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4473 /* Do W->A conversion */
4475 DeviceInstallParams
,
4476 &deviceInstallParamsW
,
4477 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4478 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4479 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4481 DeviceInstallParams
->DriverPath
[0] = '\0';
4487 TRACE("Returning %d\n", ret
);
4491 /***********************************************************************
4492 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4495 SetupDiGetDeviceInfoListClass(
4496 IN HDEVINFO DeviceInfoSet
,
4497 OUT LPGUID ClassGuid
)
4499 struct DeviceInfoSet
*list
;
4502 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4505 SetLastError(ERROR_INVALID_HANDLE
);
4506 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4507 SetLastError(ERROR_INVALID_HANDLE
);
4508 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4509 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4512 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4517 TRACE("Returning %d\n", ret
);
4521 /***********************************************************************
4522 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4525 SetupDiGetDeviceInstallParamsW(
4526 IN HDEVINFO DeviceInfoSet
,
4527 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4528 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4530 struct DeviceInfoSet
*list
;
4533 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4536 SetLastError(ERROR_INVALID_HANDLE
);
4537 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4538 SetLastError(ERROR_INVALID_HANDLE
);
4539 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4540 SetLastError(ERROR_INVALID_USER_BUFFER
);
4541 else if (!DeviceInstallParams
)
4542 SetLastError(ERROR_INVALID_PARAMETER
);
4543 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4544 SetLastError(ERROR_INVALID_USER_BUFFER
);
4547 PSP_DEVINSTALL_PARAMS_W Source
;
4550 Source
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4552 Source
= &list
->InstallParams
;
4558 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4560 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4562 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
4568 TRACE("Returning %d\n", ret
);
4573 CheckDeviceInstallParameters(
4574 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4576 DWORD SupportedFlags
=
4577 DI_NOVCP
| /* 0x00000008 */
4578 DI_DIDCOMPAT
| /* 0x00000010 */
4579 DI_DIDCLASS
| /* 0x00000020 */
4580 DI_NEEDRESTART
| /* 0x00000080 */
4581 DI_NEEDREBOOT
| /* 0x00000100 */
4582 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4583 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4584 DI_ENUMSINGLEINF
| /* 0x00010000 */
4585 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
4586 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4587 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4588 DI_QUIETINSTALL
| /* 0x00800000 */
4589 DI_NOFILECOPY
| /* 0x01000000 */
4590 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4591 DWORD SupportedFlagsEx
=
4592 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4593 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4594 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4595 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4596 DI_FLAGSEX_NO_DRVREG_MODIFY
| /* 0x00008000 */
4597 DI_FLAGSEX_INSTALLEDDRIVER
; /* 0x04000000 */
4600 /* FIXME: add support for more flags */
4602 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4603 * It should be checked before accessing to other values
4604 * of the SP_DEVINSTALL_PARAMS structure */
4606 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4608 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4609 SetLastError(ERROR_INVALID_FLAGS
);
4611 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4613 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4614 SetLastError(ERROR_INVALID_FLAGS
);
4616 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4617 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4618 SetLastError(ERROR_INVALID_USER_BUFFER
);
4621 /* FIXME: check Reserved field */
4628 /***********************************************************************
4629 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4632 SetupDiSetDeviceInstallParamsW(
4633 IN HDEVINFO DeviceInfoSet
,
4634 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4635 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4637 struct DeviceInfoSet
*list
;
4640 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4643 SetLastError(ERROR_INVALID_HANDLE
);
4644 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4645 SetLastError(ERROR_INVALID_HANDLE
);
4646 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4647 SetLastError(ERROR_INVALID_USER_BUFFER
);
4648 else if (!DeviceInstallParams
)
4649 SetLastError(ERROR_INVALID_PARAMETER
);
4650 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4651 SetLastError(ERROR_INVALID_USER_BUFFER
);
4652 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4654 PSP_DEVINSTALL_PARAMS_W Destination
;
4657 Destination
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4659 Destination
= &list
->InstallParams
;
4660 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4664 TRACE("Returning %d\n", ret
);
4668 /***********************************************************************
4669 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4672 SetupDiSetDeviceInstallParamsA(
4673 HDEVINFO DeviceInfoSet
,
4674 PSP_DEVINFO_DATA DeviceInfoData
,
4675 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4677 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4681 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4683 if (DeviceInstallParams
== NULL
)
4684 SetLastError(ERROR_INVALID_PARAMETER
);
4685 else if (DeviceInstallParams
->cbSize
< sizeof(SP_DEVINSTALL_PARAMS_A
))
4686 SetLastError(ERROR_INVALID_USER_BUFFER
);
4689 memcpy(&deviceInstallParamsW
, DeviceInstallParams
, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A
, DriverPath
));
4690 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4691 len
= MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, NULL
, 0);
4694 ERR("DrivePath is NULL\n");
4699 MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, deviceInstallParamsW
.DriverPath
, len
);
4700 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4704 TRACE("Returning %d\n", ret
);
4709 OpenHardwareProfileKey(
4712 IN DWORD samDesired
)
4714 HKEY hHWProfilesKey
= NULL
;
4715 HKEY hHWProfileKey
= NULL
;
4716 HKEY ret
= INVALID_HANDLE_VALUE
;
4719 rc
= RegOpenKeyExW(HKLM
,
4720 REGSTR_PATH_HWPROFILES
,
4724 if (rc
!= ERROR_SUCCESS
)
4731 rc
= RegOpenKeyExW(hHWProfilesKey
,
4740 snprintfW(subKey
, 4, InstanceKeyFormat
, HwProfile
);
4742 rc
= RegOpenKeyExW(hHWProfilesKey
,
4748 if (rc
!= ERROR_SUCCESS
)
4753 ret
= hHWProfileKey
;
4756 if (hHWProfilesKey
!= NULL
)
4757 RegCloseKey(hHWProfilesKey
);
4758 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4759 RegCloseKey(hHWProfileKey
);
4764 IsDeviceInfoInDeviceInfoSet(
4765 struct DeviceInfoSet
*deviceInfoSet
,
4766 struct DeviceInfo
*deviceInfo
)
4768 PLIST_ENTRY ListEntry
;
4770 ListEntry
= deviceInfoSet
->ListHead
.Flink
;
4771 while (ListEntry
!= &deviceInfoSet
->ListHead
)
4773 if (deviceInfo
== CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
))
4776 ListEntry
= ListEntry
->Flink
;
4782 /***********************************************************************
4783 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4786 SetupDiDeleteDeviceInfo(
4787 IN HDEVINFO DeviceInfoSet
,
4788 IN PSP_DEVINFO_DATA DeviceInfoData
)
4790 struct DeviceInfoSet
*deviceInfoSet
;
4791 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
;
4794 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4797 SetLastError(ERROR_INVALID_HANDLE
);
4798 else if ((deviceInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4799 SetLastError(ERROR_INVALID_HANDLE
);
4800 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4801 SetLastError(ERROR_INVALID_USER_BUFFER
);
4802 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet
, deviceInfo
))
4803 SetLastError(ERROR_INVALID_PARAMETER
);
4806 RemoveEntryList(&deviceInfo
->ListEntry
);
4807 DestroyDeviceInfo(deviceInfo
);
4815 /***********************************************************************
4816 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4819 SetupDiOpenDeviceInfoA(
4820 IN HDEVINFO DeviceInfoSet
,
4821 IN PCSTR DeviceInstanceId
,
4822 IN HWND hwndParent OPTIONAL
,
4824 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4826 LPWSTR DeviceInstanceIdW
= NULL
;
4829 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4831 DeviceInstanceIdW
= pSetupMultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4832 if (DeviceInstanceIdW
== NULL
)
4835 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4836 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4838 MyFree(DeviceInstanceIdW
);
4844 /***********************************************************************
4845 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4848 SetupDiOpenDeviceInfoW(
4849 IN HDEVINFO DeviceInfoSet
,
4850 IN PCWSTR DeviceInstanceId
,
4851 IN HWND hwndParent OPTIONAL
,
4853 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4855 struct DeviceInfoSet
*list
;
4856 HKEY hEnumKey
, hKey
= NULL
;
4860 TRACE("%p %s %p %lx %p\n",
4861 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
4862 hwndParent
, OpenFlags
, DeviceInfoData
);
4864 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4865 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4868 SetLastError(ERROR_INVALID_HANDLE
);
4869 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4870 SetLastError(ERROR_INVALID_HANDLE
);
4871 else if (!DeviceInstanceId
)
4872 SetLastError(ERROR_INVALID_PARAMETER
);
4873 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4875 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4876 SetLastError(ERROR_INVALID_FLAGS
);
4878 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4879 SetLastError(ERROR_INVALID_USER_BUFFER
);
4882 struct DeviceInfo
*deviceInfo
= NULL
;
4883 /* Search if device already exists in DeviceInfoSet.
4884 * If yes, return the existing element
4885 * If no, create a new element using information in registry
4887 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4888 while (ItemList
!= &list
->ListHead
)
4890 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
4891 if (!wcscmp(deviceInfo
->instanceId
, DeviceInstanceId
))
4894 ItemList
= ItemList
->Flink
;
4899 /* good one found */
4905 WCHAR szClassGuid
[MAX_GUID_STRING_LEN
];
4907 /* Open supposed registry key */
4910 REGSTR_PATH_SYSTEMENUM
,
4914 if (rc
!= ERROR_SUCCESS
)
4925 RegCloseKey(hEnumKey
);
4926 if (rc
!= ERROR_SUCCESS
)
4928 if (rc
== ERROR_FILE_NOT_FOUND
)
4929 rc
= ERROR_NO_SUCH_DEVINST
;
4934 ClassGUID
= GUID_NULL
;
4935 dwSize
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
4937 if (RegQueryValueExW(hKey
,
4938 REGSTR_VAL_CLASSGUID
,
4941 (LPBYTE
)szClassGuid
,
4942 &dwSize
) == ERROR_SUCCESS
)
4944 szClassGuid
[MAX_GUID_STRING_LEN
- 2] = UNICODE_NULL
;
4946 /* Convert a string to a ClassGuid */
4947 UuidFromStringW(&szClassGuid
[1], &ClassGUID
);
4950 if (!CreateDeviceInfo(list
, DeviceInstanceId
, &ClassGUID
, &deviceInfo
))
4953 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4958 if (ret
&& deviceInfo
&& DeviceInfoData
)
4960 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4961 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4962 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4973 /***********************************************************************
4974 * SetupDiGetSelectedDevice (SETUPAPI.@)
4977 SetupDiGetSelectedDevice(
4978 IN HDEVINFO DeviceInfoSet
,
4979 OUT PSP_DEVINFO_DATA DeviceInfoData
)
4981 struct DeviceInfoSet
*list
;
4984 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4987 SetLastError(ERROR_INVALID_HANDLE
);
4988 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4989 SetLastError(ERROR_INVALID_HANDLE
);
4990 else if (list
->SelectedDevice
== NULL
)
4991 SetLastError(ERROR_NO_DEVICE_SELECTED
);
4992 else if (!DeviceInfoData
)
4993 SetLastError(ERROR_INVALID_PARAMETER
);
4994 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4995 SetLastError(ERROR_INVALID_USER_BUFFER
);
4998 memcpy(&DeviceInfoData
->ClassGuid
,
4999 &list
->SelectedDevice
->ClassGuid
,
5001 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
5002 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
5006 TRACE("Returning %d\n", ret
);
5011 /***********************************************************************
5012 * SetupDiSetSelectedDevice (SETUPAPI.@)
5015 SetupDiSetSelectedDevice(
5016 IN HDEVINFO DeviceInfoSet
,
5017 IN PSP_DEVINFO_DATA DeviceInfoData
)
5019 struct DeviceInfoSet
*list
;
5022 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5025 SetLastError(ERROR_INVALID_HANDLE
);
5026 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5027 SetLastError(ERROR_INVALID_HANDLE
);
5028 else if (!DeviceInfoData
)
5029 SetLastError(ERROR_INVALID_PARAMETER
);
5030 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5031 SetLastError(ERROR_INVALID_USER_BUFFER
);
5032 else if (DeviceInfoData
->Reserved
== 0)
5033 SetLastError(ERROR_INVALID_USER_BUFFER
);
5036 list
->SelectedDevice
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5040 TRACE("Returning %d\n", ret
);
5045 /* Return the current hardware profile id, or -1 if error */
5047 SETUPAPI_GetCurrentHwProfile(
5048 IN HDEVINFO DeviceInfoSet
)
5051 DWORD dwRegType
, dwLength
;
5054 DWORD ret
= (DWORD
)-1;
5056 rc
= RegOpenKeyExW(((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
5057 REGSTR_PATH_IDCONFIGDB
,
5061 if (rc
!= ERROR_SUCCESS
)
5067 dwLength
= sizeof(DWORD
);
5068 rc
= RegQueryValueExW(hKey
,
5069 REGSTR_VAL_CURRENTCONFIG
,
5072 (LPBYTE
)&hwProfile
, &dwLength
);
5073 if (rc
!= ERROR_SUCCESS
)
5078 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5080 SetLastError(ERROR_GEN_FAILURE
);
5095 IN HDEVINFO DeviceInfoSet
,
5096 IN PSP_DEVINFO_DATA DeviceInfoData
)
5099 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5100 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5103 cr
= CM_Enable_DevNode_Ex(deviceInfo
->dnDevInst
, 0, set
->hMachine
);
5104 if (cr
!= CR_SUCCESS
)
5106 SetLastError(GetErrorCodeFromCrCode(cr
));
5112 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5117 static BOOL
StopDevice(
5118 IN HDEVINFO DeviceInfoSet
,
5119 IN PSP_DEVINFO_DATA DeviceInfoData
)
5121 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5125 /***********************************************************************
5126 * SetupDiChangeState (SETUPAPI.@)
5130 IN HDEVINFO DeviceInfoSet
,
5131 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5133 PSP_PROPCHANGE_PARAMS PropChange
;
5134 HKEY hKey
= INVALID_HANDLE_VALUE
;
5135 LPCWSTR RegistryValueName
;
5136 DWORD dwConfigFlags
, dwLength
, dwRegType
;
5140 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5142 if (!DeviceInfoData
)
5143 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChangeParams
;
5145 PropChange
= ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChangeParams
;
5148 SetLastError(ERROR_INVALID_PARAMETER
);
5152 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
5153 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
5155 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
5157 switch (PropChange
->StateChange
)
5162 /* Enable/disable device in registry */
5163 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5164 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5165 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
5166 if (hKey
== INVALID_HANDLE_VALUE
)
5168 dwLength
= sizeof(DWORD
);
5169 rc
= RegQueryValueExW(
5174 (LPBYTE
)&dwConfigFlags
, &dwLength
);
5175 if (rc
== ERROR_FILE_NOT_FOUND
)
5177 else if (rc
!= ERROR_SUCCESS
)
5182 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5184 SetLastError(ERROR_GEN_FAILURE
);
5187 if (PropChange
->StateChange
== DICS_ENABLE
)
5188 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5190 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5191 rc
= RegSetValueExW(
5196 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
5197 if (rc
!= ERROR_SUCCESS
)
5203 /* Enable/disable device if needed */
5204 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
5205 || PropChange
->HwProfile
== 0
5206 || PropChange
->HwProfile
== SETUPAPI_GetCurrentHwProfile(DeviceInfoSet
))
5208 if (PropChange
->StateChange
== DICS_ENABLE
)
5209 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5211 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
5217 case DICS_PROPCHANGE
:
5219 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5224 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
5225 SetLastError(ERROR_NOT_SUPPORTED
);
5230 if (hKey
!= INVALID_HANDLE_VALUE
)
5233 TRACE("Returning %d\n", ret
);
5237 /***********************************************************************
5238 * SetupDiSelectDevice (SETUPAPI.@)
5241 SetupDiSelectDevice(
5242 IN HDEVINFO DeviceInfoSet
,
5243 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5245 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5246 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5251 /***********************************************************************
5252 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5255 SetupDiRegisterCoDeviceInstallers(
5256 IN HDEVINFO DeviceInfoSet
,
5257 IN PSP_DEVINFO_DATA DeviceInfoData
)
5259 BOOL ret
= FALSE
; /* Return value */
5261 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5264 SetLastError(ERROR_INVALID_PARAMETER
);
5265 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5266 SetLastError(ERROR_INVALID_HANDLE
);
5267 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5268 SetLastError(ERROR_INVALID_HANDLE
);
5269 else if (!DeviceInfoData
)
5270 SetLastError(ERROR_INVALID_PARAMETER
);
5271 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5272 SetLastError(ERROR_INVALID_USER_BUFFER
);
5275 SP_DEVINSTALL_PARAMS_W InstallParams
;
5276 struct DriverInfoElement
*SelectedDriver
;
5279 WCHAR SectionName
[MAX_PATH
];
5280 DWORD SectionNameLength
= 0;
5281 HKEY hKey
= INVALID_HANDLE_VALUE
;
5282 PVOID Context
= NULL
;
5284 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5285 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5289 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5290 if (SelectedDriver
== NULL
)
5292 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5296 /* Get .CoInstallers section name */
5297 Result
= SetupDiGetActualSectionToInstallW(
5298 SelectedDriver
->InfFileDetails
->hInf
,
5299 SelectedDriver
->Details
.SectionName
,
5300 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5301 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
5303 lstrcatW(SectionName
, DotCoInstallers
);
5305 /* Open/Create driver key information */
5306 #if _WIN32_WINNT >= 0x502
5307 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5309 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5311 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5312 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5313 if (hKey
== INVALID_HANDLE_VALUE
)
5316 /* Install .CoInstallers section */
5317 DoAction
= SPINST_REGISTRY
;
5318 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5320 DoAction
|= SPINST_FILES
;
5321 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5325 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5326 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5327 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5328 SetupDefaultQueueCallbackW
, Context
,
5329 DeviceInfoSet
, DeviceInfoData
);
5337 SetupTermDefaultQueueCallback(Context
);
5338 if (hKey
!= INVALID_HANDLE_VALUE
)
5342 TRACE("Returning %d\n", ret
);
5347 InfIsFromOEMLocation(
5349 OUT LPBOOL IsOEMLocation
)
5353 last
= strrchrW(FullName
, '\\');
5356 /* No directory specified */
5357 *IsOEMLocation
= FALSE
;
5364 Windir
= MyMalloc((MAX_PATH
+ 1 + strlenW(InfDirectory
)) * sizeof(WCHAR
));
5367 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5371 ret
= GetSystemWindowsDirectoryW(Windir
, MAX_PATH
);
5372 if (ret
== 0 || ret
> MAX_PATH
)
5375 SetLastError(ERROR_GEN_FAILURE
);
5378 if (*Windir
&& Windir
[strlenW(Windir
) - 1] != '\\')
5379 strcatW(Windir
, BackSlash
);
5380 strcatW(Windir
, InfDirectory
);
5382 if (strncmpiW(FullName
, Windir
, last
- FullName
) == 0)
5384 /* The path is %SYSTEMROOT%\Inf */
5385 *IsOEMLocation
= FALSE
;
5389 /* The file is in another place */
5390 *IsOEMLocation
= TRUE
;
5397 /***********************************************************************
5398 * SetupDiInstallDevice (SETUPAPI.@)
5401 SetupDiInstallDevice(
5402 IN HDEVINFO DeviceInfoSet
,
5403 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5405 SP_DEVINSTALL_PARAMS_W InstallParams
;
5406 struct DriverInfoElement
*SelectedDriver
;
5407 SYSTEMTIME DriverDate
;
5408 WCHAR SectionName
[MAX_PATH
];
5410 DWORD SectionNameLength
= 0;
5411 BOOL Result
= FALSE
;
5414 LPWSTR pSectionName
= NULL
;
5415 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5417 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5418 BOOL RebootRequired
= FALSE
;
5419 HKEY hKey
= INVALID_HANDLE_VALUE
;
5420 BOOL NeedtoCopyFile
;
5421 LARGE_INTEGER fullVersion
;
5423 PVOID Context
= NULL
;
5424 BOOL ret
= FALSE
; /* Return value */
5426 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5429 SetLastError(ERROR_INVALID_PARAMETER
);
5430 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5431 SetLastError(ERROR_INVALID_HANDLE
);
5432 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5433 SetLastError(ERROR_INVALID_HANDLE
);
5434 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5435 SetLastError(ERROR_INVALID_USER_BUFFER
);
5441 /* One parameter is bad */
5445 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5446 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5450 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5452 /* Set FAILEDINSTALL in ConfigFlags registry value */
5453 DWORD ConfigFlags
, regType
;
5454 Result
= SetupDiGetDeviceRegistryPropertyW(
5459 (PBYTE
)&ConfigFlags
,
5460 sizeof(ConfigFlags
),
5462 if (!Result
|| regType
!= REG_DWORD
)
5464 SetLastError(ERROR_GEN_FAILURE
);
5467 ConfigFlags
|= DNF_DISABLED
;
5468 Result
= SetupDiSetDeviceRegistryPropertyW(
5472 (PBYTE
)&ConfigFlags
,
5473 sizeof(ConfigFlags
));
5476 SetLastError(ERROR_GEN_FAILURE
);
5484 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5485 if (SelectedDriver
== NULL
)
5487 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5491 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5493 Result
= SetupDiGetActualSectionToInstallW(
5494 SelectedDriver
->InfFileDetails
->hInf
,
5495 SelectedDriver
->Details
.SectionName
,
5496 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5497 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
5499 pSectionName
= &SectionName
[strlenW(SectionName
)];
5501 /* Get information from [Version] section */
5502 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5504 /* Format ClassGuid to a string */
5505 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5507 RequiredSize
= lstrlenW(lpGuidString
);
5508 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5509 if (!lpFullGuidString
)
5511 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5514 lpFullGuidString
[0] = '{';
5515 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5516 lpFullGuidString
[RequiredSize
+ 1] = '}';
5517 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5519 /* Copy .inf file to Inf\ directory (if needed) */
5520 Result
= InfIsFromOEMLocation(SelectedDriver
->Details
.InfFileName
, &NeedtoCopyFile
);
5525 WCHAR NewFileName
[MAX_PATH
];
5526 struct InfFileDetails
*newInfFileDetails
;
5527 Result
= SetupCopyOEMInfW(
5528 SelectedDriver
->Details
.InfFileName
,
5531 SP_COPY_NOOVERWRITE
,
5532 NewFileName
, MAX_PATH
,
5535 if (!Result
&& GetLastError() != ERROR_FILE_EXISTS
)
5537 /* Create a new struct InfFileDetails, and set it to
5538 * SelectedDriver->InfFileDetails, to release use of
5539 * current InfFile */
5540 newInfFileDetails
= CreateInfFileDetails(NewFileName
);
5541 if (!newInfFileDetails
)
5543 DereferenceInfFile(SelectedDriver
->InfFileDetails
);
5544 SelectedDriver
->InfFileDetails
= newInfFileDetails
;
5545 strcpyW(SelectedDriver
->Details
.InfFileName
, NewFileName
);
5548 /* Open/Create driver key information */
5549 #if _WIN32_WINNT >= 0x502
5550 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5552 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5554 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5555 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5556 if (hKey
== INVALID_HANDLE_VALUE
)
5559 /* Install main section */
5561 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5562 DoAction
|= SPINST_REGISTRY
;
5563 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5565 DoAction
|= SPINST_FILES
;
5566 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5570 *pSectionName
= '\0';
5571 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5572 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5573 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5574 SetupDefaultQueueCallbackW
, Context
,
5575 DeviceInfoSet
, DeviceInfoData
);
5578 InstallParams
.Flags
|= DI_NOFILECOPY
;
5579 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5581 /* Write information to driver key */
5582 *pSectionName
= UNICODE_NULL
;
5583 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
5584 TRACE("Write information to driver key\n");
5585 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5586 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5587 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5588 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->InfFileDetails
->FileName
));
5589 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
5590 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
5591 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
5592 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
5593 sprintfW(Buffer
, DateFormat
, DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5594 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5595 if (rc
== ERROR_SUCCESS
)
5596 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5597 if (rc
== ERROR_SUCCESS
)
5598 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5599 if (rc
== ERROR_SUCCESS
)
5601 sprintfW(Buffer
, VersionFormat
, fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5602 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5604 if (rc
== ERROR_SUCCESS
)
5605 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->InfFileDetails
->FileName
, (strlenW(SelectedDriver
->InfFileDetails
->FileName
) + 1) * sizeof(WCHAR
));
5606 if (rc
== ERROR_SUCCESS
)
5607 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5608 if (rc
== ERROR_SUCCESS
)
5609 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
));
5610 if (rc
== ERROR_SUCCESS
)
5611 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5612 if (rc
== ERROR_SUCCESS
)
5613 rc
= RegSetValueExW(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5614 if (rc
!= ERROR_SUCCESS
)
5620 hKey
= INVALID_HANDLE_VALUE
;
5622 /* FIXME: Process .LogConfigOverride section */
5624 /* Install .Services section */
5625 strcpyW(pSectionName
, DotServices
);
5626 Result
= SetupInstallServicesFromInfSectionExW(
5627 SelectedDriver
->InfFileDetails
->hInf
,
5636 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5637 RebootRequired
= TRUE
;
5639 /* Open device registry key */
5640 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5641 if (hKey
== INVALID_HANDLE_VALUE
)
5644 /* Install .HW section */
5646 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5647 DoAction
|= SPINST_REGISTRY
;
5648 strcpyW(pSectionName
, DotHW
);
5649 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5650 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5651 DoAction
, hKey
, NULL
, 0,
5653 DeviceInfoSet
, DeviceInfoData
);
5657 /* Write information to enum key */
5658 TRACE("Write information to enum key\n");
5659 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
5660 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
5661 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5662 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
5663 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
5664 if (rc
== ERROR_SUCCESS
)
5665 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5666 if (rc
== ERROR_SUCCESS
)
5667 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5668 if (rc
== ERROR_SUCCESS
)
5669 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5670 if (rc
!= ERROR_SUCCESS
)
5676 /* Start the device */
5677 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5678 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5683 /* End of installation */
5684 if (hKey
!= INVALID_HANDLE_VALUE
)
5687 RpcStringFreeW(&lpGuidString
);
5688 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
5690 SetupTermDefaultQueueCallback(Context
);
5691 TRACE("Returning %d\n", ret
);
5695 static HKEY
SETUPDI_OpenDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5697 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
5700 l
= RegOpenKeyExW(RootKey
, REGSTR_PATH_SYSTEMENUM
, 0, 0, &enumKey
);
5703 l
= RegOpenKeyExW(enumKey
, devInfo
->instanceId
, 0, samDesired
, &key
);
5704 RegCloseKey(enumKey
);
5711 static HKEY
SETUPDI_OpenDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5713 LPWSTR DriverKey
= NULL
;
5717 HKEY hEnumKey
= NULL
;
5719 HKEY key
= INVALID_HANDLE_VALUE
;
5721 hKey
= SETUPDI_OpenDevKey(RootKey
, devInfo
, KEY_QUERY_VALUE
);
5722 if (hKey
== INVALID_HANDLE_VALUE
)
5724 /* Read the 'Driver' key */
5725 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5726 if (rc
!= ERROR_SUCCESS
)
5731 else if (dwRegType
!= REG_SZ
)
5733 SetLastError(ERROR_GEN_FAILURE
);
5736 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5739 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5742 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5743 if (rc
!= ERROR_SUCCESS
)
5750 /* Need to open the driver key */
5753 REGSTR_PATH_CLASS_NT
,
5757 if (rc
!= ERROR_SUCCESS
)
5768 if (rc
!= ERROR_SUCCESS
)
5776 if (hEnumKey
!= NULL
)
5777 RegCloseKey(hEnumKey
);
5778 if (hKey
!= NULL
&& hKey
!= key
)
5783 /***********************************************************************
5784 * SetupDiOpenDevRegKey (SETUPAPI.@)
5786 HKEY WINAPI
SetupDiOpenDevRegKey(
5787 HDEVINFO DeviceInfoSet
,
5788 PSP_DEVINFO_DATA DeviceInfoData
,
5794 struct DeviceInfoSet
*set
= DeviceInfoSet
;
5795 struct DeviceInfo
*devInfo
;
5796 HKEY key
= INVALID_HANDLE_VALUE
;
5799 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet
, DeviceInfoData
,
5800 Scope
, HwProfile
, KeyType
, samDesired
);
5802 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5804 SetLastError(ERROR_INVALID_HANDLE
);
5805 return INVALID_HANDLE_VALUE
;
5807 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5809 SetLastError(ERROR_INVALID_HANDLE
);
5810 return INVALID_HANDLE_VALUE
;
5812 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5813 || !DeviceInfoData
->Reserved
)
5815 SetLastError(ERROR_INVALID_PARAMETER
);
5816 return INVALID_HANDLE_VALUE
;
5818 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5820 SetLastError(ERROR_INVALID_FLAGS
);
5821 return INVALID_HANDLE_VALUE
;
5823 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
5825 SetLastError(ERROR_INVALID_FLAGS
);
5826 return INVALID_HANDLE_VALUE
;
5828 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5829 if (devInfo
->set
!= set
)
5831 SetLastError(ERROR_INVALID_PARAMETER
);
5832 return INVALID_HANDLE_VALUE
;
5834 if (Scope
!= DICS_FLAG_GLOBAL
)
5836 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5837 if (RootKey
== INVALID_HANDLE_VALUE
)
5838 return INVALID_HANDLE_VALUE
;
5841 RootKey
= set
->HKLM
;
5845 key
= SETUPDI_OpenDevKey(RootKey
, devInfo
, samDesired
);
5848 key
= SETUPDI_OpenDrvKey(RootKey
, devInfo
, samDesired
);
5851 WARN("unknown KeyType %d\n", KeyType
);
5853 if (RootKey
!= set
->HKLM
)
5854 RegCloseKey(RootKey
);
5858 static BOOL
SETUPDI_DeleteDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5864 static BOOL
SETUPDI_DeleteDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5870 /***********************************************************************
5871 * SetupDiDeleteDevRegKey (SETUPAPI.@)
5873 BOOL WINAPI
SetupDiDeleteDevRegKey(
5874 HDEVINFO DeviceInfoSet
,
5875 PSP_DEVINFO_DATA DeviceInfoData
,
5880 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5881 struct DeviceInfo
*devInfo
;
5885 TRACE("%p %p %d %d %d\n", DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
,
5888 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5890 SetLastError(ERROR_INVALID_HANDLE
);
5893 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5895 SetLastError(ERROR_INVALID_HANDLE
);
5898 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5899 || !DeviceInfoData
->Reserved
)
5901 SetLastError(ERROR_INVALID_PARAMETER
);
5904 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5906 SetLastError(ERROR_INVALID_FLAGS
);
5909 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
&& KeyType
!= DIREG_BOTH
)
5911 SetLastError(ERROR_INVALID_FLAGS
);
5914 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5915 if (devInfo
->set
!= set
)
5917 SetLastError(ERROR_INVALID_PARAMETER
);
5920 if (Scope
!= DICS_FLAG_GLOBAL
)
5922 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5923 if (RootKey
== INVALID_HANDLE_VALUE
)
5927 RootKey
= set
->HKLM
;
5931 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
5934 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
5937 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
5939 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
5942 WARN("unknown KeyType %d\n", KeyType
);
5944 if (RootKey
!= set
->HKLM
)
5945 RegCloseKey(RootKey
);