VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp@ 51801

Last change on this file since 51801 was 51801, checked in by vboxsync, 11 years ago

SharedOpenGL: cleanup.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 53.1 KB
Line 
1/* $Id: crservice.cpp 51801 2014-07-02 08:53:52Z vboxsync $ */
2
3/** @file
4 * VBox crOpenGL: Host service entry points.
5 */
6
7/*
8 * Copyright (C) 2006-2012 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#define __STDC_CONSTANT_MACROS /* needed for a definition in iprt/string.h */
20
21#define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
22
23#include <iprt/assert.h>
24#include <iprt/asm.h>
25#include <iprt/critsect.h>
26#include <iprt/mem.h>
27#include <iprt/semaphore.h>
28#include <iprt/stream.h>
29#include <iprt/string.h>
30#include <iprt/thread.h>
31
32#include <VBox/hgcmsvc.h>
33#include <VBox/log.h>
34#include <VBox/com/array.h>
35#include <VBox/com/ErrorInfo.h>
36#include <VBox/com/VirtualBox.h>
37#include <VBox/com/errorprint.h>
38#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
39#include <VBox/vmm/ssm.h>
40
41#include "cr_mem.h"
42#include "cr_server.h"
43
44PVBOXHGCMSVCHELPERS g_pHelpers;
45static IConsole* g_pConsole = NULL;
46static uint32_t g_u32ScreenCount = 0;
47static PVM g_pVM = NULL;
48static uint32_t g_u32fCrHgcmDisabled = 0;
49
50#ifndef RT_OS_WINDOWS
51# define DWORD int
52# define WINAPI
53#endif
54
55static const char* gszVBoxOGLSSMMagic = "***OpenGL state data***";
56
57/* Used to process guest calls exceeding maximum allowed HGCM call size in a sequence of smaller calls */
58typedef struct _CRVBOXSVCBUFFER_t {
59 uint32_t uiId;
60 uint32_t uiSize;
61 void* pData;
62 _CRVBOXSVCBUFFER_t *pNext, *pPrev;
63} CRVBOXSVCBUFFER_t;
64
65static CRVBOXSVCBUFFER_t *g_pCRVBoxSVCBuffers = NULL;
66static uint32_t g_CRVBoxSVCBufferID = 0;
67
68/* svcPresentFBO related data */
69typedef struct _CRVBOXSVCPRESENTFBOCMD_t {
70 void *pData;
71 int32_t screenId, x, y, w, h;
72 _CRVBOXSVCPRESENTFBOCMD_t *pNext;
73} CRVBOXSVCPRESENTFBOCMD_t, *PCRVBOXSVCPRESENTFBOCMD_t;
74
75typedef struct _CRVBOXSVCPRESENTFBO_t {
76 PCRVBOXSVCPRESENTFBOCMD_t pQueueHead, pQueueTail; /* Head/Tail of FIFO cmds queue */
77 RTCRITSECT hQueueLock; /* Queue lock */
78 RTTHREAD hWorkerThread; /* Worker thread */
79 bool volatile bShutdownWorker; /* Shutdown flag */
80 RTSEMEVENT hEventProcess; /* Signalled when worker thread should process data or exit */
81} CRVBOXSVCPRESENTFBO_t;
82
83static CRVBOXSVCPRESENTFBO_t g_SvcPresentFBO;
84
85/* Schedule a call to a separate worker thread to avoid deadlock on EMT thread when the screen configuration changes
86 and we're processing crServerPresentFBO caused by guest application command.
87 To avoid unnecessary memcpy, worker thread frees the data passed.
88*/
89static DECLCALLBACK(void) svcPresentFBO(void *data, int32_t screenId, int32_t x, int32_t y, uint32_t w, uint32_t h)
90{
91 PCRVBOXSVCPRESENTFBOCMD_t pCmd;
92
93 pCmd = (PCRVBOXSVCPRESENTFBOCMD_t) RTMemAlloc(sizeof(CRVBOXSVCPRESENTFBOCMD_t));
94 if (!pCmd)
95 {
96 LogRel(("SHARED_CROPENGL svcPresentFBO: not enough memory (%d)\n", sizeof(CRVBOXSVCPRESENTFBOCMD_t)));
97 return;
98 }
99 pCmd->pData = data;
100 pCmd->screenId = screenId;
101 pCmd->x = x;
102 pCmd->y = y;
103 pCmd->w = w;
104 pCmd->h = h;
105 pCmd->pNext = NULL;
106
107 RTCritSectEnter(&g_SvcPresentFBO.hQueueLock);
108
109 if (g_SvcPresentFBO.pQueueTail)
110 {
111 g_SvcPresentFBO.pQueueTail->pNext = pCmd;
112 }
113 else
114 {
115 Assert(!g_SvcPresentFBO.pQueueHead);
116 g_SvcPresentFBO.pQueueHead = pCmd;
117 }
118 g_SvcPresentFBO.pQueueTail = pCmd;
119
120 RTCritSectLeave(&g_SvcPresentFBO.hQueueLock);
121
122 RTSemEventSignal(g_SvcPresentFBO.hEventProcess);
123}
124
125static DECLCALLBACK(int) svcPresentFBOWorkerThreadProc(RTTHREAD ThreadSelf, void *pvUser)
126{
127 int rc = VINF_SUCCESS;
128 PCRVBOXSVCPRESENTFBOCMD_t pCmd;
129
130 Log(("SHARED_CROPENGL svcPresentFBOWorkerThreadProc started\n"));
131
132 for (;;)
133 {
134 rc = RTSemEventWait(g_SvcPresentFBO.hEventProcess, RT_INDEFINITE_WAIT);
135 AssertRCReturn(rc, rc);
136
137 if (g_SvcPresentFBO.bShutdownWorker)
138 {
139 break;
140 }
141
142 // @todo use critsect only to fetch the list and update the g_SvcPresentFBO's pQueueHead and pQueueTail.
143 rc = RTCritSectEnter(&g_SvcPresentFBO.hQueueLock);
144 AssertRCReturn(rc, rc);
145
146 pCmd = g_SvcPresentFBO.pQueueHead;
147 while (pCmd)
148 {
149 ComPtr<IDisplay> pDisplay;
150
151 /*remove from queue*/
152 g_SvcPresentFBO.pQueueHead = pCmd->pNext;
153 if (!g_SvcPresentFBO.pQueueHead)
154 {
155 g_SvcPresentFBO.pQueueTail = NULL;
156 }
157
158 CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc);
159
160 RTCritSectLeave(&g_SvcPresentFBO.hQueueLock);
161
162 CHECK_ERROR_RET(pDisplay, DrawToScreen(pCmd->screenId, (BYTE*)pCmd->pData, pCmd->x, pCmd->y, pCmd->w, pCmd->h), rc);
163
164 crFree(pCmd->pData);
165 RTMemFree(pCmd);
166
167 rc = RTCritSectEnter(&g_SvcPresentFBO.hQueueLock);
168 AssertRCReturn(rc, rc);
169 pCmd = g_SvcPresentFBO.pQueueHead;
170 }
171
172 RTCritSectLeave(&g_SvcPresentFBO.hQueueLock);
173 }
174
175 Log(("SHARED_CROPENGL svcPresentFBOWorkerThreadProc finished\n"));
176
177 return rc;
178}
179
180static int svcPresentFBOInit(void)
181{
182 int rc = VINF_SUCCESS;
183
184 g_SvcPresentFBO.pQueueHead = NULL;
185 g_SvcPresentFBO.pQueueTail = NULL;
186 g_SvcPresentFBO.bShutdownWorker = false;
187
188 rc = RTCritSectInit(&g_SvcPresentFBO.hQueueLock);
189 AssertRCReturn(rc, rc);
190
191 rc = RTSemEventCreate(&g_SvcPresentFBO.hEventProcess);
192 AssertRCReturn(rc, rc);
193
194 rc = RTThreadCreate(&g_SvcPresentFBO.hWorkerThread, svcPresentFBOWorkerThreadProc, NULL, 0,
195 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "OpenGLWorker");
196 AssertRCReturn(rc, rc);
197
198 crVBoxServerSetPresentFBOCB(svcPresentFBO);
199
200 return rc;
201}
202
203static int svcPresentFBOTearDown(void)
204{
205 int rc = VINF_SUCCESS;
206 PCRVBOXSVCPRESENTFBOCMD_t pQueue, pTmp;
207
208 ASMAtomicWriteBool(&g_SvcPresentFBO.bShutdownWorker, true);
209 RTSemEventSignal(g_SvcPresentFBO.hEventProcess);
210 rc = RTThreadWait(g_SvcPresentFBO.hWorkerThread, 5000, NULL);
211 AssertRCReturn(rc, rc);
212
213 RTCritSectDelete(&g_SvcPresentFBO.hQueueLock);
214 RTSemEventDestroy(g_SvcPresentFBO.hEventProcess);
215
216 pQueue = g_SvcPresentFBO.pQueueHead;
217 while (pQueue)
218 {
219 pTmp = pQueue->pNext;
220 crFree(pQueue->pData);
221 RTMemFree(pQueue);
222 pQueue = pTmp;
223 }
224 g_SvcPresentFBO.pQueueHead = NULL;
225 g_SvcPresentFBO.pQueueTail = NULL;
226
227 return rc;
228}
229
230static DECLCALLBACK(void) svcNotifyEventCB(int32_t screenId, uint32_t uEvent, void* pvData, uint32_t cbData)
231{
232 ComPtr<IDisplay> pDisplay;
233 ComPtr<IFramebuffer> pFramebuffer;
234
235 if (!g_pConsole)
236 {
237 crWarning("Console not defined!");
238 return;
239 }
240
241 CHECK_ERROR2_STMT(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), return);
242
243 CHECK_ERROR2_STMT(pDisplay, QueryFramebuffer(screenId, pFramebuffer.asOutParam()), return);
244
245 if (!pFramebuffer)
246 return;
247
248 com::SafeArray<BYTE> data(cbData);
249 if (cbData)
250 memcpy(data.raw(), pvData, cbData);
251
252 pFramebuffer->Notify3DEvent(uEvent, ComSafeArrayAsInParam(data));
253}
254
255
256static DECLCALLBACK(int) svcUnload (void *)
257{
258 int rc = VINF_SUCCESS;
259
260 Log(("SHARED_CROPENGL svcUnload\n"));
261
262 crVBoxServerTearDown();
263
264 svcPresentFBOTearDown();
265
266 return rc;
267}
268
269static DECLCALLBACK(int) svcConnect (void *, uint32_t u32ClientID, void *pvClient)
270{
271 int rc = VINF_SUCCESS;
272
273 NOREF(pvClient);
274
275 if (g_u32fCrHgcmDisabled)
276 {
277 WARN(("connect not expected"));
278 return VERR_INVALID_STATE;
279 }
280
281 Log(("SHARED_CROPENGL svcConnect: u32ClientID = %d\n", u32ClientID));
282
283 rc = crVBoxServerAddClient(u32ClientID);
284
285 return rc;
286}
287
288static DECLCALLBACK(int) svcDisconnect (void *, uint32_t u32ClientID, void *pvClient)
289{
290 int rc = VINF_SUCCESS;
291
292 NOREF(pvClient);
293
294 if (g_u32fCrHgcmDisabled)
295 {
296 WARN(("disconnect not expected"));
297 return VINF_SUCCESS;
298 }
299
300 Log(("SHARED_CROPENGL svcDisconnect: u32ClientID = %d\n", u32ClientID));
301
302 crVBoxServerRemoveClient(u32ClientID);
303
304 return rc;
305}
306
307static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
308{
309 int rc = VINF_SUCCESS;
310
311 NOREF(pvClient);
312
313 Log(("SHARED_CROPENGL svcSaveState: u32ClientID = %d\n", u32ClientID));
314
315 /* Start*/
316 rc = SSMR3PutStrZ(pSSM, gszVBoxOGLSSMMagic);
317 AssertRCReturn(rc, rc);
318
319 /* Version */
320 rc = SSMR3PutU32(pSSM, (uint32_t) SHCROGL_SSM_VERSION);
321 AssertRCReturn(rc, rc);
322
323 /* The state itself */
324 rc = crVBoxServerSaveState(pSSM);
325 AssertRCReturn(rc, rc);
326
327 /* Save svc buffers info */
328 {
329 CRVBOXSVCBUFFER_t *pBuffer = g_pCRVBoxSVCBuffers;
330
331 rc = SSMR3PutU32(pSSM, g_CRVBoxSVCBufferID);
332 AssertRCReturn(rc, rc);
333
334 while (pBuffer)
335 {
336 rc = SSMR3PutU32(pSSM, pBuffer->uiId);
337 AssertRCReturn(rc, rc);
338
339 rc = SSMR3PutU32(pSSM, pBuffer->uiSize);
340 AssertRCReturn(rc, rc);
341
342 rc = SSMR3PutMem(pSSM, pBuffer->pData, pBuffer->uiSize);
343 AssertRCReturn(rc, rc);
344
345 pBuffer = pBuffer->pNext;
346 }
347
348 rc = SSMR3PutU32(pSSM, 0);
349 AssertRCReturn(rc, rc);
350 }
351
352 /* End */
353 rc = SSMR3PutStrZ(pSSM, gszVBoxOGLSSMMagic);
354 AssertRCReturn(rc, rc);
355
356 return VINF_SUCCESS;
357}
358
359static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
360{
361 int rc = VINF_SUCCESS;
362
363 NOREF(pvClient);
364
365 Log(("SHARED_CROPENGL svcLoadState: u32ClientID = %d\n", u32ClientID));
366
367 char psz[2000];
368 uint32_t ui32;
369
370 /* Start of data */
371 rc = SSMR3GetStrZEx(pSSM, psz, 2000, NULL);
372 AssertRCReturn(rc, rc);
373 if (strcmp(gszVBoxOGLSSMMagic, psz))
374 return VERR_SSM_UNEXPECTED_DATA;
375
376 /* Version */
377 rc = SSMR3GetU32(pSSM, &ui32);
378 AssertRCReturn(rc, rc);
379
380 /* The state itself */
381 rc = crVBoxServerLoadState(pSSM, ui32);
382
383 if (rc==VERR_SSM_DATA_UNIT_FORMAT_CHANGED && ui32!=SHCROGL_SSM_VERSION)
384 {
385 LogRel(("SHARED_CROPENGL svcLoadState: unsupported save state version %d\n", ui32));
386
387 /*@todo ugly hack, as we don't know size of stored opengl data try to read untill end of opengl data marker*/
388 /*VBoxSharedCrOpenGL isn't last hgcm service now, so can't use SSMR3SkipToEndOfUnit*/
389 {
390 const char *pMatch = &gszVBoxOGLSSMMagic[0];
391 char current;
392
393 while (*pMatch)
394 {
395 rc = SSMR3GetS8(pSSM, (int8_t*)&current);
396 AssertRCReturn(rc, rc);
397
398 if (current==*pMatch)
399 {
400 pMatch++;
401 }
402 else
403 {
404 pMatch = &gszVBoxOGLSSMMagic[0];
405 }
406 }
407 }
408
409 return VINF_SUCCESS;
410 }
411 AssertRCReturn(rc, rc);
412
413 /* Load svc buffers info */
414 if (ui32>=24)
415 {
416 uint32_t uiId;
417
418 rc = SSMR3GetU32(pSSM, &g_CRVBoxSVCBufferID);
419 AssertRCReturn(rc, rc);
420
421 rc = SSMR3GetU32(pSSM, &uiId);
422 AssertRCReturn(rc, rc);
423
424 while (uiId)
425 {
426 CRVBOXSVCBUFFER_t *pBuffer = (CRVBOXSVCBUFFER_t *) RTMemAlloc(sizeof(CRVBOXSVCBUFFER_t));
427 if (!pBuffer)
428 {
429 return VERR_NO_MEMORY;
430 }
431 pBuffer->uiId = uiId;
432
433 rc = SSMR3GetU32(pSSM, &pBuffer->uiSize);
434 AssertRCReturn(rc, rc);
435
436 pBuffer->pData = RTMemAlloc(pBuffer->uiSize);
437 if (!pBuffer->pData)
438 {
439 RTMemFree(pBuffer);
440 return VERR_NO_MEMORY;
441 }
442
443 rc = SSMR3GetMem(pSSM, pBuffer->pData, pBuffer->uiSize);
444 AssertRCReturn(rc, rc);
445
446 pBuffer->pNext = g_pCRVBoxSVCBuffers;
447 pBuffer->pPrev = NULL;
448 if (g_pCRVBoxSVCBuffers)
449 {
450 g_pCRVBoxSVCBuffers->pPrev = pBuffer;
451 }
452 g_pCRVBoxSVCBuffers = pBuffer;
453
454 rc = SSMR3GetU32(pSSM, &uiId);
455 AssertRCReturn(rc, rc);
456 }
457 }
458
459 /* End of data */
460 rc = SSMR3GetStrZEx(pSSM, psz, 2000, NULL);
461 AssertRCReturn(rc, rc);
462 if (strcmp(gszVBoxOGLSSMMagic, psz))
463 return VERR_SSM_UNEXPECTED_DATA;
464
465 return VINF_SUCCESS;
466}
467
468static void svcClientVersionUnsupported(uint32_t minor, uint32_t major)
469{
470 LogRel(("SHARED_CROPENGL: unsupported client version %d.%d\n", minor, major));
471
472 /*MS's opengl32 tries to load our ICD around 30 times on failure...this is to prevent unnecessary spam*/
473 static int shown = 0;
474
475 if (g_pVM && !shown)
476 {
477 VMSetRuntimeError(g_pVM, VMSETRTERR_FLAGS_NO_WAIT, "3DSupportIncompatibleAdditions",
478 "An attempt by the virtual machine to use hardware 3D acceleration failed. "
479 "The version of the Guest Additions installed in the virtual machine does not match the "
480 "version of VirtualBox on the host. Please install appropriate Guest Additions to fix this issue");
481 shown = 1;
482 }
483}
484
485static CRVBOXSVCBUFFER_t* svcGetBuffer(uint32_t iBuffer, uint32_t cbBufferSize)
486{
487 CRVBOXSVCBUFFER_t* pBuffer;
488
489 if (iBuffer)
490 {
491 pBuffer = g_pCRVBoxSVCBuffers;
492 while (pBuffer)
493 {
494 if (pBuffer->uiId == iBuffer)
495 {
496 if (cbBufferSize && pBuffer->uiSize!=cbBufferSize)
497 {
498 static int shown=0;
499
500 if (shown<20)
501 {
502 shown++;
503 LogRel(("SHARED_CROPENGL svcGetBuffer: invalid buffer(%i) size %i instead of %i\n",
504 iBuffer, pBuffer->uiSize, cbBufferSize));
505 }
506 return NULL;
507 }
508 return pBuffer;
509 }
510 pBuffer = pBuffer->pNext;
511 }
512 return NULL;
513 }
514 else /*allocate new buffer*/
515 {
516 pBuffer = (CRVBOXSVCBUFFER_t*) RTMemAlloc(sizeof(CRVBOXSVCBUFFER_t));
517 if (pBuffer)
518 {
519 pBuffer->pData = RTMemAlloc(cbBufferSize);
520 if (!pBuffer->pData)
521 {
522 LogRel(("SHARED_CROPENGL svcGetBuffer: not enough memory (%d)\n", cbBufferSize));
523 RTMemFree(pBuffer);
524 return NULL;
525 }
526 pBuffer->uiId = ++g_CRVBoxSVCBufferID;
527 if (!pBuffer->uiId)
528 {
529 pBuffer->uiId = ++g_CRVBoxSVCBufferID;
530 }
531 Assert(pBuffer->uiId);
532 pBuffer->uiSize = cbBufferSize;
533 pBuffer->pPrev = NULL;
534 pBuffer->pNext = g_pCRVBoxSVCBuffers;
535 if (g_pCRVBoxSVCBuffers)
536 {
537 g_pCRVBoxSVCBuffers->pPrev = pBuffer;
538 }
539 g_pCRVBoxSVCBuffers = pBuffer;
540 }
541 else
542 {
543 LogRel(("SHARED_CROPENGL svcGetBuffer: not enough memory (%d)\n", sizeof(CRVBOXSVCBUFFER_t)));
544 }
545 return pBuffer;
546 }
547}
548
549static void svcFreeBuffer(CRVBOXSVCBUFFER_t* pBuffer)
550{
551 Assert(pBuffer);
552
553 if (pBuffer->pPrev)
554 {
555 pBuffer->pPrev->pNext = pBuffer->pNext;
556 }
557 else
558 {
559 Assert(pBuffer==g_pCRVBoxSVCBuffers);
560 g_pCRVBoxSVCBuffers = pBuffer->pNext;
561 }
562
563 if (pBuffer->pNext)
564 {
565 pBuffer->pNext->pPrev = pBuffer->pPrev;
566 }
567
568 RTMemFree(pBuffer->pData);
569 RTMemFree(pBuffer);
570}
571
572static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
573{
574 int rc = VINF_SUCCESS;
575
576 NOREF(pvClient);
577
578 if (g_u32fCrHgcmDisabled)
579 {
580 WARN(("cr hgcm disabled!"));
581 return;
582 }
583
584 Log(("SHARED_CROPENGL svcCall: u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n", u32ClientID, u32Function, cParms, paParms));
585
586#ifdef DEBUG
587 uint32_t i;
588
589 for (i = 0; i < cParms; i++)
590 {
591 /** @todo parameters other than 32 bit */
592 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
593 }
594#endif
595
596 switch (u32Function)
597 {
598 case SHCRGL_GUEST_FN_WRITE:
599 {
600 Log(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
601
602 /* Verify parameter count and types. */
603 if (cParms != SHCRGL_CPARMS_WRITE)
604 {
605 rc = VERR_INVALID_PARAMETER;
606 }
607 else
608 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
609 )
610 {
611 rc = VERR_INVALID_PARAMETER;
612 }
613 else
614 {
615 /* Fetch parameters. */
616 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
617 uint32_t cbBuffer = paParms[0].u.pointer.size;
618
619 /* Execute the function. */
620 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
621 if (!RT_SUCCESS(rc))
622 {
623 Assert(VERR_NOT_SUPPORTED==rc);
624 svcClientVersionUnsupported(0, 0);
625 }
626
627 }
628 break;
629 }
630
631 case SHCRGL_GUEST_FN_INJECT:
632 {
633 Log(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
634
635 /* Verify parameter count and types. */
636 if (cParms != SHCRGL_CPARMS_INJECT)
637 {
638 rc = VERR_INVALID_PARAMETER;
639 }
640 else
641 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* u32ClientID */
642 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
643 )
644 {
645 rc = VERR_INVALID_PARAMETER;
646 }
647 else
648 {
649 /* Fetch parameters. */
650 uint32_t u32InjectClientID = paParms[0].u.uint32;
651 uint8_t *pBuffer = (uint8_t *)paParms[1].u.pointer.addr;
652 uint32_t cbBuffer = paParms[1].u.pointer.size;
653
654 /* Execute the function. */
655 rc = crVBoxServerClientWrite(u32InjectClientID, pBuffer, cbBuffer);
656 if (!RT_SUCCESS(rc))
657 {
658 if (VERR_NOT_SUPPORTED==rc)
659 {
660 svcClientVersionUnsupported(0, 0);
661 }
662 else
663 {
664 crWarning("SHCRGL_GUEST_FN_INJECT failed to inject for %i from %i", u32InjectClientID, u32ClientID);
665 }
666 }
667 }
668 break;
669 }
670
671 case SHCRGL_GUEST_FN_READ:
672 {
673 Log(("svcCall: SHCRGL_GUEST_FN_READ\n"));
674
675 /* Verify parameter count and types. */
676 if (cParms != SHCRGL_CPARMS_READ)
677 {
678 rc = VERR_INVALID_PARAMETER;
679 }
680 else
681 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
682 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cbBuffer */
683 )
684 {
685 rc = VERR_INVALID_PARAMETER;
686 }
687
688 /* Fetch parameters. */
689 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
690 uint32_t cbBuffer = paParms[0].u.pointer.size;
691
692 /* Execute the function. */
693 rc = crVBoxServerClientRead(u32ClientID, pBuffer, &cbBuffer);
694
695 if (RT_SUCCESS(rc))
696 {
697 /* Update parameters.*/
698 paParms[0].u.pointer.size = cbBuffer; //@todo guest doesn't see this change somehow?
699 } else if (VERR_NOT_SUPPORTED==rc)
700 {
701 svcClientVersionUnsupported(0, 0);
702 }
703
704 /* Return the required buffer size always */
705 paParms[1].u.uint32 = cbBuffer;
706
707 break;
708 }
709
710 case SHCRGL_GUEST_FN_WRITE_READ:
711 {
712 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
713
714 /* Verify parameter count and types. */
715 if (cParms != SHCRGL_CPARMS_WRITE_READ)
716 {
717 rc = VERR_INVALID_PARAMETER;
718 }
719 else
720 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
721 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pWriteback */
722 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* cbWriteback */
723 )
724 {
725 rc = VERR_INVALID_PARAMETER;
726 }
727 else
728 {
729 /* Fetch parameters. */
730 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
731 uint32_t cbBuffer = paParms[0].u.pointer.size;
732
733 uint8_t *pWriteback = (uint8_t *)paParms[1].u.pointer.addr;
734 uint32_t cbWriteback = paParms[1].u.pointer.size;
735
736 /* Execute the function. */
737 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
738 if (!RT_SUCCESS(rc))
739 {
740 Assert(VERR_NOT_SUPPORTED==rc);
741 svcClientVersionUnsupported(0, 0);
742 }
743
744 rc = crVBoxServerClientRead(u32ClientID, pWriteback, &cbWriteback);
745
746 if (RT_SUCCESS(rc))
747 {
748 /* Update parameters.*/
749 paParms[1].u.pointer.size = cbWriteback;
750 }
751 /* Return the required buffer size always */
752 paParms[2].u.uint32 = cbWriteback;
753 }
754
755 break;
756 }
757
758 case SHCRGL_GUEST_FN_SET_VERSION:
759 {
760 Log(("svcCall: SHCRGL_GUEST_FN_SET_VERSION\n"));
761
762 /* Verify parameter count and types. */
763 if (cParms != SHCRGL_CPARMS_SET_VERSION)
764 {
765 rc = VERR_INVALID_PARAMETER;
766 }
767 else
768 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* vMajor */
769 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* vMinor */
770 )
771 {
772 rc = VERR_INVALID_PARAMETER;
773 }
774 else
775 {
776 /* Fetch parameters. */
777 uint32_t vMajor = paParms[0].u.uint32;
778 uint32_t vMinor = paParms[1].u.uint32;
779
780 /* Execute the function. */
781 rc = crVBoxServerClientSetVersion(u32ClientID, vMajor, vMinor);
782
783 if (!RT_SUCCESS(rc))
784 {
785 svcClientVersionUnsupported(vMajor, vMinor);
786 }
787 }
788
789 break;
790 }
791
792 case SHCRGL_GUEST_FN_SET_PID:
793 {
794 Log(("svcCall: SHCRGL_GUEST_FN_SET_PID\n"));
795
796 /* Verify parameter count and types. */
797 if (cParms != SHCRGL_CPARMS_SET_PID)
798 {
799 rc = VERR_INVALID_PARAMETER;
800 }
801 else
802 if (paParms[0].type != VBOX_HGCM_SVC_PARM_64BIT)
803 {
804 rc = VERR_INVALID_PARAMETER;
805 }
806 else
807 {
808 /* Fetch parameters. */
809 uint64_t pid = paParms[0].u.uint64;
810
811 /* Execute the function. */
812 rc = crVBoxServerClientSetPID(u32ClientID, pid);
813 }
814
815 break;
816 }
817
818 case SHCRGL_GUEST_FN_WRITE_BUFFER:
819 {
820 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_BUFFER\n"));
821 /* Verify parameter count and types. */
822 if (cParms != SHCRGL_CPARMS_WRITE_BUFFER)
823 {
824 rc = VERR_INVALID_PARAMETER;
825 }
826 else
827 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /*iBufferID*/
828 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /*cbBufferSize*/
829 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /*ui32Offset*/
830 || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR /*pBuffer*/
831 )
832 {
833 rc = VERR_INVALID_PARAMETER;
834 }
835 else
836 {
837 /* Fetch parameters. */
838 uint32_t iBuffer = paParms[0].u.uint32;
839 uint32_t cbBufferSize = paParms[1].u.uint32;
840 uint32_t ui32Offset = paParms[2].u.uint32;
841 uint8_t *pBuffer = (uint8_t *)paParms[3].u.pointer.addr;
842 uint32_t cbBuffer = paParms[3].u.pointer.size;
843
844 /* Execute the function. */
845 CRVBOXSVCBUFFER_t *pSvcBuffer = svcGetBuffer(iBuffer, cbBufferSize);
846 if (!pSvcBuffer || ((uint64_t)ui32Offset+cbBuffer)>cbBufferSize)
847 {
848 rc = VERR_INVALID_PARAMETER;
849 }
850 else
851 {
852 memcpy((void*)((uintptr_t)pSvcBuffer->pData+ui32Offset), pBuffer, cbBuffer);
853
854 /* Return the buffer id */
855 paParms[0].u.uint32 = pSvcBuffer->uiId;
856 }
857 }
858
859 break;
860 }
861
862 case SHCRGL_GUEST_FN_WRITE_READ_BUFFERED:
863 {
864 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ_BUFFERED\n"));
865
866 /* Verify parameter count and types. */
867 if (cParms != SHCRGL_CPARMS_WRITE_READ_BUFFERED)
868 {
869 rc = VERR_INVALID_PARAMETER;
870 }
871 else
872 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* iBufferID */
873 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pWriteback */
874 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* cbWriteback */
875 || !paParms[0].u.uint32 /*iBufferID can't be 0 here*/
876 )
877 {
878 rc = VERR_INVALID_PARAMETER;
879 }
880 else
881 {
882 /* Fetch parameters. */
883 uint32_t iBuffer = paParms[0].u.uint32;
884 uint8_t *pWriteback = (uint8_t *)paParms[1].u.pointer.addr;
885 uint32_t cbWriteback = paParms[1].u.pointer.size;
886
887 CRVBOXSVCBUFFER_t *pSvcBuffer = svcGetBuffer(iBuffer, 0);
888 if (!pSvcBuffer)
889 {
890 LogRel(("SHARED_CROPENGL svcCall(WRITE_READ_BUFFERED): invalid buffer (%d)\n", iBuffer));
891 rc = VERR_INVALID_PARAMETER;
892 break;
893 }
894
895 uint8_t *pBuffer = (uint8_t *)pSvcBuffer->pData;
896 uint32_t cbBuffer = pSvcBuffer->uiSize;
897
898 /* Execute the function. */
899 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
900 if (!RT_SUCCESS(rc))
901 {
902 Assert(VERR_NOT_SUPPORTED==rc);
903 svcClientVersionUnsupported(0, 0);
904 }
905
906 rc = crVBoxServerClientRead(u32ClientID, pWriteback, &cbWriteback);
907
908 if (RT_SUCCESS(rc))
909 {
910 /* Update parameters.*/
911 paParms[1].u.pointer.size = cbWriteback;
912 }
913 /* Return the required buffer size always */
914 paParms[2].u.uint32 = cbWriteback;
915
916 svcFreeBuffer(pSvcBuffer);
917 }
918
919 break;
920 }
921
922 case SHCRGL_GUEST_FN_GET_CAPS_NEW:
923 {
924 Log(("svcCall: SHCRGL_GUEST_FN_GET_CAPS_NEW\n"));
925
926 /* Verify parameter count and types. */
927 if (cParms != SHCRGL_CPARMS_GET_CAPS_NEW)
928 {
929 WARN(("invalid parameter count"));
930 rc = VERR_INVALID_PARAMETER;
931 break;
932 }
933
934 if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
935 {
936 WARN(("invalid parameter"));
937 rc = VERR_INVALID_PARAMETER;
938 break;
939 }
940
941 if (paParms[0].u.pointer.size < sizeof (CR_CAPS_INFO))
942 {
943 WARN(("invalid buffer size"));
944 rc = VERR_INVALID_PARAMETER;
945 break;
946 }
947
948 CR_CAPS_INFO *pInfo = (CR_CAPS_INFO*)paParms[0].u.pointer.addr;
949 rc = crVBoxServerClientGetCapsNew(u32ClientID, pInfo);
950 AssertRC(rc);
951
952 break;
953 }
954
955 case SHCRGL_GUEST_FN_GET_CAPS_LEGACY:
956 {
957 Log(("svcCall: SHCRGL_GUEST_FN_GET_CAPS_LEGACY\n"));
958
959 /* Verify parameter count and types. */
960 if (cParms != SHCRGL_CPARMS_GET_CAPS_LEGACY)
961 {
962 rc = VERR_INVALID_PARAMETER;
963 }
964 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
965 {
966 rc = VERR_INVALID_PARAMETER;
967 }
968 else
969 {
970 /* Execute the function. */
971 rc = crVBoxServerClientGetCapsLegacy(u32ClientID, &paParms[0].u.uint32);
972 AssertRC(rc);
973 }
974
975 break;
976 }
977
978 default:
979 {
980 WARN(("svcCall: unexpected u32Function %d", u32Function));
981 rc = VERR_NOT_IMPLEMENTED;
982 }
983 }
984
985
986 LogFlow(("svcCall: rc = %Rrc\n", rc));
987
988 g_pHelpers->pfnCallComplete (callHandle, rc);
989}
990
991static void crScreenshotHandle(CRVBOXHGCMTAKESCREENSHOT *pScreenshot, uint32_t idScreen, uint64_t u64Now)
992{
993 if (!pScreenshot->pfnScreenshotBegin || pScreenshot->pfnScreenshotBegin(pScreenshot->pvContext, idScreen, u64Now))
994 {
995 CR_SCREENSHOT Screenshot;
996
997 int rc = crServerVBoxScreenshotGet(idScreen, pScreenshot->u32Width, pScreenshot->u32Height, pScreenshot->u32Pitch, pScreenshot->pvBuffer, &Screenshot);
998 if (RT_SUCCESS(rc))
999 {
1000 if (pScreenshot->pfnScreenshotPerform)
1001 pScreenshot->pfnScreenshotPerform(pScreenshot->pvContext, idScreen,
1002 0, 0, 32,
1003 Screenshot.Img.pitch, Screenshot.Img.width, Screenshot.Img.height,
1004 (uint8_t*)Screenshot.Img.pvData, u64Now);
1005 crServerVBoxScreenshotRelease(&Screenshot);
1006 }
1007 else
1008 {
1009 Assert(rc == VERR_INVALID_STATE);
1010 }
1011
1012 if (pScreenshot->pfnScreenshotEnd)
1013 pScreenshot->pfnScreenshotEnd(pScreenshot->pvContext, idScreen, u64Now);
1014 }
1015}
1016
1017/*
1018 * We differentiate between a function handler for the guest and one for the host.
1019 */
1020static int svcHostCallPerform(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
1021{
1022 int rc = VINF_SUCCESS;
1023
1024 Log(("SHARED_CROPENGL svcHostCall: fn = %d, cParms = %d, pparms = %d\n", u32Function, cParms, paParms));
1025
1026#ifdef DEBUG
1027 uint32_t i;
1028
1029 for (i = 0; i < cParms; i++)
1030 {
1031 /** @todo parameters other than 32 bit */
1032 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
1033 }
1034#endif
1035
1036 switch (u32Function)
1037 {
1038#ifdef VBOX_WITH_CRHGSMI
1039 case SHCRGL_HOST_FN_CRHGSMI_CMD:
1040 {
1041 Assert(cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR);
1042 if (cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR)
1043 {
1044 rc = crVBoxServerCrHgsmiCmd((PVBOXVDMACMD_CHROMIUM_CMD)paParms[0].u.pointer.addr, paParms[0].u.pointer.size);
1045 if (VERR_NOT_SUPPORTED == rc)
1046 {
1047 svcClientVersionUnsupported(0, 0);
1048 }
1049 }
1050 else
1051 rc = VERR_INVALID_PARAMETER;
1052 } break;
1053 case SHCRGL_HOST_FN_CRHGSMI_CTL:
1054 {
1055 Assert(cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR);
1056 if (cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR)
1057 rc = crVBoxServerCrHgsmiCtl((PVBOXVDMACMD_CHROMIUM_CTL)paParms[0].u.pointer.addr, paParms[0].u.pointer.size);
1058 else
1059 rc = VERR_INVALID_PARAMETER;
1060 } break;
1061#endif
1062 case SHCRGL_HOST_FN_SET_CONSOLE:
1063 {
1064 Log(("svcCall: SHCRGL_HOST_FN_SET_DISPLAY\n"));
1065
1066 /* Verify parameter count and types. */
1067 if (cParms != SHCRGL_CPARMS_SET_CONSOLE)
1068 {
1069 rc = VERR_INVALID_PARAMETER;
1070 }
1071 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1072 {
1073 rc = VERR_INVALID_PARAMETER;
1074 }
1075 else
1076 {
1077 /* Fetch parameters. */
1078 IConsole* pConsole = (IConsole*)paParms[0].u.pointer.addr;
1079 uint32_t cbData = paParms[0].u.pointer.size;
1080
1081 /* Verify parameters values. */
1082 if (cbData != sizeof (IConsole*))
1083 {
1084 rc = VERR_INVALID_PARAMETER;
1085 }
1086 else if (!pConsole)
1087 {
1088 rc = VERR_INVALID_PARAMETER;
1089 }
1090 else /* Execute the function. */
1091 {
1092 ComPtr<IMachine> pMachine;
1093 ComPtr<IDisplay> pDisplay;
1094 ComPtr<IFramebuffer> pFramebuffer;
1095 LONG xo, yo;
1096 LONG64 winId = 0;
1097 ULONG monitorCount, i, w, h;
1098
1099 CHECK_ERROR_BREAK(pConsole, COMGETTER(Machine)(pMachine.asOutParam()));
1100 CHECK_ERROR_BREAK(pMachine, COMGETTER(MonitorCount)(&monitorCount));
1101 CHECK_ERROR_BREAK(pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
1102
1103 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1104
1105 g_pConsole = pConsole;
1106 g_u32ScreenCount = monitorCount;
1107
1108 rc = crVBoxServerSetScreenCount(monitorCount);
1109 AssertRCReturn(rc, rc);
1110
1111 for (i=0; i<monitorCount; ++i)
1112 {
1113 CHECK_ERROR_RET(pDisplay, QueryFramebuffer(i, pFramebuffer.asOutParam()), rc);
1114
1115 if (!pFramebuffer)
1116 {
1117 rc = crVBoxServerUnmapScreen(i);
1118 AssertRCReturn(rc, rc);
1119 }
1120 else
1121 {
1122 CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
1123 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
1124 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
1125 CHECK_ERROR_RET(pDisplay, GetScreenResolution(i, NULL, NULL, NULL, &xo, &yo), rc);
1126
1127 rc = crVBoxServerMapScreen(i, xo, yo, w, h, winId);
1128 AssertRCReturn(rc, rc);
1129 }
1130 }
1131
1132 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1133
1134 rc = VINF_SUCCESS;
1135 }
1136 }
1137 break;
1138 }
1139 case SHCRGL_HOST_FN_SET_VM:
1140 {
1141 Log(("svcCall: SHCRGL_HOST_FN_SET_VM\n"));
1142
1143 /* Verify parameter count and types. */
1144 if (cParms != SHCRGL_CPARMS_SET_VM)
1145 {
1146 rc = VERR_INVALID_PARAMETER;
1147 }
1148 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1149 {
1150 rc = VERR_INVALID_PARAMETER;
1151 }
1152 else
1153 {
1154 /* Fetch parameters. */
1155 PVM pVM = (PVM)paParms[0].u.pointer.addr;
1156 uint32_t cbData = paParms[0].u.pointer.size;
1157
1158 /* Verify parameters values. */
1159 if (cbData != sizeof (PVM))
1160 {
1161 rc = VERR_INVALID_PARAMETER;
1162 }
1163 else
1164 {
1165 /* Execute the function. */
1166 g_pVM = pVM;
1167 rc = VINF_SUCCESS;
1168 }
1169 }
1170 break;
1171 }
1172 case SHCRGL_HOST_FN_SET_VISIBLE_REGION:
1173 {
1174 Log(("svcCall: SHCRGL_HOST_FN_SET_VISIBLE_REGION\n"));
1175
1176 if (cParms != SHCRGL_CPARMS_SET_VISIBLE_REGION)
1177 {
1178 rc = VERR_INVALID_PARAMETER;
1179 break;
1180 }
1181
1182 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pRects */
1183 )
1184 {
1185 rc = VERR_INVALID_PARAMETER;
1186 break;
1187 }
1188
1189 Assert(sizeof (RTRECT) == 4 * sizeof (GLint));
1190
1191 rc = crVBoxServerSetRootVisibleRegion(paParms[0].u.pointer.size / sizeof (RTRECT), (const RTRECT*)paParms[0].u.pointer.addr);
1192 break;
1193 }
1194 case SHCRGL_HOST_FN_SCREEN_CHANGED:
1195 {
1196 Log(("svcCall: SHCRGL_HOST_FN_SCREEN_CHANGED\n"));
1197
1198 /* Verify parameter count and types. */
1199 if (cParms != SHCRGL_CPARMS_SCREEN_CHANGED)
1200 {
1201 rc = VERR_INVALID_PARAMETER;
1202 }
1203 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
1204 {
1205 rc = VERR_INVALID_PARAMETER;
1206 }
1207 else
1208 {
1209 /* Fetch parameters. */
1210 uint32_t screenId = paParms[0].u.uint32;
1211
1212 /* Execute the function. */
1213 ComPtr<IDisplay> pDisplay;
1214 ComPtr<IFramebuffer> pFramebuffer;
1215 LONG xo, yo;
1216 LONG64 winId = 0;
1217 ULONG w, h;
1218
1219 Assert(g_pConsole);
1220 CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc);
1221 CHECK_ERROR_RET(pDisplay, QueryFramebuffer(screenId, pFramebuffer.asOutParam()), rc);
1222
1223 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1224
1225 if (!pFramebuffer)
1226 {
1227 rc = crVBoxServerUnmapScreen(screenId);
1228 AssertRCReturn(rc, rc);
1229 }
1230 else
1231 {
1232 do {
1233 /* determine if the framebuffer is functional */
1234 com::SafeArray<BYTE> data;
1235 rc = pFramebuffer->Notify3DEvent(VBOX3D_NOTIFY_EVENT_TYPE_TEST_FUNCTIONAL, ComSafeArrayAsInParam(data));
1236
1237 if (rc == S_OK)
1238 CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(WinId)(&winId));
1239
1240 if (!winId)
1241 {
1242 /* View associated with framebuffer is destroyed, happens with 2d accel enabled */
1243 rc = crVBoxServerUnmapScreen(screenId);
1244 AssertRCReturn(rc, rc);
1245 }
1246 else
1247 {
1248 CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Width)(&w));
1249 CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Height)(&h));
1250 CHECK_ERROR_BREAK(pDisplay, GetScreenResolution(screenId, NULL, NULL, NULL, &xo, &yo));
1251
1252 rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId);
1253 AssertRCReturn(rc, rc);
1254 }
1255 } while (0);
1256 }
1257
1258 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1259
1260 rc = VINF_SUCCESS;
1261 }
1262 break;
1263 }
1264 case SHCRGL_HOST_FN_TAKE_SCREENSHOT:
1265 {
1266 if (cParms != 1)
1267 {
1268 LogRel(("SHCRGL_HOST_FN_TAKE_SCREENSHOT: cParms invalid - %d", cParms));
1269 rc = VERR_INVALID_PARAMETER;
1270 break;
1271 }
1272
1273 if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
1274 {
1275 AssertMsgFailed(("invalid param\n"));
1276 rc = VERR_INVALID_PARAMETER;
1277 break;
1278 }
1279
1280 if (!paParms->u.pointer.addr)
1281 {
1282 AssertMsgFailed(("invalid param\n"));
1283 rc = VERR_INVALID_PARAMETER;
1284 break;
1285 }
1286
1287 if (paParms->u.pointer.size != sizeof (CRVBOXHGCMTAKESCREENSHOT))
1288 {
1289 AssertMsgFailed(("invalid param\n"));
1290 rc = VERR_INVALID_PARAMETER;
1291 break;
1292 }
1293
1294 CRVBOXHGCMTAKESCREENSHOT *pScreenshot = (CRVBOXHGCMTAKESCREENSHOT*)paParms->u.pointer.addr;
1295 uint64_t u64Now = RTTimeProgramMilliTS();
1296
1297 if (pScreenshot->u32Screen == CRSCREEN_ALL)
1298 {
1299 for (uint32_t i = 0; i < g_u32ScreenCount; ++i)
1300 {
1301 crScreenshotHandle(pScreenshot, i, u64Now);
1302 }
1303 }
1304 else if (pScreenshot->u32Screen < g_u32ScreenCount)
1305 {
1306 crScreenshotHandle(pScreenshot, pScreenshot->u32Screen, u64Now);
1307 }
1308 else
1309 {
1310 AssertMsgFailed(("invalid screen id\n"));
1311 rc = VERR_INVALID_PARAMETER;
1312 break;
1313 }
1314 break;
1315 }
1316 case SHCRGL_HOST_FN_DEV_RESIZE:
1317 {
1318 Log(("svcCall: SHCRGL_HOST_FN_DEV_RESIZE\n"));
1319
1320 /* Verify parameter count and types. */
1321 if (cParms != SHCRGL_CPARMS_DEV_RESIZE)
1322 {
1323 LogRel(("SHCRGL_HOST_FN_DEV_RESIZE: cParms invalid - %d", cParms));
1324 rc = VERR_INVALID_PARAMETER;
1325 break;
1326 }
1327
1328 if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
1329 {
1330 AssertMsgFailed(("invalid param\n"));
1331 return VERR_INVALID_PARAMETER;
1332 }
1333
1334 if (!paParms->u.pointer.addr)
1335 {
1336 AssertMsgFailed(("invalid param\n"));
1337 return VERR_INVALID_PARAMETER;
1338 }
1339
1340 if (paParms->u.pointer.size != sizeof (CRVBOXHGCMDEVRESIZE))
1341 {
1342 AssertMsgFailed(("invalid param\n"));
1343 return VERR_INVALID_PARAMETER;
1344 }
1345
1346 CRVBOXHGCMDEVRESIZE *pResize = (CRVBOXHGCMDEVRESIZE*)paParms->u.pointer.addr;
1347
1348 rc = crVBoxServerNotifyResize(&pResize->Screen, pResize->pvVRAM);
1349 break;
1350 }
1351 case SHCRGL_HOST_FN_VIEWPORT_CHANGED:
1352 {
1353 Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
1354
1355 /* Verify parameter count and types. */
1356 if (cParms != SHCRGL_CPARMS_VIEWPORT_CHANGED)
1357 {
1358 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: cParms invalid - %d", cParms));
1359 rc = VERR_INVALID_PARAMETER;
1360 break;
1361 }
1362
1363 for (int i = 0; i < SHCRGL_CPARMS_VIEWPORT_CHANGED; ++i)
1364 {
1365 if (paParms[i].type != VBOX_HGCM_SVC_PARM_32BIT)
1366 {
1367 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param[%d] type invalid - %d", i, paParms[i].type));
1368 rc = VERR_INVALID_PARAMETER;
1369 break;
1370 }
1371 }
1372
1373 if (!RT_SUCCESS(rc))
1374 {
1375 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param validation failed, returning.."));
1376 break;
1377 }
1378
1379 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1380
1381 rc = crVBoxServerSetScreenViewport((int)paParms[0].u.uint32,
1382 paParms[1].u.uint32, /* x */
1383 paParms[2].u.uint32, /* y */
1384 paParms[3].u.uint32, /* w */
1385 paParms[4].u.uint32 /* h */);
1386 if (!RT_SUCCESS(rc))
1387 {
1388 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc));
1389 }
1390
1391 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1392
1393 break;
1394 }
1395 case SHCRGL_HOST_FN_VIEWPORT_CHANGED2:
1396 {
1397 Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
1398
1399 /* Verify parameter count and types. */
1400 if (cParms != SHCRGL_CPARMS_VIEWPORT_CHANGED)
1401 {
1402 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: cParms invalid - %d", cParms));
1403 rc = VERR_INVALID_PARAMETER;
1404 break;
1405 }
1406
1407 if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR
1408 || !paParms[0].u.pointer.addr
1409 || paParms[0].u.pointer.size != sizeof (CRVBOXHGCMVIEWPORT))
1410 {
1411 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param invalid - %d, %#x, %d",
1412 paParms[0].type,
1413 paParms[0].u.pointer.addr,
1414 paParms[0].u.pointer.size));
1415 rc = VERR_INVALID_PARAMETER;
1416 break;
1417 }
1418
1419 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1420
1421 CRVBOXHGCMVIEWPORT *pViewportInfo = (CRVBOXHGCMVIEWPORT*)paParms[0].u.pointer.addr;
1422
1423 rc = crVBoxServerSetScreenViewport(pViewportInfo->u32Screen,
1424 pViewportInfo->x, /* x */
1425 pViewportInfo->y, /* y */
1426 pViewportInfo->width, /* w */
1427 pViewportInfo->height /* h */);
1428 if (!RT_SUCCESS(rc))
1429 {
1430 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc));
1431 }
1432
1433 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1434
1435 break;
1436 }
1437 case SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT:
1438 {
1439 /*
1440 * OutputRedirect.
1441 * Note: the service calls OutputRedirect callbacks directly
1442 * and they must not block. If asynchronous processing is needed,
1443 * the callback provider must organize this.
1444 */
1445 Log(("svcCall: SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT\n"));
1446
1447 /* Verify parameter count and types. */
1448 if (cParms != SHCRGL_CPARMS_SET_OUTPUT_REDIRECT)
1449 {
1450 rc = VERR_INVALID_PARAMETER;
1451 }
1452 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1453 {
1454 rc = VERR_INVALID_PARAMETER;
1455 }
1456 else
1457 {
1458 /* Fetch parameters. */
1459 H3DOUTPUTREDIRECT *pOutputRedirect = (H3DOUTPUTREDIRECT *)paParms[0].u.pointer.addr;
1460 uint32_t cbData = paParms[0].u.pointer.size;
1461
1462 /* Verify parameters values. */
1463 if (cbData != sizeof (H3DOUTPUTREDIRECT))
1464 {
1465 rc = VERR_INVALID_PARAMETER;
1466 }
1467 else /* Execute the function. */
1468 {
1469 if (pOutputRedirect->H3DORBegin != NULL)
1470 {
1471 CROutputRedirect outputRedirect;
1472 outputRedirect.pvContext = pOutputRedirect->pvContext;
1473 outputRedirect.CRORBegin = pOutputRedirect->H3DORBegin;
1474 outputRedirect.CRORGeometry = pOutputRedirect->H3DORGeometry;
1475 outputRedirect.CRORVisibleRegion = pOutputRedirect->H3DORVisibleRegion;
1476 outputRedirect.CRORFrame = pOutputRedirect->H3DORFrame;
1477 outputRedirect.CROREnd = pOutputRedirect->H3DOREnd;
1478 outputRedirect.CRORContextProperty = pOutputRedirect->H3DORContextProperty;
1479 rc = crVBoxServerOutputRedirectSet(&outputRedirect);
1480 if (RT_SUCCESS(rc))
1481 {
1482 rc = crVBoxServerSetOffscreenRendering(GL_TRUE);
1483 }
1484 }
1485 else
1486 {
1487 /* Redirection is disabled. */
1488 crVBoxServerSetOffscreenRendering(GL_FALSE);
1489 crVBoxServerOutputRedirectSet(NULL);
1490 }
1491 }
1492 }
1493 break;
1494 }
1495 case SHCRGL_HOST_FN_WINDOWS_SHOW:
1496 {
1497 /* Verify parameter count and types. */
1498 if (cParms != 1)
1499 {
1500 WARN(("invalid parameter"));
1501 rc = VERR_INVALID_PARAMETER;
1502 break;
1503 }
1504
1505 if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
1506 {
1507 WARN(("invalid parameter"));
1508 rc = VERR_INVALID_PARAMETER;
1509 break;
1510 }
1511
1512 rc = crServerVBoxWindowsShow(!!paParms[0].u.uint32);
1513 if (!RT_SUCCESS(rc))
1514 WARN(("crServerVBoxWindowsShow failed rc %d", rc));
1515
1516 break;
1517 }
1518 default:
1519 WARN(("svcHostCallPerform: unexpected u32Function %d", u32Function));
1520 rc = VERR_NOT_IMPLEMENTED;
1521 break;
1522 }
1523
1524 LogFlow(("svcHostCall: rc = %Rrc\n", rc));
1525 return rc;
1526}
1527
1528int crVBoxServerHostCtl(VBOXCRCMDCTL *pCtl, uint32_t cbCtl)
1529{
1530 if ((cbCtl - sizeof (VBOXCRCMDCTL)) % sizeof(VBOXHGCMSVCPARM))
1531 {
1532 WARN(("invalid param size"));
1533 return VERR_INVALID_PARAMETER;
1534 }
1535 uint32_t cParams = (cbCtl - sizeof (VBOXCRCMDCTL)) / sizeof (VBOXHGCMSVCPARM);
1536 return svcHostCallPerform(pCtl->u32Function, cParams, (VBOXHGCMSVCPARM*)(pCtl + 1));
1537}
1538
1539static DECLCALLBACK(int) svcHostCall(void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
1540{
1541 switch (u32Function)
1542 {
1543 case SHCRGL_HOST_FN_CTL:
1544 {
1545 if (cParms != 1)
1546 {
1547 WARN(("cParams != 1"));
1548 return VERR_INVALID_PARAMETER;
1549 }
1550
1551 if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
1552 {
1553 WARN(("invalid param type"));
1554 return VERR_INVALID_PARAMETER;
1555 }
1556
1557 if (paParms->u.pointer.size < sizeof (VBOXCRCMDCTL))
1558 {
1559 WARN(("invalid param size"));
1560 return VERR_INVALID_PARAMETER;
1561 }
1562
1563 VBOXCRCMDCTL *pCtl = (VBOXCRCMDCTL*)paParms->u.pointer.addr;
1564 switch (pCtl->enmType)
1565 {
1566 case VBOXCRCMDCTL_TYPE_HGCM:
1567 {
1568 return crVBoxServerHostCtl(pCtl, paParms->u.pointer.size);
1569 }
1570 case VBOXCRCMDCTL_TYPE_DISABLE:
1571 {
1572 if (paParms->u.pointer.size != sizeof (VBOXCRCMDCTL_DISABLE))
1573 WARN(("invalid param size"));
1574 VBOXCRCMDCTL_DISABLE *pDisable = (VBOXCRCMDCTL_DISABLE*)pCtl;
1575 int rc = crVBoxServerHgcmDisable(&pDisable->Data);
1576 if (RT_SUCCESS(rc))
1577 g_u32fCrHgcmDisabled = 1;
1578 else
1579 WARN(("crVBoxServerHgcmDisable failed %d", rc));
1580 return rc;
1581 }
1582 case VBOXCRCMDCTL_TYPE_ENABLE:
1583 {
1584 if (paParms->u.pointer.size != sizeof (VBOXCRCMDCTL_ENABLE))
1585 WARN(("invalid param size"));
1586 VBOXCRCMDCTL_ENABLE *pEnable = (VBOXCRCMDCTL_ENABLE*)pCtl;
1587 int rc = crVBoxServerHgcmEnable(&pEnable->Data);
1588 if (RT_SUCCESS(rc))
1589 g_u32fCrHgcmDisabled = 0;
1590 else
1591 WARN(("crVBoxServerHgcmEnable failed %d", rc));
1592 return rc;
1593 }
1594 default:
1595 WARN(("svcHostCall: invalid function %d", pCtl->enmType));
1596 return VERR_INVALID_PARAMETER;
1597 }
1598 WARN(("should not be here!"));
1599 return VERR_INTERNAL_ERROR;
1600 }
1601 default:
1602 if (g_u32fCrHgcmDisabled)
1603 {
1604 WARN(("cr hgcm disabled!"));
1605 return VERR_INVALID_STATE;
1606 }
1607 return svcHostCallPerform(u32Function, cParms, paParms);
1608 }
1609}
1610
1611extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
1612{
1613 int rc = VINF_SUCCESS;
1614
1615 Log(("SHARED_CROPENGL VBoxHGCMSvcLoad: ptable = %p\n", ptable));
1616
1617 if (!ptable)
1618 {
1619 rc = VERR_INVALID_PARAMETER;
1620 }
1621 else
1622 {
1623 Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
1624
1625 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
1626 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
1627 {
1628 rc = VERR_INVALID_PARAMETER;
1629 }
1630 else
1631 {
1632 g_pHelpers = ptable->pHelpers;
1633
1634 g_u32fCrHgcmDisabled = 0;
1635
1636 ptable->cbClient = sizeof (void*);
1637
1638 ptable->pfnUnload = svcUnload;
1639 ptable->pfnConnect = svcConnect;
1640 ptable->pfnDisconnect = svcDisconnect;
1641 ptable->pfnCall = svcCall;
1642 ptable->pfnHostCall = svcHostCall;
1643 ptable->pfnSaveState = svcSaveState;
1644 ptable->pfnLoadState = svcLoadState;
1645 ptable->pvService = NULL;
1646
1647 if (!crVBoxServerInit())
1648 return VERR_NOT_SUPPORTED;
1649
1650 rc = svcPresentFBOInit();
1651
1652 crServerVBoxSetNotifyEventCB(svcNotifyEventCB);
1653 }
1654 }
1655
1656 return rc;
1657}
1658
1659#ifdef RT_OS_WINDOWS
1660#define WIN32_LEAN_AND_MEAN
1661#include <windows.h>
1662BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
1663{
1664 (void) lpvReserved;
1665
1666 switch (fdwReason)
1667 {
1668 case DLL_THREAD_ATTACH:
1669 {
1670 crStateVBoxAttachThread();
1671 break;
1672 }
1673
1674 case DLL_PROCESS_DETACH:
1675 /* do exactly the same thing as for DLL_THREAD_DETACH since
1676 * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */
1677 case DLL_THREAD_DETACH:
1678 {
1679 crStateVBoxDetachThread();
1680 break;
1681 }
1682
1683 case DLL_PROCESS_ATTACH:
1684 default:
1685 break;
1686 }
1687
1688 return TRUE;
1689}
1690#endif
Note: See TracBrowser for help on using the repository browser.

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