Changeset 47195 in vbox for trunk/src/VBox/Additions
- Timestamp:
- Jul 16, 2013 2:48:43 PM (11 years ago)
- Location:
- trunk/src/VBox/Additions/WINNT/VBoxTray
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxIPC.cpp
r44529 r47195 1 1 /* $Id$ */ 2 2 /** @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. 4 6 */ 5 7 6 8 /* 7 * Copyright (C) 2010-201 1Oracle Corporation9 * Copyright (C) 2010-2013 Oracle Corporation 8 10 * 9 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 21 23 #include "VBoxIPC.h" 22 24 25 #include <iprt/asm.h> 23 26 #include <iprt/assert.h> 27 #include <iprt/critsect.h> 24 28 #include <iprt/err.h> 29 #include <iprt/list.h> 30 #include <iprt/localipc.h> 25 31 #include <iprt/mem.h> 26 32 #include <VBoxGuestInternal.h> 27 33 28 34 29 typedef struct _VBOXIPCCONTEXT 30 { 31 const VBOXSERVICEENV *pEnv; 32 HANDLE hPipe; 35 36 37 38 /** 39 * IPC context data. 40 */ 41 typedef 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; 33 52 34 53 } VBOXIPCCONTEXT, *PVBOXIPCCONTEXT; 35 36 54 static VBOXIPCCONTEXT gCtx = {0}; 37 55 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 */ 59 typedef 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 75 int vboxIPCSessionDestroyLocked(PVBOXIPCCONTEXT pCtx, PVBOXIPCSESSION pSession); 151 76 152 77 /** … … 160 85 int VBoxIPCInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread) 161 86 { 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(); 163 92 164 93 *pfStartThread = false; 94 165 95 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 207 113 return rc; 208 114 } 209 115 210 211 void VBoxIPCDestroy(const VBOXSERVICEENV *pEnv, void *pInstance) 212 { 213 Log(("VBoxTray: VBoxIPCDestroy\n")); 116 void VBoxIPCStop(const VBOXSERVICEENV *pEnv, void *pInstance) 117 { 118 AssertPtr(pEnv); 119 AssertPtr(pInstance); 120 121 LogFunc(("Stopping pInstance=%p\n", pInstance)); 214 122 215 123 PVBOXIPCCONTEXT pCtx = (PVBOXIPCCONTEXT)pInstance; 216 124 AssertPtr(pCtx); 217 125 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 134 void 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 */ 179 static 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 237 static 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 282 static 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; 224 300 } 225 301 … … 230 306 unsigned __stdcall VBoxIPCThread(void *pInstance) 231 307 { 232 Log (("VBoxTray: VBoxIPCThread\n"));308 LogFlowFuncEnter(); 233 309 234 310 PVBOXIPCCONTEXT pCtx = (PVBOXIPCCONTEXT)pInstance; 235 311 AssertPtr(pCtx); 236 312 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) 249 330 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(); 305 344 return 0; 306 345 } -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxIPC.h
r44528 r47195 1 /* $Id$ */ 1 2 /** @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. 3 6 */ 4 7 5 8 /* 6 * Copyright (C) 2006-201 0Oracle Corporation9 * Copyright (C) 2006-2013 Oracle Corporation 7 10 * 8 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 15 18 */ 16 19 17 #ifndef __VBOX SERVICEIPC__H18 #define __VBOX SERVICEIPC__H20 #ifndef __VBOXTRAYIPCSERVER__H 21 #define __VBOXTRAYIPCSERVER__H 19 22 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 23 int VBoxIPCInit (const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread); 24 unsigned __stdcall VBoxIPCThread (void *pInstance); 25 void VBoxIPCStop (const VBOXSERVICEENV *pEnv, void *pInstance); 26 void VBoxIPCDestroy (const VBOXSERVICEENV *pEnv, void *pInstance); 24 27 25 #endif /* __VBOX SERVICEIPC__H */28 #endif /* __VBOXTRAYIPCSERVER__H */ -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.cpp
r46625 r47195 5 5 6 6 /* 7 * Copyright (C) 2006-201 2Oracle Corporation7 * Copyright (C) 2006-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 151 151 VBoxDisplayInit, 152 152 VBoxDisplayThread, 153 NULL /* pfnStop */, 153 154 VBoxDisplayDestroy 154 155 }, … … 157 158 VBoxClipboardInit, 158 159 VBoxClipboardThread, 160 NULL /* pfnStop */, 159 161 VBoxClipboardDestroy 160 162 }, … … 163 165 VBoxSeamlessInit, 164 166 VBoxSeamlessThread, 167 NULL /* pfnStop */, 165 168 VBoxSeamlessDestroy 166 169 }, … … 170 173 VBoxRestoreInit, 171 174 VBoxRestoreThread, 175 NULL /* pfnStop */, 172 176 VBoxRestoreDestroy 173 177 }, … … 177 181 VBoxVRDPInit, 178 182 VBoxVRDPThread, 183 NULL /* pfnStop */, 179 184 VBoxVRDPDestroy 180 185 }, … … 183 188 VBoxIPCInit, 184 189 VBoxIPCThread, 190 VBoxIPCStop, 185 191 VBoxIPCDestroy 186 192 }, … … 189 195 VBoxLAInit, 190 196 VBoxLAThread, 197 NULL /* pfnStop */, 191 198 VBoxLADestroy 192 199 }, … … 196 203 VBoxMMRInit, 197 204 VBoxMMRThread, 205 NULL /* pfnStop */, 198 206 VBoxMMRDestroy 199 207 }, … … 289 297 static int vboxTrayStartServices(VBOXSERVICEENV *pEnv, VBOXSERVICEINFO *pTable) 290 298 { 299 AssertPtrReturn(pEnv, VERR_INVALID_POINTER); 300 AssertPtrReturn(pTable, VERR_INVALID_POINTER); 301 291 302 Log(("VBoxTray: Starting services ...\n")); 292 303 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); 294 307 295 308 if (!pEnv->hStopEvent) … … 299 312 } 300 313 301 while (pTable->pszName) 314 while ( pTable 315 && pTable->pszName) 302 316 { 303 317 Log(("VBoxTray: Starting %s ...\n", pTable->pszName)); … … 312 326 313 327 if (pTable->pfnInit) 314 rc = pTable->pfnInit 328 rc = pTable->pfnInit(pEnv, &pTable->pInstance, &fStartThread); 315 329 316 330 if (RT_FAILURE(rc)) 317 331 { 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)); 319 334 } 320 335 else 321 336 { 322 if (pTable->pfnThread && fStartThread) 337 if ( pTable->pfnThread 338 && fStartThread) 323 339 { 324 340 unsigned threadid; 341 /** @todo Use RTThread* here. */ 325 342 pTable->hThread = (HANDLE)_beginthreadex(NULL, /* security */ 326 343 0, /* stacksize */ … … 329 346 0, /* initflag */ 330 347 &threadid); 331 332 348 if (pTable->hThread == (HANDLE)(0)) 333 349 rc = VERR_NOT_SUPPORTED; … … 359 375 SetEvent(pEnv->hStopEvent); 360 376 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) 366 395 { 367 396 /* 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; 377 409 } 378 410 379 411 /* Advance to next table element. */ 380 p Table++;412 pCurTable++; 381 413 } 382 414 -
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxTray.h
r45837 r47195 101 101 int (* pfnInit) (const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread); 102 102 unsigned (__stdcall * pfnThread) (void *pInstance); 103 void (* pfnStop) (const VBOXSERVICEENV *pEnv, void *pInstance); 103 104 void (* pfnDestroy) (const VBOXSERVICEENV *pEnv, void *pInstance); 104 105
Note:
See TracChangeset
for help on using the changeset viewer.