#include "pch.hpp"
//==========================================================================//
// File:	 Registry.cpp													//
// Project:  GameOS					                                        //
// Contents: Registry routines												// 
//--------------------------------------------------------------------------//
// Date      Who    Modification                                            //
// 12/11/97  JTR    Created													//
//																			//
//--------------------------------------------------------------------------//
// Copyright (C) 1999 Microsoft Corp.						                 //
// All Rights reserved worldwide                                            //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL              //
//==========================================================================//
#include "Registry.hpp"
#include "ErrorHandler.hpp"
#include "Globals.hpp"
#include "Windows.hpp"
#include "Debugger.hpp"
#include "ControlManager.hpp"
#include "Profiler.hpp"
#include "Perf.h"

extern DWORD gLanguageDLL;
//
// Complete registry path used for game application
//
char RegistryKey[256]="";
DWORD UpdatedExe;					// Has the exe been updated since last run?

extern DWORD gEnableParallel;


//
// Load defult shell settings from the registry
//
void RegistryManagerInstall()
{
	HKEY hKey;
	DWORD SizeInt=sizeof(int);
	FILETIME ft;
	int VersionCheck=0;
//
	SPEW(( GROUP_GAMEOS, "RegistryManagerInstall()" ));
//
// Check if GameOS shut down badly before
//
	#ifdef LAB_ONLY
	if( Platform!=Platform_DLL && !Environment.allowMultipleApps )
	{
		SizeInt=sizeof(int);
		SYSTEMTIME st;
		__int64 ft64;
//
// If time saved in registry = time machine was booted, GameOS crashed (registry cleared when good exit)
//
		GetLocalTime( &st );
		SystemTimeToFileTime( &st, (FILETIME*)&ft64 );
		ft64=ft64-((__int64)timeGetTime()*(__int64)10000);
		FileTimeToSystemTime( (FILETIME*)&ft64, &st );
		st.wSecond=0;
		st.wMilliseconds=0;
		SystemTimeToFileTime( &st, (FILETIME*)&ft64 );
		DWORD temp1=(DWORD)(ft64&65535),temp=0;
		if( temp1==0 )
			temp1++;
		gos_LoadDataFromRegistry( "BadShutDown", (DWORD*)&temp, &SizeInt );				// Read in bad shutdown flag
		if( temp1==temp && !WindowsNT )
		{
			PAUSE(( gos_GetResourceString(gLanguageDLL, GOS_BAD_SHUTDOWN) ));
		}
		gos_SaveDataToRegistry( "BadShutDown",&temp1,sizeof(int) );				// Set bad shutdown flag
	}
	#endif
//
// Check a version number if present, if not valid, destroy old game data
//
	if( Environment.version && *Environment.version!=0 && 0==Environment.dontClearRegistry )
	{
		LONG result=RegOpenKey(HKEY_CURRENT_USER,RegistryKey,&hKey);

		if( ERROR_SUCCESS==result )
		{
			result=RegQueryValueEx(hKey,Environment.version,NULL,NULL,(BYTE*)&VersionCheck,&SizeInt );
			RegCloseKey(hKey);
			if( ERROR_SUCCESS!=result || VersionCheck!=1 )
				RegDeleteKey(HKEY_CURRENT_USER,RegistryKey);				
		}
	}
//
// Check if .exe time/date has changed - if so reset some variables
//
	HANDLE file= CreateFile( _pgmptr, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, 0, NULL );
	GetFileTime( file, 0,0,&ft );			// Get last write time
	CloseHandle( file );

	DWORD exedate=0;
	SizeInt=sizeof(int);
	gos_LoadDataFromRegistry( "ExeDate", &exedate, &SizeInt );

	UpdatedExe = ft.dwLowDateTime!=exedate;	// Has the exe been updated since last run?
//
// Get window start position
//
	WindowStartX=CW_USEDEFAULT;
	SizeInt=sizeof(int);
	gos_LoadDataFromRegistry( "Window_X", &WindowStartX, &SizeInt );
	SizeInt=sizeof(int);
	WindowStartY=CW_USEDEFAULT;
	gos_LoadDataFromRegistry( "Window_Y", &WindowStartY, &SizeInt );

	PerfCounterSelected=-1;
	gos_LoadDataFromRegistry( "PerfCounter", &PerfCounterSelected, &SizeInt );
	if( -1!=PerfCounterSelected )
	{
		SetPerformanceMonitor( PerfCounterSelected );
		NewPerformanceRegister=1;
	}

	if( WindowStartX>GetDeviceCaps(DesktopDC,HORZRES) )
		WindowStartX=CW_USEDEFAULT;
	if( WindowStartY>GetDeviceCaps(DesktopDC,VERTRES) )
		WindowStartY=CW_USEDEFAULT;
//
// Get ^Break Debugger settings - reset when .exe file changed
//
	#ifdef LAB_ONLY
	DWORD temp=1+(1<<4)+(1<<5)+(1<<9)+(1<<12);					// Default gGameLogicActive, Parallel, NoGameOSStats, ShowLFControls, ShowAverage;		
	memset( ProfileFlags, 0, sizeof(ProfileFlags) );
	ProfileFlags[0]=1;									// Default 'FrameGraph'
	SizeInt=32;
	gos_LoadDataFromRegistry( "DebuggerOptions", &temp, &SizeInt );
	if( !UpdatedExe )
	{
		SizeInt=32;
		gos_LoadDataFromRegistry( "DebuggerGraphs", &ProfileFlags, &SizeInt );
		SizeInt=32;
		gos_LoadDataFromRegistry( "DebuggerGraphMode", &GraphMode, &SizeInt );
		SizeInt=32;
		gos_LoadDataFromRegistry( "DebuggerGraphInfo", &ShowColorInfo, &SizeInt );
	}

	gGameLogicActive=temp&1;
	gControlsActive=(temp>>1)&1;
	gStopSystem=(temp>>2)&1;
	gFrameGraph=(temp>>3)&1;
	gEnableParallel=(temp>>4)&1;
	NoDebuggerStats=(temp>>5)&1;
	gShowGraphsAsTime=(temp>>6)&1;
	gShowGraphBackground=(temp>>8)&1;
	gShowLFControls=(temp>>9)&1;
	gNoGraph=(temp>>10)&1;
	gTextureOverrun=(temp>>11)&1;
	gShowAverage=(temp>>12)&1;
	#endif
}






