3
* SVCMAIN - COM out-of-proc server main entry
7
* Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
13
* in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14
* distribution. VirtualBox OSE is distributed in the hope that it will
15
* be useful, but WITHOUT ANY WARRANTY of any kind.
20
#include "VBox/com/defs.h"
25
#include <iprt/runtime.h>
27
#include "MachineImpl.h"
28
#include "HardDiskImpl.h"
29
#include "DVDImageImpl.h"
30
#include "FloppyImageImpl.h"
31
#include "GuestOSTypeImpl.h"
32
#include "ProgressImpl.h"
33
#include "SystemPropertiesImpl.h"
34
#include "VirtualBoxImpl.h"
41
#define _ATL_FREE_THREADED
43
class CExeModule : public CComModule
48
HANDLE hEventShutdown;
49
void MonitorShutdown();
54
const DWORD dwTimeOut = 5000; /* time for EXE to be idle before shutting down */
55
const DWORD dwPause = 1000; /* time to wait for threads to finish up */
57
/* Passed to CreateThread to monitor the shutdown event */
58
static DWORD WINAPI MonitorProc(void* pv)
60
CExeModule* p = (CExeModule*)pv;
65
LONG CExeModule::Unlock()
67
LONG l = CComModule::Unlock();
71
SetEvent(hEventShutdown); /* tell monitor that we transitioned to zero */
76
/* Monitors the shutdown event */
77
void CExeModule::MonitorShutdown()
81
WaitForSingleObject(hEventShutdown, INFINITE);
86
dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
87
} while (dwWait == WAIT_OBJECT_0);
89
if (!bActivity && m_nLockCnt == 0) /* if no activity let's really bail */
91
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
92
CoSuspendClassObjects();
93
if (!bActivity && m_nLockCnt == 0)
98
CloseHandle(hEventShutdown);
99
PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
102
bool CExeModule::StartMonitor()
104
hEventShutdown = CreateEvent(NULL, false, false, NULL);
105
if (hEventShutdown == NULL)
108
HANDLE h = CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
114
BEGIN_OBJECT_MAP(ObjectMap)
115
OBJECT_ENTRY(CLSID_VirtualBox, VirtualBox)
119
LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
121
while (p1 != NULL && *p1 != NULL)
124
while (p != NULL && *p != NULL)
135
static int WordCmpI(LPCTSTR psz1, LPCTSTR psz2) throw()
137
TCHAR c1 = (TCHAR)CharUpper((LPTSTR)*psz1);
138
TCHAR c2 = (TCHAR)CharUpper((LPTSTR)*psz2);
139
while (c1 != NULL && c1 == c2 && c1 != ' ' && c1 != '\t')
141
psz1 = CharNext(psz1);
142
psz2 = CharNext(psz2);
143
c1 = (TCHAR)CharUpper((LPTSTR)*psz1);
144
c2 = (TCHAR)CharUpper((LPTSTR)*psz2);
146
if ((c1 == NULL || c1 == ' ' || c1 == '\t') && (c2 == NULL || c2 == ' ' || c2 == '\t'))
149
return (c1 < c2) ? -1 : 1;
152
/////////////////////////////////////////////////////////////////////////////
154
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
155
HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
158
* Initialize the VBox runtime without loading
159
* the support driver.
163
lpCmdLine = GetCommandLine(); /* this line necessary for _ATL_MIN_CRT */
165
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
166
HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
168
HRESULT hRes = CoInitialize(NULL);
170
_ASSERTE(SUCCEEDED(hRes));
171
_Module.Init(ObjectMap, hInstance, &LIBID_VirtualBox);
172
_Module.dwThreadID = GetCurrentThreadId();
173
TCHAR szTokens[] = _T("-/");
177
LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
178
while (lpszToken != NULL)
180
if (WordCmpI(lpszToken, _T("UnregServer")) == 0)
182
_Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, FALSE);
183
nRet = _Module.UnregisterServer(TRUE);
187
else if (WordCmpI(lpszToken, _T("RegServer")) == 0)
189
_Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, TRUE);
190
nRet = _Module.RegisterServer(TRUE);
194
else if (WordCmpI(lpszToken, _T("ReregServer")) == 0)
196
_Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, FALSE);
197
nRet = _Module.UnregisterServer(TRUE);
198
_Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, TRUE);
199
nRet = _Module.RegisterServer(TRUE);
203
else if ( (WordCmpI(lpszToken, _T("h")) == 0)
204
|| (WordCmpI(lpszToken, _T("?")) == 0))
206
TCHAR txt[]= L"Options:\n\n"
207
L"/RegServer:\tregister COM out-of-proc server\n"
208
L"/UnregServer:\tunregister COM out-of-proc server\n"
209
L"/ReregServer:\tunregister and register COM server\n"
210
L"no options:\trun the server";
211
TCHAR title[]=_T("Usage");
214
MessageBox(NULL, txt, title, MB_OK);
217
else if (WordCmpI (lpszToken, _T("Helper")) == 0)
219
Log (("SVCMAIN: Processing Helper request (cmdline=\"%ls\")...\n",
222
TCHAR szTokens[] = _T (" \t");
224
int vrc = VINF_SUCCESS;
227
lpszToken = FindOneOf (lpszToken, szTokens);
230
while (*lpszToken != NULL &&
231
(*lpszToken == ' ' || *lpszToken == '\t'))
234
if (*lpszToken != NULL)
236
Bstr str (lpszToken);
237
LPCTSTR lpszToken2 = FindOneOf (lpszToken, szTokens);
239
str.mutableRaw() [lpszToken2 - lpszToken] = '\0';
240
pipeName = Utf8Str (lpszToken);
244
if (pipeName.isEmpty())
245
vrc = VERR_INVALID_PARAMETER;
247
if (VBOX_SUCCESS (vrc))
249
/* do the helper job */
251
vrc = server.open (pipeName);
252
if (VBOX_SUCCESS (vrc))
255
if (VBOX_FAILURE (vrc))
257
Utf8Str err = Utf8StrFmt (
258
"Failed to process Helper request (%Vrc).", vrc);
259
Log (("SVCMAIN: %s\n", err.raw()));
262
/* don't run the COM server */
267
lpszToken = FindOneOf(lpszToken, szTokens);
272
_Module.StartMonitor();
273
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
274
hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
275
_ASSERTE(SUCCEEDED(hRes));
276
hRes = CoResumeClassObjects();
278
hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);
280
_ASSERTE(SUCCEEDED(hRes));
283
while (GetMessage(&msg, 0, 0, 0))
284
DispatchMessage(&msg);
286
_Module.RevokeClassObjects();
287
Sleep(dwPause); //wait for any threads to finish
292
Log(("SVCMAIN: Returning, COM server process ends.\n"));