646 lines
18 KiB
C
646 lines
18 KiB
C
/******************************Module*Header*******************************\
|
|
* Module Name: dllinit.c
|
|
*
|
|
* (Brief description)
|
|
*
|
|
* Created: 18-Oct-1993 14:13:21
|
|
* Author: Gilman Wong [gilmanw]
|
|
*
|
|
* Copyright (c) 1993 Microsoft Corporation
|
|
*
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#include "batchinf.h"
|
|
#include "glteb.h"
|
|
#include "glapi.h"
|
|
#include "glsbcltu.h"
|
|
#ifdef _CLIENTSIDE_
|
|
#include "gldci.h"
|
|
#include "glgenwin.h"
|
|
#endif //_CLIENTSIDE_
|
|
#include "context.h"
|
|
#include "global.h"
|
|
#include "parray.h"
|
|
|
|
#ifdef _CLIENTSIDE_
|
|
// Global DCIMAN info. This is NULL if DCI is not available.
|
|
|
|
DCIINFO *gpDCIInfo = NULL;
|
|
|
|
extern GLubyte *dBufFill;
|
|
extern GLubyte *dBufTopLeft;
|
|
|
|
//
|
|
// This global multiply-lookup table helps with pixel-related functions.
|
|
//
|
|
|
|
BYTE gbMulTable[256*256];
|
|
BYTE gbSatTable[256+256];
|
|
|
|
// Global thread local storage index. Allocated at process attach.
|
|
// This is the slot reserved in thread local storage for per-thread
|
|
// GLTLSINFO structures.
|
|
|
|
static DWORD dwTlsIndex = 0xFFFFFFFF;
|
|
|
|
static BOOL bProcessInitialized = FALSE;
|
|
|
|
// Offset into the TEB where dwTlsIndex is
|
|
// This enables us to directly access our TLS data in the TEB
|
|
|
|
#define NT_TLS_OFFSET 3600
|
|
#define WIN95_TLS_OFFSET 136
|
|
|
|
DWORD dwTlsOffset;
|
|
|
|
// Platform indicator for conditional code
|
|
DWORD dwPlatformId;
|
|
|
|
// Thread count
|
|
LONG lThreadsAttached = 0;
|
|
|
|
// Global header node for the linked list of GLGENwindow structures.
|
|
// The semaphore in the header node is used as the list access semaphore.
|
|
|
|
GLGENwindow gwndHeader;
|
|
|
|
// Synchronization object for pixel formats
|
|
CRITICAL_SECTION gcsPixelFormat;
|
|
|
|
// Protection for palette watcher
|
|
CRITICAL_SECTION gcsPaletteWatcher;
|
|
|
|
// Synchronization object for DCI
|
|
//
|
|
// Win95 DCI acts as a global lock, synchronizing everything in the system.
|
|
// We can't do that in NT, but we can grab a per-process semaphore to
|
|
// synchronize multiple threads within our process.
|
|
CRITICAL_SECTION gcsDci;
|
|
|
|
#ifdef GL_METAFILE
|
|
BOOL (APIENTRY *pfnGdiAddGlsRecord)(HDC hdc, DWORD cb, BYTE *pb,
|
|
LPRECTL prclBounds);
|
|
BOOL (APIENTRY *pfnGdiAddGlsBounds)(HDC hdc, LPRECTL prclBounds);
|
|
BOOL (APIENTRY *pfnGdiIsMetaPrintDC)(HDC hdc);
|
|
#endif
|
|
|
|
#endif //_CLIENTSIDE_
|
|
|
|
// OpenGL client debug flag
|
|
#if DBG
|
|
long glDebugLevel;
|
|
ULONG glDebugFlags;
|
|
#endif
|
|
|
|
BOOL bDCI = FALSE;
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GLInitializeProcess
|
|
*
|
|
* Called from OPENGL32.DLL entry point for PROCESS_ATTACH.
|
|
*
|
|
* History:
|
|
* 01-Nov-1994 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL GLInitializeProcess()
|
|
{
|
|
PVOID pv;
|
|
#ifdef _CLIENTSIDE_
|
|
OSVERSIONINFO osvi;
|
|
#endif
|
|
|
|
#ifdef GL_METAFILE
|
|
// Attempt to locate GDI exports for metafiling support
|
|
{
|
|
HMODULE hdll;
|
|
|
|
hdll = GetModuleHandleA("gdi32");
|
|
ASSERTOPENGL(hdll != NULL, "Unable to get gdi32 handle\n");
|
|
*(PROC *)&pfnGdiAddGlsRecord = GetProcAddress(hdll, "GdiAddGlsRecord");
|
|
*(PROC *)&pfnGdiAddGlsBounds = GetProcAddress(hdll, "GdiAddGlsBounds");
|
|
*(PROC *)&pfnGdiIsMetaPrintDC = GetProcAddress(hdll, "GdiIsMetaPrintDC");
|
|
}
|
|
#endif
|
|
|
|
#if DBG
|
|
#define STR_OPENGL_DEBUG (PCSTR)"Software\\Microsoft\\Windows\\CurrentVersion\\DebugOpenGL"
|
|
{
|
|
HKEY hkDebug;
|
|
|
|
// Initialize debugging level and flags.
|
|
|
|
glDebugLevel = LEVEL_ERROR;
|
|
glDebugFlags = 0;
|
|
if ( RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
|
STR_OPENGL_DEBUG,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hkDebug) == ERROR_SUCCESS )
|
|
{
|
|
DWORD dwDataType;
|
|
DWORD cjSize;
|
|
long lTmp;
|
|
|
|
cjSize = sizeof(long);
|
|
if ( (RegQueryValueExA(hkDebug,
|
|
(LPSTR) "glDebugLevel",
|
|
(LPDWORD) NULL,
|
|
&dwDataType,
|
|
(LPBYTE) &lTmp,
|
|
&cjSize) == ERROR_SUCCESS) )
|
|
{
|
|
glDebugLevel = lTmp;
|
|
}
|
|
|
|
cjSize = sizeof(long);
|
|
if ( (RegQueryValueExA(hkDebug,
|
|
(LPSTR) "glDebugFlags",
|
|
(LPDWORD) NULL,
|
|
&dwDataType,
|
|
(LPBYTE) &lTmp,
|
|
&cjSize) == ERROR_SUCCESS) )
|
|
{
|
|
glDebugFlags = (ULONG) lTmp;
|
|
}
|
|
|
|
RegCloseKey(hkDebug);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef _CLIENTSIDE_
|
|
// Determine which platform we're running on and remember it
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
|
if (!GetVersionEx(&osvi))
|
|
{
|
|
WARNING1("GetVersionEx failed with %d\n", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
dwPlatformId = osvi.dwPlatformId;
|
|
|
|
if (!(
|
|
(dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) ||
|
|
(dwPlatformId == VER_PLATFORM_WIN32_NT
|
|
&& !(osvi.dwMajorVersion == 3 && osvi.dwMinorVersion <= 51)
|
|
)
|
|
)
|
|
)
|
|
{
|
|
WARNING("DLL must be run on NT 4.0 or Win95");
|
|
return FALSE;
|
|
}
|
|
|
|
// Allocate a thread local storage slot.
|
|
|
|
if ( (dwTlsIndex = TlsAlloc()) == 0xFFFFFFFF )
|
|
{
|
|
WARNING("DllInitialize: TlsAlloc failed\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// Set up the offset to the TLS slot, OS-specific
|
|
|
|
if (dwPlatformId == VER_PLATFORM_WIN32_NT)
|
|
{
|
|
ASSERTOPENGL(FIELD_OFFSET(TEB, TlsSlots) == NT_TLS_OFFSET,
|
|
"NT TLS offset not at expected location");
|
|
|
|
dwTlsOffset = dwTlsIndex*sizeof(DWORD)+NT_TLS_OFFSET;
|
|
}
|
|
else
|
|
{
|
|
// We don't have Win95's TIB type available so the assert is
|
|
// slightly different
|
|
ASSERTOPENGL(((DWORD)(NtCurrentTeb()->ThreadLocalStoragePointer)-
|
|
(DWORD)NtCurrentTeb()) == WIN95_TLS_OFFSET,
|
|
"Win95 TLS offset not at expected location");
|
|
|
|
dwTlsOffset = dwTlsIndex*sizeof(DWORD)+WIN95_TLS_OFFSET;
|
|
}
|
|
#endif
|
|
|
|
// Reserve memory for the local handle table.
|
|
|
|
if ( (pLocalTable = (PLHE) VirtualAlloc (
|
|
(LPVOID) NULL, // let base locate it
|
|
MAX_HANDLES*sizeof(LHE),
|
|
MEM_RESERVE | MEM_TOP_DOWN,
|
|
PAGE_READWRITE
|
|
)) == (PLHE) NULL )
|
|
{
|
|
WARNING("DllInitialize: VirtualAlloc failed\n");
|
|
#ifdef _CLIENTSIDE_
|
|
TlsFree(dwTlsIndex);
|
|
dwTlsIndex = 0xFFFFFFFF;
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
// Initialize the local handle manager semaphore.
|
|
|
|
INITIALIZECRITICALSECTION(&semLocal);
|
|
|
|
#ifdef _CLIENTSIDE_
|
|
// Initialize the GLGENwindow list semaphore.
|
|
|
|
INITIALIZECRITICALSECTION(&gwndHeader.sem);
|
|
gwndHeader.pNext = &gwndHeader;
|
|
|
|
// Initialize the pixel format critical section
|
|
|
|
INITIALIZECRITICALSECTION(&gcsPixelFormat);
|
|
|
|
// Initialize the palette watcher critical section.
|
|
INITIALIZECRITICALSECTION(&gcsPaletteWatcher);
|
|
|
|
// Initialize DCIMAN.
|
|
|
|
gpDCIInfo = (DCIINFO *) LocalAlloc(LMEM_FIXED|LMEM_ZEROINIT, sizeof(DCIINFO));
|
|
|
|
if ( gpDCIInfo )
|
|
{
|
|
if ( gpDCIInfo->hdc = DCIOpenProvider() )
|
|
{
|
|
int iRet;
|
|
|
|
iRet = DCICreatePrimary(gpDCIInfo->hdc, &gpDCIInfo->pDCISurfInfo);
|
|
|
|
if ( (iRet == DCI_OK) &&
|
|
(gpDCIInfo->pDCISurfInfo != (LPDCISURFACEINFO) NULL) &&
|
|
!(gpDCIInfo->pDCISurfInfo->dwDCICaps & DCI_1632_ACCESS) )
|
|
{
|
|
#define LEVEL_DCI LEVEL_INFO
|
|
|
|
DBGLEVEL (LEVEL_DCI, "=============================\n");
|
|
DBGLEVEL (LEVEL_DCI, "DCI usaged enabled for OpenGL\n\n");
|
|
DBGLEVEL (LEVEL_DCI, "DCISURFACEINFO:\n");
|
|
DBGLEVEL1(LEVEL_DCI, "\tdwSize = 0x%lx\n",
|
|
gpDCIInfo->pDCISurfInfo->dwSize);
|
|
DBGLEVEL1(LEVEL_DCI, "\tdwDCICaps = 0x%lx\n",
|
|
gpDCIInfo->pDCISurfInfo->dwDCICaps);
|
|
DBGLEVEL1(LEVEL_DCI, "\tdwCompression = %ld\n",
|
|
gpDCIInfo->pDCISurfInfo->dwCompression);
|
|
DBGLEVEL3(LEVEL_DCI,
|
|
"\tdwMask = (0x%lx, 0x%lx, 0x%lx)\n",
|
|
gpDCIInfo->pDCISurfInfo->dwMask[0],
|
|
gpDCIInfo->pDCISurfInfo->dwMask[1],
|
|
gpDCIInfo->pDCISurfInfo->dwMask[2]);
|
|
DBGLEVEL1(LEVEL_DCI, "\tdwWidth = %ld\n",
|
|
gpDCIInfo->pDCISurfInfo->dwWidth);
|
|
DBGLEVEL1(LEVEL_DCI, "\tdwHeight = %ld\n",
|
|
gpDCIInfo->pDCISurfInfo->dwHeight);
|
|
DBGLEVEL1(LEVEL_DCI, "\tlStride = 0x%lx\n",
|
|
gpDCIInfo->pDCISurfInfo->lStride);
|
|
DBGLEVEL1(LEVEL_DCI, "\tdwBitCount = %ld\n",
|
|
gpDCIInfo->pDCISurfInfo->dwBitCount);
|
|
DBGLEVEL1(LEVEL_DCI, "\tdwOffSurface = 0x%lx\n",
|
|
gpDCIInfo->pDCISurfInfo->dwOffSurface);
|
|
DBGLEVEL (LEVEL_DCI, "=============================\n");
|
|
|
|
// Verify DCI access
|
|
|
|
if( DCIBeginAccess( gpDCIInfo->pDCISurfInfo, 0, 0, 1, 1 )
|
|
< DCI_OK )
|
|
{
|
|
// DCI access failure
|
|
DBGLEVEL(LEVEL_DCI, "DCI access failure : disabling DCI\n");
|
|
} else {
|
|
DCIEndAccess( gpDCIInfo->pDCISurfInfo );
|
|
|
|
bDCI = TRUE;
|
|
|
|
// Initialize the pixel format critical section
|
|
|
|
INITIALIZECRITICALSECTION(&gcsDci);
|
|
}
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
DBGLEVEL (LEVEL_DCI, "=============================\n");
|
|
if (iRet != DCI_OK)
|
|
{
|
|
DBGLEVEL2(LEVEL_DCI, "DCICreatePrimary failed code %ld (%s)\n",
|
|
iRet, (iRet == DCI_FAIL_GENERIC ) ? "DCI_FAIL_GENERIC" :
|
|
(iRet == DCI_FAIL_UNSUPPORTEDVERSION) ? "DCI_FAIL_UNSUPPORTEDVERSION" :
|
|
(iRet == DCI_FAIL_INVALIDSURFACE ) ? "DCI_FAIL_INVALIDSURFACE" :
|
|
(iRet == DCI_FAIL_UNSUPPORTED ) ? "DCI_FAIL_UNSUPPORTED" :
|
|
"unknown");
|
|
}
|
|
else
|
|
{
|
|
if (!gpDCIInfo->pDCISurfInfo)
|
|
{
|
|
DBGLEVEL(LEVEL_DCI, "DCICreatePrimary did not set pDCISurfInfo\n");
|
|
}
|
|
else
|
|
{
|
|
DBGLEVEL1(LEVEL_DCI, "dwDCICaps = 0x%08lx\n", gpDCIInfo->pDCISurfInfo->dwDCICaps);
|
|
}
|
|
}
|
|
DBGLEVEL (LEVEL_DCI, "=============================\n");
|
|
}
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
DBGLEVEL(LEVEL_DCI, "DCIOpenProvider failed\n");
|
|
}
|
|
}
|
|
|
|
if (!bDCI)
|
|
{
|
|
if (gpDCIInfo)
|
|
{
|
|
if (gpDCIInfo->pDCISurfInfo)
|
|
DCIDestroy(gpDCIInfo->pDCISurfInfo);
|
|
if (gpDCIInfo->hdc)
|
|
DCICloseProvider(gpDCIInfo->hdc);
|
|
LocalFree(gpDCIInfo);
|
|
gpDCIInfo = (DCIINFO *) NULL;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
// Set up our multiplication table:
|
|
|
|
{
|
|
BYTE *pMulTable = gbMulTable;
|
|
ULONG i, j;
|
|
|
|
for (i = 0; i < 256; i++) {
|
|
ULONG tmp = 0;
|
|
|
|
for (j = 0; j < 256; j++, tmp += i) {
|
|
*pMulTable++ = (BYTE)(tmp >> 8);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set up our saturation table:
|
|
|
|
{
|
|
ULONG i;
|
|
|
|
for (i = 0; i < 256; i++)
|
|
gbSatTable[i] = (BYTE)i;
|
|
|
|
for (; i < (256+256); i++)
|
|
gbSatTable[i] = 255;
|
|
}
|
|
|
|
bProcessInitialized = TRUE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GLUnInitializeProcess
|
|
*
|
|
* Called from OPENGL32.DLL entry point for PROCESS_DETACH.
|
|
*
|
|
* History:
|
|
* 01-Nov-1994 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
void GLUnInitializeProcess()
|
|
{
|
|
// If we never finished process initialization, quit now.
|
|
|
|
if (!bProcessInitialized)
|
|
return;
|
|
|
|
// Cleanup stray HGLRCs that the app may have forgotten to delete.
|
|
{
|
|
static GLTEBINFO gltebInfoTmp;
|
|
|
|
// Need a temporary GLTEBINFO for this thread in order to do the
|
|
// cleanup processing.
|
|
|
|
ASSERTOPENGL(!CURRENT_GLTEBINFO(),
|
|
"GLUnInitializeProcess: GLTEBINFO not NULL!\n");
|
|
// made static and no longer need memset
|
|
// memset(&gltebInfoTmp, 0, sizeof(gltebInfoTmp));
|
|
SET_CURRENT_GLTEBINFO(&gltebInfoTmp);
|
|
|
|
vCleanupAllLRC();
|
|
|
|
SET_CURRENT_GLTEBINFO((PGLTEBINFO) NULL);
|
|
}
|
|
|
|
// Cleanup window tracking structures (GLGENwindow structs).
|
|
|
|
vCleanupWnd();
|
|
|
|
// Cleanup evaluator arrays
|
|
|
|
if (dBufFill)
|
|
LocalFree(dBufFill);
|
|
if (dBufTopLeft)
|
|
LocalFree(dBufTopLeft);
|
|
|
|
// DCI shutdown.
|
|
|
|
if (gpDCIInfo)
|
|
{
|
|
if (gpDCIInfo->pDCISurfInfo)
|
|
DCIDestroy(gpDCIInfo->pDCISurfInfo);
|
|
if (gpDCIInfo->hdc)
|
|
DCICloseProvider(gpDCIInfo->hdc);
|
|
LocalFree(gpDCIInfo);
|
|
if (bDCI)
|
|
DELETECRITICALSECTION(&gcsDci);
|
|
}
|
|
|
|
// Free the TLS slot.
|
|
|
|
if (dwTlsIndex != 0xFFFFFFFF)
|
|
if (!TlsFree(dwTlsIndex))
|
|
RIP("DllInitialize: TlsFree failed\n");
|
|
|
|
// Free the global semaphores.
|
|
|
|
DELETECRITICALSECTION(&gcsPaletteWatcher);
|
|
DELETECRITICALSECTION(&gcsPixelFormat);
|
|
DELETECRITICALSECTION(&gwndHeader.sem);
|
|
DELETECRITICALSECTION(&semLocal);
|
|
|
|
// Free the local handle table.
|
|
|
|
if ( pLocalTable )
|
|
VirtualFree(pLocalTable, 0, MEM_RELEASE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GLInitializeThread
|
|
*
|
|
* Called from OPENGL32.DLL entry point for THREAD_ATTACH. May assume that
|
|
* GLInitializeProcess has succeeded.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID GLInitializeThread(ULONG ulReason)
|
|
{
|
|
GLTEBINFO *pglti;
|
|
GLMSGBATCHINFO *pMsgBatchInfo;
|
|
POLYARRAY *pa;
|
|
|
|
#if !defined(_WIN95_) && defined(_X86_)
|
|
{
|
|
TEB *pteb;
|
|
|
|
pteb = NtCurrentTeb();
|
|
|
|
// Set up linear pointers to TEB regions in the TEB
|
|
// this saves an addition when referencing these values
|
|
// This must occur early so that these pointers are available
|
|
// for the rest of thread initialization
|
|
((POLYARRAY *)pteb->glReserved1)->paTeb =
|
|
(POLYARRAY *)pteb->glReserved1;
|
|
pteb->glTable = pteb->glDispatchTable;
|
|
}
|
|
#endif
|
|
|
|
pglti = (GLTEBINFO *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(GLTEBINFO));
|
|
SET_CURRENT_GLTEBINFO(pglti);
|
|
|
|
if (pglti)
|
|
{
|
|
pa = GLTEB_CLTPOLYARRAY();
|
|
pa->flags = 0; // not in begin mode
|
|
|
|
// Save shared section pointer in POLYARRAY for fast pointer access
|
|
pa->pMsgBatchInfo = (PVOID) pglti->glMsgBatchInfo;
|
|
|
|
pMsgBatchInfo = (GLMSGBATCHINFO *) pa->pMsgBatchInfo;
|
|
pMsgBatchInfo->MaximumOffset
|
|
= SHARED_SECTION_SIZE - GLMSG_ALIGN(sizeof(ULONG));
|
|
pMsgBatchInfo->FirstOffset
|
|
= GLMSG_ALIGN(sizeof(GLMSGBATCHINFO));
|
|
pMsgBatchInfo->NextOffset
|
|
= GLMSG_ALIGN(sizeof(GLMSGBATCHINFO));
|
|
SetCltProcTable(&glNullCltProcTable, &glNullExtProcTable, TRUE);
|
|
GLTEB_SET_CLTCURRENTRC(NULL);
|
|
GLTEB_SET_CLTPOLYMATERIAL(NULL);
|
|
GLTEB_SET_CLTDRIVERSLOT(NULL);
|
|
|
|
#if !defined(_WIN95_)
|
|
ASSERTOPENGL((ULONG) pMsgBatchInfo == GLMSG_ALIGN(pMsgBatchInfo),
|
|
"bad shared memory alignment!\n");
|
|
#endif
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GLUnInitializeThread
|
|
*
|
|
* Called from OPENGL32.DLL entry point for THREAD_DETACH.
|
|
*
|
|
* The server generic driver should cleanup on its own. Same for the
|
|
* installable driver.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
VOID GLUnInitializeThread(VOID)
|
|
{
|
|
// If we never finished process initialization, quit now.
|
|
|
|
if (!bProcessInitialized)
|
|
return;
|
|
|
|
if (!CURRENT_GLTEBINFO())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (GLTEB_CLTCURRENTRC() != NULL)
|
|
{
|
|
PLRC plrc = GLTEB_CLTCURRENTRC();
|
|
|
|
// May be an application error
|
|
|
|
DBGERROR("GLUnInitializeThread: RC is current when thread exits\n");
|
|
|
|
// Release the RC
|
|
|
|
plrc->tidCurrent = INVALID_THREAD_ID;
|
|
plrc->hdcCurrent = (HDC) 0;
|
|
GLTEB_SET_CLTCURRENTRC(NULL);
|
|
vUnlockHandle((ULONG)(plrc->hrc));
|
|
}
|
|
// GLTEB_SET_CLTPROCTABLE(&glNullCltProcTable,&glNullExtProcTable);
|
|
|
|
if (GLTEB_CLTPOLYMATERIAL())
|
|
FreePolyMaterial();
|
|
|
|
if (LocalFree((PVOID) CURRENT_GLTEBINFO()))
|
|
RIP("DllInitialize: LocalFree failed\n");
|
|
SET_CURRENT_GLTEBINFO(NULL);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DllInitialize
|
|
*
|
|
* This is the entry point for OPENGL32.DLL, which is called each time
|
|
* a process or thread that is linked to it is created or terminated.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
BOOL DllInitialize(HMODULE hModule, ULONG Reason, PVOID Reserved)
|
|
{
|
|
// Do the appropriate task for process and thread attach/detach.
|
|
|
|
DBGLEVEL3(LEVEL_INFO, "DllInitialize: %s Pid %d, Tid %d\n",
|
|
Reason == DLL_PROCESS_ATTACH ? "PROCESS_ATTACH" :
|
|
Reason == DLL_PROCESS_DETACH ? "PROCESS_DETACH" :
|
|
Reason == DLL_THREAD_ATTACH ? "THREAD_ATTACH" :
|
|
Reason == DLL_THREAD_DETACH ? "THREAD_DETACH" :
|
|
"Reason UNKNOWN!",
|
|
GetCurrentProcessId(), GetCurrentThreadId());
|
|
|
|
switch (Reason)
|
|
{
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
if (Reason == DLL_PROCESS_ATTACH)
|
|
{
|
|
if (!GLInitializeProcess())
|
|
return FALSE;
|
|
}
|
|
|
|
InterlockedIncrement(&lThreadsAttached);
|
|
GLInitializeThread(Reason);
|
|
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
case DLL_PROCESS_DETACH:
|
|
|
|
GLUnInitializeThread();
|
|
InterlockedDecrement(&lThreadsAttached);
|
|
|
|
if ( Reason == DLL_PROCESS_DETACH )
|
|
{
|
|
GLUnInitializeProcess();
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
RIP("DllInitialize: unknown reason!\n");
|
|
break;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|