VirtualBox

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

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

Merge first stage of the Chromium cleanup from the branch:

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

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