[OPENGL32]
[reactos.git] / reactos / dll / win32 / opengl32 / opengl32.c
index 1125c87..e3c5602 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$
- *
+/*
  * COPYRIGHT:            See COPYING in the top level directory
  * PROJECT:              ReactOS kernel
  * FILE:                 lib/opengl32/opengl32.c
@@ -9,16 +8,8 @@
  *                       Feb 1, 2004: Created
  */
 
-#define WIN32_LEAN_AND_MEAN
-#define WIN32_NO_STATUS
-#include <windows.h>
-#include <winreg.h>
-#include "teb.h"
-
-#include <string.h>
 #include "opengl32.h"
 
-
 /* function prototypes */
 static void OPENGL32_AppendICD( GLDRIVERDATA *icd );
 static void OPENGL32_RemoveICD( GLDRIVERDATA *icd );
@@ -29,206 +20,212 @@ static DWORD OPENGL32_RegGetDriverInfo( LPCWSTR driver, GLDRIVERDATA *icd );
 
 
 /* global vars */
-DWORD OPENGL32_tls;
+/* Do not assume it have the free value MAXDWORD set, any value can be in here */
+DWORD OPENGL32_tls = MAXDWORD;
 GLPROCESSDATA OPENGL32_processdata;
 
 
 static BOOL
-OPENGL32_ThreadAttach()
+OPENGL32_ThreadAttach( void )
 {
-       GLTHREADDATA* lpData = NULL;
-       PROC *dispatchTable = NULL;
-       TEB *teb = NULL;
-
-       dispatchTable = (PROC*)HeapAlloc( GetProcessHeap(),
-                                         HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
-                                         sizeof (((ICDTable *)(0))->dispatch_table) );
-       if (dispatchTable == NULL)
-       {
-               DBGPRINT( "Error: Couldn't allocate GL dispatch table" );
-               return FALSE;
-       }
-
-       lpData = (GLTHREADDATA*)HeapAlloc( GetProcessHeap(),
-                                          HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
-                                          sizeof (GLTHREADDATA) );
-       if (lpData == NULL)
-       {
-               DBGPRINT( "Error: Couldn't allocate GLTHREADDATA" );
-               HeapFree( GetProcessHeap(), 0, dispatchTable );
-               return FALSE;
-       }
-
-       teb = NtCurrentTeb();
-
-       /* initialize dispatch table with empty functions */
-       #define X(func, ret, typeargs, args, icdidx, tebidx, stack)            \
-               dispatchTable[icdidx] = (PROC)glEmptyFunc##stack;                  \
-               if (tebidx >= 0)                                                   \
-                       teb->glDispatchTable[tebidx] = (PVOID)glEmptyFunc##stack;
-       GLFUNCS_MACRO
-       #undef X
-
-       teb->glTable = dispatchTable;
-       TlsSetValue( OPENGL32_tls, lpData );
-       
-       return TRUE;
+    GLTHREADDATA* lpData = NULL;
+    PROC *dispatchTable = NULL;
+    TEB *teb = NULL;
+
+    dispatchTable = (PROC*)HeapAlloc( GetProcessHeap(),
+                                      HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
+                                      DISPATCH_TABLE_SIZE );
+    if (dispatchTable == NULL)
+    {
+        DBGPRINT( "Error: Couldn't allocate GL dispatch table" );
+        return FALSE;
+    }
+
+    lpData = (GLTHREADDATA*)HeapAlloc( GetProcessHeap(),
+                                       HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
+                                       sizeof (GLTHREADDATA) );
+    if (lpData == NULL)
+    {
+        DBGPRINT( "Error: Couldn't allocate GLTHREADDATA" );
+        HeapFree( GetProcessHeap(), 0, dispatchTable );
+        return FALSE;
+    }
+
+    teb = NtCurrentTeb();
+
+    /* initialize dispatch table with empty functions */
+    #define X(func, ret, typeargs, args, icdidx, tebidx, stack)            \
+        dispatchTable[icdidx] = (PROC)glEmptyFunc##stack;                  \
+        if (tebidx >= 0)                                                   \
+            teb->glDispatchTable[tebidx] = (PVOID)glEmptyFunc##stack;
+    GLFUNCS_MACRO
+    #undef X
+
+    teb->glTable = dispatchTable;
+    TlsSetValue( OPENGL32_tls, lpData );
+
+    return TRUE;
 }
 
 
 static void
