| /* | |
| * SetupAPI device installer | |
| * | |
| * Copyright 2000 Andreas Mohr for CodeWeavers | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #include "config.h" | |
| #include "wine/port.h" | |
| #include <stdarg.h> | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winnt.h" | |
| #include "winreg.h" | |
| #include "winternl.h" | |
| #include "wingdi.h" | |
| #include "winuser.h" | |
| #include "winnls.h" | |
| #include "setupapi.h" | |
| #include "wine/debug.h" | |
| #include "wine/unicode.h" | |
| #include "cfgmgr32.h" | |
| #include "initguid.h" | |
| #include "winioctl.h" | |
| #include "rpc.h" | |
| #include "rpcdce.h" | |
| #include "setupapi_private.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(setupapi); | |
| /* Unicode constants */ | |
| static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0}; | |
| static const WCHAR Class[] = {'C','l','a','s','s',0}; | |
| static const WCHAR ClassInstall32[] = {'C','l','a','s','s','I','n','s','t','a','l','l','3','2',0}; | |
| static const WCHAR NoDisplayClass[] = {'N','o','D','i','s','p','l','a','y','C','l','a','s','s',0}; | |
| static const WCHAR NoInstallClass[] = {'N','o','I','s','t','a','l','l','C','l','a','s','s',0}; | |
| static const WCHAR NoUseClass[] = {'N','o','U','s','e','C','l','a','s','s',0}; | |
| static const WCHAR NtExtension[] = {'.','N','T',0}; | |
| static const WCHAR NtPlatformExtension[] = {'.','N','T','x','8','6',0}; | |
| static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; | |
| static const WCHAR WinExtension[] = {'.','W','i','n',0}; | |
| /* Registry key and value names */ | |
| static const WCHAR ControlClass[] = {'S','y','s','t','e','m','\\', | |
| 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', | |
| 'C','o','n','t','r','o','l','\\', | |
| 'C','l','a','s','s',0}; | |
| static const WCHAR DeviceClasses[] = {'S','y','s','t','e','m','\\', | |
| 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', | |
| 'C','o','n','t','r','o','l','\\', | |
| 'D','e','v','i','c','e','C','l','a','s','s','e','s',0}; | |
| /* is used to identify if a DeviceInfoSet pointer is | |
| valid or not */ | |
| #define SETUP_DEVICE_INFO_SET_MAGIC 0xd00ff056 | |
| struct DeviceInfoSet | |
| { | |
| DWORD magic; /* if is equal to SETUP_DEVICE_INFO_SET_MAGIC struct is okay */ | |
| GUID ClassGuid; | |
| HWND hwndParent; | |
| }; | |
| /*********************************************************************** | |
| * SetupDiBuildClassInfoList (SETUPAPI.@) | |
| * | |
| * Returns a list of setup class GUIDs that identify the classes | |
| * that are installed on a local machine. | |
| * | |
| * PARAMS | |
| * Flags [I] control exclusion of classes from the list. | |
| * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs. | |
| * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList). | |
| * RequiredSize [O] pointer, which receives the number of GUIDs that are returned. | |
| * | |
| * RETURNS | |
| * Success: TRUE. | |
| * Failure: FALSE. | |
| */ | |
| BOOL WINAPI SetupDiBuildClassInfoList( | |
| DWORD Flags, | |
| LPGUID ClassGuidList, | |
| DWORD ClassGuidListSize, | |
| PDWORD RequiredSize) | |
| { | |
| TRACE("\n"); | |
| return SetupDiBuildClassInfoListExW(Flags, ClassGuidList, | |
| ClassGuidListSize, RequiredSize, | |
| NULL, NULL); | |
| } | |
| /*********************************************************************** | |
| * SetupDiBuildClassInfoListExA (SETUPAPI.@) | |
| * | |
| * Returns a list of setup class GUIDs that identify the classes | |
| * that are installed on a local or remote macine. | |
| * | |
| * PARAMS | |
| * Flags [I] control exclusion of classes from the list. | |
| * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs. | |
| * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList). | |
| * RequiredSize [O] pointer, which receives the number of GUIDs that are returned. | |
| * MachineName [I] name of a remote machine. | |
| * Reserved [I] must be NULL. | |
| * | |
| * RETURNS | |
| * Success: TRUE. | |
| * Failure: FALSE. | |
| */ | |
| BOOL WINAPI SetupDiBuildClassInfoListExA( | |
| DWORD Flags, | |
| LPGUID ClassGuidList, | |
| DWORD ClassGuidListSize, | |
| PDWORD RequiredSize, | |
| LPCSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| LPWSTR MachineNameW = NULL; | |
| BOOL bResult; | |
| TRACE("\n"); | |
| if (MachineName) | |
| { | |
| MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); | |
| if (MachineNameW == NULL) return FALSE; | |
| } | |
| bResult = SetupDiBuildClassInfoListExW(Flags, ClassGuidList, | |
| ClassGuidListSize, RequiredSize, | |
| MachineNameW, Reserved); | |
| MyFree(MachineNameW); | |
| return bResult; | |
| } | |
| /*********************************************************************** | |
| * SetupDiBuildClassInfoListExW (SETUPAPI.@) | |
| * | |
| * Returns a list of setup class GUIDs that identify the classes | |
| * that are installed on a local or remote macine. | |
| * | |
| * PARAMS | |
| * Flags [I] control exclusion of classes from the list. | |
| * ClassGuidList [O] pointer to a GUID-typed array that receives a list of setup class GUIDs. | |
| * ClassGuidListSize [I] The number of GUIDs in the array (ClassGuidList). | |
| * RequiredSize [O] pointer, which receives the number of GUIDs that are returned. | |
| * MachineName [I] name of a remote machine. | |
| * Reserved [I] must be NULL. | |
| * | |
| * RETURNS | |
| * Success: TRUE. | |
| * Failure: FALSE. | |
| */ | |
| BOOL WINAPI SetupDiBuildClassInfoListExW( | |
| DWORD Flags, | |
| LPGUID ClassGuidList, | |
| DWORD ClassGuidListSize, | |
| PDWORD RequiredSize, | |
| LPCWSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| WCHAR szKeyName[40]; | |
| HKEY hClassesKey; | |
| HKEY hClassKey; | |
| DWORD dwLength; | |
| DWORD dwIndex; | |
| LONG lError; | |
| DWORD dwGuidListIndex = 0; | |
| TRACE("\n"); | |
| if (RequiredSize != NULL) | |
| *RequiredSize = 0; | |
| hClassesKey = SetupDiOpenClassRegKeyExW(NULL, | |
| KEY_ALL_ACCESS, | |
| DIOCR_INSTALLER, | |
| MachineName, | |
| Reserved); | |
| if (hClassesKey == INVALID_HANDLE_VALUE) | |
| { | |
| return FALSE; | |
| } | |
| for (dwIndex = 0; ; dwIndex++) | |
| { | |
| dwLength = 40; | |
| lError = RegEnumKeyExW(hClassesKey, | |
| dwIndex, | |
| szKeyName, | |
| &dwLength, | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL); | |
| TRACE("RegEnumKeyExW() returns %d\n", lError); | |
| if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) | |
| { | |
| TRACE("Key name: %p\n", szKeyName); | |
| if (RegOpenKeyExW(hClassesKey, | |
| szKeyName, | |
| 0, | |
| KEY_ALL_ACCESS, | |
| &hClassKey)) | |
| { | |
| RegCloseKey(hClassesKey); | |
| return FALSE; | |
| } | |
| if (!RegQueryValueExW(hClassKey, | |
| NoUseClass, | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL)) | |
| { | |
| TRACE("'NoUseClass' value found!\n"); | |
| RegCloseKey(hClassKey); | |
| continue; | |
| } | |
| if ((Flags & DIBCI_NOINSTALLCLASS) && | |
| (!RegQueryValueExW(hClassKey, | |
| NoInstallClass, | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL))) | |
| { | |
| TRACE("'NoInstallClass' value found!\n"); | |
| RegCloseKey(hClassKey); | |
| continue; | |
| } | |
| if ((Flags & DIBCI_NODISPLAYCLASS) && | |
| (!RegQueryValueExW(hClassKey, | |
| NoDisplayClass, | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL))) | |
| { | |
| TRACE("'NoDisplayClass' value found!\n"); | |
| RegCloseKey(hClassKey); | |
| continue; | |
| } | |
| RegCloseKey(hClassKey); | |
| TRACE("Guid: %p\n", szKeyName); | |
| if (dwGuidListIndex < ClassGuidListSize) | |
| { | |
| if (szKeyName[0] == '{' && szKeyName[37] == '}') | |
| { | |
| szKeyName[37] = 0; | |
| } | |
| TRACE("Guid: %p\n", &szKeyName[1]); | |
| UuidFromStringW(&szKeyName[1], | |
| &ClassGuidList[dwGuidListIndex]); | |
| } | |
| dwGuidListIndex++; | |
| } | |
| if (lError != ERROR_SUCCESS) | |
| break; | |
| } | |
| RegCloseKey(hClassesKey); | |
| if (RequiredSize != NULL) | |
| *RequiredSize = dwGuidListIndex; | |
| if (ClassGuidListSize < dwGuidListIndex) | |
| { | |
| SetLastError(ERROR_INSUFFICIENT_BUFFER); | |
| return FALSE; | |
| } | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiClassGuidsFromNameA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiClassGuidsFromNameA( | |
| LPCSTR ClassName, | |
| LPGUID ClassGuidList, | |
| DWORD ClassGuidListSize, | |
| PDWORD RequiredSize) | |
| { | |
| return SetupDiClassGuidsFromNameExA(ClassName, ClassGuidList, | |
| ClassGuidListSize, RequiredSize, | |
| NULL, NULL); | |
| } | |
| /*********************************************************************** | |
| * SetupDiClassGuidsFromNameW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiClassGuidsFromNameW( | |
| LPCWSTR ClassName, | |
| LPGUID ClassGuidList, | |
| DWORD ClassGuidListSize, | |
| PDWORD RequiredSize) | |
| { | |
| return SetupDiClassGuidsFromNameExW(ClassName, ClassGuidList, | |
| ClassGuidListSize, RequiredSize, | |
| NULL, NULL); | |
| } | |
| /*********************************************************************** | |
| * SetupDiClassGuidsFromNameExA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiClassGuidsFromNameExA( | |
| LPCSTR ClassName, | |
| LPGUID ClassGuidList, | |
| DWORD ClassGuidListSize, | |
| PDWORD RequiredSize, | |
| LPCSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| LPWSTR ClassNameW = NULL; | |
| LPWSTR MachineNameW = NULL; | |
| BOOL bResult; | |
| FIXME("\n"); | |
| ClassNameW = MultiByteToUnicode(ClassName, CP_ACP); | |
| if (ClassNameW == NULL) | |
| return FALSE; | |
| if (MachineName) | |
| { | |
| MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); | |
| if (MachineNameW == NULL) | |
| { | |
| MyFree(ClassNameW); | |
| return FALSE; | |
| } | |
| } | |
| bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList, | |
| ClassGuidListSize, RequiredSize, | |
| MachineNameW, Reserved); | |
| MyFree(MachineNameW); | |
| MyFree(ClassNameW); | |
| return bResult; | |
| } | |
| /*********************************************************************** | |
| * SetupDiClassGuidsFromNameExW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiClassGuidsFromNameExW( | |
| LPCWSTR ClassName, | |
| LPGUID ClassGuidList, | |
| DWORD ClassGuidListSize, | |
| PDWORD RequiredSize, | |
| LPCWSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| WCHAR szKeyName[40]; | |
| WCHAR szClassName[256]; | |
| HKEY hClassesKey; | |
| HKEY hClassKey; | |
| DWORD dwLength; | |
| DWORD dwIndex; | |
| LONG lError; | |
| DWORD dwGuidListIndex = 0; | |
| if (RequiredSize != NULL) | |
| *RequiredSize = 0; | |
| hClassesKey = SetupDiOpenClassRegKeyExW(NULL, | |
| KEY_ALL_ACCESS, | |
| DIOCR_INSTALLER, | |
| MachineName, | |
| Reserved); | |
| if (hClassesKey == INVALID_HANDLE_VALUE) | |
| { | |
| return FALSE; | |
| } | |
| for (dwIndex = 0; ; dwIndex++) | |
| { | |
| dwLength = 40; | |
| lError = RegEnumKeyExW(hClassesKey, | |
| dwIndex, | |
| szKeyName, | |
| &dwLength, | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL); | |
| TRACE("RegEnumKeyExW() returns %d\n", lError); | |
| if (lError == ERROR_SUCCESS || lError == ERROR_MORE_DATA) | |
| { | |
| TRACE("Key name: %p\n", szKeyName); | |
| if (RegOpenKeyExW(hClassesKey, | |
| szKeyName, | |
| 0, | |
| KEY_ALL_ACCESS, | |
| &hClassKey)) | |
| { | |
| RegCloseKey(hClassesKey); | |
| return FALSE; | |
| } | |
| dwLength = 256 * sizeof(WCHAR); | |
| if (!RegQueryValueExW(hClassKey, | |
| Class, | |
| NULL, | |
| NULL, | |
| (LPBYTE)szClassName, | |
| &dwLength)) | |
| { | |
| TRACE("Class name: %p\n", szClassName); | |
| if (strcmpiW(szClassName, ClassName) == 0) | |
| { | |
| TRACE("Found matching class name\n"); | |
| TRACE("Guid: %p\n", szKeyName); | |
| if (dwGuidListIndex < ClassGuidListSize) | |
| { | |
| if (szKeyName[0] == '{' && szKeyName[37] == '}') | |
| { | |
| szKeyName[37] = 0; | |
| } | |
| TRACE("Guid: %p\n", &szKeyName[1]); | |
| UuidFromStringW(&szKeyName[1], | |
| &ClassGuidList[dwGuidListIndex]); | |
| } | |
| dwGuidListIndex++; | |
| } | |
| } | |
| RegCloseKey(hClassKey); | |
| } | |
| if (lError != ERROR_SUCCESS) | |
| break; | |
| } | |
| RegCloseKey(hClassesKey); | |
| if (RequiredSize != NULL) | |
| *RequiredSize = dwGuidListIndex; | |
| if (ClassGuidListSize < dwGuidListIndex) | |
| { | |
| SetLastError(ERROR_INSUFFICIENT_BUFFER); | |
| return FALSE; | |
| } | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiClassNameFromGuidA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiClassNameFromGuidA( | |
| const GUID* ClassGuid, | |
| PSTR ClassName, | |
| DWORD ClassNameSize, | |
| PDWORD RequiredSize) | |
| { | |
| return SetupDiClassNameFromGuidExA(ClassGuid, ClassName, | |
| ClassNameSize, RequiredSize, | |
| NULL, NULL); | |
| } | |
| /*********************************************************************** | |
| * SetupDiClassNameFromGuidW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiClassNameFromGuidW( | |
| const GUID* ClassGuid, | |
| PWSTR ClassName, | |
| DWORD ClassNameSize, | |
| PDWORD RequiredSize) | |
| { | |
| return SetupDiClassNameFromGuidExW(ClassGuid, ClassName, | |
| ClassNameSize, RequiredSize, | |
| NULL, NULL); | |
| } | |
| /*********************************************************************** | |
| * SetupDiClassNameFromGuidExA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiClassNameFromGuidExA( | |
| const GUID* ClassGuid, | |
| PSTR ClassName, | |
| DWORD ClassNameSize, | |
| PDWORD RequiredSize, | |
| PCSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| WCHAR ClassNameW[MAX_CLASS_NAME_LEN]; | |
| LPWSTR MachineNameW = NULL; | |
| BOOL ret; | |
| if (MachineName) | |
| MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); | |
| ret = SetupDiClassNameFromGuidExW(ClassGuid, ClassNameW, MAX_CLASS_NAME_LEN, | |
| NULL, MachineNameW, Reserved); | |
| if (ret) | |
| { | |
| int len = WideCharToMultiByte(CP_ACP, 0, ClassNameW, -1, ClassName, | |
| ClassNameSize, NULL, NULL); | |
| if (!ClassNameSize && RequiredSize) | |
| *RequiredSize = len; | |
| } | |
| MyFree(MachineNameW); | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * SetupDiClassNameFromGuidExW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiClassNameFromGuidExW( | |
| const GUID* ClassGuid, | |
| PWSTR ClassName, | |
| DWORD ClassNameSize, | |
| PDWORD RequiredSize, | |
| PCWSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| HKEY hKey; | |
| DWORD dwLength; | |
| hKey = SetupDiOpenClassRegKeyExW(ClassGuid, | |
| KEY_ALL_ACCESS, | |
| DIOCR_INSTALLER, | |
| MachineName, | |
| Reserved); | |
| if (hKey == INVALID_HANDLE_VALUE) | |
| { | |
| return FALSE; | |
| } | |
| if (RequiredSize != NULL) | |
| { | |
| dwLength = 0; | |
| if (RegQueryValueExW(hKey, | |
| Class, | |
| NULL, | |
| NULL, | |
| NULL, | |
| &dwLength)) | |
| { | |
| RegCloseKey(hKey); | |
| return FALSE; | |
| } | |
| *RequiredSize = dwLength / sizeof(WCHAR); | |
| } | |
| dwLength = ClassNameSize * sizeof(WCHAR); | |
| if (RegQueryValueExW(hKey, | |
| Class, | |
| NULL, | |
| NULL, | |
| (LPBYTE)ClassName, | |
| &dwLength)) | |
| { | |
| RegCloseKey(hKey); | |
| return FALSE; | |
| } | |
| RegCloseKey(hKey); | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiCreateDeviceInfoList (SETUPAPI.@) | |
| */ | |
| HDEVINFO WINAPI | |
| SetupDiCreateDeviceInfoList(const GUID *ClassGuid, | |
| HWND hwndParent) | |
| { | |
| return SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, NULL, NULL); | |
| } | |
| /*********************************************************************** | |
| * SetupDiCreateDeviceInfoListExA (SETUPAPI.@) | |
| */ | |
| HDEVINFO WINAPI | |
| SetupDiCreateDeviceInfoListExA(const GUID *ClassGuid, | |
| HWND hwndParent, | |
| PCSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| LPWSTR MachineNameW = NULL; | |
| HDEVINFO hDevInfo; | |
| TRACE("\n"); | |
| if (MachineName) | |
| { | |
| MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); | |
| if (MachineNameW == NULL) | |
| return (HDEVINFO)INVALID_HANDLE_VALUE; | |
| } | |
| hDevInfo = SetupDiCreateDeviceInfoListExW(ClassGuid, hwndParent, | |
| MachineNameW, Reserved); | |
| MyFree(MachineNameW); | |
| return hDevInfo; | |
| } | |
| /*********************************************************************** | |
| * SetupDiCreateDeviceInfoListExW (SETUPAPI.@) | |
| * | |
| * Create an empty DeviceInfoSet list. | |
| * | |
| * PARAMS | |
| * ClassGuid [I] if not NULL only devices with GUID ClcassGuid are associated | |
| * with this list. | |
| * hwndParent [I] hwnd needed for interface related actions. | |
| * MachineName [I] name of machine to create emtpy DeviceInfoSet list, if NULL | |
| * local registry will be used. | |
| * Reserved [I] must be NULL | |
| * | |
| * RETURNS | |
| * Success: empty list. | |
| * Failure: INVALID_HANDLE_VALUE. | |
| */ | |
| HDEVINFO WINAPI | |
| SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid, | |
| HWND hwndParent, | |
| PCWSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| struct DeviceInfoSet *list = NULL; | |
| DWORD size = sizeof(struct DeviceInfoSet); | |
| TRACE("%s %p %s %p\n", debugstr_guid(ClassGuid), hwndParent, | |
| debugstr_w(MachineName), Reserved); | |
| if (MachineName != NULL) | |
| { | |
| FIXME("remote support is not implemented\n"); | |
| SetLastError(ERROR_INVALID_MACHINENAME); | |
| return (HDEVINFO)INVALID_HANDLE_VALUE; | |
| } | |
| if (Reserved != NULL) | |
| { | |
| SetLastError(ERROR_INVALID_PARAMETER); | |
| return (HDEVINFO)INVALID_HANDLE_VALUE; | |
| } | |
| list = HeapAlloc(GetProcessHeap(), 0, size); | |
| if (!list) | |
| { | |
| SetLastError(ERROR_NOT_ENOUGH_MEMORY); | |
| return (HDEVINFO)INVALID_HANDLE_VALUE; | |
| } | |
| list->magic = SETUP_DEVICE_INFO_SET_MAGIC; | |
| list->hwndParent = hwndParent; | |
| memcpy(&list->ClassGuid, | |
| ClassGuid ? ClassGuid : &GUID_NULL, | |
| sizeof(list->ClassGuid)); | |
| return (HDEVINFO)list; | |
| } | |
| /*********************************************************************** | |
| * SetupDiCreateDeviceInfoA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiCreateDeviceInfoA( | |
| HDEVINFO DeviceInfoSet, | |
| PCSTR DeviceName, | |
| CONST GUID *ClassGuid, | |
| PCSTR DeviceDescription, | |
| HWND hwndParent, | |
| DWORD CreationFlags, | |
| PSP_DEVINFO_DATA DeviceInfoData) | |
| { | |
| BOOL ret = FALSE; | |
| LPWSTR DeviceNameW = NULL; | |
| LPWSTR DeviceDescriptionW = NULL; | |
| if (DeviceName) | |
| { | |
| DeviceNameW = MultiByteToUnicode(DeviceName, CP_ACP); | |
| if (DeviceNameW == NULL) return FALSE; | |
| } | |
| if (DeviceDescription) | |
| { | |
| DeviceDescriptionW = MultiByteToUnicode(DeviceDescription, CP_ACP); | |
| if (DeviceDescriptionW == NULL) | |
| { | |
| MyFree(DeviceNameW); | |
| return FALSE; | |
| } | |
| } | |
| ret = SetupDiCreateDeviceInfoW(DeviceInfoSet, DeviceNameW, ClassGuid, DeviceDescriptionW, | |
| hwndParent, CreationFlags, DeviceInfoData); | |
| MyFree(DeviceNameW); | |
| MyFree(DeviceDescriptionW); | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * SetupDiCreateDeviceInfoW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiCreateDeviceInfoW( | |
| HDEVINFO DeviceInfoSet, | |
| PCWSTR DeviceName, | |
| CONST GUID *ClassGuid, | |
| PCWSTR DeviceDescription, | |
| HWND hwndParent, | |
| DWORD CreationFlags, | |
| PSP_DEVINFO_DATA DeviceInfoData) | |
| { | |
| TRACE("%p %s %s %s %p %x %p\n", DeviceInfoSet, debugstr_w(DeviceName), | |
| debugstr_guid(ClassGuid), debugstr_w(DeviceDescription), | |
| hwndParent, CreationFlags, DeviceInfoData); | |
| FIXME("stub\n"); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiEnumDeviceInfo (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiEnumDeviceInfo( | |
| HDEVINFO devinfo, | |
| DWORD index, | |
| PSP_DEVINFO_DATA info) | |
| { | |
| FIXME("%p %d %p\n", devinfo, index, info); | |
| if(info==NULL) | |
| return FALSE; | |
| if(info->cbSize < sizeof(*info)) | |
| return FALSE; | |
| SetLastError(ERROR_NO_MORE_ITEMS); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetActualSectionToInstallA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiGetActualSectionToInstallA( | |
| HINF InfHandle, | |
| PCSTR InfSectionName, | |
| PSTR InfSectionWithExt, | |
| DWORD InfSectionWithExtSize, | |
| PDWORD RequiredSize, | |
| PSTR *Extension) | |
| { | |
| FIXME("\n"); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetActualSectionToInstallW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiGetActualSectionToInstallW( | |
| HINF InfHandle, | |
| PCWSTR InfSectionName, | |
| PWSTR InfSectionWithExt, | |
| DWORD InfSectionWithExtSize, | |
| PDWORD RequiredSize, | |
| PWSTR *Extension) | |
| { | |
| WCHAR szBuffer[MAX_PATH]; | |
| DWORD dwLength; | |
| DWORD dwFullLength; | |
| LONG lLineCount = -1; | |
| lstrcpyW(szBuffer, InfSectionName); | |
| dwLength = lstrlenW(szBuffer); | |
| if (OsVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) | |
| { | |
| /* Test section name with '.NTx86' extension */ | |
| lstrcpyW(&szBuffer[dwLength], NtPlatformExtension); | |
| lLineCount = SetupGetLineCountW(InfHandle, szBuffer); | |
| if (lLineCount == -1) | |
| { | |
| /* Test section name with '.NT' extension */ | |
| lstrcpyW(&szBuffer[dwLength], NtExtension); | |
| lLineCount = SetupGetLineCountW(InfHandle, szBuffer); | |
| } | |
| } | |
| else | |
| { | |
| /* Test section name with '.Win' extension */ | |
| lstrcpyW(&szBuffer[dwLength], WinExtension); | |
| lLineCount = SetupGetLineCountW(InfHandle, szBuffer); | |
| } | |
| if (lLineCount == -1) | |
| { | |
| /* Test section name without extension */ | |
| szBuffer[dwLength] = 0; | |
| lLineCount = SetupGetLineCountW(InfHandle, szBuffer); | |
| } | |
| if (lLineCount == -1) | |
| { | |
| SetLastError(ERROR_INVALID_PARAMETER); | |
| return FALSE; | |
| } | |
| dwFullLength = lstrlenW(szBuffer); | |
| if (InfSectionWithExt != NULL && InfSectionWithExtSize != 0) | |
| { | |
| if (InfSectionWithExtSize < (dwFullLength + 1)) | |
| { | |
| SetLastError(ERROR_INSUFFICIENT_BUFFER); | |
| return FALSE; | |
| } | |
| lstrcpyW(InfSectionWithExt, szBuffer); | |
| if (Extension != NULL) | |
| { | |
| *Extension = (dwLength == dwFullLength) ? NULL : &InfSectionWithExt[dwLength]; | |
| } | |
| } | |
| if (RequiredSize != NULL) | |
| { | |
| *RequiredSize = dwFullLength + 1; | |
| } | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetClassDescriptionA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiGetClassDescriptionA( | |
| const GUID* ClassGuid, | |
| PSTR ClassDescription, | |
| DWORD ClassDescriptionSize, | |
| PDWORD RequiredSize) | |
| { | |
| return SetupDiGetClassDescriptionExA(ClassGuid, ClassDescription, | |
| ClassDescriptionSize, | |
| RequiredSize, NULL, NULL); | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetClassDescriptionW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiGetClassDescriptionW( | |
| const GUID* ClassGuid, | |
| PWSTR ClassDescription, | |
| DWORD ClassDescriptionSize, | |
| PDWORD RequiredSize) | |
| { | |
| return SetupDiGetClassDescriptionExW(ClassGuid, ClassDescription, | |
| ClassDescriptionSize, | |
| RequiredSize, NULL, NULL); | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetClassDescriptionExA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiGetClassDescriptionExA( | |
| const GUID* ClassGuid, | |
| PSTR ClassDescription, | |
| DWORD ClassDescriptionSize, | |
| PDWORD RequiredSize, | |
| PCSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| FIXME("\n"); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetClassDescriptionExW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiGetClassDescriptionExW( | |
| const GUID* ClassGuid, | |
| PWSTR ClassDescription, | |
| DWORD ClassDescriptionSize, | |
| PDWORD RequiredSize, | |
| PCWSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| HKEY hKey; | |
| DWORD dwLength; | |
| hKey = SetupDiOpenClassRegKeyExW(ClassGuid, | |
| KEY_ALL_ACCESS, | |
| DIOCR_INSTALLER, | |
| MachineName, | |
| Reserved); | |
| if (hKey == INVALID_HANDLE_VALUE) | |
| { | |
| WARN("SetupDiOpenClassRegKeyExW() failed (Error %u)\n", GetLastError()); | |
| return FALSE; | |
| } | |
| if (RequiredSize != NULL) | |
| { | |
| dwLength = 0; | |
| if (RegQueryValueExW(hKey, | |
| NULL, | |
| NULL, | |
| NULL, | |
| NULL, | |
| &dwLength)) | |
| { | |
| RegCloseKey(hKey); | |
| return FALSE; | |
| } | |
| *RequiredSize = dwLength / sizeof(WCHAR); | |
| } | |
| dwLength = ClassDescriptionSize * sizeof(WCHAR); | |
| if (RegQueryValueExW(hKey, | |
| NULL, | |
| NULL, | |
| NULL, | |
| (LPBYTE)ClassDescription, | |
| &dwLength)) | |
| { | |
| RegCloseKey(hKey); | |
| return FALSE; | |
| } | |
| RegCloseKey(hKey); | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetClassDevsA (SETUPAPI.@) | |
| */ | |
| HDEVINFO WINAPI SetupDiGetClassDevsA( | |
| CONST GUID *class, | |
| LPCSTR enumstr, | |
| HWND parent, | |
| DWORD flags) | |
| { | |
| HDEVINFO ret; | |
| LPWSTR enumstrW = NULL; | |
| if (enumstr) | |
| { | |
| int len = MultiByteToWideChar(CP_ACP, 0, enumstr, -1, NULL, 0); | |
| enumstrW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); | |
| if (!enumstrW) | |
| { | |
| ret = (HDEVINFO)INVALID_HANDLE_VALUE; | |
| goto end; | |
| } | |
| MultiByteToWideChar(CP_ACP, 0, enumstr, -1, enumstrW, len); | |
| } | |
| ret = SetupDiGetClassDevsW(class, enumstrW, parent, flags); | |
| HeapFree(GetProcessHeap(), 0, enumstrW); | |
| end: | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetClassDevsW (SETUPAPI.@) | |
| */ | |
| HDEVINFO WINAPI SetupDiGetClassDevsW( | |
| CONST GUID *class, | |
| LPCWSTR enumstr, | |
| HWND parent, | |
| DWORD flags) | |
| { | |
| TRACE("%s %s %p 0x%08x\n", debugstr_guid(class), debugstr_w(enumstr), parent, flags); | |
| /* WinXP always succeeds, returns empty list for unknown classes */ | |
| FIXME("returning empty list\n"); | |
| return SetupDiCreateDeviceInfoList(class, parent); | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetClassDevsExW (SETUPAPI.@) | |
| */ | |
| HDEVINFO WINAPI SetupDiGetClassDevsExW( | |
| CONST GUID *class, | |
| PCWSTR enumstr, | |
| HWND parent, | |
| DWORD flags, | |
| HDEVINFO deviceset, | |
| PCWSTR machine, | |
| PVOID reserved) | |
| { | |
| FIXME("stub\n"); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiEnumDeviceInterfaces (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiEnumDeviceInterfaces( | |
| HDEVINFO devinfo, | |
| PSP_DEVINFO_DATA DeviceInfoData, | |
| CONST GUID * InterfaceClassGuid, | |
| DWORD MemberIndex, | |
| PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) | |
| { | |
| BOOL ret = FALSE; | |
| FIXME("%p, %p, %s, 0x%08x, %p\n", devinfo, DeviceInfoData, | |
| debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); | |
| if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE) | |
| { | |
| struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo; | |
| if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC) | |
| SetLastError(ERROR_NO_MORE_ITEMS); | |
| else | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| } | |
| else | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * SetupDiDestroyDeviceInfoList (SETUPAPI.@) | |
| * | |
| * Destroy a DeviceInfoList and free all used memory of the list. | |
| * | |
| * PARAMS | |
| * devinfo [I] DeviceInfoList pointer to list to destroy | |
| * | |
| * RETURNS | |
| * Success: non zero value. | |
| * Failure: zero value. | |
| */ | |
| BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo) | |
| { | |
| BOOL ret = FALSE; | |
| TRACE("%p\n", devinfo); | |
| if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE) | |
| { | |
| struct DeviceInfoSet *list = (struct DeviceInfoSet *)devinfo; | |
| if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC) | |
| { | |
| HeapFree(GetProcessHeap(), 0, list); | |
| ret = TRUE; | |
| } | |
| } | |
| if (ret == FALSE) | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiGetDeviceInterfaceDetailA( | |
| HDEVINFO DeviceInfoSet, | |
| PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, | |
| PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData, | |
| DWORD DeviceInterfaceDetailDataSize, | |
| PDWORD RequiredSize, | |
| PSP_DEVINFO_DATA DeviceInfoData) | |
| { | |
| BOOL ret = FALSE; | |
| FIXME("(%p, %p, %p, %d, %p, %p)\n", DeviceInfoSet, | |
| DeviceInterfaceData, DeviceInterfaceDetailData, | |
| DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiGetDeviceInterfaceDetailW( | |
| HDEVINFO DeviceInfoSet, | |
| PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, | |
| PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData, | |
| DWORD DeviceInterfaceDetailDataSize, | |
| PDWORD RequiredSize, | |
| PSP_DEVINFO_DATA DeviceInfoData) | |
| { | |
| FIXME("(%p, %p, %p, %d, %p, %p): stub\n", DeviceInfoSet, | |
| DeviceInterfaceData, DeviceInterfaceDetailData, | |
| DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiGetDeviceRegistryPropertyA( | |
| HDEVINFO devinfo, | |
| PSP_DEVINFO_DATA DeviceInfoData, | |
| DWORD Property, | |
| PDWORD PropertyRegDataType, | |
| PBYTE PropertyBuffer, | |
| DWORD PropertyBufferSize, | |
| PDWORD RequiredSize) | |
| { | |
| FIXME("%04x %p %d %p %p %d %p\n", (DWORD)devinfo, DeviceInfoData, | |
| Property, PropertyRegDataType, PropertyBuffer, PropertyBufferSize, | |
| RequiredSize); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiInstallClassA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiInstallClassA( | |
| HWND hwndParent, | |
| PCSTR InfFileName, | |
| DWORD Flags, | |
| HSPFILEQ FileQueue) | |
| { | |
| UNICODE_STRING FileNameW; | |
| BOOL Result; | |
| if (!RtlCreateUnicodeStringFromAsciiz(&FileNameW, InfFileName)) | |
| { | |
| SetLastError(ERROR_NOT_ENOUGH_MEMORY); | |
| return FALSE; | |
| } | |
| Result = SetupDiInstallClassW(hwndParent, FileNameW.Buffer, Flags, FileQueue); | |
| RtlFreeUnicodeString(&FileNameW); | |
| return Result; | |
| } | |
| static HKEY CreateClassKey(HINF hInf) | |
| { | |
| WCHAR FullBuffer[MAX_PATH]; | |
| WCHAR Buffer[MAX_PATH]; | |
| DWORD RequiredSize; | |
| HKEY hClassKey; | |
| if (!SetupGetLineTextW(NULL, | |
| hInf, | |
| Version, | |
| ClassGUID, | |
| Buffer, | |
| MAX_PATH, | |
| &RequiredSize)) | |
| { | |
| return INVALID_HANDLE_VALUE; | |
| } | |
| lstrcpyW(FullBuffer, ControlClass); | |
| lstrcatW(FullBuffer, Buffer); | |
| if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, | |
| FullBuffer, | |
| 0, | |
| KEY_ALL_ACCESS, | |
| &hClassKey)) | |
| { | |
| if (!SetupGetLineTextW(NULL, | |
| hInf, | |
| Version, | |
| Class, | |
| Buffer, | |
| MAX_PATH, | |
| &RequiredSize)) | |
| { | |
| return INVALID_HANDLE_VALUE; | |
| } | |
| if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, | |
| FullBuffer, | |
| 0, | |
| NULL, | |
| REG_OPTION_NON_VOLATILE, | |
| KEY_ALL_ACCESS, | |
| NULL, | |
| &hClassKey, | |
| NULL)) | |
| { | |
| return INVALID_HANDLE_VALUE; | |
| } | |
| } | |
| if (RegSetValueExW(hClassKey, | |
| Class, | |
| 0, | |
| REG_SZ, | |
| (LPBYTE)Buffer, | |
| RequiredSize * sizeof(WCHAR))) | |
| { | |
| RegCloseKey(hClassKey); | |
| RegDeleteKeyW(HKEY_LOCAL_MACHINE, | |
| FullBuffer); | |
| return INVALID_HANDLE_VALUE; | |
| } | |
| return hClassKey; | |
| } | |
| /*********************************************************************** | |
| * SetupDiInstallClassW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiInstallClassW( | |
| HWND hwndParent, | |
| PCWSTR InfFileName, | |
| DWORD Flags, | |
| HSPFILEQ FileQueue) | |
| { | |
| WCHAR SectionName[MAX_PATH]; | |
| DWORD SectionNameLength = 0; | |
| HINF hInf; | |
| BOOL bFileQueueCreated = FALSE; | |
| HKEY hClassKey; | |
| FIXME("\n"); | |
| if ((Flags & DI_NOVCP) && (FileQueue == NULL || FileQueue == INVALID_HANDLE_VALUE)) | |
| { | |
| SetLastError(ERROR_INVALID_PARAMETER); | |
| return FALSE; | |
| } | |
| /* Open the .inf file */ | |
| hInf = SetupOpenInfFileW(InfFileName, | |
| NULL, | |
| INF_STYLE_WIN4, | |
| NULL); | |
| if (hInf == INVALID_HANDLE_VALUE) | |
| { | |
| return FALSE; | |
| } | |
| /* Create or open the class registry key 'HKLM\\CurrentControlSet\\Class\\{GUID}' */ | |
| hClassKey = CreateClassKey(hInf); | |
| if (hClassKey == INVALID_HANDLE_VALUE) | |
| { | |
| SetupCloseInfFile(hInf); | |
| return FALSE; | |
| } | |
| /* Try to append a layout file */ | |
| #if 0 | |
| SetupOpenAppendInfFileW(NULL, hInf, NULL); | |
| #endif | |
| /* Retrieve the actual section name */ | |
| SetupDiGetActualSectionToInstallW(hInf, | |
| ClassInstall32, | |
| SectionName, | |
| MAX_PATH, | |
| &SectionNameLength, | |
| NULL); | |
| #if 0 | |
| if (!(Flags & DI_NOVCP)) | |
| { | |
| FileQueue = SetupOpenFileQueue(); | |
| if (FileQueue == INVALID_HANDLE_VALUE) | |
| { | |
| SetupCloseInfFile(hInf); | |
| return FALSE; | |
| } | |
| bFileQueueCreated = TRUE; | |
| } | |
| #endif | |
| SetupInstallFromInfSectionW(NULL, | |
| hInf, | |
| SectionName, | |
| SPINST_REGISTRY, | |
| hClassKey, | |
| NULL, | |
| 0, | |
| NULL, | |
| NULL, | |
| INVALID_HANDLE_VALUE, | |
| NULL); | |
| /* FIXME: More code! */ | |
| if (bFileQueueCreated) | |
| SetupCloseFileQueue(FileQueue); | |
| SetupCloseInfFile(hInf); | |
| return TRUE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiOpenClassRegKey (SETUPAPI.@) | |
| */ | |
| HKEY WINAPI SetupDiOpenClassRegKey( | |
| const GUID* ClassGuid, | |
| REGSAM samDesired) | |
| { | |
| return SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, | |
| DIOCR_INSTALLER, NULL, NULL); | |
| } | |
| /*********************************************************************** | |
| * SetupDiOpenClassRegKeyExA (SETUPAPI.@) | |
| */ | |
| HKEY WINAPI SetupDiOpenClassRegKeyExA( | |
| const GUID* ClassGuid, | |
| REGSAM samDesired, | |
| DWORD Flags, | |
| PCSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| PWSTR MachineNameW = NULL; | |
| HKEY hKey; | |
| TRACE("\n"); | |
| if (MachineName) | |
| { | |
| MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); | |
| if (MachineNameW == NULL) | |
| return INVALID_HANDLE_VALUE; | |
| } | |
| hKey = SetupDiOpenClassRegKeyExW(ClassGuid, samDesired, | |
| Flags, MachineNameW, Reserved); | |
| MyFree(MachineNameW); | |
| return hKey; | |
| } | |
| /*********************************************************************** | |
| * SetupDiOpenClassRegKeyExW (SETUPAPI.@) | |
| */ | |
| HKEY WINAPI SetupDiOpenClassRegKeyExW( | |
| const GUID* ClassGuid, | |
| REGSAM samDesired, | |
| DWORD Flags, | |
| PCWSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| LPWSTR lpGuidString; | |
| WCHAR bracedGuidString[39]; | |
| HKEY hClassesKey; | |
| HKEY hClassKey; | |
| LPCWSTR lpKeyName; | |
| if (MachineName != NULL) | |
| { | |
| FIXME("Remote access not supported yet!\n"); | |
| return INVALID_HANDLE_VALUE; | |
| } | |
| if (Flags == DIOCR_INSTALLER) | |
| { | |
| lpKeyName = ControlClass; | |
| } | |
| else if (Flags == DIOCR_INTERFACE) | |
| { | |
| lpKeyName = DeviceClasses; | |
| } | |
| else | |
| { | |
| ERR("Invalid Flags parameter!\n"); | |
| SetLastError(ERROR_INVALID_PARAMETER); | |
| return INVALID_HANDLE_VALUE; | |
| } | |
| if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, | |
| lpKeyName, | |
| 0, | |
| KEY_ALL_ACCESS, | |
| &hClassesKey)) | |
| { | |
| return INVALID_HANDLE_VALUE; | |
| } | |
| if (ClassGuid == NULL) | |
| return hClassesKey; | |
| if (UuidToStringW((UUID*)ClassGuid, &lpGuidString) != RPC_S_OK) | |
| { | |
| RegCloseKey(hClassesKey); | |
| return INVALID_HANDLE_VALUE; | |
| } | |
| bracedGuidString[0] = '{'; | |
| memcpy(&bracedGuidString[1], lpGuidString, 36*sizeof(WCHAR)); | |
| bracedGuidString[37] = '}'; | |
| bracedGuidString[38] = 0; | |
| RpcStringFreeW(&lpGuidString); | |
| if (RegOpenKeyExW(hClassesKey, | |
| bracedGuidString, | |
| 0, | |
| KEY_ALL_ACCESS, | |
| &hClassKey)) | |
| { | |
| RegCloseKey(hClassesKey); | |
| return INVALID_HANDLE_VALUE; | |
| } | |
| RegCloseKey(hClassesKey); | |
| return hClassKey; | |
| } | |
| /*********************************************************************** | |
| * SetupDiOpenDeviceInterfaceW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiOpenDeviceInterfaceW( | |
| HDEVINFO DeviceInfoSet, | |
| PCWSTR DevicePath, | |
| DWORD OpenFlags, | |
| PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) | |
| { | |
| FIXME("%p %s %08x %p\n", | |
| DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiOpenDeviceInterfaceA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiOpenDeviceInterfaceA( | |
| HDEVINFO DeviceInfoSet, | |
| PCSTR DevicePath, | |
| DWORD OpenFlags, | |
| PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) | |
| { | |
| FIXME("%p %s %08x %p\n", DeviceInfoSet, | |
| debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiSetClassInstallParamsA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiSetClassInstallParamsA( | |
| HDEVINFO DeviceInfoSet, | |
| PSP_DEVINFO_DATA DeviceInfoData, | |
| PSP_CLASSINSTALL_HEADER ClassInstallParams, | |
| DWORD ClassInstallParamsSize) | |
| { | |
| FIXME("%p %p %x %u\n",DeviceInfoSet, DeviceInfoData, | |
| ClassInstallParams->InstallFunction, ClassInstallParamsSize); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiCallClassInstaller (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiCallClassInstaller( | |
| DI_FUNCTION InstallFunction, | |
| HDEVINFO DeviceInfoSet, | |
| PSP_DEVINFO_DATA DeviceInfoData) | |
| { | |
| FIXME("%d %p %p\n", InstallFunction, DeviceInfoSet, DeviceInfoData); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetDeviceInstallParamsA (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiGetDeviceInstallParamsA( | |
| HDEVINFO DeviceInfoSet, | |
| PSP_DEVINFO_DATA DeviceInfoData, | |
| PSP_DEVINSTALL_PARAMS_A DeviceInstallParams) | |
| { | |
| FIXME("%p %p %p\n", DeviceInfoSet, DeviceInfoData, DeviceInstallParams); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiOpenDevRegKey (SETUPAPI.@) | |
| */ | |
| HKEY WINAPI SetupDiOpenDevRegKey( | |
| HDEVINFO DeviceInfoSet, | |
| PSP_DEVINFO_DATA DeviceInfoData, | |
| DWORD Scope, | |
| DWORD HwProfile, | |
| DWORD KeyType, | |
| REGSAM samDesired) | |
| { | |
| FIXME("%p %p %d %d %d %x\n", DeviceInfoSet, DeviceInfoData, | |
| Scope, HwProfile, KeyType, samDesired); | |
| return INVALID_HANDLE_VALUE; | |
| } |