2020-09-30 17:12:32 +02:00

313 lines
7.5 KiB
C++

#include "private.h"
#include "ssseprox.h"
#include <shdocvw.h>
#include <mluisupp.h>
#define TF_THISMODULE TF_SEPROX
// Local functions
HANDLE OpenDeskSwitchEvent(DWORD dwDesiredAccess, BOOL bInheritHandle);
BOOL ExecURL();
BOOL ReloadChannelScreenSaver();
DWORD WINAPI SSExecThread(LPVOID pVoid);
// Constants
#define TIME_WAIT_DESKTOPSWITCH 10000 // ms (10 seconds)
#define TIME_WAIT_BEFORE_RESTART 5000 // ms (5 seconds)
// Module variables
static HANDLE s_hSEThread = NULL;
static HANDLE s_hTermEvent = NULL; // Thread Terminate event.
#pragma data_seg(".text")
static TCHAR s_szRegSubKey[] = TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\IE4 Screen Saver");
static TCHAR s_szRegLastNavURL[] = TEXT("LastNavURL");
static TCHAR s_szExecuteEvent[] = TEXT("ActSaverSEEvent");
static TCHAR s_szThreadTermEvent[] = TEXT("SETTermEvent");
#pragma data_seg()
// InitSEProx
BOOL InitSEProx
(
)
{
BOOL bResult = FALSE;
ASSERT((s_hSEThread == NULL) && (s_hTermEvent == NULL));
for (;;)
{
// Create the Thread End event.
if ((s_hTermEvent = CreateEvent(NULL, FALSE, FALSE, s_szThreadTermEvent)) == NULL)
{
ASSERT(FALSE);
break;
}
// Create the Thread.
DWORD dwThreadId;
if ((s_hSEThread = CreateThread(NULL, 1024, SSExecThread, NULL, 0, &dwThreadId)) == NULL)
{
ASSERT(FALSE);
break;
}
// Lets run really low.
SetThreadPriority(s_hSEThread, THREAD_PRIORITY_IDLE);
bResult = TRUE;
break;
}
// Cleanup on error.
if (!bResult)
{
CloseHandle(s_hTermEvent);
s_hTermEvent = NULL;
ASSERT(s_hSEThread == NULL);
}
return bResult;
}
// FreeSEProx
void FreeSEProx
(
)
{
if (s_hTermEvent != NULL)
{
SetEvent(s_hTermEvent);
CloseHandle(s_hSEThread);
s_hSEThread = NULL;
CloseHandle(s_hTermEvent);
s_hTermEvent = NULL;
}
DBG("FreeSEProx: Quitting.");
}
// SSExecThread
DWORD WINAPI SSExecThread
(
LPVOID pVoid
)
{
// Prevent webcheck from disappearing while this thread is still
// running
DllAddRef();
#define MAX_EVENTS 3
HANDLE arghEvents[MAX_EVENTS] = { NULL, NULL, NULL };
DBG("SSExecThread: Thread starting.");
#ifdef DEBUG
if(!g_fInitTable)
{
if(GetLeakDetectionFunctionTable(&LeakDetFunctionTable))
g_fInitTable = TRUE;
}
if(g_fInitTable)
LeakDetFunctionTable.pfnDebugMemLeak(DML_TYPE_THREAD | DML_BEGIN, TEXT(__FILE__), __LINE__);
#endif
for (;;)
{
// Open the thread termination event and the screen
// saver restart event for all platforms.
if (
((arghEvents[0] = OpenEvent(SYNCHRONIZE, FALSE, s_szThreadTermEvent)) == NULL)
||
((arghEvents[1] = OpenDeskSwitchEvent(SYNCHRONIZE, FALSE)) == NULL)
||
((arghEvents[2] = CreateEvent(NULL, FALSE, FALSE, s_szExecuteEvent)) == NULL)
)
{
TraceMsg(TF_ERROR, "Unable to initialize basic SSExec events");
break;
}
// NOTE: Assume we are always started in the Default desktop.
BOOL bInDefaultDesktop = TRUE;
DWORD dwResult;
do
{
DBG("SSExecThread: Waiting for signal...");
dwResult = WaitForMultipleObjects( MAX_EVENTS,
arghEvents,
FALSE,
INFINITE);
DBG("SSExecThread: Signal received!");
switch (dwResult)
{
case WAIT_OBJECT_0: // Thread Terminate Event
break;
case WAIT_OBJECT_0+1: // Desktop Switch Event
{
bInDefaultDesktop = !bInDefaultDesktop;
#ifdef _DEBUG
if (bInDefaultDesktop)
DBG("SSExecThread: Now in Default desktop.");
else
DBG("SSExecThread: Now in another desktop.");
#endif // _DEBUG
break;
}
case WAIT_OBJECT_0+2: // Execute Event
{
if (!bInDefaultDesktop)
{
DBG("SSExecThread: Waiting for default desktop switch...");
WaitForSingleObject(arghEvents[1], TIME_WAIT_DESKTOPSWITCH);
}
DBG("SSExecThread: Starting ExecURL().");
EVAL(ExecURL());
break;
}
default:
{
TraceMsg(TF_ERROR, "SSExecThread: Unknown signal!");
ASSERT(FALSE);
break;
}
}
} while (dwResult != WAIT_OBJECT_0);
break;
}
// Cleanup
for (int i = 0; i < MAX_EVENTS; i++)
{
if (arghEvents[i] != NULL)
CloseHandle(arghEvents[i]);
}
#ifdef DEBUG
if(g_fInitTable)
LeakDetFunctionTable.pfnDebugMemLeak(DML_TYPE_THREAD | DML_END, TEXT(__FILE__), __LINE__);
#endif
DBG("SSExecThread: Thread ending.");
return 0;
}
// OpenDeskSwitchEvent
HANDLE OpenDeskSwitchEvent(DWORD dwDesiredAccess, BOOL bInheritHandle)
{
HWINSTA hDefaultWinSta;
TCHAR szDefaultWinSta[32];
TCHAR szSwitchName[64];
DWORD dwNameLen;
HANDLE hResult = NULL;
for (;;)
{
if (
((hDefaultWinSta = GetProcessWindowStation()) == NULL)
||
(GetUserObjectInformation( hDefaultWinSta,
UOI_NAME,
szDefaultWinSta,
sizeof(szDefaultWinSta),
&dwNameLen) == 0)
)
{
break;
}
wnsprintf(szSwitchName, ARRAYSIZE(szSwitchName), TEXT("%s_DesktopSwitch"),
szDefaultWinSta);
hResult = OpenEvent(dwDesiredAccess, bInheritHandle, szSwitchName);
break;
}
return hResult;
}
// ExecURL
BOOL ExecURL()
{
HKEY hKey = NULL;
DWORD dwType;
TCHAR szURL[INTERNET_MAX_URL_LENGTH];
DWORD cbURLLength = sizeof(szURL);
BOOL bResult;
DBG("ExecURL()");
// Get the URL to exec from the Registry.
if (
(RegOpenKey(HKEY_CURRENT_USER, s_szRegSubKey, &hKey) == ERROR_SUCCESS)
&&
(RegQueryValueEx(hKey, s_szRegLastNavURL, NULL, &dwType, (LPBYTE)szURL, &cbURLLength) == ERROR_SUCCESS)
&&
(dwType == REG_SZ)
)
{
WCHAR wszPath[INTERNET_MAX_URL_LENGTH];
TraceMsg(TF_THISMODULE, "ExecURL('%s')", szURL);
SHTCharToUnicode(szURL, wszPath, SIZECHARS(wszPath));
bResult = SUCCEEDED(HlinkNavigateString(NULL, wszPath));
TraceMsg(TF_THISMODULE, "ExecURL: HlinkNavigateString() = %d", bResult);
}
else
bResult = FALSE;
if (hKey != NULL)
RegCloseKey(hKey);
return bResult;
}
// ReloadChannelScreenSaver
BOOL ReloadChannelScreenSaver ()
{
DBG("Reloading Channel Screen Saver...");
Sleep(TIME_WAIT_BEFORE_RESTART);
TCHAR szScreenSaverEXE[MAX_PATH];
EVAL(MLLoadString(IDS_SCREENSAVEREXE, szScreenSaverEXE, ARRAYSIZE(szScreenSaverEXE)) != 0);
return (ShellExecute( NULL, NULL, szScreenSaverEXE, NULL, NULL, SW_SHOWNORMAL) > (HINSTANCE)32);
}