VirtualBox

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

Last change on this file since 52722 was 52429, checked in by vboxsync, 10 years ago

crOpenGL: 1. osx: do everything we can do in the main thread 2. bugfixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 53.4 KB
Line 
1/* $Id: crservice.cpp 52429 2014-08-20 11:58:38Z 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 g_pConsole = pConsole;
1104 g_u32ScreenCount = monitorCount;
1105
1106 rc = crVBoxServerSetScreenCount(monitorCount);
1107 AssertRCReturn(rc, rc);
1108
1109#if 1
1110 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1111
1112 for (i=0; i<monitorCount; ++i)
1113 {
1114 CHECK_ERROR_RET(pDisplay, QueryFramebuffer(i, pFramebuffer.asOutParam()), rc);
1115
1116 if (!pFramebuffer)
1117 {
1118 rc = crVBoxServerUnmapScreen(i);
1119 AssertRCReturn(rc, rc);
1120 }
1121 else
1122 {
1123 CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
1124 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
1125 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
1126 ULONG dummy;
1127 CHECK_ERROR_RET(pDisplay, GetScreenResolution(i, &dummy, &dummy, &dummy, &xo, &yo), rc);
1128
1129 rc = crVBoxServerMapScreen(i, xo, yo, w, h, winId);
1130 AssertRCReturn(rc, rc);
1131 }
1132 }
1133
1134 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1135#endif
1136
1137 rc = VINF_SUCCESS;
1138 }
1139 }
1140 break;
1141 }
1142 case SHCRGL_HOST_FN_SET_VM:
1143 {
1144 Log(("svcCall: SHCRGL_HOST_FN_SET_VM\n"));
1145
1146 /* Verify parameter count and types. */
1147 if (cParms != SHCRGL_CPARMS_SET_VM)
1148 {
1149 rc = VERR_INVALID_PARAMETER;
1150 }
1151 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1152 {
1153 rc = VERR_INVALID_PARAMETER;
1154 }
1155 else
1156 {
1157 /* Fetch parameters. */
1158 PVM pVM = (PVM)paParms[0].u.pointer.addr;
1159 uint32_t cbData = paParms[0].u.pointer.size;
1160
1161 /* Verify parameters values. */
1162 if (cbData != sizeof (PVM))
1163 {
1164 rc = VERR_INVALID_PARAMETER;
1165 }
1166 else
1167 {
1168 /* Execute the function. */
1169 g_pVM = pVM;
1170 rc = VINF_SUCCESS;
1171 }
1172 }
1173 break;
1174 }
1175 case SHCRGL_HOST_FN_SET_VISIBLE_REGION:
1176 {
1177 Log(("svcCall: SHCRGL_HOST_FN_SET_VISIBLE_REGION\n"));
1178
1179 if (cParms != SHCRGL_CPARMS_SET_VISIBLE_REGION)
1180 {
1181 rc = VERR_INVALID_PARAMETER;
1182 break;
1183 }
1184
1185 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pRects */
1186 )
1187 {
1188 rc = VERR_INVALID_PARAMETER;
1189 break;
1190 }
1191
1192 Assert(sizeof (RTRECT) == 4 * sizeof (GLint));
1193
1194 rc = crVBoxServerSetRootVisibleRegion(paParms[0].u.pointer.size / sizeof (RTRECT), (const RTRECT*)paParms[0].u.pointer.addr);
1195 break;
1196 }
1197 case SHCRGL_HOST_FN_SCREEN_CHANGED:
1198 {
1199 Log(("svcCall: SHCRGL_HOST_FN_SCREEN_CHANGED\n"));
1200
1201 /* Verify parameter count and types. */
1202 if (cParms != SHCRGL_CPARMS_SCREEN_CHANGED)
1203 {
1204 rc = VERR_INVALID_PARAMETER;
1205 }
1206 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
1207 {
1208 rc = VERR_INVALID_PARAMETER;
1209 }
1210 else
1211 {
1212 /* Fetch parameters. */
1213 uint32_t screenId = paParms[0].u.uint32;
1214
1215 /* Execute the function. */
1216 ComPtr<IDisplay> pDisplay;
1217 ComPtr<IFramebuffer> pFramebuffer;
1218 LONG xo, yo;
1219 LONG64 winId = 0;
1220 ULONG w, h;
1221
1222 Assert(g_pConsole);
1223 CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc);
1224 CHECK_ERROR_RET(pDisplay, QueryFramebuffer(screenId, pFramebuffer.asOutParam()), rc);
1225
1226 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1227
1228 if (!pFramebuffer)
1229 {
1230 rc = crVBoxServerUnmapScreen(screenId);
1231 AssertRCReturn(rc, rc);
1232 }
1233 else
1234 {
1235 do {
1236 /* determine if the framebuffer is functional */
1237 com::SafeArray<BYTE> data;
1238 rc = pFramebuffer->Notify3DEvent(VBOX3D_NOTIFY_EVENT_TYPE_TEST_FUNCTIONAL, ComSafeArrayAsInParam(data));
1239
1240 if (rc == S_OK)
1241 CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(WinId)(&winId));
1242
1243 if (!winId)
1244 {
1245 /* View associated with framebuffer is destroyed, happens with 2d accel enabled */
1246 rc = crVBoxServerUnmapScreen(screenId);
1247 AssertRCReturn(rc, rc);
1248 }
1249 else
1250 {
1251 CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Width)(&w));
1252 CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Height)(&h));
1253 ULONG dummy;
1254 CHECK_ERROR_BREAK(pDisplay, GetScreenResolution(screenId, &dummy, &dummy, &dummy, &xo, &yo));
1255
1256 rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId);
1257 AssertRCReturn(rc, rc);
1258 }
1259 } while (0);
1260 }
1261
1262 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1263
1264 rc = VINF_SUCCESS;
1265 }
1266 break;
1267 }
1268 case SHCRGL_HOST_FN_TAKE_SCREENSHOT:
1269 {
1270 if (cParms != 1)
1271 {
1272 LogRel(("SHCRGL_HOST_FN_TAKE_SCREENSHOT: cParms invalid - %d", cParms));
1273 rc = VERR_INVALID_PARAMETER;
1274 break;
1275 }
1276
1277 if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
1278 {
1279 AssertMsgFailed(("invalid param\n"));
1280 rc = VERR_INVALID_PARAMETER;
1281 break;
1282 }
1283
1284 if (!paParms->u.pointer.addr)
1285 {
1286 AssertMsgFailed(("invalid param\n"));
1287 rc = VERR_INVALID_PARAMETER;
1288 break;
1289 }
1290
1291 if (paParms->u.pointer.size != sizeof (CRVBOXHGCMTAKESCREENSHOT))
1292 {
1293 AssertMsgFailed(("invalid param\n"));
1294 rc = VERR_INVALID_PARAMETER;
1295 break;
1296 }
1297
1298 CRVBOXHGCMTAKESCREENSHOT *pScreenshot = (CRVBOXHGCMTAKESCREENSHOT*)paParms->u.pointer.addr;
1299 uint64_t u64Now = RTTimeProgramMilliTS();
1300
1301 if (pScreenshot->u32Screen == CRSCREEN_ALL)
1302 {
1303 for (uint32_t i = 0; i < g_u32ScreenCount; ++i)
1304 {
1305 crScreenshotHandle(pScreenshot, i, u64Now);
1306 }
1307 }
1308 else if (pScreenshot->u32Screen < g_u32ScreenCount)
1309 {
1310 crScreenshotHandle(pScreenshot, pScreenshot->u32Screen, u64Now);
1311 }
1312 else
1313 {
1314 AssertMsgFailed(("invalid screen id\n"));
1315 rc = VERR_INVALID_PARAMETER;
1316 break;
1317 }
1318 break;
1319 }
1320 case SHCRGL_HOST_FN_DEV_RESIZE:
1321 {
1322 Log(("svcCall: SHCRGL_HOST_FN_DEV_RESIZE\n"));
1323
1324 /* Verify parameter count and types. */
1325 if (cParms != SHCRGL_CPARMS_DEV_RESIZE)
1326 {
1327 LogRel(("SHCRGL_HOST_FN_DEV_RESIZE: cParms invalid - %d", cParms));
1328 rc = VERR_INVALID_PARAMETER;
1329 break;
1330 }
1331
1332 if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
1333 {
1334 AssertMsgFailed(("invalid param\n"));
1335 return VERR_INVALID_PARAMETER;
1336 }
1337
1338 if (!paParms->u.pointer.addr)
1339 {
1340 AssertMsgFailed(("invalid param\n"));
1341 return VERR_INVALID_PARAMETER;
1342 }
1343
1344 if (paParms->u.pointer.size != sizeof (CRVBOXHGCMDEVRESIZE))
1345 {
1346 AssertMsgFailed(("invalid param\n"));
1347 return VERR_INVALID_PARAMETER;
1348 }
1349
1350 CRVBOXHGCMDEVRESIZE *pResize = (CRVBOXHGCMDEVRESIZE*)paParms->u.pointer.addr;
1351
1352 rc = crVBoxServerNotifyResize(&pResize->Screen, pResize->pvVRAM);
1353 break;
1354 }
1355 case SHCRGL_HOST_FN_VIEWPORT_CHANGED:
1356 {
1357 Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
1358
1359 /* Verify parameter count and types. */
1360 if (cParms != SHCRGL_CPARMS_VIEWPORT_CHANGED)
1361 {
1362 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: cParms invalid - %d", cParms));
1363 rc = VERR_INVALID_PARAMETER;
1364 break;
1365 }
1366
1367 for (int i = 0; i < SHCRGL_CPARMS_VIEWPORT_CHANGED; ++i)
1368 {
1369 if (paParms[i].type != VBOX_HGCM_SVC_PARM_32BIT)
1370 {
1371 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param[%d] type invalid - %d", i, paParms[i].type));
1372 rc = VERR_INVALID_PARAMETER;
1373 break;
1374 }
1375 }
1376
1377 if (!RT_SUCCESS(rc))
1378 {
1379 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param validation failed, returning.."));
1380 break;
1381 }
1382
1383 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1384
1385 rc = crVBoxServerSetScreenViewport((int)paParms[0].u.uint32,
1386 paParms[1].u.uint32, /* x */
1387 paParms[2].u.uint32, /* y */
1388 paParms[3].u.uint32, /* w */
1389 paParms[4].u.uint32 /* h */);
1390 if (!RT_SUCCESS(rc))
1391 {
1392 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc));
1393 }
1394
1395 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1396
1397 break;
1398 }
1399 case SHCRGL_HOST_FN_VIEWPORT_CHANGED2:
1400 {
1401 Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
1402
1403 /* Verify parameter count and types. */
1404 if (cParms != SHCRGL_CPARMS_VIEWPORT_CHANGED)
1405 {
1406 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: cParms invalid - %d", cParms));
1407 rc = VERR_INVALID_PARAMETER;
1408 break;
1409 }
1410
1411 if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR
1412 || !paParms[0].u.pointer.addr
1413 || paParms[0].u.pointer.size != sizeof (CRVBOXHGCMVIEWPORT))
1414 {
1415 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param invalid - %d, %#x, %d",
1416 paParms[0].type,
1417 paParms[0].u.pointer.addr,
1418 paParms[0].u.pointer.size));
1419 rc = VERR_INVALID_PARAMETER;
1420 break;
1421 }
1422
1423 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1424
1425 CRVBOXHGCMVIEWPORT *pViewportInfo = (CRVBOXHGCMVIEWPORT*)paParms[0].u.pointer.addr;
1426
1427 rc = crVBoxServerSetScreenViewport(pViewportInfo->u32Screen,
1428 pViewportInfo->x, /* x */
1429 pViewportInfo->y, /* y */
1430 pViewportInfo->width, /* w */
1431 pViewportInfo->height /* h */);
1432 if (!RT_SUCCESS(rc))
1433 {
1434 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc));
1435 }
1436
1437 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1438
1439 break;
1440 }
1441 case SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT:
1442 {
1443 /*
1444 * OutputRedirect.
1445 * Note: the service calls OutputRedirect callbacks directly
1446 * and they must not block. If asynchronous processing is needed,
1447 * the callback provider must organize this.
1448 */
1449 Log(("svcCall: SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT\n"));
1450
1451 /* Verify parameter count and types. */
1452 if (cParms != SHCRGL_CPARMS_SET_OUTPUT_REDIRECT)
1453 {
1454 rc = VERR_INVALID_PARAMETER;
1455 }
1456 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1457 {
1458 rc = VERR_INVALID_PARAMETER;
1459 }
1460 else
1461 {
1462 /* Fetch parameters. */
1463 H3DOUTPUTREDIRECT *pOutputRedirect = (H3DOUTPUTREDIRECT *)paParms[0].u.pointer.addr;
1464 uint32_t cbData = paParms[0].u.pointer.size;
1465
1466 /* Verify parameters values. */
1467 if (cbData != sizeof (H3DOUTPUTREDIRECT))
1468 {
1469 rc = VERR_INVALID_PARAMETER;
1470 }
1471 else /* Execute the function. */
1472 {
1473 if (pOutputRedirect->H3DORBegin != NULL)
1474 {
1475 CROutputRedirect outputRedirect;
1476 outputRedirect.pvContext = pOutputRedirect->pvContext;
1477 outputRedirect.CRORBegin = pOutputRedirect->H3DORBegin;
1478 outputRedirect.CRORGeometry = pOutputRedirect->H3DORGeometry;
1479 outputRedirect.CRORVisibleRegion = pOutputRedirect->H3DORVisibleRegion;
1480 outputRedirect.CRORFrame = pOutputRedirect->H3DORFrame;
1481 outputRedirect.CROREnd = pOutputRedirect->H3DOREnd;
1482 outputRedirect.CRORContextProperty = pOutputRedirect->H3DORContextProperty;
1483 rc = crVBoxServerOutputRedirectSet(&outputRedirect);
1484 if (RT_SUCCESS(rc))
1485 {
1486 rc = crVBoxServerSetOffscreenRendering(GL_TRUE);
1487 }
1488 }
1489 else
1490 {
1491 /* Redirection is disabled. */
1492 crVBoxServerSetOffscreenRendering(GL_FALSE);
1493 crVBoxServerOutputRedirectSet(NULL);
1494 }
1495 }
1496 }
1497 break;
1498 }
1499 case SHCRGL_HOST_FN_WINDOWS_SHOW:
1500 {
1501 /* Verify parameter count and types. */
1502 if (cParms != 1)
1503 {
1504 WARN(("invalid parameter"));
1505 rc = VERR_INVALID_PARAMETER;
1506 break;
1507 }
1508
1509 if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
1510 {
1511 WARN(("invalid parameter"));
1512 rc = VERR_INVALID_PARAMETER;
1513 break;
1514 }
1515
1516 rc = crServerVBoxWindowsShow(!!paParms[0].u.uint32);
1517 if (!RT_SUCCESS(rc))
1518 WARN(("crServerVBoxWindowsShow failed rc %d", rc));
1519
1520 break;
1521 }
1522 default:
1523 WARN(("svcHostCallPerform: unexpected u32Function %d", u32Function));
1524 rc = VERR_NOT_IMPLEMENTED;
1525 break;
1526 }
1527
1528 LogFlow(("svcHostCall: rc = %Rrc\n", rc));
1529 return rc;
1530}
1531
1532int crVBoxServerHostCtl(VBOXCRCMDCTL *pCtl, uint32_t cbCtl)
1533{
1534 if ((cbCtl - sizeof (VBOXCRCMDCTL)) % sizeof(VBOXHGCMSVCPARM))
1535 {
1536 WARN(("invalid param size"));
1537 return VERR_INVALID_PARAMETER;
1538 }
1539 uint32_t cParams = (cbCtl - sizeof (VBOXCRCMDCTL)) / sizeof (VBOXHGCMSVCPARM);
1540 bool fHasCallout = VBOXCRCMDCTL_IS_CALLOUT_AVAILABLE(pCtl);
1541 if (fHasCallout)
1542 crVBoxServerCalloutEnable(pCtl);
1543
1544 int rc = svcHostCallPerform(pCtl->u32Function, cParams, (VBOXHGCMSVCPARM*)(pCtl + 1));
1545
1546 if (fHasCallout)
1547 crVBoxServerCalloutDisable();
1548
1549 return rc;
1550}
1551
1552static DECLCALLBACK(int) svcHostCall(void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
1553{
1554 switch (u32Function)
1555 {
1556 case SHCRGL_HOST_FN_CTL:
1557 {
1558 if (cParms != 1)
1559 {
1560 WARN(("cParams != 1"));
1561 return VERR_INVALID_PARAMETER;
1562 }
1563
1564 if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
1565 {
1566 WARN(("invalid param type"));
1567 return VERR_INVALID_PARAMETER;
1568 }
1569
1570 if (paParms->u.pointer.size < sizeof (VBOXCRCMDCTL))
1571 {
1572 WARN(("invalid param size"));
1573 return VERR_INVALID_PARAMETER;
1574 }
1575
1576 VBOXCRCMDCTL *pCtl = (VBOXCRCMDCTL*)paParms->u.pointer.addr;
1577 switch (pCtl->enmType)
1578 {
1579 case VBOXCRCMDCTL_TYPE_HGCM:
1580 {
1581 return crVBoxServerHostCtl(pCtl, paParms->u.pointer.size);
1582 }
1583 case VBOXCRCMDCTL_TYPE_DISABLE:
1584 {
1585 if (paParms->u.pointer.size != sizeof (VBOXCRCMDCTL_DISABLE))
1586 WARN(("invalid param size"));
1587 VBOXCRCMDCTL_DISABLE *pDisable = (VBOXCRCMDCTL_DISABLE*)pCtl;
1588 int rc = crVBoxServerHgcmDisable(&pDisable->Data);
1589 if (RT_SUCCESS(rc))
1590 g_u32fCrHgcmDisabled = 1;
1591 else
1592 WARN(("crVBoxServerHgcmDisable failed %d", rc));
1593 return rc;
1594 }
1595 case VBOXCRCMDCTL_TYPE_ENABLE:
1596 {
1597 if (paParms->u.pointer.size != sizeof (VBOXCRCMDCTL_ENABLE))
1598 WARN(("invalid param size"));
1599 VBOXCRCMDCTL_ENABLE *pEnable = (VBOXCRCMDCTL_ENABLE*)pCtl;
1600 int rc = crVBoxServerHgcmEnable(&pEnable->Data);
1601 if (RT_SUCCESS(rc))
1602 g_u32fCrHgcmDisabled = 0;
1603 else
1604 WARN(("crVBoxServerHgcmEnable failed %d", rc));
1605 return rc;
1606 }
1607 default:
1608 WARN(("svcHostCall: invalid function %d", pCtl->enmType));
1609 return VERR_INVALID_PARAMETER;
1610 }
1611 WARN(("should not be here!"));
1612 return VERR_INTERNAL_ERROR;
1613 }
1614 default:
1615 if (g_u32fCrHgcmDisabled)
1616 {
1617 WARN(("cr hgcm disabled!"));
1618 return VERR_INVALID_STATE;
1619 }
1620 return svcHostCallPerform(u32Function, cParms, paParms);
1621 }
1622}
1623
1624extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
1625{
1626 int rc = VINF_SUCCESS;
1627
1628 Log(("SHARED_CROPENGL VBoxHGCMSvcLoad: ptable = %p\n", ptable));
1629
1630 if (!ptable)
1631 {
1632 rc = VERR_INVALID_PARAMETER;
1633 }
1634 else
1635 {
1636 Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
1637
1638 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
1639 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
1640 {
1641 rc = VERR_INVALID_PARAMETER;
1642 }
1643 else
1644 {
1645 g_pHelpers = ptable->pHelpers;
1646
1647 g_u32fCrHgcmDisabled = 0;
1648
1649 ptable->cbClient = sizeof (void*);
1650
1651 ptable->pfnUnload = svcUnload;
1652 ptable->pfnConnect = svcConnect;
1653 ptable->pfnDisconnect = svcDisconnect;
1654 ptable->pfnCall = svcCall;
1655 ptable->pfnHostCall = svcHostCall;
1656 ptable->pfnSaveState = svcSaveState;
1657 ptable->pfnLoadState = svcLoadState;
1658 ptable->pvService = NULL;
1659
1660 if (!crVBoxServerInit())
1661 return VERR_NOT_SUPPORTED;
1662
1663 rc = svcPresentFBOInit();
1664
1665 crServerVBoxSetNotifyEventCB(svcNotifyEventCB);
1666 }
1667 }
1668
1669 return rc;
1670}
1671
1672#ifdef RT_OS_WINDOWS
1673#define WIN32_LEAN_AND_MEAN
1674#include <windows.h>
1675BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
1676{
1677 (void) lpvReserved;
1678
1679 switch (fdwReason)
1680 {
1681 case DLL_THREAD_ATTACH:
1682 {
1683 crStateVBoxAttachThread();
1684 break;
1685 }
1686
1687 case DLL_PROCESS_DETACH:
1688 /* do exactly the same thing as for DLL_THREAD_DETACH since
1689 * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */
1690 case DLL_THREAD_DETACH:
1691 {
1692 crStateVBoxDetachThread();
1693 break;
1694 }
1695
1696 case DLL_PROCESS_ATTACH:
1697 default:
1698 break;
1699 }
1700
1701 return TRUE;
1702}
1703#endif
Note: See TracBrowser for help on using the repository browser.

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