#include "pch.hpp"
//===========================================================================//
// File:	 Libraries.cpp													 //
// Project:  GameOS					                                         //
// Contents: Dynamically loaded library manager								 //
//---------------------------------------------------------------------------//
// Date      Who    Modification                                             //
// 11/27/98  AG     Created													 // 
//																			 //
//---------------------------------------------------------------------------//
// Copyright (C) 1999 Microsoft Corp.						                 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//
#include "Windows.hpp"
#include "DXRasterizer.hpp"
#include "ErrorHandler.hpp"
#include "ijl.h"
#include "raid.hpp"

//JJ Fix-A-Roo
GETDXFUNC g_pGetDXVB = NULL;

extern DWORD gEnableGosView;
extern DWORD gLanguageDLL;

DWORD PDBMemory=0;
extern DWORD GetVMSize();


//
// Libraries loaded
//
HINSTANCE LibAmstream=0;
HINSTANCE LibQuartz=0;
HINSTANCE LibMSADP32=0;
HINSTANCE LibBlade=0;
HINSTANCE LibDinput=0;
HINSTANCE LibDsound=0;
HINSTANCE LibIME=0;
HINSTANCE LibJpeg=0;
HINSTANCE LibPSAPI=0;
HINSTANCE LibODBC=0;
HINSTANCE LibWinSock=0;
//
// Routines in above libraries
//
HRESULT (WINAPI* _DirectDrawCreateEx)( GUID* lpGUID, void** lplpDD, REFIID iid, IUnknown* pUnkOuter ); 
HRESULT (WINAPI* _DirectDrawEnumerate)( LPDDENUMCALLBACK lpCallback, LPVOID lpContext );
HRESULT (WINAPI* _DirectDrawEnumerateEx)( LPDDENUMCALLBACKEX lpCallback, LPVOID lpContext, DWORD Flags );
HRESULT (WINAPI* _DirectInputCreate)( HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT * lplpDirectInput, LPUNKNOWN punkOuter );
HRESULT (WINAPI* _DirectInputCreateEx)( HINSTANCE hinst, DWORD dwVersion, REFIID refID, void ** lplpDirectInput, LPUNKNOWN punkOuter );
HRESULT (WINAPI* _DirectSoundCreate)( LPGUID lpGuid, LPDIRECTSOUND * ppDS, LPUNKNOWN  pUnkOuter );
HRESULT (WINAPI* _DirectSoundEnumerate)( LPDSENUMCALLBACK lpDSEnumCallback, LPVOID lpContext );
//
// Routines in IME Library + Font extern
//
HIMC (WINAPI* _ImmGetContext)( HWND hW );
BOOL (WINAPI* _ImmReleaseContext)  ( HWND hW, HIMC hIMC );
HIMC (WINAPI* _ImmAssociateContext)( HWND hW, HIMC hIMC );
LONG (WINAPI* _ImmGetCompositionString)( HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen );
BOOL (WINAPI* _ImmGetOpenStatus)( HIMC hIMC );
BOOL (WINAPI* _ImmSetOpenStatus)( HIMC hIMC, BOOL flag );
BOOL (WINAPI* _ImmGetConversionStatus)( HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence );
DWORD (WINAPI* _ImmGetCandidateList)( HIMC hIMC, DWORD deIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen );
UINT (WINAPI* _ImmGetVirtualKey)( HWND hW );
BOOL (WINAPI* _ImmNotifyIME)(HIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue);
BOOL (WINAPI* _ImmSetConversionStatus)(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence);
BOOL (WINAPI* _ImmSimulateHotKey)(HWND hWnd, DWORD dwHotKeyID);
BOOL (WINAPI* _ImmIsIME)(HKL hKL);
// *** from Win98DDK version of IMM.H ***
typedef struct tagINPUTCONTEXT {                        
    HWND                hWnd;                           
    BOOL                fOpen;                          
    POINT               ptStatusWndPos;                 
    POINT               ptSoftKbdPos;                   
    DWORD               fdwConversion;                  
    DWORD               fdwSentence;                    
    union   {                                           
        LOGFONTA        A;                              
        LOGFONTW        W;                              
    } lfFont;                                           
    COMPOSITIONFORM     cfCompForm;                     
    CANDIDATEFORM       cfCandForm[4];                  
    HIMCC               hCompStr;                       
    HIMCC               hCandInfo;                      
    HIMCC               hGuideLine;                     
    HIMCC               hPrivate;                       
    DWORD               dwNumMsgBuf;                    
    HIMCC               hMsgBuf;                        
    DWORD               fdwInit;                        
    DWORD               dwReserve[3];                   
} INPUTCONTEXT, *PINPUTCONTEXT, NEAR *NPINPUTCONTEXT, FAR *LPINPUTCONTEXT;  

LPINPUTCONTEXT (WINAPI* _ImmLockIMC)(HIMC hIMC);
BOOL (WINAPI* _ImmUnlockIMC)(HIMC hIMC);
LPVOID (WINAPI* _ImmLockIMCC)(HIMCC hIMCC);
BOOL (WINAPI* _ImmUnlockIMCC)(HIMCC hIMCC);
HWND (WINAPI* _ImmGetDefaultIMEWnd)(HWND hW);
HWND (WINAPI* _ImmGetIMEFileName)(HKL hKL, LPTSTR lpszFileName, UINT uBufLen);

