--- /dev/null
+/* 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
#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 \
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,
}
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);
)
{
BOOLEAN Success;
- PTCHAR DeviceID;
- PTCHAR InstanceID;
HRESULT Error;
+ UNREFERENCED_PARAMETER(DeviceInfoSet);
+ UNREFERENCED_PARAMETER(DeviceInfoData);
UNREFERENCED_PARAMETER(Context);
Log("====>");
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");
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);
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);
return NO_ERROR;
-fail3:
- Log("fail3");
-
- free(DeviceID);
- free(InstanceID);
-
fail2:
Log("fail2");
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
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(
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,
{
HANDLE ServiceKey;
HANDLE UnplugKey;
+ HANDLE StatusKey;
NTSTATUS status;
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
__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:
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");
VOID
)
{
+ HANDLE StatusKey;
HANDLE UnplugKey;
Trace("====>\n");
SystemTeardown();
+ StatusKey = __DriverGetStatusKey();
+
+ RegistryCloseKey(StatusKey);
+ __DriverSetStatusKey(NULL);
+
UnplugKey = __DriverGetUnplugKey();
RegistryCloseKey(UnplugKey);
typedef struct _XENBUS_DRIVER {
PDRIVER_OBJECT DriverObject;
HANDLE ParametersKey;
+ HANDLE StatusKey;
} XENBUS_DRIVER, *PXENBUS_DRIVER;
static XENBUS_DRIVER Driver;
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
)
{
HANDLE ParametersKey;
+ HANDLE StatusKey;
ASSERT3P(DriverObject, ==, __DriverGetDriverObject());
if (*InitSafeBootMode > 0)
goto done;
+ StatusKey = __DriverGetStatusKey();
+ __DriverSetStatusKey(NULL);
+
+ RegistryCloseKey(StatusKey);
+
ParametersKey = __DriverGetParametersKey();
RegistryCloseKey(ParametersKey);
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
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);
{
HANDLE ServiceKey;
HANDLE ParametersKey;
+ HANDLE StatusKey;
ULONG Index;
NTSTATUS status;
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;
return STATUS_SUCCESS;
+fail4:
+ Error("fail4\n");
+
+ __DriverSetParametersKey(NULL);
+
+ RegistryCloseKey(ParametersKey);
+
fail3:
Error("fail3\n");
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;
#include <stdlib.h>
#include <xen.h>
+#include <pvdevice_interface.h>
+
#include "names.h"
#include "registry.h"
#include "fdo.h"
#include "driver.h"
#include "range_set.h"
#include "unplug.h"
+#include "filters.h"
#include "dbg_print.h"
#include "assert.h"
#include "util.h"
PIRP DevicePowerIrp;
CHAR VendorName[MAXNAMELEN];
- BOOLEAN Active;
MUTEX Mutex;
ULONG References;
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;
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
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
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'
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),
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");
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);
extern NTSTATUS
FdoCreate(
- IN PDEVICE_OBJECT PhysicalDeviceObject,
- IN BOOLEAN Active
+ IN PDEVICE_OBJECT PhysicalDeviceObject
);
extern VOID
--- /dev/null
+/* 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");
+}
--- /dev/null
+/* 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
"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,
*/
#include <ntddk.h>
+#include <ntstrsafe.h>
#include <procgrp.h>
#include <xen.h>
#include "pdo.h"
#include "driver.h"
#include "emulated.h"
+#include "pvdevice.h"
#include "mutex.h"
#include "dbg_print.h"
#include "assert.h"
PDRIVER_OBJECT DriverObject;
HANDLE ParametersKey;
- PCHAR ActiveDeviceID;
- PCHAR ActiveInstanceID;
MUTEX Mutex;
LIST_ENTRY List;
ULONG References;
PXENFILT_EMULATED_CONTEXT EmulatedContext;
XENFILT_EMULATED_INTERFACE EmulatedInterface;
+
+ PXENFILT_PVDEVICE_CONTEXT PvdeviceContext;
+ XENFILT_PVDEVICE_INTERFACE PvdeviceInterface;
} XENFILT_DRIVER, *PXENFILT_DRIVER;
static XENFILT_DRIVER Driver;
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
--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
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;
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;
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);
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;
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;
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);
)
{
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;
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,
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;
}
HANDLE ServiceKey;
HANDLE ParametersKey;
PXENFILT_EMULATED_CONTEXT EmulatedContext;
+ PXENFILT_PVDEVICE_CONTEXT PvdeviceContext;
ULONG Index;
NTSTATUS status;
__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);
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");
VOID
);
-extern PCHAR
-DriverGetActiveDeviceID(
- VOID
- );
-
-extern PCHAR
-DriverGetActiveInstanceID(
- VOID
- );
-
extern VOID
DriverAcquireMutex(
VOID
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;
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;
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));
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;
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++;
status = STATUS_INVALID_PARAMETER;
if (*End != '.')
- goto fail3;
+ goto fail2;
End++;
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);
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
)
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
);
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
)
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
)
status = RtlStringCbPrintfA(Fdo->Name,
MAXNAMELEN,
- "%ws\\%ws",
+ "%s\\%s",
__FdoGetDeviceID(Fdo),
__FdoGetInstanceID(Fdo));
ASSERT(NT_SUCCESS(status));
return Fdo->Name;
}
-static FORCEINLINE PDEVICE_OBJECT
-__FdoGetPhysicalDeviceObject(
- IN PXENFILT_FDO Fdo
- )
-{
- return Fdo->PhysicalDeviceObject;
-}
-
VOID
FdoAddPhysicalDeviceObject(
IN PXENFILT_FDO Fdo,
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;
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;
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);
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;
if (!NT_SUCCESS(status))
goto fail3;
- ExFreePool(InstanceID);
- ExFreePool(DeviceID);
-
return STATUS_SUCCESS;
fail3:
- ExFreePool(InstanceID);
-
fail2:
- ExFreePool(DeviceID);
-
fail1:
return status;
}
NTSTATUS
FdoCreate(
IN PDEVICE_OBJECT PhysicalDeviceObject,
- IN PWCHAR DeviceID,
- IN PWCHAR InstanceID,
+ IN PCHAR DeviceID,
+ IN PCHAR InstanceID,
IN XENFILT_EMULATED_OBJECT_TYPE Type
)
{
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
);
IN PXENFILT_FDO Fdo
);
+extern PDEVICE_OBJECT
+FdoGetPhysicalDeviceObject(
+ IN PXENFILT_FDO Fdo
+ );
+
extern BOOLEAN
FdoHasEnumerated(
IN PXENFILT_FDO Fdo
#include <stdlib.h>
#include "emulated.h"
+#include "pvdevice.h"
#include "names.h"
#include "fdo.h"
#include "pdo.h"
XENFILT_EMULATED_OBJECT_TYPE Type;
PXENFILT_EMULATED_OBJECT EmulatedObject;
+
+ XENFILT_PVDEVICE_INTERFACE PvdeviceInterface;
};
static FORCEINLINE PVOID
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
)
status = RtlStringCbPrintfA(Pdo->Name,
MAXNAMELEN,
- "%ws\\%ws",
+ "%s\\%s",
Dx->DeviceID,
Dx->InstanceID);
ASSERT(NT_SUCCESS(status));
PdoDestroy(Pdo);
FdoReleaseMutex(Fdo);
+ IoInvalidateDeviceRelations(FdoGetPhysicalDeviceObject(Fdo),
+ BusRelations);
+
return status;
fail1:
} \
DEFINE_PDO_QUERY_INTERFACE(Emulated)
+DEFINE_PDO_QUERY_INTERFACE(Pvdevice)
struct _INTERFACE_ENTRY {
const GUID *Guid;
struct _INTERFACE_ENTRY PdoInterfaceTable[] = {
DEFINE_INTERFACE_ENTRY(EMULATED_INTERFACE, Emulated),
+ DEFINE_INTERFACE_ENTRY(PVDEVICE_INTERFACE, Pvdevice),
{ NULL, NULL, NULL }
};
case BusQueryInstanceID:
status = RtlStringCbPrintfW(Buffer,
Id.MaximumLength,
- L"%s",
+ L"%hs",
__PdoGetInstanceID(Pdo));
ASSERT(NT_SUCCESS(status));
case BusQueryDeviceID:
status = RtlStringCbPrintfW(Buffer,
Id.MaximumLength,
- L"%s",
+ L"%hs",
__PdoGetDeviceID(Pdo));
ASSERT(NT_SUCCESS(status));
PdoCreate(
PXENFILT_FDO Fdo,
PDEVICE_OBJECT PhysicalDeviceObject,
- PWCHAR DeviceID,
- PWCHAR InstanceID,
+ PCHAR DeviceID,
+ PCHAR InstanceID,
XENFILT_EMULATED_OBJECT_TYPE Type
)
{
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",
return STATUS_SUCCESS;
+fail7:
+ Error("fail7\n");
+
+ RtlZeroMemory(&Pdo->PvdeviceInterface,
+ sizeof (XENFILT_PVDEVICE_INTERFACE));
+
fail6:
Error("fail6\n");
RtlZeroMemory(Pdo->Name, sizeof (Pdo->Name));
+ RtlZeroMemory(&Pdo->PvdeviceInterface,
+ sizeof (XENFILT_PVDEVICE_INTERFACE));
+
EmulatedRemoveObject(DriverGetEmulatedContext(),
Pdo->EmulatedObject);
Pdo->EmulatedObject = NULL;
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
);
--- /dev/null
+/* 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");
+}
--- /dev/null
+/* 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
<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" />
<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" />
<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" />
<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" />