//
// Save any GameOS settings into the registry
//
void RegistryManagerUninstall()
{
//
// Save window position
//
	gos_SaveDataToRegistry( "Window_X",&WindowStartX,sizeof(int) );
	gos_SaveDataToRegistry( "Window_Y",&WindowStartY,sizeof(int) );
	gos_SaveDataToRegistry( "PerfCounter",&PerfCounterSelected,sizeof(int) );
//
// Clear bad shutdown flag
//
	#ifdef LAB_ONLY
	DWORD temp=0;
	gos_SaveDataToRegistry( "BadShutDown",&temp,sizeof(int) );
//
// Save debugger settings to registry
//
	temp+=gGameLogicActive ? 1 : 0;
	temp+=gControlsActive ? 1<<1 : 0;
	temp+=gStopSystem ? 1<<2 : 0;
	temp+=gFrameGraph ? 1<<3 : 0;
	temp+=gEnableParallel ? 1<<4 : 0;
	temp+=NoDebuggerStats ? 1<<5 : 0;
	temp+=gShowGraphsAsTime ? 1<<6 : 0;
	temp+=gShowGraphBackground ? 1<<8 : 0;
	temp+=gShowLFControls ? 1<<9 : 0;
	temp+=gNoGraph ? 1<<10 : 0;
	temp+=gTextureOverrun ? 1<<11 : 0;
	temp+=gShowAverage ? 1<<12 : 0;
	gos_SaveDataToRegistry( "DebuggerOptions",&temp,sizeof(int) );
//
// Save graphs activated
//
	memset( ProfileFlags, 0, sizeof(ProfileFlags) );
	Stat* pStat=pStatistics;
	DWORD count=0;
	while( pStat )
	{
		if( 0==(pStat->Flags&Stat_Format) )
		{
			if( pStat->Flags&Stat_Graph )
			{
				ProfileFlags[count>>3]|=(1<<(count&7));
			}
			count++;
		}
		pStat=pStat->pNext;
	}
	gos_SaveDataToRegistry( "DebuggerGraphs",&ProfileFlags,32 );
	gos_SaveDataToRegistry( "DebuggerGraphMode",&GraphMode,sizeof(int) );
	gos_SaveDataToRegistry( "DebuggerGraphInfo",&ShowColorInfo,sizeof(int) );
	#endif
//
// Save the exe time/date
//
	FILETIME ft;
	HANDLE file= CreateFile( _pgmptr, GENERIC_READ, FILE_SHARE_READ,NULL, OPEN_EXISTING, 0, NULL );
	GetFileTime( file, 0,0,&ft );			// Get last write time
	CloseHandle( file );
	gos_SaveDataToRegistry( "ExeDate",&ft.dwLowDateTime,sizeof(int) );
//
// If version specified, save current version number
//
	if( Environment.version && *Environment.version!=0 )
	{
		DWORD Data=1;
		gos_SaveDataToRegistry( Environment.version, &Data, sizeof(int) );
	}
}







