]> xenbits.xensource.com Git - pvdrivers/win/xeniface.git/commitdiff
[CP-4696] Git repository created for xeniface
authorBen Chalmers <Ben.Chalmers@citrix.com>
Tue, 28 May 2013 11:10:07 +0000 (12:10 +0100)
committerBen Chalmers <Ben.Chalmers@citrix.com>
Tue, 28 May 2013 11:10:07 +0000 (12:10 +0100)
43 files changed:
LICENSE [new file with mode: 0644]
WmiDocumentation.txt [new file with mode: 0644]
build.py [new file with mode: 0644]
clean.py [new file with mode: 0644]
include/shared_info_interface.h [new file with mode: 0644]
include/store_interface.h [new file with mode: 0644]
include/suspend_interface.h [new file with mode: 0644]
include/version.h [new file with mode: 0644]
include/xeniface_ioctls.h [new file with mode: 0644]
kdfiles.sh [new file with mode: 0644]
proj/msbuild.bat [new file with mode: 0644]
proj/msbuild_dvl.bat [new file with mode: 0644]
proj/msbuild_sdv.bat [new file with mode: 0644]
proj/package/package.vcxproj [new file with mode: 0644]
proj/xeniface.sln [new file with mode: 0644]
proj/xeniface/xeniface.vcxproj [new file with mode: 0644]
sdv.py [new file with mode: 0644]
src/win32stubagent/NicInfo.cpp [new file with mode: 0644]
src/win32stubagent/NicInfo.h [new file with mode: 0644]
src/win32stubagent/TSInfo.cpp [new file with mode: 0644]
src/win32stubagent/TSInfo.h [new file with mode: 0644]
src/win32stubagent/WmiAccessor.cpp [new file with mode: 0644]
src/win32stubagent/WmiAccessor.h [new file with mode: 0644]
src/win32stubagent/XSAccessor.cpp [new file with mode: 0644]
src/win32stubagent/XSAccessor.h [new file with mode: 0644]
src/win32stubagent/XService.cpp [new file with mode: 0644]
src/win32stubagent/XService.h [new file with mode: 0644]
src/win32stubagent/messages.mc [new file with mode: 0644]
src/win32stubagent/stdafx.cpp [new file with mode: 0644]
src/win32stubagent/stdafx.h [new file with mode: 0644]
src/win32stubagent/vm_stats.h [new file with mode: 0644]
src/win32stubagent/w32xagent.rc [new file with mode: 0644]
src/win32stubagent/xen.ico [new file with mode: 0644]
src/xeniface.inf [new file with mode: 0644]
src/xeniface/ioctls.c [new file with mode: 0644]
src/xeniface/ioctls.h [new file with mode: 0644]
src/xeniface/wmi.c [new file with mode: 0644]
src/xeniface/wmi.h [new file with mode: 0644]
src/xeniface/wmi.mof [new file with mode: 0644]
src/xeniface/xeniface.h [new file with mode: 0644]
src/xeniface/xeniface.rc [new file with mode: 0644]
src/xeniface64.inf [new file with mode: 0644]
testwmi.vbs [new file with mode: 0644]

diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..00be666
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+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.
+
diff --git a/WmiDocumentation.txt b/WmiDocumentation.txt
new file mode 100644 (file)
index 0000000..40248a3
--- /dev/null
@@ -0,0 +1,131 @@
+The Windows Guest WMI Interface
+
+The Windows Guest WMI interface is intended to replace as the mechanism of choice for communicating with xenstore (and other hypervisor interfaces).  It is provided by the device driver xeniface.sys, which forms part of the Windows PV Drivers.   Access to this interface is available to those users which have been granted to the root\wmi namespace - which is to say the device driver namespace.  By default this is administrators only.
+
+The WMI Interface provides a base singleton object (CitrixXenStoreBase) which can be used to generate individual session objects (CitrixXenStoreSession).  These session objects represent individual applications (or functions of an application), and are the objects used to interact with xenstore - to read write, set and unset watches.  Sessions may also take advantage of the transaction semantics to ensure atomicity of xenstore operations.
+
+The lifetime of watches and transactions are limited by the lifetime of the session object which creates them 
+
+On driverload, one object is made available via WMI
+
+CitrixXenStoreBase
+
+A singleton object representing xenstore
+
+Properties:
+    Uint64 XenTime:
+        LocalTime as set by windows for the VM, and then adjusted by the 
+        Hypervisor's clock.
+Methods:
+    AddSession(String Id) returns SessionId:
+        Add a CitrixXenStoreSession object to the WMI namespace
+        The returned value (session id) is a unique value whcih can be used to
+        identify the session which has been created (in case multiple sessions
+        have the same string identifier)
+
+
+CitrixXenStoreSession
+
+Each instance represents a single session of communication with xenstore
+
+Properties:
+    String ID:
+        A string to identify the use of the session, which can be used to
+        determine if any sessions which have been left open can be closed
+    Uint32 SessionId:
+        An integer, unique amongst all sessions.  This is the same as the value
+        returned at the time the session was created with AddSession
+
+Methods:
+    StartTransaction:
+        Until the transaction is ended, all activities on this session
+        occur within a transaction (hence will not affect xenstore until
+        they are comitted)
+    CommitTransaction:
+        Attempt to commit the current session's transaction.  If this fails,
+        the transaction has not succeded, and may need to be retried.
+    EndTransaction:
+        Cancel the current transaction without committing
+
+    GetValue(String Pathname) returns String:  return the value stored at
+        the path PathName in xenStore
+    GetChildren(String Pathname) returns children{ NoOfChildNodes, string[NoOfChildNodes]ChildNodes}:  
+        For a given node (at PathName), this returns an object containing the 
+        number of child nodes, and an array of strings, where each string 
+        is the full pathname of a child node.
+    RemoveValue(string PathName): 
+        Removes an entry from xenstore (and, if they exist, all descendent 
+        entries)
+    SetValue(string Pathname, String value): 
+        set the value at a give pathname to value
+
+    Log(string): Outputs a log message to the hypervisor  
+
+    SetWatch(string pathname):
+        register your interest in receiving an event when a particular
+        xenstore entry (at pathname) changes.  Note that multiple changes of
+        the same entry occurring soon after one another may be coalesced 
+        into one WMI event (which will be received after all changes 
+        referenced by the coalesced event occur)
+
+    RemoveWatch(string pathname):
+        indicate you no longer want to receive an event when a particular
+        xenstore entry (at pathname) changes.
+
+    EndSession():
+         Terminate this session.  Remove the session object from the WMI namespace.
+        All watches and transactions associated with the session will be ended.
+
+About events:
+
+CitrixXenStoreWatchEvent:
+
+Event emitted when a particular xenstore entry has changed.  Registering your interest in receiving such an event can be done by calling CitrixXenStoreSession.SetWatch(pathname)
+
+    string EventId : The pathname of the xen store value which has changed
+
+CitrixXenStoreUnsuspendedEvent:
+
+    Event emitted whenever a vm resumes from being suspended.
+
+
+Use:
+
+    (The following example uses powershell to show how the xenstore wmi
+    interface can be scripted)
+
+    Locate the base object
+
+    $base = gwmi -n root\wmi -cl CitrixXenStoreBase
+
+    Create a session
+
+    $sid = $base.AddSession("MyNewSession")
+
+    $session = gwmi -n root\wmi -q "select * from CitrixXenStoreSession where SessionId=$($sid.SessionId)"
+
+    Write a value
+
+    $session.SetValue("data/TempValue","This is a string")
+
+    Read a value
+
+    $session.GetValue("data/TempValue").value
+
+    Remove a value
+
+    $session.RemoveValue("data/TempValue")
+
+    Examine Children
+
+    $session.GetChildren("data").children
+
+    Set Watch
+
+    $watch = Register-WMiEvent -n root\wmi -q "select * from CitrixXenStoreWatchEvent where EventId='data/TempValue'" -action {write $session.getvalue("data/TempValue") }
+
+    $session.setvalue("data/TempValue","HELLO")
+    $session.setvalue("data/TempValue","WORLD")
+
+    $watch.action.output
+
diff --git a/build.py b/build.py
new file mode 100644 (file)
index 0000000..81b6a8a
--- /dev/null
+++ b/build.py
@@ -0,0 +1,295 @@
+#!python -u
+
+# 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.
+
+
+import os, sys
+import datetime
+import re
+import glob
+import tarfile
+import subprocess
+
+def make_header():
+    now = datetime.datetime.now()
+
+    file = open('include\\version.h', 'w')
+    file.write('#define MAJOR_VERSION\t' + os.environ['MAJOR_VERSION'] + '\n')
+    file.write('#define MAJOR_VERSION_STR\t"' + os.environ['MAJOR_VERSION'] + '"\n')
+    file.write('\n')
+
+    file.write('#define MINOR_VERSION\t' + os.environ['MINOR_VERSION'] + '\n')
+    file.write('#define MINOR_VERSION_STR\t"' + os.environ['MINOR_VERSION'] + '"\n')
+    file.write('\n')
+
+    file.write('#define MICRO_VERSION\t' + os.environ['MICRO_VERSION'] + '\n')
+    file.write('#define MICRO_VERSION_STR\t"' + os.environ['MICRO_VERSION'] + '"\n')
+    file.write('\n')
+
+    file.write('#define BUILD_NUMBER\t' + os.environ['BUILD_NUMBER'] + '\n')
+    file.write('#define BUILD_NUMBER_STR\t"' + os.environ['BUILD_NUMBER'] + '"\n')
+    file.write('\n')
+
+    file.write('#define YEAR\t' + str(now.year) + '\n')
+    file.write('#define YEAR_STR\t"' + str(now.year) + '"\n')
+
+    file.write('#define MONTH\t' + str(now.month) + '\n')
+    file.write('#define MONTH_STR\t"' + str(now.month) + '"\n')
+
+    file.write('#define DAY\t' + str(now.day) + '\n')
+    file.write('#define DAY_STR\t"' + str(now.day) + '"\n')
+
+
+    file.close()
+
+
+def get_expired_symbols(age = 30):
+    path = os.path.join(os.environ['SYMBOL_SERVER'], '000Admin\\history.txt')
+
+    try:
+        file = open(path, 'r')
+    except IOError:
+        return []
+
+    threshold = datetime.datetime.utcnow() - datetime.timedelta(days = age)
+
+    expired = []
+
+    for line in file:
+        item = line.split(',')
+
+        if (re.match('add', item[1])):
+            id = item[0]
+            date = item[3].split('/')
+            time = item[4].split(':')
+
+            age = datetime.datetime(year = int(date[2]),
+                                    month = int(date[0]),
+                                    day = int(date[1]),
+                                    hour = int(time[0]),
+                                    minute = int(time[1]),
+                                    second = int(time[2]))
+            if (age < threshold):
+                expired.append(id)
+
+        elif (re.match('del', item[1])):
+            id = item[2].rstrip()
+            try:
+                expired.remove(id)
+            except ValueError:
+                pass
+
+    file.close()
+
+    return expired
+
+def get_configuration_name(debug):
+    configuration = 'WindowsVista'
+
+    if debug:
+        configuration += 'Debug'
+    else:
+        configuration += 'Release'
+
+    return configuration
+
+def get_configuration(debug):
+    configuration = 'Windows Vista'
+
+    if debug:
+        configuration += ' Debug'
+    else:
+        configuration += ' Release'
+
+    return configuration
+
+
+def get_target_path(arch, debug):
+    configuration = get_configuration_name(debug)
+
+    target = { 'x86': 'proj', 'x64': os.sep.join(['proj', 'x64']) }
+    target_path = os.sep.join([target[arch], configuration])
+
+    return target_path
+
+
+def shell(command):
+    print(command)
+    sys.stdout.flush()
+
+    pipe = os.popen(command, 'r', 1)
+
+    for line in pipe:
+        print(line.rstrip())
+
+    return pipe.close()
+
+
+class msbuild_failure(Exception):
+    def __init__(self, value):
+        self.value = value
+    def __str__(self):
+        return repr(self.value)
+
+def msbuild(name, arch, debug):
+    cwd = os.getcwd()
+    configuration = get_configuration(debug)
+
+    os.environ['SOLUTION'] = name
+
+    if arch == 'x86':
+        os.environ['PLATFORM'] = 'Win32'
+    elif arch == 'x64':
+        os.environ['PLATFORM'] = 'x64'
+
+    os.environ['CONFIGURATION'] = configuration
+    os.environ['TARGET'] = 'Build'
+
+    os.chdir('proj')
+    status = shell('msbuild.bat')
+    os.chdir(cwd)
+
+    if (status != None):
+        raise msbuild_failure(configuration)
+
+
+def symstore_del(age):
+    symstore_path = [os.environ['KIT'], 'Debuggers']
+    if os.environ['PROCESSOR_ARCHITECTURE'] == 'x86':
+        symstore_path.append('x86')
+    else:
+        symstore_path.append('x64')
+    symstore_path.append('symstore.exe')
+
+    symstore = os.path.join(*symstore_path)
+
+    for id in get_expired_symbols(age):
+        command=['"' + symstore + '"']
+        command.append('del')
+        command.append('/i')
+        command.append(str(id))
+        command.append('/s')
+        command.append(os.environ['SYMBOL_SERVER'])
+
+        shell(' '.join(command))
+
+def symstore_add(name, arch, debug):
+    cwd = os.getcwd()
+    configuration = get_configuration_name(debug)
+    target_path = get_target_path(arch, debug)
+
+    symstore_path = [os.environ['KIT'], 'Debuggers']
+    if os.environ['PROCESSOR_ARCHITECTURE'] == 'x86':
+        symstore_path.append('x86')
+    else:
+        symstore_path.append('x64')
+    symstore_path.append('symstore.exe')
+
+    symstore = os.path.join(*symstore_path)
+
+    version = '.'.join([os.environ['MAJOR_VERSION'],
+                        os.environ['MINOR_VERSION'],
+                        os.environ['MICRO_VERSION'],
+                        os.environ['BUILD_NUMBER']])
+
+    os.chdir(target_path)
+    command=['"' + symstore + '"']
+    command.append('add')
+    command.append('/s')
+    command.append(os.environ['SYMBOL_SERVER'])
+    command.append('/r')
+    command.append('/f')
+    command.append('*.pdb')
+    command.append('/t')
+    command.append(name)
+    command.append('/v')
+    command.append(version)
+
+    shell(' '.join(command))
+
+    os.chdir(cwd)
+
+def callfnout(cmd):
+    print(cmd)
+
+    sub = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+    output = sub.communicate()[0]
+    ret = sub.returncode
+
+    if ret != 0:
+        raise(Exception("Error %d in : %s" % (ret, cmd)))
+    print("------------------------------------------------------------")
+    return output.decode('utf-8')
+
+def archive(filename, files, tgz=False):
+    access='w'
+    if tgz:
+        access='w:gz'
+    tar = tarfile.open(filename, access)
+    for name in files :
+        try:
+            print('adding '+name)
+            tar.add(name)
+        except:
+            pass
+    tar.close()
+
+
+if __name__ == '__main__':
+    os.environ['MAJOR_VERSION'] = '7'
+    os.environ['MINOR_VERSION'] = '0'
+    os.environ['MICRO_VERSION'] = '0'
+
+    if 'BUILD_NUMBER' not in os.environ.keys():
+        os.environ['BUILD_NUMBER'] = '0'
+
+    if 'MERCURIAL_REVISION' in os.environ.keys():
+        revision = open('revision', 'w')
+        print(os.environ['MERCURIAL_REVISION'], file=revision)
+        revision.close()
+
+    debug = { 'checked': True, 'free': False }
+
+    make_header()
+
+    symstore_del(30)
+
+    msbuild('xeniface', 'x86', debug[sys.argv[1]])
+    msbuild('xeniface', 'x64', debug[sys.argv[1]])
+
+    symstore_add('xeniface', 'x86', debug[sys.argv[1]])
+    symstore_add('xeniface', 'x64', debug[sys.argv[1]])
+
+
+
+    listfile = callfnout(['hg','manifest'])
+    archive('xeniface\\source.tgz', listfile.splitlines(), tgz=True)
+    archive('xeniface.tar', ['xeniface', 'revision'])
diff --git a/clean.py b/clean.py
new file mode 100644 (file)
index 0000000..3846f03
--- /dev/null
+++ b/clean.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+
+# 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.
+
+
+import os, sys
+
+file = os.popen('hg status')
+
+for line in file:
+    item = line.split(' ')
+    if item[0] == '?':
+        path = ' '.join(item[1:]).rstrip()
+        print(path)
+        os.remove(path)
+
+file.close()
diff --git a/include/shared_info_interface.h b/include/shared_info_interface.h
new file mode 100644 (file)
index 0000000..af550c3
--- /dev/null
@@ -0,0 +1,122 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XENBUS_SHARED_INFO_INTERFACE_H
+#define _XENBUS_SHARED_INFO_INTERFACE_H
+
+#define DEFINE_SHARED_INFO_OPERATIONS                                                    \
+        SHARED_INFO_OPERATION(VOID,                                                      \
+                              Acquire,                                                   \
+                              (                                                          \
+                              IN  PXENBUS_SHARED_INFO_CONTEXT Context                    \
+                              )                                                          \
+                              )                                                          \
+        SHARED_INFO_OPERATION(VOID,                                                      \
+                              Release,                                                   \
+                              (                                                          \
+                              IN  PXENBUS_SHARED_INFO_CONTEXT Context                    \
+                              )                                                          \
+                              )                                                          \
+        SHARED_INFO_OPERATION(BOOLEAN,                                                   \
+                              EvtchnPoll,                                                \
+                              (                                                          \
+                              IN  PXENBUS_SHARED_INFO_CONTEXT Context,                   \
+                              IN  BOOLEAN                     (*Function)(PVOID, ULONG), \
+                              IN  PVOID                       Argument                   \
+                              )                                                          \
+                              )                                                          \
+        SHARED_INFO_OPERATION(VOID,                                                      \
+                              EvtchnAck,                                                 \
+                              (                                                          \
+                              IN  PXENBUS_SHARED_INFO_CONTEXT Context,                   \
+                              IN  ULONG                       Port                       \
+                              )                                                          \
+                              )                                                          \
+        SHARED_INFO_OPERATION(VOID,                                                      \
+                              EvtchnMask,                                                \
+                              (                                                          \
+                              IN  PXENBUS_SHARED_INFO_CONTEXT Context,                   \
+                              IN  ULONG                       Port                       \
+                              )                                                          \
+                              )                                                          \
+        SHARED_INFO_OPERATION(BOOLEAN,                                                   \
+                              EvtchnUnmask,                                              \
+                              (                                                          \
+                              IN  PXENBUS_SHARED_INFO_CONTEXT Context,                   \
+                              IN  ULONG                       Port                       \
+                              )                                                          \
+                              )                                                          \
+        SHARED_INFO_OPERATION(LARGE_INTEGER,                                             \
+                              GetTime,                                                   \
+                              (                                                          \
+                              IN  PXENBUS_SHARED_INFO_CONTEXT Context                    \
+                              )                                                          \
+                              )
+
+typedef struct _XENBUS_SHARED_INFO_CONTEXT  XENBUS_SHARED_INFO_CONTEXT, *PXENBUS_SHARED_INFO_CONTEXT;
+
+#define SHARED_INFO_OPERATION(_Type, _Name, _Arguments) \
+        _Type (*SHARED_INFO_ ## _Name) _Arguments;
+
+typedef struct _XENBUS_SHARED_INFO_OPERATIONS {
+    DEFINE_SHARED_INFO_OPERATIONS
+} XENBUS_SHARED_INFO_OPERATIONS, *PXENBUS_SHARED_INFO_OPERATIONS;
+
+#undef SHARED_INFO_OPERATION
+
+typedef struct _XENBUS_SHARED_INFO_INTERFACE XENBUS_SHARED_INFO_INTERFACE, *PXENBUS_SHARED_INFO_INTERFACE;
+
+// {05DC267C-36CA-44a3-A124-B9BA9FE3780B}
+DEFINE_GUID(GUID_SHARED_INFO_INTERFACE, 
+            0x5dc267c,
+            0x36ca,
+            0x44a3,
+            0xa1,
+            0x24,
+            0xb9,
+            0xba,
+            0x9f,
+            0xe3,
+            0x78,
+            0xb);
+
+#define SHARED_INFO_INTERFACE_VERSION   4
+
+#define SHARED_INFO_OPERATIONS(_Interface) \
+        (PXENBUS_SHARED_INFO_OPERATIONS *)((ULONG_PTR)(_Interface))
+
+#define SHARED_INFO_CONTEXT(_Interface) \
+        (PXENBUS_SHARED_INFO_CONTEXT *)((ULONG_PTR)(_Interface) + sizeof (PVOID))
+
+#define SHARED_INFO(_Operation, _Interface, ...) \
+        (*SHARED_INFO_OPERATIONS(_Interface))->SHARED_INFO_ ## _Operation((*SHARED_INFO_CONTEXT(_Interface)), __VA_ARGS__)
+
+#endif  // _XENBUS_SHARED_INFO_H
diff --git a/include/store_interface.h b/include/store_interface.h
new file mode 100644 (file)
index 0000000..6c3218e
--- /dev/null
@@ -0,0 +1,186 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XENBUS_STORE_INTERFACE_H
+#define _XENBUS_STORE_INTERFACE_H
+
+typedef struct _XENBUS_STORE_TRANSACTION    XENBUS_STORE_TRANSACTION, *PXENBUS_STORE_TRANSACTION;
+typedef struct _XENBUS_STORE_WATCH          XENBUS_STORE_WATCH, *PXENBUS_STORE_WATCH;
+
+#define DEFINE_STORE_OPERATIONS                                                 \
+        STORE_OPERATION(VOID,                                                   \
+                        Acquire,                                                \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context                 \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(VOID,                                                   \
+                        Release,                                                \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context                 \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(VOID,                                                   \
+                        Free,                                                   \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context,                \
+                        IN  PCHAR                       Value                   \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(NTSTATUS,                                               \
+                        Read,                                                   \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context,                \
+                        IN  PXENBUS_STORE_TRANSACTION   Transaction OPTIONAL,   \
+                        IN  PCHAR                       Prefix OPTIONAL,        \
+                        IN  PCHAR                       Node,                   \
+                        OUT PCHAR                       *Value                  \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(NTSTATUS,                                               \
+                        Write,                                                  \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context,                \
+                        IN  PXENBUS_STORE_TRANSACTION   Transaction OPTIONAL,   \
+                        IN  PCHAR                       Prefix OPTIONAL,        \
+                        IN  PCHAR                       Node,                   \
+                        IN  PCHAR                       Value                   \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(NTSTATUS,                                               \
+                        Printf,                                                 \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context,                \
+                        IN  PXENBUS_STORE_TRANSACTION   Transaction OPTIONAL,   \
+                        IN  PCHAR                       Prefix OPTIONAL,        \
+                        IN  PCHAR                       Node,                   \
+                        IN  const CHAR                  *Format,                \
+                        ...                                                     \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(NTSTATUS,                                               \
+                        Remove,                                                 \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context,                \
+                        IN  PXENBUS_STORE_TRANSACTION   Transaction OPTIONAL,   \
+                        IN  PCHAR                       Prefix OPTIONAL,        \
+                        IN  PCHAR                       Node                    \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(NTSTATUS,                                               \
+                        Directory,                                              \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context,                \
+                        IN  PXENBUS_STORE_TRANSACTION   Transaction OPTIONAL,   \
+                        IN  PCHAR                       Prefix OPTIONAL,        \
+                        IN  PCHAR                       Node,                   \
+                        OUT PCHAR                       *Value                  \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(NTSTATUS,                                               \
+                        TransactionStart,                                       \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context,                \
+                        OUT PXENBUS_STORE_TRANSACTION   *Transaction            \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(NTSTATUS,                                               \
+                        TransactionEnd,                                         \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context,                \
+                        IN  PXENBUS_STORE_TRANSACTION   Transaction,            \
+                        IN  BOOLEAN                     Commit                  \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(NTSTATUS,                                               \
+                        Watch,                                                  \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context,                \
+                        IN  PCHAR                       Prefix OPTIONAL,        \
+                        IN  PCHAR                       Node,                   \
+                        IN  PKEVENT                     Event,                  \
+                        OUT PXENBUS_STORE_WATCH         *Watch                  \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(NTSTATUS,                                               \
+                        Unwatch,                                                \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context,                \
+                        IN  PXENBUS_STORE_WATCH         Watch                   \
+                        )                                                       \
+                        )                                                       \
+        STORE_OPERATION(VOID,                                                   \
+                        Poll,                                                   \
+                        (                                                       \
+                        IN  PXENBUS_STORE_CONTEXT       Context                 \
+                        )                                                       \
+                        )
+
+typedef struct _XENBUS_STORE_CONTEXT    XENBUS_STORE_CONTEXT, *PXENBUS_STORE_CONTEXT;
+
+#define STORE_OPERATION(_Type, _Name, _Arguments) \
+        _Type (*STORE_ ## _Name) _Arguments;
+
+typedef struct _XENBUS_STORE_OPERATIONS {
+    DEFINE_STORE_OPERATIONS
+} XENBUS_STORE_OPERATIONS, *PXENBUS_STORE_OPERATIONS;
+
+#undef STORE_OPERATION
+
+typedef struct _XENBUS_STORE_INTERFACE   XENBUS_STORE_INTERFACE, *PXENBUS_STORE_INTERFACE;
+
+// {916920F1-F9EE-465d-8137-5CC61786B840}
+DEFINE_GUID(GUID_STORE_INTERFACE,
+            0x916920f1,
+            0xf9ee,
+            0x465d,
+            0x81,
+            0x37,
+            0x5c,
+            0xc6,
+            0x17,
+            0x86,
+            0xb8,
+            0x40);
+
+#define STORE_INTERFACE_VERSION 4
+
+#define STORE_OPERATIONS(_Interface) \
+        (PXENBUS_STORE_OPERATIONS *)((ULONG_PTR)(_Interface))
+
+#define STORE_CONTEXT(_Interface) \
+        (PXENBUS_STORE_CONTEXT *)((ULONG_PTR)(_Interface) + sizeof (PVOID))
+
+#define STORE(_Operation, _Interface, ...) \
+        (*STORE_OPERATIONS(_Interface))->STORE_ ## _Operation((*STORE_CONTEXT(_Interface)), __VA_ARGS__)
+
+#endif  // _XENBUS_STORE_INTERFACE_H
+
diff --git a/include/suspend_interface.h b/include/suspend_interface.h
new file mode 100644 (file)
index 0000000..50728ee
--- /dev/null
@@ -0,0 +1,120 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XENBUS_SUSPEND_INTERFACE_H
+#define _XENBUS_SUSPEND_INTERFACE_H
+
+typedef enum _XENBUS_SUSPEND_CALLBACK_TYPE {
+    SUSPEND_CALLBACK_TYPE_INVALID = 0,
+    SUSPEND_CALLBACK_EARLY,
+    SUSPEND_CALLBACK_LATE
+} XENBUS_SUSPEND_CALLBACK_TYPE, *PXENBUS_SUSPEND_CALLBACK_TYPE;
+
+typedef struct _XENBUS_SUSPEND_CALLBACK   XENBUS_SUSPEND_CALLBACK, *PXENBUS_SUSPEND_CALLBACK;
+
+#define DEFINE_SUSPEND_OPERATIONS                                                   \
+        SUSPEND_OPERATION(VOID,                                                     \
+                          Acquire,                                                  \
+                          (                                                         \
+                          IN  PXENBUS_SUSPEND_CONTEXT  Context                      \
+                          )                                                         \
+                          )                                                         \
+        SUSPEND_OPERATION(VOID,                                                     \
+                          Release,                                                  \
+                          (                                                         \
+                          IN  PXENBUS_SUSPEND_CONTEXT  Context                      \
+                          )                                                         \
+                          )                                                         \
+        SUSPEND_OPERATION(NTSTATUS,                                                 \
+                          Register,                                                 \
+                          (                                                         \
+                          IN  PXENBUS_SUSPEND_CONTEXT      Context,                 \
+                          IN  XENBUS_SUSPEND_CALLBACK_TYPE Type,                    \
+                          IN  VOID                         (*Function)(PVOID),      \
+                          IN  PVOID                        Argument OPTIONAL,       \
+                          OUT PXENBUS_SUSPEND_CALLBACK     *Callback                \
+                          )                                                         \
+                          )                                                         \
+        SUSPEND_OPERATION(VOID,                                                     \
+                          Deregister,                                               \
+                          (                                                         \
+                          IN  PXENBUS_SUSPEND_CONTEXT  Context,                     \
+                          IN  PXENBUS_SUSPEND_CALLBACK Callback                     \
+                          )                                                         \
+                          )                                                         \
+        SUSPEND_OPERATION(ULONG,                                                    \
+                          Count,                                                    \
+                          (                                                         \
+                          IN  PXENBUS_SUSPEND_CONTEXT  Context                      \
+                          )                                                         \
+                          )
+
+typedef struct _XENBUS_SUSPEND_CONTEXT  XENBUS_SUSPEND_CONTEXT, *PXENBUS_SUSPEND_CONTEXT;
+
+#define SUSPEND_OPERATION(_Type, _Name, _Arguments) \
+        _Type (*SUSPEND_ ## _Name) _Arguments;
+
+typedef struct _XENBUS_SUSPEND_OPERATIONS {
+    DEFINE_SUSPEND_OPERATIONS
+} XENBUS_SUSPEND_OPERATIONS, *PXENBUS_SUSPEND_OPERATIONS;
+
+#undef SUSPEND_OPERATION
+
+typedef struct _XENBUS_SUSPEND_INTERFACE XENBUS_SUSPEND_INTERFACE, *PXENBUS_SUSPEND_INTERFACE;
+
+// 104f0a14-e2d5-42b6-b10f-a669ccd410a1
+
+DEFINE_GUID(GUID_SUSPEND_INTERFACE, 
+            0x104f0a14,
+            0xe2d5,
+            0x42b6,
+            0xb1,
+            0x0f,
+            0xa6,
+            0x69,
+            0xcc,
+            0xd4,
+            0x10,
+            0xa1);
+
+#define SUSPEND_INTERFACE_VERSION   2
+
+#define SUSPEND_OPERATIONS(_Interface) \
+        (PXENBUS_SUSPEND_OPERATIONS *)((ULONG_PTR)(_Interface))
+
+#define SUSPEND_CONTEXT(_Interface) \
+        (PXENBUS_SUSPEND_CONTEXT *)((ULONG_PTR)(_Interface) + sizeof (PVOID))
+
+#define SUSPEND(_Operation, _Interface, ...) \
+        (*SUSPEND_OPERATIONS(_Interface))->SUSPEND_ ## _Operation((*SUSPEND_CONTEXT(_Interface)), __VA_ARGS__)
+
+#endif  // _XENBUS_SUSPEND_INTERFACE_H
+
diff --git a/include/version.h b/include/version.h
new file mode 100644 (file)
index 0000000..521b86f
--- /dev/null
@@ -0,0 +1,50 @@
+/* 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/include/xeniface_ioctls.h b/include/xeniface_ioctls.h
new file mode 100644 (file)
index 0000000..1367f67
--- /dev/null
@@ -0,0 +1,48 @@
+/* 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_IOCTLS_H_
+#define _XENIFACE_IOCTLS_H_
+
+DEFINE_GUID(GUID_INTERFACE_XENIFACE, \
+    0xb2cfb085, 0xaa5e, 0x47e1, 0x8b, 0xf7, 0x97, 0x93, 0xf3, 0x15, 0x45, 0x65);
+
+#define IOCTL_XENIFACE_STORE_READ \
+    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_XENIFACE_STORE_WRITE \
+    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_XENIFACE_STORE_DIRECTORY \
+    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_XENIFACE_STORE_REMOVE \
+    CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#endif // _XENIFACE_IOCTLS_H_
+
diff --git a/kdfiles.sh b/kdfiles.sh
new file mode 100644 (file)
index 0000000..793e534
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/sh -x
+
+# 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.
+
+
+CWD=$(pwd)
+
+PKG="xeniface"
+TARGET="\\systemroot\\system32\\drivers"
+SOURCE=$(cygpath --windows ${CWD})
+
+MAP=${CWD}/kdfiles32.txt
+> ${MAP}
+
+cd ${PKG}/x86
+for DRIVER in *.sys
+do
+    echo "map" >> ${MAP}
+    echo "${TARGET}\\${DRIVER}" >> ${MAP}
+    echo "${SOURCE}\\${PKG}\\x86\\${DRIVER}" >> ${MAP}
+    echo >> ${MAP}
+done
+
+cd ${CWD}
+
+MAP=${CWD}/kdfiles64.txt
+> ${MAP}
+
+cd ${PKG}/x64
+for DRIVER in *.sys
+do
+    echo "map" >> ${MAP}
+    echo "${TARGET}\\${DRIVER}" >> ${MAP}
+    echo "${SOURCE}\\${PKG}\\x64\\${DRIVER}" >> ${MAP}
+    echo >> ${MAP}
+done
+
+
diff --git a/proj/msbuild.bat b/proj/msbuild.bat
new file mode 100644 (file)
index 0000000..f4c59ce
--- /dev/null
@@ -0,0 +1,3 @@
+call "%VS%\VC\vcvarsall.bat" x86
+msbuild.exe /p:Configuration="%CONFIGURATION%" /p:Platform="%PLATFORM%" /t:"%TARGET%" /p:SignMode="ProductionSign" %SOLUTION%.sln
+
diff --git a/proj/msbuild_dvl.bat b/proj/msbuild_dvl.bat
new file mode 100644 (file)
index 0000000..4c256b2
--- /dev/null
@@ -0,0 +1,8 @@
+call "%VS%\VC\vcvarsall.bat" x86
+echo msbuild.exe "%SDV_PROJ%" /t:dvl /p:Configuration="Windows 8 Release" /p:Platform=x64
+msbuild.exe "%SDV_PROJ%" /t:dvl /p:Configuration="Windows 8 Release" /p:Platform=x64
+if errorlevel 1 goto error
+exit 0
+
+:error
+exit 1
diff --git a/proj/msbuild_sdv.bat b/proj/msbuild_sdv.bat
new file mode 100644 (file)
index 0000000..b3b7202
--- /dev/null
@@ -0,0 +1,8 @@
+call "%VS%\VC\vcvarsall.bat" x86
+echo msbuild.exe "%SDV_PROJ%" /t:sdv /p:Inputs="%SDV_ARG%" /p:Configuration="Windows 8 Release" /p:Platform=x64
+msbuild.exe "%SDV_PROJ%" /t:sdv /p:Inputs="%SDV_ARG%" /p:Configuration="Windows 8 Release" /p:Platform=x64
+if errorlevel 1 goto error
+exit 0
+
+:error
+exit 1
diff --git a/proj/package/package.vcxproj b/proj/package/package.vcxproj
new file mode 100644 (file)
index 0000000..0cca2f1
--- /dev/null
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Windows Developer Preview Debug|Win32">
+      <Configuration>Windows Developer Preview Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Developer Preview Release|Win32">
+      <Configuration>Windows Developer Preview Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 7 Debug|Win32">
+      <Configuration>Windows 7 Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 7 Release|Win32">
+      <Configuration>Windows 7 Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Vista Debug|Win32">
+      <Configuration>Windows Vista Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Vista Release|Win32">
+      <Configuration>Windows Vista Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Developer Preview Debug|x64">
+      <Configuration>Windows Developer Preview Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Developer Preview Release|x64">
+      <Configuration>Windows Developer Preview Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 7 Debug|x64">
+      <Configuration>Windows 7 Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 7 Release|x64">
+      <Configuration>Windows 7 Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Vista Debug|x64">
+      <Configuration>Windows Vista Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Vista Release|x64">
+      <Configuration>Windows Vista Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{9B071A35-897C-477A-AEB7-95F77618A21D}</ProjectGuid>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+  </PropertyGroup>
+  <PropertyGroup Label="PropertySheets">
+    <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+    <ConfigurationType>Utility</ConfigurationType>
+    <DriverType>Package</DriverType>
+    <Configuration>Windows Developer Preview Debug</Configuration>
+    <DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Developer Preview Debug|Win32'" Label="Configuration">
+    <TargetVersion>Windows8</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Developer Preview Release|Win32'" Label="Configuration">
+    <TargetVersion>Windows8</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows 7 Debug|Win32'" Label="Configuration">
+    <TargetVersion>Windows7</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows 7 Release|Win32'" Label="Configuration">
+    <TargetVersion>Windows7</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Vista Debug|Win32'" Label="Configuration">
+    <TargetVersion>Vista</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Vista Release|Win32'" Label="Configuration">
+    <TargetVersion>Vista</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Developer Preview Debug|x64'" Label="Configuration">
+    <TargetVersion>Windows8</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Developer Preview Release|x64'" Label="Configuration">
+    <TargetVersion>Windows8</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows 7 Debug|x64'" Label="Configuration">
+    <TargetVersion>Windows7</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows 7 Release|x64'" Label="Configuration">
+    <TargetVersion>Windows7</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Vista Debug|x64'" Label="Configuration">
+    <TargetVersion>Vista</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Vista Release|x64'" Label="Configuration">
+    <TargetVersion>Vista</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <EnableInf2cat>true</EnableInf2cat>
+    <Inf2CatWindowsVersionList Condition="'$(DDKPlatform)'=='x64'">Vista_$(DDKPlatform);7_$(DDKPlatform);Server2008_$(DDKPlatform);Server2008R2_$(DDKPlatform)</Inf2CatWindowsVersionList>
+    <Inf2CatWindowsVersionList Condition="'$(DDKPlatform)'=='x86'">Vista_$(DDKPlatform);7_$(DDKPlatform);Server2008_$(DDKPlatform)</Inf2CatWindowsVersionList>
+  </PropertyGroup>
+  <PropertyGroup>
+    <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+    <EnableDeployment>False</EnableDeployment>
+    <ImportToStore>False</ImportToStore>
+    <InstallMode>None</InstallMode>
+    <HardwareIdString />
+    <CommandLine />
+    <ScriptPath />
+    <DeployFiles />
+    <ScriptName />
+    <ScriptDeviceQuery>%PathToInf%</ScriptDeviceQuery>
+    <EnableVerifier>False</EnableVerifier>
+    <AllDrivers>False</AllDrivers>
+    <VerifyProjectOutput>True</VerifyProjectOutput>
+    <VerifyDrivers />
+    <VerifyFlags>133563</VerifyFlags>
+    <PackageDir>..\..\xeniface\$(DDKPlatform)</PackageDir>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\xeniface\xeniface.vcxproj">
+      <Project>{22166290-65D8-49D2-BB88-33201797C7D8}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <FilesToPackage Include="$(KIT)\Redist\DIFx\dpinst\EngMui\x86\dpinst.exe" Condition="'$(Platform)'=='Win32'" />
+    <FilesToPackage Include="$(KIT)\Redist\DIFx\dpinst\EngMui\x64\dpinst.exe" Condition="'$(Platform)'=='x64'" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>
diff --git a/proj/xeniface.sln b/proj/xeniface.sln
new file mode 100644 (file)
index 0000000..e2ead07
--- /dev/null
@@ -0,0 +1,99 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 11
+Project("{F0176BE6-4062-49C9-B0C4-3A8785B99343}") = "xeniface", "xeniface\xeniface.vcxproj", "{22166290-65D8-49D2-BB88-33201797C7D8}"
+EndProject
+Project("{F0176BE6-4062-49C9-B0C4-3A8785B99343}") = "package", "package\package.vcxproj", "{9B071A35-897C-477A-AEB7-95F77618A21D}"
+EndProject
+Global
+       GlobalSection(SolutionConfigurationPlatforms) = preSolution
+               Windows 7 Debug|Win32 = Windows 7 Debug|Win32
+               Windows 7 Debug|x64 = Windows 7 Debug|x64
+               Windows 7 Release|Win32 = Windows 7 Release|Win32
+               Windows 7 Release|x64 = Windows 7 Release|x64
+               Windows Developer Preview Debug|Win32 = Windows Developer Preview Debug|Win32
+               Windows Developer Preview Debug|x64 = Windows Developer Preview Debug|x64
+               Windows Developer Preview Release|Win32 = Windows Developer Preview Release|Win32
+               Windows Developer Preview Release|x64 = Windows Developer Preview Release|x64
+               Windows Vista Debug|Win32 = Windows Vista Debug|Win32
+               Windows Vista Debug|x64 = Windows Vista Debug|x64
+               Windows Vista Release|Win32 = Windows Vista Release|Win32
+               Windows Vista Release|x64 = Windows Vista Release|x64
+       EndGlobalSection
+       GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Debug|Win32.ActiveCfg = Windows 7 Debug|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Debug|Win32.Build.0 = Windows 7 Debug|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Debug|Win32.Deploy.0 = Windows 7 Debug|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Debug|x64.ActiveCfg = Windows 7 Debug|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Debug|x64.Build.0 = Windows 7 Debug|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Debug|x64.Deploy.0 = Windows 7 Debug|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Release|Win32.ActiveCfg = Windows 7 Release|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Release|Win32.Build.0 = Windows 7 Release|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Release|Win32.Deploy.0 = Windows 7 Release|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Release|x64.ActiveCfg = Windows 7 Release|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Release|x64.Build.0 = Windows 7 Release|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows 7 Release|x64.Deploy.0 = Windows 7 Release|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Debug|Win32.ActiveCfg = Windows Developer Preview Debug|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Debug|Win32.Build.0 = Windows Developer Preview Debug|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Debug|Win32.Deploy.0 = Windows Developer Preview Debug|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Debug|x64.ActiveCfg = Windows Developer Preview Debug|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Debug|x64.Build.0 = Windows Developer Preview Debug|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Debug|x64.Deploy.0 = Windows Developer Preview Debug|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Release|Win32.ActiveCfg = Windows Developer Preview Release|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Release|Win32.Build.0 = Windows Developer Preview Release|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Release|Win32.Deploy.0 = Windows Developer Preview Release|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Release|x64.ActiveCfg = Windows Developer Preview Release|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Release|x64.Build.0 = Windows Developer Preview Release|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Developer Preview Release|x64.Deploy.0 = Windows Developer Preview Release|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Debug|Win32.ActiveCfg = Windows Vista Debug|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Debug|Win32.Build.0 = Windows Vista Debug|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Debug|Win32.Deploy.0 = Windows Vista Debug|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Debug|x64.ActiveCfg = Windows Vista Debug|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Debug|x64.Build.0 = Windows Vista Debug|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Debug|x64.Deploy.0 = Windows Vista Debug|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Release|Win32.ActiveCfg = Windows Vista Release|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Release|Win32.Build.0 = Windows Vista Release|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Release|Win32.Deploy.0 = Windows Vista Release|Win32
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Release|x64.ActiveCfg = Windows Vista Release|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Release|x64.Build.0 = Windows Vista Release|x64
+               {9B071A35-897C-477A-AEB7-95F77618A21D}.Windows Vista Release|x64.Deploy.0 = Windows Vista Release|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Debug|Win32.ActiveCfg = Windows 7 Debug|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Debug|Win32.Build.0 = Windows 7 Debug|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Debug|Win32.Deploy.0 = Windows 7 Debug|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Debug|x64.ActiveCfg = Windows 7 Debug|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Debug|x64.Build.0 = Windows 7 Debug|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Debug|x64.Deploy.0 = Windows 7 Debug|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Release|Win32.ActiveCfg = Windows 7 Release|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Release|Win32.Build.0 = Windows 7 Release|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Release|Win32.Deploy.0 = Windows 7 Release|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Release|x64.ActiveCfg = Windows 7 Release|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Release|x64.Build.0 = Windows 7 Release|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows 7 Release|x64.Deploy.0 = Windows 7 Release|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Debug|Win32.ActiveCfg = Windows Developer Preview Debug|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Debug|Win32.Build.0 = Windows Developer Preview Debug|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Debug|Win32.Deploy.0 = Windows Developer Preview Debug|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Debug|x64.ActiveCfg = Windows Developer Preview Debug|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Debug|x64.Build.0 = Windows Developer Preview Debug|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Debug|x64.Deploy.0 = Windows Developer Preview Debug|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Release|Win32.ActiveCfg = Windows Developer Preview Release|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Release|Win32.Build.0 = Windows Developer Preview Release|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Release|Win32.Deploy.0 = Windows Developer Preview Release|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Release|x64.ActiveCfg = Windows Developer Preview Release|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Release|x64.Build.0 = Windows Developer Preview Release|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Developer Preview Release|x64.Deploy.0 = Windows Developer Preview Release|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Debug|Win32.ActiveCfg = Windows Vista Debug|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Debug|Win32.Build.0 = Windows Vista Debug|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Debug|Win32.Deploy.0 = Windows Vista Debug|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Debug|x64.ActiveCfg = Windows Vista Debug|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Debug|x64.Build.0 = Windows Vista Debug|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Debug|x64.Deploy.0 = Windows Vista Debug|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Release|Win32.ActiveCfg = Windows Vista Release|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Release|Win32.Build.0 = Windows Vista Release|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Release|Win32.Deploy.0 = Windows Vista Release|Win32
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Release|x64.ActiveCfg = Windows Vista Release|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Release|x64.Build.0 = Windows Vista Release|x64
+               {22166290-65D8-49D2-BB88-33201797C7D8}.Windows Vista Release|x64.Deploy.0 = Windows Vista Release|x64
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/proj/xeniface/xeniface.vcxproj b/proj/xeniface/xeniface.vcxproj
new file mode 100644 (file)
index 0000000..f4a29ed
--- /dev/null
@@ -0,0 +1,218 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Windows Developer Preview Debug|Win32">
+      <Configuration>Windows Developer Preview Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Developer Preview Release|Win32">
+      <Configuration>Windows Developer Preview Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 8 Debug|Win32">
+      <Configuration>Windows 8 Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 8 Release|Win32">
+      <Configuration>Windows 8 Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 7 Debug|Win32">
+      <Configuration>Windows 7 Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 7 Release|Win32">
+      <Configuration>Windows 7 Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Vista Debug|Win32">
+      <Configuration>Windows Vista Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Vista Release|Win32">
+      <Configuration>Windows Vista Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Developer Preview Debug|x64">
+      <Configuration>Windows Developer Preview Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Developer Preview Release|x64">
+      <Configuration>Windows Developer Preview Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 8 Debug|x64">
+      <Configuration>Windows 8 Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 8 Release|x64">
+      <Configuration>Windows 8 Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 7 Debug|x64">
+      <Configuration>Windows 7 Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows 7 Release|x64">
+      <Configuration>Windows 7 Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Vista Debug|x64">
+      <Configuration>Windows Vista Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Windows Vista Release|x64">
+      <Configuration>Windows Vista Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{22166290-65D8-49D2-BB88-33201797C7D8}</ProjectGuid>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+    <ProjectName>xeniface</ProjectName>
+  </PropertyGroup>
+  <PropertyGroup Label="PropertySheets">
+    <PlatformToolset>WindowsKernelModeDriver8.0</PlatformToolset>
+    <ConfigurationType>Driver</ConfigurationType>
+    <DriverType>WDM</DriverType>
+    <Configuration>Windows Developer Preview Debug</Configuration>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Developer Preview Debug|Win32'" Label="Configuration">
+    <TargetVersion>Windows8</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Developer Preview Release|Win32'" Label="Configuration">
+    <TargetVersion>Windows8</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows 7 Debug|Win32'" Label="Configuration">
+    <TargetVersion>Windows7</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows 7 Release|Win32'" Label="Configuration">
+    <TargetVersion>Windows7</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Vista Debug|Win32'" Label="Configuration">
+    <TargetVersion>Vista</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Vista Release|Win32'" Label="Configuration">
+    <TargetVersion>Vista</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Developer Preview Debug|x64'" Label="Configuration">
+    <TargetVersion>Windows8</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Developer Preview Release|x64'" Label="Configuration">
+    <TargetVersion>Windows8</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows 7 Debug|x64'" Label="Configuration">
+    <TargetVersion>Windows7</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows 7 Release|x64'" Label="Configuration">
+    <TargetVersion>Windows7</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Vista Debug|x64'" Label="Configuration">
+    <TargetVersion>Vista</TargetVersion>
+    <UseDebugLibraries>true</UseDebugLibraries>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Windows Vista Release|x64'" Label="Configuration">
+    <TargetVersion>Vista</TargetVersion>
+    <UseDebugLibraries>false</UseDebugLibraries>
+  </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" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <IncludePath>$(IncludePath)</IncludePath>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <EnableInf2cat>false</EnableInf2cat>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>__i386__;__MODULE__="XENIFACE";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <EnablePREfast>true</EnablePREfast>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>$(DDK_LIB_PATH)\ntstrsafe.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+    </Link>
+    <ResourceCompile>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Inf>
+      <SpecifyArchitecture>true</SpecifyArchitecture>
+      <Architecture>x86</Architecture>
+      <SpecifyDriverVerDirectiveVersion>true</SpecifyDriverVerDirectiveVersion>
+      <TimeStamp>$(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION).$(BUILD_NUMBER)</TimeStamp>
+      <EnableVerbose>true</EnableVerbose>
+    </Inf>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>__x86_64__;__MODULE__="XENIFACE";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <EnablePREfast>true</EnablePREfast>
+    </ClCompile>
+    <Link>
+      <AdditionalDependencies>$(DDK_LIB_PATH)\ntstrsafe.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <ResourceCompile>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Inf>
+      <SpecifyArchitecture>true</SpecifyArchitecture>
+      <Architecture>amd64</Architecture>
+      <SpecifyDriverVerDirectiveVersion>true</SpecifyDriverVerDirectiveVersion>
+      <TimeStamp>$(MAJOR_VERSION).$(MINOR_VERSION).$(MICRO_VERSION).$(BUILD_NUMBER)</TimeStamp>
+      <EnableVerbose>true</EnableVerbose>
+    </Inf>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <FilesToPackage Include="$(TargetPath)" />
+    <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" />
+  </ItemGroup>
+  <ItemGroup>
+    <Mofcomp Include="../../src/xeniface/wmi.mof">
+        <CreateBinaryMofFile>$(IntDir)/wmi.bmf</CreateBinaryMofFile>
+    </Mofcomp>
+  </ItemGroup>
+  <ItemGroup>
+    <Wmimofck Include="$(IntDir)\wmi.bmf">
+      <HeaderOutputFile>..\..\src\xeniface\wmi_generated.h</HeaderOutputFile>
+    </Wmimofck>
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="..\..\src\xeniface\xeniface.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <Inf Include="..\..\src\xeniface.inf" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\package\package.vcxproj" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+    <Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
+  </ImportGroup>
+</Project>
diff --git a/sdv.py b/sdv.py
new file mode 100644 (file)
index 0000000..9abb28e
--- /dev/null
+++ b/sdv.py
@@ -0,0 +1,80 @@
+#!python -u
+
+# 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.
+
+
+import os, sys
+import datetime
+import re
+import glob
+import tarfile
+import subprocess
+
+def shell(command):
+    print(command)
+    sys.stdout.flush()
+
+    pipe = os.popen(command, 'r', 1)
+
+    for line in pipe:
+        print(line.rstrip())
+
+    return pipe.close()
+
+
+class msbuild_failure(Exception):
+    def __init__(self, value):
+        self.value = value
+    def __str__(self):
+        return repr(self.value)
+
+def msbuild(batfile, projdir, name, sdv_arg):
+    cwd = os.getcwd()
+
+    os.environ['CONFIGURATION'] = 'Windows 8 Release'
+    os.environ['SDV_PROJ'] = name
+    os.environ['SDV_ARG'] = sdv_arg
+
+    os.chdir('proj')
+    os.chdir(projdir)
+    status = shell(batfile)
+    os.chdir(cwd)
+
+#    if (status != None):
+#        raise msbuild_failure(sdv_arg)
+
+
+if __name__ == '__main__':
+    msbuild('..\msbuild_sdv.bat', 'xeniface', 'xeniface.vcxproj', '/clean')
+
+    msbuild('..\msbuild_sdv.bat', 'xeniface', 'xeniface.vcxproj', '/check:default.sdv')
+
+    msbuild('..\msbuild_dvl.bat', 'xeniface', 'xeniface.vcxproj', '')
diff --git a/src/win32stubagent/NicInfo.cpp b/src/win32stubagent/NicInfo.cpp
new file mode 100644 (file)
index 0000000..8f2da5d
--- /dev/null
@@ -0,0 +1,180 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#include <windows.h>
+#include "stdafx.h"
+#include "NicInfo.h"
+#include "XSAccessor.h"
+#include <winsock2.h>
+#include <Iphlpapi.h>
+
+NicInfo::NicInfo() : netif_data(NULL), nr_netifs_found(0)
+{
+    NicChangeEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+    if (!NicChangeEvent) {
+        XsLog("Failed to create NicChangeEvent");
+        exit(1);
+    }
+
+    ResetEvent(NicChangeEvent);
+
+    memset(&Overlap, 0, sizeof (Overlap));
+    Overlap.hEvent = NicChangeEvent;
+}
+
+NicInfo::~NicInfo()
+{
+    //CancelIPChangeNotify(&Overlap); <--- Function does not exist in 2k
+}
+
+void NicInfo::Prime()
+{
+    DWORD dwRet;
+    LONG  Attempt;
+
+    Attempt = 0;
+again:
+    dwRet = NotifyAddrChange(&hAddrChange, &Overlap);
+    if (dwRet != NO_ERROR) {
+        dwRet = GetLastError();
+        if (dwRet != ERROR_IO_PENDING) {
+            XsLog("NotifyAddrChange(%d) failed: 0x%08x", Attempt, dwRet);
+            if (++Attempt >= 5)
+                return;
+
+            Sleep(1000); // 1s
+            goto again;
+        }
+    }
+}
+
+void NicInfo::Refresh()
+{
+    GetNicInfo();
+    XenstoreDoNicDump(nr_netifs_found, netif_data);
+}
+
+void NicInfo::GetNicInfo()
+{
+    const char* domainVifPath = "device/vif";
+    unsigned int entry;     
+    int i;
+    unsigned int numEntries;
+    char** vifEntries = NULL;
+    char vifNode[MAX_XENBUS_PATH];
+    PIP_ADAPTER_INFO IpAdapterInfo = NULL;
+    PIP_ADAPTER_INFO currAdapterInfo;
+    ULONG cbIpAdapterInfo;
+    ULONG numIpAdapterInfo;
+    char AdapterMac[MAX_CHAR_LEN];
+
+    //
+    // Get the list of vif #'s from xenstore
+    //
+       if (XenstoreList(domainVifPath, &vifEntries, &numEntries) < 0) {
+               goto clean;
+       }
+    nr_netifs_found = 0;
+    if (netif_data) {
+        free(netif_data);
+        netif_data = NULL;
+    }
+       netif_data = (VIFData *)calloc(sizeof(VIFData), numEntries);
+    if (!netif_data) {
+        goto clean;
+    }
+
+    //
+    // Loop through xenstore and collect the vif number and the mac address
+    //
+    for (entry = 0; entry < numEntries; entry++) {
+        netif_data[entry].ethnum = atoi(vifEntries[entry]); 
+        char* macAddress;
+#pragma prefast(suppress: 28719, "We know the max length of the string")
+        sprintf(vifNode, "%s/mac", vifEntries[entry]);
+        if (XenstoreRead(vifNode, &macAddress) != -1) {
+#pragma prefast(suppress: 28719, "We know the max length of the string")
+            lstrcpyn(netif_data[entry].mac, macAddress, sizeof(netif_data[entry].mac));
+            XenstoreFree(macAddress);
+        }
+    }
+
+    //
+    // Call GetAdaptersInfo to get a list of network device information.
+    // Use this to cooralate a mac address to an IP address and the nics name.
+    //
+    cbIpAdapterInfo = 0;
+    if (GetAdaptersInfo(NULL, &cbIpAdapterInfo) != ERROR_BUFFER_OVERFLOW) {
+        goto clean;
+    }
+    IpAdapterInfo = (PIP_ADAPTER_INFO)malloc(cbIpAdapterInfo);
+    if (!IpAdapterInfo) {
+        goto clean;
+    }
+    if (GetAdaptersInfo(IpAdapterInfo, &cbIpAdapterInfo) != NO_ERROR) {
+        goto clean;
+    }
+
+    currAdapterInfo = IpAdapterInfo;
+    while (currAdapterInfo) {
+#pragma prefast(suppress:28719, "We know the max length of the string")
+        sprintf(AdapterMac, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
+            currAdapterInfo->Address[0], currAdapterInfo->Address[1], currAdapterInfo->Address[2],
+            currAdapterInfo->Address[3], currAdapterInfo->Address[4], currAdapterInfo->Address[5]);
+
+        for (entry = 0; entry < numEntries; entry++) {
+            if (!lstrcmpi(AdapterMac, netif_data[entry].mac)) {
+                //
+                // Found the matching netif_data entry, so fill in the other values from
+                // the IP_ADAPTER_INFO values.
+                //
+#pragma prefast(suppress: 28719, "We know the max length of the string")
+                lstrcpyn(netif_data[entry].name, currAdapterInfo->Description, sizeof(netif_data[entry].name));
+#pragma prefast(suppress: 28719, "We know the max length of the string")
+                lstrcpyn(netif_data[entry].ip, currAdapterInfo->IpAddressList.IpAddress.String, sizeof(netif_data[entry].ip));
+                break;
+            }
+        }
+
+        currAdapterInfo = currAdapterInfo->Next;
+    }
+
+    nr_netifs_found = numEntries;
+clean:
+    if (vifEntries) {
+        for (entry = 0; entry < numEntries; entry++)
+            XenstoreFree(vifEntries[entry]);
+        XenstoreFree(vifEntries);
+    }
+    if (IpAdapterInfo) {
+        free(IpAdapterInfo);
+    }
+}
diff --git a/src/win32stubagent/NicInfo.h b/src/win32stubagent/NicInfo.h
new file mode 100644 (file)
index 0000000..3c8f395
--- /dev/null
@@ -0,0 +1,62 @@
+/* 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 _NICINFO_H
+#define _NICINFO_H
+
+#include <string>
+#include <list>
+#include <map>
+
+#include "vm_stats.h"
+
+using namespace std;
+
+class NicInfo
+{
+public:
+    NicInfo();
+    ~NicInfo();
+
+    void Refresh();
+    void Prime();
+    HANDLE NicChangeEvent;
+
+private:
+    void GetNicInfo();
+
+    int nr_netifs_found;
+    VIFData *netif_data;
+    HANDLE hAddrChange;
+    OVERLAPPED Overlap;
+};
+
+#endif
diff --git a/src/win32stubagent/TSInfo.cpp b/src/win32stubagent/TSInfo.cpp
new file mode 100644 (file)
index 0000000..9b35731
--- /dev/null
@@ -0,0 +1,446 @@
+/* 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 _WIN32_DCOM
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+#include <iostream>
+#include <wbemidl.h>
+
+#include "XSAccessor.h"
+#include "TSInfo.h"
+
+using namespace std;
+
+#pragma comment(lib, "wbemuuid.lib")
+
+TSInfo::TSInfo()
+{
+   
+    Init();
+}
+
+void TSInfo::Init()
+{
+    HRESULT                 Result;
+    OSVERSIONINFO           VersionInfo;
+    BSTR                    NameSpace;
+    
+    Result = CoInitializeEx(0,
+                            COINIT_MULTITHREADED);
+    if (FAILED(Result))
+        goto fail1;
+
+    Result = CoInitializeSecurity(NULL,
+                                  -1,
+                                  NULL,
+                                  NULL,
+                                  RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
+                                  RPC_C_IMP_LEVEL_IMPERSONATE,
+                                  NULL,
+                                  EOAC_NONE,
+                                  NULL);
+    if (FAILED(Result) && Result != RPC_E_TOO_LATE)
+        goto fail2;
+
+    Result = CoCreateInstance(CLSID_WbemLocator,
+                              0,
+                              CLSCTX_INPROC_SERVER,
+                              IID_IWbemLocator,
+                              (LPVOID*)&pLocator);
+    if (FAILED(Result))
+        goto fail3;
+
+    VersionInfo.dwOSVersionInfoSize = sizeof (VersionInfo);
+    Result = WBEM_E_FAILED;    
+    if (!GetVersionEx(&VersionInfo))
+        goto fail4;
+
+    if (VersionInfo.dwMajorVersion >= 6)
+        NameSpace = L"ROOT\\CIMV2\\TERMINALSERVICES";
+    else
+        NameSpace = L"ROOT\\CIMV2";
+
+    Result = pLocator->ConnectServer(NameSpace,
+                                     NULL,
+                                     NULL,
+                                     0,
+                                     NULL,
+                                     0,
+                                     0,
+                                     &pNamespace);
+    if (FAILED(Result))
+        goto fail5;
+
+    Result = CoSetProxyBlanket(pNamespace,
+                               RPC_C_AUTHN_WINNT,
+                               RPC_C_AUTHZ_NONE,
+                               NULL,
+                               RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
+                               RPC_C_IMP_LEVEL_IMPERSONATE,
+                               NULL,
+                               EOAC_NONE);
+    if (FAILED(Result))
+        goto fail6;
+
+    Ready = TRUE;
+
+    return;
+
+fail6:
+    XsLog("%s: fail6\n", __FUNCTION__);
+
+    pNamespace->Release();
+
+fail5:
+    XsLog("%s: fail5\n", __FUNCTION__);
+
+fail4:
+    XsLog("%s: fail4\n", __FUNCTION__);
+
+    pLocator->Release();
+
+fail3:
+    XsLog("%s: fail3\n", __FUNCTION__);
+
+fail2:
+    XsLog("%s: fail2\n", __FUNCTION__);
+
+    CoUninitialize();
+
+fail1:
+    XsLog("%s: fail1 (%08x)\n", __FUNCTION__, Result);
+
+    Ready = FALSE;
+}
+
+TSInfo::~TSInfo()
+{
+    if (Ready) {
+        pNamespace->Release();
+
+        pLocator->Release();
+
+        CoUninitialize();
+    }
+}
+
+HRESULT
+TSInfo::Query(
+    __out   BOOLEAN         *pEnabled
+    )
+{
+    HRESULT                 Result;
+    IEnumWbemClassObject    *pEnumerator = NULL;
+    IWbemClassObject        *pObject = NULL;
+    ULONG                   Count;
+    VARIANT                 Flag;
+
+    if (!Ready) {
+        Init();
+        if (!Ready) {
+            Result = WBEM_E_FAILED;
+            goto fail_notready;
+        }
+    }
+
+    Result = pNamespace->ExecQuery(L"WQL",
+                                   L"SELECT * FROM Win32_TerminalServiceSetting",
+                                   WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &pEnumerator);
+    if (FAILED(Result))
+        goto fail1;
+
+    Count = 0;
+    (VOID) pEnumerator->Next(WBEM_INFINITE,
+                             1,
+                             &pObject,
+                             &Count);
+
+    Result = WBEM_S_FALSE;
+    if (Count == 0)
+        goto fail2;
+
+    Result = pObject->Get(L"AllowTSConnections",
+                          0,
+                          &Flag,
+                          NULL,
+                          NULL);
+
+    if (FAILED(Result))
+        goto fail3;
+
+    Result = WBEM_E_FAILED;    
+    if (V_VT(&Flag) != VT_I4)
+        goto fail4;
+
+    *pEnabled = (V_I4(&Flag) != 0) ? TRUE : FALSE;
+
+    VariantClear(&Flag);
+
+    pObject->Release();
+
+    pEnumerator->Release();
+
+    return WBEM_S_NO_ERROR;
+
+fail4:
+    XsLog("%s: fail4\n", __FUNCTION__);
+
+    VariantClear(&Flag);
+
+fail3:
+    XsLog("%s: fail3\n", __FUNCTION__);
+
+    pObject->Release();
+
+fail2:
+    XsLog("%s: fail2\n", __FUNCTION__);
+
+    pEnumerator->Release();
+
+fail1:
+    XsLog("%s: fail1 (%08x)\n", __FUNCTION__, Result);
+
+    return Result;
+
+fail_notready:
+    XsLog("%s: fail not ready\n", __FUNCTION__);
+
+    return WBEM_E_FAILED;
+
+}
+
+HRESULT
+TSInfo::Set(
+    __in    BOOLEAN         Enable
+    )
+{
+    HRESULT                 Result;
+    IEnumWbemClassObject    *pEnumerator = NULL;
+    IWbemClassObject        *pObject = NULL;
+    ULONG                   Count;
+    BSTR                    ClassName = L"Win32_TerminalServiceSetting";
+    IWbemClassObject        *pClass = NULL;
+    BSTR                    MethodName = L"SetAllowTSConnections";
+    IWbemClassObject        *pInParamsDefinition = NULL;
+    IWbemClassObject        *pClassInstance = NULL;
+    IWbemClassObject        *pOutParams = NULL;
+    VARIANT                 Flag;
+    VARIANT                 Path;
+    
+    if (!Ready) {
+        Init();
+        if (!Ready) {
+            Result = WBEM_E_FAILED;
+            goto fail_notready;
+        }
+    }
+
+    Result = pNamespace->ExecQuery(L"WQL",
+                                   L"SELECT * FROM Win32_TerminalServiceSetting",
+                                   WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
+                                   NULL,
+                                   &pEnumerator);
+    if (FAILED(Result))
+        goto fail1;
+
+    Count = 0;
+    (VOID) pEnumerator->Next(WBEM_INFINITE,
+                             1,
+                             &pObject,
+                             &Count);
+
+    Result = WBEM_S_FALSE;
+    if (Count == 0)
+        goto fail2;
+
+    Result = pNamespace->GetObject(ClassName,
+                                   0,
+                                   NULL,
+                                   &pClass,
+                                   NULL);
+    if (FAILED(Result))
+        goto fail3;
+
+    Result = pClass->GetMethod(MethodName, 
+                               0,
+                               &pInParamsDefinition,
+                               NULL);
+    if (FAILED(Result))
+        goto fail4;
+
+    Result = pInParamsDefinition->SpawnInstance(0,
+                                                &pClassInstance);
+    if (FAILED(Result))
+        goto fail5;
+
+    V_VT(&Flag) = VT_I4;
+    V_I4(&Flag) = (Enable) ? 1 : 0;
+
+    Result = pClassInstance->Put(L"AllowTSConnections",
+                                 0,
+                                 &Flag,
+                                 0);
+    if (FAILED(Result))
+        goto fail6;
+
+    Result = pObject->Get(L"__PATH",
+                          0,
+                          &Path,
+                          NULL,
+                          NULL);
+    if (FAILED(Result))
+        goto fail7;
+
+    Result = pNamespace->ExecMethod(Path.bstrVal,
+                                    MethodName, 
+                                    0,
+                                    NULL,
+                                    pClassInstance,
+                                    &pOutParams,
+                                    NULL);
+    if (FAILED(Result))
+        goto fail8;
+
+    pOutParams->Release();
+
+    VariantClear(&Path);
+
+    VariantClear(&Flag);
+
+    pClassInstance->Release();
+
+    pInParamsDefinition->Release();
+
+    pClass->Release();
+
+    pObject->Release();
+
+    pEnumerator->Release();
+
+    return WBEM_S_NO_ERROR;
+
+fail8:
+    XsLog("%s: fail8\n", __FUNCTION__);
+
+    VariantClear(&Path);
+
+fail7:
+    XsLog("%s: fail7\n", __FUNCTION__);
+
+    VariantClear(&Flag);
+
+fail6:
+    XsLog("%s: fail6\n", __FUNCTION__);
+
+    pClassInstance->Release();
+
+fail5:
+    XsLog("%s: fail5\n", __FUNCTION__);
+
+    pInParamsDefinition->Release();
+
+fail4:
+    XsLog("%s: fail4\n", __FUNCTION__);
+
+    pClass->Release();
+
+fail3:
+    XsLog("%s: fail3\n", __FUNCTION__);
+
+    pObject->Release();
+
+fail2:
+    XsLog("%s: fail2\n", __FUNCTION__);
+
+    pEnumerator->Release();
+
+fail1:
+    XsLog("%s: fail1 (%08x)\n", __FUNCTION__, Result);
+
+    return Result;
+
+fail_notready:
+    XsLog("%s: fail not ready\n", __FUNCTION__);
+
+    return WBEM_E_FAILED;
+}
+
+VOID
+TSInfo::Refresh()
+{
+    HRESULT Result;
+    BOOLEAN Enabled;
+
+    Result = Query(&Enabled);
+    if (FAILED(Result))
+        goto fail1;
+
+    XenstorePrintf("data/ts", "%d", (Enabled) ? 1 : 0);
+
+    return;
+
+fail1:
+    XsLog("%s: fail1 (%08x)\n", __FUNCTION__, Result);
+}
+
+VOID
+TSInfo::ProcessControl()
+{
+    CHAR    *Buffer; 
+    BOOLEAN Enable;
+    HRESULT Result;
+
+    if (XenstoreRead("control/ts", &Buffer) < 0)
+        return;
+
+    XenstoreRemove("control/ts");
+
+    Enable = (strtol(Buffer, NULL, 0) != 0) ? TRUE : FALSE;
+
+    Result = Set(Enable);
+    if (FAILED(Result))
+        goto fail1;
+
+    XsLog("%s terminal services", (Enable) ? "Enabled" : "Disabled");
+
+    Refresh();
+
+    return;
+
+fail1:
+    XsLog("%s: fail1 (%08x)\n", __FUNCTION__, Result);
+}
+
diff --git a/src/win32stubagent/TSInfo.h b/src/win32stubagent/TSInfo.h
new file mode 100644 (file)
index 0000000..51d0cbd
--- /dev/null
@@ -0,0 +1,59 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef _TSINFO_H
+#define _TSINFO_H
+
+#define _WIN32_DCOM
+#include <iostream>
+#include <wbemidl.h>
+
+class TSInfo {
+public:
+    TSInfo();
+    ~TSInfo();
+
+    VOID    Refresh(VOID);
+    VOID    ProcessControl(VOID);
+
+private:
+    IWbemLocator    *pLocator;
+    IWbemServices   *pNamespace;
+
+    void Init();
+    BOOLEAN Ready;
+
+    HRESULT Query(BOOLEAN *);
+    HRESULT Set(BOOLEAN);
+};
+
+#endif  // _TSINFO
diff --git a/src/win32stubagent/WmiAccessor.cpp b/src/win32stubagent/WmiAccessor.cpp
new file mode 100644 (file)
index 0000000..a52db1e
--- /dev/null
@@ -0,0 +1,1226 @@
+/* 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 "stdafx.h"
+#define _WIN32_DCOM
+#include <windows.h>
+#include <iostream>
+#include <algorithm>
+#include <hash_map>
+#include <stdio.h>
+#include "WMIAccessor.h"
+#include "XService.h"
+#include "NicInfo.h"
+
+//#include "xs_private.h"
+#include <wbemidl.h>
+
+#pragma comment(lib, "wbemuuid.lib")
+#pragma comment(lib, "uuid.lib")
+
+
+BSTR mkBstr(const char *string, size_t len) {
+    BSTR res = NULL;
+    size_t returned;
+    wchar_t* wstring = new wchar_t[len+1];
+    if (wstring == NULL) {
+        goto malloc_wstring;
+    }
+    mbstowcs_s(&returned, wstring, len+1, string, len);
+    res = SysAllocString(wstring);
+    delete wstring;
+malloc_wstring:
+    return res;
+}
+
+char * formatCharStrInt(const char *fmt, va_list l) {
+    char *buf = NULL;
+    int cnt = _vscprintf(fmt, l);
+    buf = (char *)XsAlloc(cnt+1);
+    if (buf == NULL) {
+        goto malloc_buf;
+    }
+    _vsnprintf(buf, cnt+1, fmt, l);
+malloc_buf:
+    return buf;
+}
+
+char * formatCharStr(const char *fmt, ... ) {
+    char *buf =NULL;
+    va_list l;
+    va_start(l, fmt);
+    buf = formatCharStrInt(fmt, l);
+    va_end(l);
+    return buf;
+}
+
+BSTR formatBstr(const char *fmt, ...) 
+{
+    char *buf;
+    va_list l;  
+    BSTR res = NULL;
+    va_start(l, fmt);
+    buf = formatCharStrInt(fmt, l);
+    va_end(l);
+    res = mkBstr(buf, strlen(buf));
+    XsFree(buf);
+    return res;
+}
+
+int setVariantString(VARIANT* var, const char *data, size_t len) {
+    int err=-1;
+    VariantInit(var);
+    var->vt=VT_BSTR;
+    var->bstrVal = mkBstr(data, len);
+    if (var->bstrVal == NULL) {
+        goto sysalloc;
+    }
+    err=0;
+sysalloc:
+    return err;
+}
+
+
+int setVariantString(VARIANT* var, const char *string) {
+    return setVariantString(var, string, strlen(string));
+}
+
+
+
+class WatchSink : public IWbemObjectSink
+{
+    LONG m_lRef;
+    bool bDone; 
+    HANDLE triggerevent;
+
+public:
+    char *path;
+    WatchSink(HANDLE event, const char *path) { 
+        m_lRef = 0; 
+        triggerevent = event;
+        this->path = NULL;
+        if (path) {
+            this->path=(char *)XsAlloc(strlen(path)+1);
+            strcpy(this->path, path);
+        }
+    }
+   ~WatchSink() { bDone = TRUE; }
+
+    virtual ULONG STDMETHODCALLTYPE AddRef();
+    virtual ULONG STDMETHODCALLTYPE Release();        
+    virtual HRESULT STDMETHODCALLTYPE 
+        QueryInterface(REFIID riid, void** ppv);
+
+    virtual HRESULT STDMETHODCALLTYPE Indicate( 
+            /* [in] */
+            LONG lObjectCount,
+            /* [size_is][in] */
+            IWbemClassObject __RPC_FAR *__RPC_FAR *apObjArray
+            );
+        
+    virtual HRESULT STDMETHODCALLTYPE SetStatus( 
+            /* [in] */ LONG lFlags,
+            /* [in] */ HRESULT hResult,
+            /* [in] */ BSTR strParam,
+            /* [in] */ IWbemClassObject __RPC_FAR *pObjParam
+            );
+};
+
+
+ULONG WatchSink::AddRef()
+{
+    return InterlockedIncrement(&m_lRef);
+}
+
+ULONG WatchSink::Release()
+{
+    LONG lRef = InterlockedDecrement(&m_lRef);
+    if(lRef == 0)
+        delete this;
+    return lRef;
+}
+
+HRESULT WatchSink::QueryInterface(REFIID riid, void** ppv)
+{
+    if (riid == IID_IUnknown || riid == IID_IWbemObjectSink)
+    {
+        *ppv = (IWbemObjectSink *) this;
+        AddRef();
+        return WBEM_S_NO_ERROR;
+    }
+    else return E_NOINTERFACE;
+}
+
+
+HRESULT WatchSink::Indicate(long lObjCount, IWbemClassObject **pArray)
+{
+    for (long i = 0; i < lObjCount; i++)
+    {
+        IWbemClassObject *pObj = pArray[i];
+        SetEvent(this->triggerevent);
+        // ... use the object.
+
+        // AddRef() is only required if the object will be held after
+        // the return to the caller.
+    }
+
+    return WBEM_S_NO_ERROR;
+}
+
+HRESULT WatchSink::SetStatus(
+            /* [in] */ LONG lFlags,
+            /* [in] */ HRESULT hResult,
+            /* [in] */ BSTR strParam,
+            /* [in] */ IWbemClassObject __RPC_FAR *pObjParam
+        )
+{
+    return WBEM_S_NO_ERROR;
+}
+
+
+
+struct WMIAccessor
+{
+    IWbemServices *mpSvc;
+    IWbemServices *mpXSSvc;
+    BOOLEAN com_initialized;
+    HANDLE owning_thread;
+};
+
+struct WMIAccessor *wmi = NULL;
+
+static string wstring2string(const wstring& wstr)
+{ 
+    int len;
+
+    len = WideCharToMultiByte(CP_UTF8,
+                              0,
+                              wstr.c_str(),
+                              -1,
+                              NULL,
+                              0,
+                              NULL,
+                              NULL);
+
+    string str(len, 0);
+
+    len = WideCharToMultiByte(CP_UTF8,
+                              0,
+                              wstr.c_str(),
+                              -1,
+                              &str[0],
+                              str.length(),
+                              NULL,
+                              NULL);
+
+       return str;
+}
+
+static string bstr2string(const BSTR& bstr)
+{
+       wstring wstr(bstr);
+
+       return wstring2string(wstr);
+}
+
+IWbemClassObject *getClass(WMIAccessor *wmi, BSTR path) {
+    if (wmi == NULL)
+        return NULL;
+    ASSERT(wmi->mpXSSvc != NULL);
+    IWbemClassObject *returnedObject;
+    HRESULT hres = wmi->mpXSSvc->GetObject(path,WBEM_FLAG_RETURN_WBEM_COMPLETE,
+            NULL, &returnedObject, NULL);
+    if (FAILED(hres)) {
+        returnedObject =NULL;
+    }
+    return returnedObject;
+}
+
+IWbemClassObject *getObject(WMIAccessor *wmi, BSTR path) {
+    IEnumWbemClassObject *returnedEnum;
+    IWbemClassObject *returnedObject;
+    if (wmi == NULL)
+        return NULL;
+    ASSERT(wmi->mpXSSvc != NULL);
+    HRESULT hres =  wmi->mpXSSvc->CreateInstanceEnum(path, WBEM_FLAG_FORWARD_ONLY, 
+                                            NULL, 
+                                            &returnedEnum);
+    if (FAILED(hres)) {
+        DBGPRINT(("GetEnum failed\n"));
+        returnedObject =NULL;
+    }
+    ULONG objects;
+
+    hres = returnedEnum->Next(WBEM_INFINITE, 1, &returnedObject, &objects);
+
+                
+    if (FAILED(hres) || objects < 1) {
+        DBGPRINT(("GetFromEnum failed\n"));
+        returnedObject =NULL;
+    }
+
+    return returnedObject;
+}
+
+HRESULT methodExec(WMIAccessor* wmi,  IWbemClassObject* instance, const wchar_t *methodname, IWbemClassObject *inMethodInst, IWbemClassObject **outMethodInst)
+{
+    HRESULT hres=E_FAIL ;
+
+    IWbemClassObject *outstore=NULL;
+    BSTR bpathname = SysAllocString(L"__PATH");
+    if (bpathname == NULL){
+        goto allocpathname;
+    }
+
+
+    VARIANT instancepath;
+    VariantInit(&instancepath);
+    hres = instance->Get(bpathname, 0, &instancepath, NULL, NULL);
+    if (FAILED(hres)) {
+        goto getclassname;
+    }
+
+
+    BSTR bmethodname = SysAllocString(methodname);
+    if (bmethodname == NULL){
+        goto allocmethodname;
+    }
+
+    hres = wmi->mpXSSvc->ExecMethod(instancepath.bstrVal, bmethodname, 0, NULL,inMethodInst, &outstore, NULL);
+    if (outMethodInst != NULL) {
+        *outMethodInst = NULL;
+        if (!FAILED(hres)){
+            *outMethodInst = outstore;
+        }
+    }
+
+    SysFreeString(bmethodname);
+allocmethodname:
+
+getclassname:
+    VariantClear(&instancepath);
+    SysFreeString(bpathname);
+allocpathname:
+    return hres;
+}
+static IEnumWbemClassObject* runXSQuery(WMIAccessor *wmi, BSTR query)
+{
+    if (wmi == NULL)
+        return NULL;
+
+    ASSERT(wmi->mpXSSvc != NULL);
+
+    // Use the IWbemServices pointer to make requests of WMI. 
+    // Make requests here:
+    IEnumWbemClassObject* pEnumerator = NULL;
+    HRESULT hres = wmi->mpXSSvc->ExecQuery(L"WQL", 
+                                         query,
+                                         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
+                                         NULL,
+                                         &pEnumerator);
+    if (FAILED(hres))
+    {
+               DBGPRINT(("ExecQuery failed\n"));
+               pEnumerator = NULL;
+    }
+       return pEnumerator;
+}
+static IEnumWbemClassObject* runQuery(WMIAccessor *wmi, BSTR query)
+{
+    if (wmi == NULL)
+        return NULL;
+
+    ASSERT(wmi->mpSvc != NULL);
+
+    // Use the IWbemServices pointer to make requests of WMI. 
+    // Make requests here:
+    IEnumWbemClassObject* pEnumerator = NULL;
+    HRESULT hres = wmi->mpSvc->ExecQuery(L"WQL", 
+                                         query,
+                                         WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
+                                         NULL,
+                                         &pEnumerator);
+    if (FAILED(hres))
+    {
+               DBGPRINT(("ExecQuery failed\n"));
+               pEnumerator = NULL;
+    }
+       return pEnumerator;
+}
+
+VOID
+AddHotFixInfoToStore(WMIAccessor* wmi)
+{
+    IEnumWbemClassObject *pEnum;
+    char buffer2[4096];
+    DWORD index;
+    ULONG uReturn;
+    IWbemClassObject *pclsObj;
+    HRESULT hr;
+    VARIANT vtData;
+
+    index = 0;
+    pEnum = runQuery(wmi, L"SELECT HotFixID FROM Win32_QuickFixEngineering");
+    if (pEnum == NULL)
+        return;
+
+    while (1) {
+        hr = pEnum->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
+        if (FAILED(hr) || 0 == uReturn)
+            break;
+
+        hr = pclsObj->Get(L"HotFixID", 0, &vtData, NULL, NULL);
+
+        if ( !FAILED(hr) ) {
+            if ( vtData.vt == VT_BSTR ) {
+                //
+                // Windows replaces a hotfix id with "File 1" when it has been
+                // replaced by a newer hotfix, so just ignore these.
+                //
+                if (_wcsicmp(vtData.bstrVal, L"File 1")) {
+                    string str = bstr2string(vtData.bstrVal);
+                    sprintf(buffer2, "attr/os/hotfixes/%d", index);
+                    XenstoreWrite(buffer2, str.c_str(), str.length());
+                    index++;
+                }
+            }
+            VariantClear(&vtData);
+        }
+
+        pclsObj->Release();
+    }
+    pEnum->Release ();
+}
+
+void ConnectToWMI(void)
+{
+
+    IWbemLocator *locator;
+    HRESULT hres;
+
+    wmi = (struct WMIAccessor *)XsAlloc(sizeof(*wmi));
+    if (wmi == NULL) {
+        return;
+    }
+    memset(wmi, 0, sizeof(*wmi));
+
+    hres = CoInitializeEx(0, COINIT_MULTITHREADED);
+    if (FAILED(hres)) {
+        goto err_out;
+    }
+    wmi->com_initialized = TRUE;
+    wmi->owning_thread = GetCurrentThread();
+
+    // Initialize COM security.  Most of this is irrelevant to us.
+    hres = CoInitializeSecurity(
+        NULL,     /* Security descriptor. Only relevant to servers */
+        -1,       /* Nr. of auth services. Only relevant to servers */
+        NULL,     /* List of auth services. Only relevant to servers */
+        NULL,     /* Reserved */
+        RPC_C_AUTHN_LEVEL_DEFAULT, /* Default authentication.  The
+                                      details don't really matter when
+                                      you're localhost. */
+        RPC_C_IMP_LEVEL_IMPERSONATE, /* WMI needs to be able to
+                                        impersonate us. */
+        NULL,             /* Authentication info */
+        EOAC_NONE,        /* Additional capabilities */
+        NULL              /* Reserved */
+        );
+    if (FAILED(hres)) {
+        goto err_out;
+    }
+
+    hres = CoCreateInstance(
+        CLSID_WbemLocator,
+        0, 
+        CLSCTX_INPROC_SERVER, 
+        IID_IWbemLocator,
+        (LPVOID *) &locator);
+    if (FAILED(hres)) {
+        goto err_out;
+    }
+    hres = locator->ConnectServer(
+        L"root\\CIMV2",          // WMI namespace
+        NULL,                    // User name
+        NULL,                    // User password
+        NULL,                    // Locale
+        0,                       // Security flags
+        NULL,                    // Authority
+        NULL,                    // Context object
+        &wmi->mpSvc              // IWbemServices proxy
+        );
+    locator->Release();
+    if (FAILED(hres)) {
+        goto err_out;
+    }
+
+    /* WMI needs to impersonate us, because it normally runs as an
+       unprivileged user and needs our authority in order to access
+       device files and so forth.  Turn impersonation on. */
+    hres = CoSetProxyBlanket(
+        wmi->mpSvc,                  // the proxy to set
+        RPC_C_AUTHN_WINNT,           /* LAN manager authentication,
+                                        although it doesn't really
+                                        matter on localhost. */
+        RPC_C_AUTHZ_NONE,            // LANMAN can't do much authorization.
+        NULL,                        // Server principal name
+        RPC_C_AUTHN_LEVEL_CALL,      // Do authentication on every call
+        RPC_C_IMP_LEVEL_IMPERSONATE, // Allow full impersonation.
+        NULL,                        // Use current client identity
+        EOAC_NONE                    // No extended proxy capabilities
+    );
+    if (FAILED(hres)) {
+        goto err_out;
+    }
+
+    hres = CoCreateInstance(
+        CLSID_WbemLocator,
+        0, 
+        CLSCTX_INPROC_SERVER, 
+        IID_IWbemLocator,
+        (LPVOID *) &locator);
+    if (FAILED(hres)) {
+        goto err_out;
+    }
+    hres = locator->ConnectServer(
+        L"root\\WMI",          // WMI namespace
+        NULL,                    // User name
+        NULL,                    // User password
+        NULL,                    // Locale
+        0,                       // Security flags
+        NULL,                    // Authority
+        NULL,                    // Context object
+        &wmi->mpXSSvc              // IWbemServices proxy
+        );
+    locator->Release();
+    if (FAILED(hres)) {
+        goto err_out;
+    }
+
+    /* WMI needs to impersonate us, because it normally runs as an
+       unprivileged user and needs our authority in order to access
+       device files and so forth.  Turn impersonation on. */
+    hres = CoSetProxyBlanket(
+        wmi->mpXSSvc,                  // the proxy to set
+        RPC_C_AUTHN_WINNT,           /* LAN manager authentication,
+                                        although it doesn't really
+                                        matter on localhost. */
+        RPC_C_AUTHZ_NONE,            // LANMAN can't do much authorization.
+        NULL,                        // Server principal name
+        RPC_C_AUTHN_LEVEL_CALL,      // Do authentication on every call
+        RPC_C_IMP_LEVEL_IMPERSONATE, // Allow full impersonation.
+        NULL,                        // Use current client identity
+        EOAC_NONE                    // No extended proxy capabilities
+    );
+    if (FAILED(hres)) {
+        goto err_out;
+    }
+
+
+
+    /* All done. */
+    return;
+
+err_out:
+    ReleaseWMIAccessor(wmi);
+    return;
+}
+
+/* Careful: WMI accessors must be released on the same thread that
+   allocated them. */
+void ReleaseWMIAccessor(struct WMIAccessor *wmi)
+{
+    if (wmi == NULL)
+        return;
+    if (wmi->mpXSSvc != NULL)
+        wmi->mpXSSvc->Release();
+    if (wmi->mpSvc != NULL)
+        wmi->mpSvc->Release();
+    if (wmi->com_initialized) {
+        ASSERT(wmi->owning_thread == GetCurrentThread());
+        CoUninitialize();
+    }
+    /* Poison wmi to make use-after-free()s a bit more obvious. */
+    memset(wmi, 0xab, sizeof(*wmi));
+    free(wmi);
+}
+
+/* The fact that something is documented as being a uint64_t field
+   doesn't imply that it will be returned as a VT_UI8 field in a
+   variant structure.  Work around this with a handy conversion
+   function. */
+static uint64_t
+GetVariantUint64(VARIANT *vtData)
+{
+    switch (vtData->vt) {
+    case VT_I2:
+        return vtData->iVal;
+    case VT_I4:
+        return vtData->lVal;
+    case VT_I8:
+        return vtData->llVal;
+    case VT_UI2:
+        return vtData->uiVal;
+    case VT_UI4:
+        return vtData->ulVal;
+    case VT_UI8:
+        return vtData->ullVal;
+    case VT_BSTR:
+        /* Yes, I really do mean BSTR: XP returns 64 bit values as
+           strings, and we then have to do atoill on it. */
+        return _wtoi64(vtData->bstrVal);
+    default:
+        DBGPRINT(("Bad uint64_t variant %d.\n",vtData->vt));
+        return -1;
+    }
+}
+
+static HRESULT
+QueryVariant(WMIAccessor *wmi, PWCHAR field, PWCHAR table, VARIANT *vt)
+{
+    IEnumWbemClassObject *pEnum;
+    BSTR query;
+    unsigned query_len;
+    IWbemClassObject *pclsObj;
+    HRESULT hr;
+    ULONG uReturn;
+    uint64_t result;
+
+    query_len = strlen("SELECT  FROM ") + wcslen(field) + wcslen(table) + 1;
+    query = SysAllocStringLen(NULL, query_len);
+    if (query == NULL) {
+        hr = E_OUTOFMEMORY;
+        goto err;
+    }
+    swprintf_s(query, query_len, L"SELECT %s FROM %s", field, table);
+    pEnum = runQuery(wmi, query);
+    SysFreeString(query);
+
+    if (pEnum == NULL) {
+        hr = E_OUTOFMEMORY;
+        goto err;
+    }
+
+    hr = pEnum->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
+    pEnum->Release();
+    if (FAILED(hr))
+        goto err;
+    if (uReturn == 0) {
+        hr = E_FAIL;
+        goto err;
+    }
+
+    hr = pclsObj->Get(field, 0, vt, NULL, NULL);
+    pclsObj->Release();
+
+    return hr;
+
+err:
+    return hr;
+}
+
+static uint64_t
+QueryUint64(WMIAccessor *wmi, PWCHAR field, PWCHAR table)
+{
+    HRESULT hr;
+    uint64_t res;
+    VARIANT vt;
+
+    memset(&vt, 0, sizeof(vt));
+
+    hr = QueryVariant(wmi, field, table, &vt);
+    if (FAILED(hr))
+        return 0;
+
+    res = GetVariantUint64(&vt);
+    VariantClear(&vt);
+    return res;
+}
+
+static BSTR
+QueryBstr(WMIAccessor *wmi, PWCHAR field, PWCHAR table)
+{
+    HRESULT hr;
+    BSTR res;
+    VARIANT vt;
+
+    memset(&vt, 0, sizeof(vt));
+
+    hr = QueryVariant(wmi, field, table, &vt);
+    if (FAILED(hr))
+        return NULL;
+    if (vt.vt != VT_BSTR) {
+        VariantClear(&vt);
+        return NULL;
+    }
+    return vt.bstrVal;
+}
+
+void GetWMIData(WMIAccessor *wmi, VMData& data)
+{
+    data.meminfo_free = QueryUint64(wmi, L"FreePhysicalMemory",
+                                    L"Win32_OperatingSystem");
+    //
+    // Get total memory.  We don't support ballooning, and so this can't
+    // change for the life of the VM.
+    //
+
+    static int64_t meminfo_total;
+    if (meminfo_total == 0) {
+        meminfo_total = QueryUint64(wmi, L"TotalPhysicalMemory",
+                                    L"Win32_ComputerSystem");
+        /* For some reason, TotalPhysicalMemory is in bytes but
+           FreePhysicalMemoryy is in megabytes.  The agent expects
+           megabytes, so do the conversion here. */
+        meminfo_total >>= 10;
+    }
+    data.meminfo_total = meminfo_total;
+}
+
+void DumpOSData(WMIAccessor *wmi)
+{
+    BSTR os_name;
+    BSTR host_name;
+    BSTR domain;
+
+    os_name = QueryBstr(wmi, L"Name", L"Win32_OperatingSystem");
+    if (os_name != NULL) {
+        string str = bstr2string(os_name);
+        SysFreeString(os_name);
+
+        XenstoreWrite("data/os_name", str.c_str(), str.length());
+    }
+    host_name = QueryBstr(wmi, L"Name", L"Win32_ComputerSystem");
+    if (host_name != NULL) {
+        string str = bstr2string(host_name);
+        SysFreeString(host_name);
+
+        XenstoreWrite("data/host_name", str.c_str(), str.length());
+    }
+    domain = QueryBstr(wmi, L"Domain", L"Win32_ComputerSystem");
+    if (domain != NULL) {
+        string str = bstr2string(domain);
+        SysFreeString(domain);
+
+        XenstoreWrite("data/domain", str.c_str(), str.length());
+    }
+}
+
+/* hash comparator for strings which strips off trailing .exe
+ * suffix */
+class string_eq_exe {
+private:
+    static size_t len_without_suffix(const char *x)
+    {
+        size_t l;
+        l = strlen(x);
+        if (l > 4 && !strcmp(x + l - 4, ".exe"))
+            l -= 4;
+        return l;
+    }
+
+public:
+    enum {bucket_size = 4, min_buckets = 8};
+    bool operator()(const string &a, const string &b) const
+    {
+        const char *a_c, *b_c;
+        size_t a_l, b_l;
+        a_c = a.c_str();
+        b_c = b.c_str();
+        a_l = len_without_suffix(a_c);
+        b_l = len_without_suffix(b_c);
+
+        if (a_l != b_l)
+            return 1;
+        if (memcmp(a_c, b_c, a_l))
+            return 1;
+        else
+            return 0;
+    }
+
+    size_t operator()(const string &a) const
+    {
+        size_t acc = 0;
+        const char *c_str = a.c_str();
+        size_t len = len_without_suffix(c_str);
+        unsigned x;
+        for (x = 0; x < len; x++)
+            acc = (acc * 17 + c_str[x]) % 257;
+        return acc;
+    }
+};
+
+
+IWbemClassObject *getBase(WMIAccessor* wmi) 
+{
+    return getObject(wmi, L"CitrixXenStoreBase");
+}
+IWbemClassObject *getBaseClass(WMIAccessor* wmi) 
+{
+    return getClass(wmi, L"CitrixXenStoreBase");
+}
+
+ULONGLONG get64BitUnsigned(VARIANT *var) {
+    ULONGLONG res = 0;
+    switch (var->vt) {
+        case VT_BSTR: {
+                VARIANT outvar;
+                VariantInit(&outvar);
+                VariantChangeType(&outvar, var, 0, VT_UI8);
+                res = outvar.ullVal;
+                VariantClear(&outvar);
+            }
+            break;
+        case VT_UI8: {
+                res = var->ullVal;
+            }
+            break;
+    }
+    return res;
+}
+
+FILETIME WmiGetXenTime(WMIAccessor *wmi) {
+     FILETIME out;
+     IWbemClassObject *base = getBase(wmi);
+     if (base == NULL) {
+         DBGPRINT(("Unable to find base WMI session\n"));
+         out.dwLowDateTime = 0;
+         out.dwHighDateTime = 0;
+         return out ;
+     }
+     VARIANT timevar;
+     BSTR timename = mkBstr("XenTime", 7);
+     base->Get(timename, 0, &timevar, NULL, NULL);
+
+     ULONGLONG time =get64BitUnsigned(&timevar);;
+
+     out.dwLowDateTime = (DWORD)time;
+     out.dwHighDateTime = (DWORD)(time>>32);
+     return out;
+
+}
+
+IWbemClassObject *openSession(WMIAccessor* wmi, const char *sessionname)
+{
+    HRESULT hres;
+
+    BSTR query = formatBstr("SELECT * FROM CitrixXenStoreSession WHERE Id=\"Citrix Xen Win32 Service : %s\"", sessionname);
+
+
+    IEnumWbemClassObject * sessions = runXSQuery(wmi, query);
+    SysFreeString(query);
+    if (sessions) {
+        IWbemClassObject *returnedObject;
+        ULONG count;
+        hres = sessions->Next(WBEM_INFINITE, 1, &returnedObject, &count);
+        sessions->Release();
+        if (count>0) {
+            if (sessionname !=NULL ) {
+                WmiSessionEnd(wmi, returnedObject);
+            }
+            else {
+                return returnedObject;
+            }
+        }
+    }
+    IWbemClassObject *base = getBase(wmi);
+    if (base==NULL) {
+        DBGPRINT(("Unable to find base WMI session\n"));
+        return NULL;
+    }
+    IWbemClassObject *baseclass = getBaseClass(wmi);
+    IWbemClassObject *inMethod;
+    IWbemClassObject *outMethod;
+    IWbemClassObject *inMethodInst;
+    IWbemClassObject *outMethodInst;
+    baseclass->GetMethod(L"AddSession",0,&inMethod, &outMethod);
+
+    inMethod->SpawnInstance(0, &inMethodInst);
+    VARIANT var;
+    var.vt = VT_BSTR;
+    var.bstrVal=formatBstr("Citrix Xen Win32 Service : %s", sessionname);
+    inMethodInst->Put(L"Id", 0, &var, 0);
+    methodExec(wmi, base, L"AddSession", inMethodInst, &outMethodInst);
+    VariantClear(&var);
+    outMethodInst->Get(L"SessionId", 0, &var, NULL, NULL);
+
+    ULONG query_len;
+    query_len = strlen("SELECT * FROM CitrixXenStoreSession WHERE SessionId=")+10;
+    query = SysAllocStringLen(NULL, query_len);
+    swprintf_s(query,query_len, L"SELECT * FROM CitrixXenStoreSession WHERE SessionId=%d", var.uintVal);
+
+    sessions = runXSQuery(wmi, query );
+
+    if (sessions) {
+         IWbemClassObject *returnedObject;
+        ULONG count;
+        hres = sessions->Next(WBEM_INFINITE, 1, &returnedObject, &count);
+        if (count>0) {
+            sessions->Release();
+            return returnedObject;
+        }
+        sessions->Release();
+    }
+
+    base->Release();
+    return NULL;
+}
+
+IWbemClassObject* sessionMethodStart(WMIAccessor*wmi,  
+                                     const wchar_t *methodname)
+{
+    IWbemClassObject *inMethod;
+    IWbemClassObject *outMethod;
+    IWbemClassObject *inMethodInst = NULL;
+    IWbemClassObject *sessionClass;
+    sessionClass = getClass(wmi, L"CitrixXenStoreSession");
+    if (sessionClass!=NULL) {
+      sessionClass->GetMethod(methodname,0,&inMethod, &outMethod);
+      inMethod->SpawnInstance(0, &inMethodInst);
+    }
+    return inMethodInst;
+}
+
+
+char * bstrToChar(BSTR bst) {
+    size_t size = wcslen(bst);
+    char *space = (char *)XsAlloc(size+1);
+    wcstombs_s(&size, space, size+1, bst,  _TRUNCATE);
+    return space;
+}
+
+void WmiSessionLog(WMIAccessor* wmi,  void **sessionhandle,const char *fmt, va_list args) {
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+    
+    char* message = formatCharStrInt(fmt,args);
+    
+    VARIANT vmessage;
+    if (setVariantString(&vmessage, message))
+        goto setvmessage;
+
+    IWbemClassObject *inMethodInst = sessionMethodStart( wmi, L"Log");
+    if (!inMethodInst)
+        goto sessionstart;
+    
+     inMethodInst->Put(L"Message",0,&vmessage,0);
+
+     methodExec(wmi,*session, L"Log", inMethodInst, NULL);
+
+sessionstart:
+    VariantClear(&vmessage);
+setvmessage:
+    return;
+}
+
+char **WmiSessionGetChildren(WMIAccessor* wmi, void **sessionhandle,
+              const char * path, unsigned *numentries) {
+
+    char **outarray = NULL;
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+     
+
+    VARIANT vpath;
+    if (setVariantString(&vpath, path)){
+        goto setvpath;
+    }
+    IWbemClassObject *outMethodInst;
+    IWbemClassObject *inMethodInst = sessionMethodStart( wmi, L"GetChildren");
+    if (!inMethodInst)
+        goto sessionstart;
+    inMethodInst->Put(L"PathName",0,&vpath,0);
+    methodExec(wmi,*session, L"GetChildren", inMethodInst, &outMethodInst);
+    if (outMethodInst==NULL) {
+        *numentries = 0;
+        goto sessionExec;
+    }
+
+    VARIANT children;
+    VariantInit(&children);
+    outMethodInst->Get(L"children", 0, &children, NULL, NULL);
+    
+    IWbemClassObject* innerobj = (IWbemClassObject *)(children.byref);
+
+    VARIANT noOfChildren;
+    innerobj->Get(L"NoOfChildNodes", 0, &noOfChildren, NULL, NULL);
+
+
+    VARIANT childNodeArray;
+
+    innerobj->Get(L"ChildNodes", 0, &childNodeArray, NULL, NULL);
+
+    LONG i;
+    *numentries = -1;
+    if (noOfChildren.lVal >0) {
+        outarray = (char **)XsAlloc(sizeof(char *) * noOfChildren.lVal);
+        for (i = 0; i< noOfChildren.lVal; i++) {
+            
+            BSTR arrayentry;
+            HRESULT hres = SafeArrayGetElement(childNodeArray.parray, &i, &arrayentry);
+            if (FAILED(hres)) {
+            }
+            outarray[i] = bstrToChar(arrayentry);
+        }
+
+        *numentries = noOfChildren.lVal;
+    }
+    VariantClear(&childNodeArray);
+    VariantClear(&noOfChildren);
+    VariantClear(&children);
+
+
+    if (outMethodInst != NULL) {
+        outMethodInst->Release();
+    }
+sessionExec:
+sessionstart:
+setvpath:
+   
+    return outarray;
+
+}
+
+
+char* WmiSessionGetEntry(WMIAccessor* wmi, void **sessionhandle,
+              const char * path, size_t* len) 
+{
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+
+    VARIANT vpath;
+    if (setVariantString(&vpath, path)){
+        goto setvpath;
+    }
+    IWbemClassObject *outMethodInst;
+    IWbemClassObject *inMethodInst = sessionMethodStart( wmi, L"GetValue");
+    inMethodInst->Put(L"PathName",0,&vpath,0);
+    methodExec(wmi,*session, L"GetValue", inMethodInst, &outMethodInst);
+    if (outMethodInst==NULL)
+        goto sessionExec;
+
+    VARIANT outval;
+    VariantInit(&outval);
+
+    outMethodInst->Get(L"value", 0, &outval, NULL, NULL);
+
+    char *space = bstrToChar(outval.bstrVal);
+    
+    VariantClear(&outval); 
+    return space;
+setvpath:
+sessionExec:
+    *len = 0;
+    return NULL;
+}
+
+int WmiSessionSetEntry(WMIAccessor* wmi,  void **sessionhandle, 
+              const char*path, const char * value, size_t len)
+{
+    int err = -1;
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+
+    VARIANT vpath;
+    if (setVariantString(&vpath, path)){
+        goto setvpath;
+    }
+    VARIANT vvalue;
+    if (setVariantString(&vvalue, value))
+        goto setvvalue;
+    IWbemClassObject *outMethodInst;
+    IWbemClassObject *inMethodInst = sessionMethodStart( wmi, L"SetValue");
+    if (!inMethodInst)
+        goto sessionstart;
+    inMethodInst->Put(L"PathName",0,&vpath,0);
+    inMethodInst->Put(L"value",0,&vvalue,0);
+    methodExec(wmi,*session, L"SetValue", inMethodInst, &outMethodInst);
+    if (outMethodInst==NULL)
+        goto sessionExec;
+
+    outMethodInst->Release();
+
+    err=0;
+
+sessionExec:     
+sessionstart:
+
+    SysFreeString(vvalue.bstrVal);
+setvvalue:
+
+    SysFreeString(vpath.bstrVal);
+setvpath:
+    return err;
+}
+
+int WmiSessionSetEntry(WMIAccessor* wmi,  void **sessionhandle, 
+              const char*path, const char * value) {
+    return WmiSessionSetEntry(wmi, sessionhandle, path, value, strlen(value));
+}
+
+int WmiSessionRemoveEntry(WMIAccessor* wmi,  void **sessionhandle, 
+              const char*path){
+    int err = -1;
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+
+    VARIANT vpath;
+    if (setVariantString(&vpath, path)){
+        goto setvpath;
+    }
+    IWbemClassObject *inMethodInst = sessionMethodStart( wmi, L"RemoveValue");
+    if (!inMethodInst)
+        goto sessionstart;
+    inMethodInst->Put(L"PathName",0,&vpath,0);
+    IWbemClassObject* outMethodInst;
+    methodExec(wmi,*session, L"RemoveValue", inMethodInst, &outMethodInst);
+    if (outMethodInst==NULL)
+        goto sessionExec;
+    outMethodInst->Release();
+
+    err=0;
+sessionstart:
+    VariantClear(&vpath);
+sessionExec:
+setvpath:
+    return err; 
+}
+
+int WmiSessionTransactionStart(WMIAccessor* wmi,  void **sessionhandle) 
+{
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+
+    if (FAILED(methodExec(wmi,*session, L"StartTransaction", NULL,NULL))) {
+        return 0;
+    }
+    return 1;
+}
+
+int WmiSessionTransactionCommit(WMIAccessor* wmi,  void **sessionhandle) 
+{
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+    if (FAILED(methodExec(wmi,*session, L"CommitTransaction", NULL,NULL))) {
+        return 0;
+    }
+    return 1;
+}
+
+int WmiSessionTransactionAbort(WMIAccessor* wmi,  void **sessionhandle) 
+{
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+
+    if (FAILED(methodExec(wmi,*session, L"AbortTransaction", NULL,NULL))) {
+        return 0;
+    }
+    return 1;
+}
+
+
+void WmiSessionUnwatch(WMIAccessor* wmi,  void **sessionhandle,
+                         void *watchhandle) {
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+
+    WatchSink * sink = (WatchSink *)watchhandle;
+
+    VARIANT vpath;
+    if (setVariantString(&vpath, sink->path)){
+        goto setvpath;
+    }
+    IWbemClassObject *outMethodInst;
+    IWbemClassObject *inMethodInst = sessionMethodStart( wmi, L"RemoveWatch");
+    if (!inMethodInst)
+        goto sessionstart;
+    inMethodInst->Put(L"PathName",0,&vpath,0);
+    methodExec(wmi,*session, L"RemoveWatch", inMethodInst, &outMethodInst);
+    if (outMethodInst==NULL)
+        goto sessionExec;
+    outMethodInst->Release();
+sessionExec:
+    inMethodInst->Release();
+sessionstart:
+setvpath:
+    sink->Release();
+}
+
+void WmiSessionStart(WMIAccessor* wmi,  void **sessionhandle, const char* sessionname) 
+{
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+    *session = openSession(wmi, sessionname);
+}
+
+
+void WmiSessionEnd(WMIAccessor* wmi,  void *sessionhandle) 
+{
+    IWbemClassObject *session = (IWbemClassObject *)sessionhandle;
+    if (session==NULL) {
+        return;
+    }
+    methodExec(wmi, session, L"EndSession", NULL,NULL);
+    session->Release();
+
+}
+
+void *WmiSessionWatch(WMIAccessor* wmi,  void **sessionhandle, 
+                      const char *path, HANDLE event) {
+       
+    
+    IWbemClassObject **session = (IWbemClassObject **)sessionhandle;
+     
+    WatchSink * sink = new WatchSink(event, path);
+    BSTR query=formatBstr("SELECT * from CitrixXenStoreWatchEvent WHERE EventId=\"%s\"", path);
+
+    wmi->mpXSSvc->ExecNotificationQueryAsync(L"WQL", query,0,NULL, sink);
+
+
+    VARIANT vpath;
+    if (setVariantString(&vpath, path)){
+        goto setvpath;
+    }
+    IWbemClassObject *outMethodInst;
+    IWbemClassObject *inMethodInst = sessionMethodStart( wmi, L"SetWatch");
+    if (!inMethodInst)
+        goto sessionstart;
+    inMethodInst->Put(L"PathName",0,&vpath,0);
+    methodExec(wmi,*session, L"SetWatch", inMethodInst, &outMethodInst);
+    if (outMethodInst==NULL)
+        goto sessionExec;
+    outMethodInst->Release();
+sessionExec:
+sessionstart:
+setvpath:
+    return sink;
+}
+
+void *WmiUnsuspendedEventWatch(WMIAccessor *wmi, HANDLE event) 
+{
+    WatchSink * sink = new WatchSink(event, NULL);
+    BSTR query=formatBstr("SELECT * from CitrixXenStoreUnsuspendedEvent");
+
+    wmi->mpXSSvc->ExecNotificationQueryAsync(L"WQL", query,0,NULL, sink);
+    return sink;
+}
+
diff --git a/src/win32stubagent/WmiAccessor.h b/src/win32stubagent/WmiAccessor.h
new file mode 100644 (file)
index 0000000..c9bb9d4
--- /dev/null
@@ -0,0 +1,90 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _WMIACCESSOR_H
+#define _WMIACCESSOR_H
+
+#include <Wbemidl.h>
+#include <list>
+#include <vector>
+#include <map>
+#include <string>
+
+#include "vm_stats.h"
+#include "XSAccessor.h"
+
+using namespace std;
+
+typedef unsigned __int64 uint64_t;
+
+struct WMIAccessor;
+
+extern struct WMIAccessor *wmi;
+
+void ConnectToWMI(void);
+void ReleaseWMIAccessor(struct WMIAccessor *);
+
+void GetWMIData(WMIAccessor *wmi, VMData& data);
+void DumpOSData(WMIAccessor *wmi);
+
+VOID AddHotFixInfoToStore(WMIAccessor* wmi);
+void UpdateProcessListInStore(WMIAccessor *wmi);
+
+int WmiSessionSetEntry(WMIAccessor* wmi,  void **sessionhandle, 
+              const char*path, const char * value);
+
+int WmiSessionSetEntry(WMIAccessor* wmi,  void **sessionhandle, 
+              const char*path, const char * value, size_t len);
+char* WmiSessionGetEntry(WMIAccessor* wmi, void **sessionhandle,
+              const char * path, size_t* len) ;
+
+void *WmiSessionWatch(WMIAccessor* wmi,  void **sessionhandle, 
+                      const char *path, HANDLE event);
+void WmiSessionUnwatch(WMIAccessor* wmi,  void **sessionhandle,
+                         void *watchhandle);
+
+int WmiSessionRemoveEntry(WMIAccessor* wmi,  void **sessionhandle, 
+              const char*path);
+
+char **WmiSessionGetChildren(WMIAccessor* wmi, void **sessionhandle,
+              const char * path, unsigned *numentries);
+
+
+void *WmiUnsuspendedEventWatch(WMIAccessor *wmi, HANDLE event);
+
+int WmiSessionTransactionAbort(WMIAccessor* wmi,  void **sessionhandle); 
+int WmiSessionTransactionCommit(WMIAccessor* wmi,  void **sessionhandle); 
+int WmiSessionTransactionStart(WMIAccessor* wmi,  void **sessionhandle); 
+void WmiSessionStart(WMIAccessor* wmi,  void **sessionhandle, const char *sessionname);
+void WmiSessionEnd(WMIAccessor* wmi,  void *sessionhandle);
+FILETIME WmiGetXenTime(WMIAccessor *wmi);
+void WmiSessionLog(WMIAccessor* wmi,  void **sessionhandle,const char *fmt, va_list args);
+#endif
diff --git a/src/win32stubagent/XSAccessor.cpp b/src/win32stubagent/XSAccessor.cpp
new file mode 100644 (file)
index 0000000..00ef846
--- /dev/null
@@ -0,0 +1,276 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#include <windows.h>
+#include "stdafx.h"
+#include "XSAccessor.h"
+//#include "xs_private.h"
+#include "WMIAccessor.h"
+
+static __declspec(thread) void *WmiSessionHandle = NULL;
+
+static LONG volatile threadcount = 0;
+static __declspec(thread) LONG localthreadcount = 0;
+
+static int64_t update_cnt;
+#define XENSTORE_MAGIC 0x7e6ec123
+
+void *XsAlloc(size_t size) {
+    void *buf;
+
+    buf = malloc(size + 8);
+    if (!buf) {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return NULL;
+    }
+    memset(buf, 0, size + 8);
+    *(unsigned *)buf = XENSTORE_MAGIC;
+    return (void *)((ULONG_PTR)buf + 8);
+}
+
+void XsFree(const void *buf) {
+    void *orig_buf;
+
+    if (!buf)
+        return;
+    orig_buf = (void *)((ULONG_PTR)buf - 8);
+    if (*(unsigned *)orig_buf != XENSTORE_MAGIC) {
+        OutputDebugString("XsFree() invoked on bad pointer");
+        DebugBreak();
+    }
+    free(orig_buf);
+}
+
+void GetXenTime(FILETIME *now)
+{
+    *now = WmiGetXenTime(wmi);
+}
+
+int ListenSuspend(HANDLE event)
+{
+    if (!WmiUnsuspendedEventWatch(wmi, event))
+        return -1;
+    else
+        return 0;
+}
+
+void InitXSAccessor()
+{
+    DBGPRINT(("XSAccessor"));
+    if (WmiSessionHandle == NULL) {
+        if (localthreadcount == 0) {
+            localthreadcount = InterlockedIncrement(&threadcount);
+        }
+        char wminame[12];
+        _snprintf(wminame, 12, "XS%x", localthreadcount);
+        WmiSessionStart(wmi, &WmiSessionHandle, wminame);
+    }
+    if (WmiSessionHandle == NULL)
+        exit(1);
+}
+
+void XsLog(const char *fmt, ...)
+{
+    va_list args;
+    if (!WmiSessionHandle) {
+        InitXSAccessor();
+    }
+
+    va_start(args, fmt);
+    WmiSessionLog(wmi, &WmiSessionHandle, fmt, args);
+    va_end(args);
+}
+
+
+void ShutdownXSAccessor(void)
+{
+    WmiSessionEnd(wmi, WmiSessionHandle);
+
+}
+
+int XenstorePrintf(const char *path, const char *fmt, ...)
+{
+    va_list l;
+    char buf[4096];
+    int ret;
+    int cnt;
+
+    va_start(l, fmt);
+    cnt = _vsnprintf(buf, sizeof(buf), fmt, l);
+    va_end(l);
+    if (cnt < 0) {
+        DBGPRINT (("Cannot format data for XenstorePrintf!"));
+        return -1;
+    }
+
+    /* Now have the thing we're trying to write. */
+    return WmiSessionSetEntry(wmi, &WmiSessionHandle, path, buf);
+}
+
+int XenstoreWrite(const char *path, const void *data, size_t len)
+{
+    return WmiSessionSetEntry(wmi, &WmiSessionHandle, path, (const char *)data, len);
+}
+
+void XenstoreKickXapi()
+{
+    /* Old protocol */
+    WmiSessionSetEntry(wmi, &WmiSessionHandle, "data/updated", "1");
+    /* New protocol */
+    XenstorePrintf("data/update_cnt", "%I64d", update_cnt);
+
+    update_cnt++;
+}
+
+void XenstoreDoDump(VMData *data)
+{
+    XenstorePrintf("data/meminfo_free", "%I64d", data->meminfo_free);
+    XenstorePrintf("data/meminfo_total", "%I64d", data->meminfo_total);
+}
+
+int XenstoreDoNicDump(
+    uint32_t num_vif,
+    VIFData *vif
+    )
+{
+    DWORD hStatus;
+    unsigned int i;
+    int ret = 0;
+    char path[MAX_CHAR_LEN] = "";
+    const char* domainVifPath = "data/vif";
+    unsigned int entry;     
+    unsigned int numEntries;
+    char** vifEntries = NULL;
+    char vifNode[MAX_XENBUS_PATH];
+
+    //
+    // Do any cleanup first outside of a transaction since failures are allowed
+    // and in some cases expected.
+    //
+    // Remove all of the old vif entries in case the nics have been
+    // disabled.  Otherwise they will have old stale data in xenstore.
+    //
+    if (XenstoreList(domainVifPath, &vifEntries, &numEntries) >= 0) {
+        for (entry = 0; entry < numEntries; entry++) {
+            _snprintf(path, MAX_CHAR_LEN, "%s", vifEntries[entry]);
+            WmiSessionRemoveEntry(wmi, &WmiSessionHandle, path);
+            _snprintf(path, MAX_CHAR_LEN, "attr/eth%s", vifEntries[entry]+9);
+            WmiSessionRemoveEntry(wmi, &WmiSessionHandle, path);
+            XsFree(vifEntries[entry]);
+        }
+        XsFree(vifEntries);
+    }
+    do 
+    {
+        hStatus = ERROR_SUCCESS;
+        WmiSessionTransactionStart(wmi, &WmiSessionHandle );
+        ret |= XenstorePrintf("data/num_vif", "%d", num_vif);
+
+        for( i = 0; i < num_vif; i++ ){
+            if (vif[i].ethnum != -1) {
+                _snprintf(path, MAX_CHAR_LEN, "data/vif/%d/name" , vif[i].ethnum);
+                path[MAX_CHAR_LEN-1] = 0;
+                ret |= XenstorePrintf(path, "%s", vif[i].name);
+
+
+                //
+                // IP address is dumped to /attr/eth[x]/ip
+                //
+                _snprintf (path, MAX_CHAR_LEN, "attr/eth%d/ip", vif[i].ethnum);
+                path[MAX_CHAR_LEN-1] = 0;
+                ret |= XenstorePrintf (path, "%s", vif[i].ip);
+
+            }
+        }
+        if(!WmiSessionTransactionCommit(wmi, &WmiSessionHandle))
+        {
+            hStatus = GetLastError ();
+            if (hStatus != ERROR_RETRY)
+            {
+                return -1;
+            }
+        }
+
+    } while (hStatus == ERROR_RETRY);
+       return ret;
+}
+
+int
+XenstoreList(const char *path, char ***entries, unsigned *numEntries)
+{
+    *entries = WmiSessionGetChildren(wmi, &WmiSessionHandle, path, numEntries);
+    if (*entries) {
+        return 0;
+    }
+    else {
+        return -1;
+    }
+}
+
+int
+XenstoreRemove(const char *path)
+{
+    if (WmiSessionRemoveEntry(wmi, &WmiSessionHandle, path))
+        return -1;
+    else
+        return 0;
+}
+
+ssize_t
+XenstoreRead(const char* path, char** value)
+{
+    size_t len;
+    *value =WmiSessionGetEntry(wmi, &WmiSessionHandle, path, &len);
+    if (*value)
+        return len;
+    else
+        return -1;
+}
+
+void *
+XenstoreWatch(const char *path, HANDLE event)
+{
+    return WmiSessionWatch(wmi, &WmiSessionHandle, path, event);
+}
+
+void
+XenstoreUnwatch(void *watch)
+{
+    return WmiSessionUnwatch(wmi, &WmiSessionHandle, watch);
+}
+
+void 
+XenstoreFree(void *tofree)
+{
+    return free(tofree);
+}
+
diff --git a/src/win32stubagent/XSAccessor.h b/src/win32stubagent/XSAccessor.h
new file mode 100644 (file)
index 0000000..0acb439
--- /dev/null
@@ -0,0 +1,128 @@
+/* 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 _XSACCESSOR_H
+#define _XSACCESSOR_H
+
+#include <string>
+
+#include "vm_stats.h"
+
+using namespace std;
+
+#define MAX_XENBUS_PATH 256
+
+#ifdef AMD64
+typedef long long ssize_t;
+#else
+typedef long ssize_t;
+#endif
+
+void InitXSAccessor();
+void ShutdownXSAccessor();
+int XenstoreList(const char *path, char ***entries, unsigned *numEntries);
+ssize_t XenstoreRead(const char *path, char **value);
+int XenstoreRemove(const char *path);
+int XenstorePrintf(const char *path, const char *fmt, ...);
+int XenstoreWrite(const char *path, const void *data, size_t len);
+void XenstoreKickXapi(void);
+void XenstoreDoDump(VMData *data);
+int XenstoreDoNicDump(uint32_t num_vif, VIFData *vif);
+void *XenstoreWatch(const char *path, HANDLE event);
+void XenstoreUnwatch(void *watch);
+int ListenSuspend(HANDLE event);
+void GetXenTime(FILETIME *res);
+void XsLog(const char *fmt, ...);
+void XenstoreFree(void *tofree);
+void *XsAlloc(size_t size);
+void XsFree(const void *buf);
+
+#if DBG
+
+#include <stdarg.h>         // va_list
+#include <stdio.h>          // vsprintf
+#include <malloc.h>
+
+#include <assert.h>
+#include <tchar.h>
+
+__inline void DebugPrint( IN LPCTSTR msg, IN ... )
+{
+    TCHAR   buffer[256];
+    int     res;
+    va_list args;
+
+    va_start( args, msg );
+#pragma prefast(suppress: 28719, "Yes, we all know _vsnprintf is banned in drivers, this is user level");
+    res = _vsntprintf(buffer, sizeof(buffer) / sizeof(buffer[0]), msg, args);
+    if (res >= 0)
+    {
+        OutputDebugString( buffer );
+    }
+    else
+    {
+        TCHAR *p;
+        int count;
+
+        count = 512;
+        for (;;) {
+            p = (TCHAR *)malloc(count * sizeof (TCHAR));
+            if (!p) {
+                OutputDebugString(_T("Out of memory for debug message!"));
+                break;
+            }
+            res = _vsntprintf(p, count, msg, args);
+            if (res >= 0)
+                break;
+
+            free(p);
+            count += 256;
+        }
+        if (p) {
+            OutputDebugString( p );
+            free(p);
+        }
+    }
+    va_end(args);
+}
+
+#define DBGPRINT(_x_) DebugPrint _x_
+#define ASSERT  assert
+
+#else
+
+#define DBGPRINT(_x_) 
+#define ASSERT  
+
+#endif // DBG
+
+#endif
diff --git a/src/win32stubagent/XService.cpp b/src/win32stubagent/XService.cpp
new file mode 100644 (file)
index 0000000..8ef7618
--- /dev/null
@@ -0,0 +1,1111 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#include <windows.h>
+#include <shlobj.h>
+#include <process.h>
+#include <powrprof.h>
+#include <winuser.h>
+#include "stdafx.h"
+#include "XSAccessor.h"
+#include "WMIAccessor.h"
+#include "XService.h"
+#include "vm_stats.h"
+#include "NicInfo.h"
+
+//#include "xs_private.h"
+#include "version.h"
+#include "messages.h"
+#include "TSInfo.h"
+
+#include <setupapi.h>
+#include <cfgmgr32.h>
+#include <initguid.h>
+#include <devguid.h>
+#include <wintrust.h>
+#include <shellapi.h>
+
+#ifdef AMD64
+#define XENTOOLS_INSTALL_REG_KEY "SOFTWARE\\Wow6432Node\\Citrix\\XenTools"
+#else
+#define XENTOOLS_INSTALL_REG_KEY "SOFTWARE\\Citrix\\XenTools"
+#endif
+
+SERVICE_STATUS ServiceStatus; 
+SERVICE_STATUS_HANDLE hStatus;  
+
+static HANDLE hServiceExitEvent;
+static ULONG WindowsVersion;
+static BOOL LegacyHal = FALSE;
+static HINSTANCE local_hinstance;
+
+#define SIZECHARS(x) (sizeof((x))/sizeof(TCHAR))
+
+// Internal routines
+static DWORD WINAPI ServiceControlHandler(DWORD request, DWORD evtType,
+                                          LPVOID, LPVOID);
+static void ServiceControlManagerUpdate(DWORD dwExitCode, DWORD dwState);
+static void WINAPI ServiceMain(int argc, char** argv);
+static void GetWindowsVersion();
+
+void PrintError(const char *func, DWORD err)
+{
+       LPVOID lpMsgBuf;
+       FormatMessage(
+               FORMAT_MESSAGE_ALLOCATE_BUFFER |
+               FORMAT_MESSAGE_FROM_SYSTEM,
+               NULL,
+               err,
+               MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+               (LPTSTR) &lpMsgBuf,
+               0,
+               NULL);
+       DBGPRINT(("%s failed: %s (%lx)\n", func, lpMsgBuf, err));
+    XenstorePrintf("control/error", "%s failed: %s (%x)", func, lpMsgBuf, err);
+       LocalFree(lpMsgBuf);
+}
+
+void PrintError(const char *func)
+{
+       PrintError(func, GetLastError());
+}
+
+void PrintUsage()
+{
+       printf("Usage: xenservice [-i|-u|-c|-t]\n");
+       printf("\t -i: install service\n");
+       printf("\t -u: uninstall service\n");
+}
+
+HMODULE SLC_API;
+HMODULE SLWGA_API;
+
+typedef HRESULT (WINAPI *SL_GET_WINDOWS_INFORMATION_DWORD)(
+    __in    PCWSTR  pwszValueName,
+    __out   DWORD   *pdwValue
+    );
+
+typedef GUID SLID;
+
+typedef enum _SL_GENUINE_STATE {
+  SL_GEN_STATE_IS_GENUINE        = 0,
+  SL_GEN_STATE_INVALID_LICENSE   = 1,
+  SL_GEN_STATE_TAMPERED          = 2,
+  SL_GEN_STATE_LAST              = 3 
+} SL_GENUINE_STATE;
+
+typedef HRESULT (WINAPI *SL_IS_GENUINE_LOCAL)(
+    __in        const SLID                  *pAppId,
+    __out       SL_GENUINE_STATE            *pGenuineState,
+    __inout_opt VOID                        *pUnused
+    );
+
+/* Add operating system version, service pack, etc. to store. */
+static VOID
+AddSystemInfoToStore(
+    WMIAccessor* wmi
+    )
+{
+    OSVERSIONINFOEX info;
+    char buf[MAX_PATH];
+    
+    XenstorePrintf("attr/os/class", "windows NT");
+    /* Windows version, service pack, build number */
+    info.dwOSVersionInfoSize = sizeof(info);
+    if (GetVersionEx((LPOSVERSIONINFO)&info)) {
+#define do_field(name, field) \
+        XenstorePrintf("attr/os/" #name , "%d", info. field)
+        do_field(major, dwMajorVersion);
+        do_field(minor, dwMinorVersion);
+        do_field(build, dwBuildNumber);
+        do_field(platform, dwPlatformId);
+        do_field(spmajor, wServicePackMajor);
+        do_field(spminor, wServicePackMinor);
+        do_field(suite, wSuiteMask);
+        do_field(type, wProductType);
+#undef do_field
+
+        XenstorePrintf("data/os_distro", "windows");
+        XenstorePrintf("data/os_majorver", "%d", info.dwMajorVersion);
+        XenstorePrintf("data/os_minorver", "%d", info.dwMinorVersion);
+    } else {
+        /* Flag that we couldn't collect this information. */
+        XenstorePrintf("attr/os/major", "-1");
+    }
+
+    DumpOSData(wmi);
+
+    XenstorePrintf("attr/os/boottype", "%d", GetSystemMetrics(SM_CLEANBOOT));
+    /* HAL version in use */
+    if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_SYSTEM, NULL, SHGFP_TYPE_CURRENT, buf))) {
+        DWORD tmp;
+        DWORD versize;
+        LPVOID buffer = NULL;
+        TCHAR buffer2[128];
+        LPTSTR halname;
+        UINT halnamelen;
+        struct {
+            WORD language, code_page;
+        } *trans;
+        UINT trans_size;
+
+        XenstorePrintf("attr/os/system32_dir", "%s", buf);
+        strcat(buf, "\\hal.dll");
+        versize = GetFileVersionInfoSize(buf, &tmp);
+        if (versize == 0) {
+            XenstorePrintf("attr/os/hal", "<unknown versize=0>");
+            goto done_hal;
+        }
+        buffer = malloc(versize);
+        if (!buffer) {
+            XenstorePrintf("attr/os/hal", "<unknown versize=%d>", versize);
+            goto done_hal;
+        }
+        if (GetFileVersionInfo(buf, tmp, versize, buffer) == 0) {
+            PrintError("GetFileVersioInfo(hal.dll)");
+            goto done_hal;
+        }
+        if (!VerQueryValue(buffer, TEXT("\\VarFileInfo\\Translation"),
+                           (LPVOID *)&trans, &trans_size)) {
+            PrintError("VerQueryValue(hal.Translation");
+            goto done_hal;
+        }
+        if (trans_size < sizeof(*trans)) {
+            XenstorePrintf("attr/os/hal", "<no translations>");
+            goto done_hal;
+        }
+        sprintf(buffer2, "\\StringFileInfo\\%04x%04x\\InternalName",
+                trans->language, trans->code_page);
+        if (VerQueryValue(buffer, buffer2, (LPVOID *)&halname,
+                          &halnamelen)) {
+            XenstorePrintf("attr/os/hal", "%s", halname);
+
+            if (!lstrcmpi(halname, "hal.dll")) {
+                LegacyHal = TRUE;
+            }
+        } else {
+            PrintError("VerQueryValue(hal.InternalName)");
+        }
+    done_hal:
+        free(buffer);
+    }
+
+    /* Kernel command line */
+    HKEY regKey;
+    DWORD res;
+    res = RegOpenKey(HKEY_LOCAL_MACHINE,
+                     "SYSTEM\\CurrentControlSet\\Control",
+                     &regKey);
+    if (res != ERROR_SUCCESS) {
+        PrintError("RegOpenKey(\"HKLM\\SYSTEM\\CurrentControlSet\\Control\")");
+    } else {
+        DWORD keyType;
+        DWORD tmp;
+        tmp = sizeof(buf);
+        res = RegQueryValueEx(regKey, "SystemStartOptions",
+                              NULL, &keyType, (LPBYTE)buf, &tmp);
+        if (res != ERROR_SUCCESS) {
+            PrintError("RegQueryValue(SystemStartOptions)");
+        } else if (keyType != REG_SZ) {
+            XenstorePrintf("attr/os/boot_options", "<not string>");
+        } else {
+            XenstorePrintf("attr/os/boot_options", buf);
+        }
+        RegCloseKey(regKey);
+        regKey = NULL;
+    }
+
+    AddHotFixInfoToStore(wmi);
+
+}
+
+struct watch_event {
+    HANDLE event;
+    void *watch;
+};
+
+static void
+ReleaseWatch(struct watch_event *we)
+{
+    if (we == NULL)
+        return;
+    if (we->event != INVALID_HANDLE_VALUE)
+        CloseHandle(we->event);
+    if (we->watch)
+        XenstoreUnwatch(we->watch);
+    free(we);
+}
+
+static struct watch_event *
+EstablishWatch(const char *path)
+{
+    struct watch_event *we;
+    DWORD err;
+
+    we = (struct watch_event *)malloc(sizeof(*we));
+    if (!we) {
+        SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+        return NULL;
+    }
+    memset(we, 0, sizeof(*we));
+    we->watch = NULL;
+    we->event = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (we->event != INVALID_HANDLE_VALUE)
+        we->watch = XenstoreWatch(path, we->event);
+    if (we->watch == NULL) {
+        err = GetLastError();
+        ReleaseWatch(we);
+        SetLastError(err);
+        return NULL;
+    }
+    return we;
+}
+
+struct watch_feature {
+    struct watch_event *watch;
+    const char *feature_flag;
+    const char *name;
+    void (*handler)(void *);
+    void *ctx;
+};
+
+#define MAX_FEATURES 10
+struct watch_feature_set {
+    struct watch_feature features[MAX_FEATURES];
+    unsigned nr_features;
+};
+
+static void
+AddFeature(struct watch_feature_set *wfs, const char *path,
+           const char *flag, const char *name,
+           void (*handler)(void *), void *ctx)
+{
+    unsigned n;
+    if (wfs->nr_features == MAX_FEATURES) {
+        PrintError("Too many features!", ERROR_INVALID_FUNCTION);
+        return;
+    }
+    n = wfs->nr_features;
+    wfs->features[n].watch = EstablishWatch(path);
+    if (wfs->features[n].watch == NULL) {
+        PrintError("EstablishWatch() for AddFeature()");
+        return;
+    }
+    wfs->features[n].feature_flag = flag;
+    wfs->features[n].handler = handler;
+    wfs->features[n].ctx = ctx;
+    wfs->features[n].name = name;
+    wfs->nr_features++;
+}
+
+static void
+AdvertiseFeatures(struct watch_feature_set *wfs)
+{
+    unsigned x;
+    for (x = 0; x < wfs->nr_features; x++) {
+        if (wfs->features[x].feature_flag != NULL)
+            XenstorePrintf(wfs->features[x].feature_flag, "1");
+    }
+}
+
+int isBetterAgentInstalled() {
+    LONG lRet = 0;
+    DWORD betterAgent =0;
+    HKEY hRegKey;
+
+
+
+    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                        XENTOOLS_INSTALL_REG_KEY, 
+                        0, 
+                        KEY_READ,
+                        &hRegKey);
+
+    if (lRet == ERROR_SUCCESS)
+    {
+        DWORD cbData;
+        lRet = RegQueryValueEx(hRegKey, "MsiGuestAgent", NULL, NULL, (PBYTE)&betterAgent, &cbData);
+        if (lRet != ERROR_SUCCESS) {
+            betterAgent=0;
+        }
+    }
+    else {
+        betterAgent = 0;
+        goto failKey;
+    }
+    RegCloseKey(hRegKey);
+failKey:
+    return betterAgent;
+}
+
+VOID
+RegisterPVAddOns(
+    WMIAccessor* wmi
+    )
+{
+    HKEY hRegKey;
+    HANDLE h = INVALID_HANDLE_VALUE;
+    DWORD dwVersion;
+    DWORD cbData;
+
+    // If we get here, the drivers are installed.
+    XenstorePrintf ("attr/PVAddons/Installed", "1");
+
+    // Put the major, minor, and build version numbers in the store.
+    LONG lRet = 0;
+
+    lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                        XENTOOLS_INSTALL_REG_KEY, 
+                        0, 
+                        KEY_READ,
+                        &hRegKey);
+
+    if (lRet == ERROR_SUCCESS)
+    {
+        cbData = sizeof(dwVersion);
+#define DO_VERSION(type)                                                    \
+        lRet = RegQueryValueEx (                                            \
+            hRegKey,                                                        \
+            #type "Version",                                                \
+            NULL,                                                           \
+            NULL,                                                           \
+            (PBYTE)&dwVersion,                                              \
+            &cbData);                                                       \
+        if (lRet == ERROR_SUCCESS)                                          \
+            XenstorePrintf ("attr/PVAddons/" #type "Version", "%d",         \
+                            dwVersion);                                     \
+        else                                                                \
+            DBGPRINT (("Failed to get version " #type));
+        DO_VERSION(Major);
+        DO_VERSION(Minor);
+        DO_VERSION(Micro);
+        DO_VERSION(Build);
+#undef DO_VERSION
+        RegCloseKey(hRegKey);
+    }
+
+    AddSystemInfoToStore(wmi);
+}
+
+void ServiceUninstall()
+{
+       SC_HANDLE   hSvc;
+       SC_HANDLE   hMgr;
+       
+       hMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+
+       if ( hMgr )
+       {
+               hSvc = OpenService(hMgr, SVC_NAME, SERVICE_ALL_ACCESS);
+
+               if (hSvc)
+               {
+                        // try to stop the service
+                        if ( ControlService( hSvc, SERVICE_CONTROL_STOP, &ServiceStatus ) )
+                        {
+                               printf("Stopping %s.", SVC_DISPLAYNAME);
+                               Sleep( 1000 );
+
+                               while ( QueryServiceStatus( hSvc, &ServiceStatus ) )
+                               {
+                                       if ( ServiceStatus.dwCurrentState == SERVICE_STOP_PENDING )
+                                       {
+                                               printf(".");
+                                               Sleep( 1000 );
+                                       }
+                                       else
+                                               break;
+                               }
+
+                               if ( ServiceStatus.dwCurrentState == SERVICE_STOPPED )
+                                       printf("\n%s stopped.\n", SVC_DISPLAYNAME );
+                               else
+                                       printf("\n%s failed to stop.\n", SVC_DISPLAYNAME );
+         }
+
+         // now remove the service
+         if ( DeleteService(hSvc) )
+            printf("%s uninstalled.\n", SVC_DISPLAYNAME );
+         else
+            printf("Unable to uninstall - %d\n", GetLastError());
+
+         CloseServiceHandle(hSvc);
+
+         /* Tell dom0 that we're no longer installed.  This is a bit
+            of a hack. */
+         InitXSAccessor();
+
+         XenstorePrintf("attr/PVAddons/Installed", "0");
+         XenstorePrintf("attr/PVAddons/MajorVersion", "0");
+         XenstorePrintf("attr/PVAddons/MinorVersion", "0");
+         XenstorePrintf("attr/PVAddons/BuildVersion", "0");
+
+         /* Crank the update number so xapi notices it. */
+         char *v;
+         XenstoreRead("data/update_cnt", &v);
+         if (v) {
+             int cnt = atoi(v);
+             XenstorePrintf("data/update_cnt", "%d", cnt + 1);
+             XenstoreFree(v);
+         }
+      }
+      else
+         printf("Unable to open service - %d\n", GetLastError());
+
+      CloseServiceHandle(hMgr);
+   }
+   else
+      printf("Unable to open scm - %d\n", GetLastError());
+
+}
+
+
+int __stdcall
+WinMain(HINSTANCE hInstance, HINSTANCE ignore,
+        LPSTR lpCmdLine, int nCmdShow)
+{
+    local_hinstance = hInstance;
+
+    if (strlen(lpCmdLine) == 0) {
+               SERVICE_TABLE_ENTRY ServiceTable[2];
+               ServiceTable[0].lpServiceName = SVC_NAME;
+               ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
+
+               ServiceTable[1].lpServiceName = NULL;
+               ServiceTable[1].lpServiceProc = NULL;
+
+               DBGPRINT(("XenSvc: starting ctrl dispatcher "));
+
+               // Start the control dispatcher thread for our service
+               if (!StartServiceCtrlDispatcher(ServiceTable))
+               {
+                       if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
+                       {
+                               DBGPRINT(("XenSvc: unable to start ctrl dispatcher - %d", GetLastError()));
+                       }
+               }
+               else
+               {
+                       // We get here when the service is shut down.
+               }
+    } else if (!strcmp(lpCmdLine, "-u") || !strcmp(lpCmdLine, "\"-u\"")) {
+        ServiceUninstall();
+    } else {
+        PrintUsage();
+    }
+
+    return 0;
+}
+
+void AcquireSystemPrivilege(LPCTSTR name)
+{
+    HANDLE token;
+    TOKEN_PRIVILEGES tkp;
+    DWORD err;
+
+    LookupPrivilegeValue(NULL, name, &tkp.Privileges[0].Luid);
+    tkp.PrivilegeCount = 1;
+    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+    if (!OpenProcessToken(GetCurrentProcess(),
+                          TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,
+                          &token)) {
+        DBGPRINT(("Failed to open local token.\n"));
+    } else {
+        AdjustTokenPrivileges(token, FALSE, &tkp,
+                              NULL, 0, NULL);
+        err = GetLastError();
+        if (err != ERROR_SUCCESS) {
+            PrintError("AdjustTokenPrivileges", err);
+        }
+    }
+}
+
+static void AcquireSystemShutdownPrivilege(void)
+{
+    AcquireSystemPrivilege(SE_SHUTDOWN_NAME);
+}
+
+enum XShutdownType {
+       XShutdownPoweroff,
+       XShutdownReboot,
+       XShutdownSuspend,
+    XShutdownS3
+};
+
+static void maybeReboot(void *ctx)
+{
+       char *shutdown_type;
+       unsigned int len;
+       BOOL res;
+       enum XShutdownType type;
+    int cntr = 0;
+    HANDLE eventLog;
+
+       if (XenstoreRead("control/shutdown", &shutdown_type) < 0)
+               return;
+       DBGPRINT(("Shutdown type %s\n", shutdown_type));
+       if (strcmp(shutdown_type, "poweroff") == 0 ||
+           strcmp(shutdown_type, "halt") == 0) {
+               type = XShutdownPoweroff;
+       } else if (strcmp(shutdown_type, "reboot") == 0) {
+               type = XShutdownReboot;
+       } else if (strcmp(shutdown_type, "hibernate") == 0) {
+               type = XShutdownSuspend;
+       } else if (strcmp(shutdown_type, "s3") == 0) {
+               type = XShutdownS3;
+       } else {
+               DBGPRINT(("Bad shutdown type %s\n", shutdown_type));
+               goto out;
+       }
+
+       /* We try to shutdown even if this fails, since it might work
+          and it can't do any harm. */
+       AcquireSystemShutdownPrivilege();
+
+    eventLog = RegisterEventSource(NULL, "xensvc");
+    if (eventLog) {
+        DWORD eventId;
+
+        switch (type) {
+        case XShutdownPoweroff:
+            eventId = EVENT_XENUSER_POWEROFF;
+            break;
+        case XShutdownReboot:
+            eventId = EVENT_XENUSER_REBOOT;
+            break;
+        case XShutdownSuspend:
+            eventId = EVENT_XENUSER_HIBERNATE;
+            break;
+        case XShutdownS3:
+            eventId = EVENT_XENUSER_S3;
+            break;
+        }
+        ReportEvent(eventLog, EVENTLOG_SUCCESS, 0, eventId, NULL, 0, 0,
+                    NULL, NULL);
+        DeregisterEventSource(eventLog);
+    }
+       /* do the shutdown */
+       switch (type) {
+       case XShutdownPoweroff:
+       case XShutdownReboot:
+        if (WindowsVersion >= 0x500 && WindowsVersion < 0x600)
+        {
+            /* Windows 2000 InitiateSystemShutdownEx is funny in
+               various ways (e.g. sometimes fails to power off after
+               shutdown, especially if the local terminal is locked,
+               not doing anything if there's nobody logged on, etc.).
+               ExitWindowsEx seems to be more reliable, so use it
+               instead. */
+            /* XXX I don't really understand why
+               InitiateSystemShutdownEx behaves so badly. */
+            /* If this is a legacy hal then use EWX_SHUTDOWN when shutting
+               down instead of EWX_POWEROFF. */
+           /* Similar problem on XP. Shutdown/Reboot will hang until the Welcome
+               screen screensaver is dismissed by the guest */
+#pragma warning (disable : 28159)
+            res = ExitWindowsEx((type == XShutdownReboot ? 
+                                    EWX_REBOOT : 
+                                    (LegacyHal ? 
+                                        EWX_SHUTDOWN :
+                                        EWX_POWEROFF))|
+                                EWX_FORCE,
+                                SHTDN_REASON_MAJOR_OTHER|
+                                SHTDN_REASON_MINOR_ENVIRONMENT |
+                                SHTDN_REASON_FLAG_PLANNED);
+#pragma warning (default: 28159)
+            if (!res)
+                PrintError("ExitWindowsEx");
+            else
+                XenstoreRemove("control/shutdown");
+        } else {
+#pragma warning (disable : 28159)
+            res = InitiateSystemShutdownEx(
+                NULL,
+                NULL,
+                0,
+                TRUE,
+                type == XShutdownReboot,
+                SHTDN_REASON_MAJOR_OTHER |
+                SHTDN_REASON_MINOR_ENVIRONMENT |
+                SHTDN_REASON_FLAG_PLANNED);
+#pragma warning (default: 28159)
+            if (!res) {
+                PrintError("InitiateSystemShutdownEx");
+            } else {
+                XenstoreRemove("control/shutdown");
+            }
+        }
+               break;
+       case XShutdownSuspend:
+        XenstorePrintf ("control/hibernation-state", "started");
+        /* Even if we think hibernation is disabled, try it anyway.
+           It's not like it can do any harm. */
+               res = SetSystemPowerState(FALSE, FALSE);
+        XenstoreRemove ("control/shutdown");
+        if (!res) {
+            /* Tell the tools that we've failed. */
+            PrintError("SetSystemPowerState");
+            XenstorePrintf ("control/hibernation-state", "failed");
+        }
+               break;
+    case XShutdownS3:
+        XenstorePrintf ("control/s3-state", "started");
+        res = SetSuspendState(FALSE, TRUE, FALSE);
+        XenstoreRemove ("control/shutdown");
+        if (!res) {
+            PrintError("SetSuspendState");
+            XenstorePrintf ("control/s3-state", "failed");
+        }
+        break;
+       }
+
+out:
+       XenstoreFree(shutdown_type);
+}
+
+static
+void
+GetWindowsVersion()
+{
+    OSVERSIONINFO info;
+    info.dwOSVersionInfoSize = sizeof(info);
+
+    WindowsVersion = 0;
+
+    if (GetVersionEx(&info)) {
+        if (((info.dwMajorVersion & ~0xff) == 0)
+         && ((info.dwMinorVersion & ~0xff) == 0))
+        {
+            WindowsVersion = (info.dwMajorVersion << 8) |
+                              info.dwMinorVersion;
+        }
+    }
+}
+
+/* We need to resync the clock when we recover from suspend/resume. */
+static void
+finishSuspend(void)
+{
+    FILETIME now = {0};
+    SYSTEMTIME sys_time;
+    SYSTEMTIME current_time;
+
+    DBGPRINT(("Coming back from suspend.\n"));
+    GetXenTime(&now);
+    XsLog("Xen time is %I64x", now);
+    if (!FileTimeToSystemTime(&now, &sys_time)) {
+        PrintError("FileTimeToSystemTime()");
+        DBGPRINT(("FileTimeToSystemTime(%x.%x)\n",
+                  now.dwLowDateTime, now.dwHighDateTime));
+    } else {
+        XsLog("Set time to %d.%d.%d %d:%d:%d.%d",
+              sys_time.wYear, sys_time.wMonth, sys_time.wDay,
+              sys_time.wHour, sys_time.wMinute, sys_time.wSecond,
+              sys_time.wMilliseconds);
+        GetLocalTime(&current_time);
+        XsLog("Time is now  %d.%d.%d %d:%d:%d.%d",
+              current_time.wYear, current_time.wMonth, current_time.wDay,
+              current_time.wHour, current_time.wMinute, current_time.wSecond,
+              current_time.wMilliseconds);
+        if (!SetLocalTime(&sys_time))
+            PrintError("SetSystemTime()");
+    }
+}
+
+static void
+refreshStoreData(WMIAccessor *wmi, NicInfo *nicInfo,
+                 TSInfo *tsInfo, struct watch_feature_set *wfs)
+{
+    PCHAR buffer = NULL;
+    static int64_t last_meminfo_free;
+    static int cntr;
+    unsigned need_kick;
+
+    need_kick = 0;
+    if (XenstoreRead("attr/PVAddons/Installed",
+                     &buffer) < 0) {
+        if (GetLastError() == ERROR_NO_SYSTEM_RESOURCES)
+            return;
+
+        XsLogMsg("register ourself in the store");
+        RegisterPVAddOns(wmi);
+        nicInfo->Refresh();
+        AdvertiseFeatures(wfs);
+        need_kick = 1;
+    } else {
+        XenstoreFree(buffer);
+    }
+
+    if (XenstoreRead("data/meminfo_free", &buffer) < 0) {
+        cntr = 0;
+        last_meminfo_free = 0;
+    } else {
+        XenstoreFree(buffer);
+    }
+
+    if (XenstoreRead("data/ts", &buffer) < 0) {
+        cntr = 0;
+    } else {
+        XenstoreFree(buffer);
+    }
+
+    /* XXX HACK: Restrict ourselves to only doing this once every two
+     * minutes or so (we get called about every 4.5 seconds). */
+    if (cntr++ % 26 == 0) {
+        VMData data;
+        BOOLEAN enabled;
+
+        XsLogMsg("Get memory data");
+        memset(&data, 0, sizeof(VMData));
+        GetWMIData(wmi, data);
+
+        if (data.meminfo_free - last_meminfo_free > 1024 ||
+            data.meminfo_free - last_meminfo_free < -1024) {
+            XsLogMsg("update memory data in store");
+            XenstoreDoDump(&data);
+            need_kick = 1;
+            last_meminfo_free = data.meminfo_free;
+        }
+
+        XsLogMsg("Refresh terminal services status");
+        tsInfo->Refresh();
+
+        XsLogMsg("Get volume mapping data");
+    }
+
+    if (need_kick)
+        XenstoreKickXapi();
+}
+
+static void
+ProcessTsControl(void *ctx)
+{
+    TSInfo *tsInfo = (TSInfo *)ctx;
+
+    tsInfo->ProcessControl();
+}
+
+static void
+processPing(void *ctx)
+{
+    XenstoreRemove("control/ping");
+}
+
+static void
+processExec(void *ctx)
+{
+    char *val;
+    char *file;
+    if (XenstoreRead("control/exec/command", &val) >=0) {
+        if (strcmp(val, "Install")==0) {
+            if (XenstoreRead("control/exec/file", &file) >=0) {
+                _spawnlp(_P_NOWAIT, "msiexec.exe", "/qn", "/i", file, NULL);
+                XenstoreFree(file);
+            }
+            XenstoreFree(val);
+        }
+    }
+    XenstoreRemove("control/exec/command");
+
+}
+
+static void
+processDumpLog(void *ctx)
+{
+    char *val;
+    int do_it;
+
+    do_it = 0;
+    if (XenstoreRead("control/dumplog", &val) >= 0) {
+        XenstoreFree(val);
+        do_it = 1;
+    } else if (GetLastError() != ERROR_FILE_NOT_FOUND)
+        do_it = 1;
+
+    if (do_it) {
+        XsDumpLogThisThread();
+        XenstoreRemove("control/dumplog");
+    }
+}
+
+//
+// Main loop
+//
+void Run()
+{
+    VMData data;
+    bool exit=false;
+    PCHAR pPVAddonsInstalled = NULL;
+    STARTUPINFO startInfo;
+    PROCESS_INFORMATION processInfo;
+    HANDLE suspendEvent;
+    MSG msg;
+    int cntr = 0;
+    NicInfo *nicInfo;
+    TSInfo *tsInfo;
+    struct watch_feature_set features;
+    BOOL snap = FALSE;
+
+    XsLogMsg("Guest agent main loop starting");
+
+    memset(&features, 0, sizeof(features));
+
+    GetWindowsVersion();
+
+
+    AddFeature(&features, "control/shutdown", "control/feature-shutdown", 
+               "shutdown", maybeReboot, NULL);
+    AddFeature(&features, "control/ping", NULL, "ping", processPing, NULL);
+    AddFeature(&features, "control/exec/command", NULL, "Exec", processExec, NULL);
+    AddFeature(&features, "control/dumplog", NULL, "dumplog", processDumpLog, NULL);
+
+    suspendEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if (!suspendEvent) {
+        PrintError("CreateEvent() suspendEvent");
+    } else {
+        if (ListenSuspend(suspendEvent) < 0) {
+            PrintError("ListenSuspend()");
+            CloseHandle(suspendEvent);
+            suspendEvent = NULL;
+        }
+    }
+
+
+
+    nicInfo = new NicInfo();
+    nicInfo->Prime();
+
+    tsInfo = new TSInfo();
+    AddFeature(&features,
+               "control/ts",
+               "control/feature-ts",
+               "ts",
+               ProcessTsControl,
+               tsInfo);
+
+    XenstoreRemove("attr/PVAddons/Installed");
+    refreshStoreData(wmi, nicInfo, tsInfo, &features);
+
+    while (1)
+    {
+        DWORD status;
+        int nr_handles = 2;
+        HANDLE handles[3 + MAX_FEATURES];
+        unsigned x;
+
+        handles[0] = hServiceExitEvent;
+        handles[1] = nicInfo->NicChangeEvent;
+        if (suspendEvent)
+            handles[nr_handles++] = suspendEvent;
+        for (x = 0; x < features.nr_features; x++)
+            handles[nr_handles++] = features.features[x].watch->event;
+
+        XsLogMsg("win agent going to sleep");
+        status = WaitForMultipleObjects(nr_handles, handles, FALSE, 4500);
+        XsLogMsg("win agent woke up for %d", status);
+
+        /* WAIT_OBJECT_0 happens to be 0, so the compiler gets shirty
+           about status >= WAIT_OBJECT_0 (since status is unsigned).
+           This is more obviously correct than the compiler-friendly
+           version, though, so just disable the warning. */
+        if (status == WAIT_TIMEOUT) {
+            refreshStoreData(wmi, nicInfo, tsInfo, &features);
+        }
+#pragma warning (disable: 4296)
+        else if (status >= WAIT_OBJECT_0 &&
+                 status < WAIT_OBJECT_0 + nr_handles)
+#pragma warning (default: 4296)
+        {
+            HANDLE event = handles[status - WAIT_OBJECT_0];
+            if (event == hServiceExitEvent)
+            {
+                XsLogMsg("service exit event");
+                break;
+            }
+            else if (event == nicInfo->NicChangeEvent)
+            {
+                XsLogMsg("NICs changed");
+                nicInfo->Refresh();
+                XenstoreKickXapi();
+                XsLogMsg("Handled NIC change");
+                nicInfo->Prime();
+            }
+            else if (event == suspendEvent)
+            {
+                XsLogMsg("Suspend event");
+                finishSuspend();
+                refreshStoreData(wmi, nicInfo, tsInfo, &features);
+                XsLogMsg("Handled suspend event");
+            }
+            else
+            {
+                for (x = 0; x < features.nr_features; x++) {
+                    if (features.features[x].watch->event == event) {
+                        XsLogMsg("fire feature %s", features.features[x].name);
+                        features.features[x].handler(features.features[x].ctx);
+                        XsLogMsg("fired feature %s",
+                                 features.features[x].name);
+                    }
+                }
+            }
+        }
+        else
+        {
+            PrintError("WaitForMultipleObjects()");
+            break;
+        }
+    }
+
+    XsLogMsg("Guest agent finishing");
+    ReleaseWMIAccessor(wmi);
+
+
+    delete tsInfo;
+    delete nicInfo;
+
+    ServiceControlManagerUpdate(0, SERVICE_STOPPED);
+
+    if (SLC_API != NULL)
+        FreeLibrary(SLC_API);
+    if (SLWGA_API != NULL)
+        FreeLibrary(SLWGA_API);
+
+    XsLogMsg("Guest agent finished");
+}
+
+
+// Service initialization
+bool ServiceInit()
+{
+       ServiceStatus.dwServiceType        = SERVICE_WIN32; 
+    ServiceStatus.dwCurrentState       = SERVICE_START_PENDING; 
+    ServiceStatus.dwControlsAccepted   =
+        SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN |
+        SERVICE_ACCEPT_SESSIONCHANGE;
+    ServiceStatus.dwWin32ExitCode      = 0; 
+    ServiceStatus.dwServiceSpecificExitCode = 0; 
+    ServiceStatus.dwCheckPoint         = 0; 
+    ServiceStatus.dwWaitHint           = 0; 
+    hStatus = RegisterServiceCtrlHandlerEx(
+               "XenService", 
+               ServiceControlHandler,
+        NULL);
+    if (hStatus == (SERVICE_STATUS_HANDLE)0) 
+    { 
+        // Registering Control Handler failed
+               DBGPRINT(("XenSvc: Registering service control handler failed - %d\n", GetLastError()));
+        return false; 
+    }  
+
+       ServiceStatus.dwCurrentState = SERVICE_RUNNING; 
+       SetServiceStatus (hStatus, &ServiceStatus);
+
+    if (isBetterAgentInstalled()) {
+           ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
+           SetServiceStatus (hStatus, &ServiceStatus);
+    }
+
+       return true;
+}
+
+void WINAPI ServiceMain(int argc, char** argv)
+{
+    // Perform common initialization
+    hServiceExitEvent = CreateEvent(NULL, false, false, NULL);
+    if (hServiceExitEvent == NULL)
+    {
+        DBGPRINT(("XenSvc: Unable to create the event obj - %d\n", GetLastError()));
+        return;
+    }
+
+    if (!ServiceInit())
+    {
+        DBGPRINT(("XenSvc: Unable to init xenservice\n"));
+        return;
+    }
+
+    XsInitPerThreadLogging();
+
+    ConnectToWMI();
+    InitXSAccessor();
+    XsLog("Guest agent service starting");
+
+    __try
+    {
+        Run();
+    }
+    __except(XsDumpLogThisThread(), EXCEPTION_CONTINUE_SEARCH)
+    {
+    }
+
+    XsLog("Guest agent service stopped");
+    ShutdownXSAccessor();
+
+    return;
+}
+
+void ServiceControlManagerUpdate(DWORD dwExitCode, DWORD dwState)
+{
+    ServiceStatus.dwWin32ExitCode = dwExitCode; 
+    ServiceStatus.dwCurrentState  = dwState; 
+    SetServiceStatus (hStatus, &ServiceStatus);
+}
+
+// Service control handler function
+static DWORD WINAPI ServiceControlHandler(DWORD request, DWORD evtType,
+                                          LPVOID eventData, LPVOID ctxt)
+{
+    UNREFERENCED_PARAMETER(ctxt);
+    UNREFERENCED_PARAMETER(eventData);
+
+    switch(request) 
+    { 
+        case SERVICE_CONTROL_STOP: 
+            DBGPRINT(("XenSvc: xenservice stopped.\n"));
+            ServiceControlManagerUpdate(0, SERVICE_STOP_PENDING);
+            SetEvent(hServiceExitEvent);
+            return NO_ERROR;
+        case SERVICE_CONTROL_SHUTDOWN: 
+            DBGPRINT(("XenSvc: xenservice shutdown.\n"));
+            ServiceControlManagerUpdate(0, SERVICE_STOP_PENDING);
+            SetEvent(hServiceExitEvent);
+            return NO_ERROR;
+
+        default:
+           DBGPRINT(("XenSvc: unknown request."));
+            break;
+    } 
+
+    ServiceControlManagerUpdate(0, SERVICE_RUNNING);
+    return ERROR_CALL_NOT_IMPLEMENTED;
+}
diff --git a/src/win32stubagent/XService.h b/src/win32stubagent/XService.h
new file mode 100644 (file)
index 0000000..144db5c
--- /dev/null
@@ -0,0 +1,52 @@
+/* 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 _XSERVICE_H
+#define _XSERVICE_H
+
+#define SVC_NAME "xensvc"
+#define SVC_DISPLAYNAME "Citrix Tools for Virtual Machines Service"
+#define SVC_DESC "Monitors and provides various metrics to XenStore"
+
+void PrintError(const char *func);
+void PrintError(const char *func, DWORD err);
+void StartClipboardSync(void);
+void FinishClipboardSync(void);
+void ClipboardConsoleChanged(void);
+
+void XsDumpLogThisThread(void);
+void XsInitPerThreadLogging(void);
+void XsLogMsg(const char *fmt, ...);
+void DoVolumeDump(void);
+
+void AcquireSystemPrivilege(LPCTSTR name);
+
+#endif
diff --git a/src/win32stubagent/messages.mc b/src/win32stubagent/messages.mc
new file mode 100644 (file)
index 0000000..8034ca8
--- /dev/null
@@ -0,0 +1,34 @@
+SeverityNames=(Informational=0x1)
+FacilityNames=(XenUser=0xd60)
+
+MessageId=0x0001
+Facility=XenUser
+Severity=Informational
+SymbolicName=EVENT_XENUSER_POWEROFF
+Language=English
+The tools requested that the local VM shut itself down.
+.
+
+MessageId=0x0002
+Facility=XenUser
+Severity=Informational
+SymbolicName=EVENT_XENUSER_REBOOT
+Language=English
+The tools requested that the local VM reboot.
+.
+
+MessageId=0x0003
+Facility=XenUser
+Severity=Informational
+SymbolicName=EVENT_XENUSER_HIBERNATE
+Language=English
+The tools requested that the local VM hibernate itself.
+.
+
+MessageId=0x0004
+Facility=XenUser
+Severity=Informational
+SymbolicName=EVENT_XENUSER_S3
+Language=English
+The tools requested that the local VM enter power state S3.
+.
diff --git a/src/win32stubagent/stdafx.cpp b/src/win32stubagent/stdafx.cpp
new file mode 100644 (file)
index 0000000..72ced79
--- /dev/null
@@ -0,0 +1,39 @@
+/* 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.
+ */
+
+// stdafx.cpp : source file that includes just the standard includes
+// XenService.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/src/win32stubagent/stdafx.h b/src/win32stubagent/stdafx.h
new file mode 100644 (file)
index 0000000..391a848
--- /dev/null
@@ -0,0 +1,43 @@
+/* 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.
+ */
+
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+
+#include <iostream>
+#include <tchar.h>
+
+// TODO: reference additional headers your program requires here
diff --git a/src/win32stubagent/vm_stats.h b/src/win32stubagent/vm_stats.h
new file mode 100644 (file)
index 0000000..3fd7e9d
--- /dev/null
@@ -0,0 +1,59 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+
+#ifndef __vm_stats_h
+#define __vm_stats_h
+
+#define MAX_CHAR_LEN 128
+
+typedef unsigned int uint32_t;
+typedef unsigned short uint16_t;
+typedef int int32_t;
+
+typedef __int64  int64_t;
+typedef unsigned __int64  uint64_t;
+
+typedef struct _VIFData {
+    uint32_t ethnum;
+    char mac[MAX_CHAR_LEN];
+    char name[MAX_CHAR_LEN];
+    char ip[MAX_CHAR_LEN];
+} VIFData;
+
+typedef struct _VMData {
+    time_t time;
+    int64_t meminfo_free;
+    int64_t meminfo_total;
+} VMData;
+
+#endif
+
diff --git a/src/win32stubagent/w32xagent.rc b/src/win32stubagent/w32xagent.rc
new file mode 100644 (file)
index 0000000..6de5aba
--- /dev/null
@@ -0,0 +1,49 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+
+#include <windows.h>
+#include <ntverp.h>
+
+#include "version.h"
+
+#define VER_INTERNALNAME_STR "w32xagent.exe"
+#define VER_FILEVERSION_STR "1.0"
+#define VER_FILEDESCRIPTION_STR "XenSource Windows guest agent"
+#define VER_ORIGINALFILENAME_STR "w32xagent.exe"
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE 0
+
+xen_icon ICON "xen.ico"
+
+#include "common.ver"
+
+#include "messages.rc"
diff --git a/src/win32stubagent/xen.ico b/src/win32stubagent/xen.ico
new file mode 100644 (file)
index 0000000..844c993
Binary files /dev/null and b/src/win32stubagent/xen.ico differ
diff --git a/src/xeniface.inf b/src/xeniface.inf
new file mode 100644 (file)
index 0000000..92eb3bb
--- /dev/null
@@ -0,0 +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"
+
diff --git a/src/xeniface/ioctls.c b/src/xeniface/ioctls.c
new file mode 100644 (file)
index 0000000..75936a3
--- /dev/null
@@ -0,0 +1,331 @@
+/* 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 "xeniface.h"
+#include "ioctls.h"
+#include "..\..\include\xeniface_ioctls.h"
+
+static FORCEINLINE BOOLEAN
+__IsValidStr(
+    __in  PCHAR             Str,
+    __in  ULONG             Len
+    )
+{
+    for ( ; Len--; ++Str) {
+        if (*Str == '\0')
+            return TRUE;
+        if (!isprint((unsigned char)*Str))
+            break;
+    }
+    return FALSE;
+}
+static FORCEINLINE ULONG
+__MultiSzLen(
+    __in  PCHAR             Str,
+    __out PULONG            Count
+    )
+{
+    ULONG Length = 0;
+    if (Count)  *Count = 0;
+    do {
+        for ( ; *Str; ++Str, ++Length) ;
+        ++Str; ++Length;
+        if (*Count) ++(*Count);
+    } while (*Str);
+    return Length;
+}
+static FORCEINLINE VOID
+__DisplayMultiSz(
+    __in PCHAR              Caller,
+    __in PCHAR              Str
+    )
+{
+    PCHAR   Ptr;
+    ULONG   Idx;
+    ULONG   Len;
+
+    for (Ptr = Str, Idx = 0; *Ptr; ++Idx) {
+        Len = (ULONG)strlen(Ptr);
+        XenIfaceDebugPrint(INFO, "|%s: [%d]=(%d)->\"%s\"\n", Caller, Idx, Len, Ptr);
+        Ptr += (Len + 1);
+    }
+}
+
+
+static DECLSPEC_NOINLINE NTSTATUS
+IoctlRead(
+    __in  PFDO_DATA         Fdo,
+    __in  PCHAR             Buffer,
+    __in  ULONG             InLen,
+    __in  ULONG             OutLen,
+    __out PULONG_PTR        Info
+    )
+{
+    NTSTATUS    status;
+    PCHAR       Value;
+    ULONG       Length;
+
+    status = STATUS_INVALID_BUFFER_SIZE;
+    if (InLen == 0)
+        goto fail1;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (!__IsValidStr(Buffer, InLen))
+        goto fail2;
+
+    status = STORE(Read, Fdo->StoreInterface, NULL, NULL, Buffer, &Value);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    Length = (ULONG)strlen(Value) + 1;
+
+    status = STATUS_BUFFER_OVERFLOW;
+    if (OutLen == 0) {
+        XenIfaceDebugPrint(INFO, "|%s: (\"%s\")=(%d)\n", __FUNCTION__, Buffer, Length);
+        goto done;
+    } 
+    
+    status = STATUS_INVALID_PARAMETER;
+    if (OutLen < Length)
+        goto fail4;
+
+    XenIfaceDebugPrint(INFO, "|%s: (\"%s\")=(%d)->\"%s\"\n", __FUNCTION__, Buffer, Length, Value);
+
+    RtlCopyMemory(Buffer, Value, Length);
+    Buffer[Length - 1] = 0;
+    status = STATUS_SUCCESS;
+
+done:
+    *Info = (ULONG_PTR)Length;
+    STORE(Free, Fdo->StoreInterface, Value);
+    return status;
+
+fail4:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail4 (\"%s\")=(%d < %d)\n", __FUNCTION__, Buffer, OutLen, Length);
+    STORE(Free, Fdo->StoreInterface, Value);
+fail3:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail3 (\"%s\")\n", __FUNCTION__, Buffer);
+fail2:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail2\n", __FUNCTION__);
+fail1:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail1 (%08x)\n", __FUNCTION__, status);
+    return status;
+}
+
+static DECLSPEC_NOINLINE NTSTATUS
+IoctlWrite(
+    __in  PFDO_DATA         Fdo,
+    __in  PCHAR             Buffer,
+    __in  ULONG             InLen,
+    __in  ULONG             OutLen
+    )
+{
+    NTSTATUS    status;
+    PCHAR       Value;
+    ULONG       Length;
+
+    status = STATUS_INVALID_BUFFER_SIZE;
+    if (InLen == 0 || OutLen != 0)
+        goto fail1;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (!__IsValidStr(Buffer, InLen))
+        goto fail2;
+
+    Length = (ULONG)strlen(Buffer) + 1;
+    Value = Buffer + Length;
+
+    if (!__IsValidStr(Value, InLen - Length))
+        goto fail3;
+
+    status = STORE(Write, Fdo->StoreInterface, NULL, NULL, Buffer, Value);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+    XenIfaceDebugPrint(INFO, "|%s: (\"%s\"=\"%s\")\n", __FUNCTION__, Buffer, Value);
+    return status;
+
+fail4:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail4 (\"%s\")\n", __FUNCTION__, Value);
+fail3:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail3 (\"%s\")\n", __FUNCTION__, Buffer);
+fail2:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail2\n", __FUNCTION__);
+fail1:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail1 (%08x)\n", __FUNCTION__, status);
+    return status;
+}
+
+static DECLSPEC_NOINLINE NTSTATUS
+IoctlDirectory(
+    __in  PFDO_DATA         Fdo,
+    __in  PCHAR             Buffer,
+    __in  ULONG             InLen,
+    __in  ULONG             OutLen,
+    __out PULONG_PTR        Info
+    )
+{
+    NTSTATUS    status;
+    PCHAR       Value;
+    ULONG       Length;
+    ULONG       Count;
+
+    status = STATUS_INVALID_BUFFER_SIZE;
+    if (InLen == 0)
+        goto fail1;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (!__IsValidStr(Buffer, InLen))
+        goto fail2;
+
+    status = STORE(Directory, Fdo->StoreInterface, NULL, NULL, Buffer, &Value);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    Length = __MultiSzLen(Value, &Count) + 1;
+
+    status = STATUS_BUFFER_OVERFLOW;
+    if (OutLen == 0) {
+        XenIfaceDebugPrint(INFO, "|%s: (\"%s\")=(%d)(%d)\n", __FUNCTION__, Buffer, Length, Count);
+        goto done;
+    } 
+
+    status = STATUS_INVALID_PARAMETER;
+    if (OutLen < Length)
+        goto fail4;
+
+    XenIfaceDebugPrint(INFO, "|%s: (\"%s\")=(%d)(%d)\n", __FUNCTION__, Buffer, Length, Count);
+#if DBG
+    __DisplayMultiSz(__FUNCTION__, Value);
+#endif
+
+    RtlCopyMemory(Buffer, Value, Length);
+    Buffer[Length - 2] = 0;
+    Buffer[Length - 1] = 0;
+    status = STATUS_SUCCESS;
+
+done:
+    *Info = (ULONG_PTR)Length;
+    STORE(Free, Fdo->StoreInterface, Value);
+    return status;
+
+fail4:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail4 (\"%s\")=(%d < %d)\n", __FUNCTION__, Buffer, OutLen, Length);
+    STORE(Free, Fdo->StoreInterface, Value);
+fail3:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail3 (\"%s\")\n", __FUNCTION__, Buffer);
+fail2:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail2\n", __FUNCTION__);
+fail1:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail1 (%08x)\n", __FUNCTION__, status);
+    return status;
+}
+
+static DECLSPEC_NOINLINE NTSTATUS
+IoctlRemove(
+    __in  PFDO_DATA         Fdo,
+    __in  PCHAR             Buffer,
+    __in  ULONG             InLen,
+    __in  ULONG             OutLen
+    )
+{
+    NTSTATUS    status;
+
+    status = STATUS_INVALID_BUFFER_SIZE;
+    if (InLen == 0 || OutLen != 0)
+        goto fail1;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (!__IsValidStr(Buffer, InLen))
+        goto fail2;
+
+    status = STORE(Remove, Fdo->StoreInterface, NULL, NULL, Buffer);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    XenIfaceDebugPrint(INFO, "|%s: (\"%s\")\n", __FUNCTION__, Buffer);
+    return status;
+
+fail3:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail3 (\"%s\")\n", __FUNCTION__, Buffer);
+fail2:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail2\n", __FUNCTION__);
+fail1:
+    XenIfaceDebugPrint(ERROR, "|%s: Fail1 (%08x)\n", __FUNCTION__, status);
+    return status;
+}
+
+NTSTATUS
+XenIFaceIoctl(
+    __in  PFDO_DATA         Fdo,
+    __in  PIRP              Irp
+    )
+{
+    NTSTATUS            status;
+    PIO_STACK_LOCATION  Stack = IoGetCurrentIrpStackLocation(Irp);
+    PVOID               Buffer = Irp->AssociatedIrp.SystemBuffer;
+    ULONG               InLen = Stack->Parameters.DeviceIoControl.InputBufferLength;
+    ULONG               OutLen = Stack->Parameters.DeviceIoControl.OutputBufferLength;
+
+    status = STATUS_DEVICE_NOT_READY;
+    if (Fdo->StoreInterface == NULL)
+        goto done;
+
+    if (Fdo->InterfacesAcquired == FALSE)
+        goto done;
+
+    switch (Stack->Parameters.DeviceIoControl.IoControlCode) {
+    case IOCTL_XENIFACE_STORE_READ:
+        status = IoctlRead(Fdo, (PCHAR)Buffer, InLen, OutLen, &Irp->IoStatus.Information);
+        break;
+
+    case IOCTL_XENIFACE_STORE_WRITE:
+        status = IoctlWrite(Fdo, (PCHAR)Buffer, InLen, OutLen);
+        break;
+
+    case IOCTL_XENIFACE_STORE_DIRECTORY:
+        status = IoctlDirectory(Fdo, (PCHAR)Buffer, InLen, OutLen, &Irp->IoStatus.Information);
+        break;
+
+    case IOCTL_XENIFACE_STORE_REMOVE:
+        status = IoctlRemove(Fdo, (PCHAR)Buffer, InLen, OutLen);
+        break;
+
+    default:
+        status = STATUS_INVALID_DEVICE_REQUEST;
+        break;
+    }
+
+done:
+    return status;
+}
+
diff --git a/src/xeniface/ioctls.h b/src/xeniface/ioctls.h
new file mode 100644 (file)
index 0000000..873fbbc
--- /dev/null
@@ -0,0 +1,42 @@
+/* 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 _IOCTLS_H_
+#define _IOCTLS_H_
+
+NTSTATUS
+XenIFaceIoctl(
+    __in  PFDO_DATA         Fdo,
+    __in  PIRP              Irp
+    );
+
+#endif // _IOCTLS_H_
+
diff --git a/src/xeniface/wmi.c b/src/xeniface/wmi.c
new file mode 100644 (file)
index 0000000..5a098bd
--- /dev/null
@@ -0,0 +1,3104 @@
+/* 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 <initguid.h>
+#include <wdmguid.h>
+#include <wmistr.h>
+#include <wmilib.h>
+#include <stdio.h>
+#include <ntddk.h>
+#include <guiddef.h>
+#define NTSTRSAFE_LIB
+#include<ntstrsafe.h>
+#include "wmi.h"
+#include "xeniface.h"
+#include "..\..\include\store_interface.h"
+#include "..\..\include\suspend_interface.h"
+
+__drv_raisesIRQL(APC_LEVEL)
+__drv_savesIRQLGlobal(OldIrql, fdoData->SessionLock) 
+void LockSessions(
+        FDO_DATA* fdoData)
+{
+    ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
+    ExAcquireFastMutex(&fdoData->SessionLock);
+}
+
+__drv_requiresIRQL(APC_LEVEL)
+__drv_restoresIRQLGlobal(OldIrql, fdoData->SessionLock)
+void UnlockSessions(
+        FDO_DATA* fdoData)
+{
+    ASSERT(KeGetCurrentIrql() == APC_LEVEL);
+    ExReleaseFastMutex(&fdoData->SessionLock);
+    
+}
+
+void GetUnicodeString(UNICODE_STRING *unicode, USHORT maxlength, LPWSTR location)
+{
+    int i;
+    USHORT length=0;
+    unicode->MaximumLength=maxlength;
+    unicode->Buffer=location;
+    // No appropriate fucntion to determine the length of a possibly null
+    // terminated string withing a fixed sized buffer exists.
+    for (i=0; (i*sizeof(WCHAR))<maxlength; i++) {
+        if (location[i] != L'\0')
+            length+=sizeof(WCHAR);
+        else
+            break;
+    }
+    unicode->Length = (USHORT)length;
+}
+
+NTSTATUS GetAnsiString(ANSI_STRING *ansi, USHORT maxlength, LPWSTR location) {
+    UNICODE_STRING unicode;
+    NTSTATUS status;
+    GetUnicodeString(&unicode, maxlength, location);
+    status = RtlUnicodeStringToAnsiString(ansi, &unicode, TRUE);
+    return status;
+}
+
+// Rather inconveniently, xenstore needs UTF8 data, WMI works in UTF16
+// and windows doesn't provide conversion functions in any version
+// prior to Windows 7.  
+
+USHORT Utf32FromUtf16(ULONG *utf32, const WCHAR* utf16) {
+    ULONG w;
+    ULONG u;
+    ULONG xa;
+    ULONG xb;
+    ULONG x;
+
+    if (((utf16[0]) & 0xFC00) == 0xD800) {
+        w = ((utf16[0]) & 0X03FF) >>6;
+        u = w+1;
+        xa = utf16[0] & 0x3F;
+        xb = utf16[1] & 0x03FF;
+        x = (xa<<10) | xb;
+        *utf32 = (u<<16) + x;
+        return 2;
+    }
+    else {
+        *utf32 = *utf16;
+        return 1;
+    }
+}
+
+USHORT Utf32FromUtf8(ULONG *utf32, const CHAR *utf8) {
+    ULONG y;
+    ULONG x;
+    ULONG z;
+    ULONG ua;
+    ULONG ub;
+    ULONG u;
+
+    if ((utf8[0] & 0x80) == 0) {
+        *utf32 = utf8[0];
+        return 1;
+    }
+    else if ((utf8[0] & 0xE0) == 0xC0) {
+        y = utf8[0] & 0x1F;
+        x = utf8[1] & 0x3F;
+        *utf32 = (y<<6) | x; 
+        return 2;
+    }
+    else if ((utf8[0] & 0xF0) == 0xE0) {
+        z = utf8[0] & 0x0F;
+        y = utf8[1] & 0x3F;
+        x = utf8[2] & 0x3F;
+       *utf32 = (z <<12) | (y<<6) | x; 
+       return 3;
+    } 
+    else {
+        ua = utf8[0] & 0x7;
+        ub = (utf8[1] & 0x30) >> 4;
+        u = (ua << 2) | ub;
+        z = utf8[1] & 0x0f;
+        y = utf8[2] & 0x3f; 
+        x = utf8[3] & 0x3f;
+        *utf32 = (u<<16) | (z <<12) | (y <<6) | x;
+        return 4;
+    }
+
+}
+
+USHORT Utf16FromUtf32(WCHAR *utf16, const ULONG utf32) {
+    WCHAR u;
+    WCHAR w;
+    WCHAR x;
+    if ((utf32 > 0xFFFF)) {
+        u = (utf32 & 0x1F0000) >> 16;
+        w = u-1;
+        x = utf32 & 0xFFFF;
+        utf16[0] = 0xD800 | (w<<6) | (x>>10);
+        utf16[1] = 0xDC00 | (x & 0x3F);
+        return 2;
+    }
+    else {
+        utf16[0] = utf32 & 0xFFFF;
+        return 1;
+    }
+}
+
+
+#define UTF8MASK2 0x1FFF80
+#define UTF8MASK3 0x1FF800
+#define UTF8MASK4 0x1F0000
+
+USHORT CountUtf8FromUtf32(ULONG utf32) {
+    if (utf32 & UTF8MASK4)
+        return 4;
+    if (utf32 & UTF8MASK3)
+        return 3;
+    if (utf32 & UTF8MASK2)
+        return 2;
+    return 1;
+}
+
+USHORT CountUtf16FromUtf32(ULONG utf32) {
+    if ((utf32 & 0xFF0000) > 0) {
+        return 2;
+    }
+    return 1;
+}
+
+USHORT Utf8FromUtf32(CHAR *dest, ULONG utf32) {
+    CHAR u;
+    CHAR y;
+    CHAR x;
+    CHAR z;
+
+    if (utf32 & UTF8MASK4) {
+        x = utf32 & 0x3f;
+        y = (utf32 >> 6) & 0x3f;
+        z = (utf32 >> 12) & 0xf;
+        u = (utf32 >> 16) & 0x1f;
+        dest[0] = 0xf0 | u>>2;
+        dest[1] = 0x80 | (u & 0x3) << 4 | z;
+        dest[2] = 0x80 | y;
+        dest[3] = 0x80 | x;
+        return 4;
+    }
+    else if (utf32 & UTF8MASK3) {
+        x = utf32 & 0x3f;
+        y = (utf32 >> 6) & 0x3f;
+        z = (utf32 >> 12) & 0xf;
+        dest[0] = 0xe0 | z;
+        dest[1] = 0x80 | y;
+        dest[2] = 0x80 | x;
+        return 3;
+    }
+    else if (utf32 & UTF8MASK2) {
+        x = utf32 & 0x3f;
+        y = (utf32 >> 6) & 0x3f;
+        dest[0] = 0xc0 | y;
+        dest[1] = 0x80 | x;
+        return 2;
+    }
+    else {
+        x = utf32 & 0x7f;
+        dest[0] = x;
+        return 1;
+    }
+}
+
+typedef struct {
+    USHORT Length;
+    CHAR Buffer[1];
+} UTF8_STRING;
+
+USHORT CountBytesUtf16FromUtf8String(const UTF8_STRING *utf8) {
+    ULONG utf32;
+    int i = 0;
+    USHORT bytecount = 0;
+    while (i<utf8->Length && utf8->Buffer[i] !=0) {
+        i += Utf32FromUtf8(&utf32, &utf8->Buffer[i]);
+        bytecount += CountUtf16FromUtf32(utf32);
+    }
+    return bytecount * sizeof(WCHAR);
+}
+USHORT CountBytesUtf16FromUtf8(const UCHAR *utf8) {
+    ULONG utf32;
+    int i = 0;
+    USHORT bytecount = 0;
+    while (utf8[i] !=0) {
+        i += Utf32FromUtf8(&utf32, &utf8[i]);
+        bytecount += CountUtf16FromUtf32(utf32);
+    }
+    return bytecount * sizeof(WCHAR);
+}
+NTSTATUS GetUTF8String(UTF8_STRING** utf8, USHORT bufsize, LPWSTR ustring)
+{
+    USHORT bytecount = 0;
+    USHORT i;
+    ULONG utf32;
+    i = 0;
+    while (i < (bufsize/sizeof(WCHAR))) {
+        i += Utf32FromUtf16(&utf32, &ustring[i]);
+        bytecount += CountUtf8FromUtf32(utf32);
+    }
+
+    *utf8 = ExAllocatePoolWithTag(NonPagedPool, sizeof(UTF8_STRING)+bytecount, 'XIU8');
+    if ((*utf8) == NULL)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    (*utf8)->Length = bytecount;
+    (*utf8)->Buffer[bytecount]=0;
+    
+    bytecount = 0;
+    i=0;
+    while (i < bufsize/sizeof(WCHAR)) {
+        i += Utf32FromUtf16(&utf32, &ustring[i]);
+        bytecount += Utf8FromUtf32(&((*utf8)->Buffer[bytecount]), utf32);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+void FreeUTF8String(UTF8_STRING *utf8) {
+    ExFreePoolWithTag(utf8, 'XIU8');
+}
+
+NTSTATUS GetCountedUTF8String(UTF8_STRING **utf8, UCHAR *location)
+{
+    USHORT bufsize = *(USHORT*)location;
+    LPWSTR ustring = (LPWSTR)(location+sizeof(USHORT));
+    return GetUTF8String(utf8, bufsize, ustring);
+
+}
+
+void GetCountedUnicodeString(UNICODE_STRING *unicode, UCHAR *location)
+{
+    USHORT bufsize = *(USHORT*)location;
+    LPWSTR ustring = (LPWSTR)(location+sizeof(USHORT));
+    GetUnicodeString(unicode, bufsize, ustring);
+} 
+
+NTSTATUS GetCountedAnsiString(ANSI_STRING *ansi, UCHAR *location)
+{
+    USHORT bufsize = *(USHORT*)location;
+    LPWSTR ustring = (LPWSTR)(location+sizeof(USHORT));
+    return GetAnsiString(ansi, bufsize, ustring);
+}
+
+typedef enum {
+    WMI_DONE,
+    WMI_STRING,
+    WMI_BOOLEAN,
+    WMI_SINT8,
+    WMI_UINT8,
+    WMI_SINT16,
+    WMI_UINT16,
+    WMI_INT32,
+    WMI_UINT32,
+    WMI_SINT64,
+    WMI_UINT64,
+    WMI_DATETIME,
+    WMI_BUFFER,
+    WMI_OFFSET,
+    WMI_STRINGOFFSET
+} WMI_TYPE;
+
+int AccessWmiBuffer(PUCHAR Buffer, int readbuffer, ULONG * RequiredSize, 
+                    size_t BufferSize, ...) {
+    va_list vl;
+    ULONG_PTR offset;
+    ULONG_PTR offby;
+    PUCHAR position = Buffer;
+    PUCHAR endbuffer = Buffer + BufferSize;
+    int overflow=0;
+    va_start(vl, BufferSize);
+    for(;;) {
+        WMI_TYPE type = va_arg(vl, WMI_TYPE);
+        if (type != WMI_DONE) {
+#define WMITYPECASE(_wmitype, _type, _align) \
+            case _wmitype: {\
+                _type** val; \
+                offby = ((ULONG_PTR)position)%(_align); \
+                offset = ((_align)-offby)%(_align) ; \
+                position += offset;\
+                if (position + sizeof(_type) > endbuffer) \
+                    overflow = TRUE;\
+                val = va_arg(vl, _type**); \
+                *val = NULL; \
+                if (!overflow) \
+                    *val = (_type *)position; \
+                position += sizeof(_type); } \
+                break
+            switch (type) {
+                case WMI_STRING:
+                    {
+                        UCHAR **countstr;
+                        USHORT strsize;
+                        offset = (2-((ULONG_PTR)position%2))%2;
+                        position+=offset;
+                        if (position + sizeof(USHORT) > endbuffer)
+                            overflow = TRUE;
+                        if (readbuffer) {
+                            if (!overflow)
+                                strsize = *(USHORT*)position;
+                            else
+                                strsize = 0;
+                            strsize+=sizeof(USHORT);
+                        }
+                        else {
+                            strsize = va_arg(vl, USHORT);
+                        }
+                        if (position + strsize  >endbuffer)
+                            overflow = TRUE;
+                        countstr = va_arg(vl, UCHAR**);
+                        *countstr = NULL;
+                        if (!overflow)
+                            *countstr = position;
+                        position +=strsize;
+                    }
+                    break;
+                case WMI_BUFFER:
+                    {
+                        ULONG size = va_arg(vl, ULONG);
+                        UCHAR **buffer;
+                        if (position + size > endbuffer)
+                            overflow = TRUE;
+                        buffer = va_arg(vl, UCHAR**);
+                        *buffer = NULL;
+                        if (!overflow)
+                            *buffer = position;
+                        position += size;
+                    }
+                    break;
+                case WMI_OFFSET:
+                    {
+                        ULONG inpos = va_arg(vl, ULONG);
+                        UCHAR *bufferpos = Buffer + inpos;
+                        ULONG insize = va_arg(vl, ULONG);
+                        UCHAR **writebuf = va_arg(vl, UCHAR**);
+                        *writebuf = NULL; 
+                        if (bufferpos+ insize > endbuffer) {;
+                            overflow = TRUE;
+                        }
+                        else {
+                            *writebuf = bufferpos;
+                        }
+                        // Only update position if it extends
+                        // the required size of the buffer
+                        if (bufferpos+insize > position)
+                            position = bufferpos+insize;
+                    }
+                    break;
+                    case WMI_STRINGOFFSET:
+                    {
+                        UCHAR **countstr;
+                        USHORT strsize;
+                        ULONG inpos = va_arg(vl, ULONG);
+                        UCHAR *bufferpos = Buffer + inpos;
+                        if (bufferpos + sizeof(USHORT) > endbuffer)
+                            overflow = TRUE;
+                        if (readbuffer) {
+                            if (!overflow)
+                                strsize = *(USHORT*)bufferpos;
+                            else
+                                strsize = 0;
+                            strsize+=sizeof(USHORT);
+                        }
+                        else {
+                            strsize = va_arg(vl, USHORT);
+                        }
+                        if (bufferpos + strsize  >endbuffer)
+                            overflow = TRUE;
+                        countstr = va_arg(vl, UCHAR**);
+                        *countstr = NULL;
+                        if (!overflow)
+                            *countstr = bufferpos;
+                        if (bufferpos+strsize > position)
+                            position =bufferpos+strsize;
+                    }
+                    break;
+                WMITYPECASE(WMI_BOOLEAN, UCHAR, 1);
+                WMITYPECASE(WMI_SINT8, CHAR, 1);
+                WMITYPECASE(WMI_UINT8, UCHAR, 1);
+                WMITYPECASE(WMI_SINT16, SHORT, 2);
+                WMITYPECASE(WMI_UINT16, USHORT, 2);
+                WMITYPECASE(WMI_INT32, LONG, 4);
+                WMITYPECASE(WMI_UINT32, ULONG, 4);
+                WMITYPECASE(WMI_SINT64, LONGLONG, 8);
+                WMITYPECASE(WMI_UINT64, ULONGLONG, 8);
+                case WMI_DATETIME:
+                    {
+                        LPWSTR *val;
+                        offset = (2-((ULONG_PTR)position%2))%2;
+                        position += offset;
+                        if (position + sizeof(WCHAR)*25 > endbuffer) 
+                            overflow = TRUE;
+                        val = va_arg(vl, LPWSTR*); 
+                        *val = NULL; 
+                        if (!overflow) 
+                            *val = (LPWSTR )position; 
+                        position += sizeof(WCHAR)*25;
+                    }
+                    break;
+                default:
+                    return FALSE;
+            }
+        }
+        else {
+            break;
+        }
+    }
+    *RequiredSize = (ULONG)(position - Buffer); 
+    va_end(vl);
+    if (overflow)
+        return FALSE;
+    return TRUE;
+}
+
+
+NTSTATUS 
+WriteCountedUnicodeString(
+    const UNICODE_STRING *ustr, 
+    UCHAR *location
+    )
+{
+    *((USHORT*)location) = ustr->Length;
+    RtlCopyMemory(location+sizeof(USHORT), ustr->Buffer,
+                  ustr->Length);
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+WriteCountedUTF8String(const char * string, UCHAR *location) {
+    UNICODE_STRING unicode;
+
+    int i=0;
+    USHORT b;
+    USHORT bytesize=0;
+    ULONG utf32;
+    NTSTATUS status = STATUS_SUCCESS;
+    WCHAR *buffer;
+    bytesize = CountBytesUtf16FromUtf8(string);
+    buffer = ExAllocatePoolWithTag(NonPagedPool, bytesize+sizeof(WCHAR), 'XSUc');
+
+    if (buffer == NULL) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    buffer[bytesize/sizeof(WCHAR)] = 0;
+
+    i=0; 
+    b=0;
+    while (string[i] != 0) {
+        i += Utf32FromUtf8(&utf32, &string[i]);
+        b += Utf16FromUtf32(&buffer[b], utf32);
+    }
+    RtlInitUnicodeString(&unicode, buffer);
+    status = WriteCountedUnicodeString(&unicode, location);
+    ExFreePoolWithTag(buffer, 'XSUc');
+
+    return status;
+}
+
+NTSTATUS
+WriteCountedString(
+    const char * string,
+    UCHAR * location
+    ) 
+{
+    ANSI_STRING ansi;
+    UNICODE_STRING unicode;
+    NTSTATUS status;
+
+    RtlInitAnsiString(&ansi, string);
+
+    status = RtlAnsiStringToUnicodeString(&unicode, &ansi, TRUE);
+    if (NT_SUCCESS(status)) { 
+
+        status = WriteCountedUnicodeString(&unicode, location);
+        RtlFreeUnicodeString(&unicode);
+    }
+
+    return status;
+}
+
+void AllocUnicodeStringBuffer(UNICODE_STRING *string, USHORT buffersize) {
+    string->Buffer = ExAllocatePoolWithTag(NonPagedPool, buffersize, 'XIUC');
+    string->Length = 0;
+    if (string->Buffer == NULL) {
+        string->MaximumLength=0;
+        return;
+    }
+    string->MaximumLength=(USHORT)buffersize;
+    string->Buffer[0]=0;
+    return;
+}
+void FreeUnicodeStringBuffer(UNICODE_STRING *string) {
+    if (string->Buffer)
+        ExFreePoolWithTag(string->Buffer, 'XIUC');
+    string->Length=0;
+    string->MaximumLength=0;
+    string->Buffer = NULL;
+}
+
+NTSTATUS
+CloneUnicodeString(UNICODE_STRING *dest, UNICODE_STRING *src) {
+    NTSTATUS status;
+    AllocUnicodeStringBuffer(dest, src->Length);
+    if (dest->Buffer == NULL)
+        return STATUS_INSUFFICIENT_RESOURCES;
+    status = RtlUnicodeStringCopy(dest, src);
+    if (!NT_SUCCESS(status)) {
+        FreeUnicodeStringBuffer(dest);
+    }
+    return status;
+}
+
+NTSTATUS 
+StringToUnicode(UNICODE_STRING *ustr, const char * str) {
+    ANSI_STRING ansi;
+    RtlInitAnsiString(&ansi, str);
+    return RtlAnsiStringToUnicodeString(ustr, &ansi, TRUE);
+}
+
+size_t
+GetCountedSize(const char * string) {
+    ANSI_STRING ansi;
+    RtlInitAnsiString(&ansi, string);
+    return sizeof(USHORT)+sizeof(WCHAR)*ansi.Length;
+}
+
+size_t
+GetCountedUtf8Size(const char *utf8) {
+    return sizeof(USHORT) + CountBytesUtf16FromUtf8(utf8);
+}
+
+size_t
+GetCountedUnicodeStringSize(UNICODE_STRING *string) {
+    return sizeof(USHORT)+string->Length;
+}
+
+size_t
+GetInstanceNameSize(FDO_DATA* FdoData, const char *string) {
+    ANSI_STRING ansi;
+    RtlInitAnsiString(&ansi, string);
+    return sizeof(USHORT) +
+            FdoData->SuggestedInstanceName.Length +
+            sizeof(WCHAR) +
+            sizeof(WCHAR)*ansi.Length;
+
+}
+
+
+NTSTATUS
+GetInstanceName(UNICODE_STRING *dest, FDO_DATA* FdoData, const char *string) {
+    ANSI_STRING ansi;
+    UNICODE_STRING unicode;
+    NTSTATUS status;
+    size_t destsz;
+
+    RtlInitAnsiString(&ansi, string);
+    status = RtlAnsiStringToUnicodeString(&unicode, &ansi, TRUE);
+    if (!NT_SUCCESS(status)) {
+        return status;
+    }
+    destsz = FdoData->SuggestedInstanceName.Length +
+                sizeof(WCHAR) + 
+                unicode.Length;
+
+    AllocUnicodeStringBuffer(dest, (USHORT)destsz);
+    if (dest->Buffer == NULL ) {
+        RtlFreeUnicodeString(&unicode);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    status = RtlUnicodeStringPrintf(dest, L"%s\\%s", 
+                FdoData->SuggestedInstanceName.Buffer, 
+                unicode.Buffer);
+    if (!NT_SUCCESS(status)) {
+        RtlFreeUnicodeString(&unicode);
+        FreeUnicodeStringBuffer(dest);
+        return status;
+    }
+    RtlFreeUnicodeString(&unicode);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+WriteInstanceName(FDO_DATA* FdoData, const char *string, UCHAR *location)
+{
+    UNICODE_STRING destination;
+    NTSTATUS status;
+    status = GetInstanceName(&destination, FdoData, string);
+    if (!NT_SUCCESS(status))
+        return status;
+    status = WriteCountedUnicodeString(&destination, location);
+    FreeUnicodeStringBuffer(&destination);
+    return status;
+}
+
+#define MAX_WATCH_COUNT (MAXIMUM_WAIT_OBJECTS -1)
+
+typedef struct _XenStoreSession {
+    LIST_ENTRY listentry;
+    LONG id;
+    UNICODE_STRING stringid;
+    UNICODE_STRING instancename;
+    PXENBUS_STORE_TRANSACTION transaction;
+    LIST_ENTRY watches;
+    int watchcount;
+    KEVENT* watchevents[MAXIMUM_WAIT_OBJECTS];
+    KWAIT_BLOCK watchwaitblockarray[MAXIMUM_WAIT_OBJECTS];
+    KEVENT SessionChangedEvent;
+    FAST_MUTEX WatchMapLock;
+    BOOLEAN mapchanged;
+    BOOLEAN closing;
+    BOOLEAN suspended;
+    PKTHREAD WatchThread;
+} XenStoreSession;
+
+typedef struct _XenStoreWatch {
+    LIST_ENTRY listentry;
+    UNICODE_STRING path;
+    FDO_DATA *fdoData;
+
+    ULONG   suspendcount;
+    BOOLEAN finished;
+    KEVENT watchevent;
+    PXENBUS_STORE_WATCH watchhandle;
+
+} XenStoreWatch;
+
+void UnicodeShallowCopy(UNICODE_STRING *dest, UNICODE_STRING *src) {
+    dest->Buffer = src->Buffer;
+    dest->Length = src->Length;
+    dest->MaximumLength = src->MaximumLength;
+} 
+
+
+XenStoreSession*
+FindSessionLocked(FDO_DATA *fdoData, 
+                                LONG id) {
+    XenStoreSession *session;
+     
+    session = (XenStoreSession *)fdoData->SessionHead.Flink;
+    while (session != (XenStoreSession *)&fdoData->SessionHead){
+        if (session->id == id) {
+            if (session->suspended)
+                return NULL;
+            return session;
+        }
+        session = (XenStoreSession *)session->listentry.Flink;
+    }
+    return NULL;
+}
+
+
+int CompareUnicodeStrings(PCUNICODE_STRING string1, PCUNICODE_STRING string2) {
+    if (string1->Length == string2->Length) {
+        return RtlCompareMemory(string1->Buffer,string2->Buffer, string1->Length) != string1->Length;
+    }
+    return 1;
+
+}
+
+_IRQL_raises_(APC_LEVEL)
+XenStoreWatch *
+SessionFindWatchLocked(XenStoreSession *session,
+                        UNICODE_STRING *path) {
+    XenStoreWatch * watch;
+    
+    XenIfaceDebugPrint(TRACE,"Wait for session watch lock\n");
+    ExAcquireFastMutex(&session->WatchMapLock);
+    XenIfaceDebugPrint(TRACE,"got session watch lock\n");
+    watch = (XenStoreWatch *)session->watches.Flink;
+
+    while (watch != (XenStoreWatch *)&session->watches){
+        if (CompareUnicodeStrings(path, &watch->path)==0) {
+            return watch;
+        }
+        watch = (XenStoreWatch *)watch->listentry.Flink;
+    }
+
+    XenIfaceDebugPrint(WARNING,"couldn't find watch\n");
+    return NULL;
+
+} 
+
+void FireSuspendEvent(PFDO_DATA 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,
+                (LPGUID)&CitrixXenStoreUnsuspendedEvent_GUID,
+                0,
+                0,
+                NULL);
+    }
+} 
+void FireWatch(XenStoreWatch* watch) {
+    UCHAR * eventdata;
+    ULONG RequiredSize;
+    UCHAR *sesbuf;
+
+    AccessWmiBuffer(0, FALSE, &RequiredSize, 0,
+            WMI_STRING, GetCountedUnicodeStringSize(&watch->path),
+                &sesbuf,
+            WMI_DONE);
+    
+    eventdata = ExAllocatePoolWithTag(NonPagedPool, RequiredSize,'XIEV');
+    if (eventdata!=NULL) {
+        AccessWmiBuffer(eventdata, FALSE, &RequiredSize, RequiredSize,
+            WMI_STRING, GetCountedUnicodeStringSize(&watch->path),
+                &sesbuf,
+            WMI_DONE);
+
+        WriteCountedUnicodeString(&watch->path, sesbuf); 
+    }
+
+    if (eventdata !=NULL) {
+        XenIfaceDebugPrint(TRACE,"Fire Watch Event\n");
+        WmiFireEvent(watch->fdoData->Self, 
+                        (LPGUID)&CitrixXenStoreWatchEvent_GUID,
+                        0,
+                        RequiredSize, 
+                        eventdata);
+    } 
+}
+
+
+KSTART_ROUTINE WatchCallbackThread;
+NTSTATUS
+StartWatch(FDO_DATA *fdoData, XenStoreWatch *watch)
+{
+    char *tmppath; 
+    ANSI_STRING ansipath;
+    NTSTATUS status;
+    status = RtlUnicodeStringToAnsiString(&ansipath, &watch->path, TRUE);
+    if (!NT_SUCCESS(status)) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    tmppath = ExAllocatePoolWithTag(NonPagedPool, ansipath.Length+1, 'XenP');
+    if (!tmppath) {
+        RtlFreeAnsiString(&ansipath);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    RtlZeroMemory(tmppath, ansipath.Length+1);
+    RtlCopyBytes(tmppath,ansipath.Buffer, ansipath.Length);
+    
+    status = STORE(Watch, fdoData->StoreInterface, NULL, tmppath, &watch->watchevent, &watch->watchhandle );
+    if (!NT_SUCCESS(status)) {
+        ExFreePool(tmppath);
+        RtlFreeAnsiString(&ansipath);
+        return status;
+    }
+
+    XenIfaceDebugPrint(WARNING,"Start Watch %p\n", watch->watchhandle);
+
+    ExFreePool(tmppath);
+    RtlFreeAnsiString(&ansipath);
+
+    return STATUS_SUCCESS;
+}
+
+
+VOID WatchCallbackThread(__in PVOID StartContext) {
+    NTSTATUS status;
+    int i=0;
+    XenStoreSession * session = (XenStoreSession*) StartContext;
+
+    for(;;) {
+        ExAcquireFastMutex(&session->WatchMapLock);
+        if (session->mapchanged) {
+            // Construct a new mapping
+            XenStoreWatch *watch;
+            XenIfaceDebugPrint(TRACE,"Construct a new mapping\n");
+            watch = (XenStoreWatch *)session->watches.Flink;
+            for (i=0; watch != (XenStoreWatch *)&session->watches; i++) {
+                session->watchevents[i] = &watch->watchevent;
+                watch = (XenStoreWatch *)watch->listentry.Flink;
+            }
+            session->mapchanged = FALSE;
+            session->watchevents[i] = &session->SessionChangedEvent; 
+        }
+        ExReleaseFastMutex(&session->WatchMapLock);
+        XenIfaceDebugPrint(TRACE,"Wait for new event\n");
+        status = KeWaitForMultipleObjects(i+1, session->watchevents, WaitAny, Executive, KernelMode, TRUE, NULL, session->watchwaitblockarray);
+        XenIfaceDebugPrint(TRACE,"got new event\n");
+        if ((status >= STATUS_WAIT_0) && (status < STATUS_WAIT_0 +i )) {
+            XenStoreWatch *watch;
+            XenIfaceDebugPrint(TRACE,"watch or suspend\n");
+            watch = CONTAINING_RECORD(session->watchevents[status-STATUS_WAIT_0], XenStoreWatch, watchevent );
+            ExAcquireFastMutex(&session->WatchMapLock);
+            KeClearEvent(&watch->watchevent);
+
+
+            if (watch->finished) {
+                FreeUnicodeStringBuffer(&watch->path);
+                RemoveEntryList((LIST_ENTRY*)watch);
+                ExFreePool(watch);
+                session->mapchanged = TRUE;
+                session->watchcount --;
+            }
+            else
+            {
+                if (!session->suspended) {
+                    if (watch->suspendcount !=SUSPEND(Count, watch->fdoData->SuspendInterface)) {
+                        watch->suspendcount = SUSPEND(Count, watch->fdoData->SuspendInterface);
+                        XenIfaceDebugPrint(WARNING,"SessionSuspendResumeUnwatch %p\n", watch->watchhandle);
+                        
+                        STORE(Unwatch, watch->fdoData->StoreInterface, watch->watchhandle);
+                        StartWatch(watch->fdoData, watch);
+                    }
+                }
+                FireWatch(watch);
+            }
+            ExReleaseFastMutex(&session->WatchMapLock);
+        }
+        else if ( status == STATUS_WAIT_0 + i) {
+            ExAcquireFastMutex(&session->WatchMapLock);
+            KeClearEvent(&session->SessionChangedEvent); 
+            if (session->closing==TRUE) {
+                XenIfaceDebugPrint(TRACE,"Trying to end session thread\n");
+                if (session->watchcount != 0) {
+                    XenStoreWatch *watch;
+                    for (watch = (XenStoreWatch *)session->watches.Flink; 
+                        watch!=(XenStoreWatch *)&session->watches; 
+                        watch=(XenStoreWatch *)session->watches.Flink) {
+                            FreeUnicodeStringBuffer(&watch->path);
+                            RemoveEntryList((LIST_ENTRY*)watch);
+                            ExFreePool(watch);
+                            session->mapchanged = TRUE;
+                            session->watchcount --;
+                    }
+                }
+                ExReleaseFastMutex(&session->WatchMapLock);
+                XenIfaceDebugPrint(TRACE,"Ending session thread\n");
+                PsTerminateSystemThread(STATUS_SUCCESS);
+                //ExReleaseFastMutex(&session->WatchMapLock);
+            }
+            else {
+                
+                ExReleaseFastMutex(&session->WatchMapLock);
+            }
+        }
+
+    }
+}
+
+NTSTATUS
+SessionAddWatchLocked(XenStoreSession *session, 
+                        FDO_DATA* fdoData, 
+                        UNICODE_STRING *path,
+                        XenStoreWatch **watch) {
+
+    
+    NTSTATUS status;
+    XenStoreWatch *pwatch;
+
+    if (session->watchcount >= MAX_WATCH_COUNT) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    *watch = ExAllocatePoolWithTag(NonPagedPool, sizeof(XenStoreWatch), 'XenP');
+    if (*watch == NULL) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    (*watch)->finished = FALSE; 
+    (*watch)->fdoData = fdoData;
+    UnicodeShallowCopy(&(*watch)->path, path);
+
+
+   
+    (*watch)->suspendcount = SUSPEND(Count, fdoData->SuspendInterface);
+    
+
+    KeInitializeEvent(&(*watch)->watchevent, NotificationEvent, FALSE);
+
+    
+    status = StartWatch(fdoData, *watch);
+    if ((!NT_SUCCESS(status)) || ((*watch)->watchhandle == NULL)) {
+        ExFreePool(*watch);
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    ExAcquireFastMutex(&session->WatchMapLock);
+    session->mapchanged = TRUE;
+    KeSetEvent(&session->SessionChangedEvent, IO_NO_INCREMENT,FALSE);
+    session->watchcount++;
+    InsertHeadList(&session->watches,(PLIST_ENTRY)(*watch));
+
+    XenIfaceDebugPrint(TRACE, "WATCHLIST for session %p-----------\n",session);
+    pwatch = (XenStoreWatch *)session->watches.Flink;
+
+    while (pwatch != (XenStoreWatch *)&session->watches){
+        XenIfaceDebugPrint(TRACE, "WATCHLIST %p\n",pwatch->watchhandle);
+        pwatch = (XenStoreWatch *)pwatch->listentry.Flink;
+    }
+    XenIfaceDebugPrint(TRACE, "WATCHLIST-------------------\n");
+
+    ExReleaseFastMutex(&session->WatchMapLock);
+    return STATUS_SUCCESS;
+
+}
+
+void SessionRemoveWatchLocked(XenStoreSession *session, XenStoreWatch *watch) {
+
+    XenStoreWatch *pwatch;
+    XenIfaceDebugPrint(TRACE, "Remove watch locked\n");
+    XenIfaceDebugPrint(TRACE, "watch %p\n", watch);
+    XenIfaceDebugPrint(TRACE, "handle %p\n", watch->watchhandle);
+
+    if (watch->watchhandle) {
+        STORE(Unwatch, watch->fdoData->StoreInterface, watch->watchhandle);
+        watch->watchhandle=NULL;
+        watch->finished = TRUE;
+    XenIfaceDebugPrint(TRACE, "WATCHLIST for session %p-----------\n",session);
+    pwatch = (XenStoreWatch *)session->watches.Flink;
+
+    while (pwatch != (XenStoreWatch *)&session->watches){
+        XenIfaceDebugPrint(TRACE, "WATCHLIST %p\n",pwatch->watchhandle);
+        pwatch = (XenStoreWatch *)pwatch->listentry.Flink;
+    }
+    XenIfaceDebugPrint(TRACE, "WATCHLIST-------------------\n");
+        KeSetEvent(&watch->watchevent, IO_NO_INCREMENT,FALSE);
+    }
+
+}
+
+void SessionRemoveWatchesLocked(XenStoreSession *session) {
+    XenStoreWatch *watch;
+
+    XenIfaceDebugPrint(TRACE, "wait remove mutex\n");
+    ExAcquireFastMutex(&session->WatchMapLock);
+    for (watch = (XenStoreWatch *)session->watches.Flink; 
+         watch!=(XenStoreWatch *)&session->watches; 
+         watch=(XenStoreWatch *)watch->listentry.Flink) {
+
+        XenIfaceDebugPrint(TRACE, "try remove %p\n",session->watches.Flink );
+        SessionRemoveWatchLocked(session, watch);
+    }
+    XenIfaceDebugPrint(TRACE, "release remove mutex\n");
+    ExReleaseFastMutex(&session->WatchMapLock);
+}
+
+
+XenStoreSession*
+FindSessionByInstanceLocked(FDO_DATA *fdoData,
+                            UNICODE_STRING *instance) {
+    XenStoreSession *session;
+     
+    session = (XenStoreSession *)fdoData->SessionHead.Flink;
+    while (session != (XenStoreSession *)&fdoData->SessionHead) {
+        if (CompareUnicodeStrings(instance, &session->instancename)==0) {
+            if (session->suspended)
+                return NULL;
+            return session;
+        }
+        session = (XenStoreSession *)session->listentry.Flink;
+    }
+    return NULL;
+}
+
+
+__checkReturn
+__success(return!=NULL)
+__drv_raisesIRQL(APC_LEVEL)
+__drv_savesIRQLGlobal(OldIrql, fdoData->SessionLock)
+XenStoreSession *
+FindSessionByInstanceAndLock(FDO_DATA *fdoData,
+                                UNICODE_STRING *instance) {
+    XenStoreSession *session;
+    LockSessions(fdoData);
+    session = FindSessionByInstanceLocked(fdoData, instance);
+    if (session == NULL) {
+         UnlockSessions(fdoData);
+    }
+    return session;
+}
+
+PSTR Xmasprintf(const char *fmt, ...) {
+    va_list argv;
+    PSTR out;
+    size_t basesize = 128;
+    size_t unused;
+    NTSTATUS status;
+    va_start(argv, fmt);
+    do{
+        basesize = basesize * 2;
+        out =  ExAllocatePoolWithTag(NonPagedPool, basesize, 'XenP');
+        if (out == NULL)
+            return NULL;
+        
+        status = RtlStringCbVPrintfExA(out, basesize, NULL, &unused,0, fmt, argv);
+
+        ExFreePool(out);
+    }while (status != STATUS_SUCCESS);
+
+    out = ExAllocatePoolWithTag(NonPagedPool, basesize-unused +1, 'XenP');
+    if (out == NULL)
+        return NULL;
+
+    RtlStringCbVPrintfA(out, basesize-unused+1, fmt, argv);
+
+    va_end(argv);
+    return out;
+}
+
+NTSTATUS 
+CreateNewSession(FDO_DATA *fdoData, 
+                    UNICODE_STRING *stringid, 
+                    ULONG *sessionid) {
+    XenStoreSession *session;
+    PSTR iname;
+    NTSTATUS status;
+    ANSI_STRING ansi;
+    HANDLE hthread;
+    int count = 0;
+    OBJECT_ATTRIBUTES oa;
+    if (fdoData->Sessions == MAX_SESSIONS) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    session = ExAllocatePoolWithTag(NonPagedPool, sizeof(XenStoreSession), 'XenP');
+    if (session == NULL)
+        return STATUS_INSUFFICIENT_RESOURCES;
+    RtlZeroMemory(session, sizeof(XenStoreSession));
+    
+    ExInitializeFastMutex(&session->WatchMapLock);
+    session->mapchanged = TRUE;
+    status = RtlUnicodeStringToAnsiString(&ansi, stringid, TRUE);
+    if (!NT_SUCCESS(status)) {
+        ExFreePool(session);
+        return status;
+    }
+    LockSessions(fdoData);
+    do {
+        FreeUnicodeStringBuffer(&session->instancename);
+        iname = Xmasprintf("Session_%s_%d", ansi.Buffer, count);
+
+        status = STATUS_NO_MEMORY;
+        if (iname == NULL) {
+            UnlockSessions(fdoData);
+            RtlFreeAnsiString(&ansi); 
+            ExFreePool(session);
+            return status;
+        }
+
+        status = GetInstanceName(&session->instancename ,fdoData,iname);
+        ExFreePool(iname);
+        if (!NT_SUCCESS(status)) {
+            UnlockSessions(fdoData);
+            RtlFreeAnsiString(&ansi); 
+            ExFreePool(session);
+            return status;
+        }
+        count++;
+        
+    } while (FindSessionByInstanceLocked(fdoData, &session->instancename) != NULL);
+
+    
+    
+    
+    
+    if (fdoData->SessionHead.Flink==&fdoData->SessionHead) {
+        session->id=0;
+    }
+    else {
+        session->id =((XenStoreSession*)(fdoData->SessionHead.Flink))->id+1;
+        while (FindSessionLocked(fdoData, session->id))
+            session->id = (session->id + 1) % MAX_SESSIONS;
+    }
+    session->transaction=NULL;
+    InsertHeadList((PLIST_ENTRY)&fdoData->SessionHead, (PLIST_ENTRY)session);
+    *sessionid = session->id;
+    UnicodeShallowCopy(&session->stringid, stringid);
+    
+    InitializeListHead((PLIST_ENTRY)&session->watches);
+    
+    KeInitializeEvent(&session->SessionChangedEvent, NotificationEvent, FALSE);
+    session->closing = FALSE;
+    if (fdoData->InterfacesAcquired){ 
+        XenIfaceDebugPrint(TRACE,"Add session unsuspended\n");
+        session->suspended=FALSE;
+    }
+    else {
+        XenIfaceDebugPrint(TRACE,"Add session suspended\n");
+        session->suspended=TRUE;
+    }
+    fdoData->Sessions++;
+    UnlockSessions(fdoData);
+    InitializeObjectAttributes(&oa, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
+    (VOID) PsCreateSystemThread(&hthread, THREAD_ALL_ACCESS, &oa, NULL, NULL, WatchCallbackThread, session);
+    ObReferenceObjectByHandle(hthread, THREAD_ALL_ACCESS, NULL, KernelMode,  &session->WatchThread, NULL);
+    RtlFreeAnsiString(&ansi);
+    return STATUS_SUCCESS;
+}
+
+void 
+RemoveSessionLocked(FDO_DATA *fdoData, 
+                    XenStoreSession *session) {
+     
+    XenIfaceDebugPrint(TRACE,"RemoveSessionLocked\n");
+    RemoveEntryList((LIST_ENTRY*)session);
+    fdoData->Sessions--;
+    SessionRemoveWatchesLocked(session);
+    if (session->transaction != NULL) {
+        STORE(TransactionEnd, fdoData->StoreInterface, session->transaction, FALSE);  
+    }  
+    session->closing = TRUE;
+    KeSetEvent(&session->SessionChangedEvent, IO_NO_INCREMENT, FALSE);
+    KeWaitForSingleObject(session->WatchThread, Executive, KernelMode, FALSE, NULL);
+    ObDereferenceObject(session->WatchThread);
+    FreeUnicodeStringBuffer(&session->stringid);
+    FreeUnicodeStringBuffer(&session->instancename);
+    ExFreePool(session);
+}
+
+void
+RemoveSession(FDO_DATA *fdoData, 
+                    XenStoreSession *session) {
+    XenIfaceDebugPrint(TRACE,"RemoveSession\n");
+    LockSessions(fdoData);
+    RemoveSessionLocked(fdoData, session);
+    UnlockSessions(fdoData);
+}
+
+void SessionsRemoveAll(FDO_DATA *fdoData) {
+
+    LockSessions(fdoData);
+    while (fdoData->SessionHead.Flink != &fdoData->SessionHead) {
+        RemoveSessionLocked(fdoData, (XenStoreSession *)fdoData->SessionHead.Flink);
+    }
+    UnlockSessions(fdoData);
+}
+
+
+
+void SessionUnwatchWatchesLocked(XenStoreSession *session)
+{
+    int i;
+    XenStoreWatch *watch;
+    ExAcquireFastMutex(&session->WatchMapLock);
+    watch = (XenStoreWatch *)session->watches.Flink;
+    for (i=0; watch != (XenStoreWatch *)&session->watches; i++) {
+        XenIfaceDebugPrint(TRACE,"Suspend unwatch %p\n", watch->watchhandle);
+
+        STORE(Unwatch, watch->fdoData->StoreInterface, watch->watchhandle);
+        watch = (XenStoreWatch *)watch->listentry.Flink;
+    }
+    XenIfaceDebugPrint(TRACE, "WATCHLIST for session %p-----------\n",session);
+    watch = (XenStoreWatch *)session->watches.Flink;
+
+    while (watch != (XenStoreWatch *)&session->watches){
+        XenIfaceDebugPrint(TRACE, "WATCHLIST %p\n",watch->watchhandle);
+        watch = (XenStoreWatch *)watch->listentry.Flink;
+    }
+    XenIfaceDebugPrint(TRACE, "WATCHLIST-------------------\n");
+    session->suspended=1;
+    ExReleaseFastMutex(&session->WatchMapLock);
+}
+
+void SuspendSessionLocked(FDO_DATA *fdoData, 
+                         XenStoreSession *session) {
+    SessionUnwatchWatchesLocked(session);
+    if (session->transaction != NULL) {
+        XenIfaceDebugPrint(TRACE, "End transaction %p\n",session->transaction);
+        
+        STORE(TransactionEnd, fdoData->StoreInterface, session->transaction, FALSE);  
+        session->transaction = NULL;
+    }  
+}
+
+
+void SessionsSuspendAll(FDO_DATA *fdoData) {
+    XenStoreSession *session;
+    LockSessions(fdoData);
+    XenIfaceDebugPrint(TRACE,"Suspend all sessions\n");
+    session = (XenStoreSession *)fdoData->SessionHead.Flink;
+    while (session != (XenStoreSession *)&fdoData->SessionHead) {
+        SuspendSessionLocked(fdoData, session);
+        session = (XenStoreSession *)session->listentry.Flink;
+    }
+    UnlockSessions(fdoData);
+}
+
+
+void SessionRenewWatchesLocked(XenStoreSession *session) {
+    int i;
+    XenStoreWatch *watch;
+    ExAcquireFastMutex(&session->WatchMapLock);
+    watch = (XenStoreWatch *)session->watches.Flink;
+    for (i=0; watch != (XenStoreWatch *)&session->watches; i++) {
+        if (!watch->finished) {
+            watch->suspendcount = SUSPEND(Count, watch->fdoData->SuspendInterface);
+            StartWatch(watch->fdoData, watch);
+        }
+        watch = (XenStoreWatch *)watch->listentry.Flink;
+    }
+    XenIfaceDebugPrint(TRACE, "WATCHLIST for session %p-----------\n",session);
+    watch = (XenStoreWatch *)session->watches.Flink;
+
+    while (watch != (XenStoreWatch *)&session->watches){
+        XenIfaceDebugPrint(TRACE, "WATCHLIST %p\n",watch->watchhandle);
+        watch = (XenStoreWatch *)watch->listentry.Flink;
+    }
+    XenIfaceDebugPrint(TRACE, "WATCHLIST-------------------\n");
+    session->suspended=0;
+    session->mapchanged = TRUE;
+    KeSetEvent(&session->SessionChangedEvent, IO_NO_INCREMENT,FALSE);
+    ExReleaseFastMutex(&session->WatchMapLock);
+}
+
+void ResumeSessionLocked(FDO_DATA *fdoData, 
+                         XenStoreSession *session) {
+    SessionRenewWatchesLocked(session);
+}
+
+void SessionsResumeAll(FDO_DATA *fdoData) {
+    XenStoreSession *session;
+
+    LockSessions(fdoData);
+    XenIfaceDebugPrint(TRACE,"Resume all sessions\n");
+    session = (XenStoreSession *)fdoData->SessionHead.Flink;
+    while (session != (XenStoreSession *)&fdoData->SessionHead) {
+        ResumeSessionLocked(fdoData, session );
+        session=(XenStoreSession *)session->listentry.Flink;
+    }
+    UnlockSessions(fdoData);
+}
+
+
+NTSTATUS
+WmiInit(
+        PFDO_DATA FdoData
+    ) 
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+    XenIfaceDebugPrint(INFO,"DRV: XenIface WMI Initialisation\n");
+   
+    
+
+
+    IoWMISuggestInstanceName(FdoData->UnderlyingPDO, NULL, FALSE, 
+                                &FdoData->SuggestedInstanceName);
+    InitializeListHead(&FdoData->SessionHead);
+    FdoData->Sessions = 0;
+    ExInitializeFastMutex(&FdoData->SessionLock);
+    
+    status = IoWMIRegistrationControl(FdoData->Self, WMIREG_ACTION_REGISTER);
+    FdoData->WmiReady = 1;
+    return status;
+}
+
+NTSTATUS
+WmiFinalise(       
+    PFDO_DATA FdoData
+    ) 
+{
+    NTSTATUS status = STATUS_SUCCESS;
+    if (FdoData->WmiReady) { 
+        XenIfaceDebugPrint(INFO,"DRV: XenIface WMI Finalisation\n");
+        XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+        SessionsRemoveAll(FdoData);
+
+        status =IoWMIRegistrationControl(FdoData->Self, WMIREG_ACTION_DEREGISTER);
+        FdoData->WmiReady = 0;
+    }
+    return status;
+}
+
+NTSTATUS
+WmiChangeSingleInstance(
+    PDEVICE_OBJECT DeviceObject,
+    PIO_STACK_LOCATION stack
+   )
+{
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(stack);
+    XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+WmiChangeSingleItem(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIO_STACK_LOCATION stack
+   )
+{
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(stack);
+    XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+WmiDisableCollection(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIO_STACK_LOCATION stack
+   )
+{
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(stack);
+    XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+WmiDisableEvents(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIO_STACK_LOCATION stack
+   )
+{
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(stack);
+    XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+WmiEnableCollection(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIO_STACK_LOCATION stack
+   )
+{
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(stack);
+    XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+WmiEnableEvents(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIO_STACK_LOCATION stack
+   )
+{
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(stack);
+    XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+    return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS NodeTooSmall(UCHAR *Buffer,
+                    ULONG BufferSize,
+                    ULONG Needed,
+                    ULONG_PTR *byteswritten) {
+    WNODE_TOO_SMALL *node;
+    ULONG RequiredSize;
+    if (!AccessWmiBuffer(Buffer, FALSE, &RequiredSize, BufferSize,
+                            WMI_BUFFER, sizeof(WNODE_TOO_SMALL), &node,
+                            WMI_DONE))
+    {
+        *byteswritten = RequiredSize;
+        return STATUS_BUFFER_TOO_SMALL;
+    }
+    node->WnodeHeader.BufferSize=sizeof(WNODE_TOO_SMALL);
+    KeQuerySystemTime(&node->WnodeHeader.TimeStamp);
+    node->WnodeHeader.Flags = WNODE_FLAG_TOO_SMALL;
+    node->SizeNeeded = Needed;
+    *byteswritten = sizeof(WNODE_TOO_SMALL);
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+SessionExecuteRemoveValue(UCHAR *InBuffer,
+                            ULONG InBufferSize,
+                            UCHAR *OutBuffer,
+                            ULONG OutBufferSize,
+                            FDO_DATA* fdoData,
+                            UNICODE_STRING *instance,
+                            OUT ULONG_PTR *byteswritten) {
+    ULONG RequiredSize;
+    NTSTATUS status;
+    UCHAR* upathname;
+    UTF8_STRING *pathname;
+    XenStoreSession *session;
+    char *tmpbuffer;
+
+    *byteswritten=0;
+    if (!AccessWmiBuffer(InBuffer, TRUE, &RequiredSize, InBufferSize,
+                            WMI_STRING, &upathname,
+                            WMI_DONE))
+        return STATUS_INVALID_DEVICE_REQUEST;
+    if (!fdoData->InterfacesAcquired) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    status = GetCountedUTF8String(&pathname, upathname);
+    if (!NT_SUCCESS(status)) 
+        return status;
+
+    status = STATUS_INSUFFICIENT_RESOURCES;
+    tmpbuffer = ExAllocatePoolWithTag(NonPagedPool, pathname->Length+1, 'XenP');
+    if (!tmpbuffer) {
+        goto fail1;
+    }
+    RtlZeroMemory(tmpbuffer, pathname->Length+1);
+    RtlCopyBytes(tmpbuffer,pathname->Buffer, pathname->Length);
+    
+    status = STATUS_WMI_INSTANCE_NOT_FOUND;
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        goto fail2;
+    }
+    status = STORE(Remove, fdoData->StoreInterface, session->transaction, NULL, tmpbuffer);
+    UnlockSessions(fdoData);
+
+fail2:
+    ExFreePool(tmpbuffer);
+
+fail1:
+    FreeUTF8String(pathname);
+    return status;
+
+}
+
+NTSTATUS
+SessionExecuteRemoveWatch(UCHAR *InBuffer,
+                            ULONG InBufferSize,
+                            UCHAR *OutBuffer,
+                            ULONG OutBufferSize,
+                            FDO_DATA* fdoData,
+                            UNICODE_STRING *instance,
+                            OUT ULONG_PTR *byteswritten) {
+    ULONG RequiredSize;
+    UCHAR* upathname;
+    XenStoreWatch* watch;
+    UNICODE_STRING unicpath_notbacked;
+    XenStoreSession *session;
+
+    if (!AccessWmiBuffer(InBuffer, TRUE, &RequiredSize, InBufferSize,
+                            WMI_STRING, &upathname,
+                            WMI_DONE))
+        return STATUS_INVALID_DEVICE_REQUEST;
+
+
+    GetCountedUnicodeString(&unicpath_notbacked, upathname);
+
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        return STATUS_WMI_INSTANCE_NOT_FOUND;
+    }
+
+
+    XenIfaceDebugPrint(TRACE, "Find Watch\n"); 
+
+    watch = SessionFindWatchLocked(session, &unicpath_notbacked);
+
+    if (watch) {
+
+        SessionRemoveWatchLocked(session, watch);
+    }
+    else {
+        XenIfaceDebugPrint(WARNING, "No Watch\n"); 
+    }
+    ExReleaseFastMutex(&session->WatchMapLock);
+    UnlockSessions(fdoData);
+
+    *byteswritten=0;
+
+
+    return STATUS_SUCCESS;
+
+}
+
+
+NTSTATUS
+SessionExecuteSetWatch(UCHAR *InBuffer,
+                            ULONG InBufferSize,
+                            UCHAR *OutBuffer,
+                            ULONG OutBufferSize,
+                            FDO_DATA* fdoData,
+                            UNICODE_STRING *instance,
+                            OUT ULONG_PTR *byteswritten) {
+    ULONG RequiredSize;
+    NTSTATUS status;
+    UCHAR* upathname;
+    XenStoreWatch* watch;
+    XenStoreSession *session;
+    UNICODE_STRING unicpath_notbacked;
+    UNICODE_STRING unicpath_backed;
+    if (!AccessWmiBuffer(InBuffer, TRUE, &RequiredSize, InBufferSize,
+                            WMI_STRING, &upathname,
+                            WMI_DONE))
+        return STATUS_INVALID_DEVICE_REQUEST;
+
+
+    GetCountedUnicodeString(&unicpath_notbacked, upathname);
+    status = CloneUnicodeString(&unicpath_backed, &unicpath_notbacked);
+    if (!NT_SUCCESS(status)) return status;
+
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        FreeUnicodeStringBuffer(&unicpath_backed);
+        return STATUS_WMI_INSTANCE_NOT_FOUND;
+    }
+
+    status = SessionAddWatchLocked(session, fdoData, &unicpath_backed, &watch);
+
+    UnlockSessions(fdoData);
+    if (!NT_SUCCESS(status)) {
+        FreeUnicodeStringBuffer(&unicpath_backed);
+        return status;
+    }
+    
+
+    *byteswritten=0;
+
+
+    return STATUS_SUCCESS;
+
+}
+NTSTATUS
+SessionExecuteEndSession(UCHAR *InBuffer,
+                            ULONG InBufferSize,
+                            UCHAR *OutBuffer,
+                            ULONG OutBufferSize,
+                            FDO_DATA* fdoData,
+                            UNICODE_STRING *instance,
+                            OUT ULONG_PTR *byteswritten) {
+    XenStoreSession *session;
+    XenIfaceDebugPrint(TRACE, "ExecuteEndSession\n"); 
+    *byteswritten = 0;
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        return STATUS_WMI_INSTANCE_NOT_FOUND;
+    }
+
+    RemoveSessionLocked(fdoData, session);
+    UnlockSessions(fdoData);
+    return STATUS_SUCCESS;
+}
+NTSTATUS
+SessionExecuteSetValue(UCHAR *InBuffer,
+                            ULONG InBufferSize,
+                            UCHAR *OutBuffer,
+                            ULONG OutBufferSize,
+                            FDO_DATA* fdoData,
+                            UNICODE_STRING *instance,
+                            OUT ULONG_PTR *byteswritten) {
+    ULONG RequiredSize;
+    NTSTATUS status;
+    UCHAR* upathname;
+    UCHAR* uvalue;
+    UTF8_STRING* pathname;
+    UTF8_STRING* value;
+    XenStoreSession *session;
+    char *tmppath;
+    char* tmpvalue;
+
+    XenIfaceDebugPrint(TRACE, " Try to write\n"); 
+    if (!AccessWmiBuffer(InBuffer, TRUE, &RequiredSize, InBufferSize,
+                            WMI_STRING, &upathname,
+                            WMI_STRING, &uvalue,
+                            WMI_DONE))
+        return STATUS_INVALID_DEVICE_REQUEST;
+    if (!fdoData->InterfacesAcquired) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+    status = GetCountedUTF8String(&pathname, upathname);
+    if (!NT_SUCCESS(status)) 
+        return status;
+
+       status = STATUS_INSUFFICIENT_RESOURCES;
+    tmppath = ExAllocatePoolWithTag(NonPagedPool, pathname->Length+1, 'XenP');
+    if (!tmppath) {
+        goto fail1;
+    }
+    RtlZeroMemory(tmppath, pathname->Length+1);
+    RtlCopyBytes(tmppath,pathname->Buffer, pathname->Length);
+    status = GetCountedUTF8String(&value, uvalue);
+    if (!NT_SUCCESS(status)){ 
+        goto fail2;
+    }
+    status = STATUS_INSUFFICIENT_RESOURCES;
+    tmpvalue = ExAllocatePoolWithTag(NonPagedPool,value->Length+1,'XenP');
+    if (!tmpvalue) {
+        goto fail3;
+    }
+    RtlZeroMemory(tmpvalue, value->Length+1);
+    RtlCopyBytes(tmpvalue,value->Buffer, value->Length);
+       
+    status = STATUS_WMI_INSTANCE_NOT_FOUND;
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        goto fail4;
+    }
+    status = STORE(Write, fdoData->StoreInterface, session->transaction, NULL, tmppath, tmpvalue);
+    XenIfaceDebugPrint(TRACE, " Write %s to %s (%p)\n", tmpvalue, tmppath, status); 
+    UnlockSessions(fdoData);
+
+fail4:
+    ExFreePool(tmpvalue);
+
+fail3:
+    FreeUTF8String(value);
+
+fail2:
+    ExFreePool(tmppath);
+
+fail1:
+    FreeUTF8String(pathname);
+  
+    *byteswritten = 0;
+    return status;
+    
+}
+NTSTATUS
+SessionExecuteGetFirstChild(UCHAR *InBuffer,
+                            ULONG InBufferSize,
+                            UCHAR *OutBuffer,
+                            ULONG OutBufferSize,
+                            FDO_DATA* fdoData,
+                            UNICODE_STRING *instance,
+                            OUT ULONG_PTR *byteswritten) {
+    ULONG RequiredSize;
+    UCHAR *uloc;
+    NTSTATUS status;
+    UTF8_STRING* path;
+    PCHAR listresults;
+    size_t stringarraysize;
+    UCHAR *valuepos;
+    XenStoreSession *session;
+    char *tmppath;
+    if (!AccessWmiBuffer(InBuffer, TRUE, &RequiredSize, InBufferSize,
+                            WMI_STRING, &uloc, 
+                            WMI_DONE)){
+        return  STATUS_INVALID_DEVICE_REQUEST;
+    }
+    if (!fdoData->InterfacesAcquired) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+        
+    status = GetCountedUTF8String(&path, uloc);
+                
+    if (!NT_SUCCESS(status)) {
+        return status;
+    }
+
+    status = STATUS_INSUFFICIENT_RESOURCES;
+    tmppath = ExAllocatePoolWithTag(NonPagedPool,path->Length+1, 'XenP');
+    if (!tmppath) {
+        goto fail1;
+    }
+    RtlZeroMemory(tmppath, path->Length+1);
+    RtlCopyBytes(tmppath,path->Buffer, path->Length);
+
+    status = STATUS_WMI_INSTANCE_NOT_FOUND;
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        goto fail2;
+    }
+    status = STORE(Directory,fdoData->StoreInterface, session->transaction, NULL, tmppath, &listresults);
+    UnlockSessions(fdoData);
+                        
+    if (!NT_SUCCESS(status)) {
+        goto fail2;
+    }
+
+    stringarraysize = 0;
+    if ((listresults != NULL ) && (listresults[0]!=0)) {
+        stringarraysize+=CountBytesUtf16FromUtf8String(path);
+        if ((path->Length!=1)||(path->Buffer[0]!='/')) {
+            // If the path isn't '/', we need to insert a
+            // '/' between pathname and nodename;
+            stringarraysize+=sizeof(WCHAR);
+        }
+        stringarraysize+=GetCountedUtf8Size(listresults);
+    }
+    else {
+        stringarraysize+=GetCountedUtf8Size("");
+    }
+    
+    status = STATUS_BUFFER_TOO_SMALL;
+    if (!AccessWmiBuffer(InBuffer, FALSE, &RequiredSize, OutBufferSize,
+                            WMI_STRING, stringarraysize, &valuepos,
+                            WMI_DONE)){
+        goto fail3;
+    }
+    
+    status = STATUS_SUCCESS;
+    if ((listresults != NULL) && (listresults[0] != 0)) {
+        PSTR fullpath;
+        if ((path->Length==1) && (path->Buffer[0]=='/')) {
+            fullpath = Xmasprintf("/%s", listresults);
+        }
+        else {
+            fullpath = Xmasprintf("%s/%s", 
+                                    path->Buffer, listresults); 
+        }
+
+        if (fullpath == NULL) {
+            status = STATUS_NO_MEMORY;
+            goto fail4;
+        }
+
+        WriteCountedUTF8String(fullpath, valuepos);
+        valuepos+=GetCountedUtf8Size(fullpath);
+        ExFreePool(fullpath);
+    }
+    else {
+        WriteCountedUTF8String("", valuepos);
+    }
+
+fail4:
+fail3:
+    STORE(Free, fdoData->StoreInterface, listresults);
+
+    *byteswritten = RequiredSize;
+
+fail2:
+    ExFreePool(tmppath);
+
+fail1:
+    FreeUTF8String(path);
+
+    return status;
+
+}
+
+NTSTATUS
+SessionExecuteGetNextSibling(UCHAR *InBuffer,
+                            ULONG InBufferSize,
+                            UCHAR *OutBuffer,
+                            ULONG OutBufferSize,
+                            FDO_DATA* fdoData,
+                            UNICODE_STRING *instance,
+                            OUT ULONG_PTR *byteswritten) {
+    ULONG RequiredSize;
+    UCHAR *uloc;
+    NTSTATUS status;
+    UTF8_STRING* path;
+    ANSI_STRING checkleaf;
+    PCHAR listresults;
+    PCHAR nextresult;
+    size_t stringarraysize;
+    UCHAR *valuepos;
+    XenStoreSession *session;
+    char *tmppath;
+    char *tmpleaf;
+    int leafoffset;
+    char *attemptstring;
+    if (!AccessWmiBuffer(InBuffer, TRUE, &RequiredSize, InBufferSize,
+                            WMI_STRING, &uloc, 
+                            WMI_DONE)){
+        return  STATUS_INVALID_DEVICE_REQUEST;
+    }
+    if (!fdoData->InterfacesAcquired) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+        
+    status = GetCountedUTF8String(&path, uloc);
+                
+    if (!NT_SUCCESS(status)) {
+        return status;
+    }
+
+    status = STATUS_INSUFFICIENT_RESOURCES;
+    tmppath = ExAllocatePoolWithTag(NonPagedPool,path->Length+1,'XenP');
+
+    if (!tmppath) {
+        goto fail1;
+    }
+    RtlZeroMemory(tmppath, path->Length+1);
+    tmpleaf = ExAllocatePoolWithTag(NonPagedPool,path->Length+1,'XenP');
+    if (!tmpleaf) {
+        goto fail2;
+    }
+    RtlZeroMemory(tmpleaf, path->Length+1);
+
+    status = STATUS_WMI_INSTANCE_NOT_FOUND;
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        goto fail3;
+    }
+    
+    leafoffset = 0;
+    if (path->Length>1) {
+        leafoffset = path->Length;
+        while ((leafoffset!=0) && (path->Buffer[leafoffset] != '/'))
+            leafoffset--;
+    }
+    if (leafoffset != 0){
+        RtlCopyBytes(tmppath,path->Buffer, leafoffset);
+        RtlCopyBytes(tmpleaf, path->Buffer+leafoffset+1, path->Length-leafoffset-1);
+    }
+    else {
+
+        if (path->Buffer[0] == '/') {
+            if (path->Length>1)
+                RtlCopyBytes(tmpleaf, path->Buffer+1, path->Length-1);
+            tmppath[0]='/';
+        }
+        else {
+            RtlCopyBytes(tmpleaf, path->Buffer, path->Length);
+        }
+
+    }
+
+    status = STORE(Directory,fdoData->StoreInterface, session->transaction, NULL, tmppath, &listresults);
+    UnlockSessions(fdoData);
+                        
+    if (!NT_SUCCESS(status)) {
+        goto fail3;
+    }
+
+    stringarraysize = 0;
+    RtlInitAnsiString(&checkleaf, tmpleaf);
+    
+    nextresult = listresults;
+
+    while (*nextresult != 0) {
+        ANSI_STRING checkstr;
+        RtlInitAnsiString(&checkstr, nextresult);
+        if (RtlEqualString(&checkstr, &checkleaf, TRUE)) {
+            break;
+        }
+        while (*nextresult!=0) {
+            nextresult++;
+        }
+        nextresult++;
+    }
+
+
+    attemptstring = NULL;
+    while (*nextresult !=0) {
+        nextresult++;
+    }
+    nextresult++;
+    if (*nextresult!=0) {
+        attemptstring = nextresult;
+    }
+
+    if (attemptstring!=NULL) {
+        stringarraysize+=CountBytesUtf16FromUtf8(tmppath); //sizeof(WCHAR)*leafoffset;
+        if ((path->Length!=1)||(path->Buffer[0]!='/')) {
+            // If the path isn't '/', we need to insert a
+            // '/' between pathname and nodename;
+            stringarraysize+=sizeof(WCHAR);
+        }
+        stringarraysize+=GetCountedUtf8Size(attemptstring);
+    }
+    else {
+        stringarraysize+=GetCountedUtf8Size("");
+    }
+    
+    status = STATUS_BUFFER_TOO_SMALL;
+    if (!AccessWmiBuffer(InBuffer, FALSE, &RequiredSize, OutBufferSize,
+                            WMI_STRING, stringarraysize, &valuepos,
+                            WMI_DONE)){
+        goto fail4;
+    }
+    
+    status = STATUS_SUCCESS;
+    if (attemptstring != NULL) {
+        PSTR fullpath;
+        if ((leafoffset==1) && (path->Buffer[0]=='/')) {
+            fullpath = Xmasprintf("/%s", attemptstring);
+        }
+        else {
+            fullpath = Xmasprintf("%s/%s", 
+                                    tmppath, attemptstring); 
+        }
+
+        if (fullpath == NULL) {
+            status = STATUS_NO_MEMORY;
+            goto fail5;
+        }
+
+        WriteCountedUTF8String(fullpath, valuepos);
+        ExFreePool(fullpath);
+    }
+    else {
+        WriteCountedUTF8String("", valuepos);
+        valuepos+=GetCountedUtf8Size("");
+    }
+
+
+fail5:
+fail4:
+    STORE(Free, fdoData->StoreInterface, listresults);
+
+fail3:
+    ExFreePool(tmpleaf);
+
+fail2:
+       ExFreePool(tmppath);
+
+fail1:
+    FreeUTF8String(path);
+    *byteswritten = RequiredSize;
+    return status;
+
+}
+
+NTSTATUS
+SessionExecuteGetChildren(UCHAR *InBuffer,
+                            ULONG InBufferSize,
+                            UCHAR *OutBuffer,
+                            ULONG OutBufferSize,
+                            FDO_DATA* fdoData,
+                            UNICODE_STRING *instance,
+                            OUT ULONG_PTR *byteswritten) {
+    int i;
+    ULONG RequiredSize;
+    UCHAR *uloc;
+    NTSTATUS status;
+    UTF8_STRING* path;
+    PCHAR listresults;
+    PCHAR nextresults;
+    ULONG *noofnodes;
+    size_t stringarraysize;
+    UCHAR *valuepos;
+    XenStoreSession *session;
+    char *tmppath;
+    if (!AccessWmiBuffer(InBuffer, TRUE, &RequiredSize, InBufferSize,
+                            WMI_STRING, &uloc, 
+                            WMI_DONE)){
+        return  STATUS_INVALID_DEVICE_REQUEST;
+    }
+    if (!fdoData->InterfacesAcquired) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+        
+    status = GetCountedUTF8String(&path, uloc);
+                
+    if (!NT_SUCCESS(status)) {
+        return status;
+    }
+
+    status = STATUS_INSUFFICIENT_RESOURCES;
+    tmppath = ExAllocatePoolWithTag(NonPagedPool,path->Length+1,'XenP');
+    if (!tmppath) {
+        goto fail1;
+    }
+    RtlZeroMemory(tmppath, path->Length+1);
+    RtlCopyBytes(tmppath,path->Buffer, path->Length);
+
+    status = STATUS_WMI_INSTANCE_NOT_FOUND;
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        goto fail2;
+    }
+    status = STORE(Directory,fdoData->StoreInterface,session->transaction,NULL, tmppath, &listresults);
+    UnlockSessions(fdoData);
+                        
+    if (!NT_SUCCESS(status)) {
+        goto fail2;
+    }
+
+    stringarraysize = 0;
+
+    nextresults=listresults;
+    while (*nextresults != 0) {
+        stringarraysize+=sizeof(WCHAR)*path->Length;
+        if ((path->Length!=1)||(path->Buffer[0]!='/')) {
+            // If the path isn't '/', we need to insert a
+            // '/' between pathname and nodename;
+            stringarraysize+=sizeof(WCHAR);
+        }
+        stringarraysize+=GetCountedUtf8Size(nextresults);
+        for (;*nextresults!=0;nextresults++);
+        nextresults++;
+    } 
+                
+    status = STATUS_BUFFER_TOO_SMALL;
+    if (!AccessWmiBuffer(InBuffer, FALSE, &RequiredSize, OutBufferSize,
+                            WMI_UINT32, &noofnodes,
+                            WMI_STRING, stringarraysize, &valuepos,
+                            WMI_DONE)){
+        goto fail3;
+    }
+
+    status = STATUS_SUCCESS;
+    nextresults = listresults;
+    i=0;
+    while(*nextresults!=0) {
+        PSTR fullpath;
+        if ((path->Length==1) && (path->Buffer[0]=='/')) {
+            fullpath = Xmasprintf("/%s", nextresults);
+        }
+        else {
+            fullpath = Xmasprintf("%s/%s", 
+                                    path->Buffer, nextresults); 
+        }
+
+        if (fullpath == NULL) {
+            status = STATUS_NO_MEMORY;
+            goto fail4;
+        }
+
+        WriteCountedUTF8String(fullpath, valuepos);
+        valuepos+=GetCountedUtf8Size(fullpath);
+        ExFreePool(fullpath);
+        for (;*nextresults!=0;nextresults++);
+        nextresults++;
+        i++;
+
+
+    }
+    *noofnodes = i;
+
+fail4:
+fail3:
+    STORE(Free, fdoData->StoreInterface, listresults);
+
+fail2:
+    ExFreePool(tmppath);
+
+fail1:
+    FreeUTF8String(path);
+    *byteswritten = RequiredSize;
+    return status;
+}
+
+
+NTSTATUS
+SessionExecuteLog(UCHAR *InBuffer,
+                        ULONG InBufferSize,
+                        UCHAR *OutBuffer,
+                        ULONG OutBufferSize,
+                        FDO_DATA* fdoData,
+                        UNICODE_STRING *instance,
+                        OUT ULONG_PTR *byteswritten) {
+
+    ULONG RequiredSize;
+    UCHAR *uloc;
+    NTSTATUS status;
+    ANSI_STRING message;
+    if (!AccessWmiBuffer(InBuffer, TRUE, &RequiredSize, InBufferSize,
+                                            WMI_STRING, &uloc, 
+                                            WMI_DONE))
+        return STATUS_INVALID_DEVICE_REQUEST;
+
+    status = GetCountedAnsiString(&message, uloc);
+
+    if (!NT_SUCCESS(status)) 
+        return status;
+
+    XenIfaceDebugPrint(INFO,"USER: %s\n", message.Buffer);
+
+    RtlFreeAnsiString(&message);
+    *byteswritten = 0;
+    return STATUS_SUCCESS;
+
+}
+
+NTSTATUS
+SessionExecuteStartTransaction(UCHAR *InBuffer,
+                        ULONG InBufferSize,
+                        UCHAR *OutBuffer,
+                        ULONG OutBufferSize,
+                        FDO_DATA* fdoData,
+                        UNICODE_STRING *instance,
+                        OUT ULONG_PTR *byteswritten) {
+
+    NTSTATUS status = STATUS_SUCCESS;
+    XenStoreSession *session;
+    
+    if (!fdoData->InterfacesAcquired) {
+        status= STATUS_INSUFFICIENT_RESOURCES;
+        goto failnotinitialised;
+    }
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        status= STATUS_WMI_INSTANCE_NOT_FOUND;
+        goto failsessionnotfound;
+    }
+
+    if (session->transaction!=NULL) {
+        status = STATUS_REQUEST_OUT_OF_SEQUENCE;
+        goto failtransactionactive;
+    }
+
+    STORE(TransactionStart, fdoData->StoreInterface, &session->transaction);
+    
+
+failtransactionactive:
+    UnlockSessions(fdoData);
+failsessionnotfound:
+failnotinitialised:
+
+    *byteswritten = 0;
+    return status;
+
+}
+NTSTATUS
+SessionExecuteCommitTransaction(UCHAR *InBuffer,
+                        ULONG InBufferSize,
+                        UCHAR *OutBuffer,
+                        ULONG OutBufferSize,
+                        FDO_DATA* fdoData,
+                        UNICODE_STRING *instance,
+                        OUT ULONG_PTR *byteswritten) {
+
+    NTSTATUS status = STATUS_SUCCESS;
+    XenStoreSession *session;
+    
+    if (!fdoData->InterfacesAcquired) {
+        status= STATUS_INSUFFICIENT_RESOURCES;
+        goto failnotinitialised;
+    }
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        status= STATUS_WMI_INSTANCE_NOT_FOUND;
+        goto failsessionnotfound;
+    }
+
+    if (session->transaction==NULL) {
+        status = STATUS_REQUEST_OUT_OF_SEQUENCE;
+        goto failtransactionnotactive;
+    }
+
+    status = STORE(TransactionEnd,fdoData->StoreInterface, session->transaction, TRUE);
+    
+    session->transaction = NULL;
+
+failtransactionnotactive:
+    UnlockSessions(fdoData);
+failsessionnotfound:
+failnotinitialised:
+
+    *byteswritten = 0;
+    return status;
+
+}
+NTSTATUS
+SessionExecuteAbortTransaction(UCHAR *InBuffer,
+                        ULONG InBufferSize,
+                        UCHAR *OutBuffer,
+                        ULONG OutBufferSize,
+                        FDO_DATA* fdoData,
+                        UNICODE_STRING *instance,
+                        OUT ULONG_PTR *byteswritten) {
+
+    NTSTATUS status = STATUS_SUCCESS;
+    XenStoreSession *session;
+    
+    if (!fdoData->InterfacesAcquired) {
+        status= STATUS_INSUFFICIENT_RESOURCES;
+        goto failnotinitialised;
+    }
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        status= STATUS_WMI_INSTANCE_NOT_FOUND;
+        goto failsessionnotfound;
+    }
+
+    if (session->transaction==NULL) {
+        status = STATUS_REQUEST_OUT_OF_SEQUENCE;
+        goto failtransactionnotactive;
+    }
+
+    status = STORE(TransactionEnd, fdoData->StoreInterface, session->transaction, FALSE);
+    
+    session->transaction = NULL;
+
+failtransactionnotactive:
+    UnlockSessions(fdoData);
+failsessionnotfound:
+failnotinitialised:
+
+    *byteswritten = 0;
+    return status;
+
+}
+
+NTSTATUS
+SessionExecuteGetValue(UCHAR *InBuffer,
+                        ULONG InBufferSize,
+                        UCHAR *OutBuffer,
+                        ULONG OutBufferSize,
+                        FDO_DATA* fdoData,
+                        UNICODE_STRING *instance,
+                        OUT ULONG_PTR *byteswritten) {
+    NTSTATUS status;
+    UTF8_STRING* path;
+    UCHAR *uloc;
+    char *value;
+    UCHAR *valuepos;
+    char *tmppath;
+    ULONG RequiredSize;
+    XenStoreSession *session;
+
+    *byteswritten = 0;
+    if (!AccessWmiBuffer(InBuffer, TRUE, &RequiredSize, InBufferSize,
+                                            WMI_STRING, &uloc, 
+                                            WMI_DONE))
+        return STATUS_INVALID_DEVICE_REQUEST;
+    if (!fdoData->InterfacesAcquired) {
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+        
+    status = GetCountedUTF8String(&path, uloc);
+                
+    if (!NT_SUCCESS(status)) 
+        return status;;
+    
+    status = STATUS_INSUFFICIENT_RESOURCES;
+    tmppath = ExAllocatePoolWithTag(NonPagedPool,path->Length+1,'XenP');
+    if (!tmppath) {
+        goto fail1;
+    }
+    RtlZeroMemory(tmppath, path->Length+1);
+    RtlCopyBytes(tmppath,path->Buffer, path->Length);
+    
+
+    status = STATUS_WMI_INSTANCE_NOT_FOUND;
+    if ((session = FindSessionByInstanceAndLock(fdoData, instance)) ==
+            NULL){
+        goto fail2;
+    }
+    status = STORE(Read, fdoData->StoreInterface, session->transaction, NULL, tmppath, &value);
+    UnlockSessions(fdoData);
+                
+    if (!NT_SUCCESS(status)) 
+        goto fail2;
+   
+    status = STATUS_BUFFER_TOO_SMALL;
+    if (!AccessWmiBuffer(OutBuffer, FALSE, &RequiredSize, OutBufferSize,
+                            WMI_STRING, GetCountedUtf8Size(value), &valuepos,
+                            WMI_DONE)) {
+        goto fail3;
+    }
+    status = STATUS_SUCCESS;
+    WriteCountedUTF8String(value, valuepos);
+
+fail3:
+    STORE(Free, fdoData->StoreInterface, value);
+    *byteswritten = RequiredSize;
+
+fail2:
+    ExFreePool(tmppath);
+
+fail1:
+    FreeUTF8String(path);
+    return status;
+}
+NTSTATUS
+BaseExecuteAddSession(UCHAR *InBuffer,
+                        ULONG InBufferSize,
+                        UCHAR *OutBuffer,
+                        ULONG OutBufferSize,
+                        FDO_DATA* fdoData,
+                        OUT ULONG_PTR *byteswritten) {
+    ULONG RequiredSize;
+    UNICODE_STRING ustring;
+    ULONG *id;
+    UCHAR* stringid;
+    NTSTATUS status;
+    *byteswritten = 0;
+    if (!AccessWmiBuffer(InBuffer, TRUE, &RequiredSize, InBufferSize,
+                            WMI_STRING, &stringid, 
+                            WMI_DONE)){
+        return STATUS_INVALID_DEVICE_REQUEST;
+    }
+    if (!AccessWmiBuffer(OutBuffer, FALSE, &RequiredSize, OutBufferSize,
+                            WMI_UINT32, &id,
+                            WMI_DONE)) {
+        *byteswritten = RequiredSize;
+        return STATUS_BUFFER_TOO_SMALL;
+    }
+    
+    AllocUnicodeStringBuffer(&ustring, *(USHORT*)(stringid));
+    if (ustring.Buffer == NULL)
+        return STATUS_INSUFFICIENT_RESOURCES;
+    status = RtlUnicodeStringCbCopyStringN(&ustring,
+                                            (LPCWSTR)(stringid+sizeof(USHORT)), 
+                                            *(USHORT*)(stringid));
+    if (!NT_SUCCESS(status)) {
+        FreeUnicodeStringBuffer(&ustring);
+        return status;
+    }
+    status = CreateNewSession(fdoData, &ustring, id);
+    if (!NT_SUCCESS(status)) {
+        FreeUnicodeStringBuffer(&ustring);
+        return status;
+    }
+
+    *byteswritten = RequiredSize;
+    return STATUS_SUCCESS;
+
+}
+
+
+NTSTATUS 
+SessionExecuteMethod(UCHAR *Buffer,
+                    ULONG BufferSize,
+                    FDO_DATA* fdoData,
+                    OUT ULONG_PTR *byteswritten) {
+    ULONG RequiredSize;
+    WNODE_METHOD_ITEM *Method;
+    UCHAR *InBuffer;
+    NTSTATUS status;
+    UNICODE_STRING instance;
+    UCHAR *InstStr;
+    XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+    if (!AccessWmiBuffer(Buffer, TRUE, &RequiredSize, BufferSize,
+                            WMI_BUFFER, sizeof(WNODE_METHOD_ITEM),
+                                &Method,
+                            WMI_DONE))
+    {
+        return STATUS_INVALID_DEVICE_REQUEST;
+    }
+    if (!AccessWmiBuffer(Buffer, TRUE, &RequiredSize, BufferSize,
+                            WMI_BUFFER, sizeof(WNODE_METHOD_ITEM),
+                                &Method,
+                            WMI_STRINGOFFSET, Method->OffsetInstanceName,
+                                &InstStr,
+                            WMI_DONE))
+    {
+        return STATUS_INVALID_DEVICE_REQUEST;
+    }
+
+    InBuffer = Buffer + Method->DataBlockOffset; 
+
+    GetCountedUnicodeString(&instance, InstStr);
+
+    
+    XenIfaceDebugPrint(TRACE,"Method Id %d\n", Method->MethodId);
+    switch (Method->MethodId) {
+        case GetValue: 
+            status = SessionExecuteGetValue(InBuffer, Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case SetValue: 
+            status = SessionExecuteSetValue(InBuffer, Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case GetChildren: 
+            status = SessionExecuteGetChildren(InBuffer, Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case SetWatch: 
+            status = SessionExecuteSetWatch(InBuffer, Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case EndSession:
+            status = SessionExecuteEndSession(InBuffer, Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case RemoveWatch: 
+            status = SessionExecuteRemoveWatch(InBuffer, Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case RemoveValue: 
+            status = SessionExecuteRemoveValue(InBuffer, Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case Log:
+            status = SessionExecuteLog(InBuffer,  Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case StartTransaction: 
+            status = SessionExecuteStartTransaction(InBuffer,  Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case CommitTransaction:
+            status = SessionExecuteCommitTransaction(InBuffer,  Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case AbortTransaction:
+            status = SessionExecuteAbortTransaction(InBuffer,  Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case GetFirstChild:
+            status = SessionExecuteGetFirstChild(InBuffer,  Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+        case GetNextSibling:
+            status = SessionExecuteGetNextSibling(InBuffer,  Method->SizeDataBlock,  
+                                              Buffer+Method->DataBlockOffset, 
+                                              BufferSize-Method->DataBlockOffset, 
+                                              fdoData,
+                                              &instance, 
+                                              byteswritten);
+            break;
+
+
+        default:
+            XenIfaceDebugPrint(INFO,"DRV: Unknown WMI method %d\n", Method->MethodId);
+            return STATUS_WMI_ITEMID_NOT_FOUND;
+    }
+    Method->SizeDataBlock = (ULONG)*byteswritten;
+    *byteswritten+=Method->DataBlockOffset;
+    if (status == STATUS_BUFFER_TOO_SMALL) {
+        return NodeTooSmall(Buffer, BufferSize, (ULONG)*byteswritten, byteswritten);
+    }
+            
+    Method->WnodeHeader.BufferSize = (ULONG)*byteswritten;
+     return status;
+}
+NTSTATUS 
+BaseExecuteMethod(UCHAR *Buffer,
+                    ULONG BufferSize,
+                    FDO_DATA* fdoData,
+                    OUT ULONG_PTR *byteswritten) {
+    ULONG RequiredSize;
+    WNODE_METHOD_ITEM *Method;
+    UCHAR *InBuffer;
+    NTSTATUS status;
+    if (!AccessWmiBuffer(Buffer, TRUE, &RequiredSize, BufferSize,
+                            WMI_BUFFER, sizeof(WNODE_METHOD_ITEM),
+                                &Method,
+                            WMI_DONE))
+    {
+        return STATUS_INVALID_DEVICE_REQUEST;
+    }
+
+    InBuffer = Buffer + Method->DataBlockOffset; 
+
+    switch (Method->MethodId) {
+        case AddSession: 
+            status = BaseExecuteAddSession(InBuffer, Method->SizeDataBlock,  
+                                             Buffer+Method->DataBlockOffset, 
+                                             BufferSize-Method->DataBlockOffset, 
+                                             fdoData, 
+                                             byteswritten);
+            Method->SizeDataBlock = (ULONG)*byteswritten;
+            *byteswritten+=Method->DataBlockOffset;
+            Method->WnodeHeader.BufferSize = (ULONG)*byteswritten;
+            return status;
+
+        default:
+            return STATUS_WMI_ITEMID_NOT_FOUND;
+    }
+}
+
+NTSTATUS
+WmiExecuteMethod(
+    IN PFDO_DATA fdoData,
+    IN PIO_STACK_LOCATION stack,
+    OUT ULONG_PTR *byteswritten
+   )
+{
+    if (IsEqualGUID(stack->Parameters.WMI.DataPath, &CitrixXenStoreBase_GUID)) {
+        return BaseExecuteMethod(stack->Parameters.WMI.Buffer,
+                                    stack->Parameters.WMI.BufferSize,  
+                                    fdoData,  byteswritten);
+    }
+    else if (IsEqualGUID(stack->Parameters.WMI.DataPath, &CitrixXenStoreSession_GUID)) {
+        return SessionExecuteMethod(stack->Parameters.WMI.Buffer,
+                                    stack->Parameters.WMI.BufferSize,  
+                                    fdoData,  byteswritten);
+    }
+    
+    else
+        return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+GenerateSessionBlock(UCHAR *Buffer,
+                        ULONG BufferSize,
+                        PFDO_DATA fdoData,
+                        ULONG_PTR *byteswritten) {
+    WNODE_ALL_DATA *node;
+    ULONG RequiredSize;
+    size_t nodesizerequired;
+    size_t namesizerequired;
+    int entries;
+    XenStoreSession *session;
+    OFFSETINSTANCEDATAANDLENGTH* dataoffsets;
+    ULONG* nameoffsets;
+    UCHAR *data;
+    UCHAR *names;
+    
+
+    LockSessions(fdoData);
+
+    //work out how much space we need for each session structure
+    nodesizerequired = 0;
+    namesizerequired = 0;
+    entries = 0;
+    session = (XenStoreSession *)fdoData->SessionHead.Flink;
+    //work out names for each session entry
+    while (session !=  (XenStoreSession *)&fdoData->SessionHead) {
+        ULONG *id;
+        UCHAR *sesbuf;
+        UCHAR *inamebuf;
+
+        AccessWmiBuffer((PUCHAR)nodesizerequired, FALSE, &RequiredSize, 0,
+                        WMI_UINT32, &id,
+                        WMI_STRING, 
+                            GetCountedUnicodeStringSize(&session->stringid), 
+                            &sesbuf,
+                        WMI_DONE);
+        nodesizerequired += RequiredSize;
+        
+        AccessWmiBuffer((PUCHAR)namesizerequired, FALSE, &RequiredSize, 0,
+                        WMI_STRING, 
+                            GetCountedUnicodeStringSize(&session->instancename),
+                            &inamebuf,
+                        WMI_DONE);
+        namesizerequired += RequiredSize;
+        entries++;
+        session = (XenStoreSession *)session->listentry.Flink;
+    }
+    
+    //perform the access check
+    if (!AccessWmiBuffer(Buffer, FALSE, &RequiredSize, BufferSize,
+                            WMI_BUFFER, sizeof(WNODE_ALL_DATA), &node,
+                            WMI_BUFFER, sizeof(OFFSETINSTANCEDATAANDLENGTH)*
+                                            entries, &dataoffsets,
+                            WMI_BUFFER, sizeof(ULONG)*entries, &nameoffsets,
+                            WMI_BUFFER, nodesizerequired, &data,
+                            WMI_BUFFER, namesizerequired, &names,
+                            WMI_DONE)) {
+        UnlockSessions(fdoData);
+        return NodeTooSmall(Buffer, BufferSize, RequiredSize, byteswritten);
+    }
+
+    node->DataBlockOffset = (ULONG)(data - Buffer);
+    node->OffsetInstanceNameOffsets = (ULONG)((UCHAR *)nameoffsets - Buffer);
+    node->WnodeHeader.BufferSize = RequiredSize;
+    KeQuerySystemTime(&node->WnodeHeader.TimeStamp);
+    node->WnodeHeader.Flags = WNODE_FLAG_ALL_DATA;
+    node->InstanceCount = entries;
+    *byteswritten = RequiredSize;
+
+    session = (XenStoreSession *)fdoData->SessionHead.Flink;
+    {
+        int entrynum = 0;
+        UCHAR *datapos = data;
+        UCHAR *namepos = names;
+        //work out names for each session entry
+        while (session !=  (XenStoreSession *)&fdoData->SessionHead){
+            ULONG *id;
+            UCHAR *sesbuf;
+            UCHAR *inamebuf;
+
+            AccessWmiBuffer(datapos, FALSE, &RequiredSize, BufferSize+Buffer-datapos,
+                            WMI_UINT32, &id,
+                            WMI_STRING, 
+                                GetCountedUnicodeStringSize(&session->stringid), 
+                                &sesbuf,
+                            WMI_DONE);
+
+            node->OffsetInstanceDataAndLength[entrynum].OffsetInstanceData = 
+                (ULONG)((UCHAR *)id - Buffer);
+            node->OffsetInstanceDataAndLength[entrynum].LengthInstanceData = 
+                RequiredSize;
+            *id = session->id;
+            WriteCountedUnicodeString(&session->stringid, sesbuf);
+            datapos+=RequiredSize;
+
+            AccessWmiBuffer(namepos, FALSE, &RequiredSize, BufferSize+Buffer-namepos,
+                            WMI_STRING, 
+                                GetCountedUnicodeStringSize(&session->instancename),
+                                &inamebuf,
+                            WMI_DONE);
+
+            nameoffsets[entrynum] = (ULONG)(namepos-Buffer);
+            WriteCountedUnicodeString(&session->instancename, inamebuf);
+            namepos+=RequiredSize;
+
+            namesizerequired += RequiredSize;
+            entrynum++;
+            session = (XenStoreSession *)session->listentry.Flink;
+        }
+
+    }
+
+    UnlockSessions(fdoData);
+
+    return STATUS_SUCCESS;
+
+}
+
+NTSTATUS
+GenerateBaseBlock(  FDO_DATA *fdoData,
+                    UCHAR *Buffer,
+                    ULONG BufferSize,
+                    ULONG_PTR *byteswritten) {
+    WNODE_ALL_DATA *node;
+    ULONG RequiredSize;
+    ULONGLONG *time;
+    if (!AccessWmiBuffer(Buffer, FALSE, &RequiredSize, BufferSize,
+                            WMI_BUFFER, sizeof(WNODE_ALL_DATA), &node,
+                            WMI_UINT64, &time,
+                            WMI_DONE))
+    {
+        return NodeTooSmall(Buffer, BufferSize, RequiredSize, byteswritten);
+    }
+
+    node->DataBlockOffset =(ULONG)( ((UCHAR *)time)-Buffer);
+    node->WnodeHeader.BufferSize = RequiredSize;
+    KeQuerySystemTime(&node->WnodeHeader.TimeStamp);
+    node->WnodeHeader.Flags = WNODE_FLAG_ALL_DATA |
+                                WNODE_FLAG_FIXED_INSTANCE_SIZE |
+                                WNODE_FLAG_PDO_INSTANCE_NAMES;
+    if (fdoData->InterfacesAcquired) {
+        *time = SHARED_INFO(GetTime, fdoData->SharedInfoInterface).QuadPart;
+    }
+    else {
+        *time = 0;
+    }
+    node->InstanceCount = 1;
+    node->FixedInstanceSize = sizeof(ULONGLONG);
+    *byteswritten = RequiredSize;
+    return STATUS_SUCCESS;
+}
+NTSTATUS
+GenerateBaseInstance(
+                    FDO_DATA *fdoData,
+                    UCHAR *Buffer,
+                    ULONG BufferSize,
+                    ULONG_PTR *byteswritten) {
+    WNODE_SINGLE_INSTANCE *node;
+    ULONG RequiredSize;
+    ULONGLONG *time;
+    UCHAR * dbo;
+    if (!AccessWmiBuffer(Buffer, FALSE, &RequiredSize, BufferSize,
+                            WMI_BUFFER, sizeof(WNODE_SINGLE_INSTANCE), &node,
+                            WMI_DONE))
+    {
+        return NodeTooSmall(Buffer, BufferSize, RequiredSize, byteswritten);
+    }
+    if (!AccessWmiBuffer(Buffer, FALSE, &RequiredSize, BufferSize,
+                            WMI_BUFFER, sizeof(WNODE_SINGLE_INSTANCE), &node,
+                            WMI_OFFSET, node->DataBlockOffset, 0 ,&dbo,
+                            WMI_DONE))
+    {
+        return NodeTooSmall(Buffer, BufferSize, RequiredSize, byteswritten);
+    }
+    if (!AccessWmiBuffer(dbo, FALSE, &RequiredSize, BufferSize-node->DataBlockOffset,
+                            WMI_UINT64, &time,
+                            WMI_DONE)){
+        return NodeTooSmall(Buffer, BufferSize, RequiredSize+node->DataBlockOffset,
+                            byteswritten);
+    }
+
+    if (node->InstanceIndex != 0) {
+        return STATUS_WMI_ITEMID_NOT_FOUND;
+    }
+    if (fdoData->InterfacesAcquired) {
+        *time = SHARED_INFO(GetTime, fdoData->SharedInfoInterface).QuadPart;
+    }
+    else {
+        *time = 0;
+    }
+   
+    
+    node->WnodeHeader.BufferSize = node->DataBlockOffset+RequiredSize;
+    node->SizeDataBlock = RequiredSize;
+
+    *byteswritten = node->DataBlockOffset+RequiredSize;
+
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+GenerateSessionInstance(UCHAR *Buffer,
+                    ULONG BufferSize,
+                    FDO_DATA *fdoData,
+                    ULONG_PTR *byteswritten) {
+    WNODE_SINGLE_INSTANCE *node;
+    ULONG RequiredSize;
+    UCHAR *dbo;
+    UCHAR *InstStr;
+    UNICODE_STRING instance;
+    ULONG* id;
+    XenStoreSession *session;
+    UCHAR *sesbuf;
+    
+    if (!AccessWmiBuffer(Buffer, TRUE, &RequiredSize, BufferSize,
+                            WMI_BUFFER, sizeof(WNODE_SINGLE_INSTANCE), &node,
+                            WMI_DONE))
+    {
+        return NodeTooSmall(Buffer, BufferSize, RequiredSize, byteswritten);
+    }
+    if (!AccessWmiBuffer(Buffer, TRUE, &RequiredSize, BufferSize,
+                            WMI_BUFFER, sizeof(WNODE_SINGLE_INSTANCE), &node,
+                            WMI_STRINGOFFSET, node->OffsetInstanceName, &InstStr, 
+                            WMI_OFFSET, node->DataBlockOffset, 0, &dbo,
+                            WMI_DONE))
+    {
+        return NodeTooSmall(Buffer, BufferSize, RequiredSize, byteswritten);
+    }
+
+    GetCountedUnicodeString(&instance, InstStr);
+    LockSessions(fdoData);
+    if ((session = FindSessionByInstanceLocked(fdoData, &instance))==NULL){
+        UnlockSessions(fdoData);
+        return STATUS_WMI_INSTANCE_NOT_FOUND;
+    }
+    
+    if (!AccessWmiBuffer(dbo, FALSE, &RequiredSize, BufferSize-node->DataBlockOffset,
+                            WMI_UINT32, &id,
+                            WMI_STRING, 
+                                GetCountedUnicodeStringSize(&session->stringid),
+                                &sesbuf,
+                            WMI_DONE)) {
+        UnlockSessions(fdoData);
+        return NodeTooSmall(Buffer, BufferSize, RequiredSize+node->DataBlockOffset,
+                            byteswritten);
+    }
+
+    *id = session->id;
+    WriteCountedUnicodeString(&session->stringid, sesbuf);
+    UnlockSessions(fdoData);
+    node->SizeDataBlock = RequiredSize;
+    node->WnodeHeader.BufferSize = node->DataBlockOffset + RequiredSize;
+    *byteswritten = node->DataBlockOffset + RequiredSize;
+
+    
+
+
+    return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+WmiQueryAllData(
+    IN PFDO_DATA fdoData,
+    IN PIO_STACK_LOCATION stack,
+    OUT ULONG_PTR *byteswritten
+   )
+{
+  
+    if (IsEqualGUID(stack->Parameters.WMI.DataPath, 
+                    &CitrixXenStoreBase_GUID)) {
+        return GenerateBaseBlock(   fdoData,
+                                    stack->Parameters.WMI.Buffer, 
+                                    stack->Parameters.WMI.BufferSize,
+                                    byteswritten);
+    }
+    else if (IsEqualGUID(stack->Parameters.WMI.DataPath, 
+                            &CitrixXenStoreSession_GUID)) {
+        return GenerateSessionBlock(stack->Parameters.WMI.Buffer, 
+                                    stack->Parameters.WMI.BufferSize,
+                                    fdoData,
+                                    byteswritten);
+    }
+    else
+        return STATUS_NOT_SUPPORTED;
+
+
+}
+
+NTSTATUS
+WmiQuerySingleInstance(
+    IN PFDO_DATA fdoData,
+    IN PIO_STACK_LOCATION stack,
+    OUT ULONG_PTR *byteswritten
+    )
+{
+    if (IsEqualGUID(stack->Parameters.WMI.DataPath, &CitrixXenStoreBase_GUID)) {
+        return GenerateBaseInstance(fdoData,
+                                    stack->Parameters.WMI.Buffer, 
+                                    stack->Parameters.WMI.BufferSize,
+                                    byteswritten);
+    }
+    else if (IsEqualGUID(stack->Parameters.WMI.DataPath, &CitrixXenStoreSession_GUID)) {
+        return GenerateSessionInstance(stack->Parameters.WMI.Buffer, 
+                                    stack->Parameters.WMI.BufferSize,
+                                    fdoData,
+                                    byteswritten);
+    }
+    else
+        return STATUS_NOT_SUPPORTED;
+
+}
+
+
+NTSTATUS
+WmiRegInfo(
+    IN PFDO_DATA fdoData,
+    IN PIO_STACK_LOCATION stack,
+    OUT ULONG_PTR *byteswritten
+   )
+{
+    WMIREGINFO *reginfo;
+    WMIREGGUID *guiddata;
+    UCHAR *mofnameptr;
+    UCHAR *regpath;
+    ULONG RequiredSize;
+    int entries = 4;
+    const static UNICODE_STRING mofname = RTL_CONSTANT_STRING(L"XENIFACEMOF");
+    
+    size_t mofnamesz;
+
+
+    WMIREGGUID * guid;
+    XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+
+    if  (stack->Parameters.WMI.DataPath == WMIREGISTER) {
+        mofnamesz = mofname.Length + sizeof(USHORT);
+    }
+    else {
+        mofnamesz = 0;
+    }
+    if(!AccessWmiBuffer(stack->Parameters.WMI.Buffer, FALSE,
+                        &RequiredSize, 
+                        stack->Parameters.WMI.BufferSize,
+                        WMI_BUFFER, sizeof(WMIREGINFO), (UCHAR **)&reginfo,
+                        WMI_BUFFER, entries * sizeof(WMIREGGUID), (UCHAR **)&guiddata,
+                        WMI_STRING, mofnamesz, &mofnameptr,
+                        WMI_STRING, Globals.RegistryPath.Length+sizeof(USHORT), 
+                                    &regpath,
+                        WMI_DONE)){
+        reginfo->BufferSize = RequiredSize;
+        *byteswritten = sizeof(ULONG);
+        return STATUS_BUFFER_TOO_SMALL;
+
+    }
+    if (stack->Parameters.WMI.DataPath == WMIREGISTER) {    
+        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);
+    }
+
+    reginfo->BufferSize = RequiredSize;
+    reginfo->NextWmiRegInfo = 0;
+    reginfo->GuidCount = entries;
+
+    guid = &reginfo->WmiRegGuid[0];
+    guid->InstanceCount = 1;
+    guid->Guid = CitrixXenStoreBase_GUID;
+    guid->Flags = WMIREG_FLAG_INSTANCE_PDO;
+    guid->Pdo = (ULONG_PTR)fdoData->UnderlyingPDO; 
+    ObReferenceObject(fdoData->UnderlyingPDO);
+    
+    guid = &reginfo->WmiRegGuid[1];
+    guid->Guid = CitrixXenStoreSession_GUID;
+    guid->Flags =0;
+    
+    guid = &reginfo->WmiRegGuid[2];
+    guid->InstanceCount = 1;
+    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 = &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);
+
+
+    *byteswritten = RequiredSize;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+WmiRegInfoEx(
+    IN PFDO_DATA fdoData,
+    IN PIO_STACK_LOCATION stack,
+    OUT ULONG_PTR *byteswritten
+   )
+{
+   
+    XenIfaceDebugPrint(TRACE,"%s\n",__FUNCTION__);
+    return WmiRegInfo(fdoData, stack, byteswritten);
+}
+
+
+
+NTSTATUS
+WmiProcessMinorFunction(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+)
+{
+    PIO_STACK_LOCATION stack;
+    UCHAR MinorFunction;
+    PFDO_DATA fdoData;
+
+    fdoData = (PFDO_DATA)DeviceObject->DeviceExtension;
+
+    stack = IoGetCurrentIrpStackLocation(Irp);
+
+    MinorFunction = stack->MinorFunction;
+
+    switch (MinorFunction)
+    {
+    case IRP_MN_CHANGE_SINGLE_INSTANCE:
+        return WmiChangeSingleInstance(DeviceObject, stack);
+    case IRP_MN_CHANGE_SINGLE_ITEM:
+        return WmiChangeSingleItem(DeviceObject, stack);
+    case IRP_MN_DISABLE_COLLECTION:
+        return WmiDisableCollection(DeviceObject, stack);
+    case IRP_MN_DISABLE_EVENTS:
+        return WmiDisableEvents(DeviceObject, stack);
+    case IRP_MN_ENABLE_COLLECTION:
+        return WmiEnableCollection(DeviceObject, stack);
+    case IRP_MN_ENABLE_EVENTS:
+        return WmiEnableEvents(DeviceObject, stack);
+    case IRP_MN_EXECUTE_METHOD:
+        return WmiExecuteMethod(fdoData, stack,  &Irp->IoStatus.Information);
+    case IRP_MN_QUERY_ALL_DATA:
+        return WmiQueryAllData(fdoData, stack, &Irp->IoStatus.Information);
+    case IRP_MN_QUERY_SINGLE_INSTANCE:
+        return WmiQuerySingleInstance(fdoData, stack, &Irp->IoStatus.Information);
+    case IRP_MN_REGINFO:
+        return WmiRegInfo(fdoData, stack, &Irp->IoStatus.Information);
+    case IRP_MN_REGINFO_EX:
+        return WmiRegInfoEx(fdoData, stack, &Irp->IoStatus.Information);
+    default:
+        return STATUS_NOT_SUPPORTED;
+    }
+}
+
+
+NTSTATUS XenIfaceSystemControl(
+    __in PDEVICE_OBJECT DeviceObject,
+    __inout PIRP Irp
+    )
+{
+    PFDO_DATA               fdoData;
+    NTSTATUS                status;
+
+    fdoData = (PFDO_DATA) DeviceObject->DeviceExtension;
+
+    XenIfaceIoIncrement (fdoData);
+
+    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);
+
+    if (status != STATUS_NOT_SUPPORTED) {
+        Irp->IoStatus.Status = status;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        
+    }
+    else {
+        IoSkipCurrentIrpStackLocation(Irp);
+        status = IoCallDriver(fdoData->NextLowerDriver, Irp);
+    }
+
+    XenIfaceIoDecrement(fdoData);
+    return(status);
+
+}
+
+PCHAR
+WMIMinorFunctionString (
+    __in UCHAR MinorFunction
+)
+/*++
+
+Updated Routine Description:
+    WMIMinorFunctionString does not change in this stage of the function driver.
+--*/
+{
+    switch (MinorFunction)
+    {
+    case IRP_MN_CHANGE_SINGLE_INSTANCE:
+        return "IRP_MN_CHANGE_SINGLE_INSTANCE";
+    case IRP_MN_CHANGE_SINGLE_ITEM:
+        return "IRP_MN_CHANGE_SINGLE_ITEM";
+    case IRP_MN_DISABLE_COLLECTION:
+        return "IRP_MN_DISABLE_COLLECTION";
+    case IRP_MN_DISABLE_EVENTS:
+        return "IRP_MN_DISABLE_EVENTS";
+    case IRP_MN_ENABLE_COLLECTION:
+        return "IRP_MN_ENABLE_COLLECTION";
+    case IRP_MN_ENABLE_EVENTS:
+        return "IRP_MN_ENABLE_EVENTS";
+    case IRP_MN_EXECUTE_METHOD:
+        return "IRP_MN_EXECUTE_METHOD";
+    case IRP_MN_QUERY_ALL_DATA:
+        return "IRP_MN_QUERY_ALL_DATA";
+    case IRP_MN_QUERY_SINGLE_INSTANCE:
+        return "IRP_MN_QUERY_SINGLE_INSTANCE";
+    case IRP_MN_REGINFO:
+        return "IRP_MN_REGINFO";
+    default:
+        return "unknown_syscontrol_irp";
+    }
+}
+
+
diff --git a/src/xeniface/wmi.h b/src/xeniface/wmi.h
new file mode 100644 (file)
index 0000000..561ca09
--- /dev/null
@@ -0,0 +1,57 @@
+/* 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 _XEVTCHN_WMI_H
+#define _XEVTCHN_WMI_H
+
+#include <ntddk.h>
+#include "xeniface.h"
+#include "wmi_generated.h"
+
+NTSTATUS
+WmiProcessMinorFunction(
+    IN PDEVICE_OBJECT Pdo,
+    IN PIRP Irp
+);
+
+NTSTATUS
+WmiInit(
+    PFDO_DATA FdoData
+); 
+
+
+NTSTATUS
+WmiFinalise(       
+    PFDO_DATA FdoData
+); 
+
+#endif
diff --git a/src/xeniface/wmi.mof b/src/xeniface/wmi.mof
new file mode 100644 (file)
index 0000000..9f91b78
--- /dev/null
@@ -0,0 +1,133 @@
+[Dynamic, Provider("WMIProv"),
+ WMI,
+ Description("Xenstore Node"),
+ guid("{1D80EB99-A1D6-4492-B62F-8B4549FF0B5E}"),
+ locale("MS\\0x409")]
+class CitrixXenStoreNodes
+{
+    [key, read]
+     string InstanceName;
+    [read] boolean Active;
+
+    [WmiDataId(1),
+     read,
+     Description("Number of child nodes")]
+    uint32 NoOfChildNodes;
+
+    [WmiDataId(2),
+     read,
+     WmiSizeIs("NoOfChildNodes"),
+     Description("Child Nodes")]
+    string ChildNodes[];
+    
+};
+
+[Dynamic, Provider("WMIProv"),
+ WMI,
+ Description("Xenstore Session"),
+ guid("{12138A69-97B2-49DD-B9DE-54749AABC789}"),
+ locale("MS\\0x409")]
+
+class CitrixXenStoreSession
+{
+    [key, read]
+     string InstanceName;
+    [read] boolean Active;
+
+    [WmiDataId(1), read]
+    uint32 SessionId;
+    [WmiDataId(2),read]
+    string Id;
+
+    [Implemented, WmiMethodId(1), Description("Get Value")]
+        void GetValue([In, IDQualifier(0)]string Pathname, [Out, IDQualifier(1)]string value);
+    
+    [Implemented, WmiMethodId(2), Description("Get Children")]
+        void GetChildren([In, IDQualifier(0)]string Pathname, [Out, IDQualifier(1)]CitrixXenStoreNodes children);
+
+    [Implemented, WmiMethodId(3), Description("Set Value")]
+        void SetValue([In, IDQualifier(0)]string Pathname, [In, IDQualifier(1)]string value);
+
+    [Implemented, WmiMethodId(4), Description("End Session")]
+        void EndSession();
+
+    [Implemented, WmiMethodId(5), Description("Set Watch")]
+        void SetWatch([In, IDQualifier(0)]string Pathname);
+
+    [Implemented, WmiMethodId(6), Description("Remove Watch")]
+        void RemoveWatch([In, IDQualifier(0)]string Pathname);
+    
+    [Implemented, WmiMethodId(7), Description("Remove Value")]
+        void RemoveValue([In, IDQualifier(0)]string Pathname);
+
+    [Implemented, WmiMethodId(8), Description("Log")]
+        void Log([In, IDQualifier(0)]string Message); 
+
+    [Implemented, WmiMethodId(9), Description("Start Transaction")]
+        void StartTransaction();
+
+    [Implemented, WmiMethodId(10), Description("Commit Transaction")]
+        void CommitTransaction();
+    
+    [Implemented, WmiMethodId(11), Description("Abort Transaction")]
+        void AbortTransaction();
+    
+    [Implemented, WmiMethodId(12), Description("Get First Child")]
+        void GetFirstChild([In, IDQualifier(0)]string InPath, [Out, IDQualifier(1)]string OutPath);
+
+    [Implemented, WmiMethodId(13), Description("Get Next Sibling")]
+        void GetNextSibling([In, IDQualifier(0)]string InPath, [Out, IDQualifier(1)]string OutPath);
+};
+[WMI, Dynamic, Provider("WMIProv"),
+ guid("{8C436757-56BA-4273-9E58-CA4E689260E5}"),
+ locale("MS\\0x409"),
+ WmiExpense(1),
+ Description("Event notifying XenStore")]
+class CitrixXenStoreWatchEvent : WMIEvent
+{
+    [key, read]
+    string        InstanceName;
+
+    [read]
+    boolean        Active;
+
+    [read,
+     Description("Triggered Event Id"),
+     WmiDataId(1)]    string    EventId;
+};
+
+[Dynamic, Provider("WMIProv"),
+ WMI,
+ Description("Base Citrix XenStore Object"),
+ guid("{AB8136BF-8EA7-420D-ADAD-89C83E587925}"),
+ locale("MS\\0x409")]
+class CitrixXenStoreBase {
+   [key, read]
+    string        InstanceName;
+
+    [read]
+    boolean        Active;
+
+    
+    [read,
+     Description("Time provided by Xen hypervisor"),
+     WmiDataId(1)] uint64 XenTime;
+
+    [Implemented, WmiMethodId(1), Description("Add new session")]
+        void AddSession([In, IDQualifier(0)]string Id, [Out, IDQualifier(2)]uint32 SessionId);
+
+};
+
+[WMI, Dynamic, Provider("WMIProv"),
+ guid("{6456AAFA-4D71-497C-A34E-26AA995B14A4}"),
+ locale("MS\\0x409"),
+ WmiExpense(1),
+ Description("Event notifying the VM has unsuspended")]
+class CitrixXenStoreUnsuspendedEvent : WMIEvent
+{
+    [key, read]
+    string        InstanceName;
+
+    [read]
+    boolean        Active;
+};
diff --git a/src/xeniface/xeniface.h b/src/xeniface/xeniface.h
new file mode 100644 (file)
index 0000000..74b6f6e
--- /dev/null
@@ -0,0 +1,556 @@
+/* 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_
+
+
diff --git a/src/xeniface/xeniface.rc b/src/xeniface/xeniface.rc
new file mode 100644 (file)
index 0000000..0666f97
--- /dev/null
@@ -0,0 +1,57 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#include <windows.h>
+#include <ntverp.h>
+
+#undef VER_COMPANYNAME_STR
+#undef VER_PRODUCTNAME_STR
+#undef VER_PRODUCTVERSION
+#undef VER_PRODUCTVERSION_STR
+
+#define        VER_COMPANYNAME_STR         "Citrix Systems Inc."
+#define VER_LEGALCOPYRIGHT_STR      "Copyright " YEAR_STR VER_COMPANYNAME_STR
+
+#include "..\..\include\version.h"
+
+#define VER_PRODUCTNAME_STR         "Citrix PV Tools for Virtual Machines"
+#define VER_PRODUCTVERSION          MAJOR_VERSION,MINOR_VERSION,MICRO_VERSION,BUILD_NUMBER
+#define VER_PRODUCTVERSION_STR      MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR
+
+#define VER_INTERNALNAME_STR        "XENIFACE.SYS"
+#define VER_FILEDESCRIPTION_STR     "Citrix PV Interface Driver"
+
+#define VER_FILETYPE                VFT_DRV
+#define VER_FILESUBTYPE             VFT2_DRV_SYSTEM
+
+#include <common.ver>
+
+XenIfaceMof MOFDATA wmi.bmf
diff --git a/src/xeniface64.inf b/src/xeniface64.inf
new file mode 100644 (file)
index 0000000..84e04b0
--- /dev/null
@@ -0,0 +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,NTAMD64
+
+[Citrix.NTAMD64]
+; DisplayName               Section           DeviceId
+; -----------               -------           --------
+%XenIfaceDevice.DeviceDesc%=XenIface_Device, XENBUS\CLASS&IFACE
+
+[XenIface_Device.NT]
+CopyFiles=XenIface_Device.NT.Copy
+
+[XenIFace_Device.NT.Copy]
+xeniface.sys
+
+;-------------- Service installation
+
+[Xeniface_Device.NT.Services]
+AddService = xeniface, %SPSVCINST_ASSOCSERVICE%, xeniface_Service_Inst
+
+[xeniface_Service_Inst]
+DisplayName    = %xeniface.SVCDESC%
+ServiceType    = 1               ; SERVICE_KERNEL_DRIVER
+StartType      = 3               ; SERVICE_DEMAND_START 
+ErrorControl   = 1               ; SERVICE_ERROR_NORMAL
+ServiceBinary  = %12%\xeniface.sys
+LoadOrderGroup = Extended Base
+
+
+[SourceDisksNames]
+1 = %DiskId1%,,,""
+
+[SourceDisksFiles]
+xeniface.sys  = 1,,
+
+[Strings]
+SPSVCINST_ASSOCSERVICE= 0x00000002
+Citrix= "Citrix Systems, Inc." 
+ClassName = "XenIface"
+DiskId1 = "Citrix Tools for Virtual Machines"
+XenIfaceDevice.DeviceDesc = "Citrix Xen Interface"
+xeniface.SVCDESC = "Citrix Xen Interface Device Driver"
+
diff --git a/testwmi.vbs b/testwmi.vbs
new file mode 100644 (file)
index 0000000..ef16ea7
--- /dev/null
@@ -0,0 +1,263 @@
+rem testwmi.vbs
+
+rem Copyright (c) Citrix Systems Inc.
+rem All rights reserved.
+rem
+rem Redistribution and use in source and binary forms, 
+rem with or without modification, are permitted provided 
+rem that the following conditions are met:
+rem
+rem *   Redistributions of source code must retain the above 
+rem     copyright notice, this list of conditions and the 
+rem     following disclaimer.
+rem *   Redistributions in binary form must reproduce the above 
+rem     copyright notice, this list of conditions and the 
+rem     following disclaimer in the documentation and/or other 
+rem     materials provided with the distribution.
+rem
+rem THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+rem CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+rem INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+rem MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+rem DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+rem CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+rem SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+rem BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+rem SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+rem INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+rem WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+rem NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+rem OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+rem SUCH DAMAGE.
+
+rem a sanity check for the xeniface wmi interface
+rem can be called using cscript.exe
+rem will set %ERRORLEVEL% to 0 on success and 1 on failure
+rem will also output the text 'SUCCESS' or an error message
+
+Set objWMIService = GetObject("winmgmts:\\.\root\wmi")
+Set base = objWmiService.InstancesOf("CitrixXenStoreBase")
+Dim answer
+Dim answer2
+Dim objItem
+
+
+rem Locate the base object
+
+if (base.Count) <> 1 then
+    wscript.echo("Too many base objects found")
+    wscript.quit(1)
+end if
+for each itementry in base
+  rem is there a more trivial way of getting the only item from a collection in vbscript?
+  set objItem = itementry
+next
+  
+rem Add two sessions
+
+objitem.AddSession "VBSTestSession", answer
+objitem.AddSession "AnotherVBSTestSession", answer2
+
+rem locate the first session
+
+query = "select * from CitrixXenStoreSession where SessionId = '" & answer & "'"
+Set sessions = objWMIService.ExecQuery(query)  
+if (sessions.count) <> 1 then
+    wscript.echo("Too many session-1 sessions found")
+    wscript.quit(1)
+end if
+for each itementry in sessions
+  rem is there a more trivial way of getting the only item from a collection in vbscript?
+  set session = itementry
+next
+
+rem locate te second session
+
+query = "select * from CitrixXenStoreSession where SessionId = '" & answer2 & "'"
+Set sessions2 = objWMIService.ExecQuery(query)
+if (sessions2.count) <> 1 then
+    wscript.echo("Too many session-2 sessions found")
+    wscript.quit(1)
+end if
+dim session2
+for each ses in sessions2
+  Set session2=ses
+next
+
+rem ensure we located the expected session
+
+if session.Id <> "VBSTestSession" then
+  wscript.echo("incorrect session found")
+  wscript.quit(1)
+end if
+
+rem blank a set of xenstore entries
+
+session.removevalue "data/wmitestrun"
+
+rem and put a known set of values there
+
+session.SetValue "data/wmitestrun/test1", "Testing"
+session.SetValue "data/wmitestrun/test2", "123 Testing"
+session.SetValue "data/wmitestrun/test3", "456 Testing"
+session.SetValue "data/wmitestrun/test4", "789 Testing"
+
+rem read back a value from xenstore, and check that it is right
+
+session.getvalue "data/wmitestrun/test1", res
+if res <> "Testing" then
+  wscript.echo("failed writing or reading to data/wmitestrun/test1")
+  wscript.echo("read = " & res)
+  wscript.quit(1)
+end if 
+
+rem read back a different value from xenstore, and check that it is right
+
+session.getvalue "data/wmitestrun/test2", res
+if res <> "123 Testing" then
+  wscript.echo("failed writing or reading to data/wmitestrun/test2")
+  wscript.echo("read = " & res)
+  wscript.quit(1)
+end if 
+
+rem transactions
+rem test that aborted transactions don't do anything
+
+session.starttransaction()
+session.SetValue "data/wmitestrun/test1", "WEIRD"
+session.getvalue "data/wmitestrun/test1", res
+if res <> "WEIRD" then
+  wscript.echo("failed writing or reading within transaction to data/wmitestrun/test1")
+  wscript.echo("read = " & res)
+  wscript.quit(1)
+end if 
+session.aborttransaction()
+
+session.getvalue "data/wmitestrun/test1", res
+if res <> "Testing" then
+  wscript.echo("failed reading to data/wmitestrun/test1 after aborted transaction ")
+  wscript.echo("read = " & res)
+  wscript.quit(1)
+end if
+
+
+rem test that 2 overlapping transactions honour commits and aborts, and raise errors when needed
+
+session.starttransaction()
+session2.starttransaction()
+session.SetValue "data/wmitestrun/test1", "WEIRD"
+session2.SetValue "data/wmitestrun/test1", "Fish"
+session.getvalue "data/wmitestrun/test1", res
+session2.getvalue "data/wmitestrun/test1", res2
+if res <> "WEIRD" then
+  wscript.echo("failed writing or reading within transaction to data/wmitestrun/test1 session 1")
+  wscript.echo("read = " & res)
+  wscript.quit(1)
+end if 
+if res2 <> "Fish" then
+  wscript.echo("failed writing or reading within transaction to data/wmitestrun/test1 session 2")
+  wscript.echo("read = " & res)
+  wscript.quit(1)
+end if 
+
+on error resume next
+session.committransaction()
+Err.clear()
+if Err.Number <> 0 then
+    wscript.echo("Could not commit first transaction")
+    wscript.quit(1)
+end if
+session2.committransaction() 
+if Err.Number = 0 then
+    wscript.echo("Both transactions comitted")
+    wscript.quit(1)
+end if
+session2.aborttransaction()
+session2.getvalue "data/wmitestrun/test1", res2
+if res2 <> "WEIRD" then
+  wscript.echo("failed commiting the correct transaction")
+  wscript.echo("read = " & res)
+  wscript.quit(1)
+end if 
+
+rem events
+rem set up an event sink
+
+dim refsink
+set refsink = CreateObject("WBemScripting.SWbemSink")
+wscript.ConnectObject refsink, "EVENTSINK_"
+stq = "Select * from CitrixXenStoreWatchEvent"
+objwmiservice.ExecNotificationQueryAsync refsink, stq
+
+evtcount = 0
+
+rem watch a xenstore entry
+
+allevents=0
+session.setwatch "data/wmitestrun/test1"
+session.setvalue "data/wmitestrun/test1","MAGIC"
+session.removevalue "data/wmitestrun/test1"
+session.setvalue "data/wmitestrun/test1","GOLD"
+wscript.sleep(5000)
+session.removewatch "data/wmitestrun/test1"
+
+rem check we received an event.  Also, since events can be coalesced, check
+rem that when we receive our final event, the value we read from test1 is the
+rem final value we set it to
+
+rem (note the actual work of counting and checking events is done in the 
+rem EVENTSINK_OnObjectready sub below)
+
+if evtcount <= 4 and allevents <> 1 then
+    wscript.echo("Failed to catch all the expected events")
+    wscript.quit(1)
+end if
+
+session.removevalue "data/wmitestrun/test1"
+
+rem check that we can read the list of children an entry has
+
+strComputer = "."
+Set objWMIService = GetObject("winmgmts:" _
+    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
+
+Set colOperatingSystems = objWMIService.ExecQuery _
+    ("Select * from Win32_OperatingSystem")
+
+for each os in colOperatingSystems
+  rem is there a more trivial way of getting the only item from a collection in vbscript?
+  set myos = os
+next
+
+wscript.echo(myos.Version)
+
+if Mid(myos.Version, 1 , 3) <> "6.0" then
+
+    dim children
+    session.getchildren "data/wmitestrun", children
+
+    if children.noofchildnodes <> 3 then
+        wscript.echo("Failed to find all the expected child nodes")
+        wscript.quit(1)
+    end if
+end if
+
+session.getfirstchild "data/wmitestrun", res
+session.getnextsibling res, res
+
+rem end both sessions that we created.
+
+session2.EndSession()
+session.EndSession()
+
+Wscript.echo("Success")
+
+Sub EVENTSINK_OnObjectReady(re, rc)
+   evtcount = evtcount + 1
+   session.getvalue "data/wmitestrun/test1", res
+   if res = "GOLD" then
+       allevents = 1
+   else
+       allevents = 0
+   end if
+end sub