184 lines
4.7 KiB
C++
184 lines
4.7 KiB
C++
// hangcom.cpp : Implementation of WinMain
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "resource.h"
|
|
|
|
#include <initguid.h>
|
|
#include <hangcom.h>
|
|
#include "Hang.h"
|
|
|
|
|
|
|
|
const DWORD g_dwTimeOut = 5000; // time for EXE to be idle before shutting down
|
|
const DWORD g_dwPause = 1000; // time to wait for threads to finish up
|
|
|
|
CExeModule _Module;
|
|
|
|
BEGIN_OBJECT_MAP(ObjectMap)
|
|
OBJECT_ENTRY(CLSID_Hang, CHang)
|
|
END_OBJECT_MAP()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CHang
|
|
|
|
// **************************************************************************
|
|
STDMETHODIMP CHang::DoHang(UINT64 hev, DWORD dwpid)
|
|
{
|
|
HANDLE rghWait[2] = { NULL, NULL }, hevRemote, hprocRemote;
|
|
DWORD cWait = 1;
|
|
|
|
hevRemote = (HANDLE)hev;
|
|
|
|
rghWait[0] = CreateEventW(NULL, FALSE, FALSE, NULL);
|
|
if (rghWait[0] == NULL)
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
if (hevRemote != NULL)
|
|
{
|
|
hprocRemote = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwpid);
|
|
if (hprocRemote != NULL)
|
|
{
|
|
if (DuplicateHandle(hprocRemote, hevRemote, GetCurrentProcess(),
|
|
&rghWait[1], SYNCHRONIZE, FALSE, 0))
|
|
cWait = 2;
|
|
else
|
|
rghWait[1] = NULL;
|
|
|
|
CloseHandle(hprocRemote);
|
|
}
|
|
}
|
|
|
|
WaitForMultipleObjects(cWait, rghWait, FALSE, INFINITE);
|
|
|
|
CloseHandle(rghWait[0]);
|
|
if (rghWait[1] != NULL)
|
|
CloseHandle(rghWait[1]);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// main stuff
|
|
|
|
// **************************************************************************
|
|
static DWORD WINAPI MonitorProc(void* pv)
|
|
{
|
|
CExeModule* p = (CExeModule*)pv;
|
|
p->MonitorShutdown();
|
|
return 0;
|
|
}
|
|
|
|
// **************************************************************************
|
|
LONG CExeModule::Unlock()
|
|
{
|
|
LONG l = CComModule::Unlock();
|
|
if (l == 0)
|
|
{
|
|
bActivity = true;
|
|
SetEvent(hEventShutdown); // tell monitor that we transitioned to zero
|
|
}
|
|
return l;
|
|
}
|
|
|
|
// **************************************************************************
|
|
void CExeModule::MonitorShutdown()
|
|
{
|
|
DWORD dwWait = 0;
|
|
|
|
while (1)
|
|
{
|
|
WaitForSingleObject(hEventShutdown, INFINITE);
|
|
do
|
|
{
|
|
bActivity = false;
|
|
dwWait = WaitForSingleObject(hEventShutdown, g_dwTimeOut);
|
|
} while (dwWait == WAIT_OBJECT_0);
|
|
|
|
// timed out
|
|
if (bActivity == false && m_nLockCnt == 0)
|
|
break;
|
|
}
|
|
|
|
CloseHandle(hEventShutdown);
|
|
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
|
|
}
|
|
|
|
// **************************************************************************
|
|
bool CExeModule::StartMonitor()
|
|
{
|
|
HANDLE hth;
|
|
DWORD dwThreadID;
|
|
|
|
hEventShutdown = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if (hEventShutdown == NULL)
|
|
return false;
|
|
|
|
hth = CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
|
|
if (hth != NULL)
|
|
{
|
|
CloseHandle(hth);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
// **************************************************************************
|
|
extern "C" int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR, int)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
LPWSTR *argv, wszArg;
|
|
MSG msg;
|
|
int argc, i, nRet;
|
|
|
|
argv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
|
hr = CoInitialize(NULL);
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
|
|
_Module.Init(ObjectMap, hInstance, &LIBID_HANGCOMLib);
|
|
_Module.dwThreadID = GetCurrentThreadId();
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
wszArg = argv[i];
|
|
if (*wszArg == L'/' || *wszArg == L'-')
|
|
{
|
|
wszArg++;
|
|
if (_wcsicmp(wszArg, L"uninstall") == 0)
|
|
{
|
|
_Module.UpdateRegistryFromResource(IDR_Hangcom, FALSE);
|
|
nRet = _Module.UnregisterServer(TRUE);
|
|
goto done;
|
|
}
|
|
else if (_wcsicmp(wszArg, L"install") == 0)
|
|
{
|
|
_Module.UpdateRegistryFromResource(IDR_Hangcom, TRUE);
|
|
nRet = _Module.RegisterServer(TRUE);
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
|
|
_Module.StartMonitor();
|
|
hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER,
|
|
REGCLS_MULTIPLEUSE);
|
|
_ASSERTE(SUCCEEDED(hr));
|
|
|
|
while (GetMessage(&msg, 0, 0, 0))
|
|
DispatchMessage(&msg);
|
|
|
|
_Module.RevokeClassObjects();
|
|
Sleep(g_dwPause);
|
|
|
|
_Module.Term();
|
|
|
|
done:
|
|
CoUninitialize();
|
|
return nRet;
|
|
}
|