~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Main/win/svcmain.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 
37
 
class CExeModule : public CComModule
38
 
{
39
 
public:
40
 
    LONG Unlock();
41
 
    DWORD dwThreadID;
42
 
    HANDLE hEventShutdown;
43
 
    void MonitorShutdown();
44
 
    bool StartMonitor();
45
 
    bool bActivity;
46
 
};
47
 
 
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 */
50
 
 
51
 
/* Passed to CreateThread to monitor the shutdown event */
52
 
static DWORD WINAPI MonitorProc(void* pv)
53
 
{
54
 
    CExeModule* p = (CExeModule*)pv;
55
 
    p->MonitorShutdown();
56
 
    return 0;
57
 
}
58
 
 
59
 
LONG 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 */
71
 
void 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
 
 
96
 
bool 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
 
 
106
 
CExeModule _Module;
107
 
 
108
 
BEGIN_OBJECT_MAP(ObjectMap)
109
 
    OBJECT_ENTRY(CLSID_VirtualBox, VirtualBox)
110
 
END_OBJECT_MAP()
111
 
 
112
 
 
113
 
LPCTSTR 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
 
 
129
 
static 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
 
//
148
 
extern "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.raw()));
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
 
}