-OPENGL32_ThreadDetach()
+OPENGL32_ThreadDetach( void )
 {
-       GLTHREADDATA* lpData = NULL;
-       PROC *dispatchTable = NULL;
-
-       rosglMakeCurrent( NULL, NULL );
-
-       lpData = (GLTHREADDATA*)TlsGetValue( OPENGL32_tls );
-       if (lpData != NULL)
-       {
-               if (!HeapFree( GetProcessHeap(), 0, lpData ))
-                       DBGPRINT( "Warning: HeapFree() on GLTHREADDATA failed (%d)",
-                                 GetLastError() );
-       }
-
-       dispatchTable = NtCurrentTeb()->glTable;
-       if (dispatchTable != NULL)
-       {
-               if (!HeapFree( GetProcessHeap(), 0, dispatchTable ))
-                       DBGPRINT( "Warning: HeapFree() on dispatch table failed (%d)",
-                                 GetLastError() );
-       }
+    GLTHREADDATA* lpData = NULL;
+       TEB* teb = NtCurrentTeb();
+
+    rosglMakeCurrent( NULL, NULL );
+
+    lpData = (GLTHREADDATA*)TlsGetValue( OPENGL32_tls );
+    if (lpData != NULL)
+    {
+        if (!HeapFree( GetProcessHeap(), 0, lpData ))
+            DBGPRINT( "Warning: HeapFree() on GLTHREADDATA failed (%d)",
+                      GetLastError() );
+        lpData = NULL;
+    }
+    TlsSetValue( OPENGL32_tls, NULL );
+
+    if (teb->glTable != NULL)
+    {
+        if (!HeapFree( GetProcessHeap(), 0, teb->glTable ))
+               {
+            DBGPRINT( "Warning: HeapFree() on dispatch table failed (%d)",
+                      GetLastError() );
+               }
+               /* NULL-ify it. Even if something went wrong, it's not a good idea to keep it non NULL */
+               teb->glTable = NULL;
+    }
 }
 
 
 static BOOL
-OPENGL32_ProcessAttach()
+OPENGL32_ProcessAttach( void )
 {
-       SECURITY_ATTRIBUTES attrib = { sizeof (SECURITY_ATTRIBUTES), /* nLength */
-                                      NULL, /* lpSecurityDescriptor */
-                                      TRUE /* bInheritHandle */ };
-
-       OPENGL32_tls = TlsAlloc();
-       if (0xFFFFFFFF == OPENGL32_tls)
-               return FALSE;
-
-       memset( &OPENGL32_processdata, 0, sizeof (OPENGL32_processdata) );
-
-       /* create driver, glrc & dcdata list mutex */
-       OPENGL32_processdata.driver_mutex = CreateMutex( &attrib, FALSE, NULL );
-       if (OPENGL32_processdata.driver_mutex == NULL)
-       {
-               DBGPRINT( "Error: Couldn't create driver_list mutex (%d)",
-                         GetLastError() );
-               return FALSE;
-       }
-       OPENGL32_processdata.glrc_mutex = CreateMutex( &attrib, FALSE, NULL );
-       if (OPENGL32_processdata.glrc_mutex == NULL)
-       {
-               DBGPRINT( "Error: Couldn't create glrc_list mutex (%d)",
-                         GetLastError() );
-               return FALSE;
-       }
-       OPENGL32_processdata.dcdata_mutex = CreateMutex( &attrib, FALSE, NULL );
-       if (OPENGL32_processdata.dcdata_mutex == NULL)
-       {
-               DBGPRINT( "Error: Couldn't create dcdata_list mutex (%d)",
-                         GetLastError() );
-               return FALSE;
-       }
-
-       return TRUE;
+    SECURITY_ATTRIBUTES attrib = { sizeof (SECURITY_ATTRIBUTES), /* nLength */
+                                   NULL, /* lpSecurityDescriptor */
+                                   TRUE /* bInheritHandle */ };
+
+    OPENGL32_tls = TlsAlloc();
+    if (OPENGL32_tls == MAXDWORD)
+        return FALSE;
+
+    memset( &OPENGL32_processdata, 0, sizeof (OPENGL32_processdata) );
+
+    /* create driver, glrc & dcdata list mutex */
+    OPENGL32_processdata.driver_mutex = CreateMutex( &attrib, FALSE, NULL );
+    if (OPENGL32_processdata.driver_mutex == NULL)
+    {
+        DBGPRINT( "Error: Couldn't create driver_list mutex (%d)",
+                  GetLastError() );
+        return FALSE;
+    }
+    OPENGL32_processdata.glrc_mutex = CreateMutex( &attrib, FALSE, NULL );
+    if (OPENGL32_processdata.glrc_mutex == NULL)
+    {
+        DBGPRINT( "Error: Couldn't create glrc_list mutex (%d)",
+                  GetLastError() );
+        return FALSE;
+    }
+    OPENGL32_processdata.dcdata_mutex = CreateMutex( &attrib, FALSE, NULL );
+    if (OPENGL32_processdata.dcdata_mutex == NULL)
+    {
+        DBGPRINT( "Error: Couldn't create dcdata_list mutex (%d)",
+                  GetLastError() );
+        return FALSE;
+    }
+
+    return TRUE;
 }
 
 
 static void
