[SETUPAPI]
[reactos.git] / reactos / dll / win32 / setupapi / interface.c
index b08b6fd..1d20709 100644 (file)
@@ -255,6 +255,7 @@ SETUP_CreateInterfaceList(
             rc = RegOpenKeyExW(hReferenceKey, Control, 0, KEY_QUERY_VALUE, &hControlKey);
             if (rc != ERROR_SUCCESS)
             {
+#if 0
                 if (OnlyPresentInterfaces)
                 {
                     DestroyDeviceInterface(interfaceInfo);
@@ -262,11 +263,12 @@ SETUP_CreateInterfaceList(
                 }
                 else
                     interfaceInfo->Flags |= SPINT_REMOVED;
+#endif
             }
             else
             {
                 dwLength = sizeof(DWORD);
-                if (RegQueryValueExW(hControlKey, Linked, NULL, &dwRegType, (LPBYTE)&LinkedValue, &dwLength)
+                if (RegQueryValueExW(hControlKey, Linked, NULL, &dwRegType, (LPBYTE)&LinkedValue, &dwLength) == ERROR_SUCCESS
                     && dwRegType == REG_DWORD && LinkedValue)
                     interfaceInfo->Flags |= SPINT_ACTIVE;
                 RegCloseKey(hControlKey);
@@ -290,276 +292,114 @@ cleanup:
     return rc;
 }
 
-/***********************************************************************
- *             SetupDiEnumDeviceInterfaces (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiEnumDeviceInterfaces(
-    IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL,
-    IN CONST GUID *InterfaceClassGuid,
-    IN DWORD MemberIndex,
-    OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData)
+static LPWSTR
+CreateSymbolicLink(
+    IN LPGUID InterfaceGuid,
+    IN LPCWSTR ReferenceString,
+    IN struct DeviceInfo *devInfo)
 {
-    BOOL ret = FALSE;
-
-    TRACE("%p, %p, %s, %ld, %p\n", DeviceInfoSet, DeviceInfoData,
-     debugstr_guid(InterfaceClassGuid), MemberIndex, DeviceInterfaceData);
+    DWORD Length, Index, Offset;
+    LPWSTR Key;
 
-    if (!DeviceInterfaceData)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (DeviceInfoSet && DeviceInfoSet != (HDEVINFO)INVALID_HANDLE_VALUE)
-    {
-        struct DeviceInfoSet *list = (struct DeviceInfoSet *)DeviceInfoSet;
-
-        if (list->magic == SETUP_DEVICE_INFO_SET_MAGIC)
-        {
-            PLIST_ENTRY ItemList = list->ListHead.Flink;
-            BOOL Found = FALSE;
-            while (ItemList != &list->ListHead && !Found)
-            {
-                PLIST_ENTRY InterfaceListEntry;
-                struct DeviceInfo *DevInfo = CONTAINING_RECORD(ItemList, struct DeviceInfo, ListEntry);
-                if (DeviceInfoData && (struct DeviceInfo *)DeviceInfoData->Reserved != DevInfo)
-                {
-                    /* We are not searching for this element */
-                    ItemList = ItemList->Flink;
-                    continue;
-                }
-                InterfaceListEntry = DevInfo->InterfaceListHead.Flink;
-                while (InterfaceListEntry != &DevInfo->InterfaceListHead && !Found)
-                {
-                    struct DeviceInterface *DevItf = CONTAINING_RECORD(InterfaceListEntry, struct DeviceInterface, ListEntry);
-                    if (!IsEqualIID(&DevItf->InterfaceClassGuid, InterfaceClassGuid))
-                    {
-                        InterfaceListEntry = InterfaceListEntry->Flink;
-                        continue;
-                    }
-                    if (MemberIndex-- == 0)
-                    {
-                        /* return this item */
-                        memcpy(&DeviceInterfaceData->InterfaceClassGuid,
-                            &DevItf->InterfaceClassGuid,
-                            sizeof(GUID));
-                        DeviceInterfaceData->Flags = DevItf->Flags;
-                        DeviceInterfaceData->Reserved = (ULONG_PTR)DevItf;
-                        Found = TRUE;
-                    }
-                    InterfaceListEntry = InterfaceListEntry->Flink;
-                }
-                ItemList = ItemList->Flink;
-            }
-            if (!Found)
-                SetLastError(ERROR_NO_MORE_ITEMS);
-            else
-                ret = TRUE;
-        }
-        else
-            SetLastError(ERROR_INVALID_HANDLE);
-    }
-    else
-        SetLastError(ERROR_INVALID_HANDLE);
-    return ret;
-}
+    Length = wcslen(devInfo->instanceId) + 4 /* prepend ##?# */ + 41 /* #{GUID} + */ + 1 /* zero byte */;
 