//
// Routines in the PSAPI library
//
BOOL (WINAPI* _EmptyWorkingSet)(HANDLE);
BOOL (WINAPI* _InitializeProcessForWsWatch)(HANDLE);
BOOL (WINAPI* _GetWsChanges)(HANDLE,PPSAPI_WS_WATCH_INFORMATION,DWORD);
DWORD (WINAPI* _GetMappedFileName)(HANDLE,LPVOID,LPTSTR,DWORD);

//
// Jpeg reader functions
//
IJLERR (WINAPI* _ijlInit)( JPEG_CORE_PROPERTIES* jcprops );
IJLERR (WINAPI* _ijlFree)( JPEG_CORE_PROPERTIES* jcprops );
IJLERR (WINAPI* _ijlRead)( JPEG_CORE_PROPERTIES* jcprops, IJLIOTYPE iotype );
IJLERR (WINAPI* _ijlWrite)( JPEG_CORE_PROPERTIES* jcprops, IJLIOTYPE iotype );

//
// ODBC functions - for RAID bug submission
//

SQLRETURN (WINAPI* _SQLAllocHandle)(SQLSMALLINT HandleType,SQLHANDLE InputHandle,SQLHANDLE* OutputHandlePtr);
SQLRETURN (WINAPI* _SQLSetEnvAttr)(SQLHENV EnvironmentHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGER StringLength);
SQLRETURN (WINAPI* _SQLDriverConnect)(SQLHDBC ConnectionHandle,SQLHWND WindowHandle,SQLCHAR* InConnectionString,SQLSMALLINT StringLength1,SQLCHAR* OutConnectionString,SQLSMALLINT BufferLength,SQLSMALLINT* StringLength2Ptr,SQLUSMALLINT DriverCompletion);
SQLRETURN (WINAPI* _SQLDisconnect)(SQLHDBC ConnectionHandle);
SQLRETURN (WINAPI* _SQLFreeHandle)(SQLSMALLINT HandleType,SQLHANDLE Handle);
SQLRETURN (WINAPI* _SQLGetDiagRec)(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLCHAR* Sqlstate,SQLINTEGER* NativeErrorPtr,SQLCHAR* MessageText,SQLSMALLINT BufferLength,SQLSMALLINT* TextLengthPtr);
SQLRETURN (WINAPI* _SQLGetDiagField)(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLSMALLINT DiagIdentifier,SQLPOINTER DiagInfoPtr,SQLSMALLINT BufferLength,SQLSMALLINT* StringLengthPtr);
SQLRETURN (WINAPI* _SQLBindParameter)(SQLHSTMT StatementHandle,SQLUSMALLINT ParameterNumber,SQLSMALLINT InputOutputType,SQLSMALLINT ValueType,SQLSMALLINT ParameterType,SQLUINTEGER ColumnSize,SQLSMALLINT DecimalDigits,SQLPOINTER ParameterValuePtr,SQLINTEGER BufferLength,SQLINTEGER* StrLen_or_IndPtr);
SQLRETURN (WINAPI* _SQLExecDirect)(SQLHSTMT StatementHandle,SQLCHAR* StatementText,SQLINTEGER TextLength);
SQLRETURN (WINAPI* _SQLNumResultCols)(SQLHSTMT StatementHandle,SQLSMALLINT* ColumnCountPtr);
SQLRETURN (WINAPI* _SQLBindCol)(SQLHSTMT StatementHandle,SQLUSMALLINT ColumnNumber,SQLSMALLINT TargetType,SQLPOINTER TargetValuePtr,SQLINTEGER BufferLength,SQLINTEGER *StrLen_or_Ind);
SQLRETURN (WINAPI* _SQLFetch)(SQLHSTMT StatementHandle);
SQLRETURN (WINAPI* _SQLFreeStmt)(SQLHSTMT StatementHandle,SQLUSMALLINT Option);

//
// Winsock functions - for GosView usage only
//

int (WINAPI * _closesocket)( SOCKET s );
int (WINAPI * _recv)( SOCKET s, char *buf, int len, int flags );
int (WINAPI * _recvfrom)( SOCKET s, char FAR * buf, int len, int flags, struct sockaddr FAR * from, int FAR * fromlen);
int (WINAPI * _send)( SOCKET s, char *buf, int len, int flags );
int (WINAPI * _sendto)( SOCKET s,const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen);
SOCKET (WINAPI * _accept)( SOCKET s, struct sockaddr *addr, int *addrlen );
int (WINAPI * _listen)( SOCKET s, int backlog );
int (WINAPI * _bind)( SOCKET s, const struct sockaddr *name, int namelen );
u_long (WINAPI * _htonl)( u_long hostlong );
u_short (WINAPI * _htons)( u_short hostshort );
SOCKET (WINAPI * _socket)( int af, int type, int protocol );
int (WINAPI * _gethostname)(char FAR * name, int namelen );
struct hostent FAR * (WINAPI * _gethostbyname)(const char FAR * name);
u_long (WINAPI * _ntohl)(u_long netlong);
unsigned long (WINAPI * _inet_addr)(const char FAR * cp);
int (WINAPI * _WSACleanup )(void);
int (WINAPI * _WSAStartup)( WORD wVersionRequested, LPWSADATA lpWSAData );
int (WINAPI * _WSAGetLastError)(void);
struct servent * (WINAPI * _getservbyname)(char *name, char *proto );


//
//
//
extern DWORD gDirectX7;
extern bool gNoBlade;
HWND (WINAPI* _CallmyHelp)( HWND hWindow, HINSTANCE hInst, bool Window, DWORD HelpItem );
void (WINAPI* _FreeHlpLib)();
DWORD (WINAPI* _AMGetErrorText)( HRESULT hr, TCHAR *pBuffer, DWORD MaxLen );
//
// DirectX version numbres
//
DWORD DXdwVersion, DXdwRevision;
//
// Path where blade was loaded from
//
char BladePath[MAX_PATH];
extern bool OnNetwork;

//
// A version checker
//
extern char * GetDLLInfo(char*, int);

//
// Load all libraries GOS depends upon
//
void InitLibraries()
{
//
// Loading libraries resets math precision, ignore precision and exceptions
//
	gos_MathExceptions( 0, 0 );
//
// Enable OLE
//
	CoInitialize( NULL );
//
// Check DirectX version, first find dsetup.dll
//
	char tempPath[MAX_PATH];
	strcpy( tempPath, AssetsDirectory2 );
	strcat( tempPath, "\\dsetup.dll" );
	HINSTANCE LibDSetup = LoadLibrary( tempPath );
	if ( !LibDSetup )
	{
	    strcpy( tempPath, AssetsDirectory1 );
	    strcat( tempPath, "\\assets\\binaries\\dsetup.dll" );

		LibDSetup = LoadLibrary(tempPath);
		if (!LibDSetup)
		{
			char Path[MAX_PATH*2];
			sprintf( Path, gos_GetResourceString(gLanguageDLL, GOS_REQUIRES_DSETUP), AssetsDirectory1,AssetsDirectory2 );
			MessageBox( hWindow, Path, ApplicationName, MB_OK | MB_ICONEXCLAMATION );
			status=AfterExit;
			exit(1);
		}
	}
//
// Now find the version number API in DSETUP.DLL
//
	int (WINAPI* _DirectXSetupGetVersion)(DWORD*,DWORD*) = (int(WINAPI*)(DWORD*,DWORD*)) GetProcAddress( LibDSetup, "DirectXSetupGetVersion" );
	if( !_DirectXSetupGetVersion || 0==_DirectXSetupGetVersion(&DXdwVersion,&DXdwRevision))
	{
		DXdwVersion=0;
		DXdwRevision=0;
	}
//
// Unload dsetup.dll - no longer needed
//
	FreeLibrary( LibDSetup );
//
// Do I have DirectX8 installed?
//
	if( gDirectX7 )
	{
		if( !WindowsNT && (LOWORD(DXdwVersion)<7 || (LOWORD(DXdwVersion)==7 && DXdwRevision<716)) )
		{
			char Buffer[128];
			sprintf( Buffer, "Requires DirectX 7.0a or later, found %s",GetDirectXVersion() );
			MessageBox( hWindow, Buffer, ApplicationName, MB_OK | MB_ICONEXCLAMATION );
			status=AfterExit;
			exit(1);
		}
	}
	else
	{
		if( LOWORD(DXdwVersion)<8 || (LOWORD(DXdwVersion)==8 && DXdwRevision<400) )
		{
			char Buffer[128];
			sprintf( Buffer, gos_GetResourceString(gLanguageDLL, GOS_REQUIRES_DX7A),GetDirectXVersion() );
			MessageBox( hWindow, Buffer, ApplicationName, MB_OK | MB_ICONEXCLAMATION );
			status=AfterExit;
			exit(1);
		}
	}
//
// Blade is required as it is the 'fallback' rasterizer if there is a problem with DirectX
//
	if( gNoBlade )
	{
		LibBlade = LoadLibrary( "ddraw.dll" );

		if( !LibBlade )
		{
			char Path[MAX_PATH*2];
			sprintf( Path, gos_GetResourceString(gLanguageDLL, GOS_REQUIRES_DDRAW) );
			MessageBox( hWindow, Path, ApplicationName, MB_OK | MB_ICONEXCLAMATION );
			status=AfterExit;
			exit(1);
		}

		_DirectDrawCreateEx = (HRESULT (WINAPI*)( GUID* lpGUID, void** lplpDD, REFIID iid, IUnknown* pUnkOuter ))GetProcAddress( LibBlade, "DirectDrawCreateEx" ); 
		_DirectDrawEnumerate = (HRESULT (WINAPI*)( LPDDENUMCALLBACK lpCallback, LPVOID lpContext )) GetProcAddress( LibBlade, "DirectDrawEnumerateA" );
		_DirectDrawEnumerateEx = (HRESULT (WINAPI*)( LPDDENUMCALLBACKEX lpCallback, LPVOID lpContext, DWORD Flags )) GetProcAddress( LibBlade, "DirectDrawEnumerateExA" );
		g_pGetDXVB = 0;

		if( !_DirectDrawCreateEx || !_DirectDrawEnumerate || !_DirectDrawEnumerate )
		{
			MessageBox( hWindow, "Cannot find ddraw functions", ApplicationName, MB_OK | MB_ICONEXCLAMATION );
			status=AfterExit;
			exit(1);
		}
	}
	else
	{
		bool GoodBlade=0, DebugBlade=1;
		strcpy( BladePath, AssetsDirectory2 );
		strcat( BladePath, "\\bladed.dll" );
		LibBlade = LoadLibrary( BladePath );
		if ( !LibBlade )
		{
			strcpy( BladePath, AssetsDirectory1 );
			strcat( BladePath, "\\assets\\binaries\\bladed.dll" );

			LibBlade = LoadLibrary( BladePath );
			if( !LibBlade )
			{
				if( strlen(AssetsDirectory2)>=16 && 0==strnicmp( &AssetsDirectory2[strlen(AssetsDirectory2)-16], "\\assets\\binaries", 16) )
				{
					GoodBlade=1;
				}
				DebugBlade=0;
				strcpy( BladePath, AssetsDirectory2 );
				strcat( BladePath, "\\blade.dll" );
				LibBlade = LoadLibrary( BladePath );
				if ( !LibBlade )
				{
					strcpy( BladePath, AssetsDirectory1 );
					strcat( BladePath, "\\assets\\binaries\\blade.dll" );
					LibBlade = LoadLibrary( BladePath );
					GoodBlade=1;
					if( !LibBlade )
					{
						char Path[MAX_PATH*2];
						sprintf( Path, gos_GetResourceString(gLanguageDLL, GOS_MISSING_BLADE),AssetsDirectory1,AssetsDirectory2 );
						MessageBox( hWindow, Path, ApplicationName, MB_OK | MB_ICONEXCLAMATION );
						status=AfterExit;
						exit(1);
					}
				}
			}
		}
//
// Warn if debug version of blade used or blade.dll came from the root directory and an assets\binaries directory existed
//
		#ifdef LAB_ONLY
			if( !GoodBlade && 0!=stricmp( ApplicationName, "Test Blade" ) )
			{
				/* by jcem - if( DebugBlade )
					PAUSE(( "Warning, '%s' was used",BladePath ));
				else
				{	
					if( gos_DoesFileExist( "assets\\binaries" ) )
						PAUSE(( "Warning, '%s' was used",BladePath ));
				}*/
			}
		#endif
//
// Find Blade functions
//
		_DirectDrawCreateEx = (HRESULT (WINAPI*)( GUID* lpGUID, void** lplpDD, REFIID iid, IUnknown* pUnkOuter ))GetProcAddress( LibBlade, "DirectDrawCreateEx" ); 
		_DirectDrawEnumerate = (HRESULT (WINAPI*)( LPDDENUMCALLBACK lpCallback, LPVOID lpContext )) GetProcAddress( LibBlade, "DirectDrawEnumerateA" );
		_DirectDrawEnumerateEx = (HRESULT (WINAPI*)( LPDDENUMCALLBACKEX lpCallback, LPVOID lpContext, DWORD Flags )) GetProcAddress( LibBlade, "DirectDrawEnumerateExA" );
		g_pGetDXVB = (IDirect3DVertexBuffer7 * (WINAPI *)(IDirect3DVertexBuffer7 *, IDirect3DDevice7 *))GetProcAddress(LibBlade, "GetDXVB");

		if( !_DirectDrawCreateEx || !_DirectDrawEnumerate || !_DirectDrawEnumerate || !g_pGetDXVB)
		{
			MessageBox( hWindow, "Cannot find Blade functions", ApplicationName, MB_OK | MB_ICONEXCLAMATION );
			status=AfterExit;
			exit(1);
		}
	}
//
// Now get functions for ijl10.dll   (This is optional)
//
	strcpy( tempPath, AssetsDirectory2 );
	strcat( tempPath, "\\ijl10.dll" );
	LibJpeg = LoadLibrary( tempPath );
	if ( !LibJpeg )
	{
	    strcpy( tempPath, AssetsDirectory1 );
	    strcat( tempPath, "\\assets\\binaries\\ijl10.dll" );
		LibJpeg = LoadLibrary(tempPath);
	}
	if( LibJpeg )
	{
		_ijlInit = (IJLERR (WINAPI*)( JPEG_CORE_PROPERTIES* jcprops ))GetProcAddress( LibJpeg, "ijlInit" );
		_ijlFree = (IJLERR (WINAPI*)( JPEG_CORE_PROPERTIES* jcprops ))GetProcAddress( LibJpeg, "ijlFree" );
		_ijlRead = (IJLERR (WINAPI*)( JPEG_CORE_PROPERTIES* jcprops, IJLIOTYPE iotype ))GetProcAddress( LibJpeg, "ijlRead" );
		_ijlWrite = (IJLERR (WINAPI*)( JPEG_CORE_PROPERTIES* jcprops, IJLIOTYPE iotype ))GetProcAddress( LibJpeg, "ijlWrite" );
	}
//
// Now get functions for DirectSound
//
	LibDsound = LoadLibrary( "dsound.dll" );

	if( !LibDsound )
	{
		MessageBox( hWindow, gos_GetResourceString(gLanguageDLL, GOS_REQUIRES_DSOUND), ApplicationName, MB_OK | MB_ICONEXCLAMATION );
		status=AfterExit;
		exit(1);
	}

	_DirectSoundCreate=(HRESULT (WINAPI*)( LPGUID lpGuid, LPDIRECTSOUND * ppDS, LPUNKNOWN  pUnkOuter ))GetProcAddress( LibDsound, "DirectSoundCreate" );
	_DirectSoundEnumerate=(HRESULT (WINAPI*)( LPDSENUMCALLBACK lpDSEnumCallback, LPVOID lpContext ))GetProcAddress( LibDsound, "DirectSoundEnumerateA" );

	if( !_DirectSoundCreate && !_DirectSoundEnumerate )
	{
		MessageBox( hWindow, "Cannot find DirectSound functions", ApplicationName, MB_OK | MB_ICONEXCLAMATION );
		status=AfterExit;
		exit(1);
	}
//
// Now get functions for DirectInput
//
	LibDinput = LoadLibrary( "dinput.dll" );

	if( !LibDinput )
	{
		MessageBox( hWindow, gos_GetResourceString(gLanguageDLL, GOS_REQUIRES_DINPUT), ApplicationName, MB_OK | MB_ICONEXCLAMATION );
		status=AfterExit;
		exit(1);
	}

	_DirectInputCreateEx = (HRESULT (WINAPI*)( HINSTANCE hinst, DWORD dwVersion, REFIID refID, LPVOID* lplpDirectInput, LPUNKNOWN punkOuter ))GetProcAddress( LibDinput, "DirectInputCreateEx" );
	if( !_DirectInputCreateEx )
	{
		MessageBox( hWindow, "Cannot find DirectInput functions", ApplicationName, MB_OK | MB_ICONEXCLAMATION );
		status=AfterExit;
		exit(1);
	}
//
// Now get functions for the IME
//
	LibIME = LoadLibrary( "imm32.dll" );

	if( LibIME )
	{
		_ImmGetContext =			(HIMC  (WINAPI*)(HWND hW)) GetProcAddress(LibIME, "ImmGetContext");
		_ImmReleaseContext =		(BOOL  (WINAPI*)(HWND hW, HIMC hImc)) GetProcAddress(LibIME, "ImmReleaseContext");
		_ImmAssociateContext =		(HIMC  (WINAPI*)(HWND hW, HIMC hImc)) GetProcAddress(LibIME, "ImmAssociateContext");
		_ImmGetCompositionString =	(LONG  (WINAPI*)(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen )) GetProcAddress(LibIME, "ImmGetCompositionStringA");
		_ImmGetOpenStatus =			(BOOL  (WINAPI*)(HIMC hIMC)) GetProcAddress(LibIME, "ImmGetOpenStatus");
		_ImmSetOpenStatus =			(BOOL  (WINAPI*)(HIMC hIMC, BOOL flag)) GetProcAddress(LibIME, "ImmSetOpenStatus");
		_ImmGetConversionStatus =	(BOOL  (WINAPI*)(HIMC hIMC, LPDWORD lpfdwConversion, LPDWORD lpfdwSentence )) GetProcAddress(LibIME, "ImmGetConversionStatus");
		_ImmGetCandidateList=		(DWORD (WINAPI*)(HIMC hIMC, DWORD deIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen )) GetProcAddress(LibIME, "ImmGetCandidateListA");
		_ImmGetVirtualKey =			(UINT  (WINAPI*)(HWND hW )) GetProcAddress(LibIME, "ImmGetVirtualKey");
		_ImmLockIMC =               (LPINPUTCONTEXT (WINAPI*)(HIMC hIMC)) GetProcAddress(LibIME, "ImmLockIMC");
		_ImmUnlockIMCC =            (BOOL (WINAPI*)(HIMCC hIMC)) GetProcAddress(LibIME, "ImmUnlockIMC");
		_ImmLockIMCC =              (LPVOID (WINAPI*)(HIMCC hIMCC)) GetProcAddress(LibIME, "ImmLockIMCC");
		_ImmUnlockIMC =             (BOOL (WINAPI*)(HIMC hIMCC)) GetProcAddress(LibIME, "ImmUnlockIMCC");
		_ImmGetDefaultIMEWnd =      (HWND (WINAPI*)(HWND hW)) GetProcAddress(LibIME, "ImmGetDefaultIMEWnd");
		_ImmGetIMEFileName =        (HWND (WINAPI*)(HKL hKL, LPTSTR lpszFileName, UINT uBufLen)) GetProcAddress(LibIME, "ImmGetIMEFileNameA");
		_ImmNotifyIME =				(BOOL (WINAPI*)(HIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue)) GetProcAddress(LibIME, "ImmNotifyIME");
		_ImmSetConversionStatus =	(BOOL (WINAPI*)(HIMC hIMC, DWORD fdwConversion, DWORD fdwSentence)) GetProcAddress(LibIME, "ImmSetConversionStatus");
		_ImmSimulateHotKey =		(BOOL (WINAPI*)(HWND hWnd, DWORD dwHotKeyID)) GetProcAddress(LibIME, "ImmSimulateHotKey");
		_ImmIsIME =					(BOOL (WINAPI*)(HKL)) GetProcAddress(LibIME, "ImmIsIME");
	}
//
// Now get functions from the PSAPI library (Win2K only)
//
	#ifdef LAB_ONLY
	if( WindowsNT )
		LibPSAPI = LoadLibrary( "psapi.dll" );
	else
	#endif
		LibPSAPI = 0;

	if( LibPSAPI )
	{
		_EmptyWorkingSet =				(BOOL  (WINAPI*)(HANDLE)) GetProcAddress(LibPSAPI, "EmptyWorkingSet");
		_InitializeProcessForWsWatch =	(BOOL  (WINAPI*)(HANDLE)) GetProcAddress(LibPSAPI, "InitializeProcessForWsWatch");
		_GetWsChanges =					(BOOL  (WINAPI*)(HANDLE, PPSAPI_WS_WATCH_INFORMATION,DWORD)) GetProcAddress(LibPSAPI, "GetWsChanges");
		_GetMappedFileName =			(DWORD (WINAPI*)(HANDLE,LPVOID,LPTSTR,DWORD)) GetProcAddress(LibPSAPI, "GetMappedFileNameA");;
	}

//
// Get Winsock
//
	if( Environment.NetworkGame || gEnableGosView )
	{
		LibWinSock = LoadLibrary( "ws2_32.dll" );
		if( !LibWinSock )
			LibWinSock = LoadLibrary( "wsock32.dll" );
		if( LibWinSock )
		{
			_closesocket = (int (WINAPI *)( SOCKET )) GetProcAddress(LibWinSock, "closesocket");
			_recv = (int (WINAPI *)( SOCKET s, char *buf, int len, int flags )) GetProcAddress(LibWinSock, "recv");
			_recvfrom = (int (WINAPI *) ( SOCKET s, char FAR * buf, int len, int flags, struct sockaddr FAR * from, int FAR * fromlen)) GetProcAddress(LibWinSock, "recvfrom");
			_send = (int (WINAPI *)( SOCKET s, char *buf, int len, int flags )) GetProcAddress(LibWinSock, "send");
			_sendto = (int (WINAPI *)( SOCKET s,const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen)) GetProcAddress(LibWinSock, "sendto");
			_accept = (SOCKET (WINAPI *)( SOCKET s, struct sockaddr *addr, int *addrlen )) GetProcAddress(LibWinSock, "accept");
			_listen = (int (WINAPI *)( SOCKET s, int backlog )) GetProcAddress(LibWinSock, "listen");
			_bind = (int (WINAPI *)( SOCKET s, const struct sockaddr *name, int namelen )) GetProcAddress(LibWinSock, "bind");
			_htonl = (u_long (WINAPI *)( u_long hostlong )) GetProcAddress(LibWinSock, "htonl");
			_htons = (u_short (WINAPI *)( u_short hostshort )) GetProcAddress(LibWinSock, "htons");
			_socket = (SOCKET (WINAPI *)( int af, int type, int protocol )) GetProcAddress(LibWinSock, "socket");
			_gethostname = (int (WINAPI *)(char FAR * name, int namelen )) GetProcAddress(LibWinSock, "gethostname");
			_gethostbyname = (struct hostent FAR * (WINAPI *) (const char FAR * name)) GetProcAddress(LibWinSock, "gethostbyname");
			_ntohl = (u_long (WINAPI *)(u_long netlong)) GetProcAddress(LibWinSock, "ntohl");
			_inet_addr = (unsigned long (WINAPI *)(const char FAR * cp)) GetProcAddress(LibWinSock, "inet_addr");
			_WSACleanup = (int (WINAPI *)( void )) GetProcAddress(LibWinSock, "WSACleanup");
			_WSAStartup = (int (WINAPI *)( WORD wVersionRequested, LPWSADATA lpWSAData )) GetProcAddress(LibWinSock, "WSAStartup");
			_WSAGetLastError = (int (WINAPI *)( void )) GetProcAddress(LibWinSock, "WSAGetLastError");
			_getservbyname = ( struct servent * (WINAPI *) ( char *name, char *proto )) GetProcAddress(LibWinSock, "getservbyname");
		}
	}
//
// Preload other DLL's for video and audio compression
//
	LibAmstream=LoadLibrary("amstream.dll");
	LibQuartz=LoadLibrary("quartz.dll");
	LibMSADP32=LoadLibrary("MSADP32.acm");

	if( !LibAmstream || !LibQuartz )
	{
		MessageBox( hWindow, gos_GetResourceString(gLanguageDLL, GOS_REQUIRES_DXMEDIA), ApplicationName, MB_OK | MB_ICONEXCLAMATION );
		status=AfterExit;
		exit(1);
	}
	if( !LibMSADP32 )
	{
		MessageBox( hWindow, gos_GetResourceString(gLanguageDLL, GOS_REQUIRES_MSADPCM), ApplicationName, MB_OK | MB_ICONEXCLAMATION );
		status=AfterExit;
		exit(1);
	}
	if( !LibAmstream )
	{
		if (strncmp(GetDLLInfo("amstream.dll",0), "amstream.dll  - Version 6.01",strlen("amstream.dll  - Version 6.01")) < 0 )
		{
			MessageBox( hWindow, gos_GetResourceString(gLanguageDLL, GOS_WRONG_DXMEDIA), ApplicationName, MB_OK | MB_ICONEXCLAMATION );
			status=AfterExit;
			exit(1);
		}
	}
//
// Find the AMGetErrorText function from quartz.dll
//
	_AMGetErrorText = (DWORD (WINAPI*)( HRESULT hr, TCHAR *pBuffer, DWORD MaxLen ))GetProcAddress( LibQuartz, "AMGetErrorTextA" );
	if( !_AMGetErrorText )
	{
		MessageBox( hWindow, "Cannot find DirectShow functions", ApplicationName, MB_OK | MB_ICONEXCLAMATION );
		status=AfterExit;
		exit(1);
	}
//
// Is the machine a Windows 98 machine and on a Pentium III?
//
	#ifdef LAB_ONLY
		OSVERSIONINFO osinfo;
		osinfo.dwOSVersionInfoSize=sizeof(osinfo);
		GetVersionEx( &osinfo );
		if( !WindowsNT && HasKatmai && 1998==(osinfo.dwBuildNumber&0xffff) )
		{
			char temp[MAX_PATH];
			GetSystemDirectory( temp, MAX_PATH );
			strcat(	temp, "\\vmm32\\vmcpd.vxd" );
			if( !gos_DoesFileExist(temp) )
			{
				char Buffer[256];
				strcpy( Buffer, "You need to install \"vmcpd.vxd\" This can be found in DirectX 7.0 SDK \"DXF\\extras\\win98 piii dbg\" folder." );
				if( OnNetwork )
					strcat( Buffer, "\n\n(Microsoft Internal) - This can be found at \\\\dxrelease\\release\\dx7\\DXF\\extras\\win98 piii dbg" );
				MessageBox( hWindow, Buffer, ApplicationName, MB_OK | MB_ICONEXCLAMATION);
			}
		}
	#endif
//
// Get ODBC functions - for RAID bug submission
//
#ifdef LAB_ONLY
	LibODBC = LoadLibrary("odbc32.dll");

	_SQLAllocHandle		= (SQLRETURN (WINAPI*)(SQLSMALLINT HandleType,SQLHANDLE InputHandle,SQLHANDLE* OutputHandlePtr)) GetProcAddress(LibODBC,"SQLAllocHandle");
	_SQLSetEnvAttr		= (SQLRETURN (WINAPI*)(SQLHENV EnvironmentHandle,SQLINTEGER Attribute,SQLPOINTER ValuePtr,SQLINTEGER StringLength)) GetProcAddress(LibODBC,"SQLSetEnvAttr");
	_SQLDriverConnect	= (SQLRETURN (WINAPI*)(SQLHDBC ConnectionHandle,SQLHWND WindowHandle,SQLCHAR* InConnectionString,SQLSMALLINT StringLength1,SQLCHAR* OutConnectionString,SQLSMALLINT BufferLength,SQLSMALLINT* StringLength2Ptr,SQLUSMALLINT DriverCompletion)) GetProcAddress(LibODBC,"SQLDriverConnect");
	_SQLDisconnect		= (SQLRETURN (WINAPI*)(SQLHDBC ConnectionHandle)) GetProcAddress(LibODBC,"SQLDisconnect");
	_SQLFreeHandle		= (SQLRETURN (WINAPI*)(SQLSMALLINT HandleType,SQLHANDLE Handle)) GetProcAddress(LibODBC,"SQLFreeHandle");
	_SQLGetDiagRec		= (SQLRETURN (WINAPI*)(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLCHAR* Sqlstate,SQLINTEGER* NativeErrorPtr,SQLCHAR* MessageText,SQLSMALLINT BufferLength,SQLSMALLINT* TextLengthPtr)) GetProcAddress(LibODBC,"SQLGetDiagRec");
	_SQLGetDiagField	= (SQLRETURN (WINAPI*)(SQLSMALLINT HandleType,SQLHANDLE Handle,SQLSMALLINT RecNumber,SQLSMALLINT DiagIdentifier,SQLPOINTER DiagInfoPtr,SQLSMALLINT BufferLength,SQLSMALLINT* StringLengthPtr)) GetProcAddress(LibODBC,"SQLGetDiagField");
	_SQLBindParameter	= (SQLRETURN (WINAPI*)(SQLHSTMT StatementHandle,SQLUSMALLINT ParameterNumber,SQLSMALLINT InputOutputType,SQLSMALLINT ValueType,SQLSMALLINT ParameterType,SQLUINTEGER ColumnSize,SQLSMALLINT DecimalDigits,SQLPOINTER ParameterValuePtr,SQLINTEGER BufferLength,SQLINTEGER* StrLen_or_IndPtr)) GetProcAddress(LibODBC,"SQLBindParameter");
	_SQLExecDirect		= (SQLRETURN (WINAPI*)(SQLHSTMT StatementHandle,SQLCHAR* StatementText,SQLINTEGER TextLength)) GetProcAddress(LibODBC,"SQLExecDirect");
	_SQLNumResultCols   = (SQLRETURN (WINAPI*)(SQLHSTMT StatementHandle,SQLSMALLINT* ColumnCountPtr)) GetProcAddress(LibODBC,"SQLNumResultCols");
	_SQLBindCol			= (SQLRETURN (WINAPI*)(SQLHSTMT StatementHandle,SQLUSMALLINT ColumnNumber,SQLSMALLINT TargetType,SQLPOINTER TargetValuePtr,SQLINTEGER BufferLength,SQLINTEGER *StrLen_or_Ind)) GetProcAddress(LibODBC,"SQLBindCol");
	_SQLFetch			= (SQLRETURN (WINAPI*)(SQLHSTMT StatementHandle)) GetProcAddress(LibODBC,"SQLFetch");
	_SQLFreeStmt		= (SQLRETURN (WINAPI*)(SQLHSTMT StatementHandle,SQLUSMALLINT Option)) GetProcAddress(LibODBC,"SQLFreeStmt");
#endif
//
// All critical libraries present, allow math exceptions again
//
	gos_MathExceptions(1,0);
}


