VirtualBox

source: vbox/trunk/src/VBox/Main/win/svcmain.cpp@ 12513

Last change on this file since 12513 was 11822, checked in by vboxsync, 16 years ago

IPRT: RTR3Init cleanup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1/** @file
2 *
3 * SVCMAIN - COM out-of-proc server main entry
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
8 *
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.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#include <stdio.h>
23
24#include "VBox/com/defs.h"
25
26#include "svchlp.h"
27
28#include <VBox/err.h>
29#include <iprt/runtime.h>
30
31#include "MachineImpl.h"
32#include "HardDiskImpl.h"
33#include "DVDImageImpl.h"
34#include "FloppyImageImpl.h"
35#include "GuestOSTypeImpl.h"
36#include "ProgressImpl.h"
37#include "SystemPropertiesImpl.h"
38#include "VirtualBoxImpl.h"
39
40#include "Logging.h"
41
42#include <atlbase.h>
43#include <atlcom.h>
44
45#define _ATL_FREE_THREADED
46
47class CExeModule : public CComModule
48{
49public:
50 LONG Unlock();
51 DWORD dwThreadID;
52 HANDLE hEventShutdown;
53 void MonitorShutdown();
54 bool StartMonitor();
55 bool bActivity;
56};
57
58const DWORD dwTimeOut = 5000; /* time for EXE to be idle before shutting down */
59const DWORD dwPause = 1000; /* time to wait for threads to finish up */
60
61/* Passed to CreateThread to monitor the shutdown event */
62static DWORD WINAPI MonitorProc(void* pv)
63{
64 CExeModule* p = (CExeModule*)pv;
65 p->MonitorShutdown();
66 return 0;
67}
68
69LONG CExeModule::Unlock()
70{
71 LONG l = CComModule::Unlock();
72 if (l == 0)
73 {
74 bActivity = true;
75 SetEvent(hEventShutdown); /* tell monitor that we transitioned to zero */
76 }
77 return l;
78}
79
80/* Monitors the shutdown event */
81void CExeModule::MonitorShutdown()
82{
83 while (1)
84 {
85 WaitForSingleObject(hEventShutdown, INFINITE);
86 DWORD dwWait=0;
87 do
88 {
89 bActivity = false;
90 dwWait = WaitForSingleObject(hEventShutdown, dwTimeOut);
91 } while (dwWait == WAIT_OBJECT_0);
92 /* timed out */
93 if (!bActivity && m_nLockCnt == 0) /* if no activity let's really bail */
94 {
95#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
96 CoSuspendClassObjects();
97 if (!bActivity && m_nLockCnt == 0)
98#endif
99 break;
100 }
101 }
102 CloseHandle(hEventShutdown);
103 PostThreadMessage(dwThreadID, WM_QUIT, 0, 0);
104}
105
106bool CExeModule::StartMonitor()
107{
108 hEventShutdown = CreateEvent(NULL, false, false, NULL);
109 if (hEventShutdown == NULL)
110 return false;
111 DWORD dwThreadID;
112 HANDLE h = CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
113 return (h != NULL);
114}
115
116CExeModule _Module;
117
118BEGIN_OBJECT_MAP(ObjectMap)
119 OBJECT_ENTRY(CLSID_VirtualBox, VirtualBox)
120END_OBJECT_MAP()
121
122
123LPCTSTR FindOneOf(LPCTSTR p1, LPCTSTR p2)
124{
125 while (p1 != NULL && *p1 != NULL)
126 {
127 LPCTSTR p = p2;
128 while (p != NULL && *p != NULL)
129 {
130 if (*p1 == *p)
131 return CharNext(p1);
132 p = CharNext(p);
133 }
134 p1 = CharNext(p1);
135 }
136 return NULL;
137}
138
139static int WordCmpI(LPCTSTR psz1, LPCTSTR psz2) throw()
140{
141 TCHAR c1 = (TCHAR)CharUpper((LPTSTR)*psz1);
142 TCHAR c2 = (TCHAR)CharUpper((LPTSTR)*psz2);
143 while (c1 != NULL && c1 == c2 && c1 != ' ' && c1 != '\t')
144 {
145 psz1 = CharNext(psz1);
146 psz2 = CharNext(psz2);
147 c1 = (TCHAR)CharUpper((LPTSTR)*psz1);
148 c2 = (TCHAR)CharUpper((LPTSTR)*psz2);
149 }
150 if ((c1 == NULL || c1 == ' ' || c1 == '\t') && (c2 == NULL || c2 == ' ' || c2 == '\t'))
151 return 0;
152
153 return (c1 < c2) ? -1 : 1;
154}
155
156/////////////////////////////////////////////////////////////////////////////
157//
158extern "C" int WINAPI _tWinMain(HINSTANCE hInstance,
159 HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
160{
161 /*
162 * Initialize the VBox runtime without loading
163 * the support driver.
164 */
165 RTR3Init();
166
167 lpCmdLine = GetCommandLine(); /* this line necessary for _ATL_MIN_CRT */
168
169#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
170 HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
171#else
172 HRESULT hRes = CoInitialize(NULL);
173#endif
174 _ASSERTE(SUCCEEDED(hRes));
175 /*
176 * Need to initialize security to access performance enumerators.
177 */
178 hRes = CoInitializeSecurity(
179 NULL,
180 -1,
181 NULL,
182 NULL,
183 RPC_C_AUTHN_LEVEL_NONE,
184 RPC_C_IMP_LEVEL_IMPERSONATE,
185 NULL, EOAC_NONE, 0);
186 _ASSERTE(SUCCEEDED(hRes));
187 _Module.Init(ObjectMap, hInstance, &LIBID_VirtualBox);
188 _Module.dwThreadID = GetCurrentThreadId();
189 TCHAR szTokens[] = _T("-/");
190
191 int nRet = 0;
192 BOOL bRun = TRUE;
193 LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
194 while (lpszToken != NULL)
195 {
196 if (WordCmpI(lpszToken, _T("UnregServer")) == 0)
197 {
198 _Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, FALSE);
199 nRet = _Module.UnregisterServer(TRUE);
200 bRun = FALSE;
201 break;
202 }
203 else if (WordCmpI(lpszToken, _T("RegServer")) == 0)
204 {
205 _Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, TRUE);
206 nRet = _Module.RegisterServer(TRUE);
207 bRun = FALSE;
208 break;
209 }
210 else if (WordCmpI(lpszToken, _T("ReregServer")) == 0)
211 {
212 _Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, FALSE);
213 nRet = _Module.UnregisterServer(TRUE);
214 _Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, TRUE);
215 nRet = _Module.RegisterServer(TRUE);
216 bRun = FALSE;
217 break;
218 }
219 else if ( (WordCmpI(lpszToken, _T("h")) == 0)
220 || (WordCmpI(lpszToken, _T("?")) == 0))
221 {
222 TCHAR txt[]= L"Options:\n\n"
223 L"/RegServer:\tregister COM out-of-proc server\n"
224 L"/UnregServer:\tunregister COM out-of-proc server\n"
225 L"/ReregServer:\tunregister and register COM server\n"
226 L"no options:\trun the server";
227 TCHAR title[]=_T("Usage");
228 nRet = -1;
229 bRun = FALSE;
230 MessageBox(NULL, txt, title, MB_OK);
231 break;
232 }
233 else if (WordCmpI (lpszToken, _T("Helper")) == 0)
234 {
235 Log (("SVCMAIN: Processing Helper request (cmdline=\"%ls\")...\n",
236 lpszToken + 6));
237
238 TCHAR szTokens[] = _T (" \t");
239
240 int vrc = VINF_SUCCESS;
241 Utf8Str pipeName;
242
243 lpszToken = FindOneOf (lpszToken, szTokens);
244 if (lpszToken)
245 {
246 while (*lpszToken != NULL &&
247 (*lpszToken == ' ' || *lpszToken == '\t'))
248 ++ lpszToken;
249
250 if (*lpszToken != NULL)
251 {
252 Bstr str (lpszToken);
253 LPCTSTR lpszToken2 = FindOneOf (lpszToken, szTokens);
254 if (lpszToken2)
255 str.mutableRaw() [lpszToken2 - lpszToken] = '\0';
256 pipeName = Utf8Str (lpszToken);
257 }
258 }
259
260 if (pipeName.isEmpty())
261 vrc = VERR_INVALID_PARAMETER;
262
263 if (VBOX_SUCCESS (vrc))
264 {
265 /* do the helper job */
266 SVCHlpServer server;
267 vrc = server.open (pipeName);
268 if (VBOX_SUCCESS (vrc))
269 vrc = server.run();
270 }
271 if (VBOX_FAILURE (vrc))
272 {
273 Utf8Str err = Utf8StrFmt (
274 "Failed to process Helper request (%Vrc).", vrc);
275 Log (("SVCMAIN: %s\n", err.raw()));
276 }
277
278 /* don't run the COM server */
279 bRun = FALSE;
280 break;
281 }
282
283 lpszToken = FindOneOf(lpszToken, szTokens);
284 }
285
286 if (bRun)
287 {
288 _Module.StartMonitor();
289#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
290 hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
291 _ASSERTE(SUCCEEDED(hRes));
292 hRes = CoResumeClassObjects();
293#else
294 hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);
295#endif
296 _ASSERTE(SUCCEEDED(hRes));
297
298 MSG msg;
299 while (GetMessage(&msg, 0, 0, 0))
300 DispatchMessage(&msg);
301
302 _Module.RevokeClassObjects();
303 Sleep(dwPause); //wait for any threads to finish
304 }
305
306 _Module.Term();
307 CoUninitialize();
308 Log(("SVCMAIN: Returning, COM server process ends.\n"));
309 return nRet;
310}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette