3
* SVCMAIN - COM out-of-proc server main entry
7
* Copyright (C) 2006-2007 Oracle Corporation
9
* This file is part of VirtualBox Open Source Edition (OSE), as
10
* available from http://www.virtualbox.org. This file is free software;
11
* you can redistribute it and/or modify it under the terms of the GNU
12
* General Public License (GPL) as published by the Free Software
13
* Foundation, in version 2 as it comes in the "COPYING" file of the
14
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
#include "VBox/com/defs.h"
22
#include "VBox/com/VirtualBox.h"
24
#include "VirtualBoxImpl.h"
30
#include <iprt/initterm.h>
35
#define _ATL_FREE_THREADED
37
class CExeModule : public CComModule
42
HANDLE hEventShutdown;
43
void MonitorShutdown();
48
const DWORD dwTimeOut = 5000; /* time for EXE to be idle before shutting down */
49
const DWORD dwPause = 1000; /* time to wait for threads to finish up */
51
/* Passed to CreateThread to monitor the shutdown event */
52
static DWORD WINAPI MonitorProc(void* pv)
54
CExeModule* p = (CExeModule*)pv;
59
LONG CExeModule::Unlock()
61
LONG l = CComModule::Unlock();
65
SetEvent(hEventShutdown); /* tell monitor that we transitioned to zero */
70
/* Monitors the shutdown event */
71
void CExeModule::MonitorShutdown()
75
WaitForSingleObject(hEventShutdown, INFINITE);
80
dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
81
} while (dwWait == WAIT_OBJECT_0);
83
if (!bActivity && m_nLockCnt == 0) /* if no activity let's really bail */
85
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
86
CoSuspendClassObjects();
87
if (!bActivity && m_nLockCnt == 0)
92
CloseHandle(hEventShutdown);
93
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
96
bool CExeModule::StartMonitor()
98
hEventShutdown = CreateEvent(NULL, false, false, NULL);
99
if (hEventShutdown == NULL)
102
HANDLE h = CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
108
BEGIN_OBJECT_MAP(ObjectMap)
109
OBJECT_ENTRY(CLSID_VirtualBox, VirtualBox)
113
LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
115
while (p1 != NULL && *p1 != NULL)
118
while (p != NULL && *p != NULL)
129
static int WordCmpI(LPCTSTR psz1, LPCTSTR psz2) throw()
131
TCHAR c1 = (TCHAR)CharUpper((LPTSTR)*psz1);
132
TCHAR c2 = (TCHAR)CharUpper((LPTSTR)*psz2);
133
while (c1 != NULL && c1 == c2 && c1 != ' ' && c1 != '\t')
135
psz1 = CharNext(psz1);
136
psz2 = CharNext(psz2);
137
c1 = (TCHAR)CharUpper((LPTSTR)*psz1);
138
c2 = (TCHAR)CharUpper((LPTSTR)*psz2);
140
if ((c1 == NULL || c1 == ' ' || c1 == '\t') && (c2 == NULL || c2 == ' ' || c2 == '\t'))
143
return (c1 < c2) ? -1 : 1;
146
/////////////////////////////////////////////////////////////////////////////
148
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
149
HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
152
* Initialize the VBox runtime without loading
153
* the support driver.
157
lpCmdLine = GetCommandLine(); /* this line necessary for _ATL_MIN_CRT */
159
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
160
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
162
HRESULT hRes = CoInitialize(NULL);
164
_ASSERTE(SUCCEEDED(hRes));
165
_Module.Init(ObjectMap, hInstance, &LIBID_VirtualBox);
166
_Module.dwThreadID = GetCurrentThreadId();
167
TCHAR szTokens[] = _T("-/");
171
LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
172
while (lpszToken != NULL)
174
if (WordCmpI(lpszToken, _T("UnregServer")) == 0)
176
_Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, FALSE);
177
nRet = _Module.UnregisterServer(TRUE);
181
else if (WordCmpI(lpszToken, _T("RegServer")) == 0)
183
_Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, TRUE);
184
nRet = _Module.RegisterServer(TRUE);
188
else if (WordCmpI(lpszToken, _T("ReregServer")) == 0)
190
_Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, FALSE);
191
nRet = _Module.UnregisterServer(TRUE);
192
_Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, TRUE);
193
nRet = _Module.RegisterServer(TRUE);
197
else if ( (WordCmpI(lpszToken, _T("h")) == 0)
198
|| (WordCmpI(lpszToken, _T("?")) == 0))
200
TCHAR txt[]= L"Options:\n\n"
201
L"/RegServer:\tregister COM out-of-proc server\n"
202
L"/UnregServer:\tunregister COM out-of-proc server\n"
203
L"/ReregServer:\tunregister and register COM server\n"
204
L"no options:\trun the server";
205
TCHAR title[]=_T("Usage");
208
MessageBox(NULL, txt, title, MB_OK);
211
else if (WordCmpI (lpszToken, _T("Helper")) == 0)
213
Log (("SVCMAIN: Processing Helper request (cmdline=\"%ls\")...\n",
216
TCHAR szTokens[] = _T (" \t");
218
int vrc = VINF_SUCCESS;
221
lpszToken = FindOneOf (lpszToken, szTokens);
224
while (*lpszToken != NULL &&
225
(*lpszToken == ' ' || *lpszToken == '\t'))
228
if (*lpszToken != NULL)
229
pipeName = Utf8Str(lpszToken);
232
if (pipeName.isEmpty())
233
vrc = VERR_INVALID_PARAMETER;
237
/* do the helper job */
239
vrc = server.open(pipeName.c_str());
245
Utf8Str err = Utf8StrFmt (
246
"Failed to process Helper request (%Rrc).", vrc);
247
Log (("SVCMAIN: %s\n", err.raw()));
250
/* don't run the COM server */
255
lpszToken = FindOneOf(lpszToken, szTokens);
260
_Module.StartMonitor();
261
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
262
hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
263
_ASSERTE(SUCCEEDED(hRes));
264
hRes = CoResumeClassObjects();
266
hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);
268
_ASSERTE(SUCCEEDED(hRes));
271
while (GetMessage(&msg, 0, 0, 0))
272
DispatchMessage(&msg);
274
_Module.RevokeClassObjects();
275
Sleep(dwPause); //wait for any threads to finish
280
Log(("SVCMAIN: Returning, COM server process ends.\n"));