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

[win-pv-devel] [PATCH 2/4] Move filter installation and active device selection logic into drivers



When XENBUS creates its FDO object it will query up to XENFILT for a new
PDEVICE interface. This is used for getting/setting the active device
instance.

If the query fails then it is taken to mean that XENFILT has not been
installed into the system class UpperFilters and so this is done, and a
reboot requested (the FDO creation succeeding but remaining inactive).

If the query succeeds then the code attempts to get the active device
instance. If that succeeds then then the FDO identity is checked to see if
it should be active. If, however, it fails then the code attempts to
claim the active device instance.

When XENBUS destroys its FDO object then the active device instance is
cleared (if the FDO was active) and XENFILT is removed from UpperFilters.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 include/pvdevice_interface.h   | 132 +++++++++
 src/coinst/coinst.c            | 651 ++++-------------------------------------
 src/xen/driver.c               | 136 ++++++---
 src/xenbus/driver.c            | 314 ++++----------------
 src/xenbus/driver.h            |  15 +
 src/xenbus/fdo.c               | 298 ++++++++++++++++---
 src/xenbus/fdo.h               |   3 +-
 src/xenbus/filters.c           | 319 ++++++++++++++++++++
 src/xenbus/filters.h           |  45 +++
 src/xenbus/pdo.c               |   2 +-
 src/xenfilt/driver.c           | 273 ++++++-----------
 src/xenfilt/driver.h           |  21 +-
 src/xenfilt/emulated.c         |  39 +--
 src/xenfilt/emulated.h         |   4 +-
 src/xenfilt/fdo.c              |  75 ++---
 src/xenfilt/fdo.h              |   9 +-
 src/xenfilt/pdo.c              | 131 +++++----
 src/xenfilt/pdo.h              |   4 +-
 src/xenfilt/pvdevice.c         | 439 +++++++++++++++++++++++++++
 src/xenfilt/pvdevice.h         |  59 ++++
 vs2012/xenbus/xenbus.vcxproj   |   1 +
 vs2012/xenfilt/xenfilt.vcxproj |   1 +
 vs2013/xenbus/xenbus.vcxproj   |   1 +
 vs2013/xenfilt/xenfilt.vcxproj |   1 +
 24 files changed, 1726 insertions(+), 1247 deletions(-)
 create mode 100644 include/pvdevice_interface.h
 create mode 100644 src/xenbus/filters.c
 create mode 100644 src/xenbus/filters.h
 create mode 100644 src/xenfilt/pvdevice.c
 create mode 100644 src/xenfilt/pvdevice.h

diff --git a/include/pvdevice_interface.h b/include/pvdevice_interface.h
new file mode 100644
index 0000000..9024396
--- /dev/null
+++ b/include/pvdevice_interface.h
@@ -0,0 +1,132 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*! \file pvdevice_interface.h
+    \brief XENFILT PVDEVICE Interface
+
+    This interface provides primitives to determine whether a pvdevice
+    device is active (and claim the active device id if not)
+*/
+
+#ifndef _XENFILT_PVDEVICE_INTERFACE_H
+#define _XENFILT_PVDEVICE_INTERFACE_H
+
+#ifndef _WINDLL
+
+/*! \typedef XENFILT_PVDEVICE_ACQUIRE
+    \brief Acquire a reference to the PVDEVICE interface
+
+    \param Interface The interface header
+*/
+typedef NTSTATUS
+(*XENFILT_PVDEVICE_ACQUIRE)(
+    IN  PINTERFACE  Interface
+    );
+
+/*! \typedef XENFILT_PVDEVICE_RELEASE
+    \brief Release a reference to the PVDEVICE interface
+
+    \param Interface The interface header
+*/
+typedef VOID
+(*XENFILT_PVDEVICE_RELEASE)(
+    IN  PINTERFACE  Interface
+    );
+
+/*! \typedef XENFILT_PVDEVICE_GET_ACTIVE
+    \brief Get the active device instance
+
+    \param Interface The interface header
+    \param DeviceID A buffer of length MAXNAMELEN to receive the device id
+    \param InstanceID A buffer of length MAXNAMELEN to receive the instance id
+*/
+typedef NTSTATUS
+(*XENFILT_PVDEVICE_GET_ACTIVE)(
+    IN  PVOID   Context,
+    OUT PCHAR   DeviceID,
+    OUT PCHAR   InstanceID
+    );
+
+/*! \typedef XENFILT_PVDEVICE_SET_ACTIVE
+    \brief Set the active device instance
+
+    \param Interface The interface header
+    \param DeviceID Buffer containing the device id
+    \param InstanceID Buffer containing the instance id
+*/
+typedef NTSTATUS
+(*XENFILT_PVDEVICE_SET_ACTIVE)(
+    IN  PVOID   Context,
+    IN  PCHAR   DeviceID,
+    IN  PCHAR   InstanceID
+    );
+
+/*! \typedef XENFILT_PVDEVICE_CLEAR_ACTIVE
+    \brief Clear the active device instance
+
+    \param Interface The interface header
+*/
+typedef NTSTATUS
+(*XENFILT_PVDEVICE_CLEAR_ACTIVE)(
+    IN  PVOID   Context
+    );
+
+// {7d09b250-898f-4fea-b7fa-e0490e46f95f}
+DEFINE_GUID(GUID_XENFILT_PVDEVICE_INTERFACE,
+0x7d09b250, 0x898f, 0x4fea, 0xb7, 0xfa, 0xe0, 0x49, 0x0e, 0x46, 0xf9, 0x5f);
+
+/*! \struct _XENFILT_PVDEVICE_INTERFACE_V1
+    \brief PVDEVICE interface version 1
+    \ingroup interfaces
+*/
+struct _XENFILT_PVDEVICE_INTERFACE_V1 {
+    INTERFACE                       Interface;
+    XENFILT_PVDEVICE_ACQUIRE        PvdeviceAcquire;
+    XENFILT_PVDEVICE_RELEASE        PvdeviceRelease;
+    XENFILT_PVDEVICE_GET_ACTIVE     PvdeviceGetActive;
+    XENFILT_PVDEVICE_SET_ACTIVE     PvdeviceSetActive;
+    XENFILT_PVDEVICE_CLEAR_ACTIVE   PvdeviceClearActive;
+};
+
+typedef struct _XENFILT_PVDEVICE_INTERFACE_V1 XENFILT_PVDEVICE_INTERFACE, 
*PXENFILT_PVDEVICE_INTERFACE;
+
+/*! \def XENFILT_PVDEVICE
+    \brief Macro at assist in method invocation
+*/
+#define XENFILT_PVDEVICE(_Method, _Interface, ...)    \
+    (_Interface)->Pvdevice ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
+
+#endif  // _WINDLL
+
+#define XENFILT_PVDEVICE_INTERFACE_VERSION_MIN  1
+#define XENFILT_PVDEVICE_INTERFACE_VERSION_MAX  1
+
+#endif  // _XENFILT_PVDEVICE_INTERFACE_H
diff --git a/src/coinst/coinst.c b/src/coinst/coinst.c
index 2b980a1..5e6f719 100644
--- a/src/coinst/coinst.c
+++ b/src/coinst/coinst.c
@@ -49,12 +49,6 @@ __user_code;
 
 #define SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services"
 
-#define SERVICE_KEY(_Driver)    \
-        SERVICES_KEY ## "\\" ## #_Driver
-
-#define PARAMETERS_KEY(_Driver) \
-        SERVICE_KEY(_Driver) ## "\\Parameters"
-
 #define CONTROL_KEY "SYSTEM\\CurrentControlSet\\Control"
 
 #define CLASS_KEY   \
@@ -758,289 +752,6 @@ fail1:
     return FALSE;
 }
 
-static BOOLEAN
-GetActiveDeviceInstanceID(
-    OUT PTCHAR  *DeviceID,
-    OUT PTCHAR  *InstanceID
-    )
-{
-    HKEY        ParametersKey;
-    DWORD       MaxValueLength;
-    DWORD       DeviceIDLength;
-    DWORD       InstanceIDLength;
-    DWORD       Type;
-    HRESULT     Error;
-
-    Error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
-                           PARAMETERS_KEY(XENBUS),
-                           0,
-                           NULL,
-                           REG_OPTION_NON_VOLATILE,
-                           KEY_ALL_ACCESS,
-                           NULL,
-                           &ParametersKey,
-                           NULL);
-    if (Error != ERROR_SUCCESS) {
-        SetLastError(Error);
-        goto fail1;
-    }
-
-    Error = RegQueryInfoKey(ParametersKey,
-                            NULL,
-                            NULL,
-                            NULL,    
-                            NULL,
-                            NULL,
-                            NULL,
-                            NULL,
-                            NULL,
-                            &MaxValueLength,
-                            NULL,
-                            NULL);
-    if (Error != ERROR_SUCCESS) {
-        SetLastError(Error);
-        goto fail2;
-    }
-       
-    DeviceIDLength = MaxValueLength + sizeof (TCHAR);
-
-    *DeviceID = calloc(1, DeviceIDLength);
-    if (*DeviceID == NULL)
-        goto fail3;
-
-    Error = RegQueryValueEx(ParametersKey,
-                            "ActiveDeviceID",
-                            NULL,
-                            &Type,
-                            (LPBYTE)*DeviceID,
-                            &DeviceIDLength);
-    if (Error != ERROR_SUCCESS || Type != REG_SZ) {
-        free(*DeviceID);
-        *DeviceID = NULL;
-    }
-
-    InstanceIDLength = MaxValueLength + sizeof (TCHAR);
-
-    *InstanceID = calloc(1, InstanceIDLength);
-    if (*InstanceID == NULL)
-        goto fail4;
-
-    Error = RegQueryValueEx(ParametersKey,
-                            "ActiveInstanceID",
-                            NULL,
-                            &Type,
-                            (LPBYTE)*InstanceID,
-                            &InstanceIDLength);
-    if (Error != ERROR_SUCCESS || Type != REG_SZ) {
-        free(*InstanceID);
-        *InstanceID = NULL;
-    }
-
-    Log("DeviceID = %s", (*DeviceID != NULL) ? *DeviceID : "NOT SET");
-    Log("InstanceID = %s", (*InstanceID != NULL) ? *InstanceID : "NOT SET");
-
-    RegCloseKey(ParametersKey);
-
-    return TRUE;
-
-fail4:
-    Log("fail4");
-
-    if (*DeviceID != NULL) {
-        free(*DeviceID);
-        *DeviceID = NULL;
-    }
-
-fail3:
-    Log("fail3");
-
-fail2:
-    Log("fail2");
-
-    RegCloseKey(ParametersKey);
-
-fail1:
-    Error = GetLastError();
-
-    {
-        PTCHAR  Message;
-
-        Message = GetErrorMessage(Error);
-        Log("fail1 (%s)", Message);
-        LocalFree(Message);
-    }
-
-    return FALSE;
-}
-
-static BOOLEAN
-SetActiveDeviceInstanceID(
-    IN  PTCHAR  DeviceID,
-    IN  PTCHAR  InstanceID
-    )
-{
-    PTCHAR      DeviceName;
-    BOOLEAN     Success;
-    DWORD       DeviceIDLength;
-    DWORD       InstanceIDLength;
-    HKEY        ParametersKey;
-    HRESULT     Error;
-
-    Log("DeviceID = %s", DeviceID);
-    Log("InstanceID = %s", InstanceID);
-
-    DeviceName = strchr(DeviceID, '\\');
-    assert(DeviceName != NULL);
-    DeviceName++;
-
-    // Check whether we are binding to the XenServer vendor device
-    if (strncmp(DeviceName,
-                XENSERVER_VENDOR_DEVICE_NAME,
-                strlen(XENSERVER_VENDOR_DEVICE_NAME)) != 0) {
-        PTCHAR  DeviceKeyName;
-
-        // We are binding to a legacy platform device so only make it
-        // active if there is no XenServer vendor device
-        Success = GetDeviceKeyName("PCI",
-                                   XENSERVER_VENDOR_DEVICE_NAME,
-                                   &DeviceKeyName);
-        if (!Success)
-            goto fail1;
-
-        if (DeviceKeyName != NULL) {
-            Log("ignoring");
-            free(DeviceKeyName);
-            goto done;
-        }
-    }
-
-    DeviceIDLength = (DWORD)((strlen(DeviceID) +
-                              1) * sizeof (TCHAR));
-    InstanceIDLength = (DWORD)((strlen(InstanceID) +
-                                1) * sizeof (TCHAR));
-
-    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                         PARAMETERS_KEY(XENBUS),
-                         0,
-                         KEY_ALL_ACCESS,
-                         &ParametersKey);
-    if (Error != ERROR_SUCCESS) {
-        SetLastError(Error);
-        goto fail2;
-    }
-
-    Error = RegSetValueEx(ParametersKey,
-                          "ActiveDeviceID",
-                          0,
-                          REG_SZ,
-                          (LPBYTE)DeviceID,
-                          DeviceIDLength);
-    if (Error != ERROR_SUCCESS) {
-        SetLastError(Error);
-        goto fail3;
-    }
-
-    Error = RegSetValueEx(ParametersKey,
-                          "ActiveInstanceID",
-                          0,
-                          REG_SZ,
-                          (LPBYTE)InstanceID,
-                          InstanceIDLength);
-    if (Error != ERROR_SUCCESS) {
-        SetLastError(Error);
-        goto fail4;
-    }
-
-    RegCloseKey(ParametersKey);
-
-done:
-    return TRUE;
-
-fail4:
-    Log("fail4");
-
-fail3:
-    Log("fail3");
-
-    RegCloseKey(ParametersKey);
-
-fail2:
-    Log("fail2");
-
-fail1:
-    Error = GetLastError();
-
-    {
-        PTCHAR  Message;
-
-        Message = GetErrorMessage(Error);
-        Log("fail1 (%s)", Message);
-        LocalFree(Message);
-    }
-
-    return FALSE;
-}
-
-static BOOLEAN
-ClearActiveDeviceInstanceID(
-    VOID
-    )
-{
-    HKEY        ParametersKey;
-    HRESULT     Error;
-
-    Log("<===>");
-
-    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                         PARAMETERS_KEY(XENBUS),
-                         0,
-                         KEY_ALL_ACCESS,
-                         &ParametersKey);
-    if (Error != ERROR_SUCCESS) {
-        SetLastError(Error);
-        goto fail1;
-    }
-
-    Error = RegDeleteValue(ParametersKey,
-                           "ActiveDeviceID");
-    if (Error != ERROR_SUCCESS) {
-        SetLastError(Error);
-        goto fail2;
-    }
-
-    Error = RegDeleteValue(ParametersKey,
-                           "ActiveInstanceID");
-    if (Error != ERROR_SUCCESS) {
-        SetLastError(Error);
-        goto fail3;
-    }
-
-    RegCloseKey(ParametersKey);
-
-    return TRUE;
-
-fail3:
-    Log("fail3");
-
-fail2:
-    Log("fail2");
-
-    RegCloseKey(ParametersKey);
-
-fail1:
-    Error = GetLastError();
-
-    {
-        PTCHAR  Message;
-
-        Message = GetErrorMessage(Error);
-        Log("fail1 (%s)", Message);
-        LocalFree(Message);
-    }
-
-    return FALSE;
-}
-
 static PTCHAR
 GetProperty(
     IN  HDEVINFO            DeviceInfoSet,
@@ -1604,217 +1315,80 @@ fail1:
 }
 
 static BOOLEAN
