VirtualBox

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

最後變更 在這個檔案從37432是 37432,由 vboxsync 提交於 14 年 前

crOpenGL: strict offset check (#5720)

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

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