VirtualBox

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

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

Main,Frontends: IDisplay provides the guest screen bitmap to frontends.

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