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

[win-pv-devel] [PATCH] Re-work monitor service registry keys



Instead of using the monitor service key directly to place reboot
requests, use a key under HKLM\SOFTWARE. This is a better place to handle
interactions between separate PV driver packages.

Also, give the monitor service a description and add a parameter to control
the reboot prompt dialog timeout.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 src/coinst/coinst.c   |   3 +-
 src/monitor/monitor.c | 277 ++++++++++++++++++++++++++++++++++++++++----------
 src/xenbus.inf        |  30 ++++--
 src/xenbus/driver.c   | 103 +++++++++++--------
 4 files changed, 304 insertions(+), 109 deletions(-)

diff --git a/src/coinst/coinst.c b/src/coinst/coinst.c
index 1241ad1..f09e548 100644
--- a/src/coinst/coinst.c
+++ b/src/coinst/coinst.c
@@ -1371,7 +1371,8 @@ MonitorDelete(
                              SERVICE_CONTROL_STOP,
                              &Status);
 
-    if (!Success)
+    if (!Success &&
+        GetLastError() != ERROR_SERVICE_NOT_ACTIVE)
         goto fail3;
 
     Success = DeleteService(Service);
diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c
index 739aaff..e2e8e20 100644
--- a/src/monitor/monitor.c
+++ b/src/monitor/monitor.c
@@ -48,6 +48,7 @@
 typedef struct _MONITOR_CONTEXT {
     SERVICE_STATUS          Status;
     SERVICE_STATUS_HANDLE   Service;
+    HKEY                    ParametersKey;
     HANDLE                  EventLog;
     HANDLE                  StopEvent;
     HANDLE                  RequestEvent;
@@ -62,10 +63,10 @@ MONITOR_CONTEXT MonitorContext;
 #define SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services"
 
 #define SERVICE_KEY(_Service) \
-        SERVICES_KEY ## "\\" ## #_Service
+        SERVICES_KEY ## "\\" ## _Service
 
-#define REQUEST_KEY \
-        SERVICE_KEY(XENBUS_MONITOR) ## "\\Request"
+#define PARAMETERS_KEY(_Service) \
+        SERVICE_KEY(_Service) ## "\\Parameters"
 
 static VOID
 #pragma prefast(suppress:6262) // Function uses '1036' bytes of stack: exceeds 
/analyze:stacksize'1024'
@@ -305,6 +306,34 @@ DoReboot(
                                     SHTDN_REASON_FLAG_PLANNED);
 }
 
