VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxService/VBoxService.cpp@ 13351

最後變更 在這個檔案從13351是 12723,由 vboxsync 提交於 16 年 前

VBoxService: Added some Assert(), fixed return value of service control handler, cosmetics.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 15.5 KB
 
1/* $Id: VBoxService.cpp 12723 2008-09-25 12:10:33Z vboxsync $ */
2/** @file
3 * VBoxService - The Guest Additions Helper Service.
4 */
5
6/*
7 * Copyright (C) 2008 Sun Microsystems, Inc.
8 *
9 * Sun Microsystems, Inc. confidential
10 * All rights reserved
11 */
12
13#include "VBoxService.h"
14#ifdef VBOX_WITH_GUEST_PROPS
15 #include "VBoxVMInfo.h"
16#endif
17#include "resource.h"
18
19#define VBOXSERVICE_NAME _T("VBoxService")
20#define VBOXSERVICE_FRIENDLY_NAME _T("VBoxService")
21
22/* Global variables. */
23HANDLE gvboxDriver;
24HANDLE gStopSem;
25
26SERVICE_STATUS gvboxServiceStatus;
27DWORD gvboxServiceStatusCode;
28SERVICE_STATUS_HANDLE gvboxServiceStatusHandle;
29
30VBOXSERVICEENV gServiceEnv;
31
32/* Prototypes. */
33void writeLog (char* a_pszText, ...);
34
35/* The service table. */
36static VBOXSERVICEINFO vboxServiceTable[] =
37{
38#ifdef VBOX_WITH_GUEST_PROPS
39 {
40 "VMInfo",
41 vboxVMInfoInit,
42 vboxVMInfoThread,
43 vboxVMInfoDestroy,
44 },
45#endif
46 {
47 NULL
48 }
49};
50
51/**
52 * @todo Format code style.
53 * @todo Add full unicode support.
54 * @todo Add event log capabilities / check return values.
55 */
56
57DWORD AddAceToObjectsSecurityDescriptor (LPTSTR pszObjName,
58 SE_OBJECT_TYPE ObjectType,
59 LPTSTR pszTrustee,
60 TRUSTEE_FORM TrusteeForm,
61 DWORD dwAccessRights,
62 ACCESS_MODE AccessMode,
63 DWORD dwInheritance)
64{
65 DWORD dwRes = 0;
66 PACL pOldDACL = NULL, pNewDACL = NULL;
67 PSECURITY_DESCRIPTOR pSD = NULL;
68 EXPLICIT_ACCESS ea;
69
70 if (NULL == pszObjName)
71 return ERROR_INVALID_PARAMETER;
72
73 /* Get a pointer to the existing DACL. */
74 dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,
75 DACL_SECURITY_INFORMATION,
76 NULL, NULL, &pOldDACL, NULL, &pSD);
77 if (ERROR_SUCCESS != dwRes) {
78 writeLog("VBoxService: GetNamedSecurityInfo: Error %u\n", dwRes);
79 goto Cleanup;
80 }
81
82 /* Initialize an EXPLICIT_ACCESS structure for the new ACE. */
83 ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
84 ea.grfAccessPermissions = dwAccessRights;
85 ea.grfAccessMode = AccessMode;
86 ea.grfInheritance= dwInheritance;
87 ea.Trustee.TrusteeForm = TrusteeForm;
88 ea.Trustee.ptstrName = pszTrustee;
89
90 /* Create a new ACL that merges the new ACE into the existing DACL. */
91 dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
92 if (ERROR_SUCCESS != dwRes) {
93 writeLog("VBoxService: SetEntriesInAcl: Error %u\n", dwRes);
94 goto Cleanup;
95 }
96
97 /* Attach the new ACL as the object's DACL. */
98 dwRes = SetNamedSecurityInfo(pszObjName, ObjectType,
99 DACL_SECURITY_INFORMATION,
100 NULL, NULL, pNewDACL, NULL);
101 if (ERROR_SUCCESS != dwRes) {
102 writeLog("VBoxService: SetNamedSecurityInfo: Error %u\n", dwRes);
103 goto Cleanup;
104 }
105
106Cleanup:
107
108 if(pSD != NULL)
109 LocalFree((HLOCAL) pSD);
110 if(pNewDACL != NULL)
111 LocalFree((HLOCAL) pNewDACL);
112
113 return dwRes;
114}
115
116static void SetStatus (DWORD a_dwStatus)
117{
118 if (NULL == gvboxServiceStatusHandle) /* Program could be in testing mode, so no service environment available. */
119 return;
120
121 gvboxServiceStatusCode = a_dwStatus;
122
123 SERVICE_STATUS ss;
124 ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
125 ss.dwCurrentState = gvboxServiceStatusCode;
126 ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
127 ss.dwWin32ExitCode = NOERROR;
128 ss.dwServiceSpecificExitCode = NOERROR;
129 ss.dwCheckPoint = 0;
130 ss.dwWaitHint = 3000;
131
132 SetServiceStatus (gvboxServiceStatusHandle, &ss);
133}
134
135static int vboxStartServices (VBOXSERVICEENV *pEnv, VBOXSERVICEINFO *pTable)
136{
137 Log(("VBoxService: Starting services ...\n"));
138
139 Assert(pEnv);
140 pEnv->hStopEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
141
142 if (!pEnv->hStopEvent)
143 {
144 /* Could not create event. */
145 return VERR_NOT_SUPPORTED;
146 }
147
148 while (pTable->pszName)
149 {
150 Log(("VBoxService: Starting %s ...\n", pTable->pszName));
151
152 int rc = VINF_SUCCESS;
153
154 bool fStartThread = false;
155
156 pTable->hThread = (HANDLE)0;
157 pTable->pInstance = NULL;
158 pTable->fStarted = false;
159
160 if (pTable->pfnInit)
161 {
162 rc = pTable->pfnInit (pEnv, &pTable->pInstance, &fStartThread);
163 }
164
165 if (VBOX_FAILURE (rc))
166 {
167 writeLog("VBoxService: Failed to initialize! Error = %Vrc.\n", rc);
168 }
169 else
170 {
171 if (pTable->pfnThread && fStartThread)
172 {
173 unsigned threadid;
174
175 pTable->hThread = (HANDLE)_beginthreadex (NULL, /* security */
176 0, /* stacksize */
177 pTable->pfnThread,
178 pTable->pInstance,
179 0, /* initflag */
180 &threadid);
181
182 if (pTable->hThread == (HANDLE)(0))
183 {
184 rc = VERR_NOT_SUPPORTED;
185 }
186 }
187
188 if (VBOX_FAILURE (rc))
189 {
190 Log(("VBoxService: Failed to start the thread: %s\n", pTable->pszName));
191
192 if (pTable->pfnDestroy)
193 {
194 pTable->pfnDestroy (pEnv, pTable->pInstance);
195 }
196 }
197 else
198 {
199 pTable->fStarted = true;
200 }
201 }
202
203 /* Advance to next table element. */
204 pTable++;
205 }
206
207 Log(("VBoxService: All threads started.\n"));
208 return VINF_SUCCESS;
209}
210
211static void vboxStopServices (BOOL bAlert, VBOXSERVICEENV *pEnv, VBOXSERVICEINFO *pTable)
212{
213 /* Signal to all threads. */
214 Assert(pEnv);
215 Assert(pTable);
216 if (bAlert && (NULL != pEnv->hStopEvent))
217 {
218 Log(("VBoxService: Setting stop event ...\n"));
219 SetEvent(pEnv->hStopEvent);
220 }
221
222 while (pTable->pszName)
223 {
224 if (pTable->fStarted)
225 {
226 if (pTable->pfnThread)
227 {
228 Log(("VBoxService: Waiting for thread %s to close ...\n", pTable->pszName));
229
230 /* There is a thread, wait for termination. */
231 WaitForSingleObject(pTable->hThread, INFINITE);
232
233 CloseHandle (pTable->hThread);
234 pTable->hThread = 0;
235 }
236
237 if (pTable->pfnDestroy)
238 {
239 pTable->pfnDestroy (pEnv, pTable->pInstance);
240 }
241
242 pTable->fStarted = false;
243 }
244
245 /* Advance to next table element. */
246 pTable++;
247 }
248
249 CloseHandle (pEnv->hStopEvent);
250 SetStatus (SERVICE_STOPPED);
251}
252
253void vboxServiceStart()
254{
255 gStopSem = CreateEvent(NULL, TRUE, FALSE, NULL);
256 if (gStopSem == NULL)
257 {
258 writeLog("VBoxService: CreateEvent for stopping failed: rc = %d\n", GetLastError());
259 return;
260 }
261
262 /* Create a well-known SID for the "Builtin Users" group. */
263 PSID pBuiltinUsersSID = NULL;
264 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_LOCAL_SID_AUTHORITY;
265
266 if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,
267 SECURITY_LOCAL_RID,
268 0, 0, 0, 0, 0, 0, 0,
269 &pBuiltinUsersSID))
270 {
271 writeLog("VBoxService: AllocateAndInitializeSid: Error %u\n", GetLastError());
272 }
273
274 AddAceToObjectsSecurityDescriptor (TEXT("\\\\.\\VBoxMiniRdrDN"),
275 SE_FILE_OBJECT,
276 (LPTSTR)pBuiltinUsersSID,
277 TRUSTEE_IS_SID,
278 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
279 SET_ACCESS,
280 NO_INHERITANCE);
281
282 /* Start service threads. */
283 int rc = vboxStartServices(&gServiceEnv, vboxServiceTable);
284
285 /** @todo Add error handling. */
286
287 SetStatus (SERVICE_RUNNING);
288}
289
290DWORD WINAPI ServiceCtrlHandler (DWORD dwControl,
291 DWORD dwEventType,
292 LPVOID lpEventData,
293 LPVOID lpContext)
294{
295 DWORD rc = NO_ERROR;
296
297 switch (dwControl)
298 {
299
300 case SERVICE_CONTROL_INTERROGATE:
301 SetStatus(gvboxServiceStatusCode);
302 break;
303
304 case SERVICE_CONTROL_STOP:
305 case SERVICE_CONTROL_SHUTDOWN:
306 {
307 SetStatus(SERVICE_STOP_PENDING);
308
309 vboxStopServices(TRUE, &gServiceEnv, vboxServiceTable);
310
311 /* Don't close VBox driver here - the service might be
312 * started again. */
313 CloseHandle(gStopSem);
314
315 SetStatus(SERVICE_STOPPED);
316 }
317 break;
318
319 case SERVICE_CONTROL_SESSIONCHANGE: /* Only Win XP and up. */
320
321 switch (dwEventType)
322 {
323 case WTS_SESSION_LOGON:
324 Log(("VBoxService: A user has logged on to the session.\n"));
325 break;
326 case WTS_SESSION_LOGOFF:
327 Log(("VBoxService: A user has logged off from the session.\n"));
328 break;
329 default:
330 break;
331 }
332 break;
333
334 default:
335
336 Log(("VBoxService: Service control function not implemented: %ld\n", dwControl));
337 rc = ERROR_CALL_NOT_IMPLEMENTED;
338 break;
339 }
340 return rc;
341}
342
343void WINAPI ServiceMain (DWORD argc, LPTSTR *argv)
344{
345 Log(("VBoxService: Registering service control handler ...\n"));
346 gvboxServiceStatusHandle = RegisterServiceCtrlHandlerEx (VBOXSERVICE_NAME, ServiceCtrlHandler, NULL);
347
348 if (NULL == gvboxServiceStatusHandle)
349 {
350 DWORD dwErr = GetLastError();
351
352 switch (dwErr)
353 {
354 case ERROR_INVALID_NAME:
355 writeLog("VBoxService: Invalid service name!\n");
356 break;
357 case ERROR_SERVICE_DOES_NOT_EXIST:
358 writeLog("VBoxService: Service does not exist!\n");
359 break;
360 default:
361 writeLog("VBoxService: Could not register service control handle! Error: %ld\n", dwErr);
362 break;
363 }
364 }
365 else
366 {
367 vboxServiceStart();
368
369 while (1) {
370 Sleep (100); /** @todo */
371 }
372 }
373}
374
375int Install ()
376{
377 SC_HANDLE hService, hSCManager;
378 TCHAR imagePath[MAX_PATH] = { 0 };
379
380 GetModuleFileName(NULL,imagePath,MAX_PATH);
381 writeLog("VBoxService: Installing service ...\n");
382
383 hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
384
385 if (NULL == hSCManager) {
386 writeLog("VBoxService: Could not open SCM! Error: %d\n", GetLastError());
387 return 1;
388 }
389
390 hService = ::CreateService (hSCManager,
391 VBOXSERVICE_NAME, VBOXSERVICE_FRIENDLY_NAME,
392 SERVICE_ALL_ACCESS,
393 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
394 SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
395 imagePath, NULL, NULL, NULL, NULL, NULL);
396
397 if (NULL == hService) {
398 writeLog("VBoxService: Could not create service! Error: %d\n", GetLastError());
399 CloseServiceHandle(hSCManager);
400 return 1;
401 }
402 else
403 {
404 writeLog("VBoxService: Service successfully installed!\n");
405 }
406
407 CloseServiceHandle(hService);
408 CloseServiceHandle(hSCManager);
409
410 return 0;
411}
412
413int Uninstall ()
414{
415 SC_HANDLE hService, hSCManager;
416 hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
417
418 writeLog("VBoxService: Uninstalling service ...\n");
419
420 if (NULL == hSCManager) {
421 writeLog("VBoxService: Could not open SCM! Error: %d\n", GetLastError());
422 return 1;
423 }
424
425 hService = OpenService (hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS );
426 if (NULL == hService) {
427 writeLog("VBoxService: Could not open service! Error: %d\n", GetLastError());
428 CloseServiceHandle (hSCManager);
429 return 1;
430 }
431
432 if (FALSE == DeleteService (hService))
433 {
434 writeLog("VBoxService: Could not remove service! Error: %d\n", GetLastError());
435 CloseServiceHandle (hService);
436 CloseServiceHandle (hSCManager);
437 return 1;
438 }
439 else
440 {
441 HKEY hKey = NULL;
442 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\System"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) {
443 RegDeleteKey(hKey, VBOXSERVICE_NAME);
444 RegCloseKey(hKey);
445 }
446
447 writeLog("VBoxService: Service successfully uninstalled!\n");
448 }
449
450 CloseServiceHandle(hService);
451 CloseServiceHandle(hSCManager);
452
453 return 0;
454}
455
456void writeLog (char* a_pszText, ...)
457{
458 char szBuffer[1024] = { 0 };
459
460 Assert(a_pszText);
461
462 va_list va;
463 va_start(va, a_pszText);
464
465 RTStrPrintfV(szBuffer, sizeof(szBuffer), a_pszText, va);
466 printf(szBuffer);
467 LogRel((szBuffer));
468
469 va_end(va);
470}
471
472void printHelp (_TCHAR* a_pszName)
473{
474 Assert(a_pszName);
475 _tprintf(_T("VBoxService - Guest Additions Helper Service for Windows XP/2K/Vista\n"));
476 _tprintf(_T("Version: %d.%d.%d.%d\n\n"), VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV);
477 _tprintf(_T("Syntax:\n"));
478 _tprintf(_T("\tTo install: %ws /i\n"), a_pszName);
479 _tprintf(_T("\tTo uninstall: %ws /u\n"), a_pszName);
480 _tprintf(_T("\tTo execute from command line: %ws /t\n"), a_pszName);
481 _tprintf(_T("\tThis help text: %ws /h\n"), a_pszName);
482}
483
484int _tmain(int argc, _TCHAR* argv[])
485{
486 /* Do not use a global namespace ("Global\\") for mutex name here, will blow up NT4 compatibility! */
487 HANDLE hMutexAppRunning = CreateMutex (NULL, FALSE, VBOXSERVICE_NAME);
488 if ( (hMutexAppRunning != NULL)
489 && (GetLastError() == ERROR_ALREADY_EXISTS))
490 {
491 /* Close the mutex for this application instance. */
492 CloseHandle(hMutexAppRunning);
493 hMutexAppRunning = NULL;
494 }
495
496 int rc = RTR3Init();
497 if (RT_FAILURE(rc))
498 {
499 writeLog("VBoxService: Failed to initialise the VirtualBox runtime! Error: %d\n", rc);
500 return rc;
501 }
502
503 rc = VbglR3Init();
504 if (RT_FAILURE(rc))
505 {
506 writeLog("VBoxService: Failed to contact the VirtualBox host! Program maybe not running in a VM? Error: %d\n", rc);
507 return rc;
508 }
509
510 LogRel(("VBoxService: Started.\n"));
511
512 static SERVICE_TABLE_ENTRY const s_serviceTable[]=
513 {
514 {VBOXSERVICE_NAME, ServiceMain},
515 {NULL,NULL}
516 };
517
518 if (argc > 1)
519 {
520 if (0 == _tcsicmp(argv[1], _T("/i")))
521 Install();
522 else if (0 == _tcsicmp(argv[1], _T("/u")))
523 Uninstall();
524 else if (0 == _tcsicmp(argv[1], _T("/t")))
525 {
526 vboxServiceStart();
527
528 while (1) {
529 Sleep( 100 ); /** @todo */
530 }
531 }
532 else if (0 == _tcsicmp(argv[1], _T("/h")))
533 printHelp(argv[0]);
534
535 else {
536 _tprintf(_T("Invalid command line argument: %ws\n"), argv[1]);
537 _tprintf(_T("Type %s /h to display help.\n"), argv[0]);
538 }
539 }
540 else /* Normal service. */
541 {
542 if (FALSE == StartServiceCtrlDispatcher (s_serviceTable))
543 printHelp(argv[0]); /* Application called from command line, print some help. */
544 }
545
546 /* Release instance mutex. */
547 if (hMutexAppRunning != NULL) {
548 CloseHandle (hMutexAppRunning);
549 hMutexAppRunning = NULL;
550 }
551
552 writeLog("VBoxService: Ended.\n");
553
554 VbglR3Term();
555 return 0;
556}
557
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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