]> xenbits.xensource.com Git - pvdrivers/win/xeniface.git/commitdiff
Initial commit of fully open xeniface code
authorBen Chalmers <Ben.Chalmers@citrix.com>
Fri, 5 Jul 2013 13:48:20 +0000 (14:48 +0100)
committerBen Chalmers <Ben.Chalmers@citrix.com>
Mon, 8 Jul 2013 09:07:45 +0000 (10:07 +0100)
Signed-off-by: Ben Chalmers <Ben.Chalmers@citrix.com>
28 files changed:
CHANGELOG [new file with mode: 0644]
INSTALL.md [new file with mode: 0644]
MAINTAINERS [new file with mode: 0644]
README.md [new file with mode: 0644]
build.py
include/util.h [new file with mode: 0644]
include/version.h [deleted file]
kdfiles.py [new file with mode: 0644]
proj/package/package.vcxproj.user [new file with mode: 0644]
proj/xeniface/xeniface.vcxproj
proj/xeniface/xeniface.vcxproj.user [new file with mode: 0644]
src/xeniface.inf
src/xeniface/assert.h [new file with mode: 0644]
src/xeniface/driver.c [new file with mode: 0644]
src/xeniface/driver.h [new file with mode: 0644]
src/xeniface/fdo.c [new file with mode: 0644]
src/xeniface/fdo.h [new file with mode: 0644]
src/xeniface/ioctls.c
src/xeniface/ioctls.h
src/xeniface/log.h [new file with mode: 0644]
src/xeniface/mutex.h [new file with mode: 0644]
src/xeniface/names.h [new file with mode: 0644]
src/xeniface/thread.c [new file with mode: 0644]
src/xeniface/thread.h [new file with mode: 0644]
src/xeniface/types.h [new file with mode: 0644]
src/xeniface/wmi.c
src/xeniface/wmi.h
src/xeniface/xeniface.h [deleted file]

diff --git a/CHANGELOG b/CHANGELOG
new file mode 100644 (file)
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 (file)
index 0000000..bfa325c
--- /dev/null
@@ -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 (file)
index 0000000..4009d48
--- /dev/null
@@ -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 <ben.chalmers@citrix.com>
+
+* Paul Durrant <paul.durrant@citrix.com>
+
+* Owen Smith <owen.smith@citrix.com>
+
diff --git a/README.md b/README.md
new file mode 100644 (file)
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
+
index 81b6a8ab5114a456e13c180033c5e8c1194bc1a6..5a850f43dda97b0487a2a3d7ccd10e74d710925b 100644 (file)
--- 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 (file)
index 0000000..723123b
--- /dev/null
@@ -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 <ntddk.h>
+
+#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 (file)
index 521b86f..0000000
+++ /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 (file)
index 0000000..27fd5bd
--- /dev/null
@@ -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 (file)
index 0000000..c0fb6de
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <SignMode>ProductionSign</SignMode>\r
+    <ProductionCertificate>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</ProductionCertificate>\r
+    <TimeStampServer>http://timestamp.verisign.com/scripts/timstamp.dll</TimeStampServer>\r
+  </PropertyGroup>\r
+</Project>
\ No newline at end of file
index f4a29ed3bf76d6a57e87fc3d7e8661eadc38cf3a..bf914482803b67d5dcf92a0186ddeac13f83c4e9 100644 (file)
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
   <ImportGroup Label="ExtensionSettings">
-    <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.props" />
   </ImportGroup>
   <ImportGroup Label="PropertySheets">
     <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
   </ItemDefinitionGroup>
   <ItemGroup>
     <FilesToPackage Include="$(TargetPath)" />
-    <FilesToPackage Include="$(OutDir)$(TargetName).pdb" />  
+    <FilesToPackage Include="$(OutDir)$(TargetName).pdb" />
     <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="../../src/xeniface/ioctls.c" />
-    <ClCompile Include="../../src/xeniface/power.c" />
     <ClCompile Include="../../src/xeniface/wmi.c" />
-    <ClCompile Include="../../src/xeniface/xeniface.c" />
+    <ClCompile Include="..\..\src\xeniface\driver.c" />
+    <ClCompile Include="..\..\src\xeniface\fdo.c" />
+    <ClCompile Include="..\..\src\xeniface\thread.c" />
   </ItemGroup>
   <ItemGroup>
     <Mofcomp Include="../../src/xeniface/wmi.mof">
