VirtualBox

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

Last change on this file since 78376 was 78341, checked in by vboxsync, 6 years ago

Config.kmk,Additions/common/crOpenGL,VBox/GuestHost/OpenGL,HostServices/SharedOpenGL: Remove CHROMIUM_THREADSAFE define and apply the current default

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