-OPENGL32_ProcessDetach()
+OPENGL32_ProcessDetach( void )
 {
-       GLDRIVERDATA *icd, *icd2;
-       GLDCDATA *dcdata, *dcdata2;
-       GLRC *glrc, *glrc2;
-
-       /* free lists */
-       for (dcdata = OPENGL32_processdata.dcdata_list; dcdata != NULL;)
-       {
-               dcdata2 = dcdata;
-               dcdata = dcdata->next;
-               if (!HeapFree( GetProcessHeap(), 0, dcdata ))
-                       DBGPRINT( "Warning: HeapFree() on DCDATA 0x%08x failed (%d)",
-                                 dcdata, GetLastError() );
-       }
-
-       for (glrc = OPENGL32_processdata.glrc_list; glrc != NULL;)
-       {
-               glrc2 = glrc;
-               glrc = glrc->next;
-               if (!HeapFree( GetProcessHeap(), 0, glrc ))
-                       DBGPRINT( "Warning: HeapFree() on GLRC 0x%08x failed (%d)",
-                                 glrc, GetLastError() );
-       }
-
-       for (icd = OPENGL32_processdata.driver_list; icd != NULL;)
-       {
-               icd2 = icd;
-               icd = icd->next;
-               if (!HeapFree( GetProcessHeap(), 0, icd ))
-                       DBGPRINT( "Warning: HeapFree() on DRIVERDATA 0x%08x failed (%d)",
-                                 icd, GetLastError() );
-       }
-
-       /* free mutexes */
-       if (OPENGL32_processdata.driver_mutex != NULL)
-               CloseHandle( OPENGL32_processdata.driver_mutex );
-       if (OPENGL32_processdata.glrc_mutex != NULL)
-               CloseHandle( OPENGL32_processdata.glrc_mutex );
-       if (OPENGL32_processdata.dcdata_mutex != NULL)
-               CloseHandle( OPENGL32_processdata.dcdata_mutex );
-
-       /* free TLS */
-       if (OPENGL32_tls != 0xffffffff)
-               TlsFree(OPENGL32_tls);
+    GLDRIVERDATA *icd, *icd2;
+    GLDCDATA *dcdata, *dcdata2;
+    GLRC *glrc, *glrc2;
+
+    /* free lists */
+    for (dcdata = OPENGL32_processdata.dcdata_list; dcdata != NULL;)
+    {
+        dcdata2 = dcdata;
+        dcdata = dcdata->next;
+        if (!HeapFree( GetProcessHeap(), 0, dcdata2 ))
+            DBGPRINT( "Warning: HeapFree() on DCDATA 0x%08x failed (%d)",
+                      dcdata2, GetLastError() );
+    }
+
+    for (glrc = OPENGL32_processdata.glrc_list; glrc != NULL;)
+    {
+        glrc2 = glrc;
+        glrc = glrc->next;
+        if (!HeapFree( GetProcessHeap(), 0, glrc2 ))
+            DBGPRINT( "Warning: HeapFree() on GLRC 0x%08x failed (%d)",
+                      glrc2, GetLastError() );
+    }
+
+    for (icd = OPENGL32_processdata.driver_list; icd != NULL;)
+    {
+        icd2 = icd;
+        icd = icd->next;
+        if (!HeapFree( GetProcessHeap(), 0, icd2 ))
+            DBGPRINT( "Warning: HeapFree() on DRIVERDATA 0x%08x failed (%d)",
+                      icd2, GetLastError() );
+    }
+
+    /* free mutexes */
+    if (OPENGL32_processdata.driver_mutex != NULL)
+        CloseHandle( OPENGL32_processdata.driver_mutex );
+    if (OPENGL32_processdata.glrc_mutex != NULL)
+        CloseHandle( OPENGL32_processdata.glrc_mutex );
+    if (OPENGL32_processdata.dcdata_mutex != NULL)
+        CloseHandle( OPENGL32_processdata.dcdata_mutex );
+
+    /* free TLS */
+    if (OPENGL32_tls != MAXDWORD)
+        TlsFree(OPENGL32_tls);
 }
 
 
 BOOL WINAPI
 DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)
 {
-       DBGPRINT( "Info: Called!" );
-       switch ( Reason )
-       {
-       /* The DLL is loading due to process
-        * initialization or a call to LoadLibrary.
-        */
-       case DLL_PROCESS_ATTACH:
-               DBGTRACE( "Process attach" );
-               if (!OPENGL32_ProcessAttach())
-                       return FALSE;
-               /* No break: Initialize the index for first thread. */
-
-       /* The attached process creates a new thread. */
-       case DLL_THREAD_ATTACH:
-               DBGTRACE( "Thread attach" );
-               if (!OPENGL32_ThreadAttach())
-                       return FALSE;
-               break;
-
-       /* The thread of the attached process terminates. */
-       case DLL_THREAD_DETACH:
-               DBGTRACE( "Thread detach" );
-               /* Release the allocated memory for this thread.*/
-               OPENGL32_ThreadDetach();
-               break;
-
-       /* DLL unload due to process termination or FreeLibrary. */
-       case DLL_PROCESS_DETACH:
-               DBGTRACE( "Process detach" );
-               OPENGL32_ThreadDetach();
-               OPENGL32_ProcessDetach();
-               break;
-       }
-
-       return TRUE;
+    DBGPRINT( "Info: Called!" );
+    switch ( Reason )
+    {
+    /* The DLL is loading due to process
+     * initialization or a call to LoadLibrary.
+     */
+    case DLL_PROCESS_ATTACH:
+        DBGTRACE( "Process attach" );
+        if (!OPENGL32_ProcessAttach())
+            return FALSE;
+        /* No break: Initialize the index for first thread. */
+
+    /* The attached process creates a new thread. */
+    case DLL_THREAD_ATTACH:
+        DBGTRACE( "Thread attach" );
+        if (!OPENGL32_ThreadAttach())
+            return FALSE;
+        break;
+
+    /* The thread of the attached process terminates. */
+    case DLL_THREAD_DETACH:
+        DBGTRACE( "Thread detach" );
+        /* Release the allocated memory for this thread.*/
+        OPENGL32_ThreadDetach();
+        break;
+
+    /* DLL unload due to process termination or FreeLibrary. */
+    case DLL_PROCESS_DETACH:
+        DBGTRACE( "Process detach" );
+        OPENGL32_ThreadDetach();
+        OPENGL32_ProcessDetach();
+        break;
+    }
+
+    return TRUE;
 }
 
 
