VirtualBox

source: vbox/trunk/src/VBox/Additions/common/crOpenGL/load.c@ 62847

Last change on this file since 62847 was 62847, checked in by vboxsync, 9 years ago

VbglR3GuestCtrlFileGetWriteAt: Fixed bug where the offset output parameter wasn't set, causing the caller (vgsvcGstCtrlSessionHandleFileWriteAt) to pass random stack garbage to RTFileWriteAt. (My guess is that we don't really use thie method, as we should've noticed this already.) New MSC warnings founds this problem.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 41.2 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "cr_spu.h"
8#include "cr_net.h"
9#include "cr_error.h"
10#include "cr_mem.h"
11#include "cr_string.h"
12#include "cr_net.h"
13#include "cr_environment.h"
14#include "cr_process.h"
15#include "cr_rand.h"
16#include "cr_netserver.h"
17#include "stub.h"
18#include <stdlib.h>
19#include <string.h>
20#include <signal.h>
21#include <iprt/initterm.h>
22#include <iprt/thread.h>
23#include <iprt/err.h>
24#include <iprt/asm.h>
25#ifndef WINDOWS
26# include <sys/types.h>
27# include <unistd.h>
28#endif
29
30#ifdef VBOX_WITH_WDDM
31#include <d3d9types.h>
32#include <D3dumddi.h>
33#include "../../WINNT/Graphics/Video/common/wddm/VBoxMPIf.h"
34#endif
35
36#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
37# include <VBox/VBoxCrHgsmi.h>
38#endif
39
40/**
41 * If you change this, see the comments in tilesortspu_context.c
42 */
43#define MAGIC_CONTEXT_BASE 500
44
45#define CONFIG_LOOKUP_FILE ".crconfigs"
46
47#ifdef WINDOWS
48#define PYTHON_EXE "python.exe"
49#else
50#define PYTHON_EXE "python"
51#endif
52
53static bool stub_initialized = 0;
54#ifdef WINDOWS
55static CRmutex stub_init_mutex;
56#define STUB_INIT_LOCK() do { crLockMutex(&stub_init_mutex); } while (0)
57#define STUB_INIT_UNLOCK() do { crUnlockMutex(&stub_init_mutex); } while (0)
58#else
59#define STUB_INIT_LOCK() do { } while (0)
60#define STUB_INIT_UNLOCK() do { } while (0)
61#endif
62
63/* NOTE: 'SPUDispatchTable glim' is declared in NULLfuncs.py now */
64/* NOTE: 'SPUDispatchTable stubThreadsafeDispatch' is declared in tsfuncs.c */
65Stub stub;
66#ifdef CHROMIUM_THREADSAFE
67static bool g_stubIsCurrentContextTSDInited;
68CRtsd g_stubCurrentContextTSD;
69#endif
70
71
72static void stubInitNativeDispatch( void )
73{
74#define MAX_FUNCS 1000
75 SPUNamedFunctionTable gl_funcs[MAX_FUNCS];
76 int numFuncs;
77
78 numFuncs = crLoadOpenGL( &stub.wsInterface, gl_funcs );
79
80 stub.haveNativeOpenGL = (numFuncs > 0);
81
82 /* XXX call this after context binding */
83 numFuncs += crLoadOpenGLExtensions( &stub.wsInterface, gl_funcs + numFuncs );
84
85 CRASSERT(numFuncs < MAX_FUNCS);
86
87 crSPUInitDispatchTable( &stub.nativeDispatch );
88 crSPUInitDispatch( &stub.nativeDispatch, gl_funcs );
89 crSPUInitDispatchNops( &stub.nativeDispatch );
90#undef MAX_FUNCS
91}
92
93
94/** Pointer to the SPU's real glClear and glViewport functions */
95static ClearFunc_t origClear;
96static ViewportFunc_t origViewport;
97static SwapBuffersFunc_t origSwapBuffers;
98static DrawBufferFunc_t origDrawBuffer;
99static ScissorFunc_t origScissor;
100
101static void stubCheckWindowState(WindowInfo *window, GLboolean bFlushOnChange)
102{
103 bool bForceUpdate = false;
104 bool bChanged = false;
105
106#ifdef WINDOWS
107 /* @todo install hook and track for WM_DISPLAYCHANGE */
108 {
109 DEVMODE devMode;
110
111 devMode.dmSize = sizeof(DEVMODE);
112 EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode);
113
114 if (devMode.dmPelsWidth!=window->dmPelsWidth || devMode.dmPelsHeight!=window->dmPelsHeight)
115 {
116 crDebug("Resolution changed(%d,%d), forcing window Pos/Size update", devMode.dmPelsWidth, devMode.dmPelsHeight);
117 window->dmPelsWidth = devMode.dmPelsWidth;
118 window->dmPelsHeight = devMode.dmPelsHeight;
119 bForceUpdate = true;
120 }
121 }
122#endif
123
124 bChanged = stubUpdateWindowGeometry(window, bForceUpdate) || bForceUpdate;
125
126#if defined(GLX) || defined (WINDOWS)
127 if (stub.trackWindowVisibleRgn)
128 {
129 bChanged = stubUpdateWindowVisibileRegions(window) || bChanged;
130 }
131#endif
132
133 if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) {
134 const int mapped = stubIsWindowVisible(window);
135 if (mapped != window->mapped) {
136 crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped);
137 stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped);
138 window->mapped = mapped;
139 bChanged = true;
140 }
141 }
142
143 if (bFlushOnChange && bChanged)
144 {
145 stub.spu->dispatch_table.Flush();
146 }
147}
148
149static bool stubSystemWindowExist(WindowInfo *pWindow)
150{
151#ifdef WINDOWS
152 if (pWindow->hWnd!=WindowFromDC(pWindow->drawable))
153 {
154 return false;
155 }
156#else
157 Window root;
158 int x, y;
159 unsigned int border, depth, w, h;
160 Display *dpy;
161
162 dpy = stubGetWindowDisplay(pWindow);
163
164 XLOCK(dpy);
165 if (!XGetGeometry(dpy, pWindow->drawable, &root, &x, &y, &w, &h, &border, &depth))
166 {
167 XUNLOCK(dpy);
168 return false;
169 }
170 XUNLOCK(dpy);
171#endif
172
173 return true;
174}
175
176static void stubCheckWindowsCB(unsigned long key, void *data1, void *data2)
177{
178 WindowInfo *pWindow = (WindowInfo *) data1;
179 ContextInfo *pCtx = (ContextInfo *) data2;
180
181 if (pWindow == pCtx->currentDrawable
182 || pWindow->type!=CHROMIUM
183 || pWindow->pOwner!=pCtx)
184 {
185 return;
186 }
187
188 if (!stubSystemWindowExist(pWindow))
189 {
190#ifdef WINDOWS
191 stubDestroyWindow(CR_CTX_CON(pCtx), (GLint)pWindow->hWnd);
192#else
193 stubDestroyWindow(CR_CTX_CON(pCtx), (GLint)pWindow->drawable);
194#endif
195 return;
196 }
197
198 stubCheckWindowState(pWindow, GL_FALSE);
199}
200
201static void stubCheckWindowsState(void)
202{
203 ContextInfo *context = stubGetCurrentContext();
204
205 CRASSERT(stub.trackWindowSize || stub.trackWindowPos);
206
207 if (!context)
208 return;
209
210#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
211 if (stub.bRunningUnderWDDM)
212 return;
213#endif
214
215 /* Try to keep a consistent locking order. */
216 crHashtableLock(stub.windowTable);
217#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
218 crLockMutex(&stub.mutex);
219#endif
220
221 stubCheckWindowState(context->currentDrawable, GL_TRUE);
222 crHashtableWalkUnlocked(stub.windowTable, stubCheckWindowsCB, context);
223
224#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
225 crUnlockMutex(&stub.mutex);
226#endif
227 crHashtableUnlock(stub.windowTable);
228}
229
230
231/**
232 * Override the head SPU's glClear function.
233 * We're basically trapping this function so that we can poll the
234 * application window size at a regular interval.
235 */
236static void SPU_APIENTRY trapClear(GLbitfield mask)
237{
238 stubCheckWindowsState();
239 /* call the original SPU glClear function */
240 origClear(mask);
241}
242
243/**
244 * As above, but for glViewport. Most apps call glViewport before
245 * glClear when a window is resized.
246 */
247static void SPU_APIENTRY trapViewport(GLint x, GLint y, GLsizei w, GLsizei h)
248{
249 stubCheckWindowsState();
250 /* call the original SPU glViewport function */
251 origViewport(x, y, w, h);
252}
253
254static void SPU_APIENTRY trapSwapBuffers(GLint window, GLint flags)
255{
256 stubCheckWindowsState();
257 origSwapBuffers(window, flags);
258}
259
260static void SPU_APIENTRY trapDrawBuffer(GLenum buf)
261{
262 stubCheckWindowsState();
263 origDrawBuffer(buf);
264}
265
266static void SPU_APIENTRY trapScissor(GLint x, GLint y, GLsizei w, GLsizei h)
267{
268 int winX, winY;
269 unsigned int winW, winH;
270 WindowInfo *pWindow;
271 ContextInfo *context = stubGetCurrentContext();
272 pWindow = context->currentDrawable;
273 stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH);
274 origScissor(0, 0, winW, winH);
275}
276
277/**
278 * Use the GL function pointers in <spu> to initialize the static glim
279 * dispatch table.
280 */
281static void stubInitSPUDispatch(SPU *spu)
282{
283 crSPUInitDispatchTable( &stub.spuDispatch );
284 crSPUCopyDispatchTable( &stub.spuDispatch, &(spu->dispatch_table) );
285
286 if (stub.trackWindowSize || stub.trackWindowPos || stub.trackWindowVisibleRgn) {
287 /* patch-in special glClear/Viewport function to track window sizing */
288 origClear = stub.spuDispatch.Clear;
289 origViewport = stub.spuDispatch.Viewport;
290 origSwapBuffers = stub.spuDispatch.SwapBuffers;
291 origDrawBuffer = stub.spuDispatch.DrawBuffer;
292 origScissor = stub.spuDispatch.Scissor;
293 stub.spuDispatch.Clear = trapClear;
294 stub.spuDispatch.Viewport = trapViewport;
295
296 /*stub.spuDispatch.SwapBuffers = trapSwapBuffers;
297 stub.spuDispatch.DrawBuffer = trapDrawBuffer;*/
298 }
299
300 crSPUCopyDispatchTable( &glim, &stub.spuDispatch );
301}
302
303// Callback function, used to destroy all created contexts
304static void hsWalkStubDestroyContexts(unsigned long key, void *data1, void *data2)
305{
306 stubDestroyContext(key);
307}
308
309/**
310 * This is called when we exit.
311 * We call all the SPU's cleanup functions.
312 */
313static void stubSPUTearDownLocked(void)
314{
315 crDebug("stubSPUTearDownLocked");
316
317#ifdef WINDOWS
318# ifndef CR_NEWWINTRACK
319 stubUninstallWindowMessageHook();
320# endif
321#endif
322
323#ifdef CR_NEWWINTRACK
324 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
325#endif
326
327 //delete all created contexts
328 stubMakeCurrent( NULL, NULL);
329
330 /* the lock order is windowTable->contextTable (see wglMakeCurrent_prox, glXMakeCurrent)
331 * this is why we need to take a windowTable lock since we will later do stub.windowTable access & locking */
332 crHashtableLock(stub.windowTable);
333 crHashtableWalk(stub.contextTable, hsWalkStubDestroyContexts, NULL);
334 crHashtableUnlock(stub.windowTable);
335
336 /* shutdown, now trap any calls to a NULL dispatcher */
337 crSPUCopyDispatchTable(&glim, &stubNULLDispatch);
338
339 crSPUUnloadChain(stub.spu);
340 stub.spu = NULL;
341
342#ifndef Linux
343 crUnloadOpenGL();
344#endif
345
346#ifndef WINDOWS
347 crNetTearDown();
348#endif
349
350#ifdef GLX
351 if (stub.xshmSI.shmid>=0)
352 {
353 shmctl(stub.xshmSI.shmid, IPC_RMID, 0);
354 shmdt(stub.xshmSI.shmaddr);
355 }
356 crFreeHashtable(stub.pGLXPixmapsHash, crFree);
357#endif
358
359 crFreeHashtable(stub.windowTable, crFree);
360 crFreeHashtable(stub.contextTable, NULL);
361
362 crMemset(&stub, 0, sizeof(stub));
363
364}
365
366/**
367 * This is called when we exit.
368 * We call all the SPU's cleanup functions.
369 */
370static void stubSPUTearDown(void)
371{
372 STUB_INIT_LOCK();
373 if (stub_initialized)
374 {
375 stubSPUTearDownLocked();
376 stub_initialized = 0;
377 }
378 STUB_INIT_UNLOCK();
379}
380
381static void stubSPUSafeTearDown(void)
382{
383#ifdef CHROMIUM_THREADSAFE
384 CRmutex *mutex;
385#endif
386
387 if (!stub_initialized) return;
388 stub_initialized = 0;
389
390#ifdef CHROMIUM_THREADSAFE
391 mutex = &stub.mutex;
392 crLockMutex(mutex);
393#endif
394 crDebug("stubSPUSafeTearDown");
395
396#ifdef WINDOWS
397# ifndef CR_NEWWINTRACK
398 stubUninstallWindowMessageHook();
399# endif
400#endif
401
402#if defined(CR_NEWWINTRACK)
403 crUnlockMutex(mutex);
404# if defined(WINDOWS)
405 if (stub.hSyncThread && RTThreadGetState(stub.hSyncThread)!=RTTHREADSTATE_TERMINATED)
406 {
407 HANDLE hNative;
408 DWORD ec=0;
409
410 hNative = OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION|THREAD_TERMINATE,
411 false, RTThreadGetNative(stub.hSyncThread));
412 if (!hNative)
413 {
414 crWarning("Failed to get handle for sync thread(%#x)", GetLastError());
415 }
416 else
417 {
418 crDebug("Got handle %p for thread %#x", hNative, RTThreadGetNative(stub.hSyncThread));
419 }
420
421 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
422
423 if (PostThreadMessage(RTThreadGetNative(stub.hSyncThread), WM_QUIT, 0, 0))
424 {
425 RTThreadWait(stub.hSyncThread, 1000, NULL);
426
427 /*Same issue as on linux, RTThreadWait exits before system thread is terminated, which leads
428 * to issues as our dll goes to be unloaded.
429 *@todo
430 *We usually call this function from DllMain which seems to be holding some lock and thus we have to
431 * kill thread via TerminateThread.
432 */
433 if (WaitForSingleObject(hNative, 100)==WAIT_TIMEOUT)
434 {
435 crDebug("Wait failed, terminating");
436 if (!TerminateThread(hNative, 1))
437 {
438 crDebug("TerminateThread failed");
439 }
440 }
441 if (GetExitCodeThread(hNative, &ec))
442 {
443 crDebug("Thread %p exited with ec=%i", hNative, ec);
444 }
445 else
446 {
447 crDebug("GetExitCodeThread failed(%#x)", GetLastError());
448 }
449 }
450 else
451 {
452 crDebug("Sync thread killed before DLL_PROCESS_DETACH");
453 }
454
455 if (hNative)
456 {
457 CloseHandle(hNative);
458 }
459 }
460#else
461 if (stub.hSyncThread!=NIL_RTTHREAD)
462 {
463 ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
464 {
465 int rc = RTThreadWait(stub.hSyncThread, RT_INDEFINITE_WAIT, NULL);
466 if (RT_FAILURE(rc))
467 {
468 WARN(("RTThreadWait_join failed %i", rc));
469 }
470 }
471 }
472#endif
473 crLockMutex(mutex);
474#endif
475
476#ifndef WINDOWS
477 crNetTearDown();
478#endif
479
480#ifdef CHROMIUM_THREADSAFE
481 crUnlockMutex(mutex);
482 crFreeMutex(mutex);
483#endif
484 crMemset(&stub, 0, sizeof(stub));
485}
486
487
488static void stubExitHandler(void)
489{
490 stubSPUSafeTearDown();
491 signal(SIGTERM, SIG_DFL);
492 signal(SIGINT, SIG_DFL);
493}
494
495/**
496 * Called when we receive a SIGTERM signal.
497 */
498static void stubSignalHandler(int signo)
499{
500 stubSPUSafeTearDown();
501 exit(0); /* this causes stubExitHandler() to be called */
502}
503
504#ifndef RT_OS_WINDOWS
505# ifdef CHROMIUM_THREADSAFE
506static void stubThreadTlsDtor(void *pvValue)
507{
508 ContextInfo *pCtx = (ContextInfo*)pvValue;
509 VBoxTlsRefRelease(pCtx);
510}
511# endif
512#endif
513
514
515/**
516 * Init variables in the stub structure, install signal handler.
517 */
518static void stubInitVars(void)
519{
520 WindowInfo *defaultWin;
521
522#ifdef CHROMIUM_THREADSAFE
523 crInitMutex(&stub.mutex);
524#endif
525
526 /* At the very least we want CR_RGB_BIT. */
527 stub.haveNativeOpenGL = GL_FALSE;
528 stub.spu = NULL;
529 stub.appDrawCursor = 0;
530 stub.minChromiumWindowWidth = 0;
531 stub.minChromiumWindowHeight = 0;
532 stub.maxChromiumWindowWidth = 0;
533 stub.maxChromiumWindowHeight = 0;
534 stub.matchChromiumWindowCount = 0;
535 stub.matchChromiumWindowID = NULL;
536 stub.matchWindowTitle = NULL;
537 stub.ignoreFreeglutMenus = 0;
538 stub.threadSafe = GL_FALSE;
539 stub.trackWindowSize = 0;
540 stub.trackWindowPos = 0;
541 stub.trackWindowVisibility = 0;
542 stub.trackWindowVisibleRgn = 0;
543 stub.mothershipPID = 0;
544 stub.spu_dir = NULL;
545
546 stub.freeContextNumber = MAGIC_CONTEXT_BASE;
547 stub.contextTable = crAllocHashtable();
548#ifndef RT_OS_WINDOWS
549# ifdef CHROMIUM_THREADSAFE
550 if (!g_stubIsCurrentContextTSDInited)
551 {
552 crInitTSDF(&g_stubCurrentContextTSD, stubThreadTlsDtor);
553 g_stubIsCurrentContextTSDInited = true;
554 }
555# endif
556#endif
557 stubSetCurrentContext(NULL);
558
559 stub.windowTable = crAllocHashtable();
560
561#ifdef CR_NEWWINTRACK
562 stub.bShutdownSyncThread = false;
563 stub.hSyncThread = NIL_RTTHREAD;
564#endif
565
566 defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo));
567 defaultWin->type = CHROMIUM;
568 defaultWin->spuWindow = 0; /* window 0 always exists */
569#ifdef WINDOWS
570 defaultWin->hVisibleRegion = INVALID_HANDLE_VALUE;
571#elif defined(GLX)
572 defaultWin->pVisibleRegions = NULL;
573 defaultWin->cVisibleRegions = 0;
574#endif
575 crHashtableAdd(stub.windowTable, 0, defaultWin);
576
577#if 1
578 atexit(stubExitHandler);
579 signal(SIGTERM, stubSignalHandler);
580 signal(SIGINT, stubSignalHandler);
581#ifndef WINDOWS
582 signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */
583#endif
584#else
585 (void) stubExitHandler;
586 (void) stubSignalHandler;
587#endif
588}
589
590
591#if 0 /* unused */
592
593/**
594 * Return a free port number for the mothership to use, or -1 if we
595 * can't find one.
596 */
597static int
598GenerateMothershipPort(void)
599{
600 const int MAX_PORT = 10100;
601 unsigned short port;
602
603 /* generate initial port number randomly */
604 crRandAutoSeed();
605 port = (unsigned short) crRandInt(10001, MAX_PORT);
606
607#ifdef WINDOWS
608 /* XXX should implement a free port check here */
609 return port;
610#else
611 /*
612 * See if this port number really is free, try another if needed.
613 */
614 {
615 struct sockaddr_in servaddr;
616 int so_reuseaddr = 1;
617 int sock, k;
618
619 /* create socket */
620 sock = socket(AF_INET, SOCK_STREAM, 0);
621 CRASSERT(sock > 2);
622
623 /* deallocate socket/port when we exit */
624 k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
625 (char *) &so_reuseaddr, sizeof(so_reuseaddr));
626 CRASSERT(k == 0);
627
628 /* initialize the servaddr struct */
629 crMemset(&servaddr, 0, sizeof(servaddr) );
630 servaddr.sin_family = AF_INET;
631 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
632
633 while (port < MAX_PORT) {
634 /* Bind to the given port number, return -1 if we fail */
635 servaddr.sin_port = htons((unsigned short) port);
636 k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr));
637 if (k) {
638 /* failed to create port. try next one. */
639 port++;
640 }
641 else {
642 /* free the socket/port now so mothership can make it */
643 close(sock);
644 return port;
645 }
646 }
647 }
648#endif /* WINDOWS */
649 return -1;
650}
651
652
653/**
654 * Try to determine which mothership configuration to use for this program.
655 */
656static char **
657LookupMothershipConfig(const char *procName)
658{
659 const int procNameLen = crStrlen(procName);
660 FILE *f;
661 const char *home;
662 char configPath[1000];
663
664 /* first, check if the CR_CONFIG env var is set */
665 {
666 const char *conf = crGetenv("CR_CONFIG");
667 if (conf && crStrlen(conf) > 0)
668 return crStrSplit(conf, " ");
669 }
670
671 /* second, look up config name from config file */
672 home = crGetenv("HOME");
673 if (home)
674 sprintf(configPath, "%s/%s", home, CONFIG_LOOKUP_FILE);
675 else
676 crStrcpy(configPath, CONFIG_LOOKUP_FILE); /* from current dir */
677 /* Check if the CR_CONFIG_PATH env var is set. */
678 {
679 const char *conf = crGetenv("CR_CONFIG_PATH");
680 if (conf)
681 crStrcpy(configPath, conf); /* from env var */
682 }
683
684 f = fopen(configPath, "r");
685 if (!f) {
686 return NULL;
687 }
688
689 while (!feof(f)) {
690 char line[1000];
691 char **args;
692 fgets(line, 999, f);
693 line[crStrlen(line) - 1] = 0; /* remove trailing newline */
694 if (crStrncmp(line, procName, procNameLen) == 0 &&
695 (line[procNameLen] == ' ' || line[procNameLen] == '\t'))
696 {
697 crWarning("Using Chromium configuration for %s from %s",
698 procName, configPath);
699 args = crStrSplit(line + procNameLen + 1, " ");
700 return args;
701 }
702 }
703 fclose(f);
704 return NULL;
705}
706
707
708static int Mothership_Awake = 0;
709
710
711/**
712 * Signal handler to determine when mothership is ready.
713 */
714static void
715MothershipPhoneHome(int signo)
716{
717 crDebug("Got signal %d: mothership is awake!", signo);
718 Mothership_Awake = 1;
719}
720
721#endif /* 0 */
722
723void stubSetDefaultConfigurationOptions(void)
724{
725 unsigned char key[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
726
727 stub.appDrawCursor = 0;
728 stub.minChromiumWindowWidth = 0;
729 stub.minChromiumWindowHeight = 0;
730 stub.maxChromiumWindowWidth = 0;
731 stub.maxChromiumWindowHeight = 0;
732 stub.matchChromiumWindowID = NULL;
733 stub.numIgnoreWindowID = 0;
734 stub.matchWindowTitle = NULL;
735 stub.ignoreFreeglutMenus = 0;
736 stub.trackWindowSize = 1;
737 stub.trackWindowPos = 1;
738 stub.trackWindowVisibility = 1;
739 stub.trackWindowVisibleRgn = 1;
740 stub.matchChromiumWindowCount = 0;
741 stub.spu_dir = NULL;
742 crNetSetRank(0);
743 crNetSetContextRange(32, 35);
744 crNetSetNodeRange("iam0", "iamvis20");
745 crNetSetKey(key,sizeof(key));
746 stub.force_pbuffers = 0;
747
748#ifdef WINDOWS
749# ifdef VBOX_WITH_WDDM
750 stub.bRunningUnderWDDM = false;
751# endif
752#endif
753}
754
755#ifdef CR_NEWWINTRACK
756# ifdef VBOX_WITH_WDDM
757static stubDispatchVisibleRegions(WindowInfo *pWindow)
758{
759 DWORD dwCount;
760 LPRGNDATA lpRgnData;
761
762 dwCount = GetRegionData(pWindow->hVisibleRegion, 0, NULL);
763 lpRgnData = crAlloc(dwCount);
764
765 if (lpRgnData)
766 {
767 GetRegionData(pWindow->hVisibleRegion, dwCount, lpRgnData);
768 crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount);
769 stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer);
770 crFree(lpRgnData);
771 }
772 else crWarning("GetRegionData failed, VisibleRegions update failed");
773}
774
775static HRGN stubMakeRegionFromRects(PVBOXVIDEOCM_CMD_RECTS pRegions, uint32_t start)
776{
777 HRGN hRgn, hTmpRgn;
778 uint32_t i;
779
780 if (pRegions->RectsInfo.cRects<=start)
781 {
782 return INVALID_HANDLE_VALUE;
783 }
784
785 hRgn = CreateRectRgn(0, 0, 0, 0);
786 for (i=start; i<pRegions->RectsInfo.cRects; ++i)
787 {
788 hTmpRgn = CreateRectRgnIndirect(&pRegions->RectsInfo.aRects[i]);
789 CombineRgn(hRgn, hRgn, hTmpRgn, RGN_OR);
790 DeleteObject(hTmpRgn);
791 }
792 return hRgn;
793}
794
795# endif /* VBOX_WITH_WDDM */
796
797static void stubSyncTrCheckWindowsCB(unsigned long key, void *data1, void *data2)
798{
799 WindowInfo *pWindow = (WindowInfo *) data1;
800 (void) data2;
801
802 if (pWindow->type!=CHROMIUM || pWindow->spuWindow==0)
803 {
804 return;
805 }
806
807 stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
808
809 if (!stubSystemWindowExist(pWindow))
810 {
811#ifdef WINDOWS
812 stubDestroyWindow(0, (GLint)pWindow->hWnd);
813#else
814 stubDestroyWindow(0, (GLint)pWindow->drawable);
815#endif
816 /*No need to flush here as crWindowDestroy does it*/
817 return;
818 }
819
820#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
821 if (stub.bRunningUnderWDDM)
822 return;
823#endif
824 stubCheckWindowState(pWindow, GL_TRUE);
825}
826
827static DECLCALLBACK(int) stubSyncThreadProc(RTTHREAD ThreadSelf, void *pvUser)
828{
829#ifdef WINDOWS
830 MSG msg;
831# ifdef VBOX_WITH_WDDM
832 HMODULE hVBoxD3D = NULL;
833 GLint spuConnection = 0;
834# endif
835#endif
836
837 (void) pvUser;
838
839 crDebug("Sync thread started");
840#ifdef WINDOWS
841 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
842# ifdef VBOX_WITH_WDDM
843 hVBoxD3D = NULL;
844 if (!GetModuleHandleEx(0, VBOX_MODNAME_DISPD3D, &hVBoxD3D))
845 {
846 crDebug("GetModuleHandleEx failed err %d", GetLastError());
847 hVBoxD3D = NULL;
848 }
849
850 if (hVBoxD3D)
851 {
852 crDebug("running with " VBOX_MODNAME_DISPD3D);
853 stub.trackWindowVisibleRgn = 0;
854 stub.bRunningUnderWDDM = true;
855 }
856# endif /* VBOX_WITH_WDDM */
857#endif /* WINDOWS */
858
859 crLockMutex(&stub.mutex);
860#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
861 spuConnection =
862#endif
863 stub.spu->dispatch_table.VBoxPackSetInjectThread(NULL);
864#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
865 if (stub.bRunningUnderWDDM && !spuConnection)
866 {
867 crError("VBoxPackSetInjectThread failed!");
868 }
869#endif
870 crUnlockMutex(&stub.mutex);
871
872 RTThreadUserSignal(ThreadSelf);
873
874 while(!stub.bShutdownSyncThread)
875 {
876#ifdef WINDOWS
877 if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
878 {
879# ifdef VBOX_WITH_WDDM
880 if (stub.bRunningUnderWDDM)
881 {
882
883 }
884 else
885# endif
886 {
887 crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
888 RTThreadSleep(50);
889 }
890 }
891 else
892 {
893 if (WM_QUIT==msg.message)
894 {
895 crDebug("Sync thread got WM_QUIT");
896 break;
897 }
898 else
899 {
900 TranslateMessage(&msg);
901 DispatchMessage(&msg);
902 }
903 }
904#else
905 /* Try to keep a consistent locking order. */
906 crHashtableLock(stub.windowTable);
907 crLockMutex(&stub.mutex);
908 crHashtableWalkUnlocked(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
909 crUnlockMutex(&stub.mutex);
910 crHashtableUnlock(stub.windowTable);
911 RTThreadSleep(50);
912#endif
913 }
914
915#ifdef VBOX_WITH_WDDM
916 if (spuConnection)
917 {
918 stub.spu->dispatch_table.VBoxConDestroy(spuConnection);
919 }
920 if (hVBoxD3D)
921 {
922 FreeLibrary(hVBoxD3D);
923 }
924#endif
925 crDebug("Sync thread stopped");
926 return 0;
927}
928#endif /* CR_NEWWINTRACK */
929
930/**
931 * Do one-time initializations for the faker.
932 * Returns TRUE on success, FALSE otherwise.
933 */
934static bool
935stubInitLocked(void)
936{
937 /* Here is where we contact the mothership to find out what we're supposed
938 * to be doing. Networking code in a DLL initializer. I sure hope this
939 * works :)
940 *
941 * HOW can I pass the mothership address to this if I already know it?
942 */
943
944 CRConnection *conn = NULL;
945 char response[1024];
946 char **spuchain;
947 int num_spus;
948 int *spu_ids;
949 char **spu_names;
950 const char *app_id;
951 int i;
952 int disable_sync = 0;
953#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
954 HMODULE hVBoxD3D = NULL;
955#endif
956
957 stubInitVars();
958
959 crGetProcName(response, 1024);
960 crDebug("Stub launched for %s", response);
961
962#if defined(CR_NEWWINTRACK) && !defined(WINDOWS)
963 /*@todo when vm boots with compiz turned on, new code causes hang in xcb_wait_for_reply in the sync thread
964 * as at the start compiz runs our code under XGrabServer.
965 */
966 if (!crStrcmp(response, "compiz") || !crStrcmp(response, "compiz_real") || !crStrcmp(response, "compiz.real")
967 || !crStrcmp(response, "compiz-bin"))
968 {
969 disable_sync = 1;
970 }
971#endif
972
973 /* @todo check if it'd be of any use on other than guests, no use for windows */
974 app_id = crGetenv( "CR_APPLICATION_ID_NUMBER" );
975
976 crNetInit( NULL, NULL );
977
978#ifndef WINDOWS
979 {
980 CRNetServer ns;
981
982 ns.name = "vboxhgcm://host:0";
983 ns.buffer_size = 1024;
984 crNetServerConnect(&ns
985#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
986 , NULL
987#endif
988 );
989 if (!ns.conn)
990 {
991 crWarning("Failed to connect to host. Make sure 3D acceleration is enabled for this VM.");
992# ifdef VBOXOGL_FAKEDRI
993 return false;
994# else
995 exit(1);
996# endif
997 }
998 else
999 {
1000 crNetFreeConnection(ns.conn);
1001 }
1002 }
1003#endif
1004
1005 strcpy(response, "2 0 feedback 1 pack");
1006 spuchain = crStrSplit( response, " " );
1007 num_spus = crStrToInt( spuchain[0] );
1008 spu_ids = (int *) crAlloc( num_spus * sizeof( *spu_ids ) );
1009 spu_names = (char **) crAlloc( num_spus * sizeof( *spu_names ) );
1010 for (i = 0 ; i < num_spus ; i++)
1011 {
1012 spu_ids[i] = crStrToInt( spuchain[2*i+1] );
1013 spu_names[i] = crStrdup( spuchain[2*i+2] );
1014 crDebug( "SPU %d/%d: (%d) \"%s\"", i+1, num_spus, spu_ids[i], spu_names[i] );
1015 }
1016
1017 stubSetDefaultConfigurationOptions();
1018
1019#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
1020 hVBoxD3D = NULL;
1021 if (!GetModuleHandleEx(0, VBOX_MODNAME_DISPD3D, &hVBoxD3D))
1022 {
1023 crDebug("GetModuleHandleEx failed err %d", GetLastError());
1024 hVBoxD3D = NULL;
1025 }
1026
1027 if (hVBoxD3D)
1028 {
1029 disable_sync = 1;
1030 crDebug("running with %s", VBOX_MODNAME_DISPD3D);
1031 stub.trackWindowVisibleRgn = 0;
1032 /* @todo: should we enable that? */
1033 stub.trackWindowSize = 0;
1034 stub.trackWindowPos = 0;
1035 stub.trackWindowVisibility = 0;
1036 stub.bRunningUnderWDDM = true;
1037 }
1038#endif
1039
1040 stub.spu = crSPULoadChain( num_spus, spu_ids, spu_names, stub.spu_dir, NULL );
1041
1042 crFree( spuchain );
1043 crFree( spu_ids );
1044 for (i = 0; i < num_spus; ++i)
1045 crFree(spu_names[i]);
1046 crFree( spu_names );
1047
1048 // spu chain load failed somewhere
1049 if (!stub.spu) {
1050 return false;
1051 }
1052
1053 crSPUInitDispatchTable( &glim );
1054
1055 /* This is unlikely to change -- We still want to initialize our dispatch
1056 * table with the functions of the first SPU in the chain. */
1057 stubInitSPUDispatch( stub.spu );
1058
1059 /* we need to plug one special stub function into the dispatch table */
1060 glim.GetChromiumParametervCR = stub_GetChromiumParametervCR;
1061
1062#if !defined(VBOX_NO_NATIVEGL)
1063 /* Load pointers to native OpenGL functions into stub.nativeDispatch */
1064 stubInitNativeDispatch();
1065#endif
1066
1067/*crDebug("stub init");
1068raise(SIGINT);*/
1069
1070#ifdef WINDOWS
1071# ifndef CR_NEWWINTRACK
1072 stubInstallWindowMessageHook();
1073# endif
1074#endif
1075
1076#ifdef CR_NEWWINTRACK
1077 {
1078 int rc;
1079
1080 RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE);
1081
1082 if (!disable_sync)
1083 {
1084 crDebug("Starting sync thread");
1085
1086 rc = RTThreadCreate(&stub.hSyncThread, stubSyncThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "Sync");
1087 if (RT_FAILURE(rc))
1088 {
1089 crError("Failed to start sync thread! (%x)", rc);
1090 }
1091 RTThreadUserWait(stub.hSyncThread, 60 * 1000);
1092 RTThreadUserReset(stub.hSyncThread);
1093
1094 crDebug("Going on");
1095 }
1096 }
1097#endif
1098
1099#ifdef GLX
1100 stub.xshmSI.shmid = -1;
1101 stub.bShmInitFailed = GL_FALSE;
1102 stub.pGLXPixmapsHash = crAllocHashtable();
1103
1104 stub.bXExtensionsChecked = GL_FALSE;
1105 stub.bHaveXComposite = GL_FALSE;
1106 stub.bHaveXFixes = GL_FALSE;
1107#endif
1108
1109 return true;
1110}
1111
1112/**
1113 * Do one-time initializations for the faker.
1114 * Returns TRUE on success, FALSE otherwise.
1115 */
1116bool
1117stubInit(void)
1118{
1119 bool bRc = true;
1120 /* we need to serialize the initialization, otherwise racing is possible
1121 * for XPDM-based d3d when a d3d switcher is testing the gl lib in two or more threads
1122 * NOTE: the STUB_INIT_LOCK/UNLOCK is a NOP for non-win currently */
1123 STUB_INIT_LOCK();
1124 if (!stub_initialized)
1125 bRc = stub_initialized = stubInitLocked();
1126 STUB_INIT_UNLOCK();
1127 return bRc;
1128}
1129
1130/* Sigh -- we can't do initialization at load time, since Windows forbids
1131 * the loading of other libraries from DLLMain. */
1132
1133#ifdef WINDOWS
1134#define WIN32_LEAN_AND_MEAN
1135#include <windows.h>
1136
1137#if 1//def DEBUG_misha
1138 /* debugging: this is to be able to catch first-chance notifications
1139 * for exceptions other than EXCEPTION_BREAKPOINT in kernel debugger */
1140# define VDBG_VEHANDLER
1141#endif
1142
1143#ifdef VDBG_VEHANDLER
1144# include <dbghelp.h>
1145# include <cr_string.h>
1146static PVOID g_VBoxVehHandler = NULL;
1147static DWORD g_VBoxVehEnable = 0;
1148
1149/* generate a crash dump on exception */
1150#define VBOXVEH_F_DUMP 0x00000001
1151/* generate a debugger breakpoint exception */
1152#define VBOXVEH_F_BREAK 0x00000002
1153/* exit on exception */
1154#define VBOXVEH_F_EXIT 0x00000004
1155
1156static DWORD g_VBoxVehFlags = 0;
1157
1158typedef BOOL WINAPI FNVBOXDBG_MINIDUMPWRITEDUMP(HANDLE hProcess,
1159 DWORD ProcessId,
1160 HANDLE hFile,
1161 MINIDUMP_TYPE DumpType,
1162 PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
1163 PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
1164 PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
1165typedef FNVBOXDBG_MINIDUMPWRITEDUMP *PFNVBOXDBG_MINIDUMPWRITEDUMP;
1166
1167static HMODULE g_hVBoxMdDbgHelp = NULL;
1168static PFNVBOXDBG_MINIDUMPWRITEDUMP g_pfnVBoxMdMiniDumpWriteDump = NULL;
1169static size_t g_cVBoxMdFilePrefixLen = 0;
1170static WCHAR g_aszwVBoxMdFilePrefix[MAX_PATH];
1171static WCHAR g_aszwVBoxMdDumpCount = 0;
1172static MINIDUMP_TYPE g_enmVBoxMdDumpType = MiniDumpNormal
1173 | MiniDumpWithDataSegs
1174 | MiniDumpWithFullMemory
1175 | MiniDumpWithHandleData
1176//// | MiniDumpFilterMemory
1177//// | MiniDumpScanMemory
1178// | MiniDumpWithUnloadedModules
1179//// | MiniDumpWithIndirectlyReferencedMemory
1180//// | MiniDumpFilterModulePaths
1181// | MiniDumpWithProcessThreadData
1182// | MiniDumpWithPrivateReadWriteMemory
1183//// | MiniDumpWithoutOptionalData
1184// | MiniDumpWithFullMemoryInfo
1185// | MiniDumpWithThreadInfo
1186// | MiniDumpWithCodeSegs
1187// | MiniDumpWithFullAuxiliaryState
1188// | MiniDumpWithPrivateWriteCopyMemory
1189// | MiniDumpIgnoreInaccessibleMemory
1190// | MiniDumpWithTokenInformation
1191//// | MiniDumpWithModuleHeaders
1192//// | MiniDumpFilterTriage
1193 ;
1194
1195
1196
1197#define VBOXMD_DUMP_DIR_DEFAULT "C:\\dumps"
1198#define VBOXMD_DUMP_NAME_PREFIX_W L"VBoxDmp_"
1199
1200static HMODULE loadSystemDll(const char *pszName)
1201{
1202 char szPath[MAX_PATH];
1203 UINT cchPath = GetSystemDirectoryA(szPath, sizeof(szPath));
1204 size_t cbName = strlen(pszName) + 1;
1205 if (cchPath + 1 + cbName > sizeof(szPath))
1206 {
1207 SetLastError(ERROR_FILENAME_EXCED_RANGE);
1208 return NULL;
1209 }
1210 szPath[cchPath] = '\\';
1211 memcpy(&szPath[cchPath + 1], pszName, cbName);
1212 return LoadLibraryA(szPath);
1213}
1214
1215static DWORD vboxMdMinidumpCreate(struct _EXCEPTION_POINTERS *pExceptionInfo)
1216{
1217 WCHAR aszwMdFileName[MAX_PATH];
1218 HANDLE hProcess = GetCurrentProcess();
1219 DWORD ProcessId = GetCurrentProcessId();
1220 MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo;
1221 HANDLE hFile;
1222 DWORD winErr = ERROR_SUCCESS;
1223
1224 if (!g_pfnVBoxMdMiniDumpWriteDump)
1225 {
1226 if (!g_hVBoxMdDbgHelp)
1227 {
1228 g_hVBoxMdDbgHelp = loadSystemDll("DbgHelp.dll");
1229 if (!g_hVBoxMdDbgHelp)
1230 return GetLastError();
1231 }
1232
1233 g_pfnVBoxMdMiniDumpWriteDump = (PFNVBOXDBG_MINIDUMPWRITEDUMP)GetProcAddress(g_hVBoxMdDbgHelp, "MiniDumpWriteDump");
1234 if (!g_pfnVBoxMdMiniDumpWriteDump)
1235 return GetLastError();
1236 }
1237
1238 ++g_aszwVBoxMdDumpCount;
1239
1240 memcpy(aszwMdFileName, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen * sizeof (g_aszwVBoxMdFilePrefix[0]));
1241 swprintf(aszwMdFileName + g_cVBoxMdFilePrefixLen, RT_ELEMENTS(aszwMdFileName) - g_cVBoxMdFilePrefixLen, L"%d_%d.dmp", ProcessId, g_aszwVBoxMdDumpCount);
1242
1243 hFile = CreateFileW(aszwMdFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1244 if (hFile == INVALID_HANDLE_VALUE)
1245 return GetLastError();
1246
1247 ExceptionInfo.ThreadId = GetCurrentThreadId();
1248 ExceptionInfo.ExceptionPointers = pExceptionInfo;
1249 ExceptionInfo.ClientPointers = FALSE;
1250
1251 if (!g_pfnVBoxMdMiniDumpWriteDump(hProcess, ProcessId, hFile, g_enmVBoxMdDumpType, &ExceptionInfo, NULL, NULL))
1252 winErr = GetLastError();
1253
1254 CloseHandle(hFile);
1255 return winErr;
1256}
1257
1258LONG WINAPI vboxVDbgVectoredHandler(struct _EXCEPTION_POINTERS *pExceptionInfo)
1259{
1260 PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
1261 PCONTEXT pContextRecord = pExceptionInfo->ContextRecord;
1262 switch (pExceptionRecord->ExceptionCode)
1263 {
1264 case EXCEPTION_BREAKPOINT:
1265 case EXCEPTION_ACCESS_VIOLATION:
1266 case EXCEPTION_STACK_OVERFLOW:
1267 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1268 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1269 case EXCEPTION_FLT_INVALID_OPERATION:
1270 case EXCEPTION_INT_DIVIDE_BY_ZERO:
1271 case EXCEPTION_ILLEGAL_INSTRUCTION:
1272 if (g_VBoxVehFlags & VBOXVEH_F_BREAK)
1273 {
1274 BOOL fBreak = TRUE;
1275#ifndef DEBUG_misha
1276 if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT)
1277 {
1278 HANDLE hProcess = GetCurrentProcess();
1279 BOOL fDebuggerPresent = FALSE;
1280 /* we do not want to generate breakpoint exceptions recursively, so do it only when running under debugger */
1281 if (CheckRemoteDebuggerPresent(hProcess, &fDebuggerPresent))
1282 fBreak = !!fDebuggerPresent;
1283 else
1284 fBreak = FALSE; /* <- the function has failed, don't break for sanity */
1285 }
1286#endif
1287
1288 if (fBreak)
1289 {
1290 RT_BREAKPOINT();
1291 }
1292 }
1293
1294 if (g_VBoxVehFlags & VBOXVEH_F_DUMP)
1295 vboxMdMinidumpCreate(pExceptionInfo);
1296
1297 if (g_VBoxVehFlags & VBOXVEH_F_EXIT)
1298 exit(1);
1299 break;
1300 default:
1301 break;
1302 }
1303 return EXCEPTION_CONTINUE_SEARCH;
1304}
1305
1306void vboxVDbgVEHandlerRegister()
1307{
1308 CRASSERT(!g_VBoxVehHandler);
1309 g_VBoxVehHandler = AddVectoredExceptionHandler(1,vboxVDbgVectoredHandler);
1310 CRASSERT(g_VBoxVehHandler);
1311}
1312
1313void vboxVDbgVEHandlerUnregister()
1314{
1315 ULONG uResult;
1316 if (g_VBoxVehHandler)
1317 {
1318 uResult = RemoveVectoredExceptionHandler(g_VBoxVehHandler);
1319 CRASSERT(uResult);
1320 g_VBoxVehHandler = NULL;
1321 }
1322}
1323#endif
1324
1325/* Windows crap */
1326BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
1327{
1328 (void) lpvReserved;
1329
1330 switch (fdwReason)
1331 {
1332 case DLL_PROCESS_ATTACH:
1333 {
1334 CRNetServer ns;
1335 const char * env;
1336#if defined(DEBUG_misha)
1337 HMODULE hCrUtil;
1338 char aName[MAX_PATH];
1339
1340 GetModuleFileNameA(hDLLInst, aName, RT_ELEMENTS(aName));
1341 crDbgCmdSymLoadPrint(aName, hDLLInst);
1342
1343 hCrUtil = GetModuleHandleA("VBoxOGLcrutil.dll");
1344 Assert(hCrUtil);
1345 crDbgCmdSymLoadPrint("VBoxOGLcrutil.dll", hCrUtil);
1346#endif
1347#ifdef CHROMIUM_THREADSAFE
1348 crInitTSD(&g_stubCurrentContextTSD);
1349#endif
1350
1351 crInitMutex(&stub_init_mutex);
1352
1353#ifdef VDBG_VEHANDLER
1354 env = crGetenv("CR_DBG_VEH_ENABLE");
1355 g_VBoxVehEnable = crStrParseI32(env,
1356# ifdef DEBUG_misha
1357 1
1358# else
1359 0
1360# endif
1361 );
1362
1363 if (g_VBoxVehEnable)
1364 {
1365 char procName[1024];
1366 size_t cProcName;
1367 size_t cChars;
1368
1369 env = crGetenv("CR_DBG_VEH_FLAGS");
1370 g_VBoxVehFlags = crStrParseI32(env,
1371 0
1372# ifdef DEBUG_misha
1373 | VBOXVEH_F_BREAK
1374# else
1375 | VBOXVEH_F_DUMP
1376# endif
1377 );
1378
1379 env = crGetenv("CR_DBG_VEH_DUMP_DIR");
1380 if (!env)
1381 env = VBOXMD_DUMP_DIR_DEFAULT;
1382
1383 g_cVBoxMdFilePrefixLen = strlen(env);
1384
1385 if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) <= g_cVBoxMdFilePrefixLen + 26 + (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR))
1386 {
1387 g_cVBoxMdFilePrefixLen = 0;
1388 env = "";
1389 }
1390
1391 mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen + 1, env, _TRUNCATE);
1392
1393 Assert(cChars == g_cVBoxMdFilePrefixLen + 1);
1394
1395 g_cVBoxMdFilePrefixLen = cChars - 1;
1396
1397 if (g_cVBoxMdFilePrefixLen && g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen - 1] != L'\\')
1398 g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'\\';
1399
1400 memcpy(g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, VBOXMD_DUMP_NAME_PREFIX_W, sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR));
1401 g_cVBoxMdFilePrefixLen += (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR);
1402
1403 crGetProcName(procName, RT_ELEMENTS(procName));
1404 cProcName = strlen(procName);
1405
1406 if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) > g_cVBoxMdFilePrefixLen + cProcName + 1 + 26)
1407 {
1408 mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, cProcName + 1, procName, _TRUNCATE);
1409 Assert(cChars == cProcName + 1);
1410 g_cVBoxMdFilePrefixLen += cChars - 1;
1411 g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'_';
1412 }
1413
1414 /* sanity */
1415 g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen] = L'\0';
1416
1417 env = crGetenv("CR_DBG_VEH_DUMP_TYPE");
1418
1419 g_enmVBoxMdDumpType = crStrParseI32(env,
1420 MiniDumpNormal
1421 | MiniDumpWithDataSegs
1422 | MiniDumpWithFullMemory
1423 | MiniDumpWithHandleData
1424 //// | MiniDumpFilterMemory
1425 //// | MiniDumpScanMemory
1426 // | MiniDumpWithUnloadedModules
1427 //// | MiniDumpWithIndirectlyReferencedMemory
1428 //// | MiniDumpFilterModulePaths
1429 // | MiniDumpWithProcessThreadData
1430 // | MiniDumpWithPrivateReadWriteMemory
1431 //// | MiniDumpWithoutOptionalData
1432 // | MiniDumpWithFullMemoryInfo
1433 // | MiniDumpWithThreadInfo
1434 // | MiniDumpWithCodeSegs
1435 // | MiniDumpWithFullAuxiliaryState
1436 // | MiniDumpWithPrivateWriteCopyMemory
1437 // | MiniDumpIgnoreInaccessibleMemory
1438 // | MiniDumpWithTokenInformation
1439 //// | MiniDumpWithModuleHeaders
1440 //// | MiniDumpFilterTriage
1441 );
1442
1443 vboxVDbgVEHandlerRegister();
1444 }
1445#endif
1446
1447 crNetInit(NULL, NULL);
1448 ns.name = "vboxhgcm://host:0";
1449 ns.buffer_size = 1024;
1450 crNetServerConnect(&ns
1451#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
1452 , NULL
1453#endif
1454);
1455 if (!ns.conn)
1456 {
1457 crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load.");
1458#ifdef VDBG_VEHANDLER
1459 if (g_VBoxVehEnable)
1460 vboxVDbgVEHandlerUnregister();
1461#endif
1462 return FALSE;
1463 }
1464 else
1465 {
1466 crNetFreeConnection(ns.conn);
1467 }
1468
1469#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
1470 VBoxCrHgsmiInit();
1471#endif
1472 break;
1473 }
1474
1475 case DLL_PROCESS_DETACH:
1476 {
1477 /* do exactly the same thing as for DLL_THREAD_DETACH since
1478 * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */
1479 stubSetCurrentContext(NULL);
1480 if (stub_initialized)
1481 {
1482 CRASSERT(stub.spu);
1483 stub.spu->dispatch_table.VBoxDetachThread();
1484 }
1485
1486
1487#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
1488 VBoxCrHgsmiTerm();
1489#endif
1490
1491 stubSPUSafeTearDown();
1492
1493#ifdef CHROMIUM_THREADSAFE
1494 crFreeTSD(&g_stubCurrentContextTSD);
1495#endif
1496
1497#ifdef VDBG_VEHANDLER
1498 if (g_VBoxVehEnable)
1499 vboxVDbgVEHandlerUnregister();
1500#endif
1501 break;
1502 }
1503
1504 case DLL_THREAD_ATTACH:
1505 {
1506 if (stub_initialized)
1507 {
1508 CRASSERT(stub.spu);
1509 stub.spu->dispatch_table.VBoxAttachThread();
1510 }
1511 break;
1512 }
1513
1514 case DLL_THREAD_DETACH:
1515 {
1516 stubSetCurrentContext(NULL);
1517 if (stub_initialized)
1518 {
1519 CRASSERT(stub.spu);
1520 stub.spu->dispatch_table.VBoxDetachThread();
1521 }
1522 break;
1523 }
1524
1525 default:
1526 break;
1527 }
1528
1529 return TRUE;
1530}
1531#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