VirtualBox

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

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

Main: reworked listener objects creation, fixes Win problems with events, few cleanups

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

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