@@ -241,15 +238,15 @@ DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)
 static void
 OPENGL32_AppendICD( GLDRIVERDATA *icd )
 {
-       if (OPENGL32_processdata.driver_list == NULL)
-               OPENGL32_processdata.driver_list = icd;
-       else
-       {
-               GLDRIVERDATA *p = OPENGL32_processdata.driver_list;
-               while (p->next != NULL)
-                       p = p->next;
-               p->next = icd;
-       }
+    if (OPENGL32_processdata.driver_list == NULL)
+        OPENGL32_processdata.driver_list = icd;
+    else
+    {
+        GLDRIVERDATA *p = OPENGL32_processdata.driver_list;
+        while (p->next != NULL)
+            p = p->next;
+        p->next = icd;
+    }
 }
 
 
@@ -262,22 +259,22 @@ OPENGL32_AppendICD( GLDRIVERDATA *icd )
 static void
 OPENGL32_RemoveICD( GLDRIVERDATA *icd )
 {
-       if (icd == OPENGL32_processdata.driver_list)
-               OPENGL32_processdata.driver_list = icd->next;
-       else
-       {
-               GLDRIVERDATA *p = OPENGL32_processdata.driver_list;
-               while (p != NULL)
-               {
-                       if (p->next == icd)
-                       {
-                               p->next = icd->next;
-                               return;
-                       }
-                       p = p->next;
-               }
-               DBGPRINT( "Error: ICD 0x%08x not found in list!", icd );
-       }
+    if (icd == OPENGL32_processdata.driver_list)
+        OPENGL32_processdata.driver_list = icd->next;
+    else
+    {
+        GLDRIVERDATA *p = OPENGL32_processdata.driver_list;
+        while (p != NULL)
+        {
+            if (p->next == icd)
+            {
+                p->next = icd->next;
+                return;
+            }
+            p = p->next;
+        }
+        DBGPRINT( "Error: ICD 0x%08x not found in list!", icd );
+    }
 }
 
 
@@ -293,52 +290,52 @@ OPENGL32_RemoveICD( GLDRIVERDATA *icd )
 static GLDRIVERDATA *
 OPENGL32_LoadDriver( LPCWSTR driver )
 {
-       LONG ret;
-       GLDRIVERDATA *icd;
-
-       DBGPRINT( "Info: Loading driver %ws...", driver );
-
-       /* allocate driver data */
-       icd = (GLDRIVERDATA*)HeapAlloc( GetProcessHeap(),
-                                       HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
-                                       sizeof (GLDRIVERDATA) );
-       if (icd == NULL)
-       {
-               DBGPRINT( "Error: Couldn't allocate GLDRIVERDATA! (%d)", GetLastError() );
-               return NULL;
-       }
-
-       ret = OPENGL32_RegGetDriverInfo( driver, icd );
-       if (ret != ERROR_SUCCESS)
-       {
-               DBGPRINT( "Error: Couldn't query driver information (%d)", ret );
-               if (!HeapFree( GetProcessHeap(), 0, icd ))
-                       DBGPRINT( "Error: HeapFree() returned false, error code = %d",
-                                 GetLastError() );
-               return NULL;
-       }
-
-       DBGPRINT( "Info: Dll = %ws", icd->dll );
-       DBGPRINT( "Info: Version = 0x%08x", icd->version );
-       DBGPRINT( "Info: DriverVersion = 0x%08x", icd->driver_version );
-       DBGPRINT( "Info: Flags = 0x%08x", icd->flags );
-
-       /* load/initialize ICD */
-       ret = OPENGL32_InitializeDriver( icd );
-       if (ret != ERROR_SUCCESS)
-       {
-               DBGPRINT( "Error: Couldnt initialize ICD!" );
-               if (!HeapFree( GetProcessHeap(), 0, icd ))
-                       DBGPRINT( "Error: HeapFree() returned false, error code = %d",
-                                 GetLastError() );
-               return NULL;
-       }
-
-       /* append ICD to list */
-       OPENGL32_AppendICD( icd );
-       DBGPRINT( "Info: ICD loaded." );
-
-       return icd;
+    LONG ret;
+    GLDRIVERDATA *icd;
+
+    DBGPRINT( "Info: Loading driver %ws...", driver );
+
+    /* allocate driver data */
+    icd = (GLDRIVERDATA*)HeapAlloc( GetProcessHeap(),
+                                    HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
+                                    sizeof (GLDRIVERDATA) );
+    if (icd == NULL)
+    {
+        DBGPRINT( "Error: Couldn't allocate GLDRIVERDATA! (%d)", GetLastError() );
+        return NULL;
+    }
+
+    ret = OPENGL32_RegGetDriverInfo( driver, icd );
+    if (ret != ERROR_SUCCESS)
+    {
+        DBGPRINT( "Error: Couldn't query driver information (%d)", ret );
+        if (!HeapFree( GetProcessHeap(), 0, icd ))
+            DBGPRINT( "Error: HeapFree() returned false, error code = %d",
+                      GetLastError() );
+        return NULL;
+    }
+
+    DBGPRINT( "Info: Dll = %ws", icd->dll );
+    DBGPRINT( "Info: Version = 0x%08x", icd->version );
+    DBGPRINT( "Info: DriverVersion = 0x%08x", icd->driver_version );
+    DBGPRINT( "Info: Flags = 0x%08x", icd->flags );
+
+    /* load/initialize ICD */
+    ret = OPENGL32_InitializeDriver( icd );
+    if (ret != ERROR_SUCCESS)
+    {
+        DBGPRINT( "Error: Couldnt initialize ICD!" );
+        if (!HeapFree( GetProcessHeap(), 0, icd ))
+            DBGPRINT( "Error: HeapFree() returned false, error code = %d",
+                      GetLastError() );
+        return NULL;
+    }
+
+    /* append ICD to list */
+    OPENGL32_AppendICD( icd );
+    DBGPRINT( "Info: ICD loaded." );
+
+    return icd;
 }
 
 
