SERVICE_CONTROL_STOP,
&Status);
- if (!Success)
+ if (!Success &&
+ GetLastError() != ERROR_SERVICE_NOT_ACTIVE)
goto fail3;
Success = DeleteService(Service);
typedef struct _MONITOR_CONTEXT {
SERVICE_STATUS Status;
SERVICE_STATUS_HANDLE Service;
+ HKEY ParametersKey;
HANDLE EventLog;
HANDLE StopEvent;
HANDLE RequestEvent;
#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'
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
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]",
if (State != WTSActive)
continue;
+ Timeout = GetPromptTimeout();
+
Success = WTSSendMessage(WTS_CURRENT_SERVER_HANDLE,
SessionId,
Title,
Message,
sizeof (Message),
MB_YESNO | MB_ICONEXCLAMATION,
- 0,
+ Timeout,
&Response,
TRUE);
Context->RebootPending = TRUE;
- if (Response == IDYES)
+ if (Response == IDYES || Response == IDTIMEOUT)
DoReboot();
break;
}
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("====>");
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");
Log("====>");
- CheckRebootValue();
+ CheckRequestSubKeys();
Error = RegNotifyChangeKeyValue(Context->RequestKey,
TRUE,
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,
)
{
PMONITOR_CONTEXT Context = &MonitorContext;
+ PTCHAR RequestKeyName;
BOOL Success;
HRESULT Error;
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;
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);
}
done:
+ (VOID) RegDeleteTree(Context->RequestKey, NULL);
+
CloseHandle(Context->RequestKey);
CloseHandle(Context->RequestEvent);
CloseHandle(Context->StopEvent);
(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();
; 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
AddService=xenfilt,,XenFilt_Service,
[XenBus_Service]
-DisplayName=%XenBusDesc%
+DisplayName=%XenBusName%
ServiceType=%SERVICE_KERNEL_DRIVER%
StartType=%SERVICE_BOOT_START%
ErrorControl=%SERVICE_ERROR_NORMAL%
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
HKR,"Interrupt Management\GroupPolicy",,0x00010001,1
[XenFilt_Service]
-DisplayName=%XenFiltDesc%
+DisplayName=%XenFiltName%
ServiceType=%SERVICE_KERNEL_DRIVER%
StartType=%SERVICE_BOOT_START%
ErrorControl=%SERVICE_ERROR_NORMAL%
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
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
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);
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++) {
DriverObject->MajorFunction[Index] = DriverDispatch;
}
+done:
InitializeMutex(&Driver.Mutex);
InitializeListHead(&Driver.List);
Driver.References = 1;
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);