Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648/* * SetupAPI interface-related functions * * Copyright 2000 Andreas Mohr for CodeWeavers * 2005-2006 Herv� Poussineau (hpoussin@reactos.org) * * 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 "setupapi_private.h"
/* Unicode constants */static const WCHAR AddInterface[] = {'A','d','d','I','n','t','e','r','f','a','c','e',0};static const WCHAR ClassGUID[] = {'C','l','a','s','s','G','U','I','D',0};static const WCHAR Control[] = {'C','o','n','t','r','o','l',0};static const WCHAR DeviceInstance[] = {'D','e','v','i','c','e','I','n','s','t','a','n','c','e',0};static const WCHAR DotInterfaces[] = {'.','I','n','t','e','r','f','a','c','e','s',0};static const WCHAR Linked[] = {'L','i','n','k','e','d',0};static const WCHAR SymbolicLink[] = {'S','y','m','b','o','l','i','c','L','i','n','k',0};
static BOOLCreateDeviceInterface( IN struct DeviceInfo* deviceInfo, IN LPCWSTR SymbolicLink, IN LPCGUID pInterfaceGuid, OUT struct DeviceInterface **pDeviceInterface){ struct DeviceInterface *deviceInterface;
*pDeviceInterface = NULL;
deviceInterface = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(struct DeviceInterface, SymbolicLink) + (strlenW(SymbolicLink) + 1) * sizeof(WCHAR)); if (!deviceInterface) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } deviceInterface->DeviceInfo = deviceInfo; strcpyW(deviceInterface->SymbolicLink, SymbolicLink); deviceInterface->Flags = 0; /* Flags will be updated later */ memcpy(&deviceInterface->InterfaceClassGuid, pInterfaceGuid, sizeof(GUID));
*pDeviceInterface = deviceInterface; return TRUE;}
BOOLDestroyDeviceInterface( struct DeviceInterface* deviceInterface){ return HeapFree(GetProcessHeap(), 0, deviceInterface);}
LONGSETUP_CreateInterfaceList( struct DeviceInfoSet *list, PCWSTR MachineName, CONST GUID *InterfaceGuid, PCWSTR DeviceInstanceW /* OPTIONAL */, BOOL OnlyPresentInterfaces){ HKEY hInterfaceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID} */ HKEY hDeviceInstanceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath} */ HKEY hReferenceKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString} */ HKEY hControlKey; /* HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{GUID}\##?#{InstancePath}\#{ReferenceString}\Control */ HKEY hEnumKey; /* HKLM\SYSTEM\CurrentControlSet\Enum */ HKEY hKey; /* HKLM\SYSTEM\CurrentControlSet\Enum\{Instance\Path} */ LONG rc; WCHAR KeyBuffer[max(MAX_PATH, MAX_GUID_STRING_LEN) + 1]; PWSTR pSymbolicLink = NULL; PWSTR InstancePath = NULL; DWORD i, j; DWORD dwLength, dwInstancePathLength; DWORD dwRegType; DWORD LinkedValue; GUID ClassGuid; struct DeviceInfo *deviceInfo;
hInterfaceKey = INVALID_HANDLE_VALUE; hDeviceInstanceKey = NULL; hReferenceKey = NULL;
/* Open registry key related to this interface */ hInterfaceKey = SetupDiOpenClassRegKeyExW(InterfaceGuid, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, MachineName, NULL); if (hInterfaceKey == INVALID_HANDLE_VALUE) { /* Key doesn't exist. Let's keep it empty */ rc = ERROR_SUCCESS; goto cleanup; }
/* Enumerate sub keys of hInterfaceKey */ i = 0; while (TRUE) { dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); rc = RegEnumKeyExW(hInterfaceKey, i, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); if (rc == ERROR_NO_MORE_ITEMS) break; if (rc != ERROR_SUCCESS) goto cleanup; i++;
/* Open sub key */ if (hDeviceInstanceKey != NULL) RegCloseKey(hDeviceInstanceKey); rc = RegOpenKeyExW(hInterfaceKey, KeyBuffer, 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &hDeviceInstanceKey); if (rc != ERROR_SUCCESS) goto cleanup;
/* Read DeviceInstance */ rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, &dwRegType, NULL, &dwInstancePathLength); if (rc != ERROR_SUCCESS) goto cleanup; if (dwRegType != REG_SZ) { rc = ERROR_GEN_FAILURE; goto cleanup; } HeapFree(GetProcessHeap(), 0, InstancePath); InstancePath = HeapAlloc(GetProcessHeap(), 0, dwInstancePathLength + sizeof(WCHAR)); if (!InstancePath) { rc = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } rc = RegQueryValueExW(hDeviceInstanceKey, DeviceInstance, NULL, NULL, (LPBYTE)InstancePath, &dwInstancePathLength); if (rc != ERROR_SUCCESS) goto cleanup; InstancePath[dwInstancePathLength / sizeof(WCHAR)] = '\0'; TRACE("DeviceInstance %s\n", debugstr_w(InstancePath));
if (DeviceInstanceW) { /* Check if device enumerator is not the right one */ if (strcmpW(DeviceInstanceW, InstancePath) != 0) continue; }
/* Find class GUID associated to the device instance */ rc = RegOpenKeyExW( list->HKLM, REGSTR_PATH_SYSTEMENUM, 0, /* Options */ READ_CONTROL, &hEnumKey); if (rc != ERROR_SUCCESS) goto cleanup; rc = RegOpenKeyExW( hEnumKey, InstancePath, 0, /* Options */ KEY_QUERY_VALUE, &hKey); RegCloseKey(hEnumKey); if (rc != ERROR_SUCCESS) goto cleanup; dwLength = sizeof(KeyBuffer) - sizeof(WCHAR); rc = RegQueryValueExW(hKey, ClassGUID, NULL, NULL, (LPBYTE)KeyBuffer, &dwLength); RegCloseKey(hKey); if (rc != ERROR_SUCCESS) goto cleanup; KeyBuffer[dwLength / sizeof(WCHAR)] = '\0'; KeyBuffer[37] = '\0'; /* Replace the } by a NULL character */ if (UuidFromStringW(&KeyBuffer[1], &ClassGuid) != RPC_S_OK) { rc = ERROR_GEN_FAILURE; goto cleanup; } TRACE("ClassGUID %s\n", debugstr_guid(&ClassGuid));
/* If current device doesn't match the list GUID (if any), skip this entry */ if (!IsEqualIID(&list->ClassGuid, &GUID_NULL) && !IsEqualIID(&list->ClassGuid, &ClassGuid)) continue;
/* Enumerate subkeys of hDeviceInstanceKey (ie "#ReferenceString" in IoRegisterDeviceInterface). Skip entries that don't start with '#' */ j = 0; while (TRUE) { struct DeviceInterface *interfaceInfo;
dwLength = sizeof(KeyBuffer) / sizeof(KeyBuffer[0]); rc = RegEnumKeyExW(hDeviceInstanceKey, j, KeyBuffer, &dwLength, NULL, NULL, NULL, NULL); if (rc == ERROR_NO_MORE_ITEMS) break; if (rc != ERROR_SUCCESS) goto cleanup; j++; if (KeyBuffer[0] != '#') /* This entry doesn't represent an interesting entry */ continue;
/* Open sub key */ if (hReferenceKey != NULL) RegCloseKey(hReferenceKey); rc = RegOpenKeyExW(hDeviceInstanceKey, KeyBuffer, 0, KEY_QUERY_VALUE, &hReferenceKey); if (rc != ERROR_SUCCESS) goto cleanup;
/* Read SymbolicLink value */ rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, &dwRegType, NULL, &dwLength); if (rc != ERROR_SUCCESS) { /* Skip device interface with invalid reference value (i.e. interface not actually available for this device) */ RegCloseKey(hReferenceKey); continue; } if (dwRegType != REG_SZ) { rc = ERROR_GEN_FAILURE; goto cleanup; }
/* We have found a device */ /* Step 1. Create a device info element */ if (!CreateDeviceInfo(list, InstancePath, &ClassGuid, &deviceInfo)) { rc = GetLastError(); goto cleanup; } TRACE("Adding device %s to list\n", debugstr_w(InstancePath)); InsertTailList(&list->ListHead, &deviceInfo->ListEntry);
/* Step 2. Create an interface list for this element */ HeapFree(GetProcessHeap(), 0, pSymbolicLink); pSymbolicLink = HeapAlloc(GetProcessHeap(), 0, dwLength + sizeof(WCHAR)); if (!pSymbolicLink) { rc = ERROR_NOT_ENOUGH_MEMORY; goto cleanup; } rc = RegQueryValueExW(hReferenceKey, SymbolicLink, NULL, NULL, (LPBYTE)pSymbolicLink, &dwLength); pSymbolicLink[dwLength / sizeof(WCHAR)] = '\0'; if (rc != ERROR_SUCCESS) goto cleanup; if (!CreateDeviceInterface(deviceInfo, pSymbolicLink, InterfaceGuid, &interfaceInfo)) { rc = GetLastError(); goto cleanup; }
/* Step 3. Update flags */ if (KeyBuffer[1] == '\0') interfaceInfo->Flags |= SPINT_DEFAULT; rc = RegOpenKeyExW(hReferenceKey, Control, 0, KEY_QUERY_VALUE, &hControlKey); if (rc != ERROR_SUCCESS) {#if 0 if (OnlyPresentInterfaces) { DestroyDeviceInterface(interfaceInfo); continue; } else interfaceInfo->Flags |= SPINT_REMOVED;#endif } else { dwLength = sizeof(DWORD); if (RegQueryValueExW(hControlKey, Linked, NULL, &dwRegType, (LPBYTE)&LinkedValue, &dwLength) == ERROR_SUCCESS && dwRegType == REG_DWORD && LinkedValue) interfaceInfo->Flags |= SPINT_ACTIVE; RegCloseKey(hControlKey); }
TRACE("Adding interface %s to list\n", debugstr_w(pSymbolicLink)); InsertTailList(&deviceInfo->InterfaceListHead, &interfaceInfo->ListEntry); } } rc = ERROR_SUCCESS;
cleanup: if (hReferenceKey != NULL) RegCloseKey(hReferenceKey); if (hDeviceInstanceKey != NULL) RegCloseKey(hDeviceInstanceKey); if (hInterfaceKey != INVALID_HANDLE_VALUE) RegCloseKey(hInterfaceKey); HeapFree(GetProcessHeap(), 0, InstancePath); HeapFree(GetProcessHeap(), 0, pSymbolicLink); return rc;}
static LPWSTRCreateSymbolicLink( IN LPGUID InterfaceGuid, IN LPCWSTR ReferenceString, IN struct DeviceInfo *devInfo){ DWORD Length, Index, Offset; LPWSTR Key;
Length = wcslen(devInfo->instanceId) + 4 /* prepend ##?# */ + 41 /* #{GUID} + */ + 1 /* zero byte */;
Key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length * sizeof(WCHAR)); if (!Key) return NULL;
wcscpy(Key, L"##?#"); wcscat(Key, devInfo->instanceId);
for(Index = 4; Index < Length; Index++) { if (Key[Index] == L'\\') { Key[Index] = L'#'; } }
wcscat(Key, L"#");
Offset = wcslen(Key); pSetupStringFromGuid(InterfaceGuid, Key + Offset, Length - Offset);
return Key;}
static BOOLInstallOneInterface( IN LPGUID InterfaceGuid, IN LPCWSTR ReferenceString, IN LPCWSTR InterfaceSection, IN UINT InterfaceFlags, IN HINF hInf, IN HDEVINFO DeviceInfoSet, IN struct DeviceInfo *devInfo){ HKEY hKey, hRefKey; LPWSTR Path; SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; struct DeviceInterface *DevItf = NULL;
if (InterfaceFlags != 0) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; }
TRACE("Need to InstallOneInterface(%s %s %s %u) hInf %p DeviceInfoSet %p devInfo %p instanceId %s\n", debugstr_guid(InterfaceGuid), debugstr_w(ReferenceString), debugstr_w(InterfaceSection), InterfaceFlags, hInf, DeviceInfoSet, devInfo, debugstr_w(devInfo->instanceId));
Path = CreateSymbolicLink(InterfaceGuid, ReferenceString, devInfo); if (!Path) return FALSE;
CreateDeviceInterface(devInfo, Path, InterfaceGuid, &DevItf); HeapFree(GetProcessHeap(), 0, Path); if (!DevItf) { return FALSE; }
memcpy(&DeviceInterfaceData.InterfaceClassGuid, &DevItf->InterfaceClassGuid, sizeof(GUID)); DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); DeviceInterfaceData.Flags = DevItf->Flags; DeviceInterfaceData.Reserved = (ULONG_PTR)DevItf;
hKey = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet, &DeviceInterfaceData, 0, KEY_ALL_ACCESS, NULL, 0); HeapFree(GetProcessHeap(), 0, DevItf); if (hKey == INVALID_HANDLE_VALUE) { return FALSE; }
if (ReferenceString) { Path = HeapAlloc(GetProcessHeap(), 0, (wcslen(ReferenceString) + 2) * sizeof(WCHAR)); if (!Path) { RegCloseKey(hKey); return FALSE; }
wcscpy(Path, L"#"); wcscat(Path, ReferenceString);
if (RegCreateKeyExW(hKey, Path, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hRefKey, NULL) != ERROR_SUCCESS) { ERR("failed to create key %s %lx\n", debugstr_w(Path), GetLastError()); HeapFree(GetProcessHeap(), 0, Path); return FALSE; }
RegCloseKey(hKey); hKey = hRefKey; HeapFree(GetProcessHeap(), 0, Path); }
if (RegCreateKeyExW(hKey, L"Device Parameters", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hRefKey, NULL) != ERROR_SUCCESS) { RegCloseKey(hKey); return FALSE; }
return SetupInstallFromInfSectionW(NULL, /* FIXME */ hInf, InterfaceSection, SPINST_REGISTRY, hRefKey, NULL, 0, NULL, NULL, NULL, NULL);}
/*********************************************************************** * SetupDiInstallDeviceInterfaces (SETUPAPI.@) */BOOL WINAPISetupDiInstallDeviceInterfaces( IN HDEVINFO DeviceInfoSet, IN PSP_DEVINFO_DATA DeviceInfoData){ struct DeviceInfoSet *list = NULL; BOOL ret = FALSE;
TRACE("%p %p\n", DeviceInfoSet, DeviceInfoData);
if (!DeviceInfoSet) SetLastError(ERROR_INVALID_PARAMETER); else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) SetLastError(ERROR_INVALID_HANDLE); else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) SetLastError(ERROR_INVALID_HANDLE); else if (!DeviceInfoData) SetLastError(ERROR_INVALID_PARAMETER); else if (DeviceInfoData && DeviceInfoData->Reserved == 0) SetLastError(ERROR_INVALID_USER_BUFFER); else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA)) SetLastError(ERROR_INVALID_USER_BUFFER); else { struct DeviceInfo *devInfo; struct DriverInfoElement *SelectedDriver = NULL; SP_DEVINSTALL_PARAMS_W InstallParams; WCHAR SectionName[MAX_PATH]; DWORD SectionNameLength = 0; INFCONTEXT ContextInterface; LPWSTR InterfaceGuidString = NULL; LPWSTR ReferenceString = NULL; LPWSTR InterfaceSection = NULL; INT InterfaceFlags; GUID InterfaceGuid; BOOL Result;
devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W); Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams); if (!Result) goto cleanup;
SelectedDriver = (struct DriverInfoElement *)InstallParams.ClassInstallReserved; if (SelectedDriver == NULL) { SetLastError(ERROR_NO_DRIVER_SELECTED); ret = FALSE; goto cleanup; }
/* Get .Interfaces section name */ Result = SetupDiGetActualSectionToInstallW( SelectedDriver->InfFileDetails->hInf, SelectedDriver->Details.SectionName, SectionName, MAX_PATH, &SectionNameLength, NULL); if (!Result || SectionNameLength > MAX_PATH - strlenW(DotInterfaces) - 1) goto cleanup; strcatW(SectionName, DotInterfaces);
ret = TRUE; Result = SetupFindFirstLineW( SelectedDriver->InfFileDetails->hInf, SectionName, AddInterface, &ContextInterface); while (ret && Result) { ret = GetStringField(&ContextInterface, 1, &InterfaceGuidString); if (!ret) goto cleanup; else if (strlenW(InterfaceGuidString) != MAX_GUID_STRING_LEN - 1) { SetLastError(ERROR_INVALID_PARAMETER); ret = FALSE; goto cleanup; }
InterfaceGuidString[MAX_GUID_STRING_LEN - 2] = '\0'; /* Replace the } by a NULL character */ if (UuidFromStringW(&InterfaceGuidString[1], &InterfaceGuid) != RPC_S_OK) { /* Bad GUID, skip the entry */ SetLastError(ERROR_INVALID_PARAMETER); ret = FALSE; goto cleanup; }
ret = GetStringField(&ContextInterface, 2, &ReferenceString); if (!ret) goto cleanup;
ret = GetStringField(&ContextInterface, 3, &InterfaceSection); if (!ret) { /* ReferenceString is optional */ InterfaceSection = ReferenceString; ReferenceString = NULL; }
ret = SetupGetIntField( &ContextInterface, (ReferenceString ? 4 : 3), /* Field index */ &InterfaceFlags); if (!ret) { if (GetLastError() == ERROR_INVALID_PARAMETER) { /* The field may be empty. Ignore the error */ InterfaceFlags = 0; ret = TRUE; } else goto cleanup; }
/* Install Interface */ ret = InstallOneInterface(&InterfaceGuid, ReferenceString, InterfaceSection, InterfaceFlags, SelectedDriver->InfFileDetails->hInf, DeviceInfoSet, devInfo);
cleanup: MyFree(InterfaceGuidString); if (ReferenceString) MyFree(ReferenceString); MyFree(InterfaceSection); InterfaceGuidString = ReferenceString = InterfaceSection = NULL; Result = SetupFindNextMatchLineW(&ContextInterface, AddInterface, &ContextInterface); } }
TRACE("Returning %d\n", ret); return ret;}
HKEY WINAPISetupDiOpenDeviceInterfaceRegKey( IN HDEVINFO DeviceInfoSet, IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData, IN DWORD Reserved, IN REGSAM samDesired){ HKEY hKey = INVALID_HANDLE_VALUE, hDevKey; struct DeviceInfoSet * list;
TRACE("%p %p %p 0x%08x 0x%08x)\n", DeviceInfoSet, DeviceInterfaceData, Reserved, samDesired);
if (!DeviceInfoSet) SetLastError(ERROR_INVALID_PARAMETER); else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE) SetLastError(ERROR_INVALID_HANDLE); else if ((list = (struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC) SetLastError(ERROR_INVALID_HANDLE); else if (!DeviceInterfaceData) SetLastError(ERROR_INVALID_PARAMETER); else if (DeviceInterfaceData && DeviceInterfaceData->Reserved == 0) SetLastError(ERROR_INVALID_USER_BUFFER); else if (DeviceInterfaceData && DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA)) SetLastError(ERROR_INVALID_USER_BUFFER); else { struct DeviceInterface *DevItf; LPWSTR Path, Guid, Slash; DWORD Length; DevItf = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
Length = wcslen(DevItf->SymbolicLink);
Path = HeapAlloc(GetProcessHeap(), 0, (Length+2) * sizeof(WCHAR)); if (!Path) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return INVALID_HANDLE_VALUE; }
wcscpy(Path, DevItf->SymbolicLink);
Guid = wcsrchr(Path, '}'); Slash = wcsrchr(Path, '\\'); if (!Guid || !Slash) { HeapFree(GetProcessHeap(), 0, Path); SetLastError(ERROR_INVALID_PARAMETER); return INVALID_HANDLE_VALUE; }
if ((ULONG_PTR)Slash > (ULONG_PTR)Guid) { /* Create an extra slash */ memmove(Slash+1, Slash, (wcslen(Slash) + 1) * sizeof(WCHAR)); Slash[1] = L'#'; }
Guid = Path; while((ULONG_PTR)Guid < (ULONG_PTR)Slash) { if (*Guid == L'\\') *Guid = L'#';
Guid++; }
hKey = SetupDiOpenClassRegKeyExW(&DeviceInterfaceData->InterfaceClassGuid, samDesired, DIOCR_INTERFACE, NULL, NULL); if (hKey != INVALID_HANDLE_VALUE) { if (RegOpenKeyExW(hKey, Path, 0, samDesired, &hDevKey) == ERROR_SUCCESS) { RegCloseKey(hKey); hKey = hDevKey; } else { RegCloseKey(hKey); hKey = INVALID_HANDLE_VALUE; } }
HeapFree(GetProcessHeap(), 0, Path); }
return hKey;}
/*********************************************************************** * SetupDiDeleteDeviceInterfaceData (SETUPAPI.@) */BOOLWINAPISetupDiDeleteDeviceInterfaceData( HDEVINFO DeviceInfoSet, PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData){ FIXME("SetupDiDeleteDeviceInterfaceData(%p %p) stub\n", DeviceInfoSet, DeviceInterfaceData); return TRUE;}