]> xenbits.xensource.com Git - pvdrivers/win/xenbus.git/commitdiff
Move filter installation and active device selection logic into drivers
authorPaul Durrant <paul.durrant@citrix.com>
Tue, 21 Jul 2015 13:52:27 +0000 (14:52 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Wed, 22 Jul 2015 14:23:14 +0000 (15:23 +0100)
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@citrix.com>
24 files changed:
include/pvdevice_interface.h [new file with mode: 0644]
src/coinst/coinst.c
src/xen/driver.c
src/xenbus/driver.c
src/xenbus/driver.h
src/xenbus/fdo.c
src/xenbus/fdo.h
src/xenbus/filters.c [new file with mode: 0644]
src/xenbus/filters.h [new file with mode: 0644]
src/xenbus/pdo.c
src/xenfilt/driver.c
src/xenfilt/driver.h
src/xenfilt/emulated.c
src/xenfilt/emulated.h
src/xenfilt/fdo.c
src/xenfilt/fdo.h
src/xenfilt/pdo.c
src/xenfilt/pdo.h
src/xenfilt/pvdevice.c [new file with mode: 0644]
src/xenfilt/pvdevice.h [new file with mode: 0644]
vs2012/xenbus/xenbus.vcxproj
vs2012/xenfilt/xenfilt.vcxproj
vs2013/xenbus/xenbus.vcxproj
vs2013/xenfilt/xenfilt.vcxproj

diff --git a/include/pvdevice_interface.h b/include/pvdevice_interface.h
new file mode 100644 (file)
index 0000000..9024396
--- /dev/null
@@ -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
index 2b980a1f9c16838af04057f6b4b8425b36cec921..5e6f719d9bbec38f4fa85add09279ebafa0bd83a 100644 (file)
@@ -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
index 9662ff6863f17a1db645f359b6bf81aa654a2fb2..187fe1c528409622d6ab216a791f913326f0bb62 100644 (file)
@@ -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);
index a1115a4a621baa61d33b456012feb7e61a4e0236..61354005e473bd85739d8f9a5c791624fc5e878c 100644 (file)
@@ -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");
 
index 45cbe82ad3c43782674ea8cb7bcc54adbcf77381..0208f9ce3743cac5ce7290f7a26c4c891411f879 100644 (file)
@@ -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;
 
index e8a6f2229c59387a03696920fc0d23f4b2c6bc9a..fdb394d829e5fe11a319f5ef8f445e29609ab353 100644 (file)
@@ -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);
index 1feef17b98a4e0760384947f72483767b8038484..96a22505aba13461fb79d77dfa4c72f08beaa0d2 100644 (file)
@@ -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 (file)
index 0000000..737c839
--- /dev/null
@@ -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 (file)
index 0000000..a08855b
--- /dev/null
@@ -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
index 8e7f90aac4e7efe457e58eaa6ca163c7512fdf1d..e85732e6ab59bc841d0c47a6c334ee3a646d460f 100644 (file)
@@ -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,
index f0ffac0678fc6f4d1e8fe9db90e9027a0f2cb0bd..77f719a0c2fbd1723d58fce2c5cfe9a53b4e55f2 100644 (file)
@@ -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;
@@ -154,6 +157,30 @@ DriverGetEmulatedContext(
     return __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");
index f906d362415bbe8c85001bea5b8cb0f4e41666ad..772436d2e60fdb043f49e5dfe5502f10e018a50f 100644 (file)
@@ -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;
 
index 485fed631029cf2031635968ffca80801b3148c6..31391edf059c1be7cefff03f4bd529a4d7088548 100644 (file)
@@ -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
     )
index cc63a25627edc96abc7ff0b3cc6b84079522a8e1..778c7846dd14dd4a8f199c887c58733e6859c3ec 100644 (file)
@@ -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
     );
index 25b3dc23579959c891088ad9c71b53e1720110b8..7121eb24b8888001d5342b66480f7ced989f1435 100644 (file)
@@ -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
     )
 {
index b871b26f4f8863a14d2ef4079511e643264011d6..62a667f2ad3e55242c30eaf585f4aaa117cf305f 100644 (file)
@@ -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
index 6fab34626947a3504f1a93b86a3cfe1e17f74615..57502f32df5afac038cc12ed1548019325161b67 100644 (file)
@@ -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;
index 05ca049d485010ead0613e56e80f6fd1cdc1e9e4..aac57027acedd4b42f95f5d3153cb28b1ff17143 100644 (file)
@@ -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 (file)
index 0000000..5f9345d
--- /dev/null
@@ -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 (file)
index 0000000..30cd81c
--- /dev/null
@@ -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
index 82f0dbf98d900fece999385b56aa5c1f7e178f51..b4fe9921ebaacaa2c4d2e24692d6a1578a4405e9 100644 (file)
@@ -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" />
index 4d5747d7d99421324bced4d9b15c9294f05fd762..6554ec9ff512a3841321e52ed1715f7040d19c55 100644 (file)
@@ -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" />
index fb0b0dda91d124231732c2d84b92438118ba941c..f6e057568ae805a996ca2794be3d3ca37c1b8a39 100644 (file)
@@ -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" />
index 4f749b11511d044656fbc45b67ea0ad946433c81..6250fcbec8ac8a3db3d69b8432bdd04349494994 100644 (file)
@@ -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" />