| /* | |
| * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "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}; | |
| /*********************************************************************** | |
| * SetupDiBuildClassInfoList (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiBuildClassInfoList( | |
| DWORD Flags, | |
| LPGUID ClassGuidList, | |
| DWORD ClassGuidListSize, | |
| PDWORD RequiredSize) | |
| { | |
| TRACE("\n"); | |
| return SetupDiBuildClassInfoListExW(Flags, ClassGuidList, | |
| ClassGuidListSize, RequiredSize, | |
| NULL, NULL); | |
| } | |
| /*********************************************************************** | |
| * SetupDiBuildClassInfoListExA (SETUPAPI.@) | |
| */ | |
| 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); | |
| if (MachineNameW) | |
| MyFree(MachineNameW); | |
| return bResult; | |
| } | |
| /*********************************************************************** | |
| * SetupDiBuildClassInfoListExW (SETUPAPI.@) | |
| */ | |
| 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 %ld\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] == L'{' && szKeyName[37] == L'}') | |
| { | |
| 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 (MachineNameW) | |
| { | |
| MachineNameW = MultiByteToUnicode(MachineName, CP_ACP); | |
| if (MachineNameW == NULL) | |
| { | |
| MyFree(ClassNameW); | |
| return FALSE; | |
| } | |
| } | |
| bResult = SetupDiClassGuidsFromNameExW(ClassNameW, ClassGuidList, | |
| ClassGuidListSize, RequiredSize, | |
| MachineNameW, Reserved); | |
| if (MachineNameW) | |
| 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 %ld\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] == L'{' && szKeyName[37] == L'}') | |
| { | |
| 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) | |
| { | |
| FIXME("\n"); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * 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); | |
| if (MachineNameW) | |
| MyFree(MachineNameW); | |
| return hDevInfo; | |
| } | |
| /*********************************************************************** | |
| * SetupDiCreateDeviceInfoListExW (SETUPAPI.@) | |
| */ | |
| HDEVINFO WINAPI | |
| SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid, | |
| HWND hwndParent, | |
| PCWSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| FIXME("\n"); | |
| return (HDEVINFO)INVALID_HANDLE_VALUE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiEnumDeviceInfo (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiEnumDeviceInfo( | |
| HDEVINFO devinfo, | |
| DWORD index, | |
| PSP_DEVINFO_DATA info) | |
| { | |
| FIXME("%p %ld %p\n", devinfo, index, info); | |
| if(info==NULL) | |
| return FALSE; | |
| if(info->cbSize < sizeof(*info)) | |
| return FALSE; | |
| 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 %lu)\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; | |
| } | |
| #define SETUP_SERIAL_PORT_MAGIC 0xd00ff055 | |
| typedef struct _SerialPortName | |
| { | |
| WCHAR name[5]; | |
| } SerialPortName; | |
| typedef struct _SerialPortList | |
| { | |
| DWORD magic; | |
| UINT numPorts; | |
| SerialPortName names[1]; | |
| } SerialPortList; | |
| static HDEVINFO SETUP_CreateSerialDeviceList(void) | |
| { | |
| static const size_t initialSize = 100; | |
| size_t size; | |
| WCHAR buf[initialSize]; | |
| LPWSTR devices; | |
| HDEVINFO ret; | |
| BOOL failed = FALSE; | |
| devices = buf; | |
| size = initialSize; | |
| do { | |
| if (QueryDosDeviceW(NULL, devices, size) == 0) | |
| { | |
| if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) | |
| { | |
| size *= 2; | |
| if (devices != buf) | |
| HeapFree(GetProcessHeap(), 0, devices); | |
| devices = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, | |
| size * sizeof(WCHAR)); | |
| if (!devices) | |
| failed = TRUE; | |
| else | |
| *devices = 0; | |
| } | |
| else | |
| failed = TRUE; | |
| } | |
| } while (!*devices && !failed); | |
| if (!failed) | |
| { | |
| static const WCHAR comW[] = { 'C','O','M',0 }; | |
| LPWSTR ptr; | |
| UINT numSerialPorts = 0; | |
| SerialPortList *list; | |
| for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1) | |
| { | |
| if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1)) | |
| numSerialPorts++; | |
| } | |
| list = HeapAlloc(GetProcessHeap(), 0, sizeof(SerialPortList) + | |
| numSerialPorts ? (numSerialPorts - 1) * sizeof(SerialPortName) : 0); | |
| if (list) | |
| { | |
| list->magic = SETUP_SERIAL_PORT_MAGIC; | |
| list->numPorts = 0; | |
| for (ptr = devices; *ptr; ptr += strlenW(ptr) + 1) | |
| { | |
| if (!strncmpW(comW, ptr, sizeof(comW) / sizeof(comW[0]) - 1)) | |
| { | |
| strncpyW(list->names[list->numPorts].name, ptr, | |
| sizeof(list->names[list->numPorts].name) / | |
| sizeof(list->names[list->numPorts].name[0])); | |
| TRACE("Adding %s to list\n", | |
| debugstr_w(list->names[list->numPorts].name)); | |
| list->numPorts++; | |
| } | |
| } | |
| TRACE("list->numPorts is %d\n", list->numPorts); | |
| } | |
| ret = (HDEVINFO)list; | |
| } | |
| else | |
| ret = (HDEVINFO)INVALID_HANDLE_VALUE; | |
| if (devices != buf) | |
| HeapFree(GetProcessHeap(), 0, devices); | |
| TRACE("returning %p\n", ret); | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * SetupDiGetClassDevsW (SETUPAPI.@) | |
| */ | |
| HDEVINFO WINAPI SetupDiGetClassDevsW( | |
| CONST GUID *class, | |
| LPCWSTR enumstr, | |
| HWND parent, | |
| DWORD flags) | |
| { | |
| HDEVINFO ret = (HDEVINFO)INVALID_HANDLE_VALUE; | |
| TRACE("%s %s %p 0x%08lx\n", debugstr_guid(class), debugstr_w(enumstr), | |
| parent, flags); | |
| if (enumstr) | |
| FIXME(": unimplemented for enumerator strings (%s)\n", | |
| debugstr_w(enumstr)); | |
| else if (flags & DIGCF_ALLCLASSES) | |
| FIXME(": unimplemented for DIGCF_ALLCLASSES\n"); | |
| else | |
| { | |
| if (IsEqualIID(class, &GUID_DEVINTERFACE_COMPORT)) | |
| ret = SETUP_CreateSerialDeviceList(); | |
| else if (IsEqualIID(class, &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR)) | |
| ret = SETUP_CreateSerialDeviceList(); | |
| else | |
| FIXME("(%s): stub\n", debugstr_guid(class)); | |
| } | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * SetupDiEnumDeviceInterfaces (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiEnumDeviceInterfaces( | |
| HDEVINFO DeviceInfoSet, | |
| PSP_DEVINFO_DATA DeviceInfoData, | |
| CONST GUID * InterfaceClassGuid, | |
| DWORD MemberIndex, | |
| PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) | |
| { | |
| BOOL ret = FALSE; | |
| TRACE("%p, %p, %s, 0x%08lx, %p\n", DeviceInfoSet, DeviceInfoData, | |
| debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData); | |
| if (!DeviceInterfaceData) | |
| SetLastError(ERROR_INVALID_PARAMETER); | |
| else if (DeviceInfoData) | |
| FIXME(": unimplemented with PSP_DEVINFO_DATA set\n"); | |
| else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE) | |
| { | |
| /* FIXME: this assumes the only possible enumeration is of serial | |
| * ports. | |
| */ | |
| SerialPortList *list = (SerialPortList *)DeviceInfoSet; | |
| if (list->magic == SETUP_SERIAL_PORT_MAGIC) | |
| { | |
| if (MemberIndex >= list->numPorts) | |
| SetLastError(ERROR_NO_MORE_ITEMS); | |
| else | |
| { | |
| DeviceInterfaceData->cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); | |
| memcpy(&DeviceInterfaceData->InterfaceClassGuid, | |
| &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, | |
| sizeof(DeviceInterfaceData->InterfaceClassGuid)); | |
| DeviceInterfaceData->Flags = 0; | |
| /* Note: this appears to be dangerous, passing a private | |
| * pointer a heap-allocated datum to the caller. However, the | |
| * expected lifetime of the device data is the same as the | |
| * HDEVINFO; once that is closed, the data are no longer valid. | |
| */ | |
| DeviceInterfaceData->Reserved = | |
| (ULONG_PTR)&list->names[MemberIndex].name; | |
| ret = TRUE; | |
| } | |
| } | |
| else | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| } | |
| else | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| return ret; | |
| } | |
| /*********************************************************************** | |
| * SetupDiDestroyDeviceInfoList (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo) | |
| { | |
| BOOL ret = FALSE; | |
| TRACE("%p\n", devinfo); | |
| if (devinfo && devinfo != (HDEVINFO)INVALID_HANDLE_VALUE) | |
| { | |
| /* FIXME: this assumes the only possible enumeration is of serial | |
| * ports. | |
| */ | |
| SerialPortList *list = (SerialPortList *)devinfo; | |
| if (list->magic == SETUP_SERIAL_PORT_MAGIC) | |
| { | |
| HeapFree(GetProcessHeap(), 0, list); | |
| ret = TRUE; | |
| } | |
| else | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| } | |
| else | |
| 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; | |
| TRACE("(%p, %p, %p, %ld, %p, %p)\n", DeviceInfoSet, | |
| DeviceInterfaceData, DeviceInterfaceDetailData, | |
| DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData); | |
| if (!DeviceInterfaceData) | |
| SetLastError(ERROR_INVALID_PARAMETER); | |
| else if ((DeviceInterfaceDetailDataSize && !DeviceInterfaceDetailData) || | |
| (DeviceInterfaceDetailData && !DeviceInterfaceDetailDataSize)) | |
| SetLastError(ERROR_INVALID_PARAMETER); | |
| else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE) | |
| { | |
| /* FIXME: this assumes the only possible enumeration is of serial | |
| * ports. | |
| */ | |
| SerialPortList *list = (SerialPortList *)DeviceInfoSet; | |
| if (list->magic == SETUP_SERIAL_PORT_MAGIC) | |
| { | |
| LPCWSTR devName = (LPCWSTR)DeviceInterfaceData->Reserved; | |
| DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A) + | |
| lstrlenW(devName); | |
| if (sizeRequired > DeviceInterfaceDetailDataSize) | |
| { | |
| SetLastError(ERROR_INSUFFICIENT_BUFFER); | |
| if (RequiredSize) | |
| *RequiredSize = sizeRequired; | |
| } | |
| else | |
| { | |
| LPSTR dst = DeviceInterfaceDetailData->DevicePath; | |
| LPCWSTR src = devName; | |
| /* MSDN claims cbSize must be set by the caller, but it lies */ | |
| DeviceInterfaceDetailData->cbSize = | |
| sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A); | |
| for ( ; *src; src++, dst++) | |
| *dst = *src; | |
| *dst = '\0'; | |
| TRACE("DevicePath is %s\n", | |
| debugstr_a(DeviceInterfaceDetailData->DevicePath)); | |
| if (DeviceInfoData) | |
| { | |
| DeviceInfoData->cbSize = sizeof(SP_DEVINFO_DATA); | |
| memcpy(&DeviceInfoData->ClassGuid, | |
| &GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR, | |
| sizeof(DeviceInfoData->ClassGuid)); | |
| DeviceInfoData->DevInst = 0; | |
| DeviceInfoData->Reserved = (ULONG_PTR)devName; | |
| } | |
| ret = TRUE; | |
| } | |
| } | |
| else | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| } | |
| else | |
| SetLastError(ERROR_INVALID_HANDLE); | |
| TRACE("Returning %d\n", ret); | |
| 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, %ld, %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("%04lx %p %ld %p %p %ld %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); | |
| if (MachineNameW) | |
| MyFree(MachineNameW); | |
| return hKey; | |
| } | |
| /*********************************************************************** | |
| * SetupDiOpenClassRegKeyExW (SETUPAPI.@) | |
| */ | |
| HKEY WINAPI SetupDiOpenClassRegKeyExW( | |
| const GUID* ClassGuid, | |
| REGSAM samDesired, | |
| DWORD Flags, | |
| PCWSTR MachineName, | |
| PVOID Reserved) | |
| { | |
| LPWSTR lpGuidString; | |
| 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 FALSE; | |
| } | |
| if (RegOpenKeyExW(hClassesKey, | |
| lpGuidString, | |
| 0, | |
| KEY_ALL_ACCESS, | |
| &hClassKey)) | |
| { | |
| RpcStringFreeW(&lpGuidString); | |
| RegCloseKey(hClassesKey); | |
| return FALSE; | |
| } | |
| RpcStringFreeW(&lpGuidString); | |
| RegCloseKey(hClassesKey); | |
| return hClassKey; | |
| } | |
| /*********************************************************************** | |
| * SetupDiOpenDeviceInterfaceW (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiOpenDeviceInterfaceW( | |
| HDEVINFO DeviceInfoSet, | |
| PCWSTR DevicePath, | |
| DWORD OpenFlags, | |
| PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) | |
| { | |
| FIXME("%p %s %08lx %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 %08lx %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 %lu\n",DeviceInfoSet, DeviceInfoData, | |
| ClassInstallParams->InstallFunction, ClassInstallParamsSize); | |
| return FALSE; | |
| } | |
| /*********************************************************************** | |
| * SetupDiCallClassInstaller (SETUPAPI.@) | |
| */ | |
| BOOL WINAPI SetupDiCallClassInstaller( | |
| DWORD InstallFunction, | |
| HDEVINFO DeviceInfoSet, | |
| PSP_DEVINFO_DATA DeviceInfoData) | |
| { | |
| FIXME("%ld %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 %ld %ld %ld %lx\n", DeviceInfoSet, DeviceInfoData, | |
| Scope, HwProfile, KeyType, samDesired); | |
| return INVALID_HANDLE_VALUE; | |
| } |