2 * SetupAPI device installer
4 * Copyright 2000 Andreas Mohr for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
43 #include "setupapi_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(setupapi
);
48 /* Unicode constants */
49 static const WCHAR ClassGUID
[] = {'C','l','a','s','s','G','U','I','D',0};
50 static const WCHAR Class
[] = {'C','l','a','s','s',0};
51 static const WCHAR ClassInstall32
[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0};
52 static const WCHAR NoDisplayClass
[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0};
53 static const WCHAR NoInstallClass
[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0};
54 static const WCHAR NoUseClass
[] = {'N','o','U','s','e','C','l','a','s','s',0};
55 static const WCHAR NtExtension
[] = {'.','N','T',0};
56 static const WCHAR NtPlatformExtension
[] = {'.','N','T','x','8','6',0};
57 static const WCHAR Version
[] = {'V','e','r','s','i','o','n',0};
58 static const WCHAR WinExtension
[] = {'.','W','i','n',0};
60 /* Registry key and value names */
61 static const WCHAR ControlClass
[] = {'S','y','s','t','e','m','\\',
62 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
63 'C','o','n','t','r','o','l','\\',
64 'C','l','a','s','s',0};
66 static const WCHAR DeviceClasses
[] = {'S','y','s','t','e','m','\\',
67 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
68 'C','o','n','t','r','o','l','\\',
69 'D','e','v','i','c','e','C','l','a','s','s','e','s',0};
71 /***********************************************************************
72 * SetupDiBuildClassInfoList (SETUPAPI.@)
74 BOOL WINAPI
SetupDiBuildClassInfoList(
77 DWORD ClassGuidListSize
,
81 return SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
82 ClassGuidListSize
, RequiredSize
,
86 /***********************************************************************
87 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
89 BOOL WINAPI
SetupDiBuildClassInfoListExA(
92 DWORD ClassGuidListSize
,
97 LPWSTR MachineNameW
= NULL
;
104 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
105 if (MachineNameW
== NULL
) return FALSE
;
108 bResult
= SetupDiBuildClassInfoListExW(Flags
, ClassGuidList
,
109 ClassGuidListSize
, RequiredSize
,
110 MachineNameW
, Reserved
);
113 MyFree(MachineNameW
);
118 /***********************************************************************
119 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
121 BOOL WINAPI
SetupDiBuildClassInfoListExW(
123 LPGUID ClassGuidList
,
124 DWORD ClassGuidListSize
,
135 DWORD dwGuidListIndex
= 0;
139 if (RequiredSize
!= NULL
)
142 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
147 if (hClassesKey
== INVALID_HANDLE_VALUE
)
152 for (dwIndex
= 0; ; dwIndex
++)
155 lError
= RegEnumKeyExW(hClassesKey
,
163 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
164 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
166 TRACE("Key name: %p\n", szKeyName
);
168 if (RegOpenKeyExW(hClassesKey
,
174 RegCloseKey(hClassesKey
);
178 if (!RegQueryValueExW(hClassKey
,
185 TRACE("'NoUseClass' value found!\n");
186 RegCloseKey(hClassKey
);
190 if ((Flags
& DIBCI_NOINSTALLCLASS
) &&
191 (!RegQueryValueExW(hClassKey
,
198 TRACE("'NoInstallClass' value found!\n");
199 RegCloseKey(hClassKey
);
203 if ((Flags
& DIBCI_NODISPLAYCLASS
) &&
204 (!RegQueryValueExW(hClassKey
,
211 TRACE("'NoDisplayClass' value found!\n");
212 RegCloseKey(hClassKey
);
216 RegCloseKey(hClassKey
);
218 TRACE("Guid: %p\n", szKeyName
);
219 if (dwGuidListIndex
< ClassGuidListSize
)
221 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
225 TRACE("Guid: %p\n", &szKeyName
[1]);
227 UuidFromStringW(&szKeyName
[1],
228 &ClassGuidList
[dwGuidListIndex
]);
234 if (lError
!= ERROR_SUCCESS
)
238 RegCloseKey(hClassesKey
);
240 if (RequiredSize
!= NULL
)
241 *RequiredSize
= dwGuidListIndex
;
243 if (ClassGuidListSize
< dwGuidListIndex
)
245 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
252 /***********************************************************************
253 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
255 BOOL WINAPI
SetupDiClassGuidsFromNameA(
257 LPGUID ClassGuidList
,
258 DWORD ClassGuidListSize
,
261 return SetupDiClassGuidsFromNameExA(ClassName
, ClassGuidList
,
262 ClassGuidListSize
, RequiredSize
,
266 /***********************************************************************
267 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
269 BOOL WINAPI
SetupDiClassGuidsFromNameW(
271 LPGUID ClassGuidList
,
272 DWORD ClassGuidListSize
,
275 return SetupDiClassGuidsFromNameExW(ClassName
, ClassGuidList
,
276 ClassGuidListSize
, RequiredSize
,
280 /***********************************************************************
281 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
283 BOOL WINAPI
SetupDiClassGuidsFromNameExA(
285 LPGUID ClassGuidList
,
286 DWORD ClassGuidListSize
,
291 LPWSTR ClassNameW
= NULL
;
292 LPWSTR MachineNameW
= NULL
;
297 ClassNameW
= MultiByteToUnicode(ClassName
, CP_ACP
);
298 if (ClassNameW
== NULL
)
303 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
304 if (MachineNameW
== NULL
)
311 bResult
= SetupDiClassGuidsFromNameExW(ClassNameW
, ClassGuidList
,
312 ClassGuidListSize
, RequiredSize
,
313 MachineNameW
, Reserved
);
316 MyFree(MachineNameW
);
323 /***********************************************************************
324 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
326 BOOL WINAPI
SetupDiClassGuidsFromNameExW(
328 LPGUID ClassGuidList
,
329 DWORD ClassGuidListSize
,
335 WCHAR szClassName
[256];
341 DWORD dwGuidListIndex
= 0;
343 if (RequiredSize
!= NULL
)
346 hClassesKey
= SetupDiOpenClassRegKeyExW(NULL
,
351 if (hClassesKey
== INVALID_HANDLE_VALUE
)
356 for (dwIndex
= 0; ; dwIndex
++)
359 lError
= RegEnumKeyExW(hClassesKey
,
367 TRACE("RegEnumKeyExW() returns %ld\n", lError
);
368 if (lError
== ERROR_SUCCESS
|| lError
== ERROR_MORE_DATA
)
370 TRACE("Key name: %p\n", szKeyName
);
372 if (RegOpenKeyExW(hClassesKey
,
378 RegCloseKey(hClassesKey
);
382 dwLength
= 256 * sizeof(WCHAR
);
383 if (!RegQueryValueExW(hClassKey
,
390 TRACE("Class name: %p\n", szClassName
);
392 if (strcmpiW(szClassName
, ClassName
) == 0)
394 TRACE("Found matching class name\n");
396 TRACE("Guid: %p\n", szKeyName
);
397 if (dwGuidListIndex
< ClassGuidListSize
)
399 if (szKeyName
[0] == L
'{' && szKeyName
[37] == L
'}')
403 TRACE("Guid: %p\n", &szKeyName
[1]);
405 UuidFromStringW(&szKeyName
[1],
406 &ClassGuidList
[dwGuidListIndex
]);
413 RegCloseKey(hClassKey
);
416 if (lError
!= ERROR_SUCCESS
)
420 RegCloseKey(hClassesKey
);
422 if (RequiredSize
!= NULL
)
423 *RequiredSize
= dwGuidListIndex
;
425 if (ClassGuidListSize
< dwGuidListIndex
)
427 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
434 /***********************************************************************
435 * SetupDiClassNameFromGuidA (SETUPAPI.@)
437 BOOL WINAPI
SetupDiClassNameFromGuidA(
438 const GUID
* ClassGuid
,
443 return SetupDiClassNameFromGuidExA(ClassGuid
, ClassName
,
444 ClassNameSize
, RequiredSize
,
448 /***********************************************************************
449 * SetupDiClassNameFromGuidW (SETUPAPI.@)
451 BOOL WINAPI
SetupDiClassNameFromGuidW(
452 const GUID
* ClassGuid
,
457 return SetupDiClassNameFromGuidExW(ClassGuid
, ClassName
,
458 ClassNameSize
, RequiredSize
,
462 /***********************************************************************
463 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
465 BOOL WINAPI
SetupDiClassNameFromGuidExA(
466 const GUID
* ClassGuid
,
473 WCHAR ClassNameW
[MAX_CLASS_NAME_LEN
];
474 LPWSTR MachineNameW
= NULL
;
478 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
479 ret
= SetupDiClassNameFromGuidExW(ClassGuid
, ClassNameW
, MAX_CLASS_NAME_LEN
,
480 NULL
, MachineNameW
, Reserved
);
483 int len
= WideCharToMultiByte(CP_ACP
, 0, ClassNameW
, -1, ClassName
,
484 ClassNameSize
, NULL
, NULL
);
486 if (!ClassNameSize
&& RequiredSize
)
489 MyFree(MachineNameW
);
493 /***********************************************************************
494 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
496 BOOL WINAPI
SetupDiClassNameFromGuidExW(
497 const GUID
* ClassGuid
,
507 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
512 if (hKey
== INVALID_HANDLE_VALUE
)
517 if (RequiredSize
!= NULL
)
520 if (RegQueryValueExW(hKey
,
531 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
534 dwLength
= ClassNameSize
* sizeof(WCHAR
);
535 if (RegQueryValueExW(hKey
,
551 /***********************************************************************
552 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
555 SetupDiCreateDeviceInfoList(const GUID
*ClassGuid
,
558 return SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
, NULL
, NULL
);
561 /***********************************************************************
562 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
565 SetupDiCreateDeviceInfoListExA(const GUID
*ClassGuid
,
570 LPWSTR MachineNameW
= NULL
;
577 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
578 if (MachineNameW
== NULL
)
579 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
582 hDevInfo
= SetupDiCreateDeviceInfoListExW(ClassGuid
, hwndParent
,
583 MachineNameW
, Reserved
);
586 MyFree(MachineNameW
);
591 /***********************************************************************
592 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
595 SetupDiCreateDeviceInfoListExW(const GUID
*ClassGuid
,
601 return (HDEVINFO
)INVALID_HANDLE_VALUE
;
604 /***********************************************************************
605 * SetupDiEnumDeviceInfo (SETUPAPI.@)
607 BOOL WINAPI
SetupDiEnumDeviceInfo(
610 PSP_DEVINFO_DATA info
)
612 FIXME("%p %ld %p\n", devinfo
, index
, info
);
616 if(info
->cbSize
< sizeof(*info
))
622 /***********************************************************************
623 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
625 BOOL WINAPI
SetupDiGetActualSectionToInstallA(
627 PCSTR InfSectionName
,
628 PSTR InfSectionWithExt
,
629 DWORD InfSectionWithExtSize
,
633 LPWSTR InfSectionNameW
= NULL
;
634 PWSTR InfSectionWithExtW
= NULL
;
642 InfSectionNameW
= MultiByteToUnicode(InfSectionName
, CP_ACP
);
643 if (InfSectionNameW
== NULL
) goto end
;
645 if (InfSectionWithExt
)
647 InfSectionWithExtW
= HeapAlloc(GetProcessHeap(), 0, InfSectionWithExtSize
* sizeof(WCHAR
));
648 if (InfSectionWithExtW
== NULL
) goto end
;
651 bResult
= SetupDiGetActualSectionToInstallW(InfHandle
, InfSectionNameW
,
652 InfSectionWithExt
? InfSectionNameW
: NULL
,
653 InfSectionWithExtSize
, RequiredSize
,
654 Extension
? &ExtensionW
: NULL
);
656 if (InfSectionWithExt
)
661 if (ExtensionW
== NULL
)
664 *Extension
= &InfSectionWithExt
[ExtensionW
- InfSectionWithExtW
];
668 if (InfSectionNameW
) MyFree(InfSectionNameW
);
669 if (InfSectionWithExtW
) HeapFree(GetProcessHeap(), 0, InfSectionWithExtW
);
674 /***********************************************************************
675 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
677 BOOL WINAPI
SetupDiGetActualSectionToInstallW(
679 PCWSTR InfSectionName
,
680 PWSTR InfSectionWithExt
,
681 DWORD InfSectionWithExtSize
,
685 WCHAR szBuffer
[MAX_PATH
];
688 LONG lLineCount
= -1;
690 lstrcpyW(szBuffer
, InfSectionName
);
691 dwLength
= lstrlenW(szBuffer
);
693 if (OsVersionInfo
.dwPlatformId
== VER_PLATFORM_WIN32_NT
)
695 /* Test section name with '.NTx86' extension */
696 lstrcpyW(&szBuffer
[dwLength
], NtPlatformExtension
);
697 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
699 if (lLineCount
== -1)
701 /* Test section name with '.NT' extension */
702 lstrcpyW(&szBuffer
[dwLength
], NtExtension
);
703 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
708 /* Test section name with '.Win' extension */
709 lstrcpyW(&szBuffer
[dwLength
], WinExtension
);
710 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
713 if (lLineCount
== -1)
715 /* Test section name without extension */
716 szBuffer
[dwLength
] = 0;
717 lLineCount
= SetupGetLineCountW(InfHandle
, szBuffer
);
720 if (lLineCount
== -1)
722 SetLastError(ERROR_INVALID_PARAMETER
);
726 dwFullLength
= lstrlenW(szBuffer
);
728 if (InfSectionWithExt
!= NULL
&& InfSectionWithExtSize
!= 0)
730 if (InfSectionWithExtSize
< (dwFullLength
+ 1))
732 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
736 lstrcpyW(InfSectionWithExt
, szBuffer
);
737 if (Extension
!= NULL
)
739 *Extension
= (dwLength
== dwFullLength
) ? NULL
: &InfSectionWithExt
[dwLength
];
743 if (RequiredSize
!= NULL
)
745 *RequiredSize
= dwFullLength
+ 1;
751 /***********************************************************************
752 * SetupDiGetClassDescriptionA (SETUPAPI.@)
754 BOOL WINAPI
SetupDiGetClassDescriptionA(
755 const GUID
* ClassGuid
,
756 PSTR ClassDescription
,
757 DWORD ClassDescriptionSize
,
760 return SetupDiGetClassDescriptionExA(ClassGuid
, ClassDescription
,
761 ClassDescriptionSize
,
762 RequiredSize
, NULL
, NULL
);
765 /***********************************************************************
766 * SetupDiGetClassDescriptionW (SETUPAPI.@)
768 BOOL WINAPI
SetupDiGetClassDescriptionW(
769 const GUID
* ClassGuid
,
770 PWSTR ClassDescription
,
771 DWORD ClassDescriptionSize
,
774 return SetupDiGetClassDescriptionExW(ClassGuid
, ClassDescription
,
775 ClassDescriptionSize
,
776 RequiredSize
, NULL
, NULL
);
779 /***********************************************************************
780 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
782 BOOL WINAPI
SetupDiGetClassDescriptionExA(
783 const GUID
* ClassGuid
,
784 PSTR ClassDescription
,
785 DWORD ClassDescriptionSize
,
794 /***********************************************************************
795 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
797 BOOL WINAPI
SetupDiGetClassDescriptionExW(
798 const GUID
* ClassGuid
,
799 PWSTR ClassDescription
,
800 DWORD ClassDescriptionSize
,
808 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
,
813 if (hKey
== INVALID_HANDLE_VALUE
)
815 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
819 if (RequiredSize
!= NULL
)
822 if (RegQueryValueExW(hKey
,
833 *RequiredSize
= dwLength
/ sizeof(WCHAR
);
836 dwLength
= ClassDescriptionSize
* sizeof(WCHAR
);
837 if (RegQueryValueExW(hKey
,
841 (LPBYTE
)ClassDescription
,
853 /***********************************************************************
854 * SetupDiGetClassDevsA (SETUPAPI.@)
856 HDEVINFO WINAPI
SetupDiGetClassDevsA(
863 LPWSTR enumstrW
= NULL
;
867 int len
= MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, NULL
, 0);
868 enumstrW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
871 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
874 MultiByteToWideChar(CP_ACP
, 0, enumstr
, -1, enumstrW
, len
);
876 ret
= SetupDiGetClassDevsW(class, enumstrW
, parent
, flags
);
877 HeapFree(GetProcessHeap(), 0, enumstrW
);
883 #define SETUP_SERIAL_PORT_MAGIC 0xd00ff055
885 typedef struct _SerialPortName
890 typedef struct _SerialPortList
894 SerialPortName names
[1];
897 static HDEVINFO
SETUP_CreateSerialDeviceList(void)
899 static const size_t initialSize
= 100;
901 WCHAR buf
[initialSize
];
909 if (QueryDosDeviceW(NULL
, devices
, size
) == 0)
911 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER
)
915 HeapFree(GetProcessHeap(), 0, devices
);
916 devices
= HeapAlloc(GetProcessHeap(), 0, size
* sizeof(WCHAR
));
925 } while (!*devices
&& !failed
);
928 static const WCHAR comW
[] = { 'C','O','M',0 };
930 UINT numSerialPorts
= 0;
931 SerialPortList
*list
;
933 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
935 if (!strncmpW(comW
, ptr
, sizeof(comW
) / sizeof(comW
[0]) - 1))
938 list
= HeapAlloc(GetProcessHeap(), 0, sizeof(SerialPortList
) +
939 numSerialPorts
? (numSerialPorts
- 1) * sizeof(SerialPortName
) : 0);
942 list
->magic
= SETUP_SERIAL_PORT_MAGIC
;
944 for (ptr
= devices
; *ptr
; ptr
+= strlenW(ptr
) + 1)
946 if (!strncmpW(comW
, ptr
, sizeof(comW
) / sizeof(comW
[0]) - 1))
948 lstrcpynW(list
->names
[list
->numPorts
].name
, ptr
,
949 sizeof(list
->names
[list
->numPorts
].name
) /
950 sizeof(list
->names
[list
->numPorts
].name
[0]));
951 TRACE("Adding %s to list\n",
952 debugstr_w(list
->names
[list
->numPorts
].name
));
956 TRACE("list->numPorts is %d\n", list
->numPorts
);
958 ret
= (HDEVINFO
)list
;
961 ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
963 HeapFree(GetProcessHeap(), 0, devices
);
964 TRACE("returning %p\n", ret
);
968 /***********************************************************************
969 * SetupDiGetClassDevsW (SETUPAPI.@)
971 HDEVINFO WINAPI
SetupDiGetClassDevsW(
977 HDEVINFO ret
= (HDEVINFO
)INVALID_HANDLE_VALUE
;
979 TRACE("%s %s %p 0x%08lx\n", debugstr_guid(class), debugstr_w(enumstr
),
983 FIXME(": unimplemented for enumerator strings (%s)\n",
984 debugstr_w(enumstr
));
985 else if (flags
& DIGCF_ALLCLASSES
)
986 FIXME(": unimplemented for DIGCF_ALLCLASSES\n");
989 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT
))
990 ret
= SETUP_CreateSerialDeviceList();
991 else if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
))
992 ret
= SETUP_CreateSerialDeviceList();
994 FIXME("(%s): stub\n", debugstr_guid(class));
999 /***********************************************************************
1000 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1002 BOOL WINAPI
SetupDiEnumDeviceInterfaces(
1003 HDEVINFO DeviceInfoSet
,
1004 PSP_DEVINFO_DATA DeviceInfoData
,
1005 CONST GUID
* InterfaceClassGuid
,
1007 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1011 TRACE("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet
, DeviceInfoData
,
1012 debugstr_guid(InterfaceClassGuid
), MemberIndex
, DeviceInterfaceData
);
1013 if (!DeviceInterfaceData
)
1014 SetLastError(ERROR_INVALID_PARAMETER
);
1015 else if (DeviceInfoData
)
1016 FIXME(": unimplemented with PSP_DEVINFO_DATA set\n");
1017 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1019 /* FIXME: this assumes the only possible enumeration is of serial
1022 SerialPortList
*list
= (SerialPortList
*)DeviceInfoSet
;
1024 if (list
->magic
== SETUP_SERIAL_PORT_MAGIC
)
1026 if (MemberIndex
>= list
->numPorts
)
1027 SetLastError(ERROR_NO_MORE_ITEMS
);
1030 DeviceInterfaceData
->cbSize
= sizeof(SP_DEVICE_INTERFACE_DATA
);
1031 memcpy(&DeviceInterfaceData
->InterfaceClassGuid
,
1032 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
,
1033 sizeof(DeviceInterfaceData
->InterfaceClassGuid
));
1034 DeviceInterfaceData
->Flags
= 0;
1035 /* Note: this appears to be dangerous, passing a private
1036 * pointer a heap-allocated datum to the caller. However, the
1037 * expected lifetime of the device data is the same as the
1038 * HDEVINFO; once that is closed, the data are no longer valid.
1040 DeviceInterfaceData
->Reserved
=
1041 (ULONG_PTR
)&list
->names
[MemberIndex
].name
;
1046 SetLastError(ERROR_INVALID_HANDLE
);
1049 SetLastError(ERROR_INVALID_HANDLE
);
1053 /***********************************************************************
1054 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1056 BOOL WINAPI
SetupDiDestroyDeviceInfoList(HDEVINFO devinfo
)
1060 TRACE("%p\n", devinfo
);
1061 if (devinfo
&& devinfo
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1063 /* FIXME: this assumes the only possible enumeration is of serial
1066 SerialPortList
*list
= (SerialPortList
*)devinfo
;
1068 if (list
->magic
== SETUP_SERIAL_PORT_MAGIC
)
1070 HeapFree(GetProcessHeap(), 0, list
);
1074 SetLastError(ERROR_INVALID_HANDLE
);
1077 SetLastError(ERROR_INVALID_HANDLE
);
1081 /***********************************************************************
1082 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1084 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailA(
1085 HDEVINFO DeviceInfoSet
,
1086 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
1087 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData
,
1088 DWORD DeviceInterfaceDetailDataSize
,
1089 PDWORD RequiredSize
,
1090 PSP_DEVINFO_DATA DeviceInfoData
)
1094 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet
,
1095 DeviceInterfaceData
, DeviceInterfaceDetailData
,
1096 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
1097 if (!DeviceInterfaceData
)
1098 SetLastError(ERROR_INVALID_PARAMETER
);
1099 else if ((DeviceInterfaceDetailDataSize
&& !DeviceInterfaceDetailData
) ||
1100 (DeviceInterfaceDetailData
&& !DeviceInterfaceDetailDataSize
))
1101 SetLastError(ERROR_INVALID_PARAMETER
);
1102 else if (DeviceInfoSet
&& DeviceInfoSet
!= (HDEVINFO
)INVALID_HANDLE_VALUE
)
1104 /* FIXME: this assumes the only possible enumeration is of serial
1107 SerialPortList
*list
= (SerialPortList
*)DeviceInfoSet
;
1109 if (list
->magic
== SETUP_SERIAL_PORT_MAGIC
)
1111 LPCWSTR devName
= (LPCWSTR
)DeviceInterfaceData
->Reserved
;
1112 DWORD sizeRequired
= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
) +
1115 if (sizeRequired
> DeviceInterfaceDetailDataSize
)
1117 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1119 *RequiredSize
= sizeRequired
;
1123 LPSTR dst
= DeviceInterfaceDetailData
->DevicePath
;
1124 LPCWSTR src
= devName
;
1126 /* MSDN claims cbSize must be set by the caller, but it lies */
1127 DeviceInterfaceDetailData
->cbSize
=
1128 sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A
);
1129 for ( ; *src
; src
++, dst
++)
1132 TRACE("DevicePath is %s\n",
1133 debugstr_a(DeviceInterfaceDetailData
->DevicePath
));
1136 DeviceInfoData
->cbSize
= sizeof(SP_DEVINFO_DATA
);
1137 memcpy(&DeviceInfoData
->ClassGuid
,
1138 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR
,
1139 sizeof(DeviceInfoData
->ClassGuid
));
1140 DeviceInfoData
->DevInst
= 0;
1141 DeviceInfoData
->Reserved
= (ULONG_PTR
)devName
;
1147 SetLastError(ERROR_INVALID_HANDLE
);
1150 SetLastError(ERROR_INVALID_HANDLE
);
1151 TRACE("Returning %d\n", ret
);
1155 /***********************************************************************
1156 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
1158 BOOL WINAPI
SetupDiGetDeviceInterfaceDetailW(
1159 HDEVINFO DeviceInfoSet
,
1160 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
,
1161 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData
,
1162 DWORD DeviceInterfaceDetailDataSize
,
1163 PDWORD RequiredSize
,
1164 PSP_DEVINFO_DATA DeviceInfoData
)
1166 FIXME("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet
,
1167 DeviceInterfaceData
, DeviceInterfaceDetailData
,
1168 DeviceInterfaceDetailDataSize
, RequiredSize
, DeviceInfoData
);
1172 /***********************************************************************
1173 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
1175 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyA(
1177 PSP_DEVINFO_DATA DeviceInfoData
,
1179 PDWORD PropertyRegDataType
,
1180 PBYTE PropertyBuffer
,
1181 DWORD PropertyBufferSize
,
1182 PDWORD RequiredSize
)
1185 BOOL bIsStringProperty
;
1187 DWORD RequiredSizeA
, RequiredSizeW
;
1188 DWORD PropertyBufferSizeW
;
1189 PBYTE PropertyBufferW
;
1191 TRACE("%04lx %p %ld %p %p %ld %p\n", (DWORD
)devinfo
, DeviceInfoData
,
1192 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
1195 PropertyBufferSizeW
= PropertyBufferSize
* 2;
1196 PropertyBufferW
= HeapAlloc(GetProcessHeap(), 0, PropertyBufferSizeW
);
1198 bResult
= SetupDiGetDeviceRegistryPropertyW(
1204 PropertyBufferSizeW
,
1207 HeapFree(GetProcessHeap(), 0, PropertyBufferW
);
1212 bIsStringProperty
= (RegType
== REG_SZ
|| RegType
== REG_MULTI_SZ
);
1214 if (bIsStringProperty
)
1215 RequiredSizeA
= RequiredSizeW
/ sizeof(WCHAR
);
1217 RequiredSizeA
= RequiredSizeW
;
1219 if (RequiredSizeA
<= PropertyBufferSize
)
1221 if (bIsStringProperty
&& PropertyBufferSize
> 0)
1223 if (WideCharToMultiByte(CP_ACP
, 0, (LPWSTR
)PropertyBufferW
, RequiredSizeW
/ sizeof(WCHAR
), PropertyBuffer
, PropertyBufferSize
, NULL
, NULL
) == 0)
1225 /* Last error is already set by WideCharToMultiByte */
1230 memcpy(PropertyBuffer
, PropertyBufferW
, RequiredSizeA
);
1234 SetLastError(ERROR_INSUFFICIENT_BUFFER
);
1238 if (PropertyRegDataType
)
1239 *PropertyRegDataType
= RegType
;
1241 *RequiredSize
= RequiredSizeA
;
1245 /***********************************************************************
1246 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
1248 BOOL WINAPI
SetupDiGetDeviceRegistryPropertyW(
1250 PSP_DEVINFO_DATA DeviceInfoData
,
1252 PDWORD PropertyRegDataType
,
1253 PBYTE PropertyBuffer
,
1254 DWORD PropertyBufferSize
,
1255 PDWORD RequiredSize
)
1257 FIXME("%04lx %p %ld %p %p %ld %p\n", (DWORD
)devinfo
, DeviceInfoData
,
1258 Property
, PropertyRegDataType
, PropertyBuffer
, PropertyBufferSize
,
1264 /***********************************************************************
1265 * SetupDiInstallClassA (SETUPAPI.@)
1267 BOOL WINAPI
SetupDiInstallClassA(
1273 UNICODE_STRING FileNameW
;
1276 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW
, InfFileName
))
1278 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1282 Result
= SetupDiInstallClassW(hwndParent
, FileNameW
.Buffer
, Flags
, FileQueue
);
1284 RtlFreeUnicodeString(&FileNameW
);
1289 static HKEY
CreateClassKey(HINF hInf
)
1291 WCHAR FullBuffer
[MAX_PATH
];
1292 WCHAR Buffer
[MAX_PATH
];
1297 if (!SetupGetLineTextW(NULL
,
1305 return INVALID_HANDLE_VALUE
;
1308 lstrcpyW(FullBuffer
, ControlClass
);
1309 lstrcatW(FullBuffer
, Buffer
);
1312 if (!SetupGetLineTextW(NULL
,
1320 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
1321 return INVALID_HANDLE_VALUE
;
1324 if (ERROR_SUCCESS
!= RegCreateKeyExW(HKEY_LOCAL_MACHINE
,
1328 REG_OPTION_NON_VOLATILE
,
1334 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
1335 return INVALID_HANDLE_VALUE
;
1338 if (ERROR_SUCCESS
!= RegSetValueExW(hClassKey
,
1343 RequiredSize
* sizeof(WCHAR
)))
1345 RegCloseKey(hClassKey
);
1346 RegDeleteKeyW(HKEY_LOCAL_MACHINE
, FullBuffer
);
1347 return INVALID_HANDLE_VALUE
;
1353 /***********************************************************************
1354 * SetupDiInstallClassW (SETUPAPI.@)
1356 BOOL WINAPI
SetupDiInstallClassW(
1362 WCHAR SectionName
[MAX_PATH
];
1363 DWORD SectionNameLength
= 0;
1365 BOOL bFileQueueCreated
= FALSE
;
1368 FIXME("not fully implemented\n");
1370 if ((Flags
& DI_NOVCP
) && (FileQueue
== NULL
|| FileQueue
== INVALID_HANDLE_VALUE
))
1372 SetLastError(ERROR_INVALID_PARAMETER
);
1376 /* Open the .inf file */
1377 hInf
= SetupOpenInfFileW(InfFileName
,
1381 if (hInf
== INVALID_HANDLE_VALUE
)
1387 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
1388 hClassKey
= CreateClassKey(hInf
);
1389 if (hClassKey
== INVALID_HANDLE_VALUE
)
1391 SetupCloseInfFile(hInf
);
1394 RegCloseKey(hClassKey
);
1397 /* Try to append a layout file */
1399 SetupOpenAppendInfFileW(NULL
, hInf
, NULL
);
1402 /* Retrieve the actual section name */
1403 SetupDiGetActualSectionToInstallW(hInf
,
1411 if (!(Flags
& DI_NOVCP
))
1413 FileQueue
= SetupOpenFileQueue();
1414 if (FileQueue
== INVALID_HANDLE_VALUE
)
1416 SetupCloseInfFile(hInf
);
1420 bFileQueueCreated
= TRUE
;
1425 SetupInstallFromInfSectionW(NULL
,
1434 INVALID_HANDLE_VALUE
,
1437 /* FIXME: More code! */
1439 if (bFileQueueCreated
)
1440 SetupCloseFileQueue(FileQueue
);
1442 SetupCloseInfFile(hInf
);
1448 /***********************************************************************
1449 * SetupDiOpenClassRegKey (SETUPAPI.@)
1451 HKEY WINAPI
SetupDiOpenClassRegKey(
1452 const GUID
* ClassGuid
,
1455 return SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
1456 DIOCR_INSTALLER
, NULL
, NULL
);
1460 /***********************************************************************
1461 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
1463 HKEY WINAPI
SetupDiOpenClassRegKeyExA(
1464 const GUID
* ClassGuid
,
1470 PWSTR MachineNameW
= NULL
;
1477 MachineNameW
= MultiByteToUnicode(MachineName
, CP_ACP
);
1478 if (MachineNameW
== NULL
)
1479 return INVALID_HANDLE_VALUE
;
1482 hKey
= SetupDiOpenClassRegKeyExW(ClassGuid
, samDesired
,
1483 Flags
, MachineNameW
, Reserved
);
1486 MyFree(MachineNameW
);
1492 /***********************************************************************
1493 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
1495 HKEY WINAPI
SetupDiOpenClassRegKeyExW(
1496 const GUID
* ClassGuid
,
1502 LPWSTR lpGuidString
;
1503 LPWSTR lpFullGuidString
;
1509 if (MachineName
!= NULL
)
1511 FIXME("Remote access not supported yet!\n");
1512 return INVALID_HANDLE_VALUE
;
1515 if (Flags
== DIOCR_INSTALLER
)
1517 lpKeyName
= ControlClass
;
1519 else if (Flags
== DIOCR_INTERFACE
)
1521 lpKeyName
= DeviceClasses
;
1525 ERR("Invalid Flags parameter!\n");
1526 SetLastError(ERROR_INVALID_PARAMETER
);
1527 return INVALID_HANDLE_VALUE
;
1530 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1536 return INVALID_HANDLE_VALUE
;
1539 if (ClassGuid
== NULL
)
1542 if (UuidToStringW((UUID
*)ClassGuid
, &lpGuidString
) != RPC_S_OK
)
1544 RegCloseKey(hClassesKey
);
1545 return INVALID_HANDLE_VALUE
;
1548 dwLength
= lstrlenW(lpGuidString
);
1549 lpFullGuidString
= HeapAlloc(GetProcessHeap(), 0, (dwLength
+ 3) * sizeof(WCHAR
));
1550 if (!lpFullGuidString
)
1552 RpcStringFreeW(&lpGuidString
);
1553 return INVALID_HANDLE_VALUE
;
1555 lpFullGuidString
[0] = '{';
1556 memcpy(&lpFullGuidString
[1], lpGuidString
, dwLength
* sizeof(WCHAR
));
1557 lpFullGuidString
[dwLength
+ 1] = '}';
1558 lpFullGuidString
[dwLength
+ 2] = UNICODE_NULL
;
1559 RpcStringFreeW(&lpGuidString
);
1561 if (RegOpenKeyExW(hClassesKey
,
1567 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
1568 RegCloseKey(hClassesKey
);
1569 return INVALID_HANDLE_VALUE
;
1572 HeapFree(GetProcessHeap(), 0, lpFullGuidString
);
1573 RegCloseKey(hClassesKey
);
1578 /***********************************************************************
1579 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
1581 BOOL WINAPI
SetupDiOpenDeviceInterfaceW(
1582 HDEVINFO DeviceInfoSet
,
1585 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1587 FIXME("%p %s %08lx %p\n",
1588 DeviceInfoSet
, debugstr_w(DevicePath
), OpenFlags
, DeviceInterfaceData
);
1592 /***********************************************************************
1593 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
1595 BOOL WINAPI
SetupDiOpenDeviceInterfaceA(
1596 HDEVINFO DeviceInfoSet
,
1599 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData
)
1601 FIXME("%p %s %08lx %p\n", DeviceInfoSet
,
1602 debugstr_a(DevicePath
), OpenFlags
, DeviceInterfaceData
);
1606 /***********************************************************************
1607 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
1609 BOOL WINAPI
SetupDiSetClassInstallParamsA(
1610 HDEVINFO DeviceInfoSet
,
1611 PSP_DEVINFO_DATA DeviceInfoData
,
1612 PSP_CLASSINSTALL_HEADER ClassInstallParams
,
1613 DWORD ClassInstallParamsSize
)
1615 FIXME("%p %p %x %lu\n",DeviceInfoSet
, DeviceInfoData
,
1616 ClassInstallParams
->InstallFunction
, ClassInstallParamsSize
);
1620 /***********************************************************************
1621 * SetupDiCallClassInstaller (SETUPAPI.@)
1623 BOOL WINAPI
SetupDiCallClassInstaller(
1624 DWORD InstallFunction
,
1625 HDEVINFO DeviceInfoSet
,
1626 PSP_DEVINFO_DATA DeviceInfoData
)
1628 FIXME("%ld %p %p\n", InstallFunction
, DeviceInfoSet
, DeviceInfoData
);
1632 /***********************************************************************
1633 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
1635 BOOL WINAPI
SetupDiGetDeviceInstallParamsA(
1636 HDEVINFO DeviceInfoSet
,
1637 PSP_DEVINFO_DATA DeviceInfoData
,
1638 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams
)
1640 FIXME("%p %p %p\n", DeviceInfoSet
, DeviceInfoData
, DeviceInstallParams
);
1644 /***********************************************************************
1645 * SetupDiOpenDevRegKey (SETUPAPI.@)
1647 HKEY WINAPI
SetupDiOpenDevRegKey(
1648 HDEVINFO DeviceInfoSet
,
1649 PSP_DEVINFO_DATA DeviceInfoData
,
1655 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet
, DeviceInfoData
,
1656 Scope
, HwProfile
, KeyType
, samDesired
);
1657 return INVALID_HANDLE_VALUE
;
1660 /***********************************************************************
1661 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
1663 BOOL WINAPI
SetupDiCreateDeviceInfoA(
1664 HDEVINFO DeviceInfoSet
,
1667 PCSTR DeviceDescription
,
1669 DWORD CreationFlags
,
1670 PSP_DEVINFO_DATA DeviceInfoData
)
1672 LPWSTR DeviceNameW
= NULL
;
1673 LPWSTR DeviceDescriptionW
= NULL
;
1680 DeviceNameW
= MultiByteToUnicode(DeviceName
, CP_ACP
);
1681 if (DeviceNameW
== NULL
) return FALSE
;
1683 if (DeviceDescription
)
1685 DeviceDescriptionW
= MultiByteToUnicode(DeviceDescription
, CP_ACP
);
1686 if (DeviceDescriptionW
== NULL
)
1688 if (DeviceNameW
) MyFree(DeviceNameW
);
1693 bResult
= SetupDiCreateDeviceInfoW(DeviceInfoSet
, DeviceNameW
,
1694 ClassGuid
, DeviceDescriptionW
,
1695 hwndParent
, CreationFlags
,
1698 if (DeviceNameW
) MyFree(DeviceNameW
);
1699 if (DeviceDescriptionW
) MyFree(DeviceDescriptionW
);
1704 /***********************************************************************
1705 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
1707 BOOL WINAPI
SetupDiCreateDeviceInfoW(
1708 HDEVINFO DeviceInfoSet
,
1711 PCWSTR DeviceDescription
,
1713 DWORD CreationFlags
,
1714 PSP_DEVINFO_DATA DeviceInfoData
)
1716 FIXME("%p %S %p %S %p %lx %p\n", DeviceInfoSet
, debugstr_w(DeviceName
),
1717 ClassGuid
, debugstr_w(DeviceDescription
), hwndParent
,
1718 CreationFlags
, DeviceInfoData
);