-/***********************************************************************
- *             SetupDiGetDeviceInterfaceDetailW (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiGetDeviceInterfaceDetailW(
-    IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
-    OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData OPTIONAL,
-    IN DWORD DeviceInterfaceDetailDataSize,
-    OUT PDWORD RequiredSize OPTIONAL,
-    OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
-{
-    BOOL ret = FALSE;
+    Key = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length * sizeof(WCHAR));
+    if (!Key)
+        return NULL;
 
-    TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
-        DeviceInterfaceData, DeviceInterfaceDetailData,
-        DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
+    wcscpy(Key, L"##?#");
+    wcscat(Key, devInfo->instanceId);
 
-    if (!DeviceInfoSet || !DeviceInterfaceData)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInfoSet == (HDEVINFO)INVALID_HANDLE_VALUE)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if (((struct DeviceInfoSet *)DeviceInfoSet)->magic != SETUP_DEVICE_INFO_SET_MAGIC)
-        SetLastError(ERROR_INVALID_HANDLE);
-    else if (DeviceInterfaceData->cbSize != sizeof(SP_DEVICE_INTERFACE_DATA))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (DeviceInfoData && DeviceInfoData->cbSize != sizeof(SP_DEVINFO_DATA))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath) + sizeof(WCHAR))
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else
+    for(Index = 4; Index < Length; Index++)
     {
-        struct DeviceInterface *deviceInterface = (struct DeviceInterface *)DeviceInterfaceData->Reserved;
-        LPCWSTR devName = deviceInterface->SymbolicLink;
-        DWORD sizeRequired = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) +
-            (lstrlenW(devName) + 1) * sizeof(WCHAR);
-
-        if (sizeRequired > DeviceInterfaceDetailDataSize)
+        if (Key[Index] == L'\\')
         {
-            SetLastError(ERROR_INSUFFICIENT_BUFFER);
-            if (RequiredSize)
-                *RequiredSize = sizeRequired;
-        }
-        else
-        {
-            strcpyW(DeviceInterfaceDetailData->DevicePath, devName);
-            TRACE("DevicePath is %s\n", debugstr_w(DeviceInterfaceDetailData->DevicePath));
-            if (DeviceInfoData)
-            {
-                memcpy(&DeviceInfoData->ClassGuid,
-                    &deviceInterface->DeviceInfo->ClassGuid,
-                    sizeof(GUID));
-                DeviceInfoData->DevInst = deviceInterface->DeviceInfo->dnDevInst;
-                DeviceInfoData->Reserved = (ULONG_PTR)deviceInterface->DeviceInfo;
-            }
-            ret = TRUE;
+            Key[Index] = L'#';
         }
     }
 
-    TRACE("Returning %d\n", ret);
-    return ret;
+    wcscat(Key, L"#");
+
+    Offset = wcslen(Key);
+    pSetupStringFromGuid(InterfaceGuid, Key + Offset, Length - Offset);
+
+    return Key;
 }
 
-/***********************************************************************
- *             SetupDiGetDeviceInterfaceDetailA (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiGetDeviceInterfaceDetailA(
+
+static BOOL
+InstallOneInterface(
+    IN LPGUID InterfaceGuid,
+    IN LPCWSTR ReferenceString,
+    IN LPCWSTR InterfaceSection,
+    IN UINT InterfaceFlags,
+    IN HINF hInf,
     IN HDEVINFO DeviceInfoSet,
-    IN PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
-    OUT PSP_DEVICE_INTERFACE_DETAIL_DATA_A DeviceInterfaceDetailData OPTIONAL,
-    IN DWORD DeviceInterfaceDetailDataSize,
-    OUT PDWORD RequiredSize OPTIONAL,
-    OUT PSP_DEVINFO_DATA DeviceInfoData OPTIONAL)
+    IN struct DeviceInfo *devInfo)
 {
-    PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailDataW = NULL;
-    DWORD sizeW = 0, sizeA;
-    BOOL ret = FALSE;
+    HKEY hKey, hRefKey;
+    LPWSTR Path;
+    SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
+    struct DeviceInterface *DevItf = NULL;
 
-    TRACE("%p %p %p %lu %p %p\n", DeviceInfoSet,
-        DeviceInterfaceData, DeviceInterfaceDetailData,
-        DeviceInterfaceDetailDataSize, RequiredSize, DeviceInfoData);
-
-    if (DeviceInterfaceDetailData->cbSize != sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_A))
-        SetLastError(ERROR_INVALID_USER_BUFFER);
-    else if (DeviceInterfaceDetailData == NULL && DeviceInterfaceDetailDataSize != 0)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else if (DeviceInterfaceDetailData != NULL && DeviceInterfaceDetailDataSize < FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath) + 1)
-        SetLastError(ERROR_INVALID_PARAMETER);
-    else
+    if (InterfaceFlags != 0)
     {
-        if (DeviceInterfaceDetailData != NULL)
-        {
-            sizeW = FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)
-                + (DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath)) * sizeof(WCHAR);
-            DeviceInterfaceDetailDataW = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, sizeW);
-            if (!DeviceInterfaceDetailDataW)
-            {
-                SetLastError(ERROR_NOT_ENOUGH_MEMORY);
-            }
-        }
-        if (!DeviceInterfaceDetailData || (DeviceInterfaceDetailData && DeviceInterfaceDetailDataW))
-        {
-            DeviceInterfaceDetailDataW->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
-            ret = SetupDiGetDeviceInterfaceDetailW(
-                DeviceInfoSet,
-                DeviceInterfaceData,
-                DeviceInterfaceDetailDataW,
-                sizeW,
-                &sizeW,
-                DeviceInfoData);
-            sizeA = (sizeW - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath)) / sizeof(WCHAR)
-                + FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath);
-            if (RequiredSize)
-                *RequiredSize = sizeA;
-            if (ret && DeviceInterfaceDetailData && DeviceInterfaceDetailDataSize <= sizeA)
-            {
-                if (!WideCharToMultiByte(
-                    CP_ACP, 0,
-                    DeviceInterfaceDetailDataW->DevicePath, -1,
-                    DeviceInterfaceDetailData->DevicePath, DeviceInterfaceDetailDataSize - FIELD_OFFSET(SP_DEVICE_INTERFACE_DETAIL_DATA_A, DevicePath),
-                    NULL, NULL))
-                {
-                    ret = FALSE;
-                }
-            }
-        }
-        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailDataW);
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
     }
 
-    TRACE("Returning %d\n", ret);
-    return ret;
-}
+    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));
 
-/***********************************************************************
- *             SetupDiOpenDeviceInterfaceA (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiOpenDeviceInterfaceA(
-    IN HDEVINFO DeviceInfoSet,
-    IN PCSTR DevicePath,
-    IN DWORD OpenFlags,
-    OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL)
-{
-    LPWSTR DevicePathW = NULL;
-    BOOL bResult;
 
-    TRACE("%p %s %08lx %p\n", DeviceInfoSet, debugstr_a(DevicePath), OpenFlags, DeviceInterfaceData);
+    Path = CreateSymbolicLink(InterfaceGuid, ReferenceString, devInfo);
+    if (!Path)
+        return FALSE;
 
-    DevicePathW = MultiByteToUnicode(DevicePath, CP_ACP);
-    if (DevicePathW == NULL)
+    CreateDeviceInterface(devInfo, Path, InterfaceGuid, &DevItf);
+    HeapFree(GetProcessHeap(), 0, Path);
+    if (!DevItf)
+    {
         return FALSE;
+    }
 
-    bResult = SetupDiOpenDeviceInterfaceW(DeviceInfoSet,
-        DevicePathW, OpenFlags, DeviceInterfaceData);
+    memcpy(&DeviceInterfaceData.InterfaceClassGuid, &DevItf->InterfaceClassGuid, sizeof(GUID));
+    DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+    DeviceInterfaceData.Flags = DevItf->Flags;
+    DeviceInterfaceData.Reserved = (ULONG_PTR)DevItf;
 
-    MyFree(DevicePathW);
+    hKey = SetupDiCreateDeviceInterfaceRegKeyW(DeviceInfoSet, &DeviceInterfaceData, 0, KEY_ALL_ACCESS, NULL, 0);
+    HeapFree(GetProcessHeap(), 0, DevItf);
+    if (hKey == INVALID_HANDLE_VALUE)
+    {
+        return FALSE;
+    }
 
-    return bResult;
-}
+    if (ReferenceString)
+    {
+        Path = HeapAlloc(GetProcessHeap(), 0, (wcslen(ReferenceString) + 2) * sizeof(WCHAR));
+        if (!Path)
+        {
+            RegCloseKey(hKey);
+            return FALSE;
+        }
 
-/***********************************************************************
- *             SetupDiOpenDeviceInterfaceW (SETUPAPI.@)
- */
-BOOL WINAPI
-SetupDiOpenDeviceInterfaceW(
-    IN HDEVINFO DeviceInfoSet,
-    IN PCWSTR DevicePath,
-    IN DWORD OpenFlags,
-    OUT PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData OPTIONAL)
-{
-    FIXME("%p %s %08lx %p\n",
-        DeviceInfoSet, debugstr_w(DevicePath), OpenFlags, DeviceInterfaceData);
-    return FALSE;
-}
+        wcscpy(Path, L"#");
+        wcscat(Path, ReferenceString);
 