@@ -350,74 +347,74 @@ OPENGL32_LoadDriver( LPCWSTR driver )
  * \retval ERROR_SUCCESS  Success
  */
 #define LOAD_DRV_PROC( icd, proc, required ) \
-       *(char**)&icd->proc = (char*)GetProcAddress( icd->handle, #proc ); \
-       if (required && icd->proc == NULL) { \
-               DBGPRINT( "Error: GetProcAddress(\"%s\") failed!", #proc ); \
-               FreeLibrary( icd->handle ); \
-               return GetLastError(); \
-       }
+    *(char**)&icd->proc = (char*)GetProcAddress( icd->handle, #proc ); \
+    if (required && icd->proc == NULL) { \
+        DBGPRINT( "Error: GetProcAddress(\"%s\") failed!", #proc ); \
+        FreeLibrary( icd->handle ); \
+        return GetLastError(); \
+    }
 
 static DWORD
 OPENGL32_InitializeDriver( GLDRIVERDATA *icd )
 {
-       /* check version */
-       if (icd->version > 2)
-               DBGPRINT( "Warning: ICD version > 2 (%d)", icd->version );
-
-       /* load dll */
-       icd->handle = LoadLibraryW( icd->dll );
-       if (icd->handle == NULL)
-       {
-               DWORD err = GetLastError();
-               DBGPRINT( "Error: Couldn't load DLL! (%d)", err );
-               return err;
-       }
-
-       /* validate version */
-       if (icd->driver_version > 1)
-       {
-               LOAD_DRV_PROC(icd, DrvValidateVersion, FALSE);
-               if (icd->DrvValidateVersion != NULL)
-               {
-                       if (!icd->DrvValidateVersion( icd->driver_version ))
-                       {
-                               DBGPRINT( "Error: DrvValidateVersion failed!" );
-                               DBGBREAK();
-                               FreeLibrary( icd->handle );
-                               return ERROR_INVALID_FUNCTION; /* FIXME: use better error code */
-                       }
-               }
-               else
-                       DBGPRINT( "Info: DrvValidateVersion not exported by ICD" );
-       }
-
-       /* load DrvXXX procs */
-       LOAD_DRV_PROC(icd, DrvCopyContext, TRUE);
-       LOAD_DRV_PROC(icd, DrvCreateContext, FALSE);
-       LOAD_DRV_PROC(icd, DrvCreateLayerContext, FALSE);
-       LOAD_DRV_PROC(icd, DrvDeleteContext, TRUE);
-       LOAD_DRV_PROC(icd, DrvDescribeLayerPlane, TRUE);
-       LOAD_DRV_PROC(icd, DrvDescribePixelFormat, TRUE);
-       LOAD_DRV_PROC(icd, DrvGetLayerPaletteEntries, TRUE);
-       LOAD_DRV_PROC(icd, DrvGetProcAddress, TRUE);
-       LOAD_DRV_PROC(icd, DrvReleaseContext, TRUE);
-       LOAD_DRV_PROC(icd, DrvRealizeLayerPalette, TRUE);
-       LOAD_DRV_PROC(icd, DrvSetContext, TRUE);
-       LOAD_DRV_PROC(icd, DrvSetLayerPaletteEntries, TRUE);
-       LOAD_DRV_PROC(icd, DrvSetPixelFormat, TRUE);
-       LOAD_DRV_PROC(icd, DrvShareLists, TRUE);
-       LOAD_DRV_PROC(icd, DrvSwapBuffers, TRUE);
-       LOAD_DRV_PROC(icd, DrvSwapLayerBuffers, TRUE);
-
-       /* we require at least one of DrvCreateContext and DrvCreateLayerContext */
-       if (icd->DrvCreateContext == NULL && icd->DrvCreateLayerContext == NULL)
-       {
-               DBGPRINT( "Error: One of DrvCreateContext/DrvCreateLayerContext is required!" );
-               FreeLibrary( icd->handle );
-               return ERROR_INVALID_FUNCTION; /* FIXME: use better error code... */
-       }
-
-       return ERROR_SUCCESS;
+    /* check version */
+    if (icd->version > 2)
+        DBGPRINT( "Warning: ICD version > 2 (%d)", icd->version );
+
+    /* load dll */
+    icd->handle = LoadLibraryW( icd->dll );
+    if (icd->handle == NULL)
+    {
+        DWORD err = GetLastError();
+        DBGPRINT( "Error: Couldn't load DLL! (%d)", err );
+        return err;
+    }
+
+    /* validate version */
+    if (icd->driver_version > 1)
+    {
+        LOAD_DRV_PROC(icd, DrvValidateVersion, FALSE);
+        if (icd->DrvValidateVersion != NULL)
+        {
+            if (!icd->DrvValidateVersion( icd->driver_version ))
+            {
+                DBGPRINT( "Error: DrvValidateVersion failed!" );
+                DBGBREAK();
+                FreeLibrary( icd->handle );
+                return ERROR_INVALID_FUNCTION; /* FIXME: use better error code */
+            }
+        }
+        else
+            DBGPRINT( "Info: DrvValidateVersion not exported by ICD" );
+    }
+
+    /* load DrvXXX procs */
+    LOAD_DRV_PROC(icd, DrvCopyContext, TRUE);
+    LOAD_DRV_PROC(icd, DrvCreateContext, FALSE);
+    LOAD_DRV_PROC(icd, DrvCreateLayerContext, FALSE);
+    LOAD_DRV_PROC(icd, DrvDeleteContext, TRUE);
+    LOAD_DRV_PROC(icd, DrvDescribeLayerPlane, TRUE);
+    LOAD_DRV_PROC(icd, DrvDescribePixelFormat, TRUE);
+    LOAD_DRV_PROC(icd, DrvGetLayerPaletteEntries, TRUE);
+    LOAD_DRV_PROC(icd, DrvGetProcAddress, TRUE);
+    LOAD_DRV_PROC(icd, DrvReleaseContext, TRUE);
+    LOAD_DRV_PROC(icd, DrvRealizeLayerPalette, TRUE);
+    LOAD_DRV_PROC(icd, DrvSetContext, TRUE);
+    LOAD_DRV_PROC(icd, DrvSetLayerPaletteEntries, TRUE);
+    LOAD_DRV_PROC(icd, DrvSetPixelFormat, TRUE);
+    LOAD_DRV_PROC(icd, DrvShareLists, TRUE);
+    LOAD_DRV_PROC(icd, DrvSwapBuffers, TRUE);
+    LOAD_DRV_PROC(icd, DrvSwapLayerBuffers, TRUE);
+
+    /* we require at least one of DrvCreateContext and DrvCreateLayerContext */
+    if (icd->DrvCreateContext == NULL && icd->DrvCreateLayerContext == NULL)
+    {
+        DBGPRINT( "Error: One of DrvCreateContext/DrvCreateLayerContext is required!" );
+        FreeLibrary( icd->handle );
+        return ERROR_INVALID_FUNCTION; /* FIXME: use better error code... */
+    }
+
+    return ERROR_SUCCESS;
 }
 
 
@@ -429,30 +426,30 @@ OPENGL32_InitializeDriver( GLDRIVERDATA *icd )
 static BOOL
 OPENGL32_UnloadDriver( GLDRIVERDATA *icd )
 {
-       BOOL allOk = TRUE;
-
-       DBGPRINT( "Info: Unloading driver %ws...", icd->driver_name );
-       if (icd->refcount != 0)
-               DBGPRINT( "Warning: ICD refcount = %d (should be 0)", icd->refcount );
-
-       /* unload dll */
-       if (!FreeLibrary( icd->handle ))
-       {
-               allOk = FALSE;
-               DBGPRINT( "Warning: FreeLibrary on ICD %ws failed! (%d)", icd->dll,
-                         GetLastError() );
-       }
-
-       /* free resources */
-       OPENGL32_RemoveICD( icd );
-       if (!HeapFree( GetProcessHeap(), 0, icd ))
-       {
-               allOk = FALSE;
-               DBGPRINT( "Warning: HeapFree() returned FALSE, error code = %d",
-                         GetLastError() );
-       }
-
-       return allOk;
+    BOOL allOk = TRUE;
+
+    DBGPRINT( "Info: Unloading driver %ws...", icd->driver_name );
+    if (icd->refcount != 0)
+        DBGPRINT( "Warning: ICD refcount = %d (should be 0)", icd->refcount );
+
+    /* unload dll */
+    if (!FreeLibrary( icd->handle ))
+    {
+        allOk = FALSE;
+        DBGPRINT( "Warning: FreeLibrary on ICD %ws failed! (%d)", icd->dll,
+                  GetLastError() );
+    }
+
+    /* free resources */
+    OPENGL32_RemoveICD( icd );
+    if (!HeapFree( GetProcessHeap(), 0, icd ))
+    {
+        allOk = FALSE;
+        DBGPRINT( "Warning: HeapFree() returned FALSE, error code = %d",
+                  GetLastError() );
+    }
+
+    return allOk;
 }
 
 
@@ -464,41 +461,37 @@ OPENGL32_UnloadDriver( GLDRIVERDATA *icd )
 GLDRIVERDATA *
 OPENGL32_LoadICD( LPCWSTR driver )
 {
-       GLDRIVERDATA *icd;
-
-       /* synchronize */
-       if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) ==
-           WAIT_FAILED)
-       {
-               DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
-               return NULL; /* FIXME: do we have to expect such an error and handle it? */
-       }
-
-       /* look if ICD is already loaded */
-       for (icd = OPENGL32_processdata.driver_list; icd; icd = icd->next)
-       {
-               if (!_wcsicmp( driver, icd->driver_name )) /* found */
-               {
-                       icd->refcount++;
-
-                       /* release mutex */
-                       if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
-                               DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
-
-                       return icd;
-               }
-       }
-
-       /* not found - try to load */
-       icd = OPENGL32_LoadDriver( driver );
-       if (icd != NULL)
-               icd->refcount = 1;
-
-       /* release mutex */
-       if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
-               DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
-
-       return icd;
+    GLDRIVERDATA *icd;
+
+    /* synchronize */
+    if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) ==
+        WAIT_FAILED)
+    {
+        DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
+        return NULL; /* FIXME: do we have to expect such an error and handle it? */
+    }
+
+    /* look if ICD is already loaded */
+    for (icd = OPENGL32_processdata.driver_list; icd; icd = icd->next)
+    {
+        if (!_wcsicmp( driver, icd->driver_name )) /* found */
+        {
+            /* release mutex */
+            if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
+                DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+
+            return icd;
+        }
+    }
+
+    /* not found - try to load */
+    icd = OPENGL32_LoadDriver( driver );
+
+    /* release mutex */
+    if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
+        DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+
+    return icd;
 }
 
 
