]> xenbits.xensource.com Git - pvdrivers/win/xennet.git/commitdiff
[CP-4696] Git repository created for xennet
authorBen Chalmers <Ben.Chalmers@citrix.com>
Tue, 28 May 2013 12:40:23 +0000 (13:40 +0100)
committerBen Chalmers <Ben.Chalmers@citrix.com>
Tue, 28 May 2013 12:40:23 +0000 (13:40 +0100)
33 files changed:
LICENSE [new file with mode: 0644]
build.py [new file with mode: 0644]
clean.py [new file with mode: 0644]
include/ethernet.h [new file with mode: 0644]
include/tcpip.h [new file with mode: 0644]
include/util.h [new file with mode: 0644]
include/vif_interface.h [new file with mode: 0644]
kdfiles.py [new file with mode: 0644]
proj/msbuild.bat [new file with mode: 0644]
proj/package/package.vcxproj [new file with mode: 0644]
proj/package/package.vcxproj.user [new file with mode: 0644]
proj/xennet.sln [new file with mode: 0644]
proj/xennet/xennet.vcxproj [new file with mode: 0644]
proj/xennet/xennet.vcxproj.user [new file with mode: 0644]
proj/xennet_coinst/xennet_coinst.vcxproj [new file with mode: 0644]
proj/xennet_coinst/xennet_coinst.vcxproj.user [new file with mode: 0644]
src/coinst/coinst.c [new file with mode: 0644]
src/coinst/xennet_coinst.def [new file with mode: 0644]
src/xennet.inf [new file with mode: 0644]
src/xennet/adapter.c [new file with mode: 0644]
src/xennet/adapter.h [new file with mode: 0644]
src/xennet/assert.h [new file with mode: 0644]
src/xennet/common.h [new file with mode: 0644]
src/xennet/log.h [new file with mode: 0644]
src/xennet/main.c [new file with mode: 0644]
src/xennet/miniport.c [new file with mode: 0644]
src/xennet/project.h [new file with mode: 0644]
src/xennet/receiver.c [new file with mode: 0644]
src/xennet/receiver.h [new file with mode: 0644]
src/xennet/std.h [new file with mode: 0644]
src/xennet/transmitter.c [new file with mode: 0644]
src/xennet/transmitter.h [new file with mode: 0644]
src/xennet/xennet.rc [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/build.py b/build.py
new file mode 100644 (file)
index 0000000..d457c76
--- /dev/null
+++ b/build.py
@@ -0,0 +1,301 @@
+#!python -u
+
+import os, sys
+import datetime
+import re
+import glob
+import tarfile
+import subprocess
+
+def next_build_number():
+    try:
+        file = open('.build_number', 'r')
+        build_number = file.read()
+        file.close()
+    except IOError:
+        build_number = '0'
+
+    file = open('.build_number', 'w')
+    file.write(str(int(build_number) + 1))
+    file.close()
+
+    return build_number
+
+
+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 copy_inf(name):
+    src = open('src\\%s.inf' % name, 'r')
+    dst = open('proj\\%s.inf' % name, 'w')
+
+    for line in src:
+        line = re.sub('@MAJOR_VERSION@', os.environ['MAJOR_VERSION'], line)
+        line = re.sub('@MINOR_VERSION@', os.environ['MINOR_VERSION'], line)
+        line = re.sub('@MICRO_VERSION@', os.environ['MICRO_VERSION'], line)
+        line = re.sub('@BUILD_NUMBER@', os.environ['BUILD_NUMBER'], line)
+        dst.write(line)
+
+    dst.close()
+    src.close()
+
+
+def get_expired_symbols(name, 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(':')
+            tag = item[5].strip('"')
+
+            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 (tag == name and 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(debug):
+    configuration = 'Windows Vista'
+
+    if debug:
+        configuration += ' Debug'
+    else:
+        configuration += ' Release'
+
+    return configuration
+
+def get_configuration_name(debug):
+    configuration = 'WindowsVista'
+
+    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(name, 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(name, 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)))
+
+    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__':
+    debug = { 'checked': True, 'free': False }
+    driver = 'xennet'
+
+    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'] = next_build_number()
+
+    print("BUILD_NUMBER=%s" % os.environ['BUILD_NUMBER'])
+
+    if 'MERCURIAL_REVISION' in os.environ.keys():
+        revision = open('revision', 'w')
+        print(os.environ['MERCURIAL_REVISION'], file=revision)
+        revision.close()
+
+    make_header()
+
+    copy_inf(driver)
+
+    symstore_del(driver, 30)
+
+    msbuild(driver, 'x86', debug[sys.argv[1]])
+    msbuild(driver, 'x64', debug[sys.argv[1]])
+
+    symstore_add(driver, 'x86', debug[sys.argv[1]])
+    symstore_add(driver, 'x64', debug[sys.argv[1]])
+
+    listfile = callfnout(['hg','manifest'])   
+    archive(driver + '\\source.tgz', listfile.splitlines(), tgz=True)
+    archive(driver + '.tar', [driver,'revision'])
+
+
diff --git a/clean.py b/clean.py
new file mode 100644 (file)
index 0000000..4f77ead
--- /dev/null
+++ b/clean.py
@@ -0,0 +1,14 @@
+#!/usr/bin/env python
+
+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/ethernet.h b/include/ethernet.h
new file mode 100644 (file)
index 0000000..9eb4b74
--- /dev/null
@@ -0,0 +1,135 @@
+/* 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 _ETHERNET_H_
+#define _ETHERNET_H_
+
+#pragma warning(push)
+#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union
+
+#pragma pack(push, 1)
+
+// Ethernet data structures
+//
+// NOTE: Fields are in network byte order
+
+#define ETHERNET_MTU            1500
+#define ETHERNET_MIN            60
+#define ETHERNET_MAX            1514
+
+typedef struct _ETHERNET_ADDRESS {
+    UCHAR   Byte[6];
+} ETHERNET_ADDRESS, *PETHERNET_ADDRESS;
+
+#define ETHERNET_ADDRESS_LENGTH (sizeof (ETHERNET_ADDRESS))
+
+typedef enum _ETHERNET_ADDRESS_TYPE {
+    ETHERNET_ADDRESS_TYPE_INVALID = 0,
+    ETHERNET_ADDRESS_UNICAST,
+    ETHERNET_ADDRESS_MULTICAST,
+    ETHERNET_ADDRESS_BROADCAST,
+    ETHERNET_ADDRESS_TYPE_COUNT
+} ETHERNET_ADDRESS_TYPE, *PETHERNET_ADDRESS_TYPE;
+
+#define GET_ETHERNET_ADDRESS_TYPE(_Address)                 \
+        (((_Address)->Byte[0] & 0x01) ?                     \
+            (((((_Address)->Byte[0] & ~0x03) == 0xFC) &&    \
+              (((_Address)->Byte[1]        ) == 0xFF) &&    \
+              (((_Address)->Byte[2]        ) == 0xFF) &&    \
+              (((_Address)->Byte[3]        ) == 0xFF) &&    \
+              (((_Address)->Byte[4]        ) == 0xFF) &&    \
+              (((_Address)->Byte[5]        ) == 0xFF)       \
+             ) ?                                            \
+                ETHERNET_ADDRESS_BROADCAST :                \
+                ETHERNET_ADDRESS_MULTICAST                  \
+            ) :                                             \
+            ETHERNET_ADDRESS_UNICAST                        \
+        )
+
+typedef struct _ETHERNET_UNTAGGED_HEADER {
+    ETHERNET_ADDRESS    DestinationAddress;
+    ETHERNET_ADDRESS    SourceAddress;
+    USHORT              TypeOrLength;
+
+#define ETHERTYPE_IPV4      0x0800
+#define ETHERTYPE_IPV6      0x86DD
+#define ETHERTYPE_ARP       0x0806
+#define ETHERTYPE_RARP      0x0835
+#define ETHERTYPE_TPID      0x8100
+#define ETHERTYPE_LOOPBACK  0x9000
+
+} ETHERNET_UNTAGGED_HEADER, *PETHERNET_UNTAGGED_HEADER;
+
+typedef struct _ETHERNET_TAG {
+    USHORT  ProtocolID;    // == ETHERTYPE_TPID
+    USHORT  ControlInformation;
+
+#define PACK_TAG_CONTROL_INFORMATION(_ControlInformation, _UserPriority, _CanonicalFormatId, _VlanId)   \
+        do {                                                                                            \
+            (_ControlInformation) = (USHORT)(_VlanId) & 0x0FFF;                                         \
+            (_ControlInformation) |= (USHORT)((_CanonicalFormatId) << 12) & 0x1000;                     \
+            (_ControlInformation) |= (USHORT)((_UserPriority) << 13) & 0xE000;                          \
+        } while (FALSE)
+
+#define UNPACK_TAG_CONTROL_INFORMATION(_ControlInformation, _UserPriority, _CanonicalFormatId, _VlanId) \
+        do {                                                                                            \
+            (_VlanId) = (_ControlInformation) & 0xFFF;                                                  \
+            (_CanonicalFormatId) = ((_ControlInformation) & 0x1000) >> 12;                              \
+            (_UserPriority) = ((_ControlInformation) & 0xE000) >> 13;                                   \
+        } while (FALSE)
+
+} ETHERNET_TAG, *PETHERNET_TAG;
+
+typedef struct _ETHERNET_TAGGED_HEADER {
+  ETHERNET_ADDRESS  DestinationAddress;
+  ETHERNET_ADDRESS  SourceAddress;
+  ETHERNET_TAG      Tag;
+  USHORT            TypeOrLength;
+} ETHERNET_TAGGED_HEADER, *PETHERNET_TAGGED_HEADER;
+
+typedef union _ETHERNET_HEADER {
+    ETHERNET_UNTAGGED_HEADER    Untagged;
+    ETHERNET_TAGGED_HEADER      Tagged;
+} ETHERNET_HEADER, *PETHERNET_HEADER;
+
+#define ETHERNET_HEADER_IS_TAGGED(_Header)                          \
+        ((_Header)->Untagged.TypeOrLength == NTOHS(ETHERTYPE_TPID))
+
+#define ETHERNET_HEADER_LENGTH(_Header)         \
+        ETHERNET_HEADER_IS_TAGGED(_Header) ?    \
+        sizeof (ETHERNET_TAGGED_HEADER) :       \
+        sizeof (ETHERNET_UNTAGGEDHEADER))
+
+#pragma pack(pop)
+
+#pragma warning(pop)
+
+#endif  // _ETHERNET_H
diff --git a/include/tcpip.h b/include/tcpip.h
new file mode 100644 (file)
index 0000000..7d1dade
--- /dev/null
@@ -0,0 +1,262 @@
+/* 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 "ethernet.h"
+
+#ifndef _TCPIP_H
+#define _TCPIP_H
+
+#pragma warning(push)
+#pragma warning(disable:4214) // nonstandard extension used : bit field types other than int
+#pragma warning(disable:4201) // nonstandard extension used : nameless struct/union
+
+#define NTOHS(_Value)   _byteswap_ushort(_Value)
+#define HTONS(_Value)   _byteswap_ushort(_Value)
+#define NTOHL(_Value)   _byteswap_ulong(_Value)
+#define HTONL(_Value)   _byteswap_ulong(_Value)
+
+#pragma pack(push, 1)
+
+// TCP/IP data structures
+//
+// NOTE: Fields are in network byte order
+
+// IPv4
+
+typedef struct _IPV4_ADDRESS {
+    union {
+        ULONG   Dword[1];
+        UCHAR   Byte[4];
+    };
+} IPV4_ADDRESS, *PIPV4_ADDRESS;
+
+#define IPV4_ADDRESS_LENGTH (sizeof (IPV4_ADDRESS))
+
+typedef struct _IPV4_HEADER {
+    UCHAR           HeaderLength:4;
+    UCHAR           Version:4;
+    UCHAR           TypeOfService;
+    USHORT          PacketLength;
+    USHORT          PacketID;
+    USHORT          FragmentOffsetAndFlags;
+
+#define IPV4_FRAGMENT_OFFSET(_FragmentOffsetAndFlags)   \
+        ((_FragmentOffsetAndFlags) & 0x1fff)
+#define IPV4_DONT_FRAGMENT(_FragmentOffsetAndFlags)     \
+        ((_FragmentOffsetAndFlags) & 0x4000)
+#define IPV4_MORE_FRAGMENTS(_FragmentOffsetAndFlags)    \
+        ((_FragmentOffsetAndFlags) & 0x2000)
+#define IPV4_IS_A_FRAGMENT(_FragmentOffsetAndFlags)     \
+        ((_FragmentOffsetAndFlags) & 0x3fff)
+
+    UCHAR           TimeToLive;
+    UCHAR           Protocol;
+    USHORT          Checksum;
+    IPV4_ADDRESS    SourceAddress;
+    IPV4_ADDRESS    DestinationAddress;
+} IPV4_HEADER, *PIPV4_HEADER;
+
+#define IPV4_HEADER_LENGTH(_Header) \
+        (((ULONG)((_Header)->HeaderLength)) << 2)
+
+#define MAXIMUM_IPV4_HEADER_LENGTH \
+        (0xF << 2)
+
+// IPv6
+
+typedef struct _IPV6_ADDRESS {
+    union {
+        ULONG   Dword[4];
+        UCHAR   Byte[16];
+    };
+} IPV6_ADDRESS, *PIPV6_ADDRESS;
+
+#define IPV6_ADDRESS_LENGTH (sizeof (IPV6_ADDRESS))
+
+typedef struct _IPV6_HEADER {
+    union {
+      struct {
+        UCHAR       __Pad:4;
+        UCHAR       Version:4;
+      };
+      ULONG         VCF;
+    };
+    USHORT          PayloadLength;
+    UCHAR           NextHeader;
+    UCHAR           HopLimit;
+    IPV6_ADDRESS    SourceAddress;
+    IPV6_ADDRESS    DestinationAddress;
+} IPV6_HEADER, *PIPV6_HEADER;
+
+#define IPV6_HEADER_LENGTH(_Header) \
+        (ULONG)(sizeof (IPV6_HEADER))
+
+// IP
+
+typedef union _IP_ADDRESS {
+    IPV4_ADDRESS    Version4;
+    IPV6_ADDRESS    Version6;
+} IP_ADDRESS, *PIP_ADDRESS;
+
+typedef union _IP_HEADER {
+    struct {
+        UCHAR   __Pad:4;
+        UCHAR   Version:4;
+    };
+    IPV4_HEADER Version4;
+    IPV6_HEADER Version6;
+} IP_HEADER, *PIP_HEADER;
+  
+#define IP_HEADER_LENGTH(_Header)                   \
+        (((_Header)->Version == 4) ?                \
+        IPV4_HEADER_LENGTH(&(_Header)->Version4) :  \
+        IPV6_HEADER_LENGTH(&(_Header)->Version6))
+
+#define IPPROTO_HOP_OPTIONS 0
+#define IPPROTO_DST_OPTIONS 60
+#define IPPROTO_ROUTING     43
+
+// Options
+
+typedef struct _IPV6_OPTION_HEADER {
+    UCHAR   NextHeader;
+    UCHAR   PayloadLength;
+} IPV6_OPTION_HEADER, *PIPV6_OPTION_HEADER;
+
+#define IPV6_OPTION_HEADER_LENGTH(_Header)  \
+        (ULONG)(sizeof (IPV6_OPTION_HEADER) + (_Header)->PayloadLength)
+
+#define IPPROTO_TCP         6
+
+// TCP
+
+typedef struct _TCP_HEADER {
+    USHORT  SourcePort;
+    USHORT  DestinationPort;
+    ULONG   Seq;
+    ULONG   Ack;
+    UCHAR   Reserved:4;
+    UCHAR   HeaderLength:4;
+    UCHAR   Flags;
+
+#define        TCP_FIN   0x01
+#define        TCP_SYN   0x02
+#define        TCP_RST   0x04
+#define        TCP_PSH   0x08
+#define        TCP_ACK   0x10
+#define        TCP_URG   0x20
+#define        TCP_ECE   0x40
+#define        TCP_CWR   0x80
+
+    USHORT  Window;
+    USHORT  Checksum;
+    USHORT  UrgentPointer;
+} TCP_HEADER, *PTCP_HEADER;
+
+#define TCP_HEADER_LENGTH(_Header)  \
+        (((ULONG)((_Header)->HeaderLength)) << 2)
+
+#define MAXIMUM_TCP_HEADER_LENGTH \
+        (0xF << 2)
+
+#define TCPOPT_NOP          1
+#define TCPOPT_TIMESTAMP    8
+#define TCPOLEN_TIMESTAMP   10
+
+#define IPPROTO_UDP         17
+
+// UDP
+
+typedef struct _UDP_HEADER {
+    USHORT  SourcePort;
+    USHORT  DestinationPort;
+    USHORT  PacketLength;
+    USHORT  Checksum;
+} UDP_HEADER, *PUDP_HEADER;
+
+#define UDP_HEADER_LENGTH(_Header)  \
+        (ULONG)(sizeof (UDP_HEADER))
+
+#define IPPROTO_NONE        59
+
+// Checksum
+
+typedef struct _IPV4_PSEUDO_HEADER {
+    IPV4_ADDRESS    SourceAddress;
+    IPV4_ADDRESS    DestinationAddress;
+    UCHAR           Zero;
+    UCHAR           Protocol;   // TCP or UDP
+    USHORT          Length;     // Including TCP/UDP header
+} IPV4_PSEUDO_HEADER, *PIPV4_PSEUDO_HEADER;
+
+typedef struct _IPV6_PSEUDO_HEADER {
+    IPV6_ADDRESS    SourceAddress;
+    IPV6_ADDRESS    DestinationAddress;
+    USHORT          Length;     // Including TCP/UDP header
+    UCHAR           Zero[3];
+    UCHAR           NextHeader; // TCP or UDP
+} IPV6_PSEUDO_HEADER, *PIPV6_PSEUDO_HEADER;
+
+typedef union _PSEUDO_HEADER {
+    IPV4_PSEUDO_HEADER  Version4;
+    IPV6_PSEUDO_HEADER  Version6;
+} PSEUDO_HEADER, *PPSEUDO_HEADER;
+
+// ARP
+
+typedef struct _ARP_HEADER {
+    USHORT  HardwareType;
+
+#define HARDWARE_ETHER  1
+
+    USHORT  ProtocolType;
+
+#define PROTOCOL_IPV4   ETHERTYPE_IPV4
+
+    UCHAR   HardwareAddressLength;
+    UCHAR   ProtocolAddressLength;
+    USHORT  Operation;
+
+#define ARP_REQUEST     1
+#define ARP_REPLY       2
+#define RARP_REQUEST    3
+#define RARP_REPLY      4
+
+} ARP_HEADER, *PARP_HEADER;
+
+#define ARP_HEADER_LENGTH(_Header)  \
+        (ULONG)(sizeof (ARP_HEADER))
+
+#pragma pack(pop)
+
+#pragma warning(pop)
+
+#endif  //_TCPIP_H
diff --git a/include/util.h b/include/util.h
new file mode 100644 (file)
index 0000000..9b338b6
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _UTIL_H
+#define _UTIL_H
+
+#include <ntddk.h>
+
+#define        P2ROUNDUP(_x, _a)   \
+        (-(-(_x) & -(_a)))
+
+static FORCEINLINE LONG
+__ffs(
+    IN  unsigned long long  mask
+    )
+{
+    unsigned char           *array = (unsigned char *)&mask;
+    unsigned int            byte;
+    unsigned int            bit;
+    unsigned char           val;
+
+    val = 0;
+
+    byte = 0;
+    while (byte < 8) {
+        val = array[byte];
+
+        if (val != 0)
+            break;
+
+        byte++;
+    }
+    if (byte == 8)
+        return -1;
+
+    bit = 0;
+    while (bit < 8) {
+        if (val & 0x01)
+            break;
+
+        val >>= 1;
+        bit++;
+    }
+
+    return (byte * 8) + bit;
+}
+
+#define __ffu(_mask)  \
+        __ffs(~(_mask))
+
+static FORCEINLINE LONG
+__InterlockedAdd(
+    IN  LONG    *Value,
+    IN  LONG    Delta
+    )
+{
+    LONG        New;
+    LONG        Old;
+
+    do {
+        Old = *Value;
+        New = Old + Delta;
+    } while (InterlockedCompareExchange(Value, New, Old) != Old);
+
+    return New;
+}
+
+static FORCEINLINE LONG
+__InterlockedSubtract(
+    IN  LONG    *Value,
+    IN  LONG    Delta
+    )
+{
+    LONG        New;
+    LONG        Old;
+
+    do {
+        Old = *Value;
+        New = Old - Delta;
+    } while (InterlockedCompareExchange(Value, New, Old) != Old);
+
+    return New;
+}
+
+#endif  // _UTIL_H
diff --git a/include/vif_interface.h b/include/vif_interface.h
new file mode 100644 (file)
index 0000000..ae5d6b4
--- /dev/null
@@ -0,0 +1,418 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#ifndef _XENVIF_VIF_INTERFACE_H
+#define _XENVIF_VIF_INTERFACE_H
+
+#include <ifdef.h>
+#include <ethernet.h>
+
+#define MAX_SKB_FRAGS   ((65536/PAGE_SIZE) + 2)
+
+typedef UCHAR   XENVIF_PACKET_STATUS, *PXENVIF_PACKET_STATUS;
+
+#define PACKET_STATUS_INVALID   0
+#define PACKET_PENDING          1
+#define PACKET_OK               2
+#define PACKET_DROPPED          3
+#define PACKET_ERROR            4
+
+typedef struct  _XENVIF_PACKET_HEADER {
+    ULONG   Offset;
+    ULONG   Length;
+} XENVIF_PACKET_HEADER, *PXENVIF_PACKET_HEADER;
+
+typedef struct _XENVIF_PACKET_INFO {
+    XENVIF_PACKET_HEADER    EthernetHeader;
+    XENVIF_PACKET_HEADER    LLCSnapHeader;
+    XENVIF_PACKET_HEADER    IpHeader;
+    XENVIF_PACKET_HEADER    IpOptions;
+    XENVIF_PACKET_HEADER    TcpHeader;
+    XENVIF_PACKET_HEADER    TcpOptions;
+    XENVIF_PACKET_HEADER    UdpHeader;
+    ULONG                   Length;
+} XENVIF_PACKET_INFO, *PXENVIF_PACKET_INFO;
+
+#pragma warning(push)
+#pragma warning(disable:4214)   // nonstandard extension used : bit field types other than int
+#pragma warning(disable:4201)   // nonstandard extension used : nameless struct/union
+
+typedef struct _XENVIF_CHECKSUM_FLAGS {
+    struct {
+        ULONG   IpChecksumSucceeded:1;
+        ULONG   IpChecksumFailed:1;
+        ULONG   IpChecksumPresent:1;
+        ULONG   TcpChecksumSucceeded:1;
+        ULONG   TcpChecksumFailed:1;
+        ULONG   TcpChecksumPresent:1;
+        ULONG   UdpChecksumSucceeded:1;
+        ULONG   UdpChecksumFailed:1;
+        ULONG   UdpChecksumPresent:1;
+        ULONG   Reserved:23;
+    };
+} XENVIF_CHECKSUM_FLAGS, *PXENVIF_CHECKSUM_FLAGS;
+
+#pragma warning(pop)
+
+typedef struct _XENVIF_RECEIVER_PACKET {
+    LIST_ENTRY              ListEntry;
+    ULONG                   Offset;
+    ULONG                   Length;
+    XENVIF_PACKET_INFO      Info;
+    XENVIF_CHECKSUM_FLAGS   Flags;
+    USHORT                  TagControlInformation;
+    USHORT                  MaximumSegmentSize;
+    PVOID                   Cookie;
+    MDL                     Mdl;
+    PFN_NUMBER              __Pfn;
+} XENVIF_RECEIVER_PACKET, *PXENVIF_RECEIVER_PACKET;
+
+typedef struct _XENVIF_RECEIVER_PACKET_STATISTICS {
+    ULONGLONG   Drop;
+    ULONGLONG   BackendError;
+    ULONGLONG   FrontendError;
+    ULONGLONG   Unicast;
+    ULONGLONG   UnicastBytes;
+    ULONGLONG   Multicast;
+    ULONGLONG   MulticastBytes;
+    ULONGLONG   Broadcast;
+    ULONGLONG   BroadcastBytes;
+} XENVIF_RECEIVER_PACKET_STATISTICS, *PXENVIF_RECEIVER_PACKET_STATISTICS;
+
+#pragma warning(push)
+#pragma warning(disable:4214)   // nonstandard extension used : bit field types other than int
+#pragma warning(disable:4201)   // nonstandard extension used : nameless struct/union
+
+typedef struct _XENVIF_OFFLOAD_OPTIONS {
+    union {
+        struct {
+            USHORT  OffloadTagManipulation:1;
+            USHORT  OffloadIpVersion4LargePacket:1;
+            USHORT  OffloadIpVersion4HeaderChecksum:1;
+            USHORT  OffloadIpVersion4TcpChecksum:1;
+            USHORT  OffloadIpVersion4UdpChecksum:1;
+            USHORT  OffloadIpVersion6LargePacket:1;
+            USHORT  OffloadIpVersion6TcpChecksum:1;
+            USHORT  OffloadIpVersion6UdpChecksum:1;
+            USHORT  NeedChecksumValue:1;
+            USHORT  NeedLargePacketSplit:1;
+            USHORT  Reserved:6;
+        };
+
+        USHORT  Value;
+    };
+} XENVIF_OFFLOAD_OPTIONS, *PXENVIF_OFFLOAD_OPTIONS;
+
+#pragma warning(pop)
+
+typedef struct _XENVIF_TRANSMITTER_PACKET   XENVIF_TRANSMITTER_PACKET, *PXENVIF_TRANSMITTER_PACKET;
+
+// To fit into the reserved space in NDIS_PACKET and NET_BUFFER structures the XENVIF_TRANSMITTER_PACKET
+// structure must be at most the size of 3 pointer types.
+
+#pragma pack(push, 1) 
+typedef struct _XENVIF_SEND_INFO {
+    XENVIF_OFFLOAD_OPTIONS  OffloadOptions;
+    USHORT                  MaximumSegmentSize;     // Only used if OffloadOptions.OffloadIpVersion[4|6}LargePacket is set
+    USHORT                  TagControlInformation;  // Only used if OffloadOptions.OffloadTagManipulation is set
+} XENVIF_SEND_INFO, *PXENVIF_SEND_INFO;
+
+typedef struct _XENVIF_COMPLETION_INFO {
+    UCHAR                   Type;
+    XENVIF_PACKET_STATUS    Status;
+    USHORT                  PacketLength;
+    USHORT                  PayloadLength;
+} XENVIF_COMPLETION_INFO, *PXENVIF_COMPLETION_INFO;
+
+#pragma warning(push)
+#pragma warning(disable:4201)   // nonstandard extension used : nameless struct/union
+
+struct _XENVIF_TRANSMITTER_PACKET {
+    PXENVIF_TRANSMITTER_PACKET  Next;
+    union {
+        XENVIF_SEND_INFO        Send;
+        XENVIF_COMPLETION_INFO  Completion;
+    };
+};
+
+#pragma warning(pop)
+
+#pragma pack(pop) 
+
+C_ASSERT(sizeof (XENVIF_TRANSMITTER_PACKET) <= (3 * sizeof (PVOID)));
+
+// Because we're so tight on space in the XENVIF_TRANSMITTER_PACKET structure, certain packet metadata
+// needs to be accessed via magic offsets
+typedef struct _XENVIF_TRANSMITTER_PACKET_METADATA {
+    LONG_PTR    OffsetOffset;
+    LONG_PTR    LengthOffset;
+    LONG_PTR    MdlOffset;
+} XENVIF_TRANSMITTER_PACKET_METADATA, *PXENVIF_TRANSMITTER_PACKET_METADATA;
+
+typedef struct _XENVIF_TRANSMITTER_PACKET_STATISTICS {
+    ULONG   Drop;
+    ULONG   BackendError;
+    ULONG   FrontendError;
+    ULONG   Unicast;
+    ULONG   UnicastBytes;
+    ULONG   Multicast;
+    ULONG   MulticastBytes;
+    ULONG   Broadcast;
+    ULONG   BroadcastBytes;
+} XENVIF_TRANSMITTER_PACKET_STATISTICS, *PXENVIF_TRANSMITTER_PACKET_STATISTICS;
+
+typedef struct _XENVIF_PACKET_STATISTICS {
+    XENVIF_RECEIVER_PACKET_STATISTICS       Receiver;
+    XENVIF_TRANSMITTER_PACKET_STATISTICS    Transmitter;
+} XENVIF_PACKET_STATISTICS, *PXENVIF_PACKET_STATISTICS;
+
+#define MAXIMUM_MULTICAST_ADDRESS_COUNT 32  // Minimum number to pass WHQL
+
+typedef enum _XENVIF_MAC_FILTER_LEVEL {
+    MAC_FILTER_NONE = 0,
+    MAC_FILTER_MATCHING = 1,
+    MAC_FILTER_ALL = 2
+} XENVIF_MAC_FILTER_LEVEL, *PXENVIF_MAC_FILTER_LEVEL;
+
+typedef struct _XENVIF_MEDIA_STATE {
+    NET_IF_MEDIA_CONNECT_STATE  MediaConnectState;
+    ULONG64                     LinkSpeed;
+    NET_IF_MEDIA_DUPLEX_STATE   MediaDuplexState;
+} XENVIF_MEDIA_STATE, *PXENVIF_MEDIA_STATE;
+
+typedef enum XENVIF_CALLBACK_TYPE {
+    XENVIF_CALLBACK_TYPE_INVALID = 0,
+    XENVIF_CALLBACK_COMPLETE_PACKETS,
+    XENVIF_CALLBACK_RECEIVE_PACKETS,
+    XENVIF_CALLBACK_MEDIA_STATE_CHANGE
+} XENVIF_CALLBACK_TYPE, *PXENVIF_CALLBACK_TYPE;
+
+#define DEFINE_VIF_OPERATIONS                                                                   \
+        VIF_OPERATION(VOID,                                                                     \
+                      Acquire,                                                                  \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT  Context                                          \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      Release,                                                                  \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT  Context                                          \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(NTSTATUS,                                                                 \
+                      Enable,                                                                   \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT  Context,                                         \
+                      IN  VOID                 (*Function)(PVOID, XENVIF_CALLBACK_TYPE, ...),   \
+                      IN  PVOID                Argument OPTIONAL                                \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      Disable,                                                                  \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT  Context                                          \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      QueryPacketStatistics,                                                    \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT       Context,                                    \
+                      OUT PXENVIF_PACKET_STATISTICS Statistics                                  \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      UpdatePacketMetadata,                                                     \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT                   Context,                        \
+                      IN  PXENVIF_TRANSMITTER_PACKET_METADATA   Metadata                        \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      ReturnPacket,                                                             \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT       Context,                                    \
+                      IN  PXENVIF_RECEIVER_PACKET   Packet                                      \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(NTSTATUS,                                                                 \
+                      QueuePackets,                                                             \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT           Context,                                \
+                      IN  PXENVIF_TRANSMITTER_PACKET    HeadPacket                              \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      QueryOffloadOptions,                                                      \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT       Context,                                    \
+                      OUT PXENVIF_OFFLOAD_OPTIONS   Options                                     \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      UpdateOffloadOptions,                                                     \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT       Context,                                    \
+                      IN  XENVIF_OFFLOAD_OPTIONS    Options                                     \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      QueryLargePacketSize,                                                     \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT   Context,                                        \
+                      IN  UCHAR                 Version,                                        \
+                      OUT PULONG                Size                                            \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      QueryMediaState,                                                          \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT           Context,                                \
+                      OUT PNET_IF_MEDIA_CONNECT_STATE   MediaConnectState OPTIONAL,             \
+                      OUT PULONG64                      LinkSpeed OPTIONAL,                     \
+                      OUT PNET_IF_MEDIA_DUPLEX_STATE    MediaDuplexState OPTIONAL               \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      QueryMaximumFrameSize,                                                    \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT   Context,                                        \
+                      OUT PULONG                Size                                            \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      QueryPermanentAddress,                                                    \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT   Context,                                        \
+                      OUT PETHERNET_ADDRESS     Address                                         \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      QueryCurrentAddress,                                                      \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT   Context,                                        \
+                      OUT PETHERNET_ADDRESS     Address                                         \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(NTSTATUS,                                                                 \
+                      UpdateCurrentAddress,                                                     \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT   Context,                                        \
+                      IN  PETHERNET_ADDRESS     Address                                         \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(NTSTATUS,                                                                 \
+                      QueryMulticastAddresses,                                                  \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT   Context,                                        \
+                      OUT PETHERNET_ADDRESS     Address OPTIONAL,                               \
+                      OUT PULONG                Count                                           \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(NTSTATUS,                                                                 \
+                      UpdateMulticastAddresses,                                                 \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT   Context,                                        \
+                      IN  PETHERNET_ADDRESS     Address,                                        \
+                      IN  ULONG                 Count                                           \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      QueryFilterLevel,                                                         \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT       Context,                                    \
+                      IN  ETHERNET_ADDRESS_TYPE     Type,                                       \
+                      OUT PXENVIF_MAC_FILTER_LEVEL  Level                                       \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(NTSTATUS,                                                                 \
+                      UpdateFilterLevel,                                                        \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT       Context,                                    \
+                      IN  ETHERNET_ADDRESS_TYPE     Type,                                       \
+                      IN  XENVIF_MAC_FILTER_LEVEL   Level                                       \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      QueryReceiverRingSize,                                                    \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT       Context,                                    \
+                      OUT PULONG                    Size                                        \
+                      )                                                                         \
+                      )                                                                         \
+        VIF_OPERATION(VOID,                                                                     \
+                      QueryTransmitterRingSize,                                                 \
+                      (                                                                         \
+                      IN  PXENVIF_VIF_CONTEXT       Context,                                    \
+                      OUT PULONG                    Size                                        \
+                      )                                                                         \
+                      )
+
+typedef struct _XENVIF_VIF_CONTEXT  XENVIF_VIF_CONTEXT, *PXENVIF_VIF_CONTEXT;
+
+#define VIF_OPERATION(_Type, _Name, _Arguments) \
+        _Type (*VIF_ ## _Name) _Arguments;
+
+typedef struct _XENVIF_VIF_OPERATIONS {
+    DEFINE_VIF_OPERATIONS
+} XENVIF_VIF_OPERATIONS, *PXENVIF_VIF_OPERATIONS;
+
+#undef VIF_OPERATION
+
+typedef struct _XENVIF_VIF_INTERFACE XENVIF_VIF_INTERFACE, *PXENVIF_VIF_INTERFACE;
+
+// {BAA55367-D5CD-4fab-8A2D-BB40476795C3}
+DEFINE_GUID(GUID_VIF_INTERFACE, 
+            0xbaa55367,
+            0xd5cd,
+            0x4fab,
+            0x8a,
+            0x2d,
+            0xbb,
+            0x40,
+            0x47,
+            0x67,
+            0x95,
+            0xc3);
+
+#define VIF_INTERFACE_VERSION    12
+
+#define VIF_OPERATIONS(_Interface) \
+        (PXENVIF_VIF_OPERATIONS *)((ULONG_PTR)(_Interface))
+
+#define VIF_CONTEXT(_Interface) \
+        (PXENVIF_VIF_CONTEXT *)((ULONG_PTR)(_Interface) + sizeof (PVOID))
+
+#define VIF(_Operation, _Interface, ...) \
+        (*VIF_OPERATIONS(_Interface))->VIF_ ## _Operation((*VIF_CONTEXT(_Interface)), __VA_ARGS__)
+
+#endif  // _XENVIF_INTERFACE_H
+
diff --git a/kdfiles.py b/kdfiles.py
new file mode 100644 (file)
index 0000000..7aaa586
--- /dev/null
@@ -0,0 +1,26 @@
+#!python -u
+
+import os, sys
+import subprocess
+import glob
+from pprint import pprint
+
+def regenerate_kdfiles(filename, arch, pkg, source):
+       cwd = os.getcwd()
+       file = open(filename, 'w')
+       os.chdir(pkg + '/' + arch)
+       drivers = glob.glob('*.sys')
+       pprint(drivers)
+       for driver in drivers:
+               file.write("map\n")
+               file.write('\SystemRoot\System32\drivers\\' + driver + '\n')
+               file.write(source + '\\' + pkg + '\\' + arch + '\\' + driver + '\n')
+               file.write('\n')
+       os.chdir(cwd)
+       file.close()
+
+if __name__ == '__main__':
+       pkg = 'xennet'
+       source = os.getcwd()
+       regenerate_kdfiles('kdfiles32.txt', 'x86', pkg, source)
+       regenerate_kdfiles('kdfiles64.txt', 'x64', pkg, source)
diff --git a/proj/msbuild.bat b/proj/msbuild.bat
new file mode 100644 (file)
index 0000000..0d3f6cb
--- /dev/null
@@ -0,0 +1,7 @@
+call "%VS%\VC\vcvarsall.bat" x86
+msbuild.exe /m:4 /p:Configuration="%CONFIGURATION%" /p:Platform="%PLATFORM%" /t:"%TARGET%" /p:SignMode="ProductionSign" %SOLUTION%.sln
+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..faddfee
--- /dev/null
@@ -0,0 +1,161 @@
+<?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>{445FD18F-97E3-4E5D-825F-151026242C05}</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="'$(Platform)'=='x64'">Vista_$(DDKPlatform);7_$(DDKPlatform);Server2008_$(DDKPlatform);Server2008R2_$(DDKPlatform)</Inf2CatWindowsVersionList>
+    <Inf2CatWindowsVersionList Condition="'$(Platform)'=='Win32'">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>..\..\xennet\$(DDKPlatform)</PackageDir>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\xennet\xennet.vcxproj">
+      <Project>{97D9942B-5EA3-488C-B512-C96E5D077F8E}</Project>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\xennet_coinst\xennet_coinst.vcxproj">
+      <Project>{3EDD837A-C1BE-47D4-9603-16B61353670B}</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>
\ No newline at end of file
diff --git a/proj/package/package.vcxproj.user b/proj/package/package.vcxproj.user
new file mode 100644 (file)
index 0000000..7dea6a2
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <SignMode>ProductionSign</SignMode>
+    <ProductionCertificate>CN="Citrix Systems, Inc.", OU=Digital ID Class 3 - Microsoft Software Validation v2, O="Citrix Systems, Inc.", L=Santa Clara, S=California, C=US | 9505C081954CC0A3E8B904458ACACD72EABD98B5</ProductionCertificate>
+    <TimeStampServer>http://timestamp.verisign.com/scripts/timstamp.dll</TimeStampServer>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/proj/xennet.sln b/proj/xennet.sln
new file mode 100644 (file)
index 0000000..93bb6df
--- /dev/null
@@ -0,0 +1,140 @@
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 11
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xennet", "xennet\xennet.vcxproj", "{97D9942B-5EA3-488C-B512-C96E5D077F8E}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xennet_coinst", "xennet_coinst\xennet_coinst.vcxproj", "{3EDD837A-C1BE-47D4-9603-16B61353670B}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "package\package.vcxproj", "{445FD18F-97E3-4E5D-825F-151026242C05}"
+       ProjectSection(ProjectDependencies) = postProject
+               {3EDD837A-C1BE-47D4-9603-16B61353670B} = {3EDD837A-C1BE-47D4-9603-16B61353670B}
+       EndProjectSection
+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
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Debug|Win32.ActiveCfg = Windows 7 Debug|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Debug|Win32.Build.0 = Windows 7 Debug|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Debug|Win32.Deploy.0 = Windows 7 Debug|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Debug|x64.ActiveCfg = Windows 7 Debug|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Debug|x64.Build.0 = Windows 7 Debug|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Debug|x64.Deploy.0 = Windows 7 Debug|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Release|Win32.ActiveCfg = Windows 7 Release|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Release|Win32.Build.0 = Windows 7 Release|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Release|Win32.Deploy.0 = Windows 7 Release|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Release|x64.ActiveCfg = Windows 7 Release|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Release|x64.Build.0 = Windows 7 Release|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows 7 Release|x64.Deploy.0 = Windows 7 Release|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Debug|Win32.ActiveCfg = Windows Developer Preview Debug|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Debug|Win32.Build.0 = Windows Developer Preview Debug|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Debug|Win32.Deploy.0 = Windows Developer Preview Debug|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Debug|x64.ActiveCfg = Windows Developer Preview Debug|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Debug|x64.Build.0 = Windows Developer Preview Debug|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Debug|x64.Deploy.0 = Windows Developer Preview Debug|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Release|Win32.ActiveCfg = Windows Developer Preview Release|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Release|Win32.Build.0 = Windows Developer Preview Release|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Release|Win32.Deploy.0 = Windows Developer Preview Release|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Release|x64.ActiveCfg = Windows Developer Preview Release|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Release|x64.Build.0 = Windows Developer Preview Release|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Developer Preview Release|x64.Deploy.0 = Windows Developer Preview Release|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Debug|Win32.ActiveCfg = Windows Vista Debug|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Debug|Win32.Build.0 = Windows Vista Debug|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Debug|Win32.Deploy.0 = Windows Vista Debug|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Debug|x64.ActiveCfg = Windows Vista Debug|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Debug|x64.Build.0 = Windows Vista Debug|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Debug|x64.Deploy.0 = Windows Vista Debug|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Release|Win32.ActiveCfg = Windows Vista Release|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Release|Win32.Build.0 = Windows Vista Release|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Release|Win32.Deploy.0 = Windows Vista Release|Win32
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Release|x64.ActiveCfg = Windows Vista Release|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Release|x64.Build.0 = Windows Vista Release|x64
+               {3EDD837A-C1BE-47D4-9603-16B61353670B}.Windows Vista Release|x64.Deploy.0 = Windows Vista Release|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Debug|Win32.ActiveCfg = Windows 7 Debug|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Debug|Win32.Build.0 = Windows 7 Debug|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Debug|Win32.Deploy.0 = Windows 7 Debug|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Debug|x64.ActiveCfg = Windows 7 Debug|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Debug|x64.Build.0 = Windows 7 Debug|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Debug|x64.Deploy.0 = Windows 7 Debug|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Release|Win32.ActiveCfg = Windows 7 Release|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Release|Win32.Build.0 = Windows 7 Release|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Release|Win32.Deploy.0 = Windows 7 Release|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Release|x64.ActiveCfg = Windows 7 Release|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Release|x64.Build.0 = Windows 7 Release|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows 7 Release|x64.Deploy.0 = Windows 7 Release|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Debug|Win32.ActiveCfg = Windows Developer Preview Debug|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Debug|Win32.Build.0 = Windows Developer Preview Debug|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Debug|Win32.Deploy.0 = Windows Developer Preview Debug|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Debug|x64.ActiveCfg = Windows Developer Preview Debug|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Debug|x64.Build.0 = Windows Developer Preview Debug|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Debug|x64.Deploy.0 = Windows Developer Preview Debug|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Release|Win32.ActiveCfg = Windows Developer Preview Release|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Release|Win32.Build.0 = Windows Developer Preview Release|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Release|Win32.Deploy.0 = Windows Developer Preview Release|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Release|x64.ActiveCfg = Windows Developer Preview Release|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Release|x64.Build.0 = Windows Developer Preview Release|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Developer Preview Release|x64.Deploy.0 = Windows Developer Preview Release|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Debug|Win32.ActiveCfg = Windows Vista Debug|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Debug|Win32.Build.0 = Windows Vista Debug|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Debug|Win32.Deploy.0 = Windows Vista Debug|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Debug|x64.ActiveCfg = Windows Vista Debug|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Debug|x64.Build.0 = Windows Vista Debug|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Debug|x64.Deploy.0 = Windows Vista Debug|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Release|Win32.ActiveCfg = Windows Vista Release|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Release|Win32.Build.0 = Windows Vista Release|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Release|Win32.Deploy.0 = Windows Vista Release|Win32
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Release|x64.ActiveCfg = Windows Vista Release|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Release|x64.Build.0 = Windows Vista Release|x64
+               {445FD18F-97E3-4E5D-825F-151026242C05}.Windows Vista Release|x64.Deploy.0 = Windows Vista Release|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Debug|Win32.ActiveCfg = Windows 7 Debug|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Debug|Win32.Build.0 = Windows 7 Debug|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Debug|Win32.Deploy.0 = Windows 7 Debug|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Debug|x64.ActiveCfg = Windows 7 Debug|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Debug|x64.Build.0 = Windows 7 Debug|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Debug|x64.Deploy.0 = Windows 7 Debug|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Release|Win32.ActiveCfg = Windows 7 Release|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Release|Win32.Build.0 = Windows 7 Release|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Release|Win32.Deploy.0 = Windows 7 Release|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Release|x64.ActiveCfg = Windows 7 Release|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Release|x64.Build.0 = Windows 7 Release|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows 7 Release|x64.Deploy.0 = Windows 7 Release|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Debug|Win32.ActiveCfg = Windows Developer Preview Debug|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Debug|Win32.Build.0 = Windows Developer Preview Debug|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Debug|Win32.Deploy.0 = Windows Developer Preview Debug|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Debug|x64.ActiveCfg = Windows Developer Preview Debug|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Debug|x64.Build.0 = Windows Developer Preview Debug|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Debug|x64.Deploy.0 = Windows Developer Preview Debug|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Release|Win32.ActiveCfg = Windows Developer Preview Release|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Release|Win32.Build.0 = Windows Developer Preview Release|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Release|Win32.Deploy.0 = Windows Developer Preview Release|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Release|x64.ActiveCfg = Windows Developer Preview Release|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Release|x64.Build.0 = Windows Developer Preview Release|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Developer Preview Release|x64.Deploy.0 = Windows Developer Preview Release|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Debug|Win32.ActiveCfg = Windows Vista Debug|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Debug|Win32.Build.0 = Windows Vista Debug|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Debug|Win32.Deploy.0 = Windows Vista Debug|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Debug|x64.ActiveCfg = Windows Vista Debug|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Debug|x64.Build.0 = Windows Vista Debug|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Debug|x64.Deploy.0 = Windows Vista Debug|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Release|Win32.ActiveCfg = Windows Vista Release|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Release|Win32.Build.0 = Windows Vista Release|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Release|Win32.Deploy.0 = Windows Vista Release|Win32
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Release|x64.ActiveCfg = Windows Vista Release|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Release|x64.Build.0 = Windows Vista Release|x64
+               {97D9942B-5EA3-488C-B512-C96E5D077F8E}.Windows Vista Release|x64.Deploy.0 = Windows Vista Release|x64
+       EndGlobalSection
+       GlobalSection(SolutionProperties) = preSolution
+               HideSolutionNode = FALSE
+       EndGlobalSection
+EndGlobal
diff --git a/proj/xennet/xennet.vcxproj b/proj/xennet/xennet.vcxproj
new file mode 100644 (file)
index 0000000..925df09
--- /dev/null
@@ -0,0 +1,190 @@
+<?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>{97D9942B-5EA3-488C-B512-C96E5D077F8E}</ProjectGuid>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+    <ProjectName>xennet</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="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__="XENNET";NDIS_MINIPORT_DRIVER;NDIS60_MINIPORT=1;POOL_NX_OPTIN=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <WarningLevel>EnableAllWarnings</WarningLevel>
+      <DisableSpecificWarnings>4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <EnablePREfast>true</EnablePREfast>
+    </ClCompile>
+    <Link>
+      <ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
+      <AdditionalDependencies>$(DDK_LIB_PATH)\ndis.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </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__="XENNET";NDIS_MINIPORT_DRIVER;NDIS60_MINIPORT=1;POOL_NX_OPTIN=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <WarningLevel>EnableAllWarnings</WarningLevel>
+      <DisableSpecificWarnings>4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <EnablePREfast>true</EnablePREfast>
+    </ClCompile>
+    <ResourceCompile>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+    <Link>
+      <AdditionalDependencies>$(DDK_LIB_PATH)\ndis.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <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/xennet/adapter.c" />
+    <ClCompile Include="../../src/xennet/main.c" />
+    <ClCompile Include="../../src/xennet/miniport.c" />
+    <ClCompile Include="../../src/xennet/receiver.c" />
+    <ClCompile Include="../../src/xennet/transmitter.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <ResourceCompile Include="..\..\src\xennet\xennet.rc" />
+  </ItemGroup>
+  <ItemGroup>
+    <Inf Include="..\xennet.inf" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
\ No newline at end of file
diff --git a/proj/xennet/xennet.vcxproj.user b/proj/xennet/xennet.vcxproj.user
new file mode 100644 (file)
index 0000000..7dea6a2
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <SignMode>ProductionSign</SignMode>
+    <ProductionCertificate>CN="Citrix Systems, Inc.", OU=Digital ID Class 3 - Microsoft Software Validation v2, O="Citrix Systems, Inc.", L=Santa Clara, S=California, C=US | 9505C081954CC0A3E8B904458ACACD72EABD98B5</ProductionCertificate>
+    <TimeStampServer>http://timestamp.verisign.com/scripts/timstamp.dll</TimeStampServer>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/proj/xennet_coinst/xennet_coinst.vcxproj b/proj/xennet_coinst/xennet_coinst.vcxproj
new file mode 100644 (file)
index 0000000..a98e707
--- /dev/null
@@ -0,0 +1,177 @@
+<?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>{3EDD837A-C1BE-47D4-9603-16B61353670B}</ProjectGuid>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+    <ProjectName>xennet_coinst</ProjectName>
+  </PropertyGroup>
+  <PropertyGroup Label="PropertySheets">
+    <PlatformToolset>WindowsApplicationForDrivers8.0</PlatformToolset>
+    <ConfigurationType>DynamicLibrary</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="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup>
+    <DebuggerFlavor>DbgengKernelDebugger</DebuggerFlavor>
+  </PropertyGroup>
+  <PropertyGroup>
+    <IncludePath>$(IncludePath)</IncludePath>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <EnableInf2cat>false</EnableInf2cat>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Platform)'=='Win32'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>__i386__;__MODULE__="XENNET_COINST";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <WarningLevel>EnableAllWarnings</WarningLevel>
+      <DisableSpecificWarnings>4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <EnablePREfast>true</EnablePREfast>
+      <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary>
+      <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <ModuleDefinitionFile>../../src/coinst/xennet_coinst.def</ModuleDefinitionFile>
+      <AdditionalDependencies>setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <ResourceCompile>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Platform)'=='x64'">
+    <ClCompile>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      <PreprocessorDefinitions>__x86_64__;__MODULE__="XENNET_COINST";%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <WarningLevel>EnableAllWarnings</WarningLevel>
+      <DisableSpecificWarnings>4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>
+      <EnablePREfast>true</EnablePREfast>
+      <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='true'">MultiThreadedDebug</RuntimeLibrary>
+      <RuntimeLibrary Condition="'$(UseDebugLibraries)'=='false'">MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <ModuleDefinitionFile>../../src/coinst/xennet_coinst.def</ModuleDefinitionFile>
+      <AdditionalDependencies>setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <ResourceCompile>
+      <AdditionalIncludeDirectories>$(SolutionDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+    </ResourceCompile>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <FilesToPackage Include="$(TargetPath)" />
+    <FilesToPackage Include="$(OutDir)$(TargetName).pdb" />
+    <FilesToPackage Include="@(Inf->'%(CopyOutput)')" Condition="'@(Inf)'!=''" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="..\..\src\coinst\coinst.c" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="..\..\src\coinst\xennet_coinst.def" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+</Project>
\ No newline at end of file
diff --git a/proj/xennet_coinst/xennet_coinst.vcxproj.user b/proj/xennet_coinst/xennet_coinst.vcxproj.user
new file mode 100644 (file)
index 0000000..7dea6a2
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <SignMode>ProductionSign</SignMode>
+    <ProductionCertificate>CN="Citrix Systems, Inc.", OU=Digital ID Class 3 - Microsoft Software Validation v2, O="Citrix Systems, Inc.", L=Santa Clara, S=California, C=US | 9505C081954CC0A3E8B904458ACACD72EABD98B5</ProductionCertificate>
+    <TimeStampServer>http://timestamp.verisign.com/scripts/timstamp.dll</TimeStampServer>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/src/coinst/coinst.c b/src/coinst/coinst.c
new file mode 100644 (file)
index 0000000..62b4709
--- /dev/null
@@ -0,0 +1,2817 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#define INITGUID
+
+#include <windows.h>
+#include <Ifdef.h>
+#include <setupapi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strsafe.h>
+#include <malloc.h>
+
+#include <version.h>
+
+__user_code;
+
+#define MAXIMUM_BUFFER_SIZE 1024
+
+#define ENUM_KEY "SYSTEM\\CurrentControlSet\\Enum"
+
+#define CLASS_KEY "SYSTEM\\CurrentControlSet\\Control\\Class"
+
+#define SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services"
+
+#define NSI_KEY "SYSTEM\\CurrentControlSet\\Control\\Nsi"
+
+#define PARAMETERS_KEY(_Driver)    \
+        SERVICES_KEY ## "\\" ## #_Driver ## "\\Parameters"
+
+#define ALIASES_KEY(_Driver)    \
+        SERVICES_KEY ## "\\" ## #_Driver ## "\\Aliases"
+
+#define STATUS_KEY(_Driver)    \
+        SERVICES_KEY ## "\\" ## #_Driver ## "\\Status"
+
+#define SOFTWARE_KEY "SOFTWARE\\Citrix"
+
+#define NET_SETTINGS_KEY    \
+        SOFTWARE_KEY ## "\\" ## "XenToolsNetSettings\\XEN\\VIF"
+
+static VOID
+#pragma prefast(suppress:6262) // Function uses '1036' bytes of stack: exceeds /analyze:stacksize'1024'
+__Log(
+    IN  const CHAR  *Format,
+    IN  ...
+    )
+{
+    TCHAR               Buffer[MAXIMUM_BUFFER_SIZE];
+    va_list             Arguments;
+    size_t              Length;
+    SP_LOG_TOKEN        LogToken;
+    DWORD              Category;
+    DWORD               Flags;
+    HRESULT             Result;
+
+    va_start(Arguments, Format);
+    Result = StringCchVPrintf(Buffer, MAXIMUM_BUFFER_SIZE, Format, Arguments);
+    va_end(Arguments);
+
+    if (Result != S_OK && Result != STRSAFE_E_INSUFFICIENT_BUFFER)
+        return;
+
+    Result = StringCchLength(Buffer, MAXIMUM_BUFFER_SIZE, &Length);
+    if (Result != S_OK)
+        return;
+
+    LogToken = SetupGetThreadLogToken();
+    Category = TXTLOG_VENDOR;
+    Flags = TXTLOG_DETAILS;
+
+    SetupWriteTextLog(LogToken, Category, Flags, Buffer);
+
+    __analysis_assume(Length < MAXIMUM_BUFFER_SIZE);
+    __analysis_assume(Length >= 2);
+    Length = __min(MAXIMUM_BUFFER_SIZE - 1, Length + 2);
+    Buffer[Length] = '\0';
+    Buffer[Length - 1] = '\n';
+    Buffer[Length - 2] = '\r';
+
+    OutputDebugString(Buffer);
+}
+
+#define Log(_Format, ...) \
+        __Log(__MODULE__ "|" __FUNCTION__ ": " _Format, __VA_ARGS__)
+
+static PTCHAR
+GetErrorMessage(
+    IN  DWORD   Error
+    )
+{
+    PTCHAR      Message;
+    ULONG       Index;
+
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+                  FORMAT_MESSAGE_FROM_SYSTEM |
+                  FORMAT_MESSAGE_IGNORE_INSERTS,
+                  NULL,
+                  Error,
+                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                  (LPTSTR)&Message,
+                  0,
+                  NULL);
+
+    for (Index = 0; Message[Index] != '\0'; Index++) {
+        if (Message[Index] == '\r' || Message[Index] == '\n') {
+            Message[Index] = '\0';
+            break;
+        }
+    }
+
+    return Message;
+}
+
+static const CHAR *
+FunctionName(
+    IN  DI_FUNCTION Function
+    )
+{
+#define _NAME(_Function)        \
+        case DIF_ ## _Function: \
+            return #_Function;
+
+    switch (Function) {
+    _NAME(INSTALLDEVICE);
+    _NAME(REMOVE);
+    _NAME(SELECTDEVICE);
+    _NAME(ASSIGNRESOURCES);
+    _NAME(PROPERTIES);
+    _NAME(FIRSTTIMESETUP);
+    _NAME(FOUNDDEVICE);
+    _NAME(SELECTCLASSDRIVERS);
+    _NAME(VALIDATECLASSDRIVERS);
+    _NAME(INSTALLCLASSDRIVERS);
+    _NAME(CALCDISKSPACE);
+    _NAME(DESTROYPRIVATEDATA);
+    _NAME(VALIDATEDRIVER);
+    _NAME(MOVEDEVICE);
+    _NAME(DETECT);
+    _NAME(INSTALLWIZARD);
+    _NAME(DESTROYWIZARDDATA);
+    _NAME(PROPERTYCHANGE);
+    _NAME(ENABLECLASS);
+    _NAME(DETECTVERIFY);
+    _NAME(INSTALLDEVICEFILES);
+    _NAME(ALLOW_INSTALL);
+    _NAME(SELECTBESTCOMPATDRV);
+    _NAME(REGISTERDEVICE);
+    _NAME(NEWDEVICEWIZARD_PRESELECT);
+    _NAME(NEWDEVICEWIZARD_SELECT);
+    _NAME(NEWDEVICEWIZARD_PREANALYZE);
+    _NAME(NEWDEVICEWIZARD_POSTANALYZE);
+    _NAME(NEWDEVICEWIZARD_FINISHINSTALL);
+    _NAME(INSTALLINTERFACES);
+    _NAME(DETECTCANCEL);
+    _NAME(REGISTER_COINSTALLERS);
+    _NAME(ADDPROPERTYPAGE_ADVANCED);
+    _NAME(ADDPROPERTYPAGE_BASIC);
+    _NAME(TROUBLESHOOTER);
+    _NAME(POWERMESSAGEWAKE);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _NAME
+}
+
+#define MAXIMUM_DEVICE_NAME_LENGTH  32
+#define MAXIMUM_ALIAS_LENGTH        128
+
+typedef struct _EMULATED_DEVICE {
+    TCHAR   Device[MAXIMUM_DEVICE_NAME_LENGTH];
+    TCHAR   Alias[MAXIMUM_ALIAS_LENGTH];
+} EMULATED_DEVICE, *PEMULATED_DEVICE;
+
+static PEMULATED_DEVICE
+GetEmulatedDeviceTable(
+    VOID
+    )
+{
+    HKEY                Key;
+    HRESULT             Error;
+    DWORD               Values;
+    DWORD               Index;
+    PEMULATED_DEVICE    Table;
+
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         ALIASES_KEY(XENFILT) "\\VIF",
+                         0,
+                         KEY_READ,
+                         &Key);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    Error = RegQueryInfoKey(Key,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &Values,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    Table = malloc(sizeof (EMULATED_DEVICE) * (Values + 1));
+    if (Table == NULL)
+        goto fail3;
+
+    memset(Table, 0, sizeof (EMULATED_DEVICE) * (Values + 1));
+
+    for (Index = 0; Index < Values; Index++) {
+        PEMULATED_DEVICE    Entry = &Table[Index];
+        ULONG               DeviceNameLength;
+        ULONG               AliasLength;
+        ULONG               Type;
+
+        DeviceNameLength = MAXIMUM_DEVICE_NAME_LENGTH * sizeof (TCHAR);
+        AliasLength = MAXIMUM_ALIAS_LENGTH * sizeof (TCHAR);
+
+        Error = RegEnumValue(Key,
+                             Index,
+                             (LPTSTR)Entry->Device,
+                             &DeviceNameLength,
+                             NULL,
+                             &Type,
+                             (LPBYTE)Entry->Alias,
+                             &AliasLength);
+        if (Error != ERROR_SUCCESS) {
+            SetLastError(Error);
+            goto fail4;
+        }
+
+        if (Type != REG_SZ) {
+            SetLastError(ERROR_BAD_FORMAT);
+            goto fail5;
+        }
+    }
+
+    RegCloseKey(Key);
+
+    return Table;
+
+fail5:
+    Log("fail5");
+
+fail4:
+    Log("fail4");
+
+    free(Table);
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail2");
+
+    RegCloseKey(Key);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return NULL;
+}
+
+static DECLSPEC_NOINLINE HRESULT
+OpenSoftwareKey(
+    IN  HDEVINFO            DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA    DeviceInfoData,
+    OUT PHKEY               SoftwareKey
+    )
+{
+    HKEY                    Key;
+    HRESULT                 Error;
+
+    Key = SetupDiOpenDevRegKey(DeviceInfoSet,
+                               DeviceInfoData,
+                               DICS_FLAG_GLOBAL,
+                               0,
+                               DIREG_DRV,
+                               KEY_READ);
+    if (Key == INVALID_HANDLE_VALUE) {
+        SetLastError(ERROR_PATH_NOT_FOUND);
+        goto fail1;
+    }
+
+    *SoftwareKey = Key;
+
+    return ERROR_SUCCESS;
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return Error;
+}
+
+// {4d36e972-e325-11ce-bfc1-08002be10318}
+DEFINE_GUID(GUID_NET_DEVICE, 
+            0x4d36e972,
+            0xe325,
+            0x11ce,
+            0xbf,
+            0xc1,
+            0x08,
+            0x00,
+            0x2b,
+            0xe1,
+            0x03,
+            0x18
+            );
+
+static HRESULT
+OpenAliasHardwareKey(
+    IN  PTCHAR  AliasDeviceID,
+    IN  PTCHAR  AliasInstanceID,
+    OUT PHKEY   HardwareKey
+    )
+{
+    DWORD       PathLength;
+    PTCHAR      Path;
+    HRESULT     Result;
+    HKEY        Key;
+    HRESULT     Error;
+    DWORD       SubKeys;
+    DWORD       MaxSubKeyLength;
+    PTCHAR      Name;
+    DWORD       Index;
+    HKEY        SubKey;
+
+    Log("====> (%s) (%s)", AliasDeviceID, AliasInstanceID);
+
+    PathLength = (DWORD)(strlen(ENUM_KEY) +
+                         1 +
+                         strlen(AliasDeviceID) +
+                         1) * sizeof (TCHAR);
+
+    Path = malloc(PathLength);
+    if (Path == NULL)
+        goto fail1;
+
+    Result = StringCbPrintf(Path,
+                            PathLength,
+                            "%s\\%s",
+                            ENUM_KEY,
+                            AliasDeviceID);
+    if (!SUCCEEDED(Result)) {
+        SetLastError(ERROR_BUFFER_OVERFLOW);
+        goto fail2;
+    }
+
+    Log("%s", Path);
+
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         Path,
+                         0,
+                         KEY_READ,
+                         &Key);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail3;
+    }
+
+    Error = RegQueryInfoKey(Key,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &SubKeys,
+                            &MaxSubKeyLength,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail4;
+    }
+
+    Name = malloc(MaxSubKeyLength + sizeof (TCHAR));
+    if (Name == NULL)
+        goto fail5;
+
+    for (Index = 0; Index < SubKeys; Index++) {
+        DWORD   NameLength;
+        PTCHAR  InstanceID;
+
+        NameLength = MaxSubKeyLength + sizeof (TCHAR);
+        memset(Name, 0, NameLength);
+
+        Error = RegEnumKeyEx(Key,
+                             Index,
+                             (LPTSTR)Name,
+                             &NameLength,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL);
+        if (Error != ERROR_SUCCESS) {
+            SetLastError(Error);
+            goto fail6;
+        }
+
+        Log("%s", Name);
+
+        Error = RegOpenKeyEx(Key,
+                             Name,
+                             0,
+                             KEY_READ,
+                             &SubKey);
+        if (Error != ERROR_SUCCESS) {
+            SetLastError(Error);
+            goto fail7;
+        }
+
+        InstanceID = strrchr(Name, '&');
+        InstanceID++;
+
+        if (_stricmp(AliasInstanceID, InstanceID) == 0)
+            goto done;
+        
+        RegCloseKey(SubKey);
+    }
+
+    Error = ERROR_FILE_NOT_FOUND;
+    goto fail8;
+
+done:
+    free(Name);
+
+    RegCloseKey(Key);
+
+    free(Path);
+
+    *HardwareKey = SubKey;
+
+    Log("<====");
+
+    return ERROR_SUCCESS;
+
+fail8:
+    Log("fail8");
+
+fail7:
+    Log("fail7");
+
+fail6:
+    Log("fail6");
+
+    free(Name);
+
+fail5:
+    Log("fail5");
+
+fail4:
+    Log("fail4");
+
+    RegCloseKey(Key);
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail2");
+
+    free(Path);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return Error;
+}
+
+static HRESULT
+OpenAliasSoftwareKey(
+    IN  PTCHAR  Alias,
+    OUT PHKEY   SoftwareKey
+    )
+{
+    DWORD       BufferLength;
+    PTCHAR      Buffer;
+    PTCHAR      AliasDeviceID;
+    PTCHAR      AliasInstanceID;
+    HRESULT     Error;
+    HKEY        HardwareKey;
+    DWORD       MaxValueLength;
+    DWORD       DriverLength;
+    PTCHAR      Driver;
+    DWORD       Type;
+    DWORD       PathLength;
+    PTCHAR      Path;
+    HRESULT     Result;
+    HKEY        Key;
+
+    Log("====>");
+
+    BufferLength = (DWORD)(strlen(Alias) +
+                           1) * sizeof (TCHAR);
+
+    Buffer = malloc(BufferLength);
+    if (Buffer == NULL)
+        goto fail1;
+
+    memset(Buffer, 0, BufferLength);
+
+    memcpy(Buffer, Alias, strlen(Alias));
+
+    AliasDeviceID = Buffer;
+
+    AliasInstanceID = strchr(Buffer, '#');
+    *AliasInstanceID++ = '\0';
+
+    Error = OpenAliasHardwareKey(AliasDeviceID,
+                                 AliasInstanceID,
+                                 &HardwareKey);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    Error = RegQueryInfoKey(HardwareKey,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &MaxValueLength,
+                            NULL,
+                            NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail3;
+    }
+
+    DriverLength = MaxValueLength + sizeof (TCHAR);
+
+    Driver = malloc(DriverLength);
+    if (Driver == NULL)
+        goto fail4;
+
+    memset(Driver, 0, DriverLength);
+
+    Error = RegQueryValueEx(HardwareKey,
+                            "Driver",
+                            NULL,
+                            &Type,
+                            (LPBYTE)Driver,
+                            &DriverLength);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail5;
+    }
+
+    if (Type != REG_SZ) {
+        SetLastError(ERROR_BAD_FORMAT);
+        goto fail6;
+    }
+
+    Log("%s", Driver);
+
+    PathLength = (ULONG)(strlen(CLASS_KEY) +
+                         1 +
+                         strlen(Driver) +
+                         1) * sizeof (TCHAR);
+
+    Path = malloc(PathLength);
+    if (Path == NULL)
+        goto fail7;
+
+    Result = StringCbPrintf(Path,
+                            PathLength,
+                            "%s\\%s",
+                            CLASS_KEY,
+                            Driver);
+    if (!SUCCEEDED(Result)) {
+        SetLastError(ERROR_BUFFER_OVERFLOW);
+        goto fail8;
+    }
+
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         Path,
+                         0,
+                         KEY_READ,
+                         &Key);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail9;
+    }
+
+    free(Path);
+
+    free(Driver);
+
+    RegCloseKey(HardwareKey);
+
+    free(Buffer);
+
+    *SoftwareKey = Key;
+
+    Log("<====");
+
+    return ERROR_SUCCESS;
+
+fail9:
+    Log("fail9");
+
+fail8:
+    Log("fail8");
+
+    free(Path);
+
+fail7:
+    Log("fail7");
+
+fail6:
+    Log("fail6");
+
+fail5:
+    Log("fail5");
+
+    free(Driver);
+
+fail4:
+    Log("fail4");
+
+fail3:
+    Log("fail3");
+
+    RegCloseKey(HardwareKey);
+
+fail2:
+    Log("fail2");
+
+    free(Buffer);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return Error;
+}
+
+static PTCHAR
+GetInterface(
+    IN  HKEY    Key
+    )
+{
+    HRESULT     Error;
+    HKEY        SubKey;
+    DWORD       MaxValueLength;
+    DWORD       RootDeviceLength;
+    PTCHAR      RootDevice;
+    DWORD       Type;
+
+    Error = RegOpenKeyEx(Key,
+                         "Linkage",
+                         0,
+                         KEY_READ,
+                         &SubKey);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    Error = RegQueryInfoKey(SubKey,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &MaxValueLength,
+                            NULL,
+                            NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    RootDeviceLength = MaxValueLength + sizeof (TCHAR);
+
+    RootDevice = malloc(RootDeviceLength);
+    if (RootDevice == NULL)
+        goto fail2;
+
+    memset(RootDevice, 0, RootDeviceLength);
+
+    Error = RegQueryValueEx(SubKey,
+                            "RootDevice",
+                            NULL,
+                            &Type,
+                            (LPBYTE)RootDevice,
+                            &RootDeviceLength);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail3;
+    }
+
+    if (Type != REG_MULTI_SZ) {
+        SetLastError(ERROR_BAD_FORMAT);
+        goto fail4;
+    }
+
+    RegCloseKey(SubKey);
+
+    return RootDevice;
+
+fail4:
+    Log("fail4");
+
+fail3:
+    Log("fail3");
+
+    free(RootDevice);
+
+fail2:
+    Log("fail2");
+
+    RegCloseKey(SubKey);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return NULL;
+}
+
+static BOOLEAN
+CopyValues(
+    IN  PTCHAR  TargetPath,
+    IN  PTCHAR  SourcePath
+    )
+{
+    HKEY        TargetKey;
+    HKEY        SourceKey;
+    HRESULT     Error;
+    DWORD       Values;
+    DWORD       MaxNameLength;
+    PTCHAR      Name;
+    DWORD       MaxValueLength;
+    LPBYTE      Value;
+    DWORD       Index;
+
+    Log("TARGET: %s", TargetPath);
+    Log("SOURCE: %s", SourcePath);
+
+    Error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                           TargetPath,
+                           0,
+                           NULL,
+                           REG_OPTION_NON_VOLATILE,
+                           KEY_ALL_ACCESS,
+                           NULL,
+                           &TargetKey,
+                           NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         SourcePath,
+                         0,
+                         KEY_ALL_ACCESS,
+                         &SourceKey);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    Error = RegQueryInfoKey(SourceKey,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &Values,
+                            &MaxNameLength,
+                            &MaxValueLength,
+                            NULL,
+                            NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail3;
+    }
+
+    if (Values == 0)
+        goto done;
+
+    MaxNameLength += sizeof (TCHAR);
+
+    Name = malloc(MaxNameLength);
+    if (Name == NULL)
+        goto fail4;
+
+    Value = malloc(MaxValueLength);
+    if (Value == NULL)
+        goto fail5;
+
+    for (Index = 0; Index < Values; Index++) {
+        DWORD   NameLength;
+        DWORD   ValueLength;
+        DWORD   Type;
+
+        NameLength = MaxNameLength;
+        memset(Name, 0, NameLength);
+
+        ValueLength = MaxValueLength;
+        memset(Value, 0, ValueLength);
+
+        Error = RegEnumValue(SourceKey,
+                             Index,
+                             (LPTSTR)Name,
+                             &NameLength,
+                             NULL,
+                             &Type,
+                             Value,
+                             &ValueLength);
+        if (Error != ERROR_SUCCESS) {
+            SetLastError(Error);
+            goto fail6;
+        }
+
+        Error = RegSetValueEx(TargetKey,
+                              Name,
+                              0,
+                              Type,
+                              Value,
+                              ValueLength);
+        if (Error != ERROR_SUCCESS) {
+            SetLastError(Error);
+            goto fail7;
+        }
+
+        Log("COPIED %s", Name);
+    }
+
+    free(Value);
+    free(Name);
+
+    RegCloseKey(SourceKey);
+    RegCloseKey(TargetKey);
+
+done:
+    return TRUE;
+
+fail7:
+    Log("fail7");
+
+fail6:
+    Log("fail6");
+
+    free(Value);
+
+fail5:
+    Log("fail5");
+
+    free(Name);
+
+fail4:
+    Log("fail4");
+
+fail3:
+    Log("fail3");
+
+    RegCloseKey(SourceKey);
+
+fail2:
+    Log("fail2");
+
+    RegCloseKey(TargetKey);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static BOOLEAN
+CopyParameters(
+    IN  PTCHAR  TargetPrefix,
+    IN  PTCHAR  TargetNode,
+    IN  PTCHAR  SourcePrefix,
+    IN  PTCHAR  SourceNode
+    )
+{
+    DWORD       Length;
+    PTCHAR      SourcePath;
+    PTCHAR      TargetPath;
+    HRESULT     Result;
+    HRESULT     Error;
+    BOOLEAN     Success;
+
+    Length = (DWORD)((strlen(TargetPrefix) +
+                      strlen(TargetNode) +
+                      1) * sizeof (TCHAR));
+
+    TargetPath = malloc(Length);
+    if (TargetPath == NULL)
+        goto fail1;
+
+    Result = StringCbPrintf(TargetPath,
+                            Length,
+                            "%s%s",
+                            TargetPrefix,
+                            TargetNode);
+    if (!SUCCEEDED(Result)) {
+        SetLastError(ERROR_BUFFER_OVERFLOW);
+        goto fail2;
+    }
+
+    Length = (DWORD)((strlen(SourcePrefix) +
+                      strlen(SourceNode) +
+                      1) * sizeof (TCHAR));
+
+    SourcePath = malloc(Length);
+    if (SourcePath == NULL)
+        goto fail3;
+
+    Result = StringCbPrintf(SourcePath,
+                            Length,
+                            "%s%s",
+                            SourcePrefix,
+                            SourceNode);
+    if (!SUCCEEDED(Result)) {
+        SetLastError(ERROR_BUFFER_OVERFLOW);
+        goto fail4;
+    }
+
+    Success = CopyValues(TargetPath, SourcePath);
+
+    free(SourcePath);
+    free(TargetPath);
+
+    return Success;
+
+fail4:
+    Log("fail4");
+
+    free(SourcePath);
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail2");
+
+    free(TargetPath);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static BOOLEAN
+CopyIpVersion6Addresses(
+    IN  PTCHAR  TargetPath,
+    IN  PTCHAR  TargetPrefix,
+    IN  PTCHAR  SourcePath,
+    IN  PTCHAR  SourcePrefix
+    )
+{
+    HKEY        TargetKey;
+    HKEY        SourceKey;
+    HRESULT     Error;
+    DWORD       Values;
+    DWORD       MaxNameLength;
+    PTCHAR      Name;
+    DWORD       MaxValueLength;
+    LPBYTE      Value;
+    DWORD       Index;
+
+    Log("TARGET: %s", TargetPath);
+    Log("SOURCE: %s", SourcePath);
+
+    Error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                           TargetPath,
+                           0,
+                           NULL,
+                           REG_OPTION_NON_VOLATILE,
+                           KEY_ALL_ACCESS,
+                           NULL,
+                           &TargetKey,
+                           NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         SourcePath,
+                         0,
+                         KEY_ALL_ACCESS,
+                         &SourceKey);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail2;
+    }
+
+    Error = RegQueryInfoKey(SourceKey,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &Values,
+                            &MaxNameLength,
+                            &MaxValueLength,
+                            NULL,
+                            NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail3;
+    }
+
+    if (Values == 0)
+        goto done;
+
+    MaxNameLength += sizeof (TCHAR);
+
+    Name = malloc(MaxNameLength);
+    if (Name == NULL)
+        goto fail4;
+
+    Value = malloc(MaxValueLength);
+    if (Value == NULL)
+        goto fail5;
+
+    for (Index = 0; Index < Values; Index++) {
+        DWORD   NameLength;
+        DWORD   ValueLength;
+        DWORD   Type;
+
+        NameLength = MaxNameLength;
+        memset(Name, 0, NameLength);
+
+        ValueLength = MaxValueLength;
+        memset(Value, 0, ValueLength);
+
+        Error = RegEnumValue(SourceKey,
+                             Index,
+                             (LPTSTR)Name,
+                             &NameLength,
+                             NULL,
+                             &Type,
+                             Value,
+                             &ValueLength);
+        if (Error != ERROR_SUCCESS) {
+            SetLastError(Error);
+            goto fail6;
+        }
+
+        if (strncmp(Name, SourcePrefix, sizeof (ULONG64) * 2) != 0)
+            continue;
+
+        Log("READ: %s", Name);
+
+        memcpy(Name, TargetPrefix, sizeof (ULONG64) * 2);
+
+        Log("WRITE: %s", Name);
+
+        Error = RegSetValueEx(TargetKey,
+                              Name,
+                              0,
+                              Type,
+                              Value,
+                              ValueLength);
+        if (Error != ERROR_SUCCESS) {
+            SetLastError(Error);
+            goto fail7;
+        }
+    }
+
+    free(Value);
+    free(Name);
+
+    RegCloseKey(SourceKey);
+    RegCloseKey(TargetKey);
+
+done:
+
+    return TRUE;
+
+fail7:
+    Log("fail7");
+
+fail6:
+    Log("fail6");
+
+    free(Value);
+
+fail5:
+    Log("fail5");
+
+    free(Name);
+
+fail4:
+    Log("fail4");
+
+fail3:
+    Log("fail3");
+
+    RegCloseKey(SourceKey);
+
+fail2:
+    Log("fail2");
+
+    RegCloseKey(TargetKey);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static PTCHAR
+GetNetLuid(
+    IN  HKEY    Key
+    )
+{
+    HRESULT     Error;
+    DWORD       MaxValueLength;
+    DWORD       ValueLength;
+    LPDWORD     Value;
+    DWORD       Type;
+    NET_LUID    NetLuid;
+    DWORD       BufferLength;
+    PTCHAR      Buffer;
+    HRESULT     Result;
+
+    memset(&NetLuid, 0, sizeof (NetLuid));
+
+    Error = RegQueryInfoKey(Key,
+                            NULL,
+                            NULL,
+                            NULL,    
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &MaxValueLength,
+                            NULL,
+                            NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    ValueLength = MaxValueLength;
+
+    Value = malloc(ValueLength);
+    if (Value == NULL)
+        goto fail2;
+
+    memset(Value, 0, ValueLength);
+
+    Error = RegQueryValueEx(Key,
+                            "NetLuidIndex",
+                            NULL,
+                            &Type,
+                            (LPBYTE)Value,
+                            &ValueLength);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail3;
+    }
+
+    if (Type != REG_DWORD) {
+        SetLastError(ERROR_BAD_FORMAT);
+        goto fail4;
+    }
+
+    NetLuid.Info.NetLuidIndex = *Value;
+
+    Error = RegQueryValueEx(Key,
+                            "*IfType",
+                            NULL,
+                            &Type,
+                            (LPBYTE)Value,
+                            &ValueLength);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail5;
+    }
+
+    if (Type != REG_DWORD) {
+        SetLastError(ERROR_BAD_FORMAT);
+        goto fail6;
+    }
+
+    NetLuid.Info.IfType = *Value;
+
+    BufferLength = ((sizeof (ULONG64) * 2) + 1) * sizeof (TCHAR);
+
+    Buffer = malloc(BufferLength);
+    if (Buffer == NULL)
+        goto fail7;
+
+    Result = StringCbPrintf(Buffer,
+                            BufferLength,
+                            "%016llx",
+                            _byteswap_uint64(NetLuid.Value));
+    if (!SUCCEEDED(Result)) {
+        SetLastError(ERROR_BUFFER_OVERFLOW);
+        goto fail8;
+    }
+
+    free(Value);
+
+    return Buffer;
+
+fail8:
+    Log("fail8");
+
+    free(Buffer);
+
+fail7:
+    Log("fail7");
+
+fail6:
+    Log("fail6");
+
+fail5:
+    Log("fail5");
+
+fail4:
+    Log("fail4");
+
+fail3:
+    Log("fail3");
+
+    free(Value);
+
+fail2:
+    Log("fail2");
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return NULL;
+}
+
+static BOOLEAN
+MigrateSettings(
+    IN  HKEY    SourceKey,
+    IN  HKEY    TargetKey
+    )
+{
+    PTCHAR      SourcePrefix;
+    PTCHAR      TargetPrefix;
+    BOOLEAN     Success;
+    HRESULT     Error;
+
+    Log("====>");
+
+    Success = TRUE;
+
+    SourcePrefix = GetInterface(SourceKey);
+
+    if (SourcePrefix == NULL)
+        goto fail1;
+
+    TargetPrefix = GetInterface(TargetKey);
+
+    if (TargetPrefix == NULL)
+        goto fail2;
+
+    Success &= CopyParameters(PARAMETERS_KEY(NetBT) "\\Interfaces\\Tcpip_", TargetPrefix,
+                              PARAMETERS_KEY(NetBT) "\\Interfaces\\Tcpip_", SourcePrefix);
+    Success &= CopyParameters(PARAMETERS_KEY(Tcpip) "\\Interfaces\\", TargetPrefix,
+                              PARAMETERS_KEY(Tcpip) "\\Interfaces\\", SourcePrefix);
+    Success &= CopyParameters(PARAMETERS_KEY(Tcpip6) "\\Interfaces\\", TargetPrefix,
+                              PARAMETERS_KEY(Tcpip6) "\\Interfaces\\", SourcePrefix);
+
+    free(TargetPrefix);
+    free(SourcePrefix);
+
+    SourcePrefix = GetNetLuid(SourceKey);
+
+    if (SourcePrefix == NULL)
+        goto fail3;
+
+    TargetPrefix = GetNetLuid(TargetKey);
+
+    if (TargetPrefix == NULL)
+        goto fail4;
+
+    Success &= CopyIpVersion6Addresses(NSI_KEY "\\{eb004a01-9b1a-11d4-9123-0050047759bc}\\10\\", TargetPrefix,
+                                       NSI_KEY "\\{eb004a01-9b1a-11d4-9123-0050047759bc}\\10\\", SourcePrefix);
+
+    free(TargetPrefix);
+    free(SourcePrefix);
+
+    Log("<====");
+
+    return Success;
+
+fail4:
+    Log("fail4");
+
+    free(SourcePrefix);
+    goto fail1;
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail2");
+
+    free(SourcePrefix);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static FORCEINLINE BOOLEAN
+__MigrateFromEmulated(
+    IN  PTCHAR              Location,
+    IN  HDEVINFO            DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA    DeviceInfoData
+    )
+{
+    PEMULATED_DEVICE        Table;
+    DWORD                   Index;
+    BOOLEAN                 Success;
+    HRESULT                 Error;
+    HKEY                    SourceKey;
+    HKEY                    TargetKey;
+
+    Log("====>");
+
+    Table = GetEmulatedDeviceTable();
+    if (Table == NULL)
+        goto fail1;
+
+    Success = FALSE;
+
+    for (Index = 0; strlen(Table[Index].Alias) != 0; Index++) {
+        if (_stricmp(Location, Table[Index].Device) == 0) {
+            Error = OpenAliasSoftwareKey(Table[Index].Alias,
+                                         &SourceKey);
+            if (Error != ERROR_SUCCESS)
+                goto fail2;
+
+            Error = OpenSoftwareKey(DeviceInfoSet,
+                                    DeviceInfoData,
+                                    &TargetKey);
+            if (Error != ERROR_SUCCESS)
+                goto fail3;
+
+            Success = MigrateSettings(SourceKey, TargetKey);
+
+            RegCloseKey(TargetKey);
+            RegCloseKey(SourceKey);
+
+            break;
+        }
+    }
+
+    free(Table);
+
+    Log("<====");
+
+    return Success;
+
+fail3:
+    RegCloseKey(SourceKey);
+
+fail2:
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static FORCEINLINE BOOLEAN
+__MigrateToEmulated(
+    IN  HDEVINFO            DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA    DeviceInfoData,
+    IN  PTCHAR              Location
+    )
+{
+    PEMULATED_DEVICE        Table;
+    DWORD                   Index;
+    BOOLEAN                 Success;
+    HRESULT                 Error;
+    HKEY                    SourceKey;
+    HKEY                    TargetKey;
+
+    Log("====>");
+
+    Table = GetEmulatedDeviceTable();
+    if (Table == NULL)
+        goto fail1;
+
+    Success = FALSE;
+
+    for (Index = 0; strlen(Table[Index].Alias) != 0; Index++) {
+        if (_stricmp(Location, Table[Index].Device) == 0) {
+            Error = OpenSoftwareKey(DeviceInfoSet,
+                                    DeviceInfoData,
+                                    &SourceKey);
+            if (Error != ERROR_SUCCESS)
+                goto fail3;
+
+            Error = OpenAliasSoftwareKey(Table[Index].Alias,
+                                         &TargetKey);
+            if (Error != ERROR_SUCCESS)
+                goto fail2;
+
+            Success = MigrateSettings(SourceKey, TargetKey);
+            break;
+        }
+    }
+
+    free(Table);
+
+    Log("<====");
+
+    return Success;
+
+fail3:
+    RegCloseKey(SourceKey);
+
+fail2:
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static FORCEINLINE BOOLEAN
+__MigrateFromPV(
+    IN  PTCHAR              Location,
+    IN  HDEVINFO            DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA    DeviceInfoData
+    )
+{
+    HKEY                    TargetKey;
+    PTCHAR                  TargetPrefix;
+    DWORD                   Length;
+    PTCHAR                  SourcePrefix;
+    BOOLEAN                 Success;
+    HRESULT                 Result;
+    HRESULT                 Error;
+
+    Log("====>");
+
+    Success = TRUE;
+
+    Length = (DWORD)((strlen(NET_SETTINGS_KEY) +
+                      strlen("\\") +
+                      strlen(Location) +
+                      strlen("\\") +
+                      1) * sizeof (TCHAR));
+
+    SourcePrefix = malloc(Length);
+    if (SourcePrefix == NULL)
+        goto fail1;
+
+    Result = StringCbPrintf(SourcePrefix,
+                            Length,
+                            "%s\\%s\\",
+                            NET_SETTINGS_KEY,
+                            Location);
+    if (!SUCCEEDED(Result)) {
+        SetLastError(ERROR_BUFFER_OVERFLOW);
+        goto fail2;
+    }
+
+    Error = OpenSoftwareKey(DeviceInfoSet,
+                            DeviceInfoData,
+                            &TargetKey);
+    if (Error != ERROR_SUCCESS)
+        goto fail3;
+
+    TargetPrefix = GetInterface(TargetKey);
+
+    if (TargetPrefix == NULL)
+        goto fail4;
+
+    Success &= CopyParameters(PARAMETERS_KEY(NetBT) "\\Interfaces\\Tcpip_", TargetPrefix,
+                              SourcePrefix, "nbt");
+    Success &= CopyParameters(PARAMETERS_KEY(Tcpip) "\\Interfaces\\", TargetPrefix,
+                              SourcePrefix, "tcpip");
+    Success &= CopyParameters(PARAMETERS_KEY(Tcpip6) "\\Interfaces\\", TargetPrefix,
+                              SourcePrefix, "tcpip6");
+
+    free(TargetPrefix);
+
+    TargetPrefix = GetNetLuid(TargetKey);
+
+    if (TargetPrefix == NULL)
+        goto fail5;
+
+    Success &= CopyIpVersion6Addresses(NSI_KEY "\\{eb004a01-9b1a-11d4-9123-0050047759bc}\\10\\", TargetPrefix,
+                                       SourcePrefix, "IPv6_Address____");
+
+    free(TargetPrefix);
+
+    RegCloseKey(TargetKey);
+    free(SourcePrefix);
+
+    Log("<====");
+
+    return Success;
+
+fail5:
+    Log("fail5");
+
+fail4:
+    Log("fail4");
+
+    RegCloseKey(TargetKey);
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail");
+
+    free(SourcePrefix);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static FORCEINLINE BOOLEAN
+__MigrateToPV(
+    IN  HDEVINFO            DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA    DeviceInfoData,
+    IN  PTCHAR              Location
+    )
+{
+    PTCHAR                  TargetPrefix;
+    DWORD                   Length;
+    HKEY                    SourceKey;
+    PTCHAR                  SourcePrefix;
+    BOOLEAN                 Success;
+    HRESULT                 Result;
+    HRESULT                 Error;
+
+    Log("====>");
+
+    Success = TRUE;
+
+    Length = (DWORD)((strlen(NET_SETTINGS_KEY) +
+                      strlen("\\") +
+                      strlen(Location) +
+                      strlen("\\") +
+                      1) * sizeof (TCHAR));
+
+    TargetPrefix = malloc(Length);
+    if (TargetPrefix == NULL)
+        goto fail1;
+
+    Result = StringCbPrintf(TargetPrefix,
+                            Length,
+                            "%s\\%s\\",
+                            NET_SETTINGS_KEY,
+                            Location);
+    if (!SUCCEEDED(Result)) {
+        SetLastError(ERROR_BUFFER_OVERFLOW);
+        goto fail2;
+    }
+
+    Error = OpenSoftwareKey(DeviceInfoSet,
+                            DeviceInfoData,
+                            &SourceKey);
+    if (Error != ERROR_SUCCESS)
+        goto fail3;
+
+    SourcePrefix = GetInterface(SourceKey);
+
+    if (SourcePrefix == NULL)
+        goto fail4;
+
+    Success &= CopyParameters(TargetPrefix, "nbt",
+                              PARAMETERS_KEY(NetBT) "\\Interfaces\\Tcpip_", SourcePrefix);
+    Success &= CopyParameters(TargetPrefix, "tcpip",
+                              PARAMETERS_KEY(Tcpip) "\\Interfaces\\", SourcePrefix);
+    Success &= CopyParameters(TargetPrefix, "tcpip6",
+                              PARAMETERS_KEY(Tcpip6) "\\Interfaces\\", SourcePrefix);
+
+    free(SourcePrefix);
+
+    SourcePrefix = GetNetLuid(SourceKey);
+
+    if (SourcePrefix == NULL)
+        goto fail5;
+
+    Success &= CopyIpVersion6Addresses(TargetPrefix, "IPv6_Address____",
+                                       NSI_KEY "\\{eb004a01-9b1a-11d4-9123-0050047759bc}\\10\\", SourcePrefix);
+
+    free(SourcePrefix);
+
+    RegCloseKey(SourceKey);
+    free(TargetPrefix);
+
+    Log("<====");
+
+    return Success;
+
+fail5:
+    Log("fail5");
+
+fail4:
+    Log("fail4");
+
+    RegCloseKey(SourceKey);
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail2");
+
+    free(TargetPrefix);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static PTCHAR
+GetProperty(
+    IN  HDEVINFO            DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA    DeviceInfoData,
+    IN  DWORD               Index
+    )
+{
+    DWORD                   Type;
+    DWORD                   PropertyLength;
+    PTCHAR                  Property;
+    HRESULT                 Error;
+
+    if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
+                                          DeviceInfoData,
+                                          Index,
+                                          &Type,
+                                          NULL,
+                                          0,
+                                          &PropertyLength)) {
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+            goto fail1;
+    }
+
+    if (Type != REG_SZ) {
+        SetLastError(ERROR_BAD_FORMAT);
+        goto fail2;
+    }
+
+    PropertyLength += sizeof (TCHAR);
+
+    Property = malloc(PropertyLength);
+    if (Property == NULL)
+        goto fail3;
+
+    memset(Property, 0, PropertyLength);
+
+    if (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet,
+                                          DeviceInfoData,
+                                          Index,
+                                          NULL,
+                                          (PBYTE)Property,
+                                          PropertyLength,
+                                          NULL))
+        goto fail4;
+
+    return Property;
+
+fail4:
+    free(Property);
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail2");
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return NULL;
+}
+
+static BOOLEAN
+SetFriendlyName(
+    IN  HDEVINFO            DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA    DeviceInfoData,
+    IN  PTCHAR              Description,
+    IN  PTCHAR              Location
+    )
+{
+    TCHAR                   FriendlyName[MAX_PATH];
+    DWORD                   FriendlyNameLength;
+    HRESULT                 Result;
+    HRESULT                 Error;
+
+    Result = StringCbPrintf(FriendlyName,
+                            MAX_PATH,
+                            TEXT("%s #%s"),
+                            Description,
+                            Location);
+    if (!SUCCEEDED(Result))
+        goto fail1;
+
+    FriendlyNameLength = (DWORD)(strlen(FriendlyName) + sizeof (TCHAR));
+
+    if (!SetupDiSetDeviceRegistryProperty(DeviceInfoSet,
+                                          DeviceInfoData,
+                                          SPDRP_FRIENDLYNAME,
+                                          (PBYTE)FriendlyName,
+                                          FriendlyNameLength))
+        goto fail2;
+
+    Log("%s", FriendlyName);
+
+    return TRUE;
+
+fail2:
+    Log("fail2");
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static BOOLEAN
+InstallDevice(
+    IN  PTCHAR  Class,
+    IN  PTCHAR  Device
+    )
+{
+    HKEY        Key;
+    DWORD       OldLength;
+    DWORD       NewLength;
+    DWORD       Type;
+    HRESULT     Error;
+    PTCHAR      Devices;
+    ULONG       Offset;
+
+    Error = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
+                           PARAMETERS_KEY(XENFILT),
+                           0,
+                           NULL,
+                           REG_OPTION_NON_VOLATILE,
+                           KEY_ALL_ACCESS,
+                           NULL,
+                           &Key,
+                           NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    OldLength = 0;
+    Error = RegQueryValueEx(Key,
+                            Class,
+                            NULL,
+                            &Type,
+                            NULL,
+                            &OldLength);
+    if (Error != ERROR_SUCCESS) {
+        if (Error != ERROR_FILE_NOT_FOUND) {
+            SetLastError(Error);
+            goto fail2;
+        }
+
+        OldLength = sizeof (TCHAR);
+        Type = REG_MULTI_SZ;
+    }
+
+    if (Type != REG_MULTI_SZ) {
+        SetLastError(ERROR_BAD_FORMAT);
+        goto fail3;
+    }
+
+    NewLength = OldLength + (DWORD)((strlen(Device) + 1) * sizeof (TCHAR));
+
+    Devices = malloc(NewLength);
+    if (Devices == NULL)
+        goto fail4;
+
+    memset(Devices, 0, NewLength);
+
+    Offset = 0;
+    if (OldLength != sizeof (TCHAR)) {
+        Error = RegQueryValueEx(Key,
+                                Class,
+                                NULL,
+                                NULL,
+                                (PBYTE)Devices,
+                                &OldLength);
+        if (Error != ERROR_SUCCESS) {
+            SetLastError(Error);
+            goto fail5;
+        }
+
+        while (Devices[Offset] != '\0') {
+            ULONG   DeviceLength;
+
+            DeviceLength = (ULONG)strlen(&Devices[Offset]) / sizeof (TCHAR);
+
+            if (_stricmp(&Devices[Offset], Device) == 0) {
+                Log("%s already present", Device);
+                goto done;
+            }
+
+            Offset += DeviceLength + 1;
+        }
+    }
+
+    memmove(&Devices[Offset], Device, strlen(Device));
+    Log("added %s", Device);
+
+    Error = RegSetValueEx(Key,
+                          Class,
+                          0,
+                          Type,
+                          (PBYTE)Devices,
+                          NewLength);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail6;
+    }
+
+done:
+    free(Devices);
+
+    RegCloseKey(Key);
+
+    return TRUE;
+
+fail6:
+    Log("fail6");
+
+fail5:
+    Log("fail5");
+
+    free(Devices);
+
+fail4:
+    Log("fail4");
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail2");
+
+    RegCloseKey(Key);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static BOOLEAN
+RemoveDevice(
+    IN  PTCHAR  Class,
+    IN  PTCHAR  Device
+    )
+{
+    HKEY        Key;
+    DWORD       OldLength;
+    DWORD       NewLength;
+    DWORD       Type;
+    HRESULT     Error;
+    PTCHAR      Devices;
+    ULONG       Offset;
+    ULONG       DeviceLength;
+
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         PARAMETERS_KEY(XENFILT),
+                         0,
+                         KEY_ALL_ACCESS,
+                         &Key);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    OldLength = 0;
+    Error = RegQueryValueEx(Key,
+                            Class,
+                            NULL,
+                            &Type,
+                            NULL,
+                            &OldLength);
+    if (Error != ERROR_SUCCESS) {
+        if (Error != ERROR_FILE_NOT_FOUND) {
+            SetLastError(Error);
+            goto fail2;
+        }
+
+        goto done;
+    }
+
+    if (Type != REG_MULTI_SZ) {
+        SetLastError(ERROR_BAD_FORMAT);
+        goto fail3;
+    }
+
+    Devices = malloc(OldLength);
+    if (Devices == NULL)
+        goto fail4;
+
+    memset(Devices, 0, OldLength);
+
+    Error = RegQueryValueEx(Key,
+                            Class,
+                            NULL,
+                            NULL,
+                            (PBYTE)Devices,
+                            &OldLength);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail5;
+    }
+
+    Offset = 0;
+    DeviceLength = 0;
+    while (Devices[Offset] != '\0') {
+        DeviceLength = (ULONG)strlen(&Devices[Offset]) / sizeof (TCHAR);
+
+        if (_stricmp(&Devices[Offset], Device) == 0)
+            goto remove;
+
+        Offset += DeviceLength + 1;
+    }
+
+    free(Devices);
+    goto done;
+
+remove:
+    NewLength = OldLength - ((DeviceLength + 1) * sizeof (TCHAR));
+
+    memmove(&Devices[Offset],
+            &Devices[Offset + DeviceLength + 1],
+            (NewLength - Offset) * sizeof (TCHAR));
+            
+    Log("removed %s", Device);
+
+    if (NewLength == 1) {
+        Error = RegDeleteValue(Key,
+                               Class);
+    } else {
+        Error = RegSetValueEx(Key,
+                              Class,
+                              0,
+                              Type,
+                              (PBYTE)Devices,
+                              NewLength);
+    }
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail6;
+    }
+
+    free(Devices);
+
+done:
+    RegCloseKey(Key);
+
+    return TRUE;
+
+fail6:
+    Log("fail6");
+
+fail5:
+    Log("fail5");
+
+    free(Devices);
+
+fail4:
+    Log("fail4");
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail2");
+
+    RegCloseKey(Key);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static BOOLEAN
+IsDeviceEmulated(
+    IN  PTCHAR      Class,
+    IN  PTCHAR      Device,
+    OUT PBOOLEAN    Present
+    )
+{
+    HKEY            Key;
+    DWORD           Length;
+    DWORD           Type;
+    HRESULT         Error;
+    PTCHAR          Devices;
+    ULONG           Offset;
+
+    *Present = FALSE;
+
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         STATUS_KEY(XENFILT),
+                         0,
+                         KEY_READ,
+                         &Key);
+    if (Error != ERROR_SUCCESS) {
+        if (Error == ERROR_FILE_NOT_FOUND)
+            goto done;
+
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    Length = 0;
+    Error = RegQueryValueEx(Key,
+                            Class,
+                            NULL,
+                            &Type,
+                            NULL,
+                            &Length);
+    if (Error != ERROR_SUCCESS) {
+        if (Error == ERROR_FILE_NOT_FOUND)
+            goto done;
+    }
+
+    if (Type != REG_MULTI_SZ) {
+        SetLastError(ERROR_BAD_FORMAT);
+        goto fail2;
+    }
+
+    Devices = malloc(Length);
+    if (Devices == NULL)
+        goto fail3;
+
+    memset(Devices, 0, Length);
+
+    Error = RegQueryValueEx(Key,
+                            Class,
+                            NULL,
+                            NULL,
+                            (PBYTE)Devices,
+                            &Length);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail4;
+    }
+
+    Offset = 0;
+    while (Devices[Offset] != '\0') {
+        ULONG   DeviceLength;
+
+        DeviceLength = (ULONG)strlen(&Devices[Offset]) / sizeof (TCHAR);
+
+        if (_stricmp(&Devices[Offset], Device) == 0) {
+            *Present = TRUE;
+            break;
+        }
+
+        Offset += DeviceLength + 1;
+    }
+
+    free(Devices);
+
+    RegCloseKey(Key);
+
+done:
+    return TRUE;
+
+fail4:
+    Log("fail4");
+
+    free(Devices);
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail2");
+
+    RegCloseKey(Key);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static BOOLEAN
+RequestReboot(
+    IN  HDEVINFO            DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA    DeviceInfoData
+    )
+{
+    SP_DEVINSTALL_PARAMS    DeviceInstallParams;
+    HRESULT                 Error;
+
+    DeviceInstallParams.cbSize = sizeof (DeviceInstallParams);
+
+    if (!SetupDiGetDeviceInstallParams(DeviceInfoSet,
+                                       DeviceInfoData,
+                                       &DeviceInstallParams))
+        goto fail1;
+
+    DeviceInstallParams.Flags |= DI_NEEDREBOOT;
+
+    Log("Flags = %08x", DeviceInstallParams.Flags);
+
+    if (!SetupDiSetDeviceInstallParams(DeviceInfoSet,
+                                       DeviceInfoData,
+                                       &DeviceInstallParams))
+        goto fail2;
+
+    return TRUE;
+
+fail2:
+    Log("fail2");
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
+static FORCEINLINE HRESULT
+__DifInstallPreProcess(
+    IN  HDEVINFO                    DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA            DeviceInfoData,
+    IN  PCOINSTALLER_CONTEXT_DATA   Context
+    )
+{
+    HRESULT                         Error;
+    HKEY                            Key;
+    PTCHAR                          Interface;
+    BOOLEAN                         NeedMigrateSettings;
+
+    Log("====>");
+
+    Error = OpenSoftwareKey(DeviceInfoSet,
+                            DeviceInfoData,
+                            &Key);
+
+    if (Error == ERROR_SUCCESS) {
+        Interface = GetInterface(Key);
+        RegCloseKey(Key);
+    } else {
+        Interface = NULL;
+    }
+
+    if (Interface != NULL) {
+        free(Interface);
+
+        NeedMigrateSettings = FALSE;
+    } else {
+        NeedMigrateSettings = TRUE;
+    }
+
+    Log("NeedMigrateSettings = %s",
+        (NeedMigrateSettings) ? "TRUE" : "FALSE");
+
+    Context->PrivateData = (PVOID)NeedMigrateSettings;
+
+    Log("<====");
+
+    return ERROR_DI_POSTPROCESSING_REQUIRED; 
+}
+
+static FORCEINLINE HRESULT
+__DifInstallPostProcess(
+    IN  HDEVINFO                    DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA            DeviceInfoData,
+    IN  PCOINSTALLER_CONTEXT_DATA   Context
+    )
+{
+    HRESULT                         Error;
+    BOOLEAN                         NeedMigrateSettings;
+    PTCHAR                          Description;
+    PTCHAR                          Location;
+    BOOLEAN                         MigratedSettings;
+    BOOLEAN                         Present;
+    BOOLEAN                         Success;
+
+    Log("====>");
+
+    Error = Context->InstallResult;
+    if (Error != NO_ERROR) {
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    NeedMigrateSettings = (BOOLEAN)(ULONG_PTR)Context->PrivateData;
+
+    Description = GetProperty(DeviceInfoSet, DeviceInfoData, SPDRP_DEVICEDESC);
+    if (Description == NULL)
+        goto fail2;
+
+    Location = GetProperty(DeviceInfoSet, DeviceInfoData, SPDRP_LOCATION_INFORMATION);
+    if (Location == NULL)
+        goto fail3;
+
+    Success = SetFriendlyName(DeviceInfoSet, DeviceInfoData, Description, Location);
+    if (!Success)
+        goto fail4;
+
+    MigratedSettings = FALSE;
+
+    if (NeedMigrateSettings) {
+        MigratedSettings = __MigrateFromPV(Location, DeviceInfoSet, DeviceInfoData);
+        if (!MigratedSettings)
+            MigratedSettings = __MigrateFromEmulated(Location, DeviceInfoSet, DeviceInfoData);
+    }
+
+    Success = InstallDevice("VIF", Location);
+    if (!Success)
+        goto fail5;
+
+    Success = IsDeviceEmulated("VIF", Location, &Present);
+    if (!Success)
+        goto fail6;
+
+    if (!MigratedSettings && !Present)
+        goto done;
+
+    Success = RequestReboot(DeviceInfoSet, DeviceInfoData);
+    if (!Success)
+        goto fail7;
+
+done:
+    free(Location);
+    free(Description);
+
+    Log("<====");
+
+    return NO_ERROR;
+
+fail7:
+    Log("fail7");
+
+fail6:
+    Log("fail6");
+
+fail5:
+    Log("fail5");
+
+fail4:
+    Log("fail4");
+
+    free(Location);
+
+fail3:
+    Log("fail3");
+
+    free(Description);
+
+fail2:
+    Log("fail2");
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return Error;
+}
+
+static DECLSPEC_NOINLINE HRESULT
+DifInstall(
+    IN  HDEVINFO                    DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA            DeviceInfoData,
+    IN  PCOINSTALLER_CONTEXT_DATA   Context
+    )
+{
+    SP_DEVINSTALL_PARAMS            DeviceInstallParams;
+    HRESULT                         Error;
+
+    DeviceInstallParams.cbSize = sizeof (DeviceInstallParams);
+
+    if (!SetupDiGetDeviceInstallParams(DeviceInfoSet,
+                                       DeviceInfoData,
+                                       &DeviceInstallParams))
+        goto fail1;
+
+    Log("Flags = %08x", DeviceInstallParams.Flags);
+
+    Error = (!Context->PostProcessing) ?
+            __DifInstallPreProcess(DeviceInfoSet, DeviceInfoData, Context) :
+            __DifInstallPostProcess(DeviceInfoSet, DeviceInfoData, Context);
+
+    return Error;
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return Error;
+}
+
+static FORCEINLINE HRESULT
+__DifRemovePreProcess(
+    IN  HDEVINFO                    DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA            DeviceInfoData,
+    IN  PCOINSTALLER_CONTEXT_DATA   Context
+    )
+{
+    PTCHAR                          Location;
+    HRESULT                         Error;
+
+    Log("====>");
+
+    Location = GetProperty(DeviceInfoSet, DeviceInfoData, SPDRP_LOCATION_INFORMATION);
+    if (Location == NULL)
+        goto fail1;
+
+    Context->PrivateData = Location;
+
+    (VOID) __MigrateToEmulated(DeviceInfoSet, DeviceInfoData, Location);
+    (VOID) __MigrateToPV(DeviceInfoSet, DeviceInfoData, Location);
+
+    Log("<====");
+
+    return ERROR_DI_POSTPROCESSING_REQUIRED; 
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return Error;
+}
+
+static FORCEINLINE HRESULT
+__DifRemovePostProcess(
+    IN  HDEVINFO                    DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA            DeviceInfoData,
+    IN  PCOINSTALLER_CONTEXT_DATA   Context
+    )
+{
+    HRESULT                         Error;
+    PTCHAR                          Location;
+    PEMULATED_DEVICE                Table;
+    BOOLEAN                         Success;
+
+    Log("====>");
+
+    Error = Context->InstallResult;
+    if (Error != NO_ERROR) {
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    Location = Context->PrivateData;
+
+    Success = RemoveDevice("VIF", Location);
+    if (!Success)
+        goto fail2;
+
+    Table = GetEmulatedDeviceTable();
+    if (Table == NULL) {
+        Success = FALSE;
+    } else {
+        ULONG   Index;
+
+        Success = TRUE;
+
+        for (Index = 0; strlen(Table[Index].Alias) != 0; Index++) {
+            if (_stricmp(Location, Table[Index].Device) == 0) {
+                Success = RequestReboot(DeviceInfoSet, DeviceInfoData);
+                break;
+            }
+        }
+
+        free(Table);
+    }
+
+    if (!Success)
+        goto fail3;
+
+    free(Location);
+
+    Log("<====");
+
+    return NO_ERROR;
+
+fail3:
+    Log("fail3");
+
+fail2:
+    Log("fail2");
+
+    free(Location);
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return Error;
+}
+
+static DECLSPEC_NOINLINE HRESULT
+DifRemove(
+    IN  HDEVINFO                    DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA            DeviceInfoData,
+    IN  PCOINSTALLER_CONTEXT_DATA   Context
+    )
+{
+    SP_DEVINSTALL_PARAMS            DeviceInstallParams;
+    HRESULT                         Error;
+
+    DeviceInstallParams.cbSize = sizeof (DeviceInstallParams);
+
+    if (!SetupDiGetDeviceInstallParams(DeviceInfoSet,
+                                       DeviceInfoData,
+                                       &DeviceInstallParams))
+        goto fail1;
+
+    Log("Flags = %08x", DeviceInstallParams.Flags);
+
+    Error = (!Context->PostProcessing) ?
+            __DifRemovePreProcess(DeviceInfoSet, DeviceInfoData, Context) :
+            __DifRemovePostProcess(DeviceInfoSet, DeviceInfoData, Context);
+
+    return Error;
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return Error;
+}
+
+DWORD CALLBACK
+Entry(
+    IN  DI_FUNCTION                 Function,
+    IN  HDEVINFO                    DeviceInfoSet,
+    IN  PSP_DEVINFO_DATA            DeviceInfoData,
+    IN  PCOINSTALLER_CONTEXT_DATA   Context
+    )
+{
+    HRESULT                         Error;
+
+    Log("%s (%s) ===>",
+        MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR,
+        DAY_STR "/" MONTH_STR "/" YEAR_STR);
+
+    switch (Function) {
+    case DIF_INSTALLDEVICE: {
+        SP_DRVINFO_DATA         DriverInfoData;
+        BOOLEAN                 DriverInfoAvailable;
+
+        DriverInfoData.cbSize = sizeof (DriverInfoData);
+        DriverInfoAvailable = SetupDiGetSelectedDriver(DeviceInfoSet,
+                                                       DeviceInfoData,
+                                                       &DriverInfoData) ?
+                              TRUE :
+                              FALSE;
+
+        // The NET class installer will call DIF_REMOVE even in the event of
+        // a NULL driver add, so we don't need to do it here. However, the
+        // default installer (for the NULL driver) fails for some reason so
+        // we squash the error in post-processing.
+        if (DriverInfoAvailable) {
+            Error = DifInstall(DeviceInfoSet, DeviceInfoData, Context);
+        } else {
+            if (!Context->PostProcessing) {
+                Log("%s PreProcessing",
+                    FunctionName(Function));
+
+                Error = ERROR_DI_POSTPROCESSING_REQUIRED; 
+            } else {
+                Log("%s PostProcessing (%08x)",
+                    FunctionName(Function),
+                    Context->InstallResult);
+
+                Error = NO_ERROR;
+            }
+        }
+        break;
+    }
+    case DIF_REMOVE:
+        Error = DifRemove(DeviceInfoSet, DeviceInfoData, Context);
+        break;
+    default:
+        if (!Context->PostProcessing) {
+            Log("%s PreProcessing",
+                FunctionName(Function));
+
+            Error = NO_ERROR;
+        } else {
+            Log("%s PostProcessing (%08x)",
+                FunctionName(Function),
+                Context->InstallResult);
+
+            Error = Context->InstallResult;
+        }
+
+        break;
+    }
+
+    Log("%s (%s) <===",
+        MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR,
+        DAY_STR "/" MONTH_STR "/" YEAR_STR);
+
+    return (DWORD)Error;
+}
+
+DWORD CALLBACK
+Version(
+    IN  HWND        Window,
+    IN  HINSTANCE   Module,
+    IN  PTCHAR      Buffer,
+    IN  INT         Reserved
+    )
+{
+    UNREFERENCED_PARAMETER(Window);
+    UNREFERENCED_PARAMETER(Module);
+    UNREFERENCED_PARAMETER(Buffer);
+    UNREFERENCED_PARAMETER(Reserved);
+
+    Log("%s (%s)",
+        MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR,
+        DAY_STR "/" MONTH_STR "/" YEAR_STR);
+
+    return NO_ERROR;
+}
+
+static FORCEINLINE const CHAR *
+__ReasonName(
+    IN  DWORD       Reason
+    )
+{
+#define _NAME(_Reason)          \
+        case DLL_ ## _Reason:   \
+            return #_Reason;
+
+    switch (Reason) {
+    _NAME(PROCESS_ATTACH);
+    _NAME(PROCESS_DETACH);
+    _NAME(THREAD_ATTACH);
+    _NAME(THREAD_DETACH);
+    default:
+        break;
+    }
+
+    return "UNKNOWN";
+
+#undef  _NAME
+}
+
+BOOL WINAPI
+DllMain(
+    IN  HINSTANCE   Module,
+    IN  DWORD       Reason,
+    IN  PVOID       Reserved
+    )
+{
+    UNREFERENCED_PARAMETER(Module);
+    UNREFERENCED_PARAMETER(Reserved);
+
+    Log("%s (%s): %s",
+        MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR,
+        DAY_STR "/" MONTH_STR "/" YEAR_STR,
+        __ReasonName(Reason));
+
+    return TRUE;
+}
diff --git a/src/coinst/xennet_coinst.def b/src/coinst/xennet_coinst.def
new file mode 100644 (file)
index 0000000..bcdd28b
--- /dev/null
@@ -0,0 +1,37 @@
+; 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.
+
+LIBRARY  XENNET_COINST
+
+EXPORTS   
+   Entry 
+   Version
+
+   DllMain PRIVATE
diff --git a/src/xennet.inf b/src/xennet.inf
new file mode 100644 (file)
index 0000000..51abf8a
--- /dev/null
@@ -0,0 +1,185 @@
+; Copyright 2011 Citrix Systems Inc. All rights reserved.
+; Use is subject to license terms.
+; 
+[Version] 
+Signature="$Windows NT$" 
+Class=Net
+ClassGUID={4d36e972-e325-11ce-bfc1-08002be10318}
+Provider=%Citrix% 
+CatalogFile=xennet.cat
+DriverVer=01/01/1900,0.0.0.0
+
+[DestinationDirs] 
+DefaultDestDir=12 
+CoInst_CopyFiles=11
+
+[SourceDisksNames]
+0=%DiskDesc%
+
+[SourceDisksFiles]
+xennet.sys=0,,
+xennet_coinst.dll=0,,
+
+[XenNet_Copyfiles]
+xennet.sys
+
+[CoInst_CopyFiles]
+xennet_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll,xennet_coinst.dll
+
+[Manufacturer] 
+%Citrix%=Citrix,NT$ARCH$
+
+[Citrix.NT$ARCH$]
+%DriverDesc%=XenNet_Inst,XENVIF\DEVICE&REV_02
+
+[XenNet_Inst] 
+Characteristics=0x84
+BusType=1
+*IfType=6              ; IF_TYPE_ETHERNET_CSMACD
+*MediaType=0           ; NdisMedium802_3
+*PhysicalMediaType=0   ; NdisPhysicalMediumUnspecified
+CopyFiles=XenNet_Copyfiles
+AddReg=Xennet_Inst_AddReg
+
+[XenNet_Inst_AddReg] 
+HKR, Ndi, Service, 0, "xennet"
+HKR, Ndi\Interfaces, UpperRange, 0, "ndis5"
+HKR, Ndi\Interfaces, LowerRange, 0, "ethernet"
+
+HKR, Ndi\params\*IPChecksumOffloadIPv4,           ParamDesc,  0, %IPChecksumOffloadIPv4%
+HKR, Ndi\params\*IPChecksumOffloadIPv4,           Type,       0, "enum"
+HKR, Ndi\params\*IPChecksumOffloadIPv4,           Default,    0, "3"
+HKR, Ndi\params\*IPChecksumOffloadIPv4,           Optional,   0, "0"
+HKR, Ndi\params\*IPChecksumOffloadIPv4\enum,      "0",        0, %Disabled%
+HKR, Ndi\params\*IPChecksumOffloadIPv4\enum,      "1",        0, %Enabled-Tx%
+HKR, Ndi\params\*IPChecksumOffloadIPv4\enum,      "2",        0, %Enabled-Rx%
+HKR, Ndi\params\*IPChecksumOffloadIPv4\enum,      "3",        0, %Enabled-TxRx%
+
+HKR, Ndi\params\*TCPChecksumOffloadIPv4,          ParamDesc,  0, %TCPChecksumOffloadIPv4%
+HKR, Ndi\params\*TCPChecksumOffloadIPv4,          Type,       0, "enum"
+HKR, Ndi\params\*TCPChecksumOffloadIPv4,          Default,    0, "3"
+HKR, Ndi\params\*TCPChecksumOffloadIPv4,          Optional,   0, "0"
+HKR, Ndi\params\*TCPChecksumOffloadIPv4\enum,     "0",        0, %Disabled%
+HKR, Ndi\params\*TCPChecksumOffloadIPv4\enum,     "1",        0, %Enabled-Tx%
+HKR, Ndi\params\*TCPChecksumOffloadIPv4\enum,     "2",        0, %Enabled-Rx%
+HKR, Ndi\params\*TCPChecksumOffloadIPv4\enum,     "3",        0, %Enabled-TxRx%
+
+HKR, Ndi\params\*UDPChecksumOffloadIPv4,          ParamDesc,  0, %UDPChecksumOffloadIPv4%
+HKR, Ndi\params\*UDPChecksumOffloadIPv4,          Type,       0, "enum"
+HKR, Ndi\params\*UDPChecksumOffloadIPv4,          Default,    0, "3"
+HKR, Ndi\params\*UDPChecksumOffloadIPv4,          Optional,   0, "0"
+HKR, Ndi\params\*UDPChecksumOffloadIPv4\enum,     "0",        0, %Disabled%
+HKR, Ndi\params\*UDPChecksumOffloadIPv4\enum,     "1",        0, %Enabled-Tx%
+HKR, Ndi\params\*UDPChecksumOffloadIPv4\enum,     "2",        0, %Enabled-Rx%
+HKR, Ndi\params\*UDPChecksumOffloadIPv4\enum,     "3",        0, %Enabled-TxRx%
+
+HKR, Ndi\params\*TCPChecksumOffloadIPv6,          ParamDesc,  0, %TCPChecksumOffloadIPv6%
+HKR, Ndi\params\*TCPChecksumOffloadIPv6,          Type,       0, "enum"
+HKR, Ndi\params\*TCPChecksumOffloadIPv6,          Default,    0, "3"
+HKR, Ndi\params\*TCPChecksumOffloadIPv6,          Optional,   0, "0"
+HKR, Ndi\params\*TCPChecksumOffloadIPv6\enum,     "0",        0, %Disabled%
+HKR, Ndi\params\*TCPChecksumOffloadIPv6\enum,     "1",        0, %Enabled-Tx%
+HKR, Ndi\params\*TCPChecksumOffloadIPv6\enum,     "2",        0, %Enabled-Rx%
+HKR, Ndi\params\*TCPChecksumOffloadIPv6\enum,     "3",        0, %Enabled-TxRx%
+
+HKR, Ndi\params\*UDPChecksumOffloadIPv6,          ParamDesc,  0, %UDPChecksumOffloadIPv6%
+HKR, Ndi\params\*UDPChecksumOffloadIPv6,          Type,       0, "enum"
+HKR, Ndi\params\*UDPChecksumOffloadIPv6,          Default,    0, "3"
+HKR, Ndi\params\*UDPChecksumOffloadIPv6,          Optional,   0, "0"
+HKR, Ndi\params\*UDPChecksumOffloadIPv6\enum,     "0",        0, %Disabled%
+HKR, Ndi\params\*UDPChecksumOffloadIPv6\enum,     "1",        0, %Enabled-Tx%
+HKR, Ndi\params\*UDPChecksumOffloadIPv6\enum,     "2",        0, %Enabled-Rx%
+HKR, Ndi\params\*UDPChecksumOffloadIPv6\enum,     "3",        0, %Enabled-TxRx%
+
+HKR, Ndi\params\NeedChecksumValue,               ParamDesc,  0, %NeedChecksumValue%
+HKR, Ndi\params\NeedChecksumValue,               Type,       0, "enum"
+HKR, Ndi\params\NeedChecksumValue,               Default,    0, "1"
+HKR, Ndi\params\NeedChecksumValue,               Optional,   0, "0"
+HKR, Ndi\params\NeedChecksumValue\enum,          "0",        0, %Disabled%
+HKR, Ndi\params\NeedChecksumValue\enum,          "1",        0, %Enabled%
+
+HKR, Ndi\params\*LSOV2IPv4,                       ParamDesc,  0, %LSOV2IPv4%
+HKR, Ndi\params\*LSOV2IPv4,                       Type,       0, "enum"
+HKR, Ndi\params\*LSOV2IPv4,                       Default,    0, "1"
+HKR, Ndi\params\*LSOV2IPv4,                       Optional,   0, "0"
+HKR, Ndi\params\*LSOV2IPv4\enum,                  "0",        0, %Disabled%
+HKR, Ndi\params\*LSOV2IPv4\enum,                  "1",        0, %Enabled%
+
+HKR, Ndi\params\*LSOV2IPv6,                       ParamDesc,  0, %LSOV2IPv6%
+HKR, Ndi\params\*LSOV2IPv6,                       Type,       0, "enum"
+HKR, Ndi\params\*LSOV2IPv6,                       Default,    0, "1"
+HKR, Ndi\params\*LSOV2IPv6,                       Optional,   0, "0"
+HKR, Ndi\params\*LSOV2IPv6\enum,                  "0",        0, %Disabled%
+HKR, Ndi\params\*LSOV2IPv6\enum,                  "1",        0, %Enabled%
+
+HKR, Ndi\params\LROIPv4,                          ParamDesc,  0, %LROIPv4%
+HKR, Ndi\params\LROIPv4,                          Type,       0, "enum"
+HKR, Ndi\params\LROIPv4,                          Default,    0, "1"
+HKR, Ndi\params\LROIPv4,                          Optional,   0, "0"
+HKR, Ndi\params\LROIPv4\enum,                     "0",        0, %Disabled%
+HKR, Ndi\params\LROIPv4\enum,                     "1",        0, %Enabled%
+
+HKR, Ndi\params\LROIPv6,                          ParamDesc,  0, %LROIPv6%
+HKR, Ndi\params\LROIPv6,                          Type,       0, "enum"
+HKR, Ndi\params\LROIPv6,                          Default,    0, "1"
+HKR, Ndi\params\LROIPv6,                          Optional,   0, "0"
+HKR, Ndi\params\LROIPv6\enum,                     "0",        0, %Disabled%
+HKR, Ndi\params\LROIPv6\enum,                     "1",        0, %Enabled%
+
+[XenNet_Inst.Services] 
+AddService=xennet,0x02,XenNet_Service,XenNet_EventLog
+
+[XenNet_Service] 
+ServiceType=%SERVICE_KERNEL_DRIVER% 
+StartType=%SERVICE_DEMAND_START% 
+ErrorControl=%SERVICE_ERROR_NORMAL% 
+ServiceBinary=%12%\xennet.sys 
+LoadOrderGroup="NDIS"
+
+[XenNet_EventLog]
+AddReg=XenNet_EventLog_AddReg
+
+[XenNet_EventLog_AddReg]
+HKR,,EventMessageFile,0x00020000,"%%SystemRoot%%\System32\netevent.dll"
+HKR,,TypesSupported,0x00010001,7
+
+[XenNet_Inst.CoInstallers]
+CopyFiles=CoInst_CopyFiles
+AddReg=CoInst_AddReg
+
+[CoInst_AddReg]
+HKR,,CoInstallers32,0x00010000,"xennet_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll,Entry"
+
+[Strings] 
+
+Citrix="Citrix Systems Inc." 
+DiskDesc="Citrix Tools for Virtual Machines" 
+DriverDesc="Citrix PV Network Adapter"
+IPChecksumOffloadIPv4="IPv4 Checksum Offload"
+TCPChecksumOffloadIPv4="TCP Checksum Offload (IPv4)"
+UDPChecksumOffloadIPv4="UDP Checksum Offload (IPv4)"
+TCPChecksumOffloadIPv6="TCP Checksum Offload (IPv6)"
+UDPChecksumOffloadIPv6="UDP Checksum Offload (IPv6)"
+NeedChecksumValue="Correct TCP/UDP Checksum Value"
+LSOV2IPv4="Large Send Offload V2 (IPv4)"
+LSOV2IPv6="Large Send Offload V2 (IPv6)"
+LROIPv4="Large Receive Offload (IPv4)"
+LROIPv6="Large Receive Offload (IPv6)"
+Disabled="Disabled"
+Enabled="Enabled"
+Enabled-Rx="Rx Enabled"
+Enabled-Tx="Tx Enabled"
+Enabled-TxRx="Rx & Tx Enabled"
+
+SERVICE_BOOT_START=0x0 
+SERVICE_SYSTEM_START=0x1 
+SERVICE_AUTO_START=0x2 
+SERVICE_DEMAND_START=0x3 
+SERVICE_DISABLED=0x4 
+
+SERVICE_KERNEL_DRIVER=0x1 
+SERVICE_ERROR_IGNORE=0x0 
+SERVICE_ERROR_NORMAL=0x1 
+SERVICE_ERROR_SEVERE=0x2 
+SERVICE_ERROR_CRITICAL=0x3 
diff --git a/src/xennet/adapter.c b/src/xennet/adapter.c
new file mode 100644 (file)
index 0000000..496853a
--- /dev/null
@@ -0,0 +1,2402 @@
+/* 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 <version.h>
+#include "common.h"
+
+#pragma warning(disable:4711)
+
+//
+// List of supported OIDs.
+//
+
+static NDIS_STATUS
+AdapterStop (
+    IN  PADAPTER    Adapter
+    );
+
+static NDIS_STATUS
+AdapterSetRegistrationAttributes (
+    IN  PADAPTER Adapter
+    );
+
+static NDIS_STATUS
+AdapterSetGeneralAttributes (
+    IN  PADAPTER Adapter
+    );
+
+static NDIS_STATUS
+AdapterSetOffloadAttributes (
+    IN  PADAPTER Adapter
+    );
+
+static VOID
+AdapterProcessSGList (
+    IN PDEVICE_OBJECT       DeviceObject,
+    IN PVOID                Reserved,
+    IN PSCATTER_GATHER_LIST SGL,
+    IN PVOID                Context
+    );
+
+static NDIS_STATUS
+AdapterSetInformation (
+    IN  PADAPTER            Adapter,
+    IN  PNDIS_OID_REQUEST   NdisRequest
+    );
+
+static NDIS_STATUS
+AdapterQueryInformation (
+    IN  PADAPTER            Adapter,
+    IN  PNDIS_OID_REQUEST   NdisRequest
+    );
+
+static NDIS_OID XennetSupportedOids[] =
+{
+    OID_GEN_SUPPORTED_LIST,
+    OID_GEN_HARDWARE_STATUS,
+    OID_GEN_MEDIA_SUPPORTED,
+    OID_GEN_MEDIA_IN_USE,
+    OID_GEN_PHYSICAL_MEDIUM,
+    OID_GEN_CURRENT_LOOKAHEAD,
+    OID_GEN_MAXIMUM_LOOKAHEAD,
+    OID_GEN_MAXIMUM_FRAME_SIZE,
+    OID_GEN_MAXIMUM_TOTAL_SIZE,
+    OID_GEN_RECEIVE_BLOCK_SIZE,
+    OID_GEN_TRANSMIT_BLOCK_SIZE,
+    OID_GEN_MAC_OPTIONS,
+    OID_GEN_LINK_SPEED,
+    OID_GEN_MEDIA_CONNECT_STATUS,
+    OID_GEN_VENDOR_DESCRIPTION,
+    OID_GEN_VENDOR_DRIVER_VERSION,
+    OID_GEN_DRIVER_VERSION,
+    OID_GEN_MAXIMUM_SEND_PACKETS,
+    OID_GEN_VENDOR_ID,
+    OID_GEN_CURRENT_PACKET_FILTER,
+    OID_GEN_XMIT_OK,
+    OID_GEN_RCV_OK,
+    OID_GEN_XMIT_ERROR,
+    OID_GEN_RCV_ERROR,
+    OID_GEN_RCV_CRC_ERROR,
+    OID_GEN_RCV_NO_BUFFER,
+    OID_GEN_TRANSMIT_QUEUE_LENGTH,
+    OID_GEN_TRANSMIT_BUFFER_SPACE,
+    OID_GEN_RECEIVE_BUFFER_SPACE,
+    OID_GEN_STATISTICS,
+    OID_GEN_DIRECTED_BYTES_XMIT,
+    OID_GEN_DIRECTED_FRAMES_XMIT,
+    OID_GEN_MULTICAST_BYTES_XMIT,
+    OID_GEN_MULTICAST_FRAMES_XMIT,
+    OID_GEN_BROADCAST_BYTES_XMIT,
+    OID_GEN_BROADCAST_FRAMES_XMIT,
+    OID_GEN_DIRECTED_BYTES_RCV,
+    OID_GEN_DIRECTED_FRAMES_RCV,
+    OID_GEN_MULTICAST_BYTES_RCV,
+    OID_GEN_MULTICAST_FRAMES_RCV,
+    OID_GEN_BROADCAST_BYTES_RCV,
+    OID_GEN_BROADCAST_FRAMES_RCV,
+    OID_GEN_INTERRUPT_MODERATION,
+    OID_802_3_RCV_ERROR_ALIGNMENT,
+    OID_802_3_XMIT_ONE_COLLISION,
+    OID_802_3_XMIT_MORE_COLLISIONS,
+    OID_OFFLOAD_ENCAPSULATION,
+    OID_TCP_OFFLOAD_PARAMETERS,
+    OID_PNP_CAPABILITIES,
+    OID_PNP_QUERY_POWER,
+    OID_PNP_SET_POWER,
+};
+
+#define INITIALIZE_NDIS_OBJ_HEADER(obj, type) do {               \
+    (obj).Header.Type = NDIS_OBJECT_TYPE_ ## type ;              \
+    (obj).Header.Revision = NDIS_ ## type ## _REVISION_1;        \
+    (obj).Header.Size = sizeof(obj);                             \
+} while (0)
+
+//
+// Scatter gather allocate handler callback.
+// Should never get called.
+//
+static VOID
+AdapterAllocateComplete (
+    IN NDIS_HANDLE              MiniportAdapterContext,
+    IN PVOID                    VirtualAddress,
+    IN PNDIS_PHYSICAL_ADDRESS   PhysicalAddress,
+    IN ULONG                    Length,
+    IN PVOID                    Context
+    )
+{
+    UNREFERENCED_PARAMETER(MiniportAdapterContext);
+    UNREFERENCED_PARAMETER(VirtualAddress);
+    UNREFERENCED_PARAMETER(PhysicalAddress);
+    UNREFERENCED_PARAMETER(Length);
+    UNREFERENCED_PARAMETER(Context);
+
+    ASSERT(FALSE);
+
+    return;
+}
+
+//
+// Required NDIS6 handler.
+// Should never get called.
+//
+VOID
+AdapterCancelOidRequest (
+    IN  PADAPTER    Adapter,
+    IN  PVOID       RequestId
+    )
+{
+    UNREFERENCED_PARAMETER(Adapter);
+    UNREFERENCED_PARAMETER(RequestId);
+
+    return;
+}
+
+//
+// Required NDIS6 handler.
+// Should never get called.
+//
+
+VOID 
+AdapterCancelSendNetBufferLists (
+    IN  PADAPTER    Adapter,
+    IN  PVOID       CancelId
+    )
+{
+    UNREFERENCED_PARAMETER(Adapter);
+    UNREFERENCED_PARAMETER(CancelId);
+
+    return;
+}
+
+BOOLEAN 
+AdapterCheckForHang (
+    IN  PADAPTER Adapter
+    )
+{
+    UNREFERENCED_PARAMETER(Adapter);
+
+    return FALSE;
+}
+
+//
+// Frees resources obtained by AdapterInitialize.
+//
+static VOID
+AdapterCleanup (
+    IN  PADAPTER Adapter
+    )
+{
+    Trace("====>\n");
+
+    TransmitterDelete(&Adapter->Transmitter);
+    ReceiverCleanup(&Adapter->Receiver);
+
+    if (Adapter->NdisDmaHandle != NULL)
+        NdisMDeregisterScatterGatherDma(Adapter->NdisDmaHandle);
+
+    if (Adapter->AcquiredInterfaces) {
+        VIF(Release, Adapter->VifInterface);
+        Adapter->VifInterface = NULL;
+    }
+
+    Trace("<====\n");
+    return;
+}
+
+//
+// Frees adapter storage.
+//
+VOID
+AdapterDelete (
+    IN  OUT PADAPTER* Adapter
+    )
+{
+    ASSERT(Adapter != NULL);
+
+    if (*Adapter) {
+        AdapterCleanup(*Adapter);
+        ExFreePool(*Adapter);
+        *Adapter = NULL;
+    }
+
+    return;
+}
+
+//
+// Stops adapter and frees all resources.
+//
+VOID 
+AdapterHalt (
+    IN  PADAPTER                Adapter,
+    IN  NDIS_HALT_ACTION        HaltAction
+    )
+{
+    NDIS_STATUS ndisStatus;
+
+    UNREFERENCED_PARAMETER(HaltAction);
+
+
+    ndisStatus = AdapterStop(Adapter);
+    if (ndisStatus == NDIS_STATUS_SUCCESS) {
+        AdapterDelete(&Adapter);
+    }
+
+    return;
+}
+
+static VOID
+AdapterMediaStateChange(
+    IN  PADAPTER                Adapter
+    )
+{
+    NDIS_LINK_STATE             LinkState;
+    NDIS_STATUS_INDICATION      StatusIndication;
+
+    NdisZeroMemory(&LinkState, sizeof (NDIS_LINK_STATE));
+
+    LinkState.Header.Revision = NDIS_LINK_STATE_REVISION_1;
+    LinkState.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    LinkState.Header.Size = sizeof(NDIS_LINK_STATE);
+
+    VIF(QueryMediaState,
+        Adapter->VifInterface,
+        &LinkState.MediaConnectState,
+        &LinkState.RcvLinkSpeed,
+        &LinkState.MediaDuplexState);
+
+    if (LinkState.MediaConnectState == MediaConnectStateUnknown) {
+        Info("LINK: STATE UNKNOWN\n");
+    } else if (LinkState.MediaConnectState == MediaConnectStateDisconnected) {
+        Info("LINK: DOWN\n");
+    } else {
+        ASSERT3U(LinkState.MediaConnectState, ==, MediaConnectStateConnected);
+
+        if (LinkState.MediaDuplexState == MediaDuplexStateHalf) 
+            Info("LINK: UP: SPEED=%u DUPLEX=HALF\n", LinkState.RcvLinkSpeed);
+        else if (LinkState.MediaDuplexState == MediaDuplexStateFull)
+            Info("LINK: UP: SPEED=%u DUPLEX=FULL\n", LinkState.RcvLinkSpeed);
+        else
+            Info("LINK: UP: SPEED=%u DUPLEX=UNKNOWN\n", LinkState.RcvLinkSpeed);
+    }
+
+    LinkState.XmitLinkSpeed = LinkState.RcvLinkSpeed;
+
+    NdisZeroMemory(&StatusIndication, sizeof (NDIS_STATUS_INDICATION));
+
+    StatusIndication.Header.Type = NDIS_OBJECT_TYPE_STATUS_INDICATION;
+    StatusIndication.Header.Revision = NDIS_STATUS_INDICATION_REVISION_1;
+    StatusIndication.Header.Size = sizeof (NDIS_STATUS_INDICATION);
+    StatusIndication.SourceHandle = Adapter->NdisAdapterHandle;
+    StatusIndication.StatusCode = NDIS_STATUS_LINK_STATE;
+    StatusIndication.StatusBuffer = &LinkState;
+    StatusIndication.StatusBufferSize = sizeof (NDIS_LINK_STATE);
+
+    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &StatusIndication);
+}
+
+
+//
+// Initializes adapter by allocating required resources and connects to 
+// netback.
+//
+
+static VOID
+AdapterVifCallback(
+    IN  PVOID                   Context,
+    IN  XENVIF_CALLBACK_TYPE    Type,
+    ...)
+{
+    PADAPTER                    Adapter = Context;
+    va_list                     Arguments;
+
+    va_start(Arguments, Type);
+
+    switch (Type) {
+    case XENVIF_CALLBACK_COMPLETE_PACKETS: {
+        PXENVIF_TRANSMITTER_PACKET HeadPacket;
+
+        HeadPacket = va_arg(Arguments, PXENVIF_TRANSMITTER_PACKET);
+
+        TransmitterCompletePackets(Adapter->Transmitter, HeadPacket);
+        break;
+    }
+    case XENVIF_CALLBACK_RECEIVE_PACKETS: {
+        PLIST_ENTRY List;
+
+        List = va_arg(Arguments, PLIST_ENTRY);
+
+        ReceiverReceivePackets(&Adapter->Receiver, List);
+        break;
+    }
+    case XENVIF_CALLBACK_MEDIA_STATE_CHANGE: {
+        AdapterMediaStateChange(Adapter);
+        break;
+    }
+    }
+
+    va_end(Arguments);
+}
+
+NDIS_STATUS
+AdapterGetAdvancedSettings(
+    IN PADAPTER pAdapter
+    )
+{
+    NDIS_CONFIGURATION_OBJECT configObject;
+    NDIS_HANDLE hConfigurationHandle;
+    NDIS_STRING ndisValue;
+    PNDIS_CONFIGURATION_PARAMETER pNdisData;
+    NDIS_STATUS ndisStatus;
+    NTSTATUS status;
+
+    configObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+    configObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+    configObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
+    configObject.NdisHandle = pAdapter->NdisAdapterHandle;
+    configObject.Flags = 0;
+
+    ndisStatus = NdisOpenConfigurationEx(&configObject, &hConfigurationHandle);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        goto fail1;
+
+#define read_property(field, name, default_val) \
+    do { \
+        RtlInitUnicodeString(&ndisValue, name); \
+        NdisReadConfiguration(&ndisStatus, &pNdisData, hConfigurationHandle, &ndisValue, NdisParameterInteger); \
+        if (ndisStatus == NDIS_STATUS_SUCCESS) { \
+            pAdapter->Properties.field = pNdisData->ParameterData.IntegerData; \
+        } else { \
+            pAdapter->Properties.field = default_val; \
+        } \
+    } while (FALSE);
+
+    read_property(ipv4_csum, L"*IPChecksumOffloadIPv4", 3);
+    read_property(tcpv4_csum, L"*TCPChecksumOffloadIPv4", 3);
+    read_property(udpv4_csum, L"*UDPChecksumOffloadIPv4", 3);
+    read_property(tcpv6_csum, L"*TCPChecksumOffloadIPv6", 3);
+    read_property(udpv6_csum, L"*UDPChecksumOffloadIPv6", 3);
+    read_property(lsov4, L"*LSOv2IPv4", 1);
+    read_property(lsov6, L"*LSOv2IPv6", 1);
+    read_property(lrov4, L"LROIPv4", 1);
+    read_property(lrov6, L"LROIPv6", 1);
+    read_property(need_csum_value, L"NeedChecksumValue", 1);
+
+    NdisCloseConfiguration(hConfigurationHandle);
+
+    return NDIS_STATUS_SUCCESS;
+
+fail1:
+    Error("fail1\n");
+    return NDIS_STATUS_FAILURE;
+}
+
+NDIS_STATUS 
+AdapterInitialize (
+    IN  PADAPTER    Adapter,
+    IN  NDIS_HANDLE AdapterHandle
+    )
+{
+    NDIS_STATUS ndisStatus;
+    NDIS_SG_DMA_DESCRIPTION DmaDescription;
+    NTSTATUS status;
+
+    Trace("====>\n");
+
+    Adapter->NdisAdapterHandle = AdapterHandle;
+
+    RtlZeroMemory(&Adapter->Capabilities, sizeof (Adapter->Capabilities));
+
+    Adapter->Transmitter = ExAllocatePoolWithTag(NonPagedPool, sizeof(TRANSMITTER), ' TEN');
+    if (!Adapter->Transmitter) {
+        ndisStatus = NDIS_STATUS_RESOURCES;
+        goto exit;
+    }
+
+    RtlZeroMemory(Adapter->Transmitter, sizeof (TRANSMITTER));
+
+    ndisStatus = ReceiverInitialize(&Adapter->Receiver);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        goto exit;
+    }
+
+    ndisStatus = TransmitterInitialize(Adapter->Transmitter, Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        goto exit;
+    }
+
+    ndisStatus = AdapterGetAdvancedSettings(Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        goto exit;
+    }
+
+    ndisStatus = AdapterSetRegistrationAttributes(Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        goto exit;
+    }
+
+    ndisStatus = AdapterSetGeneralAttributes(Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        goto exit;
+    }
+
+    ndisStatus = AdapterSetOffloadAttributes(Adapter);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        goto exit;
+    }
+
+    NdisZeroMemory(&DmaDescription, sizeof(DmaDescription));
+
+    DmaDescription.Header.Type = NDIS_OBJECT_TYPE_SG_DMA_DESCRIPTION;
+    DmaDescription.Header.Revision = NDIS_SG_DMA_DESCRIPTION_REVISION_1;
+    DmaDescription.Header.Size = sizeof(NDIS_SG_DMA_DESCRIPTION);
+    DmaDescription.Flags = NDIS_SG_DMA_64_BIT_ADDRESS;
+    DmaDescription.MaximumPhysicalMapping = 65536;    
+    DmaDescription.ProcessSGListHandler = AdapterProcessSGList;
+    DmaDescription.SharedMemAllocateCompleteHandler = AdapterAllocateComplete;
+
+    ndisStatus = NdisMRegisterScatterGatherDma(Adapter->NdisAdapterHandle,
+                                               &DmaDescription,
+                                               &Adapter->NdisDmaHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS)
+        Adapter->NdisDmaHandle = NULL;
+
+    ASSERT(!Adapter->Enabled);
+    VIF(Acquire, Adapter->VifInterface);
+
+    status = VIF(Enable,
+                 Adapter->VifInterface,
+                 AdapterVifCallback,
+                 Adapter);
+    if (NT_SUCCESS(status)) {
+        TransmitterEnable(Adapter->Transmitter);
+        Adapter->Enabled = TRUE;
+        ndisStatus = NDIS_STATUS_SUCCESS;
+    } else {
+        ndisStatus = NDIS_STATUS_FAILURE;
+    }
+
+exit:
+    Trace("<==== (%08x)\n", ndisStatus);
+    return ndisStatus;
+}
+
+//
+// Scatter gather process handler callback.
+// Should never get called.
+//
+static VOID
+AdapterProcessSGList (
+    IN PDEVICE_OBJECT       DeviceObject,
+    IN PVOID                Reserved,
+    IN PSCATTER_GATHER_LIST SGL,
+    IN PVOID                Context
+    )
+{
+    UNREFERENCED_PARAMETER(DeviceObject);
+    UNREFERENCED_PARAMETER(Reserved);
+    UNREFERENCED_PARAMETER(SGL);
+    UNREFERENCED_PARAMETER(Context);
+
+    ASSERT(FALSE);
+
+    return;
+}
+
+//
+// Get\Set OID handler.
+//
+NDIS_STATUS 
+AdapterOidRequest (
+    IN  PADAPTER            Adapter,
+    IN  PNDIS_OID_REQUEST   NdisRequest
+    )
+{
+    NDIS_STATUS ndisStatus;
+
+    UNREFERENCED_PARAMETER(Adapter);
+    UNREFERENCED_PARAMETER(NdisRequest);
+    
+    switch (NdisRequest->RequestType) {
+        case NdisRequestSetInformation:            
+            ndisStatus = AdapterSetInformation(Adapter, NdisRequest);
+            break;
+                
+        case NdisRequestQueryInformation:
+        case NdisRequestQueryStatistics:
+            ndisStatus = AdapterQueryInformation(Adapter, NdisRequest);
+            break;
+
+        default:
+            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    };
+
+    return ndisStatus;
+}
+
+//
+// Temporarily pauses adapter.
+//
+NDIS_STATUS
+AdapterPause (
+    IN  PADAPTER                        Adapter,
+    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
+    )
+{
+    UNREFERENCED_PARAMETER(MiniportPauseParameters);
+
+    Trace("====>\n");
+
+    if (!Adapter->Enabled)
+        goto done;
+
+    VIF(Disable,
+        Adapter->VifInterface);
+
+    AdapterMediaStateChange(Adapter);
+
+    Adapter->Enabled = FALSE;
+
+done:
+    Trace("<====\n");
+    return NDIS_STATUS_SUCCESS;
+}
+
+//
+// Handles PNP and Power events. NOP.
+//
+VOID 
+AdapterPnPEventHandler (
+    IN  PADAPTER                Adapter,
+    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+    )
+{
+    UNREFERENCED_PARAMETER(Adapter);
+
+
+    switch (NetDevicePnPEvent->DevicePnPEvent) {
+        case NdisDevicePnPEventQueryRemoved:
+            break;
+
+        case NdisDevicePnPEventRemoved:
+            break;       
+
+        case NdisDevicePnPEventSurpriseRemoved:
+            break;
+
+        case NdisDevicePnPEventQueryStopped:
+            break;
+
+        case NdisDevicePnPEventStopped:
+            break;      
+            
+        case NdisDevicePnPEventPowerProfileChanged:
+            break;      
+            
+        default:
+            break;         
+    };
+
+    return;
+}
+
+//
+// Reports general statistics to NDIS.
+//
+static NDIS_STATUS 
+AdapterQueryGeneralStatistics (
+    IN  PADAPTER                Adapter,
+    IN  PNDIS_STATISTICS_INFO   NdisStatisticsInfo
+    )
+{
+    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
+    XENVIF_PACKET_STATISTICS Statistics;
+
+    VIF(QueryPacketStatistics,
+        Adapter->VifInterface,
+        &Statistics);
+
+    NdisZeroMemory(NdisStatisticsInfo, sizeof(NDIS_STATISTICS_INFO));
+    NdisStatisticsInfo->Header.Revision = NDIS_OBJECT_REVISION_1;
+    NdisStatisticsInfo->Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    NdisStatisticsInfo->Header.Size = sizeof(NDIS_STATISTICS_INFO);
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_ERROR;
+    NdisStatisticsInfo->ifInErrors =
+        Statistics.Receiver.BackendError +
+        Statistics.Receiver.FrontendError;
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_RCV_DISCARDS;
+    NdisStatisticsInfo->ifInDiscards = Statistics.Receiver.Drop;
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_RCV;
+    NdisStatisticsInfo->ifHCInOctets = Statistics.Receiver.UnicastBytes +
+                                       Statistics.Receiver.MulticastBytes +
+                                       Statistics.Receiver.BroadcastBytes;
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_RCV;
+    NdisStatisticsInfo->ifHCInUcastOctets = Statistics.Receiver.UnicastBytes;
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_RCV;
+    NdisStatisticsInfo->ifHCInUcastPkts = Statistics.Receiver.Unicast;
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_RCV;
+    NdisStatisticsInfo->ifHCInMulticastOctets = Statistics.Receiver.MulticastBytes;  
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_RCV;
+    NdisStatisticsInfo->ifHCInMulticastPkts = Statistics.Receiver.Multicast;  
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_RCV;
+    NdisStatisticsInfo->ifHCInBroadcastOctets = Statistics.Receiver.BroadcastBytes;  
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_RCV;
+    NdisStatisticsInfo->ifHCInBroadcastPkts = Statistics.Receiver.Broadcast;  
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_ERROR;
+    NdisStatisticsInfo->ifOutErrors =
+        Statistics.Transmitter.BackendError +
+        Statistics.Transmitter.FrontendError;
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BYTES_XMIT;
+    NdisStatisticsInfo->ifHCOutOctets = Statistics.Transmitter.UnicastBytes + 
+                                        Statistics.Transmitter.MulticastBytes + 
+                                        Statistics.Transmitter.BroadcastBytes;
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_BYTES_XMIT;
+    NdisStatisticsInfo->ifHCOutUcastOctets = Statistics.Transmitter.UnicastBytes;     
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_DIRECTED_FRAMES_XMIT;
+    NdisStatisticsInfo->ifHCOutUcastPkts = Statistics.Transmitter.Unicast;     
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_BYTES_XMIT;    
+    NdisStatisticsInfo->ifHCOutMulticastOctets = Statistics.Transmitter.MulticastBytes; 
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_MULTICAST_FRAMES_XMIT;    
+    NdisStatisticsInfo->ifHCOutMulticastPkts = Statistics.Transmitter.MulticastBytes;
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_BYTES_XMIT;
+    NdisStatisticsInfo->ifHCOutBroadcastOctets = Statistics.Transmitter.BroadcastBytes; 
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_BROADCAST_FRAMES_XMIT;
+    NdisStatisticsInfo->ifHCOutBroadcastPkts = Statistics.Transmitter.Broadcast;
+
+    NdisStatisticsInfo->SupportedStatistics |= NDIS_STATISTICS_FLAGS_VALID_XMIT_DISCARDS;
+    NdisStatisticsInfo->ifOutDiscards = 0;
+
+    return ndisStatus;
+}
+
+static VOID
+GetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
+{
+    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
+
+    VIF(QueryFilterLevel,
+        Adapter->VifInterface,
+        ETHERNET_ADDRESS_UNICAST,
+        &UnicastFilterLevel);
+
+    VIF(QueryFilterLevel,
+        Adapter->VifInterface,
+        ETHERNET_ADDRESS_MULTICAST,
+        &MulticastFilterLevel);
+
+    VIF(QueryFilterLevel,
+        Adapter->VifInterface,
+        ETHERNET_ADDRESS_BROADCAST,
+        &BroadcastFilterLevel);
+
+    *PacketFilter = 0;
+
+    if (UnicastFilterLevel == MAC_FILTER_ALL) {
+        ASSERT3U(MulticastFilterLevel, ==, MAC_FILTER_ALL);
+        ASSERT3U(BroadcastFilterLevel, ==, MAC_FILTER_ALL);
+
+        *PacketFilter |= NDIS_PACKET_TYPE_PROMISCUOUS;
+        return;
+    } else if (UnicastFilterLevel == MAC_FILTER_MATCHING) {
+        *PacketFilter |= NDIS_PACKET_TYPE_DIRECTED;
+    }
+
+    if (MulticastFilterLevel == MAC_FILTER_ALL)
+        *PacketFilter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
+    else if (MulticastFilterLevel == MAC_FILTER_MATCHING)
+        *PacketFilter |= NDIS_PACKET_TYPE_MULTICAST;
+
+    if (BroadcastFilterLevel == MAC_FILTER_ALL)
+        *PacketFilter |= NDIS_PACKET_TYPE_BROADCAST;
+}
+
+#define MIN(_x, _y) (((_x) < (_y)) ? (_x) : (_y))
+
+//
+// Handles OID queries.
+//
+static NDIS_STATUS 
+AdapterQueryInformation (
+    IN  PADAPTER            Adapter,
+    IN  PNDIS_OID_REQUEST   NdisRequest
+    )
+{
+    ULONG bytesAvailable = 0;
+    ULONG bytesNeeded = 0;
+    ULONG bytesWritten = 0;
+    BOOLEAN doCopy = TRUE;
+    PVOID info = NULL;
+    ULONGLONG infoData;
+    ULONG informationBufferLength;
+    PVOID informationBuffer;
+    NDIS_INTERRUPT_MODERATION_PARAMETERS intModParams;
+    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
+    NDIS_OID oid;
+
+    informationBuffer = NdisRequest->DATA.QUERY_INFORMATION.InformationBuffer;
+    informationBufferLength = NdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength;
+    oid = NdisRequest->DATA.QUERY_INFORMATION.Oid;
+    switch (oid) {
+        case OID_PNP_CAPABILITIES:
+            Trace("PNP_CAPABILITIES\n");
+
+            info = &Adapter->Capabilities;
+            bytesAvailable = sizeof(Adapter->Capabilities);
+            break;
+
+        case OID_PNP_QUERY_POWER:
+            Trace("QUERY_POWER\n");
+
+            bytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
+            if (informationBufferLength >= bytesNeeded) {
+                PNDIS_DEVICE_POWER_STATE state;
+
+                state = (PNDIS_DEVICE_POWER_STATE)informationBuffer;
+                switch (*state) {
+                case NdisDeviceStateD0:
+                    Trace("D0\n");
+                    break;
+
+                case NdisDeviceStateD1:
+                    Trace("D1\n");
+                    break;
+
+                case NdisDeviceStateD2:
+                    Trace("D2\n");
+                    break;
+
+                case NdisDeviceStateD3:
+                    Trace("D3\n");
+                    break;
+                }
+            }
+            break;
+
+        case OID_GEN_SUPPORTED_LIST:
+            info = &XennetSupportedOids[0];
+            bytesAvailable = sizeof(XennetSupportedOids);
+            break;
+
+        case OID_GEN_HARDWARE_STATUS:
+            infoData = NdisHardwareStatusReady;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_MEDIA_SUPPORTED:
+        case OID_GEN_MEDIA_IN_USE:
+            infoData = XENNET_MEDIA_TYPE;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_MAXIMUM_LOOKAHEAD:
+            infoData = Adapter->MaximumFrameSize;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_TRANSMIT_BUFFER_SPACE:
+            VIF(QueryTransmitterRingSize,
+                Adapter->VifInterface,
+                (PULONG)&infoData);
+            infoData *= Adapter->MaximumFrameSize;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_RECEIVE_BUFFER_SPACE:
+            VIF(QueryTransmitterRingSize,
+                Adapter->VifInterface,
+                (PULONG)&infoData);
+            infoData *= Adapter->MaximumFrameSize;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_TRANSMIT_BLOCK_SIZE:
+        case OID_GEN_RECEIVE_BLOCK_SIZE:
+            infoData = Adapter->MaximumFrameSize;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_VENDOR_DESCRIPTION:
+            info = "Citrix";
+            bytesAvailable = (ULONG)strlen(info) + 1;
+            break;
+
+        case OID_GEN_VENDOR_DRIVER_VERSION:
+            infoData = ((MAJOR_VERSION << 8) | MINOR_VERSION) << 8;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_DRIVER_VERSION:
+            infoData = (6 << 8) | 0;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_MAC_OPTIONS:
+            infoData = XENNET_MAC_OPTIONS;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        
+        case OID_GEN_STATISTICS:
+            doCopy = FALSE;
+
+            bytesAvailable = sizeof(NDIS_STATISTICS_INFO);
+            if (informationBufferLength >= bytesAvailable) {
+                ndisStatus = AdapterQueryGeneralStatistics(Adapter, 
+                                                           informationBuffer);
+
+            }
+
+            break;
+
+        case OID_802_3_MULTICAST_LIST: {
+            ULONG Count;
+
+            doCopy = FALSE;
+
+            VIF(QueryMulticastAddresses,
+                Adapter->VifInterface,
+                NULL,
+                &Count);
+            bytesAvailable = Count * ETHERNET_ADDRESS_LENGTH;
+
+            if (informationBufferLength >= bytesAvailable) {
+                NTSTATUS status;
+
+                status = VIF(QueryMulticastAddresses,
+                             Adapter->VifInterface,
+                             informationBuffer,
+                             &Count);
+                if (!NT_SUCCESS(status))
+                    ndisStatus = NDIS_STATUS_FAILURE;
+            }
+
+            break;
+        }
+        case OID_802_3_PERMANENT_ADDRESS:
+            VIF(QueryPermanentAddress,
+                Adapter->VifInterface,
+                (PETHERNET_ADDRESS)&infoData);
+            info = &infoData;
+            bytesAvailable = ETH_LENGTH_OF_ADDRESS;
+            break;
+
+        case OID_802_3_CURRENT_ADDRESS:
+            VIF(QueryCurrentAddress,
+                Adapter->VifInterface,
+                (PETHERNET_ADDRESS)&infoData);
+            info = &infoData;
+            bytesAvailable = ETH_LENGTH_OF_ADDRESS;
+            break;
+
+        case OID_GEN_MAXIMUM_FRAME_SIZE:
+            infoData = Adapter->MaximumFrameSize - sizeof (ETHERNET_HEADER);
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        case OID_GEN_MAXIMUM_TOTAL_SIZE: {
+            infoData = Adapter->MaximumFrameSize - 4;
+
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_CURRENT_LOOKAHEAD:
+            infoData = Adapter->CurrentLookahead;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_VENDOR_ID:
+            infoData = 0x5853;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_LINK_SPEED: {
+            ULONG64 LinkSpeed;
+
+            VIF(QueryMediaState,
+                Adapter->VifInterface,
+                NULL,
+                &LinkSpeed,
+                NULL);
+
+            infoData = (ULONG)(LinkSpeed / 100);
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_MEDIA_CONNECT_STATUS: {
+            NET_IF_MEDIA_CONNECT_STATE MediaConnectState;
+
+            VIF(QueryMediaState,
+                Adapter->VifInterface,
+                &MediaConnectState,
+                NULL,
+                NULL);
+
+            infoData = (MediaConnectState != MediaConnectStateDisconnected) ?
+                       NdisMediaStateConnected :
+                       NdisMediaStateDisconnected;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_MAXIMUM_SEND_PACKETS:
+            infoData = 16;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_CURRENT_PACKET_FILTER:
+            GetPacketFilter(Adapter, (PULONG)&infoData);
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_XMIT_OK: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = Statistics.Transmitter.Unicast +
+                       Statistics.Transmitter.Multicast +
+                       Statistics.Transmitter.Broadcast;
+
+            info = &infoData;
+            bytesAvailable = sizeof(ULONGLONG);
+            break;
+        }
+        case OID_GEN_RCV_OK: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = Statistics.Receiver.Unicast +
+                       Statistics.Receiver.Multicast +
+                       Statistics.Receiver.Broadcast;
+
+            info = &infoData;
+            bytesAvailable = sizeof(ULONGLONG);
+            break;
+        }
+        case OID_GEN_XMIT_ERROR: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)(Statistics.Transmitter.BackendError +
+                               Statistics.Transmitter.FrontendError);
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_RCV_ERROR: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)(Statistics.Receiver.BackendError +
+                               Statistics.Receiver.FrontendError);
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_RCV_NO_BUFFER:
+            infoData = 0;   // We'd need to query VIF TX drop stats from dom0
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_TRANSMIT_QUEUE_LENGTH:
+            infoData = 0;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_802_3_MAXIMUM_LIST_SIZE:
+            infoData = MAXIMUM_MULTICAST_ADDRESS_COUNT;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_IP4_OFFLOAD_STATS:
+        case OID_IP6_OFFLOAD_STATS:
+        case OID_GEN_SUPPORTED_GUIDS:
+            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+
+        case OID_GEN_RCV_CRC_ERROR:
+            infoData = 0;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_802_3_RCV_ERROR_ALIGNMENT:
+        case OID_802_3_XMIT_ONE_COLLISION:
+        case OID_802_3_XMIT_MORE_COLLISIONS:
+            infoData = 0;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+
+        case OID_GEN_DIRECTED_BYTES_XMIT: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Transmitter.UnicastBytes;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_DIRECTED_FRAMES_XMIT: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Transmitter.Unicast;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_MULTICAST_BYTES_XMIT: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Transmitter.MulticastBytes;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_MULTICAST_FRAMES_XMIT: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Transmitter.Multicast;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_BROADCAST_BYTES_XMIT: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Transmitter.BroadcastBytes;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_BROADCAST_FRAMES_XMIT: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Transmitter.Broadcast;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_DIRECTED_BYTES_RCV: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Receiver.UnicastBytes;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_DIRECTED_FRAMES_RCV: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Receiver.Unicast;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_MULTICAST_BYTES_RCV: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Receiver.MulticastBytes;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_MULTICAST_FRAMES_RCV: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Receiver.Multicast;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_BROADCAST_BYTES_RCV: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Receiver.BroadcastBytes;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_BROADCAST_FRAMES_RCV: {
+            XENVIF_PACKET_STATISTICS    Statistics;
+
+            VIF(QueryPacketStatistics,
+                Adapter->VifInterface,
+                &Statistics);
+
+            infoData = (ULONG)Statistics.Receiver.Broadcast;
+            info = &infoData;
+            bytesAvailable = sizeof(ULONG);
+            break;
+        }
+        case OID_GEN_INTERRUPT_MODERATION:
+            intModParams.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+            intModParams.Header.Revision = NDIS_INTERRUPT_MODERATION_PARAMETERS_REVISION_1;
+            intModParams.Header.Size = sizeof(NDIS_INTERRUPT_MODERATION_PARAMETERS);
+            intModParams.Flags = 0;
+            intModParams.InterruptModeration = NdisInterruptModerationNotSupported;
+            info = &intModParams;
+            bytesAvailable = sizeof(intModParams);
+            break;
+
+        // We don't handle these since NDIS 6.0 is supposed to do this for us
+        case OID_GEN_MAC_ADDRESS:
+        case OID_GEN_MAX_LINK_SPEED:
+            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+
+               // ignore these common unwanted OIDs
+               case OID_GEN_INIT_TIME_MS:
+               case OID_GEN_RESET_COUNTS:
+               case OID_GEN_MEDIA_SENSE_COUNTS:
+            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+
+        default:
+            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    };
+
+    if (ndisStatus == NDIS_STATUS_SUCCESS) {
+        if (bytesAvailable <= informationBufferLength) {
+            bytesNeeded = bytesAvailable;
+            bytesWritten = bytesAvailable;
+        } else {
+            bytesNeeded = bytesAvailable;
+            bytesWritten = informationBufferLength;
+            ndisStatus = NDIS_STATUS_BUFFER_TOO_SHORT;
+        }
+
+        if (bytesWritten && doCopy) {
+            NdisMoveMemory(informationBuffer, info, bytesWritten);
+
+            if (oid == OID_GEN_XMIT_OK || oid == OID_GEN_RCV_OK)
+                ndisStatus = NDIS_STATUS_SUCCESS;
+        }
+    }
+    
+    NdisRequest->DATA.QUERY_INFORMATION.BytesWritten = bytesWritten;
+    NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = bytesNeeded;
+    return ndisStatus;
+}
+
+NDIS_STATUS 
+AdapterReset (
+    IN  NDIS_HANDLE     MiniportAdapterContext,
+    OUT PBOOLEAN        AddressingReset
+    )
+{
+    UNREFERENCED_PARAMETER(MiniportAdapterContext);
+
+
+    *AddressingReset = FALSE;
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+//
+// Restarts a paused adapter.
+//
+NDIS_STATUS
+AdapterRestart (
+    IN  PADAPTER                            Adapter,
+    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   MiniportRestartParameters
+    )
+{
+    NTSTATUS                                status;
+    NDIS_STATUS                             ndisStatus;
+
+    UNREFERENCED_PARAMETER(MiniportRestartParameters);
+
+    Trace("====>\n");
+
+    if (Adapter->Enabled) {
+        ndisStatus = NDIS_STATUS_SUCCESS;
+        goto done;
+    }
+
+    status = VIF(Enable,
+                 Adapter->VifInterface,
+                 AdapterVifCallback,
+                 Adapter);
+    if (NT_SUCCESS(status)) {
+        TransmitterEnable(Adapter->Transmitter);
+        Adapter->Enabled = TRUE;
+        ndisStatus = NDIS_STATUS_SUCCESS;
+    } else {
+        ndisStatus = NDIS_STATUS_FAILURE;
+    }
+
+done:
+    Trace("<====\n");
+    return ndisStatus;
+}
+
+//
+// Recycle of received net buffer lists.
+//
+VOID 
+AdapterReturnNetBufferLists (
+    IN  PADAPTER            Adapter,
+    IN  PNET_BUFFER_LIST    NetBufferLists,
+    IN  ULONG               ReturnFlags
+    )
+{
+    ReceiverReturnNetBufferLists(&Adapter->Receiver,
+                                 NetBufferLists,
+                                 ReturnFlags);
+
+    return;
+}
+
+//
+// Used to send net buffer lists.
+//
+VOID 
+AdapterSendNetBufferLists (
+    IN  PADAPTER            Adapter,
+    IN  PNET_BUFFER_LIST    NetBufferList,
+    IN  NDIS_PORT_NUMBER    PortNumber,
+    IN  ULONG               SendFlags
+    )
+{
+    TransmitterSendNetBufferLists(Adapter->Transmitter,
+                                  NetBufferList,
+                                  PortNumber,
+                                  SendFlags);
+}
+
+#define XENNET_MEDIA_MAX_SPEED 1000000000ull
+
+#define XENNET_SUPPORTED_PACKET_FILTERS     \
+        (NDIS_PACKET_TYPE_DIRECTED |        \
+         NDIS_PACKET_TYPE_MULTICAST |       \
+         NDIS_PACKET_TYPE_ALL_MULTICAST |   \
+         NDIS_PACKET_TYPE_BROADCAST |       \
+         NDIS_PACKET_TYPE_PROMISCUOUS)
+
+//
+// Sets general adapter attributes. 
+//
+static NDIS_STATUS
+AdapterSetGeneralAttributes (
+    IN  PADAPTER Adapter
+    )
+{
+    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
+    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES generalAttributes;
+    NDIS_STATUS ndisStatus;
+
+    NdisZeroMemory(&generalAttributes, 
+                   sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES));
+
+    generalAttributes.Header.Type = 
+                    NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES;
+
+    generalAttributes.Header.Revision = 
+                    NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES_REVISION_1;
+
+    generalAttributes.Header.Size = 
+                    sizeof(NDIS_MINIPORT_ADAPTER_GENERAL_ATTRIBUTES);
+
+    generalAttributes.MediaType = XENNET_MEDIA_TYPE;
+
+    VIF(QueryMaximumFrameSize,
+        Adapter->VifInterface,
+        (PULONG)&Adapter->MaximumFrameSize);
+
+    generalAttributes.MtuSize = Adapter->MaximumFrameSize - sizeof (ETHERNET_HEADER);
+    generalAttributes.MaxXmitLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    generalAttributes.MaxRcvLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    generalAttributes.XmitLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    generalAttributes.RcvLinkSpeed = XENNET_MEDIA_MAX_SPEED;
+    generalAttributes.MediaConnectState = MediaConnectStateConnected;
+    generalAttributes.MediaDuplexState = MediaDuplexStateFull;
+    generalAttributes.LookaheadSize = Adapter->MaximumFrameSize;
+    generalAttributes.PowerManagementCapabilities = &Adapter->Capabilities;
+    generalAttributes.MacOptions = XENNET_MAC_OPTIONS;
+
+    generalAttributes.SupportedPacketFilters = XENNET_SUPPORTED_PACKET_FILTERS;
+        
+    generalAttributes.MaxMulticastListSize = MAXIMUM_MULTICAST_ADDRESS_COUNT;
+    generalAttributes.MacAddressLength = ETHERNET_ADDRESS_LENGTH;
+
+    VIF(QueryPermanentAddress,
+        Adapter->VifInterface,
+        (PETHERNET_ADDRESS)&generalAttributes.PermanentMacAddress);
+    VIF(QueryCurrentAddress,
+        Adapter->VifInterface,
+        (PETHERNET_ADDRESS)&generalAttributes.CurrentMacAddress);
+
+    generalAttributes.PhysicalMediumType = NdisPhysicalMedium802_3;
+    generalAttributes.RecvScaleCapabilities = NULL;
+    generalAttributes.AccessType = NET_IF_ACCESS_BROADCAST;
+    generalAttributes.DirectionType = NET_IF_DIRECTION_SENDRECEIVE;
+    generalAttributes.ConnectionType = NET_IF_CONNECTION_DEDICATED;
+    generalAttributes.IfType = IF_TYPE_ETHERNET_CSMACD; 
+    generalAttributes.IfConnectorPresent = TRUE;
+
+    generalAttributes.SupportedStatistics = NDIS_STATISTICS_XMIT_OK_SUPPORTED |
+                                            NDIS_STATISTICS_XMIT_ERROR_SUPPORTED |
+                                            NDIS_STATISTICS_DIRECTED_BYTES_XMIT_SUPPORTED |
+                                            NDIS_STATISTICS_DIRECTED_FRAMES_XMIT_SUPPORTED |
+                                            NDIS_STATISTICS_MULTICAST_BYTES_XMIT_SUPPORTED |
+                                            NDIS_STATISTICS_MULTICAST_FRAMES_XMIT_SUPPORTED |
+                                            NDIS_STATISTICS_BROADCAST_BYTES_XMIT_SUPPORTED |
+                                            NDIS_STATISTICS_BROADCAST_FRAMES_XMIT_SUPPORTED |
+                                            NDIS_STATISTICS_RCV_OK_SUPPORTED |
+                                            NDIS_STATISTICS_RCV_ERROR_SUPPORTED |
+                                            NDIS_STATISTICS_DIRECTED_BYTES_RCV_SUPPORTED |
+                                            NDIS_STATISTICS_DIRECTED_FRAMES_RCV_SUPPORTED |
+                                            NDIS_STATISTICS_MULTICAST_BYTES_RCV_SUPPORTED |
+                                            NDIS_STATISTICS_MULTICAST_FRAMES_RCV_SUPPORTED |
+                                            NDIS_STATISTICS_BROADCAST_BYTES_RCV_SUPPORTED |
+                                            NDIS_STATISTICS_BROADCAST_FRAMES_RCV_SUPPORTED |
+                                            NDIS_STATISTICS_GEN_STATISTICS_SUPPORTED;
+                      
+    generalAttributes.SupportedOidList = XennetSupportedOids;
+    generalAttributes.SupportedOidListLength = sizeof(XennetSupportedOids);
+    adapterAttributes = 
+                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&generalAttributes;
+
+    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
+                                            adapterAttributes);
+
+    return ndisStatus;
+}
+
+#define DISPLAY_OFFLOAD(_Offload)                                   \
+        do {                                                        \
+            if ((_Offload).Checksum.IPv4Receive.IpChecksum)         \
+                Info("Checksum.IPv4Receive.IpChecksum ON\n");       \
+            else                                                    \
+                Info("Checksum.IPv4Receive.IpChecksum OFF\n");      \
+                                                                    \
+            if ((_Offload).Checksum.IPv4Receive.TcpChecksum)        \
+                Info("Checksum.IPv4Receive.TcpChecksum ON\n");      \
+            else                                                    \
+                Info("Checksum.IPv4Receive.TcpChecksum OFF\n");     \
+                                                                    \
+            if ((_Offload).Checksum.IPv4Receive.UdpChecksum)        \
+                Info("Checksum.IPv4Receive.UdpChecksum ON\n");      \
+            else                                                    \
+                Info("Checksum.IPv4Receive.UdpChecksum OFF\n");     \
+                                                                    \
+            if ((_Offload).Checksum.IPv6Receive.TcpChecksum)        \
+                Info("Checksum.IPv6Receive.TcpChecksum ON\n");      \
+            else                                                    \
+                Info("Checksum.IPv6Receive.TcpChecksum OFF\n");     \
+                                                                    \
+            if ((_Offload).Checksum.IPv6Receive.UdpChecksum)        \
+                Info("Checksum.IPv6Receive.UdpChecksum ON\n");      \
+            else                                                    \
+                Info("Checksum.IPv6Receive.UdpChecksum OFF\n");     \
+                                                                    \
+            if ((_Offload).Checksum.IPv4Transmit.IpChecksum)        \
+                Info("Checksum.IPv4Transmit.IpChecksum ON\n");      \
+            else                                                    \
+                Info("Checksum.IPv4Transmit.IpChecksum OFF\n");     \
+                                                                    \
+            if ((_Offload).Checksum.IPv4Transmit.TcpChecksum)       \
+                Info("Checksum.IPv4Transmit.TcpChecksum ON\n");     \
+            else                                                    \
+                Info("Checksum.IPv4Transmit.TcpChecksum OFF\n");    \
+                                                                    \
+            if ((_Offload).Checksum.IPv4Transmit.UdpChecksum)       \
+                Info("Checksum.IPv4Transmit.UdpChecksum ON\n");     \
+            else                                                    \
+                Info("Checksum.IPv4Transmit.UdpChecksum OFF\n");    \
+                                                                    \
+            if ((_Offload).Checksum.IPv6Transmit.TcpChecksum)       \
+                Info("Checksum.IPv6Transmit.TcpChecksum ON\n");     \
+            else                                                    \
+                Info("Checksum.IPv6Transmit.TcpChecksum OFF\n");    \
+                                                                    \
+            if ((_Offload).Checksum.IPv6Transmit.UdpChecksum)       \
+                Info("Checksum.IPv6Transmit.UdpChecksum ON\n");     \
+            else                                                    \
+                Info("Checksum.IPv6Transmit.UdpChecksum OFF\n");    \
+                                                                    \
+            if ((_Offload).LsoV2.IPv4.MaxOffLoadSize != 0)          \
+                Info("LsoV2.IPv4.MaxOffLoadSize = %u\n",            \
+                     (_Offload).LsoV2.IPv4.MaxOffLoadSize);         \
+            else                                                    \
+                Info("LsoV2.IPv4 OFF\n");                           \
+                                                                    \
+            if ((_Offload).LsoV2.IPv6.MaxOffLoadSize != 0)          \
+                Info("LsoV2.IPv6.MaxOffLoadSize = %u\n",            \
+                     (_Offload).LsoV2.IPv6.MaxOffLoadSize);         \
+            else                                                    \
+                Info("LsoV2.IPv6 OFF\n");                           \
+        } while (FALSE)
+
+static NDIS_STATUS
+AdapterSetOffloadAttributes(
+    IN  PADAPTER Adapter
+    )
+{
+    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
+    NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES offloadAttributes;
+    XENVIF_OFFLOAD_OPTIONS Options;
+    NDIS_OFFLOAD current;
+    NDIS_OFFLOAD supported;
+    NDIS_STATUS ndisStatus;
+
+    Adapter->Receiver.OffloadOptions.Value = 0;
+    Adapter->Receiver.OffloadOptions.OffloadTagManipulation = 1;
+
+    if (Adapter->Properties.need_csum_value)
+        Adapter->Receiver.OffloadOptions.NeedChecksumValue = 1;
+
+    if (Adapter->Properties.lrov4) {
+        Adapter->Receiver.OffloadOptions.OffloadIpVersion4LargePacket = 1;
+        Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
+    }
+
+    if (Adapter->Properties.lrov6) {
+        Adapter->Receiver.OffloadOptions.OffloadIpVersion6LargePacket = 1;
+        Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
+    }
+
+    Adapter->Transmitter->OffloadOptions.Value = 0;
+    Adapter->Transmitter->OffloadOptions.OffloadTagManipulation = 1;
+
+    NdisZeroMemory(&offloadAttributes, sizeof(offloadAttributes));
+    NdisZeroMemory(&current, sizeof(current));
+    NdisZeroMemory(&supported, sizeof(supported));
+    
+    VIF(UpdateOffloadOptions,
+        Adapter->VifInterface,
+        Adapter->Receiver.OffloadOptions);
+
+    supported.Header.Type = NDIS_OBJECT_TYPE_OFFLOAD;
+    supported.Header.Revision = NDIS_OFFLOAD_REVISION_1;
+    supported.Header.Size = sizeof(supported);
+
+    supported.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+
+    supported.Checksum.IPv4Receive.IpChecksum = 1;
+    supported.Checksum.IPv4Receive.IpOptionsSupported = 1;
+
+    supported.Checksum.IPv4Receive.TcpChecksum = 1;
+    supported.Checksum.IPv4Receive.TcpOptionsSupported = 1;
+
+    supported.Checksum.IPv4Receive.UdpChecksum = 1;
+
+    supported.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+
+    supported.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
+
+    supported.Checksum.IPv6Receive.TcpChecksum = 1;
+    supported.Checksum.IPv6Receive.TcpOptionsSupported = 1;
+
+    supported.Checksum.IPv6Receive.UdpChecksum = 1;
+
+    VIF(QueryOffloadOptions,
+        Adapter->VifInterface,
+        &Options);
+
+    supported.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+
+    if (Options.OffloadIpVersion4HeaderChecksum) {
+        supported.Checksum.IPv4Transmit.IpChecksum = 1;
+        supported.Checksum.IPv4Transmit.IpOptionsSupported = 1;
+    }
+
+    if (Options.OffloadIpVersion4TcpChecksum) {
+        supported.Checksum.IPv4Transmit.TcpChecksum = 1;
+        supported.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
+    }
+
+    if (Options.OffloadIpVersion4UdpChecksum)
+        supported.Checksum.IPv4Transmit.UdpChecksum = 1;
+
+    supported.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+
+    supported.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
+
+    if (Options.OffloadIpVersion6TcpChecksum) {
+        supported.Checksum.IPv6Transmit.TcpChecksum = 1;
+        supported.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
+    }
+
+    if (Options.OffloadIpVersion6UdpChecksum)
+        supported.Checksum.IPv6Transmit.UdpChecksum = 1;
+
+    if (Options.OffloadIpVersion4LargePacket) {
+        ULONG Size;
+
+        VIF(QueryLargePacketSize,
+            Adapter->VifInterface,
+            4,
+            &Size);
+
+        supported.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        supported.LsoV2.IPv4.MaxOffLoadSize = Size;
+        supported.LsoV2.IPv4.MinSegmentCount = 2;
+    }
+
+    if (Options.OffloadIpVersion6LargePacket) {
+        ULONG Size;
+
+        VIF(QueryLargePacketSize,
+            Adapter->VifInterface,
+            6,
+            &Size);
+
+        supported.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        supported.LsoV2.IPv6.MaxOffLoadSize = Size;
+        supported.LsoV2.IPv6.MinSegmentCount = 2;
+        supported.LsoV2.IPv6.IpExtensionHeadersSupported = 1;
+        supported.LsoV2.IPv6.TcpOptionsSupported = 1;
+    }
+
+    current = supported;
+
+    if (!(Adapter->Properties.ipv4_csum & 2))
+        current.Checksum.IPv4Receive.IpChecksum = 0;
+
+    if (!(Adapter->Properties.tcpv4_csum & 2))
+        current.Checksum.IPv4Receive.TcpChecksum = 0;
+
+    if (!(Adapter->Properties.udpv4_csum & 2))
+        current.Checksum.IPv4Receive.UdpChecksum = 0;
+
+    if (!(Adapter->Properties.tcpv6_csum & 2))
+        current.Checksum.IPv6Receive.TcpChecksum = 0;
+
+    if (!(Adapter->Properties.udpv6_csum & 2))
+        current.Checksum.IPv6Receive.UdpChecksum = 0;
+
+    if (!(Adapter->Properties.ipv4_csum & 1))
+        current.Checksum.IPv4Transmit.IpChecksum = 0;
+
+    if (!(Adapter->Properties.tcpv4_csum & 1))
+        current.Checksum.IPv4Transmit.TcpChecksum = 0;
+
+    if (!(Adapter->Properties.udpv4_csum & 1))
+        current.Checksum.IPv4Transmit.UdpChecksum = 0;
+
+    if (!(Adapter->Properties.tcpv6_csum & 1))
+        current.Checksum.IPv6Transmit.TcpChecksum = 0;
+
+    if (!(Adapter->Properties.udpv6_csum & 1))
+        current.Checksum.IPv6Transmit.UdpChecksum = 0;
+
+    if (!(Adapter->Properties.lsov4)) {
+        current.LsoV2.IPv4.MaxOffLoadSize = 0;
+        current.LsoV2.IPv4.MinSegmentCount = 0;
+    }
+
+    if (!(Adapter->Properties.lsov6)) {
+        current.LsoV2.IPv6.MaxOffLoadSize = 0;
+        current.LsoV2.IPv6.MinSegmentCount = 0;
+    }
+
+    if (!RtlEqualMemory(&Adapter->Offload, &current, sizeof (NDIS_OFFLOAD))) {
+        Adapter->Offload = current;
+
+        DISPLAY_OFFLOAD(current);
+    }
+
+    offloadAttributes.Header.Type =
+        NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES;
+    offloadAttributes.Header.Revision =
+        NDIS_MINIPORT_ADAPTER_OFFLOAD_ATTRIBUTES_REVISION_1;
+    offloadAttributes.Header.Size = sizeof(offloadAttributes);
+    offloadAttributes.DefaultOffloadConfiguration = &current;
+    offloadAttributes.HardwareOffloadCapabilities = &supported;
+
+    adapterAttributes =
+        (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&offloadAttributes;
+    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
+                                            adapterAttributes);
+
+    return ndisStatus;
+}
+
+static void
+AdapterIndicateOffloadChanged (
+    IN  PADAPTER Adapter
+    )
+{
+    NDIS_STATUS_INDICATION indication;
+    NDIS_OFFLOAD offload;
+
+    NdisZeroMemory(&offload, sizeof(offload));
+    INITIALIZE_NDIS_OBJ_HEADER(offload, OFFLOAD);
+
+    offload.Checksum.IPv4Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+
+    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum) {
+        offload.Checksum.IPv4Receive.IpChecksum = 1;
+        offload.Checksum.IPv4Receive.IpOptionsSupported = 1;
+    }
+
+    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum) {
+        offload.Checksum.IPv4Receive.TcpChecksum = 1;
+        offload.Checksum.IPv4Receive.TcpOptionsSupported = 1;
+    }
+
+    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum) {
+        offload.Checksum.IPv4Receive.UdpChecksum = 1;
+    }
+
+    offload.Checksum.IPv6Receive.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+
+    offload.Checksum.IPv6Receive.IpExtensionHeadersSupported = 1;
+
+    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum) {
+        offload.Checksum.IPv6Receive.TcpChecksum = 1;
+        offload.Checksum.IPv6Receive.TcpOptionsSupported = 1;
+    }
+
+    if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum) {
+        offload.Checksum.IPv6Receive.UdpChecksum = 1;
+    }
+
+    VIF(UpdateOffloadOptions,
+        Adapter->VifInterface,
+        Adapter->Receiver.OffloadOptions);
+
+    offload.Checksum.IPv4Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+
+    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
+        offload.Checksum.IPv4Transmit.IpChecksum = 1;
+        offload.Checksum.IPv4Transmit.IpOptionsSupported = 1;
+    }
+
+    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum) {
+        offload.Checksum.IPv4Transmit.TcpChecksum = 1;
+        offload.Checksum.IPv4Transmit.TcpOptionsSupported = 1;
+    }
+
+    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum) {
+        offload.Checksum.IPv4Transmit.UdpChecksum = 1;
+    }
+
+    offload.Checksum.IPv6Transmit.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+
+    offload.Checksum.IPv6Transmit.IpExtensionHeadersSupported = 1;
+
+    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum) {
+        offload.Checksum.IPv6Transmit.TcpChecksum = 1;
+        offload.Checksum.IPv6Transmit.TcpOptionsSupported = 1;
+    }
+
+    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum) {
+        offload.Checksum.IPv6Transmit.UdpChecksum = 1;
+    }
+
+    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket) {
+        ULONG Size;
+
+        VIF(QueryLargePacketSize,
+            Adapter->VifInterface,
+            4,
+            &Size);
+
+        offload.LsoV2.IPv4.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        offload.LsoV2.IPv4.MaxOffLoadSize = Size;
+        offload.LsoV2.IPv4.MinSegmentCount = 2;
+    }
+
+    if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket) {
+        ULONG Size;
+
+        VIF(QueryLargePacketSize,
+            Adapter->VifInterface,
+            6,
+            &Size);
+
+        offload.LsoV2.IPv6.Encapsulation = NDIS_ENCAPSULATION_IEEE_802_3;
+        offload.LsoV2.IPv6.MaxOffLoadSize = Size;
+        offload.LsoV2.IPv6.MinSegmentCount = 2;
+        offload.LsoV2.IPv6.IpExtensionHeadersSupported = 1;
+        offload.LsoV2.IPv6.TcpOptionsSupported = 1;
+    }
+
+    if (!RtlEqualMemory(&Adapter->Offload, &offload, sizeof (NDIS_OFFLOAD))) {
+        Adapter->Offload = offload;
+
+        DISPLAY_OFFLOAD(offload);
+    }
+
+    NdisZeroMemory(&indication, sizeof(indication));
+    INITIALIZE_NDIS_OBJ_HEADER(indication, STATUS_INDICATION);
+    indication.SourceHandle = Adapter->NdisAdapterHandle;
+    indication.StatusCode = NDIS_STATUS_TASK_OFFLOAD_CURRENT_CONFIG;
+    indication.StatusBuffer = &offload;
+    indication.StatusBufferSize = sizeof(offload);
+
+    NdisMIndicateStatusEx(Adapter->NdisAdapterHandle, &indication);
+
+}
+
+static NDIS_STATUS
+SetMulticastAddresses(PADAPTER Adapter, PETHERNET_ADDRESS Address, ULONG Count)
+{
+    NTSTATUS status;
+
+    ASSERT3U(Count, <=, MAXIMUM_MULTICAST_ADDRESS_COUNT);
+
+    status = VIF(UpdateMulticastAddresses,
+                 Adapter->VifInterface,
+                 Address,
+                 Count);
+    if (!NT_SUCCESS(status))
+        return NDIS_STATUS_INVALID_DATA;
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+static NDIS_STATUS
+SetPacketFilter(PADAPTER Adapter, PULONG PacketFilter)
+{
+    XENVIF_MAC_FILTER_LEVEL UnicastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL MulticastFilterLevel;
+    XENVIF_MAC_FILTER_LEVEL BroadcastFilterLevel;
+
+    if (*PacketFilter & ~XENNET_SUPPORTED_PACKET_FILTERS)
+        return NDIS_STATUS_INVALID_PARAMETER;
+
+    if (*PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {
+        UnicastFilterLevel = MAC_FILTER_ALL;
+        MulticastFilterLevel = MAC_FILTER_ALL;
+        BroadcastFilterLevel = MAC_FILTER_ALL;
+        goto done;
+    }
+
+    if (*PacketFilter & NDIS_PACKET_TYPE_DIRECTED)
+        UnicastFilterLevel = MAC_FILTER_MATCHING;
+    else
+        UnicastFilterLevel = MAC_FILTER_NONE;
+
+    if (*PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
+        MulticastFilterLevel = MAC_FILTER_ALL;
+    else if (*PacketFilter & NDIS_PACKET_TYPE_MULTICAST)
+        MulticastFilterLevel = MAC_FILTER_MATCHING;
+    else
+        MulticastFilterLevel = MAC_FILTER_NONE;
+
+    if (*PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
+        BroadcastFilterLevel = MAC_FILTER_ALL;
+    else
+        BroadcastFilterLevel = MAC_FILTER_NONE;
+
+done:
+    VIF(UpdateFilterLevel,
+        Adapter->VifInterface,
+        ETHERNET_ADDRESS_UNICAST,
+        UnicastFilterLevel);
+
+    VIF(UpdateFilterLevel,
+        Adapter->VifInterface,
+        ETHERNET_ADDRESS_MULTICAST,
+        MulticastFilterLevel);
+
+    VIF(UpdateFilterLevel,
+        Adapter->VifInterface,
+        ETHERNET_ADDRESS_BROADCAST,
+        BroadcastFilterLevel);
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+//
+// Set OID handler.
+//
+static NDIS_STATUS 
+AdapterSetInformation (
+    IN  PADAPTER            Adapter,
+    IN  PNDIS_OID_REQUEST   NdisRequest
+    )
+{
+    ULONG addressCount;
+    ULONG bytesNeeded = 0;
+    ULONG bytesRead = 0;
+    PVOID informationBuffer;
+    ULONG informationBufferLength;
+    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
+    NDIS_OID oid;
+    BOOLEAN offloadChanged;
+
+    informationBuffer = NdisRequest->DATA.SET_INFORMATION.InformationBuffer;
+    informationBufferLength = NdisRequest->DATA.SET_INFORMATION.InformationBufferLength;
+    oid = NdisRequest->DATA.QUERY_INFORMATION.Oid;
+    switch (oid) {
+        case OID_PNP_SET_POWER:
+            bytesNeeded = sizeof(NDIS_DEVICE_POWER_STATE);
+            if (informationBufferLength >= bytesNeeded) {
+                PNDIS_DEVICE_POWER_STATE state;
+
+                state = (PNDIS_DEVICE_POWER_STATE)informationBuffer;
+                switch (*state) {
+                case NdisDeviceStateD0:
+                    Info("SET_POWER: D0\n");
+                    break;
+
+                case NdisDeviceStateD1:
+                    Info("SET_POWER: D1\n");
+                    break;
+
+                case NdisDeviceStateD2:
+                    Info("SET_POWER: D2\n");
+                    break;
+
+                case NdisDeviceStateD3:
+                    Info("SET_POWER: D3\n");
+                    break;
+                }
+            }
+            break;
+
+        case OID_GEN_MACHINE_NAME:
+            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+
+        case OID_GEN_CURRENT_LOOKAHEAD:
+            bytesNeeded = sizeof(ULONG);
+            Adapter->CurrentLookahead = Adapter->MaximumFrameSize;
+            if (informationBufferLength == sizeof(ULONG)) {
+                Adapter->CurrentLookahead = *(PULONG)informationBuffer;
+                bytesRead = sizeof(ULONG);
+            }
+
+            break;
+
+        case OID_GEN_CURRENT_PACKET_FILTER:
+            bytesNeeded = sizeof(ULONG);
+            if (informationBufferLength == sizeof(ULONG)) {
+                ndisStatus = SetPacketFilter(Adapter, (PULONG)informationBuffer);
+                bytesRead = sizeof(ULONG);
+            }
+
+            break;
+
+        case OID_802_3_MULTICAST_LIST:
+            bytesNeeded = ETHERNET_ADDRESS_LENGTH;
+            if (informationBufferLength % ETHERNET_ADDRESS_LENGTH == 0) {
+                addressCount = informationBufferLength / ETHERNET_ADDRESS_LENGTH;
+
+                ndisStatus = SetMulticastAddresses(Adapter, informationBuffer, addressCount);
+                if (ndisStatus == NDIS_STATUS_SUCCESS)
+                    bytesRead = informationBufferLength;
+            } else {
+                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
+            }
+
+            break;
+
+        case OID_GEN_INTERRUPT_MODERATION:
+            ndisStatus = NDIS_STATUS_INVALID_DATA;
+            break;
+
+        case OID_OFFLOAD_ENCAPSULATION: {
+            PNDIS_OFFLOAD_ENCAPSULATION offloadEncapsulation;
+
+            bytesNeeded = sizeof(*offloadEncapsulation);
+            if (informationBufferLength >= bytesNeeded) {
+                XENVIF_OFFLOAD_OPTIONS Options;
+
+                bytesRead = bytesNeeded;
+                offloadEncapsulation = informationBuffer;
+                ndisStatus = NDIS_STATUS_SUCCESS;
+
+                if (offloadEncapsulation->IPv4.Enabled == NDIS_OFFLOAD_SET_ON) {
+                    if (offloadEncapsulation->IPv4.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
+                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+                }
+
+                if (offloadEncapsulation->IPv6.Enabled == NDIS_OFFLOAD_SET_ON) {
+                    if (offloadEncapsulation->IPv6.EncapsulationType != NDIS_ENCAPSULATION_IEEE_802_3)
+                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+                }
+
+                VIF(QueryOffloadOptions,
+                    Adapter->VifInterface,
+                    &Options);
+                
+                Adapter->Transmitter->OffloadOptions.Value = 0;
+                Adapter->Transmitter->OffloadOptions.OffloadTagManipulation = 1;
+
+                if ((Adapter->Properties.lsov4) && (Options.OffloadIpVersion4LargePacket))
+                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 1;
+
+                if ((Adapter->Properties.lsov6) && (Options.OffloadIpVersion6LargePacket))
+                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 1;
+
+                if ((Adapter->Properties.ipv4_csum & 1) && Options.OffloadIpVersion4HeaderChecksum)
+                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
+
+                if ((Adapter->Properties.tcpv4_csum & 1) && Options.OffloadIpVersion4TcpChecksum)
+                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
+
+                if ((Adapter->Properties.udpv4_csum & 1) && Options.OffloadIpVersion4UdpChecksum)
+                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
+
+                if ((Adapter->Properties.tcpv6_csum & 1) && Options.OffloadIpVersion6TcpChecksum)
+                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
+
+                if ((Adapter->Properties.udpv6_csum & 1) && Options.OffloadIpVersion6UdpChecksum)
+                    Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
+
+                Adapter->Receiver.OffloadOptions.Value = 0;
+                Adapter->Receiver.OffloadOptions.OffloadTagManipulation = 1;
+
+                if (Adapter->Properties.need_csum_value)
+                    Adapter->Receiver.OffloadOptions.NeedChecksumValue = 1;
+
+                if (Adapter->Properties.lrov4) {
+                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4LargePacket = 1;
+                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
+                }
+
+                if (Adapter->Properties.lrov6) {
+                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6LargePacket = 1;
+                    Adapter->Receiver.OffloadOptions.NeedLargePacketSplit = 1;
+                }
+
+                if (Adapter->Properties.ipv4_csum & 2)
+                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
+
+                if (Adapter->Properties.tcpv4_csum & 2)
+                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
+
+                if (Adapter->Properties.udpv4_csum & 2)
+                    Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
+
+                if (Adapter->Properties.tcpv6_csum & 2)
+                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
+
+                if (Adapter->Properties.udpv6_csum & 2)
+                    Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
+
+                AdapterIndicateOffloadChanged(Adapter);
+            }
+            break;
+        }
+        case OID_TCP_OFFLOAD_PARAMETERS: {
+            PNDIS_OFFLOAD_PARAMETERS offloadParameters;
+
+            bytesNeeded = sizeof(*offloadParameters);
+            if (informationBufferLength >= bytesNeeded) {
+                bytesRead = bytesNeeded;
+                offloadParameters = informationBuffer;
+                ndisStatus = NDIS_STATUS_SUCCESS;
+
+#define no_change(x)  ((x) == NDIS_OFFLOAD_PARAMETERS_NO_CHANGE)
+
+                if (!no_change(offloadParameters->IPsecV1))
+                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+                    
+                if (!no_change(offloadParameters->LsoV1))
+                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+
+                if (!no_change(offloadParameters->TcpConnectionIPv4))
+                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+
+                if (!no_change(offloadParameters->TcpConnectionIPv6))
+                    ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+
+                if (!no_change(offloadParameters->LsoV2IPv4)) {
+                    XENVIF_OFFLOAD_OPTIONS  Options;
+
+                    VIF(QueryOffloadOptions,
+                        Adapter->VifInterface,
+                        &Options);
+
+                    if (!(Options.OffloadIpVersion4LargePacket))
+                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+                }
+
+                if (!no_change(offloadParameters->LsoV2IPv6)) {
+                    XENVIF_OFFLOAD_OPTIONS  Options;
+
+                    VIF(QueryOffloadOptions,
+                        Adapter->VifInterface,
+                        &Options);
+
+                    if (!(Options.OffloadIpVersion6LargePacket))
+                        ndisStatus = NDIS_STATUS_INVALID_PARAMETER;
+                }
+
+#define rx_enabled(x) ((x) == NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED ||       \
+                       (x) == NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED)
+#define tx_enabled(x) ((x) == NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED ||       \
+                       (x) == NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED)
+
+                if (ndisStatus == NDIS_STATUS_SUCCESS) {
+                    offloadChanged = FALSE;
+
+                    if (offloadParameters->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
+                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else if (offloadParameters->LsoV2IPv4 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
+                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4LargePacket = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (offloadParameters->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED) {
+                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else if (offloadParameters->LsoV2IPv6 == NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED) {
+                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6LargePacket = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (tx_enabled(offloadParameters->IPv4Checksum)) {
+                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else {
+                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4HeaderChecksum = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (tx_enabled(offloadParameters->TCPIPv4Checksum)) {
+                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else {
+                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4TcpChecksum = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (tx_enabled(offloadParameters->UDPIPv4Checksum)) {
+                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else {
+                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion4UdpChecksum = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (tx_enabled(offloadParameters->TCPIPv6Checksum)) {
+                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else {
+                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6TcpChecksum = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (tx_enabled(offloadParameters->UDPIPv6Checksum)) {
+                        if (!Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else {
+                        if (Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum) {
+                            Adapter->Transmitter->OffloadOptions.OffloadIpVersion6UdpChecksum = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (rx_enabled(offloadParameters->IPv4Checksum)) {
+                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum) {
+                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else {
+                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum) {
+                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4HeaderChecksum = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (rx_enabled(offloadParameters->TCPIPv4Checksum)) {
+                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum) {
+                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else {
+                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum) {
+                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4TcpChecksum = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (rx_enabled(offloadParameters->UDPIPv4Checksum)) {
+                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum) {
+                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else {
+                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum) {
+                            Adapter->Receiver.OffloadOptions.OffloadIpVersion4UdpChecksum = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (rx_enabled(offloadParameters->TCPIPv6Checksum)) {
+                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum) {
+                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else {
+                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum) {
+                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6TcpChecksum = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+                    if (rx_enabled(offloadParameters->UDPIPv6Checksum)) {
+                        if (!Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum) {
+                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
+                            offloadChanged = TRUE;
+                        }
+                    } else {
+                        if (Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum) {
+                            Adapter->Receiver.OffloadOptions.OffloadIpVersion6UdpChecksum = 0;
+                            offloadChanged = TRUE;
+                        }
+                    }
+
+#undef tx_enabled
+#undef rx_enabled
+#undef no_change
+
+                    if (offloadChanged)
+                        AdapterIndicateOffloadChanged(Adapter);
+                }
+            } else {
+                ndisStatus = NDIS_STATUS_INVALID_LENGTH;
+            }
+            break;
+        }
+        default:
+            ndisStatus = NDIS_STATUS_NOT_SUPPORTED;
+            break;
+    };
+
+    NdisRequest->DATA.SET_INFORMATION.BytesNeeded = bytesNeeded;
+    if (ndisStatus == NDIS_STATUS_SUCCESS) {
+        NdisRequest->DATA.SET_INFORMATION.BytesRead = bytesRead;
+    }
+
+    return ndisStatus;
+}
+
+//
+// Sets miniport registration attributes.
+//
+static NDIS_STATUS
+AdapterSetRegistrationAttributes (
+    IN  PADAPTER Adapter
+    )
+{
+    PNDIS_MINIPORT_ADAPTER_ATTRIBUTES adapterAttributes;
+    NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES registrationAttributes;
+    NDIS_STATUS ndisStatus;
+
+
+    NdisZeroMemory(&registrationAttributes, 
+                   sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES));
+
+    registrationAttributes.Header.Type = 
+                NDIS_OBJECT_TYPE_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES;
+
+    registrationAttributes.Header.Revision = 
+                NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES_REVISION_1;
+
+    registrationAttributes.Header.Size = 
+                sizeof(NDIS_MINIPORT_ADAPTER_REGISTRATION_ATTRIBUTES);
+
+    registrationAttributes.MiniportAdapterContext = (NDIS_HANDLE)Adapter;
+    registrationAttributes.AttributeFlags = NDIS_MINIPORT_ATTRIBUTES_BUS_MASTER |
+                                            NDIS_MINIPORT_ATTRIBUTES_NO_HALT_ON_SUSPEND;
+    
+    registrationAttributes.CheckForHangTimeInSeconds = 0;
+    registrationAttributes.InterfaceType = XENNET_INTERFACE_TYPE;
+
+    adapterAttributes = 
+                (PNDIS_MINIPORT_ADAPTER_ATTRIBUTES)&registrationAttributes;
+
+    ndisStatus = NdisMSetMiniportAttributes(Adapter->NdisAdapterHandle,
+                                            adapterAttributes);
+
+    return ndisStatus;
+}
+
+//
+// Shuts down adapter.
+//
+VOID 
+AdapterShutdown (
+    IN  PADAPTER                Adapter,
+    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
+    )
+{
+    UNREFERENCED_PARAMETER(ShutdownAction);
+
+    if (ShutdownAction != NdisShutdownBugCheck)
+        AdapterStop(Adapter);
+
+    return;
+}
+
+//
+// Stops adapter. Waits for currently transmitted packets to complete.
+// Stops transmission of new packets.
+// Stops received packet indication to NDIS.
+//
+static NDIS_STATUS
+AdapterStop (
+IN  PADAPTER    Adapter
+)
+{
+    Trace("====>\n");
+
+    if (!Adapter->Enabled)
+        goto done;
+
+    VIF(Disable,
+        Adapter->VifInterface);
+
+    Adapter->Enabled = FALSE;
+
+done:
+    Trace("<====\n");
+    return NDIS_STATUS_SUCCESS;
+}
diff --git a/src/xennet/adapter.h b/src/xennet/adapter.h
new file mode 100644 (file)
index 0000000..209d6be
--- /dev/null
@@ -0,0 +1,163 @@
+/* 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.
+ */
+
+#pragma once
+
+#define XENNET_INTERFACE_TYPE           NdisInterfaceInternal
+
+#define XENNET_MEDIA_TYPE               NdisMedium802_3
+
+#define XENNET_MAC_OPTIONS              (NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |  \
+                                         NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |   \
+                                         NDIS_MAC_OPTION_NO_LOOPBACK |          \
+                                         NDIS_MAC_OPTION_8021P_PRIORITY |       \
+                                         NDIS_MAC_OPTION_SUPPORTS_MAC_ADDRESS_OVERWRITE)
+
+typedef struct _PROPERTIES {
+    int ipv4_csum;
+    int tcpv4_csum;
+    int udpv4_csum;
+    int tcpv6_csum;
+    int udpv6_csum;
+    int need_csum_value;
+    int lsov4;
+    int lsov6;
+    int lrov4;
+    int lrov6;
+} PROPERTIES, *PPROPERTIES;
+
+struct _ADAPTER {
+    LIST_ENTRY              ListEntry;
+    PXENVIF_VIF_INTERFACE   VifInterface;
+    BOOLEAN                 AcquiredInterfaces;
+    ULONG                   MaximumFrameSize;
+    ULONG                   CurrentLookahead;
+    NDIS_HANDLE             NdisAdapterHandle;
+    NDIS_HANDLE             NdisDmaHandle;
+    NDIS_PNP_CAPABILITIES   Capabilities;
+    PROPERTIES              Properties;
+    RECEIVER                Receiver;
+    PTRANSMITTER            Transmitter;
+    BOOLEAN                 Enabled;
+    NDIS_OFFLOAD            Offload;
+};
+
+VOID
+AdapterCancelOidRequest (
+    IN  PADAPTER    Adapter,
+    IN  PVOID       RequestId
+    );
+
+VOID 
+AdapterCancelSendNetBufferLists (
+    IN  PADAPTER    Adapter,
+    IN  PVOID       CancelId
+    );
+
+BOOLEAN 
+AdapterCheckForHang (
+    IN  PADAPTER Adapter
+    );
+
+VOID
+AdapterDelete (
+    IN  OUT PADAPTER* Adapter
+    );
+
+VOID 
+AdapterHalt (
+    IN  PADAPTER            Adapter,
+    IN  NDIS_HALT_ACTION    HaltAction
+    );
+
+NDIS_STATUS 
+AdapterInitialize (
+    IN  PADAPTER    Adapter,
+    IN  NDIS_HANDLE AdapterHandle
+    );
+
+NDIS_STATUS 
+AdapterOidRequest (
+    IN  PADAPTER            Adapter,
+    IN  PNDIS_OID_REQUEST   NdisRequest
+    );
+
+NDIS_STATUS 
+AdapterPause (
+    IN  PADAPTER                        Adapter,
+    IN  PNDIS_MINIPORT_PAUSE_PARAMETERS MiniportPauseParameters
+    );
+
+VOID 
+AdapterPnPEventHandler (
+    IN  PADAPTER                Adapter,
+    IN  PNET_DEVICE_PNP_EVENT   NetDevicePnPEvent
+    );
+
+NDIS_STATUS 
+AdapterReset (
+    IN  NDIS_HANDLE     MiniportAdapterContext,
+    OUT PBOOLEAN        AddressingReset
+    );
+
+NDIS_STATUS 
+AdapterRestart (
+    IN  PADAPTER                            Adapter,
+    IN  PNDIS_MINIPORT_RESTART_PARAMETERS   MiniportRestartParameters
+    );
+
+VOID 
+AdapterReturnNetBufferLists (
+    IN  PADAPTER            Adapter,
+    IN  PNET_BUFFER_LIST    NetBufferLists,
+    IN  ULONG               ReturnFlags
+    );
+
+VOID 
+AdapterSendNetBufferLists (
+    IN  PADAPTER            Adapter,
+    IN  PNET_BUFFER_LIST    NetBufferList,
+    IN  NDIS_PORT_NUMBER    PortNumber,
+    IN  ULONG               SendFlags
+    );
+
+VOID 
+AdapterShutdown (
+    IN  PADAPTER                Adapter,
+    IN  NDIS_SHUTDOWN_ACTION    ShutdownAction
+    );
+
+extern VOID
+ReceiverReceivePackets(
+    IN  PRECEIVER   Receiver,
+    IN  PLIST_ENTRY List
+    );
+
diff --git a/src/xennet/assert.h b/src/xennet/assert.h
new file mode 100644 (file)
index 0000000..2debb8e
--- /dev/null
@@ -0,0 +1,173 @@
+/* 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 _XENNET_ASSERT_H
+#define _XENNET_ASSERT_H
+
+#include <ntddk.h>
+
+#include "log.h"
+
+static FORCEINLINE VOID
+__BugCheck(
+    IN  ULONG       Code,
+    IN  ULONG_PTR   Parameter1,
+    IN  ULONG_PTR   Parameter2,
+    IN  ULONG_PTR   Parameter3,
+    IN  ULONG_PTR   Parameter4
+    )
+{
+#pragma prefast(suppress:28159)
+    KeBugCheckEx(Code,
+                 Parameter1,
+                 Parameter2,
+                 Parameter3,
+                 Parameter4);
+}
+
+#define ASSERTION_FAILURE   0x0000DEAD
+
+#define BUG(_TEXT)                                              \
+        do {                                                    \
+            const CHAR  *_Text = (_TEXT);                       \
+            const CHAR  *_File = __FILE__;                      \
+            ULONG       _Line = __LINE__;                       \
+                                                                \
+            Error("BUG: " _TEXT "\n");                          \
+            __BugCheck(ASSERTION_FAILURE,                       \
+                       (ULONG_PTR)_Text,                        \
+                       (ULONG_PTR)_File,                        \
+                       (ULONG_PTR)_Line,                        \
+                       0);                                      \
+        } while (FALSE)
+
+#define BUG_ON(_EXP)                \
+        if (_EXP) BUG(#_EXP)
+
+#if DBG
+
+#define __NT_ASSERT(_EXP)                                       \
+        ((!(_EXP)) ?                                            \
+        (Error("ASSERTION FAILED: " #_EXP "\n"),                \
+         __annotation(L"Debug", L"AssertFail", L#_EXP),         \
+         DbgRaiseAssertionFailure(), FALSE) :                   \
+        TRUE)
+
+#define __ASSERT(_EXP)  __NT_ASSERT(_EXP)
+
+#else   // DBG
+
+#define __ASSERT(_EXP)  BUG_ON(!(_EXP))
+
+#endif  // DBG
+
+#undef  ASSERT
+
+#define ASSERT(_EXP)        \
+        do {                \
+            __ASSERT(_EXP); \
+        } while (FALSE)
+
+#define ASSERT3U(_X, _OP, _Y)                       \
+        do {                                        \
+            ULONGLONG   _Lval = (ULONGLONG)(_X);    \
+            ULONGLONG   _Rval = (ULONGLONG)(_Y);    \
+            if (!(_Lval _OP _Rval)) {               \
+                Error("%s = %llu\n", #_X, _Lval);   \
+                Error("%s = %llu\n", #_Y, _Rval);   \
+                ASSERT(_X _OP _Y);                  \
+            }                                       \
+        } while (FALSE)
+
+#define ASSERT3S(_X, _OP, _Y)                       \
+        do {                                        \
+            LONGLONG    _Lval = (LONGLONG)(_X);     \
+            LONGLONG    _Rval = (LONGLONG)(_Y);     \
+            if (!(_Lval _OP _Rval)) {               \
+                Error("%s = %lld\n", #_X, _Lval);   \
+                Error("%s = %lld\n", #_Y, _Rval);   \
+                ASSERT(_X _OP _Y);                  \
+            }                                       \
+        } while (FALSE)
+
+#define ASSERT3P(_X, _OP, _Y)                       \
+        do {                                        \
+            PVOID   _Lval = (PVOID)(_X);            \
+            PVOID   _Rval = (PVOID)(_Y);            \
+            if (!(_Lval _OP _Rval)) {               \
+                Error("%s = %p\n", #_X, _Lval);     \
+                Error("%s = %p\n", #_Y, _Rval);     \
+                ASSERT(_X _OP _Y);                  \
+            }                                       \
+        } while (FALSE)
+
+#ifndef TEST_MEMORY
+#define TEST_MEMORY DBG
+#endif
+
+#if TEST_MEMORY
+
+static __inline BOOLEAN
+_IsZeroMemory(
+    IN  const PCHAR Caller,
+    IN  const PCHAR Name,
+    IN  PVOID       Buffer,
+    IN  ULONG       Length
+    )
+{
+    ULONG           Offset;
+
+    Offset = 0;
+    while (Offset < Length) {
+        if (*((PUCHAR)Buffer + Offset) != 0) {
+            Error("%s: non-zero byte in %s (0x%p+0x%x)\n", Caller, Name, Buffer, Offset);
+            return FALSE;
+        }
+        Offset++;
+    }
+
+    return TRUE;
+}
+
+#define IsZeroMemory(_Buffer, _Length) \
+        _IsZeroMemory(__FUNCTION__, #_Buffer, (_Buffer), (_Length))
+
+#else   // TEST_MEMORY
+
+#define IsZeroMemory(_Buffer, _Length)  TRUE
+
+#endif  // TEST_MEMORY
+
+#define IMPLY(_X, _Y)   (!(_X) || (_Y))
+#define EQUIV(_X, _Y)   (IMPLY((_X), (_Y)) && IMPLY((_Y), (_X)))
+
+#endif  // _XENNET_ASSERT_H
+
diff --git a/src/xennet/common.h b/src/xennet/common.h
new file mode 100644 (file)
index 0000000..7ec6a08
--- /dev/null
@@ -0,0 +1,36 @@
+/* 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.
+ */
+#pragma once
+
+#include "std.h"
+#include "project.h"
+#include "log.h"
+#include "assert.h"
diff --git a/src/xennet/log.h b/src/xennet/log.h
new file mode 100644 (file)
index 0000000..40fa389
--- /dev/null
@@ -0,0 +1,135 @@
+/* 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 _XENNET_LOG_H
+#define _XENNET_LOG_H
+
+#include <stdarg.h>
+
+#pragma warning(disable:4127)   // conditional expression is constant
+
+static __inline VOID
+__Error(
+    IN  const CHAR  *Prefix,
+    IN  const CHAR  *Format,
+    ...
+    )
+{
+    va_list         Arguments;
+
+    va_start(Arguments, Format);
+
+#pragma prefast(suppress:6001) // Using uninitialized memory
+    vDbgPrintExWithPrefix(Prefix,
+                          DPFLTR_IHVDRIVER_ID,
+                          DPFLTR_ERROR_LEVEL,
+                          Format,
+                          Arguments);
+    va_end(Arguments);
+}
+
+#define Error(...)  \
+        __Error(__MODULE__ "|" __FUNCTION__ ": ", __VA_ARGS__)
+
+static __inline VOID
+__Warning(
+    IN  const CHAR  *Prefix,
+    IN  const CHAR  *Format,
+    ...
+    )
+{
+    va_list         Arguments;
+
+    va_start(Arguments, Format);
+
+#pragma prefast(suppress:6001) // Using uninitialized memory
+    vDbgPrintExWithPrefix(Prefix,
+                          DPFLTR_IHVDRIVER_ID,
+                          DPFLTR_WARNING_LEVEL,
+                          Format,
+                          Arguments);
+    va_end(Arguments);
+}
+
+#define Warning(...)  \
+        __Warning(__MODULE__ "|" __FUNCTION__ ": ", __VA_ARGS__)
+
+#if DBG
+static __inline VOID
+__Trace(
+    IN  const CHAR  *Prefix,
+    IN  const CHAR  *Format,
+    ...
+    )
+{
+    va_list         Arguments;
+
+    va_start(Arguments, Format);
+
+#pragma prefast(suppress:6001) // Using uninitialized memory
+    vDbgPrintExWithPrefix(Prefix,
+                          DPFLTR_IHVDRIVER_ID,
+                          DPFLTR_TRACE_LEVEL,
+                          Format,
+                          Arguments);
+    va_end(Arguments);
+}
+
+#define Trace(...)  \
+        __Trace(__MODULE__ "|" __FUNCTION__ ": ", __VA_ARGS__)
+#else   // DBG
+#define Trace(...)  (VOID)(__VA_ARGS__)
+#endif  // DBG
+
+static __inline VOID
+__Info(
+    IN  const CHAR  *Prefix,
+    IN  const CHAR  *Format,
+    ...
+    )
+{
+    va_list         Arguments;
+
+    va_start(Arguments, Format);
+
+#pragma prefast(suppress:6001) // Using uninitialized memory
+    vDbgPrintExWithPrefix(Prefix,
+                          DPFLTR_IHVDRIVER_ID,
+                          DPFLTR_INFO_LEVEL,
+                          Format,
+                          Arguments);
+    va_end(Arguments);
+}
+
+#define Info(...)  \
+        __Info(__MODULE__ "|"  __FUNCTION__ ": ", __VA_ARGS__)
+
+#endif  // _XENNET_LOG_H
diff --git a/src/xennet/main.c b/src/xennet/main.c
new file mode 100644 (file)
index 0000000..bd3e9d2
--- /dev/null
@@ -0,0 +1,306 @@
+/* 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 <version.h>
+
+#include "common.h"
+
+#pragma NDIS_INIT_FUNCTION(DriverEntry)
+
+//
+// Global miniport data.
+//
+
+static NDIS_HANDLE MiniportDriverHandle;
+
+extern NDIS_STATUS 
+MiniportInitialize (
+    IN  NDIS_HANDLE                        MiniportAdapterHandle,
+    IN  NDIS_HANDLE                        MiniportDriverContext,
+    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters
+    );
+
+typedef struct _XENNET_CONTEXT {
+    PDEVICE_CAPABILITIES    Capabilities;
+    PIO_COMPLETION_ROUTINE  CompletionRoutine;
+    PVOID                   CompletionContext;
+    UCHAR                   CompletionControl;
+} XENNET_CONTEXT, *PXENNET_CONTEXT;
+
+static NTSTATUS (*NdisDispatchPnp)(PDEVICE_OBJECT, PIRP);
+
+static NTSTATUS
+__QueryCapabilities(
+    IN  PDEVICE_OBJECT      DeviceObject,
+    IN  PIRP                Irp,
+    IN  PVOID               _Context
+    )
+{
+    PXENNET_CONTEXT         Context = _Context;
+    NTSTATUS                status;
+
+    Trace("====>\n");
+
+    Context->Capabilities->SurpriseRemovalOK = 1;
+
+    if (Context->CompletionRoutine != NULL &&
+        (Context->CompletionControl & SL_INVOKE_ON_SUCCESS))
+        status = Context->CompletionRoutine(DeviceObject, Irp, Context->CompletionContext);
+    else
+        status = STATUS_SUCCESS;
+
+    ExFreePool(Context);
+
+    Trace("<====\n");
+
+    return status;
+}
+
+NTSTATUS 
+QueryCapabilities(
+    IN PDEVICE_OBJECT       DeviceObject,
+    IN PIRP                 Irp
+    )
+{
+    PIO_STACK_LOCATION      StackLocation;
+    PXENNET_CONTEXT         Context;
+    NTSTATUS                status;
+
+    Trace("====>\n");
+
+    Trace("%p\n", DeviceObject); 
+
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+
+    Context = ExAllocatePoolWithTag(NonPagedPool, sizeof (XENNET_CONTEXT), ' TEN');
+    if (Context != NULL) {
+        Context->Capabilities = StackLocation->Parameters.DeviceCapabilities.Capabilities;
+        Context->CompletionRoutine = StackLocation->CompletionRoutine;
+        Context->CompletionContext = StackLocation->Context;
+        Context->CompletionControl = StackLocation->Control;
+
+        StackLocation->CompletionRoutine = __QueryCapabilities;
+        StackLocation->Context = Context;
+        StackLocation->Control = SL_INVOKE_ON_SUCCESS;
+    }
+
+    status = NdisDispatchPnp(DeviceObject, Irp);
+
+    Trace("<====\n");
+
+    return status;    
+}
+
+NTSTATUS 
+DispatchPnp(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    PIO_STACK_LOCATION  StackLocation;
+    UCHAR               MinorFunction;
+    NTSTATUS            status;
+
+    StackLocation = IoGetCurrentIrpStackLocation(Irp);
+    MinorFunction = StackLocation->MinorFunction;
+
+    switch (StackLocation->MinorFunction) {
+    case IRP_MN_QUERY_CAPABILITIES:
+        status = QueryCapabilities(DeviceObject, Irp);
+        break;
+
+    default:
+        status = NdisDispatchPnp(DeviceObject, Irp);
+        break;
+    }
+
+    return status;
+}
+
+NTSTATUS 
+DispatchFail(
+    IN PDEVICE_OBJECT   DeviceObject,
+    IN PIRP             Irp
+    )
+{
+    NTSTATUS            status;
+
+    UNREFERENCED_PARAMETER(DeviceObject);
+
+    Trace("%p\n", Irp);
+
+    status = STATUS_UNSUCCESSFUL;
+
+    Irp->IoStatus.Status = status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+    return status;
+}
+
+NTSTATUS 
+DriverEntry (
+    IN  PDRIVER_OBJECT   DriverObject,
+    IN  PUNICODE_STRING  RegistryPath
+    )
+{
+    NDIS_STATUS ndisStatus;
+    NDIS_MINIPORT_DRIVER_CHARACTERISTICS mpChars;
+    NDIS_CONFIGURATION_OBJECT ConfigurationObject;
+    NDIS_HANDLE ConfigurationHandle;
+    NDIS_STRING ParameterName;
+    PNDIS_CONFIGURATION_PARAMETER ParameterValue;
+    ULONG FailCreateClose;
+    ULONG FailDeviceControl;
+
+    ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
+
+    Trace("====>\n");
+
+    Info("%s (%s)\n",
+         MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR,
+         DAY_STR "/" MONTH_STR "/" YEAR_STR);
+
+    if (*InitSafeBootMode > 0)
+        return NDIS_STATUS_SUCCESS;
+
+    //
+    // Register miniport with NDIS.
+    //
+
+    NdisZeroMemory(&mpChars, sizeof(mpChars));
+    mpChars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,
+    mpChars.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);
+    mpChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
+
+    mpChars.MajorNdisVersion = 6;
+    mpChars.MinorNdisVersion = 0;
+    mpChars.MajorDriverVersion = MAJOR_VERSION;
+    mpChars.MinorDriverVersion = MINOR_VERSION;
+
+    mpChars.CancelOidRequestHandler = AdapterCancelOidRequest;
+    mpChars.CancelSendHandler = AdapterCancelSendNetBufferLists;
+    mpChars.CheckForHangHandlerEx = AdapterCheckForHang;
+    mpChars.InitializeHandlerEx = MiniportInitialize;
+    mpChars.HaltHandlerEx = AdapterHalt;
+    mpChars.OidRequestHandler = AdapterOidRequest;    
+    mpChars.PauseHandler = AdapterPause;      
+    mpChars.DevicePnPEventNotifyHandler  = AdapterPnPEventHandler;
+    mpChars.ResetHandlerEx = AdapterReset;
+    mpChars.RestartHandler = AdapterRestart;    
+    mpChars.ReturnNetBufferListsHandler  = AdapterReturnNetBufferLists;
+    mpChars.SendNetBufferListsHandler = AdapterSendNetBufferLists;
+    mpChars.ShutdownHandlerEx = AdapterShutdown;
+    mpChars.UnloadHandler = DriverUnload;
+
+    MiniportDriverHandle = NULL;
+    ndisStatus = NdisMRegisterMiniportDriver(DriverObject,
+                                             RegistryPath,
+                                             NULL,
+                                             &mpChars,
+                                             &MiniportDriverHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        Error("Failed (0x%08X) to register miniport.\n", ndisStatus);
+        goto fail;
+    }
+
+    ConfigurationObject.Header.Type = NDIS_OBJECT_TYPE_CONFIGURATION_OBJECT;
+    ConfigurationObject.Header.Revision = NDIS_CONFIGURATION_OBJECT_REVISION_1;
+    ConfigurationObject.Header.Size = NDIS_SIZEOF_CONFIGURATION_OBJECT_REVISION_1;
+    ConfigurationObject.NdisHandle = MiniportDriverHandle;
+    ConfigurationObject.Flags = 0;
+
+    ndisStatus = NdisOpenConfigurationEx(&ConfigurationObject, &ConfigurationHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        Error("Failed (0x%08X) to open driver configuration.\n", ndisStatus);
+        NdisMDeregisterMiniportDriver(MiniportDriverHandle);
+        goto fail;
+    }
+
+    RtlInitUnicodeString(&ParameterName, L"FailCreateClose");
+
+    NdisReadConfiguration(&ndisStatus,
+                          &ParameterValue,
+                          ConfigurationHandle,
+                          &ParameterName,
+                          NdisParameterInteger);
+    if (ndisStatus == NDIS_STATUS_SUCCESS &&
+        ParameterValue->ParameterType == NdisParameterInteger)
+        FailCreateClose = ParameterValue->ParameterData.IntegerData;
+    else
+        FailCreateClose = 0;
+
+    RtlInitUnicodeString(&ParameterName, L"FailDeviceControl");
+
+    NdisReadConfiguration(&ndisStatus,
+                          &ParameterValue,
+                          ConfigurationHandle,
+                          &ParameterName,
+                          NdisParameterInteger);
+    if (ndisStatus == NDIS_STATUS_SUCCESS &&
+        ParameterValue->ParameterType == NdisParameterInteger)
+        FailDeviceControl = ParameterValue->ParameterData.IntegerData;
+    else
+        FailDeviceControl = 0;
+
+    NdisCloseConfiguration(ConfigurationHandle);
+    ndisStatus = NDIS_STATUS_SUCCESS;
+
+    NdisDispatchPnp = DriverObject->MajorFunction[IRP_MJ_PNP];
+    DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
+
+    if (FailCreateClose != 0) {
+        DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchFail;
+        DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchFail;
+    }
+
+    if (FailDeviceControl != 0) {
+        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchFail;
+    }
+
+fail:
+    Trace("<====\n");
+    return ndisStatus;
+}
+
+VOID 
+DriverUnload (
+    IN  PDRIVER_OBJECT  DriverObject
+    )
+{
+    UNREFERENCED_PARAMETER(DriverObject);
+
+    Trace("====>\n");
+
+    if (MiniportDriverHandle)
+        NdisMDeregisterMiniportDriver(MiniportDriverHandle);
+
+    Trace("<====\n");
+}
diff --git a/src/xennet/miniport.c b/src/xennet/miniport.c
new file mode 100644 (file)
index 0000000..3ba84cf
--- /dev/null
@@ -0,0 +1,165 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#define INITGUID 1
+
+#include "common.h"
+
+#pragma warning( disable : 4098 )
+
+static NTSTATUS
+QueryVifInterface(
+    IN  PDEVICE_OBJECT      DeviceObject,
+    IN  PADAPTER            Adapter
+    )
+{
+    KEVENT                  Event;
+    IO_STATUS_BLOCK         StatusBlock;
+    PIRP                    Irp;
+    PIO_STACK_LOCATION      StackLocation;
+    INTERFACE               Interface;
+    NTSTATUS                status;
+
+    KeInitializeEvent(&Event, NotificationEvent, FALSE);
+    RtlZeroMemory(&StatusBlock, sizeof(IO_STATUS_BLOCK));
+
+    Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+                                       DeviceObject,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       &Event,
+                                       &StatusBlock);
+
+    status = STATUS_UNSUCCESSFUL;
+    if (Irp == NULL)
+        goto fail1;
+
+    StackLocation = IoGetNextIrpStackLocation(Irp);
+    StackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
+
+    StackLocation->Parameters.QueryInterface.InterfaceType = &GUID_VIF_INTERFACE;
+    StackLocation->Parameters.QueryInterface.Size = sizeof (INTERFACE);
+    StackLocation->Parameters.QueryInterface.Version = VIF_INTERFACE_VERSION;
+    StackLocation->Parameters.QueryInterface.Interface = &Interface;
+    
+    Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+
+    status = IoCallDriver(DeviceObject, Irp);
+    if (status == STATUS_PENDING) {
+        KeWaitForSingleObject(&Event,
+                              Executive,
+                              KernelMode,
+                              FALSE,
+                              NULL);
+        status = StatusBlock.Status;
+    }
+
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    status = STATUS_INVALID_PARAMETER;
+    if (Interface.Version != VIF_INTERFACE_VERSION)
+        goto fail3;
+
+    Adapter->VifInterface = Interface.Context;
+
+    return STATUS_SUCCESS;
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NDIS_STATUS 
+MiniportInitialize (
+    IN  NDIS_HANDLE                        MiniportAdapterHandle,
+    IN  NDIS_HANDLE                        MiniportDriverContext,
+    IN  PNDIS_MINIPORT_INIT_PARAMETERS     MiniportInitParameters
+    )
+{
+    PADAPTER adapter = NULL;
+    NDIS_STATUS ndisStatus;
+    PDEVICE_OBJECT pdo;
+    NTSTATUS status;
+
+    UNREFERENCED_PARAMETER(MiniportDriverContext);
+    UNREFERENCED_PARAMETER(MiniportInitParameters);
+
+    Trace("====>\n");
+
+    adapter = ExAllocatePoolWithTag(NonPagedPool, sizeof (ADAPTER), ' TEN');
+
+    if (adapter == NULL) {
+        ndisStatus = NDIS_STATUS_RESOURCES;
+        goto exit;
+    }
+
+    RtlZeroMemory(adapter, sizeof (ADAPTER));
+
+    pdo = NULL;
+    NdisMGetDeviceProperty(MiniportAdapterHandle,
+                           &pdo,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL);
+
+    status = QueryVifInterface(pdo, adapter);
+    if (!NT_SUCCESS(status)) {
+        ndisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND;
+        goto exit;
+    }
+
+    adapter->AcquiredInterfaces = TRUE;
+
+    ndisStatus = AdapterInitialize(adapter, MiniportAdapterHandle);
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+    if (ndisStatus != NDIS_STATUS_SUCCESS) {
+        if (adapter != NULL) {
+            AdapterDelete(&adapter);
+        }
+    }
+
+    Trace("<====\n");
+    return ndisStatus;
+}
diff --git a/src/xennet/project.h b/src/xennet/project.h
new file mode 100644 (file)
index 0000000..7b90ead
--- /dev/null
@@ -0,0 +1,64 @@
+/* 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.
+ */
+
+#pragma once
+
+#include <util.h>
+#include <ethernet.h>
+#include <tcpip.h>
+#include <vif_interface.h>
+
+typedef struct _ADAPTER ADAPTER, *PADAPTER;
+
+NTSTATUS 
+DriverEntry (
+    IN  PDRIVER_OBJECT   DriverObject,
+    IN  PUNICODE_STRING  RegistryPath
+    );
+
+VOID 
+DriverUnload (
+    IN  PDRIVER_OBJECT  DriverObject
+    );
+
+NDIS_STATUS
+MpSetAdapterSettings(
+    IN PADAPTER Adapter
+    );
+
+NDIS_STATUS
+MpGetAdvancedSettings(
+    IN PADAPTER Adapter
+    );
+
+#include "transmitter.h"
+#include "receiver.h"
+#include "adapter.h"
diff --git a/src/xennet/receiver.c b/src/xennet/receiver.c
new file mode 100644 (file)
index 0000000..efa45fa
--- /dev/null
@@ -0,0 +1,421 @@
+/* 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 "common.h"
+
+#pragma warning(disable:4711)
+
+NDIS_STATUS
+ReceiverInitialize (
+    IN  PRECEIVER                   Receiver
+    )
+{
+    PADAPTER                        Adapter;
+    NDIS_STATUS                     ndisStatus = NDIS_STATUS_SUCCESS;
+    NET_BUFFER_LIST_POOL_PARAMETERS poolParameters;
+    ULONG                           Cpu;
+
+    Receiver->PutList = NULL;
+    for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++)
+        Receiver->GetList[Cpu] = NULL;
+
+    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+
+    NdisZeroMemory(&poolParameters, sizeof(NET_BUFFER_LIST_POOL_PARAMETERS));
+    poolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT;
+    poolParameters.Header.Revision =
+        NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1;
+    poolParameters.Header.Size = sizeof(poolParameters);
+    poolParameters.ProtocolId = 0;
+    poolParameters.ContextSize = 0;
+    poolParameters.fAllocateNetBuffer = TRUE;
+    poolParameters.PoolTag = ' TEN';
+
+    Receiver->NetBufferListPool =
+        NdisAllocateNetBufferListPool(Adapter->NdisAdapterHandle,
+                                      &poolParameters);
+
+    if (!Receiver->NetBufferListPool)
+        ndisStatus = NDIS_STATUS_RESOURCES;
+
+    return ndisStatus;
+}
+
+VOID 
+ReceiverCleanup (
+    IN  PRECEIVER       Receiver
+    )
+{
+    ULONG               Cpu;
+    PNET_BUFFER_LIST    NetBufferList;
+
+    ASSERT(Receiver != NULL);
+
+    for (Cpu = 0; Cpu < MAXIMUM_PROCESSORS; Cpu++) {
+        NetBufferList = Receiver->GetList[Cpu];
+        while (NetBufferList != NULL) {
+            PNET_BUFFER_LIST    Next;
+
+            Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+            NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+            NdisFreeNetBufferList(NetBufferList);
+
+            NetBufferList = Next;
+        }
+    }
+
+    NetBufferList = Receiver->PutList;
+    while (NetBufferList != NULL) {
+        PNET_BUFFER_LIST    Next;
+
+        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+        NdisFreeNetBufferList(NetBufferList);
+
+        NetBufferList = Next;
+    }
+
+    if (Receiver->NetBufferListPool) {
+        NdisFreeNetBufferListPool(Receiver->NetBufferListPool);
+        Receiver->NetBufferListPool = NULL;
+    }
+
+    return;
+}
+
+PNET_BUFFER_LIST
+ReceiverAllocateNetBufferList(
+    IN  PRECEIVER       Receiver,
+    IN  PMDL            Mdl,
+    IN  ULONG           Offset,
+    IN  ULONG           Length
+    )
+{
+    ULONG               Cpu;
+    PNET_BUFFER_LIST    NetBufferList;
+
+    Cpu = KeGetCurrentProcessorNumber();
+
+    NetBufferList = Receiver->GetList[Cpu];
+
+    if (NetBufferList == NULL)
+        Receiver->GetList[Cpu] = InterlockedExchangePointer(&Receiver->PutList, NULL);
+
+    NetBufferList = Receiver->GetList[Cpu];
+
+    if (NetBufferList != NULL) {
+        PNET_BUFFER NetBuffer;
+
+        Receiver->GetList[Cpu] = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+        NET_BUFFER_FIRST_MDL(NetBuffer) = Mdl;
+        NET_BUFFER_CURRENT_MDL(NetBuffer) = Mdl;
+        NET_BUFFER_DATA_OFFSET(NetBuffer) = Offset;
+        NET_BUFFER_DATA_LENGTH(NetBuffer) = Length;
+        NET_BUFFER_CURRENT_MDL_OFFSET(NetBuffer) = Offset;
+    } else {
+        NetBufferList = NdisAllocateNetBufferAndNetBufferList(Receiver->NetBufferListPool,
+                                                              0,
+                                                              0,
+                                                              Mdl,
+                                                              Offset,
+                                                              Length);
+        ASSERT(IMPLY(NetBufferList != NULL, NET_BUFFER_LIST_NEXT_NBL(NetBufferList) == NULL));
+    }
+
+    return NetBufferList;
+}        
+
+VOID
+ReceiverReleaseNetBufferList(
+    IN  PRECEIVER           Receiver,
+    IN  PNET_BUFFER_LIST    NetBufferList,
+    IN  BOOLEAN             Cache
+    )
+{
+    if (Cache) {
+        PNET_BUFFER_LIST    Old;
+        PNET_BUFFER_LIST    New;
+
+        ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
+
+        do {
+            Old = Receiver->PutList;
+
+            NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = Old;
+            New = NetBufferList;
+        } while (InterlockedCompareExchangePointer(&Receiver->PutList, New, Old) != Old);
+    } else {
+        NdisFreeNetBufferList(NetBufferList);
+    }
+}
+
+static FORCEINLINE ULONG
+__ReceiverReturnNetBufferLists(
+    IN  PRECEIVER           Receiver,
+    IN  PNET_BUFFER_LIST    NetBufferList,
+    IN  BOOLEAN             Cache
+    )
+{
+    PADAPTER                Adapter;
+    ULONG                   Count;
+
+    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+
+    Count = 0;
+    while (NetBufferList != NULL) {
+        PNET_BUFFER_LIST        Next;
+        PNET_BUFFER             NetBuffer;
+        PMDL                    Mdl;
+        PXENVIF_RECEIVER_PACKET Packet;
+
+        Next = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+        ASSERT3P(NET_BUFFER_NEXT_NB(NetBuffer), ==, NULL);
+
+        Mdl = NET_BUFFER_FIRST_MDL(NetBuffer);
+
+        ReceiverReleaseNetBufferList(Receiver, NetBufferList, Cache);
+
+        Packet = CONTAINING_RECORD(Mdl, XENVIF_RECEIVER_PACKET, Mdl);
+
+        VIF(ReturnPacket,
+            Adapter->VifInterface,
+            Packet);
+
+        Count++;
+        NetBufferList = Next;
+    }
+
+    return Count;
+}
+
+VOID
+ReceiverReturnNetBufferLists(
+    IN  PRECEIVER           Receiver,
+    IN  PNET_BUFFER_LIST    HeadNetBufferList,
+    IN  ULONG               Flags
+    )
+{
+    ULONG                   Count;
+
+    UNREFERENCED_PARAMETER(Flags);
+
+    Count = __ReceiverReturnNetBufferLists(Receiver, HeadNetBufferList, TRUE);
+    (VOID) __InterlockedSubtract(&Receiver->InNDIS, Count);
+}
+
+static PNET_BUFFER_LIST
+ReceiverReceivePacket(
+    IN  PRECEIVER                               Receiver,
+    IN  PMDL                                    Mdl,
+    IN  ULONG                                   Offset,
+    IN  ULONG                                   Length,
+    IN  XENVIF_CHECKSUM_FLAGS                   Flags,
+    IN  USHORT                                  TagControlInformation
+    )
+{
+    PADAPTER                                    Adapter;
+    PNET_BUFFER_LIST                            NetBufferList;
+    NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO   csumInfo;
+
+    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+
+    NetBufferList = ReceiverAllocateNetBufferList(Receiver,
+                                                  Mdl,
+                                                  Offset,
+                                                  Length);
+    if (NetBufferList == NULL)
+        goto fail1;
+
+    NetBufferList->SourceHandle = Adapter->NdisAdapterHandle;
+
+    csumInfo.Value = 0;
+
+    csumInfo.Receive.IpChecksumSucceeded = Flags.IpChecksumSucceeded;
+    csumInfo.Receive.IpChecksumFailed = Flags.IpChecksumFailed;
+
+    csumInfo.Receive.TcpChecksumSucceeded = Flags.TcpChecksumSucceeded;
+    csumInfo.Receive.TcpChecksumFailed = Flags.TcpChecksumFailed;
+
+    csumInfo.Receive.UdpChecksumSucceeded = Flags.UdpChecksumSucceeded;
+    csumInfo.Receive.UdpChecksumFailed = Flags.UdpChecksumFailed;
+
+    NET_BUFFER_LIST_INFO(NetBufferList, TcpIpChecksumNetBufferListInfo) = (PVOID)(ULONG_PTR)csumInfo.Value;
+
+    if (TagControlInformation != 0) {
+        NDIS_NET_BUFFER_LIST_8021Q_INFO Ieee8021QInfo;
+
+        UNPACK_TAG_CONTROL_INFORMATION(TagControlInformation,
+                                       Ieee8021QInfo.TagHeader.UserPriority,
+                                       Ieee8021QInfo.TagHeader.CanonicalFormatId,
+                                       Ieee8021QInfo.TagHeader.VlanId);
+
+        if (Ieee8021QInfo.TagHeader.VlanId != 0)
+            goto fail2;
+
+        NET_BUFFER_LIST_INFO(NetBufferList, Ieee8021QNetBufferListInfo) = Ieee8021QInfo.Value;
+    }
+
+    return NetBufferList;
+
+fail2:
+    ReceiverReleaseNetBufferList(Receiver, NetBufferList, TRUE);
+
+fail1:
+    return NULL;
+}
+
+static VOID
+ReceiverPushPackets(
+    IN  PRECEIVER           Receiver,
+    IN  PNET_BUFFER_LIST    NetBufferList,
+    IN  ULONG               Count,
+    IN  BOOLEAN             LowResources
+    )
+{
+    PADAPTER                Adapter;
+    ULONG                   Flags;
+    LONG                    InNDIS;
+
+    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+
+    InNDIS = Receiver->InNDIS;
+
+    Flags = NDIS_RECEIVE_FLAGS_DISPATCH_LEVEL;
+    if (LowResources) {
+        Flags |= NDIS_RECEIVE_FLAGS_RESOURCES;
+    } else {
+        InNDIS = __InterlockedAdd(&Receiver->InNDIS, Count);
+    }
+
+    for (;;) {
+        LONG    InNDISMax;
+
+        InNDISMax = Receiver->InNDISMax;
+        KeMemoryBarrier();
+
+        if (InNDIS <= InNDISMax)
+            break;
+
+        if (InterlockedCompareExchange(&Receiver->InNDISMax, InNDIS, InNDISMax) == InNDISMax)
+            break;
+    }
+
+    NdisMIndicateReceiveNetBufferLists(Adapter->NdisAdapterHandle,
+                                       NetBufferList,
+                                       NDIS_DEFAULT_PORT_NUMBER,
+                                       Count,
+                                       Flags);
+
+    if (LowResources)
+        (VOID) __ReceiverReturnNetBufferLists(Receiver, NetBufferList, FALSE);
+}
+
+#define IN_NDIS_MAX 1024
+
+VOID
+ReceiverReceivePackets(
+    IN  PRECEIVER       Receiver,
+    IN  PLIST_ENTRY     List
+    )
+{
+    PADAPTER            Adapter;
+    PNET_BUFFER_LIST    HeadNetBufferList;
+    PNET_BUFFER_LIST    *TailNetBufferList;
+    ULONG               Count;
+    BOOLEAN             LowResources;
+
+    Adapter = CONTAINING_RECORD(Receiver, ADAPTER, Receiver);
+    LowResources = FALSE;
+
+again:
+    HeadNetBufferList = NULL;
+    TailNetBufferList = &HeadNetBufferList;
+    Count = 0;
+
+    while (!IsListEmpty(List)) {
+        PLIST_ENTRY                     ListEntry;
+        PXENVIF_RECEIVER_PACKET         Packet;
+        PMDL                            Mdl;
+        ULONG                           Offset;
+        ULONG                           Length;
+        XENVIF_CHECKSUM_FLAGS           Flags;
+        USHORT                          TagControlInformation;
+        PNET_BUFFER_LIST                NetBufferList;
+
+        if (!LowResources &&
+            Receiver->InNDIS + Count > IN_NDIS_MAX)
+            break;
+
+        ListEntry = RemoveHeadList(List);
+        ASSERT(ListEntry != List);
+
+        RtlZeroMemory(ListEntry, sizeof (LIST_ENTRY));
+
+        Packet = CONTAINING_RECORD(ListEntry, XENVIF_RECEIVER_PACKET, ListEntry);
+        Mdl = &Packet->Mdl;
+        Offset = Packet->Offset;
+        Length = Packet->Length;
+        Flags = Packet->Flags;
+        TagControlInformation = Packet->TagControlInformation;
+
+        NetBufferList = ReceiverReceivePacket(Receiver, Mdl, Offset, Length, Flags, TagControlInformation);
+
+        if (NetBufferList != NULL) {
+            *TailNetBufferList = NetBufferList;
+            TailNetBufferList = &NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+            Count++;
+        } else {
+            VIF(ReturnPacket,
+                Adapter->VifInterface,
+                Packet);
+        }
+    }
+
+    if (Count != 0) {
+        ASSERT(HeadNetBufferList != NULL);
+
+        ReceiverPushPackets(Receiver, HeadNetBufferList, Count, LowResources);
+    }
+
+    if (!IsListEmpty(List)) {
+        ASSERT(!LowResources);
+        LowResources = TRUE;
+        goto again;
+    }
+}
diff --git a/src/xennet/receiver.h b/src/xennet/receiver.h
new file mode 100644 (file)
index 0000000..fe32057
--- /dev/null
@@ -0,0 +1,77 @@
+/* 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.
+ */
+
+#pragma once
+
+typedef struct _RECEIVER {
+    NDIS_HANDLE             NetBufferListPool;
+    PNET_BUFFER_LIST        PutList;
+    PNET_BUFFER_LIST        GetList[MAXIMUM_PROCESSORS];
+    LONG                    InNDIS;
+    LONG                    InNDISMax;
+    XENVIF_OFFLOAD_OPTIONS  OffloadOptions;
+} RECEIVER, *PRECEIVER;
+
+VOID
+ReceiverDebugDump (
+    IN PRECEIVER Receiver
+    );
+
+VOID 
+ReceiverCleanup (
+    IN  PRECEIVER Receiver
+    );
+
+VOID
+ReceiverHandleNotification (
+    IN  PRECEIVER Receiver
+    );
+
+NDIS_STATUS
+ReceiverInitialize (
+    IN  PRECEIVER   Receiver
+    );
+
+VOID 
+ReceiverReturnNetBufferLists (
+    IN  PRECEIVER           Receiver,
+    IN  PNET_BUFFER_LIST    NetBufferList,
+    IN  ULONG               ReturnFlags
+    );
+
+VOID
+ReceiverWaitForPacketReturn(
+    IN  PRECEIVER   Receiver,
+    IN  BOOLEAN     Locked
+    );
+
+void ReceiverPause(PRECEIVER receiver);
+void ReceiverUnpause(PRECEIVER receiver);
diff --git a/src/xennet/std.h b/src/xennet/std.h
new file mode 100644 (file)
index 0000000..c72325a
--- /dev/null
@@ -0,0 +1,45 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#pragma once
+
+#pragma warning(disable:4214)   // bit field types other than int
+
+#pragma warning(disable:4201)   // nameless struct/union
+#pragma warning(disable:4115)   // named type definition in parentheses
+#pragma warning(disable:4127)   // conditional expression is constant
+#pragma warning(disable:4054)   // cast of function pointer to PVOID
+#pragma warning(disable:4206)   // translation unit is empty
+
+#include <ndis.h>
+#include <ntstrsafe.h>
+
+extern PULONG InitSafeBootMode;
diff --git a/src/xennet/transmitter.c b/src/xennet/transmitter.c
new file mode 100644 (file)
index 0000000..d1bfff3
--- /dev/null
@@ -0,0 +1,313 @@
+/* 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 "common.h"
+
+#pragma warning(disable:4711)
+
+NDIS_STATUS
+TransmitterInitialize(
+    IN  PTRANSMITTER    Transmitter,
+    IN  PADAPTER        Adapter
+    )
+{
+    Transmitter->Adapter = Adapter;
+
+    return NDIS_STATUS_SUCCESS;
+}
+
+VOID
+TransmitterEnable(
+    IN  PTRANSMITTER    Transmitter
+    )
+{
+    XENVIF_TRANSMITTER_PACKET_METADATA  Metadata;
+
+    Metadata.OffsetOffset = (LONG_PTR)&NET_BUFFER_CURRENT_MDL_OFFSET((PNET_BUFFER)NULL) -
+                            (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL);
+    Metadata.LengthOffset = (LONG_PTR)&NET_BUFFER_DATA_LENGTH((PNET_BUFFER)NULL) -
+                            (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL);
+    Metadata.MdlOffset = (LONG_PTR)&NET_BUFFER_CURRENT_MDL((PNET_BUFFER)NULL) -
+                         (LONG_PTR)&NET_BUFFER_MINIPORT_RESERVED((PNET_BUFFER)NULL);
+
+    VIF(UpdatePacketMetadata,
+        Transmitter->Adapter->VifInterface,
+        &Metadata);
+}
+
+VOID 
+TransmitterDelete (
+    IN OUT PTRANSMITTER *Transmitter
+    )
+{
+    ASSERT(Transmitter != NULL);
+
+    if (*Transmitter) {
+        ExFreePool(*Transmitter);
+        *Transmitter = NULL;
+    }
+}
+
+typedef struct _NET_BUFFER_LIST_RESERVED {
+    LONG    Reference;
+} NET_BUFFER_LIST_RESERVED, *PNET_BUFFER_LIST_RESERVED;
+
+C_ASSERT(sizeof (NET_BUFFER_LIST_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER_LIST, MiniportReserved));
+
+typedef struct _NET_BUFFER_RESERVED {
+    XENVIF_TRANSMITTER_PACKET   Packet;
+    PNET_BUFFER_LIST            NetBufferList;
+} NET_BUFFER_RESERVED, *PNET_BUFFER_RESERVED;
+
+C_ASSERT(sizeof (NET_BUFFER_RESERVED) <= RTL_FIELD_SIZE(NET_BUFFER, MiniportReserved));
+
+static VOID
+TransmitterAbortNetBufferList(
+    IN  PTRANSMITTER        Transmitter,
+    IN  PNET_BUFFER_LIST    NetBufferList
+    )
+{
+    ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
+
+    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_NOT_ACCEPTED;
+
+    NdisMSendNetBufferListsComplete(Transmitter->Adapter->NdisAdapterHandle,
+                                    NetBufferList,
+                                    NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
+}
+
+VOID
+TransmitterAbortPackets(
+    IN  PTRANSMITTER                Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    )
+{
+    while (Packet != NULL) {
+        PXENVIF_TRANSMITTER_PACKET  Next;
+        PNET_BUFFER_RESERVED        Reserved;
+        PNET_BUFFER_LIST            NetBufferList;
+        PNET_BUFFER_LIST_RESERVED   ListReserved;
+
+        Next = Packet->Next;
+        Packet->Next = NULL;
+
+        Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED, Packet);
+
+        NetBufferList = Reserved->NetBufferList;
+        ASSERT(NetBufferList != NULL);
+
+        ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+
+        ASSERT(ListReserved->Reference != 0);
+        if (InterlockedDecrement(&ListReserved->Reference) == 0)
+            TransmitterAbortNetBufferList(Transmitter, NetBufferList);
+
+        Packet = Next;
+    }
+}
+
+VOID
+TransmitterSendNetBufferLists(
+    IN  PTRANSMITTER            Transmitter,
+    IN  PNET_BUFFER_LIST        NetBufferList,
+    IN  NDIS_PORT_NUMBER        PortNumber,
+    IN  ULONG                   SendFlags
+    )
+{
+    PXENVIF_TRANSMITTER_PACKET  HeadPacket;
+    PXENVIF_TRANSMITTER_PACKET  *TailPacket;
+    KIRQL                       Irql;
+
+    UNREFERENCED_PARAMETER(PortNumber);
+
+    HeadPacket = NULL;
+    TailPacket = &HeadPacket;
+
+    if (!NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)) {
+        ASSERT3U(NDIS_CURRENT_IRQL(), <=, DISPATCH_LEVEL);
+        NDIS_RAISE_IRQL_TO_DISPATCH(&Irql);
+    } else {
+        Irql = DISPATCH_LEVEL;
+    }
+
+    while (NetBufferList != NULL) {
+        PNET_BUFFER_LIST                                    ListNext;
+        PNET_BUFFER_LIST_RESERVED                           ListReserved;
+        PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
+        PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO          ChecksumInfo;
+        PNDIS_NET_BUFFER_LIST_8021Q_INFO                    Ieee8021QInfo;
+        PNET_BUFFER                                         NetBuffer;
+
+        ListNext = NET_BUFFER_LIST_NEXT_NBL(NetBufferList);
+        NET_BUFFER_LIST_NEXT_NBL(NetBufferList) = NULL;
+
+        ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+        RtlZeroMemory(ListReserved, sizeof (NET_BUFFER_LIST_RESERVED));
+
+        LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
+                                                                                                 TcpLargeSendNetBufferListInfo);
+        ChecksumInfo = (PNDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
+                                                                                         TcpIpChecksumNetBufferListInfo);
+        Ieee8021QInfo = (PNDIS_NET_BUFFER_LIST_8021Q_INFO)&NET_BUFFER_LIST_INFO(NetBufferList, 
+                                                                                Ieee8021QNetBufferListInfo);
+
+        NetBuffer = NET_BUFFER_LIST_FIRST_NB(NetBufferList);
+        while (NetBuffer != NULL) {
+            PNET_BUFFER_RESERVED        Reserved;
+            PXENVIF_TRANSMITTER_PACKET  Packet;
+
+            Reserved = (PNET_BUFFER_RESERVED)NET_BUFFER_MINIPORT_RESERVED(NetBuffer);
+            RtlZeroMemory(Reserved, sizeof (NET_BUFFER_RESERVED));
+
+            Reserved->NetBufferList = NetBufferList;
+            ListReserved->Reference++;
+
+            Packet = &Reserved->Packet;
+
+            if (ChecksumInfo->Transmit.IsIPv4) {
+                if (ChecksumInfo->Transmit.IpHeaderChecksum)
+                    Packet->Send.OffloadOptions.OffloadIpVersion4HeaderChecksum = 1;
+
+                if (ChecksumInfo->Transmit.TcpChecksum)
+                    Packet->Send.OffloadOptions.OffloadIpVersion4TcpChecksum = 1;
+
+                if (ChecksumInfo->Transmit.UdpChecksum)
+                    Packet->Send.OffloadOptions.OffloadIpVersion4UdpChecksum = 1;
+            }
+
+            if (ChecksumInfo->Transmit.IsIPv6) {
+                if (ChecksumInfo->Transmit.TcpChecksum)
+                    Packet->Send.OffloadOptions.OffloadIpVersion6TcpChecksum = 1;
+
+                if (ChecksumInfo->Transmit.UdpChecksum)
+                    Packet->Send.OffloadOptions.OffloadIpVersion6UdpChecksum = 1;
+            }
+
+            if (Ieee8021QInfo->TagHeader.UserPriority != 0) {
+                Packet->Send.OffloadOptions.OffloadTagManipulation = 1;
+
+                ASSERT3U(Ieee8021QInfo->TagHeader.CanonicalFormatId, ==, 0);
+                ASSERT3U(Ieee8021QInfo->TagHeader.VlanId, ==, 0);
+
+                PACK_TAG_CONTROL_INFORMATION(Packet->Send.TagControlInformation,
+                                             Ieee8021QInfo->TagHeader.UserPriority,
+                                             Ieee8021QInfo->TagHeader.CanonicalFormatId,
+                                             Ieee8021QInfo->TagHeader.VlanId);
+            }
+
+            if (LargeSendInfo->LsoV2Transmit.MSS != 0) {
+                if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv4)
+                    Packet->Send.OffloadOptions.OffloadIpVersion4LargePacket = 1;
+
+                if (LargeSendInfo->LsoV2Transmit.IPVersion == NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6)
+                    Packet->Send.OffloadOptions.OffloadIpVersion6LargePacket = 1;
+
+                ASSERT3U(LargeSendInfo->LsoV2Transmit.MSS >> 16, ==, 0);
+                Packet->Send.MaximumSegmentSize = (USHORT)LargeSendInfo->LsoV2Transmit.MSS;
+            }
+
+            Packet->Send.OffloadOptions.Value &= Transmitter->OffloadOptions.Value;
+
+            ASSERT3P(Packet->Next, ==, NULL);
+            *TailPacket = Packet;
+            TailPacket = &Packet->Next;
+
+            NetBuffer = NET_BUFFER_NEXT_NB(NetBuffer);
+        }
+
+        NetBufferList = ListNext;
+    }
+
+    if (HeadPacket != NULL) {
+        NTSTATUS    status; 
+
+        status = VIF(QueuePackets,
+                     Transmitter->Adapter->VifInterface,
+                     HeadPacket);
+        if (!NT_SUCCESS(status))
+            TransmitterAbortPackets(Transmitter, HeadPacket);
+    }
+
+    NDIS_LOWER_IRQL(Irql, DISPATCH_LEVEL);
+}
+
+static VOID
+TransmitterCompleteNetBufferList(
+    IN  PTRANSMITTER                                    Transmitter,
+    IN  PNET_BUFFER_LIST                                NetBufferList
+    )
+{
+    PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO   LargeSendInfo;
+
+    ASSERT3P(NET_BUFFER_LIST_NEXT_NBL(NetBufferList), ==, NULL);
+
+    LargeSendInfo = (PNDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO)&NET_BUFFER_LIST_INFO(NetBufferList,
+                                                                                             TcpLargeSendNetBufferListInfo);
+
+    if (LargeSendInfo->LsoV2Transmit.MSS != 0)
+        LargeSendInfo->LsoV2TransmitComplete.Reserved = 0;
+
+    NET_BUFFER_LIST_STATUS(NetBufferList) = NDIS_STATUS_SUCCESS;
+
+    NdisMSendNetBufferListsComplete(Transmitter->Adapter->NdisAdapterHandle,
+                                    NetBufferList,
+                                    NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL);
+}
+
+VOID
+TransmitterCompletePackets(
+    IN  PTRANSMITTER                Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    )
+{
+    while (Packet != NULL) {
+        PXENVIF_TRANSMITTER_PACKET  Next;
+        PNET_BUFFER_RESERVED        Reserved;
+        PNET_BUFFER_LIST            NetBufferList;
+        PNET_BUFFER_LIST_RESERVED   ListReserved;
+
+        Next = Packet->Next;
+        Packet->Next = NULL;
+
+        Reserved = CONTAINING_RECORD(Packet, NET_BUFFER_RESERVED, Packet);
+
+        NetBufferList = Reserved->NetBufferList;
+        ASSERT(NetBufferList != NULL);
+
+        ListReserved = (PNET_BUFFER_LIST_RESERVED)NET_BUFFER_LIST_MINIPORT_RESERVED(NetBufferList);
+
+        ASSERT(ListReserved->Reference != 0);
+        if (InterlockedDecrement(&ListReserved->Reference) == 0)
+            TransmitterCompleteNetBufferList(Transmitter, NetBufferList);
+
+        Packet = Next;
+    }
+}
diff --git a/src/xennet/transmitter.h b/src/xennet/transmitter.h
new file mode 100644 (file)
index 0000000..93d734b
--- /dev/null
@@ -0,0 +1,75 @@
+/* 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.
+ */
+
+#pragma once
+
+typedef struct _TRANSMITTER {
+    PADAPTER                Adapter;
+    XENVIF_OFFLOAD_OPTIONS  OffloadOptions;
+} TRANSMITTER, *PTRANSMITTER;
+
+VOID 
+TransmitterCleanup (
+    IN OUT PTRANSMITTER* Transmitter
+    );
+
+NDIS_STATUS
+TransmitterInitialize (
+    IN  PTRANSMITTER    Transmitter,
+    IN  PADAPTER        Adapter
+    );
+
+VOID
+TransmitterEnable (
+    IN  PTRANSMITTER    Transmitter
+    );
+
+VOID 
+TransmitterDelete (
+    IN OUT PTRANSMITTER* Transmitter
+    );
+
+VOID
+TransmitterSendNetBufferLists (
+    IN  PTRANSMITTER        Transmitter,
+    IN  PNET_BUFFER_LIST    NetBufferList,
+    IN  NDIS_PORT_NUMBER    PortNumber,
+    IN  ULONG               SendFlags
+    );
+
+VOID
+TransmitterCompletePackets(
+    IN  PTRANSMITTER                Transmitter,
+    IN  PXENVIF_TRANSMITTER_PACKET  Packet
+    );
+
+void TransmitterPause(PTRANSMITTER Transmitter);
+void TransmitterUnpause(PTRANSMITTER Transmitter);
diff --git a/src/xennet/xennet.rc b/src/xennet/xennet.rc
new file mode 100644 (file)
index 0000000..784ea12
--- /dev/null
@@ -0,0 +1,56 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, 
+ * with or without modification, are permitted provided 
+ * that the following conditions are met:
+ * 
+ * *   Redistributions of source code must retain the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the 
+ *     following disclaimer in the documentation and/or other 
+ *     materials provided with the distribution.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE.
+ */
+
+#include <windows.h>
+#include <ntverp.h>
+
+
+#undef VER_COMPANYNAME_STR
+#undef VER_PRODUCTNAME_STR
+#undef VER_PRODUCTVERSION
+#undef VER_PRODUCTVERSION_STR
+
+#define        VER_COMPANYNAME_STR         "Citrix Systems Inc."
+#define VER_LEGALCOPYRIGHT_STR      "Copyright " YEAR_STR VER_COMPANYNAME_STR
+
+#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        "XENNET.SYS"
+#define VER_FILEDESCRIPTION_STR     "Citrix PV Network Driver"
+
+#define VER_FILETYPE                VFT_DRV
+#define VER_FILESUBTYPE             VFT2_DRV_SYSTEM
+
+#include <common.ver>