559f61f40247015778dd7efdd02459ae0ad2fa36
[instimg] / src / rawdisk.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <windows.h>
5 #include <setupapi.h>
6 #include <devguid.h>
7 #include <winioctl.h>
8 #include "rawdisk.h"
9
10 /*#define DBG_FAKE_DISKS*/
11
12 static GUID guid_iface_disk = {0x53f56307, 0xb6bf, 0x11d0, {0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b}};
13
14 int rawdisk_detect(struct rawdisk_device *disks, int max_disks)
15 {
16         int devidx, ifidx, count;
17         HDEVINFO devset;
18         SP_DEVINFO_DATA devdata;
19         SP_DEVICE_INTERFACE_DATA devif;
20         SP_DEVICE_INTERFACE_DETAIL_DATA_A *devdetail;
21         DWORD size, regtype;
22         char devname[1024];
23
24         if((devset = SetupDiGetClassDevs(&guid_iface_disk, 0, 0,
25                         DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)) == INVALID_HANDLE_VALUE) {
26                 fprintf(stderr, "failed to enumerate devices\n");
27                 return -1;
28         }
29
30         count = 0;
31         devidx = 0;
32         for(;;) {
33                 memset(&devdata, 0, sizeof devdata);
34                 devdata.cbSize = sizeof devdata;
35                 if(!SetupDiEnumDeviceInfo(devset, devidx, &devdata)) {
36                         if(GetLastError() == ERROR_NO_MORE_ITEMS) break;
37                         devidx++;
38                         continue;
39                 }
40
41                 regtype = SPDRP_PHYSICAL_DEVICE_OBJECT_NAME;
42                 SetupDiGetDeviceRegistryProperty(devset, &devdata, SPDRP_FRIENDLYNAME,
43                                 &regtype, (unsigned char*)devname, sizeof devname, &size);
44
45                 count = 0;
46                 ifidx = 0;
47                 for(;;) {
48                         memset(&devif, 0, sizeof devif);
49                         devif.cbSize = sizeof devif;
50                         if(!SetupDiEnumDeviceInterfaces(devset, &devdata, &guid_iface_disk, ifidx, &devif)) {
51                                 if(GetLastError() == ERROR_NO_MORE_ITEMS) break;
52                                 ifidx++;
53                                 continue;
54                         }
55
56                         SetupDiGetDeviceInterfaceDetail(devset, &devif, 0, 0, &size, 0);
57                         if(!(devdetail = malloc(size))) {
58                                 fprintf(stderr, "failed to allocate device interface detail buffer (size: %lu)\n", (unsigned long)size);
59                                 return -1;
60                         }
61                         devdetail->cbSize = sizeof *devdetail;
62                         SetupDiGetDeviceInterfaceDetail(devset, &devif, devdetail, size, 0, 0);
63
64
65                         if(count < max_disks) {
66                                 disks[count].path = strdup(devdetail->DevicePath);
67                                 disks[count].name = strdup(devname);
68                                 if(!disks[count].path || !disks[count].name) {
69                                         fprintf(stderr, "failed to allocate device strings\n");
70                                         return -1;
71                                 }
72                                 count++;
73                         }
74
75                         free(devdetail);
76                         ifidx++;
77                 }
78
79                 devidx++;
80         }
81
82 #ifdef DBG_FAKE_DISKS
83         {
84                 int i;
85                 for(i=0; i<3; i++) {
86                         char buf[32];
87                         sprintf(buf, "\\\\?\\fake\\disk\\%d", i);
88                         disks[count].path = strdup(buf);
89                         sprintf(buf, "FAKE_DISK_%d", i);
90                         disks[count].name = strdup(buf);
91                         count++;
92                 }
93         }
94 #endif
95
96         return count;
97 }