/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A.  All Rights Reserved.                         *
*                                                                          *
***************************************************************************/

#pragma once

#if !GLM_IS_PLATFORM_WINDOWS
#error glmDebuggingWindows.h should only included on Windows platform
#endif

#include "glmWindows.h"
#include "glmWindowsDebug.h"

//TODO: move 'NULL_HANDLE_VALUE' def to some common windows include file
#define NULL_HANDLE_VALUE ((HANDLE)(LONG_PTR)0)
#define NULL_HMODULE_VALUE ((HMODULE)(LONG_PTR)0)

typedef BOOL (WINAPI *SymInitialize_function)( _In_ HANDLE hProcess, _In_opt_ PCTSTR UserSearchPath, _In_ BOOL fInvadeProcess );
typedef BOOL (WINAPI *SymCleanup_function)( _In_  HANDLE hProcess );

typedef BOOL (WINAPI *SymGetSearchPath_function)( _In_ HANDLE hProcess, _Out_  PTSTR SearchPath, _In_ DWORD SearchPathLength );

typedef DWORD (WINAPI *SymGetOptions_function)( void );
typedef DWORD (WINAPI *SymSetOptions_function)( _In_  DWORD SymOptions );

typedef BOOL (WINAPI *StackWalk64_function)( 
	_In_      DWORD MachineType,
	_In_      HANDLE hProcess,
	_In_      HANDLE hThread,
	_Inout_   LPSTACKFRAME64 StackFrame,
	_Inout_   PVOID ContextRecord,
	_In_opt_  PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,
	_In_opt_  PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
	_In_opt_  PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
	_In_opt_  PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress
	);

typedef DWORD64 (WINAPI *SymLoadModuleEx_function)(
	_In_  HANDLE hProcess,
	_In_  HANDLE hFile,
	_In_  PCTSTR ImageName,
	_In_  PCTSTR ModuleName,
	_In_  DWORD64 BaseOfDll,
	_In_  DWORD DllSize, 
	_In_  PMODLOAD_DATA Data,
	_In_  DWORD Flags
	);

typedef DWORD64 (WINAPI *SymGetModuleBase64_function)( _In_  HANDLE hProcess, _In_  DWORD64 dwAddr );

//See glmStackWalker.cpp if needed
//typedef BOOL (DBHLPAPI *SymGetModuleInfo64_v2_function)( _In_ HANDLE hProcess, _In_ DWORD64 dwAddr, _Out_ IMAGEHLP_MODULE64_V2 *ModuleInfo );
//typedef BOOL (DBHLPAPI *SymGetModuleInfo64_v3_function)( _In_ HANDLE hProcess, _In_ DWORD64 dwAddr, _Out_ IMAGEHLP_MODULE64_V3 *ModuleInfo );

typedef PVOID (WINAPI *SymFunctionTableAccess64_function)( _In_  HANDLE hProcess, _In_  DWORD64 AddrBase );
typedef BOOL (WINAPI *SymGetLineFromAddr64_function)( _In_ HANDLE hProcess, _In_ DWORD64 dwAddr, _Out_ PDWORD pdwDisplacement, _Out_ PIMAGEHLP_LINE64 Line );
typedef BOOL (WINAPI *SymFromAddr_function)( _In_ HANDLE hProcess, _In_ DWORD64 Address, _Out_opt_ PDWORD64 Displacement, _Inout_ PSYMBOL_INFO Symbol );

typedef DWORD (WINAPI *UnDecorateSymbolName_function)( _In_ PCTSTR DecoratedName, _Out_ PTSTR UnDecoratedName, _In_ DWORD UndecoratedLength, _In_ DWORD Flags );

namespace glm
{
	class WindowsDbgHelp
	{
	public:
		WindowsDbgHelp();
		~WindowsDbgHelp();

		bool loadDbgHelpLibrary();
		void unloadDbgHelpLibrary();

		SymInitialize_function _processSymInitialize;
		SymCleanup_function _processSymCleanup;

		SymGetSearchPath_function _processSymGetSearchPath;

		SymGetOptions_function _processSymGetOptions;
		SymSetOptions_function _processSymSetOptions;

		StackWalk64_function _processStackWalk64;

		SymLoadModuleEx_function _processSymLoadModuleEx;
		SymGetModuleBase64_function _processSymGetModuleBase64;
		//SymGetModuleInfo64_v2_function _processSymGetModuleInfo64_v2;
		//SymGetModuleInfo64_v3_function _processSymGetModuleInfo64_v3;

		SymFunctionTableAccess64_function _processSymFunctionTableAccess64;
		SymGetLineFromAddr64_function _processSymGetLineFromAddr64;
		SymFromAddr_function _processSymFromAddr;
		UnDecorateSymbolName_function _processUnDecorateSymbolName;

	private:
		HMODULE _dbghelpLibray;
	};
}
