2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
26 /* Unicode constants */
27 static const WCHAR BackSlash
[] = {'\\',0};
28 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
29 static const WCHAR Class
[] = {'C','l','a','s','s',0};
30 static const WCHAR DateFormat
[] = {'%','u','-','%','u','-','%','u',0};
31 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
32 static const WCHAR DotHW
[] = {'.','H','W',0};
33 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
34 static const WCHAR InfDirectory
[] = {'i','n','f','\\',0};
35 static const WCHAR InstanceKeyFormat
[] = {'%','0','4','l','u',0};
36 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
37 static const WCHAR VersionFormat
[] = {'%','u','.','%','u','.','%','u','.','%','u',0};
39 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
40 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
41 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
42 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
43 static const WCHAR REGSTR_UI_NUMBER_DESC_FORMAT
[] = {'U','I','N','u','m','b','e','r','D','e','s','c','F','o','r','m','a','t',0};
46 (CALLBACK
* CLASS_INSTALL_PROC
) (
47 IN DI_FUNCTION InstallFunction
,
48 IN HDEVINFO DeviceInfoSet
,
49 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
51 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
52 IN HDEVINFO DeviceInfoSet
,
53 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
55 (CALLBACK
* COINSTALLER_PROC
) (
56 IN DI_FUNCTION InstallFunction
,
57 IN HDEVINFO DeviceInfoSet
,
58 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
59 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
61 struct CoInstallerElement
66 COINSTALLER_PROC Function
;
67 BOOL DoPostProcessing
;
71 struct GetSectionCallbackInfo
73 PSP_ALTPLATFORM_INFO PlatformInfo
;
77 WCHAR BestSection
[LINE_LEN
+ 1];
78 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
83 static void SETUPDI_GuidToString(const GUID
*guid
, LPWSTR guidStr
)
85 static const WCHAR fmt
[] = {'{','%','0','8','X','-','%','0','4','X','-',
86 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
87 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
90 sprintfW(guidStr
, fmt
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
91 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
92 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
96 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
100 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
101 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
102 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
103 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
104 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
105 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
106 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
107 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
108 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
109 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
110 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
111 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
112 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
113 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
114 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
115 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
116 case CR_SUCCESS
: return ERROR_SUCCESS
;
117 default: return ERROR_GEN_FAILURE
;
120 /* Does not happen */
123 /* Lower scores are best ones */
126 IN LPCWSTR SectionName
,
127 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
130 OUT PDWORD ScorePlatform
,
131 OUT PDWORD ScoreMajorVersion
,
132 OUT PDWORD ScoreMinorVersion
,
133 OUT PDWORD ScoreProductType
,
134 OUT PDWORD ScoreSuiteMask
)
136 LPWSTR Section
= NULL
;
137 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
142 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
143 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
144 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
146 static const WCHAR ExtensionArchitectureNone
[] = {0};
147 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
148 static const WCHAR ExtensionArchitectureamd64
[] = {'A','M','D','6','4',0};
149 static const WCHAR ExtensionArchitectureia64
[] = {'I','A','6','4',0};
150 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
151 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
152 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
154 TRACE("%s %p 0x%x 0x%x\n",
155 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
157 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
159 Section
= pSetupDuplicateString(SectionName
);
162 TRACE("pSetupDuplicateString() failed\n");
166 /* Set various extensions values */
167 switch (PlatformInfo
->Platform
)
169 case VER_PLATFORM_WIN32_WINDOWS
:
170 pExtensionPlatform
= ExtensionPlatformWindows
;
172 case VER_PLATFORM_WIN32_NT
:
173 pExtensionPlatform
= ExtensionPlatformNT
;
176 ERR("Unknown platform 0x%lx\n", PlatformInfo
->Platform
);
177 pExtensionPlatform
= ExtensionPlatformNone
;
180 switch (PlatformInfo
->ProcessorArchitecture
)
182 case PROCESSOR_ARCHITECTURE_ALPHA
:
183 pExtensionArchitecture
= ExtensionArchitecturealpha
;
185 case PROCESSOR_ARCHITECTURE_AMD64
:
186 pExtensionArchitecture
= ExtensionArchitectureamd64
;
188 case PROCESSOR_ARCHITECTURE_IA64
:
189 pExtensionArchitecture
= ExtensionArchitectureia64
;
191 case PROCESSOR_ARCHITECTURE_INTEL
:
192 pExtensionArchitecture
= ExtensionArchitecturex86
;
194 case PROCESSOR_ARCHITECTURE_MIPS
:
195 pExtensionArchitecture
= ExtensionArchitecturemips
;
197 case PROCESSOR_ARCHITECTURE_PPC
:
198 pExtensionArchitecture
= ExtensionArchitectureppc
;
201 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
202 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
203 pExtensionArchitecture
= ExtensionArchitectureNone
;
209 * Field[1] Architecture
210 * Field[2] Major version
211 * Field[3] Minor version
212 * Field[4] Product type
213 * Field[5] Suite mask
214 * Remark: lastests fields may be NULL if the information is not provided
217 if (Fields
[0] == NULL
)
219 TRACE("No extension found\n");
220 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
224 Fields
[1] = Fields
[0] + 1;
225 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
226 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
228 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
232 *(Fields
[i
] - 1) = UNICODE_NULL
;
235 /* Take care of first 2 fields */
236 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
238 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
240 TRACE("Mismatch on platform field\n");
243 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
245 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
247 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
249 TRACE("Mismatch on platform field\n");
252 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
256 /* No platform specified */
257 *ScorePlatform
|= 0x02;
259 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
261 /* No architecture specified */
262 *ScorePlatform
|= 0x01;
264 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
266 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
267 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
271 /* Check if informations are matching */
272 if (Fields
[2] && *Fields
[2])
274 DWORD MajorVersion
, MinorVersion
= 0;
275 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
276 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
277 (errno
== ERANGE
|| errno
== EINVAL
))
279 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
282 if (Fields
[3] && *Fields
[3])
284 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
285 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
286 (errno
== ERANGE
|| errno
== EINVAL
))
288 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
292 if (PlatformInfo
->MajorVersion
< MajorVersion
||
293 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
295 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
296 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
299 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
300 if (MajorVersion
== PlatformInfo
->MajorVersion
)
301 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
303 *ScoreMinorVersion
= MinorVersion
;
305 else if (Fields
[3] && *Fields
[3])
307 TRACE("Minor version found without major version\n");
312 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
313 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
316 if (Fields
[4] && *Fields
[4])
318 DWORD CurrentProductType
;
319 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
320 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
321 (errno
== ERANGE
|| errno
== EINVAL
))
323 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
326 if (CurrentProductType
!= ProductType
)
328 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
329 CurrentProductType
, ProductType
);
334 *ScoreProductType
= 1;
336 if (Fields
[5] && *Fields
[5])
338 DWORD CurrentSuiteMask
;
339 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
340 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
341 (errno
== ERANGE
|| errno
== EINVAL
))
343 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
346 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
348 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
349 CurrentSuiteMask
, SuiteMask
);
352 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
355 *ScoreSuiteMask
= SuiteMask
;
366 IN LPCWSTR SectionName
,
369 struct GetSectionCallbackInfo
*info
= Context
;
370 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
373 if (SectionName
[info
->PrefixLength
] != '.')
376 ret
= CheckSectionValid(
377 &SectionName
[info
->PrefixLength
],
381 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
384 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
387 if (Score1
> info
->BestScore1
) goto done
;
388 if (Score1
< info
->BestScore1
) goto bettersection
;
389 if (Score2
> info
->BestScore2
) goto done
;
390 if (Score2
< info
->BestScore2
) goto bettersection
;
391 if (Score3
> info
->BestScore3
) goto done
;
392 if (Score3
< info
->BestScore3
) goto bettersection
;
393 if (Score4
> info
->BestScore4
) goto done
;
394 if (Score4
< info
->BestScore4
) goto bettersection
;
395 if (Score5
> info
->BestScore5
) goto done
;
396 if (Score5
< info
->BestScore5
) goto bettersection
;
400 strcpyW(info
->BestSection
, SectionName
);
401 info
->BestScore1
= Score1
;
402 info
->BestScore2
= Score2
;
403 info
->BestScore3
= Score3
;
404 info
->BestScore4
= Score4
;
405 info
->BestScore5
= Score5
;
411 /***********************************************************************
412 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
415 SetupDiGetActualSectionToInstallExW(
417 IN PCWSTR InfSectionName
,
418 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
419 OUT PWSTR InfSectionWithExt OPTIONAL
,
420 IN DWORD InfSectionWithExtSize
,
421 OUT PDWORD RequiredSize OPTIONAL
,
422 OUT PWSTR
* Extension OPTIONAL
,
427 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
428 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
429 RequiredSize
, Extension
, Reserved
);
431 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
432 SetLastError(ERROR_INVALID_HANDLE
);
433 else if (!InfSectionName
)
434 SetLastError(ERROR_INVALID_PARAMETER
);
435 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
436 SetLastError(ERROR_INVALID_USER_BUFFER
);
437 else if (Reserved
!= NULL
)
438 SetLastError(ERROR_INVALID_PARAMETER
);
441 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
442 static BYTE CurrentProductType
= 0;
443 static WORD CurrentSuiteMask
= 0;
444 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
445 struct GetSectionCallbackInfo CallbackInfo
;
450 /* Fill platform info if needed */
451 if (AlternatePlatformInfo
)
453 pPlatformInfo
= AlternatePlatformInfo
;
459 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
461 /* That's the first time we go here. We need to fill in the structure */
462 OSVERSIONINFOEX VersionInfo
;
463 SYSTEM_INFO SystemInfo
;
464 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
465 ret
= GetVersionExW((OSVERSIONINFO
*)&VersionInfo
);
468 GetSystemInfo(&SystemInfo
);
469 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
470 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
471 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
472 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
473 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
474 CurrentPlatform
.Reserved
= 0;
475 CurrentProductType
= VersionInfo
.wProductType
;
476 CurrentSuiteMask
= VersionInfo
.wSuiteMask
;
478 ProductType
= CurrentProductType
;
479 SuiteMask
= CurrentSuiteMask
;
482 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
483 CallbackInfo
.ProductType
= ProductType
;
484 CallbackInfo
.SuiteMask
= SuiteMask
;
485 CallbackInfo
.PrefixLength
= strlenW(InfSectionName
);
486 CallbackInfo
.BestScore1
= ULONG_MAX
;
487 CallbackInfo
.BestScore2
= ULONG_MAX
;
488 CallbackInfo
.BestScore3
= ULONG_MAX
;
489 CallbackInfo
.BestScore4
= ULONG_MAX
;
490 CallbackInfo
.BestScore5
= ULONG_MAX
;
491 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
492 if (!EnumerateSectionsStartingWith(
498 SetLastError(ERROR_GEN_FAILURE
);
502 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
503 if (RequiredSize
!= NULL
)
504 *RequiredSize
= dwFullLength
+ 1;
506 if (InfSectionWithExtSize
> 0)
508 if (InfSectionWithExtSize
< dwFullLength
+ 1)
510 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
513 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
516 DWORD dwLength
= lstrlenW(InfSectionName
);
517 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
525 TRACE("Returning %d\n", ret
);
532 IN
struct DeviceInfoSet
*list
,
533 IN LPCWSTR InstancePath
,
534 IN LPCGUID pClassGuid
,
535 OUT
struct DeviceInfo
**pDeviceInfo
)
539 struct DeviceInfo
*deviceInfo
;
543 size
= FIELD_OFFSET(struct DeviceInfo
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
544 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
547 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
550 ZeroMemory(deviceInfo
, size
);
552 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
553 if (cr
!= CR_SUCCESS
)
555 SetLastError(GetErrorCodeFromCrCode(cr
));
559 deviceInfo
->set
= list
;
560 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
561 strcpyW(deviceInfo
->Data
, InstancePath
);
562 deviceInfo
->instanceId
= deviceInfo
->Data
;
563 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
564 deviceInfo
->DeviceDescription
= NULL
;
565 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
566 deviceInfo
->CreationFlags
= 0;
567 InitializeListHead(&deviceInfo
->DriverListHead
);
568 InitializeListHead(&deviceInfo
->InterfaceListHead
);
570 *pDeviceInfo
= deviceInfo
;
576 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
578 HeapFree(GetProcessHeap(), 0, installParams
->PropChangeParams
);
579 HeapFree(GetProcessHeap(), 0, installParams
->AddPropertyPageData
);
584 DestroyDeviceInfo(struct DeviceInfo
*deviceInfo
)
586 PLIST_ENTRY ListEntry
;
587 struct DriverInfoElement
*driverInfo
;
588 struct DeviceInterface
*deviceInterface
;
590 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
592 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
593 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
594 if (!DestroyDriverInfoElement(driverInfo
))
597 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
599 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
600 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
601 if (!DestroyDeviceInterface(deviceInterface
))
604 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
605 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
609 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
611 PLIST_ENTRY ListEntry
;
612 struct DeviceInfo
*deviceInfo
;
614 while (!IsListEmpty(&list
->ListHead
))
616 ListEntry
= RemoveHeadList(&list
->ListHead
);
617 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
);
618 if (!DestroyDeviceInfo(deviceInfo
))
621 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
622 RegCloseKey(list
->HKLM
);
623 CM_Disconnect_Machine(list
->hMachine
);
624 DestroyClassInstallParams(&list
->ClassInstallParams
);
625 return HeapFree(GetProcessHeap(), 0, list
);
628 /***********************************************************************
629 * SetupDiBuildClassInfoList (SETUPAPI.@)
631 * Returns a list of setup class GUIDs that identify the classes
632 * that are installed on a local machine.
635 * Flags [I] control exclusion of classes from the list.
636 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
637 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
638 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
644 BOOL WINAPI
SetupDiBuildClassInfoList(
646 LPGUID ClassGuidList
,
647 DWORD ClassGuidListSize
,
651 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
652 ClassGuidListSize
, RequiredSize
,
656 /***********************************************************************
657 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
659 * Returns a list of setup class GUIDs that identify the classes
660 * that are installed on a local or remote macine.
663 * Flags [I] control exclusion of classes from the list.
664 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
665 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
666 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
667 * MachineName [I] name of a remote machine.
668 * Reserved [I] must be NULL.
674 BOOL WINAPI
SetupDiBuildClassInfoListExA(
676 LPGUID ClassGuidList
,
677 DWORD ClassGuidListSize
,
682 LPWSTR MachineNameW
= NULL
;
685 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
686 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
690 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
691 if (MachineNameW
== NULL
) return FALSE
;
694 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
695 ClassGuidListSize
, RequiredSize
,
696 MachineNameW
, Reserved
);
698 MyFree(MachineNameW
);
703 /***********************************************************************
704 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
706 * Returns a list of setup class GUIDs that identify the classes
707 * that are installed on a local or remote macine.
710 * Flags [I] control exclusion of classes from the list.
711 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
712 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
713 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
714 * MachineName [I] name of a remote machine.
715 * Reserved [I] must be NULL.
721 BOOL WINAPI
SetupDiBuildClassInfoListExW(
723 LPGUID ClassGuidList
,
724 DWORD ClassGuidListSize
,
730 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
735 DWORD dwGuidListIndex
= 0;
737 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
738 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
742 SetLastError(ERROR_INVALID_PARAMETER
);
745 else if (!ClassGuidList
&& ClassGuidListSize
> 0)
747 SetLastError(ERROR_INVALID_PARAMETER
);
751 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
752 KEY_ENUMERATE_SUB_KEYS
,
756 if (hClassesKey
== INVALID_HANDLE_VALUE
)
761 for (dwIndex
= 0; ; dwIndex
++)
764 lError
= RegEnumKeyExW(hClassesKey
,
772 TRACE("RegEnumKeyExW() returns %d\n", lError
);
773 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
775 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
777 if (RegOpenKeyExW(hClassesKey
,
783 RegCloseKey(hClassesKey
);
787 if (!RegQueryValueExW(hClassKey
,
788 REGSTR_VAL_NOUSECLASS
,
794 TRACE("'NoUseClass' value found!\n");
795 RegCloseKey(hClassKey
);
799 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
800 (!RegQueryValueExW(hClassKey
,
801 REGSTR_VAL_NOINSTALLCLASS
,
807 TRACE("'NoInstallClass' value found!\n");
808 RegCloseKey(hClassKey
);
812 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
813 (!RegQueryValueExW(hClassKey
,
814 REGSTR_VAL_NODISPLAYCLASS
,
820 TRACE("'NoDisplayClass' value found!\n");
821 RegCloseKey(hClassKey
);
825 RegCloseKey(hClassKey
);
827 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
828 if (dwGuidListIndex
< ClassGuidListSize
)
830 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
834 TRACE("Guid: %p\n", &szKeyName
[1]);
836 UuidFromStringW(&szKeyName
[1],
837 &ClassGuidList
[dwGuidListIndex
]);
843 if (lError
!= ERROR_SUCCESS
)
847 RegCloseKey(hClassesKey
);
849 if (RequiredSize
!= NULL
)
850 *RequiredSize
= dwGuidListIndex
;
852 if (ClassGuidListSize
< dwGuidListIndex
)
854 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
861 /***********************************************************************
862 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
864 BOOL WINAPI
SetupDiClassGuidsFromNameA(
866 LPGUID ClassGuidList
,
867 DWORD ClassGuidListSize
,
870 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
871 ClassGuidListSize
, RequiredSize
,
875 /***********************************************************************
876 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
878 BOOL WINAPI
SetupDiClassGuidsFromNameW(
880 LPGUID ClassGuidList
,
881 DWORD ClassGuidListSize
,
884 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
885 ClassGuidListSize
, RequiredSize
,
889 /***********************************************************************
890 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
892 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
894 LPGUID ClassGuidList
,
895 DWORD ClassGuidListSize
,
900 LPWSTR ClassNameW
= NULL
;
901 LPWSTR MachineNameW
= NULL
;
904 TRACE("%s %p %lu %p %s %p\n", debugstr_a(ClassName
), ClassGuidList
,
905 ClassGuidListSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
909 SetLastError(ERROR_INVALID_PARAMETER
);
913 ClassNameW
= pSetupMultiByteToUnicode(ClassName
, CP_ACP
);
914 if (ClassNameW
== NULL
)
919 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
920 if (MachineNameW
== NULL
)
927 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
928 ClassGuidListSize
, RequiredSize
,
929 MachineNameW
, Reserved
);
931 MyFree(MachineNameW
);
937 /***********************************************************************
938 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
940 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
942 LPGUID ClassGuidList
,
943 DWORD ClassGuidListSize
,
949 WCHAR szClassName
[MAX_CLASS_NAME_LEN
];
955 DWORD dwGuidListIndex
= 0;
957 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
958 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
960 if (!ClassName
|| !RequiredSize
)
962 SetLastError(ERROR_INVALID_PARAMETER
);
965 if (!ClassGuidList
&& ClassGuidListSize
> 0)
967 SetLastError(ERROR_INVALID_PARAMETER
);
972 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
973 KEY_ENUMERATE_SUB_KEYS
,
977 if (hClassesKey
== INVALID_HANDLE_VALUE
)
982 for (dwIndex
= 0; ; dwIndex
++)
985 lError
= RegEnumKeyExW(hClassesKey
,
993 TRACE("RegEnumKeyExW() returns %d\n", lError
);
994 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
996 TRACE("Key name: %p\n", szKeyName
);
998 if (RegOpenKeyExW(hClassesKey
,
1004 RegCloseKey(hClassesKey
);
1008 dwLength
= MAX_CLASS_NAME_LEN
* sizeof(WCHAR
);
1009 if (!RegQueryValueExW(hClassKey
,
1013 (LPBYTE
)szClassName
,
1016 TRACE("Class name: %p\n", szClassName
);
1018 if (strcmpiW(szClassName
, ClassName
) == 0)
1020 TRACE("Found matching class name\n");
1022 TRACE("Guid: %p\n", szKeyName
);
1023 if (dwGuidListIndex
< ClassGuidListSize
)
1025 if (szKeyName
[0] == '{' && szKeyName
[37] == '}')
1029 TRACE("Guid: %p\n", &szKeyName
[1]);
1031 UuidFromStringW(&szKeyName
[1],
1032 &ClassGuidList
[dwGuidListIndex
]);
1039 RegCloseKey(hClassKey
);
1042 if (lError
!= ERROR_SUCCESS
)
1046 RegCloseKey(hClassesKey
);
1048 if (RequiredSize
!= NULL
)
1049 *RequiredSize
= dwGuidListIndex
;
1051 if (ClassGuidListSize
< dwGuidListIndex
)
1053 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1060 /***********************************************************************
1061 * SetupDiClassNameFromGuidA (SETUPAPI.@)
1063 BOOL WINAPI
SetupDiClassNameFromGuidA(
1064 const GUID
* ClassGuid
,
1066 DWORD ClassNameSize
,
1067 PDWORD RequiredSize
)
1069 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
1070 ClassNameSize
, RequiredSize
,
1074 /***********************************************************************
1075 * SetupDiClassNameFromGuidW (SETUPAPI.@)
1077 BOOL WINAPI
SetupDiClassNameFromGuidW(
1078 const GUID
* ClassGuid
,
1080 DWORD ClassNameSize
,
1081 PDWORD RequiredSize
)
1083 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
1084 ClassNameSize
, RequiredSize
,
1088 /***********************************************************************
1089 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
1091 BOOL WINAPI
SetupDiClassNameFromGuidExA(
1092 const GUID
* ClassGuid
,
1094 DWORD ClassNameSize
,
1095 PDWORD RequiredSize
,
1099 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
1100 LPWSTR MachineNameW
= NULL
;
1104 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1105 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
1106 RequiredSize
, MachineNameW
, Reserved
);
1109 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
1110 ClassNameSize
, NULL
, NULL
);
1111 if (len
== 0 || len
> ClassNameSize
)
1113 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1117 MyFree(MachineNameW
);
1121 /***********************************************************************
1122 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
1124 BOOL WINAPI
SetupDiClassNameFromGuidExW(
1125 const GUID
* ClassGuid
,
1127 DWORD ClassNameSize
,
1128 PDWORD RequiredSize
,
1138 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
1139 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1141 /* Make sure there's a GUID */
1142 if (ClassGuid
== NULL
)
1144 SetLastError(ERROR_INVALID_CLASS
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1148 /* Make sure there's a real buffer when there's a size */
1149 if ((ClassNameSize
> 0) && (ClassName
== NULL
))
1151 SetLastError(ERROR_INVALID_PARAMETER
); /* On Vista: ERROR_INVALID_USER_BUFFER */
1155 /* Open the key for the GUID */
1156 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INSTALLER
, MachineName
, Reserved
);
1158 if (hKey
== INVALID_HANDLE_VALUE
)
1161 /* Retrieve the class name data and close the key */
1162 rc
= QueryRegistryValue(hKey
, Class
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
1165 /* Make sure we got the data */
1166 if (rc
!= ERROR_SUCCESS
)
1172 /* Make sure the data is a string */
1173 if (dwRegType
!= REG_SZ
)
1176 SetLastError(ERROR_GEN_FAILURE
);
1180 /* Determine the length of the class name */
1181 dwLength
/= sizeof(WCHAR
);
1183 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
1184 /* Count the null-terminator */
1187 /* Inform the caller about the class name */
1188 if ((ClassName
!= NULL
) && (dwLength
<= ClassNameSize
))
1190 memcpy(ClassName
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
1191 ClassName
[dwLength
- 1] = UNICODE_NULL
;
1194 /* Inform the caller about the required size */
1195 if (RequiredSize
!= NULL
)
1196 *RequiredSize
= dwLength
;
1198 /* Clean up the buffer */
1201 /* Make sure the buffer was large enough */
1202 if ((ClassName
== NULL
) || (dwLength
> ClassNameSize
))
1204 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1211 /***********************************************************************
1212 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
1215 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
1218 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
1221 /***********************************************************************
1222 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
1225 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
1230 LPWSTR MachineNameW
= NULL
;
1233 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1234 debugstr_a(MachineName
), Reserved
);
1238 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
1239 if (MachineNameW
== NULL
)
1240 return INVALID_HANDLE_VALUE
;
1243 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
1244 MachineNameW
, Reserved
);
1246 MyFree(MachineNameW
);
1251 /***********************************************************************
1252 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
1254 * Create an empty DeviceInfoSet list.
1257 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
1259 * hwndParent [I] hwnd needed for interface related actions.
1260 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
1261 * local registry will be used.
1262 * Reserved [I] must be NULL
1265 * Success: empty list.
1266 * Failure: INVALID_HANDLE_VALUE.
1269 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
1274 struct DeviceInfoSet
*list
= NULL
;
1275 DWORD size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
1278 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1280 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
1281 debugstr_w(MachineName
), Reserved
);
1283 if (MachineName
!= NULL
)
1285 SIZE_T len
= strlenW(MachineName
);
1286 if (len
>= SP_MAX_MACHINENAME_LENGTH
- 4)
1288 SetLastError(ERROR_INVALID_MACHINENAME
);
1292 size
+= (len
+ 3) * sizeof(WCHAR
);
1297 if (Reserved
!= NULL
)
1299 SetLastError(ERROR_INVALID_PARAMETER
);
1300 return INVALID_HANDLE_VALUE
;
1303 list
= MyMalloc(size
);
1306 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1307 return INVALID_HANDLE_VALUE
;
1309 ZeroMemory(list
, FIELD_OFFSET(struct DeviceInfoSet
, szData
));
1311 list
->magic
= SETUP_DEVICE_INFO_SET_MAGIC
;
1312 memcpy(&list
->ClassGuid
,
1313 ClassGuid
? ClassGuid
: &GUID_NULL
,
1314 sizeof(list
->ClassGuid
));
1315 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1316 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
1317 list
->InstallParams
.hwndParent
= hwndParent
;
1320 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
1321 if (rc
!= ERROR_SUCCESS
)
1323 SetLastError(ERROR_INVALID_MACHINENAME
);
1327 list
->szData
[0] = list
->szData
[1] = '\\';
1328 strcpyW(list
->szData
+ 2, MachineName
);
1329 list
->MachineName
= list
->szData
;
1333 list
->HKLM
= HKEY_LOCAL_MACHINE
;
1334 list
->MachineName
= NULL
;
1336 cr
= CM_Connect_MachineW(list
->MachineName
, &list
->hMachine
);
1337 if (cr
!= CR_SUCCESS
)
1339 SetLastError(GetErrorCodeFromCrCode(cr
));
1342 InitializeListHead(&list
->DriverListHead
);
1343 InitializeListHead(&list
->ListHead
);
1345 return (HDEVINFO
)list
;
1348 if (ret
== INVALID_HANDLE_VALUE
)
1352 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
1353 RegCloseKey(list
->HKLM
);
1360 /***********************************************************************
1361 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
1363 HKEY WINAPI
SetupDiCreateDevRegKeyA(
1364 HDEVINFO DeviceInfoSet
,
1365 PSP_DEVINFO_DATA DeviceInfoData
,
1370 PCSTR InfSectionName
)
1372 PWSTR InfSectionNameW
= NULL
;
1375 TRACE("%p %p %d %d %d %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1376 HwProfile
, KeyType
, InfHandle
, debugstr_a(InfSectionName
));
1380 if (!InfSectionName
)
1382 SetLastError(ERROR_INVALID_PARAMETER
);
1383 return INVALID_HANDLE_VALUE
;
1387 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
1388 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
1391 key
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, Scope
,
1392 HwProfile
, KeyType
, InfHandle
, InfSectionNameW
);
1393 MyFree(InfSectionNameW
);
1398 OpenHardwareProfileKey(
1401 IN DWORD samDesired
);
1403 /***********************************************************************
1404 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
1406 HKEY WINAPI
SetupDiCreateDevRegKeyW(
1407 HDEVINFO DeviceInfoSet
,
1408 PSP_DEVINFO_DATA DeviceInfoData
,
1413 PCWSTR InfSectionName
)
1415 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1416 HKEY key
= INVALID_HANDLE_VALUE
;
1417 LPWSTR lpGuidString
= NULL
;
1418 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
1419 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
1420 DWORD Index
; /* Index used in the DriverKey name */
1424 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
1425 HKEY hEnumKey
= NULL
;
1426 HKEY hClassKey
= NULL
;
1427 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
1431 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
, Scope
,
1432 HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
1434 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1436 SetLastError(ERROR_INVALID_HANDLE
);
1437 return INVALID_HANDLE_VALUE
;
1439 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1441 SetLastError(ERROR_INVALID_HANDLE
);
1442 return INVALID_HANDLE_VALUE
;
1444 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1445 || !DeviceInfoData
->Reserved
)
1447 SetLastError(ERROR_INVALID_PARAMETER
);
1448 return INVALID_HANDLE_VALUE
;
1450 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
1452 SetLastError(ERROR_INVALID_FLAGS
);
1453 return INVALID_HANDLE_VALUE
;
1455 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
1457 SetLastError(ERROR_INVALID_FLAGS
);
1458 return INVALID_HANDLE_VALUE
;
1460 if (InfHandle
&& !InfSectionName
)
1462 SetLastError(ERROR_INVALID_PARAMETER
);
1463 return INVALID_HANDLE_VALUE
;
1465 if (!InfHandle
&& InfSectionName
)
1467 SetLastError(ERROR_INVALID_PARAMETER
);
1468 return INVALID_HANDLE_VALUE
;
1471 if (Scope
== DICS_FLAG_GLOBAL
)
1472 RootKey
= set
->HKLM
;
1473 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
1475 hHWProfileKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
1476 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
1478 RootKey
= hHWProfileKey
;
1481 if (KeyType
== DIREG_DEV
)
1483 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
1485 rc
= RegCreateKeyExW(
1487 REGSTR_PATH_SYSTEMENUM
,
1490 REG_OPTION_NON_VOLATILE
,
1495 if (rc
!= ERROR_SUCCESS
)
1500 rc
= RegCreateKeyExW(
1502 deviceInfo
->instanceId
,
1505 REG_OPTION_NON_VOLATILE
,
1506 #if _WIN32_WINNT >= 0x502
1507 KEY_READ
| KEY_WRITE
,
1514 if (rc
!= ERROR_SUCCESS
)
1520 else /* KeyType == DIREG_DRV */
1522 /* Open device key, to read Driver value */
1523 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
1524 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
1527 rc
= RegOpenKeyExW(RootKey
, REGSTR_PATH_CLASS_NT
, 0, KEY_CREATE_SUB_KEY
, &hClassKey
);
1528 if (rc
!= ERROR_SUCCESS
)
1534 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, NULL
, &dwSize
);
1535 if (rc
!= ERROR_SUCCESS
)
1537 /* Create a new driver key */
1539 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
1542 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
1543 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
1546 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1551 strcpyW(&DriverKey
[1], lpGuidString
);
1552 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
1553 *pDeviceInstance
++ = '}';
1554 *pDeviceInstance
++ = '\\';
1556 /* Try all values for Index between 0 and 9999 */
1558 while (Index
<= 9999)
1560 sprintfW(pDeviceInstance
, InstanceKeyFormat
, Index
);
1561 rc
= RegCreateKeyExW(hClassKey
,
1565 REG_OPTION_NON_VOLATILE
,
1566 #if _WIN32_WINNT >= 0x502
1567 KEY_READ
| KEY_WRITE
,
1574 if (rc
!= ERROR_SUCCESS
)
1579 if (Disposition
== REG_CREATED_NEW_KEY
)
1588 /* Unable to create more than 9999 devices within the same class */
1589 SetLastError(ERROR_GEN_FAILURE
);
1593 /* Write the new Driver value */
1594 rc
= RegSetValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
1595 if (rc
!= ERROR_SUCCESS
)
1604 /* Open the existing driver key */
1606 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwSize
);
1609 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1613 rc
= RegQueryValueExW(hDeviceKey
, REGSTR_VAL_DRIVER
, NULL
, NULL
, (LPBYTE
)DriverKey
, &dwSize
);
1614 if (rc
!= ERROR_SUCCESS
)
1620 rc
= RegCreateKeyExW(hClassKey
,
1624 REG_OPTION_NON_VOLATILE
,
1625 #if _WIN32_WINNT >= 0x502
1626 KEY_READ
| KEY_WRITE
,
1633 if (rc
!= ERROR_SUCCESS
)
1641 /* Do installation of the specified section */
1644 FIXME("Need to install section %s in file %p\n",
1645 debugstr_w(InfSectionName
), InfHandle
);
1651 RpcStringFreeW(&lpGuidString
);
1652 HeapFree(GetProcessHeap(), 0, DriverKey
);
1653 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
1654 RegCloseKey(hHWProfileKey
);
1655 if (hEnumKey
!= NULL
)
1656 RegCloseKey(hEnumKey
);
1657 if (hClassKey
!= NULL
)
1658 RegCloseKey(hClassKey
);
1659 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
1660 RegCloseKey(hDeviceKey
);
1661 if (hKey
!= NULL
&& hKey
!= key
)
1664 TRACE("Returning 0x%p\n", key
);
1668 /***********************************************************************
1669 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1671 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1672 HDEVINFO DeviceInfoSet
,
1674 CONST GUID
*ClassGuid
,
1675 PCSTR DeviceDescription
,
1677 DWORD CreationFlags
,
1678 PSP_DEVINFO_DATA DeviceInfoData
)
1681 LPWSTR DeviceNameW
= NULL
;
1682 LPWSTR DeviceDescriptionW
= NULL
;
1688 DeviceNameW
= pSetupMultiByteToUnicode(DeviceName
, CP_ACP
);
1689 if (DeviceNameW
== NULL
) return FALSE
;
1691 if (DeviceDescription
)
1693 DeviceDescriptionW
= pSetupMultiByteToUnicode(DeviceDescription
, CP_ACP
);
1694 if (DeviceDescriptionW
== NULL
)
1696 MyFree(DeviceNameW
);
1701 ret
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
, ClassGuid
, DeviceDescriptionW
,
1702 hwndParent
, CreationFlags
, DeviceInfoData
);
1704 MyFree(DeviceNameW
);
1705 MyFree(DeviceDescriptionW
);
1710 /***********************************************************************
1711 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1713 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1714 HDEVINFO DeviceInfoSet
,
1716 CONST GUID
*ClassGuid
,
1717 PCWSTR DeviceDescription
,
1719 DWORD CreationFlags
,
1720 PSP_DEVINFO_DATA DeviceInfoData
)
1722 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1723 struct DeviceInfo
*deviceInfo
= NULL
;
1726 DEVINST RootDevInst
;
1729 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
1730 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
1731 hwndParent
, CreationFlags
, DeviceInfoData
);
1735 SetLastError(ERROR_INVALID_DEVINST_NAME
);
1738 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1740 SetLastError(ERROR_INVALID_HANDLE
);
1745 SetLastError(ERROR_INVALID_PARAMETER
);
1748 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1750 SetLastError(ERROR_INVALID_HANDLE
);
1753 if (!IsEqualGUID(&set
->ClassGuid
, &GUID_NULL
) &&
1754 !IsEqualGUID(ClassGuid
, &set
->ClassGuid
))
1756 SetLastError(ERROR_CLASS_MISMATCH
);
1759 if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
1761 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
1762 SetLastError(ERROR_INVALID_FLAGS
);
1766 /* Get the root device instance */
1767 cr
= CM_Locate_DevInst_ExW(&RootDevInst
,
1769 CM_LOCATE_DEVINST_NORMAL
,
1771 if (cr
!= CR_SUCCESS
)
1773 SetLastError(ERROR_INVALID_DATA
);
1777 /* Create the new device instance */
1778 cr
= CM_Create_DevInst_ExW(&DevInst
,
1779 (DEVINSTID
)DeviceName
,
1783 if (cr
!= CR_SUCCESS
)
1785 SetLastError(ERROR_INVALID_DATA
);
1789 if (CreateDeviceInfo(set
, DeviceName
, ClassGuid
, &deviceInfo
))
1791 InsertTailList(&set
->ListHead
, &deviceInfo
->ListEntry
);
1793 if (!DeviceInfoData
)
1797 if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1799 SetLastError(ERROR_INVALID_USER_BUFFER
);
1803 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
1804 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
1805 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
1813 if (deviceInfo
!= NULL
)
1815 /* Remove deviceInfo from List */
1816 RemoveEntryList(&deviceInfo
->ListEntry
);
1818 /* Destroy deviceInfo */
1819 DestroyDeviceInfo(deviceInfo
);
1823 TRACE("Returning %d\n", ret
);
1827 /***********************************************************************
1828 * SetupDiRegisterDeviceInfo (SETUPAPI.@)
1830 BOOL WINAPI
SetupDiRegisterDeviceInfo(
1831 HDEVINFO DeviceInfoSet
,
1832 PSP_DEVINFO_DATA DeviceInfoData
,
1834 PSP_DETSIG_CMPPROC CompareProc
,
1835 PVOID CompareContext
,
1836 PSP_DEVINFO_DATA DupDeviceInfoData
)
1838 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1840 TRACE("%p %p %08x %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1841 CompareProc
, CompareContext
, DupDeviceInfoData
);
1843 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
1845 SetLastError(ERROR_INVALID_HANDLE
);
1848 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
1850 SetLastError(ERROR_INVALID_HANDLE
);
1853 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
1854 || !DeviceInfoData
->Reserved
)
1856 SetLastError(ERROR_INVALID_PARAMETER
);
1859 FIXME("Stub %p %p 0x%lx %p %p %p\n", DeviceInfoSet
, DeviceInfoData
, Flags
,
1860 CompareProc
, CompareContext
, DupDeviceInfoData
);
1861 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1865 /***********************************************************************
1866 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1868 BOOL WINAPI
SetupDiEnumDeviceInfo(
1871 PSP_DEVINFO_DATA info
)
1875 TRACE("%p %d %p\n", devinfo
, index
, info
);
1879 SetLastError(ERROR_INVALID_PARAMETER
);
1882 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
1884 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
1885 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
1887 if (info
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
1888 SetLastError(ERROR_INVALID_USER_BUFFER
);
1891 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
1892 while (ItemList
!= &list
->ListHead
&& index
-- > 0)
1893 ItemList
= ItemList
->Flink
;
1894 if (ItemList
== &list
->ListHead
)
1895 SetLastError(ERROR_NO_MORE_ITEMS
);
1898 struct DeviceInfo
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
1899 memcpy(&info
->ClassGuid
,
1900 &DevInfo
->ClassGuid
,
1902 info
->DevInst
= DevInfo
->dnDevInst
;
1903 info
->Reserved
= (ULONG_PTR
)DevInfo
;
1909 SetLastError(ERROR_INVALID_HANDLE
);
1912 SetLastError(ERROR_INVALID_HANDLE
);
1916 /***********************************************************************
1917 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1919 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
1920 HDEVINFO DeviceInfoSet
,
1921 PSP_DEVINFO_DATA DeviceInfoData
,
1922 PSTR DeviceInstanceId
,
1923 DWORD DeviceInstanceIdSize
,
1924 PDWORD RequiredSize
)
1930 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1931 DeviceInstanceIdSize
, RequiredSize
);
1933 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
1935 SetLastError(ERROR_INVALID_PARAMETER
);
1939 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1944 if (!ret
&& GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
1946 instanceId
= MyMalloc(size
* sizeof(WCHAR
));
1949 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
,
1956 int len
= WideCharToMultiByte(CP_ACP
, 0, instanceId
, -1,
1958 DeviceInstanceIdSize
, NULL
, NULL
);
1964 if (len
> DeviceInstanceIdSize
)
1966 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1970 *RequiredSize
= len
;
1978 *RequiredSize
= size
;
1979 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1985 /***********************************************************************
1986 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1988 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
1989 HDEVINFO DeviceInfoSet
,
1990 PSP_DEVINFO_DATA DeviceInfoData
,
1991 PWSTR DeviceInstanceId
,
1992 DWORD DeviceInstanceIdSize
,
1993 PDWORD RequiredSize
)
1995 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
1996 struct DeviceInfo
*devInfo
;
1998 TRACE("%p %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstanceId
,
1999 DeviceInstanceIdSize
, RequiredSize
);
2001 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2003 SetLastError(ERROR_INVALID_HANDLE
);
2006 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2008 SetLastError(ERROR_INVALID_HANDLE
);
2011 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2012 || !DeviceInfoData
->Reserved
)
2014 SetLastError(ERROR_INVALID_PARAMETER
);
2017 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2018 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
2020 SetLastError(ERROR_INVALID_PARAMETER
);
2023 if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
2025 SetLastError(ERROR_INVALID_PARAMETER
);
2028 TRACE("instance ID: %s\n", debugstr_w(devInfo
->instanceId
));
2029 if (DeviceInstanceIdSize
< lstrlenW(devInfo
->instanceId
) + 1)
2031 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2033 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
2036 lstrcpyW(DeviceInstanceId
, devInfo
->instanceId
);
2038 *RequiredSize
= lstrlenW(devInfo
->instanceId
) + 1;
2042 /***********************************************************************
2043 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
2045 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
2047 PCSTR InfSectionName
,
2048 PSTR InfSectionWithExt
,
2049 DWORD InfSectionWithExtSize
,
2050 PDWORD RequiredSize
,
2053 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
2054 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2058 /***********************************************************************
2059 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
2061 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
2063 PCWSTR InfSectionName
,
2064 PWSTR InfSectionWithExt
,
2065 DWORD InfSectionWithExtSize
,
2066 PDWORD RequiredSize
,
2069 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
2070 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
2074 /***********************************************************************
2075 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
2078 SetupDiGetActualSectionToInstallExA(
2080 IN PCSTR InfSectionName
,
2081 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
2082 OUT PSTR InfSectionWithExt OPTIONAL
,
2083 IN DWORD InfSectionWithExtSize
,
2084 OUT PDWORD RequiredSize OPTIONAL
,
2085 OUT PSTR
* Extension OPTIONAL
,
2088 LPWSTR InfSectionNameW
= NULL
;
2089 LPWSTR InfSectionWithExtW
= NULL
;
2091 BOOL bResult
= FALSE
;
2097 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2098 if (InfSectionNameW
== NULL
)
2101 if (InfSectionWithExt
)
2103 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
2104 if (InfSectionWithExtW
== NULL
)
2108 bResult
= SetupDiGetActualSectionToInstallExW(
2109 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
2110 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
2111 InfSectionWithExtSize
,
2113 Extension
? &ExtensionW
: NULL
,
2116 if (bResult
&& InfSectionWithExt
)
2118 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
2119 InfSectionWithExtSize
, NULL
, NULL
) != 0;
2121 if (bResult
&& Extension
)
2123 if (ExtensionW
== NULL
)
2126 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
2130 MyFree(InfSectionNameW
);
2131 MyFree(InfSectionWithExtW
);
2136 /***********************************************************************
2137 * SetupDiGetClassDescriptionA (SETUPAPI.@)
2139 BOOL WINAPI
SetupDiGetClassDescriptionA(
2140 const GUID
* ClassGuid
,
2141 PSTR ClassDescription
,
2142 DWORD ClassDescriptionSize
,
2143 PDWORD RequiredSize
)
2145 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
2146 ClassDescriptionSize
,
2147 RequiredSize
, NULL
, NULL
);
2150 /***********************************************************************
2151 * SetupDiGetClassDescriptionW (SETUPAPI.@)
2153 BOOL WINAPI
SetupDiGetClassDescriptionW(
2154 const GUID
* ClassGuid
,
2155 PWSTR ClassDescription
,
2156 DWORD ClassDescriptionSize
,
2157 PDWORD RequiredSize
)
2159 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
2160 ClassDescriptionSize
,
2161 RequiredSize
, NULL
, NULL
);
2164 /***********************************************************************
2165 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
2167 BOOL WINAPI
SetupDiGetClassDescriptionExA(
2168 const GUID
* ClassGuid
,
2169 PSTR ClassDescription
,
2170 DWORD ClassDescriptionSize
,
2171 PDWORD RequiredSize
,
2175 PWCHAR ClassDescriptionW
= NULL
;
2176 LPWSTR MachineNameW
= NULL
;
2179 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2180 ClassDescriptionSize
, RequiredSize
, debugstr_a(MachineName
), Reserved
);
2182 if (ClassDescriptionSize
> 0)
2184 ClassDescriptionW
= MyMalloc(ClassDescriptionSize
* sizeof(WCHAR
));
2185 if (!ClassDescriptionW
)
2187 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2194 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
2197 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2202 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
,
2203 ClassDescriptionSize
* sizeof(WCHAR
), RequiredSize
, MachineNameW
, Reserved
);
2206 DWORD len
= (DWORD
)WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
2207 ClassDescriptionSize
, NULL
, NULL
);
2208 if (len
== 0 || len
> ClassDescriptionSize
)
2210 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2216 MyFree(ClassDescriptionW
);
2217 MyFree(MachineNameW
);
2221 /***********************************************************************
2222 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
2224 BOOL WINAPI
SetupDiGetClassDescriptionExW(
2225 const GUID
* ClassGuid
,
2226 PWSTR ClassDescription
,
2227 DWORD ClassDescriptionSize
,
2228 PDWORD RequiredSize
,
2238 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
2239 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
2241 /* Make sure there's a GUID */
2244 SetLastError(ERROR_INVALID_PARAMETER
);
2248 /* Make sure there's a real buffer when there's a size */
2249 if (!ClassDescription
&& ClassDescriptionSize
> 0)
2251 SetLastError(ERROR_INVALID_PARAMETER
);
2255 /* Open the key for the GUID */
2256 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
2261 if (hKey
== INVALID_HANDLE_VALUE
)
2264 /* Retrieve the class description data and close the key */
2265 rc
= QueryRegistryValue(hKey
, NULL
, (LPBYTE
*) &Buffer
, &dwRegType
, &dwLength
);
2268 /* Make sure we got the data */
2269 if (rc
!= ERROR_SUCCESS
)
2275 /* Make sure the data is a string */
2276 if (dwRegType
!= REG_SZ
)
2279 SetLastError(ERROR_GEN_FAILURE
);
2283 /* Determine the length of the class description */
2284 dwLength
/= sizeof(WCHAR
);
2286 /* Count the null-terminator if none is present */
2287 if ((dwLength
== 0) || (Buffer
[dwLength
- 1] != UNICODE_NULL
))
2290 /* Inform the caller about the class description */
2291 if ((ClassDescription
!= NULL
) && (dwLength
<= ClassDescriptionSize
))
2293 memcpy(ClassDescription
, Buffer
, (dwLength
- 1) * sizeof(WCHAR
));
2294 ClassDescription
[dwLength
- 1] = UNICODE_NULL
;
2297 /* Inform the caller about the required size */
2298 if (RequiredSize
!= NULL
)
2299 *RequiredSize
= dwLength
;
2301 /* Clean up the buffer */
2304 /* Make sure the buffer was large enough */
2305 if ((ClassDescription
== NULL
) || (dwLength
> ClassDescriptionSize
))
2307 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2314 /***********************************************************************
2315 * SetupDiGetClassDevsA (SETUPAPI.@)
2317 HDEVINFO WINAPI
SetupDiGetClassDevsA(
2323 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
2324 flags
, NULL
, NULL
, NULL
);
2327 /***********************************************************************
2328 * SetupDiGetClassDevsExA (SETUPAPI.@)
2330 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
2340 LPWSTR enumstrW
= NULL
, machineW
= NULL
;
2344 enumstrW
= pSetupMultiByteToUnicode(enumstr
, CP_ACP
);
2347 ret
= INVALID_HANDLE_VALUE
;
2353 machineW
= pSetupMultiByteToUnicode(machine
, CP_ACP
);
2357 ret
= INVALID_HANDLE_VALUE
;
2361 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
,
2362 machineW
, reserved
);
2370 /***********************************************************************
2371 * SetupDiGetClassDevsW (SETUPAPI.@)
2373 HDEVINFO WINAPI
SetupDiGetClassDevsW(
2379 return SetupDiGetClassDevsExW(class, enumstr
, parent
, flags
, NULL
, NULL
,
2383 /***********************************************************************
2384 * SetupDiGetClassDevsExW (SETUPAPI.@)
2386 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
2395 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2396 struct DeviceInfoSet
*list
;
2397 CONST GUID
*pClassGuid
;
2399 HDEVINFO set
= INVALID_HANDLE_VALUE
;
2401 TRACE("%s %s %p 0x%08x %p %s %p\n", debugstr_guid(class),
2402 debugstr_w(enumstr
), parent
, flags
, deviceset
, debugstr_w(machine
),
2405 if (!(flags
& DIGCF_ALLCLASSES
) && !class)
2407 SetLastError(ERROR_INVALID_PARAMETER
);
2408 return INVALID_HANDLE_VALUE
;
2411 /* Create the deviceset if not set */
2414 list
= (struct DeviceInfoSet
*)deviceset
;
2415 if (list
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2417 SetLastError(ERROR_INVALID_HANDLE
);
2420 hDeviceInfo
= deviceset
;
2424 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2425 flags
& (DIGCF_DEVICEINTERFACE
| DIGCF_ALLCLASSES
) ? NULL
: class,
2426 NULL
, machine
, NULL
);
2427 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2429 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2432 if (flags
& DIGCF_PROFILE
)
2433 FIXME(": flag DIGCF_PROFILE ignored\n");
2435 if (flags
& DIGCF_DEVICEINTERFACE
)
2439 SetLastError(ERROR_INVALID_PARAMETER
);
2442 rc
= SETUP_CreateInterfaceList(list
, machine
, class, enumstr
, flags
& DIGCF_PRESENT
);
2446 /* Determine which class(es) should be included in the deviceset */
2447 if (flags
& DIGCF_ALLCLASSES
)
2449 /* The caller wants all classes. Check if
2450 * the deviceset limits us to one class */
2451 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2454 pClassGuid
= &list
->ClassGuid
;
2458 /* The caller wants one class. Check if it matches deviceset class */
2459 if (IsEqualIID(&list
->ClassGuid
, class)
2460 || IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2466 SetLastError(ERROR_INVALID_PARAMETER
);
2470 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2472 /* No class specified. Try to use the one of the deviceset */
2473 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2474 pClassGuid
= &list
->ClassGuid
;
2477 SetLastError(ERROR_INVALID_PARAMETER
);
2483 SetLastError(ERROR_INVALID_PARAMETER
);
2486 rc
= SETUP_CreateDevicesList(list
, machine
, pClassGuid
, enumstr
);
2488 if (rc
!= ERROR_SUCCESS
)
2496 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= set
)
2497 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2501 /***********************************************************************
2502 * SetupDiGetDeviceInfoListDetailA (SETUPAPI.@)
2504 BOOL WINAPI
SetupDiGetDeviceInfoListDetailA(
2505 HDEVINFO DeviceInfoSet
,
2506 PSP_DEVINFO_LIST_DETAIL_DATA_A DevInfoData
)
2508 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2510 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2512 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2514 SetLastError(ERROR_INVALID_HANDLE
);
2517 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2519 SetLastError(ERROR_INVALID_HANDLE
);
2523 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_A
))
2525 SetLastError(ERROR_INVALID_PARAMETER
);
2528 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2529 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2530 if (set
->MachineName
)
2533 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2537 DevInfoData
->RemoteMachineName
[0] = 0;
2542 /***********************************************************************
2543 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
2545 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
2546 HDEVINFO DeviceInfoSet
,
2547 PSP_DEVINFO_LIST_DETAIL_DATA_W DevInfoData
)
2549 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2551 TRACE("%p %p\n", DeviceInfoSet
, DevInfoData
);
2553 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2555 SetLastError(ERROR_INVALID_HANDLE
);
2558 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2560 SetLastError(ERROR_INVALID_HANDLE
);
2564 DevInfoData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
2566 SetLastError(ERROR_INVALID_PARAMETER
);
2569 memcpy(&DevInfoData
->ClassGuid
, &set
->ClassGuid
, sizeof(GUID
));
2570 DevInfoData
->RemoteMachineHandle
= set
->hMachine
;
2571 if (set
->MachineName
)
2572 strcpyW(DevInfoData
->RemoteMachineName
, set
->MachineName
+ 2);
2574 DevInfoData
->RemoteMachineName
[0] = 0;
2579 /***********************************************************************
2580 * SetupDiCreateDeviceInterfaceA (SETUPAPI.@)
2582 BOOL WINAPI
SetupDiCreateDeviceInterfaceA(
2583 HDEVINFO DeviceInfoSet
,
2584 PSP_DEVINFO_DATA DeviceInfoData
,
2585 const GUID
*InterfaceClassGuid
,
2586 PCSTR ReferenceString
,
2587 DWORD CreationFlags
,
2588 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2591 LPWSTR ReferenceStringW
= NULL
;
2593 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2594 debugstr_guid(InterfaceClassGuid
), debugstr_a(ReferenceString
),
2595 CreationFlags
, DeviceInterfaceData
);
2597 if (ReferenceString
)
2599 ReferenceStringW
= pSetupMultiByteToUnicode(ReferenceString
, CP_ACP
);
2600 if (ReferenceStringW
== NULL
) return FALSE
;
2603 ret
= SetupDiCreateDeviceInterfaceW(DeviceInfoSet
, DeviceInfoData
,
2604 InterfaceClassGuid
, ReferenceStringW
, CreationFlags
,
2605 DeviceInterfaceData
);
2607 MyFree(ReferenceStringW
);
2612 /***********************************************************************
2613 * SetupDiCreateDeviceInterfaceW (SETUPAPI.@)
2615 BOOL WINAPI
SetupDiCreateDeviceInterfaceW(
2616 HDEVINFO DeviceInfoSet
,
2617 PSP_DEVINFO_DATA DeviceInfoData
,
2618 const GUID
*InterfaceClassGuid
,
2619 PCWSTR ReferenceString
,
2620 DWORD CreationFlags
,
2621 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2623 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2624 TRACE("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2625 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2626 CreationFlags
, DeviceInterfaceData
);
2628 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
2630 SetLastError(ERROR_INVALID_HANDLE
);
2633 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2635 SetLastError(ERROR_INVALID_HANDLE
);
2638 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
2639 || !DeviceInfoData
->Reserved
)
2641 SetLastError(ERROR_INVALID_PARAMETER
);
2644 if (!InterfaceClassGuid
)
2646 SetLastError(ERROR_INVALID_USER_BUFFER
);
2650 FIXME("%p %p %s %s %08x %p\n", DeviceInfoSet
, DeviceInfoData
,
2651 debugstr_guid(InterfaceClassGuid
), debugstr_w(ReferenceString
),
2652 CreationFlags
, DeviceInterfaceData
);
2653 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2657 /***********************************************************************
2658 * SetupDiCreateDeviceInterfaceRegKeyA (SETUPAPI.@)
2660 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyA(
2661 HDEVINFO DeviceInfoSet
,
2662 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2666 PCSTR InfSectionName
)
2669 PWSTR InfSectionNameW
= NULL
;
2671 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2672 samDesired
, InfHandle
, InfSectionName
);
2675 if (!InfSectionName
)
2677 SetLastError(ERROR_INVALID_PARAMETER
);
2678 return INVALID_HANDLE_VALUE
;
2680 InfSectionNameW
= pSetupMultiByteToUnicode(InfSectionName
, CP_ACP
);
2681 if (!InfSectionNameW
)
2682 return INVALID_HANDLE_VALUE
;
2684 key
= SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet
,
2685 DeviceInterfaceData
, Reserved
, samDesired
, InfHandle
,
2687 MyFree(InfSectionNameW
);
2691 /***********************************************************************
2692 * SetupDiCreateDeviceInterfaceRegKeyW (SETUPAPI.@)
2694 HKEY WINAPI
SetupDiCreateDeviceInterfaceRegKeyW(
2695 HDEVINFO DeviceInfoSet
,
2696 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2700 PCWSTR InfSectionName
)
2703 LPWSTR SymbolicLink
;
2704 DWORD Length
, Index
;
2706 WCHAR bracedGuidString
[39];
2707 struct DeviceInterface
*DevItf
;
2708 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2710 TRACE("%p %p %d %08x %p %p\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
,
2711 samDesired
, InfHandle
, InfSectionName
);
2713 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2714 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2716 SetLastError(ERROR_INVALID_HANDLE
);
2717 return INVALID_HANDLE_VALUE
;
2719 if (!DeviceInterfaceData
||
2720 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2721 !DeviceInterfaceData
->Reserved
)
2723 SetLastError(ERROR_INVALID_PARAMETER
);
2724 return INVALID_HANDLE_VALUE
;
2726 if (InfHandle
&& !InfSectionName
)
2728 SetLastError(ERROR_INVALID_PARAMETER
);
2729 return INVALID_HANDLE_VALUE
;
2732 hKey
= SetupDiOpenClassRegKeyExW(&DeviceInterfaceData
->InterfaceClassGuid
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2733 if (hKey
== INVALID_HANDLE_VALUE
)
2735 hKey
= SetupDiOpenClassRegKeyExW(NULL
, samDesired
, DIOCR_INTERFACE
, NULL
, NULL
);
2736 if (hKey
== INVALID_HANDLE_VALUE
)
2738 SetLastError(ERROR_INVALID_PARAMETER
);
2739 return INVALID_HANDLE_VALUE
;
2741 SETUPDI_GuidToString(&DeviceInterfaceData
->InterfaceClassGuid
, bracedGuidString
);
2743 if (RegCreateKeyExW(hKey
, bracedGuidString
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
) != ERROR_SUCCESS
)
2745 SetLastError(ERROR_INVALID_PARAMETER
);
2746 return INVALID_HANDLE_VALUE
;
2752 DevItf
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2754 Length
= (wcslen(DevItf
->SymbolicLink
)+1) * sizeof(WCHAR
);
2755 SymbolicLink
= HeapAlloc(GetProcessHeap(), 0, Length
);
2759 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2760 return INVALID_HANDLE_VALUE
;
2763 wcscpy(SymbolicLink
, DevItf
->SymbolicLink
);
2766 while(SymbolicLink
[Index
])
2768 if (SymbolicLink
[Index
] == L
'\\')
2770 SymbolicLink
[Index
] = L
'#';
2775 rc
= RegCreateKeyExW(hKey
, SymbolicLink
, 0, NULL
, 0, samDesired
, NULL
, &hDevKey
, NULL
);
2778 HeapFree(GetProcessHeap(), 0, SymbolicLink
);
2780 if (rc
== ERROR_SUCCESS
)
2782 if (InfHandle
&& InfSectionName
)
2784 if (!SetupInstallFromInfSection(NULL
/*FIXME */,
2787 SPINST_INIFILES
| SPINST_REGISTRY
| SPINST_INI2REG
| SPINST_FILES
| SPINST_BITREG
| SPINST_REGSVR
| SPINST_UNREGSVR
| SPINST_PROFILEITEMS
| SPINST_COPYINF
,
2791 set
->SelectedDevice
->InstallParams
.InstallMsgHandler
,
2792 set
->SelectedDevice
->InstallParams
.InstallMsgHandlerContext
,
2793 INVALID_HANDLE_VALUE
,
2796 RegCloseKey(hDevKey
);
2797 return INVALID_HANDLE_VALUE
;
2806 /***********************************************************************
2807 * SetupDiDeleteDeviceInterfaceRegKey (SETUPAPI.@)
2809 BOOL WINAPI
SetupDiDeleteDeviceInterfaceRegKey(
2810 HDEVINFO DeviceInfoSet
,
2811 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2814 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2817 TRACE("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2819 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2820 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2822 SetLastError(ERROR_INVALID_HANDLE
);
2825 if (!DeviceInterfaceData
||
2826 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
2827 !DeviceInterfaceData
->Reserved
)
2829 SetLastError(ERROR_INVALID_PARAMETER
);
2833 FIXME("%p %p %d\n", DeviceInfoSet
, DeviceInterfaceData
, Reserved
);
2834 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2838 /***********************************************************************
2839 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2842 * DeviceInfoSet [I] Set of devices from which to enumerate
2844 * DeviceInfoData [I] (Optional) If specified, a specific device
2845 * instance from which to enumerate interfaces.
2846 * If it isn't specified, all interfaces for all
2847 * devices in the set are enumerated.
2848 * InterfaceClassGuid [I] The interface class to enumerate.
2849 * MemberIndex [I] An index of the interface instance to enumerate.
2850 * A caller should start with MemberIndex set to 0,
2851 * and continue until the function fails with
2852 * ERROR_NO_MORE_ITEMS.
2853 * DeviceInterfaceData [I/O] Returns an enumerated interface. Its cbSize
2854 * member must be set to
2855 * sizeof(SP_DEVICE_INTERFACE_DATA).
2858 * Success: non-zero value.
2859 * Failure: FALSE. Call GetLastError() for more info.
2861 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2862 HDEVINFO DeviceInfoSet
,
2863 PSP_DEVINFO_DATA DeviceInfoData
,
2864 CONST GUID
* InterfaceClassGuid
,
2866 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2868 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2871 TRACE("%p, %p, %s, %d, %p\n", DeviceInfoSet
, DeviceInfoData
,
2872 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2874 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
2875 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
2877 SetLastError(ERROR_INVALID_HANDLE
);
2880 if (DeviceInfoData
&& (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
) ||
2881 !DeviceInfoData
->Reserved
))
2883 SetLastError(ERROR_INVALID_PARAMETER
);
2886 if (!DeviceInterfaceData
||
2887 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2889 SetLastError(ERROR_INVALID_PARAMETER
);
2894 struct DeviceInfo
*devInfo
=
2895 (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
2897 PLIST_ENTRY InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2898 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2900 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2901 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2903 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2906 if (MemberIndex
-- == 0)
2908 /* return this item */
2909 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2910 &DevItf
->InterfaceClassGuid
,
2912 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2913 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2917 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2920 SetLastError(ERROR_NO_MORE_ITEMS
);
2925 PLIST_ENTRY ItemList
= set
->ListHead
.Flink
;
2926 while (ItemList
!= &set
->ListHead
&& !found
)
2928 PLIST_ENTRY InterfaceListEntry
;
2929 struct DeviceInfo
*devInfo
=
2930 CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
2931 InterfaceListEntry
= devInfo
->InterfaceListHead
.Flink
;
2932 while (InterfaceListEntry
!= &devInfo
->InterfaceListHead
&& !found
)
2934 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2935 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2937 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2940 if (MemberIndex
-- == 0)
2942 /* return this item */
2943 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2944 &DevItf
->InterfaceClassGuid
,
2946 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2947 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2951 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2953 ItemList
= ItemList
->Flink
;
2957 SetLastError(ERROR_NO_MORE_ITEMS
);
2962 /***********************************************************************
2963 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2965 * Destroy a DeviceInfoList and free all used memory of the list.
2968 * devinfo [I] DeviceInfoList pointer to list to destroy
2971 * Success: non zero value.
2972 * Failure: zero value.
2974 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2978 TRACE("%p\n", devinfo
);
2979 if (devinfo
&& devinfo
!= INVALID_HANDLE_VALUE
)
2981 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2983 if (list
->magic
== SETUP_DEVICE_INFO_SET_MAGIC
)
2985 ret
= DestroyDeviceInfoSet(list
);
2990 SetLastError(ERROR_INVALID_HANDLE
);
2995 /***********************************************************************
2996 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2998 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2999 HDEVINFO DeviceInfoSet
,
3000 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3001 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
3002 DWORD DeviceInterfaceDetailDataSize
,
3003 PDWORD RequiredSize
,
3004 PSP_DEVINFO_DATA DeviceInfoData
)
3006 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3007 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
3008 DWORD sizeW
= 0, bytesNeeded
;
3011 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3012 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3013 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3015 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3016 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3018 SetLastError(ERROR_INVALID_HANDLE
);
3021 if (!DeviceInterfaceData
||
3022 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3023 !DeviceInterfaceData
->Reserved
)
3025 SetLastError(ERROR_INVALID_PARAMETER
);
3028 if (DeviceInterfaceDetailData
&& (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
)))
3030 SetLastError(ERROR_INVALID_USER_BUFFER
);
3034 if((DeviceInterfaceDetailDataSize
!= 0) &&
3035 (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + sizeof(CHAR
))))
3037 SetLastError(ERROR_INVALID_USER_BUFFER
);
3041 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3043 SetLastError(ERROR_INVALID_USER_BUFFER
);
3048 if (DeviceInterfaceDetailData
!= NULL
)
3050 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
3051 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
3052 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)MyMalloc(sizeW
);
3053 if (!DeviceInterfaceDetailDataW
)
3055 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3057 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
3059 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
3061 ret
= SetupDiGetDeviceInterfaceDetailW(
3063 DeviceInterfaceData
,
3064 DeviceInterfaceDetailDataW
,
3068 bytesNeeded
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
3069 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
3071 *RequiredSize
= bytesNeeded
;
3072 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
>= bytesNeeded
)
3074 if (!WideCharToMultiByte(
3076 DeviceInterfaceDetailDataW
->DevicePath
, -1,
3077 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
3084 MyFree(DeviceInterfaceDetailDataW
);
3089 /***********************************************************************
3090 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
3092 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
3093 HDEVINFO DeviceInfoSet
,
3094 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
3095 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
3096 DWORD DeviceInterfaceDetailDataSize
,
3097 PDWORD RequiredSize
,
3098 PSP_DEVINFO_DATA DeviceInfoData
)
3100 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3103 TRACE("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet
,
3104 DeviceInterfaceData
, DeviceInterfaceDetailData
,
3105 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
3107 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
||
3108 set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3110 SetLastError(ERROR_INVALID_HANDLE
);
3113 if (!DeviceInterfaceData
||
3114 DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
) ||
3115 !DeviceInterfaceData
->Reserved
)
3117 SetLastError(ERROR_INVALID_PARAMETER
);
3120 if (DeviceInterfaceDetailData
&& DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
3122 SetLastError(ERROR_INVALID_USER_BUFFER
);
3125 if (!DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
)
3127 SetLastError(ERROR_INVALID_USER_BUFFER
);
3130 if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3132 SetLastError(ERROR_INVALID_PARAMETER
);
3135 if ((DeviceInterfaceDetailData
!= NULL
)
3136 && (DeviceInterfaceDetailDataSize
< (FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) + sizeof(WCHAR
)))
3138 SetLastError(ERROR_INVALID_PARAMETER
);
3143 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
3144 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
3145 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
3146 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
3148 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
3150 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3152 *RequiredSize
= sizeRequired
;
3156 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
3157 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
3160 memcpy(&DeviceInfoData
->ClassGuid
,
3161 &deviceInterface
->DeviceInfo
->ClassGuid
,
3163 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
3164 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
3172 struct PropertyMapEntry
3179 static struct PropertyMapEntry PropertyMap
[] = {
3180 { REG_SZ
, "DeviceDesc", REGSTR_VAL_DEVDESC
},
3181 { REG_MULTI_SZ
, "HardwareId", REGSTR_VAL_HARDWAREID
},
3182 { REG_MULTI_SZ
, "CompatibleIDs", REGSTR_VAL_COMPATIBLEIDS
},
3183 { 0, NULL
, NULL
}, /* SPDRP_UNUSED0 */
3184 { REG_SZ
, "Service", REGSTR_VAL_SERVICE
},
3185 { 0, NULL
, NULL
}, /* SPDRP_UNUSED1 */
3186 { 0, NULL
, NULL
}, /* SPDRP_UNUSED2 */
3187 { REG_SZ
, "Class", REGSTR_VAL_CLASS
},
3188 { REG_SZ
, "ClassGUID", REGSTR_VAL_CLASSGUID
},
3189 { REG_SZ
, "Driver", REGSTR_VAL_DRIVER
},
3190 { REG_DWORD
, "ConfigFlags", REGSTR_VAL_CONFIGFLAGS
},
3191 { REG_SZ
, "Mfg", REGSTR_VAL_MFG
},
3192 { REG_SZ
, "FriendlyName", REGSTR_VAL_FRIENDLYNAME
},
3193 { REG_SZ
, "LocationInformation", REGSTR_VAL_LOCATION_INFORMATION
},
3194 { 0, NULL
, NULL
}, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
3195 { REG_DWORD
, "Capabilities", REGSTR_VAL_CAPABILITIES
},
3196 { REG_DWORD
, "UINumber", REGSTR_VAL_UI_NUMBER
},
3197 { REG_MULTI_SZ
, "UpperFilters", REGSTR_VAL_UPPERFILTERS
},
3198 { REG_MULTI_SZ
, "LowerFilters", REGSTR_VAL_LOWERFILTERS
},
3199 { 0, NULL
, NULL
}, /* SPDRP_BUSTYPEGUID */
3200 { 0, NULL
, NULL
}, /* SPDRP_LEGACYBUSTYPE */
3201 { 0, NULL
, NULL
}, /* SPDRP_BUSNUMBER */
3202 { 0, NULL
, NULL
}, /* SPDRP_ENUMERATOR_NAME */
3203 { REG_BINARY
, "Security", REGSTR_SECURITY
},
3204 { 0, NULL
, NULL
}, /* SPDRP_SECURITY_SDS */
3205 { 0, NULL
, NULL
}, /* SPDRP_DEVTYPE */
3206 { 0, NULL
, NULL
}, /* SPDRP_EXCLUSIVE */
3207 { 0, NULL
, NULL
}, /* SPDRP_CHARACTERISTICS */
3208 { 0, NULL
, NULL
}, /* SPDRP_ADDRESS */
3209 { REG_SZ
, "UINumberDescFormat", REGSTR_UI_NUMBER_DESC_FORMAT
},
3210 { 0, NULL
, NULL
}, /* SPDRP_DEVICE_POWER_DATA */
3211 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY */
3212 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_HW_DEFAULT */
3213 { 0, NULL
, NULL
}, /* SPDRP_REMOVAL_POLICY_OVERRIDE */
3214 { 0, NULL
, NULL
}, /* SPDRP_INSTALL_STATE */
3217 /***********************************************************************
3218 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
3220 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
3221 HDEVINFO DeviceInfoSet
,
3222 PSP_DEVINFO_DATA DeviceInfoData
,
3224 PDWORD PropertyRegDataType
,
3225 PBYTE PropertyBuffer
,
3226 DWORD PropertyBufferSize
,
3227 PDWORD RequiredSize
)
3230 BOOL bIsStringProperty
;
3232 DWORD RequiredSizeA
, RequiredSizeW
;
3233 DWORD PropertyBufferSizeW
= 0;
3234 PBYTE PropertyBufferW
= NULL
;
3236 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3237 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3240 if (PropertyBufferSize
!= 0)
3242 PropertyBufferSizeW
= PropertyBufferSize
* 2;
3243 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
3244 if (!PropertyBufferW
)
3246 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3251 ret
= SetupDiGetDeviceRegistryPropertyW(
3257 PropertyBufferSizeW
,
3260 if (ret
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
3262 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
3264 if (bIsStringProperty
)
3265 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
3267 RequiredSizeA
= RequiredSizeW
;
3269 *RequiredSize
= RequiredSizeA
;
3270 if (PropertyRegDataType
)
3271 *PropertyRegDataType
= RegType
;
3276 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3280 if (RequiredSizeA
<= PropertyBufferSize
)
3282 if (bIsStringProperty
&& PropertyBufferSize
> 0)
3284 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
3286 /* Last error is already set by WideCharToMultiByte */
3291 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
3295 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3299 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
3303 /***********************************************************************
3304 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
3306 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
3307 HDEVINFO DeviceInfoSet
,
3308 PSP_DEVINFO_DATA DeviceInfoData
,
3310 PDWORD PropertyRegDataType
,
3311 PBYTE PropertyBuffer
,
3312 DWORD PropertyBufferSize
,
3313 PDWORD RequiredSize
)
3316 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3317 struct DeviceInfo
*devInfo
;
3319 TRACE("%p %p %d %p %p %d %p\n", DeviceInfoSet
, DeviceInfoData
,
3320 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
3323 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3325 SetLastError(ERROR_INVALID_HANDLE
);
3328 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3330 SetLastError(ERROR_INVALID_HANDLE
);
3333 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3334 || !DeviceInfoData
->Reserved
)
3336 SetLastError(ERROR_INVALID_PARAMETER
);
3339 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
3340 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3341 && PropertyMap
[Property
].nameW
)
3343 DWORD size
= PropertyBufferSize
;
3346 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_QUERY_VALUE
);
3347 if (hKey
== INVALID_HANDLE_VALUE
)
3349 l
= RegQueryValueExW(hKey
, PropertyMap
[Property
].nameW
,
3350 NULL
, PropertyRegDataType
, PropertyBuffer
, &size
);
3354 *RequiredSize
= size
;
3357 if (PropertyBuffer
!= NULL
|| size
== 0)
3360 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3362 case ERROR_MORE_DATA
:
3363 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3369 else if (Property
== SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
)
3371 DWORD required
= (strlenW(devInfo
->Data
) + 1) * sizeof(WCHAR
);
3373 if (PropertyRegDataType
)
3374 *PropertyRegDataType
= REG_SZ
;
3376 *RequiredSize
= required
;
3377 if (PropertyBufferSize
>= required
)
3379 strcpyW((LPWSTR
)PropertyBuffer
, devInfo
->Data
);
3383 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3387 ERR("Property 0x%lx not implemented\n", Property
);
3388 SetLastError(ERROR_NOT_SUPPORTED
);
3393 /***********************************************************************
3394 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3396 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
3397 HDEVINFO DeviceInfoSet
,
3398 PSP_DEVINFO_DATA DeviceInfoData
,
3400 const BYTE
*PropertyBuffer
,
3401 DWORD PropertyBufferSize
)
3404 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3406 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3407 PropertyBuffer
, PropertyBufferSize
);
3409 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3411 SetLastError(ERROR_INVALID_HANDLE
);
3414 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3416 SetLastError(ERROR_INVALID_HANDLE
);
3419 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3420 || !DeviceInfoData
->Reserved
)
3422 SetLastError(ERROR_INVALID_PARAMETER
);
3426 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3427 Property
, PropertyBuffer
, PropertyBufferSize
);
3428 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3432 /***********************************************************************
3433 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3435 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
3436 HDEVINFO DeviceInfoSet
,
3437 PSP_DEVINFO_DATA DeviceInfoData
,
3439 const BYTE
*PropertyBuffer
,
3440 DWORD PropertyBufferSize
)
3443 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3445 TRACE("%p %p %d %p %d\n", DeviceInfoSet
, DeviceInfoData
, Property
,
3446 PropertyBuffer
, PropertyBufferSize
);
3448 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
3450 SetLastError(ERROR_INVALID_HANDLE
);
3453 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3455 SetLastError(ERROR_INVALID_HANDLE
);
3458 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
3459 || !DeviceInfoData
->Reserved
)
3461 SetLastError(ERROR_INVALID_PARAMETER
);
3464 if (Property
< sizeof(PropertyMap
) / sizeof(PropertyMap
[0])
3465 && PropertyMap
[Property
].nameW
)
3469 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3470 if (hKey
== INVALID_HANDLE_VALUE
)
3472 /* Write new data */
3474 hKey
, PropertyMap
[Property
].nameW
, 0,
3475 PropertyMap
[Property
].regType
, PropertyBuffer
,
3476 PropertyBufferSize
);
3485 ERR("Property 0x%lx not implemented\n", Property
);
3486 SetLastError(ERROR_NOT_SUPPORTED
);
3489 TRACE("Returning %d\n", ret
);
3493 /***********************************************************************
3494 * SetupDiInstallClassA (SETUPAPI.@)
3496 BOOL WINAPI
SetupDiInstallClassA(
3502 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3505 /***********************************************************************
3506 * SetupDiInstallClassExA (SETUPAPI.@)
3509 SetupDiInstallClassExA(
3510 IN HWND hwndParent OPTIONAL
,
3511 IN PCSTR InfFileName OPTIONAL
,
3513 IN HSPFILEQ FileQueue OPTIONAL
,
3514 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3518 PWSTR InfFileNameW
= NULL
;
3523 SetLastError(ERROR_INVALID_PARAMETER
);
3528 InfFileNameW
= pSetupMultiByteToUnicode(InfFileName
, CP_ACP
);
3529 if (InfFileNameW
== NULL
)
3531 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3536 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3537 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3539 MyFree(InfFileNameW
);
3544 HKEY
SETUP_CreateClassKey(HINF hInf
)
3546 static const WCHAR slash
[] = { '\\',0 };
3547 WCHAR FullBuffer
[MAX_PATH
];
3548 WCHAR Buffer
[MAX_PATH
];
3552 if (!SetupGetLineTextW(NULL
,
3560 return INVALID_HANDLE_VALUE
;
3563 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3564 lstrcatW(FullBuffer
, slash
);
3565 lstrcatW(FullBuffer
, Buffer
);
3567 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3573 if (!SetupGetLineTextW(NULL
,
3581 return INVALID_HANDLE_VALUE
;
3584 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3588 REG_OPTION_NON_VOLATILE
,
3594 return INVALID_HANDLE_VALUE
;
3599 if (RegSetValueExW(hClassKey
,
3604 RequiredSize
* sizeof(WCHAR
)))
3606 RegCloseKey(hClassKey
);
3607 RegDeleteKeyW(HKEY_LOCAL_MACHINE
,
3609 return INVALID_HANDLE_VALUE
;
3615 /***********************************************************************
3616 * SetupDiInstallClassW (SETUPAPI.@)
3618 BOOL WINAPI
SetupDiInstallClassW(
3624 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3628 /***********************************************************************
3629 * SetupDiOpenClassRegKey (SETUPAPI.@)
3631 HKEY WINAPI
SetupDiOpenClassRegKey(
3632 const GUID
* ClassGuid
,
3635 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3636 DIOCR_INSTALLER
, NULL
, NULL
);
3640 /***********************************************************************
3641 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3643 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3644 const GUID
* ClassGuid
,
3650 PWSTR MachineNameW
= NULL
;
3653 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3654 Flags
, debugstr_a(MachineName
), Reserved
);
3658 MachineNameW
= pSetupMultiByteToUnicode(MachineName
, CP_ACP
);
3659 if (MachineNameW
== NULL
)
3660 return INVALID_HANDLE_VALUE
;
3663 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3664 Flags
, MachineNameW
, Reserved
);
3666 MyFree(MachineNameW
);
3672 /***********************************************************************
3673 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3675 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3676 const GUID
* ClassGuid
,
3688 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3689 Flags
, debugstr_w(MachineName
), Reserved
);
3691 if (MachineName
!= NULL
)
3693 l
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3694 if (l
!= ERROR_SUCCESS
)
3697 return INVALID_HANDLE_VALUE
;
3701 HKLM
= HKEY_LOCAL_MACHINE
;
3703 if (Flags
== DIOCR_INSTALLER
)
3705 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3707 else if (Flags
== DIOCR_INTERFACE
)
3709 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3713 ERR("Invalid Flags parameter!\n");
3714 SetLastError(ERROR_INVALID_FLAGS
);
3715 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3716 return INVALID_HANDLE_VALUE
;
3721 if ((l
= RegOpenKeyExW(HKLM
,
3727 SetLastError(ERROR_INVALID_CLASS
);
3728 hClassesKey
= INVALID_HANDLE_VALUE
;
3730 if (MachineName
!= NULL
)
3736 WCHAR bracedGuidString
[39];
3738 SETUPDI_GuidToString(ClassGuid
, bracedGuidString
);
3740 if (!(l
= RegOpenKeyExW(HKLM
,
3746 if (MachineName
!= NULL
)
3749 if ((l
= RegOpenKeyExW(hClassesKey
,
3756 key
= INVALID_HANDLE_VALUE
;
3758 RegCloseKey(hClassesKey
);
3762 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3764 key
= INVALID_HANDLE_VALUE
;
3771 /***********************************************************************
3772 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3774 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3775 HDEVINFO DeviceInfoSet
,
3778 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3780 struct DeviceInfoSet
* list
;
3782 DWORD dwLength
, dwError
, dwIndex
, dwKeyName
, dwSubIndex
;
3784 WCHAR Buffer
[MAX_PATH
+ 1];
3785 WCHAR SymBuffer
[MAX_PATH
+ 1];
3786 WCHAR InstancePath
[MAX_PATH
+ 1];
3787 HKEY hKey
, hDevKey
, hSymKey
;
3788 struct DeviceInfo
* deviceInfo
;
3789 struct DeviceInterface
*deviceInterface
;
3791 PLIST_ENTRY ItemList
;
3792 PLIST_ENTRY InterfaceListEntry
;
3794 TRACE("%p %s %08x %p\n",
3795 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3798 if (DeviceInterfaceData
&& DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
3800 SetLastError(ERROR_INVALID_PARAMETER
);
3804 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
3806 SetLastError(ERROR_INVALID_HANDLE
);
3810 list
= (struct DeviceInfoSet
* )DeviceInfoSet
;
3812 dwLength
= wcslen(DevicePath
);
3815 /* path must be at least a guid length + L'\0' */
3816 SetLastError(ERROR_BAD_PATHNAME
);
3820 if (DevicePath
[0] != L
'\\' ||
3821 DevicePath
[1] != L
'\\' ||
3822 (DevicePath
[2] != L
'?' && DevicePath
[2] != L
'.') ||
3823 DevicePath
[3] != L
'\\')
3825 /* invalid formatted path */
3826 SetLastError(ERROR_BAD_PATHNAME
);
3830 /* check for reference strings */
3831 pEnd
= wcschr(&DevicePath
[4], L
'\\');
3834 /* no reference string */
3835 pEnd
= DevicePath
+ dwLength
;
3839 wcscpy(Buffer
, pEnd
- 37);
3842 dwError
= UuidFromStringW(Buffer
, &ClassId
);
3843 if (dwError
!= NOERROR
)
3845 /* invalid formatted path */
3846 SetLastError(ERROR_BAD_PATHNAME
);
3850 hKey
= SetupDiOpenClassRegKeyExW(&ClassId
, KEY_READ
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
3852 if (hKey
== INVALID_HANDLE_VALUE
)
3854 /* invalid device class */
3858 ItemList
= list
->ListHead
.Flink
;
3859 while (ItemList
!= &list
->ListHead
)
3861 deviceInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfo
, ListEntry
);
3862 InterfaceListEntry
= deviceInfo
->InterfaceListHead
.Flink
;
3863 while (InterfaceListEntry
!= &deviceInfo
->InterfaceListHead
)
3865 deviceInterface
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
3866 if (!IsEqualIID(&deviceInterface
->InterfaceClassGuid
, &ClassId
))
3868 InterfaceListEntry
= InterfaceListEntry
->Flink
;
3872 if (!wcsicmp(deviceInterface
->SymbolicLink
, DevicePath
))
3874 if (DeviceInterfaceData
)
3876 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
3877 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
3878 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3892 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3893 dwError
= RegEnumKeyExW(hKey
, dwIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3895 if (dwError
!= ERROR_SUCCESS
)
3898 if (RegOpenKeyExW(hKey
, Buffer
, 0, KEY_READ
, &hDevKey
) != ERROR_SUCCESS
)
3902 InstancePath
[0] = 0;
3903 dwKeyName
= sizeof(InstancePath
);
3905 dwError
= RegQueryValueExW(hDevKey
, L
"DeviceInstance", NULL
, NULL
, (LPBYTE
)InstancePath
, &dwKeyName
);
3910 dwKeyName
= sizeof(Buffer
) / sizeof(WCHAR
);
3911 dwError
= RegEnumKeyExW(hDevKey
, dwSubIndex
, Buffer
, &dwKeyName
, NULL
, NULL
, NULL
, NULL
);
3913 if (dwError
!= ERROR_SUCCESS
)
3916 dwError
= RegOpenKeyExW(hDevKey
, Buffer
, 0, KEY_READ
, &hSymKey
);
3917 if (dwError
!= ERROR_SUCCESS
)
3920 /* query for symbolic link */
3921 dwKeyName
= sizeof(SymBuffer
);
3922 SymBuffer
[0] = L
'\0';
3923 dwError
= RegQueryValueExW(hSymKey
, L
"SymbolicLink", NULL
, NULL
, (LPBYTE
)SymBuffer
, &dwKeyName
);
3925 if (dwError
!= ERROR_SUCCESS
)
3927 RegCloseKey(hSymKey
);
3931 if (!wcsicmp(SymBuffer
, DevicePath
))
3933 Ret
= CreateDeviceInfo(list
, InstancePath
, &ClassId
, &deviceInfo
);
3934 RegCloseKey(hSymKey
);
3935 RegCloseKey(hDevKey
);
3940 deviceInterface
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DeviceInterface
) + (wcslen(SymBuffer
) + 1) * sizeof(WCHAR
));
3941 if (deviceInterface
)
3944 CopyMemory(&deviceInterface
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3945 deviceInterface
->DeviceInfo
= deviceInfo
;
3946 deviceInterface
->Flags
= SPINT_ACTIVE
; //FIXME
3948 wcscpy(deviceInterface
->SymbolicLink
, SymBuffer
);
3950 InsertTailList(&deviceInfo
->InterfaceListHead
, &deviceInterface
->ListEntry
);
3951 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
3954 if (DeviceInterfaceData
)
3956 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)deviceInterface
;
3957 DeviceInterfaceData
->Flags
= deviceInterface
->Flags
;
3958 CopyMemory(&DeviceInterfaceData
->InterfaceClassGuid
, &ClassId
, sizeof(GUID
));
3963 SetLastError(ERROR_INVALID_USER_BUFFER
);
3969 HeapFree(GetProcessHeap(), 0, deviceInfo
);
3974 RegCloseKey(hSymKey
);
3978 RegCloseKey(hDevKey
);
3986 /***********************************************************************
3987 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3989 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3990 HDEVINFO DeviceInfoSet
,
3993 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3995 LPWSTR DevicePathW
= NULL
;
3998 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
4000 DevicePathW
= pSetupMultiByteToUnicode(DevicePath
, CP_ACP
);
4001 if (DevicePathW
== NULL
)
4004 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
4005 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
4007 MyFree(DevicePathW
);
4012 /***********************************************************************
4013 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
4015 BOOL WINAPI
SetupDiSetClassInstallParamsA(
4016 HDEVINFO DeviceInfoSet
,
4017 PSP_DEVINFO_DATA DeviceInfoData
,
4018 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
4019 DWORD ClassInstallParamsSize
)
4021 FIXME("%p %p %x %u\n",DeviceInfoSet
, DeviceInfoData
,
4022 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
4027 IntSetupDiRegisterDeviceInfo(
4028 IN HDEVINFO DeviceInfoSet
,
4029 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
4031 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
4034 /***********************************************************************
4035 * SetupDiCallClassInstaller (SETUPAPI.@)
4037 BOOL WINAPI
SetupDiCallClassInstaller(
4038 DI_FUNCTION InstallFunction
,
4039 HDEVINFO DeviceInfoSet
,
4040 PSP_DEVINFO_DATA DeviceInfoData
)
4044 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4047 SetLastError(ERROR_INVALID_PARAMETER
);
4048 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
4049 SetLastError(ERROR_INVALID_HANDLE
);
4050 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4051 SetLastError(ERROR_INVALID_HANDLE
);
4052 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
4053 SetLastError(ERROR_INVALID_HANDLE
);
4054 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4055 SetLastError(ERROR_INVALID_USER_BUFFER
);
4058 SP_DEVINSTALL_PARAMS_W InstallParams
;
4059 #define CLASS_COINSTALLER 0x1
4060 #define DEVICE_COINSTALLER 0x2
4061 #define CLASS_INSTALLER 0x4
4062 UCHAR CanHandle
= 0;
4063 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
4065 switch (InstallFunction
)
4067 case DIF_ADDPROPERTYPAGE_ADVANCED
:
4068 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4070 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
4071 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4073 case DIF_ALLOW_INSTALL
:
4074 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4077 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4079 case DIF_DESTROYPRIVATEDATA
:
4080 CanHandle
= CLASS_INSTALLER
;
4082 case DIF_INSTALLDEVICE
:
4083 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4084 DefaultHandler
= SetupDiInstallDevice
;
4086 case DIF_INSTALLDEVICEFILES
:
4087 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4088 DefaultHandler
= SetupDiInstallDriverFiles
;
4090 case DIF_INSTALLINTERFACES
:
4091 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4092 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
4094 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
4095 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4097 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
4098 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4100 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
4101 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4103 case DIF_NEWDEVICEWIZARD_PRESELECT
:
4104 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4106 case DIF_NEWDEVICEWIZARD_SELECT
:
4107 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4109 case DIF_POWERMESSAGEWAKE
:
4110 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4112 case DIF_PROPERTYCHANGE
:
4113 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4114 DefaultHandler
= SetupDiChangeState
;
4116 case DIF_REGISTER_COINSTALLERS
:
4117 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4118 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
4120 case DIF_REGISTERDEVICE
:
4121 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4122 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
4125 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4126 DefaultHandler
= SetupDiRemoveDevice
;
4128 case DIF_SELECTBESTCOMPATDRV
:
4129 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4130 DefaultHandler
= SetupDiSelectBestCompatDrv
;
4132 case DIF_SELECTDEVICE
:
4133 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4134 DefaultHandler
= SetupDiSelectDevice
;
4136 case DIF_TROUBLESHOOTER
:
4137 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4140 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4141 DefaultHandler
= SetupDiUnremoveDevice
;
4144 ERR("Install function %u not supported\n", InstallFunction
);
4145 SetLastError(ERROR_NOT_SUPPORTED
);
4148 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4149 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4150 /* Don't process this call, as a parameter is invalid */
4155 LIST_ENTRY ClassCoInstallersListHead
;
4156 LIST_ENTRY DeviceCoInstallersListHead
;
4157 HMODULE ClassInstallerLibrary
= NULL
;
4158 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
4159 COINSTALLER_CONTEXT_DATA Context
;
4160 PLIST_ENTRY ListEntry
;
4162 DWORD dwRegType
, dwLength
;
4163 DWORD rc
= NO_ERROR
;
4165 InitializeListHead(&ClassCoInstallersListHead
);
4166 InitializeListHead(&DeviceCoInstallersListHead
);
4168 if (CanHandle
& DEVICE_COINSTALLER
)
4170 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4171 if (hKey
!= INVALID_HANDLE_VALUE
)
4173 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4174 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4176 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4177 if (KeyBuffer
!= NULL
)
4179 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4180 if (rc
== ERROR_SUCCESS
)
4183 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4185 /* Add coinstaller to DeviceCoInstallersListHead list */
4186 struct CoInstallerElement
*coinstaller
;
4187 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
4188 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4191 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4192 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4193 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
4195 HeapFree(GetProcessHeap(), 0, coinstaller
);
4198 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4204 if (CanHandle
& CLASS_COINSTALLER
)
4208 REGSTR_PATH_CODEVICEINSTALLERS
,
4212 if (rc
== ERROR_SUCCESS
)
4214 LPWSTR lpGuidString
;
4215 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
4217 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
4218 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4220 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4221 if (KeyBuffer
!= NULL
)
4223 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4224 if (rc
== ERROR_SUCCESS
)
4227 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4229 /* Add coinstaller to ClassCoInstallersListHead list */
4230 struct CoInstallerElement
*coinstaller
;
4231 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
4232 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4235 ZeroMemory(coinstaller
, sizeof(struct CoInstallerElement
));
4236 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4237 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
4239 HeapFree(GetProcessHeap(), 0, coinstaller
);
4242 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4245 RpcStringFreeW(&lpGuidString
);
4250 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
4252 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
4253 if (hKey
!= INVALID_HANDLE_VALUE
)
4255 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4256 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
4258 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4259 if (KeyBuffer
!= NULL
)
4261 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4262 if (rc
== ERROR_SUCCESS
)
4264 /* Get ClassInstaller function pointer */
4265 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
4266 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
4268 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
4269 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4272 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4279 /* Call Class co-installers */
4280 Context
.PostProcessing
= FALSE
;
4282 ListEntry
= ClassCoInstallersListHead
.Flink
;
4283 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4285 struct CoInstallerElement
*coinstaller
;
4286 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4287 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4288 coinstaller
->PrivateData
= Context
.PrivateData
;
4289 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4291 coinstaller
->DoPostProcessing
= TRUE
;
4294 ListEntry
= ListEntry
->Flink
;
4297 /* Call Device co-installers */
4298 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4299 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4301 struct CoInstallerElement
*coinstaller
;
4302 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4303 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4304 coinstaller
->PrivateData
= Context
.PrivateData
;
4305 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4307 coinstaller
->DoPostProcessing
= TRUE
;
4310 ListEntry
= ListEntry
->Flink
;
4313 /* Call Class installer */
4316 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4317 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4320 rc
= ERROR_DI_DO_DEFAULT
;
4322 /* Call default handler */
4323 if (rc
== ERROR_DI_DO_DEFAULT
)
4325 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4327 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4330 rc
= GetLastError();
4336 /* Call Class co-installers that required postprocessing */
4337 Context
.PostProcessing
= TRUE
;
4338 ListEntry
= ClassCoInstallersListHead
.Flink
;
4339 while (ListEntry
!= &ClassCoInstallersListHead
)
4341 struct CoInstallerElement
*coinstaller
;
4342 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4343 if (coinstaller
->DoPostProcessing
)
4345 Context
.InstallResult
= rc
;
4346 Context
.PrivateData
= coinstaller
->PrivateData
;
4347 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4349 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4350 ListEntry
= ListEntry
->Flink
;
4353 /* Call Device co-installers that required postprocessing */
4354 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4355 while (ListEntry
!= &DeviceCoInstallersListHead
)
4357 struct CoInstallerElement
*coinstaller
;
4358 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4359 if (coinstaller
->DoPostProcessing
)
4361 Context
.InstallResult
= rc
;
4362 Context
.PrivateData
= coinstaller
->PrivateData
;
4363 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4365 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4366 ListEntry
= ListEntry
->Flink
;
4369 /* Free allocated memory */
4370 while (!IsListEmpty(&ClassCoInstallersListHead
))
4372 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4373 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4375 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4377 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4378 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4381 ret
= (rc
== NO_ERROR
);
4385 TRACE("Returning %d\n", ret
);
4389 /***********************************************************************
4390 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4392 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4393 HDEVINFO DeviceInfoSet
,
4394 PSP_DEVINFO_DATA DeviceInfoData
,
4395 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4397 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4400 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4402 if (DeviceInstallParams
== NULL
)
4403 SetLastError(ERROR_INVALID_PARAMETER
);
4404 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4405 SetLastError(ERROR_INVALID_USER_BUFFER
);
4408 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4409 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4413 /* Do W->A conversion */
4415 DeviceInstallParams
,
4416 &deviceInstallParamsW
,
4417 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4418 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4419 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4421 DeviceInstallParams
->DriverPath
[0] = '\0';
4427 TRACE("Returning %d\n", ret
);
4431 /***********************************************************************
4432 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4435 SetupDiGetDeviceInfoListClass(
4436 IN HDEVINFO DeviceInfoSet
,
4437 OUT LPGUID ClassGuid
)
4439 struct DeviceInfoSet
*list
;
4442 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4445 SetLastError(ERROR_INVALID_HANDLE
);
4446 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4447 SetLastError(ERROR_INVALID_HANDLE
);
4448 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4449 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4452 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4457 TRACE("Returning %d\n", ret
);
4461 /***********************************************************************
4462 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4465 SetupDiGetDeviceInstallParamsW(
4466 IN HDEVINFO DeviceInfoSet
,
4467 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4468 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4470 struct DeviceInfoSet
*list
;
4473 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4476 SetLastError(ERROR_INVALID_HANDLE
);
4477 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4478 SetLastError(ERROR_INVALID_HANDLE
);
4479 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4480 SetLastError(ERROR_INVALID_USER_BUFFER
);
4481 else if (!DeviceInstallParams
)
4482 SetLastError(ERROR_INVALID_PARAMETER
);
4483 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4484 SetLastError(ERROR_INVALID_USER_BUFFER
);
4487 PSP_DEVINSTALL_PARAMS_W Source
;
4490 Source
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4492 Source
= &list
->InstallParams
;
4498 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
4502 SetLastError(RtlNtStatusToDosError(_SEH2_GetExceptionCode()));
4508 TRACE("Returning %d\n", ret
);
4513 CheckDeviceInstallParameters(
4514 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4516 DWORD SupportedFlags
=
4517 DI_NOVCP
| /* 0x00000008 */
4518 DI_DIDCOMPAT
| /* 0x00000010 */
4519 DI_DIDCLASS
| /* 0x00000020 */
4520 DI_NEEDRESTART
| /* 0x00000080 */
4521 DI_NEEDREBOOT
| /* 0x00000100 */
4522 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4523 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4524 DI_ENUMSINGLEINF
| /* 0x00010000 */
4525 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
4526 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4527 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4528 DI_QUIETINSTALL
| /* 0x00800000 */
4529 DI_NOFILECOPY
| /* 0x01000000 */
4530 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4531 DWORD SupportedFlagsEx
=
4532 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4533 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4534 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4535 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4536 DI_FLAGSEX_NO_DRVREG_MODIFY
| /* 0x00008000 */
4537 DI_FLAGSEX_INSTALLEDDRIVER
; /* 0x04000000 */
4540 /* FIXME: add support for more flags */
4542 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4543 * It should be checked before accessing to other values
4544 * of the SP_DEVINSTALL_PARAMS structure */
4546 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4548 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4549 SetLastError(ERROR_INVALID_FLAGS
);
4551 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4553 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4554 SetLastError(ERROR_INVALID_FLAGS
);
4556 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4557 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4558 SetLastError(ERROR_INVALID_USER_BUFFER
);
4561 /* FIXME: check Reserved field */
4568 /***********************************************************************
4569 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4572 SetupDiSetDeviceInstallParamsW(
4573 IN HDEVINFO DeviceInfoSet
,
4574 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4575 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4577 struct DeviceInfoSet
*list
;
4580 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4583 SetLastError(ERROR_INVALID_HANDLE
);
4584 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4585 SetLastError(ERROR_INVALID_HANDLE
);
4586 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4587 SetLastError(ERROR_INVALID_USER_BUFFER
);
4588 else if (!DeviceInstallParams
)
4589 SetLastError(ERROR_INVALID_PARAMETER
);
4590 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4591 SetLastError(ERROR_INVALID_USER_BUFFER
);
4592 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4594 PSP_DEVINSTALL_PARAMS_W Destination
;
4597 Destination
= &((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->InstallParams
;
4599 Destination
= &list
->InstallParams
;
4600 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4604 TRACE("Returning %d\n", ret
);
4608 /***********************************************************************
4609 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4612 SetupDiSetDeviceInstallParamsA(
4613 HDEVINFO DeviceInfoSet
,
4614 PSP_DEVINFO_DATA DeviceInfoData
,
4615 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4617 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4621 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4623 if (DeviceInstallParams
== NULL
)
4624 SetLastError(ERROR_INVALID_PARAMETER
);
4625 else if (DeviceInstallParams
->cbSize
< sizeof(SP_DEVINSTALL_PARAMS_A
))
4626 SetLastError(ERROR_INVALID_USER_BUFFER
);
4629 memcpy(&deviceInstallParamsW
, DeviceInstallParams
, FIELD_OFFSET(SP_DEVINSTALL_PARAMS_A
, DriverPath
));
4630 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4631 len
= MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, NULL
, 0);
4634 ERR("DrivePath is NULL\n");
4639 MultiByteToWideChar(CP_ACP
, 0, DeviceInstallParams
->DriverPath
, -1, deviceInstallParamsW
.DriverPath
, len
);
4640 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4644 TRACE("Returning %d\n", ret
);
4649 OpenHardwareProfileKey(
4652 IN DWORD samDesired
)
4654 HKEY hHWProfilesKey
= NULL
;
4655 HKEY hHWProfileKey
= NULL
;
4656 HKEY ret
= INVALID_HANDLE_VALUE
;
4659 rc
= RegOpenKeyExW(HKLM
,
4660 REGSTR_PATH_HWPROFILES
,
4664 if (rc
!= ERROR_SUCCESS
)
4681 snprintfW(subKey
, 4, InstanceKeyFormat
, HwProfile
);
4690 if (rc
!= ERROR_SUCCESS
)
4695 ret
= hHWProfileKey
;
4698 if (hHWProfilesKey
!= NULL
)
4699 RegCloseKey(hHWProfilesKey
);
4700 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4701 RegCloseKey(hHWProfileKey
);
4706 IsDeviceInfoInDeviceInfoSet(
4707 struct DeviceInfoSet
*deviceInfoSet
,
4708 struct DeviceInfo
*deviceInfo
)
4710 PLIST_ENTRY ListEntry
;
4712 ListEntry
= deviceInfoSet
->ListHead
.Flink
;
4713 while (ListEntry
!= &deviceInfoSet
->ListHead
)
4715 if (deviceInfo
== CONTAINING_RECORD(ListEntry
, struct DeviceInfo
, ListEntry
))
4718 ListEntry
= ListEntry
->Flink
;
4724 /***********************************************************************
4725 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
4728 SetupDiDeleteDeviceInfo(
4729 IN HDEVINFO DeviceInfoSet
,
4730 IN PSP_DEVINFO_DATA DeviceInfoData
)
4732 struct DeviceInfoSet
*deviceInfoSet
;
4733 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
;
4736 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4739 SetLastError(ERROR_INVALID_HANDLE
);
4740 else if ((deviceInfoSet
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4741 SetLastError(ERROR_INVALID_HANDLE
);
4742 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4743 SetLastError(ERROR_INVALID_USER_BUFFER
);
4744 else if (!IsDeviceInfoInDeviceInfoSet(deviceInfoSet
, deviceInfo
))
4745 SetLastError(ERROR_INVALID_PARAMETER
);
4748 RemoveEntryList(&deviceInfo
->ListEntry
);
4749 DestroyDeviceInfo(deviceInfo
);
4757 /***********************************************************************
4758 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
4761 SetupDiOpenDeviceInfoA(
4762 IN HDEVINFO DeviceInfoSet
,
4763 IN PCSTR DeviceInstanceId
,
4764 IN HWND hwndParent OPTIONAL
,
4766 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4768 LPWSTR DeviceInstanceIdW
= NULL
;
4771 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
4773 DeviceInstanceIdW
= pSetupMultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
4774 if (DeviceInstanceIdW
== NULL
)
4777 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
4778 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
4780 MyFree(DeviceInstanceIdW
);
4786 /***********************************************************************
4787 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
4790 SetupDiOpenDeviceInfoW(
4791 IN HDEVINFO DeviceInfoSet
,
4792 IN PCWSTR DeviceInstanceId
,
4793 IN HWND hwndParent OPTIONAL
,
4795 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
4797 struct DeviceInfoSet
*list
;
4798 HKEY hEnumKey
, hKey
= NULL
;
4802 TRACE("%p %s %p %lx %p\n",
4803 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
4804 hwndParent
, OpenFlags
, DeviceInfoData
);
4806 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
4807 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
4810 SetLastError(ERROR_INVALID_HANDLE
);
4811 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4812 SetLastError(ERROR_INVALID_HANDLE
);
4813 else if (!DeviceInstanceId
)
4814 SetLastError(ERROR_INVALID_PARAMETER
);
4815 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
4817 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
4818 SetLastError(ERROR_INVALID_FLAGS
);
4820 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4821 SetLastError(ERROR_INVALID_USER_BUFFER
);
4824 struct DeviceInfo
*deviceInfo
= NULL
;
4825 /* Search if device already exists in DeviceInfoSet.
4826 * If yes, return the existing element
4827 * If no, create a new element using information in registry
4829 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
4830 while (ItemList
!= &list
->ListHead
)
4835 FIXME("not implemented\n");
4836 ItemList
= ItemList
->Flink
;
4841 /* good one found */
4847 WCHAR szClassGuid
[MAX_GUID_STRING_LEN
];
4849 /* Open supposed registry key */
4852 REGSTR_PATH_SYSTEMENUM
,
4856 if (rc
!= ERROR_SUCCESS
)
4867 RegCloseKey(hEnumKey
);
4868 if (rc
!= ERROR_SUCCESS
)
4870 if (rc
== ERROR_FILE_NOT_FOUND
)
4871 rc
= ERROR_NO_SUCH_DEVINST
;
4876 ClassGUID
= GUID_NULL
;
4877 dwSize
= MAX_GUID_STRING_LEN
* sizeof(WCHAR
);
4879 if (RegQueryValueExW(hKey
,
4880 REGSTR_VAL_CLASSGUID
,
4883 (LPBYTE
)szClassGuid
,
4884 &dwSize
) == ERROR_SUCCESS
)
4886 szClassGuid
[MAX_GUID_STRING_LEN
- 2] = UNICODE_NULL
;
4888 /* Convert a string to a ClassGuid */
4889 UuidFromStringW(&szClassGuid
[1], &ClassGUID
);
4892 if (!CreateDeviceInfo(list
, DeviceInstanceId
, &ClassGUID
, &deviceInfo
))
4895 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
4900 if (ret
&& deviceInfo
&& DeviceInfoData
)
4902 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
4903 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
4904 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
4915 /***********************************************************************
4916 * SetupDiGetSelectedDevice (SETUPAPI.@)
4919 SetupDiGetSelectedDevice(
4920 IN HDEVINFO DeviceInfoSet
,
4921 OUT PSP_DEVINFO_DATA DeviceInfoData
)
4923 struct DeviceInfoSet
*list
;
4926 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4929 SetLastError(ERROR_INVALID_HANDLE
);
4930 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4931 SetLastError(ERROR_INVALID_HANDLE
);
4932 else if (list
->SelectedDevice
== NULL
)
4933 SetLastError(ERROR_NO_DEVICE_SELECTED
);
4934 else if (!DeviceInfoData
)
4935 SetLastError(ERROR_INVALID_PARAMETER
);
4936 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4937 SetLastError(ERROR_INVALID_USER_BUFFER
);
4940 memcpy(&DeviceInfoData
->ClassGuid
,
4941 &list
->SelectedDevice
->ClassGuid
,
4943 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
4944 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
4948 TRACE("Returning %d\n", ret
);
4953 /***********************************************************************
4954 * SetupDiSetSelectedDevice (SETUPAPI.@)
4957 SetupDiSetSelectedDevice(
4958 IN HDEVINFO DeviceInfoSet
,
4959 IN PSP_DEVINFO_DATA DeviceInfoData
)
4961 struct DeviceInfoSet
*list
;
4964 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
4967 SetLastError(ERROR_INVALID_HANDLE
);
4968 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
4969 SetLastError(ERROR_INVALID_HANDLE
);
4970 else if (!DeviceInfoData
)
4971 SetLastError(ERROR_INVALID_PARAMETER
);
4972 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4973 SetLastError(ERROR_INVALID_USER_BUFFER
);
4974 else if (DeviceInfoData
->Reserved
== 0)
4975 SetLastError(ERROR_INVALID_USER_BUFFER
);
4978 list
->SelectedDevice
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
4982 TRACE("Returning %d\n", ret
);
4987 /* Return the current hardware profile id, or -1 if error */
4989 SETUPAPI_GetCurrentHwProfile(
4990 IN HDEVINFO DeviceInfoSet
)
4993 DWORD dwRegType
, dwLength
;
4996 DWORD ret
= (DWORD
)-1;
4999 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
5000 REGSTR_PATH_IDCONFIGDB
,
5004 if (rc
!= ERROR_SUCCESS
)
5010 dwLength
= sizeof(DWORD
);
5011 rc
= RegQueryValueExW(
5013 REGSTR_VAL_CURRENTCONFIG
,
5016 (LPBYTE
)&hwProfile
, &dwLength
);
5017 if (rc
!= ERROR_SUCCESS
)
5022 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5024 SetLastError(ERROR_GEN_FAILURE
);
5039 IN HDEVINFO DeviceInfoSet
,
5040 IN PSP_DEVINFO_DATA DeviceInfoData
)
5043 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5044 struct DeviceInfo
*deviceInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5047 cr
= CM_Enable_DevNode_Ex(deviceInfo
->dnDevInst
, 0, set
->hMachine
);
5048 if (cr
!= CR_SUCCESS
)
5050 SetLastError(GetErrorCodeFromCrCode(cr
));
5056 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5061 static BOOL
StopDevice(
5062 IN HDEVINFO DeviceInfoSet
,
5063 IN PSP_DEVINFO_DATA DeviceInfoData
)
5065 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
5069 /***********************************************************************
5070 * SetupDiChangeState (SETUPAPI.@)
5074 IN HDEVINFO DeviceInfoSet
,
5075 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5077 PSP_PROPCHANGE_PARAMS PropChange
;
5078 HKEY hKey
= INVALID_HANDLE_VALUE
;
5079 LPCWSTR RegistryValueName
;
5080 DWORD dwConfigFlags
, dwLength
, dwRegType
;
5084 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5086 if (!DeviceInfoData
)
5087 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChangeParams
;
5089 PropChange
= ((struct DeviceInfo
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChangeParams
;
5092 SetLastError(ERROR_INVALID_PARAMETER
);
5096 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
5097 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
5099 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
5101 switch (PropChange
->StateChange
)
5106 /* Enable/disable device in registry */
5107 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
5108 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5109 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
5110 if (hKey
== INVALID_HANDLE_VALUE
)
5112 dwLength
= sizeof(DWORD
);
5113 rc
= RegQueryValueExW(
5118 (LPBYTE
)&dwConfigFlags
, &dwLength
);
5119 if (rc
== ERROR_FILE_NOT_FOUND
)
5121 else if (rc
!= ERROR_SUCCESS
)
5126 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
5128 SetLastError(ERROR_GEN_FAILURE
);
5131 if (PropChange
->StateChange
== DICS_ENABLE
)
5132 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5134 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
5135 rc
= RegSetValueExW(
5140 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
5141 if (rc
!= ERROR_SUCCESS
)
5147 /* Enable/disable device if needed */
5148 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
5149 || PropChange
->HwProfile
== 0
5150 || PropChange
->HwProfile
== SETUPAPI_GetCurrentHwProfile(DeviceInfoSet
))
5152 if (PropChange
->StateChange
== DICS_ENABLE
)
5153 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5155 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
5161 case DICS_PROPCHANGE
:
5163 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5168 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
5169 SetLastError(ERROR_NOT_SUPPORTED
);
5174 if (hKey
!= INVALID_HANDLE_VALUE
)
5177 TRACE("Returning %d\n", ret
);
5181 /***********************************************************************
5182 * SetupDiSelectDevice (SETUPAPI.@)
5185 SetupDiSelectDevice(
5186 IN HDEVINFO DeviceInfoSet
,
5187 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5189 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5190 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5195 /***********************************************************************
5196 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
5199 SetupDiRegisterCoDeviceInstallers(
5200 IN HDEVINFO DeviceInfoSet
,
5201 IN PSP_DEVINFO_DATA DeviceInfoData
)
5203 BOOL ret
= FALSE
; /* Return value */
5205 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5208 SetLastError(ERROR_INVALID_PARAMETER
);
5209 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5210 SetLastError(ERROR_INVALID_HANDLE
);
5211 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5212 SetLastError(ERROR_INVALID_HANDLE
);
5213 else if (!DeviceInfoData
)
5214 SetLastError(ERROR_INVALID_PARAMETER
);
5215 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5216 SetLastError(ERROR_INVALID_USER_BUFFER
);
5219 SP_DEVINSTALL_PARAMS_W InstallParams
;
5220 struct DriverInfoElement
*SelectedDriver
;
5223 WCHAR SectionName
[MAX_PATH
];
5224 DWORD SectionNameLength
= 0;
5225 HKEY hKey
= INVALID_HANDLE_VALUE
;
5226 PVOID Context
= NULL
;
5228 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5229 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5233 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5234 if (SelectedDriver
== NULL
)
5236 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5240 /* Get .CoInstallers section name */
5241 Result
= SetupDiGetActualSectionToInstallW(
5242 SelectedDriver
->InfFileDetails
->hInf
,
5243 SelectedDriver
->Details
.SectionName
,
5244 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5245 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
5247 lstrcatW(SectionName
, DotCoInstallers
);
5249 /* Open/Create driver key information */
5250 #if _WIN32_WINNT >= 0x502
5251 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5253 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5255 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5256 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5257 if (hKey
== INVALID_HANDLE_VALUE
)
5260 /* Install .CoInstallers section */
5261 DoAction
= SPINST_REGISTRY
;
5262 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5264 DoAction
|= SPINST_FILES
;
5265 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5269 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5270 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5271 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5272 SetupDefaultQueueCallbackW
, Context
,
5273 DeviceInfoSet
, DeviceInfoData
);
5281 SetupTermDefaultQueueCallback(Context
);
5282 if (hKey
!= INVALID_HANDLE_VALUE
)
5286 TRACE("Returning %d\n", ret
);
5291 InfIsFromOEMLocation(
5293 OUT LPBOOL IsOEMLocation
)
5297 last
= strrchrW(FullName
, '\\');
5300 /* No directory specified */
5301 *IsOEMLocation
= FALSE
;
5308 Windir
= MyMalloc((MAX_PATH
+ 1 + strlenW(InfDirectory
)) * sizeof(WCHAR
));
5311 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5315 ret
= GetSystemWindowsDirectoryW(Windir
, MAX_PATH
);
5316 if (ret
== 0 || ret
> MAX_PATH
)
5319 SetLastError(ERROR_GEN_FAILURE
);
5322 if (*Windir
&& Windir
[strlenW(Windir
) - 1] != '\\')
5323 strcatW(Windir
, BackSlash
);
5324 strcatW(Windir
, InfDirectory
);
5326 if (strncmpiW(FullName
, Windir
, last
- FullName
) == 0)
5328 /* The path is %SYSTEMROOT%\Inf */
5329 *IsOEMLocation
= FALSE
;
5333 /* The file is in another place */
5334 *IsOEMLocation
= TRUE
;
5341 /***********************************************************************
5342 * SetupDiInstallDevice (SETUPAPI.@)
5345 SetupDiInstallDevice(
5346 IN HDEVINFO DeviceInfoSet
,
5347 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
5349 SP_DEVINSTALL_PARAMS_W InstallParams
;
5350 struct DriverInfoElement
*SelectedDriver
;
5351 SYSTEMTIME DriverDate
;
5352 WCHAR SectionName
[MAX_PATH
];
5354 DWORD SectionNameLength
= 0;
5355 BOOL Result
= FALSE
;
5358 LPWSTR pSectionName
= NULL
;
5359 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
5361 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
5362 BOOL RebootRequired
= FALSE
;
5363 HKEY hKey
= INVALID_HANDLE_VALUE
;
5364 BOOL NeedtoCopyFile
;
5365 LARGE_INTEGER fullVersion
;
5367 PVOID Context
= NULL
;
5368 BOOL ret
= FALSE
; /* Return value */
5370 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5373 SetLastError(ERROR_INVALID_PARAMETER
);
5374 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
5375 SetLastError(ERROR_INVALID_HANDLE
);
5376 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5377 SetLastError(ERROR_INVALID_HANDLE
);
5378 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5379 SetLastError(ERROR_INVALID_USER_BUFFER
);
5385 /* One parameter is bad */
5389 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5390 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5394 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
5396 /* Set FAILEDINSTALL in ConfigFlags registry value */
5397 DWORD ConfigFlags
, regType
;
5398 Result
= SetupDiGetDeviceRegistryPropertyW(
5403 (PBYTE
)&ConfigFlags
,
5404 sizeof(ConfigFlags
),
5406 if (!Result
|| regType
!= REG_DWORD
)
5408 SetLastError(ERROR_GEN_FAILURE
);
5411 ConfigFlags
|= DNF_DISABLED
;
5412 Result
= SetupDiSetDeviceRegistryPropertyW(
5416 (PBYTE
)&ConfigFlags
,
5417 sizeof(ConfigFlags
));
5420 SetLastError(ERROR_GEN_FAILURE
);
5428 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
5429 if (SelectedDriver
== NULL
)
5431 SetLastError(ERROR_NO_DRIVER_SELECTED
);
5435 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
5437 Result
= SetupDiGetActualSectionToInstallW(
5438 SelectedDriver
->InfFileDetails
->hInf
,
5439 SelectedDriver
->Details
.SectionName
,
5440 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
5441 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
5443 pSectionName
= &SectionName
[strlenW(SectionName
)];
5445 /* Get information from [Version] section */
5446 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
5448 /* Format ClassGuid to a string */
5449 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5451 RequiredSize
= lstrlenW(lpGuidString
);
5452 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
5453 if (!lpFullGuidString
)
5455 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5458 lpFullGuidString
[0] = '{';
5459 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
5460 lpFullGuidString
[RequiredSize
+ 1] = '}';
5461 lpFullGuidString
[RequiredSize
+ 2] = '\0';
5463 /* Copy .inf file to Inf\ directory (if needed) */
5464 Result
= InfIsFromOEMLocation(SelectedDriver
->Details
.InfFileName
, &NeedtoCopyFile
);
5469 WCHAR NewFileName
[MAX_PATH
];
5470 struct InfFileDetails
*newInfFileDetails
;
5471 Result
= SetupCopyOEMInfW(
5472 SelectedDriver
->Details
.InfFileName
,
5475 SP_COPY_NOOVERWRITE
,
5476 NewFileName
, MAX_PATH
,
5481 /* Create a new struct InfFileDetails, and set it to
5482 * SelectedDriver->InfFileDetails, to release use of
5483 * current InfFile */
5484 newInfFileDetails
= CreateInfFileDetails(NewFileName
);
5485 if (!newInfFileDetails
)
5487 DereferenceInfFile(SelectedDriver
->InfFileDetails
);
5488 SelectedDriver
->InfFileDetails
= newInfFileDetails
;
5489 strcpyW(SelectedDriver
->Details
.InfFileName
, NewFileName
);
5492 /* Open/Create driver key information */
5493 #if _WIN32_WINNT >= 0x502
5494 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
5496 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
5498 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5499 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
5500 if (hKey
== INVALID_HANDLE_VALUE
)
5503 /* Install main section */
5505 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5506 DoAction
|= SPINST_REGISTRY
;
5507 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
5509 DoAction
|= SPINST_FILES
;
5510 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
5514 *pSectionName
= '\0';
5515 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5516 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5517 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
5518 SetupDefaultQueueCallbackW
, Context
,
5519 DeviceInfoSet
, DeviceInfoData
);
5522 InstallParams
.Flags
|= DI_NOFILECOPY
;
5523 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5525 /* Write information to driver key */
5526 *pSectionName
= UNICODE_NULL
;
5527 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
5528 TRACE("Write information to driver key\n");
5529 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5530 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5531 TRACE("DriverVersion : '%ld.%ld.%lu.%ld'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5532 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->InfFileDetails
->FileName
));
5533 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
5534 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
5535 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
5536 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
5537 sprintfW(Buffer
, DateFormat
, DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
5538 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5539 if (rc
== ERROR_SUCCESS
)
5540 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
5541 if (rc
== ERROR_SUCCESS
)
5542 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5543 if (rc
== ERROR_SUCCESS
)
5545 sprintfW(Buffer
, VersionFormat
, fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
5546 rc
= RegSetValueExW(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
5548 if (rc
== ERROR_SUCCESS
)
5549 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->InfFileDetails
->FileName
, (strlenW(SelectedDriver
->InfFileDetails
->FileName
) + 1) * sizeof(WCHAR
));
5550 if (rc
== ERROR_SUCCESS
)
5551 rc
= RegSetValueExW(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
5552 if (rc
== ERROR_SUCCESS
)
5553 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
));
5554 if (rc
== ERROR_SUCCESS
)
5555 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
5556 if (rc
== ERROR_SUCCESS
)
5557 rc
= RegSetValueExW(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
5558 if (rc
!= ERROR_SUCCESS
)
5564 hKey
= INVALID_HANDLE_VALUE
;
5566 /* FIXME: Process .LogConfigOverride section */
5568 /* Install .Services section */
5569 strcpyW(pSectionName
, DotServices
);
5570 Result
= SetupInstallServicesFromInfSectionExW(
5571 SelectedDriver
->InfFileDetails
->hInf
,
5580 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
5581 RebootRequired
= TRUE
;
5583 /* Open device registry key */
5584 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
5585 if (hKey
== INVALID_HANDLE_VALUE
)
5588 /* Install .HW section */
5590 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
5591 DoAction
|= SPINST_REGISTRY
;
5592 strcpyW(pSectionName
, DotHW
);
5593 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
5594 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
5595 DoAction
, hKey
, NULL
, 0,
5597 DeviceInfoSet
, DeviceInfoData
);
5601 /* Write information to enum key */
5602 TRACE("Write information to enum key\n");
5603 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
5604 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
5605 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
5606 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
5607 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
5608 if (rc
== ERROR_SUCCESS
)
5609 rc
= RegSetValueExW(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
5610 if (rc
== ERROR_SUCCESS
)
5611 rc
= RegSetValueExW(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
5612 if (rc
== ERROR_SUCCESS
)
5613 rc
= RegSetValueExW(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
5614 if (rc
!= ERROR_SUCCESS
)
5620 /* Start the device */
5621 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
5622 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
5627 /* End of installation */
5628 if (hKey
!= INVALID_HANDLE_VALUE
)
5631 RpcStringFreeW(&lpGuidString
);
5632 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
5634 SetupTermDefaultQueueCallback(Context
);
5635 TRACE("Returning %d\n", ret
);
5639 static HKEY
SETUPDI_OpenDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5641 HKEY enumKey
, key
= INVALID_HANDLE_VALUE
;
5644 l
= RegOpenKeyExW(RootKey
, REGSTR_PATH_SYSTEMENUM
, 0, 0, &enumKey
);
5647 l
= RegOpenKeyExW(enumKey
, devInfo
->instanceId
, 0, samDesired
, &key
);
5648 RegCloseKey(enumKey
);
5655 static HKEY
SETUPDI_OpenDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
, REGSAM samDesired
)
5657 LPWSTR DriverKey
= NULL
;
5661 HKEY hEnumKey
= NULL
;
5663 HKEY key
= INVALID_HANDLE_VALUE
;
5665 hKey
= SETUPDI_OpenDevKey(RootKey
, devInfo
, KEY_QUERY_VALUE
);
5666 if (hKey
== INVALID_HANDLE_VALUE
)
5668 /* Read the 'Driver' key */
5669 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5670 if (rc
!= ERROR_SUCCESS
)
5675 else if (dwRegType
!= REG_SZ
)
5677 SetLastError(ERROR_GEN_FAILURE
);
5680 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5683 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5686 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5687 if (rc
!= ERROR_SUCCESS
)
5694 /* Need to open the driver key */
5697 REGSTR_PATH_CLASS_NT
,
5701 if (rc
!= ERROR_SUCCESS
)
5712 if (rc
!= ERROR_SUCCESS
)
5720 if (hEnumKey
!= NULL
)
5721 RegCloseKey(hEnumKey
);
5722 if (hKey
!= NULL
&& hKey
!= key
)
5727 /***********************************************************************
5728 * SetupDiOpenDevRegKey (SETUPAPI.@)
5730 HKEY WINAPI
SetupDiOpenDevRegKey(
5731 HDEVINFO DeviceInfoSet
,
5732 PSP_DEVINFO_DATA DeviceInfoData
,
5738 struct DeviceInfoSet
*set
= DeviceInfoSet
;
5739 struct DeviceInfo
*devInfo
;
5740 HKEY key
= INVALID_HANDLE_VALUE
;
5743 TRACE("%p %p %d %d %d %x\n", DeviceInfoSet
, DeviceInfoData
,
5744 Scope
, HwProfile
, KeyType
, samDesired
);
5746 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5748 SetLastError(ERROR_INVALID_HANDLE
);
5749 return INVALID_HANDLE_VALUE
;
5751 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5753 SetLastError(ERROR_INVALID_HANDLE
);
5754 return INVALID_HANDLE_VALUE
;
5756 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5757 || !DeviceInfoData
->Reserved
)
5759 SetLastError(ERROR_INVALID_PARAMETER
);
5760 return INVALID_HANDLE_VALUE
;
5762 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5764 SetLastError(ERROR_INVALID_FLAGS
);
5765 return INVALID_HANDLE_VALUE
;
5767 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
5769 SetLastError(ERROR_INVALID_FLAGS
);
5770 return INVALID_HANDLE_VALUE
;
5772 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5773 if (devInfo
->set
!= set
)
5775 SetLastError(ERROR_INVALID_PARAMETER
);
5776 return INVALID_HANDLE_VALUE
;
5778 if (Scope
!= DICS_FLAG_GLOBAL
)
5780 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5781 if (RootKey
== INVALID_HANDLE_VALUE
)
5782 return INVALID_HANDLE_VALUE
;
5785 RootKey
= set
->HKLM
;
5789 key
= SETUPDI_OpenDevKey(RootKey
, devInfo
, samDesired
);
5792 key
= SETUPDI_OpenDrvKey(RootKey
, devInfo
, samDesired
);
5795 WARN("unknown KeyType %d\n", KeyType
);
5797 if (RootKey
!= set
->HKLM
)
5798 RegCloseKey(RootKey
);
5802 static BOOL
SETUPDI_DeleteDevKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5808 static BOOL
SETUPDI_DeleteDrvKey(HKEY RootKey
, struct DeviceInfo
*devInfo
)
5814 /***********************************************************************
5815 * SetupDiDeleteDevRegKey (SETUPAPI.@)
5817 BOOL WINAPI
SetupDiDeleteDevRegKey(
5818 HDEVINFO DeviceInfoSet
,
5819 PSP_DEVINFO_DATA DeviceInfoData
,
5824 struct DeviceInfoSet
*set
= (struct DeviceInfoSet
*)DeviceInfoSet
;
5825 struct DeviceInfo
*devInfo
;
5829 TRACE("%p %p %d %d %d\n", DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
,
5832 if (!DeviceInfoSet
|| DeviceInfoSet
== INVALID_HANDLE_VALUE
)
5834 SetLastError(ERROR_INVALID_HANDLE
);
5837 if (set
->magic
!= SETUP_DEVICE_INFO_SET_MAGIC
)
5839 SetLastError(ERROR_INVALID_HANDLE
);
5842 if (!DeviceInfoData
|| DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
)
5843 || !DeviceInfoData
->Reserved
)
5845 SetLastError(ERROR_INVALID_PARAMETER
);
5848 if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5850 SetLastError(ERROR_INVALID_FLAGS
);
5853 if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
&& KeyType
!= DIREG_BOTH
)
5855 SetLastError(ERROR_INVALID_FLAGS
);
5858 devInfo
= (struct DeviceInfo
*)DeviceInfoData
->Reserved
;
5859 if (devInfo
->set
!= set
)
5861 SetLastError(ERROR_INVALID_PARAMETER
);
5864 if (Scope
!= DICS_FLAG_GLOBAL
)
5866 RootKey
= OpenHardwareProfileKey(set
->HKLM
, HwProfile
, 0);
5867 if (RootKey
== INVALID_HANDLE_VALUE
)
5871 RootKey
= set
->HKLM
;
5875 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
5878 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
5881 ret
= SETUPDI_DeleteDevKey(RootKey
, devInfo
);
5883 ret
= SETUPDI_DeleteDrvKey(RootKey
, devInfo
);
5886 WARN("unknown KeyType %d\n", KeyType
);
5888 if (RootKey
!= set
->HKLM
)
5889 RegCloseKey(RootKey
);