|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |