rpcrt4: Use safe_mutiply in conformant array functions.
[wine/multimedia.git] / dlls / setupapi / devinst.c
blobe8b5e972fd414cf9edd3a0314d46a4ae0acd7a00
1 /*
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnt.h"
29 #include "winreg.h"
30 #include "winternl.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "winnls.h"
34 #include "setupapi.h"
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
37 #include "ddk/cfgmgr32.h"
38 #include "initguid.h"
39 #include "winioctl.h"
40 #include "rpc.h"
41 #include "rpcdce.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(
75 DWORD Flags,
76 LPGUID ClassGuidList,
77 DWORD ClassGuidListSize,
78 PDWORD RequiredSize)
80 TRACE("\n");
81 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
82 ClassGuidListSize, RequiredSize,
83 NULL, NULL);
86 /***********************************************************************
87 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
89 BOOL WINAPI SetupDiBuildClassInfoListExA(
90 DWORD Flags,
91 LPGUID ClassGuidList,
92 DWORD ClassGuidListSize,
93 PDWORD RequiredSize,
94 LPCSTR MachineName,
95 PVOID Reserved)
97 LPWSTR MachineNameW = NULL;
98 BOOL bResult;
100 TRACE("\n");
102 if (MachineName)
104 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
105 if (MachineNameW == NULL) return FALSE;
108 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
109 ClassGuidListSize, RequiredSize,
110 MachineNameW, Reserved);
112 if (MachineNameW)
113 MyFree(MachineNameW);
115 return bResult;
118 /***********************************************************************
119 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
121 BOOL WINAPI SetupDiBuildClassInfoListExW(
122 DWORD Flags,
123 LPGUID ClassGuidList,
124 DWORD ClassGuidListSize,
125 PDWORD RequiredSize,
126 LPCWSTR MachineName,
127 PVOID Reserved)
129 WCHAR szKeyName[40];
130 HKEY hClassesKey;
131 HKEY hClassKey;
132 DWORD dwLength;
133 DWORD dwIndex;
134 LONG lError;
135 DWORD dwGuidListIndex = 0;
137 TRACE("\n");
139 if (RequiredSize != NULL)
140 *RequiredSize = 0;
142 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
143 KEY_ALL_ACCESS,
144 DIOCR_INSTALLER,
145 MachineName,
146 Reserved);
147 if (hClassesKey == INVALID_HANDLE_VALUE)
149 return FALSE;
152 for (dwIndex = 0; ; dwIndex++)
154 dwLength = 40;
155 lError = RegEnumKeyExW(hClassesKey,
156 dwIndex,
157 szKeyName,
158 &dwLength,
159 NULL,
160 NULL,
161 NULL,
162 NULL);
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,
169 szKeyName,
171 KEY_ALL_ACCESS,
172 &hClassKey))
174 RegCloseKey(hClassesKey);
175 return FALSE;
178 if (!RegQueryValueExW(hClassKey,
179 NoUseClass,
180 NULL,
181 NULL,
182 NULL,
183 NULL))
185 TRACE("'NoUseClass' value found!\n");
186 RegCloseKey(hClassKey);
187 continue;
190 if ((Flags & DIBCI_NOINSTALLCLASS) &&
191 (!RegQueryValueExW(hClassKey,
192 NoInstallClass,
193 NULL,
194 NULL,
195 NULL,
196 NULL)))
198 TRACE("'NoInstallClass' value found!\n");
199 RegCloseKey(hClassKey);
200 continue;
203 if ((Flags & DIBCI_NODISPLAYCLASS) &&
204 (!RegQueryValueExW(hClassKey,
205 NoDisplayClass,
206 NULL,
207 NULL,
208 NULL,
209 NULL)))
211 TRACE("'NoDisplayClass' value found!\n");
212 RegCloseKey(hClassKey);
213 continue;
216 RegCloseKey(hClassKey);
218 TRACE("Guid: %p\n", szKeyName);
219 if (dwGuidListIndex < ClassGuidListSize)
221 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
223 szKeyName[37] = 0;
225 TRACE("Guid: %p\n", &szKeyName[1]);
227 UuidFromStringW(&szKeyName[1],
228 &ClassGuidList[dwGuidListIndex]);
231 dwGuidListIndex++;
234 if (lError != ERROR_SUCCESS)
235 break;
238 RegCloseKey(hClassesKey);
240 if (RequiredSize != NULL)
241 *RequiredSize = dwGuidListIndex;
243 if (ClassGuidListSize < dwGuidListIndex)
245 SetLastError(ERROR_INSUFFICIENT_BUFFER);
246 return FALSE;
249 return TRUE;
252 /***********************************************************************
253 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
255 BOOL WINAPI SetupDiClassGuidsFromNameA(
256 LPCSTR ClassName,
257 LPGUID ClassGuidList,
258 DWORD ClassGuidListSize,
259 PDWORD RequiredSize)
261 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
262 ClassGuidListSize, RequiredSize,
263 NULL, NULL);
266 /***********************************************************************
267 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
269 BOOL WINAPI SetupDiClassGuidsFromNameW(
270 LPCWSTR ClassName,
271 LPGUID ClassGuidList,
272 DWORD ClassGuidListSize,
273 PDWORD RequiredSize)
275 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
276 ClassGuidListSize, RequiredSize,
277 NULL, NULL);
280 /***********************************************************************
281 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
283 BOOL WINAPI SetupDiClassGuidsFromNameExA(
284 LPCSTR ClassName,
285 LPGUID ClassGuidList,
286 DWORD ClassGuidListSize,
287 PDWORD RequiredSize,
288 LPCSTR MachineName,
289 PVOID Reserved)
291 LPWSTR ClassNameW = NULL;
292 LPWSTR MachineNameW = NULL;
293 BOOL bResult;
295 FIXME("\n");
297 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
298 if (ClassNameW == NULL)
299 return FALSE;
301 if (MachineNameW)
303 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
304 if (MachineNameW == NULL)
306 MyFree(ClassNameW);
307 return FALSE;
311 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
312 ClassGuidListSize, RequiredSize,
313 MachineNameW, Reserved);
315 if (MachineNameW)
316 MyFree(MachineNameW);
318 MyFree(ClassNameW);
320 return bResult;
323 /***********************************************************************
324 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
326 BOOL WINAPI SetupDiClassGuidsFromNameExW(
327 LPCWSTR ClassName,
328 LPGUID ClassGuidList,
329 DWORD ClassGuidListSize,
330 PDWORD RequiredSize,
331 LPCWSTR MachineName,
332 PVOID Reserved)
334 WCHAR szKeyName[40];
335 WCHAR szClassName[256];
336 HKEY hClassesKey;
337 HKEY hClassKey;
338 DWORD dwLength;
339 DWORD dwIndex;
340 LONG lError;
341 DWORD dwGuidListIndex = 0;
343 if (RequiredSize != NULL)
344 *RequiredSize = 0;
346 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
347 KEY_ALL_ACCESS,
348 DIOCR_INSTALLER,
349 MachineName,
350 Reserved);
351 if (hClassesKey == INVALID_HANDLE_VALUE)
353 return FALSE;
356 for (dwIndex = 0; ; dwIndex++)
358 dwLength = 40;
359 lError = RegEnumKeyExW(hClassesKey,
360 dwIndex,
361 szKeyName,
362 &dwLength,
363 NULL,
364 NULL,
365 NULL,
366 NULL);
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,
373 szKeyName,
375 KEY_ALL_ACCESS,
376 &hClassKey))
378 RegCloseKey(hClassesKey);
379 return FALSE;
382 dwLength = 256 * sizeof(WCHAR);
383 if (!RegQueryValueExW(hClassKey,
384 Class,
385 NULL,
386 NULL,
387 (LPBYTE)szClassName,
388 &dwLength))
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'}')
401 szKeyName[37] = 0;
403 TRACE("Guid: %p\n", &szKeyName[1]);
405 UuidFromStringW(&szKeyName[1],
406 &ClassGuidList[dwGuidListIndex]);
409 dwGuidListIndex++;
413 RegCloseKey(hClassKey);
416 if (lError != ERROR_SUCCESS)
417 break;
420 RegCloseKey(hClassesKey);
422 if (RequiredSize != NULL)
423 *RequiredSize = dwGuidListIndex;
425 if (ClassGuidListSize < dwGuidListIndex)
427 SetLastError(ERROR_INSUFFICIENT_BUFFER);
428 return FALSE;
431 return TRUE;
434 /***********************************************************************
435 * SetupDiClassNameFromGuidA (SETUPAPI.@)
437 BOOL WINAPI SetupDiClassNameFromGuidA(
438 const GUID* ClassGuid,
439 PSTR ClassName,
440 DWORD ClassNameSize,
441 PDWORD RequiredSize)
443 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
444 ClassNameSize, RequiredSize,
445 NULL, NULL);
448 /***********************************************************************
449 * SetupDiClassNameFromGuidW (SETUPAPI.@)
451 BOOL WINAPI SetupDiClassNameFromGuidW(
452 const GUID* ClassGuid,
453 PWSTR ClassName,
454 DWORD ClassNameSize,
455 PDWORD RequiredSize)
457 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
458 ClassNameSize, RequiredSize,
459 NULL, NULL);
462 /***********************************************************************
463 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
465 BOOL WINAPI SetupDiClassNameFromGuidExA(
466 const GUID* ClassGuid,
467 PSTR ClassName,
468 DWORD ClassNameSize,
469 PDWORD RequiredSize,
470 PCSTR MachineName,
471 PVOID Reserved)
473 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
474 LPWSTR MachineNameW = NULL;
475 BOOL ret;
477 if (MachineName)
478 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
479 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
480 NULL, MachineNameW, Reserved);
481 if (ret)
483 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
484 ClassNameSize, NULL, NULL);
486 if (!ClassNameSize && RequiredSize)
487 *RequiredSize = len;
489 MyFree(MachineNameW);
490 return ret;
493 /***********************************************************************
494 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
496 BOOL WINAPI SetupDiClassNameFromGuidExW(
497 const GUID* ClassGuid,
498 PWSTR ClassName,
499 DWORD ClassNameSize,
500 PDWORD RequiredSize,
501 PCWSTR MachineName,
502 PVOID Reserved)
504 HKEY hKey;
505 DWORD dwLength;
507 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
508 KEY_ALL_ACCESS,
509 DIOCR_INSTALLER,
510 MachineName,
511 Reserved);
512 if (hKey == INVALID_HANDLE_VALUE)
514 return FALSE;
517 if (RequiredSize != NULL)
519 dwLength = 0;
520 if (RegQueryValueExW(hKey,
521 Class,
522 NULL,
523 NULL,
524 NULL,
525 &dwLength))
527 RegCloseKey(hKey);
528 return FALSE;
531 *RequiredSize = dwLength / sizeof(WCHAR);
534 dwLength = ClassNameSize * sizeof(WCHAR);
535 if (RegQueryValueExW(hKey,
536 Class,
537 NULL,
538 NULL,
539 (LPBYTE)ClassName,
540 &dwLength))
542 RegCloseKey(hKey);
543 return FALSE;
546 RegCloseKey(hKey);
548 return TRUE;
551 /***********************************************************************
552 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
554 HDEVINFO WINAPI
555 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
556 HWND hwndParent)
558 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
561 /***********************************************************************
562 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
564 HDEVINFO WINAPI
565 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
566 HWND hwndParent,
567 PCSTR MachineName,
568 PVOID Reserved)
570 LPWSTR MachineNameW = NULL;
571 HDEVINFO hDevInfo;
573 TRACE("\n");
575 if (MachineName)
577 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
578 if (MachineNameW == NULL)
579 return (HDEVINFO)INVALID_HANDLE_VALUE;
582 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
583 MachineNameW, Reserved);
585 if (MachineNameW)
586 MyFree(MachineNameW);
588 return hDevInfo;
591 /***********************************************************************
592 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
594 HDEVINFO WINAPI
595 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
596 HWND hwndParent,
597 PCWSTR MachineName,
598 PVOID Reserved)
600 FIXME("\n");
601 return (HDEVINFO)INVALID_HANDLE_VALUE;
604 /***********************************************************************
605 * SetupDiEnumDeviceInfo (SETUPAPI.@)
607 BOOL WINAPI SetupDiEnumDeviceInfo(
608 HDEVINFO devinfo,
609 DWORD index,
610 PSP_DEVINFO_DATA info)
612 FIXME("%p %ld %p\n", devinfo, index, info);
614 if(info==NULL)
615 return FALSE;
616 if(info->cbSize < sizeof(*info))
617 return FALSE;
619 return FALSE;
622 /***********************************************************************
623 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
625 BOOL WINAPI SetupDiGetActualSectionToInstallA(
626 HINF InfHandle,
627 PCSTR InfSectionName,
628 PSTR InfSectionWithExt,
629 DWORD InfSectionWithExtSize,
630 PDWORD RequiredSize,
631 PSTR *Extension)
633 FIXME("\n");
634 return FALSE;
637 /***********************************************************************
638 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
640 BOOL WINAPI SetupDiGetActualSectionToInstallW(
641 HINF InfHandle,
642 PCWSTR InfSectionName,
643 PWSTR InfSectionWithExt,
644 DWORD InfSectionWithExtSize,
645 PDWORD RequiredSize,
646 PWSTR *Extension)
648 WCHAR szBuffer[MAX_PATH];
649 DWORD dwLength;
650 DWORD dwFullLength;
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);
669 else
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);
686 return FALSE;
689 dwFullLength = lstrlenW(szBuffer);
691 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
693 if (InfSectionWithExtSize < (dwFullLength + 1))
695 SetLastError(ERROR_INSUFFICIENT_BUFFER);
696 return FALSE;
699 lstrcpyW(InfSectionWithExt, szBuffer);
700 if (Extension != NULL)
702 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
706 if (RequiredSize != NULL)
708 *RequiredSize = dwFullLength + 1;
711 return TRUE;
714 /***********************************************************************
715 * SetupDiGetClassDescriptionA (SETUPAPI.@)
717 BOOL WINAPI SetupDiGetClassDescriptionA(
718 const GUID* ClassGuid,
719 PSTR ClassDescription,
720 DWORD ClassDescriptionSize,
721 PDWORD RequiredSize)
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,
735 PDWORD RequiredSize)
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,
749 PDWORD RequiredSize,
750 PCSTR MachineName,
751 PVOID Reserved)
753 FIXME("\n");
754 return FALSE;
757 /***********************************************************************
758 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
760 BOOL WINAPI SetupDiGetClassDescriptionExW(
761 const GUID* ClassGuid,
762 PWSTR ClassDescription,
763 DWORD ClassDescriptionSize,
764 PDWORD RequiredSize,
765 PCWSTR MachineName,
766 PVOID Reserved)
768 HKEY hKey;
769 DWORD dwLength;
771 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
772 KEY_ALL_ACCESS,
773 DIOCR_INSTALLER,
774 MachineName,
775 Reserved);
776 if (hKey == INVALID_HANDLE_VALUE)
778 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
779 return FALSE;
782 if (RequiredSize != NULL)
784 dwLength = 0;
785 if (RegQueryValueExW(hKey,
786 NULL,
787 NULL,
788 NULL,
789 NULL,
790 &dwLength))
792 RegCloseKey(hKey);
793 return FALSE;
796 *RequiredSize = dwLength / sizeof(WCHAR);
799 dwLength = ClassDescriptionSize * sizeof(WCHAR);
800 if (RegQueryValueExW(hKey,
801 NULL,
802 NULL,
803 NULL,
804 (LPBYTE)ClassDescription,
805 &dwLength))
807 RegCloseKey(hKey);
808 return FALSE;
811 RegCloseKey(hKey);
813 return TRUE;
816 /***********************************************************************
817 * SetupDiGetClassDevsA (SETUPAPI.@)
819 HDEVINFO WINAPI SetupDiGetClassDevsA(
820 CONST GUID *class,
821 LPCSTR enumstr,
822 HWND parent,
823 DWORD flags)
825 HDEVINFO ret;
826 LPWSTR enumstrW = NULL;
828 if (enumstr)
830 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
831 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
832 if (!enumstrW)
834 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
835 goto end;
837 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
839 ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
840 HeapFree(GetProcessHeap(), 0, enumstrW);
842 end:
843 return ret;
846 #define SETUP_SERIAL_PORT_MAGIC 0xd00ff055
848 typedef struct _SerialPortName
850 WCHAR name[5];
851 } SerialPortName;
853 typedef struct _SerialPortList
855 DWORD magic;
856 UINT numPorts;
857 SerialPortName names[1];
858 } SerialPortList;
860 static HDEVINFO SETUP_CreateSerialDeviceList(void)
862 static const size_t initialSize = 100;
863 size_t size;
864 WCHAR buf[initialSize];
865 LPWSTR devices;
866 HDEVINFO ret;
867 BOOL failed = FALSE;
869 devices = buf;
870 size = initialSize;
871 do {
872 if (QueryDosDeviceW(NULL, devices, size) == 0)
874 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
876 size *= 2;
877 if (devices != buf)
878 HeapFree(GetProcessHeap(), 0, devices);
879 devices = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
880 if (!devices)
881 failed = TRUE;
882 else
883 *devices = 0;
885 else
886 failed = TRUE;
888 } while (!*devices && !failed);
889 if (!failed)
891 static const WCHAR comW[] = { 'C','O','M',0 };
892 LPWSTR ptr;
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))
899 numSerialPorts++;
901 list = HeapAlloc(GetProcessHeap(), 0, sizeof(SerialPortList) +
902 numSerialPorts ? (numSerialPorts - 1) * sizeof(SerialPortName) : 0);
903 if (list)
905 list->magic = SETUP_SERIAL_PORT_MAGIC;
906 list->numPorts = 0;
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));
916 list->numPorts++;
919 TRACE("list->numPorts is %d\n", list->numPorts);
921 ret = (HDEVINFO)list;
923 else
924 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
925 if (devices != buf)
926 HeapFree(GetProcessHeap(), 0, devices);
927 TRACE("returning %p\n", ret);
928 return ret;
931 /***********************************************************************
932 * SetupDiGetClassDevsW (SETUPAPI.@)
934 HDEVINFO WINAPI SetupDiGetClassDevsW(
935 CONST GUID *class,
936 LPCWSTR enumstr,
937 HWND parent,
938 DWORD flags)
940 HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;
942 TRACE("%s %s %p 0x%08lx\n", debugstr_guid(class), debugstr_w(enumstr),
943 parent, flags);
945 if (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");
950 else
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();
956 else
957 FIXME("(%s): stub\n", debugstr_guid(class));
959 return ret;
962 /***********************************************************************
963 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
965 BOOL WINAPI SetupDiEnumDeviceInterfaces(
966 HDEVINFO DeviceInfoSet,
967 PSP_DEVINFO_DATA DeviceInfoData,
968 CONST GUID * InterfaceClassGuid,
969 DWORD MemberIndex,
970 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
972 BOOL ret = FALSE;
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
983 * ports.
985 SerialPortList *list = (SerialPortList *)DeviceInfoSet;
987 if (list->magic == SETUP_SERIAL_PORT_MAGIC)
989 if (MemberIndex >= list->numPorts)
990 SetLastError(ERROR_NO_MORE_ITEMS);
991 else
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;
1005 ret = TRUE;
1008 else
1009 SetLastError(ERROR_INVALID_HANDLE);
1011 else
1012 SetLastError(ERROR_INVALID_HANDLE);
1013 return ret;
1016 /***********************************************************************
1017 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1019 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1021 BOOL ret = FALSE;
1023 TRACE("%p\n", devinfo);
1024 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1026 /* FIXME: this assumes the only possible enumeration is of serial
1027 * ports.
1029 SerialPortList *list = (SerialPortList *)devinfo;
1031 if (list->magic == SETUP_SERIAL_PORT_MAGIC)
1033 HeapFree(GetProcessHeap(), 0, list);
1034 ret = TRUE;
1036 else
1037 SetLastError(ERROR_INVALID_HANDLE);
1039 else
1040 SetLastError(ERROR_INVALID_HANDLE);
1041 return ret;
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)
1055 BOOL ret = FALSE;
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
1068 * ports.
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) +
1076 lstrlenW(devName);
1078 if (sizeRequired > DeviceInterfaceDetailDataSize)
1080 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1081 if (RequiredSize)
1082 *RequiredSize = sizeRequired;
1084 else
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++)
1093 *dst = *src;
1094 *dst = '\0';
1095 TRACE("DevicePath is %s\n",
1096 debugstr_a(DeviceInterfaceDetailData->DevicePath));
1097 if (DeviceInfoData)
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;
1106 ret = TRUE;
1109 else
1110 SetLastError(ERROR_INVALID_HANDLE);
1112 else
1113 SetLastError(ERROR_INVALID_HANDLE);
1114 TRACE("Returning %d\n", ret);
1115 return 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);
1132 return FALSE;
1135 /***********************************************************************
1136 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
1138 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
1139 HDEVINFO devinfo,
1140 PSP_DEVINFO_DATA DeviceInfoData,
1141 DWORD Property,
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,
1149 RequiredSize);
1150 return FALSE;
1153 /***********************************************************************
1154 * SetupDiInstallClassA (SETUPAPI.@)
1156 BOOL WINAPI SetupDiInstallClassA(
1157 HWND hwndParent,
1158 PCSTR InfFileName,
1159 DWORD Flags,
1160 HSPFILEQ FileQueue)
1162 UNICODE_STRING FileNameW;
1163 BOOL Result;
1165 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
1167 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1168 return FALSE;
1171 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
1173 RtlFreeUnicodeString(&FileNameW);
1175 return Result;
1178 static HKEY CreateClassKey(HINF hInf)
1180 WCHAR FullBuffer[MAX_PATH];
1181 WCHAR Buffer[MAX_PATH];
1182 DWORD RequiredSize;
1183 HKEY hClassKey;
1185 if (!SetupGetLineTextW(NULL,
1186 hInf,
1187 Version,
1188 ClassGUID,
1189 Buffer,
1190 MAX_PATH,
1191 &RequiredSize))
1193 return INVALID_HANDLE_VALUE;
1196 lstrcpyW(FullBuffer, ControlClass);
1197 lstrcatW(FullBuffer, Buffer);
1199 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1200 FullBuffer,
1202 KEY_ALL_ACCESS,
1203 &hClassKey))
1205 if (!SetupGetLineTextW(NULL,
1206 hInf,
1207 Version,
1208 Class,
1209 Buffer,
1210 MAX_PATH,
1211 &RequiredSize))
1213 return INVALID_HANDLE_VALUE;
1216 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
1217 FullBuffer,
1219 NULL,
1220 REG_OPTION_NON_VOLATILE,
1221 KEY_ALL_ACCESS,
1222 NULL,
1223 &hClassKey,
1224 NULL))
1226 return INVALID_HANDLE_VALUE;
1231 if (RegSetValueExW(hClassKey,
1232 Class,
1234 REG_SZ,
1235 (LPBYTE)Buffer,
1236 RequiredSize * sizeof(WCHAR)))
1238 RegCloseKey(hClassKey);
1239 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
1240 FullBuffer);
1241 return INVALID_HANDLE_VALUE;
1244 return hClassKey;
1247 /***********************************************************************
1248 * SetupDiInstallClassW (SETUPAPI.@)
1250 BOOL WINAPI SetupDiInstallClassW(
1251 HWND hwndParent,
1252 PCWSTR InfFileName,
1253 DWORD Flags,
1254 HSPFILEQ FileQueue)
1256 WCHAR SectionName[MAX_PATH];
1257 DWORD SectionNameLength = 0;
1258 HINF hInf;
1259 BOOL bFileQueueCreated = FALSE;
1260 HKEY hClassKey;
1263 FIXME("\n");
1265 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
1267 SetLastError(ERROR_INVALID_PARAMETER);
1268 return FALSE;
1271 /* Open the .inf file */
1272 hInf = SetupOpenInfFileW(InfFileName,
1273 NULL,
1274 INF_STYLE_WIN4,
1275 NULL);
1276 if (hInf == INVALID_HANDLE_VALUE)
1279 return FALSE;
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);
1287 return FALSE;
1291 /* Try to append a layout file */
1292 #if 0
1293 SetupOpenAppendInfFileW(NULL, hInf, NULL);
1294 #endif
1296 /* Retrieve the actual section name */
1297 SetupDiGetActualSectionToInstallW(hInf,
1298 ClassInstall32,
1299 SectionName,
1300 MAX_PATH,
1301 &SectionNameLength,
1302 NULL);
1304 #if 0
1305 if (!(Flags & DI_NOVCP))
1307 FileQueue = SetupOpenFileQueue();
1308 if (FileQueue == INVALID_HANDLE_VALUE)
1310 SetupCloseInfFile(hInf);
1311 return FALSE;
1314 bFileQueueCreated = TRUE;
1317 #endif
1319 SetupInstallFromInfSectionW(NULL,
1320 hInf,
1321 SectionName,
1322 SPINST_REGISTRY,
1323 hClassKey,
1324 NULL,
1326 NULL,
1327 NULL,
1328 INVALID_HANDLE_VALUE,
1329 NULL);
1331 /* FIXME: More code! */
1333 if (bFileQueueCreated)
1334 SetupCloseFileQueue(FileQueue);
1336 SetupCloseInfFile(hInf);
1338 return TRUE;
1342 /***********************************************************************
1343 * SetupDiOpenClassRegKey (SETUPAPI.@)
1345 HKEY WINAPI SetupDiOpenClassRegKey(
1346 const GUID* ClassGuid,
1347 REGSAM samDesired)
1349 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1350 DIOCR_INSTALLER, NULL, NULL);
1354 /***********************************************************************
1355 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
1357 HKEY WINAPI SetupDiOpenClassRegKeyExA(
1358 const GUID* ClassGuid,
1359 REGSAM samDesired,
1360 DWORD Flags,
1361 PCSTR MachineName,
1362 PVOID Reserved)
1364 PWSTR MachineNameW = NULL;
1365 HKEY hKey;
1367 TRACE("\n");
1369 if (MachineName)
1371 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1372 if (MachineNameW == NULL)
1373 return INVALID_HANDLE_VALUE;
1376 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1377 Flags, MachineNameW, Reserved);
1379 if (MachineNameW)
1380 MyFree(MachineNameW);
1382 return hKey;
1386 /***********************************************************************
1387 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
1389 HKEY WINAPI SetupDiOpenClassRegKeyExW(
1390 const GUID* ClassGuid,
1391 REGSAM samDesired,
1392 DWORD Flags,
1393 PCWSTR MachineName,
1394 PVOID Reserved)
1396 LPWSTR lpGuidString;
1397 HKEY hClassesKey;
1398 HKEY hClassKey;
1399 LPCWSTR lpKeyName;
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;
1415 else
1417 ERR("Invalid Flags parameter!\n");
1418 SetLastError(ERROR_INVALID_PARAMETER);
1419 return INVALID_HANDLE_VALUE;
1422 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1423 lpKeyName,
1425 KEY_ALL_ACCESS,
1426 &hClassesKey))
1428 return INVALID_HANDLE_VALUE;
1431 if (ClassGuid == NULL)
1432 return hClassesKey;
1434 if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
1436 RegCloseKey(hClassesKey);
1437 return FALSE;
1440 if (RegOpenKeyExW(hClassesKey,
1441 lpGuidString,
1443 KEY_ALL_ACCESS,
1444 &hClassKey))
1446 RpcStringFreeW(&lpGuidString);
1447 RegCloseKey(hClassesKey);
1448 return FALSE;
1451 RpcStringFreeW(&lpGuidString);
1452 RegCloseKey(hClassesKey);
1454 return hClassKey;
1457 /***********************************************************************
1458 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
1460 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
1461 HDEVINFO DeviceInfoSet,
1462 PCWSTR DevicePath,
1463 DWORD OpenFlags,
1464 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1466 FIXME("%p %s %08lx %p\n",
1467 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
1468 return FALSE;
1471 /***********************************************************************
1472 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
1474 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
1475 HDEVINFO DeviceInfoSet,
1476 PCSTR DevicePath,
1477 DWORD OpenFlags,
1478 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1480 FIXME("%p %s %08lx %p\n", DeviceInfoSet,
1481 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
1482 return FALSE;
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);
1496 return FALSE;
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);
1508 return FALSE;
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);
1520 return FALSE;
1523 /***********************************************************************
1524 * SetupDiOpenDevRegKey (SETUPAPI.@)
1526 HKEY WINAPI SetupDiOpenDevRegKey(
1527 HDEVINFO DeviceInfoSet,
1528 PSP_DEVINFO_DATA DeviceInfoData,
1529 DWORD Scope,
1530 DWORD HwProfile,
1531 DWORD KeyType,
1532 REGSAM samDesired)
1534 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet, DeviceInfoData,
1535 Scope, HwProfile, KeyType, samDesired);
1536 return INVALID_HANDLE_VALUE;