setupapi: Devices created by SetupDiCreateDeviceInfo are "phantoms", and are deleted...
[wine/wine-kai.git] / dlls / setupapi / devinst.c
blob9476ee257c1c081aafa08550f460e319d9f23c3d
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 "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','n','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};
70 static const WCHAR Enum[] = {'S','y','s','t','e','m','\\',
71 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
72 'E','n','u','m',0};
73 static const WCHAR DeviceDesc[] = {'D','e','v','i','c','e','D','e','s','c',0};
74 static const WCHAR HardwareId[] = {'H','a','r','d','w','a','r','e','I','D',0};
75 static const WCHAR CompatibleIDs[] = {'C','o','m','p','a','t','i','b','l','e','I','d','s',0};
76 static const WCHAR Service[] = {'S','e','r','v','i','c','e',0};
77 static const WCHAR Driver[] = {'D','r','i','v','e','r',0};
78 static const WCHAR ConfigFlags[] = {'C','o','n','f','i','g','F','l','a','g','s',0};
79 static const WCHAR Mfg[] = {'M','f','g',0};
80 static const WCHAR FriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
81 static const WCHAR LocationInformation[] = {'L','o','c','a','t','i','o','n','I','n','f','o','r','m','a','t','i','o','n',0};
82 static const WCHAR Capabilities[] = {'C','a','p','a','b','i','l','i','t','i','e','s',0};
83 static const WCHAR UINumber[] = {'U','I','N','u','m','b','e','r',0};
84 static const WCHAR UpperFilters[] = {'U','p','p','e','r','F','i','l','t','e','r','s',0};
85 static const WCHAR LowerFilters[] = {'L','o','w','e','r','F','i','l','t','e','r','s',0};
86 static const WCHAR Phantom[] = {'P','h','a','n','t','o','m',0};
88 /* is used to identify if a DeviceInfoSet pointer is
89 valid or not */
90 #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056
92 struct DeviceInfoSet
94 DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */
95 GUID ClassGuid;
96 HWND hwndParent;
97 DWORD cDevices;
98 SP_DEVINFO_DATA *devices;
101 /* Pointed to by SP_DEVINFO_DATA's Reserved member */
102 struct DeviceInfo
104 HKEY key;
105 BOOL phantom;
106 LPWSTR instanceId;
109 static struct DeviceInfo *SETUPDI_AllocateDeviceInfo(LPCWSTR instanceId,
110 BOOL phantom)
112 struct DeviceInfo *devInfo = HeapAlloc(GetProcessHeap(), 0,
113 sizeof(struct DeviceInfo));
115 if (devInfo)
117 devInfo->instanceId = HeapAlloc(GetProcessHeap(), 0,
118 (lstrlenW(instanceId) + 1) * sizeof(WCHAR));
119 if (devInfo->instanceId)
121 HKEY enumKey;
122 LONG l;
124 devInfo->key = INVALID_HANDLE_VALUE;
125 devInfo->phantom = phantom;
126 lstrcpyW(devInfo->instanceId, instanceId);
127 struprW(devInfo->instanceId);
128 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
129 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
130 if (!l)
132 RegCreateKeyExW(enumKey, devInfo->instanceId, 0, NULL, 0,
133 KEY_ALL_ACCESS, NULL, &devInfo->key, NULL);
134 if (phantom)
135 RegSetValueExW(devInfo->key, Phantom, 0, REG_DWORD,
136 (LPBYTE)&phantom, sizeof(phantom));
137 RegCloseKey(enumKey);
140 else
142 HeapFree(GetProcessHeap(), 0, devInfo);
143 devInfo = NULL;
146 return devInfo;
149 static void SETUPDI_FreeDeviceInfo(struct DeviceInfo *devInfo)
151 if (devInfo->key != INVALID_HANDLE_VALUE)
152 RegCloseKey(devInfo->key);
153 if (devInfo->phantom)
155 HKEY enumKey;
156 LONG l;
158 l = RegCreateKeyExW(HKEY_LOCAL_MACHINE, Enum, 0, NULL, 0,
159 KEY_ALL_ACCESS, NULL, &enumKey, NULL);
160 if (!l)
162 RegDeleteTreeW(enumKey, devInfo->instanceId);
163 RegCloseKey(enumKey);
166 HeapFree(GetProcessHeap(), 0, devInfo->instanceId);
167 HeapFree(GetProcessHeap(), 0, devInfo);
170 static void SETUPDI_GuidToString(const GUID *guid, LPWSTR guidStr)
172 static const WCHAR fmt[] = {'{','%','0','8','X','-','%','0','4','X','-',
173 '%','0','4','X','-','%','0','2','X','%','0','2','X','-','%','0','2',
174 'X','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2','X','%',
175 '0','2','X','}',0};
177 sprintfW(guidStr, fmt, guid->Data1, guid->Data2, guid->Data3,
178 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
179 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
182 /* Adds a device with GUID guid and identifer devInst to set. Allocates a
183 * struct DeviceInfo, and points the returned device info's Reserved member
184 * to it. "Phantom" devices are deleted from the registry when closed.
185 * Returns a pointer to the newly allocated device info.
187 static BOOL SETUPDI_AddDeviceToSet(struct DeviceInfoSet *set,
188 const GUID *guid,
189 DWORD devInst,
190 LPCWSTR instanceId,
191 BOOL phantom,
192 SP_DEVINFO_DATA **dev)
194 BOOL ret = FALSE;
195 struct DeviceInfo *devInfo = SETUPDI_AllocateDeviceInfo(instanceId,
196 phantom);
198 if (devInfo)
200 if (set->devices)
201 set->devices = HeapReAlloc(GetProcessHeap(), 0, set->devices,
202 (set->cDevices + 1) * sizeof(SP_DEVINFO_DATA));
203 else
204 set->devices = HeapAlloc(GetProcessHeap(), 0,
205 sizeof(SP_DEVINFO_DATA));
206 if (set->devices)
208 WCHAR classGuidStr[39];
210 *dev = &set->devices[set->cDevices++];
211 (*dev)->cbSize = sizeof(SP_DEVINFO_DATA);
212 memcpy(&(*dev)->ClassGuid, guid, sizeof(GUID));
213 (*dev)->DevInst = devInst;
214 (*dev)->Reserved = (ULONG_PTR)devInfo;
215 SETUPDI_GuidToString(guid, classGuidStr);
216 SetupDiSetDeviceRegistryPropertyW((HDEVINFO)set,
217 *dev, SPDRP_CLASSGUID, (const BYTE *)classGuidStr,
218 lstrlenW(classGuidStr) * sizeof(WCHAR));
219 ret = TRUE;
221 else
223 HeapFree(GetProcessHeap(), 0, devInfo);
224 SetLastError(ERROR_OUTOFMEMORY);
227 return ret;
230 /***********************************************************************
231 * SetupDiBuildClassInfoList (SETUPAPI.@)
233 * Returns a list of setup class GUIDs that identify the classes
234 * that are installed on a local machine.
236 * PARAMS
237 * Flags [I] control exclusion of classes from the list.
238 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
239 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
240 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
242 * RETURNS
243 * Success: TRUE.
244 * Failure: FALSE.
246 BOOL WINAPI SetupDiBuildClassInfoList(
247 DWORD Flags,
248 LPGUID ClassGuidList,
249 DWORD ClassGuidListSize,
250 PDWORD RequiredSize)
252 TRACE("\n");
253 return SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
254 ClassGuidListSize, RequiredSize,
255 NULL, NULL);
258 /***********************************************************************
259 * SetupDiBuildClassInfoListExA (SETUPAPI.@)
261 * Returns a list of setup class GUIDs that identify the classes
262 * that are installed on a local or remote macine.
264 * PARAMS
265 * Flags [I] control exclusion of classes from the list.
266 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
267 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
268 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
269 * MachineName [I] name of a remote machine.
270 * Reserved [I] must be NULL.
272 * RETURNS
273 * Success: TRUE.
274 * Failure: FALSE.
276 BOOL WINAPI SetupDiBuildClassInfoListExA(
277 DWORD Flags,
278 LPGUID ClassGuidList,
279 DWORD ClassGuidListSize,
280 PDWORD RequiredSize,
281 LPCSTR MachineName,
282 PVOID Reserved)
284 LPWSTR MachineNameW = NULL;
285 BOOL bResult;
287 TRACE("\n");
289 if (MachineName)
291 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
292 if (MachineNameW == NULL) return FALSE;
295 bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList,
296 ClassGuidListSize, RequiredSize,
297 MachineNameW, Reserved);
299 MyFree(MachineNameW);
301 return bResult;
304 /***********************************************************************
305 * SetupDiBuildClassInfoListExW (SETUPAPI.@)
307 * Returns a list of setup class GUIDs that identify the classes
308 * that are installed on a local or remote macine.
310 * PARAMS
311 * Flags [I] control exclusion of classes from the list.
312 * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs.
313 * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList).
314 * RequiredSize [O] pointer, which receives the number of GUIDs that are returned.
315 * MachineName [I] name of a remote machine.
316 * Reserved [I] must be NULL.
318 * RETURNS
319 * Success: TRUE.
320 * Failure: FALSE.
322 BOOL WINAPI SetupDiBuildClassInfoListExW(
323 DWORD Flags,
324 LPGUID ClassGuidList,
325 DWORD ClassGuidListSize,
326 PDWORD RequiredSize,
327 LPCWSTR MachineName,
328 PVOID Reserved)
330 WCHAR szKeyName[40];
331 HKEY hClassesKey;
332 HKEY hClassKey;
333 DWORD dwLength;
334 DWORD dwIndex;
335 LONG lError;
336 DWORD dwGuidListIndex = 0;
338 TRACE("\n");
340 if (RequiredSize != NULL)
341 *RequiredSize = 0;
343 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
344 KEY_ALL_ACCESS,
345 DIOCR_INSTALLER,
346 MachineName,
347 Reserved);
348 if (hClassesKey == INVALID_HANDLE_VALUE)
350 return FALSE;
353 for (dwIndex = 0; ; dwIndex++)
355 dwLength = 40;
356 lError = RegEnumKeyExW(hClassesKey,
357 dwIndex,
358 szKeyName,
359 &dwLength,
360 NULL,
361 NULL,
362 NULL,
363 NULL);
364 TRACE("RegEnumKeyExW() returns %d\n", lError);
365 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
367 TRACE("Key name: %p\n", szKeyName);
369 if (RegOpenKeyExW(hClassesKey,
370 szKeyName,
372 KEY_ALL_ACCESS,
373 &hClassKey))
375 RegCloseKey(hClassesKey);
376 return FALSE;
379 if (!RegQueryValueExW(hClassKey,
380 NoUseClass,
381 NULL,
382 NULL,
383 NULL,
384 NULL))
386 TRACE("'NoUseClass' value found!\n");
387 RegCloseKey(hClassKey);
388 continue;
391 if ((Flags & DIBCI_NOINSTALLCLASS) &&
392 (!RegQueryValueExW(hClassKey,
393 NoInstallClass,
394 NULL,
395 NULL,
396 NULL,
397 NULL)))
399 TRACE("'NoInstallClass' value found!\n");
400 RegCloseKey(hClassKey);
401 continue;
404 if ((Flags & DIBCI_NODISPLAYCLASS) &&
405 (!RegQueryValueExW(hClassKey,
406 NoDisplayClass,
407 NULL,
408 NULL,
409 NULL,
410 NULL)))
412 TRACE("'NoDisplayClass' value found!\n");
413 RegCloseKey(hClassKey);
414 continue;
417 RegCloseKey(hClassKey);
419 TRACE("Guid: %p\n", szKeyName);
420 if (dwGuidListIndex < ClassGuidListSize)
422 if (szKeyName[0] == '{' && szKeyName[37] == '}')
424 szKeyName[37] = 0;
426 TRACE("Guid: %p\n", &szKeyName[1]);
428 UuidFromStringW(&szKeyName[1],
429 &ClassGuidList[dwGuidListIndex]);
432 dwGuidListIndex++;
435 if (lError != ERROR_SUCCESS)
436 break;
439 RegCloseKey(hClassesKey);
441 if (RequiredSize != NULL)
442 *RequiredSize = dwGuidListIndex;
444 if (ClassGuidListSize < dwGuidListIndex)
446 SetLastError(ERROR_INSUFFICIENT_BUFFER);
447 return FALSE;
450 return TRUE;
453 /***********************************************************************
454 * SetupDiClassGuidsFromNameA (SETUPAPI.@)
456 BOOL WINAPI SetupDiClassGuidsFromNameA(
457 LPCSTR ClassName,
458 LPGUID ClassGuidList,
459 DWORD ClassGuidListSize,
460 PDWORD RequiredSize)
462 return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList,
463 ClassGuidListSize, RequiredSize,
464 NULL, NULL);
467 /***********************************************************************
468 * SetupDiClassGuidsFromNameW (SETUPAPI.@)
470 BOOL WINAPI SetupDiClassGuidsFromNameW(
471 LPCWSTR ClassName,
472 LPGUID ClassGuidList,
473 DWORD ClassGuidListSize,
474 PDWORD RequiredSize)
476 return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList,
477 ClassGuidListSize, RequiredSize,
478 NULL, NULL);
481 /***********************************************************************
482 * SetupDiClassGuidsFromNameExA (SETUPAPI.@)
484 BOOL WINAPI SetupDiClassGuidsFromNameExA(
485 LPCSTR ClassName,
486 LPGUID ClassGuidList,
487 DWORD ClassGuidListSize,
488 PDWORD RequiredSize,
489 LPCSTR MachineName,
490 PVOID Reserved)
492 LPWSTR ClassNameW = NULL;
493 LPWSTR MachineNameW = NULL;
494 BOOL bResult;
496 FIXME("\n");
498 ClassNameW = MultiByteToUnicode(ClassName, CP_ACP);
499 if (ClassNameW == NULL)
500 return FALSE;
502 if (MachineName)
504 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
505 if (MachineNameW == NULL)
507 MyFree(ClassNameW);
508 return FALSE;
512 bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList,
513 ClassGuidListSize, RequiredSize,
514 MachineNameW, Reserved);
516 MyFree(MachineNameW);
517 MyFree(ClassNameW);
519 return bResult;
522 /***********************************************************************
523 * SetupDiClassGuidsFromNameExW (SETUPAPI.@)
525 BOOL WINAPI SetupDiClassGuidsFromNameExW(
526 LPCWSTR ClassName,
527 LPGUID ClassGuidList,
528 DWORD ClassGuidListSize,
529 PDWORD RequiredSize,
530 LPCWSTR MachineName,
531 PVOID Reserved)
533 WCHAR szKeyName[40];
534 WCHAR szClassName[256];
535 HKEY hClassesKey;
536 HKEY hClassKey;
537 DWORD dwLength;
538 DWORD dwIndex;
539 LONG lError;
540 DWORD dwGuidListIndex = 0;
542 if (RequiredSize != NULL)
543 *RequiredSize = 0;
545 hClassesKey = SetupDiOpenClassRegKeyExW(NULL,
546 KEY_ALL_ACCESS,
547 DIOCR_INSTALLER,
548 MachineName,
549 Reserved);
550 if (hClassesKey == INVALID_HANDLE_VALUE)
552 return FALSE;
555 for (dwIndex = 0; ; dwIndex++)
557 dwLength = 40;
558 lError = RegEnumKeyExW(hClassesKey,
559 dwIndex,
560 szKeyName,
561 &dwLength,
562 NULL,
563 NULL,
564 NULL,
565 NULL);
566 TRACE("RegEnumKeyExW() returns %d\n", lError);
567 if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA)
569 TRACE("Key name: %p\n", szKeyName);
571 if (RegOpenKeyExW(hClassesKey,
572 szKeyName,
574 KEY_ALL_ACCESS,
575 &hClassKey))
577 RegCloseKey(hClassesKey);
578 return FALSE;
581 dwLength = 256 * sizeof(WCHAR);
582 if (!RegQueryValueExW(hClassKey,
583 Class,
584 NULL,
585 NULL,
586 (LPBYTE)szClassName,
587 &dwLength))
589 TRACE("Class name: %p\n", szClassName);
591 if (strcmpiW(szClassName, ClassName) == 0)
593 TRACE("Found matching class name\n");
595 TRACE("Guid: %p\n", szKeyName);
596 if (dwGuidListIndex < ClassGuidListSize)
598 if (szKeyName[0] == '{' && szKeyName[37] == '}')
600 szKeyName[37] = 0;
602 TRACE("Guid: %p\n", &szKeyName[1]);
604 UuidFromStringW(&szKeyName[1],
605 &ClassGuidList[dwGuidListIndex]);
608 dwGuidListIndex++;
612 RegCloseKey(hClassKey);
615 if (lError != ERROR_SUCCESS)
616 break;
619 RegCloseKey(hClassesKey);
621 if (RequiredSize != NULL)
622 *RequiredSize = dwGuidListIndex;
624 if (ClassGuidListSize < dwGuidListIndex)
626 SetLastError(ERROR_INSUFFICIENT_BUFFER);
627 return FALSE;
630 return TRUE;
633 /***********************************************************************
634 * SetupDiClassNameFromGuidA (SETUPAPI.@)
636 BOOL WINAPI SetupDiClassNameFromGuidA(
637 const GUID* ClassGuid,
638 PSTR ClassName,
639 DWORD ClassNameSize,
640 PDWORD RequiredSize)
642 return SetupDiClassNameFromGuidExA(ClassGuid, ClassName,
643 ClassNameSize, RequiredSize,
644 NULL, NULL);
647 /***********************************************************************
648 * SetupDiClassNameFromGuidW (SETUPAPI.@)
650 BOOL WINAPI SetupDiClassNameFromGuidW(
651 const GUID* ClassGuid,
652 PWSTR ClassName,
653 DWORD ClassNameSize,
654 PDWORD RequiredSize)
656 return SetupDiClassNameFromGuidExW(ClassGuid, ClassName,
657 ClassNameSize, RequiredSize,
658 NULL, NULL);
661 /***********************************************************************
662 * SetupDiClassNameFromGuidExA (SETUPAPI.@)
664 BOOL WINAPI SetupDiClassNameFromGuidExA(
665 const GUID* ClassGuid,
666 PSTR ClassName,
667 DWORD ClassNameSize,
668 PDWORD RequiredSize,
669 PCSTR MachineName,
670 PVOID Reserved)
672 WCHAR ClassNameW[MAX_CLASS_NAME_LEN];
673 LPWSTR MachineNameW = NULL;
674 BOOL ret;
676 if (MachineName)
677 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
678 ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN,
679 NULL, MachineNameW, Reserved);
680 if (ret)
682 int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName,
683 ClassNameSize, NULL, NULL);
685 if (!ClassNameSize && RequiredSize)
686 *RequiredSize = len;
688 MyFree(MachineNameW);
689 return ret;
692 /***********************************************************************
693 * SetupDiClassNameFromGuidExW (SETUPAPI.@)
695 BOOL WINAPI SetupDiClassNameFromGuidExW(
696 const GUID* ClassGuid,
697 PWSTR ClassName,
698 DWORD ClassNameSize,
699 PDWORD RequiredSize,
700 PCWSTR MachineName,
701 PVOID Reserved)
703 HKEY hKey;
704 DWORD dwLength;
706 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
707 KEY_ALL_ACCESS,
708 DIOCR_INSTALLER,
709 MachineName,
710 Reserved);
711 if (hKey == INVALID_HANDLE_VALUE)
713 return FALSE;
716 if (RequiredSize != NULL)
718 dwLength = 0;
719 if (RegQueryValueExW(hKey,
720 Class,
721 NULL,
722 NULL,
723 NULL,
724 &dwLength))
726 RegCloseKey(hKey);
727 return FALSE;
730 *RequiredSize = dwLength / sizeof(WCHAR);
733 dwLength = ClassNameSize * sizeof(WCHAR);
734 if (RegQueryValueExW(hKey,
735 Class,
736 NULL,
737 NULL,
738 (LPBYTE)ClassName,
739 &dwLength))
741 RegCloseKey(hKey);
742 return FALSE;
745 RegCloseKey(hKey);
747 return TRUE;
750 /***********************************************************************
751 * SetupDiCreateDeviceInfoList (SETUPAPI.@)
753 HDEVINFO WINAPI
754 SetupDiCreateDeviceInfoList(const GUID *ClassGuid,
755 HWND hwndParent)
757 return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL);
760 /***********************************************************************
761 * SetupDiCreateDeviceInfoListExA (SETUPAPI.@)
763 HDEVINFO WINAPI
764 SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid,
765 HWND hwndParent,
766 PCSTR MachineName,
767 PVOID Reserved)
769 LPWSTR MachineNameW = NULL;
770 HDEVINFO hDevInfo;
772 TRACE("\n");
774 if (MachineName)
776 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
777 if (MachineNameW == NULL)
778 return (HDEVINFO)INVALID_HANDLE_VALUE;
781 hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent,
782 MachineNameW, Reserved);
784 MyFree(MachineNameW);
786 return hDevInfo;
789 /***********************************************************************
790 * SetupDiCreateDeviceInfoListExW (SETUPAPI.@)
792 * Create an empty DeviceInfoSet list.
794 * PARAMS
795 * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated
796 * with this list.
797 * hwndParent [I] hwnd needed for interface related actions.
798 * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL
799 * local registry will be used.
800 * Reserved [I] must be NULL
802 * RETURNS
803 * Success: empty list.
804 * Failure: INVALID_HANDLE_VALUE.
806 HDEVINFO WINAPI
807 SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid,
808 HWND hwndParent,
809 PCWSTR MachineName,
810 PVOID Reserved)
812 struct DeviceInfoSet *list = NULL;
813 DWORD size = sizeof(struct DeviceInfoSet);
815 TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent,
816 debugstr_w(MachineName), Reserved);
818 if (MachineName != NULL)
820 FIXME("remote support is not implemented\n");
821 SetLastError(ERROR_INVALID_MACHINENAME);
822 return (HDEVINFO)INVALID_HANDLE_VALUE;
825 if (Reserved != NULL)
827 SetLastError(ERROR_INVALID_PARAMETER);
828 return (HDEVINFO)INVALID_HANDLE_VALUE;
831 list = HeapAlloc(GetProcessHeap(), 0, size);
832 if (!list)
834 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
835 return (HDEVINFO)INVALID_HANDLE_VALUE;
838 list->magic = SETUP_DEVICE_INFO_SET_MAGIC;
839 list->hwndParent = hwndParent;
840 memcpy(&list->ClassGuid,
841 ClassGuid ? ClassGuid : &GUID_NULL,
842 sizeof(list->ClassGuid));
843 list->cDevices = 0;
844 list->devices = NULL;
846 return (HDEVINFO)list;
849 /***********************************************************************
850 * SetupDiCreateDeviceInfoA (SETUPAPI.@)
852 BOOL WINAPI SetupDiCreateDeviceInfoA(
853 HDEVINFO DeviceInfoSet,
854 PCSTR DeviceName,
855 CONST GUID *ClassGuid,
856 PCSTR DeviceDescription,
857 HWND hwndParent,
858 DWORD CreationFlags,
859 PSP_DEVINFO_DATA DeviceInfoData)
861 BOOL ret = FALSE;
862 LPWSTR DeviceNameW = NULL;
863 LPWSTR DeviceDescriptionW = NULL;
865 if (DeviceName)
867 DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP);
868 if (DeviceNameW == NULL) return FALSE;
870 if (DeviceDescription)
872 DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP);
873 if (DeviceDescriptionW == NULL)
875 MyFree(DeviceNameW);
876 return FALSE;
880 ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW,
881 hwndParent, CreationFlags, DeviceInfoData);
883 MyFree(DeviceNameW);
884 MyFree(DeviceDescriptionW);
886 return ret;
889 static DWORD SETUPDI_DevNameToDevID(LPCWSTR devName)
891 LPCWSTR ptr;
892 DWORD devNameLen = lstrlenW(devName), devInst = 0;
893 BOOL valid = TRUE;
895 TRACE("%s\n", debugstr_w(devName));
896 for (ptr = devName; valid && *ptr && ptr - devName < devNameLen; )
898 if (isdigitW(*ptr))
900 devInst *= 10;
901 devInst |= *ptr - '0';
902 ptr++;
904 else
905 valid = FALSE;
907 TRACE("%d\n", valid ? devInst : 0xffffffff);
908 return valid ? devInst : 0xffffffff;
911 /***********************************************************************
912 * SetupDiCreateDeviceInfoW (SETUPAPI.@)
914 BOOL WINAPI SetupDiCreateDeviceInfoW(
915 HDEVINFO DeviceInfoSet,
916 PCWSTR DeviceName,
917 CONST GUID *ClassGuid,
918 PCWSTR DeviceDescription,
919 HWND hwndParent,
920 DWORD CreationFlags,
921 PSP_DEVINFO_DATA DeviceInfoData)
923 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
924 BOOL ret = FALSE, allocatedInstanceId = FALSE;
925 LPCWSTR instanceId = NULL;
927 TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName),
928 debugstr_guid(ClassGuid), debugstr_w(DeviceDescription),
929 hwndParent, CreationFlags, DeviceInfoData);
931 if (!DeviceName)
933 SetLastError(ERROR_INVALID_DEVINST_NAME);
934 return FALSE;
936 if (!DeviceInfoSet || DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
938 SetLastError(ERROR_INVALID_HANDLE);
939 return FALSE;
941 if (!ClassGuid)
943 SetLastError(ERROR_INVALID_PARAMETER);
944 return FALSE;
946 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
948 SetLastError(ERROR_INVALID_HANDLE);
949 return FALSE;
951 if (!IsEqualGUID(&set->ClassGuid, &GUID_NULL) &&
952 !IsEqualGUID(ClassGuid, &set->ClassGuid))
954 SetLastError(ERROR_CLASS_MISMATCH);
955 return FALSE;
957 if ((CreationFlags & DICD_GENERATE_ID))
959 if (strchrW(DeviceName, '\\'))
960 SetLastError(ERROR_INVALID_DEVINST_NAME);
961 else
963 static const WCHAR newDeviceFmt[] = {'R','O','O','T','\\','%','s',
964 '\\','%','0','4','d',0};
965 DWORD devId;
967 if (set->cDevices)
969 DWORD i, highestDevID = 0;
971 for (i = 0; i < set->cDevices; i++)
973 struct DeviceInfo *devInfo =
974 (struct DeviceInfo *)set->devices[i].Reserved;
975 LPCWSTR devName = strrchrW(devInfo->instanceId, '\\');
976 DWORD id;
978 if (devName)
979 devName++;
980 else
981 devName = devInfo->instanceId;
982 id = SETUPDI_DevNameToDevID(devName);
983 if (id != 0xffffffff && id > highestDevID)
984 highestDevID = id;
986 devId = highestDevID + 1;
988 else
989 devId = 0;
990 /* 17 == lstrlenW(L"Root\\") + lstrlenW("\\") + 1 + %d max size */
991 instanceId = HeapAlloc(GetProcessHeap(), 0,
992 (17 + lstrlenW(DeviceName)) * sizeof(WCHAR));
993 if (instanceId)
995 sprintfW((LPWSTR)instanceId, newDeviceFmt, DeviceName,
996 devId);
997 allocatedInstanceId = TRUE;
998 ret = TRUE;
1000 else
1001 ret = FALSE;
1004 else
1006 DWORD i;
1008 ret = TRUE;
1009 instanceId = DeviceName;
1010 for (i = 0; ret && i < set->cDevices; i++)
1012 struct DeviceInfo *devInfo =
1013 (struct DeviceInfo *)set->devices[i].Reserved;
1015 if (!lstrcmpiW(DeviceName, devInfo->instanceId))
1017 SetLastError(ERROR_DEVINST_ALREADY_EXISTS);
1018 ret = FALSE;
1022 if (ret)
1024 SP_DEVINFO_DATA *dev = NULL;
1026 ret = SETUPDI_AddDeviceToSet(set, ClassGuid, 0 /* FIXME: DevInst */,
1027 instanceId, TRUE, &dev);
1028 if (ret)
1030 if (DeviceDescription)
1031 SetupDiSetDeviceRegistryPropertyW(DeviceInfoSet,
1032 dev, SPDRP_DEVICEDESC, (const BYTE *)DeviceDescription,
1033 lstrlenW(DeviceDescription) * sizeof(WCHAR));
1034 if (DeviceInfoData)
1036 if (DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
1038 SetLastError(ERROR_INVALID_USER_BUFFER);
1039 ret = FALSE;
1041 else
1042 memcpy(DeviceInfoData, dev, sizeof(SP_DEVINFO_DATA));
1046 if (allocatedInstanceId)
1047 HeapFree(GetProcessHeap(), 0, (LPWSTR)instanceId);
1049 return ret;
1052 /***********************************************************************
1053 * SetupDiEnumDeviceInfo (SETUPAPI.@)
1055 BOOL WINAPI SetupDiEnumDeviceInfo(
1056 HDEVINFO devinfo,
1057 DWORD index,
1058 PSP_DEVINFO_DATA info)
1060 BOOL ret = FALSE;
1062 TRACE("%p %d %p\n", devinfo, index, info);
1064 if(info==NULL)
1065 return FALSE;
1066 if(info->cbSize < sizeof(*info))
1067 return FALSE;
1068 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1070 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1071 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1073 if (index < list->cDevices)
1075 if (info->cbSize == sizeof(SP_DEVINFO_DATA))
1077 memcpy(info, &list->devices[index], info->cbSize);
1078 ret = TRUE;
1080 else
1081 SetLastError(ERROR_INVALID_USER_BUFFER);
1083 else
1084 SetLastError(ERROR_NO_MORE_ITEMS);
1086 else
1087 SetLastError(ERROR_INVALID_HANDLE);
1089 else
1090 SetLastError(ERROR_INVALID_HANDLE);
1091 return ret;
1094 /***********************************************************************
1095 * SetupDiGetDeviceInstanceIdA (SETUPAPI.@)
1097 BOOL WINAPI SetupDiGetDeviceInstanceIdA(
1098 HDEVINFO DeviceInfoSet,
1099 PSP_DEVINFO_DATA DeviceInfoData,
1100 PSTR DeviceInstanceId,
1101 DWORD DeviceInstanceIdSize,
1102 PDWORD RequiredSize)
1104 BOOL ret = FALSE;
1105 DWORD size;
1106 PWSTR instanceId;
1108 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1109 DeviceInstanceIdSize, RequiredSize);
1111 SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1112 DeviceInfoData,
1113 NULL,
1115 &size);
1116 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
1117 return FALSE;
1118 instanceId = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
1119 if (instanceId)
1121 ret = SetupDiGetDeviceInstanceIdW(DeviceInfoSet,
1122 DeviceInfoData,
1123 instanceId,
1124 size,
1125 &size);
1126 if (ret)
1128 int len = WideCharToMultiByte(CP_ACP, 0, instanceId, -1,
1129 DeviceInstanceId,
1130 DeviceInstanceIdSize, NULL, NULL);
1132 if (!len)
1133 ret = FALSE;
1134 else
1136 if (len > DeviceInstanceIdSize)
1138 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1139 ret = FALSE;
1141 if (RequiredSize)
1142 *RequiredSize = len;
1145 HeapFree(GetProcessHeap(), 0, instanceId);
1147 return ret;
1150 /***********************************************************************
1151 * SetupDiGetDeviceInstanceIdW (SETUPAPI.@)
1153 BOOL WINAPI SetupDiGetDeviceInstanceIdW(
1154 HDEVINFO DeviceInfoSet,
1155 PSP_DEVINFO_DATA DeviceInfoData,
1156 PWSTR DeviceInstanceId,
1157 DWORD DeviceInstanceIdSize,
1158 PDWORD RequiredSize)
1160 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1161 struct DeviceInfo *devInfo;
1163 TRACE("%p %p %p %d %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstanceId,
1164 DeviceInstanceIdSize, RequiredSize);
1166 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1168 SetLastError(ERROR_INVALID_HANDLE);
1169 return FALSE;
1171 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1173 SetLastError(ERROR_INVALID_HANDLE);
1174 return FALSE;
1176 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1177 || !DeviceInfoData->Reserved)
1179 SetLastError(ERROR_INVALID_PARAMETER);
1180 return FALSE;
1182 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1183 TRACE("instance ID: %s\n", debugstr_w(devInfo->instanceId));
1184 if (DeviceInstanceIdSize < lstrlenW(devInfo->instanceId) + 1)
1186 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1187 if (RequiredSize)
1188 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1189 return FALSE;
1191 lstrcpyW(DeviceInstanceId, devInfo->instanceId);
1192 if (RequiredSize)
1193 *RequiredSize = lstrlenW(devInfo->instanceId) + 1;
1194 return TRUE;
1197 /***********************************************************************
1198 * SetupDiGetActualSectionToInstallA (SETUPAPI.@)
1200 BOOL WINAPI SetupDiGetActualSectionToInstallA(
1201 HINF InfHandle,
1202 PCSTR InfSectionName,
1203 PSTR InfSectionWithExt,
1204 DWORD InfSectionWithExtSize,
1205 PDWORD RequiredSize,
1206 PSTR *Extension)
1208 FIXME("\n");
1209 return FALSE;
1212 /***********************************************************************
1213 * SetupDiGetActualSectionToInstallW (SETUPAPI.@)
1215 BOOL WINAPI SetupDiGetActualSectionToInstallW(
1216 HINF InfHandle,
1217 PCWSTR InfSectionName,
1218 PWSTR InfSectionWithExt,
1219 DWORD InfSectionWithExtSize,
1220 PDWORD RequiredSize,
1221 PWSTR *Extension)
1223 WCHAR szBuffer[MAX_PATH];
1224 DWORD dwLength;
1225 DWORD dwFullLength;
1226 LONG lLineCount = -1;
1228 lstrcpyW(szBuffer, InfSectionName);
1229 dwLength = lstrlenW(szBuffer);
1231 if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
1233 /* Test section name with '.NTx86' extension */
1234 lstrcpyW(&szBuffer[dwLength], NtPlatformExtension);
1235 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1237 if (lLineCount == -1)
1239 /* Test section name with '.NT' extension */
1240 lstrcpyW(&szBuffer[dwLength], NtExtension);
1241 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1244 else
1246 /* Test section name with '.Win' extension */
1247 lstrcpyW(&szBuffer[dwLength], WinExtension);
1248 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1251 if (lLineCount == -1)
1253 /* Test section name without extension */
1254 szBuffer[dwLength] = 0;
1255 lLineCount = SetupGetLineCountW(InfHandle, szBuffer);
1258 if (lLineCount == -1)
1260 SetLastError(ERROR_INVALID_PARAMETER);
1261 return FALSE;
1264 dwFullLength = lstrlenW(szBuffer);
1266 if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0)
1268 if (InfSectionWithExtSize < (dwFullLength + 1))
1270 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1271 return FALSE;
1274 lstrcpyW(InfSectionWithExt, szBuffer);
1275 if (Extension != NULL)
1277 *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength];
1281 if (RequiredSize != NULL)
1283 *RequiredSize = dwFullLength + 1;
1286 return TRUE;
1289 /***********************************************************************
1290 * SetupDiGetClassDescriptionA (SETUPAPI.@)
1292 BOOL WINAPI SetupDiGetClassDescriptionA(
1293 const GUID* ClassGuid,
1294 PSTR ClassDescription,
1295 DWORD ClassDescriptionSize,
1296 PDWORD RequiredSize)
1298 return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription,
1299 ClassDescriptionSize,
1300 RequiredSize, NULL, NULL);
1303 /***********************************************************************
1304 * SetupDiGetClassDescriptionW (SETUPAPI.@)
1306 BOOL WINAPI SetupDiGetClassDescriptionW(
1307 const GUID* ClassGuid,
1308 PWSTR ClassDescription,
1309 DWORD ClassDescriptionSize,
1310 PDWORD RequiredSize)
1312 return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription,
1313 ClassDescriptionSize,
1314 RequiredSize, NULL, NULL);
1317 /***********************************************************************
1318 * SetupDiGetClassDescriptionExA (SETUPAPI.@)
1320 BOOL WINAPI SetupDiGetClassDescriptionExA(
1321 const GUID* ClassGuid,
1322 PSTR ClassDescription,
1323 DWORD ClassDescriptionSize,
1324 PDWORD RequiredSize,
1325 PCSTR MachineName,
1326 PVOID Reserved)
1328 FIXME("\n");
1329 return FALSE;
1332 /***********************************************************************
1333 * SetupDiGetClassDescriptionExW (SETUPAPI.@)
1335 BOOL WINAPI SetupDiGetClassDescriptionExW(
1336 const GUID* ClassGuid,
1337 PWSTR ClassDescription,
1338 DWORD ClassDescriptionSize,
1339 PDWORD RequiredSize,
1340 PCWSTR MachineName,
1341 PVOID Reserved)
1343 HKEY hKey;
1344 DWORD dwLength;
1346 hKey = SetupDiOpenClassRegKeyExW(ClassGuid,
1347 KEY_ALL_ACCESS,
1348 DIOCR_INSTALLER,
1349 MachineName,
1350 Reserved);
1351 if (hKey == INVALID_HANDLE_VALUE)
1353 WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError());
1354 return FALSE;
1357 if (RequiredSize != NULL)
1359 dwLength = 0;
1360 if (RegQueryValueExW(hKey,
1361 NULL,
1362 NULL,
1363 NULL,
1364 NULL,
1365 &dwLength))
1367 RegCloseKey(hKey);
1368 return FALSE;
1371 *RequiredSize = dwLength / sizeof(WCHAR);
1374 dwLength = ClassDescriptionSize * sizeof(WCHAR);
1375 if (RegQueryValueExW(hKey,
1376 NULL,
1377 NULL,
1378 NULL,
1379 (LPBYTE)ClassDescription,
1380 &dwLength))
1382 RegCloseKey(hKey);
1383 return FALSE;
1386 RegCloseKey(hKey);
1388 return TRUE;
1391 /***********************************************************************
1392 * SetupDiGetClassDevsA (SETUPAPI.@)
1394 HDEVINFO WINAPI SetupDiGetClassDevsA(
1395 CONST GUID *class,
1396 LPCSTR enumstr,
1397 HWND parent,
1398 DWORD flags)
1400 HDEVINFO ret;
1401 LPWSTR enumstrW = NULL;
1403 if (enumstr)
1405 int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0);
1406 enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1407 if (!enumstrW)
1409 ret = (HDEVINFO)INVALID_HANDLE_VALUE;
1410 goto end;
1412 MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len);
1414 ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags);
1415 HeapFree(GetProcessHeap(), 0, enumstrW);
1417 end:
1418 return ret;
1421 /***********************************************************************
1422 * SetupDiGetClassDevsW (SETUPAPI.@)
1424 HDEVINFO WINAPI SetupDiGetClassDevsW(
1425 CONST GUID *class,
1426 LPCWSTR enumstr,
1427 HWND parent,
1428 DWORD flags)
1430 TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr), parent, flags);
1432 /* WinXP always succeeds, returns empty list for unknown classes */
1433 FIXME("returning empty list\n");
1434 return SetupDiCreateDeviceInfoList(class, parent);
1437 /***********************************************************************
1438 * SetupDiGetClassDevsExW (SETUPAPI.@)
1440 HDEVINFO WINAPI SetupDiGetClassDevsExW(
1441 CONST GUID *class,
1442 PCWSTR enumstr,
1443 HWND parent,
1444 DWORD flags,
1445 HDEVINFO deviceset,
1446 PCWSTR machine,
1447 PVOID reserved)
1449 FIXME("stub\n");
1450 return NULL;
1453 /***********************************************************************
1454 * SetupDiEnumDeviceInterfaces (SETUPAPI.@)
1456 BOOL WINAPI SetupDiEnumDeviceInterfaces(
1457 HDEVINFO devinfo,
1458 PSP_DEVINFO_DATA DeviceInfoData,
1459 CONST GUID * InterfaceClassGuid,
1460 DWORD MemberIndex,
1461 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
1463 BOOL ret = FALSE;
1465 FIXME("%p, %p, %s, 0x%08x, %p\n", devinfo, DeviceInfoData,
1466 debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
1468 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1470 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1471 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1472 SetLastError(ERROR_NO_MORE_ITEMS);
1473 else
1474 SetLastError(ERROR_INVALID_HANDLE);
1476 else
1477 SetLastError(ERROR_INVALID_HANDLE);
1478 return ret;
1481 /***********************************************************************
1482 * SetupDiDestroyDeviceInfoList (SETUPAPI.@)
1484 * Destroy a DeviceInfoList and free all used memory of the list.
1486 * PARAMS
1487 * devinfo [I] DeviceInfoList pointer to list to destroy
1489 * RETURNS
1490 * Success: non zero value.
1491 * Failure: zero value.
1493 BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo)
1495 BOOL ret = FALSE;
1497 TRACE("%p\n", devinfo);
1498 if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE)
1500 struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo;
1502 if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
1504 DWORD i;
1506 for (i = 0; i < list->cDevices; i++)
1507 SETUPDI_FreeDeviceInfo(
1508 (struct DeviceInfo *)list->devices[i].Reserved);
1509 HeapFree(GetProcessHeap(), 0, list->devices);
1510 HeapFree(GetProcessHeap(), 0, list);
1511 ret = TRUE;
1515 if (ret == FALSE)
1516 SetLastError(ERROR_INVALID_HANDLE);
1518 return ret;
1521 /***********************************************************************
1522 * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
1524 BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(
1525 HDEVINFO DeviceInfoSet,
1526 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1527 PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData,
1528 DWORD DeviceInterfaceDetailDataSize,
1529 PDWORD RequiredSize,
1530 PSP_DEVINFO_DATA DeviceInfoData)
1532 BOOL ret = FALSE;
1534 FIXME("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet,
1535 DeviceInterfaceData, DeviceInterfaceDetailData,
1536 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1538 SetLastError(ERROR_INVALID_HANDLE);
1539 return ret;
1542 /***********************************************************************
1543 * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
1545 BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(
1546 HDEVINFO DeviceInfoSet,
1547 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
1548 PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
1549 DWORD DeviceInterfaceDetailDataSize,
1550 PDWORD RequiredSize,
1551 PSP_DEVINFO_DATA DeviceInfoData)
1553 FIXME("(%p, %p, %p, %d, %p, %p): stub\n", DeviceInfoSet,
1554 DeviceInterfaceData, DeviceInterfaceDetailData,
1555 DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
1556 return FALSE;
1559 struct PropertyMapEntry
1561 DWORD regType;
1562 LPCSTR nameA;
1563 LPCWSTR nameW;
1566 static struct PropertyMapEntry PropertyMap[] = {
1567 { REG_SZ, "DeviceDesc", DeviceDesc },
1568 { REG_MULTI_SZ, "HardwareId", HardwareId },
1569 { REG_MULTI_SZ, "CompatibleIDs", CompatibleIDs },
1570 { 0, NULL, NULL }, /* SPDRP_UNUSED0 */
1571 { REG_SZ, "Service", Service },
1572 { 0, NULL, NULL }, /* SPDRP_UNUSED1 */
1573 { 0, NULL, NULL }, /* SPDRP_UNUSED2 */
1574 { REG_SZ, "Class", Class },
1575 { REG_SZ, "ClassGUID", ClassGUID },
1576 { REG_SZ, "Driver", Driver },
1577 { REG_DWORD, "ConfigFlags", ConfigFlags },
1578 { REG_SZ, "Mfg", Mfg },
1579 { REG_SZ, "FriendlyName", FriendlyName },
1580 { REG_SZ, "LocationInformation", LocationInformation },
1581 { 0, NULL, NULL }, /* SPDRP_PHYSICAL_DEVICE_OBJECT_NAME */
1582 { REG_DWORD, "Capabilities", Capabilities },
1583 { REG_DWORD, "UINumber", UINumber },
1584 { REG_MULTI_SZ, "UpperFilters", UpperFilters },
1585 { REG_MULTI_SZ, "LowerFilters", LowerFilters },
1588 /***********************************************************************
1589 * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@)
1591 BOOL WINAPI SetupDiGetDeviceRegistryPropertyA(
1592 HDEVINFO DeviceInfoSet,
1593 PSP_DEVINFO_DATA DeviceInfoData,
1594 DWORD Property,
1595 PDWORD PropertyRegDataType,
1596 PBYTE PropertyBuffer,
1597 DWORD PropertyBufferSize,
1598 PDWORD RequiredSize)
1600 BOOL ret = FALSE;
1601 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1602 struct DeviceInfo *devInfo;
1604 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
1605 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1606 RequiredSize);
1608 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1610 SetLastError(ERROR_INVALID_HANDLE);
1611 return FALSE;
1613 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1615 SetLastError(ERROR_INVALID_HANDLE);
1616 return FALSE;
1618 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1619 || !DeviceInfoData->Reserved)
1621 SetLastError(ERROR_INVALID_PARAMETER);
1622 return FALSE;
1624 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1625 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
1626 && PropertyMap[Property].nameA)
1628 DWORD size = PropertyBufferSize;
1629 LONG l = RegQueryValueExA(devInfo->key, PropertyMap[Property].nameA,
1630 NULL, PropertyRegDataType, PropertyBuffer, &size);
1632 if (RequiredSize)
1633 *RequiredSize = size;
1634 if (!l)
1635 ret = TRUE;
1636 else
1637 SetLastError(l);
1639 return ret;
1642 /***********************************************************************
1643 * SetupDiGetDeviceRegistryPropertyW (SETUPAPI.@)
1645 BOOL WINAPI SetupDiGetDeviceRegistryPropertyW(
1646 HDEVINFO DeviceInfoSet,
1647 PSP_DEVINFO_DATA DeviceInfoData,
1648 DWORD Property,
1649 PDWORD PropertyRegDataType,
1650 PBYTE PropertyBuffer,
1651 DWORD PropertyBufferSize,
1652 PDWORD RequiredSize)
1654 BOOL ret = FALSE;
1655 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1656 struct DeviceInfo *devInfo;
1658 TRACE("%04x %p %d %p %p %d %p\n", (DWORD)DeviceInfoSet, DeviceInfoData,
1659 Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize,
1660 RequiredSize);
1662 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1664 SetLastError(ERROR_INVALID_HANDLE);
1665 return FALSE;
1667 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1669 SetLastError(ERROR_INVALID_HANDLE);
1670 return FALSE;
1672 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1673 || !DeviceInfoData->Reserved)
1675 SetLastError(ERROR_INVALID_PARAMETER);
1676 return FALSE;
1678 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1679 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
1680 && PropertyMap[Property].nameW)
1682 DWORD size = PropertyBufferSize;
1683 LONG l = RegQueryValueExW(devInfo->key, PropertyMap[Property].nameW,
1684 NULL, PropertyRegDataType, PropertyBuffer, &size);
1686 if (RequiredSize)
1687 *RequiredSize = size;
1688 if (!l)
1689 ret = TRUE;
1690 else
1691 SetLastError(l);
1693 return ret;
1696 /***********************************************************************
1697 * SetupDiSetDeviceRegistryPropertyA (SETUPAPI.@)
1699 BOOL WINAPI SetupDiSetDeviceRegistryPropertyA(
1700 HDEVINFO DeviceInfoSet,
1701 PSP_DEVINFO_DATA DeviceInfoData,
1702 DWORD Property,
1703 const BYTE *PropertyBuffer,
1704 DWORD PropertyBufferSize)
1706 BOOL ret = FALSE;
1707 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1708 struct DeviceInfo *devInfo;
1710 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
1711 PropertyBuffer, PropertyBufferSize);
1713 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1715 SetLastError(ERROR_INVALID_HANDLE);
1716 return FALSE;
1718 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1720 SetLastError(ERROR_INVALID_HANDLE);
1721 return FALSE;
1723 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1724 || !DeviceInfoData->Reserved)
1726 SetLastError(ERROR_INVALID_PARAMETER);
1727 return FALSE;
1729 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1730 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
1731 && PropertyMap[Property].nameA)
1733 LONG l = RegSetValueExA(devInfo->key, PropertyMap[Property].nameA, 0,
1734 PropertyMap[Property].regType, PropertyBuffer,
1735 PropertyBufferSize);
1736 if (!l)
1737 ret = TRUE;
1738 else
1739 SetLastError(l);
1741 return ret;
1744 /***********************************************************************
1745 * SetupDiSetDeviceRegistryPropertyW (SETUPAPI.@)
1747 BOOL WINAPI SetupDiSetDeviceRegistryPropertyW(
1748 HDEVINFO DeviceInfoSet,
1749 PSP_DEVINFO_DATA DeviceInfoData,
1750 DWORD Property,
1751 const BYTE *PropertyBuffer,
1752 DWORD PropertyBufferSize)
1754 BOOL ret = FALSE;
1755 struct DeviceInfoSet *set = (struct DeviceInfoSet *)DeviceInfoSet;
1756 struct DeviceInfo *devInfo;
1758 TRACE("%p %p %d %p %d\n", DeviceInfoSet, DeviceInfoData, Property,
1759 PropertyBuffer, PropertyBufferSize);
1761 if (!DeviceInfoSet || DeviceInfoSet == INVALID_HANDLE_VALUE)
1763 SetLastError(ERROR_INVALID_HANDLE);
1764 return FALSE;
1766 if (set->magic != SETUP_DEVICE_INFO_SET_MAGIC)
1768 SetLastError(ERROR_INVALID_HANDLE);
1769 return FALSE;
1771 if (!DeviceInfoData || DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)
1772 || !DeviceInfoData->Reserved)
1774 SetLastError(ERROR_INVALID_PARAMETER);
1775 return FALSE;
1777 devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
1778 if (Property < sizeof(PropertyMap) / sizeof(PropertyMap[0])
1779 && PropertyMap[Property].nameW)
1781 LONG l = RegSetValueExW(devInfo->key, PropertyMap[Property].nameW, 0,
1782 PropertyMap[Property].regType, PropertyBuffer,
1783 PropertyBufferSize);
1784 if (!l)
1785 ret = TRUE;
1786 else
1787 SetLastError(l);
1789 return ret;
1792 /***********************************************************************
1793 * SetupDiInstallClassA (SETUPAPI.@)
1795 BOOL WINAPI SetupDiInstallClassA(
1796 HWND hwndParent,
1797 PCSTR InfFileName,
1798 DWORD Flags,
1799 HSPFILEQ FileQueue)
1801 UNICODE_STRING FileNameW;
1802 BOOL Result;
1804 if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName))
1806 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1807 return FALSE;
1810 Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue);
1812 RtlFreeUnicodeString(&FileNameW);
1814 return Result;
1817 static HKEY CreateClassKey(HINF hInf)
1819 WCHAR FullBuffer[MAX_PATH];
1820 WCHAR Buffer[MAX_PATH];
1821 DWORD RequiredSize;
1822 HKEY hClassKey;
1824 if (!SetupGetLineTextW(NULL,
1825 hInf,
1826 Version,
1827 ClassGUID,
1828 Buffer,
1829 MAX_PATH,
1830 &RequiredSize))
1832 return INVALID_HANDLE_VALUE;
1835 lstrcpyW(FullBuffer, ControlClass);
1836 lstrcatW(FullBuffer, Buffer);
1838 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1839 FullBuffer,
1841 KEY_ALL_ACCESS,
1842 &hClassKey))
1844 if (!SetupGetLineTextW(NULL,
1845 hInf,
1846 Version,
1847 Class,
1848 Buffer,
1849 MAX_PATH,
1850 &RequiredSize))
1852 return INVALID_HANDLE_VALUE;
1855 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,
1856 FullBuffer,
1858 NULL,
1859 REG_OPTION_NON_VOLATILE,
1860 KEY_ALL_ACCESS,
1861 NULL,
1862 &hClassKey,
1863 NULL))
1865 return INVALID_HANDLE_VALUE;
1870 if (RegSetValueExW(hClassKey,
1871 Class,
1873 REG_SZ,
1874 (LPBYTE)Buffer,
1875 RequiredSize * sizeof(WCHAR)))
1877 RegCloseKey(hClassKey);
1878 RegDeleteKeyW(HKEY_LOCAL_MACHINE,
1879 FullBuffer);
1880 return INVALID_HANDLE_VALUE;
1883 return hClassKey;
1886 /***********************************************************************
1887 * SetupDiInstallClassW (SETUPAPI.@)
1889 BOOL WINAPI SetupDiInstallClassW(
1890 HWND hwndParent,
1891 PCWSTR InfFileName,
1892 DWORD Flags,
1893 HSPFILEQ FileQueue)
1895 WCHAR SectionName[MAX_PATH];
1896 DWORD SectionNameLength = 0;
1897 HINF hInf;
1898 BOOL bFileQueueCreated = FALSE;
1899 HKEY hClassKey;
1902 FIXME("\n");
1904 if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE))
1906 SetLastError(ERROR_INVALID_PARAMETER);
1907 return FALSE;
1910 /* Open the .inf file */
1911 hInf = SetupOpenInfFileW(InfFileName,
1912 NULL,
1913 INF_STYLE_WIN4,
1914 NULL);
1915 if (hInf == INVALID_HANDLE_VALUE)
1918 return FALSE;
1921 /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */
1922 hClassKey = CreateClassKey(hInf);
1923 if (hClassKey == INVALID_HANDLE_VALUE)
1925 SetupCloseInfFile(hInf);
1926 return FALSE;
1930 /* Try to append a layout file */
1931 #if 0
1932 SetupOpenAppendInfFileW(NULL, hInf, NULL);
1933 #endif
1935 /* Retrieve the actual section name */
1936 SetupDiGetActualSectionToInstallW(hInf,
1937 ClassInstall32,
1938 SectionName,
1939 MAX_PATH,
1940 &SectionNameLength,
1941 NULL);
1943 #if 0
1944 if (!(Flags & DI_NOVCP))
1946 FileQueue = SetupOpenFileQueue();
1947 if (FileQueue == INVALID_HANDLE_VALUE)
1949 SetupCloseInfFile(hInf);
1950 return FALSE;
1953 bFileQueueCreated = TRUE;
1956 #endif
1958 SetupInstallFromInfSectionW(NULL,
1959 hInf,
1960 SectionName,
1961 SPINST_REGISTRY,
1962 hClassKey,
1963 NULL,
1965 NULL,
1966 NULL,
1967 INVALID_HANDLE_VALUE,
1968 NULL);
1970 /* FIXME: More code! */
1972 if (bFileQueueCreated)
1973 SetupCloseFileQueue(FileQueue);
1975 SetupCloseInfFile(hInf);
1977 return TRUE;
1981 /***********************************************************************
1982 * SetupDiOpenClassRegKey (SETUPAPI.@)
1984 HKEY WINAPI SetupDiOpenClassRegKey(
1985 const GUID* ClassGuid,
1986 REGSAM samDesired)
1988 return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
1989 DIOCR_INSTALLER, NULL, NULL);
1993 /***********************************************************************
1994 * SetupDiOpenClassRegKeyExA (SETUPAPI.@)
1996 HKEY WINAPI SetupDiOpenClassRegKeyExA(
1997 const GUID* ClassGuid,
1998 REGSAM samDesired,
1999 DWORD Flags,
2000 PCSTR MachineName,
2001 PVOID Reserved)
2003 PWSTR MachineNameW = NULL;
2004 HKEY hKey;
2006 TRACE("\n");
2008 if (MachineName)
2010 MachineNameW = MultiByteToUnicode(MachineName, CP_ACP);
2011 if (MachineNameW == NULL)
2012 return INVALID_HANDLE_VALUE;
2015 hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired,
2016 Flags, MachineNameW, Reserved);
2018 MyFree(MachineNameW);
2020 return hKey;
2024 /***********************************************************************
2025 * SetupDiOpenClassRegKeyExW (SETUPAPI.@)
2027 HKEY WINAPI SetupDiOpenClassRegKeyExW(
2028 const GUID* ClassGuid,
2029 REGSAM samDesired,
2030 DWORD Flags,
2031 PCWSTR MachineName,
2032 PVOID Reserved)
2034 WCHAR bracedGuidString[39];
2035 HKEY hClassesKey;
2036 HKEY hClassKey;
2037 LPCWSTR lpKeyName;
2039 if (MachineName != NULL)
2041 FIXME("Remote access not supported yet!\n");
2042 return INVALID_HANDLE_VALUE;
2045 if (Flags == DIOCR_INSTALLER)
2047 lpKeyName = ControlClass;
2049 else if (Flags == DIOCR_INTERFACE)
2051 lpKeyName = DeviceClasses;
2053 else
2055 ERR("Invalid Flags parameter!\n");
2056 SetLastError(ERROR_INVALID_PARAMETER);
2057 return INVALID_HANDLE_VALUE;
2060 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
2061 lpKeyName,
2063 KEY_ALL_ACCESS,
2064 &hClassesKey))
2066 return INVALID_HANDLE_VALUE;
2069 if (ClassGuid == NULL)
2070 return hClassesKey;
2072 SETUPDI_GuidToString(ClassGuid, bracedGuidString);
2074 if (RegOpenKeyExW(hClassesKey,
2075 bracedGuidString,
2077 KEY_ALL_ACCESS,
2078 &hClassKey))
2080 RegCloseKey(hClassesKey);
2081 return INVALID_HANDLE_VALUE;
2084 RegCloseKey(hClassesKey);
2086 return hClassKey;
2089 /***********************************************************************
2090 * SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
2092 BOOL WINAPI SetupDiOpenDeviceInterfaceW(
2093 HDEVINFO DeviceInfoSet,
2094 PCWSTR DevicePath,
2095 DWORD OpenFlags,
2096 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2098 FIXME("%p %s %08x %p\n",
2099 DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
2100 return FALSE;
2103 /***********************************************************************
2104 * SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
2106 BOOL WINAPI SetupDiOpenDeviceInterfaceA(
2107 HDEVINFO DeviceInfoSet,
2108 PCSTR DevicePath,
2109 DWORD OpenFlags,
2110 PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
2112 FIXME("%p %s %08x %p\n", DeviceInfoSet,
2113 debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
2114 return FALSE;
2117 /***********************************************************************
2118 * SetupDiSetClassInstallParamsA (SETUPAPI.@)
2120 BOOL WINAPI SetupDiSetClassInstallParamsA(
2121 HDEVINFO DeviceInfoSet,
2122 PSP_DEVINFO_DATA DeviceInfoData,
2123 PSP_CLASSINSTALL_HEADER ClassInstallParams,
2124 DWORD ClassInstallParamsSize)
2126 FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData,
2127 ClassInstallParams->InstallFunction, ClassInstallParamsSize);
2128 return FALSE;
2131 /***********************************************************************
2132 * SetupDiCallClassInstaller (SETUPAPI.@)
2134 BOOL WINAPI SetupDiCallClassInstaller(
2135 DI_FUNCTION InstallFunction,
2136 HDEVINFO DeviceInfoSet,
2137 PSP_DEVINFO_DATA DeviceInfoData)
2139 FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData);
2140 return FALSE;
2143 /***********************************************************************
2144 * SetupDiGetDeviceInstallParamsA (SETUPAPI.@)
2146 BOOL WINAPI SetupDiGetDeviceInstallParamsA(
2147 HDEVINFO DeviceInfoSet,
2148 PSP_DEVINFO_DATA DeviceInfoData,
2149 PSP_DEVINSTALL_PARAMS_A DeviceInstallParams)
2151 FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams);
2152 return FALSE;
2155 /***********************************************************************
2156 * SetupDiOpenDevRegKey (SETUPAPI.@)
2158 HKEY WINAPI SetupDiOpenDevRegKey(
2159 HDEVINFO DeviceInfoSet,
2160 PSP_DEVINFO_DATA DeviceInfoData,
2161 DWORD Scope,
2162 DWORD HwProfile,
2163 DWORD KeyType,
2164 REGSAM samDesired)
2166 FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData,
2167 Scope, HwProfile, KeyType, samDesired);
2168 return INVALID_HANDLE_VALUE;