mirror of
https://github.com/gnif/LookingGlass.git
synced 2024-11-25 14:57:20 +00:00
[host] windows: improve restart logic and remove mutex hack
Use the process handle returned by CreateProcessAsUserA to wait on the process. This results in faster response times and less polling. For example, it now restarts instantly when UAC is activated. This also removes the call to OpenProcess and rendering the mutex unnecessary. As a bonus, it should fix #298.
This commit is contained in:
parent
22920acc88
commit
323aab8ec2
@ -11,6 +11,9 @@ add_library(platform_Windows STATIC
|
|||||||
src/mousehook.c
|
src/mousehook.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# allow use of functions for Windows Vista or later
|
||||||
|
add_definitions(-D _WIN32_WINNT=0x6000)
|
||||||
|
|
||||||
add_subdirectory("capture")
|
add_subdirectory("capture")
|
||||||
|
|
||||||
FIND_PROGRAM(WINDRES_EXECUTABLE NAMES "x86_64-w64-mingw32-windres" "windres.exe" DOC "windres executable")
|
FIND_PROGRAM(WINDRES_EXECUTABLE NAMES "x86_64-w64-mingw32-windres" "windres.exe" DOC "windres executable")
|
||||||
|
@ -17,8 +17,6 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|||||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define INSTANCE_MUTEX_NAME "Global\\6f1a5eec-af3f-4a65-99dd-ebe0e4ecea55"
|
|
||||||
|
|
||||||
#include "interface/platform.h"
|
#include "interface/platform.h"
|
||||||
#include "common/ivshmem.h"
|
#include "common/ivshmem.h"
|
||||||
|
|
||||||
@ -59,8 +57,8 @@ static CreateProcessAsUserA_t f_CreateProcessAsUserA = NULL;
|
|||||||
struct Service
|
struct Service
|
||||||
{
|
{
|
||||||
FILE * logFile;
|
FILE * logFile;
|
||||||
bool running;
|
bool running;
|
||||||
DWORD processId;
|
HANDLE process;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Service service = { 0 };
|
struct Service service = { 0 };
|
||||||
@ -260,6 +258,12 @@ DWORD GetInteractiveSessionID(void)
|
|||||||
|
|
||||||
void Launch(void)
|
void Launch(void)
|
||||||
{
|
{
|
||||||
|
if (service.process)
|
||||||
|
{
|
||||||
|
CloseHandle(service.process);
|
||||||
|
service.process = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!setupAPI())
|
if (!setupAPI())
|
||||||
{
|
{
|
||||||
doLog("setupAPI failed\n");
|
doLog("setupAPI failed\n");
|
||||||
@ -353,10 +357,9 @@ void Launch(void)
|
|||||||
goto fail_exe;
|
goto fail_exe;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(pi.hProcess);
|
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
service.processId = pi.dwProcessId;
|
service.process = pi.hProcess;
|
||||||
service.running = true;
|
service.running = true;
|
||||||
|
|
||||||
fail_exe:
|
fail_exe:
|
||||||
free(exe);
|
free(exe);
|
||||||
@ -664,48 +667,60 @@ VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
|
|||||||
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
|
||||||
while(1)
|
while(1)
|
||||||
{
|
{
|
||||||
/* check if the app is running by trying to take the lock */
|
ULONGLONG launchTime;
|
||||||
bool running = true;
|
|
||||||
HANDLE m = CreateMutex(NULL, FALSE, INSTANCE_MUTEX_NAME);
|
|
||||||
if (WaitForSingleObject(m, 0) == WAIT_OBJECT_0)
|
|
||||||
{
|
|
||||||
running = false;
|
|
||||||
service.running = false;
|
|
||||||
ReleaseMutex(m);
|
|
||||||
}
|
|
||||||
CloseHandle(m);
|
|
||||||
|
|
||||||
if (!running && GetInteractiveSessionID() != 0)
|
if (GetInteractiveSessionID() != 0)
|
||||||
{
|
{
|
||||||
Launch();
|
Launch();
|
||||||
/* avoid being overly agressive in restarting */
|
launchTime = GetTickCount64();
|
||||||
Sleep(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WaitForSingleObject(ghSvcStopEvent, 100) == WAIT_OBJECT_0)
|
HANDLE waitOn[] = { ghSvcStopEvent, service.process };
|
||||||
break;
|
DWORD count = 2;
|
||||||
|
DWORD duration = INFINITE;
|
||||||
|
|
||||||
|
if (!service.running)
|
||||||
|
{
|
||||||
|
// If the service is running, wait only on ghSvcStopEvent and prepare to restart in one second.
|
||||||
|
count = 1;
|
||||||
|
duration = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (WaitForMultipleObjects(count, waitOn, FALSE, duration))
|
||||||
|
{
|
||||||
|
case WAIT_OBJECT_0:
|
||||||
|
goto stopped;
|
||||||
|
case WAIT_OBJECT_0 + 1:
|
||||||
|
{
|
||||||
|
DWORD code;
|
||||||
|
if (GetExitCodeProcess(service.process, &code))
|
||||||
|
doLog("Host application exited with code 0x%lx\n", code);
|
||||||
|
else
|
||||||
|
doLog("Failed to GetExitCodeProcess (0x%lx)\n", GetLastError());
|
||||||
|
|
||||||
|
// avoid restarting too often
|
||||||
|
if (GetTickCount64() - launchTime < 1000)
|
||||||
|
Sleep(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WAIT_FAILED:
|
||||||
|
doLog("Failed to WaitForMultipleObjects (0x%lx)\n", GetLastError());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopped:
|
||||||
if (service.running)
|
if (service.running)
|
||||||
{
|
{
|
||||||
doLog("Terminating the host application\n");
|
doLog("Terminating the host application\n");
|
||||||
HANDLE proc = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, TRUE,
|
if (TerminateProcess(service.process, 0))
|
||||||
service.processId);
|
|
||||||
if (proc)
|
|
||||||
{
|
{
|
||||||
if (TerminateProcess(proc, 0))
|
while(WaitForSingleObject(service.process, INFINITE) != WAIT_OBJECT_0) {}
|
||||||
{
|
doLog("Host application terminated\n");
|
||||||
while(WaitForSingleObject(proc, INFINITE) != WAIT_OBJECT_0) {}
|
|
||||||
doLog("Host application terminated\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
doLog("Failed to terminate the host application\n");
|
|
||||||
CloseHandle(proc);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
doLog("Failed to terminate the host application\n");
|
||||||
doLog("OpenProcess failed (%0xlx)\n", GetLastError());
|
CloseHandle(service.process);
|
||||||
}
|
service.process = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
shutdown:
|
shutdown:
|
||||||
@ -740,13 +755,5 @@ bool HandleService(int argc, char * argv[])
|
|||||||
if (StartServiceCtrlDispatcher(DispatchTable))
|
if (StartServiceCtrlDispatcher(DispatchTable))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* only allow one instance to run */
|
|
||||||
HANDLE m = CreateMutex(NULL, FALSE, INSTANCE_MUTEX_NAME);
|
|
||||||
if (WaitForSingleObject(m, 0) != WAIT_OBJECT_0)
|
|
||||||
{
|
|
||||||
CloseHandle(m);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user