@@ -510,27 +503,24 @@ OPENGL32_LoadICD( LPCWSTR driver )
 BOOL
 OPENGL32_UnloadICD( GLDRIVERDATA *icd )
 {
-       BOOL ret = TRUE;
-
-       /* synchronize */
-       if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) ==
-           WAIT_FAILED)
-       {
-               DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
-               return FALSE; /* FIXME: do we have to expect such an error and handle it? */
-       }
-
-       icd->refcount--;
-       if (icd->refcount == 0)
-//     if (0)
-               ret = OPENGL32_UnloadDriver( icd );
-       /* FIXME: InitializeICD crashes when called a second time */
-
-       /* release mutex */
-       if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
-               DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
-
-       return ret;
+    BOOL ret = TRUE;
+
+    /* synchronize */
+    if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) ==
+        WAIT_FAILED)
+    {
+        DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
+        return FALSE; /* FIXME: do we have to expect such an error and handle it? */
+    }
+
+    if (icd->refcount == 0)
+        ret = OPENGL32_UnloadDriver( icd );
+
+    /* release mutex */
+    if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
+        DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
+
+    return ret;
 }
 
 
@@ -542,7 +532,7 @@ OPENGL32_UnloadICD( GLDRIVERDATA *icd )
  *               Output is length of the drivername.
  *               Can be NULL if name is NULL.
  *
