+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include <setupapi.h>
+#include <devguid.h>
+#include <winioctl.h>
+#include "rawdisk.h"
+
+static GUID guid_iface_disk = {0x53f56307, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
+
+int rawdisk_detect(struct rawdisk_device *disks, int max_disks)
+{
+ int devidx, ifidx, count;
+ HDEVINFO devset;
+ SP_DEVINFO_DATA devdata;
+ SP_DEVICE_INTERFACE_DATA devif;
+ SP_DEVICE_INTERFACE_DETAIL_DATA_A *devdetail;
+ DWORD size, regtype;
+ char devname[1024];
+
+ if((devset = SetupDiGetClassDevs(&guid_iface_disk, 0, 0,
+ DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)) == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "failed to enumerate devices\n");
+ return -1;
+ }
+
+ count = 0;
+ devidx = 0;
+ for(;;) {
+ memset(&devdata, 0, sizeof devdata);
+ devdata.cbSize = sizeof devdata;
+ if(!SetupDiEnumDeviceInfo(devset, devidx, &devdata)) {
+ if(GetLastError() == ERROR_NO_MORE_ITEMS) break;
+ devidx++;
+ continue;
+ }
+
+ regtype = SPDRP_PHYSICAL_DEVICE_OBJECT_NAME;
+ SetupDiGetDeviceRegistryProperty(devset, &devdata, SPDRP_FRIENDLYNAME,
+ ®type, (unsigned char*)devname, sizeof devname, &size);
+
+ count = 0;
+ ifidx = 0;
+ for(;;) {
+ memset(&devif, 0, sizeof devif);
+ devif.cbSize = sizeof devif;
+ if(!SetupDiEnumDeviceInterfaces(devset, &devdata, &guid_iface_disk, ifidx, &devif)) {
+ if(GetLastError() == ERROR_NO_MORE_ITEMS) break;
+ ifidx++;
+ continue;
+ }
+
+ SetupDiGetDeviceInterfaceDetail(devset, &devif, 0, 0, &size, 0);
+ if(!(devdetail = malloc(size))) {
+ fprintf(stderr, "failed to allocate device interface detail buffer (size: %lu)\n", (unsigned long)size);
+ return -1;
+ }
+ devdetail->cbSize = sizeof *devdetail;
+ SetupDiGetDeviceInterfaceDetail(devset, &devif, devdetail, size, 0, 0);
+
+
+ if(count < max_disks) {
+ disks[count].path = strdup(devdetail->DevicePath);
+ disks[count].name = strdup(devname);
+ if(!disks[count].path || !disks[count].name) {
+ fprintf(stderr, "failed to allocate device strings\n");
+ return -1;
+ }
+ count++;
+ }
+
+ free(devdetail);
+ ifidx++;
+ }
+
+ devidx++;
+ }
+
+ return count;
+}