[host] windows: check the ivshmem device exists in the service

This commit is contained in:
Geoffrey McRae 2020-10-19 02:49:15 +11:00
parent 7a7e1d006b
commit 9ff1859dc1
4 changed files with 100 additions and 63 deletions

View File

@ -31,6 +31,8 @@ struct IVSHMEM
}; };
void ivshmemOptionsInit(); void ivshmemOptionsInit();
bool ivshmemInit(struct IVSHMEM * dev);
bool ivshmemOpen(struct IVSHMEM * dev); bool ivshmemOpen(struct IVSHMEM * dev);
bool ivshmemOpenDev(struct IVSHMEM * dev, const char * shmDev); bool ivshmemOpenDev(struct IVSHMEM * dev, const char * shmDev);
void ivshmemClose(struct IVSHMEM * dev); void ivshmemClose(struct IVSHMEM * dev);
void ivshmemFree(struct IVSHMEM * dev);

View File

@ -49,66 +49,80 @@ void ivshmemOptionsInit()
option_register(options); option_register(options);
} }
bool ivshmemOpen(struct IVSHMEM * dev) bool ivshmemInit(struct IVSHMEM * dev)
{ {
assert(dev); assert(dev && !dev->opaque);
HANDLE devHandle; HANDLE handle;
HDEVINFO devInfoSet;
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL;
SP_DEVICE_INTERFACE_DATA devInterfaceData = {0};
devInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
const int shmDevice = option_get_int("os", "shmDevice");
if (SetupDiEnumDeviceInterfaces(devInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, shmDevice, &devInterfaceData) == FALSE)
{ {
HDEVINFO devInfoSet; DWORD error = GetLastError();
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL; if (error == ERROR_NO_MORE_ITEMS)
SP_DEVICE_INTERFACE_DATA devInterfaceData = {0};
devInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
devInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
const int shmDevice = option_get_int("os", "shmDevice");
if (SetupDiEnumDeviceInterfaces(devInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, shmDevice, &devInterfaceData) == FALSE)
{ {
DWORD error = GetLastError(); DEBUG_WINERROR("Unable to enumerate the device, is it attached?", error);
if (error == ERROR_NO_MORE_ITEMS)
{
DEBUG_WINERROR("Unable to enumerate the device, is it attached?", error);
return false;
}
DEBUG_WINERROR("SetupDiEnumDeviceInterfaces failed", error);
return false; return false;
} }
DWORD reqSize = 0; DEBUG_WINERROR("SetupDiEnumDeviceInterfaces failed", error);
SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterfaceData, NULL, 0, &reqSize, NULL); return false;
if (!reqSize)
{
DEBUG_WINERROR("SetupDiGetDeviceInterfaceDetail", GetLastError());
return false;
}
infData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)calloc(reqSize, 1);
infData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterfaceData, infData, reqSize, NULL, NULL))
{
free(infData);
DEBUG_WINERROR("SetupDiGetDeviceInterfaceDetail", GetLastError());
return false;
}
devHandle = CreateFile(infData->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0);
if (devHandle == INVALID_HANDLE_VALUE)
{
SetupDiDestroyDeviceInfoList(devInfoSet);
free(infData);
DEBUG_WINERROR("CreateFile returned INVALID_HANDLE_VALUE", GetLastError());
return false;
}
free(infData);
SetupDiDestroyDeviceInfoList(devInfoSet);
} }
DWORD reqSize = 0;
SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterfaceData, NULL, 0, &reqSize, NULL);
if (!reqSize)
{
DEBUG_WINERROR("SetupDiGetDeviceInterfaceDetail", GetLastError());
return false;
}
infData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)calloc(reqSize, 1);
infData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(devInfoSet, &devInterfaceData, infData, reqSize, NULL, NULL))
{
free(infData);
DEBUG_WINERROR("SetupDiGetDeviceInterfaceDetail", GetLastError());
return false;
}
handle = CreateFile(infData->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0);
if (handle == INVALID_HANDLE_VALUE)
{
SetupDiDestroyDeviceInfoList(devInfoSet);
free(infData);
DEBUG_WINERROR("CreateFile returned INVALID_HANDLE_VALUE", GetLastError());
return false;
}
free(infData);
SetupDiDestroyDeviceInfoList(devInfoSet);
struct IVSHMEMInfo * info =
(struct IVSHMEMInfo *)malloc(sizeof(struct IVSHMEMInfo));
info->handle = handle;
dev->opaque = info;
dev->size = 0;
dev->mem = NULL;
return true;
}
bool ivshmemOpen(struct IVSHMEM * dev)
{
assert(dev && dev->opaque && !dev->mem);
struct IVSHMEMInfo * info = (struct IVSHMEMInfo *)dev->opaque;
IVSHMEM_SIZE size; IVSHMEM_SIZE size;
if (!DeviceIoControl(devHandle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &size, sizeof(IVSHMEM_SIZE), NULL, NULL)) if (!DeviceIoControl(info->handle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &size, sizeof(IVSHMEM_SIZE), NULL, NULL))
{ {
DEBUG_WINERROR("DeviceIoControl Failed", GetLastError()); DEBUG_WINERROR("DeviceIoControl Failed", GetLastError());
return 0; return 0;
@ -117,7 +131,7 @@ bool ivshmemOpen(struct IVSHMEM * dev)
IVSHMEM_MMAP_CONFIG config = { .cacheMode = IVSHMEM_CACHE_WRITECOMBINED }; IVSHMEM_MMAP_CONFIG config = { .cacheMode = IVSHMEM_CACHE_WRITECOMBINED };
IVSHMEM_MMAP map = { 0 }; IVSHMEM_MMAP map = { 0 };
if (!DeviceIoControl( if (!DeviceIoControl(
devHandle, info->handle,
IOCTL_IVSHMEM_REQUEST_MMAP, IOCTL_IVSHMEM_REQUEST_MMAP,
&config, sizeof(IVSHMEM_MMAP_CONFIG), &config, sizeof(IVSHMEM_MMAP_CONFIG),
&map , sizeof(IVSHMEM_MMAP), &map , sizeof(IVSHMEM_MMAP),
@ -127,27 +141,30 @@ bool ivshmemOpen(struct IVSHMEM * dev)
return false; return false;
} }
struct IVSHMEMInfo * info =
(struct IVSHMEMInfo *)malloc(sizeof(struct IVSHMEMInfo));
info->handle = devHandle;
dev->opaque = info;
dev->size = (unsigned int)size; dev->size = (unsigned int)size;
dev->mem = map.ptr; dev->mem = map.ptr;
return true; return true;
} }
void ivshmemClose(struct IVSHMEM * dev) void ivshmemClose(struct IVSHMEM * dev)
{ {
assert(dev); assert(dev && dev->opaque && dev->mem);
struct IVSHMEMInfo * info = struct IVSHMEMInfo * info = (struct IVSHMEMInfo *)dev->opaque;
(struct IVSHMEMInfo *)dev->opaque;
if (!DeviceIoControl(info->handle, IOCTL_IVSHMEM_RELEASE_MMAP, NULL, 0, NULL, 0, NULL, NULL)) if (!DeviceIoControl(info->handle, IOCTL_IVSHMEM_RELEASE_MMAP, NULL, 0, NULL, 0, NULL, NULL))
DEBUG_WINERROR("DeviceIoControl failed", GetLastError()); DEBUG_WINERROR("DeviceIoControl failed", GetLastError());
free(info); dev->size = 0;
dev->mem = NULL;
}
void ivshmemFree(struct IVSHMEM * dev)
{
assert(dev && dev->opaque && !dev->mem);
struct IVSHMEMInfo * info = (struct IVSHMEMInfo *)dev->opaque;
free(info);
dev->opaque = NULL;
} }

View File

@ -20,6 +20,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#define INSTANCE_MUTEX_NAME "Global\\6f1a5eec-af3f-4a65-99dd-ebe0e4ecea55" #define INSTANCE_MUTEX_NAME "Global\\6f1a5eec-af3f-4a65-99dd-ebe0e4ecea55"
#include "interface/platform.h" #include "interface/platform.h"
#include "common/ivshmem.h"
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
@ -598,6 +599,15 @@ VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
setupLogging(); setupLogging();
/* check if the ivshmem device exists */
struct IVSHMEM shmDev = { 0 };
if (!ivshmemInit(&shmDev))
{
doLog("Unable to find the IVSHMEM device, terminating the service\n");
goto shutdown;
}
ivshmemFree(&shmDev);
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0); ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
while(1) while(1)
{ {
@ -645,6 +655,7 @@ VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
} }
} }
shutdown:
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
CloseHandle(ghSvcStopEvent); CloseHandle(ghSvcStopEvent);
finishLogging(); finishLogging();

View File

@ -447,7 +447,13 @@ int app_main(int argc, char * argv[])
DEBUG_INFO("Looking Glass Host (%s)", BUILD_VERSION); DEBUG_INFO("Looking Glass Host (%s)", BUILD_VERSION);
struct IVSHMEM shmDev; struct IVSHMEM shmDev = { 0 };
if (!ivshmemInit(&shmDev))
{
DEBUG_ERROR("Failed to find the IVSHMEM device");
return -1;
}
if (!ivshmemOpen(&shmDev)) if (!ivshmemOpen(&shmDev))
{ {
DEBUG_ERROR("Failed to open the IVSHMEM device"); DEBUG_ERROR("Failed to open the IVSHMEM device");
@ -638,6 +644,7 @@ fail:
lgmpHostFree(&app.lgmp); lgmpHostFree(&app.lgmp);
ivshmemClose(&shmDev); ivshmemClose(&shmDev);
ivshmemFree(&shmDev);
return exitcode; return exitcode;
} }