- * \return Error code 
+ * \return Error code
  * \retval ERROR_NO_MORE_ITEMS  End of driver list.
  * \retval ERROR_SUCCESS        Success.
  */
@@ -550,40 +540,40 @@ OPENGL32_UnloadICD( GLDRIVERDATA *icd )
 DWORD
 OPENGL32_RegEnumDrivers( DWORD idx, LPWSTR name, LPDWORD cName )
 {
-       HKEY hKey;
-       LPCWSTR subKey = OPENGL_DRIVERS_SUBKEY;
-       LONG ret;
-       DWORD size;
-       WCHAR driver[256];
-
-       if (name == NULL)
-               return ERROR_SUCCESS; /* nothing to do */
-
-       if (cName == NULL)
-               return ERROR_INVALID_FUNCTION; /* we need cName when name is given */
-
-       /* open OpenGLDrivers registry key */
-       ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey );
-       if (ret != ERROR_SUCCESS)
-       {
-               DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey );
-               return ret;
-       }
-
-       /* get subkey name */
-       size = sizeof (driver) / sizeof (driver[0]);
-       ret = RegEnumKeyW( hKey, idx, name, *cName );
-       if (ret != ERROR_SUCCESS)
-       {
-               DBGPRINT( "Error: Couldn't get OpenGLDrivers subkey name (%d)", ret );
-               RegCloseKey( hKey );
-               return ret;
-       }
-       *cName = wcslen( name );
-
-       /* close key */
-       RegCloseKey( hKey );
-       return ERROR_SUCCESS;
+    HKEY hKey;
+    LPCWSTR subKey = OPENGL_DRIVERS_SUBKEY;
+    LONG ret;
+    DWORD size;
+    WCHAR driver[256];
+
+    if (name == NULL)
+        return ERROR_SUCCESS; /* nothing to do */
+
+    if (cName == NULL)
+        return ERROR_INVALID_FUNCTION; /* we need cName when name is given */
+
+    /* open OpenGLDrivers registry key */
+    ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey );
+    if (ret != ERROR_SUCCESS)
+    {
+        DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey );
+        return ret;
+    }
+
+    /* get subkey name */
+    size = sizeof (driver) / sizeof (driver[0]);
+    ret = RegEnumKeyW( hKey, idx, name, *cName );
+    if (ret != ERROR_SUCCESS)
+    {
+        DBGPRINT( "Error: Couldn't get OpenGLDrivers subkey name (%d)", ret );
+        RegCloseKey( hKey );
+        return ret;
+    }
+    *cName = wcslen( name );
+
+    /* close key */
+    RegCloseKey( hKey );
+    return ERROR_SUCCESS;
 }
 #endif /* 0 -- unused */
 
@@ -593,7 +583,7 @@ OPENGL32_RegEnumDrivers( DWORD idx, LPWSTR name, LPDWORD cName )
  * \param driver  Name of the driver to get information about.
  * \param icd     Pointer to GLDRIVERDATA.
  *
