VirtualBox

source: vbox/trunk/src/VBox/Additions/common/VBoxService/VBoxService-win.cpp@ 21230

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

build fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.0 KB
Line 
1/* $Id: VBoxService-win.cpp 21230 2009-07-05 20:01:45Z vboxsync $ */
2/** @file
3 * VBoxService - Guest Additions Service Skeleton, Windows Specific Parts.
4 */
5
6/*
7 * Copyright (C) 2009 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
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#include <iprt/assert.h>
27#include <iprt/err.h>
28#include <VBox/VBoxGuestLib.h>
29#include "VBoxServiceInternal.h"
30
31#include <Windows.h>
32#include <process.h>
33#include <aclapi.h>
34
35DWORD g_rcWinService = 0;
36SERVICE_STATUS_HANDLE g_hWinServiceStatus = NULL;
37
38void WINAPI VBoxServiceWinMain (DWORD argc, LPTSTR *argv);
39
40static SERVICE_TABLE_ENTRY const g_aServiceTable[]=
41{
42 {VBOXSERVICE_NAME, VBoxServiceWinMain},
43 {NULL,NULL}
44};
45
46/**
47 * @todo Format code style.
48 * @todo Add full unicode support.
49 * @todo Add event log capabilities / check return values.
50 */
51DWORD VBoxServiceWinAddAceToObjectsSecurityDescriptor (LPTSTR pszObjName,
52 SE_OBJECT_TYPE ObjectType,
53 LPTSTR pszTrustee,
54 TRUSTEE_FORM TrusteeForm,
55 DWORD dwAccessRights,
56 ACCESS_MODE AccessMode,
57 DWORD dwInheritance)
58{
59 DWORD dwRes = 0;
60 PACL pOldDACL = NULL, pNewDACL = NULL;
61 PSECURITY_DESCRIPTOR pSD = NULL;
62 EXPLICIT_ACCESS ea;
63
64 if (NULL == pszObjName)
65 return ERROR_INVALID_PARAMETER;
66
67 /* Get a pointer to the existing DACL. */
68 dwRes = GetNamedSecurityInfo(pszObjName, ObjectType,
69 DACL_SECURITY_INFORMATION,
70 NULL, NULL, &pOldDACL, NULL, &pSD);
71 if (ERROR_SUCCESS != dwRes) {
72 VBoxServiceError("GetNamedSecurityInfo: Error %u\n", dwRes);
73 goto Cleanup;
74 }
75
76 /* Initialize an EXPLICIT_ACCESS structure for the new ACE. */
77 ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
78 ea.grfAccessPermissions = dwAccessRights;
79 ea.grfAccessMode = AccessMode;
80 ea.grfInheritance= dwInheritance;
81 ea.Trustee.TrusteeForm = TrusteeForm;
82 ea.Trustee.ptstrName = pszTrustee;
83
84 /* Create a new ACL that merges the new ACE into the existing DACL. */
85 dwRes = SetEntriesInAcl(1, &ea, pOldDACL, &pNewDACL);
86 if (ERROR_SUCCESS != dwRes) {
87 VBoxServiceError("SetEntriesInAcl: Error %u\n", dwRes);
88 goto Cleanup;
89 }
90
91 /* Attach the new ACL as the object's DACL. */
92 dwRes = SetNamedSecurityInfo(pszObjName, ObjectType,
93 DACL_SECURITY_INFORMATION,
94 NULL, NULL, pNewDACL, NULL);
95 if (ERROR_SUCCESS != dwRes) {
96 VBoxServiceError("SetNamedSecurityInfo: Error %u\n", dwRes);
97 goto Cleanup;
98 }
99
100Cleanup:
101
102 if(pSD != NULL)
103 LocalFree((HLOCAL) pSD);
104 if(pNewDACL != NULL)
105 LocalFree((HLOCAL) pNewDACL);
106
107 return dwRes;
108}
109
110BOOL VBoxServiceWinSetStatus (DWORD a_dwStatus)
111{
112 if (NULL == g_hWinServiceStatus) /* Program could be in testing mode, so no service environment available. */
113 return FALSE;
114
115 VBoxServiceVerbose(2, "Setting service status to: %ld\n", a_dwStatus);
116 g_rcWinService = a_dwStatus;
117
118 SERVICE_STATUS ss;
119 ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
120 ss.dwCurrentState = g_rcWinService;
121 ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
122 ss.dwWin32ExitCode = NOERROR;
123 ss.dwServiceSpecificExitCode = NOERROR;
124 ss.dwCheckPoint = 0;
125 ss.dwWaitHint = 3000;
126
127 return SetServiceStatus (g_hWinServiceStatus, &ss);
128}
129
130int VBoxServiceWinInstall ()
131{
132 SC_HANDLE hService, hSCManager;
133 TCHAR imagePath[MAX_PATH] = { 0 };
134
135 GetModuleFileName(NULL,imagePath,MAX_PATH);
136 VBoxServiceVerbose(1, "Installing service ...\n");
137
138 hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
139
140 if (NULL == hSCManager) {
141 VBoxServiceError("Could not open SCM! Error: %d\n", GetLastError());
142 return 1;
143 }
144
145 hService = ::CreateService (hSCManager,
146 VBOXSERVICE_NAME, VBOXSERVICE_FRIENDLY_NAME,
147 SERVICE_ALL_ACCESS,
148 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
149 SERVICE_DEMAND_START,SERVICE_ERROR_NORMAL,
150 imagePath, NULL, NULL, NULL, NULL, NULL);
151
152 if (NULL == hService) {
153 VBoxServiceError("Could not create service! Error: %d\n", GetLastError());
154 CloseServiceHandle(hSCManager);
155 return 1;
156 }
157 else
158 {
159 VBoxServiceVerbose(0, "Service successfully installed!\n");
160 }
161
162 CloseServiceHandle(hService);
163 CloseServiceHandle(hSCManager);
164
165 return 0;
166}
167
168int VBoxServiceWinUninstall ()
169{
170 SC_HANDLE hService, hSCManager;
171 hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
172
173 VBoxServiceVerbose(1, "Uninstalling service ...\n");
174
175 if (NULL == hSCManager) {
176 VBoxServiceError("Could not open SCM! Error: %d\n", GetLastError());
177 return 1;
178 }
179
180 hService = OpenService (hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS );
181 if (NULL == hService) {
182 VBoxServiceError("Could not open service! Error: %d\n", GetLastError());
183 CloseServiceHandle (hSCManager);
184 return 1;
185 }
186
187 if (FALSE == DeleteService (hService))
188 {
189 VBoxServiceError("Could not remove service! Error: %d\n", GetLastError());
190 CloseServiceHandle (hService);
191 CloseServiceHandle (hSCManager);
192 return 1;
193 }
194 else
195 {
196 HKEY hKey = NULL;
197 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EventLog\\System"), 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) {
198 RegDeleteKey(hKey, VBOXSERVICE_NAME);
199 RegCloseKey(hKey);
200 }
201
202 VBoxServiceVerbose(0, "Service successfully uninstalled!\n");
203 }
204
205 CloseServiceHandle(hService);
206 CloseServiceHandle(hSCManager);
207
208 return 0;
209}
210
211int VBoxServiceWinStart()
212{
213 int rc = VINF_SUCCESS;
214
215 /* Create a well-known SID for the "Builtin Users" group. */
216 PSID pBuiltinUsersSID = NULL;
217 SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_LOCAL_SID_AUTHORITY;
218
219 if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,
220 SECURITY_LOCAL_RID,
221 0, 0, 0, 0, 0, 0, 0,
222 &pBuiltinUsersSID))
223 {
224 VBoxServiceError("AllocateAndInitializeSid: Error %u\n", GetLastError());
225 }
226 else
227 {
228 DWORD dwRes = VBoxServiceWinAddAceToObjectsSecurityDescriptor (TEXT("\\\\.\\VBoxMiniRdrDN"),
229 SE_FILE_OBJECT,
230 (LPTSTR)pBuiltinUsersSID,
231 TRUSTEE_IS_SID,
232 FILE_GENERIC_READ | FILE_GENERIC_WRITE,
233 SET_ACCESS,
234 NO_INHERITANCE);
235 if (dwRes != 0)
236 {
237 rc = VERR_ACCESS_DENIED; /* Need to add some better code later. */
238 }
239 }
240
241 if (RT_SUCCESS(rc))
242 {
243 /* Notify SCM *before* we're starting the services, because the last services
244 always starts in main thread (which causes the SCM to wait because of the non-responding
245 service). */
246 VBoxServiceWinSetStatus (SERVICE_RUNNING);
247
248 /*
249 * Check that at least one service is enabled.
250 */
251 unsigned iMain = VBoxServiceGetStartedServices();
252 rc = VBoxServiceStartServices(iMain); /* Start all the services. */
253
254 if (RT_FAILURE(rc))
255 VBoxServiceWinSetStatus (SERVICE_STOPPED);
256 }
257
258 if (RT_FAILURE(rc))
259 VBoxServiceError("Service failed to start with rc=%Rrc!\n", rc);
260
261 return rc;
262}
263
264DWORD WINAPI VBoxServiceWinCtrlHandler (DWORD dwControl,
265 DWORD dwEventType,
266 LPVOID lpEventData,
267 LPVOID lpContext)
268{
269 DWORD rc = NO_ERROR;
270
271 VBoxServiceVerbose(2, "Control handler: Control=%ld, EventType=%ld\n", dwControl, dwEventType);
272 switch (dwControl)
273 {
274
275 case SERVICE_CONTROL_INTERROGATE:
276 VBoxServiceWinSetStatus(g_rcWinService);
277 break;
278
279 case SERVICE_CONTROL_STOP:
280 case SERVICE_CONTROL_SHUTDOWN:
281 {
282 VBoxServiceWinSetStatus(SERVICE_STOP_PENDING);
283
284 rc = VBoxServiceStopServices();
285
286 VBoxServiceWinSetStatus(SERVICE_STOPPED);
287 }
288 break;
289
290 case SERVICE_CONTROL_SESSIONCHANGE: /* Only Win XP and up. */
291
292 switch (dwEventType)
293 {
294
295 /*case WTS_SESSION_LOGON:
296 VBoxServiceVerbose(2, "A user has logged on to the session.\n");
297 break;
298
299 case WTS_SESSION_LOGOFF:
300 VBoxServiceVerbose(2, "A user has logged off from the session.\n");
301 break;*/
302
303 default:
304 break;
305 }
306 break;
307
308 default:
309
310 VBoxServiceVerbose(1, "Service control function not implemented: %ld\n", dwControl);
311 rc = ERROR_CALL_NOT_IMPLEMENTED;
312 break;
313 }
314 return rc;
315}
316
317void WINAPI VBoxServiceWinMain (DWORD argc, LPTSTR *argv)
318{
319 int rc = VINF_SUCCESS;
320
321 VBoxServiceVerbose(2, "Registering service control handler ...\n");
322 g_hWinServiceStatus = RegisterServiceCtrlHandlerEx (VBOXSERVICE_NAME, VBoxServiceWinCtrlHandler, NULL);
323
324 if (NULL == g_hWinServiceStatus)
325 {
326 DWORD dwErr = GetLastError();
327
328 switch (dwErr)
329 {
330 case ERROR_INVALID_NAME:
331 VBoxServiceError("Invalid service name!\n");
332 break;
333 case ERROR_SERVICE_DOES_NOT_EXIST:
334 VBoxServiceError("Service does not exist!\n");
335 break;
336 default:
337 VBoxServiceError("Could not register service control handle! Error: %ld\n", dwErr);
338 break;
339 }
340 }
341 else
342 {
343 VBoxServiceVerbose(2, "Service control handler registered.\n");
344
345 rc = VBoxServiceWinStart();
346 }
347}
348
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