-        <CreateBinaryMofFile>$(IntDir)/wmi.bmf</CreateBinaryMofFile>
+      <CreateBinaryMofFile>$(IntDir)/wmi.bmf</CreateBinaryMofFile>
     </Mofcomp>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <None Include="..\package\package.vcxproj" />
   </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="..\..\include\util.h" />
+    <ClInclude Include="..\..\src\xeniface\assert.h" />
+    <ClInclude Include="..\..\src\xeniface\driver.h" />
+    <ClInclude Include="..\..\src\xeniface\fdo.h" />
+    <ClInclude Include="..\..\src\xeniface\ioctls.h" />
+    <ClInclude Include="..\..\src\xeniface\log.h" />
+    <ClInclude Include="..\..\src\xeniface\mutex.h" />
+    <ClInclude Include="..\..\src\xeniface\names.h" />
+    <ClInclude Include="..\..\src\xeniface\thread.h" />
+    <ClInclude Include="..\..\src\xeniface\types.h" />
+    <ClInclude Include="..\..\src\xeniface\wmi.h" />
+  </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
-    <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
   </ImportGroup>
 </Project>
diff --git a/proj/xeniface/xeniface.vcxproj.user b/proj/xeniface/xeniface.vcxproj.user
new file mode 100644 (file)
index 0000000..c0fb6de
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <PropertyGroup>\r
+    <SignMode>ProductionSign</SignMode>\r
+    <ProductionCertificate>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</ProductionCertificate>\r
+    <TimeStampServer>http://timestamp.verisign.com/scripts/timstamp.dll</TimeStampServer>\r
+  </PropertyGroup>\r
+</Project>
\ No newline at end of file
index 92eb3bb432daaa6c4fb411fd94cba6a6c9502116..ff77ab75d10e91e733e7b635b699c42516d02f45 100644 (file)
@@ -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.\r
+; All rights reserved.\r
+;\r
+; Redistribution and use in source and binary forms, \r
+; with or without modification, are permitted provided \r
+; that the following conditions are met:\r
+;\r
+; *   Redistributions of source code must retain the above \r
+;     copyright notice, this list of conditions and the \r
+;     following disclaimer.\r
+; *   Redistributions in binary form must reproduce the above \r
+;     copyright notice, this list of conditions and the \r
+;     following disclaimer in the documentation and/or other \r
+;     materials provided with the distribution.\r
+;\r
+; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \r
+; CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, \r
+; INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \r
+; MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE \r
+; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR \r
+; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \r
+; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \r
+; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR \r
+; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
+; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, \r
+; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING \r
+; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
+; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF \r
+; SUCH DAMAGE.\r
+\r
+[Version]\r
+Signature="$WINDOWS NT$"\r
+Class=System\r
+ClassGUID={4d36e97d-e325-11ce-bfc1-08002be10318} \r
+Provider=%Citrix%\r
+DriverVer=09/07/2011,6.0.0.0\r
+CatalogFile=xeniface.cat\r
+\r
+[DestinationDirs]\r
+DefaultDestDir = 12\r
+\r
+;*****************************************\r
+; Xeniface Device  Install Section\r
+;*****************************************\r
+\r
+[Manufacturer]\r
+%Citrix%=Citrix,NT$ARCH$\r
+\r
+[Citrix.NT$ARCH$]\r
+; DisplayName               Section           DeviceId\r
+; -----------               -------           --------\r
+%XenIfaceDevice.DeviceDesc%=XenIface_Device, XENBUS\CLASS_IFACE&REV_02\r
+\r
+[XenIface_Device.NT$ARCH$]\r
+CopyFiles=XenIface_Device.NT.Copy\r
+\r
+[XenIFace_Device.NT.Copy]\r
+xeniface.sys\r
+\r
+;-------------- Service installation\r
+\r
+[Xeniface_Device.NT$ARCH$.Services]\r
+AddService = xeniface, %SPSVCINST_ASSOCSERVICE%, xeniface_Service_Inst\r
+\r
+[xeniface_Service_Inst]\r
+DisplayName    = %xeniface.SVCDESC%\r
+ServiceType    = 1               ; SERVICE_KERNEL_DRIVER\r
+StartType      = 3               ; SERVICE_DEMAND_START \r
+ErrorControl   = 1               ; SERVICE_ERROR_NORMAL\r
+ServiceBinary  = %12%\xeniface.sys\r
+LoadOrderGroup = Extended Base\r
+\r
+\r
+[SourceDisksNames]\r
+1 = %DiskId1%,,,""\r
+\r
+[SourceDisksFiles]\r
+xeniface.sys  = 1,,\r
+\r
+[Strings]\r
+SPSVCINST_ASSOCSERVICE= 0x00000002\r
+Citrix= "Citrix Systems, Inc." \r
+ClassName = "XenIface"\r
+DiskId1 = "Citrix Tools for Virtual Machines"\r
+XenIfaceDevice.DeviceDesc = "Citrix Xen Interface"\r
+xeniface.SVCDESC = "Citrix Xen Interface Device Driver"\r
+\r
diff --git a/src/xeniface/assert.h b/src/xeniface/assert.h
new file mode 100644 (file)
index 0000000..89bec5f
--- /dev/null
@@ -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 <ntddk.h>
+
+#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 (file)
index 0000000..281ebdf
--- /dev/null
@@ -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 <ntddk.h>
+//#include <util.h>
+#include <version.h>
+
+#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 (file)
index 0000000..93ac645
--- /dev/null
@@ -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 <ntstrsafe.h>
+
+#pragma warning(disable:4100 4057)
+
+#include <wmilib.h>
+#include <ntddk.h>
+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 (file)
index 0000000..8c103fa
--- /dev/null
@@ -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 <ntddk.h>
+#include <wdmguid.h>
+#include <ntstrsafe.h>
+#include <stdlib.h>
+
+#include <store_interface.h>
+
+#include <suspend_interface.h>
+
+
+#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 (file)
index 0000000..272aeb9
--- /dev/null
@@ -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 <ntddk.h>
+#include <store_interface.h>
+#include <suspend_interface.h>
+#include <shared_info_interface.h>
+
+#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
index 75936a3a6b24c9992272d599c4c8fa93f81fa063..928dfedfc43b0c47b5eb53a447892427724c5a5d 100644 (file)
  */
 
 