-InstallFilter(
-    IN  const GUID  *Guid,
-    IN  PTCHAR      Filter
+CheckStatus(
+    IN  PTCHAR      DriverName,
+    OUT PBOOLEAN    NeedReboot
     )
 {
+    TCHAR           StatusKeyName[MAX_PATH];
+    HKEY            StatusKey;
+    HRESULT         Result;
     HRESULT         Error;
+    DWORD           ValueLength;
+    DWORD           Value;
     DWORD           Type;
-    DWORD           OldLength;
-    DWORD           NewLength;
-    PTCHAR          UpperFilters;
-    ULONG           Offset;
-
-    if (!SetupDiGetClassRegistryProperty(Guid,
-                                         SPCRP_UPPERFILTERS,
-                                         &Type,
-                                         NULL,
-                                         0,
-                                         &OldLength,
-                                         NULL,
-                                         NULL)) {
-        Error = GetLastError();
-
-        if (Error == ERROR_INVALID_DATA) {
-            Type = REG_MULTI_SZ;
-            OldLength = sizeof (TCHAR);
-        } else if (Error != ERROR_INSUFFICIENT_BUFFER) {
-            goto fail1;
-        }
-    }
-
-    if (Type != REG_MULTI_SZ) {
-        SetLastError(ERROR_BAD_FORMAT);
-        goto fail2;
-    }
-
-    NewLength = OldLength + (DWORD)((strlen(Filter) + 1) * sizeof (TCHAR));
-
-    UpperFilters = calloc(1, NewLength);
-    if (UpperFilters == NULL)
-        goto fail3;
-
-    Offset = 0;
-    if (OldLength != sizeof (TCHAR)) {
-        if (!SetupDiGetClassRegistryProperty(Guid,
-                                             SPCRP_UPPERFILTERS,
-                                             &Type,
-                                             (PBYTE)UpperFilters,
-                                             OldLength,
-                                             NULL,
-                                             NULL,
-                                             NULL))
-            goto fail4;
 
-        while (UpperFilters[Offset] != '\0') {
-            ULONG   FilterLength;
-
-            FilterLength = (ULONG)strlen(&UpperFilters[Offset]) / sizeof 
(TCHAR);
-
-            if (_stricmp(&UpperFilters[Offset], Filter) == 0) {
-                Log("%s already present", Filter);
-                goto done;
-            }
-
-            Offset += FilterLength + 1;
-        }
-    }
-
-    memmove(&UpperFilters[Offset], Filter, strlen(Filter));
-    Log("added %s", Filter);
-
-    if (!SetupDiSetClassRegistryProperty(Guid,
-                                         SPCRP_UPPERFILTERS,
-                                         (PBYTE)UpperFilters,
-                                         NewLength,
-                                         NULL,
-                                         NULL))
-        goto fail5;
-
-done:
-    free(UpperFilters);
-
-    return TRUE;
-
-fail5:
-    Log("fail5");
-
-fail4:
-    Log("fail4");
-
-    free(UpperFilters);
-
-fail3:
-    Log("fail3");
-
-fail2:
-    Log("fail2");
-
-fail1:
-    Error = GetLastError();
-
-    {
-        PTCHAR  Message;
+    Result = StringCbPrintf(StatusKeyName,
+                            MAX_PATH,
+                            SERVICES_KEY "\\%s\\Status",
+                            DriverName);
+    assert(SUCCEEDED(Result));
 
-        Message = GetErrorMessage(Error);
-        Log("fail1 (%s)", Message);
-        LocalFree(Message);
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         StatusKeyName,
+                         0,
+                         KEY_READ,
+                         &StatusKey);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail1;
     }
 
-    return FALSE;
-}
+    ValueLength = sizeof (Value);
 
