VirtualBox

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

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

VBoxService/common: Now works with NT4 as well.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1/* $Id: VBoxService-win.cpp 21246 2009-07-06 11:24:43Z 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
264#ifdef TARGET_NT4
265VOID WINAPI VBoxServiceWinCtrlHandler (DWORD dwControl)
266#else
267DWORD WINAPI VBoxServiceWinCtrlHandler (DWORD dwControl,
268 DWORD dwEventType,
269 LPVOID lpEventData,
270 LPVOID lpContext)
271#endif
272{
273 DWORD rc = NO_ERROR;
274
275 VBoxServiceVerbose(2, "Control handler: Control=%ld\n", dwControl);
276#ifndef TARGET_NT4
277 VBoxServiceVerbose(2, "Control handler: EventType=%ld\n", dwEventType);
278#endif
279
280 switch (dwControl)
281 {
282
283 case SERVICE_CONTROL_INTERROGATE:
284 VBoxServiceWinSetStatus(g_rcWinService);
285 break;
286
287 case SERVICE_CONTROL_STOP:
288 case SERVICE_CONTROL_SHUTDOWN:
289 {
290 VBoxServiceWinSetStatus(SERVICE_STOP_PENDING);
291
292 rc = VBoxServiceStopServices();
293
294 VBoxServiceWinSetStatus(SERVICE_STOPPED);
295 }
296 break;
297
298 case SERVICE_CONTROL_SESSIONCHANGE: /* Only Win XP and up. */
299
300#ifndef TARGET_NT4
301 switch (dwEventType)
302 {
303 /*case WTS_SESSION_LOGON:
304 VBoxServiceVerbose(2, "A user has logged on to the session.\n");
305 break;
306
307 case WTS_SESSION_LOGOFF:
308 VBoxServiceVerbose(2, "A user has logged off from the session.\n");
309 break;*/
310 default:
311 break;
312 }
313#endif /* TARGET_NT4 */
314 break;
315
316 default:
317
318 VBoxServiceVerbose(1, "Service control function not implemented: %ld\n", dwControl);
319 rc = ERROR_CALL_NOT_IMPLEMENTED;
320 break;
321 }
322
323#ifndef TARGET_NT4
324 return rc;
325#endif
326}
327
328void WINAPI VBoxServiceWinMain (DWORD argc, LPTSTR *argv)
329{
330 int rc = VINF_SUCCESS;
331
332 VBoxServiceVerbose(2, "Registering service control handler ...\n");
333#ifdef TARGET_NT4
334 g_hWinServiceStatus = RegisterServiceCtrlHandler (VBOXSERVICE_NAME, VBoxServiceWinCtrlHandler);
335#else
336 g_hWinServiceStatus = RegisterServiceCtrlHandlerEx (VBOXSERVICE_NAME, VBoxServiceWinCtrlHandler, NULL);
337#endif
338
339 if (NULL == g_hWinServiceStatus)
340 {
341 DWORD dwErr = GetLastError();
342
343 switch (dwErr)
344 {
345 case ERROR_INVALID_NAME:
346 VBoxServiceError("Invalid service name!\n");
347 break;
348 case ERROR_SERVICE_DOES_NOT_EXIST:
349 VBoxServiceError("Service does not exist!\n");
350 break;
351 default:
352 VBoxServiceError("Could not register service control handle! Error: %ld\n", dwErr);
353 break;
354 }
355 }
356 else
357 {
358 VBoxServiceVerbose(2, "Service control handler registered.\n");
359
360 rc = VBoxServiceWinStart();
361 }
362}
363
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