configure: Probe more carefully for soname support, primarily for Solaris support.
[wine.git] / dlls / setupapi / devinst.c
blobc4e0bec4f7a2e966014d4401c0699d53bcb035cf
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 /* is used to identify if a DeviceInfoSet pointer is
72 valid or not */
73 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
75 struct DeviceInfoSet
77 DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
78 GUID ClassGuid;
79 HWND hwndParent;
82 /***********************************************************************
83 * SetupDiBuildClassInfoList (SETUPAPI.@)
85 * Returns a list of setup class GUIDs that identify the classes
86 * that are installed on a local machine.
88 * PARAMS
89 * Flags [I] control exclusion of classes from the list.
90 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
91 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
92 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
94 * RETURNS
95 * Success: TRUE.
96 * Failure: FALSE.
98 BOOL WINAPI SetupDiBuildClassInfoList(
99 DWORD Flags,
100 LPGUID ClassGuidList,
101 DWORD ClassGuidListSize,
102 PDWORD RequiredSize)
104 TRACE("\n");
105 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
106 ClassGuidListSize, RequiredSize,
107 NULL, NULL);
110 /***********************************************************************
111 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
113 * Returns a list of setup class GUIDs that identify the classes
114 * that are installed on a local or remote macine.
116 * PARAMS
117 * Flags [I] control exclusion of classes from the list.
118 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
119 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
120 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
121 * MachineName [I] name of a remote machine.
122 * Reserved [I] must be NULL.
124 * RETURNS
125 * Success: TRUE.
126 * Failure: FALSE.
128 BOOL WINAPI SetupDiBuildClassInfoListExA(
129 DWORD Flags,
130 LPGUID ClassGuidList,
131 DWORD ClassGuidListSize,
132 PDWORD RequiredSize,
133 LPCSTR MachineName,
134 PVOID Reserved)
136 LPWSTR MachineNameW = NULL;
137 BOOL bResult;
139 TRACE("\n");
141 if (MachineName)
143 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
144 if (MachineNameW == NULL) return FALSE;
147 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
148 ClassGuidListSize, RequiredSize,
149 MachineNameW, Reserved);
151 if (MachineNameW)
152 MyFree(MachineNameW);
154 return bResult;
157 /***********************************************************************
158 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
160 * Returns a list of setup class GUIDs that identify the classes
161 * that are installed on a local or remote macine.
163 * PARAMS
164 * Flags [I] control exclusion of classes from the list.
165 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
166 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
167 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
168 * MachineName [I] name of a remote machine.
169 * Reserved [I] must be NULL.
171 * RETURNS
172 * Success: TRUE.
173 * Failure: FALSE.
175 BOOL WINAPI SetupDiBuildClassInfoListExW(
176 DWORD Flags,
177 LPGUID ClassGuidList,
178 DWORD ClassGuidListSize,
179 PDWORD RequiredSize,
180 LPCWSTR MachineName,
181 PVOID Reserved)
183 WCHAR szKeyName[40];
184 HKEY hClassesKey;
185 HKEY hClassKey;
186 DWORD dwLength;
187 DWORD dwIndex;
188 LONG lError;
189 DWORD dwGuidListIndex = 0;
191 TRACE("\n");
193 if (RequiredSize != NULL)
194 *RequiredSize = 0;
196 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
197 KEY_ALL_ACCESS,
198 DIOCR_INSTALLER,
199 MachineName,
200 Reserved);
201 if (hClassesKey == INVALID_HANDLE_VALUE)
203 return FALSE;
206 for (dwIndex = 0; ; dwIndex++)
208 dwLength = 40;
209 lError = RegEnumKeyExW(hClassesKey,
210 dwIndex,
211 szKeyName,
212 &dwLength,
213 NULL,
214 NULL,
215 NULL,
216 NULL);
217 TRACE("RegEnumKeyExW() returns %ld\n", lError);
218 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
220 TRACE("Key name: %p\n", szKeyName);
222 if (RegOpenKeyExW(hClassesKey,
223 szKeyName,
225 KEY_ALL_ACCESS,
226 &hClassKey))
228 RegCloseKey(hClassesKey);
229 return FALSE;
232 if (!RegQueryValueExW(hClassKey,
233 NoUseClass,
234 NULL,
235 NULL,
236 NULL,
237 NULL))
239 TRACE("'NoUseClass' value found!\n");
240 RegCloseKey(hClassKey);
241 continue;
244 if ((Flags & DIBCI_NOINSTALLCLASS) &&
245 (!RegQueryValueExW(hClassKey,
246 NoInstallClass,
247 NULL,
248 NULL,
249 NULL,
250 NULL)))
252 TRACE("'NoInstallClass' value found!\n");
253 RegCloseKey(hClassKey);
254 continue;
257 if ((Flags & DIBCI_NODISPLAYCLASS) &&
258 (!RegQueryValueExW(hClassKey,
259 NoDisplayClass,
260 NULL,
261 NULL,
262 NULL,
263 NULL)))
265 TRACE("'NoDisplayClass' value found!\n");
266 RegCloseKey(hClassKey);
267 continue;
270 RegCloseKey(hClassKey);
272 TRACE("Guid: %p\n", szKeyName);
273 if (dwGuidListIndex < ClassGuidListSize)
275 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
277 szKeyName[37] = 0;
279 TRACE("Guid: %p\n", &szKeyName[1]);
281 UuidFromStringW(&szKeyName[1],
282 &ClassGuidList[dwGuidListIndex]);
285 dwGuidListIndex++;
288 if (lError != ERROR_SUCCESS)
289 break;
292 RegCloseKey(hClassesKey);
294 if (RequiredSize != NULL)
295 *RequiredSize = dwGuidListIndex;
297 if (ClassGuidListSize < dwGuidListIndex)
299 SetLastError(ERROR_INSUFFICIENT_BUFFER);
300 return FALSE;
303 return TRUE;
306 /***********************************************************************
307 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
309 BOOL WINAPI SetupDiClassGuidsFromNameA(
310 LPCSTR ClassName,
311 LPGUID ClassGuidList,
312 DWORD ClassGuidListSize,
313 PDWORD RequiredSize)
315 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
316 ClassGuidListSize, RequiredSize,
317 NULL, NULL);
320 /***********************************************************************
321 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
323 BOOL WINAPI SetupDiClassGuidsFromNameW(
324 LPCWSTR ClassName,
325 LPGUID ClassGuidList,
326 DWORD ClassGuidListSize,
327 PDWORD RequiredSize)
329 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
330 ClassGuidListSize, RequiredSize,
331 NULL, NULL);
334 /***********************************************************************
335 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
337 BOOL WINAPI SetupDiClassGuidsFromNameExA(
338 LPCSTR ClassName,
339 LPGUID ClassGuidList,
340 DWORD ClassGuidListSize,
341 PDWORD RequiredSize,
342 LPCSTR MachineName,
343 PVOID Reserved)
345 LPWSTR ClassNameW = NULL;
346 LPWSTR MachineNameW = NULL;
347 BOOL bResult;
349 FIXME("\n");
351 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
352 if (ClassNameW == NULL)
353 return FALSE;
355 if (MachineNameW)
357 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
358 if (MachineNameW == NULL)
360 MyFree(ClassNameW);
361 return FALSE;
365 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
366 ClassGuidListSize, RequiredSize,
367 MachineNameW, Reserved);
369 if (MachineNameW)
370 MyFree(MachineNameW);
372 MyFree(ClassNameW);
374 return bResult;
377 /***********************************************************************
378 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
380 BOOL WINAPI SetupDiClassGuidsFromNameExW(
381 LPCWSTR ClassName,
382 LPGUID ClassGuidList,
383 DWORD ClassGuidListSize,
384 PDWORD RequiredSize,
385 LPCWSTR MachineName,
386 PVOID Reserved)
388 WCHAR szKeyName[40];
389 WCHAR szClassName[256];
390 HKEY hClassesKey;
391 HKEY hClassKey;
392 DWORD dwLength;
393 DWORD dwIndex;
394 LONG lError;
395 DWORD dwGuidListIndex = 0;
397 if (RequiredSize != NULL)
398 *RequiredSize = 0;
400 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
401 KEY_ALL_ACCESS,
402 DIOCR_INSTALLER,
403 MachineName,
404 Reserved);
405 if (hClassesKey == INVALID_HANDLE_VALUE)
407 return FALSE;
410 for (dwIndex = 0; ; dwIndex++)
412 dwLength = 40;
413 lError = RegEnumKeyExW(hClassesKey,
414 dwIndex,
415 szKeyName,
416 &dwLength,
417 NULL,
418 NULL,
419 NULL,
420 NULL);
421 TRACE("RegEnumKeyExW() returns %ld\n", lError);
422 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
424 TRACE("Key name: %p\n", szKeyName);
426 if (RegOpenKeyExW(hClassesKey,
427 szKeyName,
429 KEY_ALL_ACCESS,
430 &hClassKey))
432 RegCloseKey(hClassesKey);
433 return FALSE;
436 dwLength = 256 * sizeof(WCHAR);
437 if (!RegQueryValueExW(hClassKey,
438 Class,
439 NULL,
440 NULL,
441 (LPBYTE)szClassName,
442 &dwLength))
444 TRACE("Class name: %p\n", szClassName);
446 if (strcmpiW(szClassName, ClassName) == 0)
448 TRACE("Found matching class name\n");
450 TRACE("Guid: %p\n", szKeyName);
451 if (dwGuidListIndex < ClassGuidListSize)
453 if (szKeyName[0] == L'{' && szKeyName[37] == L'}')
455 szKeyName[37] = 0;
457 TRACE("Guid: %p\n", &szKeyName[1]);
459 UuidFromStringW(&szKeyName[1],
460 &ClassGuidList[dwGuidListIndex]);
463 dwGuidListIndex++;
467 RegCloseKey(hClassKey);
470 if (lError != ERROR_SUCCESS)
471 break;
474 RegCloseKey(hClassesKey);
476 if (RequiredSize != NULL)
477 *RequiredSize = dwGuidListIndex;
479 if (ClassGuidListSize < dwGuidListIndex)
481 SetLastError(ERROR_INSUFFICIENT_BUFFER);
482 return FALSE;
485 return TRUE;
488 /***********************************************************************
489 * SetupDiClassNameFromGuidA (SETUPAPI.@)
491 BOOL WINAPI SetupDiClassNameFromGuidA(
492 const GUID* ClassGuid,
493 PSTR ClassName,
494 DWORD ClassNameSize,
495 PDWORD RequiredSize)
497 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
498 ClassNameSize, RequiredSize,
499 NULL, NULL);
502 /***********************************************************************
503 * SetupDiClassNameFromGuidW (SETUPAPI.@)
505 BOOL WINAPI SetupDiClassNameFromGuidW(
506 const GUID* ClassGuid,
507 PWSTR ClassName,
508 DWORD ClassNameSize,
509 PDWORD RequiredSize)
511 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
512 ClassNameSize, RequiredSize,
513 NULL, NULL);
516 /***********************************************************************
517 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
519 BOOL WINAPI SetupDiClassNameFromGuidExA(
520 const GUID* ClassGuid,
521 PSTR ClassName,
522 DWORD ClassNameSize,
523 PDWORD RequiredSize,
524 PCSTR MachineName,
525 PVOID Reserved)
527 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
528 LPWSTR MachineNameW = NULL;
529 BOOL ret;
531 if (MachineName)
532 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
533 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
534 NULL, MachineNameW, Reserved);
535 if (ret)
537 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
538 ClassNameSize, NULL, NULL);
540 if (!ClassNameSize && RequiredSize)
541 *RequiredSize = len;
543 MyFree(MachineNameW);
544 return ret;
547 /***********************************************************************
548 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
550 BOOL WINAPI SetupDiClassNameFromGuidExW(
551 const GUID* ClassGuid,
552 PWSTR ClassName,
553 DWORD ClassNameSize,
554 PDWORD RequiredSize,
555 PCWSTR MachineName,
556 PVOID Reserved)
558 HKEY hKey;
559 DWORD dwLength;
561 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
562 KEY_ALL_ACCESS,
563 DIOCR_INSTALLER,
564 MachineName,
565 Reserved);
566 if (hKey == INVALID_HANDLE_VALUE)
568 return FALSE;
571 if (RequiredSize != NULL)
573 dwLength = 0;
574 if (RegQueryValueExW(hKey,
575 Class,
576 NULL,
577 NULL,
578 NULL,
579 &dwLength))
581 RegCloseKey(hKey);
582 return FALSE;
585 *RequiredSize = dwLength / sizeof(WCHAR);
588 dwLength = ClassNameSize * sizeof(WCHAR);
589 if (RegQueryValueExW(hKey,
590 Class,
591 NULL,
592 NULL,
593 (LPBYTE)ClassName,
594 &dwLength))
596 RegCloseKey(hKey);
597 return FALSE;
600 RegCloseKey(hKey);
602 return TRUE;
605 /***********************************************************************
606 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
608 HDEVINFO WINAPI
609 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
610 HWND hwndParent)
612 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
615 /***********************************************************************
616 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
618 HDEVINFO WINAPI
619 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
620 HWND hwndParent,
621 PCSTR MachineName,
622 PVOID Reserved)
624 LPWSTR MachineNameW = NULL;
625 HDEVINFO hDevInfo;
627 TRACE("\n");
629 if (MachineName)
631 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
632 if (MachineNameW == NULL)
633 return (HDEVINFO)INVALID_HANDLE_VALUE;
636 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
637 MachineNameW, Reserved);
639 if (MachineNameW)
640 MyFree(MachineNameW);
642 return hDevInfo;
645 /***********************************************************************
646 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
648 * Create an empty DeviceInfoSet list.
650 * PARAMS
651 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
652 * with this list.
653 * hwndParent [I] hwnd needed for interface related actions.
654 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
655 * local regestry will be used.
656 * Reserved [I] must be NULL
658 * RETURNS
659 * Success: empty list.
660 * Failure: INVALID_HANDLE_VALUE.
662 HDEVINFO WINAPI
663 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
664 HWND hwndParent,
665 PCWSTR MachineName,
666 PVOID Reserved)
668 struct DeviceInfoSet *list = NULL;
669 DWORD size = sizeof(struct DeviceInfoSet);
671 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
672 debugstr_w(MachineName), Reserved);
674 if (MachineName != NULL)
676 FIXME("remote support is not implemented");
677 SetLastError(ERROR_INVALID_MACHINENAME);
678 return (HDEVINFO)INVALID_HANDLE_VALUE;
681 if (Reserved != NULL)
683 SetLastError(ERROR_INVALID_PARAMETER);
684 return (HDEVINFO)INVALID_HANDLE_VALUE;
687 list = HeapAlloc(GetProcessHeap(), 0, size);
688 if (!list)
690 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
691 return (HDEVINFO)INVALID_HANDLE_VALUE;
694 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
695 list->hwndParent = hwndParent;
696 memcpy(&list->ClassGuid,
697 ClassGuid ? ClassGuid : &GUID_NULL,
698 sizeof(list->ClassGuid));
700 return (HDEVINFO)list;
703 /***********************************************************************
704 * SetupDiEnumDeviceInfo (SETUPAPI.@)
706 BOOL WINAPI SetupDiEnumDeviceInfo(
707 HDEVINFO devinfo,
708 DWORD index,
709 PSP_DEVINFO_DATA info)
711 FIXME("%p %ld %p\n", devinfo, index, info);
713 if(info==NULL)
714 return FALSE;
715 if(info->cbSize < sizeof(*info))
716 return FALSE;
718 return FALSE;
721 /***********************************************************************
722 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
724 BOOL WINAPI SetupDiGetActualSectionToInstallA(
725 HINF InfHandle,
726 PCSTR InfSectionName,
727 PSTR InfSectionWithExt,
728 DWORD InfSectionWithExtSize,
729 PDWORD RequiredSize,
730 PSTR *Extension)
732 FIXME("\n");
733 return FALSE;
736 /***********************************************************************
737 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
739 BOOL WINAPI SetupDiGetActualSectionToInstallW(
740 HINF InfHandle,
741 PCWSTR InfSectionName,
742 PWSTR InfSectionWithExt,
743 DWORD InfSectionWithExtSize,
744 PDWORD RequiredSize,
745 PWSTR *Extension)
747 WCHAR szBuffer[MAX_PATH];
748 DWORD dwLength;
749 DWORD dwFullLength;
750 LONG lLineCount = -1;
752 lstrcpyW(szBuffer, InfSectionName);
753 dwLength = lstrlenW(szBuffer);
755 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
757 /* Test section name with '.NTx86' extension */
758 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
759 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
761 if (lLineCount == -1)
763 /* Test section name with '.NT' extension */
764 lstrcpyW(&szBuffer[dwLength], NtExtension);
765 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
768 else
770 /* Test section name with '.Win' extension */
771 lstrcpyW(&szBuffer[dwLength], WinExtension);
772 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
775 if (lLineCount == -1)
777 /* Test section name without extension */
778 szBuffer[dwLength] = 0;
779 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
782 if (lLineCount == -1)
784 SetLastError(ERROR_INVALID_PARAMETER);
785 return FALSE;
788 dwFullLength = lstrlenW(szBuffer);
790 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
792 if (InfSectionWithExtSize < (dwFullLength + 1))
794 SetLastError(ERROR_INSUFFICIENT_BUFFER);
795 return FALSE;
798 lstrcpyW(InfSectionWithExt, szBuffer);
799 if (Extension != NULL)
801 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
805 if (RequiredSize != NULL)
807 *RequiredSize = dwFullLength + 1;
810 return TRUE;
813 /***********************************************************************
814 * SetupDiGetClassDescriptionA (SETUPAPI.@)
816 BOOL WINAPI SetupDiGetClassDescriptionA(
817 const GUID* ClassGuid,
818 PSTR ClassDescription,
819 DWORD ClassDescriptionSize,
820 PDWORD RequiredSize)
822 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
823 ClassDescriptionSize,
824 RequiredSize, NULL, NULL);
827 /***********************************************************************
828 * SetupDiGetClassDescriptionW (SETUPAPI.@)
830 BOOL WINAPI SetupDiGetClassDescriptionW(
831 const GUID* ClassGuid,
832 PWSTR ClassDescription,
833 DWORD ClassDescriptionSize,
834 PDWORD RequiredSize)
836 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
837 ClassDescriptionSize,
838 RequiredSize, NULL, NULL);
841 /***********************************************************************
842 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
844 BOOL WINAPI SetupDiGetClassDescriptionExA(
845 const GUID* ClassGuid,
846 PSTR ClassDescription,
847 DWORD ClassDescriptionSize,
848 PDWORD RequiredSize,
849 PCSTR MachineName,
850 PVOID Reserved)
852 FIXME("\n");
853 return FALSE;
856 /***********************************************************************
857 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
859 BOOL WINAPI SetupDiGetClassDescriptionExW(
860 const GUID* ClassGuid,
861 PWSTR ClassDescription,
862 DWORD ClassDescriptionSize,
863 PDWORD RequiredSize,
864 PCWSTR MachineName,
865 PVOID Reserved)
867 HKEY hKey;
868 DWORD dwLength;
870 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
871 KEY_ALL_ACCESS,
872 DIOCR_INSTALLER,
873 MachineName,
874 Reserved);
875 if (hKey == INVALID_HANDLE_VALUE)
877 WARN("SetupDiOpenClassRegKeyExW() failed (Error %lu)\n", GetLastError());
878 return FALSE;
881 if (RequiredSize != NULL)
883 dwLength = 0;
884 if (RegQueryValueExW(hKey,
885 NULL,
886 NULL,
887 NULL,
888 NULL,
889 &dwLength))
891 RegCloseKey(hKey);
892 return FALSE;
895 *RequiredSize = dwLength / sizeof(WCHAR);
898 dwLength = ClassDescriptionSize * sizeof(WCHAR);
899 if (RegQueryValueExW(hKey,
900 NULL,
901 NULL,
902 NULL,
903 (LPBYTE)ClassDescription,
904 &dwLength))
906 RegCloseKey(hKey);
907 return FALSE;
910 RegCloseKey(hKey);
912 return TRUE;
915 /***********************************************************************
916 * SetupDiGetClassDevsA (SETUPAPI.@)
918 HDEVINFO WINAPI SetupDiGetClassDevsA(
919 CONST GUID *class,
920 LPCSTR enumstr,
921 HWND parent,
922 DWORD flags)
924 HDEVINFO ret;
925 LPWSTR enumstrW = NULL;
927 if (enumstr)
929 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
930 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
931 if (!enumstrW)
933 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
934 goto end;
936 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
938 ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
939 HeapFree(GetProcessHeap(), 0, enumstrW);
941 end:
942 return ret;
945 /***********************************************************************
946 * SetupDiGetClassDevsW (SETUPAPI.@)
948 HDEVINFO WINAPI SetupDiGetClassDevsW(
949 CONST GUID *class,
950 LPCWSTR enumstr,
951 HWND parent,
952 DWORD flags)
954 HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE;
956 TRACE("%s %s %p 0x%08lx\n", debugstr_guid(class), debugstr_w(enumstr),
957 parent, flags);
959 if (enumstr)
960 FIXME(": unimplemented for enumerator strings (%s)\n",
961 debugstr_w(enumstr));
962 else if (flags & DIGCF_ALLCLASSES)
963 FIXME(": unimplemented for DIGCF_ALLCLASSES\n");
964 else
966 FIXME("(%s): stub\n", debugstr_guid(class));
968 return ret;
971 /***********************************************************************
972 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
974 BOOL WINAPI SetupDiEnumDeviceInterfaces(
975 HDEVINFO DeviceInfoSet,
976 PSP_DEVINFO_DATA DeviceInfoData,
977 CONST GUID * InterfaceClassGuid,
978 DWORD MemberIndex,
979 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
981 BOOL ret = FALSE;
983 FIXME("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet, DeviceInfoData,
984 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
986 SetLastError(ERROR_INVALID_HANDLE);
987 return ret;
990 /***********************************************************************
991 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
993 * Destroy a DeviceInfoList and free all used memory of the list.
995 * PARAMS
996 * devinfo [I] DeviceInfoList pointer to list to destroy
998 * RETURNS
999 * Success: non zero value.
1000 * Failure: zero value.
1002 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1004 BOOL ret = FALSE;
1006 TRACE("%p\n", devinfo);
1007 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1009 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1011 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1013 HeapFree(GetProcessHeap(), 0, list);
1014 ret = TRUE;
1018 if (ret == FALSE)
1019 SetLastError(ERROR_INVALID_HANDLE);
1021 return ret;
1024 /***********************************************************************
1025 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1027 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
1028 HDEVINFO DeviceInfoSet,
1029 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1030 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
1031 DWORD DeviceInterfaceDetailDataSize,
1032 PDWORD RequiredSize,
1033 PSP_DEVINFO_DATA DeviceInfoData)
1035 BOOL ret = FALSE;
1037 FIXME("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet,
1038 DeviceInterfaceData, DeviceInterfaceDetailData,
1039 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1041 SetLastError(ERROR_INVALID_HANDLE);
1042 return ret;
1045 /***********************************************************************
1046 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
1048 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
1049 HDEVINFO DeviceInfoSet,
1050 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1051 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
1052 DWORD DeviceInterfaceDetailDataSize,
1053 PDWORD RequiredSize,
1054 PSP_DEVINFO_DATA DeviceInfoData)
1056 FIXME("(%p, %p, %p, %ld, %p, %p): stub\n", DeviceInfoSet,
1057 DeviceInterfaceData, DeviceInterfaceDetailData,
1058 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1059 return FALSE;
1062 /***********************************************************************
1063 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
1065 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
1066 HDEVINFO devinfo,
1067 PSP_DEVINFO_DATA DeviceInfoData,
1068 DWORD Property,
1069 PDWORD PropertyRegDataType,
1070 PBYTE PropertyBuffer,
1071 DWORD PropertyBufferSize,
1072 PDWORD RequiredSize)
1074 FIXME("%04lx %p %ld %p %p %ld %p\n", (DWORD)devinfo, DeviceInfoData,
1075 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1076 RequiredSize);
1077 return FALSE;
1080 /***********************************************************************
1081 * SetupDiInstallClassA (SETUPAPI.@)
1083 BOOL WINAPI SetupDiInstallClassA(
1084 HWND hwndParent,
1085 PCSTR InfFileName,
1086 DWORD Flags,
1087 HSPFILEQ FileQueue)
1089 UNICODE_STRING FileNameW;
1090 BOOL Result;
1092 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
1094 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1095 return FALSE;
1098 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
1100 RtlFreeUnicodeString(&FileNameW);
1102 return Result;
1105 static HKEY CreateClassKey(HINF hInf)
1107 WCHAR FullBuffer[MAX_PATH];
1108 WCHAR Buffer[MAX_PATH];
1109 DWORD RequiredSize;
1110 HKEY hClassKey;
1112 if (!SetupGetLineTextW(NULL,
1113 hInf,
1114 Version,
1115 ClassGUID,
1116 Buffer,
1117 MAX_PATH,
1118 &RequiredSize))
1120 return INVALID_HANDLE_VALUE;
1123 lstrcpyW(FullBuffer, ControlClass);
1124 lstrcatW(FullBuffer, Buffer);
1126 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1127 FullBuffer,
1129 KEY_ALL_ACCESS,
1130 &hClassKey))
1132 if (!SetupGetLineTextW(NULL,
1133 hInf,
1134 Version,
1135 Class,
1136 Buffer,
1137 MAX_PATH,
1138 &RequiredSize))
1140 return INVALID_HANDLE_VALUE;
1143 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
1144 FullBuffer,
1146 NULL,
1147 REG_OPTION_NON_VOLATILE,
1148 KEY_ALL_ACCESS,
1149 NULL,
1150 &hClassKey,
1151 NULL))
1153 return INVALID_HANDLE_VALUE;
1158 if (RegSetValueExW(hClassKey,
1159 Class,
1161 REG_SZ,
1162 (LPBYTE)Buffer,
1163 RequiredSize * sizeof(WCHAR)))
1165 RegCloseKey(hClassKey);
1166 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
1167 FullBuffer);
1168 return INVALID_HANDLE_VALUE;
1171 return hClassKey;
1174 /***********************************************************************
1175 * SetupDiInstallClassW (SETUPAPI.@)
1177 BOOL WINAPI SetupDiInstallClassW(
1178 HWND hwndParent,
1179 PCWSTR InfFileName,
1180 DWORD Flags,
1181 HSPFILEQ FileQueue)
1183 WCHAR SectionName[MAX_PATH];
1184 DWORD SectionNameLength = 0;
1185 HINF hInf;
1186 BOOL bFileQueueCreated = FALSE;
1187 HKEY hClassKey;
1190 FIXME("\n");
1192 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
1194 SetLastError(ERROR_INVALID_PARAMETER);
1195 return FALSE;
1198 /* Open the .inf file */
1199 hInf = SetupOpenInfFileW(InfFileName,
1200 NULL,
1201 INF_STYLE_WIN4,
1202 NULL);
1203 if (hInf == INVALID_HANDLE_VALUE)
1206 return FALSE;
1209 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
1210 hClassKey = CreateClassKey(hInf);
1211 if (hClassKey == INVALID_HANDLE_VALUE)
1213 SetupCloseInfFile(hInf);
1214 return FALSE;
1218 /* Try to append a layout file */
1219 #if 0
1220 SetupOpenAppendInfFileW(NULL, hInf, NULL);
1221 #endif
1223 /* Retrieve the actual section name */
1224 SetupDiGetActualSectionToInstallW(hInf,
1225 ClassInstall32,
1226 SectionName,
1227 MAX_PATH,
1228 &SectionNameLength,
1229 NULL);
1231 #if 0
1232 if (!(Flags & DI_NOVCP))
1234 FileQueue = SetupOpenFileQueue();
1235 if (FileQueue == INVALID_HANDLE_VALUE)
1237 SetupCloseInfFile(hInf);
1238 return FALSE;
1241 bFileQueueCreated = TRUE;
1244 #endif
1246 SetupInstallFromInfSectionW(NULL,
1247 hInf,
1248 SectionName,
1249 SPINST_REGISTRY,
1250 hClassKey,
1251 NULL,
1253 NULL,
1254 NULL,
1255 INVALID_HANDLE_VALUE,
1256 NULL);
1258 /* FIXME: More code! */
1260 if (bFileQueueCreated)
1261 SetupCloseFileQueue(FileQueue);
1263 SetupCloseInfFile(hInf);
1265 return TRUE;
1269 /***********************************************************************
1270 * SetupDiOpenClassRegKey (SETUPAPI.@)
1272 HKEY WINAPI SetupDiOpenClassRegKey(
1273 const GUID* ClassGuid,
1274 REGSAM samDesired)
1276 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1277 DIOCR_INSTALLER, NULL, NULL);
1281 /***********************************************************************
1282 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
1284 HKEY WINAPI SetupDiOpenClassRegKeyExA(
1285 const GUID* ClassGuid,
1286 REGSAM samDesired,
1287 DWORD Flags,
1288 PCSTR MachineName,
1289 PVOID Reserved)
1291 PWSTR MachineNameW = NULL;
1292 HKEY hKey;
1294 TRACE("\n");
1296 if (MachineName)
1298 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
1299 if (MachineNameW == NULL)
1300 return INVALID_HANDLE_VALUE;
1303 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1304 Flags, MachineNameW, Reserved);
1306 if (MachineNameW)
1307 MyFree(MachineNameW);
1309 return hKey;
1313 /***********************************************************************
1314 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
1316 HKEY WINAPI SetupDiOpenClassRegKeyExW(
1317 const GUID* ClassGuid,
1318 REGSAM samDesired,
1319 DWORD Flags,
1320 PCWSTR MachineName,
1321 PVOID Reserved)
1323 LPWSTR lpGuidString;
1324 HKEY hClassesKey;
1325 HKEY hClassKey;
1326 LPCWSTR lpKeyName;
1328 if (MachineName != NULL)
1330 FIXME("Remote access not supported yet!\n");
1331 return INVALID_HANDLE_VALUE;
1334 if (Flags == DIOCR_INSTALLER)
1336 lpKeyName = ControlClass;
1338 else if (Flags == DIOCR_INTERFACE)
1340 lpKeyName = DeviceClasses;
1342 else
1344 ERR("Invalid Flags parameter!\n");
1345 SetLastError(ERROR_INVALID_PARAMETER);
1346 return INVALID_HANDLE_VALUE;
1349 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1350 lpKeyName,
1352 KEY_ALL_ACCESS,
1353 &hClassesKey))
1355 return INVALID_HANDLE_VALUE;
1358 if (ClassGuid == NULL)
1359 return hClassesKey;
1361 if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK)
1363 RegCloseKey(hClassesKey);
1364 return FALSE;
1367 if (RegOpenKeyExW(hClassesKey,
1368 lpGuidString,
1370 KEY_ALL_ACCESS,
1371 &hClassKey))
1373 RpcStringFreeW(&lpGuidString);
1374 RegCloseKey(hClassesKey);
1375 return FALSE;
1378 RpcStringFreeW(&lpGuidString);
1379 RegCloseKey(hClassesKey);
1381 return hClassKey;
1384 /***********************************************************************
1385 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
1387 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
1388 HDEVINFO DeviceInfoSet,
1389 PCWSTR DevicePath,
1390 DWORD OpenFlags,
1391 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1393 FIXME("%p %s %08lx %p\n",
1394 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
1395 return FALSE;
1398 /***********************************************************************
1399 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
1401 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
1402 HDEVINFO DeviceInfoSet,
1403 PCSTR DevicePath,
1404 DWORD OpenFlags,
1405 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1407 FIXME("%p %s %08lx %p\n", DeviceInfoSet,
1408 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
1409 return FALSE;
1412 /***********************************************************************
1413 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
1415 BOOL WINAPI SetupDiSetClassInstallParamsA(
1416 HDEVINFO DeviceInfoSet,
1417 PSP_DEVINFO_DATA DeviceInfoData,
1418 PSP_CLASSINSTALL_HEADER ClassInstallParams,
1419 DWORD ClassInstallParamsSize)
1421 FIXME("%p %p %x %lu\n",DeviceInfoSet, DeviceInfoData,
1422 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
1423 return FALSE;
1426 /***********************************************************************
1427 * SetupDiCallClassInstaller (SETUPAPI.@)
1429 BOOL WINAPI SetupDiCallClassInstaller(
1430 DI_FUNCTION InstallFunction,
1431 HDEVINFO DeviceInfoSet,
1432 PSP_DEVINFO_DATA DeviceInfoData)
1434 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
1435 return FALSE;
1438 /***********************************************************************
1439 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
1441 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
1442 HDEVINFO DeviceInfoSet,
1443 PSP_DEVINFO_DATA DeviceInfoData,
1444 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
1446 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
1447 return FALSE;
1450 /***********************************************************************
1451 * SetupDiOpenDevRegKey (SETUPAPI.@)
1453 HKEY WINAPI SetupDiOpenDevRegKey(
1454 HDEVINFO DeviceInfoSet,
1455 PSP_DEVINFO_DATA DeviceInfoData,
1456 DWORD Scope,
1457 DWORD HwProfile,
1458 DWORD KeyType,
1459 REGSAM samDesired)
1461 FIXME("%p %p %ld %ld %ld %lx\n", DeviceInfoSet, DeviceInfoData,
1462 Scope, HwProfile, KeyType, samDesired);
1463 return INVALID_HANDLE_VALUE;