//
// Loads *szData bytes into *pData from the registry key specified.
//
// The data can be a DWORD, Binary value or string
//
// If the key does not exist szData will be set to 0 and pData will not be altered
//
// If the *szData will be set to the actual number of bytes read
//
void __stdcall gos_LoadDataFromRegistry( char* keyName, void* pData, DWORD* szData, bool HKLM )
{
	gosASSERT( keyName && pData && szData );
	
	HKEY hKey;
	LONG result;

	if( HKLM )
		result=RegOpenKey(HKEY_LOCAL_MACHINE,RegistryKey,&hKey);
	else
		result=RegOpenKey(HKEY_CURRENT_USER,RegistryKey,&hKey);

	if( ERROR_SUCCESS==result )
	{
		result=RegQueryValueEx(hKey,keyName,NULL,NULL,(PBYTE)pData,szData);
		if (result == ERROR_SUCCESS)
		{
			RegCloseKey(hKey);
			return;
		}
		RegCloseKey(hKey);
	}

	*szData=0;
	return;
}


//
// Saves szData bytes starting at pData into the registry key specified.
//
// If szData is 4 the data will be saved as a DWORD, otherwise just binary data
//
void __stdcall gos_SaveDataToRegistry( char* keyName,  void* pData,  DWORD szData )
{
	gosASSERT( keyName && pData && szData );

	if( *RegistryKey )
	{
		HKEY hKey;
		LONG result=RegCreateKey(HKEY_CURRENT_USER,RegistryKey,&hKey);

		if( szData==4 )
			result=RegSetValueEx(hKey,keyName,0,REG_DWORD,(PBYTE)pData,szData);
		else
			result=RegSetValueEx(hKey,keyName,0,REG_BINARY,(PBYTE)pData,szData);
		RegCloseKey(hKey);
	}
}

//
// Saves a string starting at pData, length szData into the registry key specified.
//
// If szData is 4 the data will be saved as a DWORD, otherwise just binary data
//
void __stdcall gos_SaveStringToRegistry( char* keyName,  char* pData,  DWORD szData )
{
	gosASSERT( keyName && pData && szData );

	if( *RegistryKey )
	{
		HKEY hKey;
		LONG result=RegCreateKey(HKEY_CURRENT_USER,RegistryKey,&hKey);

		result=RegSetValueEx(hKey,keyName,0,REG_SZ,(PBYTE)pData,szData);

		RegCloseKey(hKey);
	}
}


//
//
// Returns a pointer to the data found in a key.
// This function only operates within HKEY_CURRENT_USER (0) or HKEY_LOCAL_MACHINE (1) if the flag is set
//
// The pointer points to a 512 byte buffer, so if a key contains more data
// it will be truncated.
//
// If the keydoes not exist 0 will be returned
//
//
char* ReadRegistry( char* KeyName, char* ValueName, bool LocalMachine )
{
	static char Buffer[512];
	HKEY hKey;
	DWORD BufferSize=sizeof(Buffer);

	Buffer[0]=0;		// Clear any previous results

	int result=RegOpenKey( LocalMachine ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, KeyName, &hKey );
	if( ERROR_SUCCESS==result )
	{
		result=RegQueryValueEx( hKey, ValueName, NULL, NULL, (LPBYTE)&Buffer, &BufferSize );
		RegCloseKey( hKey );
		if( ERROR_SUCCESS==result )
			return Buffer;
	}
	return 0;
}











