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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
26 /* Unicode constants */
27 static const WCHAR AddInterface
[] = {'A','d','d','I','n','t','e','r','f','a','c','e',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 ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
31 static const WCHAR Control
[] = {'C','o','n','t','r','o','l',0};
32 static const WCHAR DeviceInstance
[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};
33 static const WCHAR DotCoInstallers
[] = {'.','C','o','I','n','s','t','a','l','l','e','r','s',0};
34 static const WCHAR DotHW
[] = {'.','H','W',0};
35 static const WCHAR DotInterfaces
[] = {'.','I','n','t','e','r','f','a','c','e','s',0};
36 static const WCHAR DotServices
[] = {'.','S','e','r','v','i','c','e','s',0};
37 static const WCHAR InterfaceInstall32
[] = {'I','n','t','e','r','f','a','c','e','I','n','s','t','a','l','l','3','2',0};
38 static const WCHAR Linked
[] = {'L','i','n','k','e','d',0};
39 static const WCHAR SymbolicLink
[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
40 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
42 static const WCHAR REGSTR_DRIVER_DATE
[] = {'D','r','i','v','e','r','D','a','t','e',0};
43 static const WCHAR REGSTR_DRIVER_DATE_DATA
[] = {'D','r','i','v','e','r','D','a','t','e','D','a','t','a',0};
44 static const WCHAR REGSTR_DRIVER_VERSION
[] = {'D','r','i','v','e','r','V','e','r','s','i','o','n',0};
45 static const WCHAR REGSTR_SECURITY
[] = {'S','e','c','u','r','i','t','y',0};
46 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};
48 static const WCHAR INF_MANUFACTURER
[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
49 static const WCHAR INF_PROVIDER
[] = {'P','r','o','v','i','d','e','r',0};
50 static const WCHAR INF_DRIVER_VER
[] = {'D','r','i','v','e','r','V','e','r',0};
53 (CALLBACK
* CLASS_INSTALL_PROC
) (
54 IN DI_FUNCTION InstallFunction
,
55 IN HDEVINFO DeviceInfoSet
,
56 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
);
58 (WINAPI
* DEFAULT_CLASS_INSTALL_PROC
) (
59 IN HDEVINFO DeviceInfoSet
,
60 IN OUT PSP_DEVINFO_DATA DeviceInfoData
);
62 (CALLBACK
* COINSTALLER_PROC
) (
63 IN DI_FUNCTION InstallFunction
,
64 IN HDEVINFO DeviceInfoSet
,
65 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
66 IN OUT PCOINSTALLER_CONTEXT_DATA Context
);
68 (WINAPI
* PROPERTY_PAGE_PROVIDER
) (
69 IN PSP_PROPSHEETPAGE_REQUEST PropPageRequest
,
70 IN LPFNADDPROPSHEETPAGE fAddFunc
,
73 (*UPDATE_CLASS_PARAM_HANDLER
) (
74 IN HDEVINFO DeviceInfoSet
,
75 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
76 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
77 IN DWORD ClassInstallParamsSize
);
79 struct CoInstallerElement
84 COINSTALLER_PROC Function
;
85 BOOL DoPostProcessing
;
90 PropertyChangeHandler(
91 IN HDEVINFO DeviceInfoSet
,
92 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
93 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
94 IN DWORD ClassInstallParamsSize
);
96 static UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
97 NULL
, /* DIF_SELECTDEVICE */
98 NULL
, /* DIF_INSTALLDEVICE */
99 NULL
, /* DIF_ASSIGNRESOURCES */
100 NULL
, /* DIF_PROPERTIES */
101 NULL
, /* DIF_REMOVE */
102 NULL
, /* DIF_FIRSTTIMESETUP */
103 NULL
, /* DIF_FOUNDDEVICE */
104 NULL
, /* DIF_SELECTCLASSDRIVERS */
105 NULL
, /* DIF_VALIDATECLASSDRIVERS */
106 NULL
, /* DIF_INSTALLCLASSDRIVERS */
107 NULL
, /* DIF_CALCDISKSPACE */
108 NULL
, /* DIF_DESTROYPRIVATEDATA */
109 NULL
, /* DIF_VALIDATEDRIVER */
110 NULL
, /* DIF_MOVEDEVICE */
111 NULL
, /* DIF_DETECT */
112 NULL
, /* DIF_INSTALLWIZARD */
113 NULL
, /* DIF_DESTROYWIZARDDATA */
114 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
115 NULL
, /* DIF_ENABLECLASS */
116 NULL
, /* DIF_DETECTVERIFY */
117 NULL
, /* DIF_INSTALLDEVICEFILES */
118 NULL
, /* DIF_UNREMOVE */
119 NULL
, /* DIF_SELECTBESTCOMPATDRV */
120 NULL
, /* DIF_ALLOW_INSTALL */
121 NULL
, /* DIF_REGISTERDEVICE */
122 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
123 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
124 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
125 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
126 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
127 NULL
, /* DIF_UNUSED1 */
128 NULL
, /* DIF_INSTALLINTERFACES */
129 NULL
, /* DIF_DETECTCANCEL */
130 NULL
, /* DIF_REGISTER_COINSTALLERS */
131 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
132 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
133 NULL
, /* DIF_RESERVED1 */
134 NULL
, /* DIF_TROUBLESHOOTER */
135 NULL
, /* DIF_POWERMESSAGEWAKE */
136 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
137 NULL
, /* DIF_UPDATEDRIVER_UI */
138 NULL
/* DIF_RESERVED2 */
141 /***********************************************************************
142 * SetupDiBuildClassInfoList (SETUPAPI.@)
144 BOOL WINAPI
SetupDiBuildClassInfoList(
146 LPGUID ClassGuidList
,
147 DWORD ClassGuidListSize
,
151 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
152 ClassGuidListSize
, RequiredSize
,
156 /***********************************************************************
157 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
159 BOOL WINAPI
SetupDiBuildClassInfoListExA(
161 LPGUID ClassGuidList
,
162 DWORD ClassGuidListSize
,
167 LPWSTR MachineNameW
= NULL
;
174 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
175 if (MachineNameW
== NULL
) return FALSE
;
178 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
179 ClassGuidListSize
, RequiredSize
,
180 MachineNameW
, Reserved
);
183 MyFree(MachineNameW
);
188 /***********************************************************************
189 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
191 BOOL WINAPI
SetupDiBuildClassInfoListExW(
193 LPGUID ClassGuidList
,
194 DWORD ClassGuidListSize
,
199 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
200 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
201 HKEY hClassKey
= NULL
;
205 DWORD dwGuidListIndex
= 0;
208 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
209 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
211 if (RequiredSize
!= NULL
)
214 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
215 KEY_ENUMERATE_SUB_KEYS
,
219 if (hClassesKey
== INVALID_HANDLE_VALUE
)
222 for (dwIndex
= 0; ; dwIndex
++)
224 dwLength
= MAX_GUID_STRING_LEN
+ 1;
225 lError
= RegEnumKeyExW(hClassesKey
,
233 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
234 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
236 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
238 if (hClassKey
!= NULL
)
239 RegCloseKey(hClassKey
);
240 if (RegOpenKeyExW(hClassesKey
,
244 &hClassKey
) != ERROR_SUCCESS
)
249 if (RegQueryValueExW(hClassKey
,
250 REGSTR_VAL_NOUSECLASS
,
254 NULL
) == ERROR_SUCCESS
)
256 TRACE("'NoUseClass' value found!\n");
260 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
261 (!RegQueryValueExW(hClassKey
,
262 REGSTR_VAL_NOINSTALLCLASS
,
268 TRACE("'NoInstallClass' value found!\n");
272 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
273 (!RegQueryValueExW(hClassKey
,
274 REGSTR_VAL_NODISPLAYCLASS
,
280 TRACE("'NoDisplayClass' value found!\n");
284 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
285 if (dwGuidListIndex
< ClassGuidListSize
)
287 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
289 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
291 UuidFromStringW(&szKeyName
[1],
292 &ClassGuidList
[dwGuidListIndex
]);
298 if (lError
!= ERROR_SUCCESS
)
302 if (RequiredSize
!= NULL
)
303 *RequiredSize
= dwGuidListIndex
;
305 if (ClassGuidListSize
< dwGuidListIndex
)
306 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
311 if (hClassesKey
!= INVALID_HANDLE_VALUE
)
312 RegCloseKey(hClassesKey
);
313 if (hClassKey
!= NULL
)
314 RegCloseKey(hClassKey
);
318 /***********************************************************************
319 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
321 BOOL WINAPI
SetupDiClassGuidsFromNameA(
323 LPGUID ClassGuidList
,
324 DWORD ClassGuidListSize
,
327 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
328 ClassGuidListSize
, RequiredSize
,
332 /***********************************************************************
333 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
335 BOOL WINAPI
SetupDiClassGuidsFromNameW(
337 LPGUID ClassGuidList
,
338 DWORD ClassGuidListSize
,
341 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
342 ClassGuidListSize
, RequiredSize
,
346 /***********************************************************************
347 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
349 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
351 LPGUID ClassGuidList
,
352 DWORD ClassGuidListSize
,
357 LPWSTR ClassNameW
= NULL
;
358 LPWSTR MachineNameW
= NULL
;
363 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
364 if (ClassNameW
== NULL
)
369 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
370 if (MachineNameW
== NULL
)
377 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
378 ClassGuidListSize
, RequiredSize
,
379 MachineNameW
, Reserved
);
382 MyFree(MachineNameW
);
389 /***********************************************************************
390 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
392 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
394 LPGUID ClassGuidList
,
395 DWORD ClassGuidListSize
,
400 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
401 WCHAR szClassName
[256];
402 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
403 HKEY hClassKey
= NULL
;
407 DWORD dwGuidListIndex
= 0;
410 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
411 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
413 if (RequiredSize
!= NULL
)
416 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
417 KEY_ENUMERATE_SUB_KEYS
,
421 if (hClassesKey
== INVALID_HANDLE_VALUE
)
424 for (dwIndex
= 0; ; dwIndex
++)
426 dwLength
= MAX_GUID_STRING_LEN
+ 1;
427 lError
= RegEnumKeyExW(hClassesKey
,
435 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
436 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
438 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
440 if (hClassKey
!= NULL
)
441 RegCloseKey(hClassKey
);
442 if (RegOpenKeyExW(hClassesKey
,
446 &hClassKey
) != ERROR_SUCCESS
)
451 dwLength
= 256 * sizeof(WCHAR
);
452 if (RegQueryValueExW(hClassKey
,
457 &dwLength
) == ERROR_SUCCESS
)
459 TRACE("Class name: %s\n", debugstr_w(szClassName
));
461 if (strcmpiW(szClassName
, ClassName
) == 0)
463 TRACE("Found matching class name\n");
465 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
466 if (dwGuidListIndex
< ClassGuidListSize
)
468 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
470 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
472 UuidFromStringW(&szKeyName
[1],
473 &ClassGuidList
[dwGuidListIndex
]);
481 if (lError
!= ERROR_SUCCESS
)
485 if (RequiredSize
!= NULL
)
486 *RequiredSize
= dwGuidListIndex
;
488 if (ClassGuidListSize
< dwGuidListIndex
)
489 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
494 if (hClassesKey
!= INVALID_HANDLE_VALUE
)
495 RegCloseKey(hClassesKey
);
496 if (hClassKey
!= NULL
)
497 RegCloseKey(hClassKey
);
501 /***********************************************************************
502 * SetupDiClassNameFromGuidA (SETUPAPI.@)
504 BOOL WINAPI
SetupDiClassNameFromGuidA(
505 const GUID
* ClassGuid
,
510 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
511 ClassNameSize
, RequiredSize
,
515 /***********************************************************************
516 * SetupDiClassNameFromGuidW (SETUPAPI.@)
518 BOOL WINAPI
SetupDiClassNameFromGuidW(
519 const GUID
* ClassGuid
,
524 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
525 ClassNameSize
, RequiredSize
,
529 /***********************************************************************
530 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
532 BOOL WINAPI
SetupDiClassNameFromGuidExA(
533 const GUID
* ClassGuid
,
540 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
541 LPWSTR MachineNameW
= NULL
;
545 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
546 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
547 NULL
, MachineNameW
, Reserved
);
550 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
551 ClassNameSize
, NULL
, NULL
);
553 if (!ClassNameSize
&& RequiredSize
)
556 MyFree(MachineNameW
);
560 /***********************************************************************
561 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
563 BOOL WINAPI
SetupDiClassNameFromGuidExW(
564 const GUID
* ClassGuid
,
576 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
577 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
579 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
584 if (hKey
== INVALID_HANDLE_VALUE
)
587 if (RequiredSize
!= NULL
)
590 rc
= RegQueryValueExW(hKey
,
596 if (rc
!= ERROR_SUCCESS
)
602 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
605 dwLength
= ClassNameSize
* sizeof(WCHAR
);
606 rc
= RegQueryValueExW(hKey
,
612 if (rc
!= ERROR_SUCCESS
)
621 if (hKey
!= INVALID_HANDLE_VALUE
)
626 /***********************************************************************
627 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
630 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
633 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
636 /***********************************************************************
637 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
640 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
645 LPWSTR MachineNameW
= NULL
;
648 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
649 debugstr_a(MachineName
), Reserved
);
653 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
654 if (MachineNameW
== NULL
)
655 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
658 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
659 MachineNameW
, Reserved
);
662 MyFree(MachineNameW
);
668 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
672 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
673 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
674 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
675 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
676 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
677 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
678 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
679 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
680 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
681 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
682 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
683 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
684 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
685 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
686 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
687 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
688 case CR_SUCCESS
: return ERROR_SUCCESS
;
689 default: return ERROR_GEN_FAILURE
;
692 /* Does not happen */
695 /***********************************************************************
696 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
699 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
704 struct DeviceInfoSet
*list
;
705 LPWSTR UNCServerName
= NULL
;
709 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
711 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
712 debugstr_w(MachineName
), Reserved
);
714 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
716 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
717 list
= HeapAlloc(GetProcessHeap(), 0, size
);
720 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
723 memset(list
, 0, sizeof(struct DeviceInfoSet
));
725 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
728 ClassGuid
? ClassGuid
: &GUID_NULL
,
729 sizeof(list
->ClassGuid
));
730 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
731 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
732 list
->InstallParams
.hwndParent
= hwndParent
;
735 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
736 if (rc
!= ERROR_SUCCESS
)
741 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
744 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
748 strcpyW(UNCServerName
+ 2, MachineName
);
749 list
->szData
[0] = list
->szData
[1] = '\\';
750 strcpyW(list
->szData
+ 2, MachineName
);
751 list
->MachineName
= list
->szData
;
755 DWORD Size
= MAX_PATH
;
756 list
->HKLM
= HKEY_LOCAL_MACHINE
;
757 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
760 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
763 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
765 list
->MachineName
= NULL
;
768 UNCServerName
[0] = UNCServerName
[1] = '\\';
769 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
770 if (cr
!= CR_SUCCESS
)
772 SetLastError(GetErrorCodeFromCrCode(cr
));
776 InitializeListHead(&list
->DriverListHead
);
777 InitializeListHead(&list
->ListHead
);
779 ret
= (HDEVINFO
)list
;
782 if (ret
== INVALID_HANDLE_VALUE
)
786 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
787 RegCloseKey(list
->HKLM
);
789 HeapFree(GetProcessHeap(), 0, list
);
792 HeapFree(GetProcessHeap(), 0, UNCServerName
);
796 /***********************************************************************
797 * SetupDiEnumDeviceInfo (SETUPAPI.@)
799 BOOL WINAPI
SetupDiEnumDeviceInfo(
800 HDEVINFO DeviceInfoSet
,
802 PSP_DEVINFO_DATA DeviceInfoData
)
806 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
808 SetLastError(ERROR_INVALID_PARAMETER
);
809 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
811 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
813 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
814 SetLastError(ERROR_INVALID_HANDLE
);
815 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
816 SetLastError(ERROR_INVALID_USER_BUFFER
);
819 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
820 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
821 ItemList
= ItemList
->Flink
;
822 if (ItemList
== &list
->ListHead
)
823 SetLastError(ERROR_NO_MORE_ITEMS
);
826 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
827 memcpy(&DeviceInfoData
->ClassGuid
,
830 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
831 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
837 SetLastError(ERROR_INVALID_HANDLE
);
841 /***********************************************************************
842 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
845 SetupDiGetActualSectionToInstallA(
847 IN PCSTR InfSectionName
,
848 OUT PSTR InfSectionWithExt OPTIONAL
,
849 IN DWORD InfSectionWithExtSize
,
850 OUT PDWORD RequiredSize OPTIONAL
,
851 OUT PSTR
*Extension OPTIONAL
)
853 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
854 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
858 /***********************************************************************
859 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
862 SetupDiGetActualSectionToInstallW(
864 IN PCWSTR InfSectionName
,
865 OUT PWSTR InfSectionWithExt OPTIONAL
,
866 IN DWORD InfSectionWithExtSize
,
867 OUT PDWORD RequiredSize OPTIONAL
,
868 OUT PWSTR
*Extension OPTIONAL
)
870 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
871 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
875 /***********************************************************************
876 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
879 SetupDiGetActualSectionToInstallExA(
881 IN PCSTR InfSectionName
,
882 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
883 OUT PSTR InfSectionWithExt OPTIONAL
,
884 IN DWORD InfSectionWithExtSize
,
885 OUT PDWORD RequiredSize OPTIONAL
,
886 OUT PSTR
* Extension OPTIONAL
,
889 LPWSTR InfSectionNameW
= NULL
;
890 LPWSTR InfSectionWithExtW
= NULL
;
892 BOOL bResult
= FALSE
;
898 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
899 if (InfSectionNameW
== NULL
)
902 if (InfSectionWithExt
)
904 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
905 if (InfSectionWithExtW
== NULL
)
909 bResult
= SetupDiGetActualSectionToInstallExW(
910 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
911 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
912 InfSectionWithExtSize
,
914 Extension
? &ExtensionW
: NULL
,
917 if (bResult
&& InfSectionWithExt
)
919 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
920 InfSectionWithExtSize
, NULL
, NULL
) != 0;
922 if (bResult
&& Extension
)
924 if (ExtensionW
== NULL
)
927 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
931 MyFree(InfSectionNameW
);
932 MyFree(InfSectionWithExtW
);
937 /***********************************************************************
938 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
941 SetupDiGetActualSectionToInstallExW(
943 IN PCWSTR InfSectionName
,
944 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
945 OUT PWSTR InfSectionWithExt OPTIONAL
,
946 IN DWORD InfSectionWithExtSize
,
947 OUT PDWORD RequiredSize OPTIONAL
,
948 OUT PWSTR
* Extension OPTIONAL
,
953 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
954 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
955 RequiredSize
, Extension
, Reserved
);
957 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
958 SetLastError(ERROR_INVALID_HANDLE
);
959 else if (!InfSectionName
)
960 SetLastError(ERROR_INVALID_PARAMETER
);
961 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
962 SetLastError(ERROR_INVALID_USER_BUFFER
);
963 else if (Reserved
!= NULL
)
964 SetLastError(ERROR_INVALID_PARAMETER
);
967 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
968 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
969 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
970 WCHAR SectionName
[LINE_LEN
+ 1];
971 LONG lLineCount
= -1;
974 /* Fill platform info if needed */
975 if (AlternatePlatformInfo
)
976 pPlatformInfo
= AlternatePlatformInfo
;
977 else if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
979 /* That's the first time we go here. We need to fill in the structure */
980 OSVERSIONINFO VersionInfo
;
981 SYSTEM_INFO SystemInfo
;
982 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFO
);
983 ret
= GetVersionEx(&VersionInfo
);
986 GetSystemInfo(&SystemInfo
);
987 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
988 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
989 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
990 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
991 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
992 CurrentPlatform
.Reserved
= 0;
995 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
996 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
997 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
999 static const WCHAR ExtensionArchitectureNone
[] = {0};
1000 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
1001 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
1002 static const WCHAR ExtensionArchitectureia64
[] = {'i','a','6','4',0};
1003 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
1004 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
1005 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
1007 /* Set various extensions values */
1008 switch (pPlatformInfo
->Platform
)
1010 case VER_PLATFORM_WIN32_WINDOWS
:
1011 pExtensionPlatform
= ExtensionPlatformWindows
;
1013 case VER_PLATFORM_WIN32_NT
:
1014 pExtensionPlatform
= ExtensionPlatformNT
;
1017 ERR("Unkown platform 0x%lx\n", pPlatformInfo
->Platform
);
1018 pExtensionPlatform
= ExtensionPlatformNone
;
1021 switch (pPlatformInfo
->ProcessorArchitecture
)
1023 case PROCESSOR_ARCHITECTURE_ALPHA
:
1024 pExtensionArchitecture
= ExtensionArchitecturealpha
;
1026 case PROCESSOR_ARCHITECTURE_AMD64
:
1027 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1029 case PROCESSOR_ARCHITECTURE_IA64
:
1030 pExtensionArchitecture
= ExtensionArchitectureia64
;
1032 case PROCESSOR_ARCHITECTURE_INTEL
:
1033 pExtensionArchitecture
= ExtensionArchitecturex86
;
1035 case PROCESSOR_ARCHITECTURE_MIPS
:
1036 pExtensionArchitecture
= ExtensionArchitecturemips
;
1038 case PROCESSOR_ARCHITECTURE_PPC
:
1039 pExtensionArchitecture
= ExtensionArchitectureppc
;
1042 ERR("Unknown processor architecture 0x%x\n", pPlatformInfo
->ProcessorArchitecture
);
1043 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1044 pExtensionArchitecture
= ExtensionArchitectureNone
;
1048 static const WCHAR FormatPlatformArchitectureMajorMinor
[] = {'%','s','%','s','%','s','.','%','l','u','.','%','l','u',0};
1049 static const WCHAR FormatPlatformMajorMinor
[] = {'%','s','%','s','.','%','l','u','.','%','l','u',0};
1050 static const WCHAR FormatPlatformArchitectureMajor
[] = {'%','s','%','s','%','s','.','%','l','u',0};
1051 static const WCHAR FormatPlatformMajor
[] = {'%','s','%','s','.','%','l','u',0};
1052 static const WCHAR FormatPlatformArchitecture
[] = {'%','s','%','s','%','s',0};
1053 static const WCHAR FormatPlatform
[] = {'%','s','%','s',0};
1054 static const WCHAR FormatNone
[] = {'%','s',0};
1056 SectionName
[LINE_LEN
] = UNICODE_NULL
;
1058 /* Test with platform.architecture.major.minor extension */
1059 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitectureMajorMinor
, InfSectionName
,
1060 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1061 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1062 if (lLineCount
!= -1) goto sectionfound
;
1064 /* Test with platform.major.minor extension */
1065 snprintfW(SectionName
, LINE_LEN
, FormatPlatformMajorMinor
, InfSectionName
,
1066 pExtensionPlatform
, pPlatformInfo
->MajorVersion
, pPlatformInfo
->MinorVersion
);
1067 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1068 if (lLineCount
!= -1) goto sectionfound
;
1070 /* Test with platform.architecture.major extension */
1071 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitectureMajor
, InfSectionName
,
1072 pExtensionPlatform
, pExtensionArchitecture
, pPlatformInfo
->MajorVersion
);
1073 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1074 if (lLineCount
!= -1) goto sectionfound
;
1076 /* Test with platform.major extension */
1077 snprintfW(SectionName
, LINE_LEN
, FormatPlatformMajor
, InfSectionName
,
1078 pExtensionPlatform
, pPlatformInfo
->MajorVersion
);
1079 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1080 if (lLineCount
!= -1) goto sectionfound
;
1082 /* Test with platform.architecture extension */
1083 snprintfW(SectionName
, LINE_LEN
, FormatPlatformArchitecture
, InfSectionName
,
1084 pExtensionPlatform
, pExtensionArchitecture
);
1085 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1086 if (lLineCount
!= -1) goto sectionfound
;
1088 /* Test with platform extension */
1089 snprintfW(SectionName
, LINE_LEN
, FormatPlatform
, InfSectionName
,
1090 pExtensionPlatform
);
1091 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1092 if (lLineCount
!= -1) goto sectionfound
;
1094 /* Test without extension */
1095 snprintfW(SectionName
, LINE_LEN
, FormatNone
, InfSectionName
);
1096 lLineCount
= SetupGetLineCountW(InfHandle
, SectionName
);
1097 if (lLineCount
!= -1) goto sectionfound
;
1099 /* No appropriate section found */
1100 SetLastError(ERROR_INVALID_PARAMETER
);
1104 dwFullLength
= lstrlenW(SectionName
);
1105 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
1107 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
1109 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1113 lstrcpyW(InfSectionWithExt
, SectionName
);
1114 if (Extension
!= NULL
)
1116 DWORD dwLength
= lstrlenW(SectionName
);
1117 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1121 if (RequiredSize
!= NULL
)
1122 *RequiredSize
= dwFullLength
+ 1;
1128 TRACE("Returning %d\n", ret
);
1133 /***********************************************************************
1134 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1136 BOOL WINAPI
SetupDiGetClassDescriptionA(
1137 const GUID
* ClassGuid
,
1138 PSTR ClassDescription
,
1139 DWORD ClassDescriptionSize
,
1140 PDWORD RequiredSize
)
1142 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1143 ClassDescriptionSize
,
1144 RequiredSize
, NULL
, NULL
);
1147 /***********************************************************************
1148 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1150 BOOL WINAPI
SetupDiGetClassDescriptionW(
1151 const GUID
* ClassGuid
,
1152 PWSTR ClassDescription
,
1153 DWORD ClassDescriptionSize
,
1154 PDWORD RequiredSize
)
1156 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1157 ClassDescriptionSize
,
1158 RequiredSize
, NULL
, NULL
);
1161 /***********************************************************************
1162 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1164 BOOL WINAPI
SetupDiGetClassDescriptionExA(
1165 const GUID
* ClassGuid
,
1166 PSTR ClassDescription
,
1167 DWORD ClassDescriptionSize
,
1168 PDWORD RequiredSize
,
1172 PWCHAR ClassDescriptionW
;
1173 LPWSTR MachineNameW
= NULL
;
1177 if (ClassDescriptionSize
> 0)
1179 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1180 if (!ClassDescriptionW
)
1182 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1188 ClassDescriptionW
= NULL
;
1192 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1195 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1201 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1202 NULL
, MachineNameW
, Reserved
);
1205 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1206 ClassDescriptionSize
, NULL
, NULL
);
1208 if (!ClassDescriptionSize
&& RequiredSize
)
1209 *RequiredSize
= len
;
1213 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1214 MyFree(MachineNameW
);
1218 /***********************************************************************
1219 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1221 BOOL WINAPI
SetupDiGetClassDescriptionExW(
1222 const GUID
* ClassGuid
,
1223 PWSTR ClassDescription
,
1224 DWORD ClassDescriptionSize
,
1225 PDWORD RequiredSize
,
1229 HKEY hKey
= INVALID_HANDLE_VALUE
;
1233 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1234 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1236 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1241 if (hKey
== INVALID_HANDLE_VALUE
)
1243 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1247 if (RequiredSize
!= NULL
)
1250 if (RegQueryValueExW(hKey
,
1255 &dwLength
) != ERROR_SUCCESS
)
1260 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1263 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1264 if (RegQueryValueExW(hKey
,
1268 (LPBYTE
)ClassDescription
,
1269 &dwLength
) != ERROR_SUCCESS
)
1277 if (hKey
!= INVALID_HANDLE_VALUE
)
1283 /***********************************************************************
1284 * SetupDiGetClassDevsA (SETUPAPI.@)
1286 HDEVINFO WINAPI
SetupDiGetClassDevsA(
1292 return SetupDiGetClassDevsExA(class, enumstr
, parent
,
1293 flags
, NULL
, NULL
, NULL
);
1296 /***********************************************************************
1297 * SetupDiGetClassDevsW (SETUPAPI.@)
1299 HDEVINFO WINAPI
SetupDiGetClassDevsW(
1305 return SetupDiGetClassDevsExW(class, enumstr
, parent
,
1306 flags
, NULL
, NULL
, NULL
);
1309 /***********************************************************************
1310 * SetupDiGetClassDevsExA (SETUPAPI.@)
1312 HDEVINFO WINAPI
SetupDiGetClassDevsExA(
1322 LPWSTR enumstrW
= NULL
;
1323 LPWSTR machineW
= NULL
;
1327 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
1328 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1331 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1334 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
1338 int len
= MultiByteToWideChar(CP_ACP
, 0, machine
, -1, NULL
, 0);
1339 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1342 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1345 MultiByteToWideChar(CP_ACP
, 0, machine
, -1, machineW
, len
);
1347 ret
= SetupDiGetClassDevsExW(class, enumstrW
, parent
, flags
, deviceset
, machineW
, reserved
);
1350 HeapFree(GetProcessHeap(), 0, enumstrW
);
1351 HeapFree(GetProcessHeap(), 0, machineW
);
1356 CreateDeviceInfoElement(
1357 IN
struct DeviceInfoSet
*list
,
1358 IN LPCWSTR InstancePath
,
1359 IN LPCGUID pClassGuid
,
1360 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1364 struct DeviceInfoElement
*deviceInfo
;
1366 *pDeviceInfo
= NULL
;
1368 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
1369 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1372 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1375 memset(deviceInfo
, 0, size
);
1377 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1378 if (cr
!= CR_SUCCESS
)
1380 SetLastError(GetErrorCodeFromCrCode(cr
));
1384 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1385 strcpyW(deviceInfo
->Data
, InstancePath
);
1386 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1387 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
1388 deviceInfo
->DeviceDescription
= NULL
;
1389 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1390 deviceInfo
->CreationFlags
= 0;
1391 InitializeListHead(&deviceInfo
->DriverListHead
);
1392 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1394 *pDeviceInfo
= deviceInfo
;
1399 CreateDeviceInterface(
1400 IN
struct DeviceInfoElement
* deviceInfo
,
1401 IN LPCWSTR SymbolicLink
,
1402 IN LPCGUID pInterfaceGuid
,
1403 OUT
struct DeviceInterface
**pDeviceInterface
)
1405 struct DeviceInterface
*deviceInterface
;
1407 *pDeviceInterface
= NULL
;
1409 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1410 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (strlenW(SymbolicLink
) + 1) * sizeof(WCHAR
));
1411 if (!deviceInterface
)
1413 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1416 deviceInterface
->DeviceInfo
= deviceInfo
;
1417 strcpyW(deviceInterface
->SymbolicLink
, SymbolicLink
);
1418 deviceInterface
->Flags
= 0; /* Flags will be updated later */
1419 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1421 *pDeviceInterface
= deviceInterface
;
1425 static LONG
SETUP_CreateDevListFromEnumerator(
1426 struct DeviceInfoSet
*list
,
1427 LPCGUID pClassGuid OPTIONAL
,
1429 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1431 HKEY hDeviceIdKey
= NULL
, hInstanceIdKey
;
1432 WCHAR KeyBuffer
[MAX_PATH
];
1433 WCHAR InstancePath
[MAX_PATH
];
1434 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1435 struct DeviceInfoElement
*deviceInfo
;
1437 DWORD dwLength
, dwRegType
;
1440 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1443 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1444 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1445 if (rc
== ERROR_NO_MORE_ITEMS
)
1447 if (rc
!= ERROR_SUCCESS
)
1451 /* Open device id sub key */
1452 if (hDeviceIdKey
!= NULL
)
1453 RegCloseKey(hDeviceIdKey
);
1454 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1455 if (rc
!= ERROR_SUCCESS
)
1457 strcpyW(InstancePath
, Enumerator
);
1458 strcatW(InstancePath
, L
"\\");
1459 strcatW(InstancePath
, KeyBuffer
);
1460 strcatW(InstancePath
, L
"\\");
1461 pEndOfInstancePath
= &InstancePath
[strlenW(InstancePath
)];
1463 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1469 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1470 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1471 if (rc
== ERROR_NO_MORE_ITEMS
)
1473 if (rc
!= ERROR_SUCCESS
)
1477 /* Open instance id sub key */
1478 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1479 if (rc
!= ERROR_SUCCESS
)
1481 *pEndOfInstancePath
= '\0';
1482 strcatW(InstancePath
, KeyBuffer
);
1484 /* Read ClassGUID value */
1485 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1486 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1487 RegCloseKey(hInstanceIdKey
);
1488 if (rc
== ERROR_FILE_NOT_FOUND
)
1491 /* Skip this bad entry as we can't verify it */
1493 /* Set a default GUID for this device */
1494 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1496 else if (rc
!= ERROR_SUCCESS
)
1500 else if (dwRegType
!= REG_SZ
)
1502 rc
= ERROR_GEN_FAILURE
;
1507 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1508 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1509 /* Bad GUID, skip the entry */
1513 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1515 /* Skip this entry as it is not the right device class */
1519 /* Add the entry to the list */
1520 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1522 rc
= GetLastError();
1525 TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath
), list
);
1526 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1533 if (hDeviceIdKey
!= NULL
)
1534 RegCloseKey(hDeviceIdKey
);
1538 static LONG
SETUP_CreateDevList(
1539 struct DeviceInfoSet
*list
,
1540 PCWSTR MachineName OPTIONAL
,
1541 LPGUID
class OPTIONAL
,
1542 PCWSTR Enumerator OPTIONAL
)
1544 HKEY HKLM
= HKEY_LOCAL_MACHINE
;
1545 HKEY hEnumKey
= NULL
;
1546 HKEY hEnumeratorKey
= NULL
;
1547 WCHAR KeyBuffer
[MAX_PATH
];
1552 if (class && IsEqualIID(class, &GUID_NULL
))
1555 /* Open Enum key (if applicable) */
1556 if (MachineName
!= NULL
)
1558 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1559 if (rc
!= ERROR_SUCCESS
)
1565 REGSTR_PATH_SYSTEMENUM
,
1567 KEY_ENUMERATE_SUB_KEYS
,
1569 if (rc
!= ERROR_SUCCESS
)
1572 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1573 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1582 KEY_ENUMERATE_SUB_KEYS
,
1584 if (rc
!= ERROR_SUCCESS
)
1586 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1590 /* Enumerate enumerators */
1594 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1595 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1596 if (rc
== ERROR_NO_MORE_ITEMS
)
1598 else if (rc
!= ERROR_SUCCESS
)
1603 if (hEnumeratorKey
!= NULL
)
1604 RegCloseKey(hEnumeratorKey
);
1605 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1606 if (rc
!= ERROR_SUCCESS
)
1609 /* Call SETUP_CreateDevListFromEnumerator */
1610 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1611 if (rc
!= ERROR_SUCCESS
)
1618 if (HKLM
!= HKEY_LOCAL_MACHINE
)
1620 if (hEnumKey
!= NULL
)
1621 RegCloseKey(hEnumKey
);
1622 if (hEnumeratorKey
!= NULL
)
1623 RegCloseKey(hEnumeratorKey
);
1627 static BOOL
DestroyDeviceInterface(struct DeviceInterface
* deviceInterface
)
1629 HeapFree(GetProcessHeap(), 0, deviceInterface
);
1633 static LONG
SETUP_CreateInterfaceList(
1634 struct DeviceInfoSet
*list
,
1636 LPGUID InterfaceGuid
,
1637 PCWSTR DeviceInstanceW
/* OPTIONAL */,
1638 BOOL OnlyPresentInterfaces
1641 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1642 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1643 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1644 HKEY hControlKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
1645 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1646 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1648 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1649 PWSTR pSymbolicLink
= NULL
;
1650 PWSTR InstancePath
= NULL
;
1652 DWORD dwLength
, dwInstancePathLength
;
1656 struct DeviceInfoElement
*deviceInfo
;
1658 hInterfaceKey
= INVALID_HANDLE_VALUE
;
1659 hDeviceInstanceKey
= NULL
;
1660 hReferenceKey
= NULL
;
1662 /* Open registry key related to this interface */
1663 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1664 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1666 rc
= GetLastError();
1670 /* Enumerate sub keys of hInterfaceKey */
1674 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1675 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1676 if (rc
== ERROR_NO_MORE_ITEMS
)
1678 if (rc
!= ERROR_SUCCESS
)
1683 if (hDeviceInstanceKey
!= NULL
)
1684 RegCloseKey(hDeviceInstanceKey
);
1685 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1686 if (rc
!= ERROR_SUCCESS
)
1689 /* Read DeviceInstance */
1690 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1691 if (rc
!= ERROR_SUCCESS
)
1693 if (dwRegType
!= REG_SZ
)
1695 rc
= ERROR_GEN_FAILURE
;
1698 if (InstancePath
!= NULL
)
1699 HeapFree(GetProcessHeap(), 0, InstancePath
);
1700 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1703 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1706 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1707 if (rc
!= ERROR_SUCCESS
)
1709 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1710 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1712 if (DeviceInstanceW
)
1714 /* Check if device enumerator is not the right one */
1715 if (strcmpW(DeviceInstanceW
, InstancePath
) != 0)
1719 /* Find class GUID associated to the device instance */
1722 REGSTR_PATH_SYSTEMENUM
,
1726 if (rc
!= ERROR_SUCCESS
)
1734 RegCloseKey(hEnumKey
);
1735 if (rc
!= ERROR_SUCCESS
)
1737 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1738 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1740 if (rc
!= ERROR_SUCCESS
)
1742 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1743 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1744 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1746 rc
= ERROR_GEN_FAILURE
;
1749 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1751 /* If current device doesn't match the list GUID (if any), skip this entry */
1752 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1755 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1759 struct DeviceInterface
*interfaceInfo
;
1761 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1762 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1763 if (rc
== ERROR_NO_MORE_ITEMS
)
1765 if (rc
!= ERROR_SUCCESS
)
1768 if (KeyBuffer
[0] != '#')
1769 /* This entry doesn't represent an interesting entry */
1773 if (hReferenceKey
!= NULL
)
1774 RegCloseKey(hReferenceKey
);
1775 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
1776 if (rc
!= ERROR_SUCCESS
)
1779 /* Read SymbolicLink value */
1780 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
1781 if (rc
!= ERROR_SUCCESS
)
1783 if (dwRegType
!= REG_SZ
)
1785 rc
= ERROR_GEN_FAILURE
;
1789 /* We have found a device */
1790 /* Step 1. Create a device info element */
1791 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
1793 rc
= GetLastError();
1796 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
1797 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1799 /* Step 2. Create an interface list for this element */
1800 if (pSymbolicLink
!= NULL
)
1801 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1802 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
1805 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1808 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
1809 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
1810 if (rc
!= ERROR_SUCCESS
)
1812 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
1814 rc
= GetLastError();
1818 /* Step 3. Update flags */
1819 if (KeyBuffer
[1] == '\0')
1820 interfaceInfo
->Flags
|= SPINT_DEFAULT
;
1821 rc
= RegOpenKeyExW(hReferenceKey
, Control
, 0, KEY_QUERY_VALUE
, &hControlKey
);
1822 if (rc
!= ERROR_SUCCESS
)
1824 if (OnlyPresentInterfaces
)
1826 DestroyDeviceInterface(interfaceInfo
);
1830 interfaceInfo
->Flags
|= SPINT_REMOVED
;
1834 dwLength
= sizeof(DWORD
);
1835 if (RegQueryValueExW(hControlKey
, Linked
, NULL
, &dwRegType
, (LPBYTE
)&LinkedValue
, &dwLength
)
1836 && dwRegType
== REG_DWORD
&& LinkedValue
)
1837 interfaceInfo
->Flags
|= SPINT_ACTIVE
;
1838 RegCloseKey(hControlKey
);
1841 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
1842 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
1848 if (hReferenceKey
!= NULL
)
1849 RegCloseKey(hReferenceKey
);
1850 if (hDeviceInstanceKey
!= NULL
)
1851 RegCloseKey(hDeviceInstanceKey
);
1852 if (hInterfaceKey
!= INVALID_HANDLE_VALUE
)
1853 RegCloseKey(hInterfaceKey
);
1854 if (InstancePath
!= NULL
)
1855 HeapFree(GetProcessHeap(), 0, InstancePath
);
1856 if (pSymbolicLink
!= NULL
)
1857 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
1861 /***********************************************************************
1862 * SetupDiGetClassDevsExW (SETUPAPI.@)
1864 HDEVINFO WINAPI
SetupDiGetClassDevsExW(
1865 CONST GUID
*class OPTIONAL
,
1866 LPCWSTR enumstr OPTIONAL
,
1867 HWND parent OPTIONAL
,
1869 HDEVINFO deviceset OPTIONAL
,
1870 LPCWSTR machine OPTIONAL
,
1873 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
1874 struct DeviceInfoSet
*list
;
1877 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
1879 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(class), debugstr_w(enumstr
),
1880 parent
, flags
, deviceset
, debugstr_w(machine
), reserved
);
1882 /* Create the deviceset if not set */
1885 list
= (struct DeviceInfoSet
*)deviceset
;
1886 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
1888 SetLastError(ERROR_INVALID_HANDLE
);
1891 hDeviceInfo
= deviceset
;
1895 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
1896 flags
& DIGCF_DEVICEINTERFACE
? NULL
: class,
1897 NULL
, machine
, NULL
);
1898 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
1900 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
1903 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
1906 pClassGuid
= &list
->ClassGuid
;
1908 if (flags
& DIGCF_PROFILE
)
1909 FIXME(": flag DIGCF_PROFILE ignored\n");
1911 if (flags
& DIGCF_ALLCLASSES
)
1913 rc
= SETUP_CreateDevList(list
, machine
, pClassGuid
, enumstr
);
1914 if (rc
!= ERROR_SUCCESS
)
1921 else if (flags
& DIGCF_DEVICEINTERFACE
)
1925 SetLastError(ERROR_INVALID_PARAMETER
);
1929 rc
= SETUP_CreateInterfaceList(list
, machine
, (LPGUID
)class, enumstr
, flags
& DIGCF_PRESENT
);
1930 if (rc
!= ERROR_SUCCESS
)
1939 rc
= SETUP_CreateDevList(list
, machine
, (LPGUID
)class, enumstr
);
1940 if (rc
!= ERROR_SUCCESS
)
1949 if (!deviceset
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= ret
)
1950 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
1954 /***********************************************************************
1955 * SetupDiGetClassImageIndex (SETUPAPI.@)
1958 static BOOL
GetIconIndex(
1960 OUT PINT ImageIndex
)
1962 LPWSTR Buffer
= NULL
;
1963 DWORD dwRegType
, dwLength
;
1967 /* Read icon registry key */
1968 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
1969 if (rc
!= ERROR_SUCCESS
)
1973 } else if (dwRegType
!= REG_SZ
)
1975 SetLastError(ERROR_INVALID_INDEX
);
1978 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
1981 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1984 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
1985 if (rc
!= ERROR_SUCCESS
)
1990 /* make sure the returned buffer is NULL-terminated */
1991 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
1993 /* Transform icon value to a INT */
1994 *ImageIndex
= atoiW(Buffer
);
2002 BOOL WINAPI
SetupDiGetClassImageIndex(
2003 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2004 IN CONST GUID
*ClassGuid
,
2005 OUT PINT ImageIndex
)
2007 struct ClassImageList
*list
;
2010 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2012 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2013 SetLastError(ERROR_INVALID_PARAMETER
);
2014 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2015 SetLastError(ERROR_INVALID_USER_BUFFER
);
2016 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2017 SetLastError(ERROR_INVALID_USER_BUFFER
);
2018 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2019 SetLastError(ERROR_INVALID_USER_BUFFER
);
2020 else if (!ImageIndex
)
2021 SetLastError(ERROR_INVALID_PARAMETER
);
2024 HKEY hKey
= INVALID_HANDLE_VALUE
;
2027 /* Read Icon registry entry into Buffer */
2028 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2029 if (hKey
== INVALID_HANDLE_VALUE
)
2031 if (!GetIconIndex(hKey
, &iconIndex
))
2036 SetLastError(ERROR_INVALID_INDEX
);
2040 *ImageIndex
= -iconIndex
;
2044 if (hKey
!= INVALID_HANDLE_VALUE
)
2048 TRACE("Returning %d\n", ret
);
2052 /***********************************************************************
2053 * SetupDiGetClassImageList(SETUPAPI.@)
2055 BOOL WINAPI
SetupDiGetClassImageList(
2056 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2058 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2061 /***********************************************************************
2062 * SetupDiGetClassImageListExA(SETUPAPI.@)
2064 BOOL WINAPI
SetupDiGetClassImageListExA(
2065 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2066 IN PCSTR MachineName OPTIONAL
,
2069 PWSTR MachineNameW
= NULL
;
2074 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2075 if (MachineNameW
== NULL
)
2079 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2082 MyFree(MachineNameW
);
2087 /***********************************************************************
2088 * SetupDiGetClassImageListExW(SETUPAPI.@)
2090 BOOL WINAPI
SetupDiGetClassImageListExW(
2091 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2092 IN PCWSTR MachineName OPTIONAL
,
2097 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2099 if (!ClassImageListData
)
2100 SetLastError(ERROR_INVALID_PARAMETER
);
2101 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2102 SetLastError(ERROR_INVALID_USER_BUFFER
);
2104 SetLastError(ERROR_INVALID_PARAMETER
);
2107 struct ClassImageList
*list
= NULL
;
2110 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2112 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
2113 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2116 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2119 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2122 list
->szData
[0] = list
->szData
[1] = '\\';
2123 strcpyW(list
->szData
+ 2, MachineName
);
2124 list
->MachineName
= list
->szData
;
2128 list
->MachineName
= NULL
;
2131 ClassImageListData
->Reserved
= (ULONG_PTR
)list
;
2139 TRACE("Returning %d\n", ret
);
2143 /***********************************************************************
2144 * SetupDiLoadClassIcon(SETUPAPI.@)
2146 BOOL WINAPI
SetupDiLoadClassIcon(
2147 IN CONST GUID
*ClassGuid
,
2148 OUT HICON
*LargeIcon OPTIONAL
,
2149 OUT PINT MiniIconIndex OPTIONAL
)
2154 SetLastError(ERROR_INVALID_PARAMETER
);
2157 LPWSTR Buffer
= NULL
;
2160 HKEY hKey
= INVALID_HANDLE_VALUE
;
2162 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2163 if (hKey
== INVALID_HANDLE_VALUE
)
2166 if (!GetIconIndex(hKey
, &iconIndex
))
2171 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2174 DWORD dwRegType
, dwLength
;
2175 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2176 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2178 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2181 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2184 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2185 if (rc
!= ERROR_SUCCESS
)
2190 /* make sure the returned buffer is NULL-terminated */
2191 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2194 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2195 && dwRegType
== REG_SZ
)
2197 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2200 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2203 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2204 if (rc
!= ERROR_SUCCESS
)
2209 /* make sure the returned buffer is NULL-terminated */
2210 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2214 /* Unable to find where to load the icon */
2215 SetLastError(ERROR_FILE_NOT_FOUND
);
2218 Comma
= strchrW(Buffer
, ',');
2221 SetLastError(ERROR_GEN_FAILURE
);
2229 /* Look up icon in setupapi.dll */
2230 DllName
= L
"setupapi.dll";
2231 iconIndex
= -iconIndex
;
2234 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2237 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2239 SetLastError(ERROR_INVALID_INDEX
);
2244 *MiniIconIndex
= iconIndex
;
2248 if (hKey
!= INVALID_HANDLE_VALUE
)
2253 TRACE("Returning %d\n", ret
);
2257 /***********************************************************************
2258 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2260 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
2261 HDEVINFO DeviceInfoSet
,
2262 PSP_DEVINFO_DATA DeviceInfoData
,
2263 CONST GUID
* InterfaceClassGuid
,
2265 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2269 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2270 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2272 if (!DeviceInterfaceData
)
2273 SetLastError(ERROR_INVALID_PARAMETER
);
2274 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2275 SetLastError(ERROR_INVALID_USER_BUFFER
);
2276 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2278 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2280 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2282 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2284 while (ItemList
!= &list
->ListHead
&& !Found
)
2286 PLIST_ENTRY InterfaceListEntry
;
2287 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
2288 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2290 /* We are not searching for this element */
2291 ItemList
= ItemList
->Flink
;
2294 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2295 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2297 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2298 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2300 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2303 if (MemberIndex
-- == 0)
2305 /* return this item */
2306 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2307 &DevItf
->InterfaceClassGuid
,
2309 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2310 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2313 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2315 ItemList
= ItemList
->Flink
;
2318 SetLastError(ERROR_NO_MORE_ITEMS
);
2323 SetLastError(ERROR_INVALID_HANDLE
);
2326 SetLastError(ERROR_INVALID_HANDLE
);
2330 static VOID
ReferenceInfFile(struct InfFileDetails
* infFile
)
2332 InterlockedIncrement(&infFile
->References
);
2335 static VOID
DereferenceInfFile(struct InfFileDetails
* infFile
)
2337 if (InterlockedDecrement(&infFile
->References
) == 0)
2339 SetupCloseInfFile(infFile
->hInf
);
2340 HeapFree(GetProcessHeap(), 0, infFile
);
2344 static BOOL
DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2346 DereferenceInfFile(driverInfo
->InfFileDetails
);
2347 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2348 HeapFree(GetProcessHeap(), 0, driverInfo
);
2352 static BOOL
DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2354 HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2358 static BOOL
DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2360 PLIST_ENTRY ListEntry
;
2361 struct DriverInfoElement
*driverInfo
;
2362 struct DeviceInterface
*deviceInterface
;
2364 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2366 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2367 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
2368 if (!DestroyDriverInfoElement(driverInfo
))
2371 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2373 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2374 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
2375 if (!DestroyDeviceInterface(deviceInterface
))
2378 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2379 HeapFree(GetProcessHeap(), 0, deviceInfo
);
2383 static BOOL
DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2385 PLIST_ENTRY ListEntry
;
2386 struct DeviceInfoElement
*deviceInfo
;
2388 while (!IsListEmpty(&list
->ListHead
))
2390 ListEntry
= RemoveHeadList(&list
->ListHead
);
2391 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfoElement
, ListEntry
);
2392 if (!DestroyDeviceInfoElement(deviceInfo
))
2395 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2396 RegCloseKey(list
->HKLM
);
2397 CM_Disconnect_Machine(list
->hMachine
);
2398 DestroyClassInstallParams(&list
->ClassInstallParams
);
2399 HeapFree(GetProcessHeap(), 0, list
);
2403 /***********************************************************************
2404 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2406 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
2410 TRACE("%p\n", devinfo
);
2411 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2413 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)devinfo
;
2415 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2416 ret
= DestroyDeviceInfoSet(list
);
2418 SetLastError(ERROR_INVALID_HANDLE
);
2421 SetLastError(ERROR_INVALID_HANDLE
);
2423 TRACE("Returning %d\n", ret
);
2427 /***********************************************************************
2428 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2430 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
2431 HDEVINFO DeviceInfoSet
,
2432 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2433 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
2434 DWORD DeviceInterfaceDetailDataSize
,
2435 PDWORD RequiredSize
,
2436 PSP_DEVINFO_DATA DeviceInfoData
)
2438 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2439 DWORD sizeW
= 0, sizeA
;
2442 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2443 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2444 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2446 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2447 SetLastError(ERROR_INVALID_USER_BUFFER
);
2448 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2449 SetLastError(ERROR_INVALID_PARAMETER
);
2450 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2451 SetLastError(ERROR_INVALID_PARAMETER
);
2454 if (DeviceInterfaceDetailData
!= NULL
)
2456 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2457 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2458 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2459 if (!DeviceInterfaceDetailDataW
)
2461 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2464 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2466 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2467 ret
= SetupDiGetDeviceInterfaceDetailW(
2469 DeviceInterfaceData
,
2470 DeviceInterfaceDetailDataW
,
2474 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2475 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2477 *RequiredSize
= sizeA
;
2478 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2480 if (!WideCharToMultiByte(
2482 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2483 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2490 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2493 TRACE("Returning %d\n", ret
);
2497 /***********************************************************************
2498 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2500 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
2501 HDEVINFO DeviceInfoSet
,
2502 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2503 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
2504 DWORD DeviceInterfaceDetailDataSize
,
2505 PDWORD RequiredSize
,
2506 PSP_DEVINFO_DATA DeviceInfoData
)
2510 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2511 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2512 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2514 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2515 SetLastError(ERROR_INVALID_PARAMETER
);
2516 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2517 SetLastError(ERROR_INVALID_HANDLE
);
2518 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2519 SetLastError(ERROR_INVALID_HANDLE
);
2520 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2521 SetLastError(ERROR_INVALID_USER_BUFFER
);
2522 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2523 SetLastError(ERROR_INVALID_USER_BUFFER
);
2524 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2525 SetLastError(ERROR_INVALID_USER_BUFFER
);
2526 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2527 SetLastError(ERROR_INVALID_PARAMETER
);
2528 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2529 SetLastError(ERROR_INVALID_PARAMETER
);
2532 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2533 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2534 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2535 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2537 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2539 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2541 *RequiredSize
= sizeRequired
;
2545 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
2546 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2549 memcpy(&DeviceInfoData
->ClassGuid
,
2550 &deviceInterface
->DeviceInfo
->ClassGuid
,
2552 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2553 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2559 TRACE("Returning %d\n", ret
);
2563 /***********************************************************************
2564 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2566 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
2568 PSP_DEVINFO_DATA DeviceInfoData
,
2570 PDWORD PropertyRegDataType
,
2571 PBYTE PropertyBuffer
,
2572 DWORD PropertyBufferSize
,
2573 PDWORD RequiredSize
)
2576 BOOL bIsStringProperty
;
2578 DWORD RequiredSizeA
, RequiredSizeW
;
2579 DWORD PropertyBufferSizeW
;
2580 PBYTE PropertyBufferW
;
2582 TRACE("%p %p %ld %p %p %ld %p\n", devinfo
, DeviceInfoData
,
2583 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2586 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2587 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2589 bResult
= SetupDiGetDeviceRegistryPropertyW(
2595 PropertyBufferSizeW
,
2598 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2600 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2602 if (bIsStringProperty
)
2603 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2605 RequiredSizeA
= RequiredSizeW
;
2607 *RequiredSize
= RequiredSizeA
;
2608 if (PropertyRegDataType
)
2609 *PropertyRegDataType
= RegType
;
2614 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2618 if (RequiredSizeA
<= PropertyBufferSize
)
2620 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2622 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2624 /* Last error is already set by WideCharToMultiByte */
2629 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2633 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2637 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2641 /***********************************************************************
2642 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2644 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
2645 HDEVINFO DeviceInfoSet
,
2646 PSP_DEVINFO_DATA DeviceInfoData
,
2648 PDWORD PropertyRegDataType
,
2649 PBYTE PropertyBuffer
,
2650 DWORD PropertyBufferSize
,
2651 PDWORD RequiredSize
)
2653 HKEY hEnumKey
, hKey
;
2657 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2658 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2661 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2662 SetLastError(ERROR_INVALID_HANDLE
);
2663 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2664 SetLastError(ERROR_INVALID_HANDLE
);
2665 else if (!DeviceInfoData
)
2666 SetLastError(ERROR_INVALID_PARAMETER
);
2667 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2668 SetLastError(ERROR_INVALID_USER_BUFFER
);
2669 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2670 SetLastError(ERROR_INVALID_PARAMETER
);
2673 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2674 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2678 case SPDRP_CAPABILITIES
:
2680 case SPDRP_CLASSGUID
:
2681 case SPDRP_COMPATIBLEIDS
:
2682 case SPDRP_CONFIGFLAGS
:
2683 case SPDRP_DEVICEDESC
:
2685 case SPDRP_FRIENDLYNAME
:
2686 case SPDRP_HARDWAREID
:
2687 case SPDRP_LOCATION_INFORMATION
:
2688 case SPDRP_LOWERFILTERS
:
2690 case SPDRP_SECURITY
:
2692 case SPDRP_UI_NUMBER
:
2693 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2694 case SPDRP_UPPERFILTERS
:
2696 LPCWSTR RegistryPropertyName
;
2701 case SPDRP_CAPABILITIES
:
2702 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2704 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2705 case SPDRP_CLASSGUID
:
2706 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2707 case SPDRP_COMPATIBLEIDS
:
2708 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2709 case SPDRP_CONFIGFLAGS
:
2710 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2711 case SPDRP_DEVICEDESC
:
2712 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2714 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2715 case SPDRP_FRIENDLYNAME
:
2716 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2717 case SPDRP_HARDWAREID
:
2718 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2719 case SPDRP_LOCATION_INFORMATION
:
2720 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2721 case SPDRP_LOWERFILTERS
:
2722 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2724 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2725 case SPDRP_SECURITY
:
2726 RegistryPropertyName
= REGSTR_SECURITY
; break;
2728 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2729 case SPDRP_UI_NUMBER
:
2730 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2731 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2732 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
; break;
2733 case SPDRP_UPPERFILTERS
:
2734 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2736 /* Should not happen */
2737 RegistryPropertyName
= NULL
; break;
2740 /* Open registry key name */
2743 REGSTR_PATH_SYSTEMENUM
,
2747 if (rc
!= ERROR_SUCCESS
)
2758 RegCloseKey(hEnumKey
);
2759 if (rc
!= ERROR_SUCCESS
)
2764 /* Read registry entry */
2765 BufferSize
= PropertyBufferSize
;
2766 rc
= RegQueryValueExW(
2768 RegistryPropertyName
,
2769 NULL
, /* Reserved */
2770 PropertyRegDataType
,
2774 *RequiredSize
= BufferSize
;
2777 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
2780 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2782 case ERROR_MORE_DATA
:
2783 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2792 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
2794 DWORD required
= (strlenW(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
2796 if (PropertyRegDataType
)
2797 *PropertyRegDataType
= REG_SZ
;
2799 *RequiredSize
= required
;
2800 if (PropertyBufferSize
>= required
)
2802 strcpyW((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
2806 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2810 /*case SPDRP_BUSTYPEGUID:
2811 case SPDRP_LEGACYBUSTYPE:
2812 case SPDRP_BUSNUMBER:
2813 case SPDRP_ENUMERATOR_NAME:
2814 case SPDRP_SECURITY_SDS:
2816 case SPDRP_EXCLUSIVE:
2817 case SPDRP_CHARACTERISTICS:
2819 case SPDRP_DEVICE_POWER_DATA:*/
2820 #if (WINVER >= 0x501)
2821 /*case SPDRP_REMOVAL_POLICY:
2822 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
2823 case SPDRP_REMOVAL_POLICY_OVERRIDE:
2824 case SPDRP_INSTALL_STATE:*/
2829 ERR("Property 0x%lx not implemented\n", Property
);
2830 SetLastError(ERROR_NOT_SUPPORTED
);
2835 TRACE("Returning %d\n", ret
);
2839 /***********************************************************************
2840 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
2842 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyA(
2843 IN HDEVINFO DeviceInfoSet
,
2844 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2846 IN CONST BYTE
*PropertyBuffer
,
2847 IN DWORD PropertyBufferSize
)
2849 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2850 Property
, PropertyBuffer
, PropertyBufferSize
);
2851 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
2855 /***********************************************************************
2856 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
2858 BOOL WINAPI
SetupDiSetDeviceRegistryPropertyW(
2859 IN HDEVINFO DeviceInfoSet
,
2860 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
2862 IN
const BYTE
*PropertyBuffer
,
2863 IN DWORD PropertyBufferSize
)
2865 struct DeviceInfoSet
*list
;
2868 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
2869 Property
, PropertyBuffer
, PropertyBufferSize
);
2872 SetLastError(ERROR_INVALID_HANDLE
);
2873 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2874 SetLastError(ERROR_INVALID_HANDLE
);
2875 else if (!DeviceInfoData
)
2876 SetLastError(ERROR_INVALID_HANDLE
);
2877 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2878 SetLastError(ERROR_INVALID_USER_BUFFER
);
2883 case SPDRP_COMPATIBLEIDS
:
2884 case SPDRP_CONFIGFLAGS
:
2885 case SPDRP_FRIENDLYNAME
:
2886 case SPDRP_HARDWAREID
:
2887 case SPDRP_LOCATION_INFORMATION
:
2888 case SPDRP_LOWERFILTERS
:
2889 case SPDRP_SECURITY
:
2891 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2892 case SPDRP_UPPERFILTERS
:
2894 LPCWSTR RegistryPropertyName
;
2895 DWORD RegistryDataType
;
2901 case SPDRP_COMPATIBLEIDS
:
2902 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
2903 RegistryDataType
= REG_MULTI_SZ
;
2905 case SPDRP_CONFIGFLAGS
:
2906 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
2907 RegistryDataType
= REG_DWORD
;
2909 case SPDRP_FRIENDLYNAME
:
2910 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
2911 RegistryDataType
= REG_SZ
;
2913 case SPDRP_HARDWAREID
:
2914 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
2915 RegistryDataType
= REG_MULTI_SZ
;
2917 case SPDRP_LOCATION_INFORMATION
:
2918 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
2919 RegistryDataType
= REG_SZ
;
2921 case SPDRP_LOWERFILTERS
:
2922 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
2923 RegistryDataType
= REG_MULTI_SZ
;
2925 case SPDRP_SECURITY
:
2926 RegistryPropertyName
= REGSTR_SECURITY
;
2927 RegistryDataType
= REG_BINARY
;
2930 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
2931 RegistryDataType
= REG_SZ
;
2933 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2934 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
;
2935 RegistryDataType
= REG_SZ
;
2937 case SPDRP_UPPERFILTERS
:
2938 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
2939 RegistryDataType
= REG_MULTI_SZ
;
2942 /* Should not happen */
2943 RegistryPropertyName
= NULL
;
2944 RegistryDataType
= REG_BINARY
;
2947 /* Open device registry key */
2948 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
2949 if (hKey
!= INVALID_HANDLE_VALUE
)
2951 /* Write new data */
2952 rc
= RegSetValueExW(
2954 RegistryPropertyName
,
2958 PropertyBufferSize
);
2959 if (rc
== ERROR_SUCCESS
)
2968 /*case SPDRP_CHARACTERISTICS:
2970 case SPDRP_EXCLUSIVE:*/
2971 #if (WINVER >= 0x501)
2972 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
2974 //case SPDRP_SECURITY_SDS:
2978 ERR("Property 0x%lx not implemented\n", Property
);
2979 SetLastError(ERROR_NOT_SUPPORTED
);
2984 TRACE("Returning %d\n", ret
);
2989 /***********************************************************************
2990 * SetupDiInstallClassA (SETUPAPI.@)
2992 BOOL WINAPI
SetupDiInstallClassA(
2993 IN HWND hwndParent OPTIONAL
,
2994 IN PCSTR InfFileName
,
2996 IN HSPFILEQ FileQueue OPTIONAL
)
2998 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3002 /***********************************************************************
3003 * SetupDiInstallClassW (SETUPAPI.@)
3005 BOOL WINAPI
SetupDiInstallClassW(
3006 IN HWND hwndParent OPTIONAL
,
3007 IN PCWSTR InfFileName
,
3009 IN HSPFILEQ FileQueue OPTIONAL
)
3011 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3015 /***********************************************************************
3016 * SetupDiInstallClassExA (SETUPAPI.@)
3018 BOOL WINAPI
SetupDiInstallClassExA(
3019 IN HWND hwndParent OPTIONAL
,
3020 IN PCSTR InfFileName OPTIONAL
,
3022 IN HSPFILEQ FileQueue OPTIONAL
,
3023 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3027 PWSTR InfFileNameW
= NULL
;
3032 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3033 if (InfFileNameW
== NULL
)
3035 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3040 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3041 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3043 MyFree(InfFileNameW
);
3049 static HKEY
CreateClassKey(HINF hInf
)
3051 WCHAR FullBuffer
[MAX_PATH
];
3052 WCHAR Buffer
[MAX_PATH
];
3054 HKEY hClassKey
= NULL
;
3055 HKEY ret
= INVALID_HANDLE_VALUE
;
3057 FullBuffer
[0] = '\0';
3059 if (!SetupGetLineTextW(NULL
,
3070 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3071 lstrcatW(FullBuffer
, Buffer
);
3073 if (!SetupGetLineTextW(NULL
,
3081 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3085 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3089 REG_OPTION_NON_VOLATILE
,
3098 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3103 RequiredSize
* sizeof(WCHAR
)))
3111 if (hClassKey
!= NULL
&& hClassKey
!= ret
)
3112 RegCloseKey(hClassKey
);
3113 if (ret
== INVALID_HANDLE_VALUE
&& FullBuffer
[0] != '\0')
3114 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3119 /***********************************************************************
3120 * SetupDiInstallClassExW (SETUPAPI.@)
3122 BOOL WINAPI
SetupDiInstallClassExW(
3123 IN HWND hwndParent OPTIONAL
,
3124 IN PCWSTR InfFileName OPTIONAL
,
3126 IN HSPFILEQ FileQueue OPTIONAL
,
3127 IN
const GUID
* InterfaceClassGuid OPTIONAL
,
3133 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3134 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3138 FIXME("Case not implemented: InfFileName NULL\n");
3139 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3141 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3143 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3144 SetLastError(ERROR_INVALID_FLAGS
);
3146 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3147 SetLastError(ERROR_INVALID_PARAMETER
);
3148 else if (Reserved1
!= NULL
)
3149 SetLastError(ERROR_INVALID_PARAMETER
);
3150 else if (Reserved2
!= NULL
)
3151 SetLastError(ERROR_INVALID_PARAMETER
);
3154 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
3155 SP_DEVINSTALL_PARAMS_W InstallParams
;
3156 WCHAR SectionName
[MAX_PATH
];
3157 HINF hInf
= INVALID_HANDLE_VALUE
;
3158 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3159 PVOID callback_context
= NULL
;
3161 hDeviceInfo
= SetupDiCreateDeviceInfoList(NULL
, NULL
);
3163 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3164 if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3166 InstallParams
.Flags
&= ~(DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3167 InstallParams
.Flags
|= Flags
& (DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3168 if (Flags
& DI_NOVCP
)
3169 InstallParams
.FileQueue
= FileQueue
;
3170 if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3173 /* Open the .inf file */
3174 hInf
= SetupOpenInfFileW(
3179 if (hInf
== INVALID_HANDLE_VALUE
)
3182 /* Try to append a layout file */
3183 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3187 if (InterfaceClassGuid
)
3189 /* Retrieve the actual section name */
3190 ret
= SetupDiGetActualSectionToInstallW(
3200 /* Open registry key related to this interface */
3201 /* FIXME: What happens if the key doesn't exist? */
3202 hRootKey
= SetupDiOpenClassRegKeyExW(InterfaceClassGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, NULL
, NULL
);
3203 if (hRootKey
== INVALID_HANDLE_VALUE
)
3206 /* SetupDiCreateDeviceInterface??? */
3207 FIXME("Installing an interface is not implemented\n");
3208 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3212 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3213 hRootKey
= CreateClassKey(hInf
);
3214 if (hRootKey
== INVALID_HANDLE_VALUE
)
3217 /* Retrieve the actual section name */
3218 ret
= SetupDiGetActualSectionToInstallW(
3222 MAX_PATH
- strlenW(DotServices
),
3228 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3229 if (!callback_context
)
3232 ret
= SetupInstallFromInfSectionW(
3236 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3238 NULL
, /* SourceRootPath */
3239 !(Flags
& DI_NOVCP
) && (Flags
& DI_FORCECOPY
) ? SP_COPY_FORCE_IN_USE
: 0, /* CopyFlags */
3240 SetupDefaultQueueCallbackW
,
3247 /* Install .Services section */
3248 lstrcatW(SectionName
, DotServices
);
3249 ret
= SetupInstallServicesFromInfSectionExW(
3264 if (hDeviceInfo
!= INVALID_HANDLE_VALUE
)
3265 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
3266 if (hInf
!= INVALID_HANDLE_VALUE
)
3267 SetupCloseInfFile(hInf
);
3268 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3269 RegCloseKey(hRootKey
);
3270 SetupTermDefaultQueueCallback(callback_context
);
3273 TRACE("Returning %d\n", ret
);
3278 /***********************************************************************
3279 * SetupDiOpenClassRegKey (SETUPAPI.@)
3281 HKEY WINAPI
SetupDiOpenClassRegKey(
3282 const GUID
* ClassGuid
,
3285 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3286 DIOCR_INSTALLER
, NULL
, NULL
);
3290 /***********************************************************************
3291 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3293 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
3294 const GUID
* ClassGuid OPTIONAL
,
3297 PCSTR MachineName OPTIONAL
,
3300 PWSTR MachineNameW
= NULL
;
3307 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3308 if (MachineNameW
== NULL
)
3309 return INVALID_HANDLE_VALUE
;
3312 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3313 Flags
, MachineNameW
, Reserved
);
3316 MyFree(MachineNameW
);
3322 /***********************************************************************
3323 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3325 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
3326 const GUID
* ClassGuid OPTIONAL
,
3329 PCWSTR MachineName OPTIONAL
,
3332 LPWSTR lpGuidString
= NULL
;
3333 LPWSTR lpFullGuidString
= NULL
;
3336 HKEY hClassesKey
= NULL
;
3337 HKEY hClassKey
= NULL
;
3338 HKEY ret
= INVALID_HANDLE_VALUE
;
3342 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3343 Flags
, debugstr_w(MachineName
), Reserved
);
3345 if (Flags
== DIOCR_INSTALLER
)
3346 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3347 else if (Flags
== DIOCR_INTERFACE
)
3348 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3351 ERR("Invalid Flags parameter!\n");
3352 SetLastError(ERROR_INVALID_FLAGS
);
3356 if (MachineName
!= NULL
)
3358 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3359 if (rc
!= ERROR_SUCCESS
)
3366 HKLM
= HKEY_LOCAL_MACHINE
;
3368 rc
= RegOpenKeyExW(HKLM
,
3371 ClassGuid
? 0 : samDesired
,
3373 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3374 if (rc
!= ERROR_SUCCESS
)
3380 if (ClassGuid
== NULL
)
3382 /* Stop here. We don't need to open a subkey */
3387 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3389 SetLastError(ERROR_GEN_FAILURE
);
3393 dwLength
= lstrlenW(lpGuidString
);
3394 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3395 if (!lpFullGuidString
)
3397 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3400 lpFullGuidString
[0] = '{';
3401 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3402 lpFullGuidString
[dwLength
+ 1] = '}';
3403 lpFullGuidString
[dwLength
+ 2] = '\0';
3405 rc
= RegOpenKeyExW(hClassesKey
,
3410 if (rc
!= ERROR_SUCCESS
)
3418 if (hClassKey
!= NULL
&& hClassKey
!= ret
)
3419 RegCloseKey(hClassKey
);
3420 if (hClassesKey
!= NULL
&& hClassesKey
!= ret
)
3421 RegCloseKey(hClassesKey
);
3423 RpcStringFreeW(&lpGuidString
);
3424 if (lpFullGuidString
)
3425 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3430 /***********************************************************************
3431 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3433 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
3434 HDEVINFO DeviceInfoSet
,
3437 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3439 FIXME("%p %s %08lx %p\n",
3440 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3444 /***********************************************************************
3445 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3447 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
3448 HDEVINFO DeviceInfoSet
,
3451 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
3453 LPWSTR DevicePathW
= NULL
;
3456 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3458 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3459 if (DevicePathW
== NULL
)
3462 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3463 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3465 MyFree(DevicePathW
);
3470 /***********************************************************************
3471 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3473 BOOL WINAPI
SetupDiSetClassInstallParamsA(
3474 HDEVINFO DeviceInfoSet
,
3475 PSP_DEVINFO_DATA DeviceInfoData
,
3476 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
3477 DWORD ClassInstallParamsSize
)
3479 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3480 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3484 /***********************************************************************
3485 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3487 BOOL WINAPI
SetupDiSetClassInstallParamsW(
3488 IN HDEVINFO DeviceInfoSet
,
3489 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3490 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3491 IN DWORD ClassInstallParamsSize
)
3493 struct DeviceInfoSet
*list
;
3496 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3497 ClassInstallParams
, ClassInstallParamsSize
);
3500 SetLastError(ERROR_INVALID_PARAMETER
);
3501 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3502 SetLastError(ERROR_INVALID_HANDLE
);
3503 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3504 SetLastError(ERROR_INVALID_HANDLE
);
3505 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3506 SetLastError(ERROR_INVALID_USER_BUFFER
);
3507 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3508 SetLastError(ERROR_INVALID_USER_BUFFER
);
3509 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3510 SetLastError(ERROR_INVALID_PARAMETER
);
3511 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3512 SetLastError(ERROR_INVALID_PARAMETER
);
3515 SP_DEVINSTALL_PARAMS_W InstallParams
;
3518 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3519 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3523 if (ClassInstallParams
)
3525 /* Check parameters in ClassInstallParams */
3526 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3527 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3529 SetLastError(ERROR_INVALID_USER_BUFFER
);
3532 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3534 FIXME("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3535 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3538 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3541 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3545 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3548 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3552 TRACE("Returning %d\n", ret
);
3556 static BOOL
PropertyChangeHandler(
3557 IN HDEVINFO DeviceInfoSet
,
3558 IN PSP_DEVINFO_DATA DeviceInfoData
,
3559 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3560 IN DWORD ClassInstallParamsSize
)
3562 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3565 if (!DeviceInfoData
)
3566 SetLastError(ERROR_INVALID_PARAMETER
);
3567 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3568 SetLastError(ERROR_INVALID_PARAMETER
);
3569 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3570 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3571 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3572 SetLastError(ERROR_INVALID_FLAGS
);
3573 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3574 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3575 SetLastError(ERROR_INVALID_FLAGS
);
3576 else if (PropChangeParams
3577 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3578 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3579 SetLastError(ERROR_INVALID_USER_BUFFER
);
3582 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3583 if (!DeviceInfoData
)
3585 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3586 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3590 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3591 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3593 if (*CurrentPropChangeParams
)
3595 MyFree(*CurrentPropChangeParams
);
3596 *CurrentPropChangeParams
= NULL
;
3598 if (PropChangeParams
)
3600 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3601 if (!*CurrentPropChangeParams
)
3603 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3606 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3617 IN PWSTR InstallerName
,
3618 OUT HMODULE
* ModulePointer
,
3619 OUT PVOID
* FunctionPointer
)
3621 HMODULE hModule
= NULL
;
3622 LPSTR FunctionNameA
= NULL
;
3626 *ModulePointer
= NULL
;
3627 *FunctionPointer
= NULL
;
3629 Comma
= strchrW(InstallerName
, ',');
3632 rc
= ERROR_INVALID_PARAMETER
;
3638 hModule
= LoadLibraryW(InstallerName
);
3642 rc
= GetLastError();
3646 /* Skip comma spaces */
3647 while (*Comma
== ',' || isspaceW(*Comma
))
3650 /* W->A conversion for function name */
3651 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3654 rc
= GetLastError();
3658 /* Search function */
3659 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3660 if (!*FunctionPointer
)
3662 rc
= GetLastError();
3666 *ModulePointer
= hModule
;
3670 if (rc
!= ERROR_SUCCESS
&& hModule
)
3671 FreeLibrary(hModule
);
3672 MyFree(FunctionNameA
);
3677 FreeFunctionPointer(
3678 IN HMODULE ModulePointer
,
3679 IN PVOID FunctionPointer
)
3681 if (ModulePointer
== NULL
)
3682 return ERROR_SUCCESS
;
3683 if (FreeLibrary(ModulePointer
))
3684 return ERROR_SUCCESS
;
3686 return GetLastError();
3690 IntSetupDiRegisterDeviceInfo(
3691 IN HDEVINFO DeviceInfoSet
,
3692 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
3694 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
3697 /***********************************************************************
3698 * SetupDiCallClassInstaller (SETUPAPI.@)
3700 BOOL WINAPI
SetupDiCallClassInstaller(
3701 IN DI_FUNCTION InstallFunction
,
3702 IN HDEVINFO DeviceInfoSet
,
3703 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3707 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3710 SetLastError(ERROR_INVALID_PARAMETER
);
3711 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3712 SetLastError(ERROR_INVALID_HANDLE
);
3713 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3714 SetLastError(ERROR_INVALID_HANDLE
);
3715 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3716 SetLastError(ERROR_INVALID_HANDLE
);
3717 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3718 SetLastError(ERROR_INVALID_USER_BUFFER
);
3721 SP_DEVINSTALL_PARAMS_W InstallParams
;
3722 #define CLASS_COINSTALLER 0x1
3723 #define DEVICE_COINSTALLER 0x2
3724 #define CLASS_INSTALLER 0x4
3725 UCHAR CanHandle
= 0;
3726 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
3728 switch (InstallFunction
)
3730 case DIF_ADDPROPERTYPAGE_ADVANCED
:
3731 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3733 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
3734 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3736 case DIF_ALLOW_INSTALL
:
3737 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3740 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3742 case DIF_DESTROYPRIVATEDATA
:
3743 CanHandle
= CLASS_INSTALLER
;
3745 case DIF_INSTALLDEVICE
:
3746 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3747 DefaultHandler
= SetupDiInstallDevice
;
3749 case DIF_INSTALLDEVICEFILES
:
3750 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3751 DefaultHandler
= SetupDiInstallDriverFiles
;
3753 case DIF_INSTALLINTERFACES
:
3754 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3755 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
3757 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
3758 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3760 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
3761 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3763 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
3764 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3766 case DIF_NEWDEVICEWIZARD_PRESELECT
:
3767 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3769 case DIF_NEWDEVICEWIZARD_SELECT
:
3770 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3772 case DIF_POWERMESSAGEWAKE
:
3773 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3775 case DIF_PROPERTYCHANGE
:
3776 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3777 DefaultHandler
= SetupDiChangeState
;
3779 case DIF_REGISTER_COINSTALLERS
:
3780 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3781 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
3783 case DIF_REGISTERDEVICE
:
3784 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3785 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
3788 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3789 DefaultHandler
= SetupDiRemoveDevice
;
3791 case DIF_SELECTBESTCOMPATDRV
:
3792 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3793 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3795 case DIF_SELECTDEVICE
:
3796 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
3797 DefaultHandler
= SetupDiSelectBestCompatDrv
;
3799 case DIF_TROUBLESHOOTER
:
3800 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3803 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
3804 DefaultHandler
= SetupDiUnremoveDevice
;
3807 ERR("Install function %u not supported\n", InstallFunction
);
3808 SetLastError(ERROR_NOT_SUPPORTED
);
3811 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3812 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
3813 /* Don't process this call, as a parameter is invalid */
3818 LIST_ENTRY ClassCoInstallersListHead
;
3819 LIST_ENTRY DeviceCoInstallersListHead
;
3820 HMODULE ClassInstallerLibrary
= NULL
;
3821 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
3822 COINSTALLER_CONTEXT_DATA Context
;
3823 PLIST_ENTRY ListEntry
;
3825 DWORD dwRegType
, dwLength
;
3826 DWORD rc
= NO_ERROR
;
3828 InitializeListHead(&ClassCoInstallersListHead
);
3829 InitializeListHead(&DeviceCoInstallersListHead
);
3831 if (CanHandle
& DEVICE_COINSTALLER
)
3833 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
3834 if (hKey
!= INVALID_HANDLE_VALUE
)
3836 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3837 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3839 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3840 if (KeyBuffer
!= NULL
)
3842 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3843 if (rc
== ERROR_SUCCESS
)
3846 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3848 /* Add coinstaller to DeviceCoInstallersListHead list */
3849 struct CoInstallerElement
*coinstaller
;
3850 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
3851 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3854 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3855 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3856 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
3858 HeapFree(GetProcessHeap(), 0, coinstaller
);
3861 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3867 if (CanHandle
& CLASS_COINSTALLER
)
3871 REGSTR_PATH_CODEVICEINSTALLERS
,
3875 if (rc
== ERROR_SUCCESS
)
3877 LPWSTR lpGuidString
;
3878 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
3880 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
3881 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
3883 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3884 if (KeyBuffer
!= NULL
)
3886 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3887 if (rc
== ERROR_SUCCESS
)
3890 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
3892 /* Add coinstaller to ClassCoInstallersListHead list */
3893 struct CoInstallerElement
*coinstaller
;
3894 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
3895 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
3898 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
3899 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
3900 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
3902 HeapFree(GetProcessHeap(), 0, coinstaller
);
3905 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3908 RpcStringFreeW(&lpGuidString
);
3913 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
3915 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
3916 if (hKey
!= INVALID_HANDLE_VALUE
)
3918 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
3919 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
3921 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
3922 if (KeyBuffer
!= NULL
)
3924 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
3925 if (rc
== ERROR_SUCCESS
)
3927 /* Get ClassInstaller function pointer */
3928 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
3929 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
3931 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
3932 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3935 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
3942 /* Call Class co-installers */
3943 Context
.PostProcessing
= FALSE
;
3945 ListEntry
= ClassCoInstallersListHead
.Flink
;
3946 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
3948 struct CoInstallerElement
*coinstaller
;
3949 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
3950 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3951 coinstaller
->PrivateData
= Context
.PrivateData
;
3952 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3954 coinstaller
->DoPostProcessing
= TRUE
;
3957 ListEntry
= ListEntry
->Flink
;
3960 /* Call Device co-installers */
3961 ListEntry
= DeviceCoInstallersListHead
.Flink
;
3962 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
3964 struct CoInstallerElement
*coinstaller
;
3965 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
3966 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
3967 coinstaller
->PrivateData
= Context
.PrivateData
;
3968 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
3970 coinstaller
->DoPostProcessing
= TRUE
;
3973 ListEntry
= ListEntry
->Flink
;
3976 /* Call Class installer */
3979 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3980 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
3983 rc
= ERROR_DI_DO_DEFAULT
;
3985 /* Call default handler */
3986 if (rc
== ERROR_DI_DO_DEFAULT
)
3988 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
3990 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
3993 rc
= GetLastError();
3999 /* Call Class co-installers that required postprocessing */
4000 Context
.PostProcessing
= TRUE
;
4001 ListEntry
= ClassCoInstallersListHead
.Flink
;
4002 while (ListEntry
!= &ClassCoInstallersListHead
)
4004 struct CoInstallerElement
*coinstaller
;
4005 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4006 if (coinstaller
->DoPostProcessing
)
4008 Context
.InstallResult
= rc
;
4009 Context
.PrivateData
= coinstaller
->PrivateData
;
4010 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4012 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4013 ListEntry
= ListEntry
->Flink
;
4016 /* Call Device co-installers that required postprocessing */
4017 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4018 while (ListEntry
!= &DeviceCoInstallersListHead
)
4020 struct CoInstallerElement
*coinstaller
;
4021 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4022 if (coinstaller
->DoPostProcessing
)
4024 Context
.InstallResult
= rc
;
4025 Context
.PrivateData
= coinstaller
->PrivateData
;
4026 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4028 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4029 ListEntry
= ListEntry
->Flink
;
4032 /* Free allocated memory */
4033 while (!IsListEmpty(&ClassCoInstallersListHead
))
4035 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4036 HeapFree(GetProcessHeap(), 0, ListEntry
);
4038 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4040 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4041 HeapFree(GetProcessHeap(), 0, ListEntry
);
4044 ret
= (rc
== NO_ERROR
);
4048 TRACE("Returning %d\n", ret
);
4052 /***********************************************************************
4053 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4055 BOOL WINAPI
SetupDiGetDeviceInfoListClass(
4056 IN HDEVINFO DeviceInfoSet
,
4057 OUT LPGUID ClassGuid
)
4059 struct DeviceInfoSet
*list
;
4062 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4065 SetLastError(ERROR_INVALID_HANDLE
);
4066 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4067 SetLastError(ERROR_INVALID_HANDLE
);
4068 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4069 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4072 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4077 TRACE("Returning %d\n", ret
);
4081 /***********************************************************************
4082 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4084 BOOL WINAPI
SetupDiGetDeviceInfoListDetailW(
4085 IN HDEVINFO DeviceInfoSet
,
4086 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4088 struct DeviceInfoSet
*list
;
4091 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4094 SetLastError(ERROR_INVALID_HANDLE
);
4095 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4096 SetLastError(ERROR_INVALID_HANDLE
);
4097 else if (!DeviceInfoListDetailData
)
4098 SetLastError(ERROR_INVALID_PARAMETER
);
4099 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4100 SetLastError(ERROR_INVALID_USER_BUFFER
);
4104 &DeviceInfoListDetailData
->ClassGuid
,
4107 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4108 if (list
->MachineName
)
4109 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4111 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4116 TRACE("Returning %d\n", ret
);
4120 /***********************************************************************
4121 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4123 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
4124 IN HDEVINFO DeviceInfoSet
,
4125 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4126 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4128 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4131 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4133 if (DeviceInstallParams
== NULL
)
4134 SetLastError(ERROR_INVALID_PARAMETER
);
4135 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4136 SetLastError(ERROR_INVALID_USER_BUFFER
);
4139 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4140 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4144 /* Do W->A conversion */
4146 DeviceInstallParams
,
4147 &deviceInstallParamsW
,
4148 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4149 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4150 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4152 DeviceInstallParams
->DriverPath
[0] = '\0';
4158 TRACE("Returning %d\n", ret
);
4162 /***********************************************************************
4163 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4165 BOOL WINAPI
SetupDiGetDeviceInstallParamsW(
4166 IN HDEVINFO DeviceInfoSet
,
4167 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4168 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4170 struct DeviceInfoSet
*list
;
4173 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4176 SetLastError(ERROR_INVALID_HANDLE
);
4177 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4178 SetLastError(ERROR_INVALID_HANDLE
);
4179 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4180 SetLastError(ERROR_INVALID_USER_BUFFER
);
4181 else if (!DeviceInstallParams
)
4182 SetLastError(ERROR_INVALID_PARAMETER
);
4183 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4184 SetLastError(ERROR_INVALID_USER_BUFFER
);
4187 PSP_DEVINSTALL_PARAMS_W Source
;
4190 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4192 Source
= &list
->InstallParams
;
4193 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4197 TRACE("Returning %d\n", ret
);
4202 CheckDeviceInstallParameters(
4203 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4205 DWORD SupportedFlags
=
4206 DI_NOVCP
| /* 0x00000008 */
4207 DI_DIDCOMPAT
| /* 0x00000010 */
4208 DI_DIDCLASS
| /* 0x00000020 */
4209 DI_NEEDRESTART
| /* 0x00000080 */
4210 DI_NEEDREBOOT
| /* 0x00000100 */
4211 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4212 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4213 DI_ENUMSINGLEINF
| /* 0x00010000 */
4214 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4215 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4216 DI_QUIETINSTALL
| /* 0x00800000 */
4217 DI_NOFILECOPY
| /* 0x01000000 */
4218 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4219 DWORD SupportedFlagsEx
=
4220 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4221 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4222 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4223 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4224 DI_FLAGSEX_NO_DRVREG_MODIFY
; /* 0x00008000 */
4227 /* FIXME: add support for more flags */
4229 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4230 * It should be checked before accessing to other values
4231 * of the SP_DEVINSTALL_PARAMS structure */
4233 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4235 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4236 SetLastError(ERROR_INVALID_FLAGS
);
4238 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4240 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4241 SetLastError(ERROR_INVALID_FLAGS
);
4243 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4244 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4245 SetLastError(ERROR_INVALID_USER_BUFFER
);
4248 /* FIXME: check Reserved field */
4255 /***********************************************************************
4256 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4258 BOOL WINAPI
SetupDiSetDeviceInstallParamsW(
4259 IN HDEVINFO DeviceInfoSet
,
4260 IN PSP_DEVINFO_DATA DeviceInfoData
,
4261 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4263 struct DeviceInfoSet
*list
;
4266 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4269 SetLastError(ERROR_INVALID_HANDLE
);
4270 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4271 SetLastError(ERROR_INVALID_HANDLE
);
4272 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4273 SetLastError(ERROR_INVALID_USER_BUFFER
);
4274 else if (!DeviceInstallParams
)
4275 SetLastError(ERROR_INVALID_PARAMETER
);
4276 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4277 SetLastError(ERROR_INVALID_USER_BUFFER
);
4278 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4280 PSP_DEVINSTALL_PARAMS_W Destination
;
4283 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4285 Destination
= &list
->InstallParams
;
4286 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4290 TRACE("Returning %d\n", ret
);
4294 /***********************************************************************
4295 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4297 BOOL WINAPI
SetupDiGetDeviceInstanceIdA(
4298 IN HDEVINFO DeviceInfoSet
,
4299 IN PSP_DEVINFO_DATA DeviceInfoData
,
4300 OUT PSTR DeviceInstanceId OPTIONAL
,
4301 IN DWORD DeviceInstanceIdSize
,
4302 OUT PDWORD RequiredSize OPTIONAL
)
4304 PWSTR DeviceInstanceIdW
= NULL
;
4307 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4308 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4310 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4311 SetLastError(ERROR_INVALID_PARAMETER
);
4314 if (DeviceInstanceIdSize
!= 0)
4316 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4317 if (DeviceInstanceIdW
== NULL
)
4321 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4322 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4325 if (ret
&& DeviceInstanceIdW
!= NULL
)
4327 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4328 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4330 DeviceInstanceId
[0] = '\0';
4336 TRACE("Returning %d\n", ret
);
4340 /***********************************************************************
4341 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4343 BOOL WINAPI
SetupDiGetDeviceInstanceIdW(
4344 IN HDEVINFO DeviceInfoSet
,
4345 IN PSP_DEVINFO_DATA DeviceInfoData
,
4346 OUT PWSTR DeviceInstanceId OPTIONAL
,
4347 IN DWORD DeviceInstanceIdSize
,
4348 OUT PDWORD RequiredSize OPTIONAL
)
4352 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4353 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4356 SetLastError(ERROR_INVALID_HANDLE
);
4357 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4358 SetLastError(ERROR_INVALID_HANDLE
);
4359 else if (!DeviceInfoData
)
4360 SetLastError(ERROR_INVALID_PARAMETER
);
4361 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4362 SetLastError(ERROR_INVALID_USER_BUFFER
);
4363 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4364 SetLastError(ERROR_INVALID_PARAMETER
);
4365 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4366 SetLastError(ERROR_INVALID_PARAMETER
);
4369 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4372 required
= (strlenW(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4374 *RequiredSize
= required
;
4376 if (required
<= DeviceInstanceIdSize
)
4378 strcpyW(DeviceInstanceId
, DevInfo
->DeviceName
);
4382 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4385 TRACE("Returning %d\n", ret
);
4389 /***********************************************************************
4390 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4392 BOOL WINAPI
SetupDiGetClassDevPropertySheetsA(
4393 IN HDEVINFO DeviceInfoSet
,
4394 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4395 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4396 IN DWORD PropertySheetHeaderPageListSize
,
4397 OUT PDWORD RequiredSize OPTIONAL
,
4398 IN DWORD PropertySheetType
)
4400 PROPSHEETHEADERW psh
;
4403 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4404 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4405 RequiredSize
, PropertySheetType
);
4407 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4408 psh
.phpage
= PropertySheetHeader
->phpage
;
4409 psh
.nPages
= PropertySheetHeader
->nPages
;
4411 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4412 PropertySheetHeaderPageListSize
, RequiredSize
,
4416 PropertySheetHeader
->nPages
= psh
.nPages
;
4419 TRACE("Returning %d\n", ret
);
4423 struct ClassDevPropertySheetsData
4425 HPROPSHEETPAGE
*PropertySheetPages
;
4426 DWORD MaximumNumberOfPages
;
4427 DWORD NumberOfPages
;
4430 static BOOL WINAPI
GetClassDevPropertySheetsCallback(
4431 IN HPROPSHEETPAGE hPropSheetPage
,
4432 IN OUT LPARAM lParam
)
4434 struct ClassDevPropertySheetsData
*PropPageData
;
4436 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4438 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4440 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4441 PropPageData
->PropertySheetPages
++;
4444 PropPageData
->NumberOfPages
++;
4448 /***********************************************************************
4449 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4451 BOOL WINAPI
SetupDiGetClassDevPropertySheetsW(
4452 IN HDEVINFO DeviceInfoSet
,
4453 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4454 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4455 IN DWORD PropertySheetHeaderPageListSize
,
4456 OUT PDWORD RequiredSize OPTIONAL
,
4457 IN DWORD PropertySheetType
)
4459 struct DeviceInfoSet
*list
;
4462 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4463 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4464 RequiredSize
, PropertySheetType
);
4467 SetLastError(ERROR_INVALID_HANDLE
);
4468 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4469 SetLastError(ERROR_INVALID_HANDLE
);
4470 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4471 SetLastError(ERROR_INVALID_HANDLE
);
4472 else if (!PropertySheetHeader
)
4473 SetLastError(ERROR_INVALID_PARAMETER
);
4474 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4475 SetLastError(ERROR_INVALID_FLAGS
);
4476 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4477 SetLastError(ERROR_INVALID_USER_BUFFER
);
4478 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4479 SetLastError(ERROR_INVALID_PARAMETER
);
4480 else if (!PropertySheetHeader
)
4481 SetLastError(ERROR_INVALID_PARAMETER
);
4482 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4483 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4484 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4485 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4486 SetLastError(ERROR_INVALID_PARAMETER
);
4489 HKEY hKey
= INVALID_HANDLE_VALUE
;
4490 SP_PROPSHEETPAGE_REQUEST Request
;
4491 LPWSTR PropPageProvider
= NULL
;
4492 HMODULE hModule
= NULL
;
4493 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4494 struct ClassDevPropertySheetsData PropPageData
;
4495 DWORD dwLength
, dwRegType
;
4499 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4502 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4503 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4505 if (hKey
== INVALID_HANDLE_VALUE
)
4508 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4509 if (rc
== ERROR_FILE_NOT_FOUND
)
4511 /* No registry key. As it is optional, don't say it's a bad error */
4517 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4523 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4524 if (!PropPageProvider
)
4526 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4529 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4530 if (rc
!= ERROR_SUCCESS
)
4535 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4537 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4538 if (rc
!= ERROR_SUCCESS
)
4540 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4544 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4545 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4546 Request
.DeviceInfoSet
= DeviceInfoSet
;
4547 Request
.DeviceInfoData
= DeviceInfoData
;
4548 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4549 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4550 PropPageData
.NumberOfPages
= 0;
4551 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4556 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4557 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4559 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4564 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4565 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4569 if (hKey
!= INVALID_HANDLE_VALUE
)
4571 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4572 FreeFunctionPointer(hModule
, pPropPageProvider
);
4575 TRACE("Returning %d\n", ret
);
4579 /***********************************************************************
4580 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4582 HKEY WINAPI
SetupDiCreateDevRegKeyA(
4583 IN HDEVINFO DeviceInfoSet
,
4584 IN PSP_DEVINFO_DATA DeviceInfoData
,
4588 IN HINF InfHandle OPTIONAL
,
4589 IN PCSTR InfSectionName OPTIONAL
)
4591 PCWSTR InfSectionNameW
= NULL
;
4592 HKEY ret
= INVALID_HANDLE_VALUE
;
4596 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4597 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4600 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4608 if (InfSectionNameW
!= NULL
)
4609 MyFree((PVOID
)InfSectionNameW
);
4615 OpenHardwareProfileKey(
4618 IN DWORD samDesired
)
4620 HKEY hHWProfilesKey
= NULL
;
4621 HKEY hHWProfileKey
= NULL
;
4622 HKEY ret
= INVALID_HANDLE_VALUE
;
4625 rc
= RegOpenKeyExW(HKLM
,
4626 REGSTR_PATH_HWPROFILES
,
4630 if (rc
!= ERROR_SUCCESS
)
4647 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4656 if (rc
!= ERROR_SUCCESS
)
4661 ret
= hHWProfileKey
;
4664 if (hHWProfilesKey
!= NULL
)
4665 RegCloseKey(hHWProfilesKey
);
4666 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4667 RegCloseKey(hHWProfileKey
);
4671 /***********************************************************************
4672 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4674 HKEY WINAPI
SetupDiCreateDevRegKeyW(
4675 IN HDEVINFO DeviceInfoSet
,
4676 IN PSP_DEVINFO_DATA DeviceInfoData
,
4680 IN HINF InfHandle OPTIONAL
,
4681 IN PCWSTR InfSectionName OPTIONAL
)
4683 struct DeviceInfoSet
*list
;
4684 HKEY ret
= INVALID_HANDLE_VALUE
;
4686 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4687 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4690 SetLastError(ERROR_INVALID_HANDLE
);
4691 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4692 SetLastError(ERROR_INVALID_HANDLE
);
4693 else if (!DeviceInfoData
)
4694 SetLastError(ERROR_INVALID_PARAMETER
);
4695 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4696 SetLastError(ERROR_INVALID_USER_BUFFER
);
4697 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4698 SetLastError(ERROR_INVALID_PARAMETER
);
4699 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4700 SetLastError(ERROR_INVALID_PARAMETER
);
4701 else if (InfHandle
&& !InfSectionName
)
4702 SetLastError(ERROR_INVALID_PARAMETER
);
4703 else if (!InfHandle
&& InfSectionName
)
4704 SetLastError(ERROR_INVALID_PARAMETER
);
4707 LPWSTR lpGuidString
= NULL
;
4708 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4709 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4710 DWORD Index
; /* Index used in the DriverKey name */
4712 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4713 HKEY hEnumKey
= NULL
;
4714 HKEY hClassKey
= NULL
;
4715 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
4719 if (Scope
== DICS_FLAG_GLOBAL
)
4720 RootKey
= list
->HKLM
;
4721 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4723 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
4724 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4726 RootKey
= hHWProfileKey
;
4729 if (KeyType
== DIREG_DEV
)
4731 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4733 rc
= RegCreateKeyExW(
4735 REGSTR_PATH_SYSTEMENUM
,
4738 REG_OPTION_NON_VOLATILE
,
4743 if (rc
!= ERROR_SUCCESS
)
4748 rc
= RegCreateKeyExW(
4750 deviceInfo
->DeviceName
,
4753 REG_OPTION_NON_VOLATILE
,
4754 #if _WIN32_WINNT >= 0x502
4755 KEY_READ
| KEY_WRITE
,
4762 if (rc
!= ERROR_SUCCESS
)
4768 else /* KeyType == DIREG_DRV */
4770 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
4772 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
4773 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
4776 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4779 strcpyW(DriverKey
, L
"{");
4780 strcatW(DriverKey
, lpGuidString
);
4781 strcatW(DriverKey
, L
"}\\");
4782 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
4783 rc
= RegOpenKeyExW(RootKey
,
4784 REGSTR_PATH_CLASS_NT
,
4788 if (rc
!= ERROR_SUCCESS
)
4794 /* Try all values for Index between 0 and 9999 */
4796 while (Index
<= 9999)
4799 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
4800 rc
= RegCreateKeyEx(hClassKey
,
4804 REG_OPTION_NON_VOLATILE
,
4805 #if _WIN32_WINNT >= 0x502
4806 KEY_READ
| KEY_WRITE
,
4813 if (rc
!= ERROR_SUCCESS
)
4818 if (Disposition
== REG_CREATED_NEW_KEY
)
4826 /* Unable to create more than 9999 devices within the same class */
4827 SetLastError(ERROR_GEN_FAILURE
);
4831 /* Open device key, to write Driver value */
4832 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
4833 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
4835 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
4836 if (rc
!= ERROR_SUCCESS
)
4843 /* Do installation of the specified section */
4846 FIXME("Need to install section %s in file %p\n",
4847 debugstr_w(InfSectionName
), InfHandle
);
4853 RpcStringFreeW(&lpGuidString
);
4854 HeapFree(GetProcessHeap(), 0, DriverKey
);
4855 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
4856 RegCloseKey(hHWProfileKey
);
4857 if (hEnumKey
!= NULL
)
4858 RegCloseKey(hEnumKey
);
4859 if (hClassKey
!= NULL
)
4860 RegCloseKey(hClassKey
);
4861 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
4862 RegCloseKey(hDeviceKey
);
4863 if (hKey
!= NULL
&& hKey
!= ret
)
4867 TRACE("Returning 0x%p\n", ret
);
4871 /***********************************************************************
4872 * SetupDiOpenDevRegKey (SETUPAPI.@)
4874 HKEY WINAPI
SetupDiOpenDevRegKey(
4875 HDEVINFO DeviceInfoSet
,
4876 PSP_DEVINFO_DATA DeviceInfoData
,
4882 struct DeviceInfoSet
*list
;
4883 HKEY ret
= INVALID_HANDLE_VALUE
;
4885 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4886 Scope
, HwProfile
, KeyType
, samDesired
);
4889 SetLastError(ERROR_INVALID_HANDLE
);
4890 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4891 SetLastError(ERROR_INVALID_HANDLE
);
4892 else if (!DeviceInfoData
)
4893 SetLastError(ERROR_INVALID_PARAMETER
);
4894 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4895 SetLastError(ERROR_INVALID_USER_BUFFER
);
4896 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4897 SetLastError(ERROR_INVALID_PARAMETER
);
4898 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4899 SetLastError(ERROR_INVALID_PARAMETER
);
4902 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4903 LPWSTR DriverKey
= NULL
;
4907 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
4908 HKEY hEnumKey
= NULL
;
4912 if (Scope
== DICS_FLAG_GLOBAL
)
4913 RootKey
= list
->HKLM
;
4914 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
4916 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
4917 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
4919 RootKey
= hHWProfileKey
;
4924 REGSTR_PATH_SYSTEMENUM
,
4928 if (rc
!= ERROR_SUCCESS
)
4935 deviceInfo
->DeviceName
,
4937 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
4939 RegCloseKey(hEnumKey
);
4941 if (rc
!= ERROR_SUCCESS
)
4946 if (KeyType
== DIREG_DEV
)
4948 /* We're done. Just return the hKey handle */
4952 /* Read the 'Driver' key */
4953 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
4954 if (rc
!= ERROR_SUCCESS
)
4959 else if (dwRegType
!= REG_SZ
)
4961 SetLastError(ERROR_GEN_FAILURE
);
4964 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4967 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4970 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
4971 if (rc
!= ERROR_SUCCESS
)
4978 /* Need to open the driver key */
4981 REGSTR_PATH_CLASS_NT
,
4985 if (rc
!= ERROR_SUCCESS
)
4996 if (rc
!= ERROR_SUCCESS
)
5004 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
5005 RegCloseKey(hHWProfileKey
);
5006 if (hEnumKey
!= NULL
)
5007 RegCloseKey(hEnumKey
);
5008 if (hKey
!= NULL
&& hKey
!= ret
)
5012 TRACE("Returning 0x%p\n", ret
);
5016 /***********************************************************************
5017 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
5019 BOOL WINAPI
SetupDiCreateDeviceInfoA(
5020 HDEVINFO DeviceInfoSet
,
5022 CONST GUID
*ClassGuid
,
5023 PCSTR DeviceDescription
,
5025 DWORD CreationFlags
,
5026 PSP_DEVINFO_DATA DeviceInfoData
)
5028 LPWSTR DeviceNameW
= NULL
;
5029 LPWSTR DeviceDescriptionW
= NULL
;
5036 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
5037 if (DeviceNameW
== NULL
) return FALSE
;
5039 if (DeviceDescription
)
5041 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
5042 if (DeviceDescriptionW
== NULL
)
5044 if (DeviceNameW
) MyFree(DeviceNameW
);
5049 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
5050 ClassGuid
, DeviceDescriptionW
,
5051 hwndParent
, CreationFlags
,
5054 if (DeviceNameW
) MyFree(DeviceNameW
);
5055 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
5060 /***********************************************************************
5061 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5063 BOOL WINAPI
SetupDiCreateDeviceInfoW(
5064 HDEVINFO DeviceInfoSet
,
5066 CONST GUID
*ClassGuid
,
5067 PCWSTR DeviceDescription
,
5069 DWORD CreationFlags
,
5070 PSP_DEVINFO_DATA DeviceInfoData
)
5072 struct DeviceInfoSet
*list
;
5075 TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
5076 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
5077 hwndParent
, CreationFlags
, DeviceInfoData
);
5080 SetLastError(ERROR_INVALID_HANDLE
);
5081 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5082 SetLastError(ERROR_INVALID_HANDLE
);
5083 else if (!ClassGuid
)
5084 SetLastError(ERROR_INVALID_PARAMETER
);
5085 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
5086 SetLastError(ERROR_CLASS_MISMATCH
);
5087 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
5089 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
5090 SetLastError(ERROR_INVALID_FLAGS
);
5094 SP_DEVINFO_DATA DevInfo
;
5096 if (CreationFlags
& DICD_GENERATE_ID
)
5098 /* Generate a new unique ID for this device */
5099 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5100 FIXME("not implemented\n");
5104 /* Device name is fully qualified. Try to open it */
5107 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
5108 rc
= SetupDiOpenDeviceInfoW(
5111 NULL
, /* hwndParent */
5112 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5117 /* SetupDiOpenDeviceInfoW has already added
5118 * the device info to the device info set
5120 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5122 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5124 struct DeviceInfoElement
*deviceInfo
;
5126 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5128 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5130 if (!DeviceInfoData
)
5134 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5136 SetLastError(ERROR_INVALID_USER_BUFFER
);
5140 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5141 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5142 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5151 TRACE("Returning %d\n", ret
);
5155 /***********************************************************************
5156 * Helper functions for SetupDiBuildDriverInfoList
5160 IN PLIST_ENTRY DriverListHead
,
5161 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5162 IN LPGUID ClassGuid
,
5163 IN INFCONTEXT ContextDevice
,
5164 IN
struct InfFileDetails
*InfFileDetails
,
5166 IN LPCWSTR ProviderName
,
5167 IN LPCWSTR ManufacturerName
,
5168 IN LPCWSTR MatchingId
,
5169 FILETIME DriverDate
,
5170 DWORDLONG DriverVersion
,
5173 struct DriverInfoElement
*driverInfo
= NULL
;
5174 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5175 DWORD RequiredSize
= 128; /* Initial buffer size */
5176 BOOL Result
= FALSE
;
5177 PLIST_ENTRY PreviousEntry
;
5178 LPWSTR InfInstallSection
= NULL
;
5181 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5184 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5187 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5189 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5190 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5192 /* Copy InfFileName field */
5193 strncpyW(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5194 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5196 /* Fill InfDate field */
5197 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5198 GENERIC_READ, FILE_SHARE_READ,
5199 NULL, OPEN_EXISTING, 0, NULL);
5200 if (hFile == INVALID_HANDLE_VALUE)
5202 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5206 /* Fill SectionName field */
5207 Result
= SetupGetStringFieldW(
5210 driverInfo
->Details
.SectionName
, LINE_LEN
,
5215 /* Fill DrvDescription field */
5216 Result
= SetupGetStringFieldW(
5218 0, /* Field index */
5219 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5222 /* Copy MatchingId information */
5225 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
5226 if (!driverInfo
->MatchingId
)
5228 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5231 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
5234 driverInfo
->MatchingId
= NULL
;
5236 /* Get inf install section */
5238 RequiredSize
= 128; /* Initial buffer size */
5239 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5240 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5242 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5243 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5244 if (!InfInstallSection
)
5246 Result
= SetupGetStringFieldW(
5248 1, /* Field index */
5249 InfInstallSection
, RequiredSize
,
5255 TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
5256 debugstr_w(driverInfo
->Details
.DrvDescription
), debugstr_w(InfFile
),
5257 debugstr_w(InfInstallSection
), Rank
);
5259 driverInfo
->DriverRank
= Rank
;
5260 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5261 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5262 driverInfo
->Info
.DriverType
= DriverType
;
5263 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5264 strncpyW(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5265 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5266 strncpyW(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5267 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5270 strncpyW(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5271 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5274 driverInfo
->Info
.ProviderName
[0] = '\0';
5275 driverInfo
->Info
.DriverDate
= DriverDate
;
5276 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5277 ReferenceInfFile(InfFileDetails
);
5278 driverInfo
->InfFileDetails
= InfFileDetails
;
5280 /* Insert current driver in driver list, according to its rank */
5281 PreviousEntry
= DriverListHead
->Flink
;
5282 while (PreviousEntry
!= DriverListHead
)
5284 struct DriverInfoElement
*CurrentDriver
;
5285 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5286 if (CurrentDriver
->DriverRank
> Rank
||
5287 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5289 /* Insert before the current item */
5290 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5293 PreviousEntry
= PreviousEntry
->Flink
;
5295 if (PreviousEntry
== DriverListHead
)
5297 /* Insert at the end of the list */
5298 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5307 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5308 HeapFree(GetProcessHeap(), 0, driverInfo
);
5310 if (hFile
!= INVALID_HANDLE_VALUE
)
5312 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5318 GetVersionInformationFromInfFile(
5320 OUT LPGUID ClassGuid
,
5321 OUT LPWSTR
* pProviderName
,
5322 OUT FILETIME
* DriverDate
,
5323 OUT DWORDLONG
* DriverVersion
)
5326 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5327 LPWSTR DriverVer
= NULL
;
5328 LPWSTR ProviderName
= NULL
;
5329 LPWSTR pComma
; /* Points into DriverVer */
5330 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5331 SYSTEMTIME SystemTime
;
5333 BOOL ret
= FALSE
; /* Final result */
5335 /* Get class Guid */
5336 if (!SetupGetLineTextW(
5340 guidW
, sizeof(guidW
),
5341 NULL
/* Required size */))
5345 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5346 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5348 SetLastError(ERROR_GEN_FAILURE
);
5352 /* Get provider name */
5353 Result
= SetupGetLineTextW(
5355 hInf
, Version
, INF_PROVIDER
,
5360 /* We know know the needed buffer size */
5361 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5364 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5367 Result
= SetupGetLineTextW(
5369 hInf
, Version
, INF_PROVIDER
,
5370 ProviderName
, RequiredSize
,
5375 *pProviderName
= ProviderName
;
5377 /* Read the "DriverVer" value */
5378 Result
= SetupGetLineTextW(
5380 hInf
, Version
, INF_DRIVER_VER
,
5385 /* We know know the needed buffer size */
5386 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5389 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5392 Result
= SetupGetLineTextW(
5394 hInf
, Version
, INF_DRIVER_VER
,
5395 DriverVer
, RequiredSize
,
5401 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5402 pComma
= strchrW(DriverVer
, ',');
5405 *pComma
= UNICODE_NULL
;
5406 pVersion
= pComma
+ 1;
5408 /* Get driver date version. Invalid date = 00/00/00 */
5409 memset(DriverDate
, 0, sizeof(FILETIME
));
5410 if (strlenW(DriverVer
) == 10
5411 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5412 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5414 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5415 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5416 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5417 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5418 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5419 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5421 /* Get driver version. Invalid version = 0.0.0.0 */
5425 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5426 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5427 LARGE_INTEGER fullVersion
;
5429 pMinor
= strchrW(pVersion
, '.');
5433 pRevision
= strchrW(++pMinor
, '.');
5434 Minor
= atoiW(pMinor
);
5439 pBuild
= strchrW(++pRevision
, '.');
5440 Revision
= atoiW(pRevision
);
5446 Build
= atoiW(pBuild
);
5448 Major
= atoiW(pVersion
);
5449 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5450 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5451 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5458 HeapFree(GetProcessHeap(), 0, ProviderName
);
5459 HeapFree(GetProcessHeap(), 0, DriverVer
);
5465 GetHardwareAndCompatibleIDsLists(
5466 IN HDEVINFO DeviceInfoSet
,
5467 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
5468 OUT LPWSTR
*pHardwareIDs OPTIONAL
,
5469 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL
,
5470 OUT LPWSTR
*pCompatibleIDs OPTIONAL
,
5471 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL
)
5473 LPWSTR HardwareIDs
= NULL
;
5474 LPWSTR CompatibleIDs
= NULL
;
5478 /* Get hardware IDs list */
5480 RequiredSize
= 512; /* Initial buffer size */
5481 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5482 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5484 MyFree(HardwareIDs
);
5485 HardwareIDs
= MyMalloc(RequiredSize
);
5488 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5491 Result
= SetupDiGetDeviceRegistryPropertyW(
5502 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5504 /* No hardware ID for this device */
5505 MyFree(HardwareIDs
);
5513 *pHardwareIDs
= HardwareIDs
;
5514 if (pHardwareIDsRequiredSize
)
5515 *pHardwareIDsRequiredSize
= RequiredSize
;
5517 /* Get compatible IDs list */
5519 RequiredSize
= 512; /* Initial buffer size */
5520 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5521 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5523 MyFree(CompatibleIDs
);
5524 CompatibleIDs
= MyMalloc(RequiredSize
);
5527 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5530 Result
= SetupDiGetDeviceRegistryPropertyW(
5533 SPDRP_COMPATIBLEIDS
,
5535 (PBYTE
)CompatibleIDs
,
5541 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5543 /* No compatible ID for this device */
5544 MyFree(CompatibleIDs
);
5545 CompatibleIDs
= NULL
;
5552 *pCompatibleIDs
= CompatibleIDs
;
5553 if (pCompatibleIDsRequiredSize
)
5554 *pCompatibleIDsRequiredSize
= RequiredSize
;
5561 MyFree(HardwareIDs
);
5562 MyFree(CompatibleIDs
);
5567 /***********************************************************************
5568 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5571 SetupDiBuildDriverInfoList(
5572 IN HDEVINFO DeviceInfoSet
,
5573 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5574 IN DWORD DriverType
)
5576 struct DeviceInfoSet
*list
;
5577 SP_DEVINSTALL_PARAMS_W InstallParams
;
5578 PVOID Buffer
= NULL
;
5579 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5580 LPWSTR ProviderName
= NULL
;
5581 LPWSTR ManufacturerName
= NULL
;
5582 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5583 LPWSTR HardwareIDs
= NULL
;
5584 LPWSTR CompatibleIDs
= NULL
;
5585 LPWSTR FullInfFileName
= NULL
;
5586 LPWSTR ExcludeFromSelect
= NULL
;
5587 FILETIME DriverDate
;
5588 DWORDLONG DriverVersion
= 0;
5592 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5595 SetLastError(ERROR_INVALID_HANDLE
);
5596 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5597 SetLastError(ERROR_INVALID_HANDLE
);
5598 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5599 SetLastError(ERROR_INVALID_HANDLE
);
5600 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5601 SetLastError(ERROR_INVALID_PARAMETER
);
5602 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5603 SetLastError(ERROR_INVALID_PARAMETER
);
5604 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5605 SetLastError(ERROR_INVALID_USER_BUFFER
);
5608 PLIST_ENTRY pDriverListHead
= &list
->DriverListHead
;
5611 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5612 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5618 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5619 if (!(devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
5620 pDriverListHead
= &devInfo
->DriverListHead
;
5623 if (DriverType
== SPDIT_COMPATDRIVER
)
5625 /* Get hardware and compatible IDs lists */
5626 Result
= GetHardwareAndCompatibleIDsLists(
5635 if (!HardwareIDs
&& !CompatibleIDs
)
5637 SetLastError(ERROR_FILE_NOT_FOUND
);
5642 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5644 /* InstallParams.DriverPath contains the name of a .inf file */
5645 RequiredSize
= strlenW(InstallParams
.DriverPath
) + 2;
5646 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5649 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5652 strcpyW(Buffer
, InstallParams
.DriverPath
);
5653 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
5658 /* Enumerate .inf files */
5660 RequiredSize
= 32768; /* Initial buffer size */
5661 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5662 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5664 HeapFree(GetProcessHeap(), 0, Buffer
);
5665 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5669 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5672 Result
= SetupGetInfFileListW(
5673 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
5675 Buffer
, RequiredSize
,
5678 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
5680 /* No .inf file in specified directory. So, we should
5681 * success as we created an empty driver info list.
5690 LPWSTR pFullFilename
;
5692 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5694 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5695 if (!FullInfFileName
)
5697 pFullFilename
= &FullInfFileName
[0];
5699 else if (*InstallParams
.DriverPath
)
5702 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
5705 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
5706 if (!FullInfFileName
)
5708 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
5711 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
5712 strcatW(FullInfFileName
, L
"\\");
5713 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
5717 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
5718 if (!FullInfFileName
)
5720 pFullFilename
= &FullInfFileName
[0];
5723 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= strlenW(filename
) + 1)
5725 INFCONTEXT ContextManufacturer
, ContextDevice
;
5728 strcpyW(pFullFilename
, filename
);
5729 TRACE("Opening file %s\n", debugstr_w(FullInfFileName
));
5731 currentInfFileDetails
= HeapAlloc(
5734 FIELD_OFFSET(struct InfFileDetails
, FullInfFileName
) + strlenW(FullInfFileName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
));
5735 if (!currentInfFileDetails
)
5737 memset(currentInfFileDetails
, 0, sizeof(struct InfFileDetails
));
5738 strcpyW(currentInfFileDetails
->FullInfFileName
, FullInfFileName
);
5740 currentInfFileDetails
->hInf
= SetupOpenInfFileW(FullInfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5741 ReferenceInfFile(currentInfFileDetails
);
5742 if (currentInfFileDetails
->hInf
== INVALID_HANDLE_VALUE
)
5744 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
);
5745 currentInfFileDetails
= NULL
;
5749 if (!GetVersionInformationFromInfFile(
5750 currentInfFileDetails
->hInf
,
5756 SetupCloseInfFile(currentInfFileDetails
->hInf
);
5757 HeapFree(GetProcessHeap(), 0, currentInfFileDetails
->hInf
);
5758 currentInfFileDetails
= NULL
;
5762 if (DriverType
== SPDIT_CLASSDRIVER
)
5764 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
5765 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
5771 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
5773 /* Read ExcludeFromSelect control flags */
5777 FIXME("ExcludeFromSelect list ignored\n");
5779 /* Get the manufacturers list */
5780 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, INF_MANUFACTURER
, NULL
, &ContextManufacturer
);
5783 Result
= SetupGetStringFieldW(
5784 &ContextManufacturer
,
5785 0, /* Field index */
5790 /* We got the needed size for the buffer */
5791 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5792 if (!ManufacturerName
)
5794 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5797 Result
= SetupGetStringFieldW(
5798 &ContextManufacturer
,
5799 0, /* Field index */
5800 ManufacturerName
, RequiredSize
,
5803 /* Get manufacturer section name */
5804 Result
= SetupGetStringFieldW(
5805 &ContextManufacturer
,
5806 1, /* Field index */
5807 ManufacturerSection
, LINE_LEN
,
5811 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
5812 /* Add (possible) extension to manufacturer section name */
5813 Result
= SetupDiGetActualSectionToInstallW(
5814 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
5817 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection
));
5818 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
5823 if (DriverType
== SPDIT_CLASSDRIVER
)
5825 /* FIXME: Check ExcludeFromSelect list */
5826 if (!AddDriverToList(
5831 currentInfFileDetails
,
5836 DriverDate
, DriverVersion
,
5842 else /* DriverType = SPDIT_COMPATDRIVER */
5844 /* 1. Get all fields */
5845 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
5849 BOOL DriverAlreadyAdded
;
5851 for (i
= 2; i
<= FieldCount
; i
++)
5853 LPWSTR DeviceId
= NULL
;
5855 RequiredSize
= 128; /* Initial buffer size */
5856 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5857 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5859 HeapFree(GetProcessHeap(), 0, DeviceId
);
5860 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5863 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5866 Result
= SetupGetStringFieldW(
5869 DeviceId
, RequiredSize
,
5874 HeapFree(GetProcessHeap(), 0, DeviceId
);
5877 /* FIXME: Check ExcludeFromSelect list */
5878 DriverAlreadyAdded
= FALSE
;
5879 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
5881 if (wcsicmp(DeviceId
, currentId
) == 0)
5888 currentInfFileDetails
,
5893 DriverDate
, DriverVersion
,
5894 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
5895 DriverAlreadyAdded
= TRUE
;
5900 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
5902 if (wcsicmp(DeviceId
, currentId
) == 0)
5909 currentInfFileDetails
,
5914 DriverDate
, DriverVersion
,
5915 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
5916 DriverAlreadyAdded
= TRUE
;
5920 HeapFree(GetProcessHeap(), 0, DeviceId
);
5923 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
5926 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5927 ManufacturerName
= NULL
;
5928 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
5933 HeapFree(GetProcessHeap(), 0, ProviderName
);
5934 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
5935 ProviderName
= ExcludeFromSelect
= NULL
;
5937 DereferenceInfFile(currentInfFileDetails
);
5938 currentInfFileDetails
= NULL
;
5949 InstallParams
.Flags
|= DI_DIDCOMPAT
;
5950 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
5954 InstallParams
.Flags
|= DI_DIDCLASS
;
5955 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
5957 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5960 HeapFree(GetProcessHeap(), 0, ProviderName
);
5961 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
5962 MyFree(HardwareIDs
);
5963 MyFree(CompatibleIDs
);
5964 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
5965 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
5966 if (currentInfFileDetails
)
5967 DereferenceInfFile(currentInfFileDetails
);
5968 HeapFree(GetProcessHeap(), 0, Buffer
);
5970 TRACE("Returning %d\n", ret
);
5974 /***********************************************************************
5975 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
5978 SetupDiDeleteDeviceInfo(
5979 IN HDEVINFO DeviceInfoSet
,
5980 IN PSP_DEVINFO_DATA DeviceInfoData
)
5982 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
5984 FIXME("not implemented\n");
5985 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5990 /***********************************************************************
5991 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
5994 SetupDiDestroyDriverInfoList(
5995 IN HDEVINFO DeviceInfoSet
,
5996 IN PSP_DEVINFO_DATA DeviceInfoData
,
5997 IN DWORD DriverType
)
5999 struct DeviceInfoSet
*list
;
6002 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
6005 SetLastError(ERROR_INVALID_HANDLE
);
6006 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6007 SetLastError(ERROR_INVALID_HANDLE
);
6008 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6009 SetLastError(ERROR_INVALID_PARAMETER
);
6010 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6011 SetLastError(ERROR_INVALID_PARAMETER
);
6012 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6013 SetLastError(ERROR_INVALID_USER_BUFFER
);
6016 PLIST_ENTRY ListEntry
;
6017 struct DriverInfoElement
*driverInfo
;
6018 SP_DEVINSTALL_PARAMS_W InstallParams
;
6020 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6021 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6024 if (!DeviceInfoData
)
6025 /* Fall back to destroying class driver list */
6026 DriverType
= SPDIT_CLASSDRIVER
;
6028 if (DriverType
== SPDIT_CLASSDRIVER
)
6030 while (!IsListEmpty(&list
->DriverListHead
))
6032 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
6033 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
6034 DestroyDriverInfoElement(driverInfo
);
6036 InstallParams
.Reserved
= 0;
6037 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
6038 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
6039 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
6043 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
6044 struct DeviceInfoElement
*deviceInfo
;
6046 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6047 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
6049 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6050 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
6052 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
6053 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
6054 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
6056 InstallParamsSet
.Reserved
= 0;
6057 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
6059 DestroyDriverInfoElement(driverInfo
);
6061 InstallParams
.Reserved
= 0;
6062 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
6063 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
6064 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6069 TRACE("Returning %d\n", ret
);
6074 /***********************************************************************
6075 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
6078 SetupDiOpenDeviceInfoA(
6079 IN HDEVINFO DeviceInfoSet
,
6080 IN PCSTR DeviceInstanceId
,
6081 IN HWND hwndParent OPTIONAL
,
6083 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6085 LPWSTR DeviceInstanceIdW
= NULL
;
6088 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
6090 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
6091 if (DeviceInstanceIdW
== NULL
)
6094 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
6095 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
6097 MyFree(DeviceInstanceIdW
);
6103 /***********************************************************************
6104 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
6107 SetupDiOpenDeviceInfoW(
6108 IN HDEVINFO DeviceInfoSet
,
6109 IN PCWSTR DeviceInstanceId
,
6110 IN HWND hwndParent OPTIONAL
,
6112 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6114 struct DeviceInfoSet
*list
;
6115 HKEY hEnumKey
, hKey
= NULL
;
6119 TRACE("%p %s %p %lx %p\n",
6120 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
6121 hwndParent
, OpenFlags
, DeviceInfoData
);
6123 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
6124 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
6127 SetLastError(ERROR_INVALID_HANDLE
);
6128 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6129 SetLastError(ERROR_INVALID_HANDLE
);
6130 else if (!DeviceInstanceId
)
6131 SetLastError(ERROR_INVALID_PARAMETER
);
6132 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
6134 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
6135 SetLastError(ERROR_INVALID_FLAGS
);
6137 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6138 SetLastError(ERROR_INVALID_USER_BUFFER
);
6141 struct DeviceInfoElement
*deviceInfo
= NULL
;
6142 /* Search if device already exists in DeviceInfoSet.
6143 * If yes, return the existing element
6144 * If no, create a new element using informations in registry
6146 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
6147 while (ItemList
!= &list
->ListHead
)
6152 FIXME("not implemented\n");
6153 ItemList
= ItemList
->Flink
;
6158 /* good one found */
6163 /* Open supposed registry key */
6166 REGSTR_PATH_SYSTEMENUM
,
6170 if (rc
!= ERROR_SUCCESS
)
6181 RegCloseKey(hEnumKey
);
6182 if (rc
!= ERROR_SUCCESS
)
6184 if (rc
== ERROR_FILE_NOT_FOUND
)
6185 rc
= ERROR_NO_SUCH_DEVINST
;
6190 /* FIXME: try to get ClassGUID from registry, instead of
6191 * sending GUID_NULL to CreateDeviceInfoElement
6193 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6195 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6200 if (ret
&& deviceInfo
&& DeviceInfoData
)
6202 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6203 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6204 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6215 /***********************************************************************
6216 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6219 SetupDiEnumDriverInfoA(
6220 IN HDEVINFO DeviceInfoSet
,
6221 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6222 IN DWORD DriverType
,
6223 IN DWORD MemberIndex
,
6224 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6226 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6229 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6230 DriverType
, MemberIndex
, DriverInfoData
);
6232 if (DriverInfoData
== NULL
)
6233 SetLastError(ERROR_INVALID_PARAMETER
);
6234 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6235 SetLastError(ERROR_INVALID_USER_BUFFER
);
6238 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6239 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6240 DriverType
, MemberIndex
, &driverInfoData2W
);
6244 /* Do W->A conversion */
6245 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6246 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6247 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6248 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6250 DriverInfoData
->Description
[0] = '\0';
6253 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6254 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6256 DriverInfoData
->MfgName
[0] = '\0';
6259 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6260 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6262 DriverInfoData
->ProviderName
[0] = '\0';
6265 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6267 /* Copy more fields */
6268 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6269 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6274 TRACE("Returning %d\n", ret
);
6279 /***********************************************************************
6280 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6283 SetupDiEnumDriverInfoW(
6284 IN HDEVINFO DeviceInfoSet
,
6285 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6286 IN DWORD DriverType
,
6287 IN DWORD MemberIndex
,
6288 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6290 PLIST_ENTRY ListHead
;
6293 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6294 DriverType
, MemberIndex
, DriverInfoData
);
6296 if (!DeviceInfoSet
|| !DriverInfoData
)
6297 SetLastError(ERROR_INVALID_PARAMETER
);
6298 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6299 SetLastError(ERROR_INVALID_HANDLE
);
6300 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6301 SetLastError(ERROR_INVALID_HANDLE
);
6302 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6303 SetLastError(ERROR_INVALID_PARAMETER
);
6304 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6305 SetLastError(ERROR_INVALID_PARAMETER
);
6306 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6307 SetLastError(ERROR_INVALID_USER_BUFFER
);
6310 struct DeviceInfoElement
*devInfo
= NULL
;
6311 PLIST_ENTRY ItemList
;
6313 devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6314 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
6316 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6320 ListHead
= &devInfo
->DriverListHead
;
6323 ItemList
= ListHead
->Flink
;
6324 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6325 ItemList
= ItemList
->Flink
;
6326 if (ItemList
== ListHead
)
6327 SetLastError(ERROR_NO_MORE_ITEMS
);
6330 struct DriverInfoElement
*DrvInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6333 &DriverInfoData
->DriverType
,
6334 &DrvInfo
->Info
.DriverType
,
6335 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6340 TRACE("Returning %d\n", ret
);
6345 /***********************************************************************
6346 * SetupDiGetSelectedDevice (SETUPAPI.@)
6349 SetupDiGetSelectedDevice(
6350 IN HDEVINFO DeviceInfoSet
,
6351 OUT PSP_DEVINFO_DATA DeviceInfoData
)
6353 struct DeviceInfoSet
*list
;
6356 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6359 SetLastError(ERROR_INVALID_HANDLE
);
6360 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6361 SetLastError(ERROR_INVALID_HANDLE
);
6362 else if (list
->SelectedDevice
== NULL
)
6363 SetLastError(ERROR_NO_DEVICE_SELECTED
);
6364 else if (!DeviceInfoData
)
6365 SetLastError(ERROR_INVALID_PARAMETER
);
6366 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6367 SetLastError(ERROR_INVALID_USER_BUFFER
);
6370 memcpy(&DeviceInfoData
->ClassGuid
,
6371 &list
->SelectedDevice
->ClassGuid
,
6373 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
6374 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
6378 TRACE("Returning %d\n", ret
);
6383 /***********************************************************************
6384 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6387 SetupDiGetSelectedDriverA(
6388 IN HDEVINFO DeviceInfoSet
,
6389 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6390 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6392 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6395 if (DriverInfoData
== NULL
)
6396 SetLastError(ERROR_INVALID_PARAMETER
);
6397 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6398 SetLastError(ERROR_INVALID_USER_BUFFER
);
6401 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6403 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6409 /* Do W->A conversion */
6410 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6411 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6412 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6413 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6415 DriverInfoData
->Description
[0] = '\0';
6418 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6419 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6421 DriverInfoData
->MfgName
[0] = '\0';
6424 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6425 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6427 DriverInfoData
->ProviderName
[0] = '\0';
6430 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6432 /* Copy more fields */
6433 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6434 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6443 /***********************************************************************
6444 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6447 SetupDiGetSelectedDriverW(
6448 IN HDEVINFO DeviceInfoSet
,
6449 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6450 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6454 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6456 if (!DeviceInfoSet
|| !DriverInfoData
)
6457 SetLastError(ERROR_INVALID_PARAMETER
);
6458 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6459 SetLastError(ERROR_INVALID_HANDLE
);
6460 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6461 SetLastError(ERROR_INVALID_HANDLE
);
6462 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6463 SetLastError(ERROR_INVALID_USER_BUFFER
);
6464 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6465 SetLastError(ERROR_INVALID_USER_BUFFER
);
6468 SP_DEVINSTALL_PARAMS InstallParams
;
6470 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6471 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6473 struct DriverInfoElement
*driverInfo
;
6474 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6475 if (driverInfo
== NULL
)
6476 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6480 &DriverInfoData
->DriverType
,
6481 &driverInfo
->Info
.DriverType
,
6482 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6488 TRACE("Returning %d\n", ret
);
6493 /***********************************************************************
6494 * SetupDiSetSelectedDevice (SETUPAPI.@)
6497 SetupDiSetSelectedDevice(
6498 IN HDEVINFO DeviceInfoSet
,
6499 IN PSP_DEVINFO_DATA DeviceInfoData
)
6501 struct DeviceInfoSet
*list
;
6504 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6507 SetLastError(ERROR_INVALID_HANDLE
);
6508 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6509 SetLastError(ERROR_INVALID_HANDLE
);
6510 else if (!DeviceInfoData
)
6511 SetLastError(ERROR_INVALID_PARAMETER
);
6512 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6513 SetLastError(ERROR_INVALID_USER_BUFFER
);
6514 else if (DeviceInfoData
->Reserved
== 0)
6515 SetLastError(ERROR_INVALID_USER_BUFFER
);
6518 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6522 TRACE("Returning %d\n", ret
);
6527 /***********************************************************************
6528 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6531 SetupDiSetSelectedDriverA(
6532 IN HDEVINFO DeviceInfoSet
,
6533 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6534 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6536 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6537 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6540 if (DriverInfoData
!= NULL
)
6542 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6543 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6545 SetLastError(ERROR_INVALID_PARAMETER
);
6549 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6550 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6552 if (DriverInfoDataW
.Reserved
== 0)
6554 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6556 /* convert the strings to unicode */
6557 if (!MultiByteToWideChar(CP_ACP
,
6559 DriverInfoData
->Description
,
6561 DriverInfoDataW
.Description
,
6563 !MultiByteToWideChar(CP_ACP
,
6565 DriverInfoData
->ProviderName
,
6567 DriverInfoDataW
.ProviderName
,
6574 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6577 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6581 if (ret
&& pDriverInfoDataW
!= NULL
)
6583 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6590 /***********************************************************************
6591 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6594 SetupDiSetSelectedDriverW(
6595 IN HDEVINFO DeviceInfoSet
,
6596 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6597 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6601 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6604 SetLastError(ERROR_INVALID_PARAMETER
);
6605 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6606 SetLastError(ERROR_INVALID_HANDLE
);
6607 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6608 SetLastError(ERROR_INVALID_HANDLE
);
6609 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6610 SetLastError(ERROR_INVALID_USER_BUFFER
);
6611 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6612 SetLastError(ERROR_INVALID_USER_BUFFER
);
6615 struct DriverInfoElement
**pDriverInfo
;
6616 PLIST_ENTRY ListHead
, ItemList
;
6620 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6621 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6625 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6626 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6629 if (!DriverInfoData
)
6631 *pDriverInfo
= NULL
;
6636 /* Search selected driver in list */
6637 ItemList
= ListHead
->Flink
;
6638 while (ItemList
!= ListHead
)
6640 if (DriverInfoData
->Reserved
!= 0)
6642 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6647 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6648 struct DriverInfoElement
*driverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6649 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6650 && strcmpW(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6651 && strcmpW(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6656 ItemList
= ItemList
->Flink
;
6658 if (ItemList
== ListHead
)
6659 SetLastError(ERROR_INVALID_PARAMETER
);
6662 *pDriverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6663 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6665 TRACE("Choosing driver whose rank is 0x%lx\n",
6666 (*pDriverInfo
)->DriverRank
);
6668 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6673 TRACE("Returning %d\n", ret
);
6677 /***********************************************************************
6678 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6681 SetupDiGetDriverInfoDetailA(
6682 IN HDEVINFO DeviceInfoSet
,
6683 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6684 IN PSP_DRVINFO_DATA_A DriverInfoData
,
6685 OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
6686 IN DWORD DriverInfoDetailDataSize
,
6687 OUT PDWORD RequiredSize OPTIONAL
)
6689 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
6690 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
6692 DWORD HardwareIDLen
= 0;
6695 /* do some sanity checks, the unicode version might do more thorough checks */
6696 if (DriverInfoData
== NULL
||
6697 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
6698 (DriverInfoDetailData
!= NULL
&&
6699 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
6700 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
6702 SetLastError(ERROR_INVALID_PARAMETER
);
6706 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
6707 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
6709 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6711 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6713 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6717 SetLastError(ERROR_INVALID_PARAMETER
);
6720 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6721 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6723 /* convert the strings to unicode */
6724 if (MultiByteToWideChar(CP_ACP
,
6726 DriverInfoData
->Description
,
6728 DriverInfoDataW
.Description
,
6730 MultiByteToWideChar(CP_ACP
,
6732 DriverInfoData
->MfgName
,
6734 DriverInfoDataW
.MfgName
,
6736 MultiByteToWideChar(CP_ACP
,
6738 DriverInfoData
->ProviderName
,
6740 DriverInfoDataW
.ProviderName
,
6743 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
6745 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
6746 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
6749 if (DriverInfoDetailData
!= NULL
)
6751 /* calculate the unicode buffer size from the ansi buffer size */
6752 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
6753 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
6754 (HardwareIDLen
* sizeof(WCHAR
));
6756 DriverInfoDetailDataW
= MyMalloc(BufSize
);
6757 if (DriverInfoDetailDataW
== NULL
)
6759 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6763 /* initialize the buffer */
6764 ZeroMemory(DriverInfoDetailDataW
,
6766 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
6769 /* call the unicode version */
6770 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
6773 DriverInfoDetailDataW
,
6779 if (DriverInfoDetailDataW
!= NULL
)
6781 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
6782 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
6783 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
6784 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
6785 if (WideCharToMultiByte(CP_ACP
,
6787 DriverInfoDetailDataW
->SectionName
,
6789 DriverInfoDetailData
->SectionName
,
6793 WideCharToMultiByte(CP_ACP
,
6795 DriverInfoDetailDataW
->InfFileName
,
6797 DriverInfoDetailData
->InfFileName
,
6801 WideCharToMultiByte(CP_ACP
,
6803 DriverInfoDetailDataW
->DrvDescription
,
6805 DriverInfoDetailData
->DrvDescription
,
6809 WideCharToMultiByte(CP_ACP
,
6811 DriverInfoDetailDataW
->HardwareID
,
6813 DriverInfoDetailData
->HardwareID
,
6819 DWORD hwidlen
= HardwareIDLen
;
6820 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
6822 /* count the strings in the list */
6825 len
= lstrlenA(s
) + 1;
6834 /* looks like the string list wasn't terminated... */
6835 SetLastError(ERROR_INVALID_USER_BUFFER
);
6841 /* make sure CompatIDsOffset points to the second string in the
6845 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
6846 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
6847 DriverInfoDetailData
->CompatIDsOffset
+ 1;
6851 DriverInfoDetailData
->CompatIDsOffset
= 0;
6852 DriverInfoDetailData
->CompatIDsLength
= 0;
6861 if (RequiredSize
!= NULL
)
6863 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
6864 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
6870 if (DriverInfoDetailDataW
!= NULL
)
6872 MyFree(DriverInfoDetailDataW
);
6878 /***********************************************************************
6879 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
6882 SetupDiGetDriverInfoDetailW(
6883 IN HDEVINFO DeviceInfoSet
,
6884 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6885 IN PSP_DRVINFO_DATA_W DriverInfoData
,
6886 OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
6887 IN DWORD DriverInfoDetailDataSize
,
6888 OUT PDWORD RequiredSize OPTIONAL
)
6892 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
6893 DriverInfoData
, DriverInfoDetailData
,
6894 DriverInfoDetailDataSize
, RequiredSize
);
6897 SetLastError(ERROR_INVALID_PARAMETER
);
6898 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6899 SetLastError(ERROR_INVALID_HANDLE
);
6900 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6901 SetLastError(ERROR_INVALID_HANDLE
);
6902 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6903 SetLastError(ERROR_INVALID_USER_BUFFER
);
6904 else if (!DriverInfoData
)
6905 SetLastError(ERROR_INVALID_PARAMETER
);
6906 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
6907 SetLastError(ERROR_INVALID_PARAMETER
);
6908 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6909 SetLastError(ERROR_INVALID_PARAMETER
);
6910 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
6911 SetLastError(ERROR_INVALID_USER_BUFFER
);
6912 else if (DriverInfoData
->Reserved
== 0)
6913 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6916 struct DriverInfoElement
*driverInfoElement
;
6917 LPWSTR HardwareIDs
= NULL
;
6918 LPWSTR CompatibleIDs
= NULL
;
6919 LPWSTR pBuffer
= NULL
;
6920 LPCWSTR DeviceID
= NULL
;
6921 ULONG HardwareIDsSize
, CompatibleIDsSize
;
6922 ULONG sizeNeeded
, sizeLeft
, size
;
6925 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
6927 /* Get hardware and compatible IDs lists */
6928 Result
= GetHardwareAndCompatibleIDsLists(
6931 &HardwareIDs
, &HardwareIDsSize
,
6932 &CompatibleIDs
, &CompatibleIDsSize
);
6936 sizeNeeded
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)
6937 + HardwareIDsSize
+ CompatibleIDsSize
;
6939 *RequiredSize
= sizeNeeded
;
6941 if (!DriverInfoDetailData
)
6948 DriverInfoDetailData
,
6949 &driverInfoElement
->Details
,
6950 driverInfoElement
->Details
.cbSize
);
6951 DriverInfoDetailData
->CompatIDsOffset
= 0;
6952 DriverInfoDetailData
->CompatIDsLength
= 0;
6954 sizeLeft
= (DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
);
6955 pBuffer
= DriverInfoDetailData
->HardwareID
;
6956 /* Add as many as possible HardwareIDs in the list */
6957 DeviceID
= HardwareIDs
;
6958 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
6960 TRACE("Adding %S to list\n", DeviceID
);
6961 wcscpy(pBuffer
, DeviceID
);
6962 DeviceID
+= size
+ 1;
6963 pBuffer
+= size
+ 1;
6964 sizeLeft
-= size
+ 1;
6965 DriverInfoDetailData
->CompatIDsOffset
+= size
+ 1;
6969 *pBuffer
= UNICODE_NULL
;
6971 DriverInfoDetailData
->CompatIDsOffset
++;
6973 /* Add as many as possible CompatibleIDs in the list */
6974 DeviceID
= CompatibleIDs
;
6975 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
6977 TRACE("Adding %S to list\n", DeviceID
);
6978 wcscpy(pBuffer
, DeviceID
);
6979 DeviceID
+= size
+ 1;
6980 pBuffer
+= size
+ 1;
6981 sizeLeft
-= size
+ 1;
6982 DriverInfoDetailData
->CompatIDsLength
+= size
+ 1;
6986 *pBuffer
= UNICODE_NULL
;
6988 DriverInfoDetailData
->CompatIDsLength
++;
6991 if (sizeNeeded
> DriverInfoDetailDataSize
)
6992 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
6997 MyFree(HardwareIDs
);
6998 MyFree(CompatibleIDs
);
7001 TRACE("Returning %d\n", ret
);
7005 /* Return the current hardware profile id, or -1 if error */
7007 GetCurrentHwProfile(
7008 IN HDEVINFO DeviceInfoSet
)
7011 DWORD dwRegType
, dwLength
;
7014 DWORD ret
= (DWORD
)-1;
7017 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
7018 REGSTR_PATH_IDCONFIGDB
,
7022 if (rc
!= ERROR_SUCCESS
)
7028 dwLength
= sizeof(DWORD
);
7029 rc
= RegQueryValueExW(
7031 REGSTR_VAL_CURRENTCONFIG
,
7034 (LPBYTE
)&hwProfile
, &dwLength
);
7035 if (rc
!= ERROR_SUCCESS
)
7040 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7042 SetLastError(ERROR_GEN_FAILURE
);
7057 IN HDEVINFO DeviceInfoSet
,
7058 IN PSP_DEVINFO_DATA DeviceInfoData
)
7061 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
7062 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
7065 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
7067 /* At the moment, I only know how to start local devices */
7068 SetLastError(ERROR_INVALID_COMPUTERNAME
);
7072 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
7073 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
7074 SetLastError(RtlNtStatusToDosError(Status
));
7075 return NT_SUCCESS(Status
);
7077 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
7082 static BOOL
StopDevice(
7083 IN HDEVINFO DeviceInfoSet
,
7084 IN PSP_DEVINFO_DATA DeviceInfoData
)
7086 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
7090 /***********************************************************************
7091 * SetupDiChangeState (SETUPAPI.@)
7095 IN HDEVINFO DeviceInfoSet
,
7096 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7098 PSP_PROPCHANGE_PARAMS PropChange
;
7099 HKEY hKey
= INVALID_HANDLE_VALUE
;
7100 LPCWSTR RegistryValueName
;
7101 DWORD dwConfigFlags
, dwLength
, dwRegType
;
7105 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7107 if (!DeviceInfoData
)
7108 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
7110 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
7113 SetLastError(ERROR_INVALID_PARAMETER
);
7117 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
7118 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
7120 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
7122 switch (PropChange
->StateChange
)
7127 /* Enable/disable device in registry */
7128 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
7129 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7130 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
7131 if (hKey
== INVALID_HANDLE_VALUE
)
7133 dwLength
= sizeof(DWORD
);
7134 rc
= RegQueryValueExW(
7139 (LPBYTE
)&dwConfigFlags
, &dwLength
);
7140 if (rc
== ERROR_FILE_NOT_FOUND
)
7142 else if (rc
!= ERROR_SUCCESS
)
7147 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7149 SetLastError(ERROR_GEN_FAILURE
);
7152 if (PropChange
->StateChange
== DICS_ENABLE
)
7153 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7155 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7161 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
7162 if (rc
!= ERROR_SUCCESS
)
7168 /* Enable/disable device if needed */
7169 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
7170 || PropChange
->HwProfile
== 0
7171 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
7173 if (PropChange
->StateChange
== DICS_ENABLE
)
7174 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7176 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
7182 case DICS_PROPCHANGE
:
7184 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7189 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
7190 SetLastError(ERROR_NOT_SUPPORTED
);
7195 if (hKey
!= INVALID_HANDLE_VALUE
)
7198 TRACE("Returning %d\n", ret
);
7202 /***********************************************************************
7203 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
7206 SetupDiSelectBestCompatDrv(
7207 IN HDEVINFO DeviceInfoSet
,
7208 IN PSP_DEVINFO_DATA DeviceInfoData
)
7210 SP_DRVINFO_DATA_W drvInfoData
;
7213 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7215 /* Drivers are sorted by rank in the driver list, so
7216 * the first driver in the list is the best one.
7218 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
7219 ret
= SetupDiEnumDriverInfoW(
7223 0, /* Member index */
7228 ret
= SetupDiSetSelectedDriverW(
7234 TRACE("Returning %d\n", ret
);
7238 /***********************************************************************
7239 * SetupDiInstallDriverFiles (SETUPAPI.@)
7242 SetupDiInstallDriverFiles(
7243 IN HDEVINFO DeviceInfoSet
,
7244 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7248 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7251 SetLastError(ERROR_INVALID_PARAMETER
);
7252 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7253 SetLastError(ERROR_INVALID_HANDLE
);
7254 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7255 SetLastError(ERROR_INVALID_HANDLE
);
7256 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7257 SetLastError(ERROR_INVALID_USER_BUFFER
);
7258 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
7259 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7260 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
7261 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7264 SP_DEVINSTALL_PARAMS_W InstallParams
;
7265 struct DriverInfoElement
*SelectedDriver
;
7266 WCHAR SectionName
[MAX_PATH
];
7267 DWORD SectionNameLength
= 0;
7268 PVOID InstallMsgHandler
;
7269 PVOID InstallMsgHandlerContext
;
7270 PVOID Context
= NULL
;
7272 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7273 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7277 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7278 if (!SelectedDriver
)
7280 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7284 ret
= SetupDiGetActualSectionToInstallW(
7285 SelectedDriver
->InfFileDetails
->hInf
,
7286 SelectedDriver
->Details
.SectionName
,
7287 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
7291 if (InstallParams
.InstallMsgHandler
)
7293 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
7294 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
7298 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7301 InstallMsgHandler
= SetupDefaultQueueCallback
;
7302 InstallMsgHandlerContext
= Context
;
7304 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7305 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7306 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7307 InstallMsgHandler
, InstallMsgHandlerContext
,
7308 DeviceInfoSet
, DeviceInfoData
);
7312 /* Install files from .CoInstallers section */
7313 lstrcatW(SectionName
, DotCoInstallers
);
7314 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7315 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7316 SPINST_FILES
, NULL
, NULL
, SP_COPY_NEWER
,
7317 InstallMsgHandler
, InstallMsgHandlerContext
,
7318 DeviceInfoSet
, DeviceInfoData
);
7322 /* Set the DI_NOFILECOPY flag to prevent another
7323 * installation during SetupDiInstallDevice */
7324 InstallParams
.Flags
|= DI_NOFILECOPY
;
7325 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7329 SetupTermDefaultQueueCallback(Context
);
7333 TRACE("Returning %d\n", ret
);
7337 /***********************************************************************
7338 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7341 SetupDiRegisterCoDeviceInstallers(
7342 IN HDEVINFO DeviceInfoSet
,
7343 IN PSP_DEVINFO_DATA DeviceInfoData
)
7345 BOOL ret
= FALSE
; /* Return value */
7347 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7350 SetLastError(ERROR_INVALID_PARAMETER
);
7351 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7352 SetLastError(ERROR_INVALID_HANDLE
);
7353 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7354 SetLastError(ERROR_INVALID_HANDLE
);
7355 else if (!DeviceInfoData
)
7356 SetLastError(ERROR_INVALID_PARAMETER
);
7357 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7358 SetLastError(ERROR_INVALID_USER_BUFFER
);
7361 SP_DEVINSTALL_PARAMS_W InstallParams
;
7362 struct DriverInfoElement
*SelectedDriver
;
7365 WCHAR SectionName
[MAX_PATH
];
7366 DWORD SectionNameLength
= 0;
7367 HKEY hKey
= INVALID_HANDLE_VALUE
;
7368 PVOID Context
= NULL
;
7370 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7371 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7375 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7376 if (SelectedDriver
== NULL
)
7378 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7382 /* Get .CoInstallers section name */
7383 Result
= SetupDiGetActualSectionToInstallW(
7384 SelectedDriver
->InfFileDetails
->hInf
,
7385 SelectedDriver
->Details
.SectionName
,
7386 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7387 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
7389 lstrcatW(SectionName
, DotCoInstallers
);
7391 /* Open/Create driver key information */
7392 #if _WIN32_WINNT >= 0x502
7393 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7395 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7397 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7398 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7399 if (hKey
== INVALID_HANDLE_VALUE
)
7402 /* Install .CoInstallers section */
7403 DoAction
= SPINST_REGISTRY
;
7404 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7406 DoAction
|= SPINST_FILES
;
7407 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7411 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7412 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7413 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7414 SetupDefaultQueueCallback
, Context
,
7415 DeviceInfoSet
, DeviceInfoData
);
7423 SetupTermDefaultQueueCallback(Context
);
7424 if (hKey
!= INVALID_HANDLE_VALUE
)
7428 TRACE("Returning %d\n", ret
);
7433 InstallOneInterface(
7434 IN LPGUID InterfaceGuid
,
7435 IN LPCWSTR ReferenceString
,
7436 IN LPCWSTR InterfaceSection
,
7437 IN UINT InterfaceFlags
)
7439 if (InterfaceFlags
!= 0)
7441 SetLastError(ERROR_INVALID_PARAMETER
);
7445 FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid
),
7446 debugstr_w(ReferenceString
), debugstr_w(InterfaceSection
), InterfaceFlags
);
7450 /***********************************************************************
7451 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7454 SetupDiInstallDeviceInterfaces(
7455 IN HDEVINFO DeviceInfoSet
,
7456 IN PSP_DEVINFO_DATA DeviceInfoData
)
7458 struct DeviceInfoSet
*list
= NULL
;
7461 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7464 SetLastError(ERROR_INVALID_PARAMETER
);
7465 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7466 SetLastError(ERROR_INVALID_HANDLE
);
7467 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7468 SetLastError(ERROR_INVALID_HANDLE
);
7469 else if (!DeviceInfoData
)
7470 SetLastError(ERROR_INVALID_PARAMETER
);
7471 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7472 SetLastError(ERROR_INVALID_USER_BUFFER
);
7475 struct DriverInfoElement
*SelectedDriver
;
7476 SP_DEVINSTALL_PARAMS_W InstallParams
;
7477 WCHAR SectionName
[MAX_PATH
];
7478 DWORD SectionNameLength
= 0;
7479 INFCONTEXT ContextInterface
;
7480 LPWSTR InterfaceGuidString
= NULL
;
7481 LPWSTR ReferenceString
= NULL
;
7482 LPWSTR InterfaceSection
= NULL
;
7487 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7488 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7492 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7493 if (SelectedDriver
== NULL
)
7495 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7500 /* Get .Interfaces section name */
7501 Result
= SetupDiGetActualSectionToInstallW(
7502 SelectedDriver
->InfFileDetails
->hInf
,
7503 SelectedDriver
->Details
.SectionName
,
7504 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7505 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotInterfaces
) - 1)
7507 strcatW(SectionName
, DotInterfaces
);
7510 Result
= SetupFindFirstLineW(
7511 SelectedDriver
->InfFileDetails
->hInf
,
7515 while (ret
&& Result
)
7517 ret
= GetStringField(&ContextInterface
, 1, &InterfaceGuidString
);
7520 else if (strlenW(InterfaceGuidString
) != MAX_GUID_STRING_LEN
- 1)
7522 SetLastError(ERROR_INVALID_PARAMETER
);
7527 InterfaceGuidString
[MAX_GUID_STRING_LEN
- 2] = '\0'; /* Replace the } by a NULL character */
7528 if (UuidFromStringW(&InterfaceGuidString
[1], &InterfaceGuid
) != RPC_S_OK
)
7530 /* Bad GUID, skip the entry */
7531 SetLastError(ERROR_INVALID_PARAMETER
);
7536 ret
= GetStringField(&ContextInterface
, 2, &ReferenceString
);
7540 ret
= GetStringField(&ContextInterface
, 3, &InterfaceSection
);
7544 ret
= SetupGetIntField(
7546 4, /* Field index */
7550 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7552 /* The field may be empty. Ignore the error */
7560 /* Install Interface */
7561 ret
= InstallOneInterface(&InterfaceGuid
, ReferenceString
, InterfaceSection
, InterfaceFlags
);
7564 MyFree(InterfaceGuidString
);
7565 MyFree(ReferenceString
);
7566 MyFree(InterfaceSection
);
7567 InterfaceGuidString
= ReferenceString
= InterfaceSection
= NULL
;
7568 Result
= SetupFindNextMatchLineW(&ContextInterface
, AddInterface
, &ContextInterface
);
7572 TRACE("Returning %d\n", ret
);
7577 InfIsFromOEMLocation(
7579 OUT LPBOOL IsOEMLocation
)
7583 last
= strrchrW(FullName
, '\\');
7586 /* No directory specified */
7587 *IsOEMLocation
= FALSE
;
7591 WCHAR Windir
[MAX_PATH
];
7594 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7595 if (ret
== 0 || ret
>= MAX_PATH
)
7597 SetLastError(ERROR_GEN_FAILURE
);
7601 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7603 /* The path is %WINDIR%\Inf */
7604 *IsOEMLocation
= FALSE
;
7608 /* The file is in another place */
7609 *IsOEMLocation
= TRUE
;
7615 /***********************************************************************
7616 * SetupDiInstallDevice (SETUPAPI.@)
7619 SetupDiInstallDevice(
7620 IN HDEVINFO DeviceInfoSet
,
7621 IN PSP_DEVINFO_DATA DeviceInfoData
)
7623 SP_DEVINSTALL_PARAMS_W InstallParams
;
7624 struct DriverInfoElement
*SelectedDriver
;
7625 SYSTEMTIME DriverDate
;
7626 WCHAR SectionName
[MAX_PATH
];
7628 DWORD SectionNameLength
= 0;
7629 BOOL Result
= FALSE
;
7632 LPWSTR pSectionName
= NULL
;
7633 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7635 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7636 BOOL RebootRequired
= FALSE
;
7637 HKEY hKey
= INVALID_HANDLE_VALUE
;
7638 BOOL NeedtoCopyFile
;
7639 LARGE_INTEGER fullVersion
;
7641 PVOID Context
= NULL
;
7642 BOOL ret
= FALSE
; /* Return value */
7644 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7647 SetLastError(ERROR_INVALID_PARAMETER
);
7648 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7649 SetLastError(ERROR_INVALID_HANDLE
);
7650 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7651 SetLastError(ERROR_INVALID_HANDLE
);
7652 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7653 SetLastError(ERROR_INVALID_USER_BUFFER
);
7659 /* One parameter is bad */
7663 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7664 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7668 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
7670 /* Set FAILEDINSTALL in ConfigFlags registry value */
7671 DWORD ConfigFlags
, regType
;
7672 Result
= SetupDiGetDeviceRegistryPropertyW(
7677 (PBYTE
)&ConfigFlags
,
7678 sizeof(ConfigFlags
),
7680 if (!Result
|| regType
!= REG_DWORD
)
7682 SetLastError(ERROR_GEN_FAILURE
);
7685 ConfigFlags
|= DNF_DISABLED
;
7686 Result
= SetupDiSetDeviceRegistryPropertyW(
7690 (PBYTE
)&ConfigFlags
,
7691 sizeof(ConfigFlags
));
7694 SetLastError(ERROR_GEN_FAILURE
);
7702 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7703 if (SelectedDriver
== NULL
)
7705 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7709 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
7711 Result
= SetupDiGetActualSectionToInstallW(
7712 SelectedDriver
->InfFileDetails
->hInf
,
7713 SelectedDriver
->Details
.SectionName
,
7714 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7715 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
7717 pSectionName
= &SectionName
[strlenW(SectionName
)];
7719 /* Get information from [Version] section */
7720 if (!SetupDiGetINFClassW(SelectedDriver
->Details
.InfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
7722 /* Format ClassGuid to a string */
7723 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
7725 RequiredSize
= lstrlenW(lpGuidString
);
7726 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
7727 if (!lpFullGuidString
)
7729 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7732 lpFullGuidString
[0] = '{';
7733 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
7734 lpFullGuidString
[RequiredSize
+ 1] = '}';
7735 lpFullGuidString
[RequiredSize
+ 2] = '\0';
7737 /* Open/Create driver key information */
7738 #if _WIN32_WINNT >= 0x502
7739 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7741 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7743 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7744 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7745 if (hKey
== INVALID_HANDLE_VALUE
)
7748 /* Install main section */
7750 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7751 DoAction
|= SPINST_REGISTRY
;
7752 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7754 DoAction
|= SPINST_FILES
;
7755 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7759 *pSectionName
= '\0';
7760 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7761 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7762 DoAction
, hKey
, NULL
, SP_COPY_NEWER
,
7763 SetupDefaultQueueCallback
, Context
,
7764 DeviceInfoSet
, DeviceInfoData
);
7767 InstallParams
.Flags
|= DI_NOFILECOPY
;
7768 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7770 /* Write information to driver key */
7771 *pSectionName
= UNICODE_NULL
;
7772 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
7773 TRACE("Write information to driver key\n");
7774 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7775 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
7776 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7777 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->Details
.InfFileName
));
7778 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
7779 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
7780 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
7781 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
7782 swprintf(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
7783 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
7784 if (rc
== ERROR_SUCCESS
)
7785 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
7786 if (rc
== ERROR_SUCCESS
)
7787 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7788 if (rc
== ERROR_SUCCESS
)
7790 swprintf(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
7791 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
7793 if (rc
== ERROR_SUCCESS
)
7794 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (strlenW(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
7795 if (rc
== ERROR_SUCCESS
)
7796 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7797 if (rc
== ERROR_SUCCESS
)
7798 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTIONEXT
, 0, REG_SZ
, (const BYTE
*)&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)], (strlenW(SectionName
) - strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
7799 if (rc
== ERROR_SUCCESS
)
7800 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
7801 if (rc
== ERROR_SUCCESS
)
7802 rc
= RegSetValueEx(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
7803 if (rc
!= ERROR_SUCCESS
)
7809 hKey
= INVALID_HANDLE_VALUE
;
7811 /* FIXME: Process .LogConfigOverride section */
7813 /* Install .Services section */
7814 strcpyW(pSectionName
, DotServices
);
7815 Result
= SetupInstallServicesFromInfSectionExW(
7816 SelectedDriver
->InfFileDetails
->hInf
,
7825 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
7826 RebootRequired
= TRUE
;
7828 /* Copy .inf file to Inf\ directory (if needed) */
7829 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
7834 Result
= SetupCopyOEMInfW(
7835 SelectedDriver
->InfFileDetails
->FullInfFileName
,
7838 SP_COPY_NOOVERWRITE
,
7844 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
7845 * to release use of current InfFile */
7848 /* Open device registry key */
7849 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
7850 if (hKey
== INVALID_HANDLE_VALUE
)
7853 /* Install .HW section */
7855 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
7856 DoAction
|= SPINST_REGISTRY
;
7857 strcpyW(pSectionName
, DotHW
);
7858 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7859 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7860 DoAction
, hKey
, NULL
, 0,
7862 DeviceInfoSet
, DeviceInfoData
);
7866 /* Write information to enum key */
7867 TRACE("Write information to enum key\n");
7868 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
7869 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
7870 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
7871 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
7872 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
7873 if (rc
== ERROR_SUCCESS
)
7874 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
7875 if (rc
== ERROR_SUCCESS
)
7876 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
7877 if (rc
== ERROR_SUCCESS
)
7878 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
7879 if (rc
!= ERROR_SUCCESS
)
7885 /* Start the device */
7886 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
7887 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7892 /* End of installation */
7893 if (hKey
!= INVALID_HANDLE_VALUE
)
7896 RpcStringFreeW(&lpGuidString
);
7897 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
7899 SetupTermDefaultQueueCallback(Context
);
7900 TRACE("Returning %d\n", ret
);