From: Ben Chalmers Date: Fri, 5 Jul 2013 13:48:20 +0000 (+0100) Subject: Initial commit of fully open xeniface code X-Git-Tag: 8.1.0-rc1~37 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=c649edc84f8546b6acb939d8ba2dee0628cf2506;p=pvdrivers%2Fwin%2Fxeniface.git Initial commit of fully open xeniface code Signed-off-by: Ben Chalmers --- diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..4c0c3d0 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,6 @@ +7.0.0 (2013-05-30): +* Initial public release + +7.1.0 (2013-07-08): +* New 'bottom layer' of code which can be open sourced. +* Upped version number to reflect build number reset diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..bfa325c --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,12 @@ +To install the XenServer Interface Device Driver onto a XenServer Windows +guest VM: + +* Copy xeniface.sys and xeniface.inf onto the guest VM +* Install xenbus.sys on the guest VM +* Copy dpinst.exe from the Windows driver kit into the same folder as + xeniface.sys and xeniface.inf on the guest vm, ensuring the version + of dpinst.exe matches the architecture of the verison of Windows + installed on your VM +* As administrator, run dpinst.exe on the guest vm +* If any warnings arise about unknown certificates, accept them + diff --git a/MAINTAINERS b/MAINTAINERS new file mode 100644 index 0000000..4009d48 --- /dev/null +++ b/MAINTAINERS @@ -0,0 +1,40 @@ +List of maintainers and how to submit changes +============================================= + +This is an early public release of the XenServer XenIface driver. + +At the moment we are working hard on improving this early release, to make +it easier to build and install and test on your own systems. As such things +are in a state of flux, and we may well find it difficult to take submissions. + +We hope things will have improved by January 2014 + +If you do wish to submit code, we recommend reaching out to the maintainers +first, who will attempt to steer you in the right direction. + +We also request you follow these guidelines: + +1. All submissions must be made under the terms of the "Developer's Certificate + of Origin" (DC) and should include a Signed-off-by: line. + +2. All Submissions should use Unix line endings for consitency with the rest of + the XenServer project + +3. Each patch should include a descriptive commit comment that helps understand + why the patch is necessary and why it works. This will be used both for + initial review and for new people to understand how the code works later + +4. Make sure you have the right to submit any changes you make. If you do + changes at work you may find your employer owns the patches instead of + you. + + +Maintainers List +---------------- + +* Ben Chalmers + +* Paul Durrant + +* Owen Smith + diff --git a/README.md b/README.md new file mode 100644 index 0000000..6c4a1d8 --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +XenIface - The XenServer Interface Device Driver +========================================== + +XenIface is a device driver which provides userlevel applications WMI and Ioctl +read and write access to information provided to the guest domain by +xenstore and xapi + +Quick Start +=========== + +Prerequisites to build +---------------------- + +* Visual Studio 2012 or later +* Windows Driver Kit 8 or later +* Python 3 or later + +Environment variables used in building driver +----------------------------- + +MAJOR\_VERSION Major version number + +MINOR\_VERSION Minor version number + +MICRO\_VERSION Micro version number + +BUILD\_NUMBER Build number + +SYMBOL\_SERVER location of a writable symbol server directory + +KIT location of the Windows driver kit + +PROCESSOR\_ARCHITECTURE x86 or x64 + +VS location of visual studio + +Commands to build +----------------- + + git clone http://github.com/xenserver/win-xeniface + cd win-xeniface + .\\build.py [checked | free] + + +Device tree diagram +------------------- + + XenIface + | + XenBus + | + PCI Bus + +See Also +======== + +win-xeniface\WmiDocumentation.txt for documentation of the WMI interface + diff --git a/build.py b/build.py index 81b6a8a..5a850f4 100644 --- a/build.py +++ b/build.py @@ -265,7 +265,7 @@ def archive(filename, files, tgz=False): if __name__ == '__main__': os.environ['MAJOR_VERSION'] = '7' - os.environ['MINOR_VERSION'] = '0' + os.environ['MINOR_VERSION'] = '1' os.environ['MICRO_VERSION'] = '0' if 'BUILD_NUMBER' not in os.environ.keys(): @@ -290,6 +290,6 @@ if __name__ == '__main__': - listfile = callfnout(['hg','manifest']) + listfile = callfnout(['git','ls-tree', '-r', '--name-only', 'HEAD']) archive('xeniface\\source.tgz', listfile.splitlines(), tgz=True) archive('xeniface.tar', ['xeniface', 'revision']) diff --git a/include/util.h b/include/util.h new file mode 100644 index 0000000..723123b --- /dev/null +++ b/include/util.h @@ -0,0 +1,279 @@ +/* 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 + +#include "assert.h" + +#define P2ROUNDUP(_x, _a) \ + (-(-(_x) & -(_a))) + +static FORCEINLINE LONG +__ffs( + IN unsigned long long mask + ) +{ + unsigned char *array = (unsigned char *)&mask; + unsigned int byte; + unsigned int bit; + unsigned char val; + + val = 0; + + byte = 0; + while (byte < 8) { + val = array[byte]; + + if (val != 0) + break; + + byte++; + } + if (byte == 8) + return -1; + + bit = 0; + while (bit < 8) { + if (val & 0x01) + break; + + val >>= 1; + bit++; + } + + return (byte * 8) + bit; +} + +#define __ffu(_mask) \ + __ffs(~(_mask)) + +static FORCEINLINE LONG +__InterlockedAdd( + IN LONG *Value, + IN LONG Delta + ) +{ + LONG New; + LONG Old; + + do { + Old = *Value; + New = Old + Delta; + } while (InterlockedCompareExchange(Value, New, Old) != Old); + + return New; +} + +static FORCEINLINE LONG +__InterlockedSubtract( + IN LONG *Value, + IN LONG Delta + ) +{ + LONG New; + LONG Old; + + do { + Old = *Value; + New = Old - Delta; + } while (InterlockedCompareExchange(Value, New, Old) != Old); + + return New; +} + +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 SIZE_T Length, + IN ULONG Tag + ) +{ + PUCHAR Buffer; + PNON_PAGED_BUFFER_HEADER Header; + PNON_PAGED_BUFFER_TRAILER Trailer; + + ASSERT(Length != 0); + + Buffer = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, + sizeof (NON_PAGED_BUFFER_HEADER) + + Length + + sizeof (NON_PAGED_BUFFER_TRAILER), + Tag); + if (Buffer == NULL) + 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; + + ASSERT(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 +__AllocatePage( + VOID + ) +{ + PHYSICAL_ADDRESS LowAddress; + PHYSICAL_ADDRESS HighAddress; + LARGE_INTEGER SkipBytes; + SIZE_T TotalBytes; + PMDL Mdl; + PUCHAR MdlMappedSystemVa; + NTSTATUS status; + + LowAddress.QuadPart = 0ull; + HighAddress.QuadPart = ~0ull; + SkipBytes.QuadPart = 0ull; + TotalBytes = (SIZE_T)PAGE_SIZE; + + Mdl = MmAllocatePagesForMdlEx(LowAddress, + HighAddress, + SkipBytes, + TotalBytes, + MmCached, + 0); + + status = STATUS_NO_MEMORY; + if (Mdl == NULL) + goto fail1; + + ASSERT((Mdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | + MDL_PARTIAL_HAS_BEEN_MAPPED | + MDL_PARTIAL | + MDL_PARENT_MAPPED_SYSTEM_VA | + MDL_SOURCE_IS_NONPAGED_POOL | + MDL_IO_SPACE)) == 0); + + MdlMappedSystemVa = MmMapLockedPagesSpecifyCache(Mdl, + KernelMode, + MmCached, + NULL, + FALSE, + NormalPagePriority); + + status = STATUS_UNSUCCESSFUL; + if (MdlMappedSystemVa == NULL) + goto fail2; + + ASSERT3P(MdlMappedSystemVa, ==, Mdl->MappedSystemVa); + + RtlZeroMemory(MdlMappedSystemVa, PAGE_SIZE); + + return Mdl; + +fail2: + Error("fail2\n"); + + MmFreePagesFromMdl(Mdl); + ExFreePool(Mdl); + +fail1: + Error("fail1 (%08x)\n", status); + + return NULL; +} + +static FORCEINLINE VOID +__FreePage( + IN PMDL Mdl + ) +{ + PUCHAR MdlMappedSystemVa; + + ASSERT(Mdl->MdlFlags & MDL_MAPPED_TO_SYSTEM_VA); + MdlMappedSystemVa = Mdl->MappedSystemVa; + + RtlFillMemory(MdlMappedSystemVa, PAGE_SIZE, 0xAA); + + MmUnmapLockedPages(MdlMappedSystemVa, Mdl); + + MmFreePagesFromMdl(Mdl); +} + +#endif // _UTIL_H diff --git a/include/version.h b/include/version.h deleted file mode 100644 index 521b86f..0000000 --- a/include/version.h +++ /dev/null @@ -1,50 +0,0 @@ -/* 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 MAJOR_VERSION 7 -#define MAJOR_VERSION_STR "7" - -#define MINOR_VERSION 0 -#define MINOR_VERSION_STR "0" - -#define MICRO_VERSION 0 -#define MICRO_VERSION_STR "0" - -#define BUILD_NUMBER 0 -#define BUILD_NUMBER_STR "0" - -#define YEAR 2013 -#define YEAR_STR "2013" -#define MONTH 3 -#define MONTH_STR "3" -#define DAY 25 -#define DAY_STR "25" diff --git a/kdfiles.py b/kdfiles.py new file mode 100644 index 0000000..27fd5bd --- /dev/null +++ b/kdfiles.py @@ -0,0 +1,26 @@ +#!python -u + +import os, sys +import subprocess +import glob +from pprint import pprint + +def regenerate_kdfiles(filename, arch, pkg, source): + cwd = os.getcwd() + file = open(filename, 'w') + os.chdir(pkg + '/' + arch) + drivers = glob.glob('*.sys') + pprint(drivers) + for driver in drivers: + file.write("map\n") + file.write('\SystemRoot\System32\drivers\\' + driver + '\n') + file.write(source + '\\' + pkg + '\\' + arch + '\\' + driver + '\n') + file.write('\n') + os.chdir(cwd) + file.close() + +if __name__ == '__main__': + pkg = 'xeniface' + source = os.getcwd() + regenerate_kdfiles('kdfiles32.txt', 'x86', pkg, source) + regenerate_kdfiles('kdfiles64.txt', 'x64', pkg, source) diff --git a/proj/package/package.vcxproj.user b/proj/package/package.vcxproj.user new file mode 100644 index 0000000..c0fb6de --- /dev/null +++ b/proj/package/package.vcxproj.user @@ -0,0 +1,8 @@ + + + + ProductionSign + CN="Citrix Systems, Inc.", OU=Digital ID Class 3 - Microsoft Software Validation v2, O="Citrix Systems, Inc.", L=Santa Clara, S=California, C=US | 9505C081954CC0A3E8B904458ACACD72EABD98B5 + http://timestamp.verisign.com/scripts/timstamp.dll + + \ No newline at end of file diff --git a/proj/xeniface/xeniface.vcxproj b/proj/xeniface/xeniface.vcxproj index f4a29ed..bf91448 100644 --- a/proj/xeniface/xeniface.vcxproj +++ b/proj/xeniface/xeniface.vcxproj @@ -129,7 +129,6 @@ - @@ -183,18 +182,19 @@ - + - - + + + - $(IntDir)/wmi.bmf + $(IntDir)/wmi.bmf @@ -211,8 +211,20 @@ + + + + + + + + + + + + + - diff --git a/proj/xeniface/xeniface.vcxproj.user b/proj/xeniface/xeniface.vcxproj.user new file mode 100644 index 0000000..c0fb6de --- /dev/null +++ b/proj/xeniface/xeniface.vcxproj.user @@ -0,0 +1,8 @@ + + + + ProductionSign + CN="Citrix Systems, Inc.", OU=Digital ID Class 3 - Microsoft Software Validation v2, O="Citrix Systems, Inc.", L=Santa Clara, S=California, C=US | 9505C081954CC0A3E8B904458ACACD72EABD98B5 + http://timestamp.verisign.com/scripts/timstamp.dll + + \ No newline at end of file diff --git a/src/xeniface.inf b/src/xeniface.inf index 92eb3bb..ff77ab7 100644 --- a/src/xeniface.inf +++ b/src/xeniface.inf @@ -1,87 +1,87 @@ -; 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. - -[Version] -Signature="$WINDOWS NT$" -Class=System -ClassGUID={4d36e97d-e325-11ce-bfc1-08002be10318} -Provider=%Citrix% -DriverVer=09/07/2011,6.0.0.0 -CatalogFile=xeniface.cat - -[DestinationDirs] -DefaultDestDir = 12 - -;***************************************** -; Xeniface Device Install Section -;***************************************** - -[Manufacturer] -%Citrix%=Citrix,NT$ARCH$ - -[Citrix.NT$ARCH$] -; DisplayName Section DeviceId -; ----------- ------- -------- -%XenIfaceDevice.DeviceDesc%=XenIface_Device, XENBUS\CLASS_IFACE&REV_02 - -[XenIface_Device.NT$ARCH$] -CopyFiles=XenIface_Device.NT.Copy - -[XenIFace_Device.NT.Copy] -xeniface.sys - -;-------------- Service installation - -[Xeniface_Device.NT$ARCH$.Services] -AddService = xeniface, %SPSVCINST_ASSOCSERVICE%, xeniface_Service_Inst - -[xeniface_Service_Inst] -DisplayName = %xeniface.SVCDESC% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 1 ; SERVICE_ERROR_NORMAL -ServiceBinary = %12%\xeniface.sys -LoadOrderGroup = Extended Base - - -[SourceDisksNames] -1 = %DiskId1%,,,"" - -[SourceDisksFiles] -xeniface.sys = 1,, - -[Strings] -SPSVCINST_ASSOCSERVICE= 0x00000002 -Citrix= "Citrix Systems, Inc." -ClassName = "XenIface" -DiskId1 = "Citrix Tools for Virtual Machines" -XenIfaceDevice.DeviceDesc = "Citrix Xen Interface" -xeniface.SVCDESC = "Citrix Xen Interface Device Driver" - +; 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. + +[Version] +Signature="$WINDOWS NT$" +Class=System +ClassGUID={4d36e97d-e325-11ce-bfc1-08002be10318} +Provider=%Citrix% +DriverVer=09/07/2011,6.0.0.0 +CatalogFile=xeniface.cat + +[DestinationDirs] +DefaultDestDir = 12 + +;***************************************** +; Xeniface Device Install Section +;***************************************** + +[Manufacturer] +%Citrix%=Citrix,NT$ARCH$ + +[Citrix.NT$ARCH$] +; DisplayName Section DeviceId +; ----------- ------- -------- +%XenIfaceDevice.DeviceDesc%=XenIface_Device, XENBUS\CLASS_IFACE&REV_02 + +[XenIface_Device.NT$ARCH$] +CopyFiles=XenIface_Device.NT.Copy + +[XenIFace_Device.NT.Copy] +xeniface.sys + +;-------------- Service installation + +[Xeniface_Device.NT$ARCH$.Services] +AddService = xeniface, %SPSVCINST_ASSOCSERVICE%, xeniface_Service_Inst + +[xeniface_Service_Inst] +DisplayName = %xeniface.SVCDESC% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %12%\xeniface.sys +LoadOrderGroup = Extended Base + + +[SourceDisksNames] +1 = %DiskId1%,,,"" + +[SourceDisksFiles] +xeniface.sys = 1,, + +[Strings] +SPSVCINST_ASSOCSERVICE= 0x00000002 +Citrix= "Citrix Systems, Inc." +ClassName = "XenIface" +DiskId1 = "Citrix Tools for Virtual Machines" +XenIfaceDevice.DeviceDesc = "Citrix Xen Interface" +xeniface.SVCDESC = "Citrix Xen Interface Device Driver" + diff --git a/src/xeniface/assert.h b/src/xeniface/assert.h new file mode 100644 index 0000000..89bec5f --- /dev/null +++ b/src/xeniface/assert.h @@ -0,0 +1,174 @@ +/* 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 _XENIFACE_ASSERT_H +#define _XENIFACE_ASSERT_H + +#include + +#include "log.h" + +static FORCEINLINE VOID +__BugCheck( + IN ULONG Code, + IN ULONG_PTR Parameter1, + IN ULONG_PTR Parameter2, + IN ULONG_PTR Parameter3, + IN 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_ON(_EXP) \ + if (_EXP) BUG(#_EXP) + +#if DBG + +#define __NT_ASSERT(_EXP) \ + ((!(_EXP)) ? \ + (Error("ASSERTION FAILED: " #_EXP "\n"), \ + __annotation(L"Debug", L"AssertFail", L#_EXP), \ + DbgRaiseAssertionFailure(), FALSE) : \ + TRUE) + +#define __ASSERT(_EXP) __NT_ASSERT(_EXP) + +#else // DBG + +#define __ASSERT(_EXP) BUG_ON(!(_EXP)) + +#endif // DBG + +#undef ASSERT + +#define ASSERT(_EXP) \ + do { \ + __ASSERT(_EXP); \ + __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) + +#ifndef TEST_MEMORY +#define TEST_MEMORY DBG +#endif + +#if TEST_MEMORY + +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 // _XENIFACE_ASSERT_H + diff --git a/src/xeniface/driver.c b/src/xeniface/driver.c new file mode 100644 index 0000000..281ebdf --- /dev/null +++ b/src/xeniface/driver.c @@ -0,0 +1,193 @@ +/* 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 +//#include +#include + +#include "fdo.h" +#include "driver.h" + +#include "assert.h" +#include "wmi.h" +extern PULONG InitSafeBootMode; + +PDRIVER_OBJECT DriverObject; + +DRIVER_UNLOAD DriverUnload; + +XENIFACE_PARAMETERS DriverParameters; + +VOID +DriverUnload( + IN PDRIVER_OBJECT _DriverObject + ) +{ + ASSERT3P(_DriverObject, ==, DriverObject); + + Trace("====>\n"); + + if (*InitSafeBootMode > 0) + goto done; + + + if (DriverParameters.RegistryPath.Buffer != NULL) { + ExFreePool(DriverParameters.RegistryPath.Buffer); + } + +done: + DriverObject = NULL; + + Trace("<====\n"); +} + +DRIVER_ADD_DEVICE AddDevice; + +NTSTATUS +AddDevice( + IN PDRIVER_OBJECT _DriverObject, + IN PDEVICE_OBJECT DeviceObject + ) +{ + NTSTATUS status; + + ASSERT3P(_DriverObject, ==, DriverObject); + + status = FdoCreate(DeviceObject); + if (!NT_SUCCESS(status)) + goto fail1; + + // prefast stupidity + ASSERT(!(DeviceObject->Flags & DO_DEVICE_INITIALIZING)); + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +DRIVER_DISPATCH Dispatch; + +NTSTATUS +Dispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) +{ + PXENIFACE_DX Dx; + NTSTATUS status; + + Dx = (PXENIFACE_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 FUNCTION_DEVICE_OBJECT: { + PXENIFACE_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; + NTSTATUS status = STATUS_UNSUCCESSFUL; + ASSERT3P(DriverObject, ==, NULL); + + ExInitializeDriverRuntime(DrvRtPoolNxOptIn); + + Trace("====>\n"); + + Info("%s (%s)\n", + MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR, + DAY_STR "/" MONTH_STR "/" YEAR_STR); + + DriverParameters.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL); + DriverParameters.RegistryPath.Length = RegistryPath->Length; + DriverParameters.RegistryPath.Buffer = ExAllocatePoolWithTag (PagedPool, + DriverParameters.RegistryPath.MaximumLength, + XENIFACE_POOL_TAG); + if (NULL == DriverParameters.RegistryPath.Buffer) { + status = STATUS_INSUFFICIENT_RESOURCES; + goto fail1; + } + RtlCopyUnicodeString(&DriverParameters.RegistryPath, RegistryPath); + + + DriverObject = _DriverObject; + DriverObject->DriverUnload = DriverUnload; + + if (*InitSafeBootMode > 0) + goto done; + + 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; +fail1: + Error("fail1 (%08x)\n", status); + return status; +} diff --git a/src/xeniface/driver.h b/src/xeniface/driver.h new file mode 100644 index 0000000..93ac645 --- /dev/null +++ b/src/xeniface/driver.h @@ -0,0 +1,81 @@ +/* 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 _XENIFACE_DRIVER_H +#define _XENIFACE_DRIVER_H + + + +#include "fdo.h" +#include "types.h" +#include "thread.h" +#include "mutex.h" +#define NTSTRSAFE_LIB +#include + +#pragma warning(disable:4100 4057) + +#include +#include +extern PDRIVER_OBJECT DriverObject; + + +#define MAX_DEVICE_ID_LEN 200 + +typedef struct _XENIFACE_PARAMETERS { + UNICODE_STRING RegistryPath; + +} XENIFACE_PARAMETERS, *PXENIFACE_PARAMETERS; + +#define XENIFACE_POOL_TAG (ULONG) 'XIfc' + +extern XENIFACE_PARAMETERS DriverParameters; + +typedef struct _XENIFACE_DX { + PDEVICE_OBJECT DeviceObject; + DEVICE_OBJECT_TYPE Type; + + DEVICE_PNP_STATE DevicePnpState; + DEVICE_PNP_STATE PreviousDevicePnpState; + + SYSTEM_POWER_STATE SystemPowerState; + DEVICE_POWER_STATE DevicePowerState; + + CHAR Name[MAX_DEVICE_ID_LEN]; + + LIST_ENTRY ListEntry; + + struct _XENIFACE_FDO *Fdo; + +} XENIFACE_DX, *PXENIFACE_DX; + + +#endif // _XENIFACE_DRIVER_H diff --git a/src/xeniface/fdo.c b/src/xeniface/fdo.c new file mode 100644 index 0000000..8c103fa --- /dev/null +++ b/src/xeniface/fdo.c @@ -0,0 +1,2557 @@ +/* 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 +#include +#include +#include + +#include + +#include + + +#include "driver.h" +#include "fdo.h" +#include "thread.h" +#include "mutex.h" +#include "log.h" +#include "assert.h" +#include "util.h" +#include "names.h" +#include "ioctls.h" +#include "wmi.h" +#include "xeniface_ioctls.h" + +#define FDO_POOL 'ODF' + +#define MAXNAMELEN 128 + + +static void +FdoInitialiseXSRegistryEntries( + IN PXENIFACE_FDO Fdo + ) +{ + OBJECT_ATTRIBUTES Attributes; + HANDLE RegHandle; + UNICODE_STRING UnicodeValueName; + UNICODE_STRING UnicodeValue; + ANSI_STRING AnsiValue; + char *value; + NTSTATUS status; + NT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + status = STORE(Read, Fdo->StoreInterface, NULL, NULL, "/mh/boot-time/management-mac-address", &value); + if (!NT_SUCCESS(status)){ + XenIfaceDebugPrint(ERROR, "no such xenstore key\n"); + goto failXS; + } + + InitializeObjectAttributes(&Attributes, &DriverParameters.RegistryPath, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL); + + status = ZwOpenKey(&RegHandle, KEY_WRITE, &Attributes); + + if (!NT_SUCCESS(status)) { + XenIfaceDebugPrint(ERROR, "no such registry key %s\n", DriverParameters.RegistryPath); + goto failReg; + } + + RtlInitUnicodeString(&UnicodeValueName, L"MgmtMacAddr"); + RtlInitUnicodeString(&UnicodeValue, NULL); + RtlInitAnsiString(&AnsiValue, value); + + XenIfaceDebugPrint(ERROR, "About to convert unicode string\n"); + status = RtlAnsiStringToUnicodeString(&UnicodeValue, &AnsiValue, TRUE); + if (!NT_SUCCESS(status)) { + XenIfaceDebugPrint(ERROR, "Can't convert string\n"); + goto failReg; + } + + XenIfaceDebugPrint(ERROR, "About to write unicode string\n"); + status = ZwSetValueKey(RegHandle, &UnicodeValueName, 0, REG_SZ, UnicodeValue.Buffer, UnicodeValue.Length+sizeof(WCHAR)); + if (!NT_SUCCESS(status)) { + XenIfaceDebugPrint(ERROR, "Can't write key\n"); + goto failWrite; + } + + ZwClose(RegHandle); + + RtlFreeUnicodeString(&UnicodeValue); + STORE(Free, Fdo->StoreInterface, value); + + return; + +failWrite: + + XenIfaceDebugPrint(ERROR, "Fail : Write\n"); + ZwClose(RegHandle); + RtlFreeUnicodeString(&UnicodeValue); + +failReg: + + XenIfaceDebugPrint(ERROR, "Fail : Reg\n"); + STORE(Free, Fdo->StoreInterface, value); +failXS: + XenIfaceDebugPrint(ERROR, "Failed to initialise registry (%08x)\n", status); + return; +} + + +#define REGISTRY_WRITE_EVENT 0 +#define REGISTRY_THREAD_END_EVENT 1 +#define REGISTRY_EVENTS 2 + +static NTSTATUS FdoRegistryThreadHandler(IN PXENIFACE_THREAD Self, + IN PVOID StartContext) { + KEVENT* threadevents[REGISTRY_EVENTS]; + PXENIFACE_FDO Fdo = (PXENIFACE_FDO)StartContext; + NTSTATUS status; + + PKEVENT Event; + + Event = ThreadGetEvent(Self); + + threadevents[REGISTRY_WRITE_EVENT] = &Fdo->registryWriteEvent; + threadevents[REGISTRY_THREAD_END_EVENT] = Event; + + for(;;) { + + status = KeWaitForMultipleObjects(REGISTRY_EVENTS, (PVOID *)threadevents, WaitAny, Executive, KernelMode, TRUE, NULL, NULL); + if ((status>=STATUS_WAIT_0) && (status < STATUS_WAIT_0+REGISTRY_EVENTS)) { + if (status == STATUS_WAIT_0+REGISTRY_WRITE_EVENT) { + if (Fdo->StoreInterface) { + XenIfaceDebugPrint(ERROR,"WriteRegistry\n"); + FdoInitialiseXSRegistryEntries(Fdo); + KeClearEvent(threadevents[REGISTRY_WRITE_EVENT]); + } + } + if (status == STATUS_WAIT_0+REGISTRY_THREAD_END_EVENT) { + if (ThreadIsAlerted(Self)) + return STATUS_SUCCESS; + KeClearEvent(threadevents[REGISTRY_THREAD_END_EVENT]); + } + + } + else if (!NT_SUCCESS(status)) { + XenIfaceDebugPrint(ERROR, "Registry handler thread failed %x\n", status); + return status; + } + } + +} + + + +static FORCEINLINE PVOID +__FdoAllocate( + IN ULONG Length + ) +{ + return __AllocateNonPagedPoolWithTag(Length, FDO_POOL); +} + +static FORCEINLINE VOID +__FdoFree( + IN PVOID Buffer + ) +{ + __FreePoolWithTag(Buffer, FDO_POOL); +} + +static FORCEINLINE VOID +__FdoSetDevicePnpState( + IN PXENIFACE_FDO Fdo, + IN DEVICE_PNP_STATE State + ) +{ + PXENIFACE_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 PXENIFACE_FDO Fdo, + IN DEVICE_PNP_STATE State + ) +{ + PXENIFACE_DX Dx = Fdo->Dx; + + if (Dx->DevicePnpState == State) + Dx->DevicePnpState = Dx->PreviousDevicePnpState; +} + +static FORCEINLINE DEVICE_PNP_STATE +__FdoGetDevicePnpState( + IN PXENIFACE_FDO Fdo + ) +{ + PXENIFACE_DX Dx = Fdo->Dx; + + return Dx->DevicePnpState; +} + +static FORCEINLINE VOID +__FdoSetDevicePowerState( + IN PXENIFACE_FDO Fdo, + IN DEVICE_POWER_STATE State + ) +{ + PXENIFACE_DX Dx = Fdo->Dx; + + Dx->DevicePowerState = State; +} + +static FORCEINLINE DEVICE_POWER_STATE +__FdoGetDevicePowerState( + IN PXENIFACE_FDO Fdo + ) +{ + PXENIFACE_DX Dx = Fdo->Dx; + + return Dx->DevicePowerState; +} + +static FORCEINLINE VOID +__FdoSetSystemPowerState( + IN PXENIFACE_FDO Fdo, + IN SYSTEM_POWER_STATE State + ) +{ + PXENIFACE_DX Dx = Fdo->Dx; + + Dx->SystemPowerState = State; +} + +static FORCEINLINE SYSTEM_POWER_STATE +__FdoGetSystemPowerState( + IN PXENIFACE_FDO Fdo + ) +{ + PXENIFACE_DX Dx = Fdo->Dx; + + return Dx->SystemPowerState; +} + +static FORCEINLINE PDEVICE_OBJECT +__FdoGetPhysicalDeviceObject( + IN PXENIFACE_FDO Fdo + ) +{ + return Fdo->PhysicalDeviceObject; +} + +PDEVICE_OBJECT +FdoGetPhysicalDeviceObject( + IN PXENIFACE_FDO Fdo + ) +{ + return __FdoGetPhysicalDeviceObject(Fdo); +} + +static FORCEINLINE NTSTATUS +__FdoSetName( + IN PXENIFACE_FDO Fdo, + IN PWCHAR Name + ) +{ + PXENIFACE_DX Dx = Fdo->Dx; + UNICODE_STRING Unicode; + ANSI_STRING Ansi; + ULONG Index; + NTSTATUS status; + + RtlInitUnicodeString(&Unicode, Name); + + Ansi.Buffer = Dx->Name; + Ansi.MaximumLength = sizeof (Dx->Name); + Ansi.Length = 0; + + status = RtlUnicodeStringToAnsiString(&Ansi, &Unicode, FALSE); + if (!NT_SUCCESS(status)) + goto fail1; + + for (Index = 0; Dx->Name[Index] != '\0'; Index++) { + if (!isalnum((UCHAR)Dx->Name[Index])) + Dx->Name[Index] = '_'; + } + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static FORCEINLINE PCHAR +__FdoGetName( + IN PXENIFACE_FDO Fdo + ) +{ + PXENIFACE_DX Dx = Fdo->Dx; + + return Dx->Name; +} + +PCHAR +FdoGetName( + IN PXENIFACE_FDO Fdo + ) +{ + return __FdoGetName(Fdo); +} + +__drv_functionClass(IO_COMPLETION_ROUTINE) +__drv_sameIRQL +static NTSTATUS +__FdoDelegateIrp( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) +{ + PKEVENT Event = (PKEVENT)Context; + + UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Irp); + + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + +NTSTATUS +FdoDelegateIrp( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + PDEVICE_OBJECT DeviceObject; + PIO_STACK_LOCATION StackLocation; + PIRP SubIrp; + KEVENT Event; + PIO_STACK_LOCATION SubStackLocation; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + StackLocation = IoGetCurrentIrpStackLocation(Irp); + + // Find the top of the FDO stack and hold a reference + DeviceObject = IoGetAttachedDeviceReference(Fdo->Dx->DeviceObject); + + // Get a new IRP for the FDO stack + SubIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE); + + status = STATUS_NO_MEMORY; + if (SubIrp == NULL) + goto done; + + // Copy in the information from the original IRP + SubStackLocation = IoGetNextIrpStackLocation(SubIrp); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + RtlCopyMemory(SubStackLocation, StackLocation, + FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine)); + SubStackLocation->Control = 0; + + IoSetCompletionRoutine(SubIrp, + __FdoDelegateIrp, + &Event, + TRUE, + TRUE, + TRUE); + + // Default completion status + SubIrp->IoStatus.Status = Irp->IoStatus.Status; + + status = IoCallDriver(DeviceObject, SubIrp); + if (status == STATUS_PENDING) { + (VOID) KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + status = SubIrp->IoStatus.Status; + } else { + ASSERT3U(status, ==, SubIrp->IoStatus.Status); + } + + IoFreeIrp(SubIrp); + +done: + ObDereferenceObject(DeviceObject); + + return status; +} + +__drv_functionClass(IO_COMPLETION_ROUTINE) +__drv_sameIRQL +static NTSTATUS +__FdoForwardIrpSynchronously( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp, + IN PVOID Context + ) +{ + PKEVENT Event = (PKEVENT)Context; + + UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Irp); + + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); + + return STATUS_MORE_PROCESSING_REQUIRED; +} + +static NTSTATUS +FdoForwardIrpSynchronously( + IN PXENIFACE_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); + } + + Trace("%08x\n", status); + + return status; +} + +static FORCEINLINE VOID +__FdoAcquireMutex( + IN PXENIFACE_FDO Fdo + ) +{ + AcquireMutex(&Fdo->Mutex); +} + +VOID +FdoAcquireMutex( + IN PXENIFACE_FDO Fdo + ) +{ + __FdoAcquireMutex(Fdo); +} + +static FORCEINLINE VOID +__FdoReleaseMutex( + IN PXENIFACE_FDO Fdo + ) +{ + ReleaseMutex(&Fdo->Mutex); +} + +VOID +FdoReleaseMutex( + IN PXENIFACE_FDO Fdo + ) +{ + __FdoReleaseMutex(Fdo); + + if (Fdo->References == 0) + FdoDestroy(Fdo); +} + + +static FORCEINLINE PANSI_STRING +__FdoMultiSzToUpcaseAnsi( + IN PCHAR Buffer + ) +{ + PANSI_STRING Ansi; + LONG Index; + LONG Count; + NTSTATUS status; + + Index = 0; + Count = 0; + for (;;) { + if (Buffer[Index] == '\0') { + Count++; + Index++; + + // Check for double NUL + if (Buffer[Index] == '\0') + break; + } else { + Buffer[Index] = (CHAR)toupper(Buffer[Index]); + Index++; + } + } + + Ansi = (PANSI_STRING)__FdoAllocate(sizeof (ANSI_STRING) * (Count + 1)); + + status = STATUS_NO_MEMORY; + if (Ansi == NULL) + goto fail1; + + for (Index = 0; Index < Count; Index++) { + ULONG Length; + + Length = (ULONG)strlen(Buffer); + Ansi[Index].MaximumLength = (USHORT)(Length + 1); + Ansi[Index].Buffer = (PCHAR)__FdoAllocate(Ansi[Index].MaximumLength); + + status = STATUS_NO_MEMORY; + if (Ansi[Index].Buffer == NULL) + goto fail2; + + RtlCopyMemory(Ansi[Index].Buffer, Buffer, Length); + Ansi[Index].Length = (USHORT)Length; + + Buffer += Length + 1; + } + + return Ansi; + +fail2: + Error("fail2\n"); + + while (--Index >= 0) + __FdoFree(Ansi[Index].Buffer); + + __FdoFree(Ansi); + +fail1: + Error("fail1 (%08x)\n", status); + + return NULL; +} + +static FORCEINLINE VOID +__FdoFreeAnsi( + IN PANSI_STRING Ansi + ) +{ + ULONG Index; + + for (Index = 0; Ansi[Index].Buffer != NULL; Index++) + __FdoFree(Ansi[Index].Buffer); + + __FdoFree(Ansi); +} + + +static DECLSPEC_NOINLINE VOID +FdoParseResources( + IN PXENIFACE_FDO Fdo, + IN PCM_RESOURCE_LIST RawResourceList, + IN PCM_RESOURCE_LIST TranslatedResourceList + ) +{ + PCM_PARTIAL_RESOURCE_LIST RawPartialList; + PCM_PARTIAL_RESOURCE_LIST TranslatedPartialList; + ULONG Index; + + ASSERT3U(RawResourceList->Count, ==, 1); + RawPartialList = &RawResourceList->List[0].PartialResourceList; + + ASSERT3U(RawPartialList->Version, ==, 1); + ASSERT3U(RawPartialList->Revision, ==, 1); + + ASSERT3U(TranslatedResourceList->Count, ==, 1); + TranslatedPartialList = &TranslatedResourceList->List[0].PartialResourceList; + + ASSERT3U(TranslatedPartialList->Version, ==, 1); + ASSERT3U(TranslatedPartialList->Revision, ==, 1); + + for (Index = 0; Index < TranslatedPartialList->Count; Index++) { + PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDescriptor; + PCM_PARTIAL_RESOURCE_DESCRIPTOR TranslatedPartialDescriptor; + + RawPartialDescriptor = &RawPartialList->PartialDescriptors[Index]; + TranslatedPartialDescriptor = &TranslatedPartialList->PartialDescriptors[Index]; + + switch (TranslatedPartialDescriptor->Type) { + case CmResourceTypeMemory: + Fdo->Resource[MEMORY_RESOURCE].Raw = *RawPartialDescriptor; + Fdo->Resource[MEMORY_RESOURCE].Translated = *TranslatedPartialDescriptor; + break; + + case CmResourceTypeInterrupt: + Fdo->Resource[INTERRUPT_RESOURCE].Raw = *RawPartialDescriptor; + Fdo->Resource[INTERRUPT_RESOURCE].Translated = *TranslatedPartialDescriptor; + break; + + default: + break; + } + } +} + + +PXENBUS_STORE_INTERFACE +FdoGetStoreInterface( + IN PXENIFACE_FDO Fdo + ) +{ + return Fdo->StoreInterface; +} + + +PXENBUS_SUSPEND_INTERFACE +FdoGetSuspendInterface( + IN PXENIFACE_FDO Fdo + ) +{ + return Fdo->SuspendInterface; +} + + +static FORCEINLINE NTSTATUS +__FdoD3ToD0( + IN PXENIFACE_FDO Fdo + ) +{ + POWER_STATE PowerState; + + Trace("====>\n"); + + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + ASSERT3U(__FdoGetDevicePowerState(Fdo), ==, PowerDeviceD3); + + __FdoSetDevicePowerState(Fdo, PowerDeviceD0); + + STORE(Acquire, Fdo->StoreInterface); + + PowerState.DeviceState = PowerDeviceD0; + PoSetPowerState(Fdo->Dx->DeviceObject, + DevicePowerState, + PowerState); + + Trace("<====\n"); + + return STATUS_SUCCESS; +} + +static FORCEINLINE VOID +__FdoD0ToD3( + IN PXENIFACE_FDO Fdo + ) +{ + POWER_STATE PowerState; + + Trace("====>\n"); + + ASSERT3U(KeGetCurrentIrql(), ==, DISPATCH_LEVEL); + ASSERT3U(__FdoGetDevicePowerState(Fdo), ==, PowerDeviceD0); + + PowerState.DeviceState = PowerDeviceD3; + PoSetPowerState(Fdo->Dx->DeviceObject, + DevicePowerState, + PowerState); + + __FdoSetDevicePowerState(Fdo, PowerDeviceD3); + + STORE(Release, Fdo->StoreInterface); + + Trace("<====\n"); +} + +static DECLSPEC_NOINLINE VOID +FdoSuspendCallbackLate( + IN PVOID Argument + ) +{ + PXENIFACE_FDO Fdo = (PXENIFACE_FDO) Argument; + NTSTATUS status; + + __FdoD0ToD3(Fdo); + + status = __FdoD3ToD0(Fdo); + ASSERT(NT_SUCCESS(status)); +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoD3ToD0( + IN PXENIFACE_FDO Fdo + ) +{ + KIRQL Irql; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + KeRaiseIrql(DISPATCH_LEVEL, &Irql); + + status = __FdoD3ToD0(Fdo); + if (!NT_SUCCESS(status)) + goto fail1; + + SUSPEND(Acquire, Fdo->SuspendInterface); + SHARED_INFO(Acquire, Fdo->SharedInfoInterface); + + Fdo->InterfacesAcquired = TRUE; + + status = SUSPEND(Register, + Fdo->SuspendInterface, + SUSPEND_CALLBACK_LATE, + FireSuspendEvent, + Fdo, + &Fdo->SuspendCallbackLate); + if (!NT_SUCCESS(status)) + goto fail2; + + KeLowerIrql(Irql); + + return STATUS_SUCCESS; + +fail2: + Error("fail2\n"); + SHARED_INFO(Release, Fdo->SharedInfoInterface); + SUSPEND(Release, Fdo->SuspendInterface); + + __FdoD0ToD3(Fdo); + +fail1: + Error("fail1 (%08x)\n", status); + + KeLowerIrql(Irql); + + return status; +} + +static DECLSPEC_NOINLINE VOID +FdoD0ToD3( + IN PXENIFACE_FDO Fdo + ) +{ + KIRQL Irql; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + KeRaiseIrql(DISPATCH_LEVEL, &Irql); + Fdo->InterfacesAcquired = FALSE; + SUSPEND(Deregister, + Fdo->SuspendInterface, + Fdo->SuspendCallbackLate); + Fdo->SuspendCallbackLate = NULL; + + SHARED_INFO(Release, Fdo->SharedInfoInterface); + SUSPEND(Release, Fdo->SuspendInterface); + + __FdoD0ToD3(Fdo); + + KeLowerIrql(Irql); +} + +static DECLSPEC_NOINLINE VOID +FdoS4ToS3( + IN PXENIFACE_FDO Fdo + ) +{ + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + ASSERT3U(__FdoGetSystemPowerState(Fdo), ==, PowerSystemHibernate); + + __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3); +} + +static DECLSPEC_NOINLINE VOID +FdoS3ToS4( + IN PXENIFACE_FDO Fdo + ) +{ + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + ASSERT3U(__FdoGetSystemPowerState(Fdo), ==, PowerSystemSleeping3); + + __FdoSetSystemPowerState(Fdo, PowerSystemHibernate); +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoStartDevice( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + PIO_STACK_LOCATION StackLocation; + NTSTATUS status; + + status = FdoForwardIrpSynchronously(Fdo, Irp); + if (!NT_SUCCESS(status)) + goto fail1; + + StackLocation = IoGetCurrentIrpStackLocation(Irp); + + FdoParseResources(Fdo, + StackLocation->Parameters.StartDevice.AllocatedResources, + StackLocation->Parameters.StartDevice.AllocatedResourcesTranslated); + + __FdoSetSystemPowerState(Fdo, PowerSystemHibernate); + FdoS4ToS3(Fdo); + __FdoSetSystemPowerState(Fdo, PowerSystemWorking); + + status = FdoD3ToD0(Fdo); + if (!NT_SUCCESS(status)) + goto fail3; + + status = IoSetDeviceInterfaceState(&Fdo->InterfaceName, TRUE); + if (!NT_SUCCESS(status)) + goto fail4; + + + if (__FdoGetDevicePnpState(Fdo) != Stopped) { + status = WmiInit(Fdo); + if (!NT_SUCCESS(status)) + goto fail5; + } + + __FdoSetDevicePnpState(Fdo, Started); + + + status = Irp->IoStatus.Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; + +fail5: + Error("fail5\n"); + IoSetDeviceInterfaceState(&Fdo->InterfaceName, FALSE); + +fail4: + Error("fail4\n"); + FdoD0ToD3(Fdo); + +fail3: + Error("fail3\n"); + + __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3); + FdoS3ToS4(Fdo); + __FdoSetSystemPowerState(Fdo, PowerSystemShutdown); + + + RtlZeroMemory(&Fdo->Resource, sizeof (FDO_RESOURCE) * RESOURCE_COUNT); + +fail1: + Error("fail1 (%08x)\n", status); + + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoQueryStopDevice( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + NTSTATUS status; + + __FdoSetDevicePnpState(Fdo, StopPending); + Irp->IoStatus.Status = STATUS_SUCCESS; + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoCancelStopDevice( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + NTSTATUS status; + + Irp->IoStatus.Status = STATUS_SUCCESS; + + __FdoRestoreDevicePnpState(Fdo, StopPending); + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoStopDevice( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + NTSTATUS status; + + FdoD0ToD3(Fdo); + + __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3); + FdoS3ToS4(Fdo); + __FdoSetSystemPowerState(Fdo, PowerSystemShutdown); + + + RtlZeroMemory(&Fdo->Resource, sizeof (FDO_RESOURCE) * RESOURCE_COUNT); + + __FdoSetDevicePnpState(Fdo, Stopped); + Irp->IoStatus.Status = STATUS_SUCCESS; + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoQueryRemoveDevice( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + NTSTATUS status; + + __FdoSetDevicePnpState(Fdo, RemovePending); + Irp->IoStatus.Status = STATUS_SUCCESS; + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoCancelRemoveDevice( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + NTSTATUS status; + + __FdoRestoreDevicePnpState(Fdo, RemovePending); + + Irp->IoStatus.Status = STATUS_SUCCESS; + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoSurpriseRemoval( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + NTSTATUS status; + + __FdoSetDevicePnpState(Fdo, SurpriseRemovePending); + + Irp->IoStatus.Status = STATUS_SUCCESS; + IoSetDeviceInterfaceState(&Fdo->InterfaceName, FALSE); + WmiFinalise(Fdo); + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoRemoveDevice( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + if (__FdoGetDevicePowerState(Fdo) != PowerDeviceD0) + goto done; + + FdoD0ToD3(Fdo); + + __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3); + FdoS3ToS4(Fdo); + __FdoSetSystemPowerState(Fdo, PowerSystemShutdown); + + RtlZeroMemory(&Fdo->Resource, sizeof (FDO_RESOURCE) * RESOURCE_COUNT); + +done: + __FdoSetDevicePnpState(Fdo, Deleted); + + Irp->IoStatus.Status = STATUS_SUCCESS; + IoSetDeviceInterfaceState(&Fdo->InterfaceName, FALSE); + WmiFinalise(Fdo); + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + __FdoAcquireMutex(Fdo); + ASSERT3U(Fdo->References, !=, 0); + --Fdo->References; + __FdoReleaseMutex(Fdo); + + if (Fdo->References == 0) + FdoDestroy(Fdo); + + return status; +} + + +static DECLSPEC_NOINLINE NTSTATUS +FdoQueryCapabilities( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + PIO_STACK_LOCATION StackLocation; + PDEVICE_CAPABILITIES Capabilities; + SYSTEM_POWER_STATE SystemPowerState; + NTSTATUS status; + + status = FdoForwardIrpSynchronously(Fdo, Irp); + if (!NT_SUCCESS(status)) + goto fail1; + + StackLocation = IoGetCurrentIrpStackLocation(Irp); + Capabilities = StackLocation->Parameters.DeviceCapabilities.Capabilities; + + Fdo->LowerDeviceCapabilities = *Capabilities; + + for (SystemPowerState = (SYSTEM_POWER_STATE)0; SystemPowerState < PowerSystemMaximum; SystemPowerState++) { + DEVICE_POWER_STATE DevicePowerState; + + DevicePowerState = Fdo->LowerDeviceCapabilities.DeviceState[SystemPowerState]; + Trace("%s -> %s\n", + PowerSystemStateName(SystemPowerState), + PowerDeviceStateName(DevicePowerState)); + } + + status = Irp->IoStatus.Status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; + +fail1: + Error("fail1 (%08x)\n", status); + + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoDeviceUsageNotification( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + PIO_STACK_LOCATION StackLocation; + DEVICE_USAGE_NOTIFICATION_TYPE Type; + BOOLEAN InPath; + BOOLEAN NotDisableable; + NTSTATUS status; + + StackLocation = IoGetCurrentIrpStackLocation(Irp); + Type = StackLocation->Parameters.UsageNotification.Type; + InPath = StackLocation->Parameters.UsageNotification.InPath; + + if (InPath) { + Trace("%s: ADDING %s\n", + __FdoGetName(Fdo), + DeviceUsageTypeName(Type)); + Fdo->Usage[Type]++; + } else { + ASSERT(Fdo->Usage[Type] != 0); + + Trace("%s: REMOVING %s\n", + __FdoGetName(Fdo), + DeviceUsageTypeName(Type)); + --Fdo->Usage[Type]; + } + + status = FdoForwardIrpSynchronously(Fdo, Irp); + if (!NT_SUCCESS(status)) + goto fail1; + + NotDisableable = FALSE; + for (Type = (DEVICE_USAGE_NOTIFICATION_TYPE)0; Type <= DeviceUsageTypeDumpFile; Type++) { + if (Fdo->Usage[Type] != 0) { + NotDisableable = TRUE; + break; + } + } + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + if (Fdo->NotDisableable != NotDisableable) { + Fdo->NotDisableable = NotDisableable; + + IoInvalidateDeviceState(__FdoGetPhysicalDeviceObject(Fdo)); + } + + return status; + +fail1: + Error("fail1 (%08x)\n", status); + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoQueryPnpDeviceState( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + ULONG_PTR State; + NTSTATUS status; + + if (Irp->IoStatus.Status == STATUS_SUCCESS) + State = Irp->IoStatus.Information; + else if (Irp->IoStatus.Status == STATUS_NOT_SUPPORTED) + State = 0; + else + goto done; + + if (Fdo->NotDisableable) { + Info("%s: not disableable\n", __FdoGetName(Fdo)); + State |= PNP_DEVICE_NOT_DISABLEABLE; + } + + Irp->IoStatus.Information = State; + Irp->IoStatus.Status = STATUS_SUCCESS; + +done: + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoDispatchPnp( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + PIO_STACK_LOCATION StackLocation; + UCHAR MinorFunction; + NTSTATUS status; + + StackLocation = IoGetCurrentIrpStackLocation(Irp); + MinorFunction = StackLocation->MinorFunction; + + Trace("====> (%02x:%s)\n", + MinorFunction, + PnpMinorFunctionName(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_CAPABILITIES: + status = FdoQueryCapabilities(Fdo, Irp); + break; + + case IRP_MN_DEVICE_USAGE_NOTIFICATION: + status = FdoDeviceUsageNotification(Fdo, Irp); + break; + + case IRP_MN_QUERY_PNP_DEVICE_STATE: + status = FdoQueryPnpDeviceState(Fdo, Irp); + break; + + default: + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + break; + } + + Trace("<==== (%02x:%s)(%08x)\n", + MinorFunction, + PnpMinorFunctionName(MinorFunction), + status); + + return status; +} + +static FORCEINLINE NTSTATUS +__FdoSetDevicePowerUp( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + PIO_STACK_LOCATION StackLocation; + DEVICE_POWER_STATE DeviceState; + NTSTATUS status; + + Trace("====>\n"); + + StackLocation = IoGetCurrentIrpStackLocation(Irp); + DeviceState = StackLocation->Parameters.Power.State.DeviceState; + + ASSERT3U(DeviceState, <, __FdoGetDevicePowerState(Fdo)); + + status = FdoForwardIrpSynchronously(Fdo, Irp); + if (!NT_SUCCESS(status)) + goto done; + + Info("%s -> %s\n", + PowerDeviceStateName(__FdoGetDevicePowerState(Fdo)), + PowerDeviceStateName(DeviceState)); + + ASSERT3U(DeviceState, ==, PowerDeviceD0); + status = FdoD3ToD0(Fdo); + ASSERT(NT_SUCCESS(status)); + +done: + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + Trace("<==== (%08x)\n", status); + return status; +} + +static FORCEINLINE NTSTATUS +__FdoSetDevicePowerDown( + IN PXENIFACE_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)); + + Info("%s -> %s\n", + PowerDeviceStateName(__FdoGetDevicePowerState(Fdo)), + PowerDeviceStateName(DeviceState)); + + ASSERT3U(DeviceState, ==, PowerDeviceD3); + + if (__FdoGetDevicePowerState(Fdo) == PowerDeviceD0) + FdoD0ToD3(Fdo); + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static FORCEINLINE NTSTATUS +__FdoSetDevicePower( + IN PXENIFACE_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)); + + ASSERT3U(PowerAction, <, PowerActionShutdown); + + if (DeviceState == __FdoGetDevicePowerState(Fdo)) { + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + 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; +} + +__drv_functionClass(REQUEST_POWER_COMPLETE) +__drv_sameIRQL +VOID +__FdoRequestSetDevicePower( + IN PDEVICE_OBJECT DeviceObject, + IN UCHAR MinorFunction, + IN POWER_STATE PowerState, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatus + ) +{ + PKEVENT Event = (PKEVENT)Context; + + UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(MinorFunction); + UNREFERENCED_PARAMETER(PowerState); + + ASSERT(NT_SUCCESS(IoStatus->Status)); + + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); +} + +static VOID +FdoRequestSetDevicePower( + IN PXENIFACE_FDO Fdo, + IN DEVICE_POWER_STATE DeviceState + ) +{ + POWER_STATE PowerState; + KEVENT Event; + NTSTATUS status; + + Trace("%s\n", PowerDeviceStateName(DeviceState)); + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + PowerState.DeviceState = DeviceState; + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + status = PoRequestPowerIrp(Fdo->LowerDeviceObject, + IRP_MN_SET_POWER, + PowerState, + __FdoRequestSetDevicePower, + &Event, + NULL); + ASSERT(NT_SUCCESS(status)); + + (VOID) KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); +} + +static FORCEINLINE NTSTATUS +__FdoSetSystemPowerUp( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + + PIO_STACK_LOCATION StackLocation; + SYSTEM_POWER_STATE SystemState; + DEVICE_POWER_STATE DeviceState; + 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; + + if (SystemState < PowerSystemHibernate && + __FdoGetSystemPowerState(Fdo) >= PowerSystemHibernate) + __FdoSetSystemPowerState(Fdo, PowerSystemHibernate); + FdoS4ToS3(Fdo); + + Info("%s -> %s\n", + PowerSystemStateName(__FdoGetSystemPowerState(Fdo)), + PowerSystemStateName(SystemState)); + + __FdoSetSystemPowerState(Fdo, SystemState); + + DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState]; + FdoRequestSetDevicePower(Fdo, DeviceState); + +done: + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; +} + +static FORCEINLINE NTSTATUS +__FdoSetSystemPowerDown( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + PIO_STACK_LOCATION StackLocation; + SYSTEM_POWER_STATE SystemState; + DEVICE_POWER_STATE DeviceState; + NTSTATUS status; + + StackLocation = IoGetCurrentIrpStackLocation(Irp); + SystemState = StackLocation->Parameters.Power.State.SystemState; + + ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo)); + + DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState]; + + FdoRequestSetDevicePower(Fdo, DeviceState); + + Info("%s -> %s\n", + PowerSystemStateName(__FdoGetSystemPowerState(Fdo)), + PowerSystemStateName(SystemState)); + + if (SystemState >= PowerSystemHibernate && + __FdoGetSystemPowerState(Fdo) < PowerSystemHibernate) { + __FdoSetSystemPowerState(Fdo, PowerSystemSleeping3); + FdoS3ToS4(Fdo); + } + + __FdoSetSystemPowerState(Fdo, SystemState); + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static FORCEINLINE NTSTATUS +__FdoSetSystemPower( + IN PXENIFACE_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)); + + ASSERT3U(PowerAction, <, PowerActionShutdown); + + if (SystemState == __FdoGetSystemPowerState(Fdo)) { + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + 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 PXENIFACE_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); + + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; +} + +static FORCEINLINE NTSTATUS +__FdoQueryDevicePowerDown( + IN PXENIFACE_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)); + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static FORCEINLINE NTSTATUS +__FdoQueryDevicePower( + IN PXENIFACE_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)); + + ASSERT3U(PowerAction, <, PowerActionShutdown); + + if (DeviceState == __FdoGetDevicePowerState(Fdo)) { + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + 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; +} + +__drv_functionClass(REQUEST_POWER_COMPLETE) +__drv_sameIRQL +VOID +__FdoRequestQueryDevicePower( + IN PDEVICE_OBJECT DeviceObject, + IN UCHAR MinorFunction, + IN POWER_STATE PowerState, + IN PVOID Context, + IN PIO_STATUS_BLOCK IoStatus + ) +{ + PKEVENT Event = (PKEVENT)Context; + + UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(MinorFunction); + UNREFERENCED_PARAMETER(PowerState); + + ASSERT(NT_SUCCESS(IoStatus->Status)); + + KeSetEvent(Event, IO_NO_INCREMENT, FALSE); +} + +static VOID +FdoRequestQueryDevicePower( + IN PXENIFACE_FDO Fdo, + IN DEVICE_POWER_STATE DeviceState + ) +{ + POWER_STATE PowerState; + KEVENT Event; + NTSTATUS status; + + Trace("%s\n", PowerDeviceStateName(DeviceState)); + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + PowerState.DeviceState = DeviceState; + KeInitializeEvent(&Event, NotificationEvent, FALSE); + + status = PoRequestPowerIrp(Fdo->LowerDeviceObject, + IRP_MN_QUERY_POWER, + PowerState, + __FdoRequestQueryDevicePower, + &Event, + NULL); + ASSERT(NT_SUCCESS(status)); + + (VOID) KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); +} + +static FORCEINLINE NTSTATUS +__FdoQuerySystemPowerUp( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + + PIO_STACK_LOCATION StackLocation; + SYSTEM_POWER_STATE SystemState; + DEVICE_POWER_STATE DeviceState; + 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; + + DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState]; + + FdoRequestQueryDevicePower(Fdo, DeviceState); + +done: + Irp->IoStatus.Status = status; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return status; +} + +static FORCEINLINE NTSTATUS +__FdoQuerySystemPowerDown( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + PIO_STACK_LOCATION StackLocation; + SYSTEM_POWER_STATE SystemState; + DEVICE_POWER_STATE DeviceState; + NTSTATUS status; + + StackLocation = IoGetCurrentIrpStackLocation(Irp); + SystemState = StackLocation->Parameters.Power.State.SystemState; + + ASSERT3U(SystemState, >, __FdoGetSystemPowerState(Fdo)); + + DeviceState = Fdo->LowerDeviceCapabilities.DeviceState[SystemState]; + + FdoRequestQueryDevicePower(Fdo, DeviceState); + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +static FORCEINLINE NTSTATUS +__FdoQuerySystemPower( + IN PXENIFACE_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)); + + ASSERT3U(PowerAction, <, PowerActionShutdown); + + if (SystemState == __FdoGetSystemPowerState(Fdo)) { + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + 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 PXENIFACE_THREAD Self, + IN PVOID Context + ) +{ + PXENIFACE_FDO Fdo = (PXENIFACE_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; + } + } + + return STATUS_SUCCESS; +} + +static NTSTATUS +FdoSystemPower( + IN PXENIFACE_THREAD Self, + IN PVOID Context + ) +{ + PXENIFACE_FDO Fdo = (PXENIFACE_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; + } + } + + return STATUS_SUCCESS; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoDispatchPower( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + PIO_STACK_LOCATION StackLocation; + UCHAR MinorFunction; + POWER_STATE_TYPE PowerType; + POWER_ACTION PowerAction; + NTSTATUS status; + + StackLocation = IoGetCurrentIrpStackLocation(Irp); + MinorFunction = StackLocation->MinorFunction; + + if (MinorFunction != IRP_MN_QUERY_POWER && + MinorFunction != IRP_MN_SET_POWER) { + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + goto done; + } + + PowerType = StackLocation->Parameters.Power.Type; + PowerAction = StackLocation->Parameters.Power.ShutdownType; + + if (PowerAction >= PowerActionShutdown) { + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + goto done; + } + + 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: + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + break; + } + +done: + return status; +} + +static DECLSPEC_NOINLINE NTSTATUS +FdoDispatchDefault( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ) +{ + NTSTATUS status; + + IoSkipCurrentIrpStackLocation(Irp); + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + + return status; +} + +NTSTATUS +FdoCreateFile ( + __in PXENIFACE_FDO fdoData, + __inout PIRP Irp + ) +{ + NTSTATUS status; + + PAGED_CODE(); + + + XenIfaceDebugPrint(TRACE, "Create \n"); + + if (Deleted == fdoData->Dx->DevicePnpState) + { + Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + return STATUS_NO_SUCH_DEVICE; + } + + + status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = status; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return status; +} + + +NTSTATUS +FdoClose ( + __in PXENIFACE_FDO fdoData, + __inout PIRP Irp + ) + +{ + + NTSTATUS status; + + PAGED_CODE(); + + XenIfaceDebugPrint(TRACE, "Close \n"); + + status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = status; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return status; +} + + +NTSTATUS +FdoReadWrite ( + __in PXENIFACE_FDO fdoData, + __inout PIRP Irp + ) + +{ + + NTSTATUS status; + + PAGED_CODE(); + + + XenIfaceDebugPrint(TRACE, "ReadWrite called\n"); + + status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = status; + IoCompleteRequest (Irp, IO_NO_INCREMENT); + + return status; +} + + + +NTSTATUS +FdoDispatch( + IN PXENIFACE_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; + + case IRP_MJ_DEVICE_CONTROL: + status = XenIFaceIoctl(Fdo, Irp); + break; + + case IRP_MJ_SYSTEM_CONTROL: + status = XenIfaceSystemControl(Fdo, Irp); + break; + + case IRP_MJ_READ: + case IRP_MJ_WRITE: + status = FdoReadWrite(Fdo, Irp); + break; + + case IRP_MJ_CREATE: + status = FdoCreateFile(Fdo, Irp); + break; + + case IRP_MJ_CLOSE: + status = FdoClose(Fdo, Irp); + break; + + default: + status = FdoDispatchDefault(Fdo, Irp); + break; + } + + return status; +} + + +static NTSTATUS +FdoQueryStoreInterface( + IN PXENIFACE_FDO Fdo + ) +{ + KEVENT Event; + IO_STATUS_BLOCK StatusBlock; + PIRP Irp; + PIO_STACK_LOCATION StackLocation; + INTERFACE Interface; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK)); + RtlZeroMemory(&Interface, sizeof(INTERFACE)); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, + Fdo->LowerDeviceObject, + NULL, + 0, + NULL, + &Event, + &StatusBlock); + + status = STATUS_UNSUCCESSFUL; + if (Irp == NULL) + goto fail1; + + StackLocation = IoGetNextIrpStackLocation(Irp); + StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE; + + StackLocation->Parameters.QueryInterface.InterfaceType = &GUID_STORE_INTERFACE; + StackLocation->Parameters.QueryInterface.Size = sizeof (INTERFACE); + StackLocation->Parameters.QueryInterface.Version = STORE_INTERFACE_VERSION; + StackLocation->Parameters.QueryInterface.Interface = &Interface; + + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + if (status == STATUS_PENDING) { + (VOID) KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + status = StatusBlock.Status; + } + + if (!NT_SUCCESS(status)) + goto fail2; + + status = STATUS_INVALID_PARAMETER; + if (Interface.Version != STORE_INTERFACE_VERSION) + goto fail3; + + Fdo->StoreInterface = (PXENBUS_STORE_INTERFACE)Interface.Context; + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + + +static NTSTATUS +FdoQuerySuspendInterface( + IN PXENIFACE_FDO Fdo + ) +{ + KEVENT Event; + IO_STATUS_BLOCK StatusBlock; + PIRP Irp; + PIO_STACK_LOCATION StackLocation; + INTERFACE Interface; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK)); + RtlZeroMemory(&Interface, sizeof(INTERFACE)); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, + Fdo->LowerDeviceObject, + NULL, + 0, + NULL, + &Event, + &StatusBlock); + + status = STATUS_UNSUCCESSFUL; + if (Irp == NULL) + goto fail1; + + StackLocation = IoGetNextIrpStackLocation(Irp); + StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE; + + StackLocation->Parameters.QueryInterface.InterfaceType = &GUID_SUSPEND_INTERFACE; + StackLocation->Parameters.QueryInterface.Size = sizeof (INTERFACE); + StackLocation->Parameters.QueryInterface.Version = SUSPEND_INTERFACE_VERSION; + StackLocation->Parameters.QueryInterface.Interface = &Interface; + + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + if (status == STATUS_PENDING) { + (VOID) KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + status = StatusBlock.Status; + } + + if (!NT_SUCCESS(status)) + goto fail2; + + status = STATUS_INVALID_PARAMETER; + if (Interface.Version != SUSPEND_INTERFACE_VERSION) + goto fail3; + + Fdo->SuspendInterface = (PXENBUS_SUSPEND_INTERFACE)Interface.Context; + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +static NTSTATUS +FdoQuerySharedInfoInterface( + IN PXENIFACE_FDO Fdo + ) +{ + KEVENT Event; + IO_STATUS_BLOCK StatusBlock; + PIRP Irp; + PIO_STACK_LOCATION StackLocation; + INTERFACE Interface; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + KeInitializeEvent(&Event, NotificationEvent, FALSE); + RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK)); + RtlZeroMemory(&Interface, sizeof(INTERFACE)); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, + Fdo->LowerDeviceObject, + NULL, + 0, + NULL, + &Event, + &StatusBlock); + + status = STATUS_UNSUCCESSFUL; + if (Irp == NULL) + goto fail1; + + StackLocation = IoGetNextIrpStackLocation(Irp); + StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE; + + StackLocation->Parameters.QueryInterface.InterfaceType = &GUID_SHARED_INFO_INTERFACE; + StackLocation->Parameters.QueryInterface.Size = sizeof (INTERFACE); + StackLocation->Parameters.QueryInterface.Version = SHARED_INFO_INTERFACE_VERSION; + StackLocation->Parameters.QueryInterface.Interface = &Interface; + + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + + status = IoCallDriver(Fdo->LowerDeviceObject, Irp); + if (status == STATUS_PENDING) { + (VOID) KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + status = StatusBlock.Status; + } + + if (!NT_SUCCESS(status)) + goto fail2; + + status = STATUS_INVALID_PARAMETER; + if (Interface.Version != SHARED_INFO_INTERFACE_VERSION) + goto fail3; + + Fdo->SharedInfoInterface = (PXENBUS_SHARED_INFO_INTERFACE)Interface.Context; + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} +NTSTATUS +FdoCreate( + IN PDEVICE_OBJECT PhysicalDeviceObject + ) +{ + PDEVICE_OBJECT FunctionDeviceObject; + PXENIFACE_DX Dx; + PXENIFACE_FDO Fdo; + WCHAR Name[MAXNAMELEN * sizeof (WCHAR)]; + ULONG Size; + NTSTATUS status; + +#pragma prefast(suppress:28197) // Possibly leaking memory 'FunctionDeviceObject' + status = IoCreateDevice(DriverObject, + sizeof (XENIFACE_DX), + NULL, + FILE_DEVICE_UNKNOWN, + FILE_DEVICE_SECURE_OPEN, + FALSE, + &FunctionDeviceObject); + if (!NT_SUCCESS(status)) + goto fail1; + + Dx = (PXENIFACE_DX)FunctionDeviceObject->DeviceExtension; + RtlZeroMemory(Dx, sizeof (XENIFACE_DX)); + + Dx->Type = FUNCTION_DEVICE_OBJECT; + Dx->DeviceObject = FunctionDeviceObject; + Dx->DevicePnpState = Added; + Dx->SystemPowerState = PowerSystemShutdown; + Dx->DevicePowerState = PowerDeviceD3; + + FunctionDeviceObject->Flags |= DO_POWER_PAGABLE; + FunctionDeviceObject->Flags |= DO_BUFFERED_IO; + + Fdo = (PXENIFACE_FDO)__FdoAllocate(sizeof (XENIFACE_FDO)); + + status = STATUS_NO_MEMORY; + if (Fdo == NULL) + goto fail2; + + Fdo->Dx = Dx; + Fdo->PhysicalDeviceObject = PhysicalDeviceObject; + Fdo->LowerDeviceObject = IoAttachDeviceToDeviceStack(FunctionDeviceObject, + PhysicalDeviceObject); + + status = ThreadCreate(FdoSystemPower, Fdo, &Fdo->SystemPowerThread); + if (!NT_SUCCESS(status)) + goto fail3; + + status = ThreadCreate(FdoDevicePower, Fdo, &Fdo->DevicePowerThread); + if (!NT_SUCCESS(status)) + goto fail4; + + status = IoGetDeviceProperty(PhysicalDeviceObject, + DevicePropertyLocationInformation, + sizeof (Name), + Name, + &Size); + if (!NT_SUCCESS(status)) + goto fail5; + + status = IoRegisterDeviceInterface(PhysicalDeviceObject, + (LPGUID)&GUID_INTERFACE_XENIFACE, + NULL, + &Fdo->InterfaceName); + if (!NT_SUCCESS(status)) + goto fail6; + + status = __FdoSetName(Fdo, Name); + if (!NT_SUCCESS(status)) + goto fail7; + + status = FdoQueryStoreInterface(Fdo); + if (!NT_SUCCESS(status)) + goto fail8; + + status = FdoQuerySuspendInterface(Fdo); + if (!NT_SUCCESS(status)) + goto fail9; + + status = FdoQuerySharedInfoInterface(Fdo); + if (!NT_SUCCESS(status)) + goto fail10; + + InitializeMutex(&Fdo->Mutex); + InitializeListHead(&Dx->ListEntry); + Fdo->References = 1; + + FdoInitialiseXSRegistryEntries(Fdo); + + KeInitializeEvent(&Fdo->registryWriteEvent, NotificationEvent, FALSE); + + status = ThreadCreate(FdoRegistryThreadHandler, Fdo, &Fdo->registryThread); + if (!NT_SUCCESS(status)) + goto fail11; + + Info("%p (%s)\n", + FunctionDeviceObject, + __FdoGetName(Fdo)); + + Dx->Fdo = Fdo; + FunctionDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + return STATUS_SUCCESS; + + +fail11: + Error("fail11\n"); + Fdo->SharedInfoInterface = NULL; + +fail10: + Error("fail10\n"); + Fdo->SuspendInterface = NULL; + +fail9: + Error("fail8\n"); + + Fdo->StoreInterface = NULL; + +fail8: + Error("fail8\n"); + +fail7: + Error("fail7\n"); + RtlFreeUnicodeString(&Fdo->InterfaceName); + RtlZeroMemory(&Fdo->InterfaceName,sizeof(UNICODE_STRING)); + +fail6: + Error("fail6\n"); + +fail5: + Error("fail5\n"); + + ThreadAlert(Fdo->DevicePowerThread); + ThreadJoin(Fdo->DevicePowerThread); + Fdo->DevicePowerThread = NULL; + +fail4: + Error("fail4\n"); + + ThreadAlert(Fdo->SystemPowerThread); + ThreadJoin(Fdo->SystemPowerThread); + Fdo->SystemPowerThread = NULL; + +fail3: + Error("fail3\n"); + +#pragma prefast(suppress:28183) // Fdo->LowerDeviceObject could be NULL + IoDetachDevice(Fdo->LowerDeviceObject); + + Fdo->PhysicalDeviceObject = NULL; + Fdo->LowerDeviceObject = NULL; + Fdo->Dx = NULL; + + ASSERT(IsZeroMemory(Fdo, sizeof (XENIFACE_FDO))); + __FdoFree(Fdo); + +fail2: + Error("fail2\n"); + + IoDeleteDevice(FunctionDeviceObject); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + + + + +VOID +FdoDestroy( + IN PXENIFACE_FDO Fdo + ) +{ + PXENIFACE_DX Dx = Fdo->Dx; + PDEVICE_OBJECT FunctionDeviceObject = Dx->DeviceObject; + + ASSERT(IsListEmpty(&Dx->ListEntry)); + ASSERT3U(Fdo->References, ==, 0); + ASSERT3U(__FdoGetDevicePnpState(Fdo), ==, Deleted); + + Fdo->NotDisableable = FALSE; + + Info("%p (%s)\n", + FunctionDeviceObject, + __FdoGetName(Fdo)); + + Dx->Fdo = NULL; + + RtlZeroMemory(&Fdo->Mutex, sizeof (XENIFACE_MUTEX)); + + Fdo->InterfacesAcquired = FALSE; + Fdo->SuspendInterface = NULL; + Fdo->StoreInterface = NULL; + Fdo->SharedInfoInterface = NULL; + + ThreadAlert(Fdo->registryThread); + ThreadJoin(Fdo->registryThread); + Fdo->registryThread = NULL; + + ThreadAlert(Fdo->DevicePowerThread); + ThreadJoin(Fdo->DevicePowerThread); + Fdo->DevicePowerThread = NULL; + + ThreadAlert(Fdo->SystemPowerThread); + ThreadJoin(Fdo->SystemPowerThread); + Fdo->SystemPowerThread = NULL; + + IoDetachDevice(Fdo->LowerDeviceObject); + + RtlZeroMemory(&Fdo->LowerDeviceCapabilities, sizeof (DEVICE_CAPABILITIES)); + Fdo->LowerDeviceObject = NULL; + Fdo->PhysicalDeviceObject = NULL; + Fdo->Dx = NULL; + + RtlZeroMemory(&Fdo->SessionLock, sizeof(FAST_MUTEX)); + RtlZeroMemory(&Fdo->SessionHead, sizeof(LIST_ENTRY)); + RtlZeroMemory(&Fdo->registryWriteEvent, sizeof(KEVENT)); + + RtlFreeUnicodeString(&Fdo->InterfaceName); + RtlZeroMemory(&Fdo->InterfaceName,sizeof(UNICODE_STRING)); + + ASSERT(IsZeroMemory(Fdo, sizeof (XENIFACE_FDO))); + __FdoFree(Fdo); + + IoDeleteDevice(FunctionDeviceObject); +} + + diff --git a/src/xeniface/fdo.h b/src/xeniface/fdo.h new file mode 100644 index 0000000..272aeb9 --- /dev/null +++ b/src/xeniface/fdo.h @@ -0,0 +1,168 @@ +/* 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 _XENIFACE_FDO_H +#define _XENIFACE_FDO_H + +#include +#include +#include +#include + +#include "driver.h" +#include "types.h" + +#include "thread.h" +#include "mutex.h" + +typedef enum _FDO_RESOURCE_TYPE { + MEMORY_RESOURCE = 0, + INTERRUPT_RESOURCE, + RESOURCE_COUNT +} FDO_RESOURCE_TYPE, *PFDO_RESOURCE_TYPE; + +typedef struct _FDO_RESOURCE { + CM_PARTIAL_RESOURCE_DESCRIPTOR Raw; + CM_PARTIAL_RESOURCE_DESCRIPTOR Translated; +} FDO_RESOURCE, *PFDO_RESOURCE; + + +typedef struct _XENIFACE_FDO { + struct _XENIFACE_DX *Dx; + PDEVICE_OBJECT LowerDeviceObject; + PDEVICE_OBJECT PhysicalDeviceObject; + DEVICE_CAPABILITIES LowerDeviceCapabilities; + ULONG Usage[DeviceUsageTypeDumpFile + 1]; + BOOLEAN NotDisableable; + + PXENIFACE_THREAD SystemPowerThread; + PIRP SystemPowerIrp; + PXENIFACE_THREAD DevicePowerThread; + PIRP DevicePowerIrp; + + XENIFACE_MUTEX Mutex; + ULONG References; + + FDO_RESOURCE Resource[RESOURCE_COUNT]; + + + PXENBUS_STORE_INTERFACE StoreInterface; + + PXENBUS_SUSPEND_INTERFACE SuspendInterface; + + PXENBUS_SHARED_INFO_INTERFACE SharedInfoInterface; + + PXENBUS_SUSPEND_CALLBACK SuspendCallbackLate; + + BOOLEAN InterfacesAcquired; + + #define MAX_SESSIONS (65536) + + int WmiReady; + + USHORT Sessions; + FAST_MUTEX SessionLock; + LIST_ENTRY SessionHead; + + PXENIFACE_THREAD registryThread; + KEVENT registryWriteEvent; + + + UNICODE_STRING SuggestedInstanceName; + + UNICODE_STRING InterfaceName; + +} XENIFACE_FDO, *PXENIFACE_FDO; + + +extern PCHAR +FdoGetName( + IN PXENIFACE_FDO Fdo + ); + +extern NTSTATUS +FdoCreate( + IN PDEVICE_OBJECT PhysicalDeviceObject + ); + +extern VOID +FdoDestroy( + IN PXENIFACE_FDO Fdo + ); + +extern VOID +FdoAcquireMutex( + IN PXENIFACE_FDO Fdo + ); + +extern VOID +FdoReleaseMutex( + IN PXENIFACE_FDO Fdo + ); + +extern PDEVICE_OBJECT +FdoGetPhysicalDeviceObject( + IN PXENIFACE_FDO Fdo + ); + +extern VOID +FdoReap( + IN PXENIFACE_FDO Fdo + ); + +extern NTSTATUS +FdoDelegateIrp( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ); + + +extern PXENBUS_STORE_INTERFACE +FdoGetStoreInterface( + IN PXENIFACE_FDO Fdo + ); + + +extern PXENBUS_SUSPEND_INTERFACE +FdoGetSuspendInterface( + IN PXENIFACE_FDO Fdo + ); + + +extern NTSTATUS +FdoDispatch( + IN PXENIFACE_FDO Fdo, + IN PIRP Irp + ); + + + +#endif // _XENIFACE_FDO_H diff --git a/src/xeniface/ioctls.c b/src/xeniface/ioctls.c index 75936a3..928dfed 100644 --- a/src/xeniface/ioctls.c +++ b/src/xeniface/ioctls.c @@ -30,9 +30,10 @@ */ -#include "xeniface.h" +#include "driver.h" #include "ioctls.h" #include "..\..\include\xeniface_ioctls.h" +#include "log.h" static FORCEINLINE BOOLEAN __IsValidStr( @@ -83,7 +84,7 @@ __DisplayMultiSz( static DECLSPEC_NOINLINE NTSTATUS IoctlRead( - __in PFDO_DATA Fdo, + __in PXENIFACE_FDO Fdo, __in PCHAR Buffer, __in ULONG InLen, __in ULONG OutLen, @@ -143,7 +144,7 @@ fail1: static DECLSPEC_NOINLINE NTSTATUS IoctlWrite( - __in PFDO_DATA Fdo, + __in PXENIFACE_FDO Fdo, __in PCHAR Buffer, __in ULONG InLen, __in ULONG OutLen @@ -187,7 +188,7 @@ fail1: static DECLSPEC_NOINLINE NTSTATUS IoctlDirectory( - __in PFDO_DATA Fdo, + __in PXENIFACE_FDO Fdo, __in PCHAR Buffer, __in ULONG InLen, __in ULONG OutLen, @@ -252,7 +253,7 @@ fail1: static DECLSPEC_NOINLINE NTSTATUS IoctlRemove( - __in PFDO_DATA Fdo, + __in PXENIFACE_FDO Fdo, __in PCHAR Buffer, __in ULONG InLen, __in ULONG OutLen @@ -286,7 +287,7 @@ fail1: NTSTATUS XenIFaceIoctl( - __in PFDO_DATA Fdo, + __in PXENIFACE_FDO Fdo, __in PIRP Irp ) { @@ -326,6 +327,11 @@ XenIFaceIoctl( } done: + + Irp->IoStatus.Status = status; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return status; } diff --git a/src/xeniface/ioctls.h b/src/xeniface/ioctls.h index 873fbbc..63de9eb 100644 --- a/src/xeniface/ioctls.h +++ b/src/xeniface/ioctls.h @@ -34,7 +34,7 @@ NTSTATUS XenIFaceIoctl( - __in PFDO_DATA Fdo, + __in PXENIFACE_FDO Fdo, __in PIRP Irp ); diff --git a/src/xeniface/log.h b/src/xeniface/log.h new file mode 100644 index 0000000..39d9756 --- /dev/null +++ b/src/xeniface/log.h @@ -0,0 +1,174 @@ +/* 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 _XENIFACE_LOG_H +#define _XENIFACE_LOG_H + +#include +#include + +#define ERROR DPFLTR_ERROR_LEVEL +#define WARNING DPFLTR_WARNING_LEVEL +#define TRACE DPFLTR_TRACE_LEVEL +#define INFO DPFLTR_INFO_LEVEL + +#pragma warning(disable:4127) // conditional expression is constant + +static __inline VOID +__Error( + IN const CHAR *Prefix, + IN const CHAR *Format, + ... + ) +{ + va_list Arguments; + + va_start(Arguments, Format); + +#pragma prefast(suppress:6001) // Using uninitialized memory + vDbgPrintExWithPrefix(Prefix, + DPFLTR_IHVDRIVER_ID, + DPFLTR_ERROR_LEVEL, + Format, + Arguments); + va_end(Arguments); +} + +#define Error(...) \ + __Error(__MODULE__ "|" __FUNCTION__ ": ", __VA_ARGS__) + +static __inline VOID +__Warning( + IN const CHAR *Prefix, + IN const CHAR *Format, + ... + ) +{ + va_list Arguments; + + va_start(Arguments, Format); + +#pragma prefast(suppress:6001) // Using uninitialized memory + vDbgPrintExWithPrefix(Prefix, + DPFLTR_IHVDRIVER_ID, + DPFLTR_WARNING_LEVEL, + Format, + Arguments); + va_end(Arguments); +} + +#define Warning(...) \ + __Warning(__MODULE__ "|" __FUNCTION__ ": ", __VA_ARGS__) + +#if DBG +static __inline VOID +__Trace( + IN const CHAR *Prefix, + IN const CHAR *Format, + ... + ) +{ + va_list Arguments; + + va_start(Arguments, Format); + +#pragma prefast(suppress:6001) // Using uninitialized memory + vDbgPrintExWithPrefix(Prefix, + DPFLTR_IHVDRIVER_ID, + DPFLTR_TRACE_LEVEL, + Format, + Arguments); + va_end(Arguments); +} + +#define Trace(...) \ + __Trace(__MODULE__ "|" __FUNCTION__ ": ", __VA_ARGS__) +#else // DBG +#define Trace(...) (VOID)(__VA_ARGS__) +#endif // DBG + +static __inline VOID +__Info( + IN const CHAR *Prefix, + IN const CHAR *Format, + ... + ) +{ + va_list Arguments; + + va_start(Arguments, Format); + +#pragma prefast(suppress:6001) // Using uninitialized memory + vDbgPrintExWithPrefix(Prefix, + DPFLTR_IHVDRIVER_ID, + DPFLTR_INFO_LEVEL, + Format, + Arguments); + va_end(Arguments); +} + +#define Info(...) \ + __Info(__MODULE__ "|" __FUNCTION__ ": ", __VA_ARGS__) + + +#define XenIfaceDebugPrint(LEVEL, ...) \ + __XenIfaceDebugPrint(__MODULE__ "|" __FUNCTION__ ": ",LEVEL, __VA_ARGS__) + +static __inline VOID +__XenIfaceDebugPrint ( + __in const CHAR *Prefix, + __in ULONG DebugPrintLevel, + __in PCCHAR DebugMessage, + ... + ) + +{ + va_list list; + +#if !DBG + if (DebugPrintLevel == TRACE) + return; +#endif + + va_start(list, DebugMessage); + + if (DebugMessage) + { + vDbgPrintExWithPrefix(Prefix, DPFLTR_IHVDRIVER_ID, DebugPrintLevel, DebugMessage, list); + + } + va_end(list); + + return; +} + + +#endif // _XENIFACE_LOG_H diff --git a/src/xeniface/mutex.h b/src/xeniface/mutex.h new file mode 100644 index 0000000..f436f13 --- /dev/null +++ b/src/xeniface/mutex.h @@ -0,0 +1,82 @@ +/* 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 _XENIFACE_MUTEX_H +#define _XENIFACE_MUTEX_H + +#include + +#include "assert.h" + +typedef struct _XENIFACE_MUTEX { + PKTHREAD Owner; + KEVENT Event; +} XENIFACE_MUTEX, *PXENIFACE_MUTEX; + +static FORCEINLINE VOID +InitializeMutex( + IN PXENIFACE_MUTEX Mutex + ) +{ + RtlZeroMemory(Mutex, sizeof (XENIFACE_MUTEX)); + + KeInitializeEvent(&Mutex->Event, SynchronizationEvent, TRUE); +} + +static FORCEINLINE VOID +__drv_maxIRQL(PASSIVE_LEVEL) +AcquireMutex( + IN PXENIFACE_MUTEX Mutex + ) +{ + (VOID) KeWaitForSingleObject(&Mutex->Event, + Executive, + KernelMode, + FALSE, + NULL); + + ASSERT3P(Mutex->Owner, ==, NULL); + Mutex->Owner = KeGetCurrentThread(); +} + +static FORCEINLINE VOID +__drv_maxIRQL(PASSIVE_LEVEL) +ReleaseMutex( + IN PXENIFACE_MUTEX Mutex + ) +{ + ASSERT3P(Mutex->Owner, ==, KeGetCurrentThread()); + Mutex->Owner = NULL; + + KeSetEvent(&Mutex->Event, IO_NO_INCREMENT, FALSE); +} + +#endif // _XENIFACE_MUTEX_H diff --git a/src/xeniface/names.h b/src/xeniface/names.h new file mode 100644 index 0000000..9d282f7 --- /dev/null +++ b/src/xeniface/names.h @@ -0,0 +1,278 @@ +/* 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 _XENVIF_NAMES_H_ +#define _XENVIF_NAMES_H_ + +#include + +#include "types.h" + +static FORCEINLINE const CHAR * +PowerTypeName( + IN POWER_STATE_TYPE Type + ) +{ +#define _POWER_TYPE_NAME(_Type) \ + case _Type: \ + return #_Type; + + switch (Type) { + _POWER_TYPE_NAME(SystemPowerState); + _POWER_TYPE_NAME(DevicePowerState); + default: + break; + } + + return ("UNKNOWN"); +#undef _POWER_ACTION_NAME +} + +static FORCEINLINE const CHAR * +PowerSystemStateName( + IN SYSTEM_POWER_STATE State + ) +{ +#define _POWER_SYSTEM_STATE_NAME(_State) \ + case PowerSystem ## _State: \ + return #_State; + + switch (State) { + _POWER_SYSTEM_STATE_NAME(Unspecified); + _POWER_SYSTEM_STATE_NAME(Working); + _POWER_SYSTEM_STATE_NAME(Sleeping1); + _POWER_SYSTEM_STATE_NAME(Sleeping2); + _POWER_SYSTEM_STATE_NAME(Sleeping3); + _POWER_SYSTEM_STATE_NAME(Hibernate); + _POWER_SYSTEM_STATE_NAME(Shutdown); + _POWER_SYSTEM_STATE_NAME(Maximum); + default: + break; + } + + return ("UNKNOWN"); +#undef _POWER_SYSTEM_STATE_NAME +} + +static FORCEINLINE const CHAR * +PowerDeviceStateName( + IN DEVICE_POWER_STATE State + ) +{ +#define _POWER_DEVICE_STATE_NAME(_State) \ + case PowerDevice ## _State: \ + return #_State; + + switch (State) { + _POWER_DEVICE_STATE_NAME(Unspecified); + _POWER_DEVICE_STATE_NAME(D0); + _POWER_DEVICE_STATE_NAME(D1); + _POWER_DEVICE_STATE_NAME(D2); + _POWER_DEVICE_STATE_NAME(D3); + _POWER_DEVICE_STATE_NAME(Maximum); + default: + break; + } + + return ("UNKNOWN"); +#undef _POWER_DEVICE_STATE_NAME +} + +static FORCEINLINE const CHAR * +PowerActionName( + IN POWER_ACTION Type + ) +{ +#define _POWER_ACTION_NAME(_Type) \ + case PowerAction ## _Type: \ + return #_Type; + + switch (Type) { + _POWER_ACTION_NAME(None); + _POWER_ACTION_NAME(Reserved); + _POWER_ACTION_NAME(Sleep); + _POWER_ACTION_NAME(Hibernate); + _POWER_ACTION_NAME(Shutdown); + _POWER_ACTION_NAME(ShutdownReset); + _POWER_ACTION_NAME(ShutdownOff); + _POWER_ACTION_NAME(WarmEject); + default: + break; + } + + return ("UNKNOWN"); +#undef _POWER_ACTION_NAME +} + +static FORCEINLINE const CHAR * +PowerMinorFunctionName( + IN ULONG MinorFunction + ) +{ +#define _POWER_MINOR_FUNCTION_NAME(_Function) \ + case IRP_MN_ ## _Function: \ + return #_Function; + + switch (MinorFunction) { + _POWER_MINOR_FUNCTION_NAME(WAIT_WAKE); + _POWER_MINOR_FUNCTION_NAME(POWER_SEQUENCE); + _POWER_MINOR_FUNCTION_NAME(SET_POWER); + _POWER_MINOR_FUNCTION_NAME(QUERY_POWER); + + default: + return "UNKNOWN"; + } + +#undef _POWER_MINOR_FUNCTION_NAME +} + +static FORCEINLINE const CHAR * +PnpDeviceStateName( + IN DEVICE_PNP_STATE State + ) +{ +#define _PNP_DEVICE_STATE_NAME(_State) \ + case _State: \ + return #_State; + + switch (State) { + _PNP_DEVICE_STATE_NAME(Invalid); + _PNP_DEVICE_STATE_NAME(Added); + _PNP_DEVICE_STATE_NAME(Started); + _PNP_DEVICE_STATE_NAME(StopPending); + _PNP_DEVICE_STATE_NAME(Stopped); + _PNP_DEVICE_STATE_NAME(RemovePending); + _PNP_DEVICE_STATE_NAME(SurpriseRemovePending); + _PNP_DEVICE_STATE_NAME(Deleted); + default: + break; + } + + return "UNKNOWN"; + +#undef _STATE_NAME +} + +static FORCEINLINE const CHAR * +PnpMinorFunctionName( + IN ULONG Function + ) +{ +#define _PNP_MINOR_FUNCTION_NAME(_Function) \ + case IRP_MN_ ## _Function: \ + return #_Function; + + switch (Function) { + _PNP_MINOR_FUNCTION_NAME(START_DEVICE); + _PNP_MINOR_FUNCTION_NAME(QUERY_REMOVE_DEVICE); + _PNP_MINOR_FUNCTION_NAME(REMOVE_DEVICE); + _PNP_MINOR_FUNCTION_NAME(CANCEL_REMOVE_DEVICE); + _PNP_MINOR_FUNCTION_NAME(STOP_DEVICE); + _PNP_MINOR_FUNCTION_NAME(QUERY_STOP_DEVICE); + _PNP_MINOR_FUNCTION_NAME(CANCEL_STOP_DEVICE); + _PNP_MINOR_FUNCTION_NAME(QUERY_DEVICE_RELATIONS); + _PNP_MINOR_FUNCTION_NAME(QUERY_INTERFACE); + _PNP_MINOR_FUNCTION_NAME(QUERY_CAPABILITIES); + _PNP_MINOR_FUNCTION_NAME(QUERY_RESOURCES); + _PNP_MINOR_FUNCTION_NAME(QUERY_RESOURCE_REQUIREMENTS); + _PNP_MINOR_FUNCTION_NAME(QUERY_DEVICE_TEXT); + _PNP_MINOR_FUNCTION_NAME(FILTER_RESOURCE_REQUIREMENTS); + _PNP_MINOR_FUNCTION_NAME(READ_CONFIG); + _PNP_MINOR_FUNCTION_NAME(WRITE_CONFIG); + _PNP_MINOR_FUNCTION_NAME(EJECT); + _PNP_MINOR_FUNCTION_NAME(SET_LOCK); + _PNP_MINOR_FUNCTION_NAME(QUERY_ID); + _PNP_MINOR_FUNCTION_NAME(QUERY_PNP_DEVICE_STATE); + _PNP_MINOR_FUNCTION_NAME(QUERY_BUS_INFORMATION); + _PNP_MINOR_FUNCTION_NAME(DEVICE_USAGE_NOTIFICATION); + _PNP_MINOR_FUNCTION_NAME(SURPRISE_REMOVAL); + _PNP_MINOR_FUNCTION_NAME(QUERY_LEGACY_BUS_INFORMATION); + default: + break; + } + + return "UNKNOWN"; + +#undef _PNP_MINOR_FUNCTION_NAME +} + +static FORCEINLINE const CHAR * +PartialResourceDescriptorTypeName( + IN UCHAR Type + ) +{ +#define _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(_Type) \ + case CmResourceType ## _Type: \ + return #_Type; + + switch (Type) { + _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Null); + _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Port); + _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Interrupt); + _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Memory); + _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(Dma); + _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DeviceSpecific); + _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(BusNumber); + _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(MemoryLarge); + _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(ConfigData); + _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME(DevicePrivate); + default: + break; + } + + return "UNKNOWN"; + +#undef _PARTIAL_RESOURCE_DESCRIPTOR_TYPE_NAME +} + +static FORCEINLINE const CHAR * +DeviceUsageTypeName( + IN DEVICE_USAGE_NOTIFICATION_TYPE Type + ) +{ +#define _DEVICE_USAGE_TYPE_NAME(_Type) \ + case DeviceUsageType ## _Type: \ + return #_Type; + + switch (Type) { + _DEVICE_USAGE_TYPE_NAME(Paging); + _DEVICE_USAGE_TYPE_NAME(Hibernation); + _DEVICE_USAGE_TYPE_NAME(DumpFile); + default: + break; + } + + return "UNKNOWN"; + +#undef _DEVICE_USAGE_TYPE_NAME +} + +#endif // _XENVIF_NAMES_H_ diff --git a/src/xeniface/thread.c b/src/xeniface/thread.c new file mode 100644 index 0000000..51967ed --- /dev/null +++ b/src/xeniface/thread.c @@ -0,0 +1,227 @@ +/* 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 +#include + +#include "thread.h" +#include "log.h" +#include "assert.h" + +#define THREAD_POOL 'ERHT' + +struct _XENIFACE_THREAD { + XENIFACE_THREAD_FUNCTION Function; + PVOID Context; + KEVENT Event; + BOOLEAN Alerted; + LONG References; + PKTHREAD Thread; +}; + +static FORCEINLINE PVOID +__ThreadAllocate( + IN ULONG Length + ) +{ + return __AllocateNonPagedPoolWithTag(Length, THREAD_POOL); +} + +static FORCEINLINE VOID +__ThreadFree( + IN PVOID Buffer + ) +{ + __FreePoolWithTag(Buffer, THREAD_POOL); +} + +static FORCEINLINE VOID +__ThreadWake( + IN PXENIFACE_THREAD Thread + ) +{ + KeSetEvent(&Thread->Event, IO_NO_INCREMENT, FALSE); +} + +VOID +ThreadWake( + IN PXENIFACE_THREAD Thread + ) +{ + __ThreadWake(Thread); +} + +static FORCEINLINE VOID +__ThreadAlert( + IN PXENIFACE_THREAD Thread + ) +{ + Thread->Alerted = TRUE; + __ThreadWake(Thread); +} + +VOID +ThreadAlert( + IN PXENIFACE_THREAD Thread + ) +{ + __ThreadAlert(Thread); +} + +KSTART_ROUTINE ThreadFunction; + +VOID +ThreadFunction( + IN PVOID Argument + ) +{ + PXENIFACE_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 XENIFACE_THREAD_FUNCTION Function, + IN PVOID Context, + OUT PXENIFACE_THREAD *Thread + ) +{ + HANDLE Handle; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + (*Thread) = __ThreadAllocate(sizeof (XENIFACE_THREAD)); + + Warning("Create thread %p %p\n", Function, 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 PXENIFACE_THREAD Thread + ) +{ + return &Thread->Event; +} + +BOOLEAN +ThreadIsAlerted( + IN PXENIFACE_THREAD Thread + ) +{ + return Thread->Alerted; +} + +VOID +ThreadJoin( + IN PXENIFACE_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/xeniface/thread.h b/src/xeniface/thread.h new file mode 100644 index 0000000..69f3c51 --- /dev/null +++ b/src/xeniface/thread.h @@ -0,0 +1,74 @@ +/* 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 _XENIFACE_THREAD_H +#define _XENIFACE_THREAD_H + +#include + +typedef struct _XENIFACE_THREAD XENIFACE_THREAD, *PXENIFACE_THREAD; + +typedef NTSTATUS (*XENIFACE_THREAD_FUNCTION)(PXENIFACE_THREAD, PVOID); + +extern NTSTATUS +ThreadCreate( + IN XENIFACE_THREAD_FUNCTION Function, + IN PVOID Context, + OUT PXENIFACE_THREAD *Thread + ); + +extern PKEVENT +ThreadGetEvent( + IN PXENIFACE_THREAD Self + ); + +extern BOOLEAN +ThreadIsAlerted( + IN PXENIFACE_THREAD Self + ); + +extern VOID +ThreadWake( + IN PXENIFACE_THREAD Thread + ); + +extern VOID +ThreadAlert( + IN PXENIFACE_THREAD Thread + ); + +extern VOID +ThreadJoin( + IN PXENIFACE_THREAD Thread + ); + +#endif // _XENIFACE_THREAD_H + diff --git a/src/xeniface/types.h b/src/xeniface/types.h new file mode 100644 index 0000000..2339143 --- /dev/null +++ b/src/xeniface/types.h @@ -0,0 +1,51 @@ +/* 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 _XENIFACE_TYPES_H +#define _XENIFACE_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, + Added, // FDO only + Started, + StopPending, + Stopped, + RemovePending, + SurpriseRemovePending, + Deleted +} DEVICE_PNP_STATE, *PDEVICE_PNP_STATE; + +#endif // _XENIFACE_TYPES_H diff --git a/src/xeniface/wmi.c b/src/xeniface/wmi.c index 5a098bd..f0180ec 100644 --- a/src/xeniface/wmi.c +++ b/src/xeniface/wmi.c @@ -32,7 +32,6 @@ #include #include -#include #include #include #include @@ -41,14 +40,16 @@ #define NTSTRSAFE_LIB #include #include "wmi.h" -#include "xeniface.h" +#include "driver.h" #include "..\..\include\store_interface.h" #include "..\..\include\suspend_interface.h" +#include "log.h" +#include "xeniface_ioctls.h" __drv_raisesIRQL(APC_LEVEL) __drv_savesIRQLGlobal(OldIrql, fdoData->SessionLock) void LockSessions( - FDO_DATA* fdoData) + XENIFACE_FDO* fdoData) { ASSERT(KeGetCurrentIrql() <= APC_LEVEL); ExAcquireFastMutex(&fdoData->SessionLock); @@ -57,7 +58,7 @@ void LockSessions( __drv_requiresIRQL(APC_LEVEL) __drv_restoresIRQLGlobal(OldIrql, fdoData->SessionLock) void UnlockSessions( - FDO_DATA* fdoData) + XENIFACE_FDO* fdoData) { ASSERT(KeGetCurrentIrql() == APC_LEVEL); ExReleaseFastMutex(&fdoData->SessionLock); @@ -606,7 +607,7 @@ GetCountedUnicodeStringSize(UNICODE_STRING *string) { } size_t -GetInstanceNameSize(FDO_DATA* FdoData, const char *string) { +GetInstanceNameSize(XENIFACE_FDO* FdoData, const char *string) { ANSI_STRING ansi; RtlInitAnsiString(&ansi, string); return sizeof(USHORT) + @@ -618,7 +619,7 @@ GetInstanceNameSize(FDO_DATA* FdoData, const char *string) { NTSTATUS -GetInstanceName(UNICODE_STRING *dest, FDO_DATA* FdoData, const char *string) { +GetInstanceName(UNICODE_STRING *dest, XENIFACE_FDO* FdoData, const char *string) { ANSI_STRING ansi; UNICODE_STRING unicode; NTSTATUS status; @@ -651,7 +652,7 @@ GetInstanceName(UNICODE_STRING *dest, FDO_DATA* FdoData, const char *string) { } NTSTATUS -WriteInstanceName(FDO_DATA* FdoData, const char *string, UCHAR *location) +WriteInstanceName(XENIFACE_FDO* FdoData, const char *string, UCHAR *location) { UNICODE_STRING destination; NTSTATUS status; @@ -686,7 +687,7 @@ typedef struct _XenStoreSession { typedef struct _XenStoreWatch { LIST_ENTRY listentry; UNICODE_STRING path; - FDO_DATA *fdoData; + XENIFACE_FDO *fdoData; ULONG suspendcount; BOOLEAN finished; @@ -703,7 +704,7 @@ void UnicodeShallowCopy(UNICODE_STRING *dest, UNICODE_STRING *src) { XenStoreSession* -FindSessionLocked(FDO_DATA *fdoData, +FindSessionLocked(XENIFACE_FDO *fdoData, LONG id) { XenStoreSession *session; @@ -751,12 +752,12 @@ SessionFindWatchLocked(XenStoreSession *session, } -void FireSuspendEvent(PFDO_DATA fdoData) { +void FireSuspendEvent(PXENIFACE_FDO fdoData) { XenIfaceDebugPrint(ERROR,"Ready to unsuspend Event\n"); KeSetEvent(&fdoData->registryWriteEvent, IO_NO_INCREMENT, FALSE); if (fdoData->WmiReady) { XenIfaceDebugPrint(TRACE,"Fire Suspend Event\n"); - WmiFireEvent(fdoData->Self, + WmiFireEvent(fdoData->Dx->DeviceObject, (LPGUID)&CitrixXenStoreUnsuspendedEvent_GUID, 0, 0, @@ -785,7 +786,7 @@ void FireWatch(XenStoreWatch* watch) { if (eventdata !=NULL) { XenIfaceDebugPrint(TRACE,"Fire Watch Event\n"); - WmiFireEvent(watch->fdoData->Self, + WmiFireEvent(watch->fdoData->Dx->DeviceObject, (LPGUID)&CitrixXenStoreWatchEvent_GUID, 0, RequiredSize, @@ -796,7 +797,7 @@ void FireWatch(XenStoreWatch* watch) { KSTART_ROUTINE WatchCallbackThread; NTSTATUS -StartWatch(FDO_DATA *fdoData, XenStoreWatch *watch) +StartWatch(XENIFACE_FDO *fdoData, XenStoreWatch *watch) { char *tmppath; ANSI_STRING ansipath; @@ -915,7 +916,7 @@ VOID WatchCallbackThread(__in PVOID StartContext) { NTSTATUS SessionAddWatchLocked(XenStoreSession *session, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *path, XenStoreWatch **watch) { @@ -1012,7 +1013,7 @@ void SessionRemoveWatchesLocked(XenStoreSession *session) { XenStoreSession* -FindSessionByInstanceLocked(FDO_DATA *fdoData, +FindSessionByInstanceLocked(XENIFACE_FDO *fdoData, UNICODE_STRING *instance) { XenStoreSession *session; @@ -1034,7 +1035,7 @@ __success(return!=NULL) __drv_raisesIRQL(APC_LEVEL) __drv_savesIRQLGlobal(OldIrql, fdoData->SessionLock) XenStoreSession * -FindSessionByInstanceAndLock(FDO_DATA *fdoData, +FindSessionByInstanceAndLock(XENIFACE_FDO *fdoData, UNICODE_STRING *instance) { XenStoreSession *session; LockSessions(fdoData); @@ -1074,7 +1075,7 @@ PSTR Xmasprintf(const char *fmt, ...) { } NTSTATUS -CreateNewSession(FDO_DATA *fdoData, +CreateNewSession(XENIFACE_FDO *fdoData, UNICODE_STRING *stringid, ULONG *sessionid) { XenStoreSession *session; @@ -1163,7 +1164,7 @@ CreateNewSession(FDO_DATA *fdoData, } void -RemoveSessionLocked(FDO_DATA *fdoData, +RemoveSessionLocked(XENIFACE_FDO *fdoData, XenStoreSession *session) { XenIfaceDebugPrint(TRACE,"RemoveSessionLocked\n"); @@ -1183,7 +1184,7 @@ RemoveSessionLocked(FDO_DATA *fdoData, } void -RemoveSession(FDO_DATA *fdoData, +RemoveSession(XENIFACE_FDO *fdoData, XenStoreSession *session) { XenIfaceDebugPrint(TRACE,"RemoveSession\n"); LockSessions(fdoData); @@ -1191,13 +1192,16 @@ RemoveSession(FDO_DATA *fdoData, UnlockSessions(fdoData); } -void SessionsRemoveAll(FDO_DATA *fdoData) { - +void SessionsRemoveAll(XENIFACE_FDO *fdoData) { + XenIfaceDebugPrint(TRACE,"lock"); LockSessions(fdoData); + XenIfaceDebugPrint(TRACE,"in lock"); while (fdoData->SessionHead.Flink != &fdoData->SessionHead) { RemoveSessionLocked(fdoData, (XenStoreSession *)fdoData->SessionHead.Flink); } + XenIfaceDebugPrint(TRACE,"unlock"); UnlockSessions(fdoData); + XenIfaceDebugPrint(TRACE,"unlocked"); } @@ -1226,7 +1230,7 @@ void SessionUnwatchWatchesLocked(XenStoreSession *session) ExReleaseFastMutex(&session->WatchMapLock); } -void SuspendSessionLocked(FDO_DATA *fdoData, +void SuspendSessionLocked(XENIFACE_FDO *fdoData, XenStoreSession *session) { SessionUnwatchWatchesLocked(session); if (session->transaction != NULL) { @@ -1238,7 +1242,7 @@ void SuspendSessionLocked(FDO_DATA *fdoData, } -void SessionsSuspendAll(FDO_DATA *fdoData) { +void SessionsSuspendAll(XENIFACE_FDO *fdoData) { XenStoreSession *session; LockSessions(fdoData); XenIfaceDebugPrint(TRACE,"Suspend all sessions\n"); @@ -1277,12 +1281,12 @@ void SessionRenewWatchesLocked(XenStoreSession *session) { ExReleaseFastMutex(&session->WatchMapLock); } -void ResumeSessionLocked(FDO_DATA *fdoData, +void ResumeSessionLocked(XENIFACE_FDO *fdoData, XenStoreSession *session) { SessionRenewWatchesLocked(session); } -void SessionsResumeAll(FDO_DATA *fdoData) { +void SessionsResumeAll(XENIFACE_FDO *fdoData) { XenStoreSession *session; LockSessions(fdoData); @@ -1298,7 +1302,7 @@ void SessionsResumeAll(FDO_DATA *fdoData) { NTSTATUS WmiInit( - PFDO_DATA FdoData + PXENIFACE_FDO FdoData ) { NTSTATUS status = STATUS_SUCCESS; @@ -1308,20 +1312,20 @@ WmiInit( - IoWMISuggestInstanceName(FdoData->UnderlyingPDO, NULL, FALSE, + IoWMISuggestInstanceName(FdoData->PhysicalDeviceObject, NULL, FALSE, &FdoData->SuggestedInstanceName); InitializeListHead(&FdoData->SessionHead); FdoData->Sessions = 0; ExInitializeFastMutex(&FdoData->SessionLock); - status = IoWMIRegistrationControl(FdoData->Self, WMIREG_ACTION_REGISTER); + status = IoWMIRegistrationControl(FdoData->Dx->DeviceObject, WMIREG_ACTION_REGISTER); FdoData->WmiReady = 1; return status; } NTSTATUS WmiFinalise( - PFDO_DATA FdoData + PXENIFACE_FDO FdoData ) { NTSTATUS status = STATUS_SUCCESS; @@ -1330,7 +1334,10 @@ WmiFinalise( XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__); SessionsRemoveAll(FdoData); - status =IoWMIRegistrationControl(FdoData->Self, WMIREG_ACTION_DEREGISTER); + status =IoWMIRegistrationControl(FdoData->Dx->DeviceObject, WMIREG_ACTION_DEREGISTER); + RtlFreeUnicodeString(&FdoData->SuggestedInstanceName); + RtlZeroBytes(&FdoData->SuggestedInstanceName, sizeof(UNICODE_STRING)); + FdoData->WmiReady = 0; } return status; @@ -1338,11 +1345,11 @@ WmiFinalise( NTSTATUS WmiChangeSingleInstance( - PDEVICE_OBJECT DeviceObject, + PXENIFACE_FDO Fdo, PIO_STACK_LOCATION stack ) { - UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Fdo); UNREFERENCED_PARAMETER(stack); XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__); return STATUS_NOT_SUPPORTED; @@ -1350,11 +1357,11 @@ WmiChangeSingleInstance( NTSTATUS WmiChangeSingleItem( - IN PDEVICE_OBJECT DeviceObject, + IN PXENIFACE_FDO Fdo, IN PIO_STACK_LOCATION stack ) { - UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Fdo); UNREFERENCED_PARAMETER(stack); XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__); return STATUS_NOT_SUPPORTED; @@ -1362,11 +1369,11 @@ WmiChangeSingleItem( NTSTATUS WmiDisableCollection( - IN PDEVICE_OBJECT DeviceObject, + IN PXENIFACE_FDO Fdo, IN PIO_STACK_LOCATION stack ) { - UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Fdo); UNREFERENCED_PARAMETER(stack); XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__); return STATUS_NOT_SUPPORTED; @@ -1374,11 +1381,11 @@ WmiDisableCollection( NTSTATUS WmiDisableEvents( - IN PDEVICE_OBJECT DeviceObject, + IN PXENIFACE_FDO Fdo, IN PIO_STACK_LOCATION stack ) { - UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Fdo); UNREFERENCED_PARAMETER(stack); XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__); return STATUS_NOT_SUPPORTED; @@ -1386,11 +1393,11 @@ WmiDisableEvents( NTSTATUS WmiEnableCollection( - IN PDEVICE_OBJECT DeviceObject, + IN PXENIFACE_FDO Fdo, IN PIO_STACK_LOCATION stack ) { - UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Fdo); UNREFERENCED_PARAMETER(stack); XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__); return STATUS_NOT_SUPPORTED; @@ -1398,11 +1405,11 @@ WmiEnableCollection( NTSTATUS WmiEnableEvents( - IN PDEVICE_OBJECT DeviceObject, + IN PXENIFACE_FDO Fdo, IN PIO_STACK_LOCATION stack ) { - UNREFERENCED_PARAMETER(DeviceObject); + UNREFERENCED_PARAMETER(Fdo); UNREFERENCED_PARAMETER(stack); XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__); return STATUS_NOT_SUPPORTED; @@ -1434,7 +1441,7 @@ SessionExecuteRemoveValue(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { ULONG RequiredSize; @@ -1487,7 +1494,7 @@ SessionExecuteRemoveWatch(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { ULONG RequiredSize; @@ -1538,7 +1545,7 @@ SessionExecuteSetWatch(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { ULONG RequiredSize; @@ -1585,7 +1592,7 @@ SessionExecuteEndSession(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { XenStoreSession *session; @@ -1605,7 +1612,7 @@ SessionExecuteSetValue(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { ULONG RequiredSize; @@ -1680,7 +1687,7 @@ SessionExecuteGetFirstChild(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { ULONG RequiredSize; @@ -1793,7 +1800,7 @@ SessionExecuteGetNextSibling(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { ULONG RequiredSize; @@ -1968,7 +1975,7 @@ SessionExecuteGetChildren(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { int i; @@ -2089,7 +2096,7 @@ SessionExecuteLog(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { @@ -2120,7 +2127,7 @@ SessionExecuteStartTransaction(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { @@ -2159,7 +2166,7 @@ SessionExecuteCommitTransaction(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { @@ -2199,7 +2206,7 @@ SessionExecuteAbortTransaction(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { @@ -2240,7 +2247,7 @@ SessionExecuteGetValue(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, UNICODE_STRING *instance, OUT ULONG_PTR *byteswritten) { NTSTATUS status; @@ -2311,7 +2318,7 @@ BaseExecuteAddSession(UCHAR *InBuffer, ULONG InBufferSize, UCHAR *OutBuffer, ULONG OutBufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, OUT ULONG_PTR *byteswritten) { ULONG RequiredSize; UNICODE_STRING ustring; @@ -2356,7 +2363,7 @@ BaseExecuteAddSession(UCHAR *InBuffer, NTSTATUS SessionExecuteMethod(UCHAR *Buffer, ULONG BufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, OUT ULONG_PTR *byteswritten) { ULONG RequiredSize; WNODE_METHOD_ITEM *Method; @@ -2511,7 +2518,7 @@ SessionExecuteMethod(UCHAR *Buffer, NTSTATUS BaseExecuteMethod(UCHAR *Buffer, ULONG BufferSize, - FDO_DATA* fdoData, + XENIFACE_FDO* fdoData, OUT ULONG_PTR *byteswritten) { ULONG RequiredSize; WNODE_METHOD_ITEM *Method; @@ -2546,7 +2553,7 @@ BaseExecuteMethod(UCHAR *Buffer, NTSTATUS WmiExecuteMethod( - IN PFDO_DATA fdoData, + IN PXENIFACE_FDO fdoData, IN PIO_STACK_LOCATION stack, OUT ULONG_PTR *byteswritten ) @@ -2569,7 +2576,7 @@ WmiExecuteMethod( NTSTATUS GenerateSessionBlock(UCHAR *Buffer, ULONG BufferSize, - PFDO_DATA fdoData, + PXENIFACE_FDO fdoData, ULONG_PTR *byteswritten) { WNODE_ALL_DATA *node; ULONG RequiredSize; @@ -2685,7 +2692,7 @@ GenerateSessionBlock(UCHAR *Buffer, } NTSTATUS -GenerateBaseBlock( FDO_DATA *fdoData, +GenerateBaseBlock( XENIFACE_FDO *fdoData, UCHAR *Buffer, ULONG BufferSize, ULONG_PTR *byteswritten) { @@ -2719,7 +2726,7 @@ GenerateBaseBlock( FDO_DATA *fdoData, } NTSTATUS GenerateBaseInstance( - FDO_DATA *fdoData, + XENIFACE_FDO *fdoData, UCHAR *Buffer, ULONG BufferSize, ULONG_PTR *byteswritten) { @@ -2769,7 +2776,7 @@ GenerateBaseInstance( NTSTATUS GenerateSessionInstance(UCHAR *Buffer, ULONG BufferSize, - FDO_DATA *fdoData, + XENIFACE_FDO *fdoData, ULONG_PTR *byteswritten) { WNODE_SINGLE_INSTANCE *node; ULONG RequiredSize; @@ -2829,7 +2836,7 @@ GenerateSessionInstance(UCHAR *Buffer, NTSTATUS WmiQueryAllData( - IN PFDO_DATA fdoData, + IN PXENIFACE_FDO fdoData, IN PIO_STACK_LOCATION stack, OUT ULONG_PTR *byteswritten ) @@ -2857,7 +2864,7 @@ WmiQueryAllData( NTSTATUS WmiQuerySingleInstance( - IN PFDO_DATA fdoData, + IN PXENIFACE_FDO fdoData, IN PIO_STACK_LOCATION stack, OUT ULONG_PTR *byteswritten ) @@ -2882,7 +2889,7 @@ WmiQuerySingleInstance( NTSTATUS WmiRegInfo( - IN PFDO_DATA fdoData, + IN PXENIFACE_FDO fdoData, IN PIO_STACK_LOCATION stack, OUT ULONG_PTR *byteswritten ) @@ -2913,7 +2920,7 @@ WmiRegInfo( WMI_BUFFER, sizeof(WMIREGINFO), (UCHAR **)®info, WMI_BUFFER, entries * sizeof(WMIREGGUID), (UCHAR **)&guiddata, WMI_STRING, mofnamesz, &mofnameptr, - WMI_STRING, Globals.RegistryPath.Length+sizeof(USHORT), + WMI_STRING, DriverParameters.RegistryPath.Length+sizeof(USHORT), ®path, WMI_DONE)){ reginfo->BufferSize = RequiredSize; @@ -2925,7 +2932,7 @@ WmiRegInfo( reginfo->MofResourceName = (ULONG)((ULONG_PTR)mofnameptr - (ULONG_PTR)reginfo); WriteCountedUnicodeString(&mofname, mofnameptr); reginfo->RegistryPath = (ULONG)((ULONG_PTR)regpath - (ULONG_PTR)reginfo); - WriteCountedUnicodeString(&Globals.RegistryPath, regpath); + WriteCountedUnicodeString(&DriverParameters.RegistryPath, regpath); } reginfo->BufferSize = RequiredSize; @@ -2936,8 +2943,8 @@ WmiRegInfo( guid->InstanceCount = 1; guid->Guid = CitrixXenStoreBase_GUID; guid->Flags = WMIREG_FLAG_INSTANCE_PDO; - guid->Pdo = (ULONG_PTR)fdoData->UnderlyingPDO; - ObReferenceObject(fdoData->UnderlyingPDO); + guid->Pdo = (ULONG_PTR)fdoData->PhysicalDeviceObject; + ObReferenceObject(fdoData->PhysicalDeviceObject); guid = ®info->WmiRegGuid[1]; guid->Guid = CitrixXenStoreSession_GUID; @@ -2948,16 +2955,16 @@ WmiRegInfo( guid->Guid = CitrixXenStoreWatchEvent_GUID; guid->Flags = WMIREG_FLAG_INSTANCE_PDO | WMIREG_FLAG_EVENT_ONLY_GUID ; - guid->Pdo = (ULONG_PTR)fdoData->UnderlyingPDO; - ObReferenceObject(fdoData->UnderlyingPDO); + guid->Pdo = (ULONG_PTR)fdoData->PhysicalDeviceObject; + ObReferenceObject(fdoData->PhysicalDeviceObject); guid = ®info->WmiRegGuid[3]; guid->InstanceCount = 1; guid->Guid = CitrixXenStoreUnsuspendedEvent_GUID; guid->Flags = WMIREG_FLAG_INSTANCE_PDO | WMIREG_FLAG_EVENT_ONLY_GUID ; - guid->Pdo = (ULONG_PTR)fdoData->UnderlyingPDO; - ObReferenceObject(fdoData->UnderlyingPDO); + guid->Pdo = (ULONG_PTR)fdoData->PhysicalDeviceObject; + ObReferenceObject(fdoData->PhysicalDeviceObject); *byteswritten = RequiredSize; @@ -2966,7 +2973,7 @@ WmiRegInfo( NTSTATUS WmiRegInfoEx( - IN PFDO_DATA fdoData, + IN PXENIFACE_FDO fdoData, IN PIO_STACK_LOCATION stack, OUT ULONG_PTR *byteswritten ) @@ -2980,34 +2987,40 @@ WmiRegInfoEx( NTSTATUS WmiProcessMinorFunction( - IN PDEVICE_OBJECT DeviceObject, + IN PXENIFACE_FDO fdoData, IN PIRP Irp ) { PIO_STACK_LOCATION stack; UCHAR MinorFunction; - PFDO_DATA fdoData; - fdoData = (PFDO_DATA)DeviceObject->DeviceExtension; + stack = IoGetCurrentIrpStackLocation(Irp); + if (stack->Parameters.WMI.ProviderId != (ULONG_PTR)fdoData->Dx->DeviceObject) { + XenIfaceDebugPrint(TRACE,"ProviderID %p %p", stack->Parameters.WMI.ProviderId, fdoData->PhysicalDeviceObject); + return STATUS_NOT_SUPPORTED; + } + else { + XenIfaceDebugPrint(TRACE,"ProviderID Match %p %p", stack->Parameters.WMI.ProviderId, fdoData->PhysicalDeviceObject); + } MinorFunction = stack->MinorFunction; switch (MinorFunction) { case IRP_MN_CHANGE_SINGLE_INSTANCE: - return WmiChangeSingleInstance(DeviceObject, stack); + return WmiChangeSingleInstance(fdoData, stack); case IRP_MN_CHANGE_SINGLE_ITEM: - return WmiChangeSingleItem(DeviceObject, stack); + return WmiChangeSingleItem(fdoData, stack); case IRP_MN_DISABLE_COLLECTION: - return WmiDisableCollection(DeviceObject, stack); + return WmiDisableCollection(fdoData, stack); case IRP_MN_DISABLE_EVENTS: - return WmiDisableEvents(DeviceObject, stack); + return WmiDisableEvents(fdoData, stack); case IRP_MN_ENABLE_COLLECTION: - return WmiEnableCollection(DeviceObject, stack); + return WmiEnableCollection(fdoData, stack); case IRP_MN_ENABLE_EVENTS: - return WmiEnableEvents(DeviceObject, stack); + return WmiEnableEvents(fdoData, stack); case IRP_MN_EXECUTE_METHOD: return WmiExecuteMethod(fdoData, stack, &Irp->IoStatus.Information); case IRP_MN_QUERY_ALL_DATA: @@ -3023,47 +3036,32 @@ WmiProcessMinorFunction( } } - NTSTATUS XenIfaceSystemControl( - __in PDEVICE_OBJECT DeviceObject, + __in PXENIFACE_FDO fdoData, __inout PIRP Irp ) { - PFDO_DATA fdoData; - NTSTATUS status; - - fdoData = (PFDO_DATA) DeviceObject->DeviceExtension; - - XenIfaceIoIncrement (fdoData); + NTSTATUS status; - if (Deleted == fdoData->DevicePnPState) - { - Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE; - - IoCompleteRequest (Irp, IO_NO_INCREMENT); - - XenIfaceIoDecrement (fdoData); - return status; - } - status = WmiProcessMinorFunction(DeviceObject, Irp); + status = WmiProcessMinorFunction(fdoData, Irp); if (status != STATUS_NOT_SUPPORTED) { - Irp->IoStatus.Status = status; + Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } else { IoSkipCurrentIrpStackLocation(Irp); - status = IoCallDriver(fdoData->NextLowerDriver, Irp); + status = IoCallDriver(fdoData->LowerDeviceObject, Irp); } - XenIfaceIoDecrement(fdoData); return(status); } + PCHAR WMIMinorFunctionString ( __in UCHAR MinorFunction diff --git a/src/xeniface/wmi.h b/src/xeniface/wmi.h index 561ca09..f708788 100644 --- a/src/xeniface/wmi.h +++ b/src/xeniface/wmi.h @@ -34,24 +34,32 @@ #define _XEVTCHN_WMI_H #include -#include "xeniface.h" +#include "driver.h" #include "wmi_generated.h" NTSTATUS WmiProcessMinorFunction( - IN PDEVICE_OBJECT Pdo, + IN PXENIFACE_FDO Fdo, IN PIRP Irp ); NTSTATUS WmiInit( - PFDO_DATA FdoData + PXENIFACE_FDO FdoData ); NTSTATUS WmiFinalise( - PFDO_DATA FdoData + PXENIFACE_FDO FdoData ); +NTSTATUS XenIfaceSystemControl( + __in PXENIFACE_FDO fdoData, + __inout PIRP Irp + ); + +void FireSuspendEvent( + IN OUT PXENIFACE_FDO fdoData + ); #endif diff --git a/src/xeniface/xeniface.h b/src/xeniface/xeniface.h deleted file mode 100644 index 74b6f6e..0000000 --- a/src/xeniface/xeniface.h +++ /dev/null @@ -1,556 +0,0 @@ -/* 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. - */ - -#if !defined(_XENIFACE_H_) -#define _XENIFACE_H_ - -#include - -#include - -#include // required for GUID definitions - -#pragma warning(disable:4100 4057) - -#define NTSTRSAFE_LIB -#include - -#include "..\..\include\store_interface.h" -#include "..\..\include\shared_info_interface.h" -#include "..\..\include\suspend_interface.h" - -#define XENIFACE_POOL_TAG (ULONG) 'XIfc' -#define XENIFACE_FDO_INSTANCE_SIGNATURE (ULONG) 'XenI' - -#define XENIFACE_WAIT_WAKE_ENABLE L"WaitWakeEnabled" - -#define XENIFACE_POWER_SAVE_ENABLE L"PowerSaveEnabled" - -#if !defined(InterlockedOr) && (_WIN32_WINNT==0x0500) -#define InterlockedOr _InterlockedOr -#endif - -#if !defined(EVENT_TRACING) -#define ERROR 0 -#define WARNING 1 -#define TRACE 2 -#define INFO 3 - -VOID -XenIfaceDebugPrint ( - __in ULONG DebugPrintLevel, - __in PCCHAR DebugMessage, - ... - ); - -#else -#define WPP_CONTROL_GUIDS \ - WPP_DEFINE_CONTROL_GUID(XenIface,(C56386BD,7C67,4264,B8D9,C4A53B93CBEB), \ - WPP_DEFINE_BIT(ERROR) /* bit 0 = 0x00000001 */ \ - WPP_DEFINE_BIT(WARNING) /* bit 1 = 0x00000002 */ \ - WPP_DEFINE_BIT(TRACE) /* bit 2 = 0x00000004 */ \ - WPP_DEFINE_BIT(INFO) /* bit 3 = 0x00000008 */ \ - WPP_DEFINE_BIT(DebugFlag04) /* bit 4 = 0x00000010 */ \ - WPP_DEFINE_BIT(DebugFlag05) /* bit 5 = 0x00000020 */ \ - WPP_DEFINE_BIT(DebugFlag06) /* bit 6 = 0x00000040 */ \ - WPP_DEFINE_BIT(DebugFlag07) /* bit 7 = 0x00000080 */ \ - WPP_DEFINE_BIT(DebugFlag08) /* bit 8 = 0x00000100 */ \ - WPP_DEFINE_BIT(DebugFlag09) /* bit 9 = 0x00000200 */ \ - WPP_DEFINE_BIT(DebugFlag10) /* bit 10 = 0x00000400 */ \ - WPP_DEFINE_BIT(DebugFlag11) /* bit 11 = 0x00000800 */ \ - WPP_DEFINE_BIT(DebugFlag12) /* bit 12 = 0x00001000 */ \ - WPP_DEFINE_BIT(DebugFlag13) /* bit 13 = 0x00002000 */ \ - WPP_DEFINE_BIT(DebugFlag14) /* bit 14 = 0x00004000 */ \ - WPP_DEFINE_BIT(DebugFlag15) /* bit 15 = 0x00008000 */ \ - WPP_DEFINE_BIT(DebugFlag16) /* bit 16 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag17) /* bit 17 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag18) /* bit 18 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag19) /* bit 19 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag20) /* bit 20 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag21) /* bit 21 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag22) /* bit 22 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag23) /* bit 23 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag24) /* bit 24 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag25) /* bit 25 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag26) /* bit 26 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag27) /* bit 27 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag28) /* bit 28 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag29) /* bit 29 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag30) /* bit 30 = 0x00000000 */ \ - WPP_DEFINE_BIT(DebugFlag31) /* bit 31 = 0x00000000 */ \ - ) -#endif - -typedef struct _GLOBALS { - - UNICODE_STRING RegistryPath; - -} GLOBALS; - -extern GLOBALS Globals; - -#define XENIFACE_WMI_STD_I8042 0 -#define XENIFACE_WMI_STD_SERIAL 1 -#define XENIFACE_WMI_STD_PARALEL 2 -#define XENIFACE_WMI_STD_USB 3 - -typedef struct _XENIFACE_WMI_STD_DATA { - - UINT32 ConnectorType; - - UINT32 Capacity; - - UINT32 ErrorCount; - - UINT32 Controls; - - UINT32 DebugPrintLevel; - -} XENIFACE_WMI_STD_DATA, * PXENIFACE_WMI_STD_DATA; - -typedef enum _DEVICE_PNP_STATE { - - NotStarted = 0, - Started, - StopPending, - Stopped, - RemovePending, - SurpriseRemovePending, - Deleted - -} DEVICE_PNP_STATE; - -#define INITIALIZE_PNP_STATE(_Data_) \ - (_Data_)->DevicePnPState = NotStarted;\ - (_Data_)->PreviousPnPState = NotStarted; - -#define SET_NEW_PNP_STATE(_Data_, _state_) \ - (_Data_)->PreviousPnPState = (_Data_)->DevicePnPState;\ - (_Data_)->DevicePnPState = (_state_); - -#define RESTORE_PREVIOUS_PNP_STATE(_Data_) \ - (_Data_)->DevicePnPState = (_Data_)->PreviousPnPState;\ - -typedef enum _QUEUE_STATE { - - HoldRequests = 0, - AllowRequests, - FailRequests - -} QUEUE_STATE; - -typedef enum { - - WAKESTATE_DISARMED = 1, - WAKESTATE_WAITING = 2, - WAKESTATE_WAITING_CANCELLED = 3, - WAKESTATE_ARMED = 4, - WAKESTATE_ARMING_CANCELLED = 5, - WAKESTATE_COMPLETING = 7 -} WAKESTATE; - -typedef struct _FDO_DATA -{ - - - ULONG Signature; - - PDEVICE_OBJECT Self; - - PDEVICE_OBJECT UnderlyingPDO; - - PDEVICE_OBJECT NextLowerDriver; - - DEVICE_PNP_STATE DevicePnPState; - - DEVICE_PNP_STATE PreviousPnPState; - - UNICODE_STRING InterfaceName; - - - QUEUE_STATE QueueState; - - LIST_ENTRY NewRequestsQueue; - - KSPIN_LOCK QueueLock; - - KEVENT RemoveEvent; - - KEVENT StopEvent; - - ULONG OutstandingIO; - - - - BOOLEAN DontDisplayInUI; - - SYSTEM_POWER_STATE SystemPowerState; - - DEVICE_POWER_STATE DevicePowerState; - - WMILIB_CONTEXT WmiLibInfo; - - XENIFACE_WMI_STD_DATA StdDeviceData; - - DEVICE_CAPABILITIES DeviceCaps; - - PIRP PendingSIrp; - - BOOLEAN AllowIdleDetectionRegistration; - - BOOLEAN AllowWakeArming; - - - WAKESTATE WakeState; - - PIRP WakeIrp; - - KEVENT WakeCompletedEvent; - - KEVENT WakeDisableEnableLock; - - UNICODE_STRING SuggestedInstanceName; - - USHORT Sessions; - - FAST_MUTEX SessionLock; - - LIST_ENTRY SessionHead; - - PXENBUS_SUSPEND_CALLBACK SuspendHandler; - -#define MAX_SESSIONS (65536) - - int WmiReady; - - PXENBUS_SUSPEND_INTERFACE SuspendInterface; - - PXENBUS_STORE_INTERFACE StoreInterface; - - PXENBUS_SHARED_INFO_INTERFACE SharedInfoInterface; - - BOOLEAN InterfacesAcquired; - - PKTHREAD registryThread; - KEVENT registryWriteEvent; - KEVENT registryThreadEndEvent; - -} FDO_DATA, *PFDO_DATA; - -#define CLRMASK(x, mask) ((x) &= ~(mask)); -#define SETMASK(x, mask) ((x) |= (mask)); - - -DRIVER_INITIALIZE DriverEntry; - -DRIVER_ADD_DEVICE XenIfaceAddDevice; - -__drv_dispatchType(IRP_MJ_PNP) -DRIVER_DISPATCH XenIfaceDispatchPnp; - -__drv_dispatchType(IRP_MJ_POWER) -DRIVER_DISPATCH XenIfaceDispatchPower; - -__drv_dispatchType(IRP_MJ_DEVICE_CONTROL) -__drv_dispatchType(IRP_MJ_READ) -__drv_dispatchType(IRP_MJ_WRITE) -DRIVER_DISPATCH XenIfaceDispatchIO; - -__drv_dispatchType(IRP_MJ_CREATE) -DRIVER_DISPATCH XenIfaceCreate; - -__drv_dispatchType(IRP_MJ_CLOSE) -DRIVER_DISPATCH XenIfaceClose; - -__drv_dispatchType(IRP_MJ_CLEANUP) -DRIVER_DISPATCH XenIfaceCleanup; - -__drv_dispatchType(IRP_MJ_SYSTEM_CONTROL) -DRIVER_DISPATCH XenIfaceSystemControl; - -DRIVER_DISPATCH XenIfaceDispatchIoctl; - -DRIVER_DISPATCH XenIfaceReadWrite; - -DRIVER_DISPATCH XenIfaceSendIrpSynchronously; - -DRIVER_DISPATCH XenIfaceCanStopDevice; - -DRIVER_DISPATCH XenIfaceCanRemoveDevice; - -DRIVER_UNLOAD XenIfaceUnload; - -DRIVER_CANCEL XenIfaceCancelQueued; - -IO_COMPLETION_ROUTINE XenIfaceDispatchPnpComplete; - -NTSTATUS -XenIfaceStartDevice ( - __in PFDO_DATA FdoData, - __in PIRP Irp - ); - -LONG -XenIfaceIoIncrement ( - __in PFDO_DATA FdoData - ); - -LONG -XenIfaceIoDecrement ( - __in PFDO_DATA FdoData - ); - -NTSTATUS -XenIfaceGetDeviceCapabilities( - __in PDEVICE_OBJECT DeviceObject, - __in PDEVICE_CAPABILITIES DeviceCapabilities - ); - -NTSTATUS -XenIfaceSetWmiDataItem( - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp, - __in ULONG GuidIndex, - __in ULONG InstanceIndex, - __in ULONG DataItemId, - __in ULONG BufferSize, - __in_bcount(BufferSize) PUCHAR Buffer - ); - -NTSTATUS -XenIfaceSetWmiDataBlock( - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp, - __in ULONG GuidIndex, - __in ULONG InstanceIndex, - __in ULONG BufferSize, - __in_bcount(BufferSize) PUCHAR Buffer - ); - -NTSTATUS -XenIfaceQueryWmiDataBlock( - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp, - __in ULONG GuidIndex, - __in ULONG InstanceIndex, - __in ULONG InstanceCount, - __inout PULONG InstanceLengthArray, - __in ULONG BufferAvail, - __out_bcount(BufferAvail) PUCHAR Buffer - ); - -NTSTATUS -XenIfaceQueryWmiRegInfo( - __in PDEVICE_OBJECT DeviceObject, - __out ULONG *RegFlags, - __out PUNICODE_STRING InstanceName, - __out PUNICODE_STRING *RegistryPath, - __out PUNICODE_STRING MofResourceName, - __out PDEVICE_OBJECT *Pdo - ); - -PCHAR -WMIMinorFunctionString ( - __in UCHAR MinorFunction -); - -NTSTATUS -GetDeviceFriendlyName( - __in PDEVICE_OBJECT Pdo, - __inout PUNICODE_STRING DeviceName - ); - -NTSTATUS -XenIfaceWmiRegistration( - __in PFDO_DATA FdoData -); - -NTSTATUS -XenIfaceWmiDeRegistration( - __in PFDO_DATA FdoData -); - -NTSTATUS -XenIfaceReturnResources ( - __in PDEVICE_OBJECT DeviceObject - ); - -NTSTATUS -XenIfaceQueueRequest( - __in PFDO_DATA FdoData, - __in PIRP Irp - ); - - -VOID -XenIfaceProcessQueuedRequests( - __in PFDO_DATA FdoData - ); - -NTSTATUS -XenIfaceFunctionControl( - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp, - __in ULONG GuidIndex, - __in WMIENABLEDISABLECONTROL Function, - __in BOOLEAN Enable - ); - -NTSTATUS -XenIfaceDispatchWaitWake( - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp - ); - -NTSTATUS -XenIfaceSetWaitWakeEnableState( - __in PFDO_DATA FdoData, - __in BOOLEAN WakeState - ); - -BOOLEAN -XenIfaceGetWaitWakeEnableState( - __in PFDO_DATA FdoData - ); - -VOID -XenIfaceAdjustCapabilities( - __in PDEVICE_CAPABILITIES DeviceCapabilities - ); - -BOOLEAN -XenIfaceArmForWake( - __in PFDO_DATA FdoData, - __in BOOLEAN DeviceStateChange - ); - -VOID -XenIfaceDisarmWake( - __in PFDO_DATA FdoData, - __in BOOLEAN DeviceStateChange - ); - -NTSTATUS -XenIfaceWaitWakeIoCompletionRoutine( - __in PDEVICE_OBJECT DeviceObject, - __in PIRP Irp, - __in PVOID Context - ); - -VOID -XenIfaceWaitWakePoCompletionRoutine( - __in PDEVICE_OBJECT DeviceObject, - __in UCHAR MinorFunction, - __in POWER_STATE PowerState, - __in PVOID PowerContext, - __in PIO_STATUS_BLOCK IoStatus - ); - -VOID -XenIfacePassiveLevelReArmCallbackWorker( - __in PDEVICE_OBJECT DeviceObject, - __in PVOID Context - ); - -VOID -XenIfacePassiveLevelClearWaitWakeEnableState( - __in PDEVICE_OBJECT DeviceObject, - __in PVOID Context - ); - -VOID -XenIfaceQueuePassiveLevelCallback( - __in PFDO_DATA FdoData, - __in PIO_WORKITEM_ROUTINE CallbackFunction - ); - -VOID -XenIfaceRegisterForIdleDetection( - __in PFDO_DATA FdoData, - __in BOOLEAN DeviceStateChange - ); - -VOID -XenIfaceDeregisterIdleDetection( - __in PFDO_DATA FdoData, - __in BOOLEAN DeviceStateChange - ); - -NTSTATUS -XenIfaceSetPowerSaveEnableState( - __in PFDO_DATA FdoData, - __in BOOLEAN State - ); - -BOOLEAN -XenIfaceGetPowerSaveEnableState( - __in PFDO_DATA FdoData - ); - -VOID -XenIfacePowerUpDevice( - __in PFDO_DATA FdoData - ); - -PCHAR -PnPMinorFunctionString ( - __in UCHAR MinorFunction -); - -NTSTATUS -FdoQueryInterfaces( - IN FDO_DATA* Fdo - ); -void -FdoReleaseInterfaces( - IN FDO_DATA* Fdo - ) -; - -void -FdoInitialiseXSRegistryEntries( - IN FDO_DATA* Fdo - ) -; - -void -FireSuspendEvent( - PFDO_DATA fdoData -); - - - -void SessionsSuspendAll(FDO_DATA *fdoData); - -void SessionsResumeAll(FDO_DATA *fdoData); -#endif // _XENIFACE_H_ - -