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,
637 /***********************************************************************
638 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
640 BOOL WINAPI SetupDiGetActualSectionToInstallW(
642 PCWSTR InfSectionName,
643 PWSTR InfSectionWithExt,
644 DWORD InfSectionWithExtSize,
648 WCHAR szBuffer[MAX_PATH];
651 LONG lLineCount = -1;
653 lstrcpyW(szBuffer, InfSectionName);
654 dwLength = lstrlenW(szBuffer);
656 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
658 /* Test section name with '.NTx86' extension */
659 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
660 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
662 if (lLineCount == -1)
664 /* Test section name with '.NT' extension */
665 lstrcpyW(&szBuffer[dwLength], NtExtension);
666 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
671 /* Test section name with '.Win' extension */
672 lstrcpyW(&szBuffer[dwLength], WinExtension);
673 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
676 if (lLineCount == -1)
678 /* Test section name without extension */
679 szBuffer[dwLength] = 0;
680 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
683 if (lLineCount == -1)
685 SetLastError(ERROR_INVALID_PARAMETER);
689 dwFullLength = lstrlenW(szBuffer);
691 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
693 if (InfSectionWithExtSize < (dwFullLength + 1))
695 SetLastError(ERROR_INSUFFICIENT_BUFFER);
699 lstrcpyW(InfSectionWithExt, szBuffer);
700 if (Extension != NULL)
702 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
706 if (RequiredSize != NULL)
708 *RequiredSize = dwFullLength + 1;
714 /***********************************************************************
715 * SetupDiGetClassDescriptionA (SETUPAPI.@)
717 BOOL WINAPI SetupDiGetClassDescriptionA(
718 const GUID* ClassGuid,
719 PSTR ClassDescription,
720 DWORD ClassDescriptionSize,
723 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
724 ClassDescriptionSize,
725 RequiredSize, NULL, NULL);
728 /***********************************************************************
729 * SetupDiGetClassDescriptionW (SETUPAPI.@)
731 BOOL WINAPI SetupDiGetClassDescriptionW(
732 const GUID* ClassGuid,
733 PWSTR ClassDescription,
734 DWORD ClassDescriptionSize,
737 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
738 ClassDescriptionSize,
739 RequiredSize, NULL, NULL);
742 /***********************************************************************
743 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
745 BOOL WINAPI SetupDiGetClassDescriptionExA(
746 const GUID* ClassGuid,
747 PSTR ClassDescription,
748 DWORD ClassDescriptionSize,
757 /***********************************************************************
758 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
760 BOOL WINAPI SetupDiGetClassDescriptionExW(
761 const GUID* ClassGuid,
762 PWSTR ClassDescription,
763 DWORD ClassDescriptionSize,
771 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
776 if (hKey == INVALID_HANDLE_VALUE)
778 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
782 if (RequiredSize != NULL)
785 if (RegQueryValueExW(hKey,
796 *RequiredSize = dwLength / sizeof(WCHAR);
799 dwLength = ClassDescriptionSize * sizeof(WCHAR);
800 if (RegQueryValueExW(hKey,
804 (LPBYTE)ClassDescription,
816 /***********************************************************************
817 * SetupDiGetClassDevsA (SETUPAPI.@)
819 HDEVINFO WINAPI SetupDiGetClassDevsA(
826 LPWSTR enumstrW = NULL;
830 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
831 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
834 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
837 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
839 ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
840 HeapFree(GetProcessHeap(), 0, enumstrW);
846 #define SETUP_SERIAL_PORT_MAGIC 0xd00ff055
848 typedef struct _SerialPortName
853 typedef struct _SerialPortList
857 SerialPortName names[1];
860 static HDEVINFO SETUP_CreateSerialDeviceList(void)
862 static const size_t initialSize = 100;
864 WCHAR buf[initialSize];
872 if (QueryDosDeviceW(NULL, devices, size) == 0)
874 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
878 HeapFree(GetProcessHeap(), 0, devices);
879 devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
888 } while (!*devices && !failed);
891 static const WCHAR comW[] = { 'C','O','M',0 };
893 UINT numSerialPorts = 0;
894 SerialPortList *list;
896 for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
898 if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1))
901 list = HeapAlloc(GetProcessHeap(), 0, sizeof(SerialPortList) +
902 numSerialPorts ? (numSerialPorts - 1) * sizeof(SerialPortName) : 0);
905 list->magic = SETUP_SERIAL_PORT_MAGIC;
907 for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1)
909 if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1))
911 lstrcpynW(list->names[list->numPorts].name, ptr,
912 sizeof(list->names[list->numPorts].name) /
913 sizeof(list->names[list->numPorts].name[0]));
914 TRACE("Adding %s to list\n",
915 debugstr_w(list->names[list->numPorts].name));
919 TRACE("list->numPorts is %d\n", list->numPorts);
921 ret = (HDEVINFO)list;
924 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
926 HeapFree(GetProcessHeap(), 0, devices);
927 TRACE("returning %p\n", ret);
931 /***********************************************************************
932 * SetupDiGetClassDevsW (SETUPAPI.@)
934 HDEVINFO WINAPI SetupDiGetClassDevsW(
940 HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;
942 TRACE("%s %s %p 0x%08lx\n", debugstr_guid(class), debugstr_w(enumstr),
946 FIXME(": unimplemented for enumerator strings (%s)\n",
947 debugstr_w(enumstr));
948 else if (flags & DIGCF_ALLCLASSES)
949 FIXME(": unimplemented for DIGCF_ALLCLASSES\n");
952 if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT))
953 ret = SETUP_CreateSerialDeviceList();
954 else if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR))
955 ret = SETUP_CreateSerialDeviceList();
957 FIXME("(%s): stub\n", debugstr_guid(class));
962 /***********************************************************************
963 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
965 BOOL WINAPI SetupDiEnumDeviceInterfaces(
966 HDEVINFO DeviceInfoSet,
967 PSP_DEVINFO_DATA DeviceInfoData,
968 CONST GUID * InterfaceClassGuid,
970 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
974 TRACE("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet, DeviceInfoData,
975 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
976 if (!DeviceInterfaceData)
977 SetLastError(ERROR_INVALID_PARAMETER);
978 else if (DeviceInfoData)
979 FIXME(": unimplemented with PSP_DEVINFO_DATA set\n");
980 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
982 /* FIXME: this assumes the only possible enumeration is of serial
985 SerialPortList *list = (SerialPortList *)DeviceInfoSet;
987 if (list->magic == SETUP_SERIAL_PORT_MAGIC)
989 if (MemberIndex >= list->numPorts)
990 SetLastError(ERROR_NO_MORE_ITEMS);
993 DeviceInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
994 memcpy(&DeviceInterfaceData->InterfaceClassGuid,
995 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
996 sizeof(DeviceInterfaceData->InterfaceClassGuid));
997 DeviceInterfaceData->Flags = 0;
998 /* Note: this appears to be dangerous, passing a private
999 * pointer a heap-allocated datum to the caller. However, the
1000 * expected lifetime of the device data is the same as the
1001 * HDEVINFO; once that is closed, the data are no longer valid.
1003 DeviceInterfaceData->Reserved =
1004 (ULONG_PTR)&list->names[MemberIndex].name;
1009 SetLastError(ERROR_INVALID_HANDLE);
1012 SetLastError(ERROR_INVALID_HANDLE);
1016 /***********************************************************************
1017 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1019 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1023 TRACE("%p\n", devinfo);
1024 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1026 /* FIXME: this assumes the only possible enumeration is of serial
1029 SerialPortList *list = (SerialPortList *)devinfo;
1031 if (list->magic == SETUP_SERIAL_PORT_MAGIC)
1033 HeapFree(GetProcessHeap(), 0, list);
1037 SetLastError(ERROR_INVALID_HANDLE);
1040 SetLastError(ERROR_INVALID_HANDLE);
1044 /***********************************************************************
1045 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1047 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
1048 HDEVINFO DeviceInfoSet,
1049 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1050 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
1051 DWORD DeviceInterfaceDetailDataSize,
1052 PDWORD RequiredSize,
1053 PSP_DEVINFO_DATA DeviceInfoData)
1057 TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet,
1058 DeviceInterfaceData, DeviceInterfaceDetailData,
1059 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1060 if (!DeviceInterfaceData)
1061 SetLastError(ERROR_INVALID_PARAMETER);
1062 else if ((DeviceInterfaceDetailDataSize && !DeviceInterfaceDetailData) ||
1063 (DeviceInterfaceDetailData && !DeviceInterfaceDetailDataSize))
1064 SetLastError(ERROR_INVALID_PARAMETER);
1065 else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
1067 /* FIXME: this assumes the only possible enumeration is of serial
1070 SerialPortList *list = (SerialPortList *)DeviceInfoSet;
1072 if (list->magic == SETUP_SERIAL_PORT_MAGIC)
1074 LPCWSTR devName = (LPCWSTR)DeviceInterfaceData->Reserved;
1075 DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A) +
1078 if (sizeRequired > DeviceInterfaceDetailDataSize)
1080 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1082 *RequiredSize = sizeRequired;
1086 LPSTR dst = DeviceInterfaceDetailData->DevicePath;
1087 LPCWSTR src = devName;
1089 /* MSDN claims cbSize must be set by the caller, but it lies */
1090 DeviceInterfaceDetailData->cbSize =
1091 sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A);
1092 for ( ; *src; src++, dst++)
1095 TRACE("DevicePath is %s\n",
1096 debugstr_a(DeviceInterfaceDetailData->DevicePath));
1099 DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
1100 memcpy(&DeviceInfoData->ClassGuid,
1101 &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR,
1102 sizeof(DeviceInfoData->ClassGuid));
1103 DeviceInfoData->DevInst = 0;
1104 DeviceInfoData->Reserved = (ULONG_PTR)devName;
1110 SetLastError(ERROR_INVALID_HANDLE);
1113 SetLastError(ERROR_INVALID_HANDLE);
1114 TRACE("Returning %d\n", ret);
1118 /***********************************************************************
1119 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
1121 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
1122 HDEVINFO DeviceInfoSet,
1123 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1124 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
1125 DWORD DeviceInterfaceDetailDataSize,
1126 PDWORD RequiredSize,
1127 PSP_DEVINFO_DATA DeviceInfoData)
1129 FIXME("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet,
1130 DeviceInterfaceData, DeviceInterfaceDetailData,
1131 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1135 /***********************************************************************
1136 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
1138 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
1140 PSP_DEVINFO_DATA DeviceInfoData,
1142 PDWORD PropertyRegDataType,
1143 PBYTE PropertyBuffer,
1144 DWORD PropertyBufferSize,
1145 PDWORD RequiredSize)
1147 FIXME("%04lx %p %ld %p %p %ld %p\n", (DWORD)devinfo, DeviceInfoData,
1148 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1153 /***********************************************************************
1154 * SetupDiInstallClassA (SETUPAPI.@)
1156 BOOL WINAPI SetupDiInstallClassA(
1162 UNICODE_STRING FileNameW;
1165 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
1167 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1171 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
1173 RtlFreeUnicodeString(&FileNameW);
1178 static HKEY CreateClassKey(HINF hInf)
1180 WCHAR FullBuffer[MAX_PATH];
1181 WCHAR Buffer[MAX_PATH];
1185 if (!SetupGetLineTextW(NULL,
1193 return INVALID_HANDLE_VALUE;
1196 lstrcpyW(FullBuffer, ControlClass);
1197 lstrcatW(FullBuffer, Buffer);
1199 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1205 if (!SetupGetLineTextW(NULL,
1213 return INVALID_HANDLE_VALUE;
1216 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
1220 REG_OPTION_NON_VOLATILE,
1226 return INVALID_HANDLE_VALUE;
1231 if (RegSetValueExW(hClassKey,
1236 RequiredSize * sizeof(WCHAR)))
1238 RegCloseKey(hClassKey);
1239 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
1241 return INVALID_HANDLE_VALUE;
1247 /***********************************************************************
1248 * SetupDiInstallClassW (SETUPAPI.@)
1250 BOOL WINAPI SetupDiInstallClassW(
1256 WCHAR SectionName[MAX_PATH];
1257 DWORD SectionNameLength = 0;
1259 BOOL bFileQueueCreated = FALSE;
1265 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
1267 SetLastError(ERROR_INVALID_PARAMETER);
1271 /* Open the .inf file */
1272 hInf = SetupOpenInfFileW(InfFileName,
1276 if (hInf == INVALID_HANDLE_VALUE)
1282 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
1283 hClassKey = CreateClassKey(hInf);
1284 if (hClassKey == INVALID_HANDLE_VALUE)
1286 SetupCloseInfFile(hInf);
1291 /* Try to append a layout file */
1293 SetupOpenAppendInfFileW(NULL, hInf, NULL);
1296 /* Retrieve the actual section name */
1297 SetupDiGetActualSectionToInstallW(hInf,
1305 if (!(Flags & DI_NOVCP))
1307 FileQueue = SetupOpenFileQueue();
1308 if (FileQueue == INVALID_HANDLE_VALUE)
1310 SetupCloseInfFile(hInf);
1314 bFileQueueCreated = TRUE;
1319 SetupInstallFromInfSectionW(NULL,
1328 INVALID_HANDLE_VALUE,
1331 /* FIXME: More code! */
1333 if (bFileQueueCreated)
1334 SetupCloseFileQueue(FileQueue);
1336 SetupCloseInfFile(hInf);
1342 /***********************************************************************
1343 * SetupDiOpenClassRegKey (SETUPAPI.@)
1345 HKEY WINAPI SetupDiOpenClassRegKey(
1346 const GUID* ClassGuid,
1349 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1350 DIOCR_INSTALLER, NULL, NULL);
1354 /***********************************************************************
1355 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
1357 HKEY WINAPI SetupDiOpenClassRegKeyExA(
1358 const GUID* ClassGuid,
1364 PWSTR MachineNameW = NULL;
1371 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1372 if (MachineNameW == NULL)
1373 return INVALID_HANDLE_VALUE;
1376 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1377 Flags, MachineNameW, Reserved);
1380 MyFree(MachineNameW);
1386 /***********************************************************************
1387 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
1389 HKEY WINAPI SetupDiOpenClassRegKeyExW(
1390 const GUID* ClassGuid,
1396 LPWSTR lpGuidString;
1401 if (MachineName != NULL)
1403 FIXME("Remote access not supported yet!\n");
1404 return INVALID_HANDLE_VALUE;
1407 if (Flags == DIOCR_INSTALLER)
1409 lpKeyName = ControlClass;
1411 else if (Flags == DIOCR_INTERFACE)
1413 lpKeyName = DeviceClasses;
1417 ERR("Invalid Flags parameter!\n");
1418 SetLastError(ERROR_INVALID_PARAMETER);
1419 return INVALID_HANDLE_VALUE;
1422 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1428 return INVALID_HANDLE_VALUE;
1431 if (ClassGuid == NULL)
1434 if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
1436 RegCloseKey(hClassesKey);
1440 if (RegOpenKeyExW(hClassesKey,
1446 RpcStringFreeW(&lpGuidString);
1447 RegCloseKey(hClassesKey);
1451 RpcStringFreeW(&lpGuidString);
1452 RegCloseKey(hClassesKey);
1457 /***********************************************************************
1458 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
1460 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
1461 HDEVINFO DeviceInfoSet,
1464 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1466 FIXME("%p %s %08lx %p\n",
1467 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
1471 /***********************************************************************
1472 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
1474 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
1475 HDEVINFO DeviceInfoSet,
1478 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1480 FIXME("%p %s %08lx %p\n", DeviceInfoSet,
1481 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
1485 /***********************************************************************
1486 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
1488 BOOL WINAPI SetupDiSetClassInstallParamsA(
1489 HDEVINFO DeviceInfoSet,
1490 PSP_DEVINFO_DATA DeviceInfoData,
1491 PSP_CLASSINSTALL_HEADER ClassInstallParams,
1492 DWORD ClassInstallParamsSize)
1494 FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
1495 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
1499 /***********************************************************************
1500 * SetupDiCallClassInstaller (SETUPAPI.@)
1502 BOOL WINAPI SetupDiCallClassInstaller(
1503 DI_FUNCTION InstallFunction,
1504 HDEVINFO DeviceInfoSet,
1505 PSP_DEVINFO_DATA DeviceInfoData)
1507 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
1511 /***********************************************************************
1512 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
1514 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
1515 HDEVINFO DeviceInfoSet,
1516 PSP_DEVINFO_DATA DeviceInfoData,
1517 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
1519 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1523 /***********************************************************************
1524 * SetupDiOpenDevRegKey (SETUPAPI.@)
1526 HKEY WINAPI SetupDiOpenDevRegKey(
1527 HDEVINFO DeviceInfoSet,
1528 PSP_DEVINFO_DATA DeviceInfoData,
1534 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet, DeviceInfoData,
1535 Scope, HwProfile, KeyType, samDesired);
1536 return INVALID_HANDLE_VALUE;