-#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;
 }
 
index 873fbbc017f9cd64f32b09d1ea92453d9ae748d0..63de9eb489ebda2ebb44efc0713532f0ac9a4f13 100644 (file)
@@ -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 (file)
index 0000000..39d9756
--- /dev/null
@@ -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 <ntddk.h>
+#include <stdarg.h>
+
+#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 (file)
index 0000000..f436f13
--- /dev/null
@@ -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 <ntddk.h>
+
+#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 (file)
index 0000000..9d282f7
--- /dev/null
@@ -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 <ntddk.h>
+
+#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 (file)
index 0000000..51967ed
--- /dev/null
@@ -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 <ntddk.h>
+#include <util.h>
+
+#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 (file)
index 0000000..69f3c51
--- /dev/null
@@ -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 <ntddk.h>
+
+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 (file)
index 0000000..2339143
--- /dev/null
@@ -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
index 5a098bd172962408d02449168a532dfbbd618124..f0180ec76d1bdb8430eb54cc73a25b07cff346fa 100644 (file)
@@ -32,7 +32,6 @@
 
 #include <ntddk.h>
 #include <initguid.h>
-#include <wdmguid.h>
 #include <wmistr.h>
 #include <wmilib.h>
 #include <stdio.h>
 #define NTSTRSAFE_LIB
 #include<ntstrsafe.h>
 #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 **)&reginfo,
                         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), 
                                     &regpath,
                         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 = &reginfo->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 = &reginfo->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
index 561ca09a3bc9c6dcbd9f831f8719c58afc8289c7..f70878858c80562ae6b940fbdb0e0a1d1238beb7 100644 (file)
 #define _XEVTCHN_WMI_H
 
 #include <ntddk.h>
-#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 (file)
index 74b6f6e..0000000
+++ /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 <ntddk.h>
-
-#include <wmilib.h>
-
-#include <initguid.h> // required for GUID definitions
-
-#pragma warning(disable:4100 4057)
-
-#define NTSTRSAFE_LIB
-#include <ntstrsafe.h>
-
-#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_
-
-