[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [win-pv-devel] [PATCH v2] Add a user mode library wrapper for XENIFACE IOCTLs



> -----Original Message-----
> From: win-pv-devel [mailto:win-pv-devel-bounces@xxxxxxxxxxxxxxxxxxxx] On
> Behalf Of Marek Marczykowski-Górecki
> Sent: 13 July 2018 14:29
> To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> Cc: Rafal Wojdyla <omeg@xxxxxxxxxxxxxxxxxxxxxx>; Marek Marczykowski-
> Górecki <marmarek@xxxxxxxxxxxxxxxxxxxxxx>
> Subject: [win-pv-devel] [PATCH v2] Add a user mode library wrapper for
> XENIFACE IOCTLs
> 
> From: Rafal Wojdyla <omeg@xxxxxxxxxxxxxxxxxxxxxx>
> 
> Signed-off-by: Rafal Wojdyla <omeg@xxxxxxxxxxxxxxxxxxxxxx>
> [fix compile warnings, update visual studio files]
> Signed-off-by: Marek Marczykowski-Górecki
> <marmarek@xxxxxxxxxxxxxxxxxxxxxx>

Acked-by: Paul Durrant <paul.durrant@xxxxxxxxxx>

> ---
> This was posted before here:
> https://lists.xenproject.org/archives/html/win-pv-devel/2015-
> 11/msg00014.html
> 
> Back then I've raised a concern about code duplication caused by a
> different API than libxc (having libxenvchan in mind). But two years
> latter it looks like it isn't such a problem. libxenchan is the only
> piece being effectively duplicated (at least in Qubes OS), and
> everything else is really different anyway because of Linux/Windows
> differences. So, I think it isn't an issue.
> 
> Also I've renamed XcEvtchnBindUnbound to XcEvtchnOpenUnbound, as
> requested in review back then.
> 
> This has been tested with vs2017/WDK10 build for Windows 7 64bit, both
> on Windows 7 and Windows 10. The patch assume "Add Windows 7 build
> target" patches applied, but it should be easy to apply without them
> too.
> I've updated vs2015 files too, but don't have tools to test them (it
> isn't possible to download free vs2015 anymore).
> 
> Changes in v2:
>  - add xenproject to package depencencies in solution file
>  - allow multiple concurrent accesses to xeniface device
>  - drop Windows 7 targets
>  - disable spectre warning
>  - remove filter files
> ---
>  include/xencontrol.h                 | 342 +++++++++++++
>  src/xencontrol/xencontrol.c          | 919
> +++++++++++++++++++++++++++++++++++
>  src/xencontrol/xencontrol.rc         |  24 +
>  src/xencontrol/xencontrol_private.h  |  49 ++
>  vs2015/package/package.vcxproj       |   3 +
>  vs2015/xencontrol/xencontrol.vcxproj |  67 +++
>  vs2015/xeniface.sln                  |  26 +
>  vs2017/package/package.vcxproj       |   3 +
>  vs2017/xencontrol/xencontrol.vcxproj |  67 +++
>  vs2017/xeniface.sln                  |  27 +
>  10 files changed, 1527 insertions(+)
>  create mode 100644 include/xencontrol.h
>  create mode 100644 src/xencontrol/xencontrol.c
>  create mode 100644 src/xencontrol/xencontrol.rc
>  create mode 100644 src/xencontrol/xencontrol_private.h
>  create mode 100644 vs2015/xencontrol/xencontrol.vcxproj
>  create mode 100644 vs2017/xencontrol/xencontrol.vcxproj
> 
> diff --git a/include/xencontrol.h b/include/xencontrol.h
> new file mode 100644
> index 0000000..4560bc6
> --- /dev/null
> +++ b/include/xencontrol.h
> @@ -0,0 +1,342 @@
> +#ifndef _XENCONTROL_H_
> +#define _XENCONTROL_H_
> +
> +#include <windows.h>
> +#include <varargs.h>
> +#include "xeniface_ioctls.h"
> +
> +#ifdef XENCONTROL_EXPORTS
> +#    define XENCONTROL_API __declspec(dllexport)
> +#else
> +#    define XENCONTROL_API __declspec(dllimport)
> +#endif
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif
> +
> +/*! \typedef PXENCONTROL_CONTEXT
> +    \brief Library handle representing a Xen Interface session
> +*/
> +struct _XENCONTROL_CONTEXT;
> +typedef struct _XENCONTROL_CONTEXT *PXENCONTROL_CONTEXT;
> +
> +/*! \typedef XENCONTROL_LOG_LEVEL
> +    \brief Log levels used by the library
> +*/
> +typedef enum
> +_XENCONTROL_LOG_LEVEL {
> +    XLL_ERROR = 1,
> +    XLL_WARNING,
> +    XLL_INFO,
> +    XLL_DEBUG,
> +    XLL_TRACE,
> +} XENCONTROL_LOG_LEVEL;
> +
> +/*! \typedef XENCONTROL_LOGGER
> +    \brief Callback for receiving diagnostic messages from the library
> +*/
> +typedef void
> +XENCONTROL_LOGGER(
> +    IN  XENCONTROL_LOG_LEVEL LogLevel,
> +    IN  const CHAR *Function,
> +    IN  const WCHAR *Message,
> +    IN  va_list Args
> +    );
> +
> +/*! \brief Register a callback for receiving library's diagnostic messages
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param Logger Callback to register
> +*/
> +XENCONTROL_API
> +void
> +XcRegisterLogger(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  XENCONTROL_LOGGER *Logger
> +    );
> +
> +/*! \brief Set log level threshold for library's diagnostic messages
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param LogLevel Only messages with this level and above will be sent to
> the logger callback
> +*/
> +XENCONTROL_API
> +void
> +XcSetLogLevel(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  XENCONTROL_LOG_LEVEL LogLevel
> +    );
> +
> +/*! \brief Open the Xen Interface device
> +    \param Logger Callback for receiving library's diagnostic messages
> +    \param Xc Xencontrol handle representing a Xen Interface session
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcOpen(
> +    IN  XENCONTROL_LOGGER *Logger,
> +    OUT PXENCONTROL_CONTEXT *Xc
> +    );
> +
> +/*! \brief Close the Xen Interface device
> +    \param Xc Xencontrol handle returned by XcOpen()
> +*/
> +XENCONTROL_API
> +void
> +XcClose(
> +    IN  PXENCONTROL_CONTEXT Xc
> +    );
> +
> +/*! \brief Open an unbound event channel
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param RemoteDomain ID of a remote domain that will bind the channel
> +    \param Event Handle to an event object that will receive event channel
> notifications
> +    \param Mask Set to TRUE if the event channel should be initially masked
> +    \param LocalPort Port number that is assigned to the event channel
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcEvtchnOpenUnbound(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  USHORT RemoteDomain,
> +    IN  HANDLE Event,
> +    IN  BOOL Mask,
> +    OUT ULONG *LocalPort
> +    );
> +
> +/*! \brief Open an event channel that was already bound by a remote
> domain
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param RemoteDomain ID of a remote domain that has already bound
> the channel
> +    \param RemotePort Port number that is assigned to the event channel in
> the \a RemoteDomain
> +    \param Event Handle to an event that will receive event channel
> notifications
> +    \param Mask Set to TRUE if the event object channel should be initially
> masked
> +    \param LocalPort Port number that is assigned to the event channel
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcEvtchnBindInterdomain(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  USHORT RemoteDomain,
> +    IN  ULONG RemotePort,
> +    IN  HANDLE Event,
> +    IN  BOOL Mask,
> +    OUT ULONG *LocalPort
> +    );
> +
> +/*! \brief Close an event channel
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param LocalPort Port number that is assigned to the event channel
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcEvtchnClose(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  ULONG LocalPort
> +    );
> +
> +/*! \brief Notify the remote end of an event channel
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param LocalPort Port number that is assigned to the event channel
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcEvtchnNotify(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  ULONG LocalPort
> +    );
> +
> +/*! \brief Unmask an event channel
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param LocalPort Port number that is assigned to the event channel
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcEvtchnUnmask(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  ULONG LocalPort
> +    );
> +
> +/*! \brief Grant a \a RemoteDomain permission to access local memory
> pages
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param RemoteDomain ID of a remote domain that is being granted
> access
> +    \param NumberPages Number of 4k pages to grant access to
> +    \param NotifyOffset Offset of a byte in the granted region that will be 
> set
> to 0 when the grant is revoked
> +    \param NotifyPort Local port number of an open event channel that will
> be notified when the grant is revoked
> +    \param Flags Grant options
> +    \param Address Local user mode address of the granted memory region
> +    \param References An array of Xen grant numbers for every granted
> page
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcGnttabPermitForeignAccess(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  USHORT RemoteDomain,
> +    IN  ULONG NumberPages,
> +    IN  ULONG NotifyOffset,
> +    IN  ULONG NotifyPort,
> +    IN  XENIFACE_GNTTAB_PAGE_FLAGS Flags,
> +    OUT PVOID *Address,
> +    OUT ULONG *References
> +    );
> +
> +/*! \brief Revoke a foreign domain access to previously granted memory
> region
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param Address Local user mode address of the granted memory region
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcGnttabRevokeForeignAccess(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PVOID Address
> +    );
> +
> +/*! \brief Map a foreign memory region into the current address space
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param RemoteDomain ID of a remote domain that has granted access to
> the pages
> +    \param NumberPages Number of 4k pages to map
> +    \param References An array of Xen grant numbers for every granted
> page
> +    \param NotifyOffset Offset of a byte in the mapped region that will be 
> set
> to 0 when the region is unmapped
> +    \param NotifyPort Local port number of an open event channel that will
> be notified when the region is unmapped
> +    \param Flags Map options
> +    \param Address Local user mode address of the mapped memory region
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcGnttabMapForeignPages(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  USHORT RemoteDomain,
> +    IN  ULONG NumberPages,
> +    IN  PULONG References,
> +    IN  ULONG NotifyOffset,
> +    IN  ULONG NotifyPort,
> +    IN  XENIFACE_GNTTAB_PAGE_FLAGS Flags,
> +    OUT PVOID *Address
> +    );
> +
> +/*! \brief Unmap a foreign memory region from the current address space
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param Address Local user mode address of the mapped memory region
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcGnttabUnmapForeignPages(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PVOID Address
> +    );
> +
> +/*! \brief Read a XenStore key
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param Path Path to the key
> +    \param cbValue Size of the \a Value buffer, in bytes
> +    \param Value Buffer that receives the value
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcStoreRead(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path,
> +    IN  DWORD cbValue,
> +    OUT CHAR *Value
> +    );
> +
> +/*! \brief Write a value to a XenStore key
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param Path Path to the key
> +    \param Value Value to write
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcStoreWrite(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path,
> +    IN  PCHAR Value
> +    );
> +
> +/*! \brief Enumerate all immediate child keys of a XenStore key
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param Path Path to the key
> +    \param cbOutput Size of the \a Output buffer, in bytes
> +    \param Output Buffer that receives a NUL-separated child key names
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcStoreDirectory(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path,
> +    IN  DWORD cbOutput,
> +    OUT CHAR *Output
> +    );
> +
> +/*! \brief Remove a XenStore key
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param Path Path to the key
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcStoreRemove(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path
> +    );
> +
> +/*! \brief Set permissions of a XenStore key
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param Path Path to the key
> +    \param Count Number of permissions
> +    \param Permissions Array of permissions to set
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcStoreSetPermissions(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path,
> +    IN  ULONG Count,
> +    IN  PXENIFACE_STORE_PERMISSION Permissions
> +    );
> +
> +/*! \brief Add a XenStore key watch
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param Path Path to the key to be watched
> +    \param Event Handle to an event that will be signaled when the watch
> fires
> +    \param Handle An opaque value representing the watch
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcStoreAddWatch(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path,
> +    IN  HANDLE Event,
> +    OUT PVOID *Handle
> +    );
> +
> +/*! \brief Remove a XenStore watch
> +    \param Xc Xencontrol handle returned by XcOpen()
> +    \param Handle Watch handle returned by XcStoreAddWatch()
> +    \return Error code
> +*/
> +XENCONTROL_API
> +DWORD
> +XcStoreRemoveWatch(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PVOID Handle
> +    );
> +
> +#ifdef __cplusplus
> +}
> +#endif
> +
> +#endif // _XENCONTROL_H_
> diff --git a/src/xencontrol/xencontrol.c b/src/xencontrol/xencontrol.c
> new file mode 100644
> index 0000000..777fd29
> --- /dev/null
> +++ b/src/xencontrol/xencontrol.c
> @@ -0,0 +1,919 @@
> +#define INITGUID
> +#include <windows.h>
> +#include <winioctl.h>
> +#include <setupapi.h>
> +#include <stdlib.h>
> +#include <assert.h>
> +
> +#include "xencontrol.h"
> +#include "xencontrol_private.h"
> +
> +BOOL APIENTRY
> +DllMain(
> +    IN  HMODULE Module,
> +    IN  DWORD ReasonForCall,
> +    IN  LPVOID Reserved
> +)
> +{
> +    UNREFERENCED_PARAMETER(Module);
> +    UNREFERENCED_PARAMETER(ReasonForCall);
> +    UNREFERENCED_PARAMETER(Reserved);
> +    return TRUE;
> +}
> +
> +static void
> +_Log(
> +    IN  XENCONTROL_LOGGER *Logger,
> +    IN  XENCONTROL_LOG_LEVEL LogLevel,
> +    IN  XENCONTROL_LOG_LEVEL CurrentLogLevel,
> +    IN  PCHAR Function,
> +    IN  PWCHAR Format,
> +    ...
> +    )
> +{
> +    va_list Args;
> +    DWORD LastError;
> +
> +    if (Logger == NULL)
> +        return;
> +
> +    if (LogLevel > CurrentLogLevel)
> +        return;
> +
> +    LastError = GetLastError();
> +    va_start(Args, Format);
> +    Logger(LogLevel, Function, Format, Args);
> +    va_end(Args);
> +    SetLastError(LastError);
> +}
> +
> +static void
> +_LogMultiSz(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Caller,
> +    IN  XENCONTROL_LOG_LEVEL Level,
> +    IN  PCHAR MultiSz
> +    )
> +{
> +    PCHAR Ptr;
> +    ULONG Len;
> +
> +    for (Ptr = MultiSz; *Ptr;) {
> +        Len = (ULONG)strlen(Ptr);
> +        _Log(Xc->Logger, Level, Xc->LogLevel, Caller, L"%S", Ptr);
> +        Ptr += ((ptrdiff_t)Len + 1);
> +    }
> +}
> +
> +void
> +XcRegisterLogger(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  XENCONTROL_LOGGER *Logger
> +    )
> +{
> +    Xc->Logger = Logger;
> +}
> +
> +void
> +XcSetLogLevel(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  XENCONTROL_LOG_LEVEL LogLevel
> +    )
> +{
> +    Xc->LogLevel = LogLevel;
> +}
> +
> +DWORD
> +XcOpen(
> +    IN  XENCONTROL_LOGGER *Logger,
> +    OUT PXENCONTROL_CONTEXT *Xc
> +    )
> +{
> +    HDEVINFO DevInfo;
> +    SP_DEVICE_INTERFACE_DATA InterfaceData;
> +    SP_DEVICE_INTERFACE_DETAIL_DATA *DetailData = NULL;
> +    DWORD BufferSize;
> +    PXENCONTROL_CONTEXT Context;
> +
> +    Context = malloc(sizeof(*Context));
> +    if (Context == NULL)
> +        return ERROR_NOT_ENOUGH_MEMORY;
> +
> +    Context->Logger = Logger;
> +    Context->LogLevel = XLL_INFO;
> +    Context->RequestId = 1;
> +    InitializeListHead(&Context->RequestList);
> +    InitializeCriticalSection(&Context->RequestListLock);
> +
> +    DevInfo = SetupDiGetClassDevs(&GUID_INTERFACE_XENIFACE, 0, NULL,
> DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
> +    if (DevInfo == INVALID_HANDLE_VALUE) {
> +        _Log(Logger, XLL_ERROR, Context->LogLevel, __FUNCTION__,
> +             L"XENIFACE device class doesn't exist");
> +        goto fail;
> +    }
> +
> +    InterfaceData.cbSize = sizeof(InterfaceData);
> +    if (!SetupDiEnumDeviceInterfaces(DevInfo, NULL,
> &GUID_INTERFACE_XENIFACE, 0, &InterfaceData)) {
> +        _Log(Logger, XLL_ERROR, Context->LogLevel, __FUNCTION__,
> +             L"Failed to enumerate XENIFACE devices");
> +        goto fail;
> +    }
> +
> +    SetupDiGetDeviceInterfaceDetail(DevInfo, &InterfaceData, NULL, 0,
> &BufferSize, NULL);
> +    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
> +        _Log(Logger, XLL_ERROR, Context->LogLevel, __FUNCTION__,
> +             L"Failed to get buffer size for device details");
> +        goto fail;
> +    }
> +
> +    // Using 'BufferSize' from failed function call
> +#pragma warning(suppress: 6102)
> +    DetailData = (SP_DEVICE_INTERFACE_DETAIL_DATA *)malloc(BufferSize);
> +    if (!DetailData) {
> +        SetLastError(ERROR_OUTOFMEMORY);
> +        goto fail;
> +    }
> +
> +    DetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
> +
> +    if (!SetupDiGetDeviceInterfaceDetail(DevInfo, &InterfaceData,
> DetailData, BufferSize, NULL, NULL)) {
> +        _Log(Logger, XLL_ERROR, Context->LogLevel, __FUNCTION__,
> +             L"Failed to get XENIFACE device path");
> +        goto fail;
> +    }
> +
> +    Context->XenIface = CreateFile(DetailData->DevicePath,
> +                                   FILE_GENERIC_READ | FILE_GENERIC_WRITE,
> +                                   FILE_SHARE_READ | FILE_SHARE_WRITE,
> +                                   NULL,
> +                                   OPEN_EXISTING,
> +                                   FILE_ATTRIBUTE_NORMAL | 
> FILE_FLAG_OVERLAPPED,
> +                                   NULL);
> +
> +    if (Context->XenIface == INVALID_HANDLE_VALUE) {
> +        _Log(Logger, XLL_ERROR, Context->LogLevel, __FUNCTION__,
> +             L"Failed to open XENIFACE device, path: %s", DetailData-
> >DevicePath);
> +        goto fail;
> +    }
> +
> +    _Log(Logger, XLL_ERROR, Context->LogLevel, __FUNCTION__,
> +         L"XenIface handle: %p", Context->XenIface);
> +
> +    free(DetailData);
> +    *Xc = Context;
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    _Log(Logger, XLL_ERROR, Context->LogLevel, __FUNCTION__,
> +         L"Error: 0x%x", GetLastError());
> +
> +    free(DetailData);
> +    return GetLastError();
> +}
> +
> +void
> +XcClose(
> +    IN  PXENCONTROL_CONTEXT Xc
> +    )
> +{
> +    CloseHandle(Xc->XenIface);
> +    DeleteCriticalSection(&Xc->RequestListLock);
> +    free(Xc);
> +}
> +
> +DWORD
> +XcEvtchnOpenUnbound(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  USHORT RemoteDomain,
> +    IN  HANDLE Event,
> +    IN  BOOL Mask,
> +    OUT ULONG *LocalPort
> +    )
> +{
> +    XENIFACE_EVTCHN_BIND_UNBOUND_IN In;
> +    XENIFACE_EVTCHN_BIND_UNBOUND_OUT Out;
> +    DWORD Returned;
> +    BOOL Success;
> +
> +    In.RemoteDomain = RemoteDomain;
> +    In.Event = Event;
> +    In.Mask = !!Mask;
> +
> +    Log(XLL_DEBUG, L"RemoteDomain: %d, Event: %p, Mask: %d",
> RemoteDomain, Event, Mask);
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_EVTCHN_BIND_UNBOUND,
> +                              &In, sizeof(In),
> +                              &Out, sizeof(Out),
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_EVTCHN_BIND_UNBOUND_PORT
> failed");
> +        goto fail;
> +    }
> +
> +    *LocalPort = Out.LocalPort;
> +    Log(XLL_DEBUG, L"LocalPort: %lu", *LocalPort);
> +
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    return GetLastError();
> +}
> +
> +DWORD
> +XcEvtchnBindInterdomain(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  USHORT RemoteDomain,
> +    IN  ULONG RemotePort,
> +    IN  HANDLE Event,
> +    IN  BOOL Mask,
> +    OUT ULONG *LocalPort
> +    )
> +{
> +    XENIFACE_EVTCHN_BIND_INTERDOMAIN_IN In;
> +    XENIFACE_EVTCHN_BIND_INTERDOMAIN_OUT Out;
> +    DWORD Returned;
> +    BOOL Success;
> +
> +    In.RemoteDomain = RemoteDomain;
> +    In.RemotePort = RemotePort;
> +    In.Event = Event;
> +    In.Mask = !!Mask;
> +
> +    Log(XLL_DEBUG, L"RemoteDomain: %d, RemotePort %lu, Event: %p,
> Mask: %d",
> +        RemoteDomain, RemotePort, Event, Mask);
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_EVTCHN_BIND_INTERDOMAIN,
> +                              &In, sizeof(In),
> +                              &Out, sizeof(Out),
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_EVTCHN_BIND_INTERDOMAIN
> failed");
> +        goto fail;
> +    }
> +
> +    *LocalPort = Out.LocalPort;
> +    Log(XLL_DEBUG, L"LocalPort: %lu", *LocalPort);
> +
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    return GetLastError();
> +}
> +
> +DWORD
> +XcEvtchnClose(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  ULONG LocalPort
> +    )
> +{
> +    XENIFACE_EVTCHN_CLOSE_IN In;
> +    DWORD Returned;
> +    BOOL Success;
> +
> +    In.LocalPort = LocalPort;
> +
> +    Log(XLL_DEBUG, L"LocalPort: %lu", LocalPort);
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_EVTCHN_CLOSE,
> +                              &In, sizeof(In),
> +                              NULL, 0,
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_EVTCHN_CLOSE failed");
> +        goto fail;
> +    }
> +
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    return GetLastError();
> +}
> +
> +DWORD
> +XcEvtchnNotify(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  ULONG LocalPort
> +    )
> +{
> +    XENIFACE_EVTCHN_NOTIFY_IN In;
> +    DWORD Returned;
> +    BOOL Success;
> +
> +    In.LocalPort = LocalPort;
> +
> +    Log(XLL_DEBUG, L"LocalPort: %lu", LocalPort);
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_EVTCHN_NOTIFY,
> +                              &In, sizeof(In),
> +                              NULL, 0,
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_EVTCHN_NOTIFY failed");
> +        goto fail;
> +    }
> +
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    return GetLastError();
> +}
> +
> +DWORD
> +XcEvtchnUnmask(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  ULONG LocalPort
> +    )
> +{
> +    XENIFACE_EVTCHN_UNMASK_IN In;
> +    DWORD Returned;
> +    BOOL Success;
> +
> +    In.LocalPort = LocalPort;
> +
> +    Log(XLL_DEBUG, L"LocalPort: %lu", LocalPort);
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_EVTCHN_UNMASK,
> +                              &In, sizeof(In),
> +                              NULL, 0,
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_EVTCHN_UNMASK failed");
> +        goto fail;
> +    }
> +
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    return GetLastError();
> +}
> +
> +static PXENCONTROL_GNTTAB_REQUEST
> +FindRequest(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PVOID Address
> +    )
> +{
> +    PLIST_ENTRY Entry;
> +    PXENCONTROL_GNTTAB_REQUEST ReturnRequest = NULL;
> +
> +    EnterCriticalSection(&Xc->RequestListLock);
> +    Entry = Xc->RequestList.Flink;
> +    while (Entry != &Xc->RequestList) {
> +        PXENCONTROL_GNTTAB_REQUEST Request =
> CONTAINING_RECORD(Entry, XENCONTROL_GNTTAB_REQUEST, ListEntry);
> +
> +        if (Request->Address == Address) {
> +            ReturnRequest = Request;
> +            break;
> +        }
> +
> +        Entry = Entry->Flink;
> +    }
> +    LeaveCriticalSection(&Xc->RequestListLock);
> +
> +    return ReturnRequest;
> +}
> +
> +DWORD
> +XcGnttabPermitForeignAccess(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  USHORT RemoteDomain,
> +    IN  ULONG NumberPages,
> +    IN  ULONG NotifyOffset,
> +    IN  ULONG NotifyPort,
> +    IN  XENIFACE_GNTTAB_PAGE_FLAGS Flags,
> +    OUT PVOID *Address,
> +    OUT ULONG *References
> +    )
> +{
> +    XENIFACE_GNTTAB_PERMIT_FOREIGN_ACCESS_IN In;
> +    XENIFACE_GNTTAB_PERMIT_FOREIGN_ACCESS_OUT *Out;
> +    PXENCONTROL_GNTTAB_REQUEST Request;
> +    DWORD Returned, Size;
> +    BOOL Success;
> +    DWORD Status;
> +
> +    // lock the whole operation to not generate duplicate IDs
> +    EnterCriticalSection(&Xc->RequestListLock);
> +
> +    In.RequestId = Xc->RequestId;
> +    In.RemoteDomain = RemoteDomain;
> +    In.NumberPages = NumberPages;
> +    In.NotifyOffset = NotifyOffset;
> +    In.NotifyPort = NotifyPort;
> +    In.Flags = Flags;
> +
> +    Size =
> (ULONG)FIELD_OFFSET(XENIFACE_GNTTAB_PERMIT_FOREIGN_ACCESS_OU
> T, References[NumberPages]);
> +    Out = malloc(Size);
> +    Request = malloc(sizeof(*Request));
> +
> +    Status = ERROR_OUTOFMEMORY;
> +    if (!Request || !Out)
> +        goto fail;
> +
> +    ZeroMemory(Request, sizeof(*Request));
> +    Request->Id = In.RequestId;
> +
> +    Log(XLL_DEBUG, L"Id %lu, RemoteDomain: %d, NumberPages: %lu,
> NotifyOffset: 0x%x, NotifyPort: %lu, Flags: 0x%x",
> +        In.RequestId, RemoteDomain, NumberPages, NotifyOffset, NotifyPort,
> Flags);
> +
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_GNTTAB_PERMIT_FOREIGN_ACCESS,
> +                              &In, sizeof(In),
> +                              Out, Size,
> +                              &Returned,
> +                              &Request->Overlapped);
> +
> +    Status = GetLastError();
> +    // this IOCTL is expected to be pending on success
> +    if (!Success) {
> +        if (Status != ERROR_IO_PENDING) {
> +            Log(XLL_ERROR, L"IOCTL_XENIFACE_GNTTAB_GRANT_PAGES
> failed");
> +            goto fail;
> +        }
> +    } else {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_GNTTAB_GRANT_PAGES not
> pending");
> +        Status = ERROR_UNIDENTIFIED_ERROR;
> +        goto fail;
> +    }
> +
> +    Request->Address = Out->Address;
> +
> +    InsertTailList(&Xc->RequestList, &Request->ListEntry);
> +    Xc->RequestId++;
> +    LeaveCriticalSection(&Xc->RequestListLock);
> +
> +    *Address = Out->Address;
> +    memcpy(References, &Out->References, NumberPages *
> sizeof(ULONG));
> +    Log(XLL_DEBUG, L"Address: %p", *Address);
> +    for (ULONG i = 0; i < NumberPages; i++)
> +        Log(XLL_DEBUG, L"Grant ref[%lu]: %lu", i, Out->References[i]);
> +
> +    free(Out);
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    LeaveCriticalSection(&Xc->RequestListLock);
> +    Log(XLL_ERROR, L"Error: 0x%x", Status);
> +    free(Out);
> +    free(Request);
> +    return Status;
> +}
> +
> +DWORD
> +XcGnttabRevokeForeignAccess(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PVOID Address
> +    )
> +{
> +    XENIFACE_GNTTAB_REVOKE_FOREIGN_ACCESS_IN In;
> +    PXENCONTROL_GNTTAB_REQUEST Request;
> +    DWORD Returned;
> +    BOOL Success;
> +    DWORD Status;
> +
> +    Log(XLL_DEBUG, L"Address: %p", Address);
> +
> +    Status = ERROR_NOT_FOUND;
> +    Request = FindRequest(Xc, Address);
> +    if (!Request) {
> +        Log(XLL_ERROR, L"Address %p not granted", Address);
> +        goto fail;
> +    }
> +
> +    In.RequestId = Request->Id;
> +
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_GNTTAB_REVOKE_FOREIGN_ACCESS,
> +                              &In, sizeof(In),
> +                              NULL, 0,
> +                              &Returned,
> +                              NULL);
> +
> +    Status = GetLastError();
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_GNTTAB_UNGRANT_PAGES
> failed");
> +        goto fail;
> +    }
> +
> +    EnterCriticalSection(&Xc->RequestListLock);
> +    RemoveEntryList(&Request->ListEntry);
> +    LeaveCriticalSection(&Xc->RequestListLock);
> +    free(Request);
> +
> +    return Status;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: %d 0x%x", Status, Status);
> +    return Status;
> +}
> +
> +DWORD
> +XcGnttabMapForeignPages(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  USHORT RemoteDomain,
> +    IN  ULONG NumberPages,
> +    IN  PULONG References,
> +    IN  ULONG NotifyOffset,
> +    IN  ULONG NotifyPort,
> +    IN  XENIFACE_GNTTAB_PAGE_FLAGS Flags,
> +    OUT PVOID *Address
> +    )
> +{
> +    XENIFACE_GNTTAB_MAP_FOREIGN_PAGES_IN *In;
> +    XENIFACE_GNTTAB_MAP_FOREIGN_PAGES_OUT Out;
> +    PXENCONTROL_GNTTAB_REQUEST Request;
> +    DWORD Returned, Size;
> +    BOOL Success;
> +    DWORD Status;
> +
> +    // lock the whole operation to not generate duplicate IDs
> +    EnterCriticalSection(&Xc->RequestListLock);
> +
> +    Status = ERROR_OUTOFMEMORY;
> +    Size =
> (ULONG)FIELD_OFFSET(XENIFACE_GNTTAB_MAP_FOREIGN_PAGES_IN,
> References[NumberPages]);
> +    In = malloc(Size);
> +    Request = malloc(sizeof(*Request));
> +    if (!In || !Request)
> +        goto fail;
> +
> +    In->RequestId = Xc->RequestId;
> +    In->RemoteDomain = RemoteDomain;
> +    In->NumberPages = NumberPages;
> +    In->NotifyOffset = NotifyOffset;
> +    In->NotifyPort = NotifyPort;
> +    In->Flags = Flags;
> +    memcpy(&In->References, References, NumberPages * sizeof(ULONG));
> +
> +    ZeroMemory(Request, sizeof(*Request));
> +    Request->Id = In->RequestId;
> +
> +    Log(XLL_DEBUG, L"Id %lu, RemoteDomain: %d, NumberPages: %lu,
> NotifyOffset: 0x%x, NotifyPort: %lu, Flags: 0x%x",
> +        In->RequestId, RemoteDomain, NumberPages, NotifyOffset,
> NotifyPort, Flags);
> +
> +    for (ULONG i = 0; i < NumberPages; i++)
> +        Log(XLL_DEBUG, L"Grant ref[%lu]: %lu", i, References[i]);
> +
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_GNTTAB_MAP_FOREIGN_PAGES,
> +                              In, Size,
> +                              &Out, sizeof(Out),
> +                              &Returned,
> +                              &Request->Overlapped);
> +
> +    Status = GetLastError();
> +    // this IOCTL is expected to be pending on success
> +    if (!Success) {
> +        if (Status != ERROR_IO_PENDING) {
> +            Log(XLL_ERROR,
> L"IOCTL_XENIFACE_GNTTAB_MAP_FOREIGN_PAGES failed");
> +            goto fail;
> +        }
> +    } else {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_GNTTAB_MAP_FOREIGN_PAGES
> not pending");
> +        Status = ERROR_UNIDENTIFIED_ERROR;
> +        goto fail;
> +    }
> +
> +    Request->Address = Out.Address;
> +    InsertTailList(&Xc->RequestList, &Request->ListEntry);
> +    Xc->RequestId++;
> +    LeaveCriticalSection(&Xc->RequestListLock);
> +
> +    *Address = Out.Address;
> +
> +    Log(XLL_DEBUG, L"Address: %p", *Address);
> +
> +    free(In);
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    LeaveCriticalSection(&Xc->RequestListLock);
> +    Log(XLL_ERROR, L"Error: 0x%x", Status);
> +    free(In);
> +    free(Request);
> +    return Status;
> +}
> +
> +DWORD
> +XcGnttabUnmapForeignPages(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PVOID Address
> +    )
> +{
> +    XENIFACE_GNTTAB_UNMAP_FOREIGN_PAGES_IN In;
> +    PXENCONTROL_GNTTAB_REQUEST Request;
> +    DWORD Returned;
> +    BOOL Success;
> +    DWORD Status;
> +
> +    Log(XLL_DEBUG, L"Address: %p", Address);
> +
> +    Status = ERROR_NOT_FOUND;
> +    Request = FindRequest(Xc, Address);
> +    if (!Request) {
> +        Log(XLL_ERROR, L"Address %p not mapped", Address);
> +        goto fail;
> +    }
> +
> +    In.RequestId = Request->Id;
> +
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_GNTTAB_UNMAP_FOREIGN_PAGES,
> +                              &In, sizeof(In),
> +                              NULL, 0,
> +                              &Returned,
> +                              NULL);
> +
> +    Status = GetLastError();
> +    if (!Success) {
> +        Log(XLL_ERROR,
> L"IOCTL_XENIFACE_GNTTAB_UNMAP_FOREIGN_PAGES failed");
> +        goto fail;
> +    }
> +
> +    EnterCriticalSection(&Xc->RequestListLock);
> +    RemoveEntryList(&Request->ListEntry);
> +    LeaveCriticalSection(&Xc->RequestListLock);
> +    free(Request);
> +
> +    return Status;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", Status);
> +    return Status;
> +}
> +
> +DWORD
> +XcStoreRead(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PSTR Path,
> +    IN  DWORD cbValue,
> +    OUT CHAR *Value
> +    )
> +{
> +    DWORD Returned;
> +    BOOL Success;
> +
> +    Log(XLL_DEBUG, L"Path: '%S'", Path);
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_STORE_READ,
> +                              Path, (DWORD)strlen(Path) + 1,
> +                              Value, cbValue,
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_STORE_READ failed");
> +        goto fail;
> +    }
> +
> +    Log(XLL_DEBUG, L"Value: '%S'", Value);
> +
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    return GetLastError();
> +}
> +
> +DWORD
> +XcStoreWrite(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path,
> +    IN  PCHAR Value
> +    )
> +{
> +    PCHAR Buffer;
> +    DWORD cbBuffer;
> +    DWORD Returned;
> +    BOOL Success;
> +
> +    cbBuffer = (DWORD)(strlen(Path) + 1 + strlen(Value) + 1 + 1);
> +    Buffer = malloc(cbBuffer);
> +    if (!Buffer) {
> +        SetLastError(ERROR_OUTOFMEMORY);
> +        goto fail;
> +    }
> +
> +    ZeroMemory(Buffer, cbBuffer);
> +    memcpy(Buffer, Path, strlen(Path));
> +    memcpy(Buffer + strlen(Path) + 1, Value, strlen(Value));
> +
> +    Log(XLL_DEBUG, L"Path: '%S', Value: '%S'", Path, Value);
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_STORE_WRITE,
> +                              Buffer, cbBuffer,
> +                              NULL, 0,
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_STORE_WRITE failed");
> +        goto fail;
> +    }
> +
> +    free(Buffer);
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    free(Buffer);
> +    return GetLastError();
> +}
> +
> +DWORD
> +XcStoreDirectory(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path,
> +    IN  DWORD cbOutput,
> +    OUT CHAR *Output
> +    )
> +{
> +    DWORD Returned;
> +    BOOL Success;
> +
> +    Log(XLL_DEBUG, L"Path: '%S'", Path);
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_STORE_DIRECTORY,
> +                              Path, (DWORD)strlen(Path) + 1,
> +                              Output, cbOutput,
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_STORE_DIRECTORY failed");
> +        goto fail;
> +    }
> +
> +    _LogMultiSz(Xc, __FUNCTION__, XLL_DEBUG, Output);
> +
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    return GetLastError();
> +}
> +
> +DWORD
> +XcStoreRemove(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path
> +    )
> +{
> +    DWORD Returned;
> +    BOOL Success;
> +
> +    Log(XLL_DEBUG, L"Path: '%S'", Path);
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_STORE_REMOVE,
> +                              Path, (DWORD)strlen(Path) + 1,
> +                              NULL, 0,
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_STORE_REMOVE failed");
> +        goto fail;
> +    }
> +
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    return GetLastError();
> +}
> +
> +DWORD
> +XcStoreSetPermissions(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path,
> +    IN  ULONG Count,
> +    IN  PXENIFACE_STORE_PERMISSION Permissions
> +    )
> +{
> +    DWORD Returned, Size;
> +    BOOL Success;
> +    XENIFACE_STORE_SET_PERMISSIONS_IN *In = NULL;
> +
> +    Log(XLL_DEBUG, L"Path: '%S', Count: %lu", Path, Count);
> +    for (ULONG i = 0; i < Count; i++)
> +        Log(XLL_DEBUG, L"Domain: %d, Mask: 0x%x", Permissions[i].Domain,
> Permissions[i].Mask);
> +
> +    Size = (ULONG)FIELD_OFFSET(XENIFACE_STORE_SET_PERMISSIONS_IN,
> Permissions[Count]);
> +    In = malloc(Size);
> +    if (!In) {
> +        SetLastError(ERROR_OUTOFMEMORY);
> +        goto fail;
> +    }
> +
> +    In->Path = Path;
> +    In->PathLength = (DWORD)strlen(In->Path) + 1;
> +    In->NumberPermissions = Count;
> +    memcpy(&In->Permissions, Permissions, Count *
> sizeof(XENIFACE_STORE_PERMISSION));
> +
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_STORE_SET_PERMISSIONS,
> +                              In, Size,
> +                              NULL, 0,
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_STORE_SET_PERMISSIONS failed");
> +        goto fail;
> +    }
> +
> +    free(In);
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    free(In);
> +    return GetLastError();
> +}
> +
> +DWORD
> +XcStoreAddWatch(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PCHAR Path,
> +    IN  HANDLE Event,
> +    OUT PVOID *Handle
> +    )
> +{
> +    DWORD Returned;
> +    BOOL Success;
> +    XENIFACE_STORE_ADD_WATCH_IN In;
> +    XENIFACE_STORE_ADD_WATCH_OUT Out;
> +
> +    Log(XLL_DEBUG, L"Path: '%S', Event: %p", Path, Event);
> +
> +    In.Path = Path;
> +    In.PathLength = (DWORD)strlen(Path) + 1;
> +    In.Event = Event;
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_STORE_ADD_WATCH,
> +                              &In, sizeof(In),
> +                              &Out, sizeof(Out),
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_STORE_ADD_WATCH failed");
> +        goto fail;
> +    }
> +
> +    *Handle = Out.Context;
> +
> +    Log(XLL_DEBUG, L"Handle: %p", *Handle);
> +
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    return GetLastError();
> +}
> +
> +DWORD
> +XcStoreRemoveWatch(
> +    IN  PXENCONTROL_CONTEXT Xc,
> +    IN  PVOID Handle
> +    )
> +{
> +    DWORD Returned;
> +    BOOL Success;
> +    XENIFACE_STORE_REMOVE_WATCH_IN In;
> +
> +    Log(XLL_DEBUG, L"Handle: %p", Handle);
> +
> +    In.Context = Handle;
> +    Success = DeviceIoControl(Xc->XenIface,
> +                              IOCTL_XENIFACE_STORE_REMOVE_WATCH,
> +                              &In, sizeof(In),
> +                              NULL, 0,
> +                              &Returned,
> +                              NULL);
> +
> +    if (!Success) {
> +        Log(XLL_ERROR, L"IOCTL_XENIFACE_STORE_REMOVE_WATCH failed");
> +        goto fail;
> +    }
> +
> +    return ERROR_SUCCESS;
> +
> +fail:
> +    Log(XLL_ERROR, L"Error: 0x%x", GetLastError());
> +    return GetLastError();
> +}
> diff --git a/src/xencontrol/xencontrol.rc b/src/xencontrol/xencontrol.rc
> new file mode 100644
> index 0000000..6c33e84
> --- /dev/null
> +++ b/src/xencontrol/xencontrol.rc
> @@ -0,0 +1,24 @@
> +#include <windows.h>
> +#include <ntverp.h>
> +
> +#undef VER_COMPANYNAME_STR
> +#undef VER_PRODUCTNAME_STR
> +#undef VER_PRODUCTVERSION
> +#undef VER_PRODUCTVERSION_STR
> +
> +#include <version.h>
> +
> +#define VER_COMPANYNAME_STR         VENDOR_NAME_STR
> +#define VER_LEGALCOPYRIGHT_STR      "Copyright (c) Invisible Things Lab"
> +
> +#define VER_PRODUCTNAME_STR         "XENIFACE"
> +#define VER_PRODUCTVERSION
> MAJOR_VERSION,MINOR_VERSION,MICRO_VERSION,BUILD_NUMBER
> +#define VER_PRODUCTVERSION_STR      MAJOR_VERSION_STR "."
> MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR
> +
> +#define VER_INTERNALNAME_STR        "XENCONTROL.DLL"
> +#define VER_FILEDESCRIPTION_STR     "Xen interface user library"
> +
> +#define VER_FILETYPE                VFT_DLL
> +#define VER_FILESUBTYPE             0
> +
> +#include <common.ver>
> diff --git a/src/xencontrol/xencontrol_private.h
> b/src/xencontrol/xencontrol_private.h
> new file mode 100644
> index 0000000..685bcfa
> --- /dev/null
> +++ b/src/xencontrol/xencontrol_private.h
> @@ -0,0 +1,49 @@
> +#ifndef _XENCONTROL_PRIVATE_H_
> +#define _XENCONTROL_PRIVATE_H_
> +
> +#include <windows.h>
> +#include "xencontrol.h"
> +
> +#define Log(level, format, ...) \
> +        _Log(Xc->Logger, level, Xc->LogLevel, __FUNCTION__, format,
> __VA_ARGS__)
> +
> +#define InitializeListHead(ListHead) ( \
> +    (ListHead)->Flink = (ListHead)->Blink = (ListHead))
> +
> +#define InsertTailList(ListHead, Entry) { \
> +    PLIST_ENTRY _EX_Blink; \
> +    PLIST_ENTRY _EX_ListHead; \
> +    _EX_ListHead = (ListHead); \
> +    _EX_Blink = _EX_ListHead->Blink; \
> +    (Entry)->Flink = _EX_ListHead; \
> +    (Entry)->Blink = _EX_Blink; \
> +    _EX_Blink->Flink = (Entry); \
> +    _EX_ListHead->Blink = (Entry); \
> +    }
> +
> +#define RemoveEntryList(Entry) { \
> +    PLIST_ENTRY _EX_Blink; \
> +    PLIST_ENTRY _EX_Flink; \
> +    _EX_Flink = (Entry)->Flink; \
> +    _EX_Blink = (Entry)->Blink; \
> +    _EX_Blink->Flink = _EX_Flink; \
> +    _EX_Flink->Blink = _EX_Blink; \
> +    }
> +
> +typedef struct _XENCONTROL_CONTEXT {
> +    HANDLE XenIface;
> +    XENCONTROL_LOGGER *Logger;
> +    XENCONTROL_LOG_LEVEL LogLevel;
> +    ULONG RequestId;
> +    LIST_ENTRY RequestList;
> +    CRITICAL_SECTION RequestListLock;
> +} XENCONTROL_CONTEXT, *PXENCONTROL_CONTEXT;
> +
> +typedef struct _XENCONTROL_GNTTAB_REQUEST {
> +    LIST_ENTRY  ListEntry;
> +    OVERLAPPED  Overlapped;
> +    ULONG       Id;
> +    PVOID       Address;
> +} XENCONTROL_GNTTAB_REQUEST, *PXENCONTROL_GNTTAB_REQUEST;
> +
> +#endif // _XENCONTROL_PRIVATE_H_
> diff --git a/vs2015/package/package.vcxproj
> b/vs2015/package/package.vcxproj
> index 0b8c7d0..34b07aa 100644
> --- a/vs2015/package/package.vcxproj
> +++ b/vs2015/package/package.vcxproj
> @@ -42,6 +42,9 @@
>      <ProjectReference Include="..\xenagent\xenagent.vcxproj">
>        <Project>{2E61D2CC-865E-442C-8C83-B8DAFD7BBD3B}</Project>
>      </ProjectReference>
> +    <ProjectReference Include="..\xencontrol\xencontrol.vcxproj">
> +      <Project>{D386D8E9-D015-4AD2-A5C2-4F845A803FA2}</Project>
> +    </ProjectReference>
>    </ItemGroup>
>    <ItemGroup>
>      <FilesToPackage Include="$(DPINST_REDIST)\x86\dpinst.exe"
> Condition="'$(Platform)'=='Win32'" />
> diff --git a/vs2015/xencontrol/xencontrol.vcxproj
> b/vs2015/xencontrol/xencontrol.vcxproj
> new file mode 100644
> index 0000000..d1be4ca
> --- /dev/null
> +++ b/vs2015/xencontrol/xencontrol.vcxproj
> @@ -0,0 +1,67 @@
> +<?xml version="1.0" encoding="utf-8"?>
> +<Project DefaultTargets="Build" ToolsVersion="14.0"
> xmlns="http://schemas.microsoft.com/developer/msbuild/2003";>
> +  <Import Project="..\configs.props" />
> +  <PropertyGroup Label="PropertySheets">
> +    <CharacterSet>Unicode</CharacterSet>
> +    <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
> +    <ConfigurationType>DynamicLibrary</ConfigurationType>
> +  </PropertyGroup>
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
> +  <PropertyGroup Label="Globals">
> +    <ProjectGuid>{D386D8E9-D015-4AD2-A5C2-
> 4F845A803FA2}</ProjectGuid>
> +  </PropertyGroup>
> +  <Import Project="..\targets.props" />
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
> +  <PropertyGroup>
> +    <IncludePath>$(IncludePath)</IncludePath>
> +    <RunCodeAnalysis>true</RunCodeAnalysis>
> +    <EnableInf2cat>false</EnableInf2cat>
> +  </PropertyGroup>
> +  <ItemDefinitionGroup>
> +    <ClCompile>
> +
> <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDi
> rectories)</AdditionalIncludeDirectories>
> +
> <PreprocessorDefinitions>WIN32;_WINDOWS;_USRDLL;XENCONTROL_EXPO
> RTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <WarningLevel>EnableAllWarnings</WarningLevel>
> +
> <DisableSpecificWarnings>4127;4711;4548;4820;4668;4255;5045;6001;6054;28
> 196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
> +      <MultiProcessorCompilation>true</MultiProcessorCompilation>
> +      <EnablePREfast>true</EnablePREfast>
> +      <ExceptionHandling>false</ExceptionHandling>
> +      <TreatWarningAsError>true</TreatWarningAsError>
> +      <RuntimeLibrary
> Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</Runtime
> Library>
> +      <RuntimeLibrary
> Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrar
> y>
> +    </ClCompile>
> +    <Link>
> +
> <AdditionalDependencies>setupapi.lib;ws2_32.lib;shlwapi.lib;wtsapi32.lib;us
> erenv.lib;version.lib;ntdll.lib;kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;adv
> api32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;%(AdditionalDependencies)
> </AdditionalDependencies>
> +    </Link>
> +    <ResourceCompile>
> +
> <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDi
> rectories)</AdditionalIncludeDirectories>
> +    </ResourceCompile>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
> +    <ClCompile>
> +
> <PreprocessorDefinitions>__i386__;%(PreprocessorDefinitions)</Preproces
> sorDefinitions>
> +    </ClCompile>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
> +    <ClCompile>
> +
> <PreprocessorDefinitions>__x86_64__;%(PreprocessorDefinitions)</Prepro
> cessorDefinitions>
> +    </ClCompile>
> +  </ItemDefinitionGroup>
> +  <ItemGroup>
> +    <FilesToPackage Include="$(TargetPath)" />
> +    <FilesToPackage Include="$(OutDir)$(TargetName).pdb" />
> +    <FilesToPackage Include="$(OutDir)$(TargetName).dll" />
> +    <FilesToPackage Include="$(OutDir)$(TargetName).lib" />
> +  </ItemGroup>
> +  <ItemGroup>
> +    <ClCompile Include="..\..\src\xencontrol\xencontrol.c" />
> +  </ItemGroup>
> +  <ItemGroup>
> +    <ClInclude Include="..\..\include\xencontrol.h" />
> +    <ClInclude Include="..\..\src\xencontrol\xencontrol_private.h" />
> +  </ItemGroup>
> +  <ItemGroup>
> +    <ResourceCompile Include="..\..\src\xencontrol\xencontrol.rc" />
> +  </ItemGroup>
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
> +</Project>
> diff --git a/vs2015/xeniface.sln b/vs2015/xeniface.sln
> index 040f071..7f08c1c 100644
> --- a/vs2015/xeniface.sln
> +++ b/vs2015/xeniface.sln
> @@ -15,6 +15,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")
> = "package", "package\package.
>               {2E61D2CC-865E-442C-8C83-B8DAFD7BBD3B} = {2E61D2CC-
> 865E-442C-8C83-B8DAFD7BBD3B}
>       EndProjectSection
>  EndProject
> +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xencontrol",
> "xencontrol\xencontrol.vcxproj", "{D386D8E9-D015-4AD2-A5C2-
> 4F845A803FA2}"
> +EndProject
>  Global
>       GlobalSection(SolutionConfigurationPlatforms) = preSolution
>               Windows 8 Debug|Win32 = Windows 8 Debug|Win32
> @@ -123,6 +125,30 @@ Global
>               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 10
> Release|x64.ActiveCfg = Windows 10 Release|x64
>               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 10
> Release|x64.Build.0 = Windows 10 Release|x64
>               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 10
> Release|x64.Deploy.0 = Windows 10 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|Win32.ActiveCfg = Windows 8 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|Win32.Build.0 = Windows 8 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|Win32.Deploy.0 = Windows 8 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|x64.ActiveCfg = Windows 8 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|x64.Build.0 = Windows 8 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|x64.Deploy.0 = Windows 8 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|Win32.ActiveCfg = Windows 8 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|Win32.Build.0 = Windows 8 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|Win32.Deploy.0 = Windows 8 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|x64.ActiveCfg = Windows 8 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|x64.Build.0 = Windows 8 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|x64.Deploy.0 = Windows 8 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|Win32.ActiveCfg = Windows 10 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|Win32.Build.0 = Windows 10 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|Win32.Deploy.0 = Windows 10 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|x64.ActiveCfg = Windows 10 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|x64.Build.0 = Windows 10 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|x64.Deploy.0 = Windows 10 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|Win32.ActiveCfg = Windows 10 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|Win32.Build.0 = Windows 10 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|Win32.Deploy.0 = Windows 10 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|x64.ActiveCfg = Windows 10 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|x64.Build.0 = Windows 10 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|x64.Deploy.0 = Windows 10 Release|x64
>       EndGlobalSection
>       GlobalSection(SolutionProperties) = preSolution
>               HideSolutionNode = FALSE
> diff --git a/vs2017/package/package.vcxproj
> b/vs2017/package/package.vcxproj
> index 764511b..f9fd507 100644
> --- a/vs2017/package/package.vcxproj
> +++ b/vs2017/package/package.vcxproj
> @@ -42,6 +42,9 @@
>      <ProjectReference Include="..\xenagent\xenagent.vcxproj">
>        <Project>{2E61D2CC-865E-442C-8C83-B8DAFD7BBD3B}</Project>
>      </ProjectReference>
> +    <ProjectReference Include="..\xencontrol\xencontrol.vcxproj">
> +      <Project>{D386D8E9-D015-4AD2-A5C2-4F845A803FA2}</Project>
> +    </ProjectReference>
>    </ItemGroup>
>    <ItemGroup>
>      <FilesToPackage Include="$(DPINST_REDIST)\x86\dpinst.exe"
> Condition="'$(Platform)'=='Win32'" />
> diff --git a/vs2017/xencontrol/xencontrol.vcxproj
> b/vs2017/xencontrol/xencontrol.vcxproj
> new file mode 100644
> index 0000000..18f471c
> --- /dev/null
> +++ b/vs2017/xencontrol/xencontrol.vcxproj
> @@ -0,0 +1,67 @@
> +<?xml version="1.0" encoding="utf-8"?>
> +<Project DefaultTargets="Build" ToolsVersion="15.0"
> xmlns="http://schemas.microsoft.com/developer/msbuild/2003";>
> +  <Import Project="..\configs.props" />
> +  <PropertyGroup Label="PropertySheets">
> +    <CharacterSet>Unicode</CharacterSet>
> +    <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset>
> +    <ConfigurationType>DynamicLibrary</ConfigurationType>
> +  </PropertyGroup>
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
> +  <PropertyGroup Label="Globals">
> +    <ProjectGuid>{D386D8E9-D015-4AD2-A5C2-
> 4F845A803FA2}</ProjectGuid>
> +  </PropertyGroup>
> +  <Import Project="..\targets.props" />
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
> +  <PropertyGroup>
> +    <IncludePath>$(IncludePath)</IncludePath>
> +    <RunCodeAnalysis>true</RunCodeAnalysis>
> +    <EnableInf2cat>false</EnableInf2cat>
> +  </PropertyGroup>
> +  <ItemDefinitionGroup>
> +    <ClCompile>
> +
> <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDi
> rectories)</AdditionalIncludeDirectories>
> +
> <PreprocessorDefinitions>WIN32;_WINDOWS;_USRDLL;XENCONTROL_EXPO
> RTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
> +      <WarningLevel>EnableAllWarnings</WarningLevel>
> +
> <DisableSpecificWarnings>4127;4711;4548;4820;4668;4255;5045;6001;6054;28
> 196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
> +      <MultiProcessorCompilation>true</MultiProcessorCompilation>
> +      <EnablePREfast>true</EnablePREfast>
> +      <ExceptionHandling>false</ExceptionHandling>
> +      <TreatWarningAsError>true</TreatWarningAsError>
> +      <RuntimeLibrary
> Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</Runtime
> Library>
> +      <RuntimeLibrary
> Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrar
> y>
> +    </ClCompile>
> +    <Link>
> +
> <AdditionalDependencies>setupapi.lib;ws2_32.lib;shlwapi.lib;wtsapi32.lib;us
> erenv.lib;version.lib;ntdll.lib;kernel32.lib;user32.lib;gdi32.lib;comdlg32.lib;adv
> api32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;%(AdditionalDependencies)
> </AdditionalDependencies>
> +    </Link>
> +    <ResourceCompile>
> +
> <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDi
> rectories)</AdditionalIncludeDirectories>
> +    </ResourceCompile>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
> +    <ClCompile>
> +
> <PreprocessorDefinitions>__i386__;%(PreprocessorDefinitions)</Preproces
> sorDefinitions>
> +    </ClCompile>
> +  </ItemDefinitionGroup>
> +  <ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
> +    <ClCompile>
> +
> <PreprocessorDefinitions>__x86_64__;%(PreprocessorDefinitions)</Prepro
> cessorDefinitions>
> +    </ClCompile>
> +  </ItemDefinitionGroup>
> +  <ItemGroup>
> +    <FilesToPackage Include="$(TargetPath)" />
> +    <FilesToPackage Include="$(OutDir)$(TargetName).pdb" />
> +    <FilesToPackage Include="$(OutDir)$(TargetName).dll" />
> +    <FilesToPackage Include="$(OutDir)$(TargetName).lib" />
> +  </ItemGroup>
> +  <ItemGroup>
> +    <ClCompile Include="..\..\src\xencontrol\xencontrol.c" />
> +  </ItemGroup>
> +  <ItemGroup>
> +    <ClInclude Include="..\..\include\xencontrol.h" />
> +    <ClInclude Include="..\..\src\xencontrol\xencontrol_private.h" />
> +  </ItemGroup>
> +  <ItemGroup>
> +    <ResourceCompile Include="..\..\src\xencontrol\xencontrol.rc" />
> +  </ItemGroup>
> +  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
> +</Project>
> diff --git a/vs2017/xeniface.sln b/vs2017/xeniface.sln
> index 040f071..1eb8156 100644
> --- a/vs2017/xeniface.sln
> +++ b/vs2017/xeniface.sln
> @@ -8,11 +8,14 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}")
> = "xeniface", "xeniface\xenifa
>  EndProject
>  Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xenagent",
> "xenagent\xenagent.vcxproj", "{2E61D2CC-865E-442C-8C83-
> B8DAFD7BBD3B}"
>  EndProject
> +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xencontrol",
> "xencontrol\xencontrol.vcxproj", "{D386D8E9-D015-4AD2-A5C2-
> 4F845A803FA2}"
> +EndProject
>  Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package",
> "package\package.vcxproj", "{9B071A35-897C-477A-AEB7-95F77618A21D}"
>       ProjectSection(ProjectDependencies) = postProject
>               {22166290-65D8-49D2-BB88-33201797C7D8} = {22166290-
> 65D8-49D2-BB88-33201797C7D8}
>               {85C731AD-2EA2-4049-A542-D2D38EDE938C} = {85C731AD-
> 2EA2-4049-A542-D2D38EDE938C}
>               {2E61D2CC-865E-442C-8C83-B8DAFD7BBD3B} = {2E61D2CC-
> 865E-442C-8C83-B8DAFD7BBD3B}
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2} = {D386D8E9-
> D015-4AD2-A5C2-4F845A803FA2}
>       EndProjectSection
>  EndProject
>  Global
> @@ -123,6 +126,30 @@ Global
>               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 10
> Release|x64.ActiveCfg = Windows 10 Release|x64
>               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 10
> Release|x64.Build.0 = Windows 10 Release|x64
>               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 10
> Release|x64.Deploy.0 = Windows 10 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|Win32.ActiveCfg = Windows 8 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|Win32.Build.0 = Windows 8 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|Win32.Deploy.0 = Windows 8 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|x64.ActiveCfg = Windows 8 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|x64.Build.0 = Windows 8 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Debug|x64.Deploy.0 = Windows 8 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|Win32.ActiveCfg = Windows 8 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|Win32.Build.0 = Windows 8 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|Win32.Deploy.0 = Windows 8 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|x64.ActiveCfg = Windows 8 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|x64.Build.0 = Windows 8 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 8
> Release|x64.Deploy.0 = Windows 8 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|Win32.ActiveCfg = Windows 10 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|Win32.Build.0 = Windows 10 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|Win32.Deploy.0 = Windows 10 Debug|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|x64.ActiveCfg = Windows 10 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|x64.Build.0 = Windows 10 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Debug|x64.Deploy.0 = Windows 10 Debug|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|Win32.ActiveCfg = Windows 10 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|Win32.Build.0 = Windows 10 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|Win32.Deploy.0 = Windows 10 Release|Win32
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|x64.ActiveCfg = Windows 10 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|x64.Build.0 = Windows 10 Release|x64
> +             {D386D8E9-D015-4AD2-A5C2-4F845A803FA2}.Windows 10
> Release|x64.Deploy.0 = Windows 10 Release|x64
>       EndGlobalSection
>       GlobalSection(SolutionProperties) = preSolution
>               HideSolutionNode = FALSE
> --
> 2.13.6
> 
> 
> _______________________________________________
> win-pv-devel mailing list
> win-pv-devel@xxxxxxxxxxxxxxxxxxxx
> https://lists.xenproject.org/mailman/listinfo/win-pv-devel
_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.