@@ -731,7 +731,7 @@ if test "$mingw32" = "yes" ; then
sysconfdir="\${prefix}"
local_statedir=
confsuffix=""
- libs_qga="-lws2_32 -lwinmm -lpowrprof $libs_qga"
+ libs_qga="-lsetupapi -lws2_32 -lwinmm -lpowrprof $libs_qga"
fi
werror=""
@@ -18,6 +18,8 @@
#include <string.h>
#include <winioctl.h>
#include <ntddscsi.h>
+#include <setupapi.h>
+#include <initguid.h>
#include "qga/guest-agent-core.h"
#include "qga/vss-win32.h"
#include "qga-qmp-commands.h"
@@ -29,6 +31,10 @@
#define SHTDN_REASON_FLAG_PLANNED 0x80000000
#endif
+DEFINE_GUID(GUID_DEVINTERFACE_VOLUME,
+ 0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2,
+ 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
+
/* multiple of 100 nanoseconds elapsed between windows baseline
* (1/1/1601) and Unix Epoch (1/1/1970), accounting for leap years */
#define W32_FT_OFFSET (10000000ULL * 60 * 60 * 24 * \
@@ -811,6 +817,77 @@ done:
static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
{
+ HDEVINFO dev_info;
+ SP_DEVINFO_DATA dev_info_data;
+ int i;
+ char dev_name[MAX_PATH];
+ char *name = g_strdup(&guid[4]);
+ char *buffer = NULL;
+ if (!QueryDosDevice(name, dev_name, sizeof(dev_name)/sizeof(char))) {
+ error_setg_win32(errp, GetLastError(), "failed to get dos device name");
+ g_free(name);
+ return NULL;
+ }
+ g_free(name);
+
+ dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, 0, 0,
+ DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ if (dev_info == INVALID_HANDLE_VALUE) {
+ error_setg_win32(errp, GetLastError(), "failed to get devices tree");
+ return NULL;
+ }
+ dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
+ for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
+ DWORD data, addr, bus, slot, func;
+ GuestPCIAddress *pci;
+ DWORD size = 0;
+
+ while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
+ SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
+ &data, (PBYTE)buffer, size, &size)) {
+ if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
+ if (buffer) {
+ g_free(buffer);
+ }
+ buffer = g_malloc0(sizeof(char)*(size*2));
+ } else {
+ error_setg_win32(errp, GetLastError(),
+ "failed to get device name");
+ goto out;
+ }
+ }
+
+ if (g_strcmp0(buffer, dev_name)) {
+ continue;
+ }
+
+ if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
+ SPDRP_BUSNUMBER, &data, (PBYTE)&bus, size, &size)) {
+ goto out;
+ }
+
+ if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
+ SPDRP_ADDRESS, &data, (PBYTE)&addr, size, &size)) {
+ goto out;
+ }
+
+ slot = (addr >> 16) & 0xFFFF;
+ func = addr & 0xFFFF;
+ pci = g_malloc0(sizeof(*pci));
+ pci->domain = addr;
+ pci->slot = slot;
+ pci->function = func;
+ pci->bus = bus;
+
+ if (buffer) {
+ g_free(buffer);
+ }
+ return pci;
+ }
+out:
+ if (buffer) {
+ g_free(buffer);
+ }
return NULL;
}