VirtualBox

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

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

DevVGA/crOpenGL: bugfixes, logging

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