-static BOOL
-InstallOneInterface(
-    IN LPGUID InterfaceGuid,
-    IN LPCWSTR ReferenceString,
-    IN LPCWSTR InterfaceSection,
-    IN UINT InterfaceFlags)
-{
-    if (InterfaceFlags != 0)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
+        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);
     }
 
-    FIXME("Need to InstallOneInterface(%s %s %s %u)\n", debugstr_guid(InterfaceGuid),
-        debugstr_w(ReferenceString), debugstr_w(InterfaceSection), InterfaceFlags);
-    return TRUE;
+    return SetupInstallFromInfSectionW(NULL, /* FIXME */ hInf, InterfaceSection, SPINST_REGISTRY, hKey, NULL, 0, NULL, NULL, NULL, NULL);
 }
 
 /***********************************************************************
@@ -583,11 +423,14 @@ SetupDiInstallDeviceInterfaces(
         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 DriverInfoElement *SelectedDriver;
+        struct DeviceInfo *devInfo;
+        struct DriverInfoElement *SelectedDriver = NULL;
         SP_DEVINSTALL_PARAMS_W InstallParams;
         WCHAR SectionName[MAX_PATH];
         DWORD SectionNameLength = 0;
@@ -599,6 +442,8 @@ SetupDiInstallDeviceInterfaces(
         GUID InterfaceGuid;
         BOOL Result;
 
+        devInfo = (struct DeviceInfo *)DeviceInfoData->Reserved;
+
         InstallParams.cbSize = sizeof(SP_DEVINSTALL_PARAMS_W);
         Result = SetupDiGetDeviceInstallParamsW(DeviceInfoSet, DeviceInfoData, &InstallParams);
         if (!Result)
@@ -654,11 +499,15 @@ SetupDiInstallDeviceInterfaces(
 
             ret = GetStringField(&ContextInterface, 3, &InterfaceSection);
             if (!ret)
-                goto cleanup;
+            {
+                /* ReferenceString is optional */
+                InterfaceSection = ReferenceString;
+                ReferenceString = NULL;
+            }
 
             ret = SetupGetIntField(
                 &ContextInterface,
-                4, /* Field index */
+                (ReferenceString ? 4 : 3), /* Field index */
                 &InterfaceFlags);
             if (!ret)
             {
@@ -673,11 +522,12 @@ SetupDiInstallDeviceInterfaces(
             }
 
             /* Install Interface */
-            ret = InstallOneInterface(&InterfaceGuid, ReferenceString, InterfaceSection, InterfaceFlags);
+            ret = InstallOneInterface(&InterfaceGuid, ReferenceString, InterfaceSection, InterfaceFlags, SelectedDriver->InfFileDetails->hInf, DeviceInfoSet, devInfo);
 
 cleanup:
             MyFree(InterfaceGuidString);
-            MyFree(ReferenceString);
+            if (ReferenceString)
+                MyFree(ReferenceString);
             MyFree(InterfaceSection);
             InterfaceGuidString = ReferenceString = InterfaceSection = NULL;
             Result = SetupFindNextMatchLineW(&ContextInterface, AddInterface, &ContextInterface);
@@ -687,3 +537,87 @@ cleanup:
     TRACE("Returning %d\n", ret);
     return ret;
 }
+
+HKEY WINAPI
+SetupDiOpenDeviceInterfaceRegKey(
+    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)
+        {
+            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;
+}