//
// Unload any libraries GOS loaded
//
void DestroyLibraries()
{
	if( LibJpeg )
	{
		FreeLibrary( LibJpeg );
		LibJpeg=0;
	}
	if( LibMSADP32 )
	{
		FreeLibrary( LibMSADP32 );
		LibMSADP32=0;
	}
	if( LibQuartz )
	{
		FreeLibrary( LibQuartz );
		LibQuartz=0;
	}
	if( LibAmstream )
	{
		FreeLibrary( LibAmstream );
		LibAmstream=0;
	}
	if( LibBlade )
	{
		FreeLibrary( LibBlade );
		LibBlade=0;
	}
	if( LibDinput )
	{
		FreeLibrary( LibDinput );
		LibDinput=0;
	}
	if( LibDsound )
	{
		FreeLibrary( LibDsound );
		LibDsound=0;
	}
	if( LibIME )
	{
		FreeLibrary( LibIME );
		LibIME=0;
	}
	if( LibPSAPI )
	{
		FreeLibrary( LibPSAPI );
		LibPSAPI=0;
	}
	if( LibWinSock )
	{
		FreeLibrary( LibWinSock );
		LibWinSock=0;
	}
	if( LibODBC )
	{
		FreeLibrary( LibODBC );
		LibODBC=0;
	}

//
// Shutdown OLE
//
	CoUninitialize();
}


