VirtualBox

Changeset 29817 in vbox


Ignore:
Timestamp:
May 26, 2010 1:54:41 PM (15 years ago)
Author:
vboxsync
Message:

VBoxService: Some cleanup - started with reviewing r61961, but got carried away...

Location:
trunk/src/VBox/Additions/common/VBoxService
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/VBoxService-win.cpp

    r29762 r29817  
    55
    66/*
    7  * Copyright (C) 2009 Oracle Corporation
     7 * Copyright (C) 2009-2010 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2929#include <aclapi.h>
    3030
    31 DWORD                 g_rcWinService = 0;
     31
     32/*******************************************************************************
     33*   Internal Functions                                                         *
     34*******************************************************************************/
     35static void WINAPI vboxServiceWinMain(DWORD argc, LPTSTR *argv);
     36
     37
     38/*******************************************************************************
     39*   Global Variables                                                           *
     40*******************************************************************************/
     41static DWORD          g_dwWinServiceLastStatus = 0;
    3242SERVICE_STATUS_HANDLE g_hWinServiceStatus = NULL;
    3343/** The semaphore for the dummy Windows service. */
    3444static RTSEMEVENT     g_WindowsEvent = NIL_RTSEMEVENT;
    3545
    36 void WINAPI VBoxServiceWinMain (DWORD argc, LPTSTR *argv);
    37 
    38 static SERVICE_TABLE_ENTRY const g_aServiceTable[]=
    39 {
    40     {VBOXSERVICE_NAME, VBoxServiceWinMain},
    41     {NULL,NULL}
     46static SERVICE_TABLE_ENTRY const g_aServiceTable[] =
     47{
     48    { VBOXSERVICE_NAME, vboxServiceWinMain },
     49    { NULL,             NULL}
    4250};
    4351
     
    4856 * @todo Add event log capabilities / check return values.
    4957 */
    50 DWORD VBoxServiceWinAddAceToObjectsSecurityDescriptor(LPTSTR pszObjName,
    51                                                       SE_OBJECT_TYPE ObjectType,
    52                                                       LPTSTR pszTrustee,
    53                                                       TRUSTEE_FORM TrusteeForm,
    54                                                       DWORD dwAccessRights,
    55                                                       ACCESS_MODE AccessMode,
    56                                                       DWORD dwInheritance)
     58static DWORD vboxServiceWinAddAceToObjectsSecurityDescriptor(LPTSTR pszObjName,
     59                                                             SE_OBJECT_TYPE ObjectType,
     60                                                             LPTSTR pszTrustee,
     61                                                             TRUSTEE_FORM TrusteeForm,
     62                                                             DWORD dwAccessRights,
     63                                                             ACCESS_MODE AccessMode,
     64                                                             DWORD dwInheritance)
    5765{
    5866    DWORD dwRes = 0;
     
    7482        else
    7583            VBoxServiceError("AddAceToObjectsSecurityDescriptor: GetNamedSecurityInfo: Error %u\n", dwRes);
    76         goto Cleanup;
     84        goto l_Cleanup;
    7785    }
    7886
     
    9098    {
    9199        VBoxServiceError("AddAceToObjectsSecurityDescriptor: SetEntriesInAcl: Error %u\n", dwRes);
    92         goto Cleanup;
     100        goto l_Cleanup;
    93101    }
    94102
     
    100108    {
    101109        VBoxServiceError("AddAceToObjectsSecurityDescriptor: SetNamedSecurityInfo: Error %u\n", dwRes);
    102         goto Cleanup;
     110        goto l_Cleanup;
    103111    }
    104112
    105113    /** @todo get rid of that spaghetti jump ... */
    106 Cleanup:
     114l_Cleanup:
    107115
    108116    if(pSD != NULL)
     
    116124
    117125/** Reports our current status to the SCM. */
    118 BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint)
    119 {
    120     if (NULL == g_hWinServiceStatus) /* Program could be in testing mode, so no service environment available. */
     126static BOOL vboxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint)
     127{
     128    if (g_hWinServiceStatus == NULL) /* Program could be in testing mode, so no service environment available. */
    121129        return FALSE;
    122130
    123131    VBoxServiceVerbose(2, "Setting service status to: %ld\n", dwStatus);
    124     g_rcWinService = dwStatus;
     132    g_dwWinServiceLastStatus = dwStatus;
    125133
    126134    SERVICE_STATUS ss;
    127135    ss.dwServiceType              = SERVICE_WIN32_OWN_PROCESS;
    128     ss.dwCurrentState             = g_rcWinService;
     136    ss.dwCurrentState             = dwStatus;
    129137    ss.dwControlsAccepted         = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
    130138    ss.dwWin32ExitCode            = NO_ERROR;
     
    137145
    138146
    139 int VBoxServiceWinSetDesc(SC_HANDLE hService)
    140 {
     147/**
     148 * Reports SERVICE_STOP_PENDING to SCM.
     149 *
     150 * @param   uCheckPoint         Some number.
     151 */
     152void VBoxServiceWinSetStopPendingStatus(uint32_t uCheckPoint)
     153{
     154    vboxServiceWinSetStatus(SERVICE_STOP_PENDING, uCheckPoint);
     155}
     156
     157
     158static RTEXITCODE vboxServiceWinSetDesc(SC_HANDLE hService)
     159{
     160#ifndef TARGET_NT4
    141161    /* On W2K+ there's ChangeServiceConfig2() which lets us set some fields
    142162       like a longer service description. */
    143 #ifndef TARGET_NT4
     163    /** @todo On Vista+ SERVICE_DESCRIPTION also supports localized strings! */
    144164    SERVICE_DESCRIPTION desc;
    145     /** @todo On Vista+ SERVICE_DESCRIPTION also supports localized strings! */
    146     desc. lpDescription = VBOXSERVICE_DESCRIPTION;
    147     if (FALSE == ChangeServiceConfig2(hService,
    148                                       SERVICE_CONFIG_DESCRIPTION, /* Service info level */
    149                                       &desc))
     165    desc.lpDescription = VBOXSERVICE_DESCRIPTION;
     166    if (!ChangeServiceConfig2(hService,
     167                              SERVICE_CONFIG_DESCRIPTION, /* Service info level */
     168                              &desc))
    150169    {
    151170        VBoxServiceError("Cannot set the service description! Error: %ld\n", GetLastError());
    152         return 1;
    153     }
    154 #endif
    155     return VINF_SUCCESS;
    156 }
    157 
    158 
    159 /** Installs the service into the registry. */
    160 int VBoxServiceWinInstall(void)
    161 {
    162     SC_HANDLE hService, hSCManager;
     171        return RTEXITCODE_FAILURE;
     172    }
     173#endif
     174    return RTEXITCODE_SUCCESS;
     175}
     176
     177
     178/**
     179 * Installs the service.
     180 */
     181RTEXITCODE VBoxServiceWinInstall(void)
     182{
     183    VBoxServiceVerbose(1, "Installing service ...\n");
     184
    163185    TCHAR imagePath[MAX_PATH] = { 0 };
    164 
    165     GetModuleFileName(NULL,imagePath,MAX_PATH);
    166     VBoxServiceVerbose(1, "Installing service ...\n");
    167 
    168     hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    169 
    170     if (NULL == hSCManager)
     186    GetModuleFileName(NULL, imagePath, sizeof(imagePath));
     187
     188    SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
     189    if (hSCManager == NULL)
    171190    {
    172191        VBoxServiceError("Could not open SCM! Error: %ld\n", GetLastError());
    173         return 1;
    174     }
    175 
    176     hService = ::CreateService (hSCManager,
    177                                 VBOXSERVICE_NAME, VBOXSERVICE_FRIENDLY_NAME,
    178                                 SERVICE_ALL_ACCESS,
    179                                 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
    180                                 SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
    181                                 imagePath, NULL, NULL, NULL, NULL, NULL);
    182     int rc = VINF_SUCCESS;
    183     if (NULL == hService)
     192        return RTEXITCODE_FAILURE;
     193    }
     194
     195    RTEXITCODE rc       = RTEXITCODE_SUCCESS;
     196    SC_HANDLE  hService = CreateService(hSCManager,
     197                                        VBOXSERVICE_NAME, VBOXSERVICE_FRIENDLY_NAME,
     198                                        SERVICE_ALL_ACCESS,
     199                                        SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
     200                                        SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
     201                                        imagePath, NULL, NULL, NULL, NULL, NULL);
     202    if (hService != NULL)
     203        VBoxServiceVerbose(0, "Service successfully installed!\n");
     204    else
    184205    {
    185206        DWORD dwErr = GetLastError();
    186207        switch (dwErr)
    187208        {
    188 
    189         case ERROR_SERVICE_EXISTS:
    190 
    191             VBoxServiceVerbose(1, "Service already exists, just updating the service config.\n");
    192             hService = OpenService (hSCManager,
    193                                     VBOXSERVICE_NAME,
    194                                     SERVICE_ALL_ACCESS);
    195             if (NULL == hService)
    196             {
    197                 VBoxServiceError("Could not open service! Error: %ld\n", GetLastError());
    198                 rc = 1;
    199             }
    200             else
    201             {
    202                 if (ChangeServiceConfig (hService,
    203                                          SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
    204                                          SERVICE_DEMAND_START,
    205                                          SERVICE_ERROR_NORMAL,
    206                                          imagePath,
    207                                          NULL,
    208                                          NULL,
    209                                          NULL,
    210                                          NULL,
    211                                          NULL,
    212                                          VBOXSERVICE_FRIENDLY_NAME))
     209            case ERROR_SERVICE_EXISTS:
     210                VBoxServiceVerbose(1, "Service already exists, just updating the service config.\n");
     211                hService = OpenService(hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS);
     212                if (hService)
    213213                {
    214                     VBoxServiceVerbose(1, "The service config has been successfully updated.\n");
     214                    if (ChangeServiceConfig (hService,
     215                                             SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
     216                                             SERVICE_DEMAND_START,
     217                                             SERVICE_ERROR_NORMAL,
     218                                             imagePath,
     219                                             NULL,
     220                                             NULL,
     221                                             NULL,
     222                                             NULL,
     223                                             NULL,
     224                                             VBOXSERVICE_FRIENDLY_NAME))
     225                        VBoxServiceVerbose(1, "The service config has been successfully updated.\n");
     226                    else
     227                        rc = VBoxServiceError("Could not change service config! Error: %ld\n", GetLastError());
    215228                }
    216229                else
    217                 {
    218                     VBoxServiceError("Could not change service config! Error: %ld\n", GetLastError());
    219                     rc = 1;
    220                 }
    221             }
    222             break;
    223 
    224         default:
    225 
    226             VBoxServiceError("Could not create service! Error: %ld\n", dwErr);
    227             rc = 1;
    228             break;
    229         }
    230     }
    231     else
    232     {
    233         VBoxServiceVerbose(0, "Service successfully installed!\n");
    234     }
    235 
    236     if (RT_SUCCESS(rc))
    237         rc = VBoxServiceWinSetDesc(hService);
     230                    rc = VBoxServiceError("Could not open service! Error: %ld\n", GetLastError());
     231                break;
     232
     233            default:
     234                rc = VBoxServiceError("Could not create service! Error: %ld\n", dwErr);
     235                break;
     236        }
     237    }
     238
     239    if (rc == RTEXITCODE_SUCCESS)
     240        rc = vboxServiceWinSetDesc(hService);
    238241
    239242    CloseServiceHandle(hService);
     
    242245}
    243246
    244 /** Uninstalls the service from the registry. */
    245 int VBoxServiceWinUninstall(void)
    246 {
    247     SC_HANDLE hService, hSCManager;
    248     hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
    249 
     247/**
     248 * Uninstalls the service.
     249 */
     250RTEXITCODE VBoxServiceWinUninstall(void)
     251{
    250252    VBoxServiceVerbose(1, "Uninstalling service ...\n");
    251253
    252     if (NULL == hSCManager) {
     254    SC_HANDLE hSCManager = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);
     255    if (hSCManager == NULL)
     256    {
    253257        VBoxServiceError("Could not open SCM! Error: %d\n", GetLastError());
    254         return 1;
    255     }
    256 
    257     hService = OpenService (hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS );
    258     if (NULL == hService) {
    259         VBoxServiceError("Could not open service! Error: %d\n", GetLastError());
    260         CloseServiceHandle (hSCManager);
    261         return 1;
    262     }
    263 
    264     if (FALSE == DeleteService (hService))
    265     {
    266         VBoxServiceError("Could not remove service! Error: %d\n", GetLastError());
    267         CloseServiceHandle (hService);
    268         CloseServiceHandle (hSCManager);
    269         return 1;
     258        return RTEXITCODE_FAILURE;
     259    }
     260
     261    RTEXITCODE rcExit;
     262    SC_HANDLE  hService = OpenService(hSCManager, VBOXSERVICE_NAME, SERVICE_ALL_ACCESS );
     263    if (hService != NULL)
     264    {
     265        if (DeleteService(hService))
     266        {
     267            /*
     268             * ???
     269             */
     270            HKEY hKey = NULL;
     271            if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
     272                             "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System",
     273                             0,
     274                             KEY_ALL_ACCESS,
     275                             &hKey)
     276                == ERROR_SUCCESS)
     277            {
     278                RegDeleteKey(hKey, VBOXSERVICE_NAME);
     279                RegCloseKey(hKey);
     280            }
     281
     282            VBoxServiceVerbose(0, "Service successfully uninstalled!\n");
     283            rcExit = RTEXITCODE_SUCCESS;
     284        }
     285        else
     286            rcExit = VBoxServiceError("Could not remove service! Error: %d\n", GetLastError());
     287        CloseServiceHandle(hService);
    270288    }
    271289    else
    272     {
    273         HKEY hKey = NULL;
    274         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System", 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) {
    275             RegDeleteKey(hKey, VBOXSERVICE_NAME);
    276             RegCloseKey(hKey);
    277         }
    278 
    279         VBoxServiceVerbose(0, "Service successfully uninstalled!\n");
    280     }
    281 
    282     CloseServiceHandle(hService);
     290        rcExit = VBoxServiceError("Could not open service! Error: %d\n", GetLastError());
    283291    CloseServiceHandle(hSCManager);
    284292
    285     return 0;
    286 }
    287 
    288 
    289 int VBoxServiceWinStart(void)
     293    return rcExit;
     294}
     295
     296
     297static int vboxServiceWinStart(void)
    290298{
    291299    int rc = VINF_SUCCESS;
     
    296304    SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_LOCAL_SID_AUTHORITY;
    297305
    298     if(!AllocateAndInitializeSid(&SIDAuthWorld, 1,
    299                                  SECURITY_LOCAL_RID,
    300                                  0, 0, 0, 0, 0, 0, 0,
    301                                  &pBuiltinUsersSID))
    302     {
     306    if (!AllocateAndInitializeSid(&SIDAuthWorld, 1,
     307                                  SECURITY_LOCAL_RID,
     308                                  0, 0, 0, 0, 0, 0, 0,
     309                                  &pBuiltinUsersSID))
     310    {
     311        /**@todo r=bird: rc = RTErrConvertFromWin32(GetLastError()); ?*/
    303312        VBoxServiceError("AllocateAndInitializeSid: Error %u\n", GetLastError());
    304313    }
    305314    else
    306315    {
    307         DWORD dwRes = VBoxServiceWinAddAceToObjectsSecurityDescriptor (TEXT("\\\\.\\VBoxMiniRdrDN"),
    308                                                                        SE_FILE_OBJECT,
    309                                                                        (LPTSTR)pBuiltinUsersSID,
    310                                                                        TRUSTEE_IS_SID,
    311                                                                        FILE_GENERIC_READ | FILE_GENERIC_WRITE,
    312                                                                        SET_ACCESS,
    313                                                                        NO_INHERITANCE);
     316        DWORD dwRes = vboxServiceWinAddAceToObjectsSecurityDescriptor(TEXT("\\\\.\\VBoxMiniRdrDN"),
     317                                                                      SE_FILE_OBJECT,
     318                                                                      (LPTSTR)pBuiltinUsersSID,
     319                                                                      TRUSTEE_IS_SID,
     320                                                                      FILE_GENERIC_READ | FILE_GENERIC_WRITE,
     321                                                                      SET_ACCESS,
     322                                                                      NO_INHERITANCE);
    314323        if (dwRes != ERROR_SUCCESS)
    315324        {
     
    318327                /* If we don't find our "VBoxMiniRdrDN" (for Shared Folders) object above,
    319328                   don't report an error; it just might be not installed. Otherwise this
    320                    would cause the SCM to hang on starting up the service. */
     329                  would cause the SCM to hang on starting up the service. */
    321330                rc = VINF_SUCCESS;
    322331            }
    323             else rc = RTErrConvertFromWin32(dwRes);
     332            else
     333                rc = RTErrConvertFromWin32(dwRes);
    324334        }
    325335    }
     
    328338    if (RT_SUCCESS(rc))
    329339    {
    330         /* Notify SCM *before* we're starting the services, because the last services
    331            always starts in main thread (which causes the SCM to wait because of the non-responding
    332            service). */
    333         VBoxServiceWinSetStatus (SERVICE_RUNNING, 0);
    334 
    335340        rc = VBoxServiceStartServices();
    336         if (RT_FAILURE(rc))
    337             VBoxServiceWinSetStatus (SERVICE_STOPPED, 0);
    338     }
     341        if (RT_SUCCESS(rc))
     342        {
     343            vboxServiceWinSetStatus(SERVICE_RUNNING, 0);
     344            VBoxServiceMainWait();
     345        }
     346        else
     347            vboxServiceWinSetStatus(SERVICE_STOPPED, 0);
     348    }
     349    /**@todo r=bird: else vboxServiceWinSetStatus(SERVICE_STOPPED, 0); ? */
    339350
    340351    if (RT_FAILURE(rc))
     
    345356
    346357
     358/**
     359 * Call StartServiceCtrlDispatcher.
     360 *
     361 * The main() thread invokes this when not started in foreground mode.  It
     362 * won't return till the service is being shutdown (unless start up fails).
     363 *
     364 * @returns RTEXITCODE_SUCCESS on normal return after service shutdown.
     365 *          Something else on failure, error will have been reported.
     366 */
     367RTEXITCODE VBoxServiceWinEnterCtrlDispatcher(void)
     368{
     369    if (!StartServiceCtrlDispatcher(&g_aServiceTable[0]))
     370        return VBoxServiceError("StartServiceCtrlDispatcher: %u. Please start %s with option -f (foreground)!",
     371                                GetLastError(), g_pszProgName);
     372    return RTEXITCODE_SUCCESS;
     373}
     374
     375
    347376#ifdef TARGET_NT4
    348 VOID WINAPI VBoxServiceWinCtrlHandler(DWORD dwControl)
     377static VOID WINAPI vboxServiceWinCtrlHandler(DWORD dwControl)
    349378#else
    350 DWORD WINAPI VBoxServiceWinCtrlHandler(DWORD dwControl,
    351                                        DWORD dwEventType,
    352                                        LPVOID lpEventData,
    353                                        LPVOID lpContext)
    354 #endif
    355 {
    356     DWORD rc = NO_ERROR;
    357 
    358     VBoxServiceVerbose(2, "Control handler: Control=%ld\n", dwControl);
     379static DWORD WINAPI vboxServiceWinCtrlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
     380#endif
     381{
     382    DWORD rcRet = NO_ERROR;
     383
     384#ifdef TARGET_NT4
     385    VBoxServiceVerbose(2, "Control handler: Control=%#x\n", dwControl);
     386#else
     387    VBoxServiceVerbose(2, "Control handler: Control=%#x EventType=%#x\n", dwControl, dwEventType);
     388#endif
     389
     390    switch (dwControl)
     391    {
     392        case SERVICE_CONTROL_INTERROGATE:
     393            vboxServiceWinSetStatus(g_dwWinServiceLastStatus, 0);
     394            break;
     395
     396        case SERVICE_CONTROL_STOP:
     397        case SERVICE_CONTROL_SHUTDOWN:
     398        {
     399            vboxServiceWinSetStatus(SERVICE_STOP_PENDING, 0);
     400
     401            int rc2 = VBoxServiceStopServices();
     402            if (RT_FAILURE(rc2))
     403                rcRet = ERROR_GEN_FAILURE;
     404
     405            vboxServiceWinSetStatus(SERVICE_STOPPED, 0);
     406            break;
     407        }
     408
     409        case SERVICE_CONTROL_SESSIONCHANGE:     /* Only Win XP and up. */
    359410#ifndef TARGET_NT4
    360     VBoxServiceVerbose(2, "Control handler: EventType=%ld\n", dwEventType);
    361 #endif
    362 
    363     switch (dwControl)
    364     {
    365 
    366     case SERVICE_CONTROL_INTERROGATE:
    367         VBoxServiceWinSetStatus(g_rcWinService, 0);
    368         break;
    369 
    370     case SERVICE_CONTROL_STOP:
    371     case SERVICE_CONTROL_SHUTDOWN:
    372         {
    373             VBoxServiceWinSetStatus(SERVICE_STOP_PENDING, 0);
    374 
    375             rc = VBoxServiceStopServices();
    376 
    377             VBoxServiceWinSetStatus(SERVICE_STOPPED, 0);
    378         }
    379         break;
    380 
    381     case SERVICE_CONTROL_SESSIONCHANGE:     /* Only Win XP and up. */
     411# if 0
     412            switch (dwEventType)
     413            {
     414                case WTS_SESSION_LOGON:
     415                    VBoxServiceVerbose(2, "A user has logged on to the session.\n");
     416                    break;
     417
     418                case WTS_SESSION_LOGOFF:
     419                    VBoxServiceVerbose(2, "A user has logged off from the session.\n");
     420                    break;
     421                default:
     422                    break;
     423            }
     424# endif
     425#endif /* !TARGET_NT4 */
     426            break;
     427
     428        default:
     429            VBoxServiceVerbose(1, "Service control function not implemented: %#x\n", dwControl);
     430            rcRet = ERROR_CALL_NOT_IMPLEMENTED;
     431            break;
     432    }
    382433
    383434#ifndef TARGET_NT4
    384         switch (dwEventType)
    385         {
    386         /*case WTS_SESSION_LOGON:
    387             VBoxServiceVerbose(2, "A user has logged on to the session.\n");
    388             break;
    389 
    390         case WTS_SESSION_LOGOFF:
    391             VBoxServiceVerbose(2, "A user has logged off from the session.\n");
    392             break;*/
    393         default:
    394             break;
    395         }
    396 #endif /* TARGET_NT4 */
    397         break;
    398 
    399     default:
    400 
    401         VBoxServiceVerbose(1, "Service control function not implemented: %ld\n", dwControl);
    402         rc = ERROR_CALL_NOT_IMPLEMENTED;
    403         break;
    404     }
    405 
    406 #ifndef TARGET_NT4
    407     return rc;
    408 #endif
    409 }
    410 
    411 
    412 void WINAPI VBoxServiceWinMain(DWORD argc, LPTSTR *argv)
    413 {
    414     int rc = VINF_SUCCESS;
    415 
     435    return rcRet;
     436#endif
     437}
     438
     439
     440static void WINAPI vboxServiceWinMain(DWORD argc, LPTSTR *argv)
     441{
    416442    VBoxServiceVerbose(2, "Registering service control handler ...\n");
    417443#ifdef TARGET_NT4
    418     g_hWinServiceStatus = RegisterServiceCtrlHandler (VBOXSERVICE_NAME, VBoxServiceWinCtrlHandler);
     444    g_hWinServiceStatus = RegisterServiceCtrlHandler(VBOXSERVICE_NAME, vboxServiceWinCtrlHandler);
    419445#else
    420     g_hWinServiceStatus = RegisterServiceCtrlHandlerEx (VBOXSERVICE_NAME, VBoxServiceWinCtrlHandler, NULL);
    421 #endif
    422 
    423     if (NULL == g_hWinServiceStatus)
     446    g_hWinServiceStatus = RegisterServiceCtrlHandlerEx(VBOXSERVICE_NAME, vboxServiceWinCtrlHandler, NULL);
     447#endif
     448    if (g_hWinServiceStatus != NULL)
     449    {
     450        VBoxServiceVerbose(2, "Service control handler registered.\n");
     451        vboxServiceWinStart();
     452    }
     453    else
    424454    {
    425455        DWORD dwErr = GetLastError();
    426 
    427456        switch (dwErr)
    428457        {
    429         case ERROR_INVALID_NAME:
    430             VBoxServiceError("Invalid service name!\n");
    431             break;
    432         case ERROR_SERVICE_DOES_NOT_EXIST:
    433             VBoxServiceError("Service does not exist!\n");
    434             break;
    435         default:
    436             VBoxServiceError("Could not register service control handle! Error: %ld\n", dwErr);
    437             break;
    438         }
    439     }
    440     else
    441     {
    442         VBoxServiceVerbose(2, "Service control handler registered.\n");
    443 
    444         rc = VBoxServiceWinStart();
    445     }
    446 }
     458            case ERROR_INVALID_NAME:
     459                VBoxServiceError("Invalid service name!\n");
     460                break;
     461            case ERROR_SERVICE_DOES_NOT_EXIST:
     462                VBoxServiceError("Service does not exist!\n");
     463                break;
     464            default:
     465                VBoxServiceError("Could not register service control handle! Error: %ld\n", dwErr);
     466                break;
     467        }
     468    }
     469}
     470
  • trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp

    r29776 r29817  
    5757#ifdef RT_OS_WINDOWS
    5858/** Signal shutdown to the Windows service thread. */
    59 bool volatile g_WindowsServiceShutdown;
     59static bool volatile g_fWindowsServiceShutdown;
    6060/** Event the Windows service thread waits for shutdown. */
    61 RTSEMEVENT g_WindowsServiceEvent;
     61static RTSEMEVENT g_hEvtWindowsService;
    6262#endif
    6363
     
    155155 * Displays a syntax error message.
    156156 *
    157  * @returns 1
     157 * @returns RTEXITCODE_SYNTAX.
    158158 * @param   pszFormat   The message text.
    159159 * @param   ...         Format arguments.
    160160 */
    161 int VBoxServiceSyntax(const char *pszFormat, ...)
     161RTEXITCODE VBoxServiceSyntax(const char *pszFormat, ...)
    162162{
    163163    RTStrmPrintf(g_pStdErr, "%s: syntax error: ", g_pszProgName);
     
    168168    va_end(va);
    169169
    170     return 1;
     170    return RTEXITCODE_SYNTAX;
    171171}
    172172
     
    175175 * Displays an error message.
    176176 *
    177  * @returns 1
     177 * @returns RTEXITCODE_FAILURE.
    178178 * @param   pszFormat   The message text.
    179179 * @param   ...         Format arguments.
    180180 */
    181 int VBoxServiceError(const char *pszFormat, ...)
     181RTEXITCODE VBoxServiceError(const char *pszFormat, ...)
    182182{
    183183    RTStrmPrintf(g_pStdErr, "%s: error: ", g_pszProgName);
     
    192192    va_end(va);
    193193
    194     return 1;
     194    return RTEXITCODE_FAILURE;
    195195}
    196196
     
    308308    VBoxServiceVerbose(2, "Initializing services ...\n");
    309309    for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
    310     {
    311310        if (g_aServices[j].fEnabled)
    312311        {
     
    326325            }
    327326        }
    328     }
    329327
    330328    /*
     
    357355    }
    358356
    359 #ifdef RT_OS_WINDOWS
    360     if (RT_SUCCESS(rc))
    361     {
    362         /* Block the main thread. */
    363         VBoxServiceVerbose(1, "Waiting in main thread\n");
    364         int rc = RTSemEventCreate(&g_WindowsServiceEvent);
    365         AssertRC(rc);
    366         for (;;)
    367         {
    368             if (g_WindowsServiceShutdown)
    369                 break;
    370             rc = RTSemEventWait(g_WindowsServiceEvent, RT_INDEFINITE_WAIT);
    371             AssertRC(rc);
    372         }
    373         RTSemEventDestroy(g_WindowsServiceEvent);
    374         g_WindowsServiceEvent = NIL_RTSEMEVENT;
    375     }
    376 #endif
    377357    return rc;
    378358}
     
    389369    int rc = VINF_SUCCESS;
    390370
    391     for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
    392         ASMAtomicXchgBool(&g_aServices[j].fShutdown, true);
     371    /*
     372     * Signal all the services.
     373     */
     374    for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
     375        ASMAtomicWriteBool(&g_aServices[j].fShutdown, true);
     376
     377    /*
     378     * Do the pfnStop callback on all running services.
     379     */
    393380    for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
    394381        if (g_aServices[j].fStarted)
     
    397384            g_aServices[j].pDesc->pfnStop();
    398385        }
     386
     387    /*
     388     * Wait for all the service threads to complete.
     389     */
    399390    for (unsigned j = 0; j < RT_ELEMENTS(g_aServices); j++)
    400391    {
     
    411402#ifdef RT_OS_WINDOWS
    412403                /* Notify SCM that it takes a bit longer ... */
    413                 VBoxServiceWinSetStatus(SERVICE_STOP_PENDING, i);
     404                VBoxServiceWinSetStopPendingStatus(i + j*32);
    414405#endif
    415406            }
     
    423414#ifdef RT_OS_WINDOWS
    424415    /*
    425      * As we're now done terminating all service threads,
    426      * we have to stop the main thread as well (if defined). Note that the termination
    427      * function will be called in a later context (when the main thread returns from the worker
    428      * function).
    429      */
    430     if (g_WindowsServiceEvent != NIL_RTSEMEVENT)
     416     * Wake up and tell the main() thread that we're shutting down (it's
     417     * sleeping in VBoxServiceMainWait).
     418     */
     419    if (g_hEvtWindowsService != NIL_RTSEMEVENT)
    431420    {
    432421        VBoxServiceVerbose(3, "Stopping the main thread...\n");
    433         ASMAtomicXchgBool(&g_WindowsServiceShutdown, true);
    434         rc = RTSemEventSignal(g_WindowsServiceEvent);
     422        ASMAtomicWriteBool(&g_fWindowsServiceShutdown, true);
     423        rc = RTSemEventSignal(g_hEvtWindowsService);
    435424        AssertRC(rc);
    436425    }
     
    442431
    443432
    444 #ifndef RT_OS_WINDOWS
    445 /**
    446  * Block all important signals, then explicitly wait until one of these
    447  * signal arrives.
    448  */
    449 static void VBoxServiceWaitSignal(void)
    450 {
     433/**
     434 * Block the main thread until the service shuts down.
     435 */
     436void VBoxServiceMainWait(void)
     437{
     438    int rc;
     439
     440#ifdef RT_OS_WINDOWS
     441    /*
     442     * Wait for the semaphore to be signalled.
     443     */
     444    VBoxServiceVerbose(1, "Waiting in main thread\n");
     445    rc = RTSemEventCreate(&g_hEvtWindowsService);
     446    AssertRC(rc);
     447    while (!ASMAtomicReadBool(&g_fWindowsServiceShutdown))
     448    {
     449        rc = RTSemEventWait(g_hEvtWindowsService, RT_INDEFINITE_WAIT);
     450        AssertRC(rc);
     451    }
     452    RTSemEventDestroy(g_hEvtWindowsService);
     453    g_hEvtWindowsService = NIL_RTSEMEVENT;
     454
     455#else
     456    /*
     457     * Wait explicitly for a HUP, INT, QUIT, ABRT or TERM signal, blocking
     458     * all important signals.
     459     *
     460     * The annoying EINTR/ERESTART loop is for the benefit of Solaris where
     461     * sigwait returns when we receive a SIGCHLD.  Kind of makes sense since
     462     */
    451463    sigset_t signalMask;
    452     int iSignal;
    453464    sigemptyset(&signalMask);
    454465    sigaddset(&signalMask, SIGHUP);
     
    459470    pthread_sigmask(SIG_BLOCK, &signalMask, NULL);
    460471
    461     /* This loop is required on Solaris at least. FreeBSD doesn't know ERESTART. */
    462     int rc;
     472    int iSignal;
    463473    do
    464474    {
     
    472482          );
    473483
    474     VBoxServiceVerbose(3, "VBoxServiceWaitSignal: Received signal %d (rc=%d)\n", iSignal, rc);
    475 }
     484    VBoxServiceVerbose(3, "VBoxServiceMainWait: Received signal %d (rc=%d)\n", iSignal, rc);
    476485#endif /* !RT_OS_WINDOWS */
     486}
    477487
    478488
     
    653663     * Daemonize if requested.
    654664     */
     665    RTEXITCODE rcExit;
    655666    if (fDaemonize && !fDaemonized)
    656667    {
    657668#ifdef RT_OS_WINDOWS
    658         /** @todo Should do something like VBoxSVC here, OR automatically re-register
    659          *        the service and start it. Involving VbglR3Daemonize isn't an option
    660          *        here.
    661          *
    662          *        Also, the idea here, IIRC, was to map the sub service to windows
    663          *        services. The todo below is for mimicking windows services on
    664          *        non-windows systems. Not sure if this is doable or not, but in anycase
    665          *        this code can be moved into -win.
    666          *
    667          *        You should return when StartServiceCtrlDispatcher, btw., not
    668          *        continue.
    669          */
    670669        VBoxServiceVerbose(2, "Starting service dispatcher ...\n");
    671         if (!StartServiceCtrlDispatcher(&g_aServiceTable[0]))
    672             return VBoxServiceError("StartServiceCtrlDispatcher: %u. Please start %s with option -f (foreground)!",
    673                                     GetLastError(), g_pszProgName);
    674         /* Service now lives in the control dispatcher registered above. */
     670        rcExit = VBoxServiceWinEnterCtrlDispatcher();
    675671#else
    676672        VBoxServiceVerbose(1, "Daemonizing...\n");
     
    694690         */
    695691        rc = VBoxServiceStartServices();
    696 #ifndef RT_OS_WINDOWS
     692        rcExit = RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
    697693        if (RT_SUCCESS(rc))
    698             VBoxServiceWaitSignal();
    699 #endif
     694            VBoxServiceMainWait();
    700695        VBoxServiceStopServices();
    701696    }
     
    713708
    714709    VBoxServiceVerbose(0, "Ended.\n");
    715     return RT_SUCCESS(rc) ? 0 : 1;
    716 }
     710    return rcExit;
     711}
     712
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r29762 r29817  
    102102/** The following constant may be defined by including NtStatus.h. */
    103103# define STATUS_SUCCESS             ((NTSTATUS)0x00000000L)
     104
     105/** @todo Move these Windows stuff into VBoxServiceVMInfo-win.cpp and hide all
     106 *        the windows details using behind function calls!
     107 * @{  */
    104108/** Structure for storing the looked up user information. */
    105109typedef struct
     
    123127/** Function prototypes for dynamic loading. */
    124128typedef DWORD (WINAPI *PFNWTSGETACTIVECONSOLESESSIONID)(void);
     129/** @} */
    125130
    126131#endif /* RT_OS_WINDOWS */
     
    253258RT_C_DECLS_BEGIN
    254259
    255 extern char *g_pszProgName;
    256 extern int g_cVerbosity;
    257 extern uint32_t g_DefaultInterval;
    258 
    259 extern int VBoxServiceSyntax(const char *pszFormat, ...);
    260 extern int VBoxServiceError(const char *pszFormat, ...);
    261 extern void VBoxServiceVerbose(int iLevel, const char *pszFormat, ...);
    262 extern int VBoxServiceArgUInt32(int argc, char **argv, const char *psz, int *pi, uint32_t *pu32, uint32_t u32Min, uint32_t u32Max);
    263 extern int VBoxServiceStartServices(void);
    264 extern int VBoxServiceStopServices(void);
    265 
    266 extern VBOXSERVICE g_TimeSync;
    267 extern VBOXSERVICE g_Clipboard;
    268 extern VBOXSERVICE g_Control;
    269 extern VBOXSERVICE g_VMInfo;
    270 extern VBOXSERVICE g_CpuHotPlug;
     260extern char        *g_pszProgName;
     261extern int          g_cVerbosity;
     262extern uint32_t     g_DefaultInterval;
     263extern VBOXSERVICE  g_TimeSync;
     264extern VBOXSERVICE  g_Clipboard;
     265extern VBOXSERVICE  g_Control;
     266extern VBOXSERVICE  g_VMInfo;
     267extern VBOXSERVICE  g_CpuHotPlug;
    271268#ifdef VBOXSERVICE_MANAGEMENT
    272 extern VBOXSERVICE g_MemBalloon;
    273 extern VBOXSERVICE g_VMStatistics;
     269extern VBOXSERVICE  g_MemBalloon;
     270extern VBOXSERVICE  g_VMStatistics;
    274271#endif
    275272#ifdef VBOX_WITH_PAGE_SHARING
    276 extern VBOXSERVICE g_PageSharing;
    277 #endif
    278 
     273extern VBOXSERVICE  g_PageSharing;
     274#endif
     275
     276extern RTEXITCODE   VBoxServiceSyntax(const char *pszFormat, ...);
     277extern RTEXITCODE   VBoxServiceError(const char *pszFormat, ...);
     278extern void         VBoxServiceVerbose(int iLevel, const char *pszFormat, ...);
     279extern int          VBoxServiceArgUInt32(int argc, char **argv, const char *psz, int *pi, uint32_t *pu32,
     280                                         uint32_t u32Min, uint32_t u32Max);
     281extern int          VBoxServiceStartServices(void);
     282extern int          VBoxServiceStopServices(void);
     283extern void         VBoxServiceMainWait(void);
    279284#ifdef RT_OS_WINDOWS
    280 extern DWORD g_rcWinService;
    281 extern SERVICE_TABLE_ENTRY const g_aServiceTable[];     /** @todo generate on the fly, see comment in main() from the enabled sub services. */
     285extern RTEXITCODE   VBoxServiceWinInstall(void);
     286extern RTEXITCODE   VBoxServiceWinUninstall(void);
     287extern RTEXITCODE   VBoxServiceWinEnterCtrlDispatcher(void);
     288extern void         VBoxServiceWinSetStopPendingStatus(uint32_t uCheckPoint);
     289#endif
     290
     291#ifdef RT_OS_WINDOWS
    282292extern PFNWTSGETACTIVECONSOLESESSIONID g_pfnWTSGetActiveConsoleSessionId; /* VBoxServiceVMInfo-win.cpp */
    283 
    284 extern int  VBoxServiceWinInstall(void);
    285 extern int  VBoxServiceWinUninstall(void);
    286 extern BOOL VBoxServiceWinSetStatus(DWORD dwStatus, DWORD dwCheckPoint);
    287293# ifdef VBOX_WITH_GUEST_PROPS
    288294extern bool VBoxServiceVMInfoWinSessionHasProcesses(PLUID pSession, VBOXSERVICEVMINFOPROC const *paProcs, DWORD cProcs);
     
    295301
    296302#ifdef VBOX_WITH_GUEST_CONTROL
    297 extern int VBoxServiceControlExecProcess(uint32_t uContext, const char *pszCmd, uint32_t uFlags,
    298                                          const char *pszArgs, uint32_t uNumArgs,
    299                                          const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
    300                                          const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS);
     303extern int  VBoxServiceControlExecProcess(uint32_t uContext, const char *pszCmd, uint32_t uFlags,
     304                                          const char *pszArgs, uint32_t uNumArgs,
     305                                          const char *pszEnv, uint32_t cbEnv, uint32_t uNumEnvVars,
     306                                          const char *pszUser, const char *pszPassword, uint32_t uTimeLimitMS);
    301307extern void VBoxServiceControlExecDestroyThreadData(PVBOXSERVICECTRLTHREADDATAEXEC pThread);
    302 extern int VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
    303                                                        uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead);
    304 extern int VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
    305                                                  uint8_t *pbData, uint32_t cbData);
     308extern int  VBoxServiceControlExecReadPipeBufferContent(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
     309                                                        uint8_t *pbBuffer, uint32_t cbBuffer, uint32_t *pcbToRead);
     310extern int  VBoxServiceControlExecWritePipeBuffer(PVBOXSERVICECTRLEXECPIPEBUF pBuf,
     311                                                  uint8_t *pbData, uint32_t cbData);
    306312#endif
    307313
Note: See TracChangeset for help on using the changeset viewer.

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