+static DWORD
+GetPromptTimeout(
+    VOID
+    )
+{
+    PMONITOR_CONTEXT    Context = &MonitorContext;
+    DWORD               Type;
+    DWORD               Value;
+    DWORD               ValueLength;
+    HRESULT             Error;
+
+    ValueLength = sizeof (Value);
+
+    Error = RegQueryValueEx(Context->ParametersKey,
+                            "PromptTimeout",
+                            NULL,
+                            &Type,
+                            (LPBYTE)&Value,
+                            &ValueLength);
+    if (Error != ERROR_SUCCESS ||
+        Type != REG_DWORD)
+        Value = 0;
+
+    Log("%u", Value);
+
+    return Value;
+}
+
 static VOID
 PromptForReboot(
     IN PTCHAR           DriverName
@@ -419,6 +448,7 @@ PromptForReboot(
         DWORD                   SessionId = SessionInfo[Index].SessionId;
         PTCHAR                  Name = SessionInfo[Index].pWinStationName;
         WTS_CONNECTSTATE_CLASS  State = SessionInfo[Index].State;
+        DWORD                   Timeout;
         DWORD                   Response;
 
         Log("[%u]: %s [%s]",
@@ -429,6 +459,8 @@ PromptForReboot(
         if (State != WTSActive)
             continue;
 
+        Timeout = GetPromptTimeout();
+
         Success = WTSSendMessage(WTS_CURRENT_SERVER_HANDLE,
                                  SessionId,
                                  Title,
@@ -436,7 +468,7 @@ PromptForReboot(
                                  Message,
                                  sizeof (Message),
                                  MB_YESNO | MB_ICONEXCLAMATION,
-                                 0,
+                                 Timeout,
                                  &Response,
                                  TRUE);
 
@@ -445,7 +477,7 @@ PromptForReboot(
 
         Context->RebootPending = TRUE;
 
-        if (Response == IDYES)
+        if (Response == IDYES || Response == IDTIMEOUT)
             DoReboot();
 
         break;
@@ -500,16 +532,18 @@ fail1:
 }
 
 static VOID
-CheckRebootValue(
+CheckRequestSubKeys(
     VOID
     )
 {
     PMONITOR_CONTEXT    Context = &MonitorContext;
+    DWORD               SubKeys;
+    DWORD               MaxSubKeyLength;
+    DWORD               SubKeyLength;
+    PTCHAR              SubKeyName;
+    DWORD               Index;
+    HKEY                SubKey;
     HRESULT             Error;
-    DWORD               MaxValueLength;
-    DWORD               RebootLength;
-    PTCHAR              Reboot;
-    DWORD               Type;
 
     Log("====>");
 
@@ -517,64 +551,93 @@ CheckRebootValue(
                             NULL,
                             NULL,
                             NULL,
+                            &SubKeys,
+                            &MaxSubKeyLength,
                             NULL,
                             NULL,
                             NULL,
                             NULL,
                             NULL,
-                            &MaxValueLength,
-                            NULL,
                             NULL);
     if (Error != ERROR_SUCCESS) {
         SetLastError(Error);
         goto fail1;
     }
 
-    RebootLength = MaxValueLength + sizeof (TCHAR);
+    SubKeyLength = MaxSubKeyLength + sizeof (TCHAR);
 
-    Reboot = calloc(1, RebootLength);
-    if (Reboot == NULL)
+    SubKeyName = calloc(1, SubKeyLength);
+    if (SubKeyName == NULL)
         goto fail2;
 
-    Error = RegQueryValueEx(Context->RequestKey,
-                            "Reboot",
-                            NULL,
-                            &Type,
-                            (LPBYTE)Reboot,
-                            &RebootLength);
-    if (Error != ERROR_SUCCESS) {
-        if (Error == ERROR_FILE_NOT_FOUND)
-            goto done;
+    for (Index = 0; Index < SubKeys; Index++) {
+        DWORD   Length;
+        DWORD   Type;
+        DWORD   Reboot;
+
+        SubKeyLength = MaxSubKeyLength + sizeof (TCHAR);
+        memset(SubKeyName, 0, SubKeyLength);
+
+        Error = RegEnumKeyEx(Context->RequestKey,
+                             Index,
+                             (LPTSTR)SubKeyName,
+                             &SubKeyLength,
+                             NULL,
+                             NULL,
+                             NULL,
+                             NULL);
+        if (Error != ERROR_SUCCESS) {
+            SetLastError(Error);
+            goto fail3;
+        }
 
-        SetLastError(Error);
-        goto fail3;
-    }
+        Log("%s", SubKeyName);
 
-    if (Type != REG_SZ) {
-        SetLastError(ERROR_BAD_FORMAT);
-        goto fail4;
+        Error = RegOpenKeyEx(Context->RequestKey,
+                             SubKeyName,
+                             0,
+                             KEY_READ,
+                             &SubKey);
+        if (Error != ERROR_SUCCESS)
+            continue;
+
+        Length = sizeof (DWORD);
+        Error = RegQueryValueEx(SubKey,
+                                "Reboot",
+                                NULL,
+                                &Type,
+                                (LPBYTE)&Reboot,
+                                &Length);
+        if (Error != ERROR_SUCCESS ||
+            Type != REG_DWORD)
+            goto loop;
+
+        if (Reboot != 0)
+            goto found;
+
+loop:
+        RegCloseKey(SubKey);
     }
 
-    if (!Context->RebootPending)
-        PromptForReboot(Reboot);
+    goto done;
 
-    if (Context->RebootPending)
-        (VOID) RegDeleteValue(Context->RequestKey, "Reboot");
+found:
+    RegCloseKey(SubKey);
+
+    if (!Context->RebootPending)
+        PromptForReboot(SubKeyName);
 
 done:
-    free(Reboot);
+    free(SubKeyName);
 
     Log("<====");
 
     return;
 
-fail4:
-    Log("fail4");
-
 fail3:
     Log("fail3");
 
-    free(Reboot);
+    free(SubKeyName);
 
 fail2:
     Log("fail2");
@@ -600,7 +663,7 @@ CheckRequestKey(
 
     Log("====>");
 
-    CheckRebootValue();
+    CheckRequestSubKeys();
 
     Error = RegNotifyChangeKeyValue(Context->RequestKey,
                                     TRUE,
@@ -693,6 +756,84 @@ fail1:
     return FALSE;
 }
 
+static BOOL
+GetRequestKeyName(
+    OUT PTCHAR          *RequestKeyName
+    )
+{
+    PMONITOR_CONTEXT    Context = &MonitorContext;
+    DWORD               MaxValueLength;
+    DWORD               RequestKeyNameLength;
+    DWORD               Type;
+    HRESULT             Error;
+
+    Error = RegQueryInfoKey(Context->ParametersKey,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            NULL,
+                            &MaxValueLength,
+                            NULL,
+                            NULL);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail1;
+    }
+
+    RequestKeyNameLength = MaxValueLength + sizeof (TCHAR);
+
+    *RequestKeyName = calloc(1, RequestKeyNameLength);
+    if (RequestKeyName == NULL)
+        goto fail2;
+
+    Error = RegQueryValueEx(Context->ParametersKey,
+                            "RequestKey",
+                            NULL,
+                            &Type,
+                            (LPBYTE)(*RequestKeyName),
+                            &RequestKeyNameLength);
+    if (Error != ERROR_SUCCESS) {
+        SetLastError(Error);
+        goto fail3;
+    }
+
+    if (Type != REG_SZ) {
+        SetLastError(ERROR_BAD_FORMAT);
+        goto fail4;
+    }
+
+    Log("%s", *RequestKeyName);
+
+    return TRUE;
+
+fail4:
+    Log("fail4");
+
+fail3:
+    Log("fail3");
+
+    free(*RequestKeyName);
+
+fail2:
+    Log("fail2");
+
+fail1:
+    Error = GetLastError();
+
+    {
+        PTCHAR  Message;
+        Message = GetErrorMessage(Error);
+        Log("fail1 (%s)", Message);
+        LocalFree(Message);
+    }
+
+    return FALSE;
+}
+
 VOID WINAPI
 MonitorMain(
     _In_    DWORD       argc,
@@ -700,6 +841,7 @@ MonitorMain(
     )
 {
     PMONITOR_CONTEXT    Context = &MonitorContext;
+    PTCHAR              RequestKeyName;
     BOOL                Success;
     HRESULT             Error;
 
@@ -708,21 +850,28 @@ MonitorMain(
 
     Log("====>");
 
-    Success = AcquireShutdownPrivilege();
+    Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                         PARAMETERS_KEY(__MODULE__),
+                         0,
+                         KEY_READ,
+                         &Context->ParametersKey);
+    if (Error != ERROR_SUCCESS)
+        goto fail1;
 
+    Success = AcquireShutdownPrivilege();
     if (!Success)
-        goto fail1;
+        goto fail2;
 
     Context->Service = RegisterServiceCtrlHandlerEx(MONITOR_NAME,
                                                     MonitorCtrlHandlerEx,
                                                     NULL);
     if (Context->Service == NULL)
-        goto fail2;
+        goto fail3;
 
     Context->EventLog = RegisterEventSource(NULL,
                                             MONITOR_NAME);
     if (Context->EventLog == NULL)
-        goto fail3;
+        goto fail4;
 
     Context->Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
     Context->Status.dwServiceSpecificExitCode = 0;
@@ -735,24 +884,26 @@ MonitorMain(
                                      NULL);
 
     if (Context->StopEvent == NULL)
-        goto fail4;
+        goto fail5;
 
     Context->RequestEvent = CreateEvent(NULL,
                                         TRUE,
                                         FALSE,
                                         NULL);
-
     if (Context->RequestEvent == NULL)
-        goto fail5;
+        goto fail6;
+
+    Success = GetRequestKeyName(&RequestKeyName);
+    if (!Success)
+        goto fail7;
 
     Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                         REQUEST_KEY,
+                         RequestKeyName,
                          0,
                          KEY_ALL_ACCESS,
                          &Context->RequestKey);
-
     if (Error != ERROR_SUCCESS)
-        goto fail6;
+        goto fail8;
 
     SetEvent(Context->RequestEvent);
 
@@ -788,6 +939,8 @@ MonitorMain(
     }
 
 done:
+    (VOID) RegDeleteTree(Context->RequestKey, NULL);
+
     CloseHandle(Context->RequestKey);
     CloseHandle(Context->RequestEvent);
     CloseHandle(Context->StopEvent);
@@ -796,33 +949,45 @@ done:
 
     (VOID) DeregisterEventSource(Context->EventLog);
 
+    CloseHandle(Context->ParametersKey);
+
     Log("<====");
 
     return;
 
-fail6:
-    Log("fail6");
+fail8:
+    Log("fail8");
 
-    ReportStatus(SERVICE_STOPPED, GetLastError(), 0);
+    free(RequestKeyName);
+
+fail7:
+    Log("fail7");
 
     CloseHandle(Context->RequestEvent);
 
+fail6:
+    Log("fail6");
+
+    CloseHandle(Context->StopEvent);
+
 fail5:
     Log("fail5");
 
-    CloseHandle(Context->StopEvent);
+    ReportStatus(SERVICE_STOPPED, GetLastError(), 0);
+
+    (VOID) DeregisterEventSource(Context->EventLog);
 
 fail4:
     Log("fail4");
 
-    (VOID) DeregisterEventSource(Context->EventLog);
-
 fail3:
     Log("fail3");
 
 fail2:
     Log("fail2");
 
+    CloseHandle(Context->ParametersKey);
+
 fail1:
     Error = GetLastError();
 
diff --git a/src/xenbus.inf b/src/xenbus.inf
index 0b65e00..dc4e71d 100644
--- a/src/xenbus.inf
+++ b/src/xenbus.inf
@@ -72,9 +72,9 @@ 
xenbus_monitor_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dl
 ; DisplayName          Section         DeviceID
 ; -----------          -------         --------
 
-%XenBusDesc%           =XenBus_Inst,   
PCI\VEN_5853&DEV_@VENDOR_DEVICE_ID@&SUBSYS_@VENDOR_DEVICE_ID@5853&REV_01
-%XenBusDesc%           =XenBus_Inst,   PCI\VEN_5853&DEV_0002
-%XenBusDesc%           =XenBus_Inst,   PCI\VEN_5853&DEV_0001
+%XenBusName%           =XenBus_Inst,   
PCI\VEN_5853&DEV_@VENDOR_DEVICE_ID@&SUBSYS_@VENDOR_DEVICE_ID@5853&REV_01
+%XenBusName%           =XenBus_Inst,   PCI\VEN_5853&DEV_0002
+%XenBusName%           =XenBus_Inst,   PCI\VEN_5853&DEV_0001
 
 [XenBus_Inst] 
 CopyFiles=XenBus_CopyFiles
@@ -86,7 +86,7 @@ AddService=xenbus,%SPSVCINST_ASSOCSERVICE%,XenBus_Service
 AddService=xenfilt,,XenFilt_Service,
 
 [XenBus_Service] 
-DisplayName=%XenBusDesc%
+DisplayName=%XenBusName%
 ServiceType=%SERVICE_KERNEL_DRIVER% 
 StartType=%SERVICE_BOOT_START% 
 ErrorControl=%SERVICE_ERROR_NORMAL% 
@@ -98,6 +98,7 @@ AddReg = XenBus_Parameters, XenBus_Interrupts
 HKR,"Parameters",,0x00000010
 HKR,"Parameters","SupportedClasses",0x00010000,"VIF","VBD","IFACE"
 HKR,"Parameters","SyntheticClasses",0x00010000,"IFACE"
+HKR,"Parameters","RequestKey",0x00000000,%RequestKey%
 
 [XenBus_Interrupts]
 HKR,"Interrupt Management",,0x00000010
@@ -106,7 +107,7 @@ HKR,"Interrupt 
Management\MessageSignaledInterruptProperties","MSISupported",0x0
 HKR,"Interrupt Management\GroupPolicy",,0x00010001,1
 
 [XenFilt_Service] 
-DisplayName=%XenFiltDesc%
+DisplayName=%XenFiltName%
 ServiceType=%SERVICE_KERNEL_DRIVER% 
 StartType=%SERVICE_BOOT_START% 
 ErrorControl=%SERVICE_ERROR_NORMAL% 
@@ -120,15 +121,20 @@ HKR,"Parameters","ACPI\PNP0A03",0x00000000,"DEVICE"
 HKR,"Parameters","PCIIDE\IDEChannel",0x00000000,"DISK"
 
 [Monitor_Service]
-DisplayName=%MonitorDesc%
+DisplayName=%MonitorName%
+Description=%MonitorDesc%
 ServiceType=%SERVICE_WIN32_OWN_PROCESS%
 StartType=%SERVICE_AUTO_START%
 ErrorControl=%SERVICE_ERROR_NORMAL%
 
ServiceBinary=%11%\xenbus_monitor_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.exe
-AddReg = Monitor_Request
+AddReg = Monitor_Parameters, Monitor_Request
+
+[Monitor_Parameters]
+HKR,"Parameters",,0x00000010
+HKR,"Parameters","RequestKey",0x00000000,%RequestKey%
 
 [Monitor_Request]
-HKR,"Request",,0x00000010
+HKLM,%RequestKey% ,,0x00000010
 
 [Monitor_EventLog]
 AddReg=Monitor_EventLog_AddReg
@@ -148,9 +154,11 @@ 
HKR,,CoInstallers32,0x00010000,"xenbus_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@M
 
 Vendor="@VENDOR_NAME@" 
 DiskDesc="@PRODUCT_NAME@ PV Bus Package" 
-XenBusDesc="@PRODUCT_NAME@ PV Bus"
-XenFiltDesc="@PRODUCT_NAME@ Generic Bus Filter"
-MonitorDesc="@PRODUCT_NAME@ PV Driver Monitor"
+XenBusName="@PRODUCT_NAME@ PV Bus"
+XenFiltName="@PRODUCT_NAME@ Generic Bus Filter"
+MonitorName="@PRODUCT_NAME@ PV Driver Monitor"
+MonitorDesc="Provides support for @PRODUCT_NAME@ PV drivers"
+RequestKey="SOFTWARE\@VENDOR_NAME@\@PRODUCT_NAME@\PV Driver Monitor\Request"
 
 SERVICE_BOOT_START=0x0 
 SERVICE_SYSTEM_START=0x1 
diff --git a/src/xenbus/driver.c b/src/xenbus/driver.c
index 31388be..4360edc 100644
--- a/src/xenbus/driver.c
+++ b/src/xenbus/driver.c
@@ -122,55 +122,78 @@ DriverGetParametersKey(
     return __DriverGetParametersKey();
 }
 
-#define SERVICES_PATH 
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services"
-
-#define SERVICE_KEY(_Name) \
-        SERVICES_PATH ## "\\" ## #_Name
-
-#define REQUEST_KEY \
-        SERVICE_KEY(XENBUS_MONITOR) ## "\\Request"
+#define MAXNAMELEN  128
 
 static FORCEINLINE VOID
 __DriverRequestReboot(
     VOID
     )
 {
-    HANDLE      RequestKey;
-    ANSI_STRING Ansi[2];
-    NTSTATUS    status;
+    PANSI_STRING    Ansi;
+    CHAR            RequestKeyName[MAXNAMELEN];
+    HANDLE          RequestKey;
+    HANDLE          SubKey;
+    NTSTATUS        status;
 
     Info("====>\n");
 
     ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
 
+    status = RegistryQuerySzValue(__DriverGetParametersKey(),
+                                  "RequestKey",
+                                  NULL,
+                                  &Ansi);
+    if (!NT_SUCCESS(status))
+        goto fail1;
+
+    status = RtlStringCbPrintfA(RequestKeyName,
+                                MAXNAMELEN,
+                                "\\Registry\\Machine\\%Z",
+                                &Ansi[0]);
+    ASSERT(NT_SUCCESS(status));
+
     status = RegistryOpenSubKey(NULL,
-                                REQUEST_KEY,
+                                RequestKeyName,
                                 KEY_ALL_ACCESS,
                                 &RequestKey);
     if (!NT_SUCCESS(status))
-        goto fail1;
-
-    RtlZeroMemory(Ansi, sizeof (Ansi));
+        goto fail2;
 
-    RtlInitAnsiString(&Ansi[0], "XENBUS");
+    status = RegistryCreateSubKey(RequestKey,
+                                  __MODULE__,
+                                  REG_OPTION_NON_VOLATILE,
+                                  &SubKey);
+    if (!NT_SUCCESS(status))
+        goto fail3;
 
-    status = RegistryUpdateSzValue(RequestKey,
-                                   "Reboot",
-                                   REG_SZ,
-                                   Ansi);
+    status = RegistryUpdateDwordValue(SubKey,
+                                      "Reboot",
+                                      1);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail4;
 
-    RegistryCloseKey(RequestKey);
+    RegistryCloseKey(SubKey);
+
+    RegistryFreeSzValue(Ansi);
 
     Info("<====\n");
 
     return;
 
+fail4:
+    Error("fail4\n");
+
+    RegistryCloseKey(SubKey);
+
+fail3:
+    Error("fail3\n");
+
+    RegistryCloseKey(RequestKey);
+
 fail2:
     Error("fail2\n");
 
-    RegistryCloseKey(RequestKey);
+    RegistryFreeSzValue(Ansi);
 
 fail1:
     Error("fail1 (%08x)\n", status);
@@ -681,35 +704,35 @@ DriverEntry(
          MONTH,
          YEAR);
 
-    status = XenTouch(__MODULE__,
-                      MAJOR_VERSION,
-                      MINOR_VERSION,
-                      MICRO_VERSION,
-                      BUILD_NUMBER);
-    if (!NT_SUCCESS(status)) {
-        __DriverRequestReboot();
-        goto fail1;
-    }
-
     status = RegistryInitialize(RegistryPath);
     if (!NT_SUCCESS(status))
-        goto fail2;
+        goto fail1;
 
     status = RegistryOpenServiceKey(KEY_READ, &ServiceKey);
     if (!NT_SUCCESS(status))
-        goto fail3;
+        goto fail2;
 
     status = RegistryOpenSubKey(ServiceKey,
                                 "Parameters",
                                 KEY_READ,
                                 &ParametersKey);
     if (!NT_SUCCESS(status))
-        goto fail4;
+        goto fail3;
 
     __DriverSetParametersKey(ParametersKey);
 
     RegistryCloseKey(ServiceKey);
 
+    status = XenTouch(__MODULE__,
+                      MAJOR_VERSION,
+                      MINOR_VERSION,
+                      MICRO_VERSION,
+                      BUILD_NUMBER);
+    if (!NT_SUCCESS(status)) {
+        __DriverRequestReboot();
+        goto done;
+    }
+
     DriverObject->DriverExtension->AddDevice = DriverAddDevice;
 
     for (Index = 0; Index <= IRP_MJ_MAXIMUM_FUNCTION; Index++) {
@@ -718,6 +741,7 @@ DriverEntry(
        DriverObject->MajorFunction[Index] = DriverDispatch;
     }
 
+done:
     InitializeMutex(&Driver.Mutex);
     InitializeListHead(&Driver.List);
     Driver.References = 1;
@@ -726,19 +750,16 @@ DriverEntry(
 
     return STATUS_SUCCESS;
 
-fail4:
-    Error("fail4\n");
-
-    RegistryCloseKey(ServiceKey);
-
 fail3:
     Error("fail3\n");
 
-    RegistryTeardown();
+    RegistryCloseKey(ServiceKey);
 
 fail2:
     Error("fail2\n");
 
+    RegistryTeardown();
+
 fail1:
     Error("fail1 (%08x)\n", status);
 
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
https://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®.