| /* |
| * 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 "rpc.h" |
| #include "rpcdce.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) |
| { |
| FIXME("\n"); |
| return FALSE; |
| } |
| |
| /*********************************************************************** |
| * 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) |
| { |
| FIXME("\n"); |
| return FALSE; |
| } |
| |
| /*********************************************************************** |
| * 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) |
| { |
| FIXME("\n"); |
| return (HDEVINFO)INVALID_HANDLE_VALUE; |
| } |
| |
| /*********************************************************************** |
| * SetupDiCreateDeviceInfoListExW (SETUPAPI.@) |
| */ |
| HDEVINFO WINAPI |
| SetupDiCreateDeviceInfoListExW(const GUID *ClassGuid, |
| HWND hwndParent, |
| PCWSTR MachineName, |
| PVOID Reserved) |
| { |
| FIXME("\n"); |
| return (HDEVINFO)INVALID_HANDLE_VALUE; |
| } |
| |
| /*********************************************************************** |
| * SetupDiDestroyDeviceInfoList (SETUPAPI.@) |
| */ |
| BOOL WINAPI SetupDiDestroyDeviceInfoList(HDEVINFO devinfo) |
| { |
| FIXME("%p\n", devinfo); |
| return FALSE; |
| } |
| |
| /*********************************************************************** |
| * 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; |
| } |
| |
| /*********************************************************************** |
| * SetupDiEnumDeviceInterfaces (SETUPAPI.@) |
| */ |
| BOOL WINAPI SetupDiEnumDeviceInterfaces( |
| HDEVINFO DeviceInfoSet, |
| PSP_DEVINFO_DATA DeviceInfoData, |
| CONST GUID * InterfaceClassGuid, |
| DWORD MemberIndex, |
| PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData) |
| { |
| FIXME("\n"); |
| 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]; |
| OSVERSIONINFOW OsVersionInfo; |
| DWORD dwLength; |
| DWORD dwFullLength; |
| LONG lLineCount = -1; |
| |
| OsVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); |
| if (!GetVersionExW(&OsVersionInfo)) |
| { |
| return FALSE; |
| } |
| |
| 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) |
| { |
| FIXME("%s %s %p %08lx\n",debugstr_guid(class),enumstr,parent,flags); |
| |
| return (HDEVINFO) INVALID_HANDLE_VALUE; |
| } |
| |
| /*********************************************************************** |
| * SetupDiGetClassDevsW (SETUPAPI.@) |
| */ |
| HDEVINFO WINAPI SetupDiGetClassDevsW( |
| CONST GUID *class, |
| LPCWSTR enumstr, |
| HWND parent, |
| DWORD flags) |
| { |
| FIXME("%s %s %p %08lx\n",debugstr_guid(class),debugstr_w(enumstr),parent,flags); |
| |
| return (HDEVINFO) INVALID_HANDLE_VALUE; |
| } |
| |
| /*********************************************************************** |
| * 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) |
| { |
| FIXME("\n"); |
| return FALSE; |
| } |
| |
| /*********************************************************************** |
| * 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("\n"); |
| 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) |
| { |
| FIXME("\n"); |
| return INVALID_HANDLE_VALUE; |
| } |
| |
| |
| /*********************************************************************** |
| * 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; |
| } |
| |
| /*********************************************************************** |
| * SetupDiOpenDeviceInterfaceA (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; |
| } |