ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

opengl32.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:            See COPYING in the top level directory
00003  * PROJECT:              ReactOS kernel
00004  * FILE:                 lib/opengl32/opengl32.c
00005  * PURPOSE:              OpenGL32 lib
00006  * PROGRAMMER:           Anich Gregor (blight), Royce Mitchell III
00007  * UPDATE HISTORY:
00008  *                       Feb 1, 2004: Created
00009  */
00010 
00011 #include "opengl32.h"
00012 
00013 /* function prototypes */
00014 static void OPENGL32_AppendICD( GLDRIVERDATA *icd );
00015 static void OPENGL32_RemoveICD( GLDRIVERDATA *icd );
00016 static GLDRIVERDATA *OPENGL32_LoadDriver( LPCWSTR regKey );
00017 static DWORD OPENGL32_InitializeDriver( GLDRIVERDATA *icd );
00018 static BOOL OPENGL32_UnloadDriver( GLDRIVERDATA *icd );
00019 static DWORD OPENGL32_RegGetDriverInfo( LPCWSTR driver, GLDRIVERDATA *icd );
00020 
00021 
00022 /* global vars */
00023 /* Do not assume it have the free value MAXDWORD set, any value can be in here */
00024 DWORD OPENGL32_tls = MAXDWORD;
00025 GLPROCESSDATA OPENGL32_processdata;
00026 
00027 
00028 static BOOL
00029 OPENGL32_ThreadAttach( void )
00030 {
00031     GLTHREADDATA* lpData = NULL;
00032     PROC *dispatchTable = NULL;
00033     TEB *teb = NULL;
00034 
00035     dispatchTable = (PROC*)HeapAlloc( GetProcessHeap(),
00036                                       HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
00037                                       DISPATCH_TABLE_SIZE );
00038     if (dispatchTable == NULL)
00039     {
00040         DBGPRINT( "Error: Couldn't allocate GL dispatch table" );
00041         return FALSE;
00042     }
00043 
00044     lpData = (GLTHREADDATA*)HeapAlloc( GetProcessHeap(),
00045                                        HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
00046                                        sizeof (GLTHREADDATA) );
00047     if (lpData == NULL)
00048     {
00049         DBGPRINT( "Error: Couldn't allocate GLTHREADDATA" );
00050         HeapFree( GetProcessHeap(), 0, dispatchTable );
00051         return FALSE;
00052     }
00053 
00054     teb = NtCurrentTeb();
00055 
00056     /* initialize dispatch table with empty functions */
00057     #define X(func, ret, typeargs, args, icdidx, tebidx, stack)            \
00058         dispatchTable[icdidx] = (PROC)glEmptyFunc##stack;                  \
00059         if (tebidx >= 0)                                                   \
00060             teb->glDispatchTable[tebidx] = (PVOID)glEmptyFunc##stack;
00061     GLFUNCS_MACRO
00062     #undef X
00063 
00064     teb->glTable = dispatchTable;
00065     TlsSetValue( OPENGL32_tls, lpData );
00066 
00067     return TRUE;
00068 }
00069 
00070 
00071 static void
00072 OPENGL32_ThreadDetach( void )
00073 {
00074     GLTHREADDATA* lpData = NULL;
00075     TEB* teb = NtCurrentTeb();
00076 
00077     rosglMakeCurrent( NULL, NULL );
00078 
00079     lpData = (GLTHREADDATA*)TlsGetValue( OPENGL32_tls );
00080     if (lpData != NULL)
00081     {
00082         if (!HeapFree( GetProcessHeap(), 0, lpData ))
00083             DBGPRINT( "Warning: HeapFree() on GLTHREADDATA failed (%d)",
00084                       GetLastError() );
00085         lpData = NULL;
00086     }
00087     TlsSetValue( OPENGL32_tls, NULL );
00088 
00089     if (teb->glTable != NULL)
00090     {
00091         if (!HeapFree( GetProcessHeap(), 0, teb->glTable ))
00092         {
00093             DBGPRINT( "Warning: HeapFree() on dispatch table failed (%d)",
00094                       GetLastError() );
00095         }
00096         /* NULL-ify it. Even if something went wrong, it's not a good idea to keep it non NULL */
00097         teb->glTable = NULL;
00098     }
00099 }
00100 
00101 
00102 static BOOL
00103 OPENGL32_ProcessAttach( void )
00104 {
00105     SECURITY_ATTRIBUTES attrib = { sizeof (SECURITY_ATTRIBUTES), /* nLength */
00106                                    NULL, /* lpSecurityDescriptor */
00107                                    TRUE /* bInheritHandle */ };
00108 
00109     OPENGL32_tls = TlsAlloc();
00110     if (OPENGL32_tls == MAXDWORD)
00111         return FALSE;
00112 
00113     memset( &OPENGL32_processdata, 0, sizeof (OPENGL32_processdata) );
00114 
00115     /* create driver, glrc & dcdata list mutex */
00116     OPENGL32_processdata.driver_mutex = CreateMutex( &attrib, FALSE, NULL );
00117     if (OPENGL32_processdata.driver_mutex == NULL)
00118     {
00119         DBGPRINT( "Error: Couldn't create driver_list mutex (%d)",
00120                   GetLastError() );
00121         return FALSE;
00122     }
00123     OPENGL32_processdata.glrc_mutex = CreateMutex( &attrib, FALSE, NULL );
00124     if (OPENGL32_processdata.glrc_mutex == NULL)
00125     {
00126         DBGPRINT( "Error: Couldn't create glrc_list mutex (%d)",
00127                   GetLastError() );
00128         return FALSE;
00129     }
00130     OPENGL32_processdata.dcdata_mutex = CreateMutex( &attrib, FALSE, NULL );
00131     if (OPENGL32_processdata.dcdata_mutex == NULL)
00132     {
00133         DBGPRINT( "Error: Couldn't create dcdata_list mutex (%d)",
00134                   GetLastError() );
00135         return FALSE;
00136     }
00137 
00138     return TRUE;
00139 }
00140 
00141 
00142 static void
00143 OPENGL32_ProcessDetach( void )
00144 {
00145     GLDRIVERDATA *icd, *icd2;
00146     GLDCDATA *dcdata, *dcdata2;
00147     GLRC *glrc, *glrc2;
00148 
00149     /* free lists */
00150     for (dcdata = OPENGL32_processdata.dcdata_list; dcdata != NULL;)
00151     {
00152         dcdata2 = dcdata;
00153         dcdata = dcdata->next;
00154         if (!HeapFree( GetProcessHeap(), 0, dcdata2 ))
00155             DBGPRINT( "Warning: HeapFree() on DCDATA 0x%08x failed (%d)",
00156                       dcdata2, GetLastError() );
00157     }
00158 
00159     for (glrc = OPENGL32_processdata.glrc_list; glrc != NULL;)
00160     {
00161         glrc2 = glrc;
00162         glrc = glrc->next;
00163         if (!HeapFree( GetProcessHeap(), 0, glrc2 ))
00164             DBGPRINT( "Warning: HeapFree() on GLRC 0x%08x failed (%d)",
00165                       glrc2, GetLastError() );
00166     }
00167 
00168     for (icd = OPENGL32_processdata.driver_list; icd != NULL;)
00169     {
00170         icd2 = icd;
00171         icd = icd->next;
00172         if (!HeapFree( GetProcessHeap(), 0, icd2 ))
00173             DBGPRINT( "Warning: HeapFree() on DRIVERDATA 0x%08x failed (%d)",
00174                       icd2, GetLastError() );
00175     }
00176 
00177     /* free mutexes */
00178     if (OPENGL32_processdata.driver_mutex != NULL)
00179         CloseHandle( OPENGL32_processdata.driver_mutex );
00180     if (OPENGL32_processdata.glrc_mutex != NULL)
00181         CloseHandle( OPENGL32_processdata.glrc_mutex );
00182     if (OPENGL32_processdata.dcdata_mutex != NULL)
00183         CloseHandle( OPENGL32_processdata.dcdata_mutex );
00184 
00185     /* free TLS */
00186     if (OPENGL32_tls != MAXDWORD)
00187         TlsFree(OPENGL32_tls);
00188 }
00189 
00190 
00191 BOOL WINAPI
00192 DllMain(HINSTANCE hInstance, DWORD Reason, LPVOID Reserved)
00193 {
00194     DBGPRINT( "Info: Called!" );
00195     switch ( Reason )
00196     {
00197     /* The DLL is loading due to process
00198      * initialization or a call to LoadLibrary.
00199      */
00200     case DLL_PROCESS_ATTACH:
00201         DBGTRACE( "Process attach" );
00202         if (!OPENGL32_ProcessAttach())
00203             return FALSE;
00204         /* No break: Initialize the index for first thread. */
00205 
00206     /* The attached process creates a new thread. */
00207     case DLL_THREAD_ATTACH:
00208         DBGTRACE( "Thread attach" );
00209         if (!OPENGL32_ThreadAttach())
00210             return FALSE;
00211         break;
00212 
00213     /* The thread of the attached process terminates. */
00214     case DLL_THREAD_DETACH:
00215         DBGTRACE( "Thread detach" );
00216         /* Release the allocated memory for this thread.*/
00217         OPENGL32_ThreadDetach();
00218         break;
00219 
00220     /* DLL unload due to process termination or FreeLibrary. */
00221     case DLL_PROCESS_DETACH:
00222         DBGTRACE( "Process detach" );
00223         OPENGL32_ThreadDetach();
00224         OPENGL32_ProcessDetach();
00225         break;
00226     }
00227 
00228     return TRUE;
00229 }
00230 
00231 
00238 static void
00239 OPENGL32_AppendICD( GLDRIVERDATA *icd )
00240 {
00241     if (OPENGL32_processdata.driver_list == NULL)
00242         OPENGL32_processdata.driver_list = icd;
00243     else
00244     {
00245         GLDRIVERDATA *p = OPENGL32_processdata.driver_list;
00246         while (p->next != NULL)
00247             p = p->next;
00248         p->next = icd;
00249     }
00250 }
00251 
00252 
00259 static void
00260 OPENGL32_RemoveICD( GLDRIVERDATA *icd )
00261 {
00262     if (icd == OPENGL32_processdata.driver_list)
00263         OPENGL32_processdata.driver_list = icd->next;
00264     else
00265     {
00266         GLDRIVERDATA *p = OPENGL32_processdata.driver_list;
00267         while (p != NULL)
00268         {
00269             if (p->next == icd)
00270             {
00271                 p->next = icd->next;
00272                 return;
00273             }
00274             p = p->next;
00275         }
00276         DBGPRINT( "Error: ICD 0x%08x not found in list!", icd );
00277     }
00278 }
00279 
00280 
00290 static GLDRIVERDATA *
00291 OPENGL32_LoadDriver( LPCWSTR driver )
00292 {
00293     LONG ret;
00294     GLDRIVERDATA *icd;
00295 
00296     DBGPRINT( "Info: Loading driver %ws...", driver );
00297 
00298     /* allocate driver data */
00299     icd = (GLDRIVERDATA*)HeapAlloc( GetProcessHeap(),
00300                                     HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
00301                                     sizeof (GLDRIVERDATA) );
00302     if (icd == NULL)
00303     {
00304         DBGPRINT( "Error: Couldn't allocate GLDRIVERDATA! (%d)", GetLastError() );
00305         return NULL;
00306     }
00307 
00308     ret = OPENGL32_RegGetDriverInfo( driver, icd );
00309     if (ret != ERROR_SUCCESS)
00310     {
00311         DBGPRINT( "Error: Couldn't query driver information (%d)", ret );
00312         if (!HeapFree( GetProcessHeap(), 0, icd ))
00313             DBGPRINT( "Error: HeapFree() returned false, error code = %d",
00314                       GetLastError() );
00315         return NULL;
00316     }
00317 
00318     DBGPRINT( "Info: Dll = %ws", icd->dll );
00319     DBGPRINT( "Info: Version = 0x%08x", icd->version );
00320     DBGPRINT( "Info: DriverVersion = 0x%08x", icd->driver_version );
00321     DBGPRINT( "Info: Flags = 0x%08x", icd->flags );
00322 
00323     /* load/initialize ICD */
00324     ret = OPENGL32_InitializeDriver( icd );
00325     if (ret != ERROR_SUCCESS)
00326     {
00327         DBGPRINT( "Error: Couldnt initialize ICD!" );
00328         if (!HeapFree( GetProcessHeap(), 0, icd ))
00329             DBGPRINT( "Error: HeapFree() returned false, error code = %d",
00330                       GetLastError() );
00331         return NULL;
00332     }
00333 
00334     /* append ICD to list */
00335     OPENGL32_AppendICD( icd );
00336     DBGPRINT( "Info: ICD loaded." );
00337 
00338     return icd;
00339 }
00340 
00341 
00349 #define LOAD_DRV_PROC( icd, proc, required ) \
00350     *(char**)&icd->proc = (char*)GetProcAddress( icd->handle, #proc ); \
00351     if (required && icd->proc == NULL) { \
00352         DBGPRINT( "Error: GetProcAddress(\"%s\") failed!", #proc ); \
00353         FreeLibrary( icd->handle ); \
00354         return GetLastError(); \
00355     }
00356 
00357 static DWORD
00358 OPENGL32_InitializeDriver( GLDRIVERDATA *icd )
00359 {
00360     /* check version */
00361     if (icd->version > 2)
00362         DBGPRINT( "Warning: ICD version > 2 (%d)", icd->version );
00363 
00364     /* load dll */
00365     icd->handle = LoadLibraryW( icd->dll );
00366     if (icd->handle == NULL)
00367     {
00368         DWORD err = GetLastError();
00369         DBGPRINT( "Error: Couldn't load DLL! (%d)", err );
00370         return err;
00371     }
00372 
00373     /* validate version */
00374     if (icd->driver_version > 1)
00375     {
00376         LOAD_DRV_PROC(icd, DrvValidateVersion, FALSE);
00377         if (icd->DrvValidateVersion != NULL)
00378         {
00379             if (!icd->DrvValidateVersion( icd->driver_version ))
00380             {
00381                 DBGPRINT( "Error: DrvValidateVersion failed!" );
00382                 DBGBREAK();
00383                 FreeLibrary( icd->handle );
00384                 return ERROR_INVALID_FUNCTION; /* FIXME: use better error code */
00385             }
00386         }
00387         else
00388             DBGPRINT( "Info: DrvValidateVersion not exported by ICD" );
00389     }
00390 
00391     /* load DrvXXX procs */
00392     LOAD_DRV_PROC(icd, DrvCopyContext, TRUE);
00393     LOAD_DRV_PROC(icd, DrvCreateContext, FALSE);
00394     LOAD_DRV_PROC(icd, DrvCreateLayerContext, FALSE);
00395     LOAD_DRV_PROC(icd, DrvDeleteContext, TRUE);
00396     LOAD_DRV_PROC(icd, DrvDescribeLayerPlane, TRUE);
00397     LOAD_DRV_PROC(icd, DrvDescribePixelFormat, TRUE);
00398     LOAD_DRV_PROC(icd, DrvGetLayerPaletteEntries, TRUE);
00399     LOAD_DRV_PROC(icd, DrvGetProcAddress, TRUE);
00400     LOAD_DRV_PROC(icd, DrvReleaseContext, TRUE);
00401     LOAD_DRV_PROC(icd, DrvRealizeLayerPalette, TRUE);
00402     LOAD_DRV_PROC(icd, DrvSetContext, TRUE);
00403     LOAD_DRV_PROC(icd, DrvSetLayerPaletteEntries, TRUE);
00404     LOAD_DRV_PROC(icd, DrvSetPixelFormat, TRUE);
00405     LOAD_DRV_PROC(icd, DrvShareLists, TRUE);
00406     LOAD_DRV_PROC(icd, DrvSwapBuffers, TRUE);
00407     LOAD_DRV_PROC(icd, DrvSwapLayerBuffers, TRUE);
00408 
00409     /* we require at least one of DrvCreateContext and DrvCreateLayerContext */
00410     if (icd->DrvCreateContext == NULL && icd->DrvCreateLayerContext == NULL)
00411     {
00412         DBGPRINT( "Error: One of DrvCreateContext/DrvCreateLayerContext is required!" );
00413         FreeLibrary( icd->handle );
00414         return ERROR_INVALID_FUNCTION; /* FIXME: use better error code... */
00415     }
00416 
00417     return ERROR_SUCCESS;
00418 }
00419 
00420 
00426 static BOOL
00427 OPENGL32_UnloadDriver( GLDRIVERDATA *icd )
00428 {
00429     BOOL allOk = TRUE;
00430 
00431     DBGPRINT( "Info: Unloading driver %ws...", icd->driver_name );
00432     if (icd->refcount != 0)
00433         DBGPRINT( "Warning: ICD refcount = %d (should be 0)", icd->refcount );
00434 
00435     /* unload dll */
00436     if (!FreeLibrary( icd->handle ))
00437     {
00438         allOk = FALSE;
00439         DBGPRINT( "Warning: FreeLibrary on ICD %ws failed! (%d)", icd->dll,
00440                   GetLastError() );
00441     }
00442 
00443     /* free resources */
00444     OPENGL32_RemoveICD( icd );
00445     if (!HeapFree( GetProcessHeap(), 0, icd ))
00446     {
00447         allOk = FALSE;
00448         DBGPRINT( "Warning: HeapFree() returned FALSE, error code = %d",
00449                   GetLastError() );
00450     }
00451 
00452     return allOk;
00453 }
00454 
00455 
00461 GLDRIVERDATA *
00462 OPENGL32_LoadICD( LPCWSTR driver )
00463 {
00464     GLDRIVERDATA *icd;
00465 
00466     /* synchronize */
00467     if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) ==
00468         WAIT_FAILED)
00469     {
00470         DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
00471         return NULL; /* FIXME: do we have to expect such an error and handle it? */
00472     }
00473 
00474     /* look if ICD is already loaded */
00475     for (icd = OPENGL32_processdata.driver_list; icd; icd = icd->next)
00476     {
00477         if (!_wcsicmp( driver, icd->driver_name )) /* found */
00478         {
00479             /* release mutex */
00480             if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
00481                 DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
00482 
00483             return icd;
00484         }
00485     }
00486 
00487     /* not found - try to load */
00488     icd = OPENGL32_LoadDriver( driver );
00489 
00490     /* release mutex */
00491     if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
00492         DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
00493 
00494     return icd;
00495 }
00496 
00497 
00503 BOOL
00504 OPENGL32_UnloadICD( GLDRIVERDATA *icd )
00505 {
00506     BOOL ret = TRUE;
00507 
00508     /* synchronize */
00509     if (WaitForSingleObject( OPENGL32_processdata.driver_mutex, INFINITE ) ==
00510         WAIT_FAILED)
00511     {
00512         DBGPRINT( "Error: WaitForSingleObject() failed (%d)", GetLastError() );
00513         return FALSE; /* FIXME: do we have to expect such an error and handle it? */
00514     }
00515 
00516     if (icd->refcount == 0)
00517         ret = OPENGL32_UnloadDriver( icd );
00518 
00519     /* release mutex */
00520     if (!ReleaseMutex( OPENGL32_processdata.driver_mutex ))
00521         DBGPRINT( "Error: ReleaseMutex() failed (%d)", GetLastError() );
00522 
00523     return ret;
00524 }
00525 
00526 
00539 #if 0 /* unused */
00540 DWORD
00541 OPENGL32_RegEnumDrivers( DWORD idx, LPWSTR name, LPDWORD cName )
00542 {
00543     HKEY hKey;
00544     LPCWSTR subKey = OPENGL_DRIVERS_SUBKEY;
00545     LONG ret;
00546     DWORD size;
00547     WCHAR driver[256];
00548 
00549     if (name == NULL)
00550         return ERROR_SUCCESS; /* nothing to do */
00551 
00552     if (cName == NULL)
00553         return ERROR_INVALID_FUNCTION; /* we need cName when name is given */
00554 
00555     /* open OpenGLDrivers registry key */
00556     ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey );
00557     if (ret != ERROR_SUCCESS)
00558     {
00559         DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey );
00560         return ret;
00561     }
00562 
00563     /* get subkey name */
00564     size = sizeof (driver) / sizeof (driver[0]);
00565     ret = RegEnumKeyW( hKey, idx, name, *cName );
00566     if (ret != ERROR_SUCCESS)
00567     {
00568         DBGPRINT( "Error: Couldn't get OpenGLDrivers subkey name (%d)", ret );
00569         RegCloseKey( hKey );
00570         return ret;
00571     }
00572     *cName = wcslen( name );
00573 
00574     /* close key */
00575     RegCloseKey( hKey );
00576     return ERROR_SUCCESS;
00577 }
00578 #endif /* 0 -- unused */
00579 
00580 
00592 static DWORD
00593 OPENGL32_RegGetDriverInfo( LPCWSTR driver, GLDRIVERDATA *icd )
00594 {
00595     HKEY hKey;
00596     WCHAR subKey[1024] = OPENGL_DRIVERS_SUBKEY2;
00597     LONG ret;
00598     DWORD type, size;
00599 
00600     /* drivers registry values */
00601     DWORD version = 1, driverVersion = 0, flags = 0;
00602     WCHAR dll[256];
00603 
00604     /* open driver registry key */
00605     wcsncat( subKey, driver, 1024 );
00606     ret = RegOpenKeyExW( HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, &hKey );
00607     if (ret != ERROR_SUCCESS)
00608     {
00609         DBGPRINT( "Error: Couldn't open registry key '%ws'", subKey );
00610         return ret;
00611     }
00612 
00613     /* query values */
00614     size = sizeof (dll);
00615     ret = RegQueryValueExW( hKey, L"Dll", 0, &type, (LPBYTE)dll, &size );
00616     if (ret != ERROR_SUCCESS || type != REG_SZ)
00617     {
00618         DBGPRINT( "Error: Couldn't query Dll value or not a string" );
00619         RegCloseKey( hKey );
00620         return ret;
00621     }
00622 
00623     size = sizeof (DWORD);
00624     ret = RegQueryValueExW( hKey, L"Version", 0, &type, (LPBYTE)&version, &size );
00625     if (ret != ERROR_SUCCESS || type != REG_DWORD)
00626         DBGPRINT( "Warning: Couldn't query Version value or not a DWORD" );
00627 
00628     size = sizeof (DWORD);
00629     ret = RegQueryValueExW( hKey, L"DriverVersion", 0, &type,
00630                             (LPBYTE)&driverVersion, &size );
00631     if (ret != ERROR_SUCCESS || type != REG_DWORD)
00632         DBGPRINT( "Warning: Couldn't query DriverVersion value or not a DWORD" );
00633 
00634     size = sizeof (DWORD);
00635     ret = RegQueryValueExW( hKey, L"Flags", 0, &type, (LPBYTE)&flags, &size );
00636     if (ret != ERROR_SUCCESS || type != REG_DWORD)
00637         DBGPRINT( "Warning: Couldn't query Flags value or not a DWORD" );
00638 
00639     /* close key */
00640     RegCloseKey( hKey );
00641 
00642     /* output data */
00643     /* FIXME: NUL-terminate strings? */
00644     wcsncpy( icd->driver_name, driver,
00645              sizeof (icd->driver_name) / sizeof (icd->driver_name[0]) - 1 );
00646     wcsncpy( icd->dll, dll,
00647              sizeof (icd->dll) / sizeof (icd->dll[0]) );
00648     icd->version = version;
00649     icd->driver_version = driverVersion;
00650     icd->flags = flags;
00651 
00652     return ERROR_SUCCESS;
00653 }
00654 
00655 /* EOF */
00656 

Generated on Sat May 26 2012 04:24:27 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.