From: Paul Durrant Date: Fri, 5 May 2017 14:45:06 +0000 (+0100) Subject: Add a monitor service X-Git-Tag: 9.0.0-rc1~49 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=efc67ede23ae37aee463745c011f2890bb60f641;p=pvdrivers%2Fwin%2Fxencons.git Add a monitor service This patch adds a basic service to monitor the xencons interface. All it does is open the interface when it becomes available and close it down when either the device is going away, or the service is being stopped. Signed-off-by: Paul Durrant --- diff --git a/src/coinst/coinst.c b/src/coinst/coinst.c index 26c07f4..1a2343b 100644 --- a/src/coinst/coinst.c +++ b/src/coinst/coinst.c @@ -43,6 +43,8 @@ __user_code; #define MAXIMUM_BUFFER_SIZE 1024 +#define MONITOR_NAME "XENCONS_MONITOR" + static VOID #pragma prefast(suppress:6262) // Function uses '1036' bytes of stack: exceeds /analyze:stacksize'1024' __Log( @@ -172,6 +174,79 @@ __FunctionName( #undef _NAME } +static BOOL +MonitorDelete( + VOID + ) +{ + SC_HANDLE SCManager; + SC_HANDLE Service; + BOOL Success; + SERVICE_STATUS Status; + HRESULT Error; + + Log("====>"); + + SCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_ALL_ACCESS); + + if (SCManager == NULL) + goto fail1; + + Service = OpenService(SCManager, + MONITOR_NAME, + SERVICE_ALL_ACCESS); + + if (Service == NULL) + goto fail2; + + Success = ControlService(Service, + SERVICE_CONTROL_STOP, + &Status); + + if (!Success && + GetLastError() != ERROR_SERVICE_NOT_ACTIVE) + goto fail3; + + Success = DeleteService(Service); + + if (!Success) + goto fail4; + + CloseServiceHandle(Service); + CloseServiceHandle(SCManager); + + Log("<===="); + + return TRUE; + +fail4: + Log("fail4"); + +fail3: + Log("fail3"); + + CloseServiceHandle(Service); + +fail2: + Log("fail2"); + + CloseServiceHandle(SCManager); + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } + + return FALSE; +} + static HRESULT DifInstallPreProcess( IN HDEVINFO DeviceInfoSet, @@ -271,7 +346,11 @@ DifRemovePreProcess( UNREFERENCED_PARAMETER(DeviceInfoData); UNREFERENCED_PARAMETER(Context); - Log("<===>"); + Log("====>"); + + (VOID) MonitorDelete(); + + Log("<===="); return NO_ERROR; } diff --git a/src/monitor/messages.mc b/src/monitor/messages.mc new file mode 100644 index 0000000..9fff135 --- /dev/null +++ b/src/monitor/messages.mc @@ -0,0 +1,54 @@ +; // 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. + +MessageIdTypedef=DWORD + +SeverityNames=( + Success=0x0:STATUS_SEVERITY_SUCCESS + Informational=0x1:STATUS_SEVERITY_INFORMATIONAL + Warning=0x2:STATUS_SEVERITY_WARNING + Error=0x3:STATUS_SEVERITY_ERROR + ) + + +FacilityNames=( + System=0x0:FACILITY_SYSTEM + Runtime=0x2:FACILITY_RUNTIME + Stubs=0x3:FACILITY_STUBS + Io=0x4:FACILITY_IO_ERROR_CODE + ) + +MessageId=0x1 +Severity=Informational +Facility=System +SymbolicName=MONITOR_LOG +Language=English +%1 +. diff --git a/src/monitor/monitor.c b/src/monitor/monitor.c new file mode 100644 index 0000000..fabca77 --- /dev/null +++ b/src/monitor/monitor.c @@ -0,0 +1,916 @@ +/* Copyright (c) Citrix Systems Inc. + * All rights reserved. + * + * Redistribution and use in source 1and 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 the23 + * 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. + */ + +#define INITGUID 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "messages.h" + +#define MONITOR_NAME __MODULE__ +#define MONITOR_DISPLAYNAME MONITOR_NAME + +typedef struct _MONITOR_CONTEXT { + SERVICE_STATUS Status; + SERVICE_STATUS_HANDLE Service; + HKEY ParametersKey; + HANDLE EventLog; + HANDLE StopEvent; + HANDLE AddEvent; + HANDLE RemoveEvent; + HDEVNOTIFY InterfaceNotification; + PTCHAR DevicePath; + HDEVNOTIFY DeviceNotification; + HANDLE Device; +} MONITOR_CONTEXT, *PMONITOR_CONTEXT; + +MONITOR_CONTEXT MonitorContext; + +#define MAXIMUM_BUFFER_SIZE 1024 + +#define SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services" + +#define SERVICE_KEY(_Service) \ + SERVICES_KEY ## "\\" ## _Service + +#define PARAMETERS_KEY(_Service) \ + SERVICE_KEY(_Service) ## "\\Parameters" + +static VOID +#pragma prefast(suppress:6262) // Function uses '1036' bytes of stack: exceeds /analyze:stacksize'1024' +__Log( + IN const CHAR *Format, + IN ... + ) +{ +#if DBG + PMONITOR_CONTEXT Context = &MonitorContext; + const TCHAR *Strings[1]; +#endif + TCHAR Buffer[MAXIMUM_BUFFER_SIZE]; + va_list Arguments; + size_t Length; + HRESULT Result; + + va_start(Arguments, Format); + Result = StringCchVPrintf(Buffer, + MAXIMUM_BUFFER_SIZE, + Format, + Arguments); + va_end(Arguments); + + if (Result != S_OK && Result != STRSAFE_E_INSUFFICIENT_BUFFER) + return; + + Result = StringCchLength(Buffer, MAXIMUM_BUFFER_SIZE, &Length); + if (Result != S_OK) + return; + + Length = __min(MAXIMUM_BUFFER_SIZE - 1, Length + 2); + + __analysis_assume(Length < MAXIMUM_BUFFER_SIZE); + __analysis_assume(Length >= 2); + Buffer[Length] = '\0'; + Buffer[Length - 1] = '\n'; + Buffer[Length - 2] = '\r'; + + OutputDebugString(Buffer); + +#if DBG + Strings[0] = Buffer; + + if (Context->EventLog != NULL) + ReportEvent(Context->EventLog, + EVENTLOG_INFORMATION_TYPE, + 0, + MONITOR_LOG, + NULL, + ARRAYSIZE(Strings), + 0, + Strings, + NULL); +#endif +} + +#define Log(_Format, ...) \ + __Log(TEXT(__MODULE__ "|" __FUNCTION__ ": " _Format), __VA_ARGS__) + +static PTCHAR +GetErrorMessage( + IN HRESULT Error + ) +{ + PTCHAR Message; + ULONG Index; + + if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + Error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&Message, + 0, + NULL)) + return NULL; + + for (Index = 0; Message[Index] != '\0'; Index++) { + if (Message[Index] == '\r' || Message[Index] == '\n') { + Message[Index] = '\0'; + break; + } + } + + return Message; +} + +static const CHAR * +ServiceStateName( + IN DWORD State + ) +{ +#define _STATE_NAME(_State) \ + case SERVICE_ ## _State: \ + return #_State + + switch (State) { + _STATE_NAME(START_PENDING); + _STATE_NAME(RUNNING); + _STATE_NAME(STOP_PENDING); + _STATE_NAME(STOPPED); + default: + break; + } + + return "UNKNOWN"; + +#undef _STATE_NAME +} + +static VOID +ReportStatus( + IN DWORD CurrentState, + IN DWORD Win32ExitCode, + IN DWORD WaitHint) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + static DWORD CheckPoint = 1; + BOOL Success; + HRESULT Error; + + Log("====> (%s)", ServiceStateName(CurrentState)); + + Context->Status.dwCurrentState = CurrentState; + Context->Status.dwWin32ExitCode = Win32ExitCode; + Context->Status.dwWaitHint = WaitHint; + + if (CurrentState == SERVICE_START_PENDING) + Context->Status.dwControlsAccepted = 0; + else + Context->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP | + SERVICE_ACCEPT_SHUTDOWN | + SERVICE_ACCEPT_SESSIONCHANGE; + + if (CurrentState == SERVICE_RUNNING || + CurrentState == SERVICE_STOPPED ) + Context->Status.dwCheckPoint = 0; + else + Context->Status.dwCheckPoint = CheckPoint++; + + Success = SetServiceStatus(Context->Service, &Context->Status); + + if (!Success) + goto fail1; + + Log("<===="); + + return; + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } +} + +static BOOL +MonitorGetPath( + IN const GUID *Guid, + OUT PTCHAR *Path + ) +{ + HDEVINFO DeviceInfoSet; + SP_DEVICE_INTERFACE_DATA DeviceInterfaceData; + PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetail; + DWORD Size; + HRESULT Error; + BOOL Success; + + Log("====>"); + + DeviceInfoSet = SetupDiGetClassDevs(Guid, + NULL, + NULL, + DIGCF_PRESENT | + DIGCF_DEVICEINTERFACE); + if (DeviceInfoSet == INVALID_HANDLE_VALUE) + goto fail1; + + DeviceInterfaceData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA); + + Success = SetupDiEnumDeviceInterfaces(DeviceInfoSet, + NULL, + Guid, + 0, + &DeviceInterfaceData); + if (!Success) + goto fail2; + + Success = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, + &DeviceInterfaceData, + NULL, + 0, + &Size, + NULL); + if (!Success && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + goto fail3; + + DeviceInterfaceDetail = calloc(1, Size); + if (DeviceInterfaceDetail == NULL) + goto fail4; + + DeviceInterfaceDetail->cbSize = + sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA); + + Success = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, + &DeviceInterfaceData, + DeviceInterfaceDetail, + Size, + NULL, + NULL); + if (!Success) + goto fail5; + + *Path = _tcsdup(DeviceInterfaceDetail->DevicePath); + + if (*Path == NULL) + goto fail6; + + Log("%s", *Path); + + free(DeviceInterfaceDetail); + + SetupDiDestroyDeviceInfoList(DeviceInfoSet); + + Log("<===="); + + return TRUE; + +fail6: + Log("fail6"); + +fail5: + Log("fail5"); + + free(DeviceInterfaceDetail); + +fail4: + Log("fail4"); + +fail3: + Log("fail3"); + +fail2: + Log("fail2"); + + SetupDiDestroyDeviceInfoList(DeviceInfoSet); + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } + + return FALSE; +} + +static VOID +PutString( + IN HANDLE Handle, + IN PTCHAR Buffer, + IN DWORD Length + ) +{ + DWORD Offset; + + Offset = 0; + while (Offset < Length) { + DWORD Written; + BOOL Success; + + Success = WriteFile(Handle, + &Buffer[Offset], + Length - Offset, + &Written, + NULL); + if (!Success) + break; + + Offset += Written; + } +} + +#define ECHO(_Handle, _Buffer) \ + PutString((_Handle), TEXT(_Buffer), (DWORD)_tcslen(_Buffer)) + +static VOID +MonitorAdd( + VOID + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + PTCHAR Path; + DEV_BROADCAST_HANDLE Handle; + HRESULT Error; + BOOL Success; + + if (Context->Device != INVALID_HANDLE_VALUE) + return; + + Log("====>"); + + Success = MonitorGetPath(&GUID_XENCONS_DEVICE, &Path); + + if (!Success) + goto fail1; + + Context->Device = CreateFile(Path, + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (Context->Device == INVALID_HANDLE_VALUE) + goto fail2; + + ECHO(Context->Device, "\r\n[ATTACHED]\r\n"); + + ZeroMemory(&Handle, sizeof (Handle)); + Handle.dbch_size = sizeof (Handle); + Handle.dbch_devicetype = DBT_DEVTYP_HANDLE; + Handle.dbch_handle = Context->Device; + + Context->DeviceNotification = + RegisterDeviceNotification(Context->Service, + &Handle, + DEVICE_NOTIFY_SERVICE_HANDLE); + if (Context->DeviceNotification == NULL) + goto fail3; + + Context->DevicePath = Path; + + Log("<===="); + + return; + +fail3: + Log("fail3"); + + CloseHandle(Context->Device); + Context->Device = INVALID_HANDLE_VALUE; + +fail2: + Log("fail2"); + + free(Path); + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } +} + +static VOID +MonitorRemove( + VOID + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + + if (Context->Device == INVALID_HANDLE_VALUE) + return; + + Log("====>"); + + free(Context->DevicePath); + Context->DevicePath = NULL; + + UnregisterDeviceNotification(Context->DeviceNotification); + Context->DeviceNotification = NULL; + + ECHO(Context->Device, "\r\n[DETACHED]\r\n"); + + CloseHandle(Context->Device); + Context->Device = INVALID_HANDLE_VALUE; + + Log("<===="); +} + +DWORD WINAPI +MonitorCtrlHandlerEx( + IN DWORD Ctrl, + IN DWORD EventType, + IN LPVOID EventData, + IN LPVOID Argument + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + + UNREFERENCED_PARAMETER(Argument); + + switch (Ctrl) { + case SERVICE_CONTROL_STOP: + case SERVICE_CONTROL_SHUTDOWN: + ReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); + SetEvent(Context->StopEvent); + return NO_ERROR; + + case SERVICE_CONTROL_INTERROGATE: + ReportStatus(SERVICE_RUNNING, NO_ERROR, 0); + return NO_ERROR; + + case SERVICE_CONTROL_DEVICEEVENT: { + PDEV_BROADCAST_HDR Header = EventData; + + switch (EventType) { + case DBT_DEVICEARRIVAL: + if (Header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE) { + PDEV_BROADCAST_DEVICEINTERFACE Interface = EventData; + + if (IsEqualGUID(&Interface->dbcc_classguid, + &GUID_XENCONS_DEVICE)) + SetEvent(Context->AddEvent); + } + break; + + case DBT_DEVICEQUERYREMOVE: + if (Header->dbch_devicetype == DBT_DEVTYP_HANDLE) { + PDEV_BROADCAST_HANDLE Device = EventData; + + if (Device->dbch_handle == Context->Device) + SetEvent(Context->RemoveEvent); + } + break; + } + + return NO_ERROR; + } + default: + break; + } + + ReportStatus(SERVICE_RUNNING, NO_ERROR, 0); + return ERROR_CALL_NOT_IMPLEMENTED; +} + +VOID WINAPI +MonitorMain( + _In_ DWORD argc, + _In_ LPTSTR *argv + ) +{ + PMONITOR_CONTEXT Context = &MonitorContext; + DEV_BROADCAST_DEVICEINTERFACE Interface; + HRESULT Error; + + UNREFERENCED_PARAMETER(argc); + UNREFERENCED_PARAMETER(argv); + + Log("====>"); + + Error = RegOpenKeyEx(HKEY_LOCAL_MACHINE, + PARAMETERS_KEY(__MODULE__), + 0, + KEY_READ, + &Context->ParametersKey); + if (Error != ERROR_SUCCESS) + goto fail1; + + Context->Service = RegisterServiceCtrlHandlerEx(MONITOR_NAME, + MonitorCtrlHandlerEx, + NULL); + if (Context->Service == NULL) + goto fail2; + + Context->EventLog = RegisterEventSource(NULL, + MONITOR_NAME); + if (Context->EventLog == NULL) + goto fail3; + + Context->Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + Context->Status.dwServiceSpecificExitCode = 0; + + ReportStatus(SERVICE_START_PENDING, NO_ERROR, 3000); + + Context->StopEvent = CreateEvent(NULL, + TRUE, + FALSE, + NULL); + + if (Context->StopEvent == NULL) + goto fail4; + + Context->AddEvent = CreateEvent(NULL, + TRUE, + FALSE, + NULL); + + if (Context->AddEvent == NULL) + goto fail5; + + Context->RemoveEvent = CreateEvent(NULL, + TRUE, + FALSE, + NULL); + + if (Context->RemoveEvent == NULL) + goto fail6; + + Context->Device = INVALID_HANDLE_VALUE; + + ZeroMemory(&Interface, sizeof (Interface)); + Interface.dbcc_size = sizeof (Interface); + Interface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + Interface.dbcc_classguid = GUID_XENCONS_DEVICE; + + Context->InterfaceNotification = + RegisterDeviceNotification(Context->Service, + &Interface, + DEVICE_NOTIFY_SERVICE_HANDLE); + if (Context->InterfaceNotification == NULL) + goto fail7; + + // The device may already by present + SetEvent(Context->AddEvent); + + ReportStatus(SERVICE_RUNNING, NO_ERROR, 0); + + for (;;) { + HANDLE Events[3]; + DWORD Object; + + Events[0] = Context->StopEvent; + Events[1] = Context->AddEvent; + Events[2] = Context->RemoveEvent; + + Log("waiting (%u)...", ARRAYSIZE(Events)); + Object = WaitForMultipleObjects(ARRAYSIZE(Events), + Events, + FALSE, + INFINITE); + Log("awake"); + +#define WAIT_OBJECT_1 (WAIT_OBJECT_0 + 1) +#define WAIT_OBJECT_2 (WAIT_OBJECT_0 + 2) + + switch (Object) { + case WAIT_OBJECT_0: + ResetEvent(Context->StopEvent); + goto done; + + case WAIT_OBJECT_1: + ResetEvent(Context->AddEvent); + MonitorAdd(); + break; + + case WAIT_OBJECT_2: + ResetEvent(Context->RemoveEvent); + MonitorRemove(); + + default: + break; + } + +#undef WAIT_OBJECT_1 +#undef WAIT_OBJECT_2 + } + +done: + MonitorRemove(); + + UnregisterDeviceNotification(Context->InterfaceNotification); + + CloseHandle(Context->RemoveEvent); + + CloseHandle(Context->AddEvent); + + CloseHandle(Context->StopEvent); + + ReportStatus(SERVICE_STOPPED, NO_ERROR, 0); + + (VOID) DeregisterEventSource(Context->EventLog); + + CloseHandle(Context->ParametersKey); + + Log("<===="); + + return; + +fail7: + Log("fail7"); + + CloseHandle(Context->RemoveEvent); + +fail6: + Log("fail6"); + + CloseHandle(Context->AddEvent); + +fail5: + Log("fail5"); + + CloseHandle(Context->StopEvent); + +fail4: + Log("fail4"); + + ReportStatus(SERVICE_STOPPED, GetLastError(), 0); + + (VOID) DeregisterEventSource(Context->EventLog); + +fail3: + Log("fail3"); + +fail2: + Log("fail2"); + + CloseHandle(Context->ParametersKey); + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } +} + +static BOOL +MonitorCreate( + VOID + ) +{ + SC_HANDLE SCManager; + SC_HANDLE Service; + TCHAR Path[MAX_PATH]; + HRESULT Error; + + Log("====>"); + + if(!GetModuleFileName(NULL, Path, MAX_PATH)) + goto fail1; + + SCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_ALL_ACCESS); + + if (SCManager == NULL) + goto fail2; + + Service = CreateService(SCManager, + MONITOR_NAME, + MONITOR_DISPLAYNAME, + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, + SERVICE_ERROR_NORMAL, + Path, + NULL, + NULL, + NULL, + NULL, + NULL); + + if (Service == NULL) + goto fail3; + + CloseServiceHandle(Service); + CloseServiceHandle(SCManager); + + Log("<===="); + + return TRUE; + +fail3: + Log("fail3"); + + CloseServiceHandle(SCManager); + +fail2: + Log("fail2"); + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } + + return FALSE; +} + +static BOOL +MonitorDelete( + VOID + ) +{ + SC_HANDLE SCManager; + SC_HANDLE Service; + BOOL Success; + SERVICE_STATUS Status; + HRESULT Error; + + Log("====>"); + + SCManager = OpenSCManager(NULL, + NULL, + SC_MANAGER_ALL_ACCESS); + + if (SCManager == NULL) + goto fail1; + + Service = OpenService(SCManager, + MONITOR_NAME, + SERVICE_ALL_ACCESS); + + if (Service == NULL) + goto fail2; + + Success = ControlService(Service, + SERVICE_CONTROL_STOP, + &Status); + + if (!Success) + goto fail3; + + Success = DeleteService(Service); + + if (!Success) + goto fail4; + + CloseServiceHandle(Service); + CloseServiceHandle(SCManager); + + Log("<===="); + + return TRUE; + +fail4: + Log("fail4"); + +fail3: + Log("fail3"); + + CloseServiceHandle(Service); + +fail2: + Log("fail2"); + + CloseServiceHandle(SCManager); + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } + + return FALSE; +} + +static BOOL +MonitorEntry( + VOID + ) +{ + SERVICE_TABLE_ENTRY Table[] = { + { MONITOR_NAME, MonitorMain }, + { NULL, NULL } + }; + HRESULT Error; + + Log("%s (%s) ====>", + MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR, + DAY_STR "/" MONTH_STR "/" YEAR_STR); + + if (!StartServiceCtrlDispatcher(Table)) + goto fail1; + + Log("%s (%s) <====", + MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR, + DAY_STR "/" MONTH_STR "/" YEAR_STR); + + return TRUE; + +fail1: + Error = GetLastError(); + + { + PTCHAR Message; + Message = GetErrorMessage(Error); + Log("fail1 (%s)", Message); + LocalFree(Message); + } + + return FALSE; +} + +int CALLBACK +_tWinMain( + _In_ HINSTANCE Current, + _In_opt_ HINSTANCE Previous, + _In_ LPSTR CmdLine, + _In_ int CmdShow + ) +{ + BOOL Success; + + UNREFERENCED_PARAMETER(Current); + UNREFERENCED_PARAMETER(Previous); + UNREFERENCED_PARAMETER(CmdShow); + + if (_tcslen(CmdLine) != 0) { + if (_tcsicmp(CmdLine, TEXT("create")) == 0) + Success = MonitorCreate(); + else if (_tcsicmp(CmdLine, TEXT("delete")) == 0) + Success = MonitorDelete(); + else + Success = FALSE; + } else + Success = MonitorEntry(); + + return Success ? 0 : 1; +} diff --git a/src/monitor/xencons_monitor.rc b/src/monitor/xencons_monitor.rc new file mode 100644 index 0000000..bd3b141 --- /dev/null +++ b/src/monitor/xencons_monitor.rc @@ -0,0 +1,56 @@ +/* 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 +#include + +#undef VER_COMPANYNAME_STR +#undef VER_PRODUCTNAME_STR +#undef VER_PRODUCTVERSION +#undef VER_PRODUCTVERSION_STR + +#include + +#define VER_COMPANYNAME_STR VENDOR_NAME_STR +#define VER_LEGALCOPYRIGHT_STR "Copyright (c) Citrix Systems Inc." + +#define VER_PRODUCTNAME_STR "XENCONS" +#define VER_PRODUCTVERSION MAJOR_VERSION,MINOR_VERSION,MICRO_VERSION,BUILD_NUMBER +#define VER_PRODUCTVERSION_STR MAJOR_VERSION_STR "." MINOR_VERSION_STR "." MICRO_VERSION_STR "." BUILD_NUMBER_STR + +#define VER_INTERNALNAME_STR "XENCONS_MONITOR.EXE" +#define VER_FILEDESCRIPTION_STR "XENCONS_MONITOR" + +#define VER_FILETYPE VFT_APP +#define VER_FILESUBTYPE VFT2_UNKNOWN + +#include "common.ver" +#include "messages.rc" diff --git a/src/xencons.inf b/src/xencons.inf index c64c667..dbff121 100644 --- a/src/xencons.inf +++ b/src/xencons.inf @@ -41,6 +41,7 @@ DriverPackageDisplayName=%DiskDesc% [DestinationDirs] DefaultDestDir=12 CoInst_CopyFiles=11 +Monitor_CopyFiles=11 [SourceDisksNames] 0=%DiskDesc% @@ -48,10 +49,16 @@ CoInst_CopyFiles=11 [SourceDisksFiles] xencons.sys=0,, xencons_coinst.dll=0,, +xencons_monitor.exe=0,, +xencons_monitor.dll=0,, [CoInst_CopyFiles] xencons_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll,xencons_coinst.dll +[Monitor_CopyFiles] +xencons_monitor_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.exe,xencons_monitor.exe +xencons_monitor_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll,xencons_monitor.dll + [Manufacturer] %Vendor%=Inst,NT$ARCH$ @@ -59,35 +66,56 @@ xencons_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dl ; DisplayName Section DeviceID ; ----------- ------- -------- -%XenconsName% =Xencons_Inst, XENBUS\VEN_@VENDOR_PREFIX@@VENDOR_DEVICE_ID@&DEV_CONS&REV_09000000 -%XenconsName% =Xencons_Inst, XENBUS\VEN_@VENDOR_PREFIX@0001&DEV_CONS&REV_09000000 -%XenconsName% =Xencons_Inst, XENBUS\VEN_@VENDOR_PREFIX@0002&DEV_CONS&REV_09000000 +%XenConsName% =XenCons_Inst, XENBUS\VEN_@VENDOR_PREFIX@@VENDOR_DEVICE_ID@&DEV_CONS&REV_09000000 +%XenConsName% =XenCons_Inst, XENBUS\VEN_@VENDOR_PREFIX@0001&DEV_CONS&REV_09000000 +%XenConsName% =XenCons_Inst, XENBUS\VEN_@VENDOR_PREFIX@0002&DEV_CONS&REV_09000000 -[Xencons_Inst] -CopyFiles=Xencons_Copyfiles +[XenCons_Inst] +CopyFiles=XenCons_Copyfiles +CopyFiles=Monitor_Copyfiles -[Xencons_Copyfiles] +[XenCons_Copyfiles] xencons.sys -[Xencons_Inst.Services] -AddService=xencons,0x02,Xencons_Service, +[XenCons_Inst.Services] +AddService=xencons_monitor,%SPSVCSINST_STARTSERVICE%,Monitor_Service,Monitor_EventLog +AddService=xencons,%SPSVCINST_ASSOCSERVICE%,XenCons_Service -[Xencons_Service] -DisplayName=%XenconsName% +[XenCons_Service] +DisplayName=%XenConsName% ServiceType=%SERVICE_KERNEL_DRIVER% StartType=%SERVICE_DEMAND_START% ErrorControl=%SERVICE_ERROR_NORMAL% ServiceBinary=%12%\xencons.sys LoadOrderGroup="Extended Base" -AddReg = Xencons_BootFlags, Xencons_Parameters +AddReg = XenCons_BootFlags, XenCons_Parameters -[Xencons_BootFlags] +[XenCons_BootFlags] HKR,,"BootFlags",0x00010003,0x81 -[Xencons_Parameters] +[XenCons_Parameters] +HKR,"Parameters",,0x00000010 + +[Monitor_Service] +DisplayName=%MonitorName% +Description=%MonitorDesc% +ServiceType=%SERVICE_WIN32_OWN_PROCESS% +StartType=%SERVICE_AUTO_START% +ErrorControl=%SERVICE_ERROR_NORMAL% +ServiceBinary=%11%\xencons_monitor_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.exe +AddReg = Monitor_Parameters + +[Monitor_Parameters] HKR,"Parameters",,0x00000010 -[Xencons_Inst.CoInstallers] +[Monitor_EventLog] +AddReg=Monitor_EventLog_AddReg + +[Monitor_EventLog_AddReg] +HKR,,EventMessageFile,0x00020000,"%%SystemRoot%%\System32\xencons_monitor_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll" +HKR,,TypesSupported,0x00010001,7 + +[XenCons_Inst.CoInstallers] CopyFiles=CoInst_CopyFiles AddReg=CoInst_AddReg @@ -98,7 +126,10 @@ HKR,,CoInstallers32,0x00010000,"xencons_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@ Vendor="@VENDOR_NAME@" DiskDesc="@PRODUCT_NAME@ PV Console Package" -XenconsName="@PRODUCT_NAME@ PV Console" +XenConsName="@PRODUCT_NAME@ PV Console" +MonitorName="@PRODUCT_NAME@ PV Console Monitor" +MonitorDesc="Provides a monitor for the @PRODUCT_NAME@ PV Console" + SERVICE_BOOT_START=0x0 SERVICE_SYSTEM_START=0x1 @@ -106,8 +137,12 @@ SERVICE_AUTO_START=0x2 SERVICE_DEMAND_START=0x3 SERVICE_DISABLED=0x4 +SERVICE_WIN32_OWN_PROCESS=0x10 SERVICE_KERNEL_DRIVER=0x1 SERVICE_ERROR_IGNORE=0x0 SERVICE_ERROR_NORMAL=0x1 SERVICE_ERROR_SEVERE=0x2 SERVICE_ERROR_CRITICAL=0x3 + +SPSVCINST_ASSOCSERVICE=0x00000002 +SPSVCSINST_STARTSERVICE=0x00000800 diff --git a/vs2015/package/package.vcxproj b/vs2015/package/package.vcxproj index 5359406..65f9125 100644 --- a/vs2015/package/package.vcxproj +++ b/vs2015/package/package.vcxproj @@ -39,6 +39,9 @@ {6CC9B8DD-A5AE-427D-8157-E91D21DD7E19} + + {8991F0A5-408B-43E0-88CC-9550D4AAE616} + diff --git a/vs2015/xencons.sln b/vs2015/xencons.sln index 88baf21..6801b45 100644 --- a/vs2015/xencons.sln +++ b/vs2015/xencons.sln @@ -6,10 +6,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xencons", "xencons\xencons. EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xencons_coinst", "xencons_coinst\xencons_coinst.vcxproj", "{6CC9B8DD-A5AE-427D-8157-E91D21DD7E19}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xencons_monitor", "xencons_monitor\xencons_monitor.vcxproj", "{8991F0A5-408B-43E0-88CC-9550D4AAE616}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "package\package.vcxproj", "{8B5B8F4B-7FF3-4B64-AC4A-5246026217E7}" ProjectSection(ProjectDependencies) = postProject {4674B8C2-876B-4F2A-AB71-BAC968A9B529} = {4674B8C2-876B-4F2A-AB71-BAC968A9B529} {6CC9B8DD-A5AE-427D-8157-E91D21DD7E19} = {6CC9B8DD-A5AE-427D-8157-E91D21DD7E19} + {8991F0A5-408B-43E0-88CC-9550D4AAE616} = {8991F0A5-408B-43E0-88CC-9550D4AAE616} EndProjectSection EndProject Global diff --git a/vs2015/xencons_monitor/xencons_monitor.vcxproj b/vs2015/xencons_monitor/xencons_monitor.vcxproj new file mode 100644 index 0000000..05b5e45 --- /dev/null +++ b/vs2015/xencons_monitor/xencons_monitor.vcxproj @@ -0,0 +1,77 @@ + + + + + MultiByte + WindowsApplicationForDrivers10.0 + Application + + + + {8991F0A5-408B-43E0-88CC-9550D4AAE616} + + + + + $(IncludePath) + true + false + + + Link + + + + $(SolutionDir)..\include;%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;_CRT_SECURE_NO_WARNINGS;__MODULE__="XENCONS_MONITOR";%(PreprocessorDefinitions) + EnableAllWarnings + 4127;4711;4548;4820;4668;4255;6001;6054;28196;%(DisableSpecificWarnings) + true + true + MultiThreadedDebug + MultiThreaded + + + wtsapi32.lib;cfgmgr32.lib;setupapi.lib;%(AdditionalDependencies) + + + $(SolutionDir)..\include;%(AdditionalIncludeDirectories) + + + + + __i386__;%(PreprocessorDefinitions) + + + $(TargetDir)$(TargetName).dll + $(IntDir)$(TargetName).res + link -machine:x86 -dll -noentry -out:%(Outputs) %(Inputs) + + + + + __x86_64__;%(PreprocessorDefinitions) + + + $(TargetDir)$(TargetName).dll + $(IntDir)$(TargetName).res + link -machine:x64 -dll -noentry -out:%(Outputs) %(Inputs) + + + + + + + + + + + + + + + + + + + diff --git a/vs2015/xencons_monitor/xencons_monitor.vcxproj.user b/vs2015/xencons_monitor/xencons_monitor.vcxproj.user new file mode 100644 index 0000000..a427c80 --- /dev/null +++ b/vs2015/xencons_monitor/xencons_monitor.vcxproj.user @@ -0,0 +1,8 @@ + + + + TestSign + ..\..\src\xencons.pfx + http://timestamp.verisign.com/scripts/timstamp.dll + +