Example #1
0
BOOL
IsSoftwareBusPnpEnumeratorInstalled()
{
    HDEVINFO hDevInfo;
    SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
    GUID SWBusGuid = {STATIC_BUSID_SoftwareDeviceEnumerator};
    PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData;

    hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL,  DIGCF_DEVICEINTERFACE| DIGCF_PRESENT);
    if (!hDevInfo)
    {
        // failed
        return FALSE;
    }

    DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &SWBusGuid, 0, &DeviceInterfaceData))
    {
        // failed
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return FALSE;
    }

    DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W));
    if (!DeviceInterfaceDetailData)
    {
        // failed
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return FALSE;
    }

    DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
    if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo,  &DeviceInterfaceData, DeviceInterfaceDetailData,MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W), NULL, NULL))
    {
        // failed
        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return FALSE;
    }
    HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return TRUE;
}
static void
frida_foreach_usb_device (const GUID * guid, FridaEnumerateDeviceFunc func, gpointer user_data)
{
  HANDLE info_set;
  gboolean carry_on = TRUE;
  guint member_index;

  info_set = SetupDiGetClassDevs (guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
  if (info_set == INVALID_HANDLE_VALUE)
    goto beach;

  for (member_index = 0; carry_on; member_index++)
  {
    SP_DEVICE_INTERFACE_DATA iface_data = { 0, };
    SP_DEVINFO_DATA info_data = { 0, };
    DWORD detail_size;
    SP_DEVICE_INTERFACE_DETAIL_DATA_W * detail_data = NULL;
    BOOL success;
    FridaDeviceInfo device_info = { 0, };
    DWORD instance_id_size;

    iface_data.cbSize = sizeof (iface_data);
    if (!SetupDiEnumDeviceInterfaces (info_set, NULL, guid, member_index, &iface_data))
      break;

    info_data.cbSize = sizeof (info_data);
    success = SetupDiGetDeviceInterfaceDetailW (info_set, &iface_data, NULL, 0, &detail_size, &info_data);
    if (!success && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
      goto skip_device;

    detail_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *) g_malloc (detail_size);
    detail_data->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA_W);
    success = SetupDiGetDeviceInterfaceDetailW (info_set, &iface_data, detail_data, detail_size, NULL, &info_data);
    if (!success)
      goto skip_device;

    device_info.device_path = detail_data->DevicePath;

    success = SetupDiGetDeviceInstanceIdW (info_set, &info_data, NULL, 0, &instance_id_size);
    if (!success && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
      goto skip_device;

    device_info.instance_id = (WCHAR *) g_malloc (instance_id_size * sizeof (WCHAR));
    success = SetupDiGetDeviceInstanceIdW (info_set, &info_data, device_info.instance_id, instance_id_size, NULL);
    if (!success)
      goto skip_device;

    device_info.friendly_name = frida_read_device_registry_string_property (info_set, &info_data, SPDRP_FRIENDLYNAME);

    device_info.location = frida_read_device_registry_string_property (info_set, &info_data, SPDRP_LOCATION_INFORMATION);

    device_info.device_info_set = info_set;
    device_info.device_info_data = &info_data;

    carry_on = func (&device_info, user_data);

skip_device:
    g_free (device_info.location);
    g_free (device_info.friendly_name);
    g_free (device_info.instance_id);

    g_free (detail_data);
  }

beach:
  if (info_set != INVALID_HANDLE_VALUE)
    SetupDiDestroyDeviceInfoList (info_set);
}
Example #3
0
DWORD
InstallSoftwareDeviceInterface(IN LPGUID DeviceId,
                               IN LPGUID InterfaceId,
                               IN LPWSTR ReferenceString)
{
    HDEVINFO hDevInfo;
    SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
    GUID SWBusGuid = {STATIC_BUSID_SoftwareDeviceEnumerator};
    PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData;
    HANDLE hDevice;
    PSWENUM_INSTALL_INTERFACE InstallInterface;
    DWORD dwResult;

    hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL,  DIGCF_DEVICEINTERFACE| DIGCF_PRESENT);
    if (!hDevInfo)
    {
        // failed
        return GetLastError();
    }

    DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &SWBusGuid, 0, &DeviceInterfaceData))
    {
        // failed
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return GetLastError();
    }

    DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W));
    if (!DeviceInterfaceDetailData)
    {
        // failed
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return GetLastError();
    }

    DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
    if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo,  &DeviceInterfaceData, DeviceInterfaceDetailData,MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W), NULL, NULL))
    {
        // failed
        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return GetLastError();
    }

    hDevice = CreateFileW(DeviceInterfaceDetailData->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED|FILE_ATTRIBUTE_NORMAL, NULL);
    if (hDevice == INVALID_HANDLE_VALUE)
    {
        // failed
        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return GetLastError();
    }

    InstallInterface  = (PSWENUM_INSTALL_INTERFACE)HeapAlloc(GetProcessHeap(), 0, sizeof(SWENUM_INSTALL_INTERFACE) + wcslen(ReferenceString) * sizeof(WCHAR));
    if (!InstallInterface)
    {
        // failed
        CloseHandle(hDevice);
        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
        SetupDiDestroyDeviceInfoList(hDevInfo);
        return GetLastError();
    }

    // init install interface param
    InstallInterface->DeviceId = *DeviceId;
    InstallInterface->InterfaceId = *InterfaceId;
    wcscpy(InstallInterface->ReferenceString, ReferenceString);

    PerformIO(hDevice, IOCTL_SWENUM_INSTALL_INTERFACE, InstallInterface, sizeof(SWENUM_INSTALL_INTERFACE) + wcslen(ReferenceString) * sizeof(WCHAR), NULL, 0, NULL);
    dwResult = HeapFree(GetProcessHeap(), 0, InstallInterface);

    CloseHandle(hDevice);
    HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
    SetupDiDestroyDeviceInfoList(hDevInfo);
    return dwResult;
}
Example #4
0
static void find_devices(HWND hwnd, const GUID* guid, const nt_handle& mountmgr, vector<device>& device_list) {
    HDEVINFO h;

    static WCHAR dosdevices[] = L"\\DosDevices\\";

    h = SetupDiGetClassDevs(guid, nullptr, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);

    if (h != INVALID_HANDLE_VALUE) {
        DWORD index = 0;
        SP_DEVICE_INTERFACE_DATA did;

        did.cbSize = sizeof(did);

        if (!SetupDiEnumDeviceInterfaces(h, nullptr, guid, index, &did))
            return;

        do {
            SP_DEVINFO_DATA dd;
            SP_DEVICE_INTERFACE_DETAIL_DATA_W* detail;
            DWORD size;

            dd.cbSize = sizeof(dd);

            SetupDiGetDeviceInterfaceDetailW(h, &did, nullptr, 0, &size, nullptr);

            detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(size);
            memset(detail, 0, size);

            detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);

            if (SetupDiGetDeviceInterfaceDetailW(h, &did, detail, size, &size, &dd)) {
                NTSTATUS Status;
                nt_handle file;
                device dev;
                STORAGE_DEVICE_NUMBER sdn;
                IO_STATUS_BLOCK iosb;
                UNICODE_STRING path;
                OBJECT_ATTRIBUTES attr;
                GET_LENGTH_INFORMATION gli;
                ULONG i;
                uint8_t sb[4096];

                path.Buffer = detail->DevicePath;
                path.Length = path.MaximumLength = (uint16_t)(wcslen(detail->DevicePath) * sizeof(WCHAR));

                if (path.Length > 4 * sizeof(WCHAR) && path.Buffer[0] == '\\' && path.Buffer[1] == '\\'  && path.Buffer[2] == '?'  && path.Buffer[3] == '\\')
                    path.Buffer[1] = '?';

                InitializeObjectAttributes(&attr, &path, 0, nullptr, nullptr);

                Status = NtOpenFile(&file, FILE_GENERIC_READ, &attr, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_ALERT);

                if (!NT_SUCCESS(Status)) {
                    free(detail);
                    index++;
                    continue;
                }

                dev.pnp_name = detail->DevicePath;

                Status = NtDeviceIoControlFile(file, nullptr, nullptr, nullptr, &iosb, IOCTL_DISK_GET_LENGTH_INFO, nullptr, 0, &gli, sizeof(GET_LENGTH_INFORMATION));
                if (!NT_SUCCESS(Status)) {
                    free(detail);
                    index++;
                    continue;
                }

                dev.size = gli.Length.QuadPart;

                Status = NtDeviceIoControlFile(file, nullptr, nullptr, nullptr, &iosb, IOCTL_STORAGE_GET_DEVICE_NUMBER, nullptr, 0, &sdn, sizeof(STORAGE_DEVICE_NUMBER));
                if (!NT_SUCCESS(Status)) {
                    dev.disk_num = 0xffffffff;
                    dev.part_num = 0xffffffff;
                } else {
                    dev.disk_num = sdn.DeviceNumber;
                    dev.part_num = sdn.PartitionNumber;
                }

                dev.friendly_name = L"";
                dev.drive = L"";
                dev.fstype = L"";
                dev.has_parts = false;
                dev.ignore = false;
                dev.multi_device = false;

                dev.is_disk = RtlCompareMemory(guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID);

                if (dev.is_disk) {
                    STORAGE_PROPERTY_QUERY spq;
                    STORAGE_DEVICE_DESCRIPTOR sdd, *sdd2;
                    ULONG dlisize;
                    DRIVE_LAYOUT_INFORMATION_EX* dli;

                    spq.PropertyId = StorageDeviceProperty;
                    spq.QueryType = PropertyStandardQuery;
                    spq.AdditionalParameters[0] = 0;

                    Status = NtDeviceIoControlFile(file, nullptr, nullptr, nullptr, &iosb, IOCTL_STORAGE_QUERY_PROPERTY,
                                                   &spq, sizeof(STORAGE_PROPERTY_QUERY), &sdd, sizeof(STORAGE_DEVICE_DESCRIPTOR));

                    if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) {
                        sdd2 = (STORAGE_DEVICE_DESCRIPTOR*)malloc(sdd.Size);

                        Status = NtDeviceIoControlFile(file, nullptr, nullptr, nullptr, &iosb, IOCTL_STORAGE_QUERY_PROPERTY,
                                                       &spq, sizeof(STORAGE_PROPERTY_QUERY), sdd2, sdd.Size);
                        if (NT_SUCCESS(Status)) {
                            string desc2;

                            desc2 = "";

                            if (sdd2->VendorIdOffset != 0) {
                                desc2 += (char*)((uint8_t*)sdd2 + sdd2->VendorIdOffset);

                                while (desc2.length() > 0 && desc2[desc2.length() - 1] == ' ')
                                    desc2 = desc2.substr(0, desc2.length() - 1);
                            }

                            if (sdd2->ProductIdOffset != 0) {
                                if (sdd2->VendorIdOffset != 0 && desc2.length() != 0 && desc2[desc2.length() - 1] != ' ')
                                    desc2 += " ";

                                desc2 += (char*)((uint8_t*)sdd2 + sdd2->ProductIdOffset);

                                while (desc2.length() > 0 && desc2[desc2.length() - 1] == ' ')
                                    desc2 = desc2.substr(0, desc2.length() - 1);
                            }

                            if (sdd2->VendorIdOffset != 0 || sdd2->ProductIdOffset != 0) {
                                ULONG ss;

                                ss = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, desc2.c_str(), -1, nullptr, 0);

                                if (ss > 0) {
                                    WCHAR* desc3 = (WCHAR*)malloc(ss * sizeof(WCHAR));

                                    if (MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, desc2.c_str(), -1, desc3, ss * sizeof(WCHAR)))
                                        dev.friendly_name = desc3;

                                    free(desc3);
                                }
                            }
                        }

                        free(sdd2);
                    }

                    dlisize = 0;
                    dli = nullptr;

                    do {
                        dlisize += 1024;

                        if (dli)
                            free(dli);

                        dli = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(dlisize);

                        Status = NtDeviceIoControlFile(file, nullptr, nullptr, nullptr, &iosb, IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
                                                       nullptr, 0, dli, dlisize);
                    } while (Status == STATUS_BUFFER_TOO_SMALL);

                    if (NT_SUCCESS(Status) && dli->PartitionCount > 0)
                        dev.has_parts = true;

                    free(dli);
                } else {
                    ULONG mmpsize;
                    MOUNTMGR_MOUNT_POINT* mmp;
                    MOUNTMGR_MOUNT_POINTS mmps;

                    mmpsize = sizeof(MOUNTMGR_MOUNT_POINT) + path.Length;

                    mmp = (MOUNTMGR_MOUNT_POINT*)malloc(mmpsize);

                    RtlZeroMemory(mmp, sizeof(MOUNTMGR_MOUNT_POINT));
                    mmp->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
                    mmp->DeviceNameLength = path.Length;
                    RtlCopyMemory(&mmp[1], path.Buffer, path.Length);

                    Status = NtDeviceIoControlFile(mountmgr, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_QUERY_POINTS,
                                                   mmp, mmpsize, &mmps, sizeof(MOUNTMGR_MOUNT_POINTS));
                    if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) {
                        MOUNTMGR_MOUNT_POINTS* mmps2;

                        mmps2 = (MOUNTMGR_MOUNT_POINTS*)malloc(mmps.Size);

                        Status = NtDeviceIoControlFile(mountmgr, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_QUERY_POINTS,
                                                    mmp, mmpsize, mmps2, mmps.Size);

                        if (NT_SUCCESS(Status)) {
                            ULONG i;

                            for (i = 0; i < mmps2->NumberOfMountPoints; i++) {
                                WCHAR* symlink = (WCHAR*)((uint8_t*)mmps2 + mmps2->MountPoints[i].SymbolicLinkNameOffset);

                                if (mmps2->MountPoints[i].SymbolicLinkNameLength == 0x1c &&
                                    RtlCompareMemory(symlink, dosdevices, wcslen(dosdevices) * sizeof(WCHAR)) == wcslen(dosdevices) * sizeof(WCHAR) &&
                                    symlink[13] == ':'
                                ) {
                                    WCHAR dr[3];

                                    dr[0] = symlink[12];
                                    dr[1] = ':';
                                    dr[2] = 0;

                                    dev.drive = dr;
                                    break;
                                }
                            }
                        }
                    }

                    free(mmp);
                }

                if (!dev.is_disk || !dev.has_parts) {
                    i = 0;
                    while (fs_ident[i].name) {
                        if (i == 0 || fs_ident[i].kboff != fs_ident[i-1].kboff) {
                            LARGE_INTEGER off;

                            off.QuadPart = fs_ident[i].kboff * 1024;
                            Status = NtReadFile(file, nullptr, nullptr, nullptr, &iosb, sb, sizeof(sb), &off, nullptr);
                        }

                        if (NT_SUCCESS(Status)) {
                            if (RtlCompareMemory(sb + fs_ident[i].sboff, fs_ident[i].magic, fs_ident[i].magiclen) == fs_ident[i].magiclen) {
                                dev.fstype = fs_ident[i].name;

                                if (dev.fstype == L"Btrfs") {
                                    superblock* bsb = (superblock*)sb;

                                    RtlCopyMemory(&dev.fs_uuid, &bsb->uuid, sizeof(BTRFS_UUID));
                                    RtlCopyMemory(&dev.dev_uuid, &bsb->dev_item.device_uuid, sizeof(BTRFS_UUID));
                                }

                                break;
                            }
                        }

                        i++;
                    }

                    if (dev.fstype == L"Btrfs" && RtlCompareMemory(guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) != sizeof(GUID)) {
                        wstring name;
                        wstring pref = L"\\Device\\Btrfs{";

                        name = get_mountdev_name(file);

                        if (name.length() > pref.length() && RtlCompareMemory(name.c_str(), pref.c_str(), pref.length() * sizeof(WCHAR)) == pref.length() * sizeof(WCHAR))
                            dev.ignore = true;
                    }
                }

                device_list.push_back(dev);
            }

            free(detail);

            index++;
        } while (SetupDiEnumDeviceInterfaces(h, nullptr, guid, index, &did));

        SetupDiDestroyDeviceInfoList(h);
    } else
        throw last_error(GetLastError());
}
Example #5
0
GList *
ks_enumerate_devices (const GUID * category)
{
  GList *result = NULL;
  HDEVINFO devinfo;
  gint i;

  devinfo = SetupDiGetClassDevsW (category, NULL, NULL,
      DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
  if (!ks_is_valid_handle (devinfo))
    return NULL;                /* no devices */

  for (i = 0;; i++) {
    BOOL success;
    SP_DEVICE_INTERFACE_DATA if_data = { 0, };
    SP_DEVICE_INTERFACE_DETAIL_DATA_W *if_detail_data;
    DWORD if_detail_data_size;
    SP_DEVINFO_DATA devinfo_data = { 0, };
    DWORD req_size;

    if_data.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);

    success = SetupDiEnumDeviceInterfaces (devinfo, NULL, category, i,
        &if_data);
    if (!success)               /* all devices enumerated? */
      break;

    if_detail_data_size = (MAX_PATH - 1) * sizeof (gunichar2);
    if_detail_data = g_malloc0 (if_detail_data_size);
    if_detail_data->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA_W);

    devinfo_data.cbSize = sizeof (SP_DEVINFO_DATA);

    success = SetupDiGetDeviceInterfaceDetailW (devinfo, &if_data,
        if_detail_data, if_detail_data_size, &req_size, &devinfo_data);
    if (success) {
      KsDeviceEntry *entry;
      WCHAR buf[512];

      entry = g_new0 (KsDeviceEntry, 1);
      entry->index = i;
      entry->path =
          g_utf16_to_utf8 (if_detail_data->DevicePath, -1, NULL, NULL, NULL);

      if (SetupDiGetDeviceRegistryPropertyW (devinfo, &devinfo_data,
              SPDRP_FRIENDLYNAME, NULL, (BYTE *) buf, sizeof (buf), NULL)) {
        entry->name = g_utf16_to_utf8 (buf, -1, NULL, NULL, NULL);
      }

      if (entry->name == NULL) {
        if (SetupDiGetDeviceRegistryPropertyW (devinfo, &devinfo_data,
                SPDRP_DEVICEDESC, NULL, (BYTE *) buf, sizeof (buf), NULL)) {
          entry->name = g_utf16_to_utf8 (buf, -1, NULL, NULL, NULL);
        }
      }

      if (entry->name != NULL)
        result = g_list_prepend (result, entry);
      else
        ks_device_entry_free (entry);
    }

    g_free (if_detail_data);
  }

  SetupDiDestroyDeviceInfoList (devinfo);

  return g_list_reverse (result);
}
Example #6
0
VOID
D3DKMTInitialize()
{
    VOID *gdi32 = NULL;
    VOID *deviceInfoSet;
    UINT32 result;
    UINT32 memberIndex;
    UINT32 detailDataSize;
    SP_DEVICE_INTERFACE_DATA            deviceInterfaceData;
    SP_DEVICE_INTERFACE_DETAIL_DATA_W   *detailData;
    SP_DEVINFO_DATA                     deviceInfoData;
    //D3DKMT_OPENADAPTERFROMDEVICENAME    openAdapterFromDeviceName;
    D3DKMT_QUERYSTATISTICS              queryStatistics;

    gdi32 = Module::Load(L"gdi32.dll");

    if (!gdi32)
    {
        return;
    }

    D3DKMTOpenAdapterFromDeviceName = (TYPE_D3DKMTOpenAdapterFromDeviceName) Module::GetProcedureAddress(
                                                                                gdi32,
                                                                                "D3DKMTOpenAdapterFromDeviceName"
                                                                                );

    D3DKMTQueryStatistics = (TYPE_D3DKMTQueryStatistics) Module::GetProcedureAddress(gdi32, "D3DKMTQueryStatistics");

    if (!D3DKMTOpenAdapterFromDeviceName || !D3DKMTQueryStatistics)
    {
        return;
    }

    deviceInfoSet = SetupDiGetClassDevsW(&GUID_DISPLAY_DEVICE_ARRIVAL_I,
                                         NULL, NULL,
                                         DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);

    if (!deviceInfoSet)
    {
        return;
    }

    memberIndex = 0;
    deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

    while (SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DISPLAY_DEVICE_ARRIVAL_I, memberIndex, &deviceInterfaceData))
    {
        detailDataSize = 0x100;
		detailData = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*) Memory::Allocate(detailDataSize);
        detailData->cbSize = 6; /*sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W)*/
        deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

        result = SetupDiGetDeviceInterfaceDetailW(
                    deviceInfoSet,
                    &deviceInterfaceData,
                    detailData,
                    detailDataSize,
                    &detailDataSize,
                    &deviceInfoData
                    );

        if (result)
        {
            openAdapterFromDeviceName.pDeviceName = detailData->DevicePath;

            if (NT_SUCCESS(D3DKMTOpenAdapterFromDeviceName(&openAdapterFromDeviceName)))
            {
                memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS));

                queryStatistics.Type = D3DKMT_QUERYSTATISTICS_ADAPTER;
                queryStatistics.AdapterLuid = openAdapterFromDeviceName.AdapterLuid;

                if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics)))
                {
                    UINT32 i;

                    D3dkmt_GpuAdapter = AllocateGpuAdapter(queryStatistics.QueryResult.AdapterInformation.NbSegments);

                    D3dkmt_GpuAdapter->AdapterLuid       = openAdapterFromDeviceName.AdapterLuid;
                    D3dkmt_GpuAdapter->NodeCount     = queryStatistics.QueryResult.AdapterInformation.NodeCount;
                    D3dkmt_GpuAdapter->SegmentCount  = queryStatistics.QueryResult.AdapterInformation.NbSegments;

                    RtlInitializeBitMap(
                        &D3dkmt_GpuAdapter->ApertureBitMap,
                        D3dkmt_GpuAdapter->ApertureBitMapBuffer,
                        queryStatistics.QueryResult.AdapterInformation.NbSegments
                        );

                    EtGpuTotalNodeCount += D3dkmt_GpuAdapter->NodeCount;

                    EtGpuTotalSegmentCount += D3dkmt_GpuAdapter->SegmentCount;

                    D3dkmt_GpuAdapter->FirstNodeIndex = EtGpuNextNodeIndex;
                    EtGpuNextNodeIndex += D3dkmt_GpuAdapter->NodeCount;

                    for (i = 0; i < D3dkmt_GpuAdapter->SegmentCount; i++)
                    {
                        memset(&queryStatistics, 0, sizeof(D3DKMT_QUERYSTATISTICS));

                        queryStatistics.Type = D3DKMT_QUERYSTATISTICS_SEGMENT;
                        queryStatistics.AdapterLuid = D3dkmt_GpuAdapter->AdapterLuid;
                        queryStatistics.QuerySegment.SegmentId = i;

                        if (NT_SUCCESS(D3DKMTQueryStatistics(&queryStatistics)))
                        {
                            UINT64 commitLimit;
                            UINT32 aperature;

                            commitLimit = queryStatistics.QueryResult.SegmentInformationV1.CommitLimit;
                            aperature = queryStatistics.QueryResult.SegmentInformationV1.Aperture;

                            if (aperature)
                                RtlSetBits(&D3dkmt_GpuAdapter->ApertureBitMap, i, 1);
                            else
                                EtGpuDedicatedLimit += commitLimit;
                        }
                    }
                }
            }
        }

		Memory::Free(detailData);

        memberIndex++;
    }

    SetupDiDestroyDeviceInfoList(deviceInfoSet);

    EtGpuNodeBitMapBuffer = (UINT32*) Memory::Allocate(BYTES_NEEDED_FOR_BITS(EtGpuTotalNodeCount));
    
	RtlInitializeBitMap(&EtGpuNodeBitMap, EtGpuNodeBitMapBuffer, EtGpuTotalNodeCount);

    EtGpuNodesTotalRunningTimeDelta = (PPH_UINT64_DELTA) Memory::Allocate(sizeof(PH_UINT64_DELTA) * EtGpuTotalNodeCount);

    memset(EtGpuNodesTotalRunningTimeDelta, 0, sizeof(PH_UINT64_DELTA) * EtGpuTotalNodeCount);
}
Example #7
0
BOOL
GetDeviceListInterfaces(
    HDEVINFO DeviceHandle,
    IN LPGUID InterfaceGuid,
    LPFILTERINFO *OutPath)
{
    ULONG Length, Index = 0;
    SP_DEVICE_INTERFACE_DATA InterfaceData;
    PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData;
    SP_DEVINFO_DATA DeviceData;
    LPFILTERINFO LastDevice = NULL, RootDevice = NULL, CurDevice;
    BOOL Result;


    do
    {
        InterfaceData.cbSize = sizeof(InterfaceData);
        InterfaceData.Reserved = 0;

        /* query device interface */
        Result = SetupDiEnumDeviceInterfaces(DeviceHandle,
                                NULL,
                                InterfaceGuid,
                                Index,
                                &InterfaceData);

        if (!Result)
        {
            /* failed */
            DPRINT("SetupDiEnumDeviceInterfaces Index %u failed with %lx\n", Index, GetLastError());
            break;
        }

        /* allocate device interface struct */
        Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR);
        DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(),
                                                                 HEAP_ZERO_MEMORY,
                                                                 Length);

        if (!DetailData)
        {
            /* insufficient memory */
            break;
        }

        /* initialize device interface detail struct */
        DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);

        DeviceData.cbSize = sizeof(DeviceData);
        DeviceData.Reserved = 0;

        Result = SetupDiGetDeviceInterfaceDetailW(DeviceHandle,
                                                  &InterfaceData,
                                                  DetailData,
                                                  Length,
                                                  NULL,
                                                  &DeviceData);

       if (!Result)
       {
           /* failed */
           DPRINT("SetupDiGetDeviceInterfaceDetail failed with %x\n", GetLastError());
           HeapFree(GetProcessHeap(), 0, DetailData);

           break;
       }

       /* allocate device path struct */
       CurDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(FILTERINFO));
       if (!CurDevice)
       {
           /* no memory */
           HeapFree(GetProcessHeap(), 0, DetailData);
           break;
       }

       /* store device path */
       CopyMemory(&CurDevice->DeviceData, &DeviceData, sizeof(SP_DEVINFO_DATA));
       wcscpy(CurDevice->DevicePath, DetailData->DevicePath);
       CurDevice->MappedId[0] = ULONG_MAX;
       CurDevice->MappedId[1] = ULONG_MAX;

       DPRINT("DevicePath %S\n", CurDevice->DevicePath);

       if (!RootDevice)
           RootDevice = CurDevice;

       if (LastDevice)
       {
           LastDevice->lpNext = CurDevice;
       }

       /* set as last device */
       LastDevice = CurDevice;

        /* free device interface struct */
        HeapFree(GetProcessHeap(), 0, DetailData);

       /* increment device interface index */
       Index++;
    }while(TRUE);

    /* store result */
    *OutPath = RootDevice;

    if (!RootDevice)
        return FALSE;


    return TRUE;
}
Example #8
0
MIXER_STATUS
Enum(
    IN  PVOID EnumContext,
    IN  ULONG DeviceIndex,
    OUT LPWSTR * DeviceName,
    OUT PHANDLE OutHandle,
    OUT PHANDLE OutKey)
{
    SP_DEVICE_INTERFACE_DATA InterfaceData;
    SP_DEVINFO_DATA DeviceData;
    PSP_DEVICE_INTERFACE_DETAIL_DATA_W DetailData;
    BOOL Result;
    DWORD Length;
    MIXER_STATUS Status;

    //printf("Enum EnumContext %p DeviceIndex %lu OutHandle %p\n", EnumContext, DeviceIndex, OutHandle);

    InterfaceData.cbSize = sizeof(InterfaceData);
    InterfaceData.Reserved = 0;

    Result = SetupDiEnumDeviceInterfaces(EnumContext,
                                NULL,
                                &CategoryGuid,
                                DeviceIndex,
                                &InterfaceData);

    if (!Result)
    {
        if (GetLastError() == ERROR_NO_MORE_ITEMS)
        {
            return MM_STATUS_NO_MORE_DEVICES;
        }
        return MM_STATUS_UNSUCCESSFUL;
    }

    Length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR);
    DetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(),
                                                             0,
                                                             Length);
    DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
    DeviceData.cbSize = sizeof(DeviceData);
    DeviceData.Reserved = 0;

    Result = SetupDiGetDeviceInterfaceDetailW(EnumContext,
                                    &InterfaceData,
                                    DetailData,
                                    Length,
                                    NULL,
                                    &DeviceData);

    if (!Result)
    {
        DPRINT("SetupDiGetDeviceInterfaceDetailW failed with %lu\n", GetLastError());
        return MM_STATUS_UNSUCCESSFUL;
    }


    *OutKey = SetupDiOpenDeviceInterfaceRegKey(EnumContext, &InterfaceData, 0, KEY_READ);
     if ((HKEY)*OutKey == INVALID_HANDLE_VALUE)
     {
        HeapFree(GetProcessHeap(), 0, DetailData);
        return MM_STATUS_UNSUCCESSFUL;
    }

    Status = Open(DetailData->DevicePath, OutHandle);

    if (Status != MM_STATUS_SUCCESS)
    {
        RegCloseKey((HKEY)*OutKey);
        HeapFree(GetProcessHeap(), 0, DetailData);
        return Status;
    }

    *DeviceName = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(DetailData->DevicePath)+1) * sizeof(WCHAR));
    if (*DeviceName == NULL)
    {
        CloseHandle(*OutHandle);
        RegCloseKey((HKEY)*OutKey);
        HeapFree(GetProcessHeap(), 0, DetailData);
        return MM_STATUS_NO_MEMORY;
    }
    wcscpy(*DeviceName, DetailData->DevicePath);
    HeapFree(GetProcessHeap(), 0, DetailData);

    return Status;
}
nsresult
sbWinGetDevInterfaceDetail(PSP_DEVICE_INTERFACE_DETAIL_DATA* aDevIfDetailData,
                           HDEVINFO                          aDevInfo,
                           SP_DEVINFO_DATA*                  aDevInfoData,
                           const GUID*                       aGUID)
{
  // Validate arguments.
  NS_ENSURE_ARG_POINTER(aDevIfDetailData);
  NS_ENSURE_ARG_POINTER(aDevInfoData);
  NS_ENSURE_ARG_POINTER(aGUID);

  // Function variables.
  BOOL success;

  // Get the device interface data for the requested device and interface GUID.
  SP_DEVICE_INTERFACE_DATA devIfData;
  ZeroMemory(&devIfData, sizeof(SP_DEVICE_INTERFACE_DATA));
  devIfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  success = SetupDiEnumDeviceInterfaces(aDevInfo,
                                        aDevInfoData,
                                        aGUID,
                                        0,
                                        &devIfData);
  if (!success)
    return NS_ERROR_NOT_AVAILABLE;

  // Get the required size of the device interface detail data.
  DWORD size = 0;
  success = SetupDiGetDeviceInterfaceDetailW(aDevInfo,
                                             &devIfData,
                                             NULL,
                                             0,
                                             &size,
                                             NULL);
  if (!success) {
    NS_ENSURE_TRUE(GetLastError() == ERROR_INSUFFICIENT_BUFFER,
                   NS_ERROR_FAILURE);
  }
  NS_ENSURE_TRUE(size > 0, NS_ERROR_FAILURE);

  // Allocate the device interface detail data record and set it up for
  // auto-disposal.
  PSP_DEVICE_INTERFACE_DETAIL_DATA devIfDetailData;
  devIfDetailData =
    static_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(NS_Alloc(size));
  NS_ENSURE_TRUE(devIfDetailData, NS_ERROR_OUT_OF_MEMORY);
  sbAutoNSMemPtr autoDevIfDetailData(devIfDetailData);

  // Get the device interface details.
  devIfDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
  success = SetupDiGetDeviceInterfaceDetailW(aDevInfo,
                                             &devIfData,
                                             devIfDetailData,
                                             size,
                                             NULL,
                                             NULL);
  NS_ENSURE_SUCCESS(success, NS_ERROR_FAILURE);

  // Return results.
  *aDevIfDetailData =
    static_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(autoDevIfDetailData.forget());

  return NS_OK;
}
nsresult
sbWinGetDevDetail(PSP_DEVICE_INTERFACE_DETAIL_DATA* aDevIfDetailData,
                  SP_DEVINFO_DATA*                  aDevInfoData,
                  HDEVINFO                          aDevInfo,
                  const GUID*                       aGUID,
                  DWORD                             aDevIndex)
{
  // Validate arguments.
  NS_ENSURE_ARG_POINTER(aDevIfDetailData);
  NS_ENSURE_ARG_POINTER(aDevInfoData);
  NS_ENSURE_ARG_POINTER(aGUID);

  // Function variables.
  BOOL success;

  // Set up to get the device interface detail data.  If not successful, there's
  // no more device interfaces to enumerate.
  SP_DEVICE_INTERFACE_DATA devIfData;
  ZeroMemory(&devIfData, sizeof(SP_DEVICE_INTERFACE_DATA));
  devIfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  success = SetupDiEnumDeviceInterfaces(aDevInfo,
                                        NULL,
                                        aGUID,
                                        aDevIndex,
                                        &devIfData);
  if (!success)
    return NS_ERROR_NOT_AVAILABLE;

  // Get the required size of the device interface detail data.
  DWORD size = 0;
  success = SetupDiGetDeviceInterfaceDetailW(aDevInfo,
                                             &devIfData,
                                             NULL,
                                             0,
                                             &size,
                                             NULL);
  NS_ENSURE_TRUE(size > 0, NS_ERROR_FAILURE);

  // Allocate the device interface detail data record and set it up for
  // auto-disposal.
  PSP_DEVICE_INTERFACE_DETAIL_DATA
    devIfDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) malloc(size);
  NS_ENSURE_TRUE(devIfDetailData, NS_ERROR_OUT_OF_MEMORY);
  sbAutoMemPtr<SP_DEVICE_INTERFACE_DETAIL_DATA>
    autoDevIfDetailData(devIfDetailData);
  devIfDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

  // Get the device interface details.
  ZeroMemory(aDevInfoData, sizeof(SP_DEVINFO_DATA));
  aDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
  success = SetupDiGetDeviceInterfaceDetailW(aDevInfo,
                                             &devIfData,
                                             devIfDetailData,
                                             size,
                                             NULL,
                                             aDevInfoData);
  NS_ENSURE_SUCCESS(success, NS_ERROR_FAILURE);

  // Return results.
  *aDevIfDetailData =
    (PSP_DEVICE_INTERFACE_DETAIL_DATA) autoDevIfDetailData.forget();

  return NS_OK;
}
Example #11
0
/// <summary>
/// Get physical device paths.
/// </summary>
/// <param name="drives">Found drives</param>
/// <returns>Error code</returns>
DWORD PhysicalDisk::GetPhysicalPaths( std::vector<std::wstring>& drives )
{
    HDEVINFO diskClassDevices = nullptr;
    GUID diskClassDeviceInterfaceGuid = GUID_DEVINTERFACE_DISK;
    SP_DEVICE_INTERFACE_DATA deviceInterfaceData = { 0 };
    PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData = nullptr;
    DWORD requiredSize = 0;
    DWORD deviceIndex = 0;

    HANDLE disk = INVALID_HANDLE_VALUE;
    STORAGE_DEVICE_NUMBER diskNumber = { 0 };
    DWORD bytesReturned = 0;

    //
    // Get the handle to the device information set for installed
    // disk class devices. Returns only devices that are currently
    // present in the system and have an enabled disk device
    // interface.
    //
    diskClassDevices = SetupDiGetClassDevs( &diskClassDeviceInterfaceGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );
    if (diskClassDevices == INVALID_HANDLE_VALUE)
        return GetLastError();

    ZeroMemory( &deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA) );
    deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

    for (; SetupDiEnumDeviceInterfaces( diskClassDevices, NULL, &diskClassDeviceInterfaceGuid, deviceIndex, &deviceInterfaceData ); ++deviceIndex)
    {
        SetupDiGetDeviceInterfaceDetailW( diskClassDevices, &deviceInterfaceData, NULL, 0, &requiredSize, NULL );
        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
            goto Exit;

        deviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc( requiredSize );

        ZeroMemory( deviceInterfaceDetailData, requiredSize );
        deviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

        if (!SetupDiGetDeviceInterfaceDetail( diskClassDevices, &deviceInterfaceData, deviceInterfaceDetailData, requiredSize, NULL, NULL ))
            goto Exit;

        disk = CreateFile( deviceInterfaceDetailData->DevicePath,
                           GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
                           NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );

        if (disk == INVALID_HANDLE_VALUE)
            goto Exit;

        if (!DeviceIoControl( disk, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &diskNumber, sizeof(STORAGE_DEVICE_NUMBER), &bytesReturned, NULL ))
            goto Exit;

        CloseHandle( disk );
        disk = INVALID_HANDLE_VALUE;

        drives.emplace_back( L"\\\\?\\PhysicalDrive" + std::to_wstring( diskNumber.DeviceNumber ) );

        if (deviceInterfaceDetailData)
        {
            free( deviceInterfaceDetailData );
            deviceInterfaceDetailData = nullptr;
        }
    }

Exit:

    if (INVALID_HANDLE_VALUE != diskClassDevices)
        SetupDiDestroyDeviceInfoList( diskClassDevices );

    if (INVALID_HANDLE_VALUE != disk)
        CloseHandle( disk );

    if (deviceInterfaceDetailData)
        free( deviceInterfaceDetailData );

    return GetLastError();
}
Example #12
0
MMRESULT
WdmAudOpenSoundDeviceByLegacy(
    IN PSOUND_DEVICE SoundDevice,
    OUT PVOID *Handle)
{
    HDEVINFO hDevInfo;
    SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
    GUID SWBusGuid = {STATIC_KSCATEGORY_WDMAUD};
    PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData;

    if ( KernelHandle == INVALID_HANDLE_VALUE )
    {
        hDevInfo = SetupDiGetClassDevsW(&SWBusGuid, NULL, NULL,  DIGCF_DEVICEINTERFACE| DIGCF_PRESENT);
        if (!hDevInfo)
        {
            // failed
            return MMSYSERR_ERROR;
        }

        DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
        if (!SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &SWBusGuid, 0, &DeviceInterfaceData))
        {
            // failed
            SetupDiDestroyDeviceInfoList(hDevInfo);
            return MMSYSERR_ERROR;
        }

        DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W));
        if (!DeviceInterfaceDetailData)
        {
            // failed
            SetupDiDestroyDeviceInfoList(hDevInfo);
            return MMSYSERR_ERROR;
        }

        DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
        if (!SetupDiGetDeviceInterfaceDetailW(hDevInfo,  &DeviceInterfaceData, DeviceInterfaceDetailData,MAX_PATH * sizeof(WCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W), NULL, NULL))
        {
            // failed
            HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
            SetupDiDestroyDeviceInfoList(hDevInfo);
            return MMSYSERR_ERROR;
        }
        SND_TRACE(L"Opening wdmaud device '%s'\n",DeviceInterfaceDetailData->DevicePath);
        KernelHandle = CreateFileW(DeviceInterfaceDetailData->DevicePath,
                                   GENERIC_READ | GENERIC_WRITE,
                                   0,
                                   NULL,
                                   OPEN_EXISTING,
                                   FILE_FLAG_OVERLAPPED,
                                   NULL);

        HeapFree(GetProcessHeap(), 0, DeviceInterfaceDetailData);
        SetupDiDestroyDeviceInfoList(hDevInfo);
    }


    if ( KernelHandle == INVALID_HANDLE_VALUE )
        return MMSYSERR_ERROR;

    ++ OpenCount;
    return MMSYSERR_NOERROR;

}
Example #13
0
BOOL
ProcessExistingDevices()
{
    SP_DEVICE_INTERFACE_DATA interface_data;
    SP_DEVINFO_DATA device_data;
    PSP_DEVICE_INTERFACE_DETAIL_DATA_W detail_data;
    HDEVINFO dev_info;
    DWORD length;
    int index = 0;

    const GUID category_guid = {STATIC_KSCATEGORY_AUDIO};

    dev_info = SetupDiGetClassDevsExW(&category_guid,
                                      NULL,
                                      NULL,
                                      DIGCF_PRESENT | DIGCF_DEVICEINTERFACE,
                                      NULL,
                                      NULL,
                                      NULL);

/*    printf("%s:\n", ClassString); */

    interface_data.cbSize = sizeof(interface_data);
    interface_data.Reserved = 0;

    /* Enumerate the devices within the category */
    index = 0;

    length = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA)
                + (MAX_PATH * sizeof(WCHAR));

    detail_data =
        (PSP_DEVICE_INTERFACE_DETAIL_DATA_W)HeapAlloc(GetProcessHeap(),
                                                      0,
                                                      length);

    if ( ! detail_data )
    {
        logmsg("ProcessExistingDevices() failed to allocate detail_data\n");
        return TRUE;
    }

    while (
    SetupDiEnumDeviceInterfaces(dev_info,
                                NULL,
                                &category_guid,
                                index,
                                &interface_data) )
    {
        PnP_AudioDevice* list_node;

        ZeroMemory(detail_data, length);

        /* NOTE: We don't actually use device_data... */
        detail_data->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W);
        device_data.cbSize = sizeof(device_data);
        device_data.Reserved = 0;
        SetupDiGetDeviceInterfaceDetailW(dev_info,
                                         &interface_data,
                                         detail_data,
                                         length,
                                         NULL,
                                         &device_data);

        list_node = CreateDeviceDescriptor(detail_data->DevicePath, TRUE);
        AppendAudioDeviceToList(list_node);
        DestroyDeviceDescriptor(list_node);

        /* TODO: Cleanup the device we enumerated? */

        index ++;
    };

    HeapFree(GetProcessHeap(), 0, detail_data);

    SetupDiDestroyDeviceInfoList(dev_info);

    return TRUE;
}