mirror of
https://github.com/finos/SymphonyElectron.git
synced 2024-12-27 17:31:36 -06:00
Merge branch 'main' into SDA-3033-Close-notifs-on-logout
This commit is contained in:
commit
6bc3e2c9ff
41
auto_update/auto_update.sln
Normal file
41
auto_update/auto_update.sln
Normal file
@ -0,0 +1,41 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31112.23
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "auto_update_helper", "auto_update_helper.vcxproj", "{9A61CB06-1A97-440C-A931-508C9019F0FB}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "auto_update_service", "auto_update_service.vcxproj", "{7E157BD0-86F0-4325-848C-BA1C87D9C99C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{9A61CB06-1A97-440C-A931-508C9019F0FB}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9A61CB06-1A97-440C-A931-508C9019F0FB}.Debug|x64.Build.0 = Debug|x64
|
||||
{9A61CB06-1A97-440C-A931-508C9019F0FB}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{9A61CB06-1A97-440C-A931-508C9019F0FB}.Debug|x86.Build.0 = Debug|Win32
|
||||
{9A61CB06-1A97-440C-A931-508C9019F0FB}.Release|x64.ActiveCfg = Release|x64
|
||||
{9A61CB06-1A97-440C-A931-508C9019F0FB}.Release|x64.Build.0 = Release|x64
|
||||
{9A61CB06-1A97-440C-A931-508C9019F0FB}.Release|x86.ActiveCfg = Release|Win32
|
||||
{9A61CB06-1A97-440C-A931-508C9019F0FB}.Release|x86.Build.0 = Release|Win32
|
||||
{7E157BD0-86F0-4325-848C-BA1C87D9C99C}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7E157BD0-86F0-4325-848C-BA1C87D9C99C}.Debug|x64.Build.0 = Debug|x64
|
||||
{7E157BD0-86F0-4325-848C-BA1C87D9C99C}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{7E157BD0-86F0-4325-848C-BA1C87D9C99C}.Debug|x86.Build.0 = Debug|Win32
|
||||
{7E157BD0-86F0-4325-848C-BA1C87D9C99C}.Release|x64.ActiveCfg = Release|x64
|
||||
{7E157BD0-86F0-4325-848C-BA1C87D9C99C}.Release|x64.Build.0 = Release|x64
|
||||
{7E157BD0-86F0-4325-848C-BA1C87D9C99C}.Release|x86.ActiveCfg = Release|Win32
|
||||
{7E157BD0-86F0-4325-848C-BA1C87D9C99C}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {ACFD70FC-B270-4021-9FB7-2FB6C2EB1C43}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
47
auto_update/auto_update_helper.cpp
Normal file
47
auto_update/auto_update_helper.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <windows.h>
|
||||
#include <aclapi.h>
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
#pragma comment( lib, "shell32.lib" )
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "ipc.h"
|
||||
|
||||
|
||||
int main( int argc, char** argv ) {
|
||||
if( argc < 3 ) {
|
||||
printf( "Not enough arguments" );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
char const* installer_filename = argv[ 1 ];
|
||||
char const* application_filename = argv[ 2 ];
|
||||
ipc_client_t* client = ipc_client_connect();
|
||||
ipc_client_send( client, installer_filename );
|
||||
char response[ 256 ];
|
||||
int size = 0;
|
||||
int temp_size = 0;
|
||||
ipc_receive_status_t status = IPC_RECEIVE_STATUS_MORE_DATA;
|
||||
while( size < sizeof( response ) - 1 && status == IPC_RECEIVE_STATUS_MORE_DATA ) {
|
||||
status = ipc_client_receive( client, response + size,
|
||||
sizeof( response ) - size - 1, &temp_size );
|
||||
size += temp_size;
|
||||
}
|
||||
response[ size ] = '\0';
|
||||
printf( "%s\n", response );
|
||||
ipc_client_connect();
|
||||
|
||||
int result = (int)(uintptr_t) ShellExecute( NULL, NULL, application_filename,
|
||||
NULL, NULL, SW_SHOWNORMAL );
|
||||
|
||||
if( result <= 32 ) {
|
||||
printf( "Failed to launch SDA after installation" );
|
||||
}
|
||||
|
||||
if( strcmp( response, "OK" ) != 0 ) {
|
||||
printf( "Installation failed" );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
135
auto_update/auto_update_helper.vcxproj
Normal file
135
auto_update/auto_update_helper.vcxproj
Normal file
@ -0,0 +1,135 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{9A61CB06-1A97-440C-A931-508C9019F0FB}</ProjectGuid>
|
||||
<RootNamespace>autoupdate</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>auto_update_helper</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="auto_update_helper.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ipc.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
298
auto_update/auto_update_service.cpp
Normal file
298
auto_update/auto_update_service.cpp
Normal file
@ -0,0 +1,298 @@
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <windows.h>
|
||||
#include <aclapi.h>
|
||||
#include <stdio.h>
|
||||
#include <tchar.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#include "ipc.h"
|
||||
|
||||
#pragma comment(lib, "advapi32.lib")
|
||||
#pragma comment(lib, "Shell32.lib")
|
||||
|
||||
#define SVCNAME TEXT("SDA Auto Update")
|
||||
|
||||
SERVICE_STATUS gSvcStatus;
|
||||
SERVICE_STATUS_HANDLE gSvcStatusHandle;
|
||||
HANDLE ghSvcStopEvent = NULL;
|
||||
|
||||
VOID SvcInstall(void);
|
||||
VOID WINAPI SvcCtrlHandler( DWORD );
|
||||
VOID WINAPI SvcMain( DWORD, LPTSTR * );
|
||||
|
||||
VOID ReportSvcStatus( DWORD, DWORD, DWORD );
|
||||
VOID SvcInit( DWORD, LPTSTR * );
|
||||
|
||||
|
||||
//
|
||||
// Purpose:
|
||||
// Entry point for the process
|
||||
//
|
||||
// Parameters:
|
||||
// None
|
||||
//
|
||||
// Return value:
|
||||
// None, defaults to 0 (zero)
|
||||
//
|
||||
int __cdecl _tmain(int argc, TCHAR *argv[])
|
||||
{
|
||||
// If command-line parameter is "install", install the service.
|
||||
// Otherwise, the service is probably being started by the SCM.
|
||||
|
||||
if( lstrcmpi( argv[1], TEXT("install")) == 0 )
|
||||
{
|
||||
SvcInstall();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TO_DO: Add any additional services for the process to this table.
|
||||
SERVICE_TABLE_ENTRY DispatchTable[] =
|
||||
{
|
||||
{ (LPSTR)SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
// This call returns when the service has stopped.
|
||||
// The process should simply terminate when the call returns.
|
||||
|
||||
if (!StartServiceCtrlDispatcher( DispatchTable ))
|
||||
{
|
||||
//SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Purpose:
|
||||
// Installs a service in the SCM database
|
||||
//
|
||||
// Parameters:
|
||||
// None
|
||||
//
|
||||
// Return value:
|
||||
// None
|
||||
//
|
||||
VOID SvcInstall()
|
||||
{
|
||||
SC_HANDLE schSCManager;
|
||||
SC_HANDLE schService;
|
||||
TCHAR szPath[MAX_PATH];
|
||||
|
||||
if( !GetModuleFileName( NULL, szPath, MAX_PATH ) )
|
||||
{
|
||||
printf("Cannot install service (%d)\n", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
// Get a handle to the SCM database.
|
||||
|
||||
schSCManager = OpenSCManager(
|
||||
NULL, // local computer
|
||||
NULL, // ServicesActive database
|
||||
SC_MANAGER_ALL_ACCESS); // full access rights
|
||||
|
||||
if (NULL == schSCManager)
|
||||
{
|
||||
printf("OpenSCManager failed (%d)\n", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the service
|
||||
|
||||
schService = CreateService(
|
||||
schSCManager, // SCM database
|
||||
SVCNAME, // name of service
|
||||
SVCNAME, // service name to display
|
||||
SERVICE_ALL_ACCESS, // desired access
|
||||
SERVICE_WIN32_OWN_PROCESS, // service type
|
||||
SERVICE_DEMAND_START, // start type
|
||||
SERVICE_ERROR_NORMAL, // error control type
|
||||
szPath, // path to service's binary
|
||||
NULL, // no load ordering group
|
||||
NULL, // no tag identifier
|
||||
NULL, // no dependencies
|
||||
NULL, // LocalSystem account
|
||||
NULL); // no password
|
||||
|
||||
if (schService == NULL)
|
||||
{
|
||||
printf("CreateService failed (%d)\n", GetLastError());
|
||||
CloseServiceHandle(schSCManager);
|
||||
return;
|
||||
}
|
||||
else printf("Service installed successfully\n");
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
}
|
||||
|
||||
//
|
||||
// Purpose:
|
||||
// Entry point for the service
|
||||
//
|
||||
// Parameters:
|
||||
// dwArgc - Number of arguments in the lpszArgv array
|
||||
// lpszArgv - Array of strings. The first string is the name of
|
||||
// the service and subsequent strings are passed by the process
|
||||
// that called the StartService function to start the service.
|
||||
//
|
||||
// Return value:
|
||||
// None.
|
||||
//
|
||||
VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv )
|
||||
{
|
||||
// Register the handler function for the service
|
||||
|
||||
gSvcStatusHandle = RegisterServiceCtrlHandler(
|
||||
SVCNAME,
|
||||
SvcCtrlHandler);
|
||||
|
||||
if( !gSvcStatusHandle )
|
||||
{
|
||||
// SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
|
||||
return;
|
||||
}
|
||||
|
||||
// These SERVICE_STATUS members remain as set here
|
||||
|
||||
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||
gSvcStatus.dwServiceSpecificExitCode = 0;
|
||||
|
||||
// Report initial status to the SCM
|
||||
|
||||
ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 );
|
||||
|
||||
// Perform service-specific initialization and work.
|
||||
|
||||
SvcInit( dwArgc, lpszArgv );
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Purpose:
|
||||
// The service code
|
||||
//
|
||||
// Parameters:
|
||||
// dwArgc - Number of arguments in the lpszArgv array
|
||||
// lpszArgv - Array of strings. The first string is the name of
|
||||
// the service and subsequent strings are passed by the process
|
||||
// that called the StartService function to start the service.
|
||||
//
|
||||
// Return value:
|
||||
// None
|
||||
//
|
||||
VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
|
||||
{
|
||||
ipc_server_t* server = ipc_server_start();
|
||||
|
||||
// TO_DO: Declare and set any required variables.
|
||||
// Be sure to periodically call ReportSvcStatus() with
|
||||
// SERVICE_START_PENDING. If initialization fails, call
|
||||
// ReportSvcStatus with SERVICE_STOPPED.
|
||||
|
||||
// Create an event. The control handler function, SvcCtrlHandler,
|
||||
// signals this event when it receives the stop control code.
|
||||
|
||||
ghSvcStopEvent = CreateEvent(
|
||||
NULL, // default security attributes
|
||||
TRUE, // manual reset event
|
||||
FALSE, // not signaled
|
||||
NULL); // no name
|
||||
|
||||
if ( ghSvcStopEvent == NULL)
|
||||
{
|
||||
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
// Report running status when initialization is complete.
|
||||
|
||||
ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
|
||||
|
||||
// TO_DO: Perform work until service stops.
|
||||
|
||||
while(1)
|
||||
{
|
||||
// Check whether to stop the service.
|
||||
|
||||
WaitForSingleObject(ghSvcStopEvent, INFINITE);
|
||||
|
||||
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Purpose:
|
||||
// Sets the current service status and reports it to the SCM.
|
||||
//
|
||||
// Parameters:
|
||||
// dwCurrentState - The current state (see SERVICE_STATUS)
|
||||
// dwWin32ExitCode - The system error code
|
||||
// dwWaitHint - Estimated time for pending operation,
|
||||
// in milliseconds
|
||||
//
|
||||
// Return value:
|
||||
// None
|
||||
//
|
||||
VOID ReportSvcStatus( DWORD dwCurrentState,
|
||||
DWORD dwWin32ExitCode,
|
||||
DWORD dwWaitHint)
|
||||
{
|
||||
static DWORD dwCheckPoint = 1;
|
||||
|
||||
// Fill in the SERVICE_STATUS structure.
|
||||
|
||||
gSvcStatus.dwCurrentState = dwCurrentState;
|
||||
gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
|
||||
gSvcStatus.dwWaitHint = dwWaitHint;
|
||||
|
||||
if (dwCurrentState == SERVICE_START_PENDING)
|
||||
gSvcStatus.dwControlsAccepted = 0;
|
||||
else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
|
||||
|
||||
if ( (dwCurrentState == SERVICE_RUNNING) ||
|
||||
(dwCurrentState == SERVICE_STOPPED) )
|
||||
gSvcStatus.dwCheckPoint = 0;
|
||||
else gSvcStatus.dwCheckPoint = dwCheckPoint++;
|
||||
|
||||
// Report the status of the service to the SCM.
|
||||
SetServiceStatus( gSvcStatusHandle, &gSvcStatus );
|
||||
}
|
||||
|
||||
//
|
||||
// Purpose:
|
||||
// Called by SCM whenever a control code is sent to the service
|
||||
// using the ControlService function.
|
||||
//
|
||||
// Parameters:
|
||||
// dwCtrl - control code
|
||||
//
|
||||
// Return value:
|
||||
// None
|
||||
//
|
||||
VOID WINAPI SvcCtrlHandler( DWORD dwCtrl )
|
||||
{
|
||||
// Handle the requested control code.
|
||||
|
||||
switch(dwCtrl)
|
||||
{
|
||||
case SERVICE_CONTROL_STOP:
|
||||
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
|
||||
|
||||
// Signal the service to stop.
|
||||
|
||||
SetEvent(ghSvcStopEvent);
|
||||
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
|
||||
|
||||
return;
|
||||
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
131
auto_update/auto_update_service.vcxproj
Normal file
131
auto_update/auto_update_service.vcxproj
Normal file
@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{7E157BD0-86F0-4325-848C-BA1C87D9C99C}</ProjectGuid>
|
||||
<RootNamespace>autoupdateservice</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="auto_update_service.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
425
auto_update/ipc.h
Normal file
425
auto_update/ipc.h
Normal file
@ -0,0 +1,425 @@
|
||||
|
||||
|
||||
bool pipe_exists( const char* pipe_name ) {
|
||||
WIN32_FIND_DATA data;
|
||||
memset( &data, 0, sizeof( data ) );
|
||||
|
||||
HANDLE hfind = FindFirstFileA( "\\\\.\\pipe\\*", &data );
|
||||
if( hfind != INVALID_HANDLE_VALUE ) {
|
||||
do {
|
||||
char const* filename = data.cFileName;
|
||||
if( _stricmp( filename, pipe_name ) == 0 ) {
|
||||
FindClose( hfind );
|
||||
return true;
|
||||
}
|
||||
} while( FindNextFileA( hfind, &data ) );
|
||||
FindClose( hfind );
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#define PIPE_NAME "\\\\.\\pipe\\symphony_sda_auto_update_ipc"
|
||||
#define BUFSIZE 512
|
||||
|
||||
struct ipc_client_t {
|
||||
HANDLE pipe;
|
||||
};
|
||||
|
||||
|
||||
ipc_client_t* ipc_client_connect() {
|
||||
if( !pipe_exists( PIPE_NAME ) ) {
|
||||
printf( "Named pipe does not exits\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HANDLE pipe = NULL;
|
||||
for( ; ; ) { // Keep trying to connect while pipe is busy
|
||||
pipe = CreateFile(
|
||||
PIPE_NAME, // pipe name
|
||||
GENERIC_READ | // read and write access
|
||||
GENERIC_WRITE,
|
||||
0, // no sharing
|
||||
NULL, // default security attributes
|
||||
OPEN_EXISTING, // opens existing pipe
|
||||
0, // default attributes
|
||||
NULL ); // no template file
|
||||
|
||||
// Break if the pipe handle is valid.
|
||||
if( pipe != INVALID_HANDLE_VALUE ) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Exit if an error other than ERROR_PIPE_BUSY occurs.
|
||||
if( GetLastError() != ERROR_PIPE_BUSY ) {
|
||||
printf( "Could not open pipe. LastError=%d\n", GetLastError() );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// All pipe instances are busy, so wait for 20 seconds.
|
||||
if( !WaitNamedPipe( PIPE_NAME, 20000 ) ) {
|
||||
printf( "Could not open pipe: 20 second wait timed out." );
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
ipc_client_t* connection = new ipc_client_t();
|
||||
connection->pipe = pipe;
|
||||
return connection;
|
||||
}
|
||||
|
||||
|
||||
void ipc_client_disconnect( ipc_client_t* connection ) {
|
||||
CloseHandle( connection->pipe );
|
||||
delete connection;
|
||||
}
|
||||
|
||||
|
||||
bool ipc_client_send( ipc_client_t* connection, char const* message ) {
|
||||
DWORD mode = PIPE_READMODE_MESSAGE;
|
||||
BOOL success = SetNamedPipeHandleState(
|
||||
connection->pipe, // pipe handle
|
||||
&mode, // new pipe mode
|
||||
NULL, // don't set maximum bytes
|
||||
NULL ); // don't set maximum time
|
||||
if( !success ) {
|
||||
printf( "SetNamedPipeHandleState failed. LastError=%d\n", GetLastError() );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Send a message to the pipe server.
|
||||
DWORD written = 0;
|
||||
success = WriteFile(
|
||||
connection->pipe, // pipe handle
|
||||
message, // message
|
||||
(DWORD) strlen( message ) + 1, // message length
|
||||
&written, // bytes written
|
||||
NULL ); // not overlapped
|
||||
|
||||
if( !success ) {
|
||||
printf( "WriteFile to pipe failed. LastError=%d\n", GetLastError() );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum ipc_receive_status_t {
|
||||
IPC_RECEIVE_STATUS_DONE,
|
||||
IPC_RECEIVE_STATUS_MORE_DATA,
|
||||
IPC_RECEIVE_STATUS_ERROR,
|
||||
};
|
||||
|
||||
ipc_receive_status_t ipc_client_receive( ipc_client_t* connection, char* output, int output_size, int* received_size ) {
|
||||
DWORD size_read = 0;
|
||||
BOOL success = ReadFile(
|
||||
connection->pipe, // pipe handle
|
||||
output, // buffer to receive reply
|
||||
output_size, // size of buffer
|
||||
&size_read, // number of bytes read
|
||||
NULL ); // not overlapped
|
||||
|
||||
if( !success && GetLastError() != ERROR_MORE_DATA ) {
|
||||
printf( "ReadFile from pipe failed. LastError=%d\n", GetLastError() );
|
||||
return IPC_RECEIVE_STATUS_ERROR;
|
||||
}
|
||||
|
||||
if( received_size ) {
|
||||
*received_size = size_read;
|
||||
}
|
||||
|
||||
if( success ) {
|
||||
return IPC_RECEIVE_STATUS_DONE;
|
||||
} else {
|
||||
return IPC_RECEIVE_STATUS_MORE_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This routine is a simple function to print the client request to the console
|
||||
// and populate the reply buffer with a default data string. This is where you
|
||||
// would put the actual client request processing code that runs in the context
|
||||
// of an instance thread. Keep in mind the main thread will continue to wait for
|
||||
// and receive other client connections while the instance thread is working.
|
||||
VOID run_installer( LPSTR pchRequest, LPSTR pchReply, LPDWORD pchBytes ) {
|
||||
printf( "Client Request String:\"%s\"\n", pchRequest );
|
||||
|
||||
char command[ 512 ];
|
||||
sprintf( command, "/i %s /q", pchRequest );
|
||||
|
||||
SHELLEXECUTEINFO ShExecInfo = { 0 };
|
||||
ShExecInfo.cbSize = sizeof( SHELLEXECUTEINFO );
|
||||
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
|
||||
ShExecInfo.hwnd = NULL;
|
||||
ShExecInfo.lpVerb = "open";
|
||||
ShExecInfo.lpFile = "msiexec";
|
||||
ShExecInfo.lpParameters = command;
|
||||
ShExecInfo.lpDirectory = NULL;
|
||||
ShExecInfo.nShow = SW_SHOW;
|
||||
ShExecInfo.hInstApp = NULL;
|
||||
ShellExecuteEx( &ShExecInfo );
|
||||
WaitForSingleObject( ShExecInfo.hProcess, INFINITE );
|
||||
CloseHandle( ShExecInfo.hProcess );
|
||||
|
||||
strcpy( pchReply, "OK" );
|
||||
*pchBytes = (DWORD)( ( strlen( pchReply ) + 1 ) * sizeof( CHAR ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct ipc_server_t {
|
||||
HANDLE thread;
|
||||
};
|
||||
|
||||
|
||||
// This routine is a thread processing function to read from and reply to a client
|
||||
// via the open pipe connection passed from the main loop. Note this allows
|
||||
// the main loop to continue executing, potentially creating more threads of
|
||||
// this procedure to run concurrently, depending on the number of incoming
|
||||
// client connections.
|
||||
DWORD WINAPI ipc_client_thread( LPVOID param ) {
|
||||
HANDLE hHeap = GetProcessHeap();
|
||||
CHAR* pchRequest = (CHAR*) HeapAlloc( hHeap, 0, BUFSIZE * sizeof( CHAR ) );
|
||||
CHAR* pchReply = (CHAR*) HeapAlloc( hHeap, 0, BUFSIZE * sizeof( CHAR ) );
|
||||
|
||||
DWORD cbBytesRead = 0, cbReplyBytes = 0, cbWritten = 0;
|
||||
|
||||
// Do some extra error checking since the app will keep running even if this
|
||||
// thread fails.
|
||||
|
||||
if( param == NULL ) {
|
||||
printf( "\nERROR - Pipe Server Failure:\n" );
|
||||
printf( " ipc_client_thread got an unexpected NULL value in lpvParam.\n" );
|
||||
printf( " ipc_client_thread exitting.\n" );
|
||||
if( pchReply != NULL ) {
|
||||
HeapFree( hHeap, 0, pchReply );
|
||||
}
|
||||
if( pchRequest != NULL ) {
|
||||
HeapFree( hHeap, 0, pchRequest );
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if( pchRequest == NULL ) {
|
||||
printf( "\nERROR - Pipe Server Failure:\n" );
|
||||
printf( " ipc_client_thread got an unexpected NULL heap allocation.\n" );
|
||||
printf( " ipc_client_thread exitting.\n" );
|
||||
if( pchReply != NULL ) {
|
||||
HeapFree( hHeap, 0, pchReply );
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if( pchReply == NULL ) {
|
||||
printf( "\nERROR - Pipe Server Failure:\n");
|
||||
printf( " ipc_client_thread got an unexpected NULL heap allocation.\n" );
|
||||
printf( " ipc_client_thread exitting.\n");
|
||||
if( pchRequest != NULL ) {
|
||||
HeapFree( hHeap, 0, pchRequest );
|
||||
}
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Print verbose messages. In production code, this should be for debugging only.
|
||||
printf( "ipc_client_thread created, receiving and processing messages.\n" );
|
||||
|
||||
// The thread's parameter is a handle to a pipe object instance.
|
||||
HANDLE hPipe = (HANDLE) param;
|
||||
|
||||
// Loop until done reading
|
||||
for( ; ; ) {
|
||||
// Read client requests from the pipe. This simplistic code only allows messages
|
||||
// up to BUFSIZE characters in length.
|
||||
BOOL fSuccess = ReadFile(
|
||||
hPipe, // handle to pipe
|
||||
pchRequest, // buffer to receive data
|
||||
BUFSIZE * sizeof( CHAR ), // size of buffer
|
||||
&cbBytesRead, // number of bytes read
|
||||
NULL ); // not overlapped I/O
|
||||
|
||||
if( !fSuccess || cbBytesRead == 0 ) {
|
||||
if (GetLastError() == ERROR_BROKEN_PIPE) {
|
||||
printf( "ipc_client_thread: client disconnected.\n" );
|
||||
} else {
|
||||
printf( "ipc_client_thread ReadFile failed, LastError=%d.\n", GetLastError() );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Process the incoming message.
|
||||
run_installer( pchRequest, pchReply, &cbReplyBytes );
|
||||
|
||||
// Write the reply to the pipe.
|
||||
fSuccess = WriteFile(
|
||||
hPipe, // handle to pipe
|
||||
pchReply, // buffer to write from
|
||||
cbReplyBytes, // number of bytes to write
|
||||
&cbWritten, // number of bytes written
|
||||
NULL ); // not overlapped I/O
|
||||
|
||||
if( !fSuccess || cbReplyBytes != cbWritten ) {
|
||||
printf( ("ipc_client_thread WriteFile failed, LastError=%d.\n"), GetLastError());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Flush the pipe to allow the client to read the pipe's contents
|
||||
// before disconnecting. Then disconnect the pipe, and close the
|
||||
// handle to this pipe instance.
|
||||
|
||||
FlushFileBuffers( hPipe );
|
||||
DisconnectNamedPipe( hPipe );
|
||||
CloseHandle( hPipe );
|
||||
|
||||
HeapFree( hHeap, 0, pchRequest );
|
||||
HeapFree( hHeap, 0, pchReply );
|
||||
|
||||
printf( "ipc_client_thread exiting.\n" );
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
DWORD WINAPI ipc_server_thread( LPVOID param ) {
|
||||
ipc_server_t* server = (ipc_server_t*) param;
|
||||
|
||||
// TODO: logging
|
||||
//fp = fopen( "C:\\auto_update_poc\\log.txt", "w" );
|
||||
//setvbuf(fp, NULL, _IONBF, 0);
|
||||
|
||||
// Create security attribs
|
||||
SID_IDENTIFIER_AUTHORITY auth = { SECURITY_WORLD_SID_AUTHORITY };
|
||||
PSID sid;
|
||||
if( !AllocateAndInitializeSid( &auth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &sid ) ) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
EXPLICIT_ACCESS access = { 0 };
|
||||
access.grfAccessPermissions = FILE_ALL_ACCESS;
|
||||
access.grfAccessMode = SET_ACCESS;
|
||||
access.grfInheritance = NO_INHERITANCE;
|
||||
access.Trustee.TrusteeForm = TRUSTEE_IS_SID;
|
||||
access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
|
||||
access.Trustee.ptstrName = (LPTSTR)sid;
|
||||
|
||||
PACL acl;
|
||||
if( SetEntriesInAcl(1, &access, NULL, &acl) != ERROR_SUCCESS ) {
|
||||
FreeSid(sid);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
PSECURITY_DESCRIPTOR sd = (PSECURITY_DESCRIPTOR)LocalAlloc( LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH );
|
||||
if( !sd ) {
|
||||
FreeSid( sid );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if( !InitializeSecurityDescriptor( sd, SECURITY_DESCRIPTOR_REVISION ) ) {
|
||||
LocalFree(sd);
|
||||
FreeSid(sid);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if( !SetSecurityDescriptorDacl( sd, TRUE, acl, FALSE ) ) {
|
||||
LocalFree( sd );
|
||||
FreeSid( sid );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
SECURITY_ATTRIBUTES attribs;
|
||||
attribs.nLength = sizeof( SECURITY_ATTRIBUTES );
|
||||
attribs.lpSecurityDescriptor = sd;
|
||||
attribs.bInheritHandle = -1;
|
||||
|
||||
|
||||
// The main loop creates an instance of the named pipe and
|
||||
// then waits for a client to connect to it. When the client
|
||||
// connects, a thread is created to handle communications
|
||||
// with that client, and this loop is free to wait for the
|
||||
// next client connect request. It is an infinite loop.
|
||||
|
||||
for( ; ; ) {
|
||||
printf( "\nPipe Server: Main thread awaiting client connection on %s\n", PIPE_NAME );
|
||||
HANDLE hPipe = CreateNamedPipe(
|
||||
PIPE_NAME, // pipe name
|
||||
PIPE_ACCESS_DUPLEX, // read/write access
|
||||
PIPE_TYPE_MESSAGE | // message type pipe
|
||||
PIPE_READMODE_MESSAGE | // message-read mode
|
||||
PIPE_WAIT, // blocking mode
|
||||
PIPE_UNLIMITED_INSTANCES, // max. instances
|
||||
BUFSIZE, // output buffer size
|
||||
BUFSIZE, // input buffer size
|
||||
0, // client time-out
|
||||
&attribs ); // default security attribute
|
||||
|
||||
if( hPipe == INVALID_HANDLE_VALUE ) {
|
||||
printf( "CreateNamedPipe failed, LastError=%d.\n", GetLastError() );
|
||||
LocalFree( acl );
|
||||
LocalFree( sd );
|
||||
FreeSid( sid );
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Wait for the client to connect; if it succeeds,
|
||||
// the function returns a nonzero value. If the function
|
||||
// returns zero, GetLastError returns ERROR_PIPE_CONNECTED.
|
||||
|
||||
BOOL fConnected = ConnectNamedPipe( hPipe, NULL ) ?
|
||||
TRUE : ( GetLastError() == ERROR_PIPE_CONNECTED );
|
||||
|
||||
if( fConnected ) {
|
||||
printf( "Client connected, creating a processing thread.\n" );
|
||||
|
||||
// Create a thread for this client.
|
||||
DWORD dwThreadId = 0;
|
||||
HANDLE hThread = CreateThread(
|
||||
NULL, // no security attribute
|
||||
0, // default stack size
|
||||
ipc_client_thread, // thread proc
|
||||
(LPVOID) hPipe, // thread parameter
|
||||
0, // not suspended
|
||||
&dwThreadId ); // returns thread ID
|
||||
|
||||
if( hThread == NULL ) {
|
||||
printf( "CreateThread failed, LastError=%d.\n", GetLastError() );
|
||||
LocalFree( acl );
|
||||
LocalFree( sd );
|
||||
FreeSid( sid );
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
CloseHandle( hThread );
|
||||
}
|
||||
} else {
|
||||
// The client could not connect, so close the pipe.
|
||||
CloseHandle( hPipe );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LocalFree( acl );
|
||||
LocalFree( sd );
|
||||
FreeSid( sid );
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
ipc_server_t* ipc_server_start() {
|
||||
DWORD threadId = 0;
|
||||
HANDLE thread = CreateThread(
|
||||
NULL, // default security attributes
|
||||
0, // use default stack size
|
||||
ipc_server_thread, // thread function name
|
||||
NULL, // argument to thread function
|
||||
0, // use default creation flags
|
||||
&threadId ); // returns the thread identifier
|
||||
|
||||
ipc_server_t* server = new ipc_server_t;
|
||||
server->thread = thread;
|
||||
return server;
|
||||
}
|
||||
|
||||
|
||||
void ipc_server_stop( ipc_server_t* server ) {
|
||||
TerminateThread( server->thread, EXIT_SUCCESS );
|
||||
WaitForSingleObject( server->thread, INFINITE );
|
||||
delete server;
|
||||
}
|
10
auto_update/package.json
Normal file
10
auto_update/package.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "auto_update",
|
||||
"version": "0.0.1",
|
||||
"description": "SDA Auto Update",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"preinstall": "npm run build",
|
||||
"build": "cl auto_update_helper.cpp /O2 /MT /nologo /link /SUBSYSTEM:CONSOLE"
|
||||
}
|
||||
}
|
@ -176,7 +176,8 @@
|
||||
"shell-path": "2.1.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"screen-snippet": "git+https://github.com/symphonyoss/ScreenSnippet2.git#v1.0.11",
|
||||
"auto-update": "file:auto_update",
|
||||
"screen-snippet": "git+https://github.com/symphonyoss/ScreenSnippet2.git#v2.0.0",
|
||||
"screen-share-indicator-frame": "git+https://github.com/symphonyoss/ScreenShareIndicatorFrame.git#v1.4.10",
|
||||
"swift-search": "2.0.2"
|
||||
},
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { app } from 'electron';
|
||||
import { app, powerSaveBlocker } from 'electron';
|
||||
import { logger } from '../common/logger';
|
||||
|
||||
class AppStateHandler {
|
||||
private id?: number;
|
||||
|
||||
/**
|
||||
* Restarts the app with the command line arguments
|
||||
* passed from the previous session
|
||||
@ -11,6 +12,33 @@ class AppStateHandler {
|
||||
app.relaunch();
|
||||
app.exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent the display to go to sleep
|
||||
*/
|
||||
public preventDisplaySleep(preventSleep: boolean) {
|
||||
logger.info(
|
||||
'App-state: preventDisplaySleep, preventSleep: ' + preventSleep,
|
||||
);
|
||||
|
||||
if (preventSleep) {
|
||||
if (this.id) {
|
||||
logger.info(
|
||||
'App-state: Stop previous power save blocker, id: ' + this.id,
|
||||
);
|
||||
powerSaveBlocker.stop(this.id);
|
||||
this.id = undefined;
|
||||
}
|
||||
this.id = powerSaveBlocker.start('prevent-display-sleep');
|
||||
logger.info('App-state: Prevent display to sleep, id: ' + this.id);
|
||||
} else {
|
||||
if (this.id) {
|
||||
logger.info('App-state: Allow display to sleep, id: ' + this.id);
|
||||
powerSaveBlocker.stop(this.id);
|
||||
this.id = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const appStateHandler = new AppStateHandler();
|
||||
|
@ -207,6 +207,7 @@ ipcMain.on(
|
||||
case apiCmds.setIsInMeeting:
|
||||
if (typeof arg.isInMeeting === 'boolean') {
|
||||
memoryMonitor.setMeetingStatus(arg.isInMeeting);
|
||||
appStateHandler.preventDisplaySleep(arg.isInMeeting);
|
||||
}
|
||||
break;
|
||||
case apiCmds.memoryInfo:
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { app, BrowserWindow, ipcMain, nativeImage } from 'electron';
|
||||
import { app, BrowserWindow, clipboard, ipcMain, nativeImage } from 'electron';
|
||||
import * as fs from 'fs';
|
||||
import * as os from 'os';
|
||||
import * as path from 'path';
|
||||
@ -28,9 +28,10 @@ const readFile = util.promisify(fs.readFile);
|
||||
|
||||
class ScreenSnippet {
|
||||
private readonly tempDir: string;
|
||||
private readonly captureUtil: string;
|
||||
private readonly isOldWindows: boolean;
|
||||
private outputFilePath: string | undefined;
|
||||
private captureUtilArgs: ReadonlyArray<string> | undefined;
|
||||
private captureUtil: string;
|
||||
private captureUtilArgs: ReadonlyArray<string>;
|
||||
private child: ChildProcess | undefined;
|
||||
private focusedWindow: BrowserWindow | null = null;
|
||||
private shouldUpdateAlwaysOnTop: boolean = false;
|
||||
@ -44,18 +45,16 @@ class ScreenSnippet {
|
||||
fs.mkdirSync(this.tempDir);
|
||||
}
|
||||
}
|
||||
this.captureUtil = isMac
|
||||
? '/usr/sbin/screencapture'
|
||||
: isDevEnv
|
||||
? path.join(
|
||||
__dirname,
|
||||
'../../../node_modules/screen-snippet/ScreenSnippet.exe',
|
||||
)
|
||||
: path.join(path.dirname(app.getPath('exe')), 'ScreenSnippet.exe');
|
||||
this.isOldWindows =
|
||||
isWindowsOS && parseInt(os.release().split('.')[0], 10) < 10;
|
||||
logger.info(
|
||||
`screen-snippet-handler: isOldWindows ${
|
||||
this.isOldWindows
|
||||
} os.release: ${os.release()}`,
|
||||
);
|
||||
|
||||
if (isLinux) {
|
||||
this.captureUtil = '/usr/bin/gnome-screenshot';
|
||||
}
|
||||
this.captureUtil = '';
|
||||
this.captureUtilArgs = [];
|
||||
|
||||
ipcMain.on(
|
||||
'snippet-analytics-data',
|
||||
@ -93,23 +92,44 @@ class ScreenSnippet {
|
||||
this.tempDir,
|
||||
'symphonyImage-' + Date.now() + '.png',
|
||||
);
|
||||
|
||||
let usingClipboard = false;
|
||||
if (isMac) {
|
||||
this.captureUtil = '/usr/sbin/screencapture';
|
||||
this.captureUtilArgs = ['-i', '-s', '-t', 'png', this.outputFilePath];
|
||||
} else if (isWindowsOS) {
|
||||
if (windowHandler.isMana) {
|
||||
this.captureUtilArgs = [
|
||||
'--no-annotate',
|
||||
this.outputFilePath,
|
||||
i18n.getLocale(),
|
||||
];
|
||||
if (this.isOldWindows) {
|
||||
this.captureUtil = isDevEnv
|
||||
? path.join(
|
||||
__dirname,
|
||||
'../../../node_modules/screen-snippet/ScreenSnippet.exe',
|
||||
)
|
||||
: path.join(path.dirname(app.getPath('exe')), 'ScreenSnippet.exe');
|
||||
this.captureUtilArgs = [
|
||||
'--no-annotate',
|
||||
this.outputFilePath,
|
||||
i18n.getLocale(),
|
||||
];
|
||||
} else {
|
||||
this.captureUtil = 'SnippingTool';
|
||||
this.captureUtilArgs = ['/clip'];
|
||||
usingClipboard = true;
|
||||
}
|
||||
} else {
|
||||
this.captureUtil = isDevEnv
|
||||
? path.join(
|
||||
__dirname,
|
||||
'../../../node_modules/screen-snippet/ScreenSnippet.exe',
|
||||
)
|
||||
: path.join(path.dirname(app.getPath('exe')), 'ScreenSnippet.exe');
|
||||
this.captureUtilArgs = [this.outputFilePath, i18n.getLocale()];
|
||||
}
|
||||
} else if (isLinux) {
|
||||
this.captureUtil = '/usr/bin/gnome-screenshot';
|
||||
this.captureUtilArgs = ['-a', '-f', this.outputFilePath];
|
||||
} else {
|
||||
this.captureUtilArgs = [];
|
||||
}
|
||||
|
||||
this.focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
|
||||
logger.info(
|
||||
@ -124,7 +144,17 @@ class ScreenSnippet {
|
||||
this.killChildProcess();
|
||||
}
|
||||
try {
|
||||
await this.execCmd(this.captureUtil, this.captureUtilArgs);
|
||||
if (usingClipboard) {
|
||||
logger.info(
|
||||
`screen-snippet-handler: Using clipboard when capturing screen snippet`,
|
||||
);
|
||||
clipboard.clear();
|
||||
await this.execCmd(this.captureUtil, this.captureUtilArgs);
|
||||
fs.writeFileSync(this.outputFilePath, clipboard.readImage().toPNG());
|
||||
clipboard.clear();
|
||||
} else {
|
||||
await this.execCmd(this.captureUtil, this.captureUtilArgs);
|
||||
}
|
||||
if (windowHandler.isMana) {
|
||||
logger.info(
|
||||
'screen-snippet-handler: Attempting to extract image dimensions from: ' +
|
||||
@ -172,7 +202,7 @@ class ScreenSnippet {
|
||||
* Cancels a screen capture and closes the snippet window
|
||||
*/
|
||||
public async cancelCapture() {
|
||||
if (!isWindowsOS) {
|
||||
if (!isWindowsOS || windowHandler.isMana || this.captureUtil === '') {
|
||||
return;
|
||||
}
|
||||
logger.info(`screen-snippet-handler: Cancel screen capture!`);
|
||||
|
Loading…
Reference in New Issue
Block a user