- * \return Error code. 
+ * \return Error code.
  * \retval ERROR_SUCCESS  Success.
  *
  * \note On success the following fields of \a icd are filled: \a driver_name,
@@ -602,64 +592,64 @@ OPENGL32_RegEnumDrivers( DWORD idx, LPWSTR name, LPDWORD cName )
 static DWORD
 OPENGL32_RegGetDriverInfo( LPCWSTR driver, GLDRIVERDATA *icd )
 {
-       HKEY hKey;
-       WCHAR subKey[1024] = OPENGL_DRIVERS_SUBKEY"\\";
-       LONG ret;
-       DWORD type, size;
-
-       /* drivers registry values */
-       DWORD version = 1, driverVersion = 0, flags = 0;
-       WCHAR dll[256];
-
-       /* open driver registry key */
-       wcsncat( subKey, driver, 1024 );
-       ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey );
-       if (ret != ERROR_SUCCESS)
-       {
-               DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey );
-               return ret;
-       }
-
-       /* query values */
-       size = sizeof (dll);
-       ret = RegQueryValueExW( hKey, L"Dll", 0, &type, (LPBYTE)dll, &size );
-       if (ret != ERROR_SUCCESS || type != REG_SZ)
-       {
-               DBGPRINT( "Error: Couldn't query Dll value or not a string" );
-               RegCloseKey( hKey );
-               return ret;
-       }
-
-       size = sizeof (DWORD);
-       ret = RegQueryValueExW( hKey, L"Version", 0, &type, (LPBYTE)&version, &size );
-       if (ret != ERROR_SUCCESS || type != REG_DWORD)
-               DBGPRINT( "Warning: Couldn't query Version value or not a DWORD" );
-
-       size = sizeof (DWORD);
-       ret = RegQueryValueExW( hKey, L"DriverVersion", 0, &type,
-                                                       (LPBYTE)&driverVersion, &size );
-       if (ret != ERROR_SUCCESS || type != REG_DWORD)
-               DBGPRINT( "Warning: Couldn't query DriverVersion value or not a DWORD" );
-
-       size = sizeof (DWORD);
-       ret = RegQueryValueExW( hKey, L"Flags", 0, &type, (LPBYTE)&flags, &size );
-       if (ret != ERROR_SUCCESS || type != REG_DWORD)
-               DBGPRINT( "Warning: Couldn't query Flags value or not a DWORD" );
-
-       /* close key */
-       RegCloseKey( hKey );
-
-       /* output data */
-       /* FIXME: NUL-terminate strings? */
-       wcsncpy( icd->driver_name, driver,
-                sizeof (icd->driver_name) / sizeof (icd->driver_name[0]) - 1 );
-       wcsncpy( icd->dll, dll,
-                sizeof (icd->dll) / sizeof (icd->dll[0]) );
-       icd->version = version;
-       icd->driver_version = driverVersion;
-       icd->flags = flags;
-
-       return ERROR_SUCCESS;
+    HKEY hKey;
+    WCHAR subKey[1024] = OPENGL_DRIVERS_SUBKEY2;
+    LONG ret;
+    DWORD type, size;
+
+    /* drivers registry values */
+    DWORD version = 1, driverVersion = 0, flags = 0;
+    WCHAR dll[256];
+
+    /* open driver registry key */
+    wcsncat( subKey, driver, 1024 );
+    ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey );
+    if (ret != ERROR_SUCCESS)
+    {
+        DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey );
+        return ret;
+    }
+
+    /* query values */
+    size = sizeof (dll);
+    ret = RegQueryValueExW( hKey, L"Dll", 0, &type, (LPBYTE)dll, &size );
+    if (ret != ERROR_SUCCESS || type != REG_SZ)
+    {
+        DBGPRINT( "Error: Couldn't query Dll value or not a string" );
+        RegCloseKey( hKey );
+        return ret;
+    }
+
+    size = sizeof (DWORD);
+    ret = RegQueryValueExW( hKey, L"Version", 0, &type, (LPBYTE)&version, &size );
+    if (ret != ERROR_SUCCESS || type != REG_DWORD)
+        DBGPRINT( "Warning: Couldn't query Version value or not a DWORD" );
+
+    size = sizeof (DWORD);
+    ret = RegQueryValueExW( hKey, L"DriverVersion", 0, &type,
+                            (LPBYTE)&driverVersion, &size );
+    if (ret != ERROR_SUCCESS || type != REG_DWORD)
+        DBGPRINT( "Warning: Couldn't query DriverVersion value or not a DWORD" );
+
+    size = sizeof (DWORD);
+    ret = RegQueryValueExW( hKey, L"Flags", 0, &type, (LPBYTE)&flags, &size );
+    if (ret != ERROR_SUCCESS || type != REG_DWORD)
+        DBGPRINT( "Warning: Couldn't query Flags value or not a DWORD" );
+
+    /* close key */
+    RegCloseKey( hKey );
+
+    /* output data */
+    /* FIXME: NUL-terminate strings? */
+    wcsncpy( icd->driver_name, driver,
+             sizeof (icd->driver_name) / sizeof (icd->driver_name[0]) - 1 );
+    wcsncpy( icd->dll, dll,
+             sizeof (icd->dll) / sizeof (icd->dll[0]) );
+    icd->version = version;
+    icd->driver_version = driverVersion;
+    icd->flags = flags;
+
+    return ERROR_SUCCESS;
 }
 
 /* EOF */