-static BOOLEAN
-RemoveFilter(
-    IN  const GUID  *Guid,
-    IN  PTCHAR      Filter
-    )
-{
-    HRESULT         Error;
-    DWORD           Type;
-    DWORD           OldLength;
-    DWORD           NewLength;
-    PTCHAR          UpperFilters;
-    ULONG           Offset;
-    ULONG           FilterLength;
-
-    if (!SetupDiGetClassRegistryProperty(Guid,
-                                         SPCRP_UPPERFILTERS,
-                                         &Type,
-                                         NULL,
-                                         0,
-                                         &OldLength,
-                                         NULL,
-                                         NULL)) {
-        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
-            goto fail1;
+    Error = RegQueryValueEx(StatusKey,
+                            "NeedReboot",
+                            NULL,
+                            &Type,
+                            (LPBYTE)&Value,
+                            &ValueLength);
+    if (Error != ERROR_SUCCESS) {
+        if (Error == ERROR_FILE_NOT_FOUND) {
+            Type = REG_DWORD;
+            Value = 0;
+        } else {
+            SetLastError(Error);
+            goto fail2;
+        }
     }
 
-    if (Type != REG_MULTI_SZ) {
+    if (Type != REG_DWORD) {
         SetLastError(ERROR_BAD_FORMAT);
-        goto fail2;
-    }
-
-    UpperFilters = calloc(1, OldLength);
-    if (UpperFilters == NULL)
         goto fail3;
-
-    if (!SetupDiGetClassRegistryProperty(Guid,
-                                         SPCRP_UPPERFILTERS,
-                                         &Type,
-                                         (PBYTE)UpperFilters,
-                                         OldLength,
-                                         NULL,
-                                         NULL,
-                                         NULL))
-        goto fail4;
-
-    Offset = 0;
-    FilterLength = 0;
-    while (UpperFilters[Offset] != '\0') {
-        FilterLength = (ULONG)strlen(&UpperFilters[Offset]) / sizeof (TCHAR);
-
-        if (_stricmp(&UpperFilters[Offset], Filter) == 0)
-            goto remove;
-
-        Offset += FilterLength + 1;
     }
 
-    goto done;
-
-remove:
-    NewLength = OldLength - ((FilterLength + 1) * sizeof (TCHAR));
+    *NeedReboot = (Value != 0) ? TRUE : FALSE;
 
-    memmove(&UpperFilters[Offset],
-            &UpperFilters[Offset + FilterLength + 1],
-            (NewLength - Offset) * sizeof (TCHAR));
+    if (*NeedReboot)
+        Log("NeedReboot");
 
-    Log("removed %s", Filter);
-
-    if (!SetupDiSetClassRegistryProperty(Guid,
-                                         SPCRP_UPPERFILTERS,
-                                         (PBYTE)UpperFilters,
-                                         NewLength,
-                                         NULL,
-                                         NULL))
-        goto fail5;
-
-done:
-    free(UpperFilters);
+    RegCloseKey(StatusKey);
 
     return TRUE;
 
-fail5:
-    Log("fail5");
-
-fail4:
-    Log("fail4");
-
-    free(UpperFilters);
-
 fail3:
     Log("fail3");
 
 fail2:
     Log("fail2");
 
+    RegCloseKey(StatusKey);
+
 fail1:
     Error = GetLastError();
 
     {
         PTCHAR  Message;
-
         Message = GetErrorMessage(Error);
         Log("fail1 (%s)", Message);
         LocalFree(Message);
@@ -1950,10 +1524,10 @@ DifInstallPreProcess(
     )
 {
     BOOLEAN                         Success;
-    PTCHAR                          DeviceID;
-    PTCHAR                          InstanceID;
     HRESULT                         Error;
 
+    UNREFERENCED_PARAMETER(DeviceInfoSet);
+    UNREFERENCED_PARAMETER(DeviceInfoData);
     UNREFERENCED_PARAMETER(Context);
 
     Log("====>");
@@ -1966,42 +1540,10 @@ DifInstallPreProcess(
     if (!Success)
         goto fail2;
 
-    Success = GetActiveDeviceInstanceID(&DeviceID, &InstanceID);
-    if (!Success)
-        goto fail3;
-
-    if (DeviceID == NULL) {
-        assert(InstanceID == NULL);
-
-        Success = GetDeviceInstanceID(DeviceInfoSet, DeviceInfoData,
-                                      &DeviceID, &InstanceID);
-        if (!Success)
-            goto fail4;
-
-        Success = SetActiveDeviceInstanceID(DeviceID, InstanceID);
-        if (!Success)
-            goto fail5;
-    }
-
-    free(DeviceID);
-    free(InstanceID);
-
     Log("<====");
     
     return NO_ERROR;
 
-fail5:
-    Log("fail5");
-
-    free(DeviceID);
-    free(InstanceID);
-
-fail4:
-    Log("fail4");
-
-fail3:
-    Log("fail3");
-
 fail2:
     Log("fail2");
 
@@ -2026,13 +1568,11 @@ DifInstallPostProcess(
     IN  PCOINSTALLER_CONTEXT_DATA   Context
     )
 {
-    HRESULT                         Error;
+    BOOLEAN                         Success;
     PTCHAR                          DeviceID;
     PTCHAR                          InstanceID;
-    PTCHAR                          ActiveDeviceID;
-    PTCHAR                          ActiveInstanceID;
-    BOOLEAN                         Active;
-    BOOLEAN                         Success;
+    BOOLEAN                         NeedReboot;
+    HRESULT                         Error;
 
     UNREFERENCED_PARAMETER(Context);
 
@@ -2047,28 +1587,14 @@ DifInstallPostProcess(
     if (!Success)
         goto fail2;
 
-    Success = GetActiveDeviceInstanceID(&ActiveDeviceID, &ActiveInstanceID);
-    if (!Success)
-        goto fail3;
+    NeedReboot = FALSE;
 
-    if (ActiveDeviceID != NULL) {
-        assert(ActiveInstanceID != NULL);
-        Active = (_stricmp(ActiveDeviceID, DeviceID) == 0 &&
-                  _stricmp(ActiveInstanceID, InstanceID) == 0) ?
-            TRUE :
-            FALSE;
+    (VOID) CheckStatus("XEN", &NeedReboot);
+    if (!NeedReboot)
+        (VOID) CheckStatus("XENBUS", &NeedReboot);
 
-        free(ActiveDeviceID);
-        free(ActiveInstanceID);
-    } else {
-        Active = FALSE;
-    }
-
-    if (Active) {
-        (VOID) InstallFilter(&GUID_DEVCLASS_SYSTEM, "XENFILT");
-        (VOID) InstallFilter(&GUID_DEVCLASS_HDC, "XENFILT");
+    if (NeedReboot)
         (VOID) RequestReboot(DeviceInfoSet, DeviceInfoData);
-    }
 
     free(DeviceID);
     free(InstanceID);
@@ -2077,12 +1603,6 @@ DifInstallPostProcess(
 
     return NO_ERROR;
 
-fail3:
-    Log("fail3");
-
-    free(DeviceID);
-    free(InstanceID);
-
 fail2:
     Log("fail2");
 
@@ -2163,72 +1683,13 @@ DifRemovePreProcess(
     IN  PCOINSTALLER_CONTEXT_DATA   Context
     )
 {
-    BOOLEAN                         Success;
-    PTCHAR                          DeviceID;
-    PTCHAR                          InstanceID;
-    PTCHAR                          ActiveDeviceID;
-    PTCHAR                          ActiveInstanceID;
-    BOOLEAN                         Active;
-    HRESULT                         Error;
-
+    UNREFERENCED_PARAMETER(DeviceInfoSet);
+    UNREFERENCED_PARAMETER(DeviceInfoData);
     UNREFERENCED_PARAMETER(Context);
 
-    Log("====>");
-
-    Success = GetDeviceInstanceID(DeviceInfoSet, DeviceInfoData,
-                                  &DeviceID, &InstanceID);
-    if (!Success)
-        goto fail1;
-
-    Success = GetActiveDeviceInstanceID(&ActiveDeviceID, &ActiveInstanceID);
-    if (!Success)
-        goto fail2;
-
-    if (ActiveDeviceID != NULL) {
-        assert(ActiveInstanceID != NULL);
-        Active = (_stricmp(ActiveDeviceID, DeviceID) == 0 &&
-                  _stricmp(ActiveInstanceID, InstanceID) == 0) ?
-            TRUE :
-            FALSE;
-        
-        free(ActiveDeviceID);
-        free(ActiveInstanceID);
-    } else {
-        Active = FALSE;
-    }
-
-    if (Active) {
-        ClearActiveDeviceInstanceID();
-
-        (VOID) RemoveFilter(&GUID_DEVCLASS_HDC, "XENFILT");
-        (VOID) RemoveFilter(&GUID_DEVCLASS_SYSTEM, "XENFILT");
-    }
-
-    free(DeviceID);
-    free(InstanceID);
-
-    Log("<====");
+    Log("<===>");
 
     return NO_ERROR;
-
-fail2:
-    Log("fail2");
-
-    free(DeviceID);
-    free(InstanceID);
-
-fail1:
-    Error = GetLastError();
-
-    {
-        PTCHAR  Message;
-
-        Message = GetErrorMessage(Error);
-        Log("fail1 (%s)", Message);
-        LocalFree(Message);
-    }
-
-    return Error;
 }
 
 static HRESULT
diff --git a/src/xen/driver.c b/src/xen/driver.c
index 9662ff6..187fe1c 100644
--- a/src/xen/driver.c
+++ b/src/xen/driver.c
@@ -55,10 +55,73 @@ typedef struct _XEN_DRIVER {
     PLOG_DISPOSITION    TraceDisposition;
     PLOG_DISPOSITION    InfoDisposition;
     HANDLE              UnplugKey;
+    HANDLE              StatusKey;
 } XEN_DRIVER, *PXEN_DRIVER;
 
 static XEN_DRIVER   Driver;
 
+static FORCEINLINE VOID
+__DriverSetUnplugKey(
+    IN  HANDLE  Key
+    )
+{
+    Driver.UnplugKey = Key;
+}
+
+static FORCEINLINE HANDLE
+__DriverGetUnplugKey(
+    VOID
+    )
+{
+    return Driver.UnplugKey;
+}
+
+HANDLE
+DriverGetUnplugKey(
+    VOID
+    )
+{
+    return __DriverGetUnplugKey();
+}
+
+static FORCEINLINE VOID
+__DriverSetStatusKey(
+    IN  HANDLE  Key
+    )
+{
+    Driver.StatusKey = Key;
+}
+
+static FORCEINLINE HANDLE
+__DriverGetStatusKey(
+    VOID
+    )
+{
+    return Driver.StatusKey;
+}
+
+HANDLE
+DriverGetStatusKey(
+    VOID
+    )
+{
+    return __DriverGetStatusKey();
+}
+
+static FORCEINLINE VOID
+__DriverRequestReboot(
+    VOID
+    )
+{
+    Info("<===>\n");
+
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+
+    (VOID) RegistryUpdateDwordValue(__DriverGetStatusKey(),
+                                    "NeedReboot",
+                                    1);
+}
+
 XEN_API
 NTSTATUS
 XenTouch(
@@ -102,34 +165,11 @@ done:
 
 fail1:
     Info("MODULE '%s' NOT COMPATIBLE (REBOOT REQUIRED)\n", Name);
+    __DriverRequestReboot();
 
     return STATUS_INCOMPATIBLE_DRIVER_BLOCKED;
 }
 
-static FORCEINLINE VOID
-__DriverSetUnplugKey(
-    IN  HANDLE  Key
-    )
-{
-    Driver.UnplugKey = Key;
-}
-
-static FORCEINLINE HANDLE
-__DriverGetUnplugKey(
-    VOID
-    )
-{
-    return Driver.UnplugKey;
-}
-
-HANDLE
-DriverGetUnplugKey(
-    VOID
-    )
-{
-    return __DriverGetUnplugKey();
-}
-
 static VOID
 DriverOutputBuffer(
     IN  PVOID   Argument,
@@ -152,6 +192,7 @@ DllInitialize(
 {
     HANDLE              ServiceKey;
     HANDLE              UnplugKey;
+    HANDLE              StatusKey;
     NTSTATUS            status;
 
     ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
@@ -210,34 +251,43 @@ DllInitialize(
 
     __DriverSetUnplugKey(UnplugKey);
 
-    status = AcpiInitialize();
+    status = RegistryCreateSubKey(ServiceKey,
+                                  "Status",
+                                  REG_OPTION_VOLATILE,
+                                  &StatusKey);
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    status = SystemInitialize();
+    __DriverSetUnplugKey(UnplugKey);
+
+    status = AcpiInitialize();
     if (!NT_SUCCESS(status))
         goto fail6;
 
-    status = HypercallInitialize();
+    status = SystemInitialize();
     if (!NT_SUCCESS(status))
         goto fail7;
 
-    status = BugCheckInitialize();
+    status = HypercallInitialize();
     if (!NT_SUCCESS(status))
         goto fail8;
 
-    status = ModuleInitialize();
+    status = BugCheckInitialize();
     if (!NT_SUCCESS(status))
         goto fail9;
 
-    status = ProcessInitialize();
+    status = ModuleInitialize();
     if (!NT_SUCCESS(status))
         goto fail10;
 
-    status = UnplugInitialize();
+    status = ProcessInitialize();
     if (!NT_SUCCESS(status))
         goto fail11;
 
+    status = UnplugInitialize();
+    if (!NT_SUCCESS(status))
+        goto fail12;
+
     RegistryCloseKey(ServiceKey);
 
 done:
@@ -245,35 +295,41 @@ done:
 
     return STATUS_SUCCESS;
 
+fail12:
+    Error("fail12\n");
+
+    ProcessTeardown();
+
 fail11:
     Error("fail11\n");
 
-    ProcessTeardown();
+    ModuleTeardown();
 
 fail10:
     Error("fail10\n");
 
-    ModuleTeardown();
+    BugCheckTeardown();
 
 fail9:
     Error("fail9\n");
 
-    BugCheckTeardown();
+    HypercallTeardown();
 
 fail8:
     Error("fail8\n");
 
-    HypercallTeardown();
+    SystemTeardown();
 
 fail7:
     Error("fail7\n");
 
-    SystemTeardown();
+    AcpiTeardown();
 
 fail6:
     Error("fail6\n");
 
-    AcpiTeardown();
+    RegistryCloseKey(StatusKey);
+    __DriverSetStatusKey(NULL);
 
 fail5:
     Error("fail5\n");
@@ -315,6 +371,7 @@ DllUnload(
     VOID
     )
 {
+    HANDLE  StatusKey;
     HANDLE  UnplugKey;
 
     Trace("====>\n");
@@ -334,6 +391,11 @@ DllUnload(
 
     SystemTeardown();
 
+    StatusKey = __DriverGetStatusKey();
+
+    RegistryCloseKey(StatusKey);
+    __DriverSetStatusKey(NULL);
+
     UnplugKey = __DriverGetUnplugKey();
 
     RegistryCloseKey(UnplugKey);
diff --git a/src/xenbus/driver.c b/src/xenbus/driver.c
index a1115a4..6135400 100644
--- a/src/xenbus/driver.c
+++ b/src/xenbus/driver.c
@@ -48,6 +48,7 @@ extern PULONG       InitSafeBootMode;
 typedef struct _XENBUS_DRIVER {
     PDRIVER_OBJECT      DriverObject;
     HANDLE              ParametersKey;
+    HANDLE              StatusKey;
 } XENBUS_DRIVER, *PXENBUS_DRIVER;
 
 static XENBUS_DRIVER    Driver;
@@ -118,6 +119,36 @@ DriverGetParametersKey(
     return __DriverGetParametersKey();
 }
 
+static FORCEINLINE VOID
+__DriverSetStatusKey(
+    IN  HANDLE  Key
+    )
+{
+    Driver.StatusKey = Key;
+}
+
+static FORCEINLINE HANDLE
+__DriverGetStatusKey(
+    VOID
+    )
+{
+    return Driver.StatusKey;
+}
+
+VOID
+DriverRequestReboot(
+    VOID
+    )
+{
+    Info("<===>\n");
+
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+
+    (VOID) RegistryUpdateDwordValue(__DriverGetStatusKey(),
+                                    "NeedReboot",
+                                    1);
+}
+
 DRIVER_UNLOAD       DriverUnload;
 
 VOID
@@ -126,6 +157,7 @@ DriverUnload(
     )
 {
     HANDLE              ParametersKey;
+    HANDLE              StatusKey;
 
     ASSERT3P(DriverObject, ==, __DriverGetDriverObject());
 
@@ -134,6 +166,11 @@ DriverUnload(
     if (*InitSafeBootMode > 0)
         goto done;
 
+    StatusKey = __DriverGetStatusKey();
+    __DriverSetStatusKey(NULL);
+
+    RegistryCloseKey(StatusKey);
+
     ParametersKey = __DriverGetParametersKey();
 
     RegistryCloseKey(ParametersKey);
@@ -158,203 +195,6 @@ done:
     Trace("<====\n");
 }
 
-__drv_functionClass(IO_COMPLETION_ROUTINE)
-__drv_sameIRQL
-static NTSTATUS
-DriverQueryIdCompletion(
-    IN  PDEVICE_OBJECT  DeviceObject,
-    IN  PIRP            Irp,
-    IN  PVOID           Context
-    )
-{
-    PKEVENT             Event = Context;
-
-    UNREFERENCED_PARAMETER(DeviceObject);
-    UNREFERENCED_PARAMETER(Irp);
-
-    KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
-
-    return STATUS_MORE_PROCESSING_REQUIRED;
-}
-
-static NTSTATUS
-DriverQueryId(
-    IN  PDEVICE_OBJECT      PhysicalDeviceObject,
-    IN  BUS_QUERY_ID_TYPE   Type,
-    OUT PVOID               *Information
-    )
-{
-    PDEVICE_OBJECT          DeviceObject;
-    PIRP                    Irp;
-    KEVENT                  Event;
-    PIO_STACK_LOCATION      StackLocation;
-    NTSTATUS                status;
-
-    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
-
-    Trace("====> %s\n", BusQueryIdTypeName(Type));
-
-    DeviceObject = IoGetAttachedDeviceReference(PhysicalDeviceObject);
-
-    Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
-
-    status = STATUS_INSUFFICIENT_RESOURCES;
-    if (Irp == NULL)
-        goto fail1;
-
-    StackLocation = IoGetNextIrpStackLocation(Irp);
-
-    StackLocation->MajorFunction = IRP_MJ_PNP;
-    StackLocation->MinorFunction = IRP_MN_QUERY_ID;
-    StackLocation->Flags = 0;
-    StackLocation->Parameters.QueryId.IdType = Type;
-    StackLocation->DeviceObject = DeviceObject;
-    StackLocation->FileObject = NULL;
-
-    KeInitializeEvent(&Event, NotificationEvent, FALSE);
-
-    IoSetCompletionRoutine(Irp,
-                           DriverQueryIdCompletion,
-                           &Event,
-                           TRUE,
-                           TRUE,
-                           TRUE);
-
-    // Default completion status
-    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
-
-    status = IoCallDriver(DeviceObject, Irp);
-    if (status == STATUS_PENDING) {
-        (VOID) KeWaitForSingleObject(&Event,
-                                     Executive,
-                                     KernelMode,
-                                     FALSE,
-                                     NULL);
-        status = Irp->IoStatus.Status;
-    } else {
-        ASSERT3U(status, ==, Irp->IoStatus.Status);
-    }
-
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    *Information = (PVOID)Irp->IoStatus.Information;
-
-    IoFreeIrp(Irp);
-    ObDereferenceObject(DeviceObject);
-
-    Trace("<====\n");
-
-    return STATUS_SUCCESS;
-
-fail2:
-    Error("fail2\n");
-
-    IoFreeIrp(Irp);
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    ObDereferenceObject(DeviceObject);
-
-    return status;
-}
-
-static NTSTATUS
-DriverGetActiveDeviceInstance(
-    OUT PWCHAR      *DeviceID,
-    OUT PWCHAR      *InstanceID
-    )
-{
-    HANDLE          ParametersKey;
-    PANSI_STRING    Ansi;
-    UNICODE_STRING  Unicode;
-    NTSTATUS        status;
-
-    ParametersKey = __DriverGetParametersKey();
-
-    *DeviceID = NULL;
-    *InstanceID = NULL;
-
-    status = RegistryQuerySzValue(ParametersKey,
-                                  "ActiveDeviceID",
-                                  &Ansi);
-    if (!NT_SUCCESS(status)) {
-        if (status != STATUS_OBJECT_NAME_NOT_FOUND)
-            goto fail1;
-
-        // The active device is not yet set
-        goto done;
-    }
-
-    Unicode.MaximumLength = (USHORT)(Ansi[0].MaximumLength / sizeof (CHAR) * 
sizeof (WCHAR));
-    Unicode.Buffer = __DriverAllocate(Unicode.MaximumLength);
-
-    status = STATUS_NO_MEMORY;
-    if (Unicode.Buffer == NULL)
-        goto fail2;
-
-    status = RtlAnsiStringToUnicodeString(&Unicode,
-                                          &Ansi[0],
-                                          FALSE);
-    ASSERT(NT_SUCCESS(status));
-
-    RegistryFreeSzValue(Ansi);
-
-    *DeviceID = Unicode.Buffer;
-        
-    status = RegistryQuerySzValue(ParametersKey,
-                                  "ActiveInstanceID",
-                                  &Ansi);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    Unicode.MaximumLength = (USHORT)(Ansi[0].MaximumLength / sizeof (CHAR) * 
sizeof (WCHAR));
-    Unicode.Buffer = __DriverAllocate(Unicode.MaximumLength);
-
-    status = STATUS_NO_MEMORY;
-    if (Unicode.Buffer == NULL)
-        goto fail4;
-
-    status = RtlAnsiStringToUnicodeString(&Unicode,
-                                          &Ansi[0],
-                                          FALSE);
-    ASSERT(NT_SUCCESS(status));
-
-    RegistryFreeSzValue(Ansi);
-
-    *InstanceID = Unicode.Buffer;
-
-done:        
-    Trace("DeviceID = %ws\n", (*DeviceID != NULL) ? *DeviceID : L"NOT SET");
-    Trace("InstanceID = %ws\n", (*InstanceID != NULL) ? *InstanceID : L"NOT 
SET");
-
-    return STATUS_SUCCESS;
-
-fail4:
-    Error("fail4\n");
-
-    RegistryFreeSzValue(Ansi);
-
-fail3:
-    Error("fail3\n");
-
-    __DriverFree(*DeviceID);
-    *DeviceID = NULL;
-
-    goto fail1;
-
-fail2:
-    Error("fail2\n");
-
-    RegistryFreeSzValue(Ansi);
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
 DRIVER_ADD_DEVICE   DriverAddDevice;
 
 NTSTATUS
@@ -364,76 +204,20 @@ DriverAddDevice(
     IN  PDEVICE_OBJECT  DeviceObject
     )
 {
-    PWCHAR              ActiveDeviceID;
-    PWCHAR              ActiveInstanceID;
-    PWCHAR              DeviceID;
-    PWCHAR              InstanceID;
-    BOOLEAN             Active;
     NTSTATUS            status;
 
     ASSERT3P(DriverObject, ==, __DriverGetDriverObject());
 
     Trace("====>\n");
 
-    status = DriverGetActiveDeviceInstance(&ActiveDeviceID, &ActiveInstanceID);
+    status = FdoCreate(DeviceObject);
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    Active = FALSE;
-
-    if (ActiveDeviceID == NULL) {
-        ASSERT3P(ActiveInstanceID, ==, NULL);
-        goto done;
-    }
-
-    status = DriverQueryId(DeviceObject, BusQueryDeviceID, &DeviceID);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    Trace("DeviceID = %ws\n", DeviceID);
-
-    status = DriverQueryId(DeviceObject, BusQueryInstanceID, &InstanceID);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    Trace("InstanceID = %ws\n", InstanceID);
-
-    if (_wcsicmp(DeviceID, ActiveDeviceID) == 0 &&
-        _wcsicmp(InstanceID, ActiveInstanceID) == 0)
-        Active = TRUE;
-
-    ExFreePool(InstanceID);
-
-    ExFreePool(DeviceID);
-
-    __DriverFree(ActiveInstanceID);
-    __DriverFree(ActiveDeviceID);
-
-done:
-    status = FdoCreate(DeviceObject, Active);
-    if (!NT_SUCCESS(status))
-        goto fail4;
-
     Trace("<====\n");
 
     return STATUS_SUCCESS;
 
-fail4:
-    Error("fail4\n");
-
-    goto fail1;
-
-fail3:
-    Error("fail3\n");
-
-    ExFreePool(DeviceID);
-
-fail2:
-    Error("fail2\n");
-
-    __DriverFree(ActiveInstanceID);
-    __DriverFree(ActiveDeviceID);
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -495,6 +279,7 @@ DriverEntry(
 {
     HANDLE              ServiceKey;
     HANDLE              ParametersKey;
+    HANDLE              StatusKey;
     ULONG               Index;
     NTSTATUS            status;
 
@@ -539,12 +324,24 @@ DriverEntry(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = RegistryOpenSubKey(ServiceKey, "Parameters", KEY_READ, 
&ParametersKey);
+    status = RegistryOpenSubKey(ServiceKey,
+                                "Parameters",
+                                KEY_READ,
+                                &ParametersKey);
     if (!NT_SUCCESS(status))
         goto fail3;
 
     __DriverSetParametersKey(ParametersKey);
 
+    status = RegistryCreateSubKey(ServiceKey,
+                                  "Status",
+                                  REG_OPTION_VOLATILE,
+                                  &StatusKey);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+    __DriverSetStatusKey(StatusKey);
+
     RegistryCloseKey(ServiceKey);
 
     DriverObject->DriverExtension->AddDevice = DriverAddDevice;
@@ -560,6 +357,13 @@ done:
 
     return STATUS_SUCCESS;
 
+fail4:
+    Error("fail4\n");
+
+    __DriverSetParametersKey(NULL);
+
+    RegistryCloseKey(ParametersKey);
+
 fail3:
     Error("fail3\n");
 
diff --git a/src/xenbus/driver.h b/src/xenbus/driver.h
index 45cbe82..0208f9c 100644
--- a/src/xenbus/driver.h
+++ b/src/xenbus/driver.h
@@ -42,6 +42,21 @@ DriverGetParametersKey(
     VOID
     );
 
+extern VOID
+DriverRequestReboot(
+    VOID
+    );
+
+extern VOID
+DriverAddFilters(
+    VOID
+    );
+
+extern VOID
+DriverRemoveFilters(
+    VOID
+    );
+
 typedef struct _XENBUS_FDO      XENBUS_FDO, *PXENBUS_FDO;
 typedef struct _XENBUS_PDO      XENBUS_PDO, *PXENBUS_PDO;
 
diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c
index e8a6f22..fdb394d 100644
--- a/src/xenbus/fdo.c
+++ b/src/xenbus/fdo.c
@@ -38,6 +38,8 @@
 #include <stdlib.h>
 #include <xen.h>
 
+#include <pvdevice_interface.h>
+
 #include "names.h"
 #include "registry.h"
 #include "fdo.h"
@@ -57,6 +59,7 @@
 #include "driver.h"
 #include "range_set.h"
 #include "unplug.h"
+#include "filters.h"
 #include "dbg_print.h"
 #include "assert.h"
 #include "util.h"
@@ -92,7 +95,6 @@ struct _XENBUS_FDO {
     PIRP                            DevicePowerIrp;
 
     CHAR                            VendorName[MAXNAMELEN];
-    BOOLEAN                         Active;
 
     MUTEX                           Mutex;
     ULONG                           References;
@@ -113,6 +115,9 @@ struct _XENBUS_FDO {
     PCM_PARTIAL_RESOURCE_LIST       RawResourceList;
     PCM_PARTIAL_RESOURCE_LIST       TranslatedResourceList;
 
+    XENFILT_PVDEVICE_INTERFACE      PvdeviceInterface;
+    BOOLEAN                         Active;
+
     PXENBUS_SUSPEND_CONTEXT         SuspendContext;
     PXENBUS_SHARED_INFO_CONTEXT     SharedInfoContext;
     PXENBUS_EVTCHN_CONTEXT          EvtchnContext;
@@ -441,19 +446,31 @@ FdoGetBusData(
                                     Length);
 }
 
-static FORCEINLINE VOID
+static FORCEINLINE NTSTATUS
 __FdoSetVendorName(
     IN  PXENBUS_FDO Fdo,
+    IN  USHORT      VendorID,
     IN  USHORT      DeviceID
     )
 {
     NTSTATUS        status;
 
+    status = STATUS_NOT_SUPPORTED;
+    if (VendorID != 'XS')
+        goto fail1;
+
     status = RtlStringCbPrintfA(Fdo->VendorName,
                                 MAXNAMELEN,
                                 "XS%04X",
                                 DeviceID);
     ASSERT(NT_SUCCESS(status));
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
 }
 
 static FORCEINLINE PCHAR
@@ -505,13 +522,161 @@ FdoGetName(
     return __FdoGetName(Fdo);
 }
 
-static FORCEINLINE VOID
-__FdoSetActive(
-    IN  PXENBUS_FDO Fdo,
-    IN  BOOLEAN     Active
+static NTSTATUS
+FdoQueryId(
+    IN  PXENBUS_FDO         Fdo,
+    IN  BUS_QUERY_ID_TYPE   Type,
+    OUT PCHAR               Id
     )
 {
-    Fdo->Active = Active;
+    KEVENT                  Event;
+    IO_STATUS_BLOCK         StatusBlock;
+    PIRP                    Irp;
+    PIO_STACK_LOCATION      StackLocation;
+    NTSTATUS                status;
+
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+    RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK));
+
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+                                       Fdo->LowerDeviceObject,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       &Event,
+                                       &StatusBlock);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Irp == NULL)
+        goto fail1;
+
+    StackLocation = IoGetNextIrpStackLocation(Irp);
+    StackLocation->MinorFunction = IRP_MN_QUERY_ID;
+
+    StackLocation->Parameters.QueryId.IdType = Type;
+
+    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+
+    status = IoCallDriver(Fdo->LowerDeviceObject, Irp);
+    if (status == STATUS_PENDING) {
+        (VOID) KeWaitForSingleObject(&Event,
+                                     Executive,
+                                     KernelMode,
+                                     FALSE,
+                                     NULL);
+        status = StatusBlock.Status;
+    }
+
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = RtlStringCbPrintfA(Id,
+                                MAXNAMELEN,
+                                "%ws",
+                                (PWCHAR)StatusBlock.Information);
+    ASSERT(NT_SUCCESS(status));
+
+    ExFreePool((PVOID)StatusBlock.Information);
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static NTSTATUS
+FdoSetActive(
+    IN  PXENBUS_FDO Fdo
+    )
+{
+    CHAR            DeviceID[MAX_DEVICE_ID_LEN];
+    CHAR            InstanceID[MAX_DEVICE_ID_LEN];
+    CHAR            ActiveDeviceID[MAX_DEVICE_ID_LEN];
+    CHAR            ActiveInstanceID[MAX_DEVICE_ID_LEN];
+    NTSTATUS        status;
+
+    status = FdoQueryId(Fdo,
+                        BusQueryDeviceID,
+                        DeviceID);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = FdoQueryId(Fdo,
+                        BusQueryInstanceID,
+                        InstanceID);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = XENFILT_PVDEVICE(Acquire, &Fdo->PvdeviceInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENFILT_PVDEVICE(GetActive,
+                              &Fdo->PvdeviceInterface,
+                              ActiveDeviceID,
+                              ActiveInstanceID);
+    if (NT_SUCCESS(status)) {
+        if (_stricmp(DeviceID, ActiveDeviceID) != 0)
+            goto done;
+    } else {
+        status = XENFILT_PVDEVICE(SetActive,
+                                  &Fdo->PvdeviceInterface,
+                                  DeviceID,
+                                  InstanceID);
+        if (!NT_SUCCESS(status))
+            goto done;
+    }
+
+    Fdo->Active = TRUE;
+
+done:
+    XENFILT_PVDEVICE(Release, &Fdo->PvdeviceInterface);
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static NTSTATUS
+FdoClearActive(
+    IN  PXENBUS_FDO Fdo
+    )
+{
+    NTSTATUS        status;
+
+    status = XENFILT_PVDEVICE(Acquire, &Fdo->PvdeviceInterface);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    (VOID) XENFILT_PVDEVICE(ClearActive,
+                            &Fdo->PvdeviceInterface);
+
+    Fdo->Active = FALSE;
+
+    XENFILT_PVDEVICE(Release, &Fdo->PvdeviceInterface);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
 }
 
 static FORCEINLINE BOOLEAN
@@ -4487,14 +4652,13 @@ done:
 
 NTSTATUS
 FdoCreate(
-    IN  PDEVICE_OBJECT          PhysicalDeviceObject,
-    IN  BOOLEAN                 Active      
+    IN  PDEVICE_OBJECT          PhysicalDeviceObject
     )
 {
     PDEVICE_OBJECT              FunctionDeviceObject;
     PXENBUS_DX                  Dx;
     PXENBUS_FDO                 Fdo;
-    USHORT                      DeviceID;
+    PCI_COMMON_HEADER           Header;
     NTSTATUS                    status;
 
 #pragma prefast(suppress:28197) // Possibly leaking memory 
'FunctionDeviceObject'
@@ -4542,60 +4706,81 @@ FdoCreate(
 
     if (FdoGetBusData(Fdo,
                       PCI_WHICHSPACE_CONFIG,
-                      &DeviceID,
-                      FIELD_OFFSET(PCI_COMMON_HEADER, DeviceID),
-                      FIELD_SIZE(PCI_COMMON_HEADER, DeviceID)) == 0)
+                      &Header,
+                      0,
+                      sizeof (PCI_COMMON_HEADER)) == 0)
         goto fail6;
 
-    __FdoSetVendorName(Fdo, DeviceID);
+    status = __FdoSetVendorName(Fdo,
+                                Header.VendorID,
+                                Header.DeviceID);
+    if (!NT_SUCCESS(status))
+        goto fail7;
 
     __FdoSetName(Fdo);
 
-    __FdoSetActive(Fdo, Active);
+    status = FDO_QUERY_INTERFACE(Fdo,
+                                 XENFILT,
+                                 PVDEVICE,
+                                 (PINTERFACE)&Fdo->PvdeviceInterface,
+                                 sizeof (Fdo->PvdeviceInterface),
+                                 TRUE);
+    if (!NT_SUCCESS(status))
+        goto fail8;
+
+    if (Fdo->PvdeviceInterface.Interface.Context == NULL) {
+        (VOID) FiltersInstall();
+        DriverRequestReboot();
+        goto done;
+    }
+
+    status = FdoSetActive(Fdo);
+    if (!NT_SUCCESS(status))
+        goto fail9;
 
     if (!__FdoIsActive(Fdo))
         goto done;
 
     status = DebugInitialize(Fdo, &Fdo->DebugContext);
     if (!NT_SUCCESS(status))
-        goto fail7;
+        goto fail10;
 
     status = SuspendInitialize(Fdo, &Fdo->SuspendContext);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail11;
 
     status = SharedInfoInitialize(Fdo, &Fdo->SharedInfoContext);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail12;
 
     status = EvtchnInitialize(Fdo, &Fdo->EvtchnContext);
     if (!NT_SUCCESS(status))
-        goto fail10;
+        goto fail13;
 
     status = StoreInitialize(Fdo, &Fdo->StoreContext);
     if (!NT_SUCCESS(status))
-        goto fail11;
+        goto fail14;
 
     status = RangeSetInitialize(Fdo, &Fdo->RangeSetContext);
     if (!NT_SUCCESS(status))
-        goto fail12;
+        goto fail15;
 
     status = CacheInitialize(Fdo, &Fdo->CacheContext);
     if (!NT_SUCCESS(status))
-        goto fail13;
+        goto fail16;
 
     status = GnttabInitialize(Fdo, &Fdo->GnttabContext);
     if (!NT_SUCCESS(status))
-        goto fail14;
+        goto fail17;
 
     status = UnplugInitialize(Fdo, &Fdo->UnplugContext);
     if (!NT_SUCCESS(status))
-        goto fail15;
+        goto fail18;
 
     if (FdoIsBalloonEnabled(Fdo)) {
         status = BalloonInitialize(Fdo, &Fdo->BalloonContext);
         if (!NT_SUCCESS(status))
-            goto fail16;
+            goto fail19;
     }
 
     status = DebugGetInterface(__FdoGetDebugContext(Fdo),
@@ -4654,67 +4839,79 @@ done:
 
     return STATUS_SUCCESS;
 
-fail16:
-    Error("fail16\n");
+fail19:
+    Error("fail19\n");
 
     UnplugTeardown(Fdo->UnplugContext);
     Fdo->UnplugContext = NULL;
 
-fail15:
-    Error("fail15\n");
+fail18:
+    Error("fail18\n");
 
     GnttabTeardown(Fdo->GnttabContext);
     Fdo->GnttabContext = NULL;
 
-fail14:
-    Error("fail14\n");
+fail17:
+    Error("fail17\n");
 
     CacheTeardown(Fdo->CacheContext);
     Fdo->CacheContext = NULL;
 
-fail13:
-    Error("fail13\n");
+fail16:
+    Error("fail16\n");
 
     RangeSetTeardown(Fdo->RangeSetContext);
     Fdo->RangeSetContext = NULL;
 
-fail12:
-    Error("fail12\n");
+fail15:
+    Error("fail15\n");
 
     StoreTeardown(Fdo->StoreContext);
     Fdo->StoreContext = NULL;
 
-fail11:
-    Error("fail11\n");
+fail14:
+    Error("fail14\n");
 
     EvtchnTeardown(Fdo->EvtchnContext);
     Fdo->EvtchnContext = NULL;
 
-fail10:
-    Error("fail10\n");
+fail13:
+    Error("fail13\n");
 
     SharedInfoTeardown(Fdo->SharedInfoContext);
     Fdo->SharedInfoContext = NULL;
 
-fail9:
-    Error("fail9\n");
+fail12:
+    Error("fail12\n");
 
     SuspendTeardown(Fdo->SuspendContext);
     Fdo->SuspendContext = NULL;
 
-fail8:
-    Error("fail8\n");
+fail11:
+    Error("fail11\n");
 
     DebugTeardown(Fdo->DebugContext);
     Fdo->DebugContext = NULL;
 
-fail7:
-    Error("fail7\n");
+fail10:
+    Error("fail10\n");
 
-    __FdoSetActive(Fdo, FALSE);
+    Fdo->Active = FALSE;
+
+fail9:
+    Error("fail9\n");
+
+    RtlZeroMemory(&Fdo->PvdeviceInterface,
+                  sizeof (XENFILT_PVDEVICE_INTERFACE));
+
+fail8:
+    Error("fail8\n");
 
     RtlZeroMemory(Fdo->VendorName, MAXNAMELEN);
 
+fail7:
+    Error("fail7\n");
+
 fail6:
     Error("fail6\n");
 
@@ -4831,9 +5028,16 @@ FdoDestroy(
         DebugTeardown(Fdo->DebugContext);
         Fdo->DebugContext = NULL;
 
-        __FdoSetActive(Fdo, FALSE);
+        Fdo->Active = FALSE;
+
+        FdoClearActive(Fdo);
     }
 
+    (VOID) FiltersUninstall();
+
+    RtlZeroMemory(&Fdo->PvdeviceInterface,
+                  sizeof (XENFILT_PVDEVICE_INTERFACE));
+
     RtlZeroMemory(Fdo->VendorName, MAXNAMELEN);
 
     FdoReleaseLowerBusInterface(Fdo);
diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h
index 1feef17..96a2250 100644
--- a/src/xenbus/fdo.h
+++ b/src/xenbus/fdo.h
@@ -41,8 +41,7 @@ typedef struct _XENBUS_INTERRUPT XENBUS_INTERRUPT, 
*PXENBUS_INTERRUPT;
 
 extern NTSTATUS
 FdoCreate(
-    IN  PDEVICE_OBJECT  PhysicalDeviceObject,
-    IN  BOOLEAN         Active
+    IN  PDEVICE_OBJECT  PhysicalDeviceObject
     );
 
 extern VOID
diff --git a/src/xenbus/filters.c b/src/xenbus/filters.c
new file mode 100644
index 0000000..737c839
--- /dev/null
+++ b/src/xenbus/filters.c
@@ -0,0 +1,319 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define INITGUID 1
+
+#include <ntddk.h>
+#include <ntstrsafe.h>
+#include <devguid.h>
+#include <xen.h>
+
+#include "registry.h"
+#include "driver.h"
+#include "dbg_print.h"
+#include "assert.h"
+#include "util.h"
+
+#define XENBUS_FILTERS_TAG 'TLIF'
+
+static FORCEINLINE PVOID
+__FiltersAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_FILTERS_TAG);
+}
+
+static FORCEINLINE VOID
+__FiltersFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENBUS_FILTERS_TAG);
+}
+
+#define CLASS_PATH 
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Class"
+
+static NTSTATUS
+FiltersInstallClass(
+    IN  const CHAR  *ClassName,
+    IN  const GUID  *ClassGuid,
+    IN  const CHAR  *DriverName
+    )
+{
+    HANDLE          ClassKey;
+    UNICODE_STRING  Unicode;
+    HANDLE          Key;
+    ULONG           Count;
+    PANSI_STRING    Old;
+    ULONG           Index;
+    PANSI_STRING    New;
+    NTSTATUS        status;
+
+    Trace("====>\n");
+
+    Info("%s %s\n", ClassName, DriverName);
+
+    status = RegistryOpenSubKey(NULL,
+                                CLASS_PATH,
+                                KEY_ALL_ACCESS,
+                                &ClassKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = RtlStringFromGUID(ClassGuid, &Unicode);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = RegistryOpenKey(ClassKey,
+                             &Unicode,
+                             KEY_ALL_ACCESS,
+                             &Key);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    Count = 0;
+
+    status = RegistryQuerySzValue(Key, "UpperFilters", &Old);
+    if (NT_SUCCESS(status)) {
+        for (Index = 0; Old[Index].Buffer != NULL; Index++) {
+            if (_stricmp(Old[Index].Buffer, DriverName) == 0)
+                goto done;
+
+            Count++;
+        }
+    } else {
+        Old = NULL;
+    }
+
+    New = __FiltersAllocate(sizeof (ANSI_STRING) * (Count + 2));
+
+    status = STATUS_NO_MEMORY;
+    if (New == NULL)
+        goto fail4;
+
+    Index = 0;
+    while (Index < Count) {
+        New[Index] = Old[Index];
+        Index++;
+    }
+
+    RtlInitAnsiString(&New[Index], DriverName);
+
+    status = RegistryUpdateSzValue(Key, "UpperFilters", New);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
+    __FiltersFree(New);
+
+done:
+    if (Old != NULL)
+        RegistryFreeSzValue(Old);
+
+    RegistryCloseKey(Key);
+
+    RtlFreeUnicodeString(&Unicode);
+
+    RegistryCloseKey(ClassKey);
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail5:
+    Error("fail5\n");
+
+    __FiltersFree(New);
+
+fail4:
+    Error("fail4\n");
+
+    if (Old != NULL)
+        RegistryFreeSzValue(Old);
+
+    RegistryCloseKey(Key);
+
+fail3:
+    Error("fail3\n");
+
+    RtlFreeUnicodeString(&Unicode);
+
+fail2:
+    Error("fail2\n");
+
+    RegistryCloseKey(ClassKey);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+#define FILTERS_INSTALL_CLASS(_ClassGuid, _DriverName) \
+        FiltersInstallClass(#_ClassGuid, &GUID_ ## _ClassGuid, (_DriverName))
+
+static NTSTATUS
+FiltersUninstallClass(
+    IN  const CHAR  *ClassName,
+    IN  const GUID  *ClassGuid,
+    IN  const CHAR  *DriverName
+    )
+{
+    HANDLE          ClassKey;
+    UNICODE_STRING  Unicode;
+    HANDLE          Key;
+    ULONG           Count;
+    PANSI_STRING    Old;
+    ULONG           Index;
+    PANSI_STRING    New;
+    NTSTATUS        status;
+
+    Trace("====>\n");
+
+    Info("%s %s\n", ClassName, DriverName);
+
+    status = RegistryOpenSubKey(NULL,
+                                CLASS_PATH,
+                                KEY_ALL_ACCESS,
+                                &ClassKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = RtlStringFromGUID(ClassGuid, &Unicode);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = RegistryOpenKey(ClassKey,
+                             &Unicode,
+                             KEY_ALL_ACCESS,
+                             &Key);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = RegistryQuerySzValue(Key, "UpperFilters", &Old);
+    if (NT_SUCCESS(status)) {
+        for (Index = 0; Old[Index].Buffer != NULL; Index++) {
+            if (_stricmp(Old[Index].Buffer, DriverName) == 0)
+                goto found;
+        }
+    }
+
+    goto done;
+
+found:
+    Count = 0;
+    for (Index = 0; Old[Index].Buffer != NULL; Index++)
+        Count++;
+
+    New = __FiltersAllocate(sizeof (ANSI_STRING) * Count);
+
+    status = STATUS_NO_MEMORY;
+    if (New == NULL)
+        goto fail4;
+
+    Count = 0;
+    for (Index = 0; Old[Index].Buffer != NULL; Index++) {
+        if (_stricmp(Old[Index].Buffer, DriverName) == 0)
+            continue;
+
+        New[Count] = Old[Index];
+        Count++;
+    }
+
+    status = RegistryUpdateSzValue(Key, "UpperFilters", New);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
+    __FiltersFree(New);
+
+done:
+    if (Old != NULL)
+        RegistryFreeSzValue(Old);
+
+    RegistryCloseKey(Key);
+
+    RtlFreeUnicodeString(&Unicode);
+
+    RegistryCloseKey(ClassKey);
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail5:
+    Error("fail5\n");
+
+    __FiltersFree(New);
+
+fail4:
+    Error("fail4\n");
+
+    if (Old != NULL)
+        RegistryFreeSzValue(Old);
+
+    RegistryCloseKey(Key);
+
+fail3:
+    Error("fail3\n");
+
+    RtlFreeUnicodeString(&Unicode);
+
+fail2:
+    Error("fail2\n");
+
+    RegistryCloseKey(ClassKey);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+#define FILTERS_UNINSTALL_CLASS(_ClassGuid, _DriverName) \
+        FiltersUninstallClass(#_ClassGuid, &GUID_ ## _ClassGuid, (_DriverName))
+
+VOID
+FiltersInstall(
+    VOID
+    )
+{
+    (VOID) FILTERS_INSTALL_CLASS(DEVCLASS_SYSTEM, "XENFILT");
+    (VOID) FILTERS_INSTALL_CLASS(DEVCLASS_HDC, "XENFILT");
+}
+
+VOID
+FiltersUninstall(
+    VOID
+    )
+{
+    (VOID) FILTERS_UNINSTALL_CLASS(DEVCLASS_HDC, "XENFILT");
+    (VOID) FILTERS_UNINSTALL_CLASS(DEVCLASS_SYSTEM, "XENFILT");
+}
diff --git a/src/xenbus/filters.h b/src/xenbus/filters.h
new file mode 100644
index 0000000..a08855b
--- /dev/null
+++ b/src/xenbus/filters.h
@@ -0,0 +1,45 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XENBUS_FILTERS_H
+#define _XENBUS_FILTERS_H
+
+extern NTSTATUS
+FiltersInstall(
+     VOID
+     );
+
+extern NTSTATUS
+FiltersUninstall(
+     VOID
+     );
+
+#endif  // _XENBUS_FILTERS_H
diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c
index 8e7f90a..e85732e 100644
--- a/src/xenbus/pdo.c
+++ b/src/xenbus/pdo.c
@@ -448,7 +448,7 @@ PdoDumpRevisions(
              "RANGE_SET v%u "
              "CACHE v%u "
              "GNTTAB v%u "
-             "UNPLUG v%u\n"
+             "UNPLUG v%u "
              "EMULATED v%u\n",
              Revision->Number,
              Revision->SuspendInterfaceVersion,
diff --git a/src/xenfilt/driver.c b/src/xenfilt/driver.c
index f0ffac0..77f719a 100644
--- a/src/xenfilt/driver.c
+++ b/src/xenfilt/driver.c
@@ -30,6 +30,7 @@
  */
 
 #include <ntddk.h>
+#include <ntstrsafe.h>
 #include <procgrp.h>
 #include <xen.h>
 
@@ -38,6 +39,7 @@
 #include "pdo.h"
 #include "driver.h"
 #include "emulated.h"
+#include "pvdevice.h"
 #include "mutex.h"
 #include "dbg_print.h"
 #include "assert.h"
@@ -50,8 +52,6 @@ typedef struct _XENFILT_DRIVER {
     PDRIVER_OBJECT              DriverObject;
     HANDLE                      ParametersKey;
 
-    PCHAR                       ActiveDeviceID;
-    PCHAR                       ActiveInstanceID;
     MUTEX                       Mutex;
     LIST_ENTRY                  List;
     ULONG                       References;
@@ -60,6 +60,9 @@ typedef struct _XENFILT_DRIVER {
 
     PXENFILT_EMULATED_CONTEXT   EmulatedContext;
     XENFILT_EMULATED_INTERFACE  EmulatedInterface;
+
+    PXENFILT_PVDEVICE_CONTEXT   PvdeviceContext;
+    XENFILT_PVDEVICE_INTERFACE  PvdeviceInterface;
 } XENFILT_DRIVER, *PXENFILT_DRIVER;
 
 static XENFILT_DRIVER   Driver;
@@ -155,6 +158,30 @@ DriverGetEmulatedContext(
 }
 
 static FORCEINLINE VOID
+__DriverSetPvdeviceContext(
+    IN  PXENFILT_PVDEVICE_CONTEXT   Context
+    )
+{
+    Driver.PvdeviceContext = Context;
+}
+
+static FORCEINLINE PXENFILT_PVDEVICE_CONTEXT
+__DriverGetPvdeviceContext(
+    VOID
+    )
+{
+    return Driver.PvdeviceContext;
+}
+
+PXENFILT_PVDEVICE_CONTEXT
+DriverGetPvdeviceContext(
+    VOID
+    )
+{
+    return __DriverGetPvdeviceContext();
+}
+
+static FORCEINLINE VOID
 __DriverAcquireMutex(
     VOID
     )
@@ -219,134 +246,51 @@ DriverRemoveFunctionDeviceObject(
     --Driver.References;
 }
 
-#define SERVICES_KEY 
L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services"
-
-#define SERVICE_KEY(_Driver)    \
-        SERVICES_KEY L"\\" L#_Driver
-
-#define PARAMETERS_KEY(_Driver) \
-        SERVICE_KEY(_Driver) L"\\Parameters"
-
-static NTSTATUS
-DriverSetActiveDeviceInstance(
+static BOOLEAN
+DriverIsActivePresent(
     VOID
     )
 {
-    UNICODE_STRING  Unicode;
-    HANDLE          ParametersKey;
-    PANSI_STRING    Ansi;
-    NTSTATUS        status;
-
-    RtlInitUnicodeString(&Unicode, PARAMETERS_KEY(XENBUS));
-    
-    status = RegistryOpenKey(NULL, &Unicode, KEY_READ, &ParametersKey);
+    CHAR        ActiveDeviceID[MAX_DEVICE_ID_LEN];
+    CHAR        ActiveInstanceID[MAX_DEVICE_ID_LEN];
+    BOOLEAN     Present;
+    NTSTATUS    status;
+
+    status = XENFILT_PVDEVICE(Acquire, &Driver.PvdeviceInterface);
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    status = RegistryQuerySzValue(ParametersKey,
-                                  "ActiveDeviceID",
-                                  &Ansi);
-    if (!NT_SUCCESS(status)) {
-        if (status != STATUS_OBJECT_NAME_NOT_FOUND)
-            goto fail2;
-
-        // The active device is not yet set
-        goto done;
-    }
-
-    Driver.ActiveDeviceID = __DriverAllocate(Ansi[0].MaximumLength);
-
-    status = STATUS_NO_MEMORY;
-    if (Driver.ActiveDeviceID == NULL)
-        goto fail3;
-
-    RtlCopyMemory(Driver.ActiveDeviceID, Ansi[0].Buffer, Ansi[0].Length);
-
-    RegistryFreeSzValue(Ansi);
-        
-    status = RegistryQuerySzValue(ParametersKey,
-                                  "ActiveInstanceID",
-                                  &Ansi);
+    status = XENFILT_EMULATED(Acquire, &Driver.EmulatedInterface);
     if (!NT_SUCCESS(status))
-        goto fail4;
-
-    Driver.ActiveInstanceID = __DriverAllocate(Ansi[0].MaximumLength);
+        goto fail2;
 
-    status = STATUS_NO_MEMORY;
-    if (Driver.ActiveInstanceID == NULL)
-        goto fail5;
+    Present = FALSE;
 
-    RtlCopyMemory(Driver.ActiveInstanceID, Ansi[0].Buffer, Ansi[0].Length);
+    status = XENFILT_PVDEVICE(GetActive,
+                              &Driver.PvdeviceInterface,
+                              ActiveDeviceID,
+                              ActiveInstanceID);
+    if (!NT_SUCCESS(status))
+        goto done;
 
-    RegistryFreeSzValue(Ansi);
+    Present = XENFILT_EMULATED(IsDevicePresent,
+                               &Driver.EmulatedInterface,
+                               ActiveDeviceID,
+                               NULL);
 
 done:
-    if (Driver.ActiveDeviceID != NULL)
-        Info("%s/%s\n", Driver.ActiveDeviceID, Driver.ActiveInstanceID);
-
-    RegistryCloseKey(ParametersKey);
-
-    return STATUS_SUCCESS;
-
-fail5:
-    Error("fail5\n");
-
-    RegistryFreeSzValue(Ansi);
-
-fail4:
-    Error("fail4\n");
-
-    __DriverFree(Driver.ActiveDeviceID);
-    Driver.ActiveDeviceID = NULL;
-
-    goto fail2;
-
-fail3:
-    Error("fail3\n");
+    XENFILT_EMULATED(Release, &Driver.EmulatedInterface);
+    XENFILT_PVDEVICE(Release, &Driver.PvdeviceInterface);
 
-    RegistryFreeSzValue(Ansi);
+    return Present;
 
 fail2:
     Error("fail2\n");
 
-    RegistryCloseKey(ParametersKey);
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    return status;
-}
-
-static PCHAR
-__DriverGetActiveDeviceID(
-    VOID
-    )
-{
-    return Driver.ActiveDeviceID;
-}
-
-PCHAR
-DriverGetActiveDeviceID(
-    VOID
-    )
-{
-    return __DriverGetActiveDeviceID();
-}
-
-static FORCEINLINE PCHAR
-__DriverGetActiveInstanceID(
-    VOID
-    )
-{
-    return Driver.ActiveInstanceID;
-}
-
-PCHAR
-DriverGetActiveInstanceID(
-    VOID
-    )
-{
-    return __DriverGetActiveInstanceID();
+    return FALSE;
 }
 
 VOID
@@ -359,7 +303,6 @@ DriverSetFilterState(
     switch (Driver.FilterState) {
     case XENFILT_FILTER_ENABLED: {
         PLIST_ENTRY ListEntry;
-        BOOLEAN     Present;
 
         // Assume all FDOs have enumerated until we know otherwise
         Driver.FilterState = XENFILT_FILTER_PENDING;
@@ -379,15 +322,11 @@ DriverSetFilterState(
         if (Driver.FilterState != XENFILT_FILTER_PENDING)
             break;
 
-        Present = XENFILT_EMULATED(IsDevicePresent,
-                                   &Driver.EmulatedInterface,
-                                   __DriverGetActiveDeviceID(),
-                                   NULL);
+        if (DriverIsActivePresent()) {
+            Info("ACTIVE DEVICE %sPRESENT\n", (!Present) ? "NOT " : "");
 
-        Info("ACTIVE DEVICE %sPRESENT\n", (!Present) ? "NOT " : "");
-
-        if (Present)
             UnplugDevices();
+        }
 
         Info("PENDING\n");
         break;
@@ -446,22 +385,18 @@ DriverUnload(
     RtlZeroMemory(&Driver.List, sizeof (LIST_ENTRY));
     RtlZeroMemory(&Driver.Mutex, sizeof (MUTEX));
 
-    XENFILT_EMULATED(Release, &Driver.EmulatedInterface);
+    RtlZeroMemory(&Driver.PvdeviceInterface,
+                  sizeof (XENFILT_PVDEVICE_INTERFACE));
 
     RtlZeroMemory(&Driver.EmulatedInterface,
                   sizeof (XENFILT_EMULATED_INTERFACE));
 
+    PvdeviceTeardown(Driver.PvdeviceContext);
+    Driver.PvdeviceContext = NULL;
+
     EmulatedTeardown(Driver.EmulatedContext);
     Driver.EmulatedContext = NULL;
 
-    if (Driver.ActiveDeviceID != NULL) {
-        __DriverFree(Driver.ActiveDeviceID);
-        Driver.ActiveDeviceID = NULL;
-
-        __DriverFree(Driver.ActiveInstanceID);
-        Driver.ActiveInstanceID = NULL;
-    }
-
     ParametersKey = __DriverGetParametersKey();
     __DriverSetParametersKey(NULL);
     RegistryCloseKey(ParametersKey);
@@ -507,8 +442,8 @@ DriverQueryIdCompletion(
 static FORCEINLINE NTSTATUS
 DriverQueryId(
     IN  PDEVICE_OBJECT      PhysicalDeviceObject,
-    IN  BUS_QUERY_ID_TYPE   IdType,
-    OUT PVOID               *Information
+    IN  BUS_QUERY_ID_TYPE   Type,
+    OUT PCHAR               Id
     )
 {
     PDEVICE_OBJECT          DeviceObject;
@@ -532,7 +467,7 @@ DriverQueryId(
     StackLocation->MajorFunction = IRP_MJ_PNP;
     StackLocation->MinorFunction = IRP_MN_QUERY_ID;
     StackLocation->Flags = 0;
-    StackLocation->Parameters.QueryId.IdType = IdType;
+    StackLocation->Parameters.QueryId.IdType = Type;
     StackLocation->DeviceObject = DeviceObject;
     StackLocation->FileObject = NULL;
 
@@ -563,7 +498,13 @@ DriverQueryId(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    *Information = (PVOID)Irp->IoStatus.Information;
+    status = RtlStringCbPrintfA(Id,
+                                MAX_DEVICE_ID_LEN,
+                                "%ws",
+                                (PWCHAR)Irp->IoStatus.Information);
+    ASSERT(NT_SUCCESS(status));
+
+    ExFreePool((PVOID)Irp->IoStatus.Information);
 
     IoFreeIrp(Irp);
     ObDereferenceObject(DeviceObject);
@@ -606,10 +547,8 @@ DriverAddDevice(
     )
 {
     HANDLE              ParametersKey;
-    PWCHAR              DeviceID;
-    PWCHAR              InstanceID;
-    UNICODE_STRING      Unicode;
-    ANSI_STRING         Name;
+    CHAR                DeviceID[MAX_DEVICE_ID_LEN];
+    CHAR                InstanceID[MAX_DEVICE_ID_LEN];
     PANSI_STRING        Type;
     NTSTATUS            status;
 
@@ -617,22 +556,20 @@ DriverAddDevice(
 
     ParametersKey = __DriverGetParametersKey();
 
-    status = DriverQueryId(PhysicalDeviceObject, BusQueryDeviceID, &DeviceID);
+    status = DriverQueryId(PhysicalDeviceObject,
+                           BusQueryDeviceID,
+                           DeviceID);
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    status = DriverQueryId(PhysicalDeviceObject, BusQueryInstanceID, 
&InstanceID);
+    status = DriverQueryId(PhysicalDeviceObject,
+                           BusQueryInstanceID,
+                           InstanceID);
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    RtlInitUnicodeString(&Unicode, DeviceID);
-
-    status = RtlUnicodeStringToAnsiString(&Name, &Unicode, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
     status = RegistryQuerySzValue(ParametersKey,
-                                  Name.Buffer,
+                                  DeviceID,
                                   &Type);
     if (NT_SUCCESS(status)) {
         status = FdoCreate(PhysicalDeviceObject,
@@ -641,28 +578,15 @@ DriverAddDevice(
                            DriverGetEmulatedType(Type));
 
         if (!NT_SUCCESS(status))
-            goto fail4;
+            goto fail3;
 
         RegistryFreeSzValue(Type);
     }
 
-    RtlFreeAnsiString(&Name);
-    ExFreePool(InstanceID);
-    ExFreePool(DeviceID);
-
     return STATUS_SUCCESS;
 
-fail4:
-    RegistryFreeSzValue(Type);
-
-    RtlFreeAnsiString(&Name);
-
 fail3:
-    ExFreePool(InstanceID);
-
 fail2:
-    ExFreePool(DeviceID);
-
 fail1:
     return status;
 }
@@ -723,6 +647,7 @@ DriverEntry(
     HANDLE                      ServiceKey;
     HANDLE                      ParametersKey;
     PXENFILT_EMULATED_CONTEXT   EmulatedContext;
+    PXENFILT_PVDEVICE_CONTEXT   PvdeviceContext;
     ULONG                       Index;
     NTSTATUS                    status;
 
@@ -773,26 +698,29 @@ DriverEntry(
 
     __DriverSetParametersKey(ParametersKey);
 
-    status = DriverSetActiveDeviceInstance();
+    status = EmulatedInitialize(&EmulatedContext);
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    status = EmulatedInitialize(&EmulatedContext);
+    __DriverSetEmulatedContext(EmulatedContext);
+
+    status = PvdeviceInitialize(&PvdeviceContext);
     if (!NT_SUCCESS(status))
         goto fail5;
 
-    __DriverSetEmulatedContext(EmulatedContext);
+    __DriverSetPvdeviceContext(PvdeviceContext);
 
     status = EmulatedGetInterface(__DriverGetEmulatedContext(),
                                   XENFILT_EMULATED_INTERFACE_VERSION_MAX,
                                   (PINTERFACE)&Driver.EmulatedInterface,
                                   sizeof (Driver.EmulatedInterface));
     ASSERT(NT_SUCCESS(status));
-    ASSERT(Driver.EmulatedInterface.Interface.Context != NULL);
 
-    status = XENFILT_EMULATED(Acquire, &Driver.EmulatedInterface);
-    if (!NT_SUCCESS(status))
-        goto fail6;
+    status = PvdeviceGetInterface(__DriverGetPvdeviceContext(),
+                                  XENFILT_PVDEVICE_INTERFACE_VERSION_MAX,
+                                  (PINTERFACE)&Driver.PvdeviceInterface,
+                                  sizeof (Driver.PvdeviceInterface));
+    ASSERT(NT_SUCCESS(status));
 
     RegistryCloseKey(ServiceKey);
 
@@ -812,22 +740,11 @@ done:
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail6:
-    Error("fail6\n");
-
-    EmulatedTeardown(Driver.EmulatedContext);
-    Driver.EmulatedContext = NULL;
-
 fail5:
     Error("fail5\n");
 
-    if (Driver.ActiveDeviceID != NULL) {
-        __DriverFree(Driver.ActiveDeviceID);
-        Driver.ActiveDeviceID = NULL;
-
-        __DriverFree(Driver.ActiveInstanceID);
-        Driver.ActiveInstanceID = NULL;
-    }
+    EmulatedTeardown(Driver.EmulatedContext);
+    Driver.EmulatedContext = NULL;
 
 fail4:
     Error("fail4\n");
diff --git a/src/xenfilt/driver.h b/src/xenfilt/driver.h
index f906d36..772436d 100644
--- a/src/xenfilt/driver.h
+++ b/src/xenfilt/driver.h
@@ -42,16 +42,6 @@ DriverGetParametersKey(
     VOID
     );
 
-extern PCHAR
-DriverGetActiveDeviceID(
-    VOID
-    );
-
-extern PCHAR
-DriverGetActiveInstanceID(
-    VOID
-    );
-
 extern VOID
 DriverAcquireMutex(
     VOID
@@ -85,6 +75,13 @@ DriverGetEmulatedContext(
     VOID
     );
 
+#include "pvdevice.h"
+
+PXENFILT_PVDEVICE_CONTEXT
+DriverGetPvdeviceContext(
+    VOID
+    );
+
 typedef struct _XENFILT_FDO XENFILT_FDO, *PXENFILT_FDO;
 typedef struct _XENFILT_PDO XENFILT_PDO, *PXENFILT_PDO;
 
@@ -116,8 +113,8 @@ typedef struct _XENFILT_DX {
     SYSTEM_POWER_STATE  SystemPowerState;
     DEVICE_POWER_STATE  DevicePowerState;
 
-    WCHAR               DeviceID[MAX_DEVICE_ID_LEN];
-    WCHAR               InstanceID[MAX_DEVICE_ID_LEN];
+    CHAR                DeviceID[MAX_DEVICE_ID_LEN];
+    CHAR                InstanceID[MAX_DEVICE_ID_LEN];
 
     IO_REMOVE_LOCK      RemoveLock;
 
diff --git a/src/xenfilt/emulated.c b/src/xenfilt/emulated.c
index 485fed6..31391ed 100644
--- a/src/xenfilt/emulated.c
+++ b/src/xenfilt/emulated.c
@@ -92,21 +92,21 @@ __EmulatedFree(
 static NTSTATUS
 EmulatedSetObjectDeviceData(
     IN  PXENFILT_EMULATED_OBJECT    EmulatedObject,
-    IN  PWCHAR                      DeviceID,
-    IN  PWCHAR                      InstanceID
+    IN  PCHAR                       DeviceID,
+    IN  PCHAR                       InstanceID
     )
 {
     NTSTATUS                        status;
 
     status = RtlStringCbPrintfA(EmulatedObject->Data.Device.DeviceID,
                                 MAXNAMELEN,
-                                "%ws",
+                                "%s",
                                 DeviceID);
     ASSERT(NT_SUCCESS(status));
 
     status = RtlStringCbPrintfA(EmulatedObject->Data.Device.InstanceID,
                                 MAXNAMELEN,
-                                "%ws",
+                                "%s",
                                 InstanceID);
     ASSERT(NT_SUCCESS(status));
 
@@ -116,12 +116,10 @@ EmulatedSetObjectDeviceData(
 static NTSTATUS
 EmulatedSetObjectDiskData(
     IN  PXENFILT_EMULATED_OBJECT    EmulatedObject,
-    IN  PWCHAR                      DeviceID,
-    IN  PWCHAR                      InstanceID
+    IN  PCHAR                       DeviceID,
+    IN  PCHAR                       InstanceID
     )
 {
-    UNICODE_STRING                  Unicode;
-    ANSI_STRING                     Ansi;
     PCHAR                           End;
     ULONG                           Controller;
     ULONG                           Target;
@@ -130,17 +128,11 @@ EmulatedSetObjectDiskData(
 
     UNREFERENCED_PARAMETER(DeviceID);
 
-    RtlInitUnicodeString(&Unicode, InstanceID);
-
-    status = RtlUnicodeStringToAnsiString(&Ansi, &Unicode, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    Controller = strtol(Ansi.Buffer, &End, 10);
+    Controller = strtol(InstanceID, &End, 10);
 
     status = STATUS_INVALID_PARAMETER;
     if (*End != '.')
-        goto fail2;
+        goto fail1;
 
     End++;
 
@@ -148,7 +140,7 @@ EmulatedSetObjectDiskData(
 
     status = STATUS_INVALID_PARAMETER;
     if (*End != '.')
-        goto fail3;
+        goto fail2;
 
     End++;
 
@@ -156,27 +148,20 @@ EmulatedSetObjectDiskData(
 
     status = STATUS_INVALID_PARAMETER;
     if (*End != '\0')
-        goto fail4;
+        goto fail3;
 
     EmulatedObject->Data.Disk.Controller = Controller;
     EmulatedObject->Data.Disk.Target = Target;
     EmulatedObject->Data.Disk.Lun = Lun;
 
-    RtlFreeAnsiString(&Ansi);
-
     return STATUS_SUCCESS;
 
-fail4:
-    Error("fail4\n");
-
 fail3:
     Error("fail3\n");
 
 fail2:
     Error("fail2\n");
 
-    RtlFreeAnsiString(&Ansi);
-
 fail1:
     Error("fail1 (%08x)\n", status);
 
@@ -186,8 +171,8 @@ fail1:
 NTSTATUS
 EmulatedAddObject(
     IN  PXENFILT_EMULATED_CONTEXT       Context,
-    IN  PWCHAR                          DeviceID,
-    IN  PWCHAR                          InstanceID,
+    IN  PCHAR                           DeviceID,
+    IN  PCHAR                           InstanceID,
     IN  XENFILT_EMULATED_OBJECT_TYPE    Type,
     OUT PXENFILT_EMULATED_OBJECT        *EmulatedObject
     )
diff --git a/src/xenfilt/emulated.h b/src/xenfilt/emulated.h
index cc63a25..778c784 100644
--- a/src/xenfilt/emulated.h
+++ b/src/xenfilt/emulated.h
@@ -67,8 +67,8 @@ EmulatedTeardown(
 extern NTSTATUS
 EmulatedAddObject(
     IN  PXENFILT_EMULATED_CONTEXT       Context,
-    IN  PWCHAR                          DeviceID,
-    IN  PWCHAR                          InstanceID,
+    IN  PCHAR                           DeviceID,
+    IN  PCHAR                           InstanceID,
     IN  XENFILT_EMULATED_OBJECT_TYPE    Type,
     OUT PXENFILT_EMULATED_OBJECT        *EmulatedObject
     );
diff --git a/src/xenfilt/fdo.c b/src/xenfilt/fdo.c
index 25b3dc2..7121eb2 100644
--- a/src/xenfilt/fdo.c
+++ b/src/xenfilt/fdo.c
@@ -186,23 +186,39 @@ FdoGetDeviceObject(
     return __FdoGetDeviceObject(Fdo);
 }
 
+static FORCEINLINE PDEVICE_OBJECT
+__FdoGetPhysicalDeviceObject(
+    IN  PXENFILT_FDO    Fdo
+    )
+{
+    return Fdo->PhysicalDeviceObject;
+}
+
+PDEVICE_OBJECT
+FdoGetPhysicalDeviceObject(
+    IN  PXENFILT_FDO    Fdo
+    )
+{
+    return __FdoGetPhysicalDeviceObject(Fdo);
+}
+
 static FORCEINLINE VOID
 __FdoSetDeviceID(
     IN  PXENFILT_FDO    Fdo,
-    IN  PWCHAR          DeviceID
+    IN  PCHAR           DeviceID
     )
 {
     PXENFILT_DX         Dx = Fdo->Dx;
     NTSTATUS            status;
 
-    status = RtlStringCbPrintfW(Dx->DeviceID,
+    status = RtlStringCbPrintfA(Dx->DeviceID,
                                 MAX_DEVICE_ID_LEN,
-                                L"%ws",
+                                "%s",
                                 DeviceID);
     ASSERT(NT_SUCCESS(status));
 }
 
-static FORCEINLINE PWCHAR
+static FORCEINLINE PCHAR
 __FdoGetDeviceID(
     IN  PXENFILT_FDO    Fdo
     )
@@ -215,20 +231,20 @@ __FdoGetDeviceID(
 static FORCEINLINE VOID
 __FdoSetInstanceID(
     IN  PXENFILT_FDO    Fdo,
-    IN  PWCHAR          InstanceID
+    IN  PCHAR           InstanceID
     )
 {
     PXENFILT_DX         Dx = Fdo->Dx;
     NTSTATUS            status;
 
-    status = RtlStringCbPrintfW(Dx->InstanceID,
+    status = RtlStringCbPrintfA(Dx->InstanceID,
                                 MAX_DEVICE_ID_LEN,
-                                L"%ws",
+                                "%s",
                                 InstanceID);
     ASSERT(NT_SUCCESS(status));
 }
 
-static FORCEINLINE PWCHAR
+static FORCEINLINE PCHAR
 __FdoGetInstanceID(
     IN  PXENFILT_FDO    Fdo
     )
@@ -247,7 +263,7 @@ __FdoSetName(
 
     status = RtlStringCbPrintfA(Fdo->Name,
                                 MAXNAMELEN,
-                                "%ws\\%ws",
+                                "%s\\%s",
                                 __FdoGetDeviceID(Fdo),
                                 __FdoGetInstanceID(Fdo));
     ASSERT(NT_SUCCESS(status));
@@ -261,14 +277,6 @@ __FdoGetName(
     return Fdo->Name;
 }
 
-static FORCEINLINE PDEVICE_OBJECT
-__FdoGetPhysicalDeviceObject(
-    IN  PXENFILT_FDO    Fdo
-    )
-{
-    return Fdo->PhysicalDeviceObject;
-}
-
 VOID
 FdoAddPhysicalDeviceObject(
     IN  PXENFILT_FDO    Fdo,
@@ -388,8 +396,8 @@ static NTSTATUS
 FdoQueryId(
     IN  PXENFILT_FDO        Fdo,
     IN  PDEVICE_OBJECT      DeviceObject,
-    IN  BUS_QUERY_ID_TYPE   IdType,
-    OUT PVOID               *Information
+    IN  BUS_QUERY_ID_TYPE   Type,
+    OUT PCHAR               Id
     )
 {
     PIRP                    Irp;
@@ -412,7 +420,7 @@ FdoQueryId(
     StackLocation->MajorFunction = IRP_MJ_PNP;
     StackLocation->MinorFunction = IRP_MN_QUERY_ID;
     StackLocation->Flags = 0;
-    StackLocation->Parameters.QueryId.IdType = IdType;
+    StackLocation->Parameters.QueryId.IdType = Type;
     StackLocation->DeviceObject = DeviceObject;
     StackLocation->FileObject = NULL;
 
@@ -443,7 +451,13 @@ FdoQueryId(
     if (!NT_SUCCESS(status))
         goto fail2;
 
-    *Information = (PVOID)Irp->IoStatus.Information;
+    status = RtlStringCbPrintfA(Id,
+                                MAX_DEVICE_ID_LEN,
+                                "%ws",
+                                (PWCHAR)Irp->IoStatus.Information);
+    ASSERT(NT_SUCCESS(status));
+
+    ExFreePool((PVOID)Irp->IoStatus.Information);
 
     IoFreeIrp(Irp);
 
@@ -462,21 +476,21 @@ FdoAddDevice(
     IN  PDEVICE_OBJECT  PhysicalDeviceObject
     )
 {
-    PWCHAR              DeviceID;
-    PWCHAR              InstanceID;
+    CHAR                DeviceID[MAX_DEVICE_ID_LEN];
+    CHAR                InstanceID[MAX_DEVICE_ID_LEN];
     NTSTATUS            status;
 
     status = FdoQueryId(Fdo,
                         PhysicalDeviceObject,
                         BusQueryDeviceID,
-                        &DeviceID);
+                        DeviceID);
     if (!NT_SUCCESS(status))
         goto fail1;
 
     status = FdoQueryId(Fdo,
                         PhysicalDeviceObject,
                         BusQueryInstanceID,
-                        &InstanceID);
+                        InstanceID);
     if (!NT_SUCCESS(status))
         goto fail2;
 
@@ -488,17 +502,10 @@ FdoAddDevice(
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    ExFreePool(InstanceID);
-    ExFreePool(DeviceID);
-
     return STATUS_SUCCESS;
 
 fail3:
-    ExFreePool(InstanceID);
-
 fail2:
-    ExFreePool(DeviceID);
-
 fail1:
     return status;
 }
@@ -1983,8 +1990,8 @@ FdoDispatch(
 NTSTATUS
 FdoCreate(
     IN  PDEVICE_OBJECT                  PhysicalDeviceObject,
-    IN  PWCHAR                          DeviceID,
-    IN  PWCHAR                          InstanceID,
+    IN  PCHAR                           DeviceID,
+    IN  PCHAR                           InstanceID,
     IN  XENFILT_EMULATED_OBJECT_TYPE    Type
     )
 {
diff --git a/src/xenfilt/fdo.h b/src/xenfilt/fdo.h
index b871b26..62a667f 100644
--- a/src/xenfilt/fdo.h
+++ b/src/xenfilt/fdo.h
@@ -43,8 +43,8 @@ typedef struct _XENFILT_FDO XENFILT_FDO, *PXENFILT_FDO;
 extern NTSTATUS
 FdoCreate(
     IN  PDEVICE_OBJECT                  PhysicalDeviceObject,
-    IN  PWCHAR                          DeviceID,
-    IN  PWCHAR                          InstanceID,
+    IN  PCHAR                           DeviceID,
+    IN  PCHAR                           InstanceID,
     IN  XENFILT_EMULATED_OBJECT_TYPE    Type
     );
 
@@ -85,6 +85,11 @@ FdoGetDeviceObject(
     IN  PXENFILT_FDO    Fdo
     );
 
+extern PDEVICE_OBJECT
+FdoGetPhysicalDeviceObject(
+    IN  PXENFILT_FDO    Fdo
+    );
+
 extern BOOLEAN
 FdoHasEnumerated(
     IN  PXENFILT_FDO    Fdo
diff --git a/src/xenfilt/pdo.c b/src/xenfilt/pdo.c
index 6fab346..57502f3 100644
--- a/src/xenfilt/pdo.c
+++ b/src/xenfilt/pdo.c
@@ -37,6 +37,7 @@
 #include <stdlib.h>
 
 #include "emulated.h"
+#include "pvdevice.h"
 #include "names.h"
 #include "fdo.h"
 #include "pdo.h"
@@ -65,6 +66,8 @@ struct _XENFILT_PDO {
 
     XENFILT_EMULATED_OBJECT_TYPE    Type;
     PXENFILT_EMULATED_OBJECT        EmulatedObject;
+
+    XENFILT_PVDEVICE_INTERFACE      PvdeviceInterface;
 };
 
 static FORCEINLINE PVOID
@@ -213,74 +216,74 @@ __PdoGetFdo(
     return Pdo->Fdo;
 }
 
-static FORCEINLINE VOID
-__PdoSetDeviceID(
+static NTSTATUS
+PdoSetDeviceInstance(
     IN  PXENFILT_PDO    Pdo,
-    IN  PWCHAR          DeviceID
+    IN  PCHAR           DeviceID,
+    IN  PCHAR           InstanceID
     )
 {
     PXENFILT_DX         Dx = Pdo->Dx;
+    CHAR                ActiveDeviceID[MAX_DEVICE_ID_LEN];
+    CHAR                ActiveInstanceID[MAX_DEVICE_ID_LEN];
     NTSTATUS            status;
 
-    status = RtlStringCbPrintfW(Dx->DeviceID,
-                                MAX_DEVICE_ID_LEN,
-                                L"%ws",
-                                DeviceID);
-    ASSERT(NT_SUCCESS(status));
-}
-
-static FORCEINLINE PWCHAR
-__PdoGetDeviceID(
-    IN  PXENFILT_PDO    Pdo
-    )
-{
-    PXENFILT_DX         Dx = Pdo->Dx;
-
-    return Dx->DeviceID;
-}
-
-static FORCEINLINE VOID
-__PdoSetInstanceID(
-    IN  PXENFILT_PDO    Pdo,
-    IN  PWCHAR          InstanceID
-    )
-{
-    WCHAR               ActiveDeviceID[MAX_DEVICE_ID_LEN];
-    WCHAR               ActiveInstanceID[MAX_DEVICE_ID_LEN];
-    PXENFILT_DX         Dx = Pdo->Dx;
-    NTSTATUS            status;
+    status = XENFILT_PVDEVICE(Acquire, &Pdo->PvdeviceInterface);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-    RtlStringCbPrintfW(ActiveDeviceID,
-                       sizeof (ActiveDeviceID),
-                       L"%hs",
-                       DriverGetActiveDeviceID());
-    
-    RtlStringCbPrintfW(ActiveInstanceID,
-                       sizeof (ActiveInstanceID),
-                       L"%hs",
-                       DriverGetActiveInstanceID());
+    status = XENFILT_PVDEVICE(GetActive,
+                              &Pdo->PvdeviceInterface,
+                              ActiveDeviceID,
+                              ActiveInstanceID);
+    if (!NT_SUCCESS(status))
+        goto done;
 
-    if (_wcsicmp(Dx->DeviceID, ActiveDeviceID) != 0)
+    if (_stricmp(DeviceID, ActiveDeviceID) != 0)
         goto done;
 
-    if (_wcsicmp(InstanceID, ActiveInstanceID) != 0) {
-        Warning("(%ws) '%ws' -> '%ws'\n",
+    if (_stricmp(InstanceID, ActiveInstanceID) != 0) {
+        Warning("(%s) '%s' -> '%s'\n",
                 Dx->DeviceID,
                 InstanceID,
                 ActiveInstanceID);
-
         InstanceID = ActiveInstanceID;
     }
 
 done:
-    status = RtlStringCbPrintfW(Dx->InstanceID,
+    XENFILT_PVDEVICE(Release, &Pdo->PvdeviceInterface);
+
+    status = RtlStringCbPrintfA(Dx->DeviceID,
                                 MAX_DEVICE_ID_LEN,
-                                L"%ws",
+                                "%s",
+                                DeviceID);
+    ASSERT(NT_SUCCESS(status));
+
+    status = RtlStringCbPrintfA(Dx->InstanceID,
+                                MAX_DEVICE_ID_LEN,
+                                "%s",
                                 InstanceID);
     ASSERT(NT_SUCCESS(status));
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static FORCEINLINE PCHAR
+__PdoGetDeviceID(
+    IN  PXENFILT_PDO    Pdo
+    )
+{
+    PXENFILT_DX         Dx = Pdo->Dx;
+
+    return Dx->DeviceID;
 }
 
-static FORCEINLINE PWCHAR
+static FORCEINLINE PCHAR
 __PdoGetInstanceID(
     IN  PXENFILT_PDO    Pdo
     )
@@ -300,7 +303,7 @@ __PdoSetName(
 
     status = RtlStringCbPrintfA(Pdo->Name,
                                 MAXNAMELEN,
-                                "%ws\\%ws",
+                                "%s\\%s",
                                 Dx->DeviceID,
                                 Dx->InstanceID);
     ASSERT(NT_SUCCESS(status));
@@ -793,6 +796,9 @@ done:
     PdoDestroy(Pdo);
     FdoReleaseMutex(Fdo);
 
+    IoInvalidateDeviceRelations(FdoGetPhysicalDeviceObject(Fdo),
+                                BusRelations);
+
     return status;
 
 fail1:
@@ -863,6 +869,7 @@ done:                                                       
        \
 }                                                                   \
 
 DEFINE_PDO_QUERY_INTERFACE(Emulated)
+DEFINE_PDO_QUERY_INTERFACE(Pvdevice)
 
 struct _INTERFACE_ENTRY {
     const GUID  *Guid;
@@ -875,6 +882,7 @@ struct _INTERFACE_ENTRY {
 
 struct _INTERFACE_ENTRY PdoInterfaceTable[] = {
     DEFINE_INTERFACE_ENTRY(EMULATED_INTERFACE, Emulated),
+    DEFINE_INTERFACE_ENTRY(PVDEVICE_INTERFACE, Pvdevice),
     { NULL, NULL, NULL }
 };
 
@@ -983,7 +991,7 @@ PdoQueryId(
     case BusQueryInstanceID:
         status = RtlStringCbPrintfW(Buffer,
                                     Id.MaximumLength,
-                                    L"%s",
+                                    L"%hs",
                                     __PdoGetInstanceID(Pdo));
         ASSERT(NT_SUCCESS(status));
 
@@ -993,7 +1001,7 @@ PdoQueryId(
     case BusQueryDeviceID:
         status = RtlStringCbPrintfW(Buffer,
                                     Id.MaximumLength,
-                                    L"%s",
+                                    L"%hs",
                                     __PdoGetDeviceID(Pdo));
         ASSERT(NT_SUCCESS(status));
 
@@ -1880,8 +1888,8 @@ NTSTATUS
 PdoCreate(
     PXENFILT_FDO                    Fdo,
     PDEVICE_OBJECT                  PhysicalDeviceObject,
-    PWCHAR                          DeviceID,
-    PWCHAR                          InstanceID,
+    PCHAR                           DeviceID,
+    PCHAR                           InstanceID,
     XENFILT_EMULATED_OBJECT_TYPE    Type
     )
 {
@@ -1953,8 +1961,16 @@ PdoCreate(
     if (!NT_SUCCESS(status))
         goto fail6;
 
-    __PdoSetDeviceID(Pdo, DeviceID);
-    __PdoSetInstanceID(Pdo, InstanceID);
+    status = PvdeviceGetInterface(DriverGetPvdeviceContext(),
+                                  XENFILT_PVDEVICE_INTERFACE_VERSION_MAX,
+                                  (PINTERFACE)&Pdo->PvdeviceInterface,
+                                  sizeof (Pdo->PvdeviceInterface));
+    ASSERT(NT_SUCCESS(status));
+
+    status = PdoSetDeviceInstance(Pdo, DeviceID, InstanceID);
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
     __PdoSetName(Pdo);
 
     Info("%p (%s)\n",
@@ -1974,6 +1990,12 @@ PdoCreate(
 
     return STATUS_SUCCESS;
 
+fail7:
+    Error("fail7\n");
+
+    RtlZeroMemory(&Pdo->PvdeviceInterface,
+                  sizeof (XENFILT_PVDEVICE_INTERFACE));
+
 fail6:
     Error("fail6\n");
 
@@ -2038,6 +2060,9 @@ PdoDestroy(
 
     RtlZeroMemory(Pdo->Name, sizeof (Pdo->Name));
 
+    RtlZeroMemory(&Pdo->PvdeviceInterface,
+                  sizeof (XENFILT_PVDEVICE_INTERFACE));
+
     EmulatedRemoveObject(DriverGetEmulatedContext(),
                          Pdo->EmulatedObject);
     Pdo->EmulatedObject = NULL;
diff --git a/src/xenfilt/pdo.h b/src/xenfilt/pdo.h
index 05ca049..aac5702 100644
--- a/src/xenfilt/pdo.h
+++ b/src/xenfilt/pdo.h
@@ -65,8 +65,8 @@ extern NTSTATUS
 PdoCreate(
     IN  PXENFILT_FDO                    Fdo,
     IN  PDEVICE_OBJECT                  PhysicalDeviceObject,
-    IN  PWCHAR                          DeviceID,
-    IN  PWCHAR                          InstanceID,
+    IN  PCHAR                           DeviceID,
+    IN  PCHAR                           InstanceID,
     IN  XENFILT_EMULATED_OBJECT_TYPE    Type
     );
 
diff --git a/src/xenfilt/pvdevice.c b/src/xenfilt/pvdevice.c
new file mode 100644
index 0000000..5f9345d
--- /dev/null
+++ b/src/xenfilt/pvdevice.c
@@ -0,0 +1,439 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ntddk.h>
+#include <ntstrsafe.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <xen.h>
+
+#include "driver.h"
+#include "registry.h"
+#include "emulated.h"
+#include "pvdevice.h"
+#include "mutex.h"
+#include "dbg_print.h"
+#include "assert.h"
+#include "util.h"
+
+struct _XENFILT_PVDEVICE_CONTEXT {
+    KSPIN_LOCK                  Lock;
+    LONG                        References;
+    XENFILT_EMULATED_INTERFACE  EmulatedInterface;
+    MUTEX                       Mutex;
+};
+
+#define XENFILT_PVDEVICE_TAG    'EDVP'
+
+static FORCEINLINE PVOID
+__PvdeviceAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENFILT_PVDEVICE_TAG);
+}
+
+static FORCEINLINE VOID
+__PvdeviceFree(
+    IN  PVOID   Buffer
+    )
+{
+    ExFreePoolWithTag(Buffer, XENFILT_PVDEVICE_TAG);
+}
+
+static const CHAR *PvdeviceLegacyPrefix[] = {
+    "PCI\\VEN_5853&DEV_0001",
+    "PCI\\VEN_5853&DEV_0002",
+};
+
+static BOOLEAN
+PvdeviceIsLegacy(
+    IN  PXENFILT_PVDEVICE_CONTEXT   Context,
+    IN  PCHAR                       DeviceID
+    )
+{
+    ULONG                           Index;
+
+    UNREFERENCED_PARAMETER(Context);
+
+    for (Index = 0; Index < ARRAYSIZE(PvdeviceLegacyPrefix); Index++) {
+        const CHAR  *Prefix = PvdeviceLegacyPrefix[Index];
+
+        if (_strnicmp(DeviceID, Prefix, strlen(Prefix)) == 0)
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+static const CHAR *PvdeviceVendorDeviceID[] = {
+    "PCI\\VEN_5853&DEV_C000&SUBSYS_C0005853&REV_01", // XenServer
+};
+
+static BOOLEAN
+PvdeviceIsVendorPresent(
+    IN  PXENFILT_PVDEVICE_CONTEXT   Context
+    )
+{
+    ULONG                           Index;
+
+    for (Index = 0; Index < ARRAYSIZE(PvdeviceVendorDeviceID); Index++) {
+        const CHAR  *DeviceID = PvdeviceVendorDeviceID[Index];
+
+        if (XENFILT_EMULATED(IsDevicePresent,
+                             &Context->EmulatedInterface,
+                             (PCHAR)DeviceID,
+                             NULL))
+            return TRUE;
+    }
+
+    return FALSE;
+}
+
+static NTSTATUS
+PvdeviceGetActive(
+    IN  PINTERFACE              Interface,
+    OUT PCHAR                   DeviceID,
+    OUT PCHAR                   InstanceID
+    )
+{
+    PXENFILT_PVDEVICE_CONTEXT   Context = Interface->Context;
+    HANDLE                      ParametersKey;
+    PANSI_STRING                Ansi;
+    NTSTATUS                    status;
+
+    Trace("====>\n");
+
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+
+    ParametersKey = DriverGetParametersKey();
+
+    AcquireMutex(&Context->Mutex);
+
+    status = RegistryQuerySzValue(ParametersKey,
+                                  "ActiveDeviceID",
+                                  &Ansi);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = RtlStringCbPrintfA(DeviceID,
+                                MAX_DEVICE_ID_LEN,
+                                "%Z",
+                                &Ansi[0]);
+    ASSERT(NT_SUCCESS(status));
+
+    RegistryFreeSzValue(Ansi);
+
+    status = RegistryQuerySzValue(ParametersKey,
+                                  "ActiveInstanceID",
+                                  &Ansi);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = RtlStringCbPrintfA(InstanceID,
+                                MAX_DEVICE_ID_LEN,
+                                "%Z",
+                                &Ansi[0]);
+    ASSERT(NT_SUCCESS(status));
+
+    RegistryFreeSzValue(Ansi);
+
+    ReleaseMutex(&Context->Mutex);
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail2:
+fail1:
+    ReleaseMutex(&Context->Mutex);
+
+    return status;
+}
+
+static NTSTATUS
+PvdeviceSetActive(
+    IN  PINTERFACE              Interface,
+    IN  PCHAR                   DeviceID,
+    IN  PCHAR                   InstanceID
+    )
+{
+    PXENFILT_PVDEVICE_CONTEXT   Context = Interface->Context;
+    HANDLE                      ParametersKey;
+    ANSI_STRING                 Ansi[2];
+    NTSTATUS                    status;
+
+    Trace("====>\n");
+
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+
+    ParametersKey = DriverGetParametersKey();
+
+    AcquireMutex(&Context->Mutex);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (PvdeviceIsLegacy(Context, DeviceID) &&
+        PvdeviceIsVendorPresent(Context))
+        goto fail1;
+
+    RtlZeroMemory(Ansi, sizeof (ANSI_STRING) * 2);
+
+    RtlInitAnsiString(&Ansi[0], DeviceID);
+
+    status = RegistryUpdateSzValue(ParametersKey,
+                                   "ActiveDeviceID",
+                                   Ansi);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    RtlInitAnsiString(&Ansi[0], InstanceID);
+
+    status = RegistryUpdateSzValue(ParametersKey,
+                                   "ActiveInstanceID",
+                                   Ansi);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    Info("%s\\%s\n", DeviceID, InstanceID);
+
+    ReleaseMutex(&Context->Mutex);
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail3:
+fail2:
+fail1:
+    ReleaseMutex(&Context->Mutex);
+
+    return status;
+}
+
+static NTSTATUS
+PvdeviceClearActive(
+    IN  PINTERFACE              Interface
+    )
+{
+    PXENFILT_PVDEVICE_CONTEXT   Context = Interface->Context;
+    HANDLE                      ParametersKey;
+    NTSTATUS                    status;
+
+    Trace("====>\n");
+
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+
+    ParametersKey = DriverGetParametersKey();
+
+    AcquireMutex(&Context->Mutex);
+
+    status = RegistryDeleteValue(ParametersKey,
+                                 "ActiveDeviceID");
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = RegistryDeleteValue(ParametersKey,
+                                 "ActiveInstanceID");
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    Info("DONE\n");
+
+    ReleaseMutex(&Context->Mutex);
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail2:
+fail1:
+    ReleaseMutex(&Context->Mutex);
+
+    return status;
+}
+
+static NTSTATUS
+PvdeviceAcquire(
+    IN  PINTERFACE              Interface
+    )
+{
+    PXENFILT_PVDEVICE_CONTEXT   Context = Interface->Context;
+    KIRQL                       Irql;
+    NTSTATUS                    status;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (Context->References++ != 0)
+        goto done;
+
+    Trace("====>\n");
+
+    status = XENFILT_EMULATED(Acquire, &Context->EmulatedInterface);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return status;
+}
+
+static VOID
+PvdeviceRelease(
+    IN  PINTERFACE              Interface
+    )
+{
+    PXENFILT_PVDEVICE_CONTEXT   Context = Interface->Context;
+    KIRQL                       Irql;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (--Context->References > 0)
+        goto done;
+
+    Trace("====>\n");
+
+    XENFILT_EMULATED(Release, &Context->EmulatedInterface);
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+}
+
+static struct _XENFILT_PVDEVICE_INTERFACE_V1 PvdeviceInterfaceVersion1 = {
+    { sizeof (struct _XENFILT_PVDEVICE_INTERFACE_V1), 1, NULL, NULL, NULL },
+    PvdeviceAcquire,
+    PvdeviceRelease,
+    PvdeviceGetActive,
+    PvdeviceSetActive,
+    PvdeviceClearActive
+};
+
+NTSTATUS
+PvdeviceInitialize(
+    OUT PXENFILT_PVDEVICE_CONTEXT   *Context
+    )
+{
+    NTSTATUS                        status;
+
+    Trace("====>\n");
+
+    *Context = __PvdeviceAllocate(sizeof (XENFILT_PVDEVICE_CONTEXT));
+
+    status = STATUS_NO_MEMORY;
+    if (*Context == NULL)
+        goto fail1;
+
+    status = EmulatedGetInterface(DriverGetEmulatedContext(),
+                                  XENFILT_EMULATED_INTERFACE_VERSION_MAX,
+                                  (PINTERFACE)&(*Context)->EmulatedInterface,
+                                  sizeof ((*Context)->EmulatedInterface));
+    ASSERT(NT_SUCCESS(status));
+
+    KeInitializeSpinLock(&(*Context)->Lock);
+    InitializeMutex(&(*Context)->Mutex);
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+PvdeviceGetInterface(
+    IN      PXENFILT_PVDEVICE_CONTEXT   Context,
+    IN      ULONG                       Version,
+    IN OUT  PINTERFACE                  Interface,
+    IN      ULONG                       Size
+    )
+{
+    NTSTATUS                            status;
+
+    ASSERT(Context != NULL);
+
+    switch (Version) {
+    case 1: {
+        struct _XENFILT_PVDEVICE_INTERFACE_V1   *PvdeviceInterface;
+
+        PvdeviceInterface = (struct _XENFILT_PVDEVICE_INTERFACE_V1 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENFILT_PVDEVICE_INTERFACE_V1))
+            break;
+
+        *PvdeviceInterface = PvdeviceInterfaceVersion1;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
+    default:
+        status = STATUS_NOT_SUPPORTED;
+        break;
+    }
+
+    return status;
+}
+
+VOID
+PvdeviceTeardown(
+    IN  PXENFILT_PVDEVICE_CONTEXT   Context
+    )
+{
+    Trace("====>\n");
+
+    RtlZeroMemory(&Context->Mutex, sizeof (MUTEX));
+    RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
+
+    RtlZeroMemory(&Context->EmulatedInterface,
+                  sizeof (XENFILT_EMULATED_INTERFACE));
+
+    ASSERT(IsZeroMemory(Context, sizeof (XENFILT_PVDEVICE_CONTEXT)));
+    __PvdeviceFree(Context);
+
+    Trace("<====\n");
+}
diff --git a/src/xenfilt/pvdevice.h b/src/xenfilt/pvdevice.h
new file mode 100644
index 0000000..30cd81c
--- /dev/null
+++ b/src/xenfilt/pvdevice.h
@@ -0,0 +1,59 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XENFILT_PVDEVICE_H
+#define _XENFILT_PVDEVICE_H
+
+#include <ntddk.h>
+#include <xen.h>
+#include <pvdevice_interface.h>
+
+typedef struct _XENFILT_PVDEVICE_CONTEXT XENFILT_PVDEVICE_CONTEXT, 
*PXENFILT_PVDEVICE_CONTEXT;
+
+extern NTSTATUS
+PvdeviceInitialize(
+    OUT PXENFILT_PVDEVICE_CONTEXT   *Context
+    );
+
+extern NTSTATUS
+PvdeviceGetInterface(
+    IN      PXENFILT_PVDEVICE_CONTEXT   Context,
+    IN      ULONG                       Version,
+    IN OUT  PINTERFACE                  Interface,
+    IN      ULONG                       Size
+    );
+
+extern VOID
+PvdeviceTeardown(
+    IN  PXENFILT_PVDEVICE_CONTEXT   Context
+    );
+
+#endif  // _XENFILT_PVDEVICE_H
diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj
index 82f0dbf..b4fe992 100644
--- a/vs2012/xenbus/xenbus.vcxproj
+++ b/vs2012/xenbus/xenbus.vcxproj
@@ -83,6 +83,7 @@
     <ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
     <ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" />
     <ClCompile Include="..\..\src\xenbus\fdo.c" />
+    <ClCompile Include="..\..\src\xenbus\filters.c" />
     <ClCompile Include="..\..\src\xenbus\gnttab.c" />
     <ClCompile Include="..\..\src\xenbus\pdo.c" />
     <ClCompile Include="..\..\src\xenbus\shared_info.c" />
diff --git a/vs2012/xenfilt/xenfilt.vcxproj b/vs2012/xenfilt/xenfilt.vcxproj
index 4d5747d..6554ec9 100644
--- a/vs2012/xenfilt/xenfilt.vcxproj
+++ b/vs2012/xenfilt/xenfilt.vcxproj
@@ -69,6 +69,7 @@
     <ClCompile Include="../../src/common/registry.c" />
     <ClCompile Include="../../src/xenfilt/driver.c" />
     <ClCompile Include="../../src/xenfilt/emulated.c" />
+    <ClCompile Include="../../src/xenfilt/pvdevice.c" />
     <ClCompile Include="../../src/xenfilt/fdo.c" />
     <ClCompile Include="../../src/xenfilt/pdo.c" />
     <ClCompile Include="../../src/xenfilt/thread.c" />
diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj
index fb0b0dd..f6e0575 100644
--- a/vs2013/xenbus/xenbus.vcxproj
+++ b/vs2013/xenbus/xenbus.vcxproj
@@ -86,6 +86,7 @@
     <ClCompile Include="..\..\src\xenbus\evtchn_2l.c" />
     <ClCompile Include="..\..\src\xenbus\evtchn_fifo.c" />
     <ClCompile Include="..\..\src\xenbus\fdo.c" />
+    <ClCompile Include="..\..\src\xenbus\filters.c" />
     <ClCompile Include="..\..\src\xenbus\gnttab.c" />
     <ClCompile Include="..\..\src\xenbus\pdo.c" />
     <ClCompile Include="..\..\src\xenbus\shared_info.c" />
diff --git a/vs2013/xenfilt/xenfilt.vcxproj b/vs2013/xenfilt/xenfilt.vcxproj
index 4f749b1..6250fcb 100644
--- a/vs2013/xenfilt/xenfilt.vcxproj
+++ b/vs2013/xenfilt/xenfilt.vcxproj
@@ -72,6 +72,7 @@
     <ClCompile Include="../../src/common/registry.c" />
     <ClCompile Include="../../src/xenfilt/driver.c" />
     <ClCompile Include="../../src/xenfilt/emulated.c" />
+    <ClCompile Include="../../src/xenfilt/pvdevice.c" />
     <ClCompile Include="../../src/xenfilt/fdo.c" />
     <ClCompile Include="../../src/xenfilt/pdo.c" />
     <ClCompile Include="../../src/xenfilt/thread.c" />
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel


 


Rackspace

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