2025-04-27 07:49:33 -04:00

355 lines
8.5 KiB
C++

/*++
Copyright (C) 1996-1999 Microsoft Corporation
Module Name:
EXEMAIN.CPP
Abstract:
EXE/COM Helpers
History:
--*/
#include "precomp.h"
#include <stdio.h>
#include <tchar.h>
#include "commain.cpp"
static DWORD g_dwMainThreadId = 0xFFFFFFFF;
class CExeLifeControl : public CLifeControl
{
protected:
long m_lNumObjects;
BOOL m_bUnloading;
CMyCritSec m_cs;
protected:
virtual void Quit()
{
PostThreadMessage(g_dwMainThreadId, WM_QUIT, 0, 0);
}
public:
CExeLifeControl() : m_lNumObjects(0), m_bUnloading(FALSE){}
virtual BOOL ObjectCreated(IUnknown* pv)
{
CMyInCritSec ics(&m_cs);
if(m_bUnloading)
return FALSE;
m_lNumObjects++;
return TRUE;
}
virtual void ObjectDestroyed(IUnknown* pv)
{
EnterCriticalSection(&m_cs);
long l = --m_lNumObjects;
if(l == 0)
{
m_bUnloading = TRUE;
LeaveCriticalSection(&m_cs);
Quit();
}
else
{
LeaveCriticalSection(&m_cs);
}
}
virtual void AddRef(IUnknown* pv){}
virtual void Release(IUnknown* pv){}
};
void MessageLoop()
{
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
struct ServiceInfo
{
BOOL m_bUsed;
LPTSTR m_szServiceName;
LPTSTR m_szDisplayName;
BOOL m_bAuto;
HANDLE m_hEvent;
SERVICE_STATUS_HANDLE m_hStatus;
ServiceInfo() : m_bUsed(FALSE){}
} g_ServiceInfo;
void SetServiceInfo(LPTSTR szServiceName, LPTSTR szDisplayName, BOOL bAuto)
{
g_ServiceInfo.m_bUsed = TRUE;
g_ServiceInfo.m_szServiceName = szServiceName;
g_ServiceInfo.m_szDisplayName = szDisplayName;
g_ServiceInfo.m_bAuto = bAuto;
}
void WINAPI ServiceHandler(DWORD dwControl)
{
SERVICE_STATUS Status;
Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
Status.dwCurrentState = SERVICE_RUNNING;
Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
Status.dwWin32ExitCode = NO_ERROR;
Status.dwCheckPoint = 0;
Status.dwWaitHint = 0;
if(!SetServiceStatus(g_ServiceInfo.m_hStatus, &Status))
{
long lRes = GetLastError();
return;
}
switch(dwControl)
{
case SERVICE_CONTROL_STOP:
Status.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(g_ServiceInfo.m_hStatus, &Status);
SetEvent(g_ServiceInfo.m_hEvent);
ExitProcess(0);
return;
case SERVICE_CONTROL_PAUSE:
case SERVICE_CONTROL_CONTINUE:
case SERVICE_CONTROL_INTERROGATE:
case SERVICE_CONTROL_SHUTDOWN:
return;
};
}
void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
{
g_ServiceInfo.m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
g_ServiceInfo.m_hStatus = RegisterServiceCtrlHandler(
g_ServiceInfo.m_szServiceName,
(LPHANDLER_FUNCTION)&ServiceHandler);
if(g_ServiceInfo.m_hStatus == NULL)
{
long lRes = GetLastError();
return;
}
SERVICE_STATUS Status;
Status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
Status.dwCurrentState = SERVICE_START_PENDING;
Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
Status.dwWin32ExitCode = NO_ERROR;
Status.dwCheckPoint = 0;
Status.dwWaitHint = 10000;
if(!SetServiceStatus(g_ServiceInfo.m_hStatus, &Status))
{
long lRes = GetLastError();
return;
}
Status.dwCurrentState = SERVICE_RUNNING;
if(!SetServiceStatus(g_ServiceInfo.m_hStatus, &Status))
{
long lRes = GetLastError();
return;
}
MessageLoop();
}
BOOL StartService()
{
SERVICE_TABLE_ENTRY aEntries[2];
aEntries[0].lpServiceName = g_ServiceInfo.m_szServiceName;
aEntries[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)&ServiceMain;
aEntries[1].lpServiceName = NULL;
aEntries[1].lpServiceProc = NULL;
if(!StartServiceCtrlDispatcher(aEntries))
{
long lRes = GetLastError();
return FALSE;
}
return TRUE;
}
BOOL InstallService()
{
SC_HANDLE hManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
TCHAR szFilename[1024];
GetModuleFileName(NULL, szFilename, 1023);
SC_HANDLE hService = CreateService(hManager,
g_ServiceInfo.m_szServiceName,
g_ServiceInfo.m_szDisplayName,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
g_ServiceInfo.m_bAuto?SERVICE_AUTO_START : SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
szFilename, NULL, NULL, NULL,
NULL, //Local System
NULL // no password
);
if(hService == NULL)
{
long lRes = GetLastError();
return FALSE;
}
/*
// Create AppId key
// ================
GUID AppId = *g_aClassInfos[0].m_pClsid;
char szAppId[128];
WCHAR wszAppId[128];
char szAppIdKey[128];
StringFromGUID2(*pInfo->m_pClsid, wszAppId, 128);
wcstombs(szAppId, wszAppId, 128);
strcpy(szAppIdKey, "SOFTWARE\\Classes\\AppId\\");
strcat(szAppIdKey, szAppId);
HKEY hKey1;
RegCreateKey(HKEY_LOCAL_MACHINE, szAppIdKey, &hKey1);
RegSetValueEx(hKey1, "LocalService", 0, REG_SZ,
g_ServiceInfo.m_szServiceName,
strlen(g_ServiceInfo.m_szServiceName)+1);
*/
return TRUE;
}
BOOL DeinstallService()
{
SC_HANDLE hManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
SC_HANDLE hService = OpenService(hManager, g_ServiceInfo.m_szServiceName,
SERVICE_ALL_ACCESS);
if(hService == NULL)
{
long lRes = GetLastError();
return FALSE;
}
if(!DeleteService(hService))
{
long lRes = GetLastError();
return FALSE;
}
return TRUE;
}
CLifeControl* g_pLifeControl = new CExeLifeControl;
void CALLBACK MyTimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
PostQuitMessage(0);
}
void __cdecl main()
{
LPTSTR szOrigCommandLine = GetCommandLine();
LPTSTR szCommandLine = new TCHAR[lstrlen(szOrigCommandLine)+1];
lstrcpy(szCommandLine, szOrigCommandLine);
TCHAR * pc = szCommandLine;
while(*pc)
*(pc++) = (TCHAR)toupper(*pc);
GlobalInitialize();
if(_tcsstr(szCommandLine, TEXT("-REGSERVER")) ||
_tcsstr(szCommandLine, TEXT("/REGSERVER")))
{
GlobalRegister();
for(int i = 0; i < g_pClassInfos->size(); i++)
{
CClassInfo* pInfo = (*g_pClassInfos)[i];
HRESULT hres = RegisterServer(pInfo, TRUE);
if(FAILED(hres)) return;
}
if(g_ServiceInfo.m_bUsed)
{
InstallService();
}
}
else if(_tcsstr(szCommandLine, TEXT("-UNREGSERVER")) ||
_tcsstr(szCommandLine, TEXT("/UNREGSERVER")))
{
GlobalUnregister();
for(int i = 0; i < g_pClassInfos->size(); i++)
{
CClassInfo* pInfo = (*g_pClassInfos)[i];
HRESULT hres = UnregisterServer(pInfo, TRUE);
if(FAILED(hres)) return;
}
if(g_ServiceInfo.m_bUsed)
{
DeinstallService();
}
}
else if(_tcsstr(szCommandLine, TEXT("EMBEDDING")) == NULL &&
!g_ServiceInfo.m_bUsed)
{
printf("Cannot run standalone\n");
}
else
{
int i;
GlobalInitializeCom();
for(i = 0; i < g_pClassInfos->size(); i++)
{
CClassInfo* pInfo = (*g_pClassInfos)[i];
HRESULT hres = CoRegisterClassObject(
*pInfo->m_pClsid, pInfo->m_pFactory, CLSCTX_SERVER,
REGCLS_MULTIPLEUSE, &pInfo->m_dwCookie);
if(FAILED(hres)) return;
}
if(g_ServiceInfo.m_bUsed)
{
StartService();
}
else
{
g_dwMainThreadId = GetCurrentThreadId();
MessageLoop();
}
for(i = 0; i < g_pClassInfos->size(); i++)
{
CClassInfo* pInfo = (*g_pClassInfos)[i];
HRESULT hres = CoRevokeClassObject(pInfo->m_dwCookie);
if(FAILED(hres)) return;
}
SetTimer(NULL, 0, 1000, (TIMERPROC)MyTimerProc);
MessageLoop();
GlobalUninitialize();
}
}
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR lpCmdLine,
int nCmdShow)
{
main();
return 0;
}