2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
5 * 2005-2006 Hervé Poussineau (hpoussin@reactos.org)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "setupapi_private.h"
24 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
26 /* Unicode constants */
27 static const WCHAR 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
;
89 struct GetSectionCallbackInfo
91 PSP_ALTPLATFORM_INFO PlatformInfo
;
94 WCHAR BestSection
[LINE_LEN
+ 1];
95 DWORD BestScore1
, BestScore2
, BestScore3
, BestScore4
, BestScore5
;
99 PropertyChangeHandler(
100 IN HDEVINFO DeviceInfoSet
,
101 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
102 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
103 IN DWORD ClassInstallParamsSize
);
105 static const UPDATE_CLASS_PARAM_HANDLER UpdateClassInstallParamHandlers
[] = {
106 NULL
, /* DIF_SELECTDEVICE */
107 NULL
, /* DIF_INSTALLDEVICE */
108 NULL
, /* DIF_ASSIGNRESOURCES */
109 NULL
, /* DIF_PROPERTIES */
110 NULL
, /* DIF_REMOVE */
111 NULL
, /* DIF_FIRSTTIMESETUP */
112 NULL
, /* DIF_FOUNDDEVICE */
113 NULL
, /* DIF_SELECTCLASSDRIVERS */
114 NULL
, /* DIF_VALIDATECLASSDRIVERS */
115 NULL
, /* DIF_INSTALLCLASSDRIVERS */
116 NULL
, /* DIF_CALCDISKSPACE */
117 NULL
, /* DIF_DESTROYPRIVATEDATA */
118 NULL
, /* DIF_VALIDATEDRIVER */
119 NULL
, /* DIF_MOVEDEVICE */
120 NULL
, /* DIF_DETECT */
121 NULL
, /* DIF_INSTALLWIZARD */
122 NULL
, /* DIF_DESTROYWIZARDDATA */
123 PropertyChangeHandler
, /* DIF_PROPERTYCHANGE */
124 NULL
, /* DIF_ENABLECLASS */
125 NULL
, /* DIF_DETECTVERIFY */
126 NULL
, /* DIF_INSTALLDEVICEFILES */
127 NULL
, /* DIF_UNREMOVE */
128 NULL
, /* DIF_SELECTBESTCOMPATDRV */
129 NULL
, /* DIF_ALLOW_INSTALL */
130 NULL
, /* DIF_REGISTERDEVICE */
131 NULL
, /* DIF_NEWDEVICEWIZARD_PRESELECT */
132 NULL
, /* DIF_NEWDEVICEWIZARD_SELECT */
133 NULL
, /* DIF_NEWDEVICEWIZARD_PREANALYZE */
134 NULL
, /* DIF_NEWDEVICEWIZARD_POSTANALYZE */
135 NULL
, /* DIF_NEWDEVICEWIZARD_FINISHINSTALL */
136 NULL
, /* DIF_UNUSED1 */
137 NULL
, /* DIF_INSTALLINTERFACES */
138 NULL
, /* DIF_DETECTCANCEL */
139 NULL
, /* DIF_REGISTER_COINSTALLERS */
140 NULL
, /* DIF_ADDPROPERTYPAGE_ADVANCED */
141 NULL
, /* DIF_ADDPROPERTYPAGE_BASIC */
142 NULL
, /* DIF_RESERVED1 */
143 NULL
, /* DIF_TROUBLESHOOTER */
144 NULL
, /* DIF_POWERMESSAGEWAKE */
145 NULL
, /* DIF_ADDREMOTEPROPERTYPAGE_ADVANCED */
146 NULL
, /* DIF_UPDATEDRIVER_UI */
147 NULL
/* DIF_RESERVED2 */
150 /***********************************************************************
151 * SetupDiBuildClassInfoList (SETUPAPI.@)
154 SetupDiBuildClassInfoList(
156 OUT LPGUID ClassGuidList OPTIONAL
,
157 IN DWORD ClassGuidListSize
,
158 OUT PDWORD RequiredSize
)
161 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
162 ClassGuidListSize
, RequiredSize
,
166 /***********************************************************************
167 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
170 SetupDiBuildClassInfoListExA(
172 OUT LPGUID ClassGuidList OPTIONAL
,
173 IN DWORD ClassGuidListSize
,
174 OUT PDWORD RequiredSize
,
175 IN PCSTR MachineName OPTIONAL
,
178 LPWSTR MachineNameW
= NULL
;
185 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
186 if (MachineNameW
== NULL
) return FALSE
;
189 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
190 ClassGuidListSize
, RequiredSize
,
191 MachineNameW
, Reserved
);
194 MyFree(MachineNameW
);
199 /***********************************************************************
200 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
203 SetupDiBuildClassInfoListExW(
205 OUT LPGUID ClassGuidList OPTIONAL
,
206 IN DWORD ClassGuidListSize
,
207 OUT PDWORD RequiredSize
,
208 IN PCWSTR MachineName OPTIONAL
,
211 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
212 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
213 HKEY hClassKey
= NULL
;
217 DWORD dwGuidListIndex
= 0;
220 TRACE("0x%lx %p %lu %p %s %p\n", Flags
, ClassGuidList
,
221 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
223 if (RequiredSize
!= NULL
)
226 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
227 KEY_ENUMERATE_SUB_KEYS
,
231 if (hClassesKey
== INVALID_HANDLE_VALUE
)
234 for (dwIndex
= 0; ; dwIndex
++)
236 dwLength
= MAX_GUID_STRING_LEN
+ 1;
237 lError
= RegEnumKeyExW(hClassesKey
,
245 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
246 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
248 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
250 if (hClassKey
!= NULL
)
251 RegCloseKey(hClassKey
);
252 if (RegOpenKeyExW(hClassesKey
,
256 &hClassKey
) != ERROR_SUCCESS
)
261 if (RegQueryValueExW(hClassKey
,
262 REGSTR_VAL_NOUSECLASS
,
266 NULL
) == ERROR_SUCCESS
)
268 TRACE("'NoUseClass' value found!\n");
272 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
273 (!RegQueryValueExW(hClassKey
,
274 REGSTR_VAL_NOINSTALLCLASS
,
280 TRACE("'NoInstallClass' value found!\n");
284 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
285 (!RegQueryValueExW(hClassKey
,
286 REGSTR_VAL_NODISPLAYCLASS
,
292 TRACE("'NoDisplayClass' value found!\n");
296 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
297 if (dwGuidListIndex
< ClassGuidListSize
)
299 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
301 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
303 UuidFromStringW(&szKeyName
[1],
304 &ClassGuidList
[dwGuidListIndex
]);
310 if (lError
!= ERROR_SUCCESS
)
314 if (RequiredSize
!= NULL
)
315 *RequiredSize
= dwGuidListIndex
;
317 if (ClassGuidListSize
< dwGuidListIndex
)
318 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
323 if (hClassesKey
!= INVALID_HANDLE_VALUE
)
324 RegCloseKey(hClassesKey
);
325 if (hClassKey
!= NULL
)
326 RegCloseKey(hClassKey
);
330 /***********************************************************************
331 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
334 SetupDiClassGuidsFromNameA(
336 OUT LPGUID ClassGuidList
,
337 IN DWORD ClassGuidListSize
,
338 OUT PDWORD RequiredSize
)
340 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
341 ClassGuidListSize
, RequiredSize
,
345 /***********************************************************************
346 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
348 BOOL WINAPI
SetupDiClassGuidsFromNameW(
350 OUT LPGUID ClassGuidList
,
351 IN DWORD ClassGuidListSize
,
352 OUT PDWORD RequiredSize
)
354 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
355 ClassGuidListSize
, RequiredSize
,
359 /***********************************************************************
360 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
363 SetupDiClassGuidsFromNameExA(
365 OUT LPGUID ClassGuidList
,
366 IN DWORD ClassGuidListSize
,
367 OUT PDWORD RequiredSize
,
368 IN PCSTR MachineName OPTIONAL
,
371 LPWSTR ClassNameW
= NULL
;
372 LPWSTR MachineNameW
= NULL
;
377 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
378 if (ClassNameW
== NULL
)
383 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
384 if (MachineNameW
== NULL
)
391 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
392 ClassGuidListSize
, RequiredSize
,
393 MachineNameW
, Reserved
);
396 MyFree(MachineNameW
);
403 /***********************************************************************
404 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
407 SetupDiClassGuidsFromNameExW(
409 OUT LPGUID ClassGuidList
,
410 IN DWORD ClassGuidListSize
,
411 OUT PDWORD RequiredSize
,
412 IN PCWSTR MachineName OPTIONAL
,
415 WCHAR szKeyName
[MAX_GUID_STRING_LEN
+ 1];
416 WCHAR szClassName
[256];
417 HKEY hClassesKey
= INVALID_HANDLE_VALUE
;
418 HKEY hClassKey
= NULL
;
422 DWORD dwGuidListIndex
= 0;
425 TRACE("%s %p %lu %p %s %p\n", debugstr_w(ClassName
), ClassGuidList
,
426 ClassGuidListSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
428 if (RequiredSize
!= NULL
)
431 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
432 KEY_ENUMERATE_SUB_KEYS
,
436 if (hClassesKey
== INVALID_HANDLE_VALUE
)
439 for (dwIndex
= 0; ; dwIndex
++)
441 dwLength
= MAX_GUID_STRING_LEN
+ 1;
442 lError
= RegEnumKeyExW(hClassesKey
,
450 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
451 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
453 TRACE("Key name: %s\n", debugstr_w(szKeyName
));
455 if (hClassKey
!= NULL
)
456 RegCloseKey(hClassKey
);
457 if (RegOpenKeyExW(hClassesKey
,
461 &hClassKey
) != ERROR_SUCCESS
)
466 dwLength
= 256 * sizeof(WCHAR
);
467 if (RegQueryValueExW(hClassKey
,
472 &dwLength
) == ERROR_SUCCESS
)
474 TRACE("Class name: %s\n", debugstr_w(szClassName
));
476 if (strcmpiW(szClassName
, ClassName
) == 0)
478 TRACE("Found matching class name\n");
480 TRACE("Guid: %s\n", debugstr_w(szKeyName
));
481 if (dwGuidListIndex
< ClassGuidListSize
)
483 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
485 TRACE("Guid: %s\n", debugstr_w(&szKeyName
[1]));
487 UuidFromStringW(&szKeyName
[1],
488 &ClassGuidList
[dwGuidListIndex
]);
496 if (lError
!= ERROR_SUCCESS
)
500 if (RequiredSize
!= NULL
)
501 *RequiredSize
= dwGuidListIndex
;
503 if (ClassGuidListSize
< dwGuidListIndex
)
504 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
509 if (hClassesKey
!= INVALID_HANDLE_VALUE
)
510 RegCloseKey(hClassesKey
);
511 if (hClassKey
!= NULL
)
512 RegCloseKey(hClassKey
);
516 /***********************************************************************
517 * SetupDiClassNameFromGuidA (SETUPAPI.@)
520 SetupDiClassNameFromGuidA(
521 IN CONST GUID
* ClassGuid
,
523 IN DWORD ClassNameSize
,
524 OUT PDWORD RequiredSize OPTIONAL
)
526 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
527 ClassNameSize
, RequiredSize
,
531 /***********************************************************************
532 * SetupDiClassNameFromGuidW (SETUPAPI.@)
535 SetupDiClassNameFromGuidW(
536 IN CONST GUID
* ClassGuid
,
538 IN DWORD ClassNameSize
,
539 OUT PDWORD RequiredSize OPTIONAL
)
541 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
542 ClassNameSize
, RequiredSize
,
546 /***********************************************************************
547 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
550 SetupDiClassNameFromGuidExA(
551 IN CONST GUID
* ClassGuid
,
553 IN DWORD ClassNameSize
,
554 OUT PDWORD RequiredSize OPTIONAL
,
555 IN PCSTR MachineName OPTIONAL
,
558 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
559 LPWSTR MachineNameW
= NULL
;
563 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
564 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
565 NULL
, MachineNameW
, Reserved
);
568 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
569 ClassNameSize
, NULL
, NULL
);
571 if (!ClassNameSize
&& RequiredSize
)
574 MyFree(MachineNameW
);
578 /***********************************************************************
579 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
582 SetupDiClassNameFromGuidExW(
583 IN CONST GUID
* ClassGuid
,
585 IN DWORD ClassNameSize
,
586 OUT PDWORD RequiredSize OPTIONAL
,
587 IN PCWSTR MachineName OPTIONAL
,
595 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassName
,
596 ClassNameSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
598 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
603 if (hKey
== INVALID_HANDLE_VALUE
)
606 if (RequiredSize
!= NULL
)
609 rc
= RegQueryValueExW(hKey
,
615 if (rc
!= ERROR_SUCCESS
)
621 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
624 dwLength
= ClassNameSize
* sizeof(WCHAR
);
625 rc
= RegQueryValueExW(hKey
,
631 if (rc
!= ERROR_SUCCESS
)
640 if (hKey
!= INVALID_HANDLE_VALUE
)
645 /***********************************************************************
646 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
649 SetupDiCreateDeviceInfoList(
650 IN CONST GUID
*ClassGuid OPTIONAL
,
651 IN HWND hwndParent OPTIONAL
)
653 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
656 /***********************************************************************
657 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
660 SetupDiCreateDeviceInfoListExA(
661 IN CONST GUID
*ClassGuid OPTIONAL
,
662 IN HWND hwndParent OPTIONAL
,
663 IN PCSTR MachineName OPTIONAL
,
666 LPWSTR MachineNameW
= NULL
;
669 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
670 debugstr_a(MachineName
), Reserved
);
674 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
675 if (MachineNameW
== NULL
)
676 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
679 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
680 MachineNameW
, Reserved
);
683 MyFree(MachineNameW
);
689 GetErrorCodeFromCrCode(const IN CONFIGRET cr
)
693 case CR_ACCESS_DENIED
: return ERROR_ACCESS_DENIED
;
694 case CR_BUFFER_SMALL
: return ERROR_INSUFFICIENT_BUFFER
;
695 case CR_CALL_NOT_IMPLEMENTED
: return ERROR_CALL_NOT_IMPLEMENTED
;
696 case CR_FAILURE
: return ERROR_GEN_FAILURE
;
697 case CR_INVALID_DATA
: return ERROR_INVALID_USER_BUFFER
;
698 case CR_INVALID_DEVICE_ID
: return ERROR_INVALID_PARAMETER
;
699 case CR_INVALID_MACHINENAME
: return ERROR_INVALID_COMPUTERNAME
;
700 case CR_INVALID_DEVNODE
: return ERROR_INVALID_PARAMETER
;
701 case CR_INVALID_FLAG
: return ERROR_INVALID_FLAGS
;
702 case CR_INVALID_POINTER
: return ERROR_INVALID_PARAMETER
;
703 case CR_INVALID_PROPERTY
: return ERROR_INVALID_PARAMETER
;
704 case CR_NO_SUCH_DEVNODE
: return ERROR_FILE_NOT_FOUND
;
705 case CR_NO_SUCH_REGISTRY_KEY
: return ERROR_FILE_NOT_FOUND
;
706 case CR_NO_SUCH_VALUE
: return ERROR_FILE_NOT_FOUND
;
707 case CR_OUT_OF_MEMORY
: return ERROR_NOT_ENOUGH_MEMORY
;
708 case CR_REGISTRY_ERROR
: return ERROR_GEN_FAILURE
;
709 case CR_SUCCESS
: return ERROR_SUCCESS
;
710 default: return ERROR_GEN_FAILURE
;
713 /* Does not happen */
716 /***********************************************************************
717 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
720 SetupDiCreateDeviceInfoListExW(
721 IN CONST GUID
*ClassGuid OPTIONAL
,
722 IN HWND hwndParent OPTIONAL
,
723 IN PCWSTR MachineName OPTIONAL
,
726 struct DeviceInfoSet
*list
;
727 LPWSTR UNCServerName
= NULL
;
731 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;;
733 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid
), hwndParent
,
734 debugstr_w(MachineName
), Reserved
);
736 size
= FIELD_OFFSET(struct DeviceInfoSet
, szData
);
738 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
739 list
= HeapAlloc(GetProcessHeap(), 0, size
);
742 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
745 memset(list
, 0, sizeof(struct DeviceInfoSet
));
747 list
->magic
= SETUP_DEV_INFO_SET_MAGIC
;
750 ClassGuid
? ClassGuid
: &GUID_NULL
,
751 sizeof(list
->ClassGuid
));
752 list
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
753 list
->InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
754 list
->InstallParams
.hwndParent
= hwndParent
;
757 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &list
->HKLM
);
758 if (rc
!= ERROR_SUCCESS
)
763 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MachineName
) + 3) * sizeof(WCHAR
));
766 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
770 strcpyW(UNCServerName
+ 2, MachineName
);
771 list
->szData
[0] = list
->szData
[1] = '\\';
772 strcpyW(list
->szData
+ 2, MachineName
);
773 list
->MachineName
= list
->szData
;
777 DWORD Size
= MAX_PATH
;
778 list
->HKLM
= HKEY_LOCAL_MACHINE
;
779 UNCServerName
= HeapAlloc(GetProcessHeap(), 0, (MAX_PATH
+ 2) * sizeof(WCHAR
));
782 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
785 if (!GetComputerNameW(UNCServerName
+ 2, &Size
))
787 list
->MachineName
= NULL
;
790 UNCServerName
[0] = UNCServerName
[1] = '\\';
791 cr
= CM_Connect_MachineW(UNCServerName
, &list
->hMachine
);
792 if (cr
!= CR_SUCCESS
)
794 SetLastError(GetErrorCodeFromCrCode(cr
));
798 InitializeListHead(&list
->DriverListHead
);
799 InitializeListHead(&list
->ListHead
);
801 ret
= (HDEVINFO
)list
;
804 if (ret
== INVALID_HANDLE_VALUE
)
808 if (list
->HKLM
!= NULL
&& list
->HKLM
!= HKEY_LOCAL_MACHINE
)
809 RegCloseKey(list
->HKLM
);
811 HeapFree(GetProcessHeap(), 0, list
);
814 HeapFree(GetProcessHeap(), 0, UNCServerName
);
818 /***********************************************************************
819 * SetupDiEnumDeviceInfo (SETUPAPI.@)
822 SetupDiEnumDeviceInfo(
823 IN HDEVINFO DeviceInfoSet
,
824 IN DWORD MemberIndex
,
825 OUT PSP_DEVINFO_DATA DeviceInfoData
)
829 TRACE("%p, 0x%08lx, %p\n", DeviceInfoSet
, MemberIndex
, DeviceInfoData
);
831 SetLastError(ERROR_INVALID_PARAMETER
);
832 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
834 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
836 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
837 SetLastError(ERROR_INVALID_HANDLE
);
838 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
839 SetLastError(ERROR_INVALID_USER_BUFFER
);
842 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
843 while (ItemList
!= &list
->ListHead
&& MemberIndex
-- > 0)
844 ItemList
= ItemList
->Flink
;
845 if (ItemList
== &list
->ListHead
)
846 SetLastError(ERROR_NO_MORE_ITEMS
);
849 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
850 memcpy(&DeviceInfoData
->ClassGuid
,
853 DeviceInfoData
->DevInst
= DevInfo
->dnDevInst
;
854 DeviceInfoData
->Reserved
= (ULONG_PTR
)DevInfo
;
860 SetLastError(ERROR_INVALID_HANDLE
);
864 /***********************************************************************
865 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
868 SetupDiGetActualSectionToInstallA(
870 IN PCSTR InfSectionName
,
871 OUT PSTR InfSectionWithExt OPTIONAL
,
872 IN DWORD InfSectionWithExtSize
,
873 OUT PDWORD RequiredSize OPTIONAL
,
874 OUT PSTR
*Extension OPTIONAL
)
876 return SetupDiGetActualSectionToInstallExA(InfHandle
, InfSectionName
,
877 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
881 /***********************************************************************
882 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
885 SetupDiGetActualSectionToInstallW(
887 IN PCWSTR InfSectionName
,
888 OUT PWSTR InfSectionWithExt OPTIONAL
,
889 IN DWORD InfSectionWithExtSize
,
890 OUT PDWORD RequiredSize OPTIONAL
,
891 OUT PWSTR
*Extension OPTIONAL
)
893 return SetupDiGetActualSectionToInstallExW(InfHandle
, InfSectionName
,
894 NULL
, InfSectionWithExt
, InfSectionWithExtSize
, RequiredSize
,
898 /***********************************************************************
899 * SetupDiGetActualSectionToInstallExA (SETUPAPI.@)
902 SetupDiGetActualSectionToInstallExA(
904 IN PCSTR InfSectionName
,
905 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
906 OUT PSTR InfSectionWithExt OPTIONAL
,
907 IN DWORD InfSectionWithExtSize
,
908 OUT PDWORD RequiredSize OPTIONAL
,
909 OUT PSTR
* Extension OPTIONAL
,
912 LPWSTR InfSectionNameW
= NULL
;
913 LPWSTR InfSectionWithExtW
= NULL
;
915 BOOL bResult
= FALSE
;
921 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
922 if (InfSectionNameW
== NULL
)
925 if (InfSectionWithExt
)
927 InfSectionWithExtW
= MyMalloc(InfSectionWithExtSize
* sizeof(WCHAR
));
928 if (InfSectionWithExtW
== NULL
)
932 bResult
= SetupDiGetActualSectionToInstallExW(
933 InfHandle
, InfSectionNameW
, AlternatePlatformInfo
,
934 InfSectionWithExt
? InfSectionWithExtW
: NULL
,
935 InfSectionWithExtSize
,
937 Extension
? &ExtensionW
: NULL
,
940 if (bResult
&& InfSectionWithExt
)
942 bResult
= WideCharToMultiByte(CP_ACP
, 0, InfSectionWithExtW
, -1, InfSectionWithExt
,
943 InfSectionWithExtSize
, NULL
, NULL
) != 0;
945 if (bResult
&& Extension
)
947 if (ExtensionW
== NULL
)
950 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
954 MyFree(InfSectionNameW
);
955 MyFree(InfSectionWithExtW
);
960 /* Lower scores are best ones */
963 IN LPCWSTR SectionName
,
964 IN PSP_ALTPLATFORM_INFO PlatformInfo
,
967 OUT PDWORD ScorePlatform
,
968 OUT PDWORD ScoreMajorVersion
,
969 OUT PDWORD ScoreMinorVersion
,
970 OUT PDWORD ScoreProductType
,
971 OUT PDWORD ScoreSuiteMask
)
973 LPWSTR Section
= NULL
;
974 LPCWSTR pExtensionPlatform
, pExtensionArchitecture
;
979 TRACE("%s %p 0x%x 0x%x\n",
980 debugstr_w(SectionName
), PlatformInfo
, ProductType
, SuiteMask
);
982 static const WCHAR ExtensionPlatformNone
[] = {'.',0};
983 static const WCHAR ExtensionPlatformNT
[] = {'.','N','T',0};
984 static const WCHAR ExtensionPlatformWindows
[] = {'.','W','i','n',0};
986 static const WCHAR ExtensionArchitectureNone
[] = {0};
987 static const WCHAR ExtensionArchitecturealpha
[] = {'a','l','p','h','a',0};
988 static const WCHAR ExtensionArchitectureamd64
[] = {'a','m','d','6','4',0};
989 static const WCHAR ExtensionArchitectureia64
[] = {'i','a','6','4',0};
990 static const WCHAR ExtensionArchitecturemips
[] = {'m','i','p','s',0};
991 static const WCHAR ExtensionArchitectureppc
[] = {'p','p','c',0};
992 static const WCHAR ExtensionArchitecturex86
[] = {'x','8','6',0};
994 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= 0;
996 Section
= DuplicateString(SectionName
);
999 TRACE("DuplicateString() failed\n");
1003 /* Set various extensions values */
1004 switch (PlatformInfo
->Platform
)
1006 case VER_PLATFORM_WIN32_WINDOWS
:
1007 pExtensionPlatform
= ExtensionPlatformWindows
;
1009 case VER_PLATFORM_WIN32_NT
:
1010 pExtensionPlatform
= ExtensionPlatformNT
;
1013 ERR("Unkown platform 0x%lx\n", PlatformInfo
->Platform
);
1014 pExtensionPlatform
= ExtensionPlatformNone
;
1017 switch (PlatformInfo
->ProcessorArchitecture
)
1019 case PROCESSOR_ARCHITECTURE_ALPHA
:
1020 pExtensionArchitecture
= ExtensionArchitecturealpha
;
1022 case PROCESSOR_ARCHITECTURE_AMD64
:
1023 pExtensionArchitecture
= ExtensionArchitectureamd64
;
1025 case PROCESSOR_ARCHITECTURE_IA64
:
1026 pExtensionArchitecture
= ExtensionArchitectureia64
;
1028 case PROCESSOR_ARCHITECTURE_INTEL
:
1029 pExtensionArchitecture
= ExtensionArchitecturex86
;
1031 case PROCESSOR_ARCHITECTURE_MIPS
:
1032 pExtensionArchitecture
= ExtensionArchitecturemips
;
1034 case PROCESSOR_ARCHITECTURE_PPC
:
1035 pExtensionArchitecture
= ExtensionArchitectureppc
;
1038 ERR("Unknown processor architecture 0x%x\n", PlatformInfo
->ProcessorArchitecture
);
1039 case PROCESSOR_ARCHITECTURE_UNKNOWN
:
1040 pExtensionArchitecture
= ExtensionArchitectureNone
;
1046 * Field[1] Architecture
1047 * Field[2] Major version
1048 * Field[3] Minor version
1049 * Field[4] Product type
1050 * Field[5] Suite mask
1051 * Remark: lastests fields may be NULL if the information is not provided
1053 Fields
[0] = strchrW(Section
, '.');
1054 if (Fields
[0] == NULL
)
1056 TRACE("No extension found\n");
1057 *ScorePlatform
= *ScoreMajorVersion
= *ScoreMinorVersion
= *ScoreProductType
= *ScoreSuiteMask
= ULONG_MAX
;
1061 Fields
[1] = Fields
[0] + 1;
1062 Fields
[2] = Fields
[3] = Fields
[4] = Fields
[5] = NULL
;
1063 for (i
= 2; Fields
[i
- 1] != NULL
&& i
< 6; i
++)
1065 Fields
[i
] = wcschr(Fields
[i
- 1], '.');
1069 *(Fields
[i
] - 1) = L
'\0';
1072 /* Take care of first 2 fields */
1073 if (strncmpiW(Fields
[0], ExtensionPlatformWindows
, strlenW(ExtensionPlatformWindows
)) == 0)
1075 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_WINDOWS
)
1077 TRACE("Mismatch on platform field\n");
1080 Fields
[1] += wcslen(ExtensionPlatformWindows
) - 1;
1082 else if (strncmpiW(Fields
[0], ExtensionPlatformNT
, strlenW(ExtensionPlatformNT
)) == 0)
1084 if (PlatformInfo
->Platform
!= VER_PLATFORM_WIN32_NT
)
1086 TRACE("Mismatch on platform field\n");
1089 Fields
[1] += wcslen(ExtensionPlatformNT
) - 1;
1093 /* No platform specified */
1094 *ScorePlatform
|= 0x02;
1096 if (strcmpiW(Fields
[1], ExtensionArchitectureNone
) == 0)
1098 /* No architecture specified */
1099 *ScorePlatform
|= 0x01;
1101 else if (strcmpiW(Fields
[1], pExtensionArchitecture
) != 0)
1103 TRACE("Mismatch on architecture field ('%s' and '%s')\n",
1104 debugstr_w(Fields
[1]), debugstr_w(pExtensionArchitecture
));
1108 /* Check if informations are matching */
1109 if (Fields
[2] && *Fields
[2])
1111 DWORD MajorVersion
, MinorVersion
= 0;
1112 MajorVersion
= strtoulW(Fields
[2], NULL
, 0);
1113 if ((MajorVersion
== 0 || MajorVersion
== ULONG_MAX
) &&
1114 (errno
== ERANGE
|| errno
== EINVAL
))
1116 TRACE("Wrong MajorVersion ('%s')\n", debugstr_w(Fields
[2]));
1119 if (Fields
[3] && *Fields
[3])
1121 MinorVersion
= strtoulW(Fields
[3], NULL
, 0);
1122 if ((MinorVersion
== 0 || MinorVersion
== ULONG_MAX
) &&
1123 (errno
== ERANGE
|| errno
== EINVAL
))
1125 TRACE("Wrong MinorVersion ('%s')\n", debugstr_w(Fields
[3]));
1129 if (PlatformInfo
->MajorVersion
< MajorVersion
||
1130 (PlatformInfo
->MajorVersion
== MajorVersion
&& PlatformInfo
->MinorVersion
< MinorVersion
))
1132 TRACE("Mismatch on version field (%lu.%lu and %lu.%lu)\n",
1133 MajorVersion
, MinorVersion
, PlatformInfo
->MajorVersion
, PlatformInfo
->MinorVersion
);
1136 *ScoreMajorVersion
= MajorVersion
- PlatformInfo
->MajorVersion
;
1137 if (MajorVersion
== PlatformInfo
->MajorVersion
)
1138 *ScoreMinorVersion
= MinorVersion
- PlatformInfo
->MinorVersion
;
1140 *ScoreMinorVersion
= MinorVersion
;
1142 else if (Fields
[3] && *Fields
[3])
1144 TRACE("Minor version found without major version\n");
1149 *ScoreMajorVersion
= PlatformInfo
->MajorVersion
;
1150 *ScoreMinorVersion
= PlatformInfo
->MinorVersion
;
1153 if (Fields
[4] && *Fields
[4])
1155 DWORD CurrentProductType
;
1156 CurrentProductType
= strtoulW(Fields
[4], NULL
, 0);
1157 if ((CurrentProductType
== 0 || CurrentProductType
== ULONG_MAX
) &&
1158 (errno
== ERANGE
|| errno
== EINVAL
))
1160 TRACE("Wrong Product type ('%s')\n", debugstr_w(Fields
[4]));
1163 if (CurrentProductType
!= ProductType
)
1165 TRACE("Mismatch on product type (0x%08lx and 0x%08x)\n",
1166 CurrentProductType
, ProductType
);
1171 *ScoreProductType
= 1;
1173 if (Fields
[5] && *Fields
[5])
1175 DWORD CurrentSuiteMask
;
1176 CurrentSuiteMask
= strtoulW(Fields
[5], NULL
, 0);
1177 if ((CurrentSuiteMask
== 0 || CurrentSuiteMask
== ULONG_MAX
) &&
1178 (errno
== ERANGE
|| errno
== EINVAL
))
1180 TRACE("Wrong Suite mask ('%s')\n", debugstr_w(Fields
[5]));
1183 if ((CurrentSuiteMask
& ~SuiteMask
) != 0)
1185 TRACE("Mismatch on suite mask (0x%08lx and 0x%08x)\n",
1186 CurrentSuiteMask
, SuiteMask
);
1189 *ScoreSuiteMask
= SuiteMask
& ~CurrentSuiteMask
;
1192 *ScoreSuiteMask
= SuiteMask
;
1203 IN LPCWSTR SectionName
,
1206 struct GetSectionCallbackInfo
*info
= Context
;
1207 DWORD Score1
, Score2
, Score3
, Score4
, Score5
;
1210 ret
= CheckSectionValid(
1215 &Score1
, &Score2
, &Score3
, &Score4
, &Score5
);
1218 TRACE("Section %s not compatible\n", debugstr_w(SectionName
));
1221 if (Score1
> info
->BestScore1
) goto done
;
1222 if (Score1
< info
->BestScore1
) goto bettersection
;
1223 if (Score2
> info
->BestScore2
) goto done
;
1224 if (Score2
< info
->BestScore2
) goto bettersection
;
1225 if (Score3
> info
->BestScore3
) goto done
;
1226 if (Score3
< info
->BestScore3
) goto bettersection
;
1227 if (Score4
> info
->BestScore4
) goto done
;
1228 if (Score4
< info
->BestScore4
) goto bettersection
;
1229 if (Score5
> info
->BestScore5
) goto done
;
1230 if (Score5
< info
->BestScore5
) goto bettersection
;
1234 strcpyW(info
->BestSection
, SectionName
);
1235 info
->BestScore1
= Score1
;
1236 info
->BestScore2
= Score2
;
1237 info
->BestScore3
= Score3
;
1238 info
->BestScore4
= Score4
;
1239 info
->BestScore5
= Score5
;
1245 /***********************************************************************
1246 * SetupDiGetActualSectionToInstallExW (SETUPAPI.@)
1249 SetupDiGetActualSectionToInstallExW(
1251 IN PCWSTR InfSectionName
,
1252 IN PSP_ALTPLATFORM_INFO AlternatePlatformInfo OPTIONAL
,
1253 OUT PWSTR InfSectionWithExt OPTIONAL
,
1254 IN DWORD InfSectionWithExtSize
,
1255 OUT PDWORD RequiredSize OPTIONAL
,
1256 OUT PWSTR
* Extension OPTIONAL
,
1261 TRACE("%p %s %p %p %lu %p %p %p\n", InfHandle
, debugstr_w(InfSectionName
),
1262 AlternatePlatformInfo
, InfSectionWithExt
, InfSectionWithExtSize
,
1263 RequiredSize
, Extension
, Reserved
);
1265 if (!InfHandle
|| InfHandle
== (HINF
)INVALID_HANDLE_VALUE
)
1266 SetLastError(ERROR_INVALID_HANDLE
);
1267 else if (!InfSectionName
)
1268 SetLastError(ERROR_INVALID_PARAMETER
);
1269 else if (AlternatePlatformInfo
&& AlternatePlatformInfo
->cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
1270 SetLastError(ERROR_INVALID_USER_BUFFER
);
1271 else if (Reserved
!= NULL
)
1272 SetLastError(ERROR_INVALID_PARAMETER
);
1275 static SP_ALTPLATFORM_INFO CurrentPlatform
= { 0, };
1276 static BYTE CurrentProductType
= 0;
1277 static WORD CurrentSuiteMask
= 0;
1278 PSP_ALTPLATFORM_INFO pPlatformInfo
= &CurrentPlatform
;
1279 struct GetSectionCallbackInfo CallbackInfo
;
1284 /* Fill platform info if needed */
1285 if (AlternatePlatformInfo
)
1287 pPlatformInfo
= AlternatePlatformInfo
;
1293 if (CurrentPlatform
.cbSize
!= sizeof(SP_ALTPLATFORM_INFO
))
1295 /* That's the first time we go here. We need to fill in the structure */
1296 OSVERSIONINFOEX VersionInfo
;
1297 SYSTEM_INFO SystemInfo
;
1298 VersionInfo
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOEX
);
1299 ret
= GetVersionEx((POSVERSIONINFO
)&VersionInfo
);
1302 GetSystemInfo(&SystemInfo
);
1303 CurrentPlatform
.cbSize
= sizeof(SP_ALTPLATFORM_INFO
);
1304 CurrentPlatform
.Platform
= VersionInfo
.dwPlatformId
;
1305 CurrentPlatform
.MajorVersion
= VersionInfo
.dwMajorVersion
;
1306 CurrentPlatform
.MinorVersion
= VersionInfo
.dwMinorVersion
;
1307 CurrentPlatform
.ProcessorArchitecture
= SystemInfo
.wProcessorArchitecture
;
1308 CurrentPlatform
.Reserved
= 0;
1309 CurrentProductType
= VersionInfo
.wProductType
;
1310 CurrentSuiteMask
= VersionInfo
.wSuiteMask
;
1312 ProductType
= CurrentProductType
;
1313 SuiteMask
= CurrentSuiteMask
;
1316 CallbackInfo
.PlatformInfo
= pPlatformInfo
;
1317 CallbackInfo
.ProductType
= ProductType
;
1318 CallbackInfo
.SuiteMask
= SuiteMask
;
1319 CallbackInfo
.BestScore1
= ULONG_MAX
;
1320 CallbackInfo
.BestScore2
= ULONG_MAX
;
1321 CallbackInfo
.BestScore3
= ULONG_MAX
;
1322 CallbackInfo
.BestScore4
= ULONG_MAX
;
1323 CallbackInfo
.BestScore5
= ULONG_MAX
;
1324 strcpyW(CallbackInfo
.BestSection
, InfSectionName
);
1325 if (!EnumerateSectionsStartingWith(
1331 SetLastError(ERROR_GEN_FAILURE
);
1335 dwFullLength
= lstrlenW(CallbackInfo
.BestSection
);
1336 if (RequiredSize
!= NULL
)
1337 *RequiredSize
= dwFullLength
+ 1;
1339 if (InfSectionWithExtSize
> 0)
1341 if (InfSectionWithExtSize
< dwFullLength
+ 1)
1343 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1346 strcpyW(InfSectionWithExt
, CallbackInfo
.BestSection
);
1349 DWORD dwLength
= lstrlenW(InfSectionName
);
1350 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
1358 TRACE("Returning %d\n", ret
);
1363 /***********************************************************************
1364 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1367 SetupDiGetClassDescriptionA(
1368 IN CONST GUID
*ClassGuid
,
1369 OUT PSTR ClassDescription
,
1370 IN DWORD ClassDescriptionSize
,
1371 OUT PDWORD RequiredSize OPTIONAL
)
1373 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
1374 ClassDescriptionSize
,
1375 RequiredSize
, NULL
, NULL
);
1378 /***********************************************************************
1379 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1382 SetupDiGetClassDescriptionW(
1383 IN CONST GUID
*ClassGuid
,
1384 OUT PWSTR ClassDescription
,
1385 IN DWORD ClassDescriptionSize
,
1386 OUT PDWORD RequiredSize OPTIONAL
)
1388 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
1389 ClassDescriptionSize
,
1390 RequiredSize
, NULL
, NULL
);
1393 /***********************************************************************
1394 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1397 SetupDiGetClassDescriptionExA(
1398 IN CONST GUID
*ClassGuid
,
1399 OUT PSTR ClassDescription
,
1400 IN DWORD ClassDescriptionSize
,
1401 OUT PDWORD RequiredSize OPTIONAL
,
1402 IN PCSTR MachineName OPTIONAL
,
1405 PWCHAR ClassDescriptionW
;
1406 LPWSTR MachineNameW
= NULL
;
1410 if (ClassDescriptionSize
> 0)
1412 ClassDescriptionW
= HeapAlloc(GetProcessHeap(), 0, ClassDescriptionSize
* sizeof(WCHAR
));
1413 if (!ClassDescriptionW
)
1415 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1421 ClassDescriptionW
= NULL
;
1425 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1428 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1434 ret
= SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescriptionW
, ClassDescriptionSize
* sizeof(WCHAR
),
1435 NULL
, MachineNameW
, Reserved
);
1438 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassDescriptionW
, -1, ClassDescription
,
1439 ClassDescriptionSize
, NULL
, NULL
);
1441 if (!ClassDescriptionSize
&& RequiredSize
)
1442 *RequiredSize
= len
;
1446 HeapFree(GetProcessHeap(), 0, ClassDescriptionW
);
1447 MyFree(MachineNameW
);
1451 /***********************************************************************
1452 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1455 SetupDiGetClassDescriptionExW(
1456 IN CONST GUID
*ClassGuid
,
1457 OUT PWSTR ClassDescription
,
1458 IN DWORD ClassDescriptionSize
,
1459 OUT PDWORD RequiredSize OPTIONAL
,
1460 IN PCWSTR MachineName OPTIONAL
,
1463 HKEY hKey
= INVALID_HANDLE_VALUE
;
1467 TRACE("%s %p %lu %p %s %p\n", debugstr_guid(ClassGuid
), ClassDescription
,
1468 ClassDescriptionSize
, RequiredSize
, debugstr_w(MachineName
), Reserved
);
1470 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
1475 if (hKey
== INVALID_HANDLE_VALUE
)
1477 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
1481 if (RequiredSize
!= NULL
)
1484 if (RegQueryValueExW(hKey
,
1489 &dwLength
) != ERROR_SUCCESS
)
1494 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
1497 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
1498 if (RegQueryValueExW(hKey
,
1502 (LPBYTE
)ClassDescription
,
1503 &dwLength
) != ERROR_SUCCESS
)
1511 if (hKey
!= INVALID_HANDLE_VALUE
)
1517 /***********************************************************************
1518 * SetupDiGetClassDevsA (SETUPAPI.@)
1521 SetupDiGetClassDevsA(
1522 IN CONST GUID
*ClassGuid OPTIONAL
,
1523 IN PCSTR Enumerator OPTIONAL
,
1524 IN HWND hwndParent OPTIONAL
,
1527 return SetupDiGetClassDevsExA(ClassGuid
, Enumerator
, hwndParent
,
1528 Flags
, NULL
, NULL
, NULL
);
1531 /***********************************************************************
1532 * SetupDiGetClassDevsW (SETUPAPI.@)
1535 SetupDiGetClassDevsW(
1536 IN CONST GUID
*ClassGuid OPTIONAL
,
1537 IN PCWSTR Enumerator OPTIONAL
,
1538 IN HWND hwndParent OPTIONAL
,
1541 return SetupDiGetClassDevsExW(ClassGuid
, Enumerator
, hwndParent
,
1542 Flags
, NULL
, NULL
, NULL
);
1545 /***********************************************************************
1546 * SetupDiGetClassDevsExA (SETUPAPI.@)
1549 SetupDiGetClassDevsExA(
1550 IN CONST GUID
*ClassGuid OPTIONAL
,
1551 IN PCSTR Enumerator OPTIONAL
,
1552 IN HWND hwndParent OPTIONAL
,
1554 IN HDEVINFO DeviceInfoSet OPTIONAL
,
1555 IN PCSTR MachineName OPTIONAL
,
1559 LPWSTR enumstrW
= NULL
;
1560 LPWSTR machineW
= NULL
;
1564 int len
= MultiByteToWideChar(CP_ACP
, 0, Enumerator
, -1, NULL
, 0);
1565 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1568 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1571 MultiByteToWideChar(CP_ACP
, 0, Enumerator
, -1, enumstrW
, len
);
1575 int len
= MultiByteToWideChar(CP_ACP
, 0, MachineName
, -1, NULL
, 0);
1576 machineW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1579 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
1582 MultiByteToWideChar(CP_ACP
, 0, MachineName
, -1, machineW
, len
);
1584 ret
= SetupDiGetClassDevsExW(ClassGuid
, enumstrW
, hwndParent
, Flags
, DeviceInfoSet
, machineW
, Reserved
);
1587 HeapFree(GetProcessHeap(), 0, enumstrW
);
1588 HeapFree(GetProcessHeap(), 0, machineW
);
1593 CreateDeviceInfoElement(
1594 IN
struct DeviceInfoSet
*list
,
1595 IN LPCWSTR InstancePath
,
1596 IN LPCGUID pClassGuid
,
1597 OUT
struct DeviceInfoElement
**pDeviceInfo
)
1601 struct DeviceInfoElement
*deviceInfo
;
1603 *pDeviceInfo
= NULL
;
1605 size
= FIELD_OFFSET(struct DeviceInfoElement
, Data
) + (strlenW(InstancePath
) + 1) * sizeof(WCHAR
);
1606 deviceInfo
= HeapAlloc(GetProcessHeap(), 0, size
);
1609 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1612 memset(deviceInfo
, 0, size
);
1614 cr
= CM_Locate_DevNode_ExW(&deviceInfo
->dnDevInst
, (DEVINSTID_W
)InstancePath
, CM_LOCATE_DEVNODE_PHANTOM
, list
->hMachine
);
1615 if (cr
!= CR_SUCCESS
)
1617 SetLastError(GetErrorCodeFromCrCode(cr
));
1621 deviceInfo
->InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
1622 strcpyW(deviceInfo
->Data
, InstancePath
);
1623 deviceInfo
->DeviceName
= deviceInfo
->Data
;
1624 deviceInfo
->UniqueId
= strrchrW(deviceInfo
->Data
, '\\');
1625 deviceInfo
->DeviceDescription
= NULL
;
1626 memcpy(&deviceInfo
->ClassGuid
, pClassGuid
, sizeof(GUID
));
1627 deviceInfo
->CreationFlags
= 0;
1628 InitializeListHead(&deviceInfo
->DriverListHead
);
1629 InitializeListHead(&deviceInfo
->InterfaceListHead
);
1631 *pDeviceInfo
= deviceInfo
;
1636 CreateDeviceInterface(
1637 IN
struct DeviceInfoElement
* deviceInfo
,
1638 IN LPCWSTR SymbolicLink
,
1639 IN LPCGUID pInterfaceGuid
,
1640 OUT
struct DeviceInterface
**pDeviceInterface
)
1642 struct DeviceInterface
*deviceInterface
;
1644 *pDeviceInterface
= NULL
;
1646 deviceInterface
= HeapAlloc(GetProcessHeap(), 0,
1647 FIELD_OFFSET(struct DeviceInterface
, SymbolicLink
) + (strlenW(SymbolicLink
) + 1) * sizeof(WCHAR
));
1648 if (!deviceInterface
)
1650 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1653 deviceInterface
->DeviceInfo
= deviceInfo
;
1654 strcpyW(deviceInterface
->SymbolicLink
, SymbolicLink
);
1655 deviceInterface
->Flags
= 0; /* Flags will be updated later */
1656 memcpy(&deviceInterface
->InterfaceClassGuid
, pInterfaceGuid
, sizeof(GUID
));
1658 *pDeviceInterface
= deviceInterface
;
1663 SETUP_CreateDevListFromEnumerator(
1664 struct DeviceInfoSet
*list
,
1665 CONST GUID
*pClassGuid OPTIONAL
,
1667 HKEY hEnumeratorKey
) /* handle to Enumerator registry key */
1669 HKEY hDeviceIdKey
= NULL
, hInstanceIdKey
;
1670 WCHAR KeyBuffer
[MAX_PATH
];
1671 WCHAR InstancePath
[MAX_PATH
];
1672 LPWSTR pEndOfInstancePath
; /* Pointer into InstancePath buffer */
1673 struct DeviceInfoElement
*deviceInfo
;
1675 DWORD dwLength
, dwRegType
;
1678 /* Enumerate device IDs (subkeys of hEnumeratorKey) */
1681 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1682 rc
= RegEnumKeyExW(hEnumeratorKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1683 if (rc
== ERROR_NO_MORE_ITEMS
)
1685 if (rc
!= ERROR_SUCCESS
)
1689 /* Open device id sub key */
1690 if (hDeviceIdKey
!= NULL
)
1691 RegCloseKey(hDeviceIdKey
);
1692 rc
= RegOpenKeyExW(hEnumeratorKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hDeviceIdKey
);
1693 if (rc
!= ERROR_SUCCESS
)
1695 strcpyW(InstancePath
, Enumerator
);
1696 strcatW(InstancePath
, L
"\\");
1697 strcatW(InstancePath
, KeyBuffer
);
1698 strcatW(InstancePath
, L
"\\");
1699 pEndOfInstancePath
= &InstancePath
[strlenW(InstancePath
)];
1701 /* Enumerate instance IDs (subkeys of hDeviceIdKey) */
1707 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1708 rc
= RegEnumKeyExW(hDeviceIdKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1709 if (rc
== ERROR_NO_MORE_ITEMS
)
1711 if (rc
!= ERROR_SUCCESS
)
1715 /* Open instance id sub key */
1716 rc
= RegOpenKeyExW(hDeviceIdKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hInstanceIdKey
);
1717 if (rc
!= ERROR_SUCCESS
)
1719 *pEndOfInstancePath
= '\0';
1720 strcatW(InstancePath
, KeyBuffer
);
1722 /* Read ClassGUID value */
1723 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1724 rc
= RegQueryValueExW(hInstanceIdKey
, ClassGUID
, NULL
, &dwRegType
, (LPBYTE
)KeyBuffer
, &dwLength
);
1725 RegCloseKey(hInstanceIdKey
);
1726 if (rc
== ERROR_FILE_NOT_FOUND
)
1729 /* Skip this bad entry as we can't verify it */
1731 /* Set a default GUID for this device */
1732 memcpy(&KeyGuid
, &GUID_NULL
, sizeof(GUID
));
1734 else if (rc
!= ERROR_SUCCESS
)
1738 else if (dwRegType
!= REG_SZ
)
1740 rc
= ERROR_GEN_FAILURE
;
1745 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1746 if (UuidFromStringW(&KeyBuffer
[1], &KeyGuid
) != RPC_S_OK
)
1747 /* Bad GUID, skip the entry */
1751 if (pClassGuid
&& !IsEqualIID(&KeyGuid
, pClassGuid
))
1753 /* Skip this entry as it is not the right device class */
1757 /* Add the entry to the list */
1758 if (!CreateDeviceInfoElement(list
, InstancePath
, &KeyGuid
, &deviceInfo
))
1760 rc
= GetLastError();
1763 TRACE("Adding '%s' to device info set %p\n", debugstr_w(InstancePath
), list
);
1764 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
1771 if (hDeviceIdKey
!= NULL
)
1772 RegCloseKey(hDeviceIdKey
);
1777 SETUP_CreateDevList(
1778 struct DeviceInfoSet
*list
,
1779 PCWSTR MachineName OPTIONAL
,
1780 CONST GUID
*class OPTIONAL
,
1781 PCWSTR Enumerator OPTIONAL
)
1783 HKEY HKLM
= HKEY_LOCAL_MACHINE
;
1784 HKEY hEnumKey
= NULL
;
1785 HKEY hEnumeratorKey
= NULL
;
1786 WCHAR KeyBuffer
[MAX_PATH
];
1791 if (class && IsEqualIID(class, &GUID_NULL
))
1794 /* Open Enum key (if applicable) */
1795 if (MachineName
!= NULL
)
1797 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
1798 if (rc
!= ERROR_SUCCESS
)
1804 REGSTR_PATH_SYSTEMENUM
,
1806 KEY_ENUMERATE_SUB_KEYS
,
1808 if (rc
!= ERROR_SUCCESS
)
1811 /* If enumerator is provided, call directly SETUP_CreateDevListFromEnumerator.
1812 * Else, enumerate all enumerators and call SETUP_CreateDevListFromEnumerator
1821 KEY_ENUMERATE_SUB_KEYS
,
1823 if (rc
!= ERROR_SUCCESS
)
1825 rc
= SETUP_CreateDevListFromEnumerator(list
, class, Enumerator
, hEnumeratorKey
);
1829 /* Enumerate enumerators */
1833 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1834 rc
= RegEnumKeyExW(hEnumKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1835 if (rc
== ERROR_NO_MORE_ITEMS
)
1837 else if (rc
!= ERROR_SUCCESS
)
1842 if (hEnumeratorKey
!= NULL
)
1843 RegCloseKey(hEnumeratorKey
);
1844 rc
= RegOpenKeyExW(hEnumKey
, KeyBuffer
, 0, KEY_ENUMERATE_SUB_KEYS
, &hEnumeratorKey
);
1845 if (rc
!= ERROR_SUCCESS
)
1848 /* Call SETUP_CreateDevListFromEnumerator */
1849 rc
= SETUP_CreateDevListFromEnumerator(list
, class, KeyBuffer
, hEnumeratorKey
);
1850 if (rc
!= ERROR_SUCCESS
)
1857 if (HKLM
!= HKEY_LOCAL_MACHINE
)
1859 if (hEnumKey
!= NULL
)
1860 RegCloseKey(hEnumKey
);
1861 if (hEnumeratorKey
!= NULL
)
1862 RegCloseKey(hEnumeratorKey
);
1867 DestroyDeviceInterface(
1868 struct DeviceInterface
* deviceInterface
)
1870 return HeapFree(GetProcessHeap(), 0, deviceInterface
);
1874 SETUP_CreateInterfaceList(
1875 struct DeviceInfoSet
*list
,
1877 CONST GUID
*InterfaceGuid
,
1878 PCWSTR DeviceInstanceW
/* OPTIONAL */,
1879 BOOL OnlyPresentInterfaces
)
1881 HKEY hInterfaceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */
1882 HKEY hDeviceInstanceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */
1883 HKEY hReferenceKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */
1884 HKEY hControlKey
; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */
1885 HKEY hEnumKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum */
1886 HKEY hKey
; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */
1888 WCHAR KeyBuffer
[max(MAX_PATH
, MAX_GUID_STRING_LEN
) + 1];
1889 PWSTR pSymbolicLink
= NULL
;
1890 PWSTR InstancePath
= NULL
;
1892 DWORD dwLength
, dwInstancePathLength
;
1896 struct DeviceInfoElement
*deviceInfo
;
1898 hInterfaceKey
= INVALID_HANDLE_VALUE
;
1899 hDeviceInstanceKey
= NULL
;
1900 hReferenceKey
= NULL
;
1902 /* Open registry key related to this interface */
1903 hInterfaceKey
= SetupDiOpenClassRegKeyExW(InterfaceGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, MachineName
, NULL
);
1904 if (hInterfaceKey
== INVALID_HANDLE_VALUE
)
1906 rc
= GetLastError();
1910 /* Enumerate sub keys of hInterfaceKey */
1914 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
1915 rc
= RegEnumKeyExW(hInterfaceKey
, i
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
1916 if (rc
== ERROR_NO_MORE_ITEMS
)
1918 if (rc
!= ERROR_SUCCESS
)
1923 if (hDeviceInstanceKey
!= NULL
)
1924 RegCloseKey(hDeviceInstanceKey
);
1925 rc
= RegOpenKeyExW(hInterfaceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
| KEY_ENUMERATE_SUB_KEYS
, &hDeviceInstanceKey
);
1926 if (rc
!= ERROR_SUCCESS
)
1929 /* Read DeviceInstance */
1930 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, &dwRegType
, NULL
, &dwInstancePathLength
);
1931 if (rc
!= ERROR_SUCCESS
)
1933 if (dwRegType
!= REG_SZ
)
1935 rc
= ERROR_GEN_FAILURE
;
1938 HeapFree(GetProcessHeap(), 0, InstancePath
);
1939 InstancePath
= HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength
+ sizeof(WCHAR
));
1942 rc
= ERROR_NOT_ENOUGH_MEMORY
;
1945 rc
= RegQueryValueExW(hDeviceInstanceKey
, DeviceInstance
, NULL
, NULL
, (LPBYTE
)InstancePath
, &dwInstancePathLength
);
1946 if (rc
!= ERROR_SUCCESS
)
1948 InstancePath
[dwInstancePathLength
/ sizeof(WCHAR
)] = '\0';
1949 TRACE("DeviceInstance %s\n", debugstr_w(InstancePath
));
1951 if (DeviceInstanceW
)
1953 /* Check if device enumerator is not the right one */
1954 if (strcmpW(DeviceInstanceW
, InstancePath
) != 0)
1958 /* Find class GUID associated to the device instance */
1961 REGSTR_PATH_SYSTEMENUM
,
1965 if (rc
!= ERROR_SUCCESS
)
1973 RegCloseKey(hEnumKey
);
1974 if (rc
!= ERROR_SUCCESS
)
1976 dwLength
= sizeof(KeyBuffer
) - sizeof(WCHAR
);
1977 rc
= RegQueryValueExW(hKey
, ClassGUID
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
1979 if (rc
!= ERROR_SUCCESS
)
1981 KeyBuffer
[dwLength
/ sizeof(WCHAR
)] = '\0';
1982 KeyBuffer
[37] = '\0'; /* Replace the } by a NULL character */
1983 if (UuidFromStringW(&KeyBuffer
[1], &ClassGuid
) != RPC_S_OK
)
1985 rc
= ERROR_GEN_FAILURE
;
1988 TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid
));
1990 /* If current device doesn't match the list GUID (if any), skip this entry */
1991 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
1994 /* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */
1998 struct DeviceInterface
*interfaceInfo
;
2000 dwLength
= sizeof(KeyBuffer
) / sizeof(KeyBuffer
[0]);
2001 rc
= RegEnumKeyExW(hDeviceInstanceKey
, j
, KeyBuffer
, &dwLength
, NULL
, NULL
, NULL
, NULL
);
2002 if (rc
== ERROR_NO_MORE_ITEMS
)
2004 if (rc
!= ERROR_SUCCESS
)
2007 if (KeyBuffer
[0] != '#')
2008 /* This entry doesn't represent an interesting entry */
2012 if (hReferenceKey
!= NULL
)
2013 RegCloseKey(hReferenceKey
);
2014 rc
= RegOpenKeyExW(hDeviceInstanceKey
, KeyBuffer
, 0, KEY_QUERY_VALUE
, &hReferenceKey
);
2015 if (rc
!= ERROR_SUCCESS
)
2018 /* Read SymbolicLink value */
2019 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, &dwRegType
, NULL
, &dwLength
);
2020 if (rc
!= ERROR_SUCCESS
)
2022 if (dwRegType
!= REG_SZ
)
2024 rc
= ERROR_GEN_FAILURE
;
2028 /* We have found a device */
2029 /* Step 1. Create a device info element */
2030 if (!CreateDeviceInfoElement(list
, InstancePath
, &ClassGuid
, &deviceInfo
))
2032 rc
= GetLastError();
2035 TRACE("Adding device %s to list\n", debugstr_w(InstancePath
));
2036 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
2038 /* Step 2. Create an interface list for this element */
2039 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
2040 pSymbolicLink
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 1) * sizeof(WCHAR
));
2043 rc
= ERROR_NOT_ENOUGH_MEMORY
;
2046 rc
= RegQueryValueExW(hReferenceKey
, SymbolicLink
, NULL
, NULL
, (LPBYTE
)pSymbolicLink
, &dwLength
);
2047 pSymbolicLink
[dwLength
/ sizeof(WCHAR
)] = '\0';
2048 if (rc
!= ERROR_SUCCESS
)
2050 if (!CreateDeviceInterface(deviceInfo
, pSymbolicLink
, InterfaceGuid
, &interfaceInfo
))
2052 rc
= GetLastError();
2056 /* Step 3. Update flags */
2057 if (KeyBuffer
[1] == '\0')
2058 interfaceInfo
->Flags
|= SPINT_DEFAULT
;
2059 rc
= RegOpenKeyExW(hReferenceKey
, Control
, 0, KEY_QUERY_VALUE
, &hControlKey
);
2060 if (rc
!= ERROR_SUCCESS
)
2062 if (OnlyPresentInterfaces
)
2064 DestroyDeviceInterface(interfaceInfo
);
2068 interfaceInfo
->Flags
|= SPINT_REMOVED
;
2072 dwLength
= sizeof(DWORD
);
2073 if (RegQueryValueExW(hControlKey
, Linked
, NULL
, &dwRegType
, (LPBYTE
)&LinkedValue
, &dwLength
)
2074 && dwRegType
== REG_DWORD
&& LinkedValue
)
2075 interfaceInfo
->Flags
|= SPINT_ACTIVE
;
2076 RegCloseKey(hControlKey
);
2079 TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink
));
2080 InsertTailList(&deviceInfo
->InterfaceListHead
, &interfaceInfo
->ListEntry
);
2086 if (hReferenceKey
!= NULL
)
2087 RegCloseKey(hReferenceKey
);
2088 if (hDeviceInstanceKey
!= NULL
)
2089 RegCloseKey(hDeviceInstanceKey
);
2090 if (hInterfaceKey
!= INVALID_HANDLE_VALUE
)
2091 RegCloseKey(hInterfaceKey
);
2092 HeapFree(GetProcessHeap(), 0, InstancePath
);
2093 HeapFree(GetProcessHeap(), 0, pSymbolicLink
);
2097 /***********************************************************************
2098 * SetupDiGetClassDevsExW (SETUPAPI.@)
2101 SetupDiGetClassDevsExW(
2102 IN CONST GUID
*ClassGuid OPTIONAL
,
2103 IN PCWSTR Enumerator OPTIONAL
,
2104 IN HWND hwndParent OPTIONAL
,
2106 IN HDEVINFO DeviceInfoSet OPTIONAL
,
2107 IN PCWSTR MachineName OPTIONAL
,
2110 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
2111 struct DeviceInfoSet
*list
;
2112 CONST GUID
*pClassGuid
;
2114 HDEVINFO ret
= INVALID_HANDLE_VALUE
;
2116 TRACE("%s %s %p 0x%08lx %p %s %p\n", debugstr_guid(ClassGuid
), debugstr_w(Enumerator
),
2117 hwndParent
, Flags
, DeviceInfoSet
, debugstr_w(MachineName
), Reserved
);
2119 /* Create the deviceset if not set */
2122 list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2123 if (list
->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2125 SetLastError(ERROR_INVALID_HANDLE
);
2128 hDeviceInfo
= DeviceInfoSet
;
2132 hDeviceInfo
= SetupDiCreateDeviceInfoListExW(
2133 Flags
& DIGCF_DEVICEINTERFACE
? NULL
: ClassGuid
,
2134 NULL
, MachineName
, NULL
);
2135 if (hDeviceInfo
== INVALID_HANDLE_VALUE
)
2137 list
= (struct DeviceInfoSet
*)hDeviceInfo
;
2140 if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
2143 pClassGuid
= &list
->ClassGuid
;
2145 if (Flags
& DIGCF_PROFILE
)
2146 FIXME(": flag DIGCF_PROFILE ignored\n");
2148 if (Flags
& DIGCF_ALLCLASSES
)
2150 rc
= SETUP_CreateDevList(list
, MachineName
, pClassGuid
, Enumerator
);
2151 if (rc
!= ERROR_SUCCESS
)
2158 else if (Flags
& DIGCF_DEVICEINTERFACE
)
2160 if (ClassGuid
== NULL
)
2162 SetLastError(ERROR_INVALID_PARAMETER
);
2166 rc
= SETUP_CreateInterfaceList(list
, MachineName
, ClassGuid
, Enumerator
, Flags
& DIGCF_PRESENT
);
2167 if (rc
!= ERROR_SUCCESS
)
2176 rc
= SETUP_CreateDevList(list
, MachineName
, ClassGuid
, Enumerator
);
2177 if (rc
!= ERROR_SUCCESS
)
2186 if (!DeviceInfoSet
&& hDeviceInfo
!= INVALID_HANDLE_VALUE
&& hDeviceInfo
!= ret
)
2187 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
2191 /***********************************************************************
2192 * SetupDiGetClassImageIndex (SETUPAPI.@)
2198 OUT PINT ImageIndex
)
2200 LPWSTR Buffer
= NULL
;
2201 DWORD dwRegType
, dwLength
;
2205 /* Read icon registry key */
2206 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, &dwRegType
, NULL
, &dwLength
);
2207 if (rc
!= ERROR_SUCCESS
)
2211 } else if (dwRegType
!= REG_SZ
)
2213 SetLastError(ERROR_INVALID_INDEX
);
2216 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2219 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2222 rc
= RegQueryValueExW(hClassKey
, REGSTR_VAL_INSICON
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2223 if (rc
!= ERROR_SUCCESS
)
2228 /* make sure the returned buffer is NULL-terminated */
2229 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2231 /* Transform icon value to a INT */
2232 *ImageIndex
= atoiW(Buffer
);
2241 SetupDiGetClassImageIndex(
2242 IN PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2243 IN CONST GUID
*ClassGuid
,
2244 OUT PINT ImageIndex
)
2246 struct ClassImageList
*list
;
2249 TRACE("%p %s %p\n", ClassImageListData
, debugstr_guid(ClassGuid
), ImageIndex
);
2251 if (!ClassImageListData
|| !ClassGuid
|| !ImageIndex
)
2252 SetLastError(ERROR_INVALID_PARAMETER
);
2253 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2254 SetLastError(ERROR_INVALID_USER_BUFFER
);
2255 else if ((list
= (struct ClassImageList
*)ClassImageListData
->Reserved
) == NULL
)
2256 SetLastError(ERROR_INVALID_USER_BUFFER
);
2257 else if (list
->magic
!= SETUP_CLASS_IMAGE_LIST_MAGIC
)
2258 SetLastError(ERROR_INVALID_USER_BUFFER
);
2259 else if (!ImageIndex
)
2260 SetLastError(ERROR_INVALID_PARAMETER
);
2263 HKEY hKey
= INVALID_HANDLE_VALUE
;
2266 /* Read Icon registry entry into Buffer */
2267 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, KEY_QUERY_VALUE
, DIOCR_INTERFACE
, list
->MachineName
, NULL
);
2268 if (hKey
== INVALID_HANDLE_VALUE
)
2270 if (!GetIconIndex(hKey
, &iconIndex
))
2275 SetLastError(ERROR_INVALID_INDEX
);
2279 *ImageIndex
= -iconIndex
;
2283 if (hKey
!= INVALID_HANDLE_VALUE
)
2287 TRACE("Returning %d\n", ret
);
2291 /***********************************************************************
2292 * SetupDiGetClassImageList(SETUPAPI.@)
2295 SetupDiGetClassImageList(
2296 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
)
2298 return SetupDiGetClassImageListExW(ClassImageListData
, NULL
, NULL
);
2301 /***********************************************************************
2302 * SetupDiGetClassImageListExA(SETUPAPI.@)
2305 SetupDiGetClassImageListExA(
2306 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2307 IN PCSTR MachineName OPTIONAL
,
2310 PWSTR MachineNameW
= NULL
;
2315 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
2316 if (MachineNameW
== NULL
)
2320 ret
= SetupDiGetClassImageListExW(ClassImageListData
, MachineNameW
, Reserved
);
2323 MyFree(MachineNameW
);
2328 /***********************************************************************
2329 * SetupDiGetClassImageListExW(SETUPAPI.@)
2332 SetupDiGetClassImageListExW(
2333 OUT PSP_CLASSIMAGELIST_DATA ClassImageListData
,
2334 IN PCWSTR MachineName OPTIONAL
,
2339 TRACE("%p %p %p\n", ClassImageListData
, debugstr_w(MachineName
), Reserved
);
2341 if (!ClassImageListData
)
2342 SetLastError(ERROR_INVALID_PARAMETER
);
2343 else if (ClassImageListData
->cbSize
!= sizeof(SP_CLASSIMAGELIST_DATA
))
2344 SetLastError(ERROR_INVALID_USER_BUFFER
);
2346 SetLastError(ERROR_INVALID_PARAMETER
);
2349 struct ClassImageList
*list
= NULL
;
2352 size
= FIELD_OFFSET(struct ClassImageList
, szData
);
2354 size
+= (strlenW(MachineName
) + 3) * sizeof(WCHAR
);
2355 list
= HeapAlloc(GetProcessHeap(), 0, size
);
2358 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2361 list
->magic
= SETUP_CLASS_IMAGE_LIST_MAGIC
;
2364 list
->szData
[0] = list
->szData
[1] = '\\';
2365 strcpyW(list
->szData
+ 2, MachineName
);
2366 list
->MachineName
= list
->szData
;
2370 list
->MachineName
= NULL
;
2373 ClassImageListData
->Reserved
= (ULONG_PTR
)list
;
2381 TRACE("Returning %d\n", ret
);
2385 /***********************************************************************
2386 * SetupDiLoadClassIcon(SETUPAPI.@)
2389 SetupDiLoadClassIcon(
2390 IN CONST GUID
*ClassGuid
,
2391 OUT HICON
*LargeIcon OPTIONAL
,
2392 OUT PINT MiniIconIndex OPTIONAL
)
2397 SetLastError(ERROR_INVALID_PARAMETER
);
2400 LPWSTR Buffer
= NULL
;
2403 HKEY hKey
= INVALID_HANDLE_VALUE
;
2405 hKey
= SetupDiOpenClassRegKey(ClassGuid
, KEY_QUERY_VALUE
);
2406 if (hKey
== INVALID_HANDLE_VALUE
)
2409 if (!GetIconIndex(hKey
, &iconIndex
))
2414 /* Look up icon in dll specified by Installer32 or EnumPropPages32 key */
2417 DWORD dwRegType
, dwLength
;
2418 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
2419 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
2421 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2424 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2427 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2428 if (rc
!= ERROR_SUCCESS
)
2433 /* make sure the returned buffer is NULL-terminated */
2434 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2437 (ERROR_SUCCESS
== (rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
))
2438 && dwRegType
== REG_SZ
)
2440 Buffer
= MyMalloc(dwLength
+ sizeof(WCHAR
));
2443 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2446 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)Buffer
, &dwLength
);
2447 if (rc
!= ERROR_SUCCESS
)
2452 /* make sure the returned buffer is NULL-terminated */
2453 Buffer
[dwLength
/ sizeof(WCHAR
)] = 0;
2457 /* Unable to find where to load the icon */
2458 SetLastError(ERROR_FILE_NOT_FOUND
);
2461 Comma
= strchrW(Buffer
, ',');
2464 SetLastError(ERROR_GEN_FAILURE
);
2472 /* Look up icon in setupapi.dll */
2473 DllName
= L
"setupapi.dll";
2474 iconIndex
= -iconIndex
;
2477 TRACE("Icon index %d, dll name %s\n", iconIndex
, debugstr_w(DllName
));
2480 if (1 != ExtractIconEx(DllName
, iconIndex
, LargeIcon
, NULL
, 1))
2482 SetLastError(ERROR_INVALID_INDEX
);
2487 *MiniIconIndex
= iconIndex
;
2491 if (hKey
!= INVALID_HANDLE_VALUE
)
2496 TRACE("Returning %d\n", ret
);
2500 /***********************************************************************
2501 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
2504 SetupDiEnumDeviceInterfaces(
2505 IN HDEVINFO DeviceInfoSet
,
2506 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
2507 IN CONST GUID
*InterfaceClassGuid
,
2508 IN DWORD MemberIndex
,
2509 OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
2513 TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet
, DeviceInfoData
,
2514 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
2516 if (!DeviceInterfaceData
)
2517 SetLastError(ERROR_INVALID_PARAMETER
);
2518 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2519 SetLastError(ERROR_INVALID_USER_BUFFER
);
2520 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2522 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2524 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2526 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
2528 while (ItemList
!= &list
->ListHead
&& !Found
)
2530 PLIST_ENTRY InterfaceListEntry
;
2531 struct DeviceInfoElement
*DevInfo
= CONTAINING_RECORD(ItemList
, struct DeviceInfoElement
, ListEntry
);
2532 if (DeviceInfoData
&& (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
!= DevInfo
)
2534 /* We are not searching for this element */
2535 ItemList
= ItemList
->Flink
;
2538 InterfaceListEntry
= DevInfo
->InterfaceListHead
.Flink
;
2539 while (InterfaceListEntry
!= &DevInfo
->InterfaceListHead
&& !Found
)
2541 struct DeviceInterface
*DevItf
= CONTAINING_RECORD(InterfaceListEntry
, struct DeviceInterface
, ListEntry
);
2542 if (!IsEqualIID(&DevItf
->InterfaceClassGuid
, InterfaceClassGuid
))
2544 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2547 if (MemberIndex
-- == 0)
2549 /* return this item */
2550 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
2551 &DevItf
->InterfaceClassGuid
,
2553 DeviceInterfaceData
->Flags
= DevItf
->Flags
;
2554 DeviceInterfaceData
->Reserved
= (ULONG_PTR
)DevItf
;
2557 InterfaceListEntry
= InterfaceListEntry
->Flink
;
2559 ItemList
= ItemList
->Flink
;
2562 SetLastError(ERROR_NO_MORE_ITEMS
);
2567 SetLastError(ERROR_INVALID_HANDLE
);
2570 SetLastError(ERROR_INVALID_HANDLE
);
2575 ReferenceInfFile(struct InfFileDetails
* infFile
)
2577 InterlockedIncrement(&infFile
->References
);
2581 DereferenceInfFile(struct InfFileDetails
* infFile
)
2583 if (InterlockedDecrement(&infFile
->References
) == 0)
2585 SetupCloseInfFile(infFile
->hInf
);
2586 HeapFree(GetProcessHeap(), 0, infFile
);
2591 DestroyDriverInfoElement(struct DriverInfoElement
* driverInfo
)
2593 DereferenceInfFile(driverInfo
->InfFileDetails
);
2594 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
2595 HeapFree(GetProcessHeap(), 0, driverInfo
);
2600 DestroyClassInstallParams(struct ClassInstallParams
* installParams
)
2602 return HeapFree(GetProcessHeap(), 0, installParams
->PropChange
);
2606 DestroyDeviceInfoElement(struct DeviceInfoElement
* deviceInfo
)
2608 PLIST_ENTRY ListEntry
;
2609 struct DriverInfoElement
*driverInfo
;
2610 struct DeviceInterface
*deviceInterface
;
2612 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
2614 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
2615 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
2616 if (!DestroyDriverInfoElement(driverInfo
))
2619 while (!IsListEmpty(&deviceInfo
->InterfaceListHead
))
2621 ListEntry
= RemoveHeadList(&deviceInfo
->InterfaceListHead
);
2622 deviceInterface
= CONTAINING_RECORD(ListEntry
, struct DeviceInterface
, ListEntry
);
2623 if (!DestroyDeviceInterface(deviceInterface
))
2626 DestroyClassInstallParams(&deviceInfo
->ClassInstallParams
);
2627 return HeapFree(GetProcessHeap(), 0, deviceInfo
);
2631 DestroyDeviceInfoSet(struct DeviceInfoSet
* list
)
2633 PLIST_ENTRY ListEntry
;
2634 struct DeviceInfoElement
*deviceInfo
;
2636 while (!IsListEmpty(&list
->ListHead
))
2638 ListEntry
= RemoveHeadList(&list
->ListHead
);
2639 deviceInfo
= CONTAINING_RECORD(ListEntry
, struct DeviceInfoElement
, ListEntry
);
2640 if (!DestroyDeviceInfoElement(deviceInfo
))
2643 if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
2644 RegCloseKey(list
->HKLM
);
2645 CM_Disconnect_Machine(list
->hMachine
);
2646 DestroyClassInstallParams(&list
->ClassInstallParams
);
2647 return HeapFree(GetProcessHeap(), 0, list
);
2650 /***********************************************************************
2651 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
2654 SetupDiDestroyDeviceInfoList(
2655 IN HDEVINFO DeviceInfoSet
)
2659 TRACE("%p\n", DeviceInfoSet
);
2660 if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
2662 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2664 if (list
->magic
== SETUP_DEV_INFO_SET_MAGIC
)
2665 ret
= DestroyDeviceInfoSet(list
);
2667 SetLastError(ERROR_INVALID_HANDLE
);
2670 SetLastError(ERROR_INVALID_HANDLE
);
2672 TRACE("Returning %d\n", ret
);
2676 /***********************************************************************
2677 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
2680 SetupDiGetDeviceInterfaceDetailA(
2681 IN HDEVINFO DeviceInfoSet
,
2682 IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2683 OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData OPTIONAL
,
2684 IN DWORD DeviceInterfaceDetailDataSize
,
2685 OUT PDWORD RequiredSize OPTIONAL
,
2686 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2688 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW
= NULL
;
2689 DWORD sizeW
= 0, sizeA
;
2692 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2693 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2694 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2696 if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
))
2697 SetLastError(ERROR_INVALID_USER_BUFFER
);
2698 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2699 SetLastError(ERROR_INVALID_PARAMETER
);
2700 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
) + 1)
2701 SetLastError(ERROR_INVALID_PARAMETER
);
2704 if (DeviceInterfaceDetailData
!= NULL
)
2706 sizeW
= FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)
2707 + (DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
)) * sizeof(WCHAR
);
2708 DeviceInterfaceDetailDataW
= (PSP_DEVICE_INTERFACE_DETAIL_DATA_W
)HeapAlloc(GetProcessHeap(), 0, sizeW
);
2709 if (!DeviceInterfaceDetailDataW
)
2711 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2714 if (!DeviceInterfaceDetailData
|| (DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataW
))
2716 DeviceInterfaceDetailDataW
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
);
2717 ret
= SetupDiGetDeviceInterfaceDetailW(
2719 DeviceInterfaceData
,
2720 DeviceInterfaceDetailDataW
,
2724 sizeA
= (sizeW
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
)) / sizeof(WCHAR
)
2725 + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
);
2727 *RequiredSize
= sizeA
;
2728 if (ret
&& DeviceInterfaceDetailData
&& DeviceInterfaceDetailDataSize
<= sizeA
)
2730 if (!WideCharToMultiByte(
2732 DeviceInterfaceDetailDataW
->DevicePath
, -1,
2733 DeviceInterfaceDetailData
->DevicePath
, DeviceInterfaceDetailDataSize
- FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A
, DevicePath
),
2740 HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW
);
2743 TRACE("Returning %d\n", ret
);
2747 /***********************************************************************
2748 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
2751 SetupDiGetDeviceInterfaceDetailW(
2752 IN HDEVINFO DeviceInfoSet
,
2753 IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
2754 OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData OPTIONAL
,
2755 IN DWORD DeviceInterfaceDetailDataSize
,
2756 OUT PDWORD RequiredSize OPTIONAL
,
2757 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
2761 TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet
,
2762 DeviceInterfaceData
, DeviceInterfaceDetailData
,
2763 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
2765 if (!DeviceInfoSet
|| !DeviceInterfaceData
)
2766 SetLastError(ERROR_INVALID_PARAMETER
);
2767 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2768 SetLastError(ERROR_INVALID_HANDLE
);
2769 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2770 SetLastError(ERROR_INVALID_HANDLE
);
2771 else if (DeviceInterfaceData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DATA
))
2772 SetLastError(ERROR_INVALID_USER_BUFFER
);
2773 else if (DeviceInterfaceDetailData
->cbSize
!= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
))
2774 SetLastError(ERROR_INVALID_USER_BUFFER
);
2775 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2776 SetLastError(ERROR_INVALID_USER_BUFFER
);
2777 else if (DeviceInterfaceDetailData
== NULL
&& DeviceInterfaceDetailDataSize
!= 0)
2778 SetLastError(ERROR_INVALID_PARAMETER
);
2779 else if (DeviceInterfaceDetailData
!= NULL
&& DeviceInterfaceDetailDataSize
< FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W
, DevicePath
) + sizeof(WCHAR
))
2780 SetLastError(ERROR_INVALID_PARAMETER
);
2783 struct DeviceInterface
*deviceInterface
= (struct DeviceInterface
*)DeviceInterfaceData
->Reserved
;
2784 LPCWSTR devName
= deviceInterface
->SymbolicLink
;
2785 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W
) +
2786 (lstrlenW(devName
) + 1) * sizeof(WCHAR
);
2788 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
2790 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2792 *RequiredSize
= sizeRequired
;
2796 strcpyW(DeviceInterfaceDetailData
->DevicePath
, devName
);
2797 TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData
->DevicePath
));
2800 memcpy(&DeviceInfoData
->ClassGuid
,
2801 &deviceInterface
->DeviceInfo
->ClassGuid
,
2803 DeviceInfoData
->DevInst
= deviceInterface
->DeviceInfo
->dnDevInst
;
2804 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInterface
->DeviceInfo
;
2810 TRACE("Returning %d\n", ret
);
2814 /***********************************************************************
2815 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
2818 SetupDiGetDeviceRegistryPropertyA(
2819 IN HDEVINFO DeviceInfoSet
,
2820 IN PSP_DEVINFO_DATA DeviceInfoData
,
2822 OUT PDWORD PropertyRegDataType OPTIONAL
,
2823 OUT PBYTE PropertyBuffer OPTIONAL
,
2824 IN DWORD PropertyBufferSize
,
2825 OUT PDWORD RequiredSize OPTIONAL
)
2828 BOOL bIsStringProperty
;
2830 DWORD RequiredSizeA
, RequiredSizeW
;
2831 DWORD PropertyBufferSizeW
= 0;
2832 PBYTE PropertyBufferW
= NULL
;
2834 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2835 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2838 if (PropertyBufferSize
!= 0)
2840 PropertyBufferSizeW
= PropertyBufferSize
* 2;
2841 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
2842 if (!PropertyBufferW
)
2844 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
2849 bResult
= SetupDiGetDeviceRegistryPropertyW(
2855 PropertyBufferSizeW
,
2858 if (bResult
|| GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
2860 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
|| RegType
== REG_EXPAND_SZ
);
2862 if (bIsStringProperty
)
2863 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
2865 RequiredSizeA
= RequiredSizeW
;
2867 *RequiredSize
= RequiredSizeA
;
2868 if (PropertyRegDataType
)
2869 *PropertyRegDataType
= RegType
;
2874 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2878 if (RequiredSizeA
<= PropertyBufferSize
)
2880 if (bIsStringProperty
&& PropertyBufferSize
> 0)
2882 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), (LPSTR
)PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
2884 /* Last error is already set by WideCharToMultiByte */
2889 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
2893 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
2897 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
2901 /***********************************************************************
2902 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
2905 SetupDiGetDeviceRegistryPropertyW(
2906 IN HDEVINFO DeviceInfoSet
,
2907 IN PSP_DEVINFO_DATA DeviceInfoData
,
2909 OUT PDWORD PropertyRegDataType OPTIONAL
,
2910 OUT PBYTE PropertyBuffer OPTIONAL
,
2911 IN DWORD PropertyBufferSize
,
2912 OUT PDWORD RequiredSize OPTIONAL
)
2914 HKEY hEnumKey
, hKey
;
2918 TRACE("%p %p %ld %p %p %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
2919 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
2922 if (!DeviceInfoSet
|| DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
2923 SetLastError(ERROR_INVALID_HANDLE
);
2924 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
2925 SetLastError(ERROR_INVALID_HANDLE
);
2926 else if (!DeviceInfoData
)
2927 SetLastError(ERROR_INVALID_PARAMETER
);
2928 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
2929 SetLastError(ERROR_INVALID_USER_BUFFER
);
2930 else if (Property
>= SPDRP_MAXIMUM_PROPERTY
)
2931 SetLastError(ERROR_INVALID_PARAMETER
);
2934 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
2935 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
2939 case SPDRP_CAPABILITIES
:
2941 case SPDRP_CLASSGUID
:
2942 case SPDRP_COMPATIBLEIDS
:
2943 case SPDRP_CONFIGFLAGS
:
2944 case SPDRP_DEVICEDESC
:
2946 case SPDRP_FRIENDLYNAME
:
2947 case SPDRP_HARDWAREID
:
2948 case SPDRP_LOCATION_INFORMATION
:
2949 case SPDRP_LOWERFILTERS
:
2951 case SPDRP_SECURITY
:
2953 case SPDRP_UI_NUMBER
:
2954 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2955 case SPDRP_UPPERFILTERS
:
2957 LPCWSTR RegistryPropertyName
;
2962 case SPDRP_CAPABILITIES
:
2963 RegistryPropertyName
= REGSTR_VAL_CAPABILITIES
; break;
2965 RegistryPropertyName
= REGSTR_VAL_CLASS
; break;
2966 case SPDRP_CLASSGUID
:
2967 RegistryPropertyName
= REGSTR_VAL_CLASSGUID
; break;
2968 case SPDRP_COMPATIBLEIDS
:
2969 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
; break;
2970 case SPDRP_CONFIGFLAGS
:
2971 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
; break;
2972 case SPDRP_DEVICEDESC
:
2973 RegistryPropertyName
= REGSTR_VAL_DEVDESC
; break;
2975 RegistryPropertyName
= REGSTR_VAL_DRIVER
; break;
2976 case SPDRP_FRIENDLYNAME
:
2977 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
; break;
2978 case SPDRP_HARDWAREID
:
2979 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
; break;
2980 case SPDRP_LOCATION_INFORMATION
:
2981 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
; break;
2982 case SPDRP_LOWERFILTERS
:
2983 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
; break;
2985 RegistryPropertyName
= REGSTR_VAL_MFG
; break;
2986 case SPDRP_SECURITY
:
2987 RegistryPropertyName
= REGSTR_SECURITY
; break;
2989 RegistryPropertyName
= REGSTR_VAL_SERVICE
; break;
2990 case SPDRP_UI_NUMBER
:
2991 RegistryPropertyName
= REGSTR_VAL_UI_NUMBER
; break;
2992 case SPDRP_UI_NUMBER_DESC_FORMAT
:
2993 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
; break;
2994 case SPDRP_UPPERFILTERS
:
2995 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
; break;
2997 /* Should not happen */
2998 RegistryPropertyName
= NULL
; break;
3001 /* Open registry key name */
3004 REGSTR_PATH_SYSTEMENUM
,
3008 if (rc
!= ERROR_SUCCESS
)
3019 RegCloseKey(hEnumKey
);
3020 if (rc
!= ERROR_SUCCESS
)
3025 /* Read registry entry */
3026 BufferSize
= PropertyBufferSize
;
3027 rc
= RegQueryValueExW(
3029 RegistryPropertyName
,
3030 NULL
, /* Reserved */
3031 PropertyRegDataType
,
3035 *RequiredSize
= BufferSize
;
3038 if (PropertyBuffer
!= NULL
|| BufferSize
== 0)
3041 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3043 case ERROR_MORE_DATA
:
3044 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3053 case SPDRP_PHYSICAL_DEVICE_OBJECT_NAME
:
3055 DWORD required
= (strlenW(DevInfo
->Data
) + 1) * sizeof(WCHAR
);
3057 if (PropertyRegDataType
)
3058 *PropertyRegDataType
= REG_SZ
;
3060 *RequiredSize
= required
;
3061 if (PropertyBufferSize
>= required
)
3063 strcpyW((LPWSTR
)PropertyBuffer
, DevInfo
->Data
);
3067 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
3071 /*case SPDRP_BUSTYPEGUID:
3072 case SPDRP_LEGACYBUSTYPE:
3073 case SPDRP_BUSNUMBER:
3074 case SPDRP_ENUMERATOR_NAME:
3075 case SPDRP_SECURITY_SDS:
3077 case SPDRP_EXCLUSIVE:
3078 case SPDRP_CHARACTERISTICS:
3080 case SPDRP_DEVICE_POWER_DATA:*/
3081 #if (WINVER >= 0x501)
3082 /*case SPDRP_REMOVAL_POLICY:
3083 case SPDRP_REMOVAL_POLICY_HW_DEFAULT:
3084 case SPDRP_REMOVAL_POLICY_OVERRIDE:
3085 case SPDRP_INSTALL_STATE:*/
3090 ERR("Property 0x%lx not implemented\n", Property
);
3091 SetLastError(ERROR_NOT_SUPPORTED
);
3096 TRACE("Returning %d\n", ret
);
3100 /***********************************************************************
3101 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
3104 SetupDiSetDeviceRegistryPropertyA(
3105 IN HDEVINFO DeviceInfoSet
,
3106 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
3108 IN CONST BYTE
*PropertyBuffer OPTIONAL
,
3109 IN DWORD PropertyBufferSize
)
3111 FIXME("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3112 Property
, PropertyBuffer
, PropertyBufferSize
);
3113 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3117 /***********************************************************************
3118 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
3121 SetupDiSetDeviceRegistryPropertyW(
3122 IN HDEVINFO DeviceInfoSet
,
3123 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
3125 IN CONST BYTE
*PropertyBuffer OPTIONAL
,
3126 IN DWORD PropertyBufferSize
)
3128 struct DeviceInfoSet
*list
;
3131 TRACE("%p %p 0x%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
3132 Property
, PropertyBuffer
, PropertyBufferSize
);
3135 SetLastError(ERROR_INVALID_HANDLE
);
3136 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3137 SetLastError(ERROR_INVALID_HANDLE
);
3138 else if (!DeviceInfoData
)
3139 SetLastError(ERROR_INVALID_HANDLE
);
3140 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3141 SetLastError(ERROR_INVALID_USER_BUFFER
);
3146 case SPDRP_COMPATIBLEIDS
:
3147 case SPDRP_CONFIGFLAGS
:
3148 case SPDRP_FRIENDLYNAME
:
3149 case SPDRP_HARDWAREID
:
3150 case SPDRP_LOCATION_INFORMATION
:
3151 case SPDRP_LOWERFILTERS
:
3152 case SPDRP_SECURITY
:
3154 case SPDRP_UI_NUMBER_DESC_FORMAT
:
3155 case SPDRP_UPPERFILTERS
:
3157 LPCWSTR RegistryPropertyName
;
3158 DWORD RegistryDataType
;
3164 case SPDRP_COMPATIBLEIDS
:
3165 RegistryPropertyName
= REGSTR_VAL_COMPATIBLEIDS
;
3166 RegistryDataType
= REG_MULTI_SZ
;
3168 case SPDRP_CONFIGFLAGS
:
3169 RegistryPropertyName
= REGSTR_VAL_CONFIGFLAGS
;
3170 RegistryDataType
= REG_DWORD
;
3172 case SPDRP_FRIENDLYNAME
:
3173 RegistryPropertyName
= REGSTR_VAL_FRIENDLYNAME
;
3174 RegistryDataType
= REG_SZ
;
3176 case SPDRP_HARDWAREID
:
3177 RegistryPropertyName
= REGSTR_VAL_HARDWAREID
;
3178 RegistryDataType
= REG_MULTI_SZ
;
3180 case SPDRP_LOCATION_INFORMATION
:
3181 RegistryPropertyName
= REGSTR_VAL_LOCATION_INFORMATION
;
3182 RegistryDataType
= REG_SZ
;
3184 case SPDRP_LOWERFILTERS
:
3185 RegistryPropertyName
= REGSTR_VAL_LOWERFILTERS
;
3186 RegistryDataType
= REG_MULTI_SZ
;
3188 case SPDRP_SECURITY
:
3189 RegistryPropertyName
= REGSTR_SECURITY
;
3190 RegistryDataType
= REG_BINARY
;
3193 RegistryPropertyName
= REGSTR_VAL_SERVICE
;
3194 RegistryDataType
= REG_SZ
;
3196 case SPDRP_UI_NUMBER_DESC_FORMAT
:
3197 RegistryPropertyName
= REGSTR_UI_NUMBER_DESC_FORMAT
;
3198 RegistryDataType
= REG_SZ
;
3200 case SPDRP_UPPERFILTERS
:
3201 RegistryPropertyName
= REGSTR_VAL_UPPERFILTERS
;
3202 RegistryDataType
= REG_MULTI_SZ
;
3205 /* Should not happen */
3206 RegistryPropertyName
= NULL
;
3207 RegistryDataType
= REG_BINARY
;
3210 /* Open device registry key */
3211 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
3212 if (hKey
!= INVALID_HANDLE_VALUE
)
3214 /* Write new data */
3215 rc
= RegSetValueExW(
3217 RegistryPropertyName
,
3221 PropertyBufferSize
);
3222 if (rc
== ERROR_SUCCESS
)
3231 /*case SPDRP_CHARACTERISTICS:
3233 case SPDRP_EXCLUSIVE:*/
3234 #if (WINVER >= 0x501)
3235 //case SPDRP_REMOVAL_POLICY_OVERRIDE:
3237 //case SPDRP_SECURITY_SDS:
3241 ERR("Property 0x%lx not implemented\n", Property
);
3242 SetLastError(ERROR_NOT_SUPPORTED
);
3247 TRACE("Returning %d\n", ret
);
3252 /***********************************************************************
3253 * SetupDiInstallClassA (SETUPAPI.@)
3256 SetupDiInstallClassA(
3257 IN HWND hwndParent OPTIONAL
,
3258 IN PCSTR InfFileName
,
3260 IN HSPFILEQ FileQueue OPTIONAL
)
3262 return SetupDiInstallClassExA(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3266 /***********************************************************************
3267 * SetupDiInstallClassW (SETUPAPI.@)
3270 SetupDiInstallClassW(
3271 IN HWND hwndParent OPTIONAL
,
3272 IN PCWSTR InfFileName
,
3274 IN HSPFILEQ FileQueue OPTIONAL
)
3276 return SetupDiInstallClassExW(hwndParent
, InfFileName
, Flags
, FileQueue
, NULL
, NULL
, NULL
);
3280 /***********************************************************************
3281 * SetupDiInstallClassExA (SETUPAPI.@)
3284 SetupDiInstallClassExA(
3285 IN HWND hwndParent OPTIONAL
,
3286 IN PCSTR InfFileName OPTIONAL
,
3288 IN HSPFILEQ FileQueue OPTIONAL
,
3289 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3293 PWSTR InfFileNameW
= NULL
;
3298 InfFileNameW
= MultiByteToUnicode(InfFileName
, CP_ACP
);
3299 if (InfFileNameW
== NULL
)
3301 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3306 Result
= SetupDiInstallClassExW(hwndParent
, InfFileNameW
, Flags
,
3307 FileQueue
, InterfaceClassGuid
, Reserved1
, Reserved2
);
3309 MyFree(InfFileNameW
);
3316 CreateClassKey(HINF hInf
)
3318 WCHAR FullBuffer
[MAX_PATH
];
3319 WCHAR Buffer
[MAX_PATH
];
3321 HKEY hClassKey
= NULL
;
3322 HKEY ret
= INVALID_HANDLE_VALUE
;
3324 FullBuffer
[0] = '\0';
3326 if (!SetupGetLineTextW(NULL
,
3337 lstrcpyW(FullBuffer
, REGSTR_PATH_CLASS_NT
);
3338 lstrcatW(FullBuffer
, Buffer
);
3340 if (!SetupGetLineTextW(NULL
,
3348 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3352 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
3356 REG_OPTION_NON_VOLATILE
,
3365 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
3370 RequiredSize
* sizeof(WCHAR
)))
3378 if (hClassKey
!= NULL
&& hClassKey
!= ret
)
3379 RegCloseKey(hClassKey
);
3380 if (ret
== INVALID_HANDLE_VALUE
&& FullBuffer
[0] != '\0')
3381 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
3386 /***********************************************************************
3387 * SetupDiInstallClassExW (SETUPAPI.@)
3390 SetupDiInstallClassExW(
3391 IN HWND hwndParent OPTIONAL
,
3392 IN PCWSTR InfFileName OPTIONAL
,
3394 IN HSPFILEQ FileQueue OPTIONAL
,
3395 IN CONST GUID
*InterfaceClassGuid OPTIONAL
,
3401 TRACE("%p %s 0x%lx %p %s %p %p\n", hwndParent
, debugstr_w(InfFileName
), Flags
,
3402 FileQueue
, debugstr_guid(InterfaceClassGuid
), Reserved1
, Reserved2
);
3406 FIXME("Case not implemented: InfFileName NULL\n");
3407 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3409 else if (Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
))
3411 TRACE("Unknown flags: 0x%08lx\n", Flags
& ~(DI_NOVCP
| DI_NOBROWSE
| DI_FORCECOPY
| DI_QUIETINSTALL
));
3412 SetLastError(ERROR_INVALID_FLAGS
);
3414 else if ((Flags
& DI_NOVCP
) && FileQueue
== NULL
)
3415 SetLastError(ERROR_INVALID_PARAMETER
);
3416 else if (Reserved1
!= NULL
)
3417 SetLastError(ERROR_INVALID_PARAMETER
);
3418 else if (Reserved2
!= NULL
)
3419 SetLastError(ERROR_INVALID_PARAMETER
);
3422 HDEVINFO hDeviceInfo
= INVALID_HANDLE_VALUE
;
3423 SP_DEVINSTALL_PARAMS_W InstallParams
;
3424 WCHAR SectionName
[MAX_PATH
];
3425 HINF hInf
= INVALID_HANDLE_VALUE
;
3426 HKEY hRootKey
= INVALID_HANDLE_VALUE
;
3427 PVOID callback_context
= NULL
;
3429 hDeviceInfo
= SetupDiCreateDeviceInfoList(NULL
, NULL
);
3431 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS
);
3432 if (!SetupDiGetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3434 InstallParams
.Flags
&= ~(DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3435 InstallParams
.Flags
|= Flags
& (DI_NOVCP
| DI_NOBROWSE
| DI_QUIETINSTALL
);
3436 if (Flags
& DI_NOVCP
)
3437 InstallParams
.FileQueue
= FileQueue
;
3438 if (!SetupDiSetDeviceInstallParamsW(hDeviceInfo
, NULL
, &InstallParams
))
3441 /* Open the .inf file */
3442 hInf
= SetupOpenInfFileW(
3447 if (hInf
== INVALID_HANDLE_VALUE
)
3450 /* Try to append a layout file */
3451 ret
= SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
3455 if (InterfaceClassGuid
)
3457 /* Retrieve the actual section name */
3458 ret
= SetupDiGetActualSectionToInstallW(
3468 /* Open registry key related to this interface */
3469 /* FIXME: What happens if the key doesn't exist? */
3470 hRootKey
= SetupDiOpenClassRegKeyExW(InterfaceClassGuid
, KEY_ENUMERATE_SUB_KEYS
, DIOCR_INTERFACE
, NULL
, NULL
);
3471 if (hRootKey
== INVALID_HANDLE_VALUE
)
3474 /* SetupDiCreateDeviceInterface??? */
3475 FIXME("Installing an interface is not implemented\n");
3476 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3480 /* Create or open the class registry key 'HKLM\CurrentControlSet\Class\{GUID}' */
3481 hRootKey
= CreateClassKey(hInf
);
3482 if (hRootKey
== INVALID_HANDLE_VALUE
)
3485 /* Retrieve the actual section name */
3486 ret
= SetupDiGetActualSectionToInstallW(
3490 MAX_PATH
- strlenW(DotServices
),
3496 callback_context
= SetupInitDefaultQueueCallback(hwndParent
);
3497 if (!callback_context
)
3500 ret
= SetupInstallFromInfSectionW(
3504 SPINST_REGISTRY
| SPINST_FILES
| SPINST_BITREG
| SPINST_INIFILES
| SPINST_INI2REG
,
3506 NULL
, /* FIXME: SourceRootPath */
3507 !(Flags
& DI_NOVCP
) && (Flags
& DI_FORCECOPY
) ? SP_COPY_FORCE_IN_USE
: 0, /* CopyFlags */
3508 SetupDefaultQueueCallbackW
,
3515 /* Install .Services section */
3516 lstrcatW(SectionName
, DotServices
);
3517 ret
= SetupInstallServicesFromInfSectionExW(
3532 if (hDeviceInfo
!= INVALID_HANDLE_VALUE
)
3533 SetupDiDestroyDeviceInfoList(hDeviceInfo
);
3534 if (hInf
!= INVALID_HANDLE_VALUE
)
3535 SetupCloseInfFile(hInf
);
3536 if (hRootKey
!= INVALID_HANDLE_VALUE
)
3537 RegCloseKey(hRootKey
);
3538 SetupTermDefaultQueueCallback(callback_context
);
3541 TRACE("Returning %d\n", ret
);
3546 /***********************************************************************
3547 * SetupDiOpenClassRegKey (SETUPAPI.@)
3550 SetupDiOpenClassRegKey(
3551 IN CONST GUID
*ClassGuid OPTIONAL
,
3552 IN REGSAM samDesired
)
3554 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3555 DIOCR_INSTALLER
, NULL
, NULL
);
3559 /***********************************************************************
3560 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
3563 SetupDiOpenClassRegKeyExA(
3564 IN CONST GUID
*ClassGuid OPTIONAL
,
3565 IN REGSAM samDesired
,
3567 IN PCSTR MachineName OPTIONAL
,
3570 PWSTR MachineNameW
= NULL
;
3577 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
3578 if (MachineNameW
== NULL
)
3579 return INVALID_HANDLE_VALUE
;
3582 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
3583 Flags
, MachineNameW
, Reserved
);
3586 MyFree(MachineNameW
);
3592 /***********************************************************************
3593 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
3596 SetupDiOpenClassRegKeyExW(
3597 IN CONST GUID
* ClassGuid OPTIONAL
,
3598 IN REGSAM samDesired
,
3600 IN PCWSTR MachineName OPTIONAL
,
3603 LPWSTR lpGuidString
= NULL
;
3604 LPWSTR lpFullGuidString
= NULL
;
3607 HKEY hClassesKey
= NULL
;
3608 HKEY hClassKey
= NULL
;
3609 HKEY ret
= INVALID_HANDLE_VALUE
;
3613 TRACE("%s 0x%lx 0x%lx %s %p\n", debugstr_guid(ClassGuid
), samDesired
,
3614 Flags
, debugstr_w(MachineName
), Reserved
);
3616 if (Flags
== DIOCR_INSTALLER
)
3617 lpKeyName
= REGSTR_PATH_CLASS_NT
;
3618 else if (Flags
== DIOCR_INTERFACE
)
3619 lpKeyName
= REGSTR_PATH_DEVICE_CLASSES
;
3622 ERR("Invalid Flags parameter!\n");
3623 SetLastError(ERROR_INVALID_FLAGS
);
3627 if (MachineName
!= NULL
)
3629 rc
= RegConnectRegistryW(MachineName
, HKEY_LOCAL_MACHINE
, &HKLM
);
3630 if (rc
!= ERROR_SUCCESS
)
3637 HKLM
= HKEY_LOCAL_MACHINE
;
3639 rc
= RegOpenKeyExW(HKLM
,
3642 ClassGuid
? 0 : samDesired
,
3644 if (MachineName
!= NULL
) RegCloseKey(HKLM
);
3645 if (rc
!= ERROR_SUCCESS
)
3651 if (ClassGuid
== NULL
)
3653 /* Stop here. We don't need to open a subkey */
3658 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
3660 SetLastError(ERROR_GEN_FAILURE
);
3664 dwLength
= lstrlenW(lpGuidString
);
3665 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
3666 if (!lpFullGuidString
)
3668 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3671 lpFullGuidString
[0] = '{';
3672 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
3673 lpFullGuidString
[dwLength
+ 1] = '}';
3674 lpFullGuidString
[dwLength
+ 2] = '\0';
3676 rc
= RegOpenKeyExW(hClassesKey
,
3681 if (rc
!= ERROR_SUCCESS
)
3689 if (hClassKey
!= NULL
&& hClassKey
!= ret
)
3690 RegCloseKey(hClassKey
);
3691 if (hClassesKey
!= NULL
&& hClassesKey
!= ret
)
3692 RegCloseKey(hClassesKey
);
3694 RpcStringFreeW(&lpGuidString
);
3695 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
3700 /***********************************************************************
3701 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
3704 SetupDiOpenDeviceInterfaceW(
3705 IN HDEVINFO DeviceInfoSet
,
3706 IN PCWSTR DevicePath
,
3708 OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL
)
3710 FIXME("%p %s %08lx %p\n",
3711 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3715 /***********************************************************************
3716 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
3719 SetupDiOpenDeviceInterfaceA(
3720 IN HDEVINFO DeviceInfoSet
,
3721 IN PCSTR DevicePath
,
3723 OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL
)
3725 LPWSTR DevicePathW
= NULL
;
3728 TRACE("%p %s %08lx %p\n", DeviceInfoSet
, debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
3730 DevicePathW
= MultiByteToUnicode(DevicePath
, CP_ACP
);
3731 if (DevicePathW
== NULL
)
3734 bResult
= SetupDiOpenDeviceInterfaceW(DeviceInfoSet
,
3735 DevicePathW
, OpenFlags
, DeviceInterfaceData
);
3737 MyFree(DevicePathW
);
3742 /***********************************************************************
3743 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
3746 SetupDiSetClassInstallParamsA(
3747 IN HDEVINFO DeviceInfoSet
,
3748 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3749 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3750 IN DWORD ClassInstallParamsSize
)
3752 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
3753 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
3757 /***********************************************************************
3758 * SetupDiSetClassInstallParamsW (SETUPAPI.@)
3761 SetupDiSetClassInstallParamsW(
3762 IN HDEVINFO DeviceInfoSet
,
3763 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
3764 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3765 IN DWORD ClassInstallParamsSize
)
3767 struct DeviceInfoSet
*list
;
3770 TRACE("%p %p %p %lu\n", DeviceInfoSet
, DeviceInfoData
,
3771 ClassInstallParams
, ClassInstallParamsSize
);
3774 SetLastError(ERROR_INVALID_PARAMETER
);
3775 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3776 SetLastError(ERROR_INVALID_HANDLE
);
3777 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3778 SetLastError(ERROR_INVALID_HANDLE
);
3779 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3780 SetLastError(ERROR_INVALID_USER_BUFFER
);
3781 else if (ClassInstallParams
&& ClassInstallParams
->cbSize
!= sizeof(SP_CLASSINSTALL_HEADER
))
3782 SetLastError(ERROR_INVALID_USER_BUFFER
);
3783 else if (ClassInstallParams
&& ClassInstallParamsSize
< sizeof(SP_CLASSINSTALL_HEADER
))
3784 SetLastError(ERROR_INVALID_PARAMETER
);
3785 else if (!ClassInstallParams
&& ClassInstallParamsSize
!= 0)
3786 SetLastError(ERROR_INVALID_PARAMETER
);
3789 SP_DEVINSTALL_PARAMS_W InstallParams
;
3792 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
3793 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3797 if (ClassInstallParams
)
3799 /* Check parameters in ClassInstallParams */
3800 if (ClassInstallParams
->InstallFunction
< DIF_SELECTDEVICE
3801 || ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
>= sizeof(UpdateClassInstallParamHandlers
)/sizeof(UpdateClassInstallParamHandlers
[0]))
3803 SetLastError(ERROR_INVALID_USER_BUFFER
);
3806 else if (UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
] == NULL
)
3808 ERR("InstallFunction %u is valid, but has no associated update handler\n", ClassInstallParams
->InstallFunction
);
3809 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
3812 ret
= UpdateClassInstallParamHandlers
[ClassInstallParams
->InstallFunction
- DIF_SELECTDEVICE
](DeviceInfoSet
, DeviceInfoData
, ClassInstallParams
, ClassInstallParamsSize
);
3815 InstallParams
.Flags
|= DI_CLASSINSTALLPARAMS
;
3819 InstallParams
.Flags
&= ~DI_CLASSINSTALLPARAMS
;
3822 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
3826 TRACE("Returning %d\n", ret
);
3831 PropertyChangeHandler(
3832 IN HDEVINFO DeviceInfoSet
,
3833 IN PSP_DEVINFO_DATA DeviceInfoData
,
3834 IN PSP_CLASSINSTALL_HEADER ClassInstallParams OPTIONAL
,
3835 IN DWORD ClassInstallParamsSize
)
3837 PSP_PROPCHANGE_PARAMS PropChangeParams
= (PSP_PROPCHANGE_PARAMS
)ClassInstallParams
;
3840 if (!DeviceInfoData
)
3841 SetLastError(ERROR_INVALID_PARAMETER
);
3842 else if (ClassInstallParamsSize
!= sizeof(SP_PROPCHANGE_PARAMS
))
3843 SetLastError(ERROR_INVALID_PARAMETER
);
3844 else if (PropChangeParams
&& PropChangeParams
->StateChange
!= DICS_ENABLE
3845 && PropChangeParams
->StateChange
!= DICS_DISABLE
&& PropChangeParams
->StateChange
!= DICS_PROPCHANGE
3846 && PropChangeParams
->StateChange
!= DICS_START
&& PropChangeParams
->StateChange
!= DICS_STOP
)
3847 SetLastError(ERROR_INVALID_FLAGS
);
3848 else if (PropChangeParams
&& PropChangeParams
->Scope
!= DICS_FLAG_GLOBAL
3849 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3850 SetLastError(ERROR_INVALID_FLAGS
);
3851 else if (PropChangeParams
3852 && (PropChangeParams
->StateChange
== DICS_START
|| PropChangeParams
->StateChange
== DICS_STOP
)
3853 && PropChangeParams
->Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
3854 SetLastError(ERROR_INVALID_USER_BUFFER
);
3857 PSP_PROPCHANGE_PARAMS
*CurrentPropChangeParams
;
3858 if (!DeviceInfoData
)
3860 struct DeviceInfoSet
*list
= (struct DeviceInfoSet
*)DeviceInfoSet
;
3861 CurrentPropChangeParams
= &list
->ClassInstallParams
.PropChange
;
3865 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
3866 CurrentPropChangeParams
= &deviceInfo
->ClassInstallParams
.PropChange
;
3868 if (*CurrentPropChangeParams
)
3870 MyFree(*CurrentPropChangeParams
);
3871 *CurrentPropChangeParams
= NULL
;
3873 if (PropChangeParams
)
3875 *CurrentPropChangeParams
= MyMalloc(sizeof(SP_PROPCHANGE_PARAMS
));
3876 if (!*CurrentPropChangeParams
)
3878 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3881 memcpy(*CurrentPropChangeParams
, PropChangeParams
, sizeof(SP_PROPCHANGE_PARAMS
));
3892 IN PWSTR InstallerName
,
3893 OUT HMODULE
* ModulePointer
,
3894 OUT PVOID
* FunctionPointer
)
3896 HMODULE hModule
= NULL
;
3897 LPSTR FunctionNameA
= NULL
;
3901 *ModulePointer
= NULL
;
3902 *FunctionPointer
= NULL
;
3904 Comma
= strchrW(InstallerName
, ',');
3907 rc
= ERROR_INVALID_PARAMETER
;
3913 hModule
= LoadLibraryW(InstallerName
);
3917 rc
= GetLastError();
3921 /* Skip comma spaces */
3922 while (*Comma
== ',' || isspaceW(*Comma
))
3925 /* W->A conversion for function name */
3926 FunctionNameA
= UnicodeToMultiByte(Comma
, CP_ACP
);
3929 rc
= GetLastError();
3933 /* Search function */
3934 *FunctionPointer
= GetProcAddress(hModule
, FunctionNameA
);
3935 if (!*FunctionPointer
)
3937 rc
= GetLastError();
3941 *ModulePointer
= hModule
;
3945 if (rc
!= ERROR_SUCCESS
&& hModule
)
3946 FreeLibrary(hModule
);
3947 MyFree(FunctionNameA
);
3952 FreeFunctionPointer(
3953 IN HMODULE ModulePointer
,
3954 IN PVOID FunctionPointer
)
3956 if (ModulePointer
== NULL
)
3957 return ERROR_SUCCESS
;
3958 if (FreeLibrary(ModulePointer
))
3959 return ERROR_SUCCESS
;
3961 return GetLastError();
3965 IntSetupDiRegisterDeviceInfo(
3966 IN HDEVINFO DeviceInfoSet
,
3967 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
3969 return SetupDiRegisterDeviceInfo(DeviceInfoSet
, DeviceInfoData
, 0, NULL
, NULL
, NULL
);
3972 /***********************************************************************
3973 * SetupDiCallClassInstaller (SETUPAPI.@)
3976 SetupDiCallClassInstaller(
3977 IN DI_FUNCTION InstallFunction
,
3978 IN HDEVINFO DeviceInfoSet
,
3979 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
3983 TRACE("%u %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
3986 SetLastError(ERROR_INVALID_PARAMETER
);
3987 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
3988 SetLastError(ERROR_INVALID_HANDLE
);
3989 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
3990 SetLastError(ERROR_INVALID_HANDLE
);
3991 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
3992 SetLastError(ERROR_INVALID_HANDLE
);
3993 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
3994 SetLastError(ERROR_INVALID_USER_BUFFER
);
3997 SP_DEVINSTALL_PARAMS_W InstallParams
;
3998 #define CLASS_COINSTALLER 0x1
3999 #define DEVICE_COINSTALLER 0x2
4000 #define CLASS_INSTALLER 0x4
4001 UCHAR CanHandle
= 0;
4002 DEFAULT_CLASS_INSTALL_PROC DefaultHandler
= NULL
;
4004 switch (InstallFunction
)
4006 case DIF_ADDPROPERTYPAGE_ADVANCED
:
4007 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4009 case DIF_ADDREMOTEPROPERTYPAGE_ADVANCED
:
4010 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4012 case DIF_ALLOW_INSTALL
:
4013 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4016 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4018 case DIF_DESTROYPRIVATEDATA
:
4019 CanHandle
= CLASS_INSTALLER
;
4021 case DIF_INSTALLDEVICE
:
4022 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4023 DefaultHandler
= SetupDiInstallDevice
;
4025 case DIF_INSTALLDEVICEFILES
:
4026 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4027 DefaultHandler
= SetupDiInstallDriverFiles
;
4029 case DIF_INSTALLINTERFACES
:
4030 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4031 DefaultHandler
= SetupDiInstallDeviceInterfaces
;
4033 case DIF_NEWDEVICEWIZARD_FINISHINSTALL
:
4034 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4036 case DIF_NEWDEVICEWIZARD_POSTANALYZE
:
4037 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4039 case DIF_NEWDEVICEWIZARD_PREANALYZE
:
4040 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4042 case DIF_NEWDEVICEWIZARD_PRESELECT
:
4043 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4045 case DIF_NEWDEVICEWIZARD_SELECT
:
4046 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4048 case DIF_POWERMESSAGEWAKE
:
4049 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4051 case DIF_PROPERTYCHANGE
:
4052 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4053 DefaultHandler
= SetupDiChangeState
;
4055 case DIF_REGISTER_COINSTALLERS
:
4056 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4057 DefaultHandler
= SetupDiRegisterCoDeviceInstallers
;
4059 case DIF_REGISTERDEVICE
:
4060 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4061 DefaultHandler
= IntSetupDiRegisterDeviceInfo
;
4064 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4065 DefaultHandler
= SetupDiRemoveDevice
;
4067 case DIF_SELECTBESTCOMPATDRV
:
4068 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4069 DefaultHandler
= SetupDiSelectBestCompatDrv
;
4071 case DIF_SELECTDEVICE
:
4072 CanHandle
= CLASS_COINSTALLER
| CLASS_INSTALLER
;
4073 DefaultHandler
= SetupDiSelectDevice
;
4075 case DIF_TROUBLESHOOTER
:
4076 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4079 CanHandle
= CLASS_COINSTALLER
| DEVICE_COINSTALLER
| CLASS_INSTALLER
;
4080 DefaultHandler
= SetupDiUnremoveDevice
;
4083 ERR("Install function %u not supported\n", InstallFunction
);
4084 SetLastError(ERROR_NOT_SUPPORTED
);
4087 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4088 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
4089 /* Don't process this call, as a parameter is invalid */
4094 LIST_ENTRY ClassCoInstallersListHead
;
4095 LIST_ENTRY DeviceCoInstallersListHead
;
4096 HMODULE ClassInstallerLibrary
= NULL
;
4097 CLASS_INSTALL_PROC ClassInstaller
= NULL
;
4098 COINSTALLER_CONTEXT_DATA Context
;
4099 PLIST_ENTRY ListEntry
;
4101 DWORD dwRegType
, dwLength
;
4102 DWORD rc
= NO_ERROR
;
4104 InitializeListHead(&ClassCoInstallersListHead
);
4105 InitializeListHead(&DeviceCoInstallersListHead
);
4107 if (CanHandle
& DEVICE_COINSTALLER
)
4109 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4110 if (hKey
!= INVALID_HANDLE_VALUE
)
4112 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4113 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4115 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4116 if (KeyBuffer
!= NULL
)
4118 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_COINSTALLERS_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4119 if (rc
== ERROR_SUCCESS
)
4122 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4124 /* Add coinstaller to DeviceCoInstallersListHead list */
4125 struct CoInstallerElement
*coinstaller
;
4126 TRACE("Got device coinstaller '%s'\n", debugstr_w(ptr
));
4127 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4130 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
4131 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4132 InsertTailList(&DeviceCoInstallersListHead
, &coinstaller
->ListEntry
);
4134 HeapFree(GetProcessHeap(), 0, coinstaller
);
4137 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4143 if (CanHandle
& CLASS_COINSTALLER
)
4147 REGSTR_PATH_CODEVICEINSTALLERS
,
4151 if (rc
== ERROR_SUCCESS
)
4153 LPWSTR lpGuidString
;
4154 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) == RPC_S_OK
)
4156 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, &dwRegType
, NULL
, &dwLength
);
4157 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_MULTI_SZ
)
4159 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4160 if (KeyBuffer
!= NULL
)
4162 rc
= RegQueryValueExW(hKey
, lpGuidString
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4163 if (rc
== ERROR_SUCCESS
)
4166 for (ptr
= KeyBuffer
; *ptr
; ptr
+= strlenW(ptr
) + 1)
4168 /* Add coinstaller to ClassCoInstallersListHead list */
4169 struct CoInstallerElement
*coinstaller
;
4170 TRACE("Got class coinstaller '%s'\n", debugstr_w(ptr
));
4171 coinstaller
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct CoInstallerElement
));
4174 memset(coinstaller
, 0, sizeof(struct CoInstallerElement
));
4175 if (GetFunctionPointer(ptr
, &coinstaller
->Module
, (PVOID
*)&coinstaller
->Function
) == ERROR_SUCCESS
)
4176 InsertTailList(&ClassCoInstallersListHead
, &coinstaller
->ListEntry
);
4178 HeapFree(GetProcessHeap(), 0, coinstaller
);
4181 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4184 RpcStringFreeW(&lpGuidString
);
4189 if ((CanHandle
& CLASS_INSTALLER
) && !(InstallParams
.FlagsEx
& DI_FLAGSEX_CI_FAILED
))
4191 hKey
= SetupDiOpenClassRegKey(&DeviceInfoData
->ClassGuid
, KEY_QUERY_VALUE
);
4192 if (hKey
!= INVALID_HANDLE_VALUE
)
4194 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4195 if (rc
== ERROR_SUCCESS
&& dwRegType
== REG_SZ
)
4197 LPWSTR KeyBuffer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
4198 if (KeyBuffer
!= NULL
)
4200 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_INSTALLER_32
, NULL
, NULL
, (LPBYTE
)KeyBuffer
, &dwLength
);
4201 if (rc
== ERROR_SUCCESS
)
4203 /* Get ClassInstaller function pointer */
4204 TRACE("Got class installer '%s'\n", debugstr_w(KeyBuffer
));
4205 if (GetFunctionPointer(KeyBuffer
, &ClassInstallerLibrary
, (PVOID
*)&ClassInstaller
) != ERROR_SUCCESS
)
4207 InstallParams
.FlagsEx
|= DI_FLAGSEX_CI_FAILED
;
4208 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
4211 HeapFree(GetProcessHeap(), 0, KeyBuffer
);
4218 /* Call Class co-installers */
4219 Context
.PostProcessing
= FALSE
;
4221 ListEntry
= ClassCoInstallersListHead
.Flink
;
4222 while (rc
== NO_ERROR
&& ListEntry
!= &ClassCoInstallersListHead
)
4224 struct CoInstallerElement
*coinstaller
;
4225 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4226 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4227 coinstaller
->PrivateData
= Context
.PrivateData
;
4228 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4230 coinstaller
->DoPostProcessing
= TRUE
;
4233 ListEntry
= ListEntry
->Flink
;
4236 /* Call Device co-installers */
4237 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4238 while (rc
== NO_ERROR
&& ListEntry
!= &DeviceCoInstallersListHead
)
4240 struct CoInstallerElement
*coinstaller
;
4241 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4242 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4243 coinstaller
->PrivateData
= Context
.PrivateData
;
4244 if (rc
== ERROR_DI_POSTPROCESSING_REQUIRED
)
4246 coinstaller
->DoPostProcessing
= TRUE
;
4249 ListEntry
= ListEntry
->Flink
;
4252 /* Call Class installer */
4255 rc
= (*ClassInstaller
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
4256 FreeFunctionPointer(ClassInstallerLibrary
, ClassInstaller
);
4259 rc
= ERROR_DI_DO_DEFAULT
;
4261 /* Call default handler */
4262 if (rc
== ERROR_DI_DO_DEFAULT
)
4264 if (DefaultHandler
&& !(InstallParams
.Flags
& DI_NODI_DEFAULTACTION
))
4266 if ((*DefaultHandler
)(DeviceInfoSet
, DeviceInfoData
))
4269 rc
= GetLastError();
4275 /* Call Class co-installers that required postprocessing */
4276 Context
.PostProcessing
= TRUE
;
4277 ListEntry
= ClassCoInstallersListHead
.Flink
;
4278 while (ListEntry
!= &ClassCoInstallersListHead
)
4280 struct CoInstallerElement
*coinstaller
;
4281 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4282 if (coinstaller
->DoPostProcessing
)
4284 Context
.InstallResult
= rc
;
4285 Context
.PrivateData
= coinstaller
->PrivateData
;
4286 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4288 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4289 ListEntry
= ListEntry
->Flink
;
4292 /* Call Device co-installers that required postprocessing */
4293 ListEntry
= DeviceCoInstallersListHead
.Flink
;
4294 while (ListEntry
!= &DeviceCoInstallersListHead
)
4296 struct CoInstallerElement
*coinstaller
;
4297 coinstaller
= CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
);
4298 if (coinstaller
->DoPostProcessing
)
4300 Context
.InstallResult
= rc
;
4301 Context
.PrivateData
= coinstaller
->PrivateData
;
4302 rc
= (*coinstaller
->Function
)(InstallFunction
, DeviceInfoSet
, DeviceInfoData
, &Context
);
4304 FreeFunctionPointer(coinstaller
->Module
, coinstaller
->Function
);
4305 ListEntry
= ListEntry
->Flink
;
4308 /* Free allocated memory */
4309 while (!IsListEmpty(&ClassCoInstallersListHead
))
4311 ListEntry
= RemoveHeadList(&ClassCoInstallersListHead
);
4312 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4314 while (!IsListEmpty(&DeviceCoInstallersListHead
))
4316 ListEntry
= RemoveHeadList(&DeviceCoInstallersListHead
);
4317 HeapFree(GetProcessHeap(), 0, CONTAINING_RECORD(ListEntry
, struct CoInstallerElement
, ListEntry
));
4320 ret
= (rc
== NO_ERROR
);
4324 TRACE("Returning %d\n", ret
);
4328 /***********************************************************************
4329 * SetupDiGetDeviceInfoListClass (SETUPAPI.@)
4332 SetupDiGetDeviceInfoListClass(
4333 IN HDEVINFO DeviceInfoSet
,
4334 OUT LPGUID ClassGuid
)
4336 struct DeviceInfoSet
*list
;
4339 TRACE("%p %p\n", DeviceInfoSet
, ClassGuid
);
4342 SetLastError(ERROR_INVALID_HANDLE
);
4343 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4344 SetLastError(ERROR_INVALID_HANDLE
);
4345 else if (IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4346 SetLastError(ERROR_NO_ASSOCIATED_CLASS
);
4349 memcpy(&ClassGuid
, &list
->ClassGuid
, sizeof(GUID
));
4354 TRACE("Returning %d\n", ret
);
4358 /***********************************************************************
4359 * SetupDiGetDeviceInfoListDetailW (SETUPAPI.@)
4362 SetupDiGetDeviceInfoListDetailW(
4363 IN HDEVINFO DeviceInfoSet
,
4364 OUT PSP_DEVINFO_LIST_DETAIL_DATA_W DeviceInfoListDetailData
)
4366 struct DeviceInfoSet
*list
;
4369 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoListDetailData
);
4372 SetLastError(ERROR_INVALID_HANDLE
);
4373 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4374 SetLastError(ERROR_INVALID_HANDLE
);
4375 else if (!DeviceInfoListDetailData
)
4376 SetLastError(ERROR_INVALID_PARAMETER
);
4377 else if (DeviceInfoListDetailData
->cbSize
!= sizeof(SP_DEVINFO_LIST_DETAIL_DATA_W
))
4378 SetLastError(ERROR_INVALID_USER_BUFFER
);
4382 &DeviceInfoListDetailData
->ClassGuid
,
4385 DeviceInfoListDetailData
->RemoteMachineHandle
= list
->hMachine
;
4386 if (list
->MachineName
)
4387 strcpyW(DeviceInfoListDetailData
->RemoteMachineName
, list
->MachineName
+ 2);
4389 DeviceInfoListDetailData
->RemoteMachineName
[0] = 0;
4394 TRACE("Returning %d\n", ret
);
4398 /***********************************************************************
4399 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
4402 SetupDiGetDeviceInstallParamsA(
4403 IN HDEVINFO DeviceInfoSet
,
4404 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4405 OUT PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
4407 SP_DEVINSTALL_PARAMS_W deviceInstallParamsW
;
4410 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4412 if (DeviceInstallParams
== NULL
)
4413 SetLastError(ERROR_INVALID_PARAMETER
);
4414 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_A
))
4415 SetLastError(ERROR_INVALID_USER_BUFFER
);
4418 deviceInstallParamsW
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
4419 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &deviceInstallParamsW
);
4423 /* Do W->A conversion */
4425 DeviceInstallParams
,
4426 &deviceInstallParamsW
,
4427 FIELD_OFFSET(SP_DEVINSTALL_PARAMS_W
, DriverPath
));
4428 if (WideCharToMultiByte(CP_ACP
, 0, deviceInstallParamsW
.DriverPath
, -1,
4429 DeviceInstallParams
->DriverPath
, MAX_PATH
, NULL
, NULL
) == 0)
4431 DeviceInstallParams
->DriverPath
[0] = '\0';
4437 TRACE("Returning %d\n", ret
);
4441 /***********************************************************************
4442 * SetupDiGetDeviceInstallParamsW (SETUPAPI.@)
4445 SetupDiGetDeviceInstallParamsW(
4446 IN HDEVINFO DeviceInfoSet
,
4447 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4448 OUT PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4450 struct DeviceInfoSet
*list
;
4453 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4456 SetLastError(ERROR_INVALID_HANDLE
);
4457 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4458 SetLastError(ERROR_INVALID_HANDLE
);
4459 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4460 SetLastError(ERROR_INVALID_USER_BUFFER
);
4461 else if (!DeviceInstallParams
)
4462 SetLastError(ERROR_INVALID_PARAMETER
);
4463 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4464 SetLastError(ERROR_INVALID_USER_BUFFER
);
4467 PSP_DEVINSTALL_PARAMS_W Source
;
4470 Source
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4472 Source
= &list
->InstallParams
;
4473 memcpy(DeviceInstallParams
, Source
, Source
->cbSize
);
4477 TRACE("Returning %d\n", ret
);
4482 CheckDeviceInstallParameters(
4483 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4485 DWORD SupportedFlags
=
4486 DI_NOVCP
| /* 0x00000008 */
4487 DI_DIDCOMPAT
| /* 0x00000010 */
4488 DI_DIDCLASS
| /* 0x00000020 */
4489 DI_NEEDRESTART
| /* 0x00000080 */
4490 DI_NEEDREBOOT
| /* 0x00000100 */
4491 DI_RESOURCEPAGE_ADDED
| /* 0x00002000 */
4492 DI_PROPERTIES_CHANGE
| /* 0x00004000 */
4493 DI_ENUMSINGLEINF
| /* 0x00010000 */
4494 DI_DONOTCALLCONFIGMG
| /* 0x00020000 */
4495 DI_CLASSINSTALLPARAMS
| /* 0x00100000 */
4496 DI_NODI_DEFAULTACTION
| /* 0x00200000 */
4497 DI_QUIETINSTALL
| /* 0x00800000 */
4498 DI_NOFILECOPY
| /* 0x01000000 */
4499 DI_DRIVERPAGE_ADDED
; /* 0x04000000 */
4500 DWORD SupportedFlagsEx
=
4501 DI_FLAGSEX_CI_FAILED
| /* 0x00000004 */
4502 DI_FLAGSEX_DIDINFOLIST
| /* 0x00000010 */
4503 DI_FLAGSEX_DIDCOMPATINFO
| /* 0x00000020 */
4504 DI_FLAGSEX_ALLOWEXCLUDEDDRVS
| /* 0x00000800 */
4505 DI_FLAGSEX_NO_DRVREG_MODIFY
; /* 0x00008000 */
4508 /* FIXME: add support for more flags */
4510 /* FIXME: DI_CLASSINSTALLPARAMS flag is not correctly used.
4511 * It should be checked before accessing to other values
4512 * of the SP_DEVINSTALL_PARAMS structure */
4514 if (DeviceInstallParams
->Flags
& ~SupportedFlags
)
4516 FIXME("Unknown Flags: 0x%08lx\n", DeviceInstallParams
->Flags
& ~SupportedFlags
);
4517 SetLastError(ERROR_INVALID_FLAGS
);
4519 else if (DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
)
4521 FIXME("Unknown FlagsEx: 0x%08lx\n", DeviceInstallParams
->FlagsEx
& ~SupportedFlagsEx
);
4522 SetLastError(ERROR_INVALID_FLAGS
);
4524 else if ((DeviceInstallParams
->Flags
& DI_NOVCP
)
4525 && (DeviceInstallParams
->FileQueue
== NULL
|| DeviceInstallParams
->FileQueue
== (HSPFILEQ
)INVALID_HANDLE_VALUE
))
4526 SetLastError(ERROR_INVALID_USER_BUFFER
);
4529 /* FIXME: check Reserved field */
4536 /***********************************************************************
4537 * SetupDiSetDeviceInstallParamsW (SETUPAPI.@)
4540 SetupDiSetDeviceInstallParamsW(
4541 IN HDEVINFO DeviceInfoSet
,
4542 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4543 IN PSP_DEVINSTALL_PARAMS_W DeviceInstallParams
)
4545 struct DeviceInfoSet
*list
;
4548 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
4551 SetLastError(ERROR_INVALID_HANDLE
);
4552 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4553 SetLastError(ERROR_INVALID_HANDLE
);
4554 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4555 SetLastError(ERROR_INVALID_USER_BUFFER
);
4556 else if (!DeviceInstallParams
)
4557 SetLastError(ERROR_INVALID_PARAMETER
);
4558 else if (DeviceInstallParams
->cbSize
!= sizeof(SP_DEVINSTALL_PARAMS_W
))
4559 SetLastError(ERROR_INVALID_USER_BUFFER
);
4560 else if (CheckDeviceInstallParameters(DeviceInstallParams
))
4562 PSP_DEVINSTALL_PARAMS_W Destination
;
4565 Destination
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
;
4567 Destination
= &list
->InstallParams
;
4568 memcpy(Destination
, DeviceInstallParams
, DeviceInstallParams
->cbSize
);
4572 TRACE("Returning %d\n", ret
);
4576 /***********************************************************************
4577 * SetupDiGetDeviceInstanceIdA(SETUPAPI.@)
4580 SetupDiGetDeviceInstanceIdA(
4581 IN HDEVINFO DeviceInfoSet
,
4582 IN PSP_DEVINFO_DATA DeviceInfoData
,
4583 OUT PSTR DeviceInstanceId OPTIONAL
,
4584 IN DWORD DeviceInstanceIdSize
,
4585 OUT PDWORD RequiredSize OPTIONAL
)
4587 PWSTR DeviceInstanceIdW
= NULL
;
4590 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4591 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4593 if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4594 SetLastError(ERROR_INVALID_PARAMETER
);
4597 if (DeviceInstanceIdSize
!= 0)
4599 DeviceInstanceIdW
= MyMalloc(DeviceInstanceIdSize
* sizeof(WCHAR
));
4600 if (DeviceInstanceIdW
== NULL
)
4604 ret
= SetupDiGetDeviceInstanceIdW(DeviceInfoSet
, DeviceInfoData
,
4605 DeviceInstanceIdW
, DeviceInstanceIdSize
,
4608 if (ret
&& DeviceInstanceIdW
!= NULL
)
4610 if (WideCharToMultiByte(CP_ACP
, 0, DeviceInstanceIdW
, -1,
4611 DeviceInstanceId
, DeviceInstanceIdSize
, NULL
, NULL
) == 0)
4613 DeviceInstanceId
[0] = '\0';
4619 TRACE("Returning %d\n", ret
);
4623 /***********************************************************************
4624 * SetupDiGetDeviceInstanceIdW(SETUPAPI.@)
4627 SetupDiGetDeviceInstanceIdW(
4628 IN HDEVINFO DeviceInfoSet
,
4629 IN PSP_DEVINFO_DATA DeviceInfoData
,
4630 OUT PWSTR DeviceInstanceId OPTIONAL
,
4631 IN DWORD DeviceInstanceIdSize
,
4632 OUT PDWORD RequiredSize OPTIONAL
)
4636 TRACE("%p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
4637 DeviceInstanceId
, DeviceInstanceIdSize
, RequiredSize
);
4640 SetLastError(ERROR_INVALID_HANDLE
);
4641 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4642 SetLastError(ERROR_INVALID_HANDLE
);
4643 else if (!DeviceInfoData
)
4644 SetLastError(ERROR_INVALID_PARAMETER
);
4645 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4646 SetLastError(ERROR_INVALID_USER_BUFFER
);
4647 else if (!DeviceInstanceId
&& DeviceInstanceIdSize
> 0)
4648 SetLastError(ERROR_INVALID_PARAMETER
);
4649 else if (DeviceInstanceId
&& DeviceInstanceIdSize
== 0)
4650 SetLastError(ERROR_INVALID_PARAMETER
);
4653 struct DeviceInfoElement
*DevInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
4656 required
= (strlenW(DevInfo
->DeviceName
) + 1) * sizeof(WCHAR
);
4658 *RequiredSize
= required
;
4660 if (required
<= DeviceInstanceIdSize
)
4662 strcpyW(DeviceInstanceId
, DevInfo
->DeviceName
);
4666 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4669 TRACE("Returning %d\n", ret
);
4673 /***********************************************************************
4674 * SetupDiGetClassDevPropertySheetsA(SETUPAPI.@)
4677 SetupDiGetClassDevPropertySheetsA(
4678 IN HDEVINFO DeviceInfoSet
,
4679 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4680 IN LPPROPSHEETHEADERA PropertySheetHeader
,
4681 IN DWORD PropertySheetHeaderPageListSize
,
4682 OUT PDWORD RequiredSize OPTIONAL
,
4683 IN DWORD PropertySheetType
)
4685 PROPSHEETHEADERW psh
;
4688 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4689 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4690 RequiredSize
, PropertySheetType
);
4692 psh
.dwFlags
= PropertySheetHeader
->dwFlags
;
4693 psh
.phpage
= PropertySheetHeader
->phpage
;
4694 psh
.nPages
= PropertySheetHeader
->nPages
;
4696 ret
= SetupDiGetClassDevPropertySheetsW(DeviceInfoSet
, DeviceInfoData
, PropertySheetHeader
? &psh
: NULL
,
4697 PropertySheetHeaderPageListSize
, RequiredSize
,
4701 PropertySheetHeader
->nPages
= psh
.nPages
;
4704 TRACE("Returning %d\n", ret
);
4708 struct ClassDevPropertySheetsData
4710 HPROPSHEETPAGE
*PropertySheetPages
;
4711 DWORD MaximumNumberOfPages
;
4712 DWORD NumberOfPages
;
4716 GetClassDevPropertySheetsCallback(
4717 IN HPROPSHEETPAGE hPropSheetPage
,
4718 IN OUT LPARAM lParam
)
4720 struct ClassDevPropertySheetsData
*PropPageData
;
4722 PropPageData
= (struct ClassDevPropertySheetsData
*)lParam
;
4724 if (PropPageData
->NumberOfPages
< PropPageData
->MaximumNumberOfPages
)
4726 *PropPageData
->PropertySheetPages
= hPropSheetPage
;
4727 PropPageData
->PropertySheetPages
++;
4730 PropPageData
->NumberOfPages
++;
4734 /***********************************************************************
4735 * SetupDiGetClassDevPropertySheetsW(SETUPAPI.@)
4738 SetupDiGetClassDevPropertySheetsW(
4739 IN HDEVINFO DeviceInfoSet
,
4740 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
4741 IN OUT LPPROPSHEETHEADERW PropertySheetHeader
,
4742 IN DWORD PropertySheetHeaderPageListSize
,
4743 OUT PDWORD RequiredSize OPTIONAL
,
4744 IN DWORD PropertySheetType
)
4746 struct DeviceInfoSet
*list
;
4749 TRACE("%p %p %p 0%lx %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
4750 PropertySheetHeader
, PropertySheetHeaderPageListSize
,
4751 RequiredSize
, PropertySheetType
);
4754 SetLastError(ERROR_INVALID_HANDLE
);
4755 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4756 SetLastError(ERROR_INVALID_HANDLE
);
4757 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4758 SetLastError(ERROR_INVALID_HANDLE
);
4759 else if (!PropertySheetHeader
)
4760 SetLastError(ERROR_INVALID_PARAMETER
);
4761 else if (PropertySheetHeader
->dwFlags
& PSH_PROPSHEETPAGE
)
4762 SetLastError(ERROR_INVALID_FLAGS
);
4763 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4764 SetLastError(ERROR_INVALID_USER_BUFFER
);
4765 else if (!DeviceInfoData
&& IsEqualIID(&list
->ClassGuid
, &GUID_NULL
))
4766 SetLastError(ERROR_INVALID_PARAMETER
);
4767 else if (!PropertySheetHeader
)
4768 SetLastError(ERROR_INVALID_PARAMETER
);
4769 else if (PropertySheetType
!= DIGCDP_FLAG_ADVANCED
4770 && PropertySheetType
!= DIGCDP_FLAG_BASIC
4771 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_ADVANCED
4772 && PropertySheetType
!= DIGCDP_FLAG_REMOTE_BASIC
)
4773 SetLastError(ERROR_INVALID_PARAMETER
);
4776 HKEY hKey
= INVALID_HANDLE_VALUE
;
4777 SP_PROPSHEETPAGE_REQUEST Request
;
4778 LPWSTR PropPageProvider
= NULL
;
4779 HMODULE hModule
= NULL
;
4780 PROPERTY_PAGE_PROVIDER pPropPageProvider
= NULL
;
4781 struct ClassDevPropertySheetsData PropPageData
;
4782 DWORD dwLength
, dwRegType
;
4786 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_QUERY_VALUE
);
4789 hKey
= SetupDiOpenClassRegKeyExW(&list
->ClassGuid
, KEY_QUERY_VALUE
,
4790 DIOCR_INSTALLER
, list
->MachineName
+ 2, NULL
);
4792 if (hKey
== INVALID_HANDLE_VALUE
)
4795 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, &dwRegType
, NULL
, &dwLength
);
4796 if (rc
== ERROR_FILE_NOT_FOUND
)
4798 /* No registry key. As it is optional, don't say it's a bad error */
4804 else if (rc
!= ERROR_SUCCESS
&& dwRegType
!= REG_SZ
)
4810 PropPageProvider
= HeapAlloc(GetProcessHeap(), 0, dwLength
+ sizeof(WCHAR
));
4811 if (!PropPageProvider
)
4813 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
4816 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_ENUMPROPPAGES_32
, NULL
, NULL
, (LPBYTE
)PropPageProvider
, &dwLength
);
4817 if (rc
!= ERROR_SUCCESS
)
4822 PropPageProvider
[dwLength
/ sizeof(WCHAR
)] = 0;
4824 rc
= GetFunctionPointer(PropPageProvider
, &hModule
, (PVOID
*)&pPropPageProvider
);
4825 if (rc
!= ERROR_SUCCESS
)
4827 SetLastError(ERROR_INVALID_PROPPAGE_PROVIDER
);
4831 Request
.cbSize
= sizeof(SP_PROPSHEETPAGE_REQUEST
);
4832 Request
.PageRequested
= SPPSR_ENUM_ADV_DEVICE_PROPERTIES
;
4833 Request
.DeviceInfoSet
= DeviceInfoSet
;
4834 Request
.DeviceInfoData
= DeviceInfoData
;
4835 PropPageData
.PropertySheetPages
= &PropertySheetHeader
->phpage
[PropertySheetHeader
->nPages
];
4836 PropPageData
.MaximumNumberOfPages
= PropertySheetHeaderPageListSize
- PropertySheetHeader
->nPages
;
4837 PropPageData
.NumberOfPages
= 0;
4838 ret
= pPropPageProvider(&Request
, GetClassDevPropertySheetsCallback
, (LPARAM
)&PropPageData
);
4843 *RequiredSize
= PropPageData
.NumberOfPages
+ PropertySheetHeader
->nPages
;
4844 if (PropPageData
.NumberOfPages
<= PropPageData
.MaximumNumberOfPages
)
4846 PropertySheetHeader
->nPages
+= PropPageData
.NumberOfPages
;
4851 PropertySheetHeader
->nPages
+= PropPageData
.MaximumNumberOfPages
;
4852 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
4856 if (hKey
!= INVALID_HANDLE_VALUE
)
4858 HeapFree(GetProcessHeap(), 0, PropPageProvider
);
4859 FreeFunctionPointer(hModule
, pPropPageProvider
);
4862 TRACE("Returning %d\n", ret
);
4866 /***********************************************************************
4867 * SetupDiCreateDevRegKeyA (SETUPAPI.@)
4870 SetupDiCreateDevRegKeyA(
4871 IN HDEVINFO DeviceInfoSet
,
4872 IN PSP_DEVINFO_DATA DeviceInfoData
,
4876 IN HINF InfHandle OPTIONAL
,
4877 IN PCSTR InfSectionName OPTIONAL
)
4879 PCWSTR InfSectionNameW
= NULL
;
4880 HKEY ret
= INVALID_HANDLE_VALUE
;
4884 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
4885 if (InfSectionNameW
== NULL
) return INVALID_HANDLE_VALUE
;
4888 ret
= SetupDiCreateDevRegKeyW(DeviceInfoSet
,
4896 if (InfSectionNameW
!= NULL
)
4897 MyFree((PVOID
)InfSectionNameW
);
4903 OpenHardwareProfileKey(
4906 IN DWORD samDesired
)
4908 HKEY hHWProfilesKey
= NULL
;
4909 HKEY hHWProfileKey
= NULL
;
4910 HKEY ret
= INVALID_HANDLE_VALUE
;
4913 rc
= RegOpenKeyExW(HKLM
,
4914 REGSTR_PATH_HWPROFILES
,
4918 if (rc
!= ERROR_SUCCESS
)
4935 snprintfW(subKey
, 4, L
"%04lu", HwProfile
);
4944 if (rc
!= ERROR_SUCCESS
)
4949 ret
= hHWProfileKey
;
4952 if (hHWProfilesKey
!= NULL
)
4953 RegCloseKey(hHWProfilesKey
);
4954 if (hHWProfileKey
!= NULL
&& hHWProfileKey
!= ret
)
4955 RegCloseKey(hHWProfileKey
);
4959 /***********************************************************************
4960 * SetupDiCreateDevRegKeyW (SETUPAPI.@)
4963 SetupDiCreateDevRegKeyW(
4964 IN HDEVINFO DeviceInfoSet
,
4965 IN PSP_DEVINFO_DATA DeviceInfoData
,
4969 IN HINF InfHandle OPTIONAL
,
4970 IN PCWSTR InfSectionName OPTIONAL
)
4972 struct DeviceInfoSet
*list
;
4973 HKEY ret
= INVALID_HANDLE_VALUE
;
4975 TRACE("%p %p %lu %lu %lu %p %s\n", DeviceInfoSet
, DeviceInfoData
,
4976 Scope
, HwProfile
, KeyType
, InfHandle
, debugstr_w(InfSectionName
));
4979 SetLastError(ERROR_INVALID_HANDLE
);
4980 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
4981 SetLastError(ERROR_INVALID_HANDLE
);
4982 else if (!DeviceInfoData
)
4983 SetLastError(ERROR_INVALID_PARAMETER
);
4984 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
4985 SetLastError(ERROR_INVALID_USER_BUFFER
);
4986 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
4987 SetLastError(ERROR_INVALID_PARAMETER
);
4988 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
4989 SetLastError(ERROR_INVALID_PARAMETER
);
4990 else if (InfHandle
&& !InfSectionName
)
4991 SetLastError(ERROR_INVALID_PARAMETER
);
4992 else if (!InfHandle
&& InfSectionName
)
4993 SetLastError(ERROR_INVALID_PARAMETER
);
4996 LPWSTR lpGuidString
= NULL
;
4997 LPWSTR DriverKey
= NULL
; /* {GUID}\Index */
4998 LPWSTR pDeviceInstance
; /* Points into DriverKey, on the Index field */
4999 DWORD Index
; /* Index used in the DriverKey name */
5001 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
5002 HKEY hEnumKey
= NULL
;
5003 HKEY hClassKey
= NULL
;
5004 HKEY hDeviceKey
= INVALID_HANDLE_VALUE
;
5008 if (Scope
== DICS_FLAG_GLOBAL
)
5009 RootKey
= list
->HKLM
;
5010 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
5012 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, KEY_CREATE_SUB_KEY
);
5013 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
5015 RootKey
= hHWProfileKey
;
5018 if (KeyType
== DIREG_DEV
)
5020 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5022 rc
= RegCreateKeyExW(
5024 REGSTR_PATH_SYSTEMENUM
,
5027 REG_OPTION_NON_VOLATILE
,
5032 if (rc
!= ERROR_SUCCESS
)
5037 rc
= RegCreateKeyExW(
5039 deviceInfo
->DeviceName
,
5042 REG_OPTION_NON_VOLATILE
,
5043 #if _WIN32_WINNT >= 0x502
5044 KEY_READ
| KEY_WRITE
,
5051 if (rc
!= ERROR_SUCCESS
)
5057 else /* KeyType == DIREG_DRV */
5059 if (UuidToStringW((UUID
*)&DeviceInfoData
->ClassGuid
, &lpGuidString
) != RPC_S_OK
)
5061 /* The driver key is in \System\CurrentControlSet\Control\Class\{GUID}\Index */
5062 DriverKey
= HeapAlloc(GetProcessHeap(), 0, (strlenW(lpGuidString
) + 7) * sizeof(WCHAR
) + sizeof(UNICODE_STRING
));
5065 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5068 strcpyW(DriverKey
, L
"{");
5069 strcatW(DriverKey
, lpGuidString
);
5070 strcatW(DriverKey
, L
"}\\");
5071 pDeviceInstance
= &DriverKey
[strlenW(DriverKey
)];
5072 rc
= RegOpenKeyExW(RootKey
,
5073 REGSTR_PATH_CLASS_NT
,
5077 if (rc
!= ERROR_SUCCESS
)
5083 /* Try all values for Index between 0 and 9999 */
5085 while (Index
<= 9999)
5088 wsprintf(pDeviceInstance
, L
"%04lu", Index
);
5089 rc
= RegCreateKeyEx(hClassKey
,
5093 REG_OPTION_NON_VOLATILE
,
5094 #if _WIN32_WINNT >= 0x502
5095 KEY_READ
| KEY_WRITE
,
5102 if (rc
!= ERROR_SUCCESS
)
5107 if (Disposition
== REG_CREATED_NEW_KEY
)
5115 /* Unable to create more than 9999 devices within the same class */
5116 SetLastError(ERROR_GEN_FAILURE
);
5120 /* Open device key, to write Driver value */
5121 hDeviceKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, Scope
, HwProfile
, DIREG_DEV
, KEY_SET_VALUE
);
5122 if (hDeviceKey
== INVALID_HANDLE_VALUE
)
5124 rc
= RegSetValueEx(hDeviceKey
, REGSTR_VAL_DRIVER
, 0, REG_SZ
, (const BYTE
*)DriverKey
, (strlenW(DriverKey
) + 1) * sizeof(WCHAR
));
5125 if (rc
!= ERROR_SUCCESS
)
5132 /* Do installation of the specified section */
5135 FIXME("Need to install section %s in file %p\n",
5136 debugstr_w(InfSectionName
), InfHandle
);
5142 RpcStringFreeW(&lpGuidString
);
5143 HeapFree(GetProcessHeap(), 0, DriverKey
);
5144 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
5145 RegCloseKey(hHWProfileKey
);
5146 if (hEnumKey
!= NULL
)
5147 RegCloseKey(hEnumKey
);
5148 if (hClassKey
!= NULL
)
5149 RegCloseKey(hClassKey
);
5150 if (hDeviceKey
!= INVALID_HANDLE_VALUE
)
5151 RegCloseKey(hDeviceKey
);
5152 if (hKey
!= NULL
&& hKey
!= ret
)
5156 TRACE("Returning 0x%p\n", ret
);
5160 /***********************************************************************
5161 * SetupDiOpenDevRegKey (SETUPAPI.@)
5164 SetupDiOpenDevRegKey(
5165 IN HDEVINFO DeviceInfoSet
,
5166 IN PSP_DEVINFO_DATA DeviceInfoData
,
5170 IN REGSAM samDesired
)
5172 struct DeviceInfoSet
*list
;
5173 HKEY ret
= INVALID_HANDLE_VALUE
;
5175 TRACE("%p %p %lu %lu %lu 0x%lx\n", DeviceInfoSet
, DeviceInfoData
,
5176 Scope
, HwProfile
, KeyType
, samDesired
);
5179 SetLastError(ERROR_INVALID_HANDLE
);
5180 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5181 SetLastError(ERROR_INVALID_HANDLE
);
5182 else if (!DeviceInfoData
)
5183 SetLastError(ERROR_INVALID_PARAMETER
);
5184 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5185 SetLastError(ERROR_INVALID_USER_BUFFER
);
5186 else if (Scope
!= DICS_FLAG_GLOBAL
&& Scope
!= DICS_FLAG_CONFIGSPECIFIC
)
5187 SetLastError(ERROR_INVALID_PARAMETER
);
5188 else if (KeyType
!= DIREG_DEV
&& KeyType
!= DIREG_DRV
)
5189 SetLastError(ERROR_INVALID_PARAMETER
);
5192 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5193 LPWSTR DriverKey
= NULL
;
5197 HKEY hHWProfileKey
= INVALID_HANDLE_VALUE
;
5198 HKEY hEnumKey
= NULL
;
5202 if (Scope
== DICS_FLAG_GLOBAL
)
5203 RootKey
= list
->HKLM
;
5204 else /* Scope == DICS_FLAG_CONFIGSPECIFIC */
5206 hHWProfileKey
= OpenHardwareProfileKey(list
->HKLM
, HwProfile
, 0);
5207 if (hHWProfileKey
== INVALID_HANDLE_VALUE
)
5209 RootKey
= hHWProfileKey
;
5214 REGSTR_PATH_SYSTEMENUM
,
5218 if (rc
!= ERROR_SUCCESS
)
5225 deviceInfo
->DeviceName
,
5227 KeyType
== DIREG_DEV
? samDesired
: KEY_QUERY_VALUE
,
5229 RegCloseKey(hEnumKey
);
5231 if (rc
!= ERROR_SUCCESS
)
5236 if (KeyType
== DIREG_DEV
)
5238 /* We're done. Just return the hKey handle */
5242 /* Read the 'Driver' key */
5243 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, NULL
, &dwLength
);
5244 if (rc
!= ERROR_SUCCESS
)
5249 else if (dwRegType
!= REG_SZ
)
5251 SetLastError(ERROR_GEN_FAILURE
);
5254 DriverKey
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
5257 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5260 rc
= RegQueryValueExW(hKey
, REGSTR_VAL_DRIVER
, NULL
, &dwRegType
, (LPBYTE
)DriverKey
, &dwLength
);
5261 if (rc
!= ERROR_SUCCESS
)
5268 /* Need to open the driver key */
5271 REGSTR_PATH_CLASS_NT
,
5275 if (rc
!= ERROR_SUCCESS
)
5286 if (rc
!= ERROR_SUCCESS
)
5294 if (hHWProfileKey
!= INVALID_HANDLE_VALUE
)
5295 RegCloseKey(hHWProfileKey
);
5296 if (hEnumKey
!= NULL
)
5297 RegCloseKey(hEnumKey
);
5298 if (hKey
!= NULL
&& hKey
!= ret
)
5302 TRACE("Returning 0x%p\n", ret
);
5306 /***********************************************************************
5307 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
5310 SetupDiCreateDeviceInfoA(
5311 IN HDEVINFO DeviceInfoSet
,
5312 IN PCSTR DeviceName
,
5313 IN CONST GUID
*ClassGuid
,
5314 IN PCSTR DeviceDescription OPTIONAL
,
5315 IN HWND hwndParent OPTIONAL
,
5316 IN DWORD CreationFlags
,
5317 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5319 LPWSTR DeviceNameW
= NULL
;
5320 LPWSTR DeviceDescriptionW
= NULL
;
5327 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
5328 if (DeviceNameW
== NULL
) return FALSE
;
5330 if (DeviceDescription
)
5332 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
5333 if (DeviceDescriptionW
== NULL
)
5335 if (DeviceNameW
) MyFree(DeviceNameW
);
5340 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
5341 ClassGuid
, DeviceDescriptionW
,
5342 hwndParent
, CreationFlags
,
5345 if (DeviceNameW
) MyFree(DeviceNameW
);
5346 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
5351 /***********************************************************************
5352 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
5355 SetupDiCreateDeviceInfoW(
5356 IN HDEVINFO DeviceInfoSet
,
5357 IN PCWSTR DeviceName
,
5358 IN CONST GUID
*ClassGuid
,
5359 IN PCWSTR DeviceDescription OPTIONAL
,
5360 IN HWND hwndParent OPTIONAL
,
5361 IN DWORD CreationFlags
,
5362 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
5364 struct DeviceInfoSet
*list
;
5367 TRACE("%p %s %s %s %p %lx %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
5368 debugstr_guid(ClassGuid
), debugstr_w(DeviceDescription
),
5369 hwndParent
, CreationFlags
, DeviceInfoData
);
5372 SetLastError(ERROR_INVALID_HANDLE
);
5373 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5374 SetLastError(ERROR_INVALID_HANDLE
);
5375 else if (!ClassGuid
)
5376 SetLastError(ERROR_INVALID_PARAMETER
);
5377 else if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, ClassGuid
))
5378 SetLastError(ERROR_CLASS_MISMATCH
);
5379 else if (CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
))
5381 TRACE("Unknown flags: 0x%08lx\n", CreationFlags
& ~(DICD_GENERATE_ID
| DICD_INHERIT_CLASSDRVS
));
5382 SetLastError(ERROR_INVALID_FLAGS
);
5386 SP_DEVINFO_DATA DevInfo
;
5388 if (CreationFlags
& DICD_GENERATE_ID
)
5390 /* Generate a new unique ID for this device */
5391 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
5392 FIXME("not implemented\n");
5396 /* Device name is fully qualified. Try to open it */
5399 DevInfo
.cbSize
= sizeof(SP_DEVINFO_DATA
);
5400 rc
= SetupDiOpenDeviceInfoW(
5403 NULL
, /* hwndParent */
5404 CreationFlags
& DICD_INHERIT_CLASSDRVS
? DIOD_INHERIT_CLASSDRVS
: 0,
5409 /* SetupDiOpenDeviceInfoW has already added
5410 * the device info to the device info set
5412 SetLastError(ERROR_DEVINST_ALREADY_EXISTS
);
5414 else if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5416 struct DeviceInfoElement
*deviceInfo
;
5418 if (CreateDeviceInfoElement(list
, DeviceName
, ClassGuid
, &deviceInfo
))
5420 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
5422 if (!DeviceInfoData
)
5426 if (DeviceInfoData
->cbSize
!= sizeof(PSP_DEVINFO_DATA
))
5428 SetLastError(ERROR_INVALID_USER_BUFFER
);
5432 memcpy(&DeviceInfoData
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5433 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
5434 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
5443 TRACE("Returning %d\n", ret
);
5447 /***********************************************************************
5448 * Helper functions for SetupDiBuildDriverInfoList
5452 IN PLIST_ENTRY DriverListHead
,
5453 IN DWORD DriverType
, /* SPDIT_CLASSDRIVER or SPDIT_COMPATDRIVER */
5454 IN LPGUID ClassGuid
,
5455 IN INFCONTEXT ContextDevice
,
5456 IN
struct InfFileDetails
*InfFileDetails
,
5458 IN LPCWSTR ProviderName
,
5459 IN LPCWSTR ManufacturerName
,
5460 IN LPCWSTR MatchingId
,
5461 FILETIME DriverDate
,
5462 DWORDLONG DriverVersion
,
5465 struct DriverInfoElement
*driverInfo
= NULL
;
5466 HANDLE hFile
= INVALID_HANDLE_VALUE
;
5467 DWORD RequiredSize
= 128; /* Initial buffer size */
5468 BOOL Result
= FALSE
;
5469 PLIST_ENTRY PreviousEntry
;
5470 LPWSTR InfInstallSection
= NULL
;
5473 driverInfo
= HeapAlloc(GetProcessHeap(), 0, sizeof(struct DriverInfoElement
));
5476 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5479 memset(driverInfo
, 0, sizeof(struct DriverInfoElement
));
5481 driverInfo
->Details
.cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA
);
5482 driverInfo
->Details
.Reserved
= (ULONG_PTR
)driverInfo
;
5484 /* Copy InfFileName field */
5485 strncpyW(driverInfo
->Details
.InfFileName
, InfFile
, MAX_PATH
- 1);
5486 driverInfo
->Details
.InfFileName
[MAX_PATH
- 1] = '\0';
5488 /* Fill InfDate field */
5489 /* FIXME: hFile = CreateFile(driverInfo->Details.InfFileName,
5490 GENERIC_READ, FILE_SHARE_READ,
5491 NULL, OPEN_EXISTING, 0, NULL);
5492 if (hFile == INVALID_HANDLE_VALUE)
5494 Result = GetFileTime(hFile, NULL, NULL, &driverInfo->Details.InfDate);
5498 /* Fill SectionName field */
5499 Result
= SetupGetStringFieldW(
5502 driverInfo
->Details
.SectionName
, LINE_LEN
,
5507 /* Fill DrvDescription field */
5508 Result
= SetupGetStringFieldW(
5510 0, /* Field index */
5511 driverInfo
->Details
.DrvDescription
, LINE_LEN
,
5514 /* Copy MatchingId information */
5517 driverInfo
->MatchingId
= HeapAlloc(GetProcessHeap(), 0, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
5518 if (!driverInfo
->MatchingId
)
5520 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5523 RtlCopyMemory(driverInfo
->MatchingId
, MatchingId
, (strlenW(MatchingId
) + 1) * sizeof(WCHAR
));
5526 driverInfo
->MatchingId
= NULL
;
5528 /* Get inf install section */
5530 RequiredSize
= 128; /* Initial buffer size */
5531 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5532 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5534 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5535 InfInstallSection
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5536 if (!InfInstallSection
)
5538 Result
= SetupGetStringFieldW(
5540 1, /* Field index */
5541 InfInstallSection
, RequiredSize
,
5547 TRACE("Adding driver '%s' [%s/%s] (Rank 0x%lx)\n",
5548 debugstr_w(driverInfo
->Details
.DrvDescription
), debugstr_w(InfFile
),
5549 debugstr_w(InfInstallSection
), Rank
);
5551 driverInfo
->DriverRank
= Rank
;
5552 memcpy(&driverInfo
->DriverDate
, &DriverDate
, sizeof(FILETIME
));
5553 memcpy(&driverInfo
->ClassGuid
, ClassGuid
, sizeof(GUID
));
5554 driverInfo
->Info
.DriverType
= DriverType
;
5555 driverInfo
->Info
.Reserved
= (ULONG_PTR
)driverInfo
;
5556 strncpyW(driverInfo
->Info
.Description
, driverInfo
->Details
.DrvDescription
, LINE_LEN
- 1);
5557 driverInfo
->Info
.Description
[LINE_LEN
- 1] = '\0';
5558 strncpyW(driverInfo
->Info
.MfgName
, ManufacturerName
, LINE_LEN
- 1);
5559 driverInfo
->Info
.MfgName
[LINE_LEN
- 1] = '\0';
5562 strncpyW(driverInfo
->Info
.ProviderName
, ProviderName
, LINE_LEN
- 1);
5563 driverInfo
->Info
.ProviderName
[LINE_LEN
- 1] = '\0';
5566 driverInfo
->Info
.ProviderName
[0] = '\0';
5567 driverInfo
->Info
.DriverDate
= DriverDate
;
5568 driverInfo
->Info
.DriverVersion
= DriverVersion
;
5569 ReferenceInfFile(InfFileDetails
);
5570 driverInfo
->InfFileDetails
= InfFileDetails
;
5572 /* Insert current driver in driver list, according to its rank */
5573 PreviousEntry
= DriverListHead
->Flink
;
5574 while (PreviousEntry
!= DriverListHead
)
5576 struct DriverInfoElement
*CurrentDriver
;
5577 CurrentDriver
= CONTAINING_RECORD(PreviousEntry
, struct DriverInfoElement
, ListEntry
);
5578 if (CurrentDriver
->DriverRank
> Rank
||
5579 (CurrentDriver
->DriverRank
== Rank
&& CurrentDriver
->DriverDate
.QuadPart
> driverInfo
->DriverDate
.QuadPart
))
5581 /* Insert before the current item */
5582 InsertHeadList(PreviousEntry
, &driverInfo
->ListEntry
);
5585 PreviousEntry
= PreviousEntry
->Flink
;
5587 if (PreviousEntry
== DriverListHead
)
5589 /* Insert at the end of the list */
5590 InsertTailList(DriverListHead
, &driverInfo
->ListEntry
);
5599 HeapFree(GetProcessHeap(), 0, driverInfo
->MatchingId
);
5600 HeapFree(GetProcessHeap(), 0, driverInfo
);
5602 if (hFile
!= INVALID_HANDLE_VALUE
)
5604 HeapFree(GetProcessHeap(), 0, InfInstallSection
);
5610 GetVersionInformationFromInfFile(
5612 OUT LPGUID ClassGuid
,
5613 OUT LPWSTR
* pProviderName
,
5614 OUT FILETIME
* DriverDate
,
5615 OUT DWORDLONG
* DriverVersion
)
5618 WCHAR guidW
[MAX_GUID_STRING_LEN
+ 1];
5619 LPWSTR DriverVer
= NULL
;
5620 LPWSTR ProviderName
= NULL
;
5621 LPWSTR pComma
; /* Points into DriverVer */
5622 LPWSTR pVersion
= NULL
; /* Points into DriverVer */
5623 SYSTEMTIME SystemTime
;
5625 BOOL ret
= FALSE
; /* Final result */
5627 /* Get class Guid */
5628 if (!SetupGetLineTextW(
5632 guidW
, sizeof(guidW
),
5633 NULL
/* Required size */))
5637 guidW
[37] = '\0'; /* Replace the } by a NULL character */
5638 if (UuidFromStringW(&guidW
[1], ClassGuid
) != RPC_S_OK
)
5640 SetLastError(ERROR_GEN_FAILURE
);
5644 /* Get provider name */
5645 Result
= SetupGetLineTextW(
5647 hInf
, Version
, INF_PROVIDER
,
5652 /* We know know the needed buffer size */
5653 ProviderName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5656 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5659 Result
= SetupGetLineTextW(
5661 hInf
, Version
, INF_PROVIDER
,
5662 ProviderName
, RequiredSize
,
5667 *pProviderName
= ProviderName
;
5669 /* Read the "DriverVer" value */
5670 Result
= SetupGetLineTextW(
5672 hInf
, Version
, INF_DRIVER_VER
,
5677 /* We know know the needed buffer size */
5678 DriverVer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5681 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5684 Result
= SetupGetLineTextW(
5686 hInf
, Version
, INF_DRIVER_VER
,
5687 DriverVer
, RequiredSize
,
5693 /* Get driver date and driver version, by analyzing the "DriverVer" value */
5694 pComma
= strchrW(DriverVer
, ',');
5697 *pComma
= UNICODE_NULL
;
5698 pVersion
= pComma
+ 1;
5700 /* Get driver date version. Invalid date = 00/00/00 */
5701 memset(DriverDate
, 0, sizeof(FILETIME
));
5702 if (strlenW(DriverVer
) == 10
5703 && (DriverVer
[2] == '-' || DriverVer
[2] == '/')
5704 && (DriverVer
[5] == '-' || DriverVer
[5] == '/'))
5706 memset(&SystemTime
, 0, sizeof(SYSTEMTIME
));
5707 DriverVer
[2] = DriverVer
[5] = UNICODE_NULL
;
5708 SystemTime
.wMonth
= ((DriverVer
[0] - '0') * 10) + DriverVer
[1] - '0';
5709 SystemTime
.wDay
= ((DriverVer
[3] - '0') * 10) + DriverVer
[4] - '0';
5710 SystemTime
.wYear
= ((DriverVer
[6] - '0') * 1000) + ((DriverVer
[7] - '0') * 100) + ((DriverVer
[8] - '0') * 10) + DriverVer
[9] - '0';
5711 SystemTimeToFileTime(&SystemTime
, DriverDate
);
5713 /* Get driver version. Invalid version = 0.0.0.0 */
5717 WORD Major
, Minor
= 0, Revision
= 0, Build
= 0;
5718 LPWSTR pMinor
= NULL
, pRevision
= NULL
, pBuild
= NULL
;
5719 LARGE_INTEGER fullVersion
;
5721 pMinor
= strchrW(pVersion
, '.');
5725 pRevision
= strchrW(++pMinor
, '.');
5726 Minor
= atoiW(pMinor
);
5731 pBuild
= strchrW(++pRevision
, '.');
5732 Revision
= atoiW(pRevision
);
5738 Build
= atoiW(pBuild
);
5740 Major
= atoiW(pVersion
);
5741 fullVersion
.u
.HighPart
= Major
<< 16 | Minor
;
5742 fullVersion
.u
.LowPart
= Revision
<< 16 | Build
;
5743 memcpy(DriverVersion
, &fullVersion
, sizeof(LARGE_INTEGER
));
5750 HeapFree(GetProcessHeap(), 0, ProviderName
);
5751 HeapFree(GetProcessHeap(), 0, DriverVer
);
5757 GetHardwareAndCompatibleIDsLists(
5758 IN HDEVINFO DeviceInfoSet
,
5759 IN OUT PSP_DEVINFO_DATA DeviceInfoData
,
5760 OUT LPWSTR
*pHardwareIDs OPTIONAL
,
5761 OUT LPDWORD pHardwareIDsRequiredSize OPTIONAL
,
5762 OUT LPWSTR
*pCompatibleIDs OPTIONAL
,
5763 OUT LPDWORD pCompatibleIDsRequiredSize OPTIONAL
)
5765 LPWSTR HardwareIDs
= NULL
;
5766 LPWSTR CompatibleIDs
= NULL
;
5770 /* Get hardware IDs list */
5772 RequiredSize
= 512; /* Initial buffer size */
5773 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5774 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5776 MyFree(HardwareIDs
);
5777 HardwareIDs
= MyMalloc(RequiredSize
);
5780 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5783 Result
= SetupDiGetDeviceRegistryPropertyW(
5794 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5796 /* No hardware ID for this device */
5797 MyFree(HardwareIDs
);
5805 *pHardwareIDs
= HardwareIDs
;
5806 if (pHardwareIDsRequiredSize
)
5807 *pHardwareIDsRequiredSize
= RequiredSize
;
5809 /* Get compatible IDs list */
5811 RequiredSize
= 512; /* Initial buffer size */
5812 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5813 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5815 MyFree(CompatibleIDs
);
5816 CompatibleIDs
= MyMalloc(RequiredSize
);
5819 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5822 Result
= SetupDiGetDeviceRegistryPropertyW(
5825 SPDRP_COMPATIBLEIDS
,
5827 (PBYTE
)CompatibleIDs
,
5833 if (GetLastError() == ERROR_FILE_NOT_FOUND
)
5835 /* No compatible ID for this device */
5836 MyFree(CompatibleIDs
);
5837 CompatibleIDs
= NULL
;
5844 *pCompatibleIDs
= CompatibleIDs
;
5845 if (pCompatibleIDsRequiredSize
)
5846 *pCompatibleIDsRequiredSize
= RequiredSize
;
5853 MyFree(HardwareIDs
);
5854 MyFree(CompatibleIDs
);
5859 static struct InfFileDetails
*
5860 CreateInfFileDetails(
5861 IN LPCWSTR InfFileName
)
5863 struct InfFileDetails
*details
;
5867 last
= strrchrW(InfFileName
, '\\');
5868 Needed
= FIELD_OFFSET(struct InfFileDetails
, szData
)
5869 + strlenW(InfFileName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
5871 Needed
+= (last
- InfFileName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
5873 details
= HeapAlloc(GetProcessHeap(), 0, Needed
);
5876 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5880 memset(details
, 0, Needed
);
5883 details
->DirectoryName
= details
->szData
;
5884 details
->FullInfFileName
= &details
->szData
[last
- InfFileName
+ 1];
5885 strncpyW(details
->DirectoryName
, InfFileName
, last
- InfFileName
);
5888 details
->FullInfFileName
= details
->szData
;
5889 strcpyW(details
->FullInfFileName
, InfFileName
);
5890 ReferenceInfFile(details
);
5891 details
->hInf
= SetupOpenInfFileW(InfFileName
, NULL
, INF_STYLE_WIN4
, NULL
);
5892 if (details
->hInf
== INVALID_HANDLE_VALUE
)
5894 HeapFree(GetProcessHeap(), 0, details
);
5900 /***********************************************************************
5901 * SetupDiBuildDriverInfoList (SETUPAPI.@)
5904 SetupDiBuildDriverInfoList(
5905 IN HDEVINFO DeviceInfoSet
,
5906 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
5907 IN DWORD DriverType
)
5909 struct DeviceInfoSet
*list
;
5910 SP_DEVINSTALL_PARAMS_W InstallParams
;
5911 PVOID Buffer
= NULL
;
5912 struct InfFileDetails
*currentInfFileDetails
= NULL
;
5913 LPWSTR ProviderName
= NULL
;
5914 LPWSTR ManufacturerName
= NULL
;
5915 WCHAR ManufacturerSection
[LINE_LEN
+ 1];
5916 LPWSTR HardwareIDs
= NULL
;
5917 LPWSTR CompatibleIDs
= NULL
;
5918 LPWSTR FullInfFileName
= NULL
;
5919 LPWSTR ExcludeFromSelect
= NULL
;
5920 FILETIME DriverDate
;
5921 DWORDLONG DriverVersion
= 0;
5925 TRACE("%p %p %ld\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
5928 SetLastError(ERROR_INVALID_HANDLE
);
5929 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
5930 SetLastError(ERROR_INVALID_HANDLE
);
5931 else if (list
->HKLM
!= HKEY_LOCAL_MACHINE
)
5932 SetLastError(ERROR_INVALID_HANDLE
);
5933 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
5934 SetLastError(ERROR_INVALID_PARAMETER
);
5935 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
5936 SetLastError(ERROR_INVALID_PARAMETER
);
5937 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
5938 SetLastError(ERROR_INVALID_USER_BUFFER
);
5941 PLIST_ENTRY pDriverListHead
= &list
->DriverListHead
;
5944 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
5945 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
5951 struct DeviceInfoElement
*devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
5952 if (!(devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
5953 pDriverListHead
= &devInfo
->DriverListHead
;
5956 if (DriverType
== SPDIT_COMPATDRIVER
)
5958 /* Get hardware and compatible IDs lists */
5959 Result
= GetHardwareAndCompatibleIDsLists(
5968 if (!HardwareIDs
&& !CompatibleIDs
)
5970 SetLastError(ERROR_FILE_NOT_FOUND
);
5975 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
5977 /* InstallParams.DriverPath contains the name of a .inf file */
5978 RequiredSize
= strlenW(InstallParams
.DriverPath
) + 2;
5979 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
5982 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
5985 strcpyW(Buffer
, InstallParams
.DriverPath
);
5986 ((LPWSTR
)Buffer
)[RequiredSize
- 1] = 0;
5991 /* Enumerate .inf files */
5993 RequiredSize
= 32768; /* Initial buffer size */
5994 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
5995 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
5997 HeapFree(GetProcessHeap(), 0, Buffer
);
5998 Buffer
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
6002 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6005 Result
= SetupGetInfFileListW(
6006 *InstallParams
.DriverPath
? InstallParams
.DriverPath
: NULL
,
6008 Buffer
, RequiredSize
,
6011 if (!Result
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
6013 /* No .inf file in specified directory. So, we should
6014 * success as we created an empty driver info list.
6023 LPWSTR pFullFilename
;
6025 if (InstallParams
.Flags
& DI_ENUMSINGLEINF
)
6027 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
6028 if (!FullInfFileName
)
6030 pFullFilename
= &FullInfFileName
[0];
6032 else if (*InstallParams
.DriverPath
)
6035 len
= GetFullPathNameW(InstallParams
.DriverPath
, 0, NULL
, NULL
);
6038 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, len
+ MAX_PATH
);
6039 if (!FullInfFileName
)
6041 len
= GetFullPathNameW(InstallParams
.DriverPath
, len
, FullInfFileName
, NULL
);
6044 if (*FullInfFileName
&& FullInfFileName
[strlenW(FullInfFileName
) - 1] != '\\')
6045 strcatW(FullInfFileName
, L
"\\");
6046 pFullFilename
= &FullInfFileName
[strlenW(FullInfFileName
)];
6050 FullInfFileName
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
);
6051 if (!FullInfFileName
)
6053 pFullFilename
= &FullInfFileName
[0];
6056 for (filename
= (LPCWSTR
)Buffer
; *filename
; filename
+= strlenW(filename
) + 1)
6058 INFCONTEXT ContextManufacturer
, ContextDevice
;
6061 strcpyW(pFullFilename
, filename
);
6062 TRACE("Opening file %s\n", debugstr_w(FullInfFileName
));
6064 currentInfFileDetails
= CreateInfFileDetails(FullInfFileName
);
6065 if (!currentInfFileDetails
)
6068 if (!GetVersionInformationFromInfFile(
6069 currentInfFileDetails
->hInf
,
6075 DereferenceInfFile(currentInfFileDetails
);
6076 currentInfFileDetails
= NULL
;
6080 if (DriverType
== SPDIT_CLASSDRIVER
)
6082 /* Check if the ClassGuid in this .inf file is corresponding with our needs */
6083 if (!IsEqualIID(&list
->ClassGuid
, &GUID_NULL
) && !IsEqualIID(&list
->ClassGuid
, &ClassGuid
))
6089 if (InstallParams
.FlagsEx
& DI_FLAGSEX_ALLOWEXCLUDEDDRVS
)
6091 /* Read ExcludeFromSelect control flags */
6095 FIXME("ExcludeFromSelect list ignored\n");
6097 /* Get the manufacturers list */
6098 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, INF_MANUFACTURER
, NULL
, &ContextManufacturer
);
6101 Result
= SetupGetStringFieldW(
6102 &ContextManufacturer
,
6103 0, /* Field index */
6108 /* We got the needed size for the buffer */
6109 ManufacturerName
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
6110 if (!ManufacturerName
)
6112 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6115 Result
= SetupGetStringFieldW(
6116 &ContextManufacturer
,
6117 0, /* Field index */
6118 ManufacturerName
, RequiredSize
,
6121 /* Get manufacturer section name */
6122 Result
= SetupGetStringFieldW(
6123 &ContextManufacturer
,
6124 1, /* Field index */
6125 ManufacturerSection
, LINE_LEN
,
6129 ManufacturerSection
[RequiredSize
] = 0; /* Final NULL char */
6130 /* Add (possible) extension to manufacturer section name */
6131 Result
= SetupDiGetActualSectionToInstallW(
6132 currentInfFileDetails
->hInf
, ManufacturerSection
, ManufacturerSection
, LINE_LEN
, NULL
, NULL
);
6135 TRACE("Enumerating devices in manufacturer %s\n", debugstr_w(ManufacturerSection
));
6136 Result
= SetupFindFirstLineW(currentInfFileDetails
->hInf
, ManufacturerSection
, NULL
, &ContextDevice
);
6141 if (DriverType
== SPDIT_CLASSDRIVER
)
6143 /* FIXME: Check ExcludeFromSelect list */
6144 if (!AddDriverToList(
6149 currentInfFileDetails
,
6154 DriverDate
, DriverVersion
,
6160 else /* DriverType = SPDIT_COMPATDRIVER */
6162 /* 1. Get all fields */
6163 DWORD FieldCount
= SetupGetFieldCount(&ContextDevice
);
6167 BOOL DriverAlreadyAdded
;
6169 for (i
= 2; i
<= FieldCount
; i
++)
6171 LPWSTR DeviceId
= NULL
;
6173 RequiredSize
= 128; /* Initial buffer size */
6174 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
6175 while (!Result
&& GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
6177 HeapFree(GetProcessHeap(), 0, DeviceId
);
6178 DeviceId
= HeapAlloc(GetProcessHeap(), 0, RequiredSize
* sizeof(WCHAR
));
6181 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
6184 Result
= SetupGetStringFieldW(
6187 DeviceId
, RequiredSize
,
6192 HeapFree(GetProcessHeap(), 0, DeviceId
);
6195 /* FIXME: Check ExcludeFromSelect list */
6196 DriverAlreadyAdded
= FALSE
;
6197 for (DriverRank
= 0, currentId
= (LPCWSTR
)HardwareIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
6199 if (strcmpiW(DeviceId
, currentId
) == 0)
6206 currentInfFileDetails
,
6211 DriverDate
, DriverVersion
,
6212 DriverRank
+ (i
== 2 ? 0 : 0x1000 + i
- 3));
6213 DriverAlreadyAdded
= TRUE
;
6218 for (DriverRank
= 0, currentId
= (LPCWSTR
)CompatibleIDs
; !DriverAlreadyAdded
&& *currentId
; currentId
+= strlenW(currentId
) + 1, DriverRank
++)
6220 if (strcmpiW(DeviceId
, currentId
) == 0)
6227 currentInfFileDetails
,
6232 DriverDate
, DriverVersion
,
6233 DriverRank
+ (i
== 2 ? 0x2000 : 0x3000 + i
- 3));
6234 DriverAlreadyAdded
= TRUE
;
6238 HeapFree(GetProcessHeap(), 0, DeviceId
);
6241 Result
= SetupFindNextLine(&ContextDevice
, &ContextDevice
);
6244 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
6245 ManufacturerName
= NULL
;
6246 Result
= SetupFindNextLine(&ContextManufacturer
, &ContextManufacturer
);
6251 HeapFree(GetProcessHeap(), 0, ProviderName
);
6252 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
6253 ProviderName
= ExcludeFromSelect
= NULL
;
6255 DereferenceInfFile(currentInfFileDetails
);
6256 currentInfFileDetails
= NULL
;
6267 InstallParams
.Flags
|= DI_DIDCOMPAT
;
6268 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDCOMPATINFO
;
6272 InstallParams
.Flags
|= DI_DIDCLASS
;
6273 InstallParams
.FlagsEx
|= DI_FLAGSEX_DIDINFOLIST
;
6275 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6278 HeapFree(GetProcessHeap(), 0, ProviderName
);
6279 HeapFree(GetProcessHeap(), 0, ManufacturerName
);
6280 MyFree(HardwareIDs
);
6281 MyFree(CompatibleIDs
);
6282 HeapFree(GetProcessHeap(), 0, FullInfFileName
);
6283 HeapFree(GetProcessHeap(), 0, ExcludeFromSelect
);
6284 if (currentInfFileDetails
)
6285 DereferenceInfFile(currentInfFileDetails
);
6286 HeapFree(GetProcessHeap(), 0, Buffer
);
6288 TRACE("Returning %d\n", ret
);
6292 /***********************************************************************
6293 * SetupDiDeleteDeviceInfo (SETUPAPI.@)
6296 SetupDiDeleteDeviceInfo(
6297 IN HDEVINFO DeviceInfoSet
,
6298 IN PSP_DEVINFO_DATA DeviceInfoData
)
6300 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6302 FIXME("not implemented\n");
6303 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
6308 /***********************************************************************
6309 * SetupDiDestroyDriverInfoList (SETUPAPI.@)
6312 SetupDiDestroyDriverInfoList(
6313 IN HDEVINFO DeviceInfoSet
,
6314 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6315 IN DWORD DriverType
)
6317 struct DeviceInfoSet
*list
;
6320 TRACE("%p %p 0x%lx\n", DeviceInfoSet
, DeviceInfoData
, DriverType
);
6323 SetLastError(ERROR_INVALID_HANDLE
);
6324 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6325 SetLastError(ERROR_INVALID_HANDLE
);
6326 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6327 SetLastError(ERROR_INVALID_PARAMETER
);
6328 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6329 SetLastError(ERROR_INVALID_PARAMETER
);
6330 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6331 SetLastError(ERROR_INVALID_USER_BUFFER
);
6334 PLIST_ENTRY ListEntry
;
6335 struct DriverInfoElement
*driverInfo
;
6336 SP_DEVINSTALL_PARAMS_W InstallParams
;
6338 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6339 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6342 if (!DeviceInfoData
)
6343 /* Fall back to destroying class driver list */
6344 DriverType
= SPDIT_CLASSDRIVER
;
6346 if (DriverType
== SPDIT_CLASSDRIVER
)
6348 while (!IsListEmpty(&list
->DriverListHead
))
6350 ListEntry
= RemoveHeadList(&list
->DriverListHead
);
6351 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
6352 DestroyDriverInfoElement(driverInfo
);
6354 InstallParams
.Reserved
= 0;
6355 InstallParams
.Flags
&= ~(DI_DIDCLASS
| DI_MULTMFGS
);
6356 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDINFOLIST
;
6357 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParams
);
6361 SP_DEVINSTALL_PARAMS_W InstallParamsSet
;
6362 struct DeviceInfoElement
*deviceInfo
;
6364 InstallParamsSet
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6365 if (!SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
))
6367 deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6368 while (!IsListEmpty(&deviceInfo
->DriverListHead
))
6370 ListEntry
= RemoveHeadList(&deviceInfo
->DriverListHead
);
6371 driverInfo
= CONTAINING_RECORD(ListEntry
, struct DriverInfoElement
, ListEntry
);
6372 if ((PVOID
)InstallParamsSet
.Reserved
== driverInfo
)
6374 InstallParamsSet
.Reserved
= 0;
6375 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, NULL
, &InstallParamsSet
);
6377 DestroyDriverInfoElement(driverInfo
);
6379 InstallParams
.Reserved
= 0;
6380 InstallParams
.Flags
&= ~DI_DIDCOMPAT
;
6381 InstallParams
.FlagsEx
&= ~DI_FLAGSEX_DIDCOMPATINFO
;
6382 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
6387 TRACE("Returning %d\n", ret
);
6392 /***********************************************************************
6393 * SetupDiOpenDeviceInfoA (SETUPAPI.@)
6396 SetupDiOpenDeviceInfoA(
6397 IN HDEVINFO DeviceInfoSet
,
6398 IN PCSTR DeviceInstanceId
,
6399 IN HWND hwndParent OPTIONAL
,
6401 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6403 LPWSTR DeviceInstanceIdW
= NULL
;
6406 TRACE("%p %s %p %lx %p\n", DeviceInfoSet
, DeviceInstanceId
, hwndParent
, OpenFlags
, DeviceInfoData
);
6408 DeviceInstanceIdW
= MultiByteToUnicode(DeviceInstanceId
, CP_ACP
);
6409 if (DeviceInstanceIdW
== NULL
)
6412 bResult
= SetupDiOpenDeviceInfoW(DeviceInfoSet
,
6413 DeviceInstanceIdW
, hwndParent
, OpenFlags
, DeviceInfoData
);
6415 MyFree(DeviceInstanceIdW
);
6421 /***********************************************************************
6422 * SetupDiOpenDeviceInfoW (SETUPAPI.@)
6425 SetupDiOpenDeviceInfoW(
6426 IN HDEVINFO DeviceInfoSet
,
6427 IN PCWSTR DeviceInstanceId
,
6428 IN HWND hwndParent OPTIONAL
,
6430 OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
6432 struct DeviceInfoSet
*list
;
6433 HKEY hEnumKey
, hKey
= NULL
;
6437 TRACE("%p %s %p %lx %p\n",
6438 DeviceInfoSet
, debugstr_w(DeviceInstanceId
),
6439 hwndParent
, OpenFlags
, DeviceInfoData
);
6441 if (OpenFlags
& DIOD_CANCEL_REMOVE
)
6442 FIXME("DIOD_CANCEL_REMOVE flag not implemented\n");
6445 SetLastError(ERROR_INVALID_HANDLE
);
6446 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6447 SetLastError(ERROR_INVALID_HANDLE
);
6448 else if (!DeviceInstanceId
)
6449 SetLastError(ERROR_INVALID_PARAMETER
);
6450 else if (OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
))
6452 TRACE("Unknown flags: 0x%08lx\n", OpenFlags
& ~(DIOD_CANCEL_REMOVE
| DIOD_INHERIT_CLASSDRVS
));
6453 SetLastError(ERROR_INVALID_FLAGS
);
6455 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6456 SetLastError(ERROR_INVALID_USER_BUFFER
);
6459 struct DeviceInfoElement
*deviceInfo
= NULL
;
6460 /* Search if device already exists in DeviceInfoSet.
6461 * If yes, return the existing element
6462 * If no, create a new element using informations in registry
6464 PLIST_ENTRY ItemList
= list
->ListHead
.Flink
;
6465 while (ItemList
!= &list
->ListHead
)
6470 FIXME("not implemented\n");
6471 ItemList
= ItemList
->Flink
;
6476 /* good one found */
6481 /* Open supposed registry key */
6484 REGSTR_PATH_SYSTEMENUM
,
6488 if (rc
!= ERROR_SUCCESS
)
6499 RegCloseKey(hEnumKey
);
6500 if (rc
!= ERROR_SUCCESS
)
6502 if (rc
== ERROR_FILE_NOT_FOUND
)
6503 rc
= ERROR_NO_SUCH_DEVINST
;
6508 /* FIXME: try to get ClassGUID from registry, instead of
6509 * sending GUID_NULL to CreateDeviceInfoElement
6511 if (!CreateDeviceInfoElement(list
, DeviceInstanceId
, &GUID_NULL
, &deviceInfo
))
6513 InsertTailList(&list
->ListHead
, &deviceInfo
->ListEntry
);
6518 if (ret
&& deviceInfo
&& DeviceInfoData
)
6520 memcpy(&DeviceInfoData
->ClassGuid
, &deviceInfo
->ClassGuid
, sizeof(GUID
));
6521 DeviceInfoData
->DevInst
= deviceInfo
->dnDevInst
;
6522 DeviceInfoData
->Reserved
= (ULONG_PTR
)deviceInfo
;
6533 /***********************************************************************
6534 * SetupDiEnumDriverInfoA (SETUPAPI.@)
6537 SetupDiEnumDriverInfoA(
6538 IN HDEVINFO DeviceInfoSet
,
6539 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6540 IN DWORD DriverType
,
6541 IN DWORD MemberIndex
,
6542 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6544 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6547 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6548 DriverType
, MemberIndex
, DriverInfoData
);
6550 if (DriverInfoData
== NULL
)
6551 SetLastError(ERROR_INVALID_PARAMETER
);
6552 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6553 SetLastError(ERROR_INVALID_USER_BUFFER
);
6556 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6557 ret
= SetupDiEnumDriverInfoW(DeviceInfoSet
, DeviceInfoData
,
6558 DriverType
, MemberIndex
, &driverInfoData2W
);
6562 /* Do W->A conversion */
6563 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6564 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6565 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6566 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6568 DriverInfoData
->Description
[0] = '\0';
6571 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6572 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6574 DriverInfoData
->MfgName
[0] = '\0';
6577 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6578 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6580 DriverInfoData
->ProviderName
[0] = '\0';
6583 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6585 /* Copy more fields */
6586 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6587 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6592 TRACE("Returning %d\n", ret
);
6597 /***********************************************************************
6598 * SetupDiEnumDriverInfoW (SETUPAPI.@)
6601 SetupDiEnumDriverInfoW(
6602 IN HDEVINFO DeviceInfoSet
,
6603 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6604 IN DWORD DriverType
,
6605 IN DWORD MemberIndex
,
6606 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6608 PLIST_ENTRY ListHead
;
6611 TRACE("%p %p 0x%lx %ld %p\n", DeviceInfoSet
, DeviceInfoData
,
6612 DriverType
, MemberIndex
, DriverInfoData
);
6614 if (!DeviceInfoSet
|| !DriverInfoData
)
6615 SetLastError(ERROR_INVALID_PARAMETER
);
6616 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6617 SetLastError(ERROR_INVALID_HANDLE
);
6618 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6619 SetLastError(ERROR_INVALID_HANDLE
);
6620 else if (DriverType
!= SPDIT_CLASSDRIVER
&& DriverType
!= SPDIT_COMPATDRIVER
)
6621 SetLastError(ERROR_INVALID_PARAMETER
);
6622 else if (DriverType
== SPDIT_COMPATDRIVER
&& !DeviceInfoData
)
6623 SetLastError(ERROR_INVALID_PARAMETER
);
6624 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6625 SetLastError(ERROR_INVALID_USER_BUFFER
);
6628 struct DeviceInfoElement
*devInfo
= NULL
;
6629 PLIST_ENTRY ItemList
;
6631 devInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6632 if (!devInfo
|| (devInfo
->CreationFlags
& DICD_INHERIT_CLASSDRVS
))
6634 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6638 ListHead
= &devInfo
->DriverListHead
;
6641 ItemList
= ListHead
->Flink
;
6642 while (ItemList
!= ListHead
&& MemberIndex
-- > 0)
6643 ItemList
= ItemList
->Flink
;
6644 if (ItemList
== ListHead
)
6645 SetLastError(ERROR_NO_MORE_ITEMS
);
6648 struct DriverInfoElement
*DrvInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6651 &DriverInfoData
->DriverType
,
6652 &DrvInfo
->Info
.DriverType
,
6653 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6658 TRACE("Returning %d\n", ret
);
6663 /***********************************************************************
6664 * SetupDiGetSelectedDevice (SETUPAPI.@)
6667 SetupDiGetSelectedDevice(
6668 IN HDEVINFO DeviceInfoSet
,
6669 OUT PSP_DEVINFO_DATA DeviceInfoData
)
6671 struct DeviceInfoSet
*list
;
6674 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6677 SetLastError(ERROR_INVALID_HANDLE
);
6678 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6679 SetLastError(ERROR_INVALID_HANDLE
);
6680 else if (list
->SelectedDevice
== NULL
)
6681 SetLastError(ERROR_NO_DEVICE_SELECTED
);
6682 else if (!DeviceInfoData
)
6683 SetLastError(ERROR_INVALID_PARAMETER
);
6684 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6685 SetLastError(ERROR_INVALID_USER_BUFFER
);
6688 memcpy(&DeviceInfoData
->ClassGuid
,
6689 &list
->SelectedDevice
->ClassGuid
,
6691 DeviceInfoData
->DevInst
= list
->SelectedDevice
->dnDevInst
;
6692 DeviceInfoData
->Reserved
= (ULONG_PTR
)list
->SelectedDevice
;
6696 TRACE("Returning %d\n", ret
);
6701 /***********************************************************************
6702 * SetupDiGetSelectedDriverA (SETUPAPI.@)
6705 SetupDiGetSelectedDriverA(
6706 IN HDEVINFO DeviceInfoSet
,
6707 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6708 OUT PSP_DRVINFO_DATA_A DriverInfoData
)
6710 SP_DRVINFO_DATA_V2_W driverInfoData2W
;
6713 if (DriverInfoData
== NULL
)
6714 SetLastError(ERROR_INVALID_PARAMETER
);
6715 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
))
6716 SetLastError(ERROR_INVALID_USER_BUFFER
);
6719 driverInfoData2W
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
6721 ret
= SetupDiGetSelectedDriverW(DeviceInfoSet
,
6727 /* Do W->A conversion */
6728 DriverInfoData
->DriverType
= driverInfoData2W
.DriverType
;
6729 DriverInfoData
->Reserved
= driverInfoData2W
.Reserved
;
6730 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.Description
, -1,
6731 DriverInfoData
->Description
, LINE_LEN
, NULL
, NULL
) == 0)
6733 DriverInfoData
->Description
[0] = '\0';
6736 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.MfgName
, -1,
6737 DriverInfoData
->MfgName
, LINE_LEN
, NULL
, NULL
) == 0)
6739 DriverInfoData
->MfgName
[0] = '\0';
6742 if (WideCharToMultiByte(CP_ACP
, 0, driverInfoData2W
.ProviderName
, -1,
6743 DriverInfoData
->ProviderName
, LINE_LEN
, NULL
, NULL
) == 0)
6745 DriverInfoData
->ProviderName
[0] = '\0';
6748 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
6750 /* Copy more fields */
6751 DriverInfoData
->DriverDate
= driverInfoData2W
.DriverDate
;
6752 DriverInfoData
->DriverVersion
= driverInfoData2W
.DriverVersion
;
6761 /***********************************************************************
6762 * SetupDiGetSelectedDriverW (SETUPAPI.@)
6765 SetupDiGetSelectedDriverW(
6766 IN HDEVINFO DeviceInfoSet
,
6767 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6768 OUT PSP_DRVINFO_DATA_W DriverInfoData
)
6772 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6774 if (!DeviceInfoSet
|| !DriverInfoData
)
6775 SetLastError(ERROR_INVALID_PARAMETER
);
6776 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6777 SetLastError(ERROR_INVALID_HANDLE
);
6778 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6779 SetLastError(ERROR_INVALID_HANDLE
);
6780 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6781 SetLastError(ERROR_INVALID_USER_BUFFER
);
6782 else if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6783 SetLastError(ERROR_INVALID_USER_BUFFER
);
6786 SP_DEVINSTALL_PARAMS InstallParams
;
6788 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
6789 if (SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
))
6791 struct DriverInfoElement
*driverInfo
;
6792 driverInfo
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
6793 if (driverInfo
== NULL
)
6794 SetLastError(ERROR_NO_DRIVER_SELECTED
);
6798 &DriverInfoData
->DriverType
,
6799 &driverInfo
->Info
.DriverType
,
6800 DriverInfoData
->cbSize
- FIELD_OFFSET(SP_DRVINFO_DATA_W
, DriverType
));
6806 TRACE("Returning %d\n", ret
);
6811 /***********************************************************************
6812 * SetupDiSetSelectedDevice (SETUPAPI.@)
6815 SetupDiSetSelectedDevice(
6816 IN HDEVINFO DeviceInfoSet
,
6817 IN PSP_DEVINFO_DATA DeviceInfoData
)
6819 struct DeviceInfoSet
*list
;
6822 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
6825 SetLastError(ERROR_INVALID_HANDLE
);
6826 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6827 SetLastError(ERROR_INVALID_HANDLE
);
6828 else if (!DeviceInfoData
)
6829 SetLastError(ERROR_INVALID_PARAMETER
);
6830 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6831 SetLastError(ERROR_INVALID_USER_BUFFER
);
6832 else if (DeviceInfoData
->Reserved
== 0)
6833 SetLastError(ERROR_INVALID_USER_BUFFER
);
6836 list
->SelectedDevice
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
6840 TRACE("Returning %d\n", ret
);
6845 /***********************************************************************
6846 * SetupDiSetSelectedDriverA (SETUPAPI.@)
6849 SetupDiSetSelectedDriverA(
6850 IN HDEVINFO DeviceInfoSet
,
6851 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6852 IN OUT PSP_DRVINFO_DATA_A DriverInfoData OPTIONAL
)
6854 SP_DRVINFO_DATA_V1_W DriverInfoDataW
;
6855 PSP_DRVINFO_DATA_W pDriverInfoDataW
= NULL
;
6858 if (DriverInfoData
!= NULL
)
6860 if (DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_A
) &&
6861 DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_A
));
6863 SetLastError(ERROR_INVALID_PARAMETER
);
6867 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
6868 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
6870 if (DriverInfoDataW
.Reserved
== 0)
6872 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
6874 /* convert the strings to unicode */
6875 if (!MultiByteToWideChar(CP_ACP
,
6877 DriverInfoData
->Description
,
6879 DriverInfoDataW
.Description
,
6881 !MultiByteToWideChar(CP_ACP
,
6883 DriverInfoData
->ProviderName
,
6885 DriverInfoDataW
.ProviderName
,
6892 pDriverInfoDataW
= (PSP_DRVINFO_DATA_W
)&DriverInfoDataW
;
6895 ret
= SetupDiSetSelectedDriverW(DeviceInfoSet
,
6899 if (ret
&& pDriverInfoDataW
!= NULL
)
6901 DriverInfoData
->Reserved
= DriverInfoDataW
.Reserved
;
6908 /***********************************************************************
6909 * SetupDiSetSelectedDriverW (SETUPAPI.@)
6912 SetupDiSetSelectedDriverW(
6913 IN HDEVINFO DeviceInfoSet
,
6914 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
6915 IN OUT PSP_DRVINFO_DATA_W DriverInfoData OPTIONAL
)
6919 TRACE("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DriverInfoData
);
6922 SetLastError(ERROR_INVALID_PARAMETER
);
6923 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
6924 SetLastError(ERROR_INVALID_HANDLE
);
6925 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
6926 SetLastError(ERROR_INVALID_HANDLE
);
6927 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
6928 SetLastError(ERROR_INVALID_USER_BUFFER
);
6929 else if (DriverInfoData
&& DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V1_W
) && DriverInfoData
->cbSize
!= sizeof(SP_DRVINFO_DATA_V2_W
))
6930 SetLastError(ERROR_INVALID_USER_BUFFER
);
6933 struct DriverInfoElement
**pDriverInfo
;
6934 PLIST_ENTRY ListHead
, ItemList
;
6938 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
;
6939 ListHead
= &((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->DriverListHead
;
6943 pDriverInfo
= (struct DriverInfoElement
**)&((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
;
6944 ListHead
= &((struct DeviceInfoSet
*)DeviceInfoSet
)->DriverListHead
;
6947 if (!DriverInfoData
)
6949 *pDriverInfo
= NULL
;
6954 /* Search selected driver in list */
6955 ItemList
= ListHead
->Flink
;
6956 while (ItemList
!= ListHead
)
6958 if (DriverInfoData
->Reserved
!= 0)
6960 if (DriverInfoData
->Reserved
== (ULONG_PTR
)ItemList
)
6965 /* The caller wants to compare only DriverType, Description and ProviderName fields */
6966 struct DriverInfoElement
*driverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6967 if (driverInfo
->Info
.DriverType
== DriverInfoData
->DriverType
6968 && strcmpW(driverInfo
->Info
.Description
, DriverInfoData
->Description
) == 0
6969 && strcmpW(driverInfo
->Info
.ProviderName
, DriverInfoData
->ProviderName
) == 0)
6974 ItemList
= ItemList
->Flink
;
6976 if (ItemList
== ListHead
)
6977 SetLastError(ERROR_INVALID_PARAMETER
);
6980 *pDriverInfo
= CONTAINING_RECORD(ItemList
, struct DriverInfoElement
, ListEntry
);
6981 DriverInfoData
->Reserved
= (ULONG_PTR
)ItemList
;
6983 TRACE("Choosing driver whose rank is 0x%lx\n",
6984 (*pDriverInfo
)->DriverRank
);
6986 memcpy(&DeviceInfoData
->ClassGuid
, &(*pDriverInfo
)->ClassGuid
, sizeof(GUID
));
6991 TRACE("Returning %d\n", ret
);
6995 /***********************************************************************
6996 * SetupDiGetDriverInfoDetailA (SETUPAPI.@)
6999 SetupDiGetDriverInfoDetailA(
7000 IN HDEVINFO DeviceInfoSet
,
7001 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
7002 IN PSP_DRVINFO_DATA_A DriverInfoData
,
7003 IN OUT PSP_DRVINFO_DETAIL_DATA_A DriverInfoDetailData OPTIONAL
,
7004 IN DWORD DriverInfoDetailDataSize
,
7005 OUT PDWORD RequiredSize OPTIONAL
)
7007 SP_DRVINFO_DATA_V2_W DriverInfoDataW
;
7008 PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailDataW
= NULL
;
7010 DWORD HardwareIDLen
= 0;
7013 /* do some sanity checks, the unicode version might do more thorough checks */
7014 if (DriverInfoData
== NULL
||
7015 (DriverInfoDetailData
== NULL
&& DriverInfoDetailDataSize
!= 0) ||
7016 (DriverInfoDetailData
!= NULL
&&
7017 (DriverInfoDetailDataSize
< FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) + sizeof(CHAR
) ||
7018 DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_A
))))
7020 SetLastError(ERROR_INVALID_PARAMETER
);
7024 /* make sure we support both versions of the SP_DRVINFO_DATA structure */
7025 if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V1_A
))
7027 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V1_W
);
7029 else if (DriverInfoData
->cbSize
== sizeof(SP_DRVINFO_DATA_V2_A
))
7031 DriverInfoDataW
.cbSize
= sizeof(SP_DRVINFO_DATA_V2_W
);
7035 SetLastError(ERROR_INVALID_PARAMETER
);
7038 DriverInfoDataW
.DriverType
= DriverInfoData
->DriverType
;
7039 DriverInfoDataW
.Reserved
= DriverInfoData
->Reserved
;
7041 /* convert the strings to unicode */
7042 if (MultiByteToWideChar(CP_ACP
,
7044 DriverInfoData
->Description
,
7046 DriverInfoDataW
.Description
,
7048 MultiByteToWideChar(CP_ACP
,
7050 DriverInfoData
->MfgName
,
7052 DriverInfoDataW
.MfgName
,
7054 MultiByteToWideChar(CP_ACP
,
7056 DriverInfoData
->ProviderName
,
7058 DriverInfoDataW
.ProviderName
,
7061 if (DriverInfoDataW
.cbSize
== sizeof(SP_DRVINFO_DATA_V2_W
))
7063 DriverInfoDataW
.DriverDate
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverDate
;
7064 DriverInfoDataW
.DriverVersion
= ((PSP_DRVINFO_DATA_V2_A
)DriverInfoData
)->DriverVersion
;
7067 if (DriverInfoDetailData
!= NULL
)
7069 /* calculate the unicode buffer size from the ansi buffer size */
7070 HardwareIDLen
= DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
);
7071 BufSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
) +
7072 (HardwareIDLen
* sizeof(WCHAR
));
7074 DriverInfoDetailDataW
= MyMalloc(BufSize
);
7075 if (DriverInfoDetailDataW
== NULL
)
7077 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
7081 /* initialize the buffer */
7082 ZeroMemory(DriverInfoDetailDataW
,
7084 DriverInfoDetailDataW
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_W
);
7087 /* call the unicode version */
7088 ret
= SetupDiGetDriverInfoDetailW(DeviceInfoSet
,
7091 DriverInfoDetailDataW
,
7097 if (DriverInfoDetailDataW
!= NULL
)
7099 /* convert the SP_DRVINFO_DETAIL_DATA_W structure to ansi */
7100 DriverInfoDetailData
->cbSize
= sizeof(SP_DRVINFO_DETAIL_DATA_A
);
7101 DriverInfoDetailData
->InfDate
= DriverInfoDetailDataW
->InfDate
;
7102 DriverInfoDetailData
->Reserved
= DriverInfoDetailDataW
->Reserved
;
7103 if (WideCharToMultiByte(CP_ACP
,
7105 DriverInfoDetailDataW
->SectionName
,
7107 DriverInfoDetailData
->SectionName
,
7111 WideCharToMultiByte(CP_ACP
,
7113 DriverInfoDetailDataW
->InfFileName
,
7115 DriverInfoDetailData
->InfFileName
,
7119 WideCharToMultiByte(CP_ACP
,
7121 DriverInfoDetailDataW
->DrvDescription
,
7123 DriverInfoDetailData
->DrvDescription
,
7127 WideCharToMultiByte(CP_ACP
,
7129 DriverInfoDetailDataW
->HardwareID
,
7131 DriverInfoDetailData
->HardwareID
,
7137 DWORD hwidlen
= HardwareIDLen
;
7138 CHAR
*s
= DriverInfoDetailData
->HardwareID
;
7140 /* count the strings in the list */
7143 len
= lstrlenA(s
) + 1;
7152 /* looks like the string list wasn't terminated... */
7153 SetLastError(ERROR_INVALID_USER_BUFFER
);
7159 /* make sure CompatIDsOffset points to the second string in the
7163 DriverInfoDetailData
->CompatIDsOffset
= lstrlenA(DriverInfoDetailData
->HardwareID
) + 1;
7164 DriverInfoDetailData
->CompatIDsLength
= (DWORD
)(s
- DriverInfoDetailData
->HardwareID
) -
7165 DriverInfoDetailData
->CompatIDsOffset
+ 1;
7169 DriverInfoDetailData
->CompatIDsOffset
= 0;
7170 DriverInfoDetailData
->CompatIDsLength
= 0;
7179 if (RequiredSize
!= NULL
)
7181 *RequiredSize
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_A
, HardwareID
) +
7182 (((*RequiredSize
) - FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
));
7188 if (DriverInfoDetailDataW
!= NULL
)
7190 MyFree(DriverInfoDetailDataW
);
7196 /***********************************************************************
7197 * SetupDiGetDriverInfoDetailW (SETUPAPI.@)
7200 SetupDiGetDriverInfoDetailW(
7201 IN HDEVINFO DeviceInfoSet
,
7202 IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
,
7203 IN PSP_DRVINFO_DATA_W DriverInfoData
,
7204 IN OUT PSP_DRVINFO_DETAIL_DATA_W DriverInfoDetailData OPTIONAL
,
7205 IN DWORD DriverInfoDetailDataSize
,
7206 OUT PDWORD RequiredSize OPTIONAL
)
7210 TRACE("%p %p %p %p %lu %p\n", DeviceInfoSet
, DeviceInfoData
,
7211 DriverInfoData
, DriverInfoDetailData
,
7212 DriverInfoDetailDataSize
, RequiredSize
);
7215 SetLastError(ERROR_INVALID_PARAMETER
);
7216 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7217 SetLastError(ERROR_INVALID_HANDLE
);
7218 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7219 SetLastError(ERROR_INVALID_HANDLE
);
7220 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7221 SetLastError(ERROR_INVALID_USER_BUFFER
);
7222 else if (!DriverInfoData
)
7223 SetLastError(ERROR_INVALID_PARAMETER
);
7224 else if (!DriverInfoDetailData
&& DriverInfoDetailDataSize
!= 0)
7225 SetLastError(ERROR_INVALID_PARAMETER
);
7226 else if (DriverInfoDetailData
&& DriverInfoDetailDataSize
< sizeof(SP_DRVINFO_DETAIL_DATA_W
))
7227 SetLastError(ERROR_INVALID_PARAMETER
);
7228 else if (DriverInfoDetailData
&& DriverInfoDetailData
->cbSize
!= sizeof(SP_DRVINFO_DETAIL_DATA_W
))
7229 SetLastError(ERROR_INVALID_USER_BUFFER
);
7230 else if (DriverInfoData
->Reserved
== 0)
7231 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7234 struct DriverInfoElement
*driverInfoElement
;
7235 LPWSTR HardwareIDs
= NULL
;
7236 LPWSTR CompatibleIDs
= NULL
;
7237 LPWSTR pBuffer
= NULL
;
7238 LPCWSTR DeviceID
= NULL
;
7239 ULONG HardwareIDsSize
, CompatibleIDsSize
;
7240 ULONG sizeNeeded
, sizeLeft
, size
;
7243 driverInfoElement
= (struct DriverInfoElement
*)DriverInfoData
->Reserved
;
7245 /* Get hardware and compatible IDs lists */
7246 Result
= GetHardwareAndCompatibleIDsLists(
7249 &HardwareIDs
, &HardwareIDsSize
,
7250 &CompatibleIDs
, &CompatibleIDsSize
);
7254 sizeNeeded
= FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)
7255 + HardwareIDsSize
+ CompatibleIDsSize
;
7257 *RequiredSize
= sizeNeeded
;
7259 if (!DriverInfoDetailData
)
7266 DriverInfoDetailData
,
7267 &driverInfoElement
->Details
,
7268 driverInfoElement
->Details
.cbSize
);
7269 DriverInfoDetailData
->CompatIDsOffset
= 0;
7270 DriverInfoDetailData
->CompatIDsLength
= 0;
7272 sizeLeft
= (DriverInfoDetailDataSize
- FIELD_OFFSET(SP_DRVINFO_DETAIL_DATA_W
, HardwareID
)) / sizeof(WCHAR
);
7273 pBuffer
= DriverInfoDetailData
->HardwareID
;
7274 /* Add as many as possible HardwareIDs in the list */
7275 DeviceID
= HardwareIDs
;
7276 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
7278 TRACE("Adding %s to list\n", debugstr_w(DeviceID
));
7279 wcscpy(pBuffer
, DeviceID
);
7280 DeviceID
+= size
+ 1;
7281 pBuffer
+= size
+ 1;
7282 sizeLeft
-= size
+ 1;
7283 DriverInfoDetailData
->CompatIDsOffset
+= size
+ 1;
7287 *pBuffer
= UNICODE_NULL
;
7289 DriverInfoDetailData
->CompatIDsOffset
++;
7291 /* Add as many as possible CompatibleIDs in the list */
7292 DeviceID
= CompatibleIDs
;
7293 while (DeviceID
&& *DeviceID
&& (size
= wcslen(DeviceID
)) + 1 < sizeLeft
)
7295 TRACE("Adding %s to list\n", debugstr_w(DeviceID
));
7296 wcscpy(pBuffer
, DeviceID
);
7297 DeviceID
+= size
+ 1;
7298 pBuffer
+= size
+ 1;
7299 sizeLeft
-= size
+ 1;
7300 DriverInfoDetailData
->CompatIDsLength
+= size
+ 1;
7304 *pBuffer
= UNICODE_NULL
;
7306 DriverInfoDetailData
->CompatIDsLength
++;
7309 if (sizeNeeded
> DriverInfoDetailDataSize
)
7310 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
7315 MyFree(HardwareIDs
);
7316 MyFree(CompatibleIDs
);
7319 TRACE("Returning %d\n", ret
);
7323 /* Return the current hardware profile id, or -1 if error */
7325 GetCurrentHwProfile(
7326 IN HDEVINFO DeviceInfoSet
)
7329 DWORD dwRegType
, dwLength
;
7332 DWORD ret
= (DWORD
)-1;
7335 ((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
,
7336 REGSTR_PATH_IDCONFIGDB
,
7340 if (rc
!= ERROR_SUCCESS
)
7346 dwLength
= sizeof(DWORD
);
7347 rc
= RegQueryValueExW(
7349 REGSTR_VAL_CURRENTCONFIG
,
7352 (LPBYTE
)&hwProfile
, &dwLength
);
7353 if (rc
!= ERROR_SUCCESS
)
7358 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7360 SetLastError(ERROR_GEN_FAILURE
);
7375 IN HDEVINFO DeviceInfoSet
,
7376 IN PSP_DEVINFO_DATA DeviceInfoData
)
7379 PLUGPLAY_CONTROL_RESET_DEVICE_DATA ResetDeviceData
;
7380 struct DeviceInfoElement
*deviceInfo
= (struct DeviceInfoElement
*)DeviceInfoData
->Reserved
;
7383 if (((struct DeviceInfoSet
*)DeviceInfoSet
)->HKLM
!= HKEY_LOCAL_MACHINE
)
7385 /* At the moment, I only know how to start local devices */
7386 SetLastError(ERROR_INVALID_COMPUTERNAME
);
7390 RtlInitUnicodeString(&ResetDeviceData
.DeviceInstance
, deviceInfo
->DeviceName
);
7391 Status
= NtPlugPlayControl(PlugPlayControlResetDevice
, &ResetDeviceData
, sizeof(PLUGPLAY_CONTROL_RESET_DEVICE_DATA
));
7392 SetLastError(RtlNtStatusToDosError(Status
));
7393 return NT_SUCCESS(Status
);
7395 FIXME("Stub: ResetDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
7400 static BOOL
StopDevice(
7401 IN HDEVINFO DeviceInfoSet
,
7402 IN PSP_DEVINFO_DATA DeviceInfoData
)
7404 FIXME("Stub: StopDevice(%p %p)\n", DeviceInfoSet
, DeviceInfoData
);
7408 /***********************************************************************
7409 * SetupDiChangeState (SETUPAPI.@)
7413 IN HDEVINFO DeviceInfoSet
,
7414 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
7416 PSP_PROPCHANGE_PARAMS PropChange
;
7417 HKEY hKey
= INVALID_HANDLE_VALUE
;
7418 LPCWSTR RegistryValueName
;
7419 DWORD dwConfigFlags
, dwLength
, dwRegType
;
7423 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7425 if (!DeviceInfoData
)
7426 PropChange
= ((struct DeviceInfoSet
*)DeviceInfoSet
)->ClassInstallParams
.PropChange
;
7428 PropChange
= ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->ClassInstallParams
.PropChange
;
7431 SetLastError(ERROR_INVALID_PARAMETER
);
7435 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
)
7436 RegistryValueName
= REGSTR_VAL_CONFIGFLAGS
;
7438 RegistryValueName
= REGSTR_VAL_CSCONFIGFLAGS
;
7440 switch (PropChange
->StateChange
)
7445 /* Enable/disable device in registry */
7446 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, KEY_QUERY_VALUE
| KEY_SET_VALUE
);
7447 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7448 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, PropChange
->Scope
, PropChange
->HwProfile
, DIREG_DEV
, NULL
, NULL
);
7449 if (hKey
== INVALID_HANDLE_VALUE
)
7451 dwLength
= sizeof(DWORD
);
7452 rc
= RegQueryValueExW(
7457 (LPBYTE
)&dwConfigFlags
, &dwLength
);
7458 if (rc
== ERROR_FILE_NOT_FOUND
)
7460 else if (rc
!= ERROR_SUCCESS
)
7465 else if (dwRegType
!= REG_DWORD
|| dwLength
!= sizeof(DWORD
))
7467 SetLastError(ERROR_GEN_FAILURE
);
7470 if (PropChange
->StateChange
== DICS_ENABLE
)
7471 dwConfigFlags
&= ~(PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7473 dwConfigFlags
|= (PropChange
->Scope
== DICS_FLAG_GLOBAL
? CONFIGFLAG_DISABLED
: CSCONFIGFLAG_DISABLED
);
7479 (LPBYTE
)&dwConfigFlags
, sizeof(DWORD
));
7480 if (rc
!= ERROR_SUCCESS
)
7486 /* Enable/disable device if needed */
7487 if (PropChange
->Scope
== DICS_FLAG_GLOBAL
7488 || PropChange
->HwProfile
== 0
7489 || PropChange
->HwProfile
== GetCurrentHwProfile(DeviceInfoSet
))
7491 if (PropChange
->StateChange
== DICS_ENABLE
)
7492 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7494 ret
= StopDevice(DeviceInfoSet
, DeviceInfoData
);
7500 case DICS_PROPCHANGE
:
7502 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
7507 ERR("Unknown StateChange 0x%lx\n", PropChange
->StateChange
);
7508 SetLastError(ERROR_NOT_SUPPORTED
);
7513 if (hKey
!= INVALID_HANDLE_VALUE
)
7516 TRACE("Returning %d\n", ret
);
7520 /***********************************************************************
7521 * SetupDiSelectBestCompatDrv (SETUPAPI.@)
7524 SetupDiSelectBestCompatDrv(
7525 IN HDEVINFO DeviceInfoSet
,
7526 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7528 SP_DRVINFO_DATA_W drvInfoData
;
7531 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7533 /* Drivers are sorted by rank in the driver list, so
7534 * the first driver in the list is the best one.
7536 drvInfoData
.cbSize
= sizeof(SP_DRVINFO_DATA_W
);
7537 ret
= SetupDiEnumDriverInfoW(
7541 0, /* Member index */
7546 ret
= SetupDiSetSelectedDriverW(
7552 TRACE("Returning %d\n", ret
);
7556 /***********************************************************************
7557 * SetupDiSelectDevice (SETUPAPI.@)
7560 SetupDiSelectDevice(
7561 IN HDEVINFO DeviceInfoSet
,
7562 IN OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
)
7564 FIXME("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7565 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
7569 /***********************************************************************
7570 * SetupDiInstallDriverFiles (SETUPAPI.@)
7573 SetupDiInstallDriverFiles(
7574 IN HDEVINFO DeviceInfoSet
,
7575 IN PSP_DEVINFO_DATA DeviceInfoData
)
7579 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7582 SetLastError(ERROR_INVALID_PARAMETER
);
7583 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7584 SetLastError(ERROR_INVALID_HANDLE
);
7585 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7586 SetLastError(ERROR_INVALID_HANDLE
);
7587 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7588 SetLastError(ERROR_INVALID_USER_BUFFER
);
7589 else if (DeviceInfoData
&& ((struct DeviceInfoElement
*)DeviceInfoData
->Reserved
)->InstallParams
.Reserved
== 0)
7590 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7591 else if (!DeviceInfoData
&& ((struct DeviceInfoSet
*)DeviceInfoSet
)->InstallParams
.Reserved
== 0)
7592 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7595 SP_DEVINSTALL_PARAMS_W InstallParams
;
7596 struct DriverInfoElement
*SelectedDriver
;
7597 WCHAR SectionName
[MAX_PATH
];
7598 DWORD SectionNameLength
= 0;
7599 PVOID InstallMsgHandler
;
7600 PVOID InstallMsgHandlerContext
;
7601 PVOID Context
= NULL
;
7603 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7604 ret
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7608 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7609 if (!SelectedDriver
)
7611 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7615 ret
= SetupDiGetActualSectionToInstallW(
7616 SelectedDriver
->InfFileDetails
->hInf
,
7617 SelectedDriver
->Details
.SectionName
,
7618 SectionName
, MAX_PATH
- strlenW(DotCoInstallers
), &SectionNameLength
, NULL
);
7622 if (InstallParams
.InstallMsgHandler
)
7624 InstallMsgHandler
= InstallParams
.InstallMsgHandler
;
7625 InstallMsgHandlerContext
= InstallParams
.InstallMsgHandlerContext
;
7629 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7632 InstallMsgHandler
= SetupDefaultQueueCallback
;
7633 InstallMsgHandlerContext
= Context
;
7635 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7636 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7637 SPINST_FILES
, NULL
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
7638 InstallMsgHandler
, InstallMsgHandlerContext
,
7639 DeviceInfoSet
, DeviceInfoData
);
7643 /* Install files from .CoInstallers section */
7644 lstrcatW(SectionName
, DotCoInstallers
);
7645 ret
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7646 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7647 SPINST_FILES
, NULL
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
7648 InstallMsgHandler
, InstallMsgHandlerContext
,
7649 DeviceInfoSet
, DeviceInfoData
);
7653 /* Set the DI_NOFILECOPY flag to prevent another
7654 * installation during SetupDiInstallDevice */
7655 InstallParams
.Flags
|= DI_NOFILECOPY
;
7656 ret
= SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7660 SetupTermDefaultQueueCallback(Context
);
7664 TRACE("Returning %d\n", ret
);
7668 /***********************************************************************
7669 * SetupDiRegisterCoDeviceInstallers (SETUPAPI.@)
7672 SetupDiRegisterCoDeviceInstallers(
7673 IN HDEVINFO DeviceInfoSet
,
7674 IN PSP_DEVINFO_DATA DeviceInfoData
)
7676 BOOL ret
= FALSE
; /* Return value */
7678 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7681 SetLastError(ERROR_INVALID_PARAMETER
);
7682 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7683 SetLastError(ERROR_INVALID_HANDLE
);
7684 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7685 SetLastError(ERROR_INVALID_HANDLE
);
7686 else if (!DeviceInfoData
)
7687 SetLastError(ERROR_INVALID_PARAMETER
);
7688 else if (DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7689 SetLastError(ERROR_INVALID_USER_BUFFER
);
7692 SP_DEVINSTALL_PARAMS_W InstallParams
;
7693 struct DriverInfoElement
*SelectedDriver
;
7696 WCHAR SectionName
[MAX_PATH
];
7697 DWORD SectionNameLength
= 0;
7698 HKEY hKey
= INVALID_HANDLE_VALUE
;
7699 PVOID Context
= NULL
;
7701 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7702 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7706 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7707 if (SelectedDriver
== NULL
)
7709 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7713 /* Get .CoInstallers section name */
7714 Result
= SetupDiGetActualSectionToInstallW(
7715 SelectedDriver
->InfFileDetails
->hInf
,
7716 SelectedDriver
->Details
.SectionName
,
7717 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7718 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotCoInstallers
) - 1)
7720 lstrcatW(SectionName
, DotCoInstallers
);
7722 /* Open/Create driver key information */
7723 #if _WIN32_WINNT >= 0x502
7724 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
7726 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
7728 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
7729 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
7730 if (hKey
== INVALID_HANDLE_VALUE
)
7733 /* Install .CoInstallers section */
7734 DoAction
= SPINST_REGISTRY
;
7735 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
7737 DoAction
|= SPINST_FILES
;
7738 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
7742 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
7743 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
7744 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
7745 SetupDefaultQueueCallback
, Context
,
7746 DeviceInfoSet
, DeviceInfoData
);
7754 SetupTermDefaultQueueCallback(Context
);
7755 if (hKey
!= INVALID_HANDLE_VALUE
)
7759 TRACE("Returning %d\n", ret
);
7764 InstallOneInterface(
7765 IN LPGUID InterfaceGuid
,
7766 IN LPCWSTR ReferenceString
,
7767 IN LPCWSTR InterfaceSection
,
7768 IN UINT InterfaceFlags
)
7770 if (InterfaceFlags
!= 0)
7772 SetLastError(ERROR_INVALID_PARAMETER
);
7776 FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid
),
7777 debugstr_w(ReferenceString
), debugstr_w(InterfaceSection
), InterfaceFlags
);
7781 /***********************************************************************
7782 * SetupDiInstallDeviceInterfaces (SETUPAPI.@)
7785 SetupDiInstallDeviceInterfaces(
7786 IN HDEVINFO DeviceInfoSet
,
7787 IN PSP_DEVINFO_DATA DeviceInfoData
)
7789 struct DeviceInfoSet
*list
= NULL
;
7792 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7795 SetLastError(ERROR_INVALID_PARAMETER
);
7796 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7797 SetLastError(ERROR_INVALID_HANDLE
);
7798 else if ((list
= (struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7799 SetLastError(ERROR_INVALID_HANDLE
);
7800 else if (!DeviceInfoData
)
7801 SetLastError(ERROR_INVALID_PARAMETER
);
7802 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7803 SetLastError(ERROR_INVALID_USER_BUFFER
);
7806 struct DriverInfoElement
*SelectedDriver
;
7807 SP_DEVINSTALL_PARAMS_W InstallParams
;
7808 WCHAR SectionName
[MAX_PATH
];
7809 DWORD SectionNameLength
= 0;
7810 INFCONTEXT ContextInterface
;
7811 LPWSTR InterfaceGuidString
= NULL
;
7812 LPWSTR ReferenceString
= NULL
;
7813 LPWSTR InterfaceSection
= NULL
;
7818 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7819 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7823 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
7824 if (SelectedDriver
== NULL
)
7826 SetLastError(ERROR_NO_DRIVER_SELECTED
);
7831 /* Get .Interfaces section name */
7832 Result
= SetupDiGetActualSectionToInstallW(
7833 SelectedDriver
->InfFileDetails
->hInf
,
7834 SelectedDriver
->Details
.SectionName
,
7835 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
7836 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotInterfaces
) - 1)
7838 strcatW(SectionName
, DotInterfaces
);
7841 Result
= SetupFindFirstLineW(
7842 SelectedDriver
->InfFileDetails
->hInf
,
7846 while (ret
&& Result
)
7848 ret
= GetStringField(&ContextInterface
, 1, &InterfaceGuidString
);
7851 else if (strlenW(InterfaceGuidString
) != MAX_GUID_STRING_LEN
- 1)
7853 SetLastError(ERROR_INVALID_PARAMETER
);
7858 InterfaceGuidString
[MAX_GUID_STRING_LEN
- 2] = '\0'; /* Replace the } by a NULL character */
7859 if (UuidFromStringW(&InterfaceGuidString
[1], &InterfaceGuid
) != RPC_S_OK
)
7861 /* Bad GUID, skip the entry */
7862 SetLastError(ERROR_INVALID_PARAMETER
);
7867 ret
= GetStringField(&ContextInterface
, 2, &ReferenceString
);
7871 ret
= GetStringField(&ContextInterface
, 3, &InterfaceSection
);
7875 ret
= SetupGetIntField(
7877 4, /* Field index */
7881 if (GetLastError() == ERROR_INVALID_PARAMETER
)
7883 /* The field may be empty. Ignore the error */
7891 /* Install Interface */
7892 ret
= InstallOneInterface(&InterfaceGuid
, ReferenceString
, InterfaceSection
, InterfaceFlags
);
7895 MyFree(InterfaceGuidString
);
7896 MyFree(ReferenceString
);
7897 MyFree(InterfaceSection
);
7898 InterfaceGuidString
= ReferenceString
= InterfaceSection
= NULL
;
7899 Result
= SetupFindNextMatchLineW(&ContextInterface
, AddInterface
, &ContextInterface
);
7903 TRACE("Returning %d\n", ret
);
7908 InfIsFromOEMLocation(
7910 OUT LPBOOL IsOEMLocation
)
7914 last
= strrchrW(FullName
, '\\');
7917 /* No directory specified */
7918 *IsOEMLocation
= FALSE
;
7922 WCHAR Windir
[MAX_PATH
];
7925 ret
= GetWindowsDirectory(Windir
, MAX_PATH
);
7926 if (ret
== 0 || ret
>= MAX_PATH
)
7928 SetLastError(ERROR_GEN_FAILURE
);
7932 if (strncmpW(FullName
, Windir
, last
- FullName
) == 0)
7934 /* The path is %WINDIR%\Inf */
7935 *IsOEMLocation
= FALSE
;
7939 /* The file is in another place */
7940 *IsOEMLocation
= TRUE
;
7946 /***********************************************************************
7947 * SetupDiInstallDevice (SETUPAPI.@)
7950 SetupDiInstallDevice(
7951 IN HDEVINFO DeviceInfoSet
,
7952 IN OUT PSP_DEVINFO_DATA DeviceInfoData
)
7954 SP_DEVINSTALL_PARAMS_W InstallParams
;
7955 struct DriverInfoElement
*SelectedDriver
;
7956 SYSTEMTIME DriverDate
;
7957 WCHAR SectionName
[MAX_PATH
];
7959 DWORD SectionNameLength
= 0;
7960 BOOL Result
= FALSE
;
7963 LPWSTR pSectionName
= NULL
;
7964 WCHAR ClassName
[MAX_CLASS_NAME_LEN
];
7966 LPWSTR lpGuidString
= NULL
, lpFullGuidString
= NULL
;
7967 BOOL RebootRequired
= FALSE
;
7968 HKEY hKey
= INVALID_HANDLE_VALUE
;
7969 BOOL NeedtoCopyFile
;
7970 LARGE_INTEGER fullVersion
;
7972 PVOID Context
= NULL
;
7973 BOOL ret
= FALSE
; /* Return value */
7975 TRACE("%p %p\n", DeviceInfoSet
, DeviceInfoData
);
7978 SetLastError(ERROR_INVALID_PARAMETER
);
7979 else if (DeviceInfoSet
== (HDEVINFO
)INVALID_HANDLE_VALUE
)
7980 SetLastError(ERROR_INVALID_HANDLE
);
7981 else if (((struct DeviceInfoSet
*)DeviceInfoSet
)->magic
!= SETUP_DEV_INFO_SET_MAGIC
)
7982 SetLastError(ERROR_INVALID_HANDLE
);
7983 else if (DeviceInfoData
&& DeviceInfoData
->cbSize
!= sizeof(SP_DEVINFO_DATA
))
7984 SetLastError(ERROR_INVALID_USER_BUFFER
);
7990 /* One parameter is bad */
7994 InstallParams
.cbSize
= sizeof(SP_DEVINSTALL_PARAMS_W
);
7995 Result
= SetupDiGetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
7999 if (InstallParams
.FlagsEx
& DI_FLAGSEX_SETFAILEDINSTALL
)
8001 /* Set FAILEDINSTALL in ConfigFlags registry value */
8002 DWORD ConfigFlags
, regType
;
8003 Result
= SetupDiGetDeviceRegistryPropertyW(
8008 (PBYTE
)&ConfigFlags
,
8009 sizeof(ConfigFlags
),
8011 if (!Result
|| regType
!= REG_DWORD
)
8013 SetLastError(ERROR_GEN_FAILURE
);
8016 ConfigFlags
|= DNF_DISABLED
;
8017 Result
= SetupDiSetDeviceRegistryPropertyW(
8021 (PBYTE
)&ConfigFlags
,
8022 sizeof(ConfigFlags
));
8025 SetLastError(ERROR_GEN_FAILURE
);
8033 SelectedDriver
= (struct DriverInfoElement
*)InstallParams
.Reserved
;
8034 if (SelectedDriver
== NULL
)
8036 SetLastError(ERROR_NO_DRIVER_SELECTED
);
8040 FileTimeToSystemTime(&SelectedDriver
->Info
.DriverDate
, &DriverDate
);
8042 Result
= SetupDiGetActualSectionToInstallW(
8043 SelectedDriver
->InfFileDetails
->hInf
,
8044 SelectedDriver
->Details
.SectionName
,
8045 SectionName
, MAX_PATH
, &SectionNameLength
, NULL
);
8046 if (!Result
|| SectionNameLength
> MAX_PATH
- strlenW(DotServices
))
8048 pSectionName
= &SectionName
[strlenW(SectionName
)];
8050 /* Get information from [Version] section */
8051 if (!SetupDiGetINFClassW(SelectedDriver
->InfFileDetails
->FullInfFileName
, &ClassGuid
, ClassName
, MAX_CLASS_NAME_LEN
, &RequiredSize
))
8053 /* Format ClassGuid to a string */
8054 if (UuidToStringW((UUID
*)&ClassGuid
, &lpGuidString
) != RPC_S_OK
)
8056 RequiredSize
= lstrlenW(lpGuidString
);
8057 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (RequiredSize
+ 3) * sizeof(WCHAR
));
8058 if (!lpFullGuidString
)
8060 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
8063 lpFullGuidString
[0] = '{';
8064 memcpy(&lpFullGuidString
[1], lpGuidString
, RequiredSize
* sizeof(WCHAR
));
8065 lpFullGuidString
[RequiredSize
+ 1] = '}';
8066 lpFullGuidString
[RequiredSize
+ 2] = '\0';
8068 /* Open/Create driver key information */
8069 #if _WIN32_WINNT >= 0x502
8070 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_READ
| KEY_WRITE
);
8072 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, KEY_ALL_ACCESS
);
8074 if (hKey
== INVALID_HANDLE_VALUE
&& GetLastError() == ERROR_FILE_NOT_FOUND
)
8075 hKey
= SetupDiCreateDevRegKeyW(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DRV
, NULL
, NULL
);
8076 if (hKey
== INVALID_HANDLE_VALUE
)
8079 /* Install main section */
8081 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
8082 DoAction
|= SPINST_REGISTRY
;
8083 if (!(InstallParams
.Flags
& DI_NOFILECOPY
))
8085 DoAction
|= SPINST_FILES
;
8086 Context
= SetupInitDefaultQueueCallback(InstallParams
.hwndParent
);
8090 *pSectionName
= '\0';
8091 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
8092 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
8093 DoAction
, hKey
, SelectedDriver
->InfFileDetails
->DirectoryName
, SP_COPY_NEWER
,
8094 SetupDefaultQueueCallback
, Context
,
8095 DeviceInfoSet
, DeviceInfoData
);
8098 InstallParams
.Flags
|= DI_NOFILECOPY
;
8099 SetupDiSetDeviceInstallParamsW(DeviceInfoSet
, DeviceInfoData
, &InstallParams
);
8101 /* Write information to driver key */
8102 *pSectionName
= UNICODE_NULL
;
8103 memcpy(&fullVersion
, &SelectedDriver
->Info
.DriverVersion
, sizeof(LARGE_INTEGER
));
8104 TRACE("Write information to driver key\n");
8105 TRACE("DriverDate : '%u-%u-%u'\n", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
8106 TRACE("DriverDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
8107 TRACE("DriverVersion : '%u.%u.%u.%u'\n", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
8108 TRACE("InfPath : '%s'\n", debugstr_w(SelectedDriver
->Details
.InfFileName
));
8109 TRACE("InfSection : '%s'\n", debugstr_w(SelectedDriver
->Details
.SectionName
));
8110 TRACE("InfSectionExt : '%s'\n", debugstr_w(&SectionName
[strlenW(SelectedDriver
->Details
.SectionName
)]));
8111 TRACE("MatchingDeviceId: '%s'\n", debugstr_w(SelectedDriver
->MatchingId
));
8112 TRACE("ProviderName : '%s'\n", debugstr_w(SelectedDriver
->Info
.ProviderName
));
8113 sprintfW(Buffer
, L
"%u-%u-%u", DriverDate
.wMonth
, DriverDate
.wDay
, DriverDate
.wYear
);
8114 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
8115 if (rc
== ERROR_SUCCESS
)
8116 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_DATE_DATA
, 0, REG_BINARY
, (const BYTE
*)&SelectedDriver
->Info
.DriverDate
, sizeof(FILETIME
));
8117 if (rc
== ERROR_SUCCESS
)
8118 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DRVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
8119 if (rc
== ERROR_SUCCESS
)
8121 sprintfW(Buffer
, L
"%u.%u.%u.%u", fullVersion
.HighPart
>> 16, fullVersion
.HighPart
& 0xffff, fullVersion
.LowPart
>> 16, fullVersion
.LowPart
& 0xffff);
8122 rc
= RegSetValueEx(hKey
, REGSTR_DRIVER_VERSION
, 0, REG_SZ
, (const BYTE
*)Buffer
, (strlenW(Buffer
) + 1) * sizeof(WCHAR
));
8124 if (rc
== ERROR_SUCCESS
)
8125 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFPATH
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.InfFileName
, (strlenW(SelectedDriver
->Details
.InfFileName
) + 1) * sizeof(WCHAR
));
8126 if (rc
== ERROR_SUCCESS
)
8127 rc
= RegSetValueEx(hKey
, REGSTR_VAL_INFSECTION
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Details
.SectionName
, (strlenW(SelectedDriver
->Details
.SectionName
) + 1) * sizeof(WCHAR
));
8128 if (rc
== ERROR_SUCCESS
)
8129 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
));
8130 if (rc
== ERROR_SUCCESS
)
8131 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MATCHINGDEVID
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->MatchingId
, (strlenW(SelectedDriver
->MatchingId
) + 1) * sizeof(WCHAR
));
8132 if (rc
== ERROR_SUCCESS
)
8133 rc
= RegSetValueEx(hKey
, REGSTR_VAL_PROVIDER_NAME
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.ProviderName
, (strlenW(SelectedDriver
->Info
.ProviderName
) + 1) * sizeof(WCHAR
));
8134 if (rc
!= ERROR_SUCCESS
)
8140 hKey
= INVALID_HANDLE_VALUE
;
8142 /* FIXME: Process .LogConfigOverride section */
8144 /* Install .Services section */
8145 strcpyW(pSectionName
, DotServices
);
8146 Result
= SetupInstallServicesFromInfSectionExW(
8147 SelectedDriver
->InfFileDetails
->hInf
,
8156 if (GetLastError() == ERROR_SUCCESS_REBOOT_REQUIRED
)
8157 RebootRequired
= TRUE
;
8159 /* Copy .inf file to Inf\ directory (if needed) */
8160 Result
= InfIsFromOEMLocation(SelectedDriver
->InfFileDetails
->FullInfFileName
, &NeedtoCopyFile
);
8165 Result
= SetupCopyOEMInfW(
8166 SelectedDriver
->InfFileDetails
->FullInfFileName
,
8169 SP_COPY_NOOVERWRITE
,
8175 /* FIXME: create a new struct InfFileDetails, and set it to SelectedDriver->InfFileDetails,
8176 * to release use of current InfFile */
8179 /* Open device registry key */
8180 hKey
= SetupDiOpenDevRegKey(DeviceInfoSet
, DeviceInfoData
, DICS_FLAG_GLOBAL
, 0, DIREG_DEV
, KEY_SET_VALUE
);
8181 if (hKey
== INVALID_HANDLE_VALUE
)
8184 /* Install .HW section */
8186 if (!(InstallParams
.FlagsEx
& DI_FLAGSEX_NO_DRVREG_MODIFY
))
8187 DoAction
|= SPINST_REGISTRY
;
8188 strcpyW(pSectionName
, DotHW
);
8189 Result
= SetupInstallFromInfSectionW(InstallParams
.hwndParent
,
8190 SelectedDriver
->InfFileDetails
->hInf
, SectionName
,
8191 DoAction
, hKey
, NULL
, 0,
8193 DeviceInfoSet
, DeviceInfoData
);
8197 /* Write information to enum key */
8198 TRACE("Write information to enum key\n");
8199 TRACE("Class : '%s'\n", debugstr_w(ClassName
));
8200 TRACE("ClassGUID : '%s'\n", debugstr_w(lpFullGuidString
));
8201 TRACE("DeviceDesc : '%s'\n", debugstr_w(SelectedDriver
->Info
.Description
));
8202 TRACE("Mfg : '%s'\n", debugstr_w(SelectedDriver
->Info
.MfgName
));
8203 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASS
, 0, REG_SZ
, (const BYTE
*)ClassName
, (strlenW(ClassName
) + 1) * sizeof(WCHAR
));
8204 if (rc
== ERROR_SUCCESS
)
8205 rc
= RegSetValueEx(hKey
, REGSTR_VAL_CLASSGUID
, 0, REG_SZ
, (const BYTE
*)lpFullGuidString
, (strlenW(lpFullGuidString
) + 1) * sizeof(WCHAR
));
8206 if (rc
== ERROR_SUCCESS
)
8207 rc
= RegSetValueEx(hKey
, REGSTR_VAL_DEVDESC
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.Description
, (strlenW(SelectedDriver
->Info
.Description
) + 1) * sizeof(WCHAR
));
8208 if (rc
== ERROR_SUCCESS
)
8209 rc
= RegSetValueEx(hKey
, REGSTR_VAL_MFG
, 0, REG_SZ
, (const BYTE
*)SelectedDriver
->Info
.MfgName
, (strlenW(SelectedDriver
->Info
.MfgName
) + 1) * sizeof(WCHAR
));
8210 if (rc
!= ERROR_SUCCESS
)
8216 /* Start the device */
8217 if (!RebootRequired
&& !(InstallParams
.Flags
& (DI_NEEDRESTART
| DI_NEEDREBOOT
| DI_DONOTCALLCONFIGMG
)))
8218 ret
= ResetDevice(DeviceInfoSet
, DeviceInfoData
);
8223 /* End of installation */
8224 if (hKey
!= INVALID_HANDLE_VALUE
)
8227 RpcStringFreeW(&lpGuidString
);
8228 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
8230 SetupTermDefaultQueueCallback(Context
);
8231 TRACE("Returning %d\n", ret
);