VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/win/svcmain.cpp@ 35368

Last change on this file since 35368 was 35368, checked in by vboxsync, 14 years ago

Main: source re-org.

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