2024-08-01 22:38:55 +08:00
# include "Utilities.hpp"
namespace VSW : : Materializer : : Utilities {
2024-08-06 18:06:17 +08:00
# pragma region Enhanced Reporter
EnhancedReporter : : EnhancedReporter ( CKContext * ctx ) :
m_Ctx ( ctx ) { }
EnhancedReporter : : ~ EnhancedReporter ( ) { }
void EnhancedReporter : : PrePrint ( const YYCC : : yycc_char8_t * strl ) const {
if ( m_Ctx ! = nullptr )
m_Ctx - > OutputToConsole ( const_cast < CKSTRING > ( YYCC : : EncodingHelper : : UTF8ToChar ( strl , CP_ACP ) . c_str ( ) ) , FALSE ) ;
}
# pragma endregion
2024-08-07 11:40:18 +08:00
void RelativeAddress ( const EnhancedReporter & reporter , YYCC : : yycc_u8string & relative_addr_str , const void * absolute_addr ) {
2024-08-02 17:04:37 +08:00
// If address is nullptr, return directly
if ( absolute_addr = = nullptr ) {
2024-08-07 11:40:18 +08:00
relative_addr_str = YYCC_U8 ( " <nullptr> " ) ;
return ;
2024-08-02 17:04:37 +08:00
}
// Get the module handle which given function address belongs to
// Reference: https://stackoverflow.com/questions/557081/how-do-i-get-the-hmodule-for-the-currently-executing-code
HMODULE hModule = NULL ;
GetModuleHandleExW (
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT , // get address and do not inc ref counter.
( LPCWSTR ) absolute_addr ,
& hModule ) ;
2024-08-06 18:06:17 +08:00
if ( hModule = = NULL ) {
reporter . ErrF ( YYCC_U8 ( " Fail to get module of given absolute address 0x% " PRI_XPTR_LEFT_PADDING PRIXPTR " . Some relative address may be empty. " ) , absolute_addr ) ;
2024-08-07 11:40:18 +08:00
relative_addr_str . clear ( ) ;
return ;
2024-08-06 18:06:17 +08:00
}
2024-08-02 17:04:37 +08:00
// Get full path to module
YYCC : : yycc_u8string u8_module_path ;
2024-08-06 18:06:17 +08:00
if ( ! YYCC : : WinFctHelper : : GetModuleFileName ( hModule , u8_module_path ) ) {
reporter . ErrF ( YYCC_U8 ( " Fail to get file name of given module 0x% " PRI_XPTR_LEFT_PADDING PRIXPTR " . Some relative address may be empty. " ) , hModule ) ;
2024-08-07 11:40:18 +08:00
relative_addr_str . clear ( ) ;
return ;
2024-08-06 18:06:17 +08:00
}
2024-08-02 17:04:37 +08:00
// Then get its file name part
auto module_path = YYCC : : FsPathPatch : : FromUTF8Path ( u8_module_path . c_str ( ) ) ;
auto u8_module_name = YYCC : : FsPathPatch : : ToUTF8Path ( module_path . filename ( ) ) ;
2024-08-04 17:43:18 +08:00
2024-08-02 17:04:37 +08:00
// Get the base address of current module
// HMODULE is the base address of loaded module
// Reference: https://stackoverflow.com/questions/4298331/exe-or-dll-image-base-address
uintptr_t relative_addr = reinterpret_cast < uintptr_t > ( absolute_addr ) - reinterpret_cast < uintptr_t > ( hModule ) ;
2024-08-04 17:43:18 +08:00
2024-08-02 17:04:37 +08:00
// get final result
2024-08-07 11:40:18 +08:00
if ( ! YYCC : : StringHelper : : Printf ( relative_addr_str , YYCC_U8 ( " %s+0x% " PRI_XPTR_LEFT_PADDING PRIXPTR ) , u8_module_name . c_str ( ) , relative_addr ) ) {
2024-08-06 18:06:17 +08:00
reporter . Err ( YYCC_U8 ( " Fail to format relative address. Some relative address may be empty. " ) ) ;
2024-08-07 11:40:18 +08:00
relative_addr_str . clear ( ) ;
2024-08-06 18:06:17 +08:00
}
2024-08-02 17:04:37 +08:00
}
2024-08-06 18:06:17 +08:00
void CopyStrGuid ( const EnhancedReporter & reporter , YYCC : : yycc_u8string & dst , const CKGUID & src ) {
if ( ! YYCC : : StringHelper : : Printf ( dst , YYCC_U8 ( " <0x%08 " PRIX32 " , 0x%08 " PRIX32 " > " ) , src . d1 , src . d2 ) ) {
reporter . Err ( YYCC_U8 ( " Fail to format CKGUID. Some stringified GUID may be empty. " ) ) ;
dst . clear ( ) ;
}
}
2024-08-05 14:23:26 +08:00
2024-08-06 18:06:17 +08:00
void CopyGuid ( const EnhancedReporter & reporter , int64_t & dst , const CKGUID & src ) {
// reset dst to zero
uint64_t * pdst = reinterpret_cast < uint64_t * > ( & dst ) ;
// CKGUID.d1 to high 32 bits
* pdst = static_cast < uint64_t > ( src . d1 ) ;
* pdst < < = 32u ;
// CKGUID.d2 to low 32 bits
* pdst = ( * pdst ) | static_cast < uint64_t > ( src . d2 ) ;
2024-08-02 17:04:37 +08:00
}
2024-08-06 18:06:17 +08:00
void CopyCKString ( const EnhancedReporter & reporter , YYCC : : yycc_u8string & storage , const char * str , UINT code_page , const YYCC : : yycc_char8_t * fallback ) {
// check whether callback is nullptr.
2024-08-05 14:23:26 +08:00
if ( fallback = = nullptr )
throw std : : invalid_argument ( " fallback string should not be nullptr! " ) ;
2024-08-04 17:43:18 +08:00
2024-08-06 18:06:17 +08:00
// if given string is nullptr, use fallback instead
if ( str = = nullptr ) {
storage = fallback ;
return ;
}
2024-08-04 17:43:18 +08:00
2024-08-06 18:06:17 +08:00
// otherwise do encoding convertion of original string.
if ( ! YYCC : : EncodingHelper : : CharToUTF8 ( str , storage , code_page ) ) {
reporter . Err ( YYCC_U8 ( " Fail to convert encoding. Some string may use fallback string accidently. " ) ) ;
storage = fallback ;
}
2024-08-04 17:43:18 +08:00
}
2024-08-01 22:38:55 +08:00
}