//
// Returns a string describing the DirectX version
//
char* GetDirectXVersion()
{
	static char Buffer[64];
	sprintf( Buffer, "%d.%02d.%02d.%04d",LOWORD(DXdwVersion),HIWORD(DXdwVersion),HIWORD(DXdwRevision),LOWORD(DXdwRevision) );
	if( DXdwVersion==0x40005 && DXdwRevision==0x9b )
		strcat( Buffer, " (DirectX 5.0)" );
	if( DXdwVersion==0x40005 && DXdwRevision==0x10640 )
		strcat( Buffer, " (DirectX 5.2)" );
	if( DXdwVersion==0x40006 && DXdwRevision==0x13e )
		strcat( Buffer, " (DirectX 6.0)" );
	if( DXdwVersion==0x40006 && DXdwRevision==0x201b4 )
		strcat( Buffer, " (DirectX 6.1)" );
	if( DXdwVersion==0x40006 && DXdwRevision==0x30206 )
		strcat( Buffer, " (DirectX 6.2)" );
	if( DXdwVersion==0x40007 && DXdwRevision==0xa6 )
		strcat( Buffer, " (DirectX 7 Beta 1)" );
	if( DXdwVersion==0x40007 && DXdwRevision==0xc9 )
		strcat( Buffer, " (DirectX 7 Beta 2)" );
	if( DXdwVersion==0x40007 && DXdwRevision==0xe0 )
		strcat( Buffer, " (DirectX 7 Build 224)" );
	if( DXdwVersion==0x40007 && DXdwRevision==242 )
		strcat( Buffer, " (DirectX 7 RC3)" );
	if( DXdwVersion==0x40007 && DXdwRevision==700 )
		strcat( Buffer, " (DirectX 7.0)" );
	if( DXdwVersion==0x40007 && DXdwRevision==716 )
		strcat( Buffer, " (DirectX 7.0a)" );
	if( DXdwVersion==0x40007 && DXdwRevision==0x1bb8 )
		strcat( Buffer, " (DirectX 7.1)" );
	if( DXdwVersion==0x40008 && DXdwRevision==0xb7 )
		strcat( Buffer, " (DirectX 8 RC0)" );
	if( DXdwVersion==0x40008 && DXdwRevision==219 )
		strcat( Buffer, " (DirectX 8 RC1)" );
	if( DXdwVersion==0x40008 && DXdwRevision==400 )
	{
		strcat( Buffer, " (DirectX 8.0)" );
//
// For current version detect DEBUG DLL's by size of DDRAW.DLL file
//
		char temp[MAX_PATH];
		GetSystemDirectory( temp, 256 );
		strcat(	temp, "\\ddraw.dll" );
		if( 464896==gos_FileSize(temp) || 979456==gos_FileSize(temp) )
			strcat( Buffer, " DEBUG DLL's" );
	}
	return Buffer;
}



