]> xenbits.xensource.com Git - people/pauldu/xenvif.git/commitdiff
Revert all settings stealing patches
authorPaul Durrant <paul.durrant@citrix.com>
Wed, 7 Sep 2016 15:25:52 +0000 (16:25 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Wed, 7 Sep 2016 15:25:52 +0000 (16:25 +0100)
Windows has completely defeated me. There appears to be no way to
duplicate the stack binding of the emulated device without that binding
being removed if XENNET is un-installed, despite clearing all the
relevant registry keys in the DIF_REMOVE pre-process phase.

So, this patch reverts the code back to using the settings copy
mechanism employed in the 8.1 source.

The patches reverted (with some fix-up) are:

32bd2878 "Remove settings code"
70f4bb96 "Re-work identity stealing code"
04c391d9 "Replace copying network settings with identity stealing"

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
src/xenvif/pdo.c
src/xenvif/settings.c [new file with mode: 0644]
src/xenvif/settings.h [new file with mode: 0644]
vs2012/xenvif/xenvif.vcxproj
vs2013/xenvif/xenvif.vcxproj

index 33a75ae424b41aa85f63818bf542635dd52b3eae..1b773a1c8d01c72a77d590ff6efa1df95da42ada 100644 (file)
@@ -53,6 +53,7 @@
 #include "registry.h"
 #include "thread.h"
 #include "link.h"
+#include "settings.h"
 #include "dbg_print.h"
 #include "assert.h"
 #include "util.h"
@@ -71,9 +72,6 @@ struct _XENVIF_PDO {
     PXENVIF_THREAD              DevicePowerThread;
     PIRP                        DevicePowerIrp;
 
-    HANDLE                      SoftwareKey;
-    HANDLE                      HardwareKey;
-
     PXENVIF_FDO                 Fdo;
     BOOLEAN                     Missing;
     const CHAR                  *Reason;
@@ -787,67 +785,11 @@ __PdoClearPermanentAddress(
     RtlZeroMemory(&Pdo->PermanentAddress, sizeof (ETHERNET_ADDRESS));
 }
 
-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  PXENVIF_PDO Pdo,
+    IN  HANDLE      SoftwareKey,
+    IN  HANDLE      HardwareKey
     )
 {
     PANSI_STRING    DriverDesc;
@@ -855,7 +797,7 @@ PdoSetFriendlyName(
     ANSI_STRING     Ansi[2];
     NTSTATUS        status;
 
-    status = RegistryQuerySzValue(__PdoGetSoftwareKey(Pdo),
+    status = RegistryQuerySzValue(SoftwareKey,
                                   "DriverDesc",
                                   NULL,
                                   &DriverDesc);
@@ -874,7 +816,7 @@ PdoSetFriendlyName(
     RtlZeroMemory(Ansi, sizeof (ANSI_STRING) * 2);
     RtlInitAnsiString(&Ansi[0], Buffer);
 
-    status = RegistryUpdateSzValue(__PdoGetHardwareKey(Pdo),
+    status = RegistryUpdateSzValue(HardwareKey,
                                    "FriendlyName",
                                    REG_SZ,
                                    Ansi);
@@ -901,7 +843,8 @@ fail1:
 
 static FORCEINLINE NTSTATUS
 __PdoSetCurrentAddress(
-    IN  PXENVIF_PDO Pdo
+    IN  PXENVIF_PDO Pdo,
+    IN  HANDLE      Key
     )
 {
     PANSI_STRING    Ansi;
@@ -909,7 +852,7 @@ __PdoSetCurrentAddress(
 
     RtlFillMemory(Pdo->CurrentAddress.Byte, ETHERNET_ADDRESS_LENGTH, 0xFF);
 
-    status = RegistryQuerySzValue(__PdoGetSoftwareKey(Pdo),
+    status = RegistryQuerySzValue(Key,
                                   "NetworkAddress",
                                   NULL,
                                   &Ansi);
@@ -1191,6 +1134,56 @@ 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,
@@ -1224,8 +1217,10 @@ PdoStartDevice(
     VOID                (*__FreeMibTable)(PVOID);
     PMIB_IF_TABLE2      Table;
     ULONG               Index;
-    PMIB_IF_ROW2        Row;
     PIO_STACK_LOCATION  StackLocation;
+    HANDLE              SoftwareKey;
+    HANDLE              HardwareKey;
+    GUID                Guid;
     NTSTATUS            status;
 
     status = STATUS_UNSUCCESSFUL;
@@ -1235,17 +1230,23 @@ PdoStartDevice(
     if (DriverSafeMode())
         goto fail2;
 
-    status = __PdoSetSoftwareKey(Pdo);
+    status = RegistryOpenSoftwareKey(__PdoGetDeviceObject(Pdo),
+                                     KEY_ALL_ACCESS,
+                                     &SoftwareKey);
     if (!NT_SUCCESS(status))
         goto fail3;
 
-    status = __PdoSetHardwareKey(Pdo);
+    status = RegistryOpenHardwareKey(__PdoGetDeviceObject(Pdo),
+                                     KEY_ALL_ACCESS,
+                                     &HardwareKey);
     if (!NT_SUCCESS(status))
         goto fail4;
 
-    (VOID) PdoSetFriendlyName(Pdo);
+    (VOID) PdoSetFriendlyName(Pdo,
+                              SoftwareKey,
+                              HardwareKey);
 
-    status = __PdoSetCurrentAddress(Pdo);
+    status = __PdoSetCurrentAddress(Pdo, SoftwareKey);
     if (!NT_SUCCESS(status))
         goto fail5;
 
@@ -1271,14 +1272,13 @@ PdoStartDevice(
     // aliasing emulated device, so save its settings.
     //
     for (Index = 0; Index < Table->NumEntries; Index++) {
-        Row = &Table->Table[Index];
+        PMIB_IF_ROW2    Row = &Table->Table[Index];
 
-        Trace("%s: checking %ws (%ws)\n",
-              __PdoGetName(Pdo),
-              Row->Alias,
-              Row->Description);
+        if (!(Row->InterfaceAndOperStatusFlags.HardwareInterface) ||
+            !(Row->InterfaceAndOperStatusFlags.ConnectorPresent))
+            continue;
 
-        if (!Row->InterfaceAndOperStatusFlags.ConnectorPresent)
+        if (Row->OperStatus != IfOperStatusUp)
             continue;
 
         if (Row->PhysicalAddressLength != sizeof (ETHERNET_ADDRESS))
@@ -1289,10 +1289,14 @@ PdoStartDevice(
                    sizeof (ETHERNET_ADDRESS)) != 0)
             continue;
 
-        if (Row->OperStatus != IfOperStatusUp)
-            continue;
+        (VOID) SettingsSave(SoftwareKey,
+                            Row->Alias,
+                            Row->Description,
+                            &Row->InterfaceGuid,
+                            &Row->InterfaceLuid);
 
         Pdo->HasAlias = TRUE;
+        break;
     }
 
     if (Pdo->HasAlias) {
@@ -1302,6 +1306,27 @@ PdoStartDevice(
         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++) {
+            PMIB_IF_ROW2    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);
@@ -1317,6 +1342,8 @@ PdoStartDevice(
 
     __FreeMibTable(Table);
 
+    RegistryCloseKey(SoftwareKey);
+
     return STATUS_SUCCESS;
 
 fail10:
@@ -1346,14 +1373,12 @@ fail6:
 fail5:
     Error("fail5\n");
 
-    RegistryCloseKey(__PdoGetHardwareKey(Pdo));
-    Pdo->HardwareKey = NULL;
+    RegistryCloseKey(HardwareKey);
 
 fail4:
     Error("fail4\n");
 
-    RegistryCloseKey(__PdoGetSoftwareKey(Pdo));
-    Pdo->SoftwareKey = NULL;
+    RegistryCloseKey(SoftwareKey);
 
 fail3:
     Error("fail3\n");
@@ -1422,12 +1447,6 @@ 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;
 
@@ -1513,12 +1532,6 @@ PdoRemoveDevice(
 done:
     RtlZeroMemory(&Pdo->CurrentAddress, sizeof (ETHERNET_ADDRESS));
 
-    RegistryCloseKey(__PdoGetHardwareKey(Pdo));
-    Pdo->HardwareKey = NULL;
-
-    RegistryCloseKey(__PdoGetSoftwareKey(Pdo));
-    Pdo->SoftwareKey = NULL;
-
     NeedInvalidate = FALSE;
 
     FdoAcquireMutex(Fdo);
@@ -2804,11 +2817,12 @@ PdoDestroy(
     PDEVICE_OBJECT  PhysicalDeviceObject = Dx->DeviceObject;
     PXENVIF_FDO     Fdo = __PdoGetFdo(Pdo);
 
-    ASSERT3U(__PdoGetDevicePnpState(Pdo), ==, Deleted);
+    ASSERT(!Pdo->UnplugRequested);
 
-    Pdo->UnplugRequested = FALSE;
     Pdo->HasAlias = FALSE;
 
+    ASSERT3U(__PdoGetDevicePnpState(Pdo), ==, Deleted);
+
     ASSERT(__PdoIsMissing(Pdo));
     Pdo->Missing = FALSE;
 
diff --git a/src/xenvif/settings.c b/src/xenvif/settings.c
new file mode 100644 (file)
index 0000000..5cb9984
--- /dev/null
@@ -0,0 +1,612 @@
+/* Copyright (c) Citrix Systems Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms,
+ * with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * *   Redistributions of source code must retain the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer.
+ * *   Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the
+ *     following disclaimer in the documentation and/or other
+ *     materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ntddk.h>
+#include <ntstrsafe.h>
+
+#include "registry.h"
+#include "driver.h"
+#include "dbg_print.h"
+#include "assert.h"
+#include "util.h"
+
+#define SETTINGS_TAG 'TTES'
+
+static FORCEINLINE PVOID
+__SettingsAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, SETTINGS_TAG);
+}
+
+static FORCEINLINE VOID
+__SettingsFree(
+    IN  PVOID   Buffer
+    )
+{
+    __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
+    )
+{
+    PSETTINGS_INTERFACE_COPY_PARAMETERS Parameters = Context;
+    NTSTATUS                            status;
+
+    Trace("%s:%Z\n", Parameters->SaveKeyName, ValueName);
+
+    switch (Type) {
+    case REG_DWORD: {
+        ULONG   Value;
+
+        status = RegistryQueryDwordValue(SourceKey,
+                                         ValueName->Buffer,
+                                         &Value);
+        if (NT_SUCCESS(status))
+            (VOID) RegistryUpdateDwordValue(Parameters->DestinationKey,
+                                            ValueName->Buffer,
+                                            Value);
+
+        break;
+    }
+    case REG_SZ:
+    case REG_MULTI_SZ: {
+        PANSI_STRING    Value;
+
+        status = RegistryQuerySzValue(SourceKey,
+                                      ValueName->Buffer,
+                                      NULL,
+                                      &Value);
+        if (NT_SUCCESS(status)) {
+            (VOID) RegistryUpdateSzValue(Parameters->DestinationKey,
+                                         ValueName->Buffer,
+                                         Type,
+                                         Value);
+            RegistryFreeSzValue(Value);
+        }
+
+        break;
+    }
+    case REG_BINARY: {
+        PVOID   Value;
+        ULONG   Length;
+
+        status = RegistryQueryBinaryValue(SourceKey,
+                                          ValueName->Buffer,
+                                          &Value,
+                                          &Length);
+        if (NT_SUCCESS(status)) {
+            (VOID) RegistryUpdateBinaryValue(Parameters->DestinationKey,
+                                             ValueName->Buffer,
+                                             Value,
+                                             Length);
+            if (Length != 0)
+                RegistryFreeBinaryValue(Value);
+        }
+
+        break;
+    }
+    default:
+        ASSERT(FALSE);
+    }
+
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+SettingsCopyInterface(
+    IN  HANDLE      SettingsKey,
+    IN  PCHAR       SaveKeyName,
+    IN  PCHAR       InterfacesPath,
+    IN  PCHAR       InterfacePrefix,
+    IN  LPGUID      Guid,
+    IN  BOOLEAN     Save
+    )
+{
+    UNICODE_STRING  Unicode;
+    ULONG           Length;
+    PCHAR           InterfaceName;
+    HANDLE          InterfacesKey;
+    PCHAR           KeyName;
+    HANDLE          Key;
+    HANDLE          SaveKey;
+    NTSTATUS        status;
+
+    Trace("====>\n");
+
+    status = RtlStringFromGUID(Guid, &Unicode);
+    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)
+        goto fail2;
+
+    status = RtlStringCbPrintfA(InterfaceName,
+                                Length,
+                                "%wZ",
+                                &Unicode);
+    ASSERT(NT_SUCCESS(status));
+
+    status = RegistryOpenSubKey(NULL,
+                                InterfacesPath,
+                                KEY_ALL_ACCESS,
+                                &InterfacesKey);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    Length = (ULONG)((strlen(InterfacePrefix) +
+                      strlen(InterfaceName) +
+                      1) * sizeof (CHAR));
+
+    KeyName = __SettingsAllocate(Length);
+
+    status = STATUS_NO_MEMORY;
+    if (KeyName == NULL)
+        goto fail4;
+
+    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;
+
+    status = (Save) ?
+        RegistryCreateSubKey(SettingsKey,
+                             SaveKeyName,
+                             REG_OPTION_NON_VOLATILE,
+                             &SaveKey) :
+        RegistryOpenSubKey(SettingsKey,
+                           SaveKeyName,
+                           KEY_READ,
+                           &SaveKey);
+    if (!NT_SUCCESS(status))
+        goto fail6;
+
+    if (Save) {
+        SETTINGS_INTERFACE_COPY_PARAMETERS  Parameters;
+
+        Parameters.SaveKeyName = SaveKeyName;
+        Parameters.DestinationKey = SaveKey;
+
+        status = RegistryEnumerateValues(Key,
+                                         SettingsCopyInterfaceValue,
+                                         &Parameters);
+    } else { // Restore
+        SETTINGS_INTERFACE_COPY_PARAMETERS  Parameters;
+
+        Parameters.SaveKeyName = SaveKeyName;
+        Parameters.DestinationKey = Key;
+
+        status = RegistryEnumerateValues(SaveKey,
+                                         SettingsCopyInterfaceValue,
+                                         &Parameters);
+    }
+
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
+    RegistryCloseKey(SaveKey);
+
+    if (!Save)
+        (VOID) RegistryDeleteSubKey(SettingsKey, SaveKeyName);
+
+    RegistryCloseKey(Key);
+
+    __SettingsFree(KeyName);
+
+    RegistryCloseKey(InterfacesKey);
+
+    __SettingsFree(InterfaceName);
+
+    RtlFreeUnicodeString(&Unicode);
+
+    Trace("<====\n");
+
+    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);
+
+fail3:
+    Error("fail3\n");
+
+    __SettingsFree(InterfaceName);
+
+fail2:
+    Error("fail2\n");
+
+    RtlFreeUnicodeString(&Unicode);
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    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;
+
+static NTSTATUS
+SettingsCopyIpAddressesValue(
+    IN  PVOID                               Context,
+    IN  HANDLE                              SourceKey,
+    IN  PANSI_STRING                        SourceValueName,
+    IN  ULONG                               Type
+    )
+{
+    PSETTINGS_IP_ADDRESSES_COPY_PARAMETERS  Parameters = Context;
+    ULONG                                   SourceValuePrefixLength;
+    ULONG                                   DestinationValuePrefixLength;
+    ULONG                                   DestinationValueNameLength;
+    PCHAR                                   DestinationValueName;
+    PVOID                                   Value;
+    ULONG                                   ValueLength;
+    NTSTATUS                                status;
+
+    if (Type != REG_BINARY)
+        goto done;
+
+    SourceValuePrefixLength = (ULONG)strlen(Parameters->SourceValuePrefix);
+    DestinationValuePrefixLength = (ULONG)strlen(Parameters->DestinationValuePrefix);
+
+    if (_strnicmp(SourceValueName->Buffer,
+                  Parameters->SourceValuePrefix,
+                  SourceValuePrefixLength) != 0)
+        goto done;
+
+    DestinationValueNameLength = SourceValueName->Length -
+                                 (SourceValuePrefixLength * sizeof (CHAR)) +
+                                 ((DestinationValuePrefixLength + 1) * sizeof (CHAR));
+
+    DestinationValueName = __SettingsAllocate(DestinationValueNameLength);
+
+    status = STATUS_NO_MEMORY;
+    if (DestinationValueName == NULL)
+        goto fail1;
+
+    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);
+    }
+
+    __SettingsFree(DestinationValueName);
+
+done:
+    return STATUS_SUCCESS;
+
+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
+    )
+{
+    const CHAR      *Path;
+    HANDLE          Key;
+    ULONG           ValuePrefixLength;
+    PCHAR           ValuePrefix;
+    const CHAR      *SaveKeyName;
+    HANDLE          SaveKey;
+    NTSTATUS        status;
+
+    Trace("====>\n");
+
+    ASSERT(Version == 4 || Version == 6);
+    Path = (Version == 4) ? IPV4_PATH : IPV6_PATH;
+
+    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;
+    }
+
+    ValuePrefixLength = (ULONG)(((sizeof (NET_LUID) * 2) +
+                                 1) * sizeof (CHAR));
+
+    ValuePrefix = __SettingsAllocate(ValuePrefixLength);
+
+    status = STATUS_NO_MEMORY;
+    if (ValuePrefix == NULL)
+        goto fail1;
+
+    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);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    if (Save) {
+        SETTINGS_IP_ADDRESSES_COPY_PARAMETERS   Parameters;
+
+        Parameters.Version = Version;
+        Parameters.SourceValuePrefix = ValuePrefix;
+        Parameters.DestinationKey = SaveKey;
+        Parameters.DestinationValuePrefix = "LUID";
+
+        status = RegistryEnumerateValues(Key,
+                                         SettingsCopyIpAddressesValue,
+                                         &Parameters);
+    } else { // Restore
+        SETTINGS_IP_ADDRESSES_COPY_PARAMETERS   Parameters;
+
+        Parameters.Version = Version;
+        Parameters.SourceValuePrefix = "LUID";
+        Parameters.DestinationKey = Key;
+        Parameters.DestinationValuePrefix = ValuePrefix;
+
+        status = RegistryEnumerateValues(SaveKey,
+                                         SettingsCopyIpAddressesValue,
+                                         &Parameters);
+    }
+
+    RegistryCloseKey(SaveKey);
+
+    if (!Save)
+        (VOID) RegistryDeleteSubKey(SettingsKey, (PCHAR)SaveKeyName);
+
+    __SettingsFree(ValuePrefix);
+
+    RegistryCloseKey(Key);
+
+done:
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail2:
+    Error("fail2\n");
+
+    __SettingsFree(ValuePrefix);
+
+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
+     )
+{
+    HANDLE          SettingsKey;
+    NTSTATUS        status;
+
+    Info("FROM %ws (%ws)\n", Alias, Description);
+
+    status = RegistryCreateSubKey(SoftwareKey,
+                                  "Settings",
+                                  REG_OPTION_NON_VOLATILE,
+                                  &SettingsKey);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    SettingsCopy(SettingsKey, InterfaceGuid, InterfaceLuid, TRUE);
+
+    RegistryCloseKey(SettingsKey);
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1\n", status);
+
+    return status;
+}
+
+NTSTATUS
+SettingsRestore(
+     IN HANDLE      SoftwareKey,
+     IN PWCHAR      Alias,
+     IN PWCHAR      Description,
+     IN LPGUID      InterfaceGuid,
+     IN PNET_LUID   InterfaceLuid
+     )
+{
+    HANDLE          SettingsKey;
+    NTSTATUS        status;
+
+    status = RegistryOpenSubKey(SoftwareKey,
+                                "Settings",
+                                KEY_ALL_ACCESS,
+                                &SettingsKey);
+    if (!NT_SUCCESS(status)) {
+        if (status == STATUS_OBJECT_NAME_NOT_FOUND)
+            goto done;
+
+        goto fail1;
+    }
+
+    Info("TO %ws (%ws)\n", Alias, Description);
+
+    SettingsCopy(SettingsKey, InterfaceGuid, InterfaceLuid, FALSE);
+
+    RegistryCloseKey(SettingsKey);
+
+    (VOID) RegistryDeleteSubKey(SoftwareKey, "Settings");
+
+done:
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1\n", status);
+
+    return status;
+}
diff --git a/src/xenvif/settings.h b/src/xenvif/settings.h
new file mode 100644 (file)
index 0000000..7bd1824
--- /dev/null
@@ -0,0 +1,53 @@
+/* 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_SETTINGS_H
+#define _XENVIF_SETTINGS_H
+
+extern NTSTATUS
+SettingsSave(
+     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
+     );
+
+#endif  // _XENVIF_SETTINGS_H
index 2c24e1216ae8b74a21e0409009d709f678d484f3..170ab53120d70b0fbf9e94a30ddb188d7ae93f0b 100644 (file)
@@ -77,6 +77,7 @@
     <ClCompile Include="../../src/xenvif/pdo.c" />
     <ClCompile Include="../../src/xenvif/receiver.c" />
     <ClCompile Include="../../src/xenvif/registry.c" />
+    <ClCompile Include="../../src/xenvif/settings.c" />
     <ClCompile Include="../../src/xenvif/thread.c" />
     <ClCompile Include="../../src/xenvif/transmitter.c" />
     <ClCompile Include="../../src/xenvif/controller.c" />
index b1319cd48c8322f332e9c6c1209b87a2360234eb..9d1dba3641944f0676fbeac9684e147edd63d347 100644 (file)
@@ -80,6 +80,7 @@
     <ClCompile Include="../../src/xenvif/pdo.c" />
     <ClCompile Include="../../src/xenvif/receiver.c" />
     <ClCompile Include="../../src/xenvif/registry.c" />
+    <ClCompile Include="../../src/xenvif/settings.c" />
     <ClCompile Include="../../src/xenvif/thread.c" />
     <ClCompile Include="../../src/xenvif/transmitter.c" />
     <ClCompile Include="../../src/xenvif/controller.c" />