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