[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [win-pv-devel] [PATCH 3/3] Add XenDisk device upper filter.
> -----Original Message----- > From: Owen Smith [mailto:owen.smith@xxxxxxxxxx] > Sent: 28 October 2014 11:27 > To: win-pv-devel@xxxxxxxxxxxxxxxxxxxx > Cc: Paul Durrant; Owen Smith > Subject: [PATCH 3/3] Add XenDisk device upper filter. > > XenDisk intercepts and translates > IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES > into SCSIOP_UNMAP SRBs. Storport will pass on these SCSIOP_UNMAP > requests > to XenVbd, which will create the appropriate BLKIF_OP_DISCARD requests. > XenDisk is only neccessary because Storport does not do the translation > to SCSIOP_UNMAPs. > > Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> Acked-by: Paul Durrant <paul.durrant@xxxxxxxxxx> > --- > build.py | 1 + > src/xendisk/assert.h | 220 ++++ > src/xendisk/debug.h | 94 ++ > src/xendisk/driver.c | 203 ++++ > src/xendisk/driver.h | 68 ++ > src/xendisk/fdo.c | 1862 +++++++++++++++++++++++++++++++ > src/xendisk/fdo.h | 78 ++ > src/xendisk/mutex.h | 113 ++ > src/xendisk/pdo.c | 2079 > +++++++++++++++++++++++++++++++++++ > src/xendisk/pdo.h | 90 ++ > src/xendisk/thread.c | 225 ++++ > src/xendisk/thread.h | 73 ++ > src/xendisk/types.h | 53 + > src/xendisk/util.h | 222 ++++ > src/xendisk/xendisk.rc | 56 + > src/xenvbd.inf | 18 + > vs2012/package/package.vcxproj | 3 + > vs2012/xendisk/xendisk.vcxproj | 84 ++ > vs2012/xendisk/xendisk.vcxproj.user | 8 + > vs2012/xenvbd.sln | 28 + > vs2013/package/package.vcxproj | 3 + > vs2013/xendisk/xendisk.vcxproj | 112 ++ > vs2013/xendisk/xendisk.vcxproj.user | 8 + > vs2013/xenvbd.sln | 28 + > 24 files changed, 5729 insertions(+) > create mode 100644 src/xendisk/assert.h > create mode 100644 src/xendisk/debug.h > create mode 100644 src/xendisk/driver.c > create mode 100644 src/xendisk/driver.h > create mode 100644 src/xendisk/fdo.c > create mode 100644 src/xendisk/fdo.h > create mode 100644 src/xendisk/mutex.h > create mode 100644 src/xendisk/pdo.c > create mode 100644 src/xendisk/pdo.h > create mode 100644 src/xendisk/thread.c > create mode 100644 src/xendisk/thread.h > create mode 100644 src/xendisk/types.h > create mode 100644 src/xendisk/util.h > create mode 100644 src/xendisk/xendisk.rc > create mode 100644 vs2012/xendisk/xendisk.vcxproj > create mode 100644 vs2012/xendisk/xendisk.vcxproj.user > create mode 100644 vs2013/xendisk/xendisk.vcxproj > create mode 100644 vs2013/xendisk/xendisk.vcxproj.user > > diff --git a/build.py b/build.py > index 26261ad..3a71d0c 100644 > --- a/build.py > +++ b/build.py > @@ -368,6 +368,7 @@ if __name__ == '__main__': > > if len(sys.argv) <= 2 or sdv[sys.argv[2]]: > run_sdv('xencrsh', driver, vs) > + run_sdv('xendisk', driver, vs) > run_sdv('xenvbd', driver, vs) > > archive(driver + '\\source.tgz', manifest().splitlines(), tgz=True) > diff --git a/src/xendisk/assert.h b/src/xendisk/assert.h > new file mode 100644 > index 0000000..cd571bd > --- /dev/null > +++ b/src/xendisk/assert.h > @@ -0,0 +1,220 @@ > +/* 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 _XENDISK_ASSERT_H > +#define _XENDISK_ASSERT_H > + > +#include <ntddk.h> > + > +#include "debug.h" > + > +static FORCEINLINE VOID > +__BugCheck( > + __in ULONG Code, > + __in_opt ULONG_PTR Parameter1, > + __in_opt ULONG_PTR Parameter2, > + __in_opt ULONG_PTR Parameter3, > + __in_opt ULONG_PTR Parameter4 > + ) > +{ > +#pragma prefast(suppress:28159) > + KeBugCheckEx(Code, > + Parameter1, > + Parameter2, > + Parameter3, > + Parameter4); > +} > + > +#define ASSERTION_FAILURE 0x0000DEAD > + > + > +#define BUG(_TEXT) \ > + do { \ > + const CHAR *_Text = (_TEXT); \ > + const CHAR *_File = __FILE__; \ > + ULONG _Line = __LINE__; \ > + \ > + Error("BUG: " _TEXT "\n"); \ > + __BugCheck(ASSERTION_FAILURE, \ > + (ULONG_PTR)_Text, \ > + (ULONG_PTR)_File, \ > + (ULONG_PTR)_Line, \ > + 0); \ > + } while (FALSE) > + > +#define BUG_MSG(_TEXT1, _TEXT2) \ > + do { \ > + const CHAR *_Text1 = (_TEXT1); \ > + const CHAR *_Text2 = (_TEXT2); \ > + const CHAR *_File = __FILE__; \ > + ULONG _Line = __LINE__; \ > + \ > + Error("BUG: " _TEXT1 " %s\n", _Text2); \ > + __BugCheck(ASSERTION_FAILURE, \ > + (ULONG_PTR)_Text1, \ > + (ULONG_PTR)_File, \ > + (ULONG_PTR)_Line, \ > + (ULONG_PTR)_Text2); \ > + } while (FALSE) > + > +#define BUG_ON(_EXP) \ > + if (_EXP) BUG(#_EXP) > + > +#define BUG_ON_MSG(_EXP, _TEXT) \ > + if (_EXP) BUG_MSG(#_EXP, _TEXT) > + > +#if DBG > + > +#define __NT_ASSERT(_EXP) \ > + ((!(_EXP)) ? \ > + (Error("ASSERTION FAILED: " #_EXP "\n"), \ > + __annotation(L"Debug", L"AssertFail", L#_EXP), \ > + DbgRaiseAssertionFailure(), FALSE) : \ > + TRUE) > + > +#define __NT_ASSERT_MSG(_EXP, _TEXT) \ > + ((!(_EXP)) ? \ > + (Error("ASSERTION FAILED: " #_EXP " " #_TEXT "\n"), \ > + __annotation(L"Debug", L"AssertFail", L#_EXP), \ > + DbgRaiseAssertionFailure(), FALSE) : \ > + TRUE) > + > +#define __ASSERT(_EXP) __NT_ASSERT(_EXP) > +#define __ASSERT_MSG(_EXP, _TEXT) __NT_ASSERT_MSG(_EXP, _TEXT) > + > +#else // DBG > + > +#define __ASSERT(_EXP) BUG_ON(!(_EXP)) > +#define __ASSERT_MSG(_EXP, _TEXT) BUG_ON_MSG(!(_EXP), _TEXT) > + > +#endif // DBG > + > +#undef ASSERT > + > +#define ASSERT(_EXP) \ > + do { \ > + __ASSERT(_EXP); \ > + __analysis_assume(_EXP); \ > + } while (FALSE) > + > +#define ASSERT_MSG(_EXP, _TEXT) \ > + do { \ > + __ASSERT_MSG(_EXP, _TEXT); \ > + __analysis_assume(_EXP); \ > + } while (FALSE) > + > +#define ASSERT3U(_X, _OP, _Y) \ > + do { \ > + ULONGLONG _Lval = (ULONGLONG)(_X); \ > + ULONGLONG _Rval = (ULONGLONG)(_Y); \ > + if (!(_Lval _OP _Rval)) { \ > + Error("%s = %llu\n", #_X, _Lval); \ > + Error("%s = %llu\n", #_Y, _Rval); \ > + ASSERT(_X _OP _Y); \ > + } \ > + } while (FALSE) > + > +#define ASSERT3S(_X, _OP, _Y) \ > + do { \ > + LONGLONG _Lval = (LONGLONG)(_X); \ > + LONGLONG _Rval = (LONGLONG)(_Y); \ > + if (!(_Lval _OP _Rval)) { \ > + Error("%s = %lld\n", #_X, _Lval); \ > + Error("%s = %lld\n", #_Y, _Rval); \ > + ASSERT(_X _OP _Y); \ > + } \ > + } while (FALSE) > + > +#define ASSERT3P(_X, _OP, _Y) \ > + do { \ > + PVOID _Lval = (PVOID)(_X); \ > + PVOID _Rval = (PVOID)(_Y); \ > + if (!(_Lval _OP _Rval)) { \ > + Error("%s = %p\n", #_X, _Lval); \ > + Error("%s = %p\n", #_Y, _Rval); \ > + ASSERT(_X _OP _Y); \ > + } \ > + } while (FALSE) > + > +#define ASSERTREFCOUNT(_X, _OP, _Y, _Z) \ > + do { \ > + LONG _L = (LONG)(_X); \ > + LONG _R = (LONG)(_Y); \ > + if (!(_L _OP _R)) { \ > + Error("%s:%s = %d\n", (_Z), #_X, _L); \ > + Error("%s:%s = %d\n", (_Z), #_Y, _R); \ > + ASSERT_MSG(_X _OP _Y, (_Z)); \ > + } \ > + } while (FALSE) > + > +#ifndef TEST_MEMORY > +#define TEST_MEMORY DBG > +#endif > + > +#if TEST_MEMORY > + > +__checkReturn > +static __inline BOOLEAN > +_IsZeroMemory( > + __in const PCHAR Caller, > + __in const PCHAR Name, > + __in PVOID Buffer, > + __in ULONG Length > + ) > +{ > + ULONG Offset; > + > + Offset = 0; > + while (Offset < Length) { > + if (*((PUCHAR)Buffer + Offset) != 0) { > + Error("%s: non-zero byte in %s (0x%p+0x%x)\n", Caller, Name, > Buffer, Offset); > + return FALSE; > + } > + Offset++; > + } > + > + return TRUE; > +} > + > +#define IsZeroMemory(_Buffer, _Length) \ > + _IsZeroMemory(__FUNCTION__, #_Buffer, (_Buffer), (_Length)) > + > +#else // TEST_MEMORY > + > +#define IsZeroMemory(_Buffer, _Length) TRUE > + > +#endif // TEST_MEMORY > + > +#define IMPLY(_X, _Y) (!(_X) || (_Y)) > +#define EQUIV(_X, _Y) (IMPLY((_X), (_Y)) && IMPLY((_Y), (_X))) > + > +#endif // _XENDISK_ASSERT_H > + > diff --git a/src/xendisk/debug.h b/src/xendisk/debug.h > new file mode 100644 > index 0000000..f592f86 > --- /dev/null > +++ b/src/xendisk/debug.h > @@ -0,0 +1,94 @@ > +/* 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 _DEBUG_H > +#define _DEBUG_H > + > +#include <ntddk.h> > +#include <stdarg.h> > + > +#ifdef _SDV_ > +#define __MODULE__ "" > +#endif > + > +// DEBUG_FILTER_MASKs > +// Set these to see relevant output > +// ERROR 0x00000001 > +// WARNING 0x00000002 > +// TRACE 0x00000004 > +// INFO 0x00000008 > + > +#pragma warning(disable:4127) // conditional expression is constant > + > +// > +// Debug Output and Logging > +// > +static __inline VOID > +__DebugMessage( > + __in ULONG Level, > + __in __nullterminated const CHAR *Prefix, > + __in __nullterminated const CHAR *Format, > + ... > + ) > +{ > + va_list Arguments; > + > + va_start(Arguments, Format); > + > +#pragma prefast(suppress:6001) // Using uninitialized memory > + vDbgPrintExWithPrefix(Prefix, > + DPFLTR_IHVDRIVER_ID, > + Level, > + Format, > + Arguments); > + va_end(Arguments); > +} > + > +#define Error(...) \ > + __DebugMessage(DPFLTR_ERROR_LEVEL, __MODULE__ "|" > __FUNCTION__ ":", __VA_ARGS__) > + > +#define Warning(...) \ > + __DebugMessage(DPFLTR_WARNING_LEVEL, __MODULE__ "|" > __FUNCTION__ ":", __VA_ARGS__) > + > +#if DBG > +#define Trace(...) \ > + __DebugMessage(DPFLTR_TRACE_LEVEL, __MODULE__ "|" > __FUNCTION__ ":", __VA_ARGS__) > +#else // DBG > +#define Trace(...) \ > + (VOID)(__VA_ARGS__) > +#endif // DBG > + > +#define Verbose(...) \ > + __DebugMessage(DPFLTR_INFO_LEVEL, __MODULE__ "|" > __FUNCTION__ ":", __VA_ARGS__) > + > +#include "assert.h" > + > +#endif // _DEBUG_H > diff --git a/src/xendisk/driver.c b/src/xendisk/driver.c > new file mode 100644 > index 0000000..743fc61 > --- /dev/null > +++ b/src/xendisk/driver.c > @@ -0,0 +1,203 @@ > +/* 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 "driver.h" > +#include "util.h" > +#include "debug.h" > +#include "assert.h" > +#include <version.h> > + > +extern PULONG InitSafeBootMode; > + > +typedef struct _XENDISK_DRIVER { > + PDRIVER_OBJECT DriverObject; > +} XENDISK_DRIVER, *PXENDISK_DRIVER; > + > +static XENDISK_DRIVER Driver; > + > +static FORCEINLINE VOID > +__DriverSetDriverObject( > + IN PDRIVER_OBJECT DriverObject > + ) > +{ > + Driver.DriverObject = DriverObject; > +} > + > +static FORCEINLINE PDRIVER_OBJECT > +__DriverGetDriverObject( > + VOID > + ) > +{ > + return Driver.DriverObject; > +} > + > +PDRIVER_OBJECT > +DriverGetDriverObject( > + VOID > + ) > +{ > + return __DriverGetDriverObject(); > +} > + > +DRIVER_UNLOAD DriverUnload; > + > +VOID > +DriverUnload( > + IN PDRIVER_OBJECT DriverObject > + ) > +{ > + ASSERT3P(DriverObject, ==, __DriverGetDriverObject()); > + > + Trace("====>\n"); > + > + __DriverSetDriverObject(NULL); > + > + ASSERT(IsZeroMemory(&Driver, sizeof (XENDISK_DRIVER))); > + > + Trace("<====\n"); > +} > + > +DRIVER_ADD_DEVICE AddDevice; > + > +NTSTATUS > +#pragma prefast(suppress:28152) // Does not clear > DO_DEVICE_INITIALIZING > +AddDevice( > + IN PDRIVER_OBJECT DriverObject, > + IN PDEVICE_OBJECT PhysicalDeviceObject > + ) > +{ > + NTSTATUS status; > + > + ASSERT3P(DriverObject, ==, __DriverGetDriverObject()); > + > + status = FdoCreate(PhysicalDeviceObject); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + return STATUS_SUCCESS; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +DRIVER_DISPATCH Dispatch; > + > +NTSTATUS > +Dispatch( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp > + ) > +{ > + PXENDISK_DX Dx; > + NTSTATUS status; > + > + Dx = (PXENDISK_DX)DeviceObject->DeviceExtension; > + ASSERT3P(Dx->DeviceObject, ==, DeviceObject); > + > + if (Dx->DevicePnpState == Deleted) { > + status = STATUS_NO_SUCH_DEVICE; > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + goto done; > + } > + > + status = STATUS_NOT_SUPPORTED; > + switch (Dx->Type) { > + case PHYSICAL_DEVICE_OBJECT: { > + PXENDISK_PDO Pdo = Dx->Pdo; > + > + status = PdoDispatch(Pdo, Irp); > + break; > + } > + case FUNCTION_DEVICE_OBJECT: { > + PXENDISK_FDO Fdo = Dx->Fdo; > + > + status = FdoDispatch(Fdo, Irp); > + break; > + } > + default: > + ASSERT(FALSE); > + break; > + } > + > +done: > + return status; > +} > + > +DRIVER_INITIALIZE DriverEntry; > + > +NTSTATUS > +DriverEntry( > + IN PDRIVER_OBJECT DriverObject, > + IN PUNICODE_STRING RegistryPath > + ) > +{ > + ULONG Index; > + > + ASSERT3P(__DriverGetDriverObject(), ==, NULL); > + UNREFERENCED_PARAMETER(RegistryPath); > + > + ExInitializeDriverRuntime(DrvRtPoolNxOptIn); > + > + Trace("====>\n"); > + > + __DriverSetDriverObject(DriverObject); > + > + DriverObject->DriverUnload = DriverUnload; > + > + if (*InitSafeBootMode > 0) > + goto done; > + > + Verbose("XENDISK %d.%d.%d (%d) (%02d.%02d.%04d)\n", > + MAJOR_VERSION, > + MINOR_VERSION, > + MICRO_VERSION, > + BUILD_NUMBER, > + DAY, > + MONTH, > + YEAR); > + > + DriverObject->DriverExtension->AddDevice = AddDevice; > + > + for (Index = 0; Index <= IRP_MJ_MAXIMUM_FUNCTION; Index++) { > +#pragma prefast(suppress:28169) // No __drv_dispatchType annotation > +#pragma prefast(suppress:28168) // No matching __drv_dispatchType > annotation for IRP_MJ_CREATE > + DriverObject->MajorFunction[Index] = Dispatch; > + } > + > +done: > + Trace("<====\n"); > + return STATUS_SUCCESS; > +} > diff --git a/src/xendisk/driver.h b/src/xendisk/driver.h > new file mode 100644 > index 0000000..b47e21b > --- /dev/null > +++ b/src/xendisk/driver.h > @@ -0,0 +1,68 @@ > +/* 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 _XENDISK_DRIVER_H > +#define _XENDISK_DRIVER_H > + > +#include "fdo.h" > +#include "pdo.h" > + > +extern PDRIVER_OBJECT > +DriverGetDriverObject( > + VOID > + ); > + > +#pragma warning(push) > +#pragma warning(disable:4201) // nonstandard extension used : nameless > struct/union > + > +typedef struct _XENDISK_DX { > + PDEVICE_OBJECT DeviceObject; > + DEVICE_OBJECT_TYPE Type; > + > + DEVICE_PNP_STATE DevicePnpState; > + DEVICE_PNP_STATE PreviousDevicePnpState; > + > + SYSTEM_POWER_STATE SystemPowerState; > + DEVICE_POWER_STATE DevicePowerState; > + > + IO_REMOVE_LOCK RemoveLock; > + > + LIST_ENTRY ListEntry; > + > + union { > + PXENDISK_FDO Fdo; > + PXENDISK_PDO Pdo; > + }; > +} XENDISK_DX, *PXENDISK_DX; > + > +#pragma warning(pop) > + > +#endif // _XENDISK_DRIVER_H > diff --git a/src/xendisk/fdo.c b/src/xendisk/fdo.c > new file mode 100644 > index 0000000..771c82e > --- /dev/null > +++ b/src/xendisk/fdo.c > @@ -0,0 +1,1862 @@ > +/* 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 <wdmguid.h> > +#include <ntstrsafe.h> > +#include <stdlib.h> > +#include <names.h> > + > +#include "driver.h" > +#include "fdo.h" > +#include "pdo.h" > +#include "thread.h" > +#include "mutex.h" > +#include "debug.h" > +#include "assert.h" > +#include "util.h" > + > +#define FDO_TAG 'ODF' > + > +struct _XENDISK_FDO { > + PXENDISK_DX Dx; > + PDEVICE_OBJECT LowerDeviceObject; > + PDEVICE_OBJECT PhysicalDeviceObject; > + > + PXENDISK_THREAD SystemPowerThread; > + PIRP SystemPowerIrp; > + PXENDISK_THREAD DevicePowerThread; > + PIRP DevicePowerIrp; > + > + MUTEX Mutex; > + ULONG References; > +}; > + > +static FORCEINLINE PVOID > +__FdoAllocate( > + IN ULONG Length > + ) > +{ > + return __AllocateNonPagedPoolWithTag(__FUNCTION__, __LINE__, > Length, FDO_TAG); > +} > + > +static FORCEINLINE VOID > +__FdoFree( > + IN PVOID Buffer > + ) > +{ > + __FreePoolWithTag(Buffer, FDO_TAG); > +} > + > +static FORCEINLINE VOID > +__FdoSetDevicePnpState( > + IN PXENDISK_FDO Fdo, > + IN DEVICE_PNP_STATE State > + ) > +{ > + PXENDISK_DX Dx = Fdo->Dx; > + > + // We can never transition out of the deleted state > + ASSERT(Dx->DevicePnpState != Deleted || State == Deleted); > + > + Dx->PreviousDevicePnpState = Dx->DevicePnpState; > + Dx->DevicePnpState = State; > +} > + > +static FORCEINLINE VOID > +__FdoRestoreDevicePnpState( > + IN PXENDISK_FDO Fdo, > + IN DEVICE_PNP_STATE State > + ) > +{ > + PXENDISK_DX Dx = Fdo->Dx; > + > + if (Dx->DevicePnpState == State) > + Dx->DevicePnpState = Dx->PreviousDevicePnpState; > +} > + > +static FORCEINLINE DEVICE_PNP_STATE > +__FdoGetDevicePnpState( > + IN PXENDISK_FDO Fdo > + ) > +{ > + PXENDISK_DX Dx = Fdo->Dx; > + > + return Dx->DevicePnpState; > +} > + > +static FORCEINLINE VOID > +__FdoSetDevicePowerState( > + IN PXENDISK_FDO Fdo, > + IN DEVICE_POWER_STATE State > + ) > +{ > + PXENDISK_DX Dx = Fdo->Dx; > + > + Dx->DevicePowerState = State; > +} > + > +static FORCEINLINE DEVICE_POWER_STATE > +__FdoGetDevicePowerState( > + IN PXENDISK_FDO Fdo > + ) > +{ > + PXENDISK_DX Dx = Fdo->Dx; > + > + return Dx->DevicePowerState; > +} > + > +static FORCEINLINE VOID > +__FdoSetSystemPowerState( > + IN PXENDISK_FDO Fdo, > + IN SYSTEM_POWER_STATE State > + ) > +{ > + PXENDISK_DX Dx = Fdo->Dx; > + > + Dx->SystemPowerState = State; > +} > + > +static FORCEINLINE SYSTEM_POWER_STATE > +__FdoGetSystemPowerState( > + IN PXENDISK_FDO Fdo > + ) > +{ > + PXENDISK_DX Dx = Fdo->Dx; > + > + return Dx->SystemPowerState; > +} > + > +static FORCEINLINE PDEVICE_OBJECT > +__FdoGetPhysicalDeviceObject( > + IN PXENDISK_FDO Fdo > + ) > +{ > + return Fdo->PhysicalDeviceObject; > +} > + > +VOID > +FdoAddPhysicalDeviceObject( > + IN PXENDISK_FDO Fdo, > + IN PDEVICE_OBJECT DeviceObject > + ) > +{ > + PXENDISK_DX Dx; > + > + Dx = (PXENDISK_DX)DeviceObject->DeviceExtension; > + ASSERT3U(Dx->Type, ==, PHYSICAL_DEVICE_OBJECT); > + > + InsertTailList(&Fdo->Dx->ListEntry, &Dx->ListEntry); > + ASSERT3U(Fdo->References, !=, 0); > + Fdo->References++; > +} > + > +VOID > +FdoRemovePhysicalDeviceObject( > + IN PXENDISK_FDO Fdo, > + IN PDEVICE_OBJECT DeviceObject > + ) > +{ > + PXENDISK_DX Dx; > + > + Dx = (PXENDISK_DX)DeviceObject->DeviceExtension; > + ASSERT3U(Dx->Type, ==, PHYSICAL_DEVICE_OBJECT); > + > + RemoveEntryList(&Dx->ListEntry); > + ASSERT3U(Fdo->References, !=, 0); > + --Fdo->References; > +} > + > +static FORCEINLINE VOID > +__FdoAcquireMutex( > + IN PXENDISK_FDO Fdo > + ) > +{ > + AcquireMutex(&Fdo->Mutex); > +} > + > +VOID > +FdoAcquireMutex( > + IN PXENDISK_FDO Fdo > + ) > +{ > + __FdoAcquireMutex(Fdo); > +} > + > +static FORCEINLINE VOID > +__FdoReleaseMutex( > + IN PXENDISK_FDO Fdo > + ) > +{ > + ReleaseMutex(&Fdo->Mutex); > +} > + > +VOID > +FdoReleaseMutex( > + IN PXENDISK_FDO Fdo > + ) > +{ > + __FdoReleaseMutex(Fdo); > + > + if (Fdo->References == 0) > + FdoDestroy(Fdo); > +} > + > +static FORCEINLINE VOID > +__FdoEnumerate( > + IN PXENDISK_FDO Fdo, > + IN PDEVICE_RELATIONS Relations > + ) > +{ > + PDEVICE_OBJECT *PhysicalDeviceObject; > + ULONG Count; > + PLIST_ENTRY ListEntry; > + ULONG Index; > + NTSTATUS status; > + > + Count = Relations->Count; > + ASSERT(Count != 0); > + > + PhysicalDeviceObject = __FdoAllocate(sizeof (PDEVICE_OBJECT) * > Count); > + > + status = STATUS_NO_MEMORY; > + if (PhysicalDeviceObject == NULL) > + goto fail1; > + > + RtlCopyMemory(PhysicalDeviceObject, > + Relations->Objects, > + sizeof (PDEVICE_OBJECT) * Count); > + > + AcquireMutex(&Fdo->Mutex); > + > + // Remove any PDOs that do not appear in the device list > + ListEntry = Fdo->Dx->ListEntry.Flink; > + while (ListEntry != &Fdo->Dx->ListEntry) { > + PLIST_ENTRY Next = ListEntry->Flink; > + PXENDISK_DX Dx = CONTAINING_RECORD(ListEntry, XENDISK_DX, > ListEntry); > + PXENDISK_PDO Pdo = Dx->Pdo; > + BOOLEAN Missing; > + > + Missing = TRUE; > + for (Index = 0; Index < Count; Index++) { > + if (PdoGetPhysicalDeviceObject(Pdo) == > PhysicalDeviceObject[Index]) { > + Missing = FALSE; > +#pragma prefast(suppress:6387) // PhysicalDeviceObject[Index] could be > NULL > + ObDereferenceObject(PhysicalDeviceObject[Index]); > + PhysicalDeviceObject[Index] = NULL; // avoid duplication > + break; > + } > + } > + > + if (Missing && !PdoIsMissing(Pdo)) { > + if (PdoGetDevicePnpState(Pdo) == Present) { > + PdoSetDevicePnpState(Pdo, Deleted); > + PdoDestroy(Pdo); > + } else { > + PdoSetMissing(Pdo, "device disappeared"); > + } > + } > + > + ListEntry = Next; > + } > + > + // Walk the list and create PDO filters for any new devices > + for (Index = 0; Index < Count; Index++) { > +#pragma warning(suppress:6385) // Reading invalid data from > 'PhysicalDeviceObject' > + if (PhysicalDeviceObject[Index] != NULL) { > + (VOID) PdoCreate(Fdo, > + PhysicalDeviceObject[Index]); > + ObDereferenceObject(PhysicalDeviceObject[Index]); > + } > + } > + > + ReleaseMutex(&Fdo->Mutex); > + > + __FdoFree(PhysicalDeviceObject); > + return; > + > +fail1: > + Error("fail1 (%08x)\n", status); > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoForwardIrpSynchronously( > + 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 > +FdoForwardIrpSynchronously( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + KEVENT Event; > + NTSTATUS status; > + > + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); > + > + KeInitializeEvent(&Event, NotificationEvent, FALSE); > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoForwardIrpSynchronously, > + &Event, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + if (status == STATUS_PENDING) { > + (VOID) KeWaitForSingleObject(&Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + status = Irp->IoStatus.Status; > + } else { > + ASSERT3U(status, ==, Irp->IoStatus.Status); > + } > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoStartDevice( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + POWER_STATE PowerState; > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + __FdoSetSystemPowerState(Fdo, PowerSystemWorking); > + __FdoSetDevicePowerState(Fdo, PowerDeviceD0); > + > + PowerState.DeviceState = PowerDeviceD0; > + PoSetPowerState(Fdo->Dx->DeviceObject, > + DevicePowerState, > + PowerState); > + > + __FdoSetDevicePnpState(Fdo, Started); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > + > +fail2: > + Error("fail2\n"); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoQueryStopDevice( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoQueryStopDevice( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __FdoSetDevicePnpState(Fdo, StopPending); > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoQueryStopDevice, > + Fdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoCancelStopDevice( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoCancelStopDevice( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + __FdoRestoreDevicePnpState(Fdo, StopPending); > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoCancelStopDevice, > + Fdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoStopDevice( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoStopDevice( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + POWER_STATE PowerState; > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + if (__FdoGetDevicePowerState(Fdo) != PowerDeviceD0) > + goto done; > + > + PowerState.DeviceState = PowerDeviceD3; > + PoSetPowerState(Fdo->Dx->DeviceObject, > + DevicePowerState, > + PowerState); > + > + __FdoSetDevicePowerState(Fdo, PowerDeviceD3); > + __FdoSetSystemPowerState(Fdo, PowerSystemShutdown); > + > +done: > + __FdoSetDevicePnpState(Fdo, Stopped); > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoStopDevice, > + Fdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoQueryRemoveDevice( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoQueryRemoveDevice( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __FdoSetDevicePnpState(Fdo, RemovePending); > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoQueryRemoveDevice, > + Fdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoCancelRemoveDevice( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoCancelRemoveDevice( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __FdoRestoreDevicePnpState(Fdo, RemovePending); > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoCancelRemoveDevice, > + Fdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoSurpriseRemoval( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoSurpriseRemoval( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __FdoSetDevicePnpState(Fdo, SurpriseRemovePending); > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoSurpriseRemoval, > + Fdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoRemoveDevice( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + POWER_STATE PowerState; > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + if (__FdoGetDevicePowerState(Fdo) != PowerDeviceD0) > + goto done; > + > + PowerState.DeviceState = PowerDeviceD3; > + PoSetPowerState(Fdo->Dx->DeviceObject, > + DevicePowerState, > + PowerState); > + > + __FdoSetDevicePowerState(Fdo, PowerDeviceD3); > + __FdoSetSystemPowerState(Fdo, PowerSystemShutdown); > + > +done: > + __FdoSetDevicePnpState(Fdo, Deleted); > + > + IoReleaseRemoveLockAndWait(&Fdo->Dx->RemoveLock, Irp); > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + AcquireMutex(&Fdo->Mutex); > + ASSERT3U(Fdo->References, !=, 0); > + --Fdo->References; > + ReleaseMutex(&Fdo->Mutex); > + > + if (Fdo->References == 0) > + FdoDestroy(Fdo); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoQueryDeviceRelations( > + 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 DECLSPEC_NOINLINE NTSTATUS > +FdoQueryDeviceRelations( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + KEVENT Event; > + PIO_STACK_LOCATION StackLocation; > + ULONG Size; > + PDEVICE_RELATIONS Relations; > + PLIST_ENTRY ListEntry; > + ULONG Count; > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + KeInitializeEvent(&Event, NotificationEvent, FALSE); > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoQueryDeviceRelations, > + &Event, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, 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; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + if (StackLocation->Parameters.QueryDeviceRelations.Type != > BusRelations) > + goto done; > + > + Relations = (PDEVICE_RELATIONS)Irp->IoStatus.Information; > + > + if (Relations->Count != 0) > + __FdoEnumerate(Fdo, Relations); > + > + ExFreePool(Relations); > + > + AcquireMutex(&Fdo->Mutex); > + > + Count = 0; > + for (ListEntry = Fdo->Dx->ListEntry.Flink; > + ListEntry != &Fdo->Dx->ListEntry; > + ListEntry = ListEntry->Flink) > + Count++; > + > + Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) + (sizeof > (DEVICE_OBJECT) * __min(Count, 1)); > + > + Relations = ExAllocatePoolWithTag(PagedPool, Size, 'TLIF'); > + > + status = STATUS_NO_MEMORY; > + if (Relations == NULL) > + goto fail3; > + > + RtlZeroMemory(Relations, Size); > + > + for (ListEntry = Fdo->Dx->ListEntry.Flink; > + ListEntry != &Fdo->Dx->ListEntry; > + ListEntry = ListEntry->Flink) { > + PXENDISK_DX Dx = CONTAINING_RECORD(ListEntry, XENDISK_DX, > ListEntry); > + PXENDISK_PDO Pdo = Dx->Pdo; > + > + ASSERT3U(Dx->Type, ==, PHYSICAL_DEVICE_OBJECT); > + > + if (PdoGetDevicePnpState(Pdo) == Present) > + PdoSetDevicePnpState(Pdo, Enumerated); > + > + ObReferenceObject(PdoGetPhysicalDeviceObject(Pdo)); > + Relations->Objects[Relations->Count++] = > PdoGetPhysicalDeviceObject(Pdo); > + } > + > + ASSERT3U(Relations->Count, ==, Count); > + > + Trace("%d PDO(s)\n", Relations->Count); > + > + ReleaseMutex(&Fdo->Mutex); > + > + Irp->IoStatus.Information = (ULONG_PTR)Relations; > + status = STATUS_SUCCESS; > + > +done: > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > + > +fail3: > + ReleaseMutex(&Fdo->Mutex); > + > +fail2: > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoDispatchPnp( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoDispatchPnp( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + UCHAR MinorFunction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + MinorFunction = StackLocation->MinorFunction; > + > + switch (StackLocation->MinorFunction) { > + case IRP_MN_START_DEVICE: > + status = FdoStartDevice(Fdo, Irp); > + break; > + > + case IRP_MN_QUERY_STOP_DEVICE: > + status = FdoQueryStopDevice(Fdo, Irp); > + break; > + > + case IRP_MN_CANCEL_STOP_DEVICE: > + status = FdoCancelStopDevice(Fdo, Irp); > + break; > + > + case IRP_MN_STOP_DEVICE: > + status = FdoStopDevice(Fdo, Irp); > + break; > + > + case IRP_MN_QUERY_REMOVE_DEVICE: > + status = FdoQueryRemoveDevice(Fdo, Irp); > + break; > + > + case IRP_MN_SURPRISE_REMOVAL: > + status = FdoSurpriseRemoval(Fdo, Irp); > + break; > + > + case IRP_MN_REMOVE_DEVICE: > + status = FdoRemoveDevice(Fdo, Irp); > + break; > + > + case IRP_MN_CANCEL_REMOVE_DEVICE: > + status = FdoCancelRemoveDevice(Fdo, Irp); > + break; > + > + case IRP_MN_QUERY_DEVICE_RELATIONS: > + status = FdoQueryDeviceRelations(Fdo, Irp); > + break; > + > + default: > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoDispatchPnp, > + Fdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + break; > + } > + > + return status; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoSetDevicePowerUp( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + > + ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo)); > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + if (!NT_SUCCESS(status)) > + goto done; > + > + Verbose("%p: %s -> %s\n", > + Fdo->Dx->DeviceObject, > + PowerDeviceStateName(__FdoGetDevicePowerState(Fdo)), > + PowerDeviceStateName(DeviceState)); > + > + __FdoSetDevicePowerState(Fdo, DeviceState); > + > +done: > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoSetDevicePowerDown( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + > + ASSERT3U(DeviceState, >, __FdoGetDevicePowerState(Fdo)); > + > + Verbose("%p: %s -> %s\n", > + Fdo->Dx->DeviceObject, > + PowerDeviceStateName(__FdoGetDevicePowerState(Fdo)), > + PowerDeviceStateName(DeviceState)); > + > + __FdoSetDevicePowerState(Fdo, DeviceState); > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoSetDevicePower( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + POWER_ACTION PowerAction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + Trace("====> (%s:%s)\n", > + PowerDeviceStateName(DeviceState), > + PowerActionName(PowerAction)); > + > + if (DeviceState == __FdoGetDevicePowerState(Fdo)) { > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + goto done; > + } > + > + status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ? > + __FdoSetDevicePowerUp(Fdo, Irp) : > + __FdoSetDevicePowerDown(Fdo, Irp); > + > +done: > + Trace("<==== (%s:%s)(%08x)\n", > + PowerDeviceStateName(DeviceState), > + PowerActionName(PowerAction), > + status); > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoSetSystemPowerUp( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + > + ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo)); > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + if (!NT_SUCCESS(status)) > + goto done; > + > + Verbose("%p: %s -> %s\n", > + Fdo->Dx->DeviceObject, > + PowerSystemStateName(__FdoGetSystemPowerState(Fdo)), > + PowerSystemStateName(SystemState)); > + > + __FdoSetSystemPowerState(Fdo, SystemState); > + > +done: > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoSetSystemPowerDown( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + > + ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo)); > + > + Verbose("%p: %s -> %s\n", > + Fdo->Dx->DeviceObject, > + PowerSystemStateName(__FdoGetSystemPowerState(Fdo)), > + PowerSystemStateName(SystemState)); > + > + __FdoSetSystemPowerState(Fdo, SystemState); > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoSetSystemPower( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + POWER_ACTION PowerAction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + Trace("====> (%s:%s)\n", > + PowerSystemStateName(SystemState), > + PowerActionName(PowerAction)); > + > + if (SystemState == __FdoGetSystemPowerState(Fdo)) { > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + goto done; > + } > + > + status = (SystemState < __FdoGetSystemPowerState(Fdo)) ? > + __FdoSetSystemPowerUp(Fdo, Irp) : > + __FdoSetSystemPowerDown(Fdo, Irp); > + > +done: > + Trace("<==== (%s:%s)(%08x)\n", > + PowerSystemStateName(SystemState), > + PowerActionName(PowerAction), > + status); > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoQueryDevicePowerUp( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + > + ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo)); > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoQueryDevicePowerDown( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + > + ASSERT3U(DeviceState, >, __FdoGetDevicePowerState(Fdo)); > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoQueryDevicePower( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + POWER_ACTION PowerAction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + Trace("====> (%s:%s)\n", > + PowerDeviceStateName(DeviceState), > + PowerActionName(PowerAction)); > + > + if (DeviceState == __FdoGetDevicePowerState(Fdo)) { > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + goto done; > + } > + > + status = (DeviceState < __FdoGetDevicePowerState(Fdo)) ? > + __FdoQueryDevicePowerUp(Fdo, Irp) : > + __FdoQueryDevicePowerDown(Fdo, Irp); > + > +done: > + Trace("<==== (%s:%s)(%08x)\n", > + PowerDeviceStateName(DeviceState), > + PowerActionName(PowerAction), > + status); > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoQuerySystemPowerUp( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + > + ASSERT3U(SystemState, <, __FdoGetSystemPowerState(Fdo)); > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoQuerySystemPowerDown( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + > + ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo)); > + > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__FdoQuerySystemPower( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + POWER_ACTION PowerAction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + Trace("====> (%s:%s)\n", > + PowerSystemStateName(SystemState), > + PowerActionName(PowerAction)); > + > + if (SystemState == __FdoGetSystemPowerState(Fdo)) { > + status = FdoForwardIrpSynchronously(Fdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + goto done; > + } > + > + status = (SystemState < __FdoGetSystemPowerState(Fdo)) ? > + __FdoQuerySystemPowerUp(Fdo, Irp) : > + __FdoQuerySystemPowerDown(Fdo, Irp); > + > +done: > + Trace("<==== (%s:%s)(%08x)\n", > + PowerSystemStateName(SystemState), > + PowerActionName(PowerAction), > + status); > + > + return status; > +} > + > +static NTSTATUS > +FdoDevicePower( > + IN PXENDISK_THREAD Self, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + PKEVENT Event; > + > + Event = ThreadGetEvent(Self); > + > + for (;;) { > + PIRP Irp; > + PIO_STACK_LOCATION StackLocation; > + UCHAR MinorFunction; > + > + if (Fdo->DevicePowerIrp == NULL) { > + (VOID) KeWaitForSingleObject(Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + KeClearEvent(Event); > + } > + > + if (ThreadIsAlerted(Self)) > + break; > + > + Irp = Fdo->DevicePowerIrp; > + > + if (Irp == NULL) > + continue; > + > + Fdo->DevicePowerIrp = NULL; > + KeMemoryBarrier(); > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + MinorFunction = StackLocation->MinorFunction; > + > + switch (StackLocation->MinorFunction) { > + case IRP_MN_SET_POWER: > + (VOID) __FdoSetDevicePower(Fdo, Irp); > + break; > + > + case IRP_MN_QUERY_POWER: > + (VOID) __FdoQueryDevicePower(Fdo, Irp); > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + } > + > + return STATUS_SUCCESS; > +} > + > +static NTSTATUS > +FdoSystemPower( > + IN PXENDISK_THREAD Self, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + PKEVENT Event; > + > + Event = ThreadGetEvent(Self); > + > + for (;;) { > + PIRP Irp; > + PIO_STACK_LOCATION StackLocation; > + UCHAR MinorFunction; > + > + if (Fdo->SystemPowerIrp == NULL) { > + (VOID) KeWaitForSingleObject(Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + KeClearEvent(Event); > + } > + > + if (ThreadIsAlerted(Self)) > + break; > + > + Irp = Fdo->SystemPowerIrp; > + > + if (Irp == NULL) > + continue; > + > + Fdo->SystemPowerIrp = NULL; > + KeMemoryBarrier(); > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + MinorFunction = StackLocation->MinorFunction; > + > + switch (StackLocation->MinorFunction) { > + case IRP_MN_SET_POWER: > + (VOID) __FdoSetSystemPower(Fdo, Irp); > + break; > + > + case IRP_MN_QUERY_POWER: > + (VOID) __FdoQuerySystemPower(Fdo, Irp); > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + } > + > + return STATUS_SUCCESS; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoDispatchPower( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoDispatchPower( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + UCHAR MinorFunction; > + POWER_STATE_TYPE PowerType; > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + MinorFunction = StackLocation->MinorFunction; > + > + if (MinorFunction != IRP_MN_QUERY_POWER && > + MinorFunction != IRP_MN_SET_POWER) { > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoDispatchPower, > + Fdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + > + goto done; > + } > + > + PowerType = StackLocation->Parameters.Power.Type; > + > + Trace("====> (%02x:%s)\n", > + MinorFunction, > + PowerMinorFunctionName(MinorFunction)); > + > + switch (PowerType) { > + case DevicePowerState: > + IoMarkIrpPending(Irp); > + > + ASSERT3P(Fdo->DevicePowerIrp, ==, NULL); > + Fdo->DevicePowerIrp = Irp; > + KeMemoryBarrier(); > + > + ThreadWake(Fdo->DevicePowerThread); > + > + status = STATUS_PENDING; > + break; > + > + case SystemPowerState: > + IoMarkIrpPending(Irp); > + > + ASSERT3P(Fdo->SystemPowerIrp, ==, NULL); > + Fdo->SystemPowerIrp = Irp; > + KeMemoryBarrier(); > + > + ThreadWake(Fdo->SystemPowerThread); > + > + status = STATUS_PENDING; > + break; > + > + default: > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoDispatchPower, > + Fdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + break; > + } > + > + Trace("<==== (%02x:%s) (%08x)\n", > + MinorFunction, > + PowerMinorFunctionName(MinorFunction), > + status); > + > +done: > + return status; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__FdoDispatchDefault( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_FDO Fdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +FdoDispatchDefault( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Fdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __FdoDispatchDefault, > + Fdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +NTSTATUS > +FdoDispatch( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + > + switch (StackLocation->MajorFunction) { > + case IRP_MJ_PNP: > + status = FdoDispatchPnp(Fdo, Irp); > + break; > + > + case IRP_MJ_POWER: > + status = FdoDispatchPower(Fdo, Irp); > + break; > + > + default: > + status = FdoDispatchDefault(Fdo, Irp); > + break; > + } > + > + return status; > +} > + > +NTSTATUS > +FdoCreate( > + IN PDEVICE_OBJECT PhysicalDeviceObject > + ) > +{ > + PDEVICE_OBJECT LowerDeviceObject; > + ULONG DeviceType; > + PDEVICE_OBJECT FilterDeviceObject; > + PXENDISK_DX Dx; > + PXENDISK_FDO Fdo; > + NTSTATUS status; > + > + LowerDeviceObject = > IoGetAttachedDeviceReference(PhysicalDeviceObject); > + DeviceType = LowerDeviceObject->DeviceType; > + ObDereferenceObject(LowerDeviceObject); > + > +#pragma prefast(suppress:28197) // Possibly leaking memory > 'FilterDeviceObject' > + status = IoCreateDevice(DriverGetDriverObject(), > + sizeof (XENDISK_DX), > + NULL, > + DeviceType, > + FILE_DEVICE_SECURE_OPEN, > + FALSE, > + &FilterDeviceObject); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + Dx = (PXENDISK_DX)FilterDeviceObject->DeviceExtension; > + RtlZeroMemory(Dx, sizeof (XENDISK_DX)); > + > + Dx->Type = FUNCTION_DEVICE_OBJECT; > + Dx->DeviceObject = FilterDeviceObject; > + Dx->DevicePnpState = Added; > + Dx->SystemPowerState = PowerSystemShutdown; > + Dx->DevicePowerState = PowerDeviceD3; > + > + IoInitializeRemoveLock(&Dx->RemoveLock, FDO_TAG, 0, 0); > + > + Fdo = __FdoAllocate(sizeof (XENDISK_FDO)); > + > + status = STATUS_NO_MEMORY; > + if (Fdo == NULL) > + goto fail2; > + > + LowerDeviceObject = IoAttachDeviceToDeviceStack(FilterDeviceObject, > + PhysicalDeviceObject); > + > + status = STATUS_UNSUCCESSFUL; > + if (LowerDeviceObject == NULL) > + goto fail3; > + > + Fdo->Dx = Dx; > + Fdo->PhysicalDeviceObject = PhysicalDeviceObject; > + Fdo->LowerDeviceObject = LowerDeviceObject; > + > + status = ThreadCreate(FdoSystemPower, Fdo, &Fdo- > >SystemPowerThread); > + if (!NT_SUCCESS(status)) > + goto fail4; > + > + status = ThreadCreate(FdoDevicePower, Fdo, &Fdo- > >DevicePowerThread); > + if (!NT_SUCCESS(status)) > + goto fail5; > + > + InitializeMutex(&Fdo->Mutex); > + InitializeListHead(&Dx->ListEntry); > + Fdo->References = 1; > + > + Verbose("%p\n", FilterDeviceObject); > + > + Dx->Fdo = Fdo; > + > +#pragma prefast(suppress:28182) // Dereferencing NULL pointer > + FilterDeviceObject->DeviceType = LowerDeviceObject->DeviceType; > + FilterDeviceObject->Characteristics = LowerDeviceObject- > >Characteristics; > + > + FilterDeviceObject->Flags |= LowerDeviceObject->Flags; > + FilterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; > + > + return STATUS_SUCCESS; > + > +fail5: > + Error("fail5\n"); > + > + ThreadAlert(Fdo->SystemPowerThread); > + ThreadJoin(Fdo->SystemPowerThread); > + Fdo->SystemPowerThread = NULL; > + > +fail4: > + Error("fail4\n"); > + > + Fdo->PhysicalDeviceObject = NULL; > + Fdo->LowerDeviceObject = NULL; > + Fdo->Dx = NULL; > + > + IoDetachDevice(LowerDeviceObject); > + > +fail3: > + Error("fail3\n"); > + > + ASSERT(IsZeroMemory(Fdo, sizeof (XENDISK_FDO))); > + __FdoFree(Fdo); > + > +fail2: > + Error("fail2\n"); > + > + IoDeleteDevice(FilterDeviceObject); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +VOID > +FdoDestroy( > + IN PXENDISK_FDO Fdo > + ) > +{ > + PDEVICE_OBJECT LowerDeviceObject = Fdo->LowerDeviceObject; > + PXENDISK_DX Dx = Fdo->Dx; > + PDEVICE_OBJECT FilterDeviceObject = Dx->DeviceObject; > + > + ASSERT(IsListEmpty(&Dx->ListEntry)); > + ASSERT3U(Fdo->References, ==, 0); > + ASSERT3U(__FdoGetDevicePnpState(Fdo), ==, Deleted); > + > + Dx->Fdo = NULL; > + > + RtlZeroMemory(&Fdo->Mutex, sizeof (MUTEX)); > + > + ThreadAlert(Fdo->DevicePowerThread); > + ThreadJoin(Fdo->DevicePowerThread); > + Fdo->DevicePowerThread = NULL; > + > + ThreadAlert(Fdo->SystemPowerThread); > + ThreadJoin(Fdo->SystemPowerThread); > + Fdo->SystemPowerThread = NULL; > + > + Fdo->LowerDeviceObject = NULL; > + Fdo->PhysicalDeviceObject = NULL; > + Fdo->Dx = NULL; > + > + IoDetachDevice(LowerDeviceObject); > + > + ASSERT(IsZeroMemory(Fdo, sizeof (XENDISK_FDO))); > + __FdoFree(Fdo); > + > + IoDeleteDevice(FilterDeviceObject); > +} > diff --git a/src/xendisk/fdo.h b/src/xendisk/fdo.h > new file mode 100644 > index 0000000..8aa0529 > --- /dev/null > +++ b/src/xendisk/fdo.h > @@ -0,0 +1,78 @@ > +/* 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 _XENDISK_FDO_H > +#define _XENDISK_FDO_H > + > +#include <ntddk.h> > +#include "types.h" > + > +typedef struct _XENDISK_FDO XENDISK_FDO, *PXENDISK_FDO; > + > +extern VOID > +FdoAddPhysicalDeviceObject( > + IN PXENDISK_FDO Fdo, > + IN PDEVICE_OBJECT DeviceObject > + ); > + > +extern VOID > +FdoRemovePhysicalDeviceObject( > + IN PXENDISK_FDO Fdo, > + IN PDEVICE_OBJECT DeviceObject > + ); > + > +extern VOID > +FdoAcquireMutex( > + IN PXENDISK_FDO Fdo > + ); > + > +extern VOID > +FdoReleaseMutex( > + IN PXENDISK_FDO Fdo > + ); > + > +extern NTSTATUS > +FdoDispatch( > + IN PXENDISK_FDO Fdo, > + IN PIRP Irp > + ); > + > +extern NTSTATUS > +FdoCreate( > + IN PDEVICE_OBJECT PhysicalDeviceObject > + ); > + > +extern VOID > +FdoDestroy( > + IN PXENDISK_FDO Fdo > + ); > + > +#endif // _XENDISK_FDO_H > diff --git a/src/xendisk/mutex.h b/src/xendisk/mutex.h > new file mode 100644 > index 0000000..bcc2414 > --- /dev/null > +++ b/src/xendisk/mutex.h > @@ -0,0 +1,113 @@ > +/* 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 _XENDISK_MUTEX_H > +#define _XENDISK_MUTEX_H > + > +#include <ntddk.h> > + > +#include "assert.h" > + > +typedef struct _MUTEX { > + PKTHREAD Owner; > + KEVENT Event; > +} MUTEX, *PMUTEX; > + > +static FORCEINLINE VOID > +InitializeMutex( > + IN PMUTEX Mutex > + ) > +{ > + RtlZeroMemory(Mutex, sizeof (MUTEX)); > + > + KeInitializeEvent(&Mutex->Event, SynchronizationEvent, TRUE); > +} > + > +static FORCEINLINE BOOLEAN > +__drv_maxIRQL(PASSIVE_LEVEL) > +TryAcquireMutex( > + IN PMUTEX Mutex > + ) > +{ > + LARGE_INTEGER Timeout; > + NTSTATUS status; > + > + Timeout.QuadPart = 0; > + > + status = KeWaitForSingleObject(&Mutex->Event, > + Executive, > + KernelMode, > + FALSE, > + &Timeout); > + if (status == STATUS_TIMEOUT) > + return FALSE; > + > + ASSERT(NT_SUCCESS(status)); > + > + ASSERT3P(Mutex->Owner, ==, NULL); > + Mutex->Owner = KeGetCurrentThread(); > + > + return TRUE; > +} > + > +static FORCEINLINE VOID > +__drv_maxIRQL(PASSIVE_LEVEL) > +AcquireMutex( > + IN PMUTEX Mutex > + ) > +{ > + NTSTATUS status; > + > + status = KeWaitForSingleObject(&Mutex->Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + > + ASSERT(NT_SUCCESS(status)); > + > + ASSERT3P(Mutex->Owner, ==, NULL); > + Mutex->Owner = KeGetCurrentThread(); > +} > + > +static FORCEINLINE VOID > +__drv_maxIRQL(PASSIVE_LEVEL) > +ReleaseMutex( > + IN PMUTEX Mutex > + ) > +{ > + ASSERT3P(Mutex->Owner, ==, KeGetCurrentThread()); > + Mutex->Owner = NULL; > + > + KeSetEvent(&Mutex->Event, IO_NO_INCREMENT, FALSE); > +} > + > +#endif // _XENDISK_MUTEX_H > diff --git a/src/xendisk/pdo.c b/src/xendisk/pdo.c > new file mode 100644 > index 0000000..3de958a > --- /dev/null > +++ b/src/xendisk/pdo.c > @@ -0,0 +1,2079 @@ > +/* 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 <wdmguid.h> > +#include <ntstrsafe.h> > +#include <stdlib.h> > +#include <storport.h> > +#include <Ntddstor.h> > +#include <Ntddscsi.h> > +#include <names.h> > + > +#include "fdo.h" > +#include "pdo.h" > +#include "driver.h" > +#include "thread.h" > +#include "debug.h" > +#include "assert.h" > +#include "util.h" > + > +#define PDO_TAG 'ODP' > + > +struct _XENDISK_PDO { > + PXENDISK_DX Dx; > + PDEVICE_OBJECT LowerDeviceObject; > + PDEVICE_OBJECT PhysicalDeviceObject; > + > + PXENDISK_THREAD SystemPowerThread; > + PIRP SystemPowerIrp; > + PXENDISK_THREAD DevicePowerThread; > + PIRP DevicePowerIrp; > + > + PXENDISK_FDO Fdo; > + BOOLEAN Missing; > + const CHAR *Reason; > + > + ULONG SectorSize; > +}; > + > +static FORCEINLINE PVOID > +__PdoAllocate( > + IN ULONG Length > + ) > +{ > + return __AllocateNonPagedPoolWithTag(__FUNCTION__, __LINE__, > Length, PDO_TAG); > +} > + > +static FORCEINLINE VOID > +__PdoFree( > + IN PVOID Buffer > + ) > +{ > + __FreePoolWithTag(Buffer, PDO_TAG); > +} > + > +static FORCEINLINE VOID > +__PdoSetDevicePnpState( > + IN PXENDISK_PDO Pdo, > + IN DEVICE_PNP_STATE State > + ) > +{ > + PXENDISK_DX Dx = Pdo->Dx; > + > + // We can never transition out of the deleted state > + ASSERT(Dx->DevicePnpState != Deleted || State == Deleted); > + > + Dx->PreviousDevicePnpState = Dx->DevicePnpState; > + Dx->DevicePnpState = State; > +} > + > +VOID > +PdoSetDevicePnpState( > + IN PXENDISK_PDO Pdo, > + IN DEVICE_PNP_STATE State > + ) > +{ > + __PdoSetDevicePnpState(Pdo, State); > +} > + > +static FORCEINLINE VOID > +__PdoRestoreDevicePnpState( > + IN PXENDISK_PDO Pdo, > + IN DEVICE_PNP_STATE State > + ) > +{ > + PXENDISK_DX Dx = Pdo->Dx; > + > + if (Dx->DevicePnpState == State) > + Dx->DevicePnpState = Dx->PreviousDevicePnpState; > +} > + > +static FORCEINLINE DEVICE_PNP_STATE > +__PdoGetDevicePnpState( > + IN PXENDISK_PDO Pdo > + ) > +{ > + PXENDISK_DX Dx = Pdo->Dx; > + > + return Dx->DevicePnpState; > +} > + > +DEVICE_PNP_STATE > +PdoGetDevicePnpState( > + IN PXENDISK_PDO Pdo > + ) > +{ > + return __PdoGetDevicePnpState(Pdo); > +} > + > +static FORCEINLINE VOID > +__PdoSetDevicePowerState( > + IN PXENDISK_PDO Pdo, > + IN DEVICE_POWER_STATE State > + ) > +{ > + PXENDISK_DX Dx = Pdo->Dx; > + > + Dx->DevicePowerState = State; > +} > + > +static FORCEINLINE DEVICE_POWER_STATE > +__PdoGetDevicePowerState( > + IN PXENDISK_PDO Pdo > + ) > +{ > + PXENDISK_DX Dx = Pdo->Dx; > + > + return Dx->DevicePowerState; > +} > + > +static FORCEINLINE VOID > +__PdoSetSystemPowerState( > + IN PXENDISK_PDO Pdo, > + IN SYSTEM_POWER_STATE State > + ) > +{ > + PXENDISK_DX Dx = Pdo->Dx; > + > + Dx->SystemPowerState = State; > +} > + > +static FORCEINLINE SYSTEM_POWER_STATE > +__PdoGetSystemPowerState( > + IN PXENDISK_PDO Pdo > + ) > +{ > + PXENDISK_DX Dx = Pdo->Dx; > + > + return Dx->SystemPowerState; > +} > + > +PDEVICE_OBJECT > +PdoGetPhysicalDeviceObject( > + IN PXENDISK_PDO Pdo > + ) > +{ > + return Pdo->PhysicalDeviceObject; > +} > + > +static FORCEINLINE VOID > +__PdoSetMissing( > + IN PXENDISK_PDO Pdo, > + IN const CHAR *Reason > + ) > +{ > + Pdo->Reason = Reason; > + Pdo->Missing = TRUE; > +} > + > +VOID > +PdoSetMissing( > + IN PXENDISK_PDO Pdo, > + IN const CHAR *Reason > + ) > +{ > + __PdoSetMissing(Pdo, Reason); > +} > + > +static FORCEINLINE BOOLEAN > +__PdoIsMissing( > + IN PXENDISK_PDO Pdo > + ) > +{ > + return Pdo->Missing; > +} > + > +BOOLEAN > +PdoIsMissing( > + IN PXENDISK_PDO Pdo > + ) > +{ > + return __PdoIsMissing(Pdo); > +} > + > +static FORCEINLINE VOID > +__PdoLink( > + IN PXENDISK_PDO Pdo, > + IN PXENDISK_FDO Fdo > + ) > +{ > + Pdo->Fdo = Fdo; > + FdoAddPhysicalDeviceObject(Fdo, Pdo->Dx->DeviceObject); > +} > + > +static FORCEINLINE VOID > +__PdoUnlink( > + IN PXENDISK_PDO Pdo > + ) > +{ > + PXENDISK_FDO Fdo = Pdo->Fdo; > + > + ASSERT(Fdo != NULL); > + > + FdoRemovePhysicalDeviceObject(Fdo, Pdo->Dx->DeviceObject); > + > + Pdo->Fdo = NULL; > +} > + > +static FORCEINLINE PXENDISK_FDO > +__PdoGetFdo( > + IN PXENDISK_PDO Pdo > + ) > +{ > + return Pdo->Fdo; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoForwardIrpSynchronously( > + 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 > +PdoForwardIrpSynchronously( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + KEVENT Event; > + NTSTATUS status; > + > + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); > + > + KeInitializeEvent(&Event, NotificationEvent, FALSE); > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoForwardIrpSynchronously, > + &Event, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + if (status == STATUS_PENDING) { > + (VOID) KeWaitForSingleObject(&Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + status = Irp->IoStatus.Status; > + } else { > + ASSERT3U(status, ==, Irp->IoStatus.Status); > + } > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoForwardIrpAndForget( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static NTSTATUS > +PdoForwardIrpAndForget( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoForwardIrpAndForget, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + return IoCallDriver(Pdo->LowerDeviceObject, Irp); > +} > + > +static NTSTATUS > +PdoCompleteIrp( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp, > + IN NTSTATUS Status > + ) > +{ > + Irp->IoStatus.Status = Status; > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + return Status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoQueryProperty( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + PSTORAGE_ACCESS_ALIGNMENT_DESCRIPTOR Descriptor = Irp- > >UserBuffer; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + if (!NT_SUCCESS(Irp->IoStatus.Status)) > + goto done; > + > + Descriptor = Irp->UserBuffer; > + Pdo->SectorSize = Descriptor->BytesPerLogicalSector; > + Verbose("%p : %u bytes per sector\n", Pdo->Dx->DeviceObject, Pdo- > >SectorSize); > + > +done: > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryProperty( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PSTORAGE_PROPERTY_QUERY Query; > + PDEVICE_TRIM_DESCRIPTOR Trim; > + NTSTATUS status; > + > + Query = Irp->AssociatedIrp.SystemBuffer; > + > + switch (Query->PropertyId) { > + case StorageAccessAlignmentProperty: > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoQueryProperty, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + break; > + > + case StorageDeviceTrimProperty: > + Trim = Irp->AssociatedIrp.SystemBuffer; > + > + Trim->Version = 0; > + Trim->Size = sizeof(DEVICE_TRIM_DESCRIPTOR); > + Trim->TrimEnabled = TRUE; > + > + Irp->IoStatus.Information = > (ULONG_PTR)sizeof(DEVICE_TRIM_DESCRIPTOR); > + status = PdoCompleteIrp(Pdo, Irp, STATUS_SUCCESS); > + break; > + > + default: > + status = PdoForwardIrpAndForget(Pdo, Irp); > + break; > + } > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoSendAwaitSrb( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + UNREFERENCED_PARAMETER(DeviceObject); > + UNREFERENCED_PARAMETER(Context); > + > + *(Irp->UserIosb) = Irp->IoStatus; > + > + if (Irp->MdlAddress) { > + MmUnlockPages(Irp->MdlAddress); > + IoFreeMdl(Irp->MdlAddress); > + } > + > + KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, FALSE); > + > + IoFreeIrp(Irp); > + return STATUS_MORE_PROCESSING_REQUIRED; > +} > + > +static NTSTATUS > +PdoSendAwaitSrb( > + IN PXENDISK_PDO Pdo, > + IN PSCSI_REQUEST_BLOCK Srb > + ) > +{ > + PIRP Irp; > + IO_STATUS_BLOCK IoStatus; > + KEVENT Event; > + PIO_STACK_LOCATION Stack; > + NTSTATUS status; > + > + KeInitializeEvent(&Event, NotificationEvent, FALSE); > + > + status = STATUS_NO_MEMORY; > + Irp = IoAllocateIrp((CCHAR)(Pdo->LowerDeviceObject->StackSize + 1), > FALSE); > + if (Irp == NULL) > + goto fail1; > + > + Stack = IoGetNextIrpStackLocation(Irp); > + Stack->MajorFunction = IRP_MJ_SCSI; > + Stack->Parameters.Scsi.Srb = Srb; > + > + IoSetCompletionRoutine(Irp, > + __PdoSendAwaitSrb, > + Srb, > + TRUE, > + TRUE, > + TRUE); > + Irp->UserIosb = &IoStatus; > + Irp->UserEvent = &Event; > + > + Irp->MdlAddress = IoAllocateMdl(Srb->DataBuffer, > + Srb->DataTransferLength, > + FALSE, > + FALSE, > + Irp); > + if (Irp->MdlAddress == NULL) > + goto fail2; > + > +#pragma warning(disable:6320) > + try { > + MmProbeAndLockPages(Irp->MdlAddress, KernelMode, > IoReadAccess); > + } except (EXCEPTION_EXECUTE_HANDLER) { > + status = GetExceptionCode(); > + > + goto fail3; > + } > +#pragma warning(default:6320) > + > + Srb->OriginalRequest = Irp; > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + if (status == STATUS_PENDING) { > + (VOID) KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, > NULL); > + status = IoStatus.Status; > + } > + > + return status; > + > +fail3: > + Error("fail3\n"); > + > + IoFreeMdl(Irp->MdlAddress); > + > +fail2: > + Error("fail2\n"); > + > + IoFreeIrp(Irp); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +static NTSTATUS > +PdoSendTrimSynchronous( > + IN PXENDISK_PDO Pdo, > + IN PDEVICE_DATA_SET_RANGE Ranges, > + IN ULONG Count > + ) > +{ > + SCSI_REQUEST_BLOCK Srb; > + PCDB Cdb; > + PUNMAP_LIST_HEADER Unmap; > + ULONG Length; > + ULONG Index; > + NTSTATUS status; > + > + Length = sizeof(UNMAP_LIST_HEADER) + > + (Count * sizeof(UNMAP_BLOCK_DESCRIPTOR)); > + > + status = STATUS_NO_MEMORY; > + Unmap = __PdoAllocate(Length); > + if (Unmap == NULL) > + goto fail1; > + > + RtlZeroMemory(&Srb, sizeof(SCSI_REQUEST_BLOCK)); > + Srb.Length = sizeof(SCSI_REQUEST_BLOCK); > + Srb.SrbFlags = 0; > + Srb.Function = SRB_FUNCTION_EXECUTE_SCSI; > + Srb.DataBuffer = Unmap; > + Srb.DataTransferLength = Length; > + Srb.TimeOutValue = (ULONG)-1; > + Srb.CdbLength = 10; > + > + Cdb = (PCDB)&Srb.Cdb[0]; > + Cdb->UNMAP.OperationCode = SCSIOP_UNMAP; > + *(PUSHORT)Cdb->UNMAP.AllocationLength = > _byteswap_ushort((USHORT)Length); > + > + *(PUSHORT)Unmap->DataLength = > _byteswap_ushort((USHORT)Length); > + *(PUSHORT)Unmap->BlockDescrDataLength = > _byteswap_ushort((USHORT)sizeof(UNMAP_BLOCK_DESCRIPTOR)); > + > + for (Index = 0; Index < Count; ++Index) { > + PUNMAP_BLOCK_DESCRIPTOR Block = &Unmap->Descriptors[Index]; > + PDEVICE_DATA_SET_RANGE Range = &Ranges[Index]; > + > + ULONG LengthInSectors = (ULONG)(Range->LengthInBytes / Pdo- > >SectorSize); > + ULONG64 OffsetInSectors = (ULONG64)(Range->StartingOffset / Pdo- > >SectorSize); > + > + Trace("TRIM[%x] %x @ %llx\n", > + Index, > + LengthInSectors, > + OffsetInSectors); > + > + *(PULONG64)Block->StartingLba = _byteswap_uint64(OffsetInSectors); > + *(PULONG)Block->LbaCount = _byteswap_ulong(LengthInSectors); > + } > + > + status = PdoSendAwaitSrb(Pdo, &Srb); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + __PdoFree(Unmap); > + return status; > + > +fail2: > + Error("fail2\n"); > + > + __PdoFree(Unmap); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoManageDataSetAttributes( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PDEVICE_MANAGE_DATA_SET_ATTRIBUTES Attributes; > + PDEVICE_DATA_SET_RANGE Ranges; > + ULONG NumRanges; > + NTSTATUS status; > + > + Attributes = Irp->AssociatedIrp.SystemBuffer; > + > + switch (Attributes->Action) { > + case DeviceDsmAction_Trim: > + Ranges = (PDEVICE_DATA_SET_RANGE)((PUCHAR)Attributes + > Attributes->DataSetRangesOffset); > + NumRanges = Attributes->DataSetRangesLength / > sizeof(DEVICE_DATA_SET_RANGE); > + > + status = PdoSendTrimSynchronous(Pdo, Ranges, NumRanges); > + > + status = PdoCompleteIrp(Pdo, Irp, status); > + break; > + > + default: > + status = PdoForwardIrpAndForget(Pdo, Irp); > + break; > + } > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoDispatchControl( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + ULONG ControlCode; > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + ControlCode = StackLocation- > >Parameters.DeviceIoControl.IoControlCode; > + > + switch (ControlCode) { > + case IOCTL_STORAGE_QUERY_PROPERTY: > + status = PdoQueryProperty(Pdo, Irp); > + break; > + > + case IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES: > + status = PdoManageDataSetAttributes(Pdo, Irp); > + break; > + > + default: > + status = PdoForwardIrpAndForget(Pdo, Irp); > + break; > + } > + > + return status; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoStartDevice( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + POWER_STATE PowerState; > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + if (!NT_SUCCESS(status)) > + goto fail2; > + > + __PdoSetSystemPowerState(Pdo, PowerSystemWorking); > + __PdoSetDevicePowerState(Pdo, PowerDeviceD0); > + > + PowerState.DeviceState = PowerDeviceD0; > + PoSetPowerState(Pdo->Dx->DeviceObject, > + DevicePowerState, > + PowerState); > + > + __PdoSetDevicePnpState(Pdo, Started); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > + Irp->IoStatus.Status = STATUS_SUCCESS; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return STATUS_SUCCESS; > + > +fail2: > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoQueryStopDevice( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryStopDevice( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __PdoSetDevicePnpState(Pdo, StopPending); > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoQueryStopDevice, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoCancelStopDevice( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoCancelStopDevice( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + __PdoRestoreDevicePnpState(Pdo, StopPending); > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoCancelStopDevice, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoStopDevice( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoStopDevice( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + POWER_STATE PowerState; > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + if (__PdoGetDevicePowerState(Pdo) != PowerDeviceD0) > + goto done; > + > + __PdoSetDevicePowerState(Pdo, PowerDeviceD3); > + __PdoSetSystemPowerState(Pdo, PowerSystemShutdown); > + > + PowerState.DeviceState = PowerDeviceD3; > + PoSetPowerState(Pdo->Dx->DeviceObject, > + DevicePowerState, > + PowerState); > + > +done: > + __PdoSetDevicePnpState(Pdo, Stopped); > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoStopDevice, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoQueryRemoveDevice( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoQueryRemoveDevice( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __PdoSetDevicePnpState(Pdo, RemovePending); > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoQueryRemoveDevice, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoCancelRemoveDevice( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoCancelRemoveDevice( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __PdoRestoreDevicePnpState(Pdo, RemovePending); > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoCancelRemoveDevice, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoSurpriseRemoval( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoSurpriseRemoval( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + __PdoSetDevicePnpState(Pdo, SurpriseRemovePending); > + Irp->IoStatus.Status = STATUS_SUCCESS; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoSurpriseRemoval, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoRemoveDevice( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PXENDISK_FDO Fdo = __PdoGetFdo(Pdo); > + POWER_STATE PowerState; > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + if (__PdoGetDevicePowerState(Pdo) != PowerDeviceD0) > + goto done; > + > + __PdoSetDevicePowerState(Pdo, PowerDeviceD3); > + __PdoSetSystemPowerState(Pdo, PowerSystemShutdown); > + > + PowerState.DeviceState = PowerDeviceD3; > + PoSetPowerState(Pdo->Dx->DeviceObject, > + DevicePowerState, > + PowerState); > + > +done: > + if (__PdoIsMissing(Pdo)) { > + __PdoSetDevicePnpState(Pdo, Deleted); > + IoReleaseRemoveLockAndWait(&Pdo->Dx->RemoveLock, Irp); > + } else { > + __PdoSetDevicePnpState(Pdo, Enumerated); > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + } > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + if (__PdoIsMissing(Pdo)) { > + FdoAcquireMutex(Fdo); > + PdoDestroy(Pdo); > + FdoReleaseMutex(Fdo); > + } > + > + return status; > + > +fail1: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoEject( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PXENDISK_FDO Fdo = __PdoGetFdo(Pdo); > + NTSTATUS status; > + > + __PdoSetMissing(Pdo, "Ejected"); > + __PdoSetDevicePnpState(Pdo, Deleted); > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + FdoAcquireMutex(Fdo); > + PdoDestroy(Pdo); > + FdoReleaseMutex(Fdo); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoDispatchPnp( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoDispatchPnp( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + UCHAR MinorFunction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + MinorFunction = StackLocation->MinorFunction; > + > + switch (StackLocation->MinorFunction) { > + case IRP_MN_START_DEVICE: > + status = PdoStartDevice(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_STOP_DEVICE: > + status = PdoQueryStopDevice(Pdo, Irp); > + break; > + > + case IRP_MN_CANCEL_STOP_DEVICE: > + status = PdoCancelStopDevice(Pdo, Irp); > + break; > + > + case IRP_MN_STOP_DEVICE: > + status = PdoStopDevice(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_REMOVE_DEVICE: > + status = PdoQueryRemoveDevice(Pdo, Irp); > + break; > + > + case IRP_MN_SURPRISE_REMOVAL: > + status = PdoSurpriseRemoval(Pdo, Irp); > + break; > + > + case IRP_MN_REMOVE_DEVICE: > + status = PdoRemoveDevice(Pdo, Irp); > + break; > + > + case IRP_MN_CANCEL_REMOVE_DEVICE: > + status = PdoCancelRemoveDevice(Pdo, Irp); > + break; > + > + case IRP_MN_EJECT: > + status = PdoEject(Pdo, Irp); > + break; > + > + default: > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoDispatchPnp, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + break; > + } > + > + return status; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoSetDevicePowerUp( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + > + ASSERT3U(DeviceState, <, __PdoGetDevicePowerState(Pdo)); > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + if (!NT_SUCCESS(status)) > + goto done; > + > + Verbose("%p: %s -> %s\n", > + Pdo->Dx->DeviceObject, > + PowerDeviceStateName(__PdoGetDevicePowerState(Pdo)), > + PowerDeviceStateName(DeviceState)); > + > + __PdoSetDevicePowerState(Pdo, DeviceState); > + > +done: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoSetDevicePowerDown( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + > + ASSERT3U(DeviceState, >, __PdoGetDevicePowerState(Pdo)); > + > + Verbose("%p: %s -> %s\n", > + Pdo->Dx->DeviceObject, > + PowerDeviceStateName(__PdoGetDevicePowerState(Pdo)), > + PowerDeviceStateName(DeviceState)); > + > + __PdoSetDevicePowerState(Pdo, DeviceState); > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoSetDevicePower( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + POWER_ACTION PowerAction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + Trace("====> (%s:%s)\n", > + PowerDeviceStateName(DeviceState), > + PowerActionName(PowerAction)); > + > + if (DeviceState == __PdoGetDevicePowerState(Pdo)) { > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + goto done; > + } > + > + status = (DeviceState < __PdoGetDevicePowerState(Pdo)) ? > + __PdoSetDevicePowerUp(Pdo, Irp) : > + __PdoSetDevicePowerDown(Pdo, Irp); > + > +done: > + Trace("<==== (%s:%s)(%08x)\n", > + PowerDeviceStateName(DeviceState), > + PowerActionName(PowerAction), > + status); > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoSetSystemPowerUp( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + > + ASSERT3U(SystemState, <, __PdoGetSystemPowerState(Pdo)); > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + if (!NT_SUCCESS(status)) > + goto done; > + > + Verbose("%p: %s -> %s\n", > + Pdo->Dx->DeviceObject, > + PowerSystemStateName(__PdoGetSystemPowerState(Pdo)), > + PowerSystemStateName(SystemState)); > + > + __PdoSetSystemPowerState(Pdo, SystemState); > + > +done: > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoSetSystemPowerDown( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + > + ASSERT3U(SystemState, >, __PdoGetSystemPowerState(Pdo)); > + > + Verbose("%p: %s -> %s\n", > + Pdo->Dx->DeviceObject, > + PowerSystemStateName(__PdoGetSystemPowerState(Pdo)), > + PowerSystemStateName(SystemState)); > + > + __PdoSetSystemPowerState(Pdo, SystemState); > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoSetSystemPower( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + POWER_ACTION PowerAction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + Trace("====> (%s:%s)\n", > + PowerSystemStateName(SystemState), > + PowerActionName(PowerAction)); > + > + if (SystemState == __PdoGetSystemPowerState(Pdo)) { > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + goto done; > + } > + > + status = (SystemState < __PdoGetSystemPowerState(Pdo)) ? > + __PdoSetSystemPowerUp(Pdo, Irp) : > + __PdoSetSystemPowerDown(Pdo, Irp); > + > +done: > + Trace("<==== (%s:%s)(%08x)\n", > + PowerSystemStateName(SystemState), > + PowerActionName(PowerAction), > + status); > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoQueryDevicePowerUp( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + > + ASSERT3U(DeviceState, <, __PdoGetDevicePowerState(Pdo)); > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoQueryDevicePowerDown( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + > + ASSERT3U(DeviceState, >, __PdoGetDevicePowerState(Pdo)); > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoQueryDevicePower( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + DEVICE_POWER_STATE DeviceState; > + POWER_ACTION PowerAction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + DeviceState = StackLocation->Parameters.Power.State.DeviceState; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + Trace("====> (%s:%s)\n", > + PowerDeviceStateName(DeviceState), > + PowerActionName(PowerAction)); > + > + if (DeviceState == __PdoGetDevicePowerState(Pdo)) { > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + goto done; > + } > + > + status = (DeviceState < __PdoGetDevicePowerState(Pdo)) ? > + __PdoQueryDevicePowerUp(Pdo, Irp) : > + __PdoQueryDevicePowerDown(Pdo, Irp); > + > +done: > + Trace("<==== (%s:%s)(%08x)\n", > + PowerDeviceStateName(DeviceState), > + PowerActionName(PowerAction), > + status); > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoQuerySystemPowerUp( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + > + ASSERT3U(SystemState, <, __PdoGetSystemPowerState(Pdo)); > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoQuerySystemPowerDown( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + > + ASSERT3U(SystemState, >, __PdoGetSystemPowerState(Pdo)); > + > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +static FORCEINLINE NTSTATUS > +__PdoQuerySystemPower( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + SYSTEM_POWER_STATE SystemState; > + POWER_ACTION PowerAction; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + SystemState = StackLocation->Parameters.Power.State.SystemState; > + PowerAction = StackLocation->Parameters.Power.ShutdownType; > + > + Trace("====> (%s:%s)\n", > + PowerSystemStateName(SystemState), > + PowerActionName(PowerAction)); > + > + if (SystemState == __PdoGetSystemPowerState(Pdo)) { > + status = PdoForwardIrpSynchronously(Pdo, Irp); > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + goto done; > + } > + > + status = (SystemState < __PdoGetSystemPowerState(Pdo)) ? > + __PdoQuerySystemPowerUp(Pdo, Irp) : > + __PdoQuerySystemPowerDown(Pdo, Irp); > + > +done: > + Trace("<==== (%s:%s)(%08x)\n", > + PowerSystemStateName(SystemState), > + PowerActionName(PowerAction), > + status); > + > + return status; > +} > + > +static NTSTATUS > +PdoDevicePower( > + IN PXENDISK_THREAD Self, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + PKEVENT Event; > + > + Event = ThreadGetEvent(Self); > + > + for (;;) { > + PIRP Irp; > + PIO_STACK_LOCATION StackLocation; > + UCHAR MinorFunction; > + > + if (Pdo->DevicePowerIrp == NULL) { > + (VOID) KeWaitForSingleObject(Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + KeClearEvent(Event); > + } > + > + if (ThreadIsAlerted(Self)) > + break; > + > + Irp = Pdo->DevicePowerIrp; > + > + if (Irp == NULL) > + continue; > + > + Pdo->DevicePowerIrp = NULL; > + KeMemoryBarrier(); > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + MinorFunction = StackLocation->MinorFunction; > + > + switch (StackLocation->MinorFunction) { > + case IRP_MN_SET_POWER: > + (VOID) __PdoSetDevicePower(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_POWER: > + (VOID) __PdoQueryDevicePower(Pdo, Irp); > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + } > + > + return STATUS_SUCCESS; > +} > + > +static NTSTATUS > +PdoSystemPower( > + IN PXENDISK_THREAD Self, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + PKEVENT Event; > + > + Event = ThreadGetEvent(Self); > + > + for (;;) { > + PIRP Irp; > + PIO_STACK_LOCATION StackLocation; > + UCHAR MinorFunction; > + > + if (Pdo->SystemPowerIrp == NULL) { > + (VOID) KeWaitForSingleObject(Event, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + KeClearEvent(Event); > + } > + > + if (ThreadIsAlerted(Self)) > + break; > + > + Irp = Pdo->SystemPowerIrp; > + > + if (Irp == NULL) > + continue; > + > + Pdo->SystemPowerIrp = NULL; > + KeMemoryBarrier(); > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + MinorFunction = StackLocation->MinorFunction; > + > + switch (StackLocation->MinorFunction) { > + case IRP_MN_SET_POWER: > + (VOID) __PdoSetSystemPower(Pdo, Irp); > + break; > + > + case IRP_MN_QUERY_POWER: > + (VOID) __PdoQuerySystemPower(Pdo, Irp); > + break; > + > + default: > + ASSERT(FALSE); > + break; > + } > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + } > + > + return STATUS_SUCCESS; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoDispatchPower( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoDispatchPower( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + UCHAR MinorFunction; > + POWER_STATE_TYPE PowerType; > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + MinorFunction = StackLocation->MinorFunction; > + > + if (MinorFunction != IRP_MN_QUERY_POWER && > + MinorFunction != IRP_MN_SET_POWER) { > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoDispatchPower, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + > + goto done; > + } > + > + PowerType = StackLocation->Parameters.Power.Type; > + > + Trace("====> (%02x:%s)\n", > + MinorFunction, > + PowerMinorFunctionName(MinorFunction)); > + > + switch (PowerType) { > + case DevicePowerState: > + IoMarkIrpPending(Irp); > + > + ASSERT3P(Pdo->DevicePowerIrp, ==, NULL); > + Pdo->DevicePowerIrp = Irp; > + KeMemoryBarrier(); > + > + ThreadWake(Pdo->DevicePowerThread); > + > + status = STATUS_PENDING; > + break; > + > + case SystemPowerState: > + IoMarkIrpPending(Irp); > + > + ASSERT3P(Pdo->SystemPowerIrp, ==, NULL); > + Pdo->SystemPowerIrp = Irp; > + KeMemoryBarrier(); > + > + ThreadWake(Pdo->SystemPowerThread); > + > + status = STATUS_PENDING; > + break; > + > + default: > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoDispatchPower, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + break; > + } > + > + Trace("<==== (%02x:%s) (%08x)\n", > + MinorFunction, > + PowerMinorFunctionName(MinorFunction), > + status); > + > +done: > + return status; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +__drv_functionClass(IO_COMPLETION_ROUTINE) > +__drv_sameIRQL > +static NTSTATUS > +__PdoDispatchDefault( > + IN PDEVICE_OBJECT DeviceObject, > + IN PIRP Irp, > + IN PVOID Context > + ) > +{ > + PXENDISK_PDO Pdo = Context; > + > + UNREFERENCED_PARAMETER(DeviceObject); > + > + if (Irp->PendingReturned) > + IoMarkIrpPending(Irp); > + > + IoReleaseRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + > + return STATUS_SUCCESS; > +} > + > +static DECLSPEC_NOINLINE NTSTATUS > +PdoDispatchDefault( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + NTSTATUS status; > + > + status = IoAcquireRemoveLock(&Pdo->Dx->RemoveLock, Irp); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + IoCopyCurrentIrpStackLocationToNext(Irp); > + IoSetCompletionRoutine(Irp, > + __PdoDispatchDefault, > + Pdo, > + TRUE, > + TRUE, > + TRUE); > + > + status = IoCallDriver(Pdo->LowerDeviceObject, Irp); > + > + return status; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + Irp->IoStatus.Status = status; > + IoCompleteRequest(Irp, IO_NO_INCREMENT); > + > + return status; > +} > + > +NTSTATUS > +PdoDispatch( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ) > +{ > + PIO_STACK_LOCATION StackLocation; > + NTSTATUS status; > + > + StackLocation = IoGetCurrentIrpStackLocation(Irp); > + > + switch (StackLocation->MajorFunction) { > + case IRP_MJ_DEVICE_CONTROL: > + status = PdoDispatchControl(Pdo, Irp); > + break; > + > + case IRP_MJ_PNP: > + status = PdoDispatchPnp(Pdo, Irp); > + break; > + > + case IRP_MJ_POWER: > + status = PdoDispatchPower(Pdo, Irp); > + break; > + > + default: > + status = PdoDispatchDefault(Pdo, Irp); > + break; > + } > + > + return status; > +} > + > +NTSTATUS > +PdoCreate( > + PXENDISK_FDO Fdo, > + PDEVICE_OBJECT PhysicalDeviceObject > + ) > +{ > + PDEVICE_OBJECT LowerDeviceObject; > + ULONG DeviceType; > + PDEVICE_OBJECT FilterDeviceObject; > + PXENDISK_DX Dx; > + PXENDISK_PDO Pdo; > + NTSTATUS status; > + > + LowerDeviceObject = > IoGetAttachedDeviceReference(PhysicalDeviceObject); > + DeviceType = LowerDeviceObject->DeviceType; > + ObDereferenceObject(LowerDeviceObject); > + > +#pragma prefast(suppress:28197) // Possibly leaking memory > 'PhysicalDeviceObject' > + status = IoCreateDevice(DriverGetDriverObject(), > + sizeof(XENDISK_DX), > + NULL, > + DeviceType, > + FILE_DEVICE_SECURE_OPEN, > + FALSE, > + &FilterDeviceObject); > + if (!NT_SUCCESS(status)) > + goto fail1; > + > + Dx = (PXENDISK_DX)FilterDeviceObject->DeviceExtension; > + RtlZeroMemory(Dx, sizeof (XENDISK_DX)); > + > + Dx->Type = PHYSICAL_DEVICE_OBJECT; > + Dx->DeviceObject = FilterDeviceObject; > + Dx->DevicePnpState = Present; > + Dx->SystemPowerState = PowerSystemShutdown; > + Dx->DevicePowerState = PowerDeviceD3; > + > + IoInitializeRemoveLock(&Dx->RemoveLock, PDO_TAG, 0, 0); > + > + Pdo = __PdoAllocate(sizeof (XENDISK_PDO)); > + > + status = STATUS_NO_MEMORY; > + if (Pdo == NULL) > + goto fail2; > + > + LowerDeviceObject = IoAttachDeviceToDeviceStack(FilterDeviceObject, > + PhysicalDeviceObject); > + > + status = STATUS_UNSUCCESSFUL; > + if (LowerDeviceObject == NULL) > + goto fail3; > + > + Pdo->Dx = Dx; > + Pdo->PhysicalDeviceObject = PhysicalDeviceObject; > + Pdo->LowerDeviceObject = LowerDeviceObject; > + Pdo->SectorSize = 512; > + > + status = ThreadCreate(PdoSystemPower, Pdo, &Pdo- > >SystemPowerThread); > + if (!NT_SUCCESS(status)) > + goto fail4; > + > + status = ThreadCreate(PdoDevicePower, Pdo, &Pdo- > >DevicePowerThread); > + if (!NT_SUCCESS(status)) > + goto fail5; > + > + Verbose("%p\n", FilterDeviceObject); > + > + Dx->Pdo = Pdo; > + > +#pragma prefast(suppress:28182) // Dereferencing NULL pointer > + FilterDeviceObject->DeviceType = LowerDeviceObject->DeviceType; > + FilterDeviceObject->Characteristics = LowerDeviceObject- > >Characteristics; > + > + FilterDeviceObject->Flags |= LowerDeviceObject->Flags; > + FilterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; > + > + __PdoLink(Pdo, Fdo); > + > + return STATUS_SUCCESS; > + > +fail5: > + Error("fail5\n"); > + > + ThreadAlert(Pdo->SystemPowerThread); > + ThreadJoin(Pdo->SystemPowerThread); > + Pdo->SystemPowerThread = NULL; > + > +fail4: > + Error("fail4\n"); > + > + Pdo->PhysicalDeviceObject = NULL; > + Pdo->LowerDeviceObject = NULL; > + Pdo->Dx = NULL; > + > + IoDetachDevice(LowerDeviceObject); > + > +fail3: > + Error("fail3\n"); > + > + ASSERT(IsZeroMemory(Pdo, sizeof (XENDISK_PDO))); > + __PdoFree(Pdo); > + > +fail2: > + Error("fail2\n"); > + > + IoDeleteDevice(FilterDeviceObject); > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +VOID > +PdoDestroy( > + IN PXENDISK_PDO Pdo > + ) > +{ > + PDEVICE_OBJECT LowerDeviceObject = Pdo->LowerDeviceObject; > + PXENDISK_DX Dx = Pdo->Dx; > + PDEVICE_OBJECT FilterDeviceObject = Dx->DeviceObject; > + > + ASSERT3U(__PdoGetDevicePnpState(Pdo), ==, Deleted); > + > + ASSERT(__PdoIsMissing(Pdo)); > + Pdo->Missing = FALSE; > + > + __PdoUnlink(Pdo); > + > + Verbose("%p (%s)\n", > + FilterDeviceObject, > + Pdo->Reason); > + Pdo->Reason = NULL; > + > + Dx->Pdo = NULL; > + > + ThreadAlert(Pdo->DevicePowerThread); > + ThreadJoin(Pdo->DevicePowerThread); > + Pdo->DevicePowerThread = NULL; > + > + ThreadAlert(Pdo->SystemPowerThread); > + ThreadJoin(Pdo->SystemPowerThread); > + Pdo->SystemPowerThread = NULL; > + > + Pdo->SectorSize = 0; > + Pdo->PhysicalDeviceObject = NULL; > + Pdo->LowerDeviceObject = NULL; > + Pdo->Dx = NULL; > + > + IoDetachDevice(LowerDeviceObject); > + > + ASSERT(IsZeroMemory(Pdo, sizeof (XENDISK_PDO))); > + __PdoFree(Pdo); > + > + IoDeleteDevice(FilterDeviceObject); > +} > diff --git a/src/xendisk/pdo.h b/src/xendisk/pdo.h > new file mode 100644 > index 0000000..5e2e5d6 > --- /dev/null > +++ b/src/xendisk/pdo.h > @@ -0,0 +1,90 @@ > +/* 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 _XENDISK_PDO_H > +#define _XENDISK_PDO_H > + > +#include <ntddk.h> > +#include "types.h" > +#include "fdo.h" > + > +typedef struct _XENDISK_PDO XENDISK_PDO, *PXENDISK_PDO; > + > +extern VOID > +PdoSetDevicePnpState( > + IN PXENDISK_PDO Pdo, > + IN DEVICE_PNP_STATE State > + ); > + > +extern DEVICE_PNP_STATE > +PdoGetDevicePnpState( > + IN PXENDISK_PDO Pdo > + ); > + > +extern PDEVICE_OBJECT > +PdoGetPhysicalDeviceObject( > + IN PXENDISK_PDO Pdo > + ); > + > +extern BOOLEAN > +PdoIsMissing( > + IN PXENDISK_PDO Pdo > + ); > + > +extern VOID > +PdoSetMissing( > + IN PXENDISK_PDO Pdo, > + IN const CHAR *Reason > + ); > + > +extern BOOLEAN > +PdoIsMasked( > + IN PXENDISK_PDO Pdo > + ); > + > +extern NTSTATUS > +PdoCreate( > + IN PXENDISK_FDO Fdo, > + IN PDEVICE_OBJECT PhysicalDeviceObject > + ); > + > +extern VOID > +PdoDestroy( > + IN PXENDISK_PDO Pdo > + ); > + > +extern NTSTATUS > +PdoDispatch( > + IN PXENDISK_PDO Pdo, > + IN PIRP Irp > + ); > + > +#endif // _XENDISK_PDO_H > diff --git a/src/xendisk/thread.c b/src/xendisk/thread.c > new file mode 100644 > index 0000000..92e2b94 > --- /dev/null > +++ b/src/xendisk/thread.c > @@ -0,0 +1,225 @@ > +/* 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 "thread.h" > +#include "debug.h" > +#include "assert.h" > +#include "util.h" > + > +#define THREAD_POOL 'ERHT' > + > +struct _XENDISK_THREAD { > + XENDISK_THREAD_FUNCTION Function; > + PVOID Context; > + KEVENT Event; > + BOOLEAN Alerted; > + LONG References; > + PKTHREAD Thread; > +}; > + > +static FORCEINLINE PVOID > +__ThreadAllocate( > + IN ULONG Length > + ) > +{ > + return __AllocateNonPagedPoolWithTag(__FUNCTION__, __LINE__, > Length, THREAD_POOL); > +} > + > +static FORCEINLINE VOID > +__ThreadFree( > + IN PVOID Buffer > + ) > +{ > + __FreePoolWithTag(Buffer, THREAD_POOL); > +} > + > +static FORCEINLINE VOID > +__ThreadWake( > + IN PXENDISK_THREAD Thread > + ) > +{ > + KeSetEvent(&Thread->Event, IO_NO_INCREMENT, FALSE); > +} > + > +VOID > +ThreadWake( > + IN PXENDISK_THREAD Thread > + ) > +{ > + __ThreadWake(Thread); > +} > + > +static FORCEINLINE VOID > +__ThreadAlert( > + IN PXENDISK_THREAD Thread > + ) > +{ > + Thread->Alerted = TRUE; > + __ThreadWake(Thread); > +} > + > +VOID > +ThreadAlert( > + IN PXENDISK_THREAD Thread > + ) > +{ > + __ThreadAlert(Thread); > +} > + > +KSTART_ROUTINE ThreadFunction; > + > +VOID > +ThreadFunction( > + IN PVOID Argument > + ) > +{ > + PXENDISK_THREAD Self = Argument; > + NTSTATUS status; > + > + status = Self->Function(Self, Self->Context); > + > + if (InterlockedDecrement(&Self->References) == 0) > + __ThreadFree(Self); > + > + PsTerminateSystemThread(status); > + // NOT REACHED > +} > + > +NTSTATUS > +ThreadCreate( > + IN XENDISK_THREAD_FUNCTION Function, > + IN PVOID Context, > + OUT PXENDISK_THREAD *Thread > + ) > +{ > + HANDLE Handle; > + NTSTATUS status; > + > + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); > + > + (*Thread) = __ThreadAllocate(sizeof (XENDISK_THREAD)); > + > + status = STATUS_NO_MEMORY; > + if (*Thread == NULL) > + goto fail1; > + > + (*Thread)->Function = Function; > + (*Thread)->Context = Context; > + (*Thread)->Alerted = FALSE; > + (*Thread)->References = 2; // One for us, one for the thread function > + > + KeInitializeEvent(&(*Thread)->Event, NotificationEvent, FALSE); > + > + status = PsCreateSystemThread(&Handle, > + STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL, > + NULL, > + NULL, > + NULL, > + ThreadFunction, > + *Thread); > + if (!NT_SUCCESS(status)) { > + --(*Thread)->References; // Fake thread function termination > + goto fail2; > + } > + > + status = ObReferenceObjectByHandle(Handle, > + SYNCHRONIZE, > + *PsThreadType, > + KernelMode, > + &(*Thread)->Thread, > + NULL); > + if (!NT_SUCCESS(status)) > + goto fail3; > + > + ZwClose(Handle); > + > + return STATUS_SUCCESS; > + > +fail3: > + Error("fail3\n"); > + > + __ThreadAlert(*Thread); > + ZwClose(Handle); > + > +fail2: > + Error("fail2\n"); > + > + if (InterlockedDecrement(&(*Thread)->References) == 0) > + __ThreadFree(*Thread); > + > + *Thread = NULL; > + > +fail1: > + Error("fail1 (%08x)\n", status); > + > + return status; > +} > + > +PKEVENT > +ThreadGetEvent( > + IN PXENDISK_THREAD Thread > + ) > +{ > + return &Thread->Event; > +} > + > +BOOLEAN > +ThreadIsAlerted( > + IN PXENDISK_THREAD Thread > + ) > +{ > + return Thread->Alerted; > +} > + > +VOID > +ThreadJoin( > + IN PXENDISK_THREAD Thread > + ) > +{ > + LONG References; > + > + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); > + ASSERT3P(KeGetCurrentThread(), !=, Thread->Thread); > + > + (VOID) KeWaitForSingleObject(Thread->Thread, > + Executive, > + KernelMode, > + FALSE, > + NULL); > + > + References = InterlockedDecrement(&Thread->References); > + ASSERT3U(References, ==, 0); > + > + __ThreadFree(Thread); > +} > + > diff --git a/src/xendisk/thread.h b/src/xendisk/thread.h > new file mode 100644 > index 0000000..c197337 > --- /dev/null > +++ b/src/xendisk/thread.h > @@ -0,0 +1,73 @@ > +/* 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 _XENDISK_THREAD_H > +#define _XENDISK_THREAD_H > + > +#include <ntddk.h> > + > +typedef struct _XENDISK_THREAD XENDISK_THREAD, *PXENDISK_THREAD; > + > +typedef NTSTATUS (*XENDISK_THREAD_FUNCTION)(PXENDISK_THREAD, > PVOID); > + > +extern NTSTATUS > +ThreadCreate( > + IN XENDISK_THREAD_FUNCTION Function, > + IN PVOID Context, > + OUT PXENDISK_THREAD *Thread > + ); > + > +extern PKEVENT > +ThreadGetEvent( > + IN PXENDISK_THREAD Self > + ); > + > +extern BOOLEAN > +ThreadIsAlerted( > + IN PXENDISK_THREAD Self > + ); > + > +extern VOID > +ThreadWake( > + IN PXENDISK_THREAD Thread > + ); > + > +extern VOID > +ThreadAlert( > + IN PXENDISK_THREAD Thread > + ); > + > +extern VOID > +ThreadJoin( > + IN PXENDISK_THREAD Thread > + ); > + > +#endif // _XENDISK_THREAD_H > diff --git a/src/xendisk/types.h b/src/xendisk/types.h > new file mode 100644 > index 0000000..b2b4218 > --- /dev/null > +++ b/src/xendisk/types.h > @@ -0,0 +1,53 @@ > +/* 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 _XENDISK_TYPES_H > +#define _XENDISK_TYPES_H > + > +typedef enum _DEVICE_OBJECT_TYPE { > + PHYSICAL_DEVICE_OBJECT = 'ODP', > + FUNCTION_DEVICE_OBJECT = 'ODF' > +} DEVICE_OBJECT_TYPE, *PDEVICE_OBJECT_TYPE; > + > +typedef enum _DEVICE_PNP_STATE { > + Invalid = 0, > + Present, // PDO only > + Enumerated, // PDO only > + Added, // FDO only > + Started, > + StopPending, > + Stopped, > + RemovePending, > + SurpriseRemovePending, > + Deleted > +} DEVICE_PNP_STATE, *PDEVICE_PNP_STATE; > + > +#endif // _XENDISK_TYPES_H > diff --git a/src/xendisk/util.h b/src/xendisk/util.h > new file mode 100644 > index 0000000..e7adc22 > --- /dev/null > +++ b/src/xendisk/util.h > @@ -0,0 +1,222 @@ > +/* 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 _UTIL_H > +#define _UTIL_H > + > +#include <ntddk.h> > + > +#include "assert.h" > + > +typedef struct _NON_PAGED_BUFFER_HEADER { > + SIZE_T Length; > + ULONG Tag; > +} NON_PAGED_BUFFER_HEADER, *PNON_PAGED_BUFFER_HEADER; > + > +typedef struct _NON_PAGED_BUFFER_TRAILER { > + ULONG Tag; > +} NON_PAGED_BUFFER_TRAILER, *PNON_PAGED_BUFFER_TRAILER; > + > +static FORCEINLINE PVOID > +__AllocateNonPagedPoolWithTag( > + IN PCHAR Caller, > + IN ULONG Line, > + IN SIZE_T Length, > + IN ULONG Tag > + ) > +{ > + PUCHAR Buffer; > + PNON_PAGED_BUFFER_HEADER Header; > + PNON_PAGED_BUFFER_TRAILER Trailer; > + > + ASSERT3S(Length, !=, 0); > + > + Buffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, > + sizeof (NON_PAGED_BUFFER_HEADER) + > + Length + > + sizeof (NON_PAGED_BUFFER_TRAILER), > + Tag); > + if (Buffer == NULL) { > + Warning("%s:%u : AllocFailed %d bytes, %08x tag\n", Caller, Line, > Length, Tag); > + goto done; > + } > + > + RtlZeroMemory(Buffer, > + sizeof (NON_PAGED_BUFFER_HEADER) + > + Length + > + sizeof (NON_PAGED_BUFFER_TRAILER)); > + > + Header = (PNON_PAGED_BUFFER_HEADER)Buffer; > + Header->Length = Length; > + Header->Tag = Tag; > + > + Buffer += sizeof (NON_PAGED_BUFFER_HEADER); > + > + Trailer = (PNON_PAGED_BUFFER_TRAILER)(Buffer + Length); > + Trailer->Tag = Tag; > + > +done: > + return Buffer; > +} > + > +static FORCEINLINE VOID > +__FreePoolWithTag( > + IN PVOID _Buffer, > + IN ULONG Tag > + ) > +{ > + PUCHAR Buffer = (PUCHAR)_Buffer; > + SIZE_T Length; > + PNON_PAGED_BUFFER_HEADER Header; > + PNON_PAGED_BUFFER_TRAILER Trailer; > + > + ASSERT3P(Buffer, !=, NULL); > + > + Buffer -= sizeof (NON_PAGED_BUFFER_HEADER); > + > + Header = (PNON_PAGED_BUFFER_HEADER)Buffer; > + ASSERT3U(Tag, ==, Header->Tag); > + Length = Header->Length; > + > + Buffer += sizeof (NON_PAGED_BUFFER_HEADER); > + > + Trailer = (PNON_PAGED_BUFFER_TRAILER)(Buffer + Length); > + ASSERT3U(Tag, ==, Trailer->Tag); > + > + Buffer -= sizeof (NON_PAGED_BUFFER_HEADER); > + > + RtlFillMemory(Buffer, > + sizeof (NON_PAGED_BUFFER_HEADER) + > + Length + > + sizeof (NON_PAGED_BUFFER_TRAILER), > + 0xAA); > + > + ExFreePoolWithTag(Buffer, Tag); > +} > + > +static FORCEINLINE PMDL > +__AllocPagesForMdl( > + IN SIZE_T Size > + ) > +{ > + PMDL Mdl; > + PHYSICAL_ADDRESS LowAddr; > + PHYSICAL_ADDRESS HighAddr; > + PHYSICAL_ADDRESS SkipBytes; > + > + SkipBytes.QuadPart = 0ull; > + HighAddr.QuadPart = ~0ull; > + > + // try > 4GB > + LowAddr.QuadPart = 0x100000000ull; > + Mdl = MmAllocatePagesForMdlEx(LowAddr, HighAddr, SkipBytes, Size, > MmCached, 0); > + if (Mdl) { > + if (MmGetMdlByteCount(Mdl) == Size) { > + goto done; > + } > + MmFreePagesFromMdl(Mdl); > + ExFreePool(Mdl); > + Mdl = NULL; > + } > + > + // try > 2GB > + LowAddr.QuadPart = 0x80000000ull; > + Mdl = MmAllocatePagesForMdlEx(LowAddr, HighAddr, SkipBytes, Size, > MmCached, 0); > + if (Mdl) { > + if (MmGetMdlByteCount(Mdl) == Size) { > + goto done; > + } > + MmFreePagesFromMdl(Mdl); > + ExFreePool(Mdl); > + Mdl = NULL; > + } > + > + // try anywhere > + LowAddr.QuadPart = 0ull; > + Mdl = MmAllocatePagesForMdlEx(LowAddr, HighAddr, SkipBytes, Size, > MmCached, 0); > + // Mdl byte count gets checked again after this returns > + > +done: > + return Mdl; > +} > +static FORCEINLINE PVOID > +___AllocPages( > + IN PCHAR Caller, > + IN ULONG Line, > + IN SIZE_T Size, > + OUT PMDL* Mdl > + ) > +{ > + PVOID Buffer; > + > + *Mdl = __AllocPagesForMdl(Size); > + if (*Mdl == NULL) { > + Warning("%s:%u : MmAllocatePagesForMdlEx Failed %d bytes\n", > Caller, Line, Size); > + goto fail1; > + } > + > + if (MmGetMdlByteCount(*Mdl) != Size) { > + Warning("%s:%u : %d bytes != %d bytes requested\n", Caller, Line, > MmGetMdlByteCount(*Mdl), Size); > + goto fail2; > + } > + > + Buffer = MmMapLockedPagesSpecifyCache(*Mdl, KernelMode, > MmCached, NULL, FALSE, NormalPagePriority); > + if (Buffer == NULL) { > + Warning("%s:%u : MmMapLockedPagesSpecifyCache Failed %d > bytes\n", Caller, Line, Size); > + goto fail3; > + } > + > + return Buffer; > + > +fail3: > +fail2: > + MmFreePagesFromMdl(*Mdl); > + ExFreePool(*Mdl); > +fail1: > + *Mdl = NULL; > + return NULL; > +} > +#define __AllocPages(Size, Mdl) ___AllocPages(__FUNCTION__, __LINE__, > Size, Mdl) > + > +static FORCEINLINE VOID > +__FreePages( > + IN PVOID Buffer, > + IN PMDL Mdl > + ) > +{ > + if (Buffer && Mdl) { > + MmUnmapLockedPages(Buffer, Mdl); > + MmFreePagesFromMdl(Mdl); > + ExFreePool(Mdl); > + } > +} > + > +#endif // _UTIL_H > diff --git a/src/xendisk/xendisk.rc b/src/xendisk/xendisk.rc > new file mode 100644 > index 0000000..df2e5b6 > --- /dev/null > +++ b/src/xendisk/xendisk.rc > @@ -0,0 +1,56 @@ > +/* 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 <windows.h> > +#include <ntverp.h> > + > + > +#undef VER_COMPANYNAME_STR > +#undef VER_PRODUCTNAME_STR > +#undef VER_PRODUCTVERSION > +#undef VER_PRODUCTVERSION_STR > + > +#include <version.h> > + > +#define VER_COMPANYNAME_STR COMPANY_NAME_STR > +#define VER_LEGALCOPYRIGHT_STR "Copyright (c) Citrix Systems Inc." > + > +#define VER_PRODUCTNAME_STR "XENDISK" > +#define VER_PRODUCTVERSION > MAJOR_VERSION,MINOR_VERSION,MICRO_VERSION,BUILD_NUMBER > +#define VER_PRODUCTVERSION_STR MAJOR_VERSION_STR "." > MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR > + > +#define VER_INTERNALNAME_STR "XENDISK.SYS" > +#define VER_FILEDESCRIPTION_STR "XENDISK" > + > +#define VER_FILETYPE VFT_DRV > +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM > + > +#include <common.ver> > diff --git a/src/xenvbd.inf b/src/xenvbd.inf > index bc8627b..0d58453 100644 > --- a/src/xenvbd.inf > +++ b/src/xenvbd.inf > @@ -46,6 +46,7 @@ CoInst_CopyFiles=11 > [SourceDisksFiles] > xenvbd.sys=0,, > xencrsh.sys=0,, > +xendisk.sys=0,, > xenvbd_coinst.dll=0,, > > [Manufacturer] > @@ -62,9 +63,25 @@ CopyFiles=XenVbd_Copyfiles > [XenVbd_Copyfiles] > xenvbd.sys > xencrsh.sys > +xendisk.sys > + > +[XenVbd_Inst.HW] > +AddReg=XenVbd_AddReg > + > +[XenVbd_AddReg] > +HKR,,"UpperFilters",0x00010000,"xendisk" > > [XenVbd_Inst.Services] > AddService=xenvbd,2,XenVbd_Service, > +AddService=xendisk,,XenDisk_Service, > + > +[XenDisk_Service] > +DisplayName=%XenDiskDesc% > +ServiceType=%SERVICE_KERNEL_DRIVER% > +StartType=%SERVICE_BOOT_START% > +ErrorControl=%SERVICE_ERROR_NORMAL% > +ServiceBinary=%12%\xendisk.sys > +LoadOrderGroup="Scsi Miniport" > > [XenVbd_Service] > DisplayName=%XenVbdDesc% > @@ -95,6 +112,7 @@ > HKR,,CoInstallers32,0x00010000,"xenvbd_coinst_@MAJOR_VERSION@_@M > INOR_VERSION@_@M > Company = "@COMPANY_NAME@" > DiskDesc = "@PRODUCT_NAME@ PV Storage Host Adapter Package" > XenVbdDesc= "@PRODUCT_NAME@ PV Storage Host Adapter" > +XenDiskDesc= "@PRODUCT_NAME@ PV Storage Filter" > > SERVICE_BOOT_START = 0x0 > SERVICE_SYSTEM_START = 0x1 > diff --git a/vs2012/package/package.vcxproj > b/vs2012/package/package.vcxproj > index 5e5fcbc..9782f19 100644 > --- a/vs2012/package/package.vcxproj > +++ b/vs2012/package/package.vcxproj > @@ -51,6 +51,9 @@ > <ProjectReference Include="..\xenvbd\xenvbd.vcxproj"> > <Project>{ef236371-3145-41b1-99c9- > 82b33e353f17}</Project> > </ProjectReference> > + <ProjectReference Include="..\xendisk\xendisk.vcxproj"> > + <Project>{d7411b2c-2c43-434d-9f56- > e10a3d2f5bad}</Project> > + </ProjectReference> > </ItemGroup> > <ItemGroup> > <FilesToPackage > Include="$(KIT)\Redist\DIFx\dpinst\EngMui\x86\dpinst.exe" > Condition="'$(Platform)'=='Win32'" /> > diff --git a/vs2012/xendisk/xendisk.vcxproj > b/vs2012/xendisk/xendisk.vcxproj > new file mode 100644 > index 0000000..333bc40 > --- /dev/null > +++ b/vs2012/xendisk/xendisk.vcxproj > @@ -0,0 +1,84 @@ > +<?xml version="1.0" encoding="utf-8"?> > +<Project DefaultTargets="Build" ToolsVersion="4.0" > xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> > + <Import Project="..\configs.props" /> > + > + <PropertyGroup Label="Globals"> > + <Configuration>Windows Vista Debug</Configuration> > + <Platform Condition="'$(Platform)' == ''">Win32</Platform> > + > <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> > + </PropertyGroup> > + <PropertyGroup Label="ProeprtySheets"> > + > <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset > > > + <ConfigurationType>Driver</ConfigurationType> > + <DriverType>WDM</DriverType> > + </PropertyGroup> > + > + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> > + > + <PropertyGroup Label="Globals"> > + <ProjectGuid>{D7411B2C-2C43-434D-9F56- > E10A3D2F5BAD}</ProjectGuid> > + </PropertyGroup> > + > + <Import Project="..\targets.props" /> > + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> > + > + <PropertyGroup> > + > <IncludePath>$(ProjectDir)..\..\include;$(IncludePath)</IncludePath > > > + <RunCodeAnalysis>true</RunCodeAnalysis> > + <EnableInf2cat>false</EnableInf2cat> > + > <IntDir>..\$(ProjectName)\$(ConfigurationName)\$(Platform)\</Int > Dir> > + <OutDir>..\$(ConfigurationName)\$(Platform)\</OutDir> > + </PropertyGroup> > + > + <ItemDefinitionGroup> > + <ClCompile> > + <BufferSecurityCheck>false</BufferSecurityCheck> > + > <PreprocessorDefinitions>__MODULE__="XENDISK";%(Preprocesso > rDefinitions)</PreprocessorDefinitions> > + <WarningLevel>EnableAllWarnings</WarningLevel> > + > <DisableSpecificWarnings>4548;4711;4820;4668;4255;6001;6054;28196 > ;%(DisableSpecificWarnings)</DisableSpecificWarnings> > + > <MultiProcessorCompilation>true</MultiProcessorCompilation> > + <EnablePREfast>true</EnablePREfast> > + </ClCompile> > + <Link> > + > <AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;%(Addition > alDependencies)</AdditionalDependencies> > + </Link> > + <Inf> > + <SpecifyArchitecture>true</SpecifyArchitecture> > + > <SpecifyDriverVerDirectiveVersion>true</SpecifyDriverVerDirective > Version> > + > <TimeStamp>$(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VE > RSION).$(BUILD_NUMBER)</TimeStamp> > + <EnableVerbose>true</EnableVerbose> > + </Inf> > + </ItemDefinitionGroup> > + <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'"> > + <ClCompile> > + > <PreprocessorDefinitions>__i386__;%(PreprocessorDefinitions)</Pr > eprocessorDefinitions> > + </ClCompile> > + <Inf> > + <Architecture>x86</Architecture> > + </Inf> > + </ItemDefinitionGroup> > + <ItemDefinitionGroup Condition="'$(Platform)'=='x64'"> > + <ClCompile> > + > <PreprocessorDefinitions>__x86_64__;%(PreprocessorDefinitions)< > /PreprocessorDefinitions> > + </ClCompile> > + <Inf> > + <Architecture>amd64</Architecture> > + </Inf> > + </ItemDefinitionGroup> > + > + <ItemGroup> > + <FilesToPackage Include="$(TargetPath)" /> > + <FilesToPackage Include="$(OutDir)$(TargetName).pdb" /> > + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" > Condition="'@(Inf)'!=''" /> > + </ItemGroup> > + <ItemGroup> > + <ClCompile Include="../../src/xendisk/driver.c" /> > + <ClCompile Include="../../src/xendisk/fdo.c" /> > + <ClCompile Include="../../src/xendisk/pdo.c" /> > + <ClCompile Include="../../src/xendisk/thread.c" /> > + </ItemGroup> > + <ItemGroup> > + <ResourceCompile Include="..\..\src\xendisk\xendisk.rc" /> > + </ItemGroup> > + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> > +</Project> > diff --git a/vs2012/xendisk/xendisk.vcxproj.user > b/vs2012/xendisk/xendisk.vcxproj.user > new file mode 100644 > index 0000000..0b2b210 > --- /dev/null > +++ b/vs2012/xendisk/xendisk.vcxproj.user > @@ -0,0 +1,8 @@ > +<?xml version="1.0" encoding="utf-8"?> > +<Project ToolsVersion="4.0" > xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> > + <PropertyGroup> > + <SignMode>TestSign</SignMode> > + <TestCertificate>..\..\src\xenvbd.pfx</TestCertificate> > + > <TimeStampServer>http://timestamp.verisign.com/scripts/timstam > p.dll</TimeStampServer> > + </PropertyGroup> > +</Project> > diff --git a/vs2012/xenvbd.sln b/vs2012/xenvbd.sln > index 86fb1a5..15113cf 100644 > --- a/vs2012/xenvbd.sln > +++ b/vs2012/xenvbd.sln > @@ -4,10 +4,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") > = "xenvbd", "xenvbd\xenvbd.vcx > ProjectSection(ProjectDependencies) = postProject > {50C08437-C1F3-4349-BF6A-7B55A06BF999} = {50C08437- > C1F3-4349-BF6A-7B55A06BF999} > {58F5BC43-B92E-4A2B-975D-0066EAB29092} = {58F5BC43- > B92E-4A2B-975D-0066EAB29092} > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD} = {D7411B2C- > 2C43-434D-9F56-E10A3D2F5BAD} > EndProjectSection > EndProject > Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xencrsh", > "xencrsh\xencrsh.vcxproj", "{58F5BC43-B92E-4A2B-975D-0066EAB29092}" > EndProject > +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xendisk", > "xendisk\xendisk.vcxproj", "{D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}" > +EndProject > Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xenvbd_coinst", > "coinst\xenvbd_coinst.vcxproj", "{50C08437-C1F3-4349-BF6A- > 7B55A06BF999}" > ProjectSection(ProjectDependencies) = postProject > {58F5BC43-B92E-4A2B-975D-0066EAB29092} = {58F5BC43- > B92E-4A2B-975D-0066EAB29092} > @@ -18,6 +21,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") > = "package", "package\package. > {50C08437-C1F3-4349-BF6A-7B55A06BF999} = {50C08437- > C1F3-4349-BF6A-7B55A06BF999} > {58F5BC43-B92E-4A2B-975D-0066EAB29092} = {58F5BC43- > B92E-4A2B-975D-0066EAB29092} > {EF236371-3145-41B1-99C9-82B33E353F17} = {EF236371-3145-41B1-99C9- > 82B33E353F17} > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD} = {D7411B2C- > 2C43-434D-9F56-E10A3D2F5BAD} > EndProjectSection > EndProject > Global > @@ -36,6 +40,30 @@ Global > Windows Vista Release|x64 = Windows Vista Release|x64 > EndGlobalSection > GlobalSection(ProjectConfigurationPlatforms) = postSolution > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Debug|Win32.ActiveCfg = Windows 7 Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Debug|Win32.Build.0 = Windows 7 Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Debug|x64.ActiveCfg = Windows 7 Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Debug|x64.Build.0 = Windows 7 Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Release|Win32.ActiveCfg = Windows 7 Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Release|Win32.Build.0 = Windows 7 Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Release|x64.ActiveCfg = Windows 7 Release|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Release|x64.Build.0 = Windows 7 Release|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Debug|Win32.ActiveCfg = Windows 8 Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Debug|Win32.Build.0 = Windows 8 Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Debug|x64.ActiveCfg = Windows 8 Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Debug|x64.Build.0 = Windows 8 Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Release|Win32.ActiveCfg = Windows 8 Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Release|Win32.Build.0 = Windows 8 Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Release|x64.ActiveCfg = Windows 8 Release|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Release|x64.Build.0 = Windows 8 Release|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Debug|Win32.ActiveCfg = Windows Vista Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Debug|Win32.Build.0 = Windows Vista Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Debug|x64.ActiveCfg = Windows Vista Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Debug|x64.Build.0 = Windows Vista Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Release|Win32.ActiveCfg = Windows Vista Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Release|Win32.Build.0 = Windows Vista Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Release|x64.ActiveCfg = Windows Vista Release|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Release|x64.Build.0 = Windows Vista Release|x64 > {EF236371-3145-41B1-99C9-82B33E353F17}.Windows 7 > Debug|Win32.ActiveCfg = Windows 7 Debug|Win32 > {EF236371-3145-41B1-99C9-82B33E353F17}.Windows 7 > Debug|Win32.Build.0 = Windows 7 Debug|Win32 > {EF236371-3145-41B1-99C9-82B33E353F17}.Windows 7 > Debug|x64.ActiveCfg = Windows 7 Debug|x64 > diff --git a/vs2013/package/package.vcxproj > b/vs2013/package/package.vcxproj > index 5d0de4d..8b2fa4f 100644 > --- a/vs2013/package/package.vcxproj > +++ b/vs2013/package/package.vcxproj > @@ -80,6 +80,9 @@ > <ProjectReference Include="..\xenvbd\xenvbd.vcxproj"> > <Project>{ef236371-3145-41b1-99c9-82b33e353f17}</Project> > </ProjectReference> > + <ProjectReference Include="..\xendisk\xendisk.vcxproj"> > + <Project>{d7411b2c-2c43-434d-9f56-e10a3d2f5bad}</Project> > + </ProjectReference> > </ItemGroup> > <ItemGroup> > <FilesToPackage > Include="$(KIT)\Redist\DIFx\dpinst\EngMui\x86\dpinst.exe" > Condition="'$(Platform)'=='Win32'" /> > diff --git a/vs2013/xendisk/xendisk.vcxproj > b/vs2013/xendisk/xendisk.vcxproj > new file mode 100644 > index 0000000..39b9163 > --- /dev/null > +++ b/vs2013/xendisk/xendisk.vcxproj > @@ -0,0 +1,112 @@ > +<?xml version="1.0" encoding="utf-8"?> > +<Project DefaultTargets="Build" ToolsVersion="4.0" > xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> > + <Import Project="..\configs.props" /> > + <PropertyGroup Label="Globals"> > + <Configuration>Windows Vista Debug</Configuration> > + <Platform Condition="'$(Platform)' == ''">Win32</Platform> > + <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor> > + </PropertyGroup> > + <PropertyGroup Label="ProeprtySheets"> > + <ConfigurationType>Driver</ConfigurationType> > + <DriverType>WDM</DriverType> > + </PropertyGroup> > + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows 8 Release|Win32'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows Vista Debug|Win32'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows Vista > Release|Win32'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows 7 Release|Win32'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows 7 Debug|Win32'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows 8 Debug|Win32'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows 8 Release|x64'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows Vista Debug|x64'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows Vista Release|x64'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows 7 Release|x64'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows 7 Debug|x64'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Configuration" > Condition="'$(Configuration)|$(Platform)'=='Windows 8 Debug|x64'"> > + <PlatformToolset>WindowsKernelModeDriver8.1</PlatformToolset> > + </PropertyGroup> > + <PropertyGroup Label="Globals"> > + <ProjectGuid>{D7411B2C-2C43-434D-9F56- > E10A3D2F5BAD}</ProjectGuid> > + </PropertyGroup> > + <Import Project="..\targets.props" /> > + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> > + <PropertyGroup> > + <IncludePath>$(ProjectDir)..\..\include;$(IncludePath)</IncludePath> > + <RunCodeAnalysis>true</RunCodeAnalysis> > + <EnableInf2cat>false</EnableInf2cat> > + <IntDir>..\$(ProjectName)\$(ConfigurationName)\$(Platform)\</IntDir> > + <OutDir>..\$(ConfigurationName)\$(Platform)\</OutDir> > + </PropertyGroup> > + <ItemDefinitionGroup> > + <ClCompile> > + <BufferSecurityCheck>false</BufferSecurityCheck> > + > <PreprocessorDefinitions>__MODULE__="XENDISK";%(PreprocessorDefiniti > ons)</PreprocessorDefinitions> > + <WarningLevel>EnableAllWarnings</WarningLevel> > + > <DisableSpecificWarnings>4548;4711;4820;4668;4255;6001;6054;28196;%(Disa > bleSpecificWarnings)</DisableSpecificWarnings> > + <MultiProcessorCompilation>true</MultiProcessorCompilation> > + <EnablePREfast>true</EnablePREfast> > + </ClCompile> > + <Link> > + > <AdditionalDependencies>$(DDK_LIB_PATH)/libcntpr.lib;%(AdditionalDepen > dencies)</AdditionalDependencies> > + </Link> > + <Inf> > + <SpecifyArchitecture>true</SpecifyArchitecture> > + > <SpecifyDriverVerDirectiveVersion>true</SpecifyDriverVerDirectiveVersion > > > + > <TimeStamp>$(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION). > $(BUILD_NUMBER)</TimeStamp> > + <EnableVerbose>true</EnableVerbose> > + </Inf> > + </ItemDefinitionGroup> > + <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'"> > + <ClCompile> > + > <PreprocessorDefinitions>__i386__;%(PreprocessorDefinitions)</Preproces > sorDefinitions> > + </ClCompile> > + <Inf> > + <Architecture>x86</Architecture> > + </Inf> > + </ItemDefinitionGroup> > + <ItemDefinitionGroup Condition="'$(Platform)'=='x64'"> > + <ClCompile> > + > <PreprocessorDefinitions>__x86_64__;%(PreprocessorDefinitions)</Prepro > cessorDefinitions> > + </ClCompile> > + <Inf> > + <Architecture>amd64</Architecture> > + </Inf> > + </ItemDefinitionGroup> > + <ItemGroup> > + <FilesToPackage Include="$(TargetPath)" /> > + <FilesToPackage Include="$(OutDir)$(TargetName).pdb" /> > + <FilesToPackage Include="@(Inf->'%(CopyOutput)')" > Condition="'@(Inf)'!=''" /> > + </ItemGroup> > + <ItemGroup> > + <ClCompile Include="../../src/xendisk/driver.c" /> > + <ClCompile Include="../../src/xendisk/fdo.c" /> > + <ClCompile Include="../../src/xendisk/pdo.c" /> > + <ClCompile Include="../../src/xendisk/thread.c" /> > + </ItemGroup> > + <ItemGroup> > + <ResourceCompile Include="..\..\src\xendisk\xendisk.rc" /> > + </ItemGroup> > + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> > +</Project> > diff --git a/vs2013/xendisk/xendisk.vcxproj.user > b/vs2013/xendisk/xendisk.vcxproj.user > new file mode 100644 > index 0000000..1f1f3c0 > --- /dev/null > +++ b/vs2013/xendisk/xendisk.vcxproj.user > @@ -0,0 +1,8 @@ > +<?xml version="1.0" encoding="utf-8"?> > +<Project ToolsVersion="4.0" > xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> > + <PropertyGroup> > + <SignMode>TestSign</SignMode> > + <TestCertificate>..\..\src\xenvbd.pfx</TestCertificate> > + > <TimeStampServer>http://timestamp.verisign.com/scripts/timstamp.dll</Ti > meStampServer> > + </PropertyGroup> > +</Project> > diff --git a/vs2013/xenvbd.sln b/vs2013/xenvbd.sln > index 13128c5..da798d2 100644 > --- a/vs2013/xenvbd.sln > +++ b/vs2013/xenvbd.sln > @@ -4,10 +4,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") > = "xenvbd", "xenvbd\xenvbd.vcx > ProjectSection(ProjectDependencies) = postProject > {50C08437-C1F3-4349-BF6A-7B55A06BF999} = {50C08437- > C1F3-4349-BF6A-7B55A06BF999} > {58F5BC43-B92E-4A2B-975D-0066EAB29092} = {58F5BC43- > B92E-4A2B-975D-0066EAB29092} > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD} = {D7411B2C- > 2C43-434D-9F56-E10A3D2F5BAD} > EndProjectSection > EndProject > Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xencrsh", > "xencrsh\xencrsh.vcxproj", "{58F5BC43-B92E-4A2B-975D-0066EAB29092}" > EndProject > +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xendisk", > "xendisk\xendisk.vcxproj", "{D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}" > +EndProject > Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xenvbd_coinst", > "coinst\xenvbd_coinst.vcxproj", "{50C08437-C1F3-4349-BF6A- > 7B55A06BF999}" > ProjectSection(ProjectDependencies) = postProject > {58F5BC43-B92E-4A2B-975D-0066EAB29092} = {58F5BC43- > B92E-4A2B-975D-0066EAB29092} > @@ -18,6 +21,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") > = "package", "package\package. > {50C08437-C1F3-4349-BF6A-7B55A06BF999} = {50C08437- > C1F3-4349-BF6A-7B55A06BF999} > {58F5BC43-B92E-4A2B-975D-0066EAB29092} = {58F5BC43- > B92E-4A2B-975D-0066EAB29092} > {EF236371-3145-41B1-99C9-82B33E353F17} = {EF236371-3145-41B1-99C9- > 82B33E353F17} > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD} = {D7411B2C- > 2C43-434D-9F56-E10A3D2F5BAD} > EndProjectSection > EndProject > Global > @@ -36,6 +40,30 @@ Global > Windows Vista Release|x64 = Windows Vista Release|x64 > EndGlobalSection > GlobalSection(ProjectConfigurationPlatforms) = postSolution > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Debug|Win32.ActiveCfg = Windows 7 Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Debug|Win32.Build.0 = Windows 7 Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Debug|x64.ActiveCfg = Windows 7 Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Debug|x64.Build.0 = Windows 7 Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Release|Win32.ActiveCfg = Windows 7 Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Release|Win32.Build.0 = Windows 7 Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Release|x64.ActiveCfg = Windows 7 Release|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 7 > Release|x64.Build.0 = Windows 7 Release|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Debug|Win32.ActiveCfg = Windows 8 Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Debug|Win32.Build.0 = Windows 8 Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Debug|x64.ActiveCfg = Windows 8 Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Debug|x64.Build.0 = Windows 8 Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Release|Win32.ActiveCfg = Windows 8 Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Release|Win32.Build.0 = Windows 8 Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Release|x64.ActiveCfg = Windows 8 Release|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows 8 > Release|x64.Build.0 = Windows 8 Release|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Debug|Win32.ActiveCfg = Windows Vista Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Debug|Win32.Build.0 = Windows Vista Debug|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Debug|x64.ActiveCfg = Windows Vista Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Debug|x64.Build.0 = Windows Vista Debug|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Release|Win32.ActiveCfg = Windows Vista Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Release|Win32.Build.0 = Windows Vista Release|Win32 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Release|x64.ActiveCfg = Windows Vista Release|x64 > + {D7411B2C-2C43-434D-9F56-E10A3D2F5BAD}.Windows Vista > Release|x64.Build.0 = Windows Vista Release|x64 > {EF236371-3145-41B1-99C9-82B33E353F17}.Windows 7 > Debug|Win32.ActiveCfg = Windows 7 Debug|Win32 > {EF236371-3145-41B1-99C9-82B33E353F17}.Windows 7 > Debug|Win32.Build.0 = Windows 7 Debug|Win32 > {EF236371-3145-41B1-99C9-82B33E353F17}.Windows 7 > Debug|x64.ActiveCfg = Windows 7 Debug|x64 > -- > 1.9.4.msysgit.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 |