[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH] Replace copying network settings with identity stealing



It is becoming increasingly hard to find all the places in the registry
that Windows uses to stash network settings and copy them from the
emulated NIC to the new PV device when it is first installed.

So, rather than fighting a losing battle, steal the identity of emulated
devices instead, The identity information is essentially contained in two
values stored in the 'software'registry key of a NIC (under Control/Class/
<NET GUID>): NetCfgInstanceId and the NET_LUID, made up of *IfType and
NetLuidIndex. By copying these values and the contents of the Linkage subkey
we can effectively impersonate the emulated NIC once it is unplugged after
reboot.

This patch amends the settings code accordingly and also does some tidying
in pdo.c and registry.c.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/xenvif/driver.c   |  11 +-
 src/xenvif/driver.h   |   5 -
 src/xenvif/pdo.c      | 207 ++++++++-------
 src/xenvif/registry.c | 101 ++++----
 src/xenvif/settings.c | 697 +++++++++++++++++++++++---------------------------
 src/xenvif/settings.h |  14 +-
 6 files changed, 491 insertions(+), 544 deletions(-)

diff --git a/src/xenvif/driver.c b/src/xenvif/driver.c
index 4b1e538..8e61420 100644
--- a/src/xenvif/driver.c
+++ b/src/xenvif/driver.c
@@ -142,20 +142,15 @@ DriverRequestReboot(
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
+    if (Driver.NeedReboot)
+        return;
+
     (VOID) RegistryUpdateDwordValue(__DriverGetStatusKey(),
                                     "NeedReboot",
                                     1);
     Driver.NeedReboot = TRUE;
 }
 
-BOOLEAN
-DriverIsRebootRequested(
-    VOID
-    )
-{
-    return Driver.NeedReboot;
-}
-
 DRIVER_UNLOAD       DriverUnload;
 
 VOID
diff --git a/src/xenvif/driver.h b/src/xenvif/driver.h
index ec23933..c045583 100644
--- a/src/xenvif/driver.h
+++ b/src/xenvif/driver.h
@@ -52,11 +52,6 @@ DriverRequestReboot(
     VOID
     );
 
-BOOLEAN
-DriverIsRebootRequested(
-    VOID
-    );
-
 typedef struct _XENVIF_PDO  XENVIF_PDO, *PXENVIF_PDO;
 typedef struct _XENVIF_FDO  XENVIF_FDO, *PXENVIF_FDO;
 
diff --git a/src/xenvif/pdo.c b/src/xenvif/pdo.c
index 418c161..28f9eb0 100644
--- a/src/xenvif/pdo.c
+++ b/src/xenvif/pdo.c
@@ -72,6 +72,9 @@ struct _XENVIF_PDO {
     PXENVIF_THREAD              DevicePowerThread;
     PIRP                        DevicePowerIrp;
 
+    HANDLE                      SoftwareKey;
+    HANDLE                      HardwareKey;
+
     PXENVIF_FDO                 Fdo;
     BOOLEAN                     Missing;
     const CHAR                  *Reason;
@@ -93,6 +96,8 @@ struct _XENVIF_PDO {
 
     PXENVIF_VIF_CONTEXT         VifContext;
     XENVIF_VIF_INTERFACE        VifInterface;
+
+    BOOLEAN                     HasAlias;
 };
 
 static FORCEINLINE PVOID
@@ -757,11 +762,67 @@ PdoGetPermanentAddress(
     return __PdoGetPermanentAddress(Pdo);
 }
 
+static FORCEINLINE NTSTATUS
+__PdoSetSoftwareKey(
+    IN  PXENVIF_PDO Pdo
+    )
+{
+    NTSTATUS        status;
+
+    status = RegistryOpenSoftwareKey(__PdoGetDeviceObject(Pdo),
+                                     KEY_ALL_ACCESS,
+                                     &Pdo->SoftwareKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1\n");
+
+    return status;
+}
+
+static FORCEINLINE HANDLE
+__PdoGetSoftwareKey(
+    IN  PXENVIF_PDO Pdo
+    )
+{
+    return Pdo->SoftwareKey;
+}
+
+static FORCEINLINE NTSTATUS
+__PdoSetHardwareKey(
+    IN  PXENVIF_PDO Pdo
+    )
+{
+    NTSTATUS        status;
+
+    status = RegistryOpenHardwareKey(__PdoGetDeviceObject(Pdo),
+                                     KEY_ALL_ACCESS,
+                                     &Pdo->HardwareKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1\n");
+
+    return status;
+}
+
+static FORCEINLINE HANDLE
+__PdoGetHardwareKey(
+    IN  PXENVIF_PDO Pdo
+    )
+{
+    return Pdo->HardwareKey;
+}
+
 static NTSTATUS
 PdoSetFriendlyName(
-    IN  PXENVIF_PDO Pdo,
-    IN  HANDLE      SoftwareKey,
-    IN  HANDLE      HardwareKey
+    IN  PXENVIF_PDO Pdo
     )
 {
     PANSI_STRING    DriverDesc;
@@ -769,7 +830,7 @@ PdoSetFriendlyName(
     ANSI_STRING     FriendlyName[2];
     NTSTATUS        status;
 
-    status = RegistryQuerySzValue(SoftwareKey,
+    status = RegistryQuerySzValue(__PdoGetSoftwareKey(Pdo),
                                   "DriverDesc",
                                   NULL,
                                   &DriverDesc);
@@ -788,7 +849,7 @@ PdoSetFriendlyName(
     RtlZeroMemory(FriendlyName, sizeof (ANSI_STRING) * 2);
     RtlInitAnsiString(&FriendlyName[0], Buffer);
 
-    status = RegistryUpdateSzValue(HardwareKey,
+    status = RegistryUpdateSzValue(__PdoGetHardwareKey(Pdo),
                                    "FriendlyName",
                                    REG_SZ,
                                    FriendlyName);
@@ -815,8 +876,7 @@ fail1:
 
 static FORCEINLINE NTSTATUS
 __PdoSetCurrentAddress(
-    IN  PXENVIF_PDO Pdo,
-    IN  HANDLE      Key
+    IN  PXENVIF_PDO Pdo
     )
 {
     PANSI_STRING    Ansi;
@@ -824,7 +884,7 @@ __PdoSetCurrentAddress(
 
     RtlFillMemory(Pdo->CurrentAddress.Byte, ETHERNET_ADDRESS_LENGTH, 0xFF);
 
-    status = RegistryQuerySzValue(Key,
+    status = RegistryQuerySzValue(__PdoGetSoftwareKey(Pdo),
                                   "NetworkAddress",
                                   NULL,
                                   &Ansi);
@@ -1106,56 +1166,6 @@ PdoS3ToS4(
     Trace("(%s) <====\n", __PdoGetName(Pdo));
 }
 
-static NTSTATUS
-PdoGetInterfaceGuid(
-    IN  PXENVIF_PDO Pdo,
-    IN  HANDLE      Key,
-    OUT LPGUID      Guid
-    )
-{
-    PANSI_STRING    Ansi;
-    UNICODE_STRING  Unicode;
-    NTSTATUS        status;
-
-    UNREFERENCED_PARAMETER(Pdo);
-
-    status = RegistryQuerySzValue(Key,
-                                  "NetCfgInstanceId",
-                                  NULL,
-                                  &Ansi);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi[0], TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = RtlGUIDFromString(&Unicode, Guid);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    RtlFreeUnicodeString(&Unicode);
-
-    RegistryFreeSzValue(Ansi);
-
-    return STATUS_SUCCESS;
-
-fail3:
-    Error("fail3\n");
-
-    RtlFreeUnicodeString(&Unicode);
-
-fail2:
-    Error("fail2\n");
-
-    RegistryFreeSzValue(Ansi);
-
-fail1:
-    Error("fail1 (%08x)\n", status);
-
-    return status;
-}
-
 static VOID
 PdoUnplugRequest(
     IN  PXENVIF_PDO Pdo,
@@ -1188,13 +1198,10 @@ PdoStartDevice(
     ULONG               Index;
     PMIB_IF_ROW2        Row;
     PIO_STACK_LOCATION  StackLocation;
-    HANDLE              SoftwareKey;
-    HANDLE              HardwareKey;
-    GUID                Guid;
     NTSTATUS            status;
 
     status = STATUS_UNSUCCESSFUL;
-    if (DriverIsRebootRequested())
+    if (Pdo->HasAlias)
         goto fail1;
 
     PdoUnplugRequest(Pdo, TRUE);
@@ -1202,23 +1209,17 @@ PdoStartDevice(
     if (DriverSafeMode())
         goto fail2;
 
-    status = RegistryOpenSoftwareKey(__PdoGetDeviceObject(Pdo),
-                                     KEY_ALL_ACCESS,
-                                     &SoftwareKey);
+    status = __PdoSetSoftwareKey(Pdo);
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    status = RegistryOpenHardwareKey(__PdoGetDeviceObject(Pdo),
-                                     KEY_ALL_ACCESS,
-                                     &HardwareKey);
+    status = __PdoSetHardwareKey(Pdo);
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    (VOID) PdoSetFriendlyName(Pdo,
-                              SoftwareKey,
-                              HardwareKey);
+    (VOID) PdoSetFriendlyName(Pdo);
 
-    status = __PdoSetCurrentAddress(Pdo, SoftwareKey);
+    status = __PdoSetCurrentAddress(Pdo);
     if (!NT_SUCCESS(status))
         goto fail5;
 
@@ -1246,8 +1247,12 @@ PdoStartDevice(
     for (Index = 0; Index < Table->NumEntries; Index++) {
         Row = &Table->Table[Index];
 
-        if (!(Row->InterfaceAndOperStatusFlags.HardwareInterface) ||
-            !(Row->InterfaceAndOperStatusFlags.ConnectorPresent))
+        Trace("%s: checking %ws (%ws)\n",
+              __PdoGetName(Pdo),
+              Row->Alias,
+              Row->Description);
+
+        if (!Row->InterfaceAndOperStatusFlags.ConnectorPresent)
             continue;
 
         if (Row->OperStatus != IfOperStatusUp)
@@ -1261,31 +1266,12 @@ PdoStartDevice(
                    sizeof (ETHERNET_ADDRESS)) != 0)
             continue;
 
+        Pdo->HasAlias = TRUE;
+
         status = STATUS_UNSUCCESSFUL;
         goto fail9;
     }
 
-    //
-    // If there is a stack bound then restore any settings that
-    // may have been saved from an aliasing emulated device.
-    //
-    status = PdoGetInterfaceGuid(Pdo, SoftwareKey, &Guid);
-    if (NT_SUCCESS(status)) {
-        for (Index = 0; Index < Table->NumEntries; Index++) {
-            Row = &Table->Table[Index];
-
-            if (!IsEqualGUID(&Row->InterfaceGuid, &Guid))
-                continue;
-
-            (VOID) SettingsRestore(SoftwareKey,
-                                   Row->Alias,
-                                   Row->Description,
-                                   &Row->InterfaceGuid,
-                                   &Row->InterfaceLuid);
-            break;
-        }
-    }
-
     StackLocation = IoGetCurrentIrpStackLocation(Irp);
 
     status = PdoD3ToD0(Pdo);
@@ -1299,8 +1285,6 @@ PdoStartDevice(
 
     __FreeMibTable(Table);
 
-    RegistryCloseKey(SoftwareKey);
-
     return STATUS_SUCCESS;
 
 fail10:
@@ -1313,11 +1297,10 @@ fail10:
 fail9:
     Error("fail9\n");
 
-    (VOID) SettingsSave(SoftwareKey,
-                        Row->Alias,
-                        Row->Description,
-                        &Row->InterfaceGuid,
-                        &Row->InterfaceLuid);
+    (VOID) SettingsStealIdentity(__PdoGetSoftwareKey(Pdo),
+                                 Row->Alias,
+                                 Row->Description,
+                                 &Row->InterfaceGuid);
 
     DriverRequestReboot();
     __FreeMibTable(Table);
@@ -1336,12 +1319,14 @@ fail6:
 fail5:
     Error("fail5\n");
 
-    RegistryCloseKey(HardwareKey);
+    RegistryCloseKey(__PdoGetHardwareKey(Pdo));
+    Pdo->HardwareKey = NULL;
 
 fail4:
     Error("fail4\n");
 
-    RegistryCloseKey(SoftwareKey);
+    RegistryCloseKey(__PdoGetSoftwareKey(Pdo));
+    Pdo->SoftwareKey = NULL;
 
 fail3:
     Error("fail3\n");
@@ -1410,6 +1395,12 @@ PdoStopDevice(
 done:
     RtlZeroMemory(&Pdo->CurrentAddress, sizeof (ETHERNET_ADDRESS));
 
+    RegistryCloseKey(__PdoGetHardwareKey(Pdo));
+    Pdo->HardwareKey = NULL;
+
+    RegistryCloseKey(__PdoGetSoftwareKey(Pdo));
+    Pdo->SoftwareKey = NULL;
+
     __PdoSetDevicePnpState(Pdo, Stopped);
     status = STATUS_SUCCESS;
 
@@ -1495,6 +1486,12 @@ PdoRemoveDevice(
 done:
     RtlZeroMemory(&Pdo->CurrentAddress, sizeof (ETHERNET_ADDRESS));
 
+    RegistryCloseKey(__PdoGetHardwareKey(Pdo));
+    Pdo->HardwareKey = NULL;
+
+    RegistryCloseKey(__PdoGetSoftwareKey(Pdo));
+    Pdo->SoftwareKey = NULL;
+
     NeedInvalidate = FALSE;
 
     FdoAcquireMutex(Fdo);
@@ -2782,6 +2779,8 @@ PdoDestroy(
 
     ASSERT3U(__PdoGetDevicePnpState(Pdo), ==, Deleted);
 
+    Pdo->HasAlias = FALSE;
+
     ASSERT(__PdoIsMissing(Pdo));
     Pdo->Missing = FALSE;
 
diff --git a/src/xenvif/registry.c b/src/xenvif/registry.c
index d994e13..0d3b3c5 100644
--- a/src/xenvif/registry.c
+++ b/src/xenvif/registry.c
@@ -346,49 +346,6 @@ fail1:
 }
 
 NTSTATUS
-RegistryDeleteSubKey(
-    IN  PHANDLE         Key,
-    IN  PCHAR           Name
-    )
-{
-    ANSI_STRING         Ansi;
-    UNICODE_STRING      Unicode;
-    HANDLE              SubKey;
-    NTSTATUS            status;
-
-    RtlInitAnsiString(&Ansi, Name);
-
-    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
-    if (!NT_SUCCESS(status))
-        goto fail1;
-
-    status = RegistryOpenKey(Key, &Unicode, KEY_ALL_ACCESS, &SubKey);
-    if (!NT_SUCCESS(status))
-        goto fail2;
-
-    status = ZwDeleteKey(SubKey);
-    if (!NT_SUCCESS(status))
-        goto fail3;
-
-    ZwClose(SubKey);
-
-    (VOID) ZwFlushKey(Key);
-
-    RtlFreeUnicodeString(&Unicode);
-
-    return STATUS_SUCCESS;
-
-fail3:
-    ZwClose(SubKey);
-
-fail2:
-    RtlFreeUnicodeString(&Unicode);
-
-fail1:
-    return status;
-}
-
-NTSTATUS
 RegistryEnumerateSubKeys(
     IN  HANDLE              Key,
     IN  NTSTATUS            (*Callback)(PVOID, HANDLE, PANSI_STRING),
@@ -492,6 +449,64 @@ fail1:
     return status;
 }
 
+static NTSTATUS
+RegistryDeleteSubKeyTree(
+    IN  PVOID           Context,
+    IN  PHANDLE         Key,
+    IN  PANSI_STRING    Name
+    )
+{
+    HANDLE              SubKey;
+    NTSTATUS            status;
+
+    UNREFERENCED_PARAMETER(Context);
+
+    status = RegistryOpenSubKey(Key,
+                                Name->Buffer,
+                                KEY_ALL_ACCESS,
+                                &SubKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    (VOID) RegistryEnumerateSubKeys(SubKey,
+                                    RegistryDeleteSubKeyTree,
+                                    NULL);
+
+    status = ZwDeleteKey(SubKey);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    ZwClose(SubKey);
+
+    return STATUS_SUCCESS;
+
+fail2:
+    ZwClose(SubKey);
+
+fail1:
+    return status;
+}
+
+NTSTATUS
+RegistryDeleteSubKey(
+    IN  PHANDLE Key,
+    IN  PCHAR   Name
+    )
+{
+    ANSI_STRING Ansi;
+    NTSTATUS    status;
+
+    RtlInitAnsiString(&Ansi, Name);
+
+    status = RegistryDeleteSubKeyTree(NULL,
+                                      Key,
+                                      &Ansi);
+
+    (VOID) ZwFlushKey(Key);
+
+    return status;
+}
+
 NTSTATUS
 RegistryEnumerateValues(
     IN  HANDLE                      Key,
diff --git a/src/xenvif/settings.c b/src/xenvif/settings.c
index 5cb9984..65c84f8 100644
--- a/src/xenvif/settings.c
+++ b/src/xenvif/settings.c
@@ -29,8 +29,11 @@
  * SUCH DAMAGE.
  */
 
+#define INITGUID 1
+
 #include <ntddk.h>
 #include <ntstrsafe.h>
+#include <devguid.h>
 
 #include "registry.h"
 #include "driver.h"
@@ -56,35 +59,31 @@ __SettingsFree(
     __FreePoolWithTag(Buffer, SETTINGS_TAG);
 }
 
-typedef struct _SETTINGS_INTERFACE_COPY_PARAMETERS {
-    PCHAR   SaveKeyName;
-    HANDLE  DestinationKey;
-} SETTINGS_INTERFACE_COPY_PARAMETERS, *PSETTINGS_INTERFACE_COPY_PARAMETERS;
-
 static NTSTATUS
-SettingsCopyInterfaceValue(
-    IN  PVOID                           Context,
-    IN  HANDLE                          SourceKey,
-    IN  PANSI_STRING                    ValueName,
-    IN  ULONG                           Type
+SettingsCopyValue(
+    IN  HANDLE  DestinationKey,
+    IN  HANDLE  SourceKey,
+    IN  PCHAR   ValueName,
+    IN  ULONG   Type
     )
 {
-    PSETTINGS_INTERFACE_COPY_PARAMETERS Parameters = Context;
-    NTSTATUS                            status;
+    NTSTATUS    status;
 
-    Trace("%s:%Z\n", Parameters->SaveKeyName, ValueName);
+    Trace("%s\n", ValueName);
 
     switch (Type) {
     case REG_DWORD: {
         ULONG   Value;
 
         status = RegistryQueryDwordValue(SourceKey,
-                                         ValueName->Buffer,
+                                         ValueName,
                                          &Value);
-        if (NT_SUCCESS(status))
-            (VOID) RegistryUpdateDwordValue(Parameters->DestinationKey,
-                                            ValueName->Buffer,
-                                            Value);
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        (VOID) RegistryUpdateDwordValue(DestinationKey,
+                                        ValueName,
+                                        Value);
 
         break;
     }
@@ -93,16 +92,18 @@ SettingsCopyInterfaceValue(
         PANSI_STRING    Value;
 
         status = RegistryQuerySzValue(SourceKey,
-                                      ValueName->Buffer,
+                                      ValueName,
                                       NULL,
                                       &Value);
-        if (NT_SUCCESS(status)) {
-            (VOID) RegistryUpdateSzValue(Parameters->DestinationKey,
-                                         ValueName->Buffer,
-                                         Type,
-                                         Value);
-            RegistryFreeSzValue(Value);
-        }
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        (VOID) RegistryUpdateSzValue(DestinationKey,
+                                     ValueName,
+                                     Type,
+                                     Value);
+
+        RegistryFreeSzValue(Value);
 
         break;
     }
@@ -111,17 +112,18 @@ SettingsCopyInterfaceValue(
         ULONG   Length;
 
         status = RegistryQueryBinaryValue(SourceKey,
-                                          ValueName->Buffer,
+                                          ValueName,
                                           &Value,
                                           &Length);
-        if (NT_SUCCESS(status)) {
-            (VOID) RegistryUpdateBinaryValue(Parameters->DestinationKey,
-                                             ValueName->Buffer,
-                                             Value,
-                                             Length);
-            if (Length != 0)
-                RegistryFreeBinaryValue(Value);
-        }
+        if (!NT_SUCCESS(status))
+            goto fail1;
+
+        (VOID) RegistryUpdateBinaryValue(DestinationKey,
+                                         ValueName,
+                                         Value,
+                                         Length);
+        if (Length != 0)
+            RegistryFreeBinaryValue(Value);
 
         break;
     }
@@ -130,167 +132,148 @@ SettingsCopyInterfaceValue(
     }
 
     return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
 }
 
+typedef struct _SETTINGS_COPY_SUBKEY_VALUE_PARAMETERS {
+    HANDLE  DestinationKey;
+} SETTINGS_COPY_SUBKEY_VALUE_PARAMETERS, 
*PSETTINGS_COPY_SUBKEY_VALUE_PARAMETERS;
+
 static NTSTATUS
-SettingsCopyInterface(
-    IN  HANDLE      SettingsKey,
-    IN  PCHAR       SaveKeyName,
-    IN  PCHAR       InterfacesPath,
-    IN  PCHAR       InterfacePrefix,
-    IN  LPGUID      Guid,
-    IN  BOOLEAN     Save
+SettingsCopySubKeyValue(
+    IN  PVOID                               Context,
+    IN  HANDLE                              Key,
+    IN  PANSI_STRING                        ValueName,
+    IN  ULONG                               Type
     )
 {
-    UNICODE_STRING  Unicode;
-    ULONG           Length;
-    PCHAR           InterfaceName;
-    HANDLE          InterfacesKey;
-    PCHAR           KeyName;
-    HANDLE          Key;
-    HANDLE          SaveKey;
-    NTSTATUS        status;
+    PSETTINGS_COPY_SUBKEY_VALUE_PARAMETERS Parameters = Context;
 
-    Trace("====>\n");
+    return SettingsCopyValue(Parameters->DestinationKey,
+                             Key,
+                             ValueName->Buffer,
+                             Type);
+}
+
+static NTSTATUS
+SettingsCopySubKey(
+    IN  HANDLE                              DestinationKey,
+    IN  HANDLE                              SourceKey,
+    IN  PCHAR                               SubKeyName
+    )
+{
+    SETTINGS_COPY_SUBKEY_VALUE_PARAMETERS   Parameters;
+    HANDLE                                  DestinationSubKey;
+    HANDLE                                  SourceSubKey;
+    NTSTATUS                                status;
 
-    status = RtlStringFromGUID(Guid, &Unicode);
+    status = RegistryCreateSubKey(DestinationKey,
+                                  SubKeyName,
+                                  REG_OPTION_NON_VOLATILE,
+                                  &DestinationSubKey);
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    Length = (ULONG)(((Unicode.Length / sizeof (WCHAR)) +
-                      1) * sizeof (CHAR));
-
-    InterfaceName = __SettingsAllocate(Length);
-
-    status = STATUS_NO_MEMORY;
-    if (InterfaceName == NULL)
+    status = RegistryOpenSubKey(SourceKey,
+                                SubKeyName,
+                                KEY_READ,
+                                &SourceSubKey);
+    if (!NT_SUCCESS(status))
         goto fail2;
 
-    status = RtlStringCbPrintfA(InterfaceName,
-                                Length,
-                                "%wZ",
-                                &Unicode);
-    ASSERT(NT_SUCCESS(status));
+    RtlZeroMemory(&Parameters, sizeof (Parameters));
 
-    status = RegistryOpenSubKey(NULL,
-                                InterfacesPath,
-                                KEY_ALL_ACCESS,
-                                &InterfacesKey);
+    Parameters.DestinationKey = DestinationSubKey;
+
+    status = RegistryEnumerateValues(SourceSubKey,
+                                     SettingsCopySubKeyValue,
+                                     &Parameters);
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    Length = (ULONG)((strlen(InterfacePrefix) +
-                      strlen(InterfaceName) +
-                      1) * sizeof (CHAR));
-
-    KeyName = __SettingsAllocate(Length);
+    RegistryCloseKey(SourceSubKey);
 
-    status = STATUS_NO_MEMORY;
-    if (KeyName == NULL)
-        goto fail4;
+    RegistryCloseKey(DestinationSubKey);
 
-    status = RtlStringCbPrintfA(KeyName,
-                                Length,
-                                "%s%s",
-                                InterfacePrefix,
-                                InterfaceName);
-    ASSERT(NT_SUCCESS(status));
-
-    status = (!Save) ?
-        RegistryCreateSubKey(InterfacesKey,
-                             KeyName,
-                             REG_OPTION_NON_VOLATILE,
-                             &Key) :
-        RegistryOpenSubKey(InterfacesKey,
-                           KeyName,
-                           KEY_READ,
-                           &Key);
-    if (!NT_SUCCESS(status))
-        goto fail5;
+    return STATUS_SUCCESS;
 
-    status = (Save) ?
-        RegistryCreateSubKey(SettingsKey,
-                             SaveKeyName,
-                             REG_OPTION_NON_VOLATILE,
-                             &SaveKey) :
-        RegistryOpenSubKey(SettingsKey,
-                           SaveKeyName,
-                           KEY_READ,
-                           &SaveKey);
-    if (!NT_SUCCESS(status))
-        goto fail6;
+fail3:
+    Error("fail3\n");
 
-    if (Save) {
-        SETTINGS_INTERFACE_COPY_PARAMETERS  Parameters;
+    RegistryCloseKey(SourceSubKey);
 
-        Parameters.SaveKeyName = SaveKeyName;
-        Parameters.DestinationKey = SaveKey;
+fail2:
+    Error("fail2\n");
 
-        status = RegistryEnumerateValues(Key,
-                                         SettingsCopyInterfaceValue,
-                                         &Parameters);
-    } else { // Restore
-        SETTINGS_INTERFACE_COPY_PARAMETERS  Parameters;
+    RegistryCloseKey(DestinationSubKey);
 
-        Parameters.SaveKeyName = SaveKeyName;
-        Parameters.DestinationKey = Key;
+fail1:
+    Error("fail1 (%08x)\n", status);
 
-        status = RegistryEnumerateValues(SaveKey,
-                                         SettingsCopyInterfaceValue,
-                                         &Parameters);
-    }
+    return status;
+}
 
-    if (!NT_SUCCESS(status))
-        goto fail7;
+#define CLASS_PATH 
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Class"
 
-    RegistryCloseKey(SaveKey);
+static NTSTATUS
+SettingsOpenNetKey(
+    IN  ACCESS_MASK DesiredAccess,
+    OUT PHANDLE     NetKey
+    )
+{
+    HANDLE          ClassKey;
+    UNICODE_STRING  Unicode;
+    ANSI_STRING     Ansi;
+    NTSTATUS        status;
 
-    if (!Save)
-        (VOID) RegistryDeleteSubKey(SettingsKey, SaveKeyName);
+    status = RegistryOpenSubKey(NULL,
+                                CLASS_PATH,
+                                KEY_ALL_ACCESS,
+                                &ClassKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-    RegistryCloseKey(Key);
+    status = RtlStringFromGUID(&GUID_DEVCLASS_NET, &Unicode);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    __SettingsFree(KeyName);
+    status = RtlUnicodeStringToAnsiString(&Ansi, &Unicode, TRUE);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    RegistryCloseKey(InterfacesKey);
+    status = RegistryOpenSubKey(ClassKey,
+                                Ansi.Buffer,
+                                DesiredAccess,
+                                NetKey);
+    if (!NT_SUCCESS(status))
+        goto fail4;
 
-    __SettingsFree(InterfaceName);
+    RtlFreeAnsiString(&Ansi);
 
     RtlFreeUnicodeString(&Unicode);
 
-    Trace("<====\n");
+    RegistryCloseKey(ClassKey);
 
     return STATUS_SUCCESS;
 
-fail7:
-    Error("fail7\n");
-
-    RegistryCloseKey(SaveKey);
-
-fail6:
-    Error("fail6\n");
-
-    RegistryCloseKey(Key);
-
-fail5:
-    Error("fail5\n");
-
-    __SettingsFree(KeyName);
-
 fail4:
     Error("fail4\n");
 
-    RegistryCloseKey(InterfacesKey);
+    RtlFreeAnsiString(&Ansi);
 
 fail3:
     Error("fail3\n");
 
-    __SettingsFree(InterfaceName);
+    RtlFreeUnicodeString(&Unicode);
 
 fail2:
     Error("fail2\n");
 
-    RtlFreeUnicodeString(&Unicode);
+    RegistryCloseKey(ClassKey);
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -298,315 +281,285 @@ fail1:
     return status;
 }
 
-typedef struct _SETTINGS_IP_ADDRESSES_COPY_PARAMETERS {
-    UCHAR   Version;
-    PCHAR   SourceValuePrefix;
-    HANDLE  DestinationKey;
-    PCHAR   DestinationValuePrefix;
-} SETTINGS_IP_ADDRESSES_COPY_PARAMETERS, 
*PSETTINGS_IP_ADDRESSES_COPY_PARAMETERS;
+typedef struct _SETTINGS_MATCH_NET_CFG_INSTANCE_ID_PARAMETERS {
+    ANSI_STRING NetCfgInstanceID;
+    ANSI_STRING SubKeyName;
+} SETTINGS_MATCH_NET_CFG_INSTANCE_ID_PARAMETERS, 
*PSETTINGS_MATCH_NET_CFG_INSTANCE_ID_PARAMETERS;
 
 static NTSTATUS
-SettingsCopyIpAddressesValue(
-    IN  PVOID                               Context,
-    IN  HANDLE                              SourceKey,
-    IN  PANSI_STRING                        SourceValueName,
-    IN  ULONG                               Type
+SettingsMatchNetCfgInstanceID(
+    IN  PVOID                                       Context,
+    IN  HANDLE                                      Key,
+    IN  PANSI_STRING                                SubKeyName
     )
 {
-    PSETTINGS_IP_ADDRESSES_COPY_PARAMETERS  Parameters = Context;
-    ULONG                                   SourceValuePrefixLength;
-    ULONG                                   DestinationValuePrefixLength;
-    ULONG                                   DestinationValueNameLength;
-    PCHAR                                   DestinationValueName;
-    PVOID                                   Value;
-    ULONG                                   ValueLength;
-    NTSTATUS                                status;
+    PSETTINGS_MATCH_NET_CFG_INSTANCE_ID_PARAMETERS  Parameters = Context;
+    HANDLE                                          SubKey;
+    ANSI_STRING                                     Ansi;
+    ULONG                                           Type;
+    PANSI_STRING                                    Value;
+    NTSTATUS                                        status;
 
-    if (Type != REG_BINARY)
+    Trace("====> (%Z)\n", SubKeyName);
+
+    if (Parameters->SubKeyName.Length != 0)
         goto done;
 
-    SourceValuePrefixLength = (ULONG)strlen(Parameters->SourceValuePrefix);
-    DestinationValuePrefixLength = 
(ULONG)strlen(Parameters->DestinationValuePrefix);
+    RtlInitAnsiString(&Ansi, "Properties");
 
-    if (_strnicmp(SourceValueName->Buffer,
-                  Parameters->SourceValuePrefix,
-                  SourceValuePrefixLength) != 0)
+    if (RtlCompareString(&Ansi, SubKeyName, TRUE) == 0)
         goto done;
 
-    DestinationValueNameLength = SourceValueName->Length -
-                                 (SourceValuePrefixLength * sizeof (CHAR)) +
-                                 ((DestinationValuePrefixLength + 1) * sizeof 
(CHAR));
+    status = RegistryOpenSubKey(Key,
+                                SubKeyName->Buffer,
+                                KEY_READ,
+                                &SubKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-    DestinationValueName = __SettingsAllocate(DestinationValueNameLength);
+    status = RegistryQuerySzValue(SubKey,
+                                  "NetCfgInstanceID",
+                                  &Type,
+                                  &Value);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    status = STATUS_NO_MEMORY;
-    if (DestinationValueName == NULL)
-        goto fail1;
+    status = STATUS_INVALID_PARAMETER;
+    if (Type != REG_SZ)
+        goto fail3;
 
-    status = RtlStringCbPrintfA(DestinationValueName,
-                                DestinationValueNameLength,
-                                "%s%s",
-                                Parameters->DestinationValuePrefix,
-                                SourceValueName->Buffer + 
SourceValuePrefixLength);
-    ASSERT(NT_SUCCESS(status));
-
-    Trace("Version%u: %Z -> %s\n",
-          Parameters->Version,
-          SourceValueName,
-          DestinationValueName);
-
-    status = RegistryQueryBinaryValue(SourceKey,
-                                      SourceValueName->Buffer,
-                                      &Value,
-                                      &ValueLength);
-    if (NT_SUCCESS(status)) {
-        (VOID) RegistryUpdateBinaryValue(Parameters->DestinationKey,
-                                         DestinationValueName,
-                                         Value,
-                                         ValueLength);
-        RegistryFreeBinaryValue(Value);
+    if (RtlCompareString(&Parameters->NetCfgInstanceID,
+                         &Value[0],
+                         TRUE) == 0) {
+        Parameters->SubKeyName.MaximumLength = SubKeyName->MaximumLength;
+        Parameters->SubKeyName.Buffer = 
__SettingsAllocate(Parameters->SubKeyName.MaximumLength);
+
+        status = STATUS_NO_MEMORY;
+        if (Parameters->SubKeyName.Buffer == NULL)
+            goto fail4;
+
+        RtlCopyMemory(Parameters->SubKeyName.Buffer,
+                      SubKeyName->Buffer,
+                      SubKeyName->Length);
+
+        Parameters->SubKeyName.Length = SubKeyName->Length;
     }
 
-    __SettingsFree(DestinationValueName);
+    RegistryFreeSzValue(Value);
+
+    RegistryCloseKey(SubKey);
 
 done:
+    Trace("<====\n");
+
     return STATUS_SUCCESS;
 
+fail4:
+    Error("fail4\n");
+
+fail3:
+    Error("fail3\n");
+
+    RegistryFreeSzValue(Value);
+
+fail2:
+    Error("fail2\n");
+
+    RegistryCloseKey(SubKey);
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
     return status;
 }
 
-#define IPV6_PATH 
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Nsi\\{eb004a01-9b1a-11d4-9123-0050047759bc}\\10"
-
-#define IPV4_PATH 
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Nsi\\{eb004a00-9b1a-11d4-9123-0050047759bc}\\10"
-
 static NTSTATUS
-SettingsCopyIpAddresses(
-    IN  HANDLE      SettingsKey,
-    IN  UCHAR       Version,
-    IN  PNET_LUID   Luid,
-    IN  BOOLEAN     Save
+SettingsGetAliasNetInstance(
+    IN  LPGUID                                      NetCfgInstanceID,
+    OUT PANSI_STRING                                SubKeyName
     )
 {
-    const CHAR      *Path;
-    HANDLE          Key;
-    ULONG           ValuePrefixLength;
-    PCHAR           ValuePrefix;
-    const CHAR      *SaveKeyName;
-    HANDLE          SaveKey;
-    NTSTATUS        status;
+    HANDLE                                          NetKey;
+    UNICODE_STRING                                  Unicode;
+    ANSI_STRING                                     Ansi;
+    SETTINGS_MATCH_NET_CFG_INSTANCE_ID_PARAMETERS   Parameters;
+    NTSTATUS                                        status;
 
-    Trace("====>\n");
-
-    ASSERT(Version == 4 || Version == 6);
-    Path = (Version == 4) ? IPV4_PATH : IPV6_PATH;
+    status = SettingsOpenNetKey(KEY_READ, &NetKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
 
-    status = RegistryOpenSubKey(NULL,
-                                (PCHAR)Path,
-                                (Save) ? KEY_READ : KEY_ALL_ACCESS,
-                                &Key);
-    if (!NT_SUCCESS(status)) {
-        Info("Version%u: ADDRESSES NOT FOUND\n", Version);
-        goto done;
-    }
+    status = RtlStringFromGUID(NetCfgInstanceID, &Unicode);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    ValuePrefixLength = (ULONG)(((sizeof (NET_LUID) * 2) +
-                                 1) * sizeof (CHAR));
+    status = RtlUnicodeStringToAnsiString(&Ansi, &Unicode, TRUE);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    ValuePrefix = __SettingsAllocate(ValuePrefixLength);
+    RtlZeroMemory(&Parameters, sizeof (Parameters));
 
-    status = STATUS_NO_MEMORY;
-    if (ValuePrefix == NULL)
-        goto fail1;
+    Parameters.NetCfgInstanceID = Ansi;
 
-    status = RtlStringCbPrintfA(ValuePrefix,
-                                ValuePrefixLength,
-                                "%016llX",
-                                Luid->Value);
-    ASSERT(NT_SUCCESS(status));
-
-    SaveKeyName = (Version == 4) ? "IpVersion4Addresses" : 
"IpVersion6Addresses";
-
-    status = (Save) ?
-        RegistryCreateSubKey(SettingsKey,
-                             (PCHAR)SaveKeyName,
-                             REG_OPTION_NON_VOLATILE,
-                             &SaveKey) :
-        RegistryOpenSubKey(SettingsKey,
-                           (PCHAR)SaveKeyName,
-                           KEY_READ,
-                           &SaveKey);
+    status = RegistryEnumerateSubKeys(NetKey,
+                                      SettingsMatchNetCfgInstanceID,
+                                      &Parameters);
     if (!NT_SUCCESS(status))
-        goto fail2;
-
-    if (Save) {
-        SETTINGS_IP_ADDRESSES_COPY_PARAMETERS   Parameters;
+        goto fail4;
 
-        Parameters.Version = Version;
-        Parameters.SourceValuePrefix = ValuePrefix;
-        Parameters.DestinationKey = SaveKey;
-        Parameters.DestinationValuePrefix = "LUID";
+    status = STATUS_UNSUCCESSFUL;
+    if (Parameters.SubKeyName.Length == 0)
+        goto fail5;
 
-        status = RegistryEnumerateValues(Key,
-                                         SettingsCopyIpAddressesValue,
-                                         &Parameters);
-    } else { // Restore
-        SETTINGS_IP_ADDRESSES_COPY_PARAMETERS   Parameters;
+    Info("%Z\n", &Parameters.SubKeyName);
 
-        Parameters.Version = Version;
-        Parameters.SourceValuePrefix = "LUID";
-        Parameters.DestinationKey = Key;
-        Parameters.DestinationValuePrefix = ValuePrefix;
+    *SubKeyName = Parameters.SubKeyName;
 
-        status = RegistryEnumerateValues(SaveKey,
-                                         SettingsCopyIpAddressesValue,
-                                         &Parameters);
-    }
+    RegistryCloseKey(NetKey);
 
-    RegistryCloseKey(SaveKey);
+    return STATUS_SUCCESS;
 
-    if (!Save)
-        (VOID) RegistryDeleteSubKey(SettingsKey, (PCHAR)SaveKeyName);
+fail5:
+    Error("fail5\n");
 
-    __SettingsFree(ValuePrefix);
+fail4:
+    Error("fail4\n");
 
-    RegistryCloseKey(Key);
+    RtlFreeAnsiString(&Ansi);
 
-done:
-    Trace("<====\n");
+fail3:
+    Error("fail3\n");
 
-    return STATUS_SUCCESS;
+    RtlFreeUnicodeString(&Unicode);
 
 fail2:
     Error("fail2\n");
 
-    __SettingsFree(ValuePrefix);
+    RegistryCloseKey(NetKey);
 
 fail1:
     Error("fail1 (%08x)\n", status);
 
-    RegistryCloseKey(Key);
-
     return status;
 }
 
-#define INTERFACES_PATH(_Name) 
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services\\" ## #_Name ## 
"\\Parameters\\Interfaces\\"
-
-static VOID
-SettingsCopy(
-     IN HANDLE      SettingsKey,
-     IN LPGUID      InterfaceGuid,
-     IN PNET_LUID   InterfaceLuid,
-     IN BOOLEAN     Save
-     )
-{
-    Trace("====>\n");
-
-    (VOID) SettingsCopyInterface(SettingsKey,
-                                 "NetBT",
-                                 INTERFACES_PATH(NetBT),
-                                 "Tcpip_",
-                                 InterfaceGuid,
-                                 Save);
-
-    (VOID) SettingsCopyInterface(SettingsKey,
-                                 "Tcpip",
-                                 INTERFACES_PATH(Tcpip),
-                                 "",
-                                 InterfaceGuid,
-                                 Save);
-
-    (VOID) SettingsCopyInterface(SettingsKey,
-                                 "Tcpip6",
-                                 INTERFACES_PATH(Tcpip6),
-                                 "",
-                                 InterfaceGuid,
-                                 Save);
-
-    (VOID) SettingsCopyIpAddresses(SettingsKey,
-                                   4,
-                                   InterfaceLuid,
-                                   Save);
-
-    (VOID) SettingsCopyIpAddresses(SettingsKey,
-                                   6,
-                                   InterfaceLuid,
-                                   Save);
-
-    Trace("<====\n");
-}
-
-NTSTATUS
-SettingsSave(
-     IN HANDLE      SoftwareKey,
-     IN PWCHAR      Alias,
-     IN PWCHAR      Description,
-     IN LPGUID      InterfaceGuid,
-     IN PNET_LUID   InterfaceLuid
-     )
+static NTSTATUS
+SettingsCopyLinkage(
+    IN HANDLE       DestinationKey,
+    IN HANDLE       SourceKey
+    )
 {
-    HANDLE          SettingsKey;
     NTSTATUS        status;
 
-    Info("FROM %ws (%ws)\n", Alias, Description);
+    Trace("====>\n");
 
-    status = RegistryCreateSubKey(SoftwareKey,
-                                  "Settings",
-                                  REG_OPTION_NON_VOLATILE,
-                                  &SettingsKey);
+    status = SettingsCopyValue(DestinationKey,
+                               SourceKey,
+                               "NetCfgInstanceID",
+                               REG_SZ);
     if (!NT_SUCCESS(status))
         goto fail1;
 
-    SettingsCopy(SettingsKey, InterfaceGuid, InterfaceLuid, TRUE);
+    status = SettingsCopyValue(DestinationKey,
+                               SourceKey,
+                               "NetLuidIndex",
+                               REG_DWORD);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    RegistryCloseKey(SettingsKey);
+    status = SettingsCopySubKey(DestinationKey,
+                                SourceKey,
+                                "Linkage");
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    Trace("<====\n");
 
     return STATUS_SUCCESS;
 
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
 fail1:
-    Error("fail1\n", status);
+    Error("fail1 (%08x)\n", status);
 
     return status;
 }
 
 NTSTATUS
-SettingsRestore(
-     IN HANDLE      SoftwareKey,
-     IN PWCHAR      Alias,
-     IN PWCHAR      Description,
-     IN LPGUID      InterfaceGuid,
-     IN PNET_LUID   InterfaceLuid
-     )
+SettingsStealIdentity(
+    IN HANDLE   SoftwareKey,
+    IN PWCHAR   Alias,
+    IN PWCHAR   Description,
+    IN LPGUID   NetCfgInstanceID
+    )
 {
-    HANDLE          SettingsKey;
-    NTSTATUS        status;
+    ANSI_STRING SubKeyName;
+    HANDLE      NetKey;
+    HANDLE      SubKey;
+    NTSTATUS    status;
 
-    status = RegistryOpenSubKey(SoftwareKey,
-                                "Settings",
-                                KEY_ALL_ACCESS,
-                                &SettingsKey);
-    if (!NT_SUCCESS(status)) {
-        if (status == STATUS_OBJECT_NAME_NOT_FOUND)
-            goto done;
+    Info("%ws (%ws)\n", Alias, Description);
 
+    status = SettingsGetAliasNetInstance(NetCfgInstanceID,
+                                         &SubKeyName);
+    if (!NT_SUCCESS(status))
         goto fail1;
-    }
 
-    Info("TO %ws (%ws)\n", Alias, Description);
+    status = RegistryUpdateSzValue(SoftwareKey,
+                                   "AliasNetInstance",
+                                   REG_SZ,
+                                   &SubKeyName);
+    if (!NT_SUCCESS(status))
+        goto fail2;
 
-    SettingsCopy(SettingsKey, InterfaceGuid, InterfaceLuid, FALSE);
+    status = SettingsOpenNetKey(KEY_READ, &NetKey);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    RegistryCloseKey(SettingsKey);
+    status = RegistryOpenSubKey(NetKey,
+                                SubKeyName.Buffer,
+                                KEY_READ,
+                                &SubKey);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+    status = SettingsCopyLinkage(SoftwareKey,
+                                 SubKey);
+    if (!NT_SUCCESS(status))
+        goto fail5;
 
-    (VOID) RegistryDeleteSubKey(SoftwareKey, "Settings");
+    RegistryCloseKey(SubKey);
+
+    RegistryCloseKey(NetKey);
+
+    __SettingsFree(SubKeyName.Buffer);
 
-done:
     return STATUS_SUCCESS;
 
+fail5:
+    Error("fail5\n");
+
+    RegistryCloseKey(SubKey);
+
+fail4:
+    Error("fail4\n");
+
+    RegistryCloseKey(NetKey);
+
+fail3:
+    Error("fail3\n");
+
+fail2:
+    Error("fail2\n");
+
+    __SettingsFree(SubKeyName.Buffer);
+
 fail1:
-    Error("fail1\n", status);
+    Error("fail1 (%08x)\n", status);
 
     return status;
 }
diff --git a/src/xenvif/settings.h b/src/xenvif/settings.h
index 7bd1824..08221f2 100644
--- a/src/xenvif/settings.h
+++ b/src/xenvif/settings.h
@@ -33,21 +33,11 @@
 #define _XENVIF_SETTINGS_H
 
 extern NTSTATUS
-SettingsSave(
+SettingsStealIdentity(
      IN HANDLE      SoftwareKey,
      IN PWCHAR      Alias,
      IN PWCHAR      Description,
-     IN LPGUID      InterfaceGuid,
-     IN PNET_LUID   InterfaceLuid
-     );
-
-extern NTSTATUS
-SettingsRestore(
-     IN HANDLE      SoftwareKey,
-     IN PWCHAR      Alias,
-     IN PWCHAR      Description,
-     IN LPGUID      InterfaceGuid,
-     IN PNET_LUID   InterfaceLuid
+     IN LPGUID      InterfaceGuid
      );
 
 #endif  // _XENVIF_SETTINGS_H
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.