VirtualBox

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

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

Main: IDisplay converted to use API wrappers.

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