VirtualBox

Changeset 47195 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Jul 16, 2013 2:48:43 PM (11 years ago)
Author:
vboxsync
Message:

VBoxTray/IPC: Now using RTLocalIpc (work in progress).

Location:
trunk/src/VBox/Additions/WINNT/VBoxTray
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxIPC.cpp

    r44529 r47195  
    11/* $Id$ */
    22/** @file
    3  * VboxIPC - IPC thread.
     3 * VBoxIPC - IPC thread, acts as a (purely) local IPC server.
     4 *           Multiple sessions are supported, whereas every session
     5 *           has its own thread for processing requests.
    46 */
    57
    68/*
    7  * Copyright (C) 2010-2011 Oracle Corporation
     9 * Copyright (C) 2010-2013 Oracle Corporation
    810 *
    911 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2123#include "VBoxIPC.h"
    2224
     25#include <iprt/asm.h>
    2326#include <iprt/assert.h>
     27#include <iprt/critsect.h>
    2428#include <iprt/err.h>
     29#include <iprt/list.h>
     30#include <iprt/localipc.h>
    2531#include <iprt/mem.h>
    2632#include <VBoxGuestInternal.h>
    2733
    2834
    29 typedef struct _VBOXIPCCONTEXT
    30 {
    31     const VBOXSERVICEENV *pEnv;
    32     HANDLE hPipe;
     35
     36
     37
     38/**
     39 * IPC context data.
     40 */
     41typedef struct VBOXIPCCONTEXT
     42{
     43    /** Pointer to the service environment. */
     44    const VBOXSERVICEENV      *pEnv;
     45    /** Handle for the local IPC server. */
     46    RTLOCALIPCSERVER           hServer;
     47    /** Critical section serializing access to the session list, the state,
     48     * the response event, the session event, and the thread event. */
     49    RTCRITSECT                 CritSect;
     50    /** List of all active IPC sessions. */
     51    RTLISTANCHOR               SessionList;
    3352
    3453} VBOXIPCCONTEXT, *PVBOXIPCCONTEXT;
    35 
    3654static VBOXIPCCONTEXT gCtx = {0};
    3755
    38 
    39 /**
    40  * Reads an IPC message from a connected client, represented by the IPC
    41  * context.
    42  *
    43  * @return  IPRT status code.
    44  * @param   pCtx                    The IPC context.
    45  * @param   pMessage                Buffer for receiving the message to be read.
    46  * @param   cbMessage               Size (in bytes) of buffer for received message.
    47  */
    48 int VBoxIPCReadMessage(PVBOXIPCCONTEXT pCtx, BYTE *pMessage, DWORD cbMessage)
    49 {
    50     int rc = VINF_SUCCESS;
    51     do
    52     {
    53         DWORD dwRead;
    54         if (!ReadFile(pCtx->hPipe, pMessage, cbMessage, &dwRead, 0))
    55         {
    56             rc = RTErrConvertFromWin32(GetLastError());
    57         }
    58         else
    59         {
    60             if (rc == VERR_MORE_DATA)
    61                 rc = VINF_SUCCESS;
    62             pMessage += dwRead;
    63             cbMessage -= dwRead;
    64         }
    65     }
    66     while (cbMessage && RT_SUCCESS(rc));
    67     return rc;
    68 }
    69 
    70 /**
    71  * Skips an IPC message by reading out the outstanding message
    72  * body to discard it.
    73  *
    74  * @return  IPRT status code.
    75  * @param   pCtx                    The IPC context.
    76  * @param   pHdr                    The header of message to skip.
    77  */
    78 int VBoxIPCSkipMessage(PVBOXIPCCONTEXT pCtx, PVBOXTRAYIPCHEADER pHdr)
    79 {
    80     Assert(pHdr->cbBody);
    81     BYTE *pbBuf = (BYTE*)RTMemAlloc(pHdr->cbBody);
    82     if (!pbBuf)
    83         return VERR_NO_MEMORY;
    84     int rc = VBoxIPCReadMessage(pCtx, pbBuf, pHdr->cbBody);
    85     RTMemFree(pbBuf);
    86     return rc;
    87 }
    88 
    89 /**
    90  * Writes an IPC message to the IPC context's client.
    91  *
    92  * @return  IPRT status code.
    93  * @param   pCtx                    The IPC context.
    94  * @param   pMessage                Pointer to message to send.
    95  * @param   cbMessage               Size (in bytes) of message to send.
    96  */
    97 int VBoxIPCWriteMessage(PVBOXIPCCONTEXT pCtx, BYTE *pMessage, DWORD cbMessage)
    98 {
    99     int rc = VINF_SUCCESS;
    100     while (RT_SUCCESS(rc))
    101     {
    102         DWORD cbWritten;
    103         if (!WriteFile(pCtx->hPipe, pMessage, cbMessage, &cbWritten, 0))
    104             rc = RTErrConvertFromWin32(GetLastError());
    105         pMessage += cbWritten;
    106     }
    107     return rc;
    108 }
    109 
    110 int VBoxIPCPostQuitMessage(PVBOXIPCCONTEXT pCtx)
    111 {
    112     VBOXTRAYIPCHEADER hdr;
    113     hdr.ulMsg = VBOXTRAYIPCMSGTYPE_IPC_QUIT;
    114     return VBoxIPCWriteMessage(pCtx, (BYTE*)&hdr, sizeof(hdr));
    115 }
    116 
    117 /**
    118  * Shows a balloon tooltip message in VBoxTray's
    119  * message area in the Windows main taskbar.
    120  *
    121  * @return  IPRT status code.
    122  * @param   pCtx                    IPC context of the caller.
    123  * @param   wParam                  wParam of received IPC message.
    124  * @param   lParam                  lParam of received IPC message.
    125  */
    126 int VBoxIPCMsgShowBalloonMsg(PVBOXIPCCONTEXT pCtx, UINT wParam, UINT lParam)
    127 {
    128     VBOXTRAYIPCMSG_SHOWBALLOONMSG msg;
    129     int rc = VBoxIPCReadMessage(pCtx,(BYTE*)&msg, sizeof(msg));
    130     if (RT_SUCCESS(rc))
    131     {
    132         hlpShowBalloonTip(ghInstance, ghwndToolWindow, ID_TRAYICON,
    133                           msg.szContent, msg.szTitle,
    134                           msg.ulShowMS, msg.ulType);
    135     }
    136     return rc;
    137 }
    138 
    139 /**
    140  * Takes action to restart VBoxTray (this application).
    141  *
    142  * @return  IPRT status code.
    143  * @param   pCtx                    IPC context of the caller.
    144  * @param   wParam                  wParam of received IPC message.
    145  * @param   lParam                  lParam of received IPC message.
    146  */
    147 int VBoxIPCMsgRestart(PVBOXIPCCONTEXT pCtx, UINT wParam, UINT lParam)
    148 {
    149     return 0;
    150 }
     56/**
     57 * IPC per-session thread data.
     58 */
     59typedef struct VBOXIPCSESSION
     60{
     61    /** The list node required to be part of the
     62     *  IPC session list. */
     63    RTLISTNODE                          Node;
     64    /** Pointer to the IPC context data. */
     65    PVBOXIPCCONTEXT volatile            pCtx;
     66    /** The local ipc client handle. */
     67    RTLOCALIPCSESSION volatile          hSession;
     68    /** Indicate that the thread should terminate ASAP. */
     69    bool volatile                       fTerminate;
     70    /** The thread handle. */
     71    RTTHREAD                            hThread;
     72
     73} VBOXIPCSESSION, *PVBOXIPCSESSION;
     74
     75int vboxIPCSessionDestroyLocked(PVBOXIPCCONTEXT pCtx, PVBOXIPCSESSION pSession);
    15176
    15277/**
     
    16085int VBoxIPCInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread)
    16186{
    162     Log(("VBoxTray: VBoxIPCInit\n"));
     87    AssertPtrReturn(pEnv, VERR_INVALID_POINTER);
     88    /** ppInstance not used here. */
     89    AssertPtrReturn(pfStartThread, VERR_INVALID_POINTER);
     90
     91    LogFlowFuncEnter();
    16392
    16493    *pfStartThread = false;
     94
    16595    gCtx.pEnv = pEnv;
    166 
    167     int rc = VINF_SUCCESS;
    168     SECURITY_ATTRIBUTES sa;
    169     sa.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)RTMemAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
    170     if (!sa.lpSecurityDescriptor)
    171         rc = VERR_NO_MEMORY;
    172     else
    173     {
    174         if (!InitializeSecurityDescriptor(sa.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION))
    175             rc = RTErrConvertFromWin32(GetLastError());
    176         else
    177         {
    178             if (!SetSecurityDescriptorDacl(sa.lpSecurityDescriptor, TRUE, (PACL)0, FALSE))
    179                 rc = RTErrConvertFromWin32(GetLastError());
    180             else
    181             {
    182                 sa.nLength = sizeof(sa);
    183                 sa.bInheritHandle = TRUE;
    184             }
    185         }
    186 
    187         if (RT_SUCCESS(rc))
    188         {
    189             gCtx.hPipe = CreateNamedPipe((LPSTR)VBOXTRAY_PIPE_IPC,
    190                                          PIPE_ACCESS_DUPLEX,
    191                                          PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
    192                                          PIPE_UNLIMITED_INSTANCES,
    193                                          VBOXTRAY_PIPE_IPC_BUFSIZE, /* Output buffer size. */
    194                                          VBOXTRAY_PIPE_IPC_BUFSIZE, /* Input buffer size. */
    195                                          NMPWAIT_USE_DEFAULT_WAIT,
    196                                          &sa);
    197             if (gCtx.hPipe == INVALID_HANDLE_VALUE)
    198                 rc = RTErrConvertFromWin32(GetLastError());
    199             else
    200             {
    201                 *pfStartThread = true;
    202                 *ppInstance = &gCtx;
    203             }
    204         }
    205         RTMemFree(sa.lpSecurityDescriptor);
    206     }
     96    gCtx.hServer = NIL_RTLOCALIPCSERVER;
     97
     98    int rc = RTCritSectInit(&gCtx.CritSect);
     99    if (RT_SUCCESS(rc))
     100    {
     101        rc = RTLocalIpcServerCreate(&gCtx.hServer, "VBoxTrayIPCSvc", RTLOCALIPC_FLAGS_MULTI_SESSION);
     102        if (RT_FAILURE(rc))
     103        {
     104            LogRelFunc(("Creating local IPC server failed with rc=%Rrc\n", rc));
     105            return rc;
     106        }
     107
     108        RTListInit(&gCtx.SessionList);
     109
     110        *pfStartThread = true;
     111    }
     112
    207113    return rc;
    208114}
    209115
    210 
    211 void VBoxIPCDestroy(const VBOXSERVICEENV *pEnv, void *pInstance)
    212 {
    213     Log(("VBoxTray: VBoxIPCDestroy\n"));
     116void VBoxIPCStop(const VBOXSERVICEENV *pEnv, void *pInstance)
     117{
     118    AssertPtr(pEnv);
     119    AssertPtr(pInstance);
     120
     121    LogFunc(("Stopping pInstance=%p\n", pInstance));
    214122
    215123    PVBOXIPCCONTEXT pCtx = (PVBOXIPCCONTEXT)pInstance;
    216124    AssertPtr(pCtx);
    217125
    218     if (pCtx->hPipe)
    219     {
    220         VBoxIPCPostQuitMessage(pCtx);
    221         CloseHandle(pCtx->hPipe);
    222     }
    223     return;
     126    if (pCtx->hServer != NIL_RTLOCALIPCSERVER)
     127    {
     128        int rc2 = RTLocalIpcServerCancel(pCtx->hServer);
     129        if (RT_FAILURE(rc2))
     130            LogFunc(("Cancelling current listening call failed with rc=%Rrc\n", rc2));
     131    }
     132}
     133
     134void VBoxIPCDestroy(const VBOXSERVICEENV *pEnv, void *pInstance)
     135{
     136    AssertPtr(pEnv);
     137    AssertPtr(pInstance);
     138
     139    LogFunc(("Destroying pInstance=%p\n", pInstance));
     140
     141    PVBOXIPCCONTEXT pCtx = (PVBOXIPCCONTEXT)pInstance;
     142    AssertPtr(pCtx);
     143
     144    int rc = RTCritSectEnter(&pCtx->CritSect);
     145    if (RT_SUCCESS(rc))
     146    {
     147        PVBOXIPCSESSION pSession;
     148        RTListForEach(&pCtx->SessionList, pSession, VBOXIPCSESSION, Node)
     149        {
     150            int rc2 = vboxIPCSessionDestroyLocked(pCtx, pSession);
     151            if (RT_FAILURE(rc2))
     152            {
     153                LogFunc(("Destroying IPC session %p failed with rc=%Rrc\n",
     154                         pSession, rc2));
     155                /* Keep going. */
     156            }
     157        }
     158
     159        RTLocalIpcServerDestroy(pCtx->hServer);
     160
     161        int rc2 = RTCritSectLeave(&pCtx->CritSect);
     162        AssertRC(rc2);
     163
     164        rc2 = RTCritSectDelete(&pCtx->CritSect);
     165        AssertRC(rc2);
     166    }
     167
     168    LogFunc(("Destroyed pInstance=%p, rc=%Rrc\n",
     169             pInstance, rc));
     170}
     171
     172/**
     173 * Services a client session.
     174 *
     175 * @returns VINF_SUCCESS.
     176 * @param   hThread         The thread handle.
     177 * @param   pvSession       Pointer to the session instance data.
     178 */
     179static DECLCALLBACK(int) vboxIPCSessionThread(RTTHREAD hThread, void *pvSession)
     180{
     181    PVBOXIPCSESSION pThis = (PVBOXIPCSESSION)pvSession;
     182    AssertPtrReturn(pThis, VERR_INVALID_POINTER);
     183    RTLOCALIPCSESSION hSession = pThis->hSession;
     184    AssertReturn(hSession != NIL_RTLOCALIPCSESSION, VERR_INVALID_PARAMETER);
     185
     186    LogFunc(("pThis=%p\n", pThis));
     187
     188    /*
     189     * Process client requests until it quits or we're cancelled on termination.
     190     */
     191    while (!ASMAtomicUoReadBool(&pThis->fTerminate))
     192    {
     193        int rc = RTLocalIpcSessionWaitForData(hSession, 1000 /* Timeout in ms. */);
     194        if (RT_FAILURE(rc))
     195        {
     196            if (rc == VERR_CANCELLED)
     197            {
     198                LogFunc(("Waiting for data cancelled\n"));
     199                rc = VINF_SUCCESS;
     200                break;
     201            }
     202            else if (rc != VERR_TIMEOUT)
     203            {
     204                LogFunc(("Waiting for data failed, rc=%Rrc\n", rc));
     205                break;
     206            }
     207        }
     208
     209        /** @todo Implement handler. */
     210    }
     211
     212    /*
     213     * Clean up the session.
     214     */
     215    PVBOXIPCCONTEXT pCtx = ASMAtomicReadPtrT(&pThis->pCtx, PVBOXIPCCONTEXT);
     216    if (pCtx)
     217        RTCritSectEnter(&pCtx->CritSect);
     218    else
     219        AssertMsgFailed(("Session %p: No context found\n", pThis));
     220
     221    ASMAtomicXchgHandle(&pThis->hSession, NIL_RTLOCALIPCSESSION, &hSession);
     222    if (hSession != NIL_RTLOCALIPCSESSION)
     223        RTLocalIpcSessionClose(hSession);
     224    else
     225        AssertMsgFailed(("Session %p: No/invalid session handle\n", pThis));
     226
     227    if (pCtx)
     228    {
     229        //RTSemEventSignal(pCtx->hSessionEvent);
     230        RTCritSectLeave(&pCtx->CritSect);
     231    }
     232
     233    LogFunc(("pThis=%p terminated\n", pThis));
     234    return VINF_SUCCESS;
     235}
     236
     237static int vboxIPCSessionCreate(PVBOXIPCCONTEXT pCtx, RTLOCALIPCSESSION hSession)
     238{
     239    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     240    AssertReturn(hSession != NIL_RTLOCALIPCSESSION, VERR_INVALID_PARAMETER);
     241
     242    int rc = RTCritSectEnter(&pCtx->CritSect);
     243    if (RT_SUCCESS(rc))
     244    {
     245        PVBOXIPCSESSION pSession = (PVBOXIPCSESSION)RTMemAllocZ(sizeof(VBOXIPCSESSION));
     246        if (pSession)
     247        {
     248            pSession->pCtx = pCtx;
     249            pSession->hSession = hSession;
     250            pSession->fTerminate = false;
     251            pSession->hThread = NIL_RTTHREAD;
     252
     253            /* Start IPC session thread. */
     254            LogFlowFunc(("Creating thread for session %p ...\n", pSession));
     255            rc = RTThreadCreate(&pSession->hThread, vboxIPCSessionThread, pSession, 0,
     256                                RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "VBXTRYIPCSESS");
     257            if (RT_SUCCESS(rc))
     258            {
     259                /* Add session thread to session IPC list. */
     260                RTListAppend(&pCtx->SessionList, &pSession->Node);
     261            }
     262            else
     263            {
     264                int rc2 = RTLocalIpcSessionClose(hSession);
     265                if (RT_FAILURE(rc2))
     266                    LogFunc(("Failed closing session %p, rc=%Rrc\n", pSession, rc2));
     267
     268                LogFunc(("Failed to create thread for session %p, rc=%Rrc\n", pSession, rc));
     269                RTMemFree(pSession);
     270            }
     271        }
     272        else
     273            rc = VERR_NO_MEMORY;
     274
     275        int rc2 = RTCritSectLeave(&pCtx->CritSect);
     276        AssertRC(rc2);
     277    }
     278
     279    return rc;
     280}
     281
     282static int vboxIPCSessionDestroyLocked(PVBOXIPCCONTEXT pCtx, PVBOXIPCSESSION pSession)
     283{
     284    AssertPtrReturn(pCtx, VERR_INVALID_POINTER);
     285    AssertPtrReturn(pSession, VERR_INVALID_POINTER);
     286
     287    pSession->hThread = NIL_RTTHREAD;
     288
     289    RTLOCALIPCSESSION hSession;
     290    ASMAtomicXchgHandle(&pSession->hSession, NIL_RTLOCALIPCSESSION, &hSession);
     291    if (hSession != NIL_RTLOCALIPCSESSION)
     292        RTLocalIpcSessionClose(hSession);
     293
     294    RTListNodeRemove(&pSession->Node);
     295
     296    RTMemFree(pSession);
     297    pSession = NULL;
     298
     299    return VINF_SUCCESS;
    224300}
    225301
     
    230306unsigned __stdcall VBoxIPCThread(void *pInstance)
    231307{
    232     Log(("VBoxTray: VBoxIPCThread\n"));
     308    LogFlowFuncEnter();
    233309
    234310    PVBOXIPCCONTEXT pCtx = (PVBOXIPCCONTEXT)pInstance;
    235311    AssertPtr(pCtx);
    236312
    237     bool fTerminate = false;
    238     int rc = VINF_SUCCESS;
    239 
    240     do
    241     {
    242         DWORD dwErr = ERROR_SUCCESS;
    243         BOOL fConnected =   ConnectNamedPipe(pCtx->hPipe, NULL)
    244                           ? TRUE
    245                           : (GetLastError() == ERROR_PIPE_CONNECTED);
    246 
    247         /* Are we supposed to stop? */
    248         if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 0) == WAIT_OBJECT_0)
     313    bool fShutdown = false;
     314    for (;;)
     315    {
     316        RTLOCALIPCSESSION hClientSession = NIL_RTLOCALIPCSESSION;
     317        int rc = RTLocalIpcServerListen(pCtx->hServer, &hClientSession);
     318        if (RT_FAILURE(rc))
     319        {
     320            if (rc == VERR_CANCELLED)
     321            {
     322                LogFlow(("Cancelled\n"));
     323                fShutdown = true;
     324            }
     325            else
     326                LogRelFunc(("Listening failed with rc=%Rrc\n", rc));
     327        }
     328
     329        if (fShutdown)
    249330            break;
    250 
    251         if (fConnected)
    252         {
    253             VBOXTRAYIPCHEADER hdr;
    254             DWORD read = 0;
    255 
    256             if (!ReadFile(pCtx->hPipe, &hdr, sizeof(hdr), &read, 0))
    257                 dwErr = GetLastError();
    258 
    259             /** @todo We might want to spawn a thread per connected client
    260              *        in order to perform longer tasks. */
    261 
    262             if (SUCCEEDED(dwErr))
    263             {
    264                 Log(("VBoxTray: VBoxIPCThread: Received message %ld ...\n", hdr.ulMsg));
    265                 switch (hdr.ulMsg)
    266                 {
    267                     case VBOXTRAYIPCMSGTYPE_RESTART:
    268                         rc = VBoxIPCMsgRestart(pCtx, hdr.wParam, hdr.lParam);
    269                         if (RT_SUCCESS(rc))
    270                             fTerminate = true;
    271                         break;
    272 
    273                     case VBOXTRAYIPCMSGTYPE_IPC_QUIT:
    274                         fTerminate = true;
    275                         break;
    276 
    277                     case VBOXTRAYIPCMSGTYPE_SHOWBALLOONMSG:
    278                         rc = VBoxIPCMsgShowBalloonMsg(pCtx, hdr.wParam, hdr.lParam);
    279                         break;
    280 
    281                     default:
    282                         /* Unknown message received, try to receive the body and
    283                          * just skip it. */
    284                         Log(("VBoxTray: VBoxIPCThread: Unknown message %ld, skipping ...\n", hdr.ulMsg));
    285                         if (hdr.cbBody)
    286                             rc = VBoxIPCSkipMessage(pCtx, &hdr);
    287                         break;
    288                 }
    289             }
    290 
    291             /* Disconnect the client from the pipe. */
    292             DisconnectNamedPipe(pCtx->hPipe);
    293         }
    294         else
    295             CloseHandle(pCtx->hPipe);
    296 
    297         /* Sleep a bit to not eat too much CPU in case the above call always fails. */
    298         if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 10) == WAIT_OBJECT_0)
    299             fTerminate = true;
    300         if (fTerminate)
    301             Log(("VBoxTray: VBoxIPCThread: Terminating ...\n"));
    302     } while (!fTerminate);
    303 
    304     Log(("VBoxTray: VBoxIPCThread exited\n"));
     331        rc = vboxIPCSessionCreate(pCtx, hClientSession);
     332        if (RT_FAILURE(rc))
     333        {
     334            LogRelFunc(("Creating new IPC server session failed with rc=%Rrc\n", rc));
     335            /* Keep going. */
     336        }
     337
     338        AssertPtr(pCtx->pEnv);
     339        if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 0 /* No waiting */) == WAIT_OBJECT_0)
     340            break;
     341    }
     342
     343    LogFlowFuncLeave();
    305344    return 0;
    306345}
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxIPC.h

    r44528 r47195  
     1/* $Id$ */
    12/** @file
    2  * VBoxSeamless - Seamless windows
     3 * VBoxIPC - IPC thread, acts as a (purely) local IPC server.
     4 *           Multiple sessions are supported, whereas every session
     5 *           has its own thread for processing requests.
    36 */
    47
    58/*
    6  * Copyright (C) 2006-2010 Oracle Corporation
     9 * Copyright (C) 2006-2013 Oracle Corporation
    710 *
    811 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    1518 */
    1619
    17 #ifndef __VBOXSERVICEIPC__H
    18 #define __VBOXSERVICEIPC__H
     20#ifndef __VBOXTRAYIPCSERVER__H
     21#define __VBOXTRAYIPCSERVER__H
    1922
    20 /* The seamless windows service prototypes */
    21 int                VBoxIPCInit     (const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread);
    22 unsigned __stdcall VBoxIPCThread   (void *pInstance);
    23 void               VBoxIPCDestroy  (const VBOXSERVICEENV *pEnv, void *pInstance);
     23int                VBoxIPCInit    (const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread);
     24unsigned __stdcall VBoxIPCThread  (void *pInstance);
     25void               VBoxIPCStop    (const VBOXSERVICEENV *pEnv, void *pInstance);
     26void               VBoxIPCDestroy (const VBOXSERVICEENV *pEnv, void *pInstance);
    2427
    25 #endif /* __VBOXSERVICEIPC__H */
     28#endif /* __VBOXTRAYIPCSERVER__H */
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp

    r46625 r47195  
    55
    66/*
    7  * Copyright (C) 2006-2012 Oracle Corporation
     7 * Copyright (C) 2006-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    151151        VBoxDisplayInit,
    152152        VBoxDisplayThread,
     153        NULL /* pfnStop */,
    153154        VBoxDisplayDestroy
    154155    },
     
    157158        VBoxClipboardInit,
    158159        VBoxClipboardThread,
     160        NULL /* pfnStop */,
    159161        VBoxClipboardDestroy
    160162    },
     
    163165        VBoxSeamlessInit,
    164166        VBoxSeamlessThread,
     167        NULL /* pfnStop */,
    165168        VBoxSeamlessDestroy
    166169    },
     
    170173        VBoxRestoreInit,
    171174        VBoxRestoreThread,
     175        NULL /* pfnStop */,
    172176        VBoxRestoreDestroy
    173177    },
     
    177181        VBoxVRDPInit,
    178182        VBoxVRDPThread,
     183        NULL /* pfnStop */,
    179184        VBoxVRDPDestroy
    180185    },
     
    183188        VBoxIPCInit,
    184189        VBoxIPCThread,
     190        VBoxIPCStop,
    185191        VBoxIPCDestroy
    186192    },
     
    189195        VBoxLAInit,
    190196        VBoxLAThread,
     197        NULL /* pfnStop */,
    191198        VBoxLADestroy
    192199    },
     
    196203        VBoxMMRInit,
    197204        VBoxMMRThread,
     205        NULL /* pfnStop */,
    198206        VBoxMMRDestroy
    199207    },
     
    289297static int vboxTrayStartServices(VBOXSERVICEENV *pEnv, VBOXSERVICEINFO *pTable)
    290298{
     299    AssertPtrReturn(pEnv, VERR_INVALID_POINTER);
     300    AssertPtrReturn(pTable, VERR_INVALID_POINTER);
     301
    291302    Log(("VBoxTray: Starting services ...\n"));
    292303
    293     pEnv->hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
     304    /** @todo Use IPRT events here. */
     305    pEnv->hStopEvent = CreateEvent(NULL, TRUE /* bManualReset */,
     306                                   FALSE /* bInitialState */, NULL);
    294307
    295308    if (!pEnv->hStopEvent)
     
    299312    }
    300313
    301     while (pTable->pszName)
     314    while (   pTable
     315           && pTable->pszName)
    302316    {
    303317        Log(("VBoxTray: Starting %s ...\n", pTable->pszName));
     
    312326
    313327        if (pTable->pfnInit)
    314             rc = pTable->pfnInit (pEnv, &pTable->pInstance, &fStartThread);
     328            rc = pTable->pfnInit(pEnv, &pTable->pInstance, &fStartThread);
    315329
    316330        if (RT_FAILURE(rc))
    317331        {
    318             Log(("VBoxTray: Failed to initialize rc = %Rrc\n", rc));
     332            LogRel(("VBoxTray: Failed to initialize service \"%s\", rc=%Rrc\n",
     333                    pTable->pszName, rc));
    319334        }
    320335        else
    321336        {
    322             if (pTable->pfnThread && fStartThread)
     337            if (   pTable->pfnThread
     338                && fStartThread)
    323339            {
    324340                unsigned threadid;
     341                /** @todo Use RTThread* here. */
    325342                pTable->hThread = (HANDLE)_beginthreadex(NULL,  /* security */
    326343                                                         0,     /* stacksize */
     
    329346                                                         0,     /* initflag */
    330347                                                         &threadid);
    331 
    332348                if (pTable->hThread == (HANDLE)(0))
    333349                    rc = VERR_NOT_SUPPORTED;
     
    359375    SetEvent(pEnv->hStopEvent);
    360376
    361     while (pTable->pszName)
    362     {
    363         if (pTable->fStarted)
    364         {
    365             if (pTable->pfnThread)
     377    VBOXSERVICEINFO *pCurTable = pTable;
     378    while (   pCurTable
     379           && pCurTable->pszName)
     380    {
     381        if (pCurTable->pfnStop)
     382            pCurTable->pfnStop(pEnv, pCurTable->pInstance);
     383
     384        /* Advance to next table element. */
     385        pCurTable++;
     386    }
     387
     388    pCurTable = pTable; /* Reset to first element. */
     389    while (   pCurTable
     390           && pCurTable->pszName)
     391    {
     392        if (pCurTable->fStarted)
     393        {
     394            if (pCurTable->pfnThread)
    366395            {
    367396                /* There is a thread, wait for termination. */
    368                 WaitForSingleObject(pTable->hThread, INFINITE);
    369 
    370                 CloseHandle(pTable->hThread);
    371                 pTable->hThread = 0;
    372             }
    373 
    374             if (pTable->pfnDestroy)
    375                 pTable->pfnDestroy (pEnv, pTable->pInstance);
    376             pTable->fStarted = false;
     397                /** @todo Use RTThread* here. */
     398                /** @todo Don't wait forever here. Use a sensible default. */
     399                WaitForSingleObject(pCurTable->hThread, INFINITE);
     400
     401                /** @todo Dito. */
     402                CloseHandle(pCurTable->hThread);
     403                pCurTable->hThread = NULL;
     404            }
     405
     406            if (pCurTable->pfnDestroy)
     407                pCurTable->pfnDestroy(pEnv, pCurTable->pInstance);
     408            pCurTable->fStarted = false;
    377409        }
    378410
    379411        /* Advance to next table element. */
    380         pTable++;
     412        pCurTable++;
    381413    }
    382414
  • trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.h

    r45837 r47195  
    101101    int      (* pfnInit)             (const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread);
    102102    unsigned (__stdcall * pfnThread) (void *pInstance);
     103    void     (* pfnStop)             (const VBOXSERVICEENV *pEnv, void *pInstance);
    103104    void     (* pfnDestroy)          (const VBOXSERVICEENV *pEnv, void *pInstance);
    104105
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