How to replace the RCData of an executable? - c++

I'm trying to modify the RCData of a compiled AutoHotkey script:
void ReplaceStringTable() {
HANDLE hRes = BeginUpdateResource( _T( "C:\\Users\\CAIO\\Documents\\Github\\main\\scripts\\ahkDebug\\Novo(a) AutoHotkey Script.exe" ), FALSE );
if ( hRes != NULL ) {
std::wstring data[] = { L"MsgBox Test" };
std::vector< WORD > buffer;
for ( size_t index = 0;
index < sizeof( data ) / sizeof( data[ 0 ] );
++index ) {
size_t pos = buffer.size();
buffer.resize( pos + data[ index ].size() + 1 );
buffer[ pos++ ] = static_cast< WORD >( data[ index ].size() );
copy( data[ index ].begin(), data[ index ].end(),
buffer.begin() + pos );
}
UpdateResource( hRes,
RT_RCDATA,
L">AUTOHOTKEY SCRIPT<", //MAKEINTRESOURCE( 1 ),
1033, //MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
reinterpret_cast< void* >( &buffer[ 0 ] ),
buffer.size() * sizeof( WORD ) );
EndUpdateResource( hRes, FALSE );
}
}
However, this is the result after running the code:
The code does add an empty blank line (line 1), this line makes the exe not work correctly, how do I get rid of it?

You need to use std::string instead of std::wstring, as AHK is expecting 8bit characters, not 16bit characters. Also, you need to get rid of your vector, as AHK does not expect each line to be prefixed by its length.
Try this instead:
void ReplaceStringTable() {
HANDLE hRes = BeginUpdateResource( TEXT( "C:\\Users\\CAIO\\Documents\\Github\\main\\scripts\\ahkDebug\\Novo(a) AutoHotkey Script.exe" ), FALSE );
if ( hRes != NULL ) {
std::string data = "MsgBox Test";
UpdateResource( hRes,
RT_RCDATA,
L">AUTOHOTKEY SCRIPT<", //MAKEINTRESOURCE( 1 ),
1033, //MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
const_cast<char*>(data.c_str()),
data.size() );
EndUpdateResource( hRes, FALSE );
}
}

Related

How to get word list using ISpLexicon::GetWords?

I'm developping a Text-To-Speech application using Microsoft SAPI. I found out that it is possible to add customized prononciations of words in a dictionnary (correct me if I'm wrong). I implemented a function which allows to add words into this dictionnary. Here is my code:
int addPrononciation( const char* addPron, const char* phon )
{
hr = cpLexicon.CoCreateInstance( CLSID_SpLexicon );
hr = cpContainerLexicon.CoCreateInstance( CLSID_SpLexicon );
hr = SpEnumTokens( SPCAT_VOICES, NULL, NULL, &cpEnum );
cpEnum->Item( saveVoice, &cpVoiceToken ); //get saveVoice token defined at line 136
cpVoice->SetVoice( cpVoiceToken ); //Initialization of the voice
hr = cpContainerLexicon->AddLexicon( cpLexicon, eLEXTYPE_APP );
langId = MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US );
hr = SpCreatePhoneConverter( langId, NULL, NULL, &cpPhoneConv );
int wchars_num = MultiByteToWideChar( CP_ACP, 0, addPron, -1, NULL, 0 );
wchar_t* pronWstr = new wchar_t[ wchars_num ];
MultiByteToWideChar( CP_ACP, 0, addPron, -1, pronWstr, wchars_num );
int phonWchars_num = MultiByteToWideChar( CP_ACP, 0, phon, -1, NULL, 0 );
wchar_t* phonWstr = new wchar_t[ phonWchars_num ];
MultiByteToWideChar( CP_ACP, 0, phon, -1, phonWstr, phonWchars_num );
if(SUCCEEDED( hr ))
{
hr = cpPhoneConv->PhoneToId( phonWstr, wszId );
hr = cpVoice->Speak( phonWstr, SPF_DEFAULT, NULL );
hr = cpLexicon->AddPronunciation( pronWstr, langId, SPPS_Noun, wszId );
hr = cpVoice->Speak( pronWstr, SPF_DEFAULT, NULL );
if( SUCCEEDED( hr ) )
{
printf( "Success\n" );
}
else
{
printf( "Failed\n" );
}
}
cpEnum.Release();
cpVoiceToken.Release();
cpContainerLexicon.Release();
cpLexicon.Release();
cpPhoneConv.Release();
delete new wchar_t[ wchars_num ];
delete new wchar_t[ phonWchars_num ];
return true;
}
Now I would like to list these words using ISpLexicon::GetWords.
I already read the documentation on the Microsoft website and tried to implement the function, but I can't figure out how to initialize the variable spWordList.
Here is my code:
ZeroMemory( &spWordList, sizeof( spWordList ) );
if( SUCCEEDED( hr ) )
{
hr = cpLexicon->GetWords( eLEXTYPE_APP, &dwGeneration, &dwCookie, &spWordList );
printf( "Words: %ls\n", spWordList ); //print words but the output is null
}
CoTaskMemFree( spWordList.pvBuffer );
I'm triying to print the words, but the output is null. I think the spWordList variable is not initialized. Here is a screenshot of the variable values.
How can I initialize it?
I found out how to initialize spWordList. You have to replace eLEXTYPE_APP with eLEXTYPE_USER. However, you can keep both of them like I did. Below you will find an example on how it lists the words.
ZeroMemory( &spWordList, sizeof( spWordList ) );
hr = S_FALSE;
if( hr == S_FALSE )
{
hr = cpLexicon->GetWords( eLEXTYPE_USER | eLEXTYPE_APP, &dwGeneration, &dwCookie, &spWordList );
for( spWord = spWordList.pFirstWord; spWord != NULL; spWord = spWord->pNextWord )
{
for( spWordPron = spWord->pFirstWordPronunciation; spWordPron != NULL; spWordPron = spWordPron->pNextWordPronunciation )
{
printf( "Words in dictionnary: %i\n", dwGeneration );
printf( "Word: %ls\n", spWord->pszWord );
//you can also display the pronunciation of words if you wish
}
}
}
CoTaskMemFree( spWordList.pvBuffer );
In the code, I loop through the entire dictionnary. Notice that the listed words are displayed randomly. I'll update my answer if I find other important information about ISpLexicon::GetWords

Jumplist in Windows 10 failing

I'm using the below code to have the taskbar jumplist open the users default browser at certain pages.
Everything has been working fine for about a year now on Win 7/8 but with Windows 10 the browser is not called when the taskbar task is clicked and the Microsoft documentation shows no changes from Win 8 to 10.
bool SetUpJumpList( )
{
HRESULT hr;
CComPtr<ICustomDestinationList> pDestList;
hr = pDestList.CoCreateInstance ( CLSID_DestinationList , NULL , CLSCTX_INPROC_SERVER );
if ( FAILED ( hr ) )
{
return false;
}
hr = pDestList->SetAppID ( _TBID );
if ( FAILED ( hr ) )
{
return false;
}
UINT cMaxSlots;
CComPtr<IObjectArray> pRemovedItems;
hr = pDestList->BeginList ( &cMaxSlots , IID_PPV_ARGS ( &pRemovedItems ) );
if ( FAILED ( hr ) )
{
return false;
}
CComPtr<IObjectCollection> pObjColl;
hr = pObjColl.CoCreateInstance ( CLSID_EnumerableObjectCollection , NULL , CLSCTX_INPROC_SERVER );
if ( FAILED ( hr ) )
{
return false;
}
if ( !AddJumpListTasks ( pObjColl ) )
{
return false;
}
CComQIPtr<IObjectArray> pTasksArray = pObjColl;
if ( !pTasksArray )
{
return false;
}
hr = pDestList->AddUserTasks ( pTasksArray );
if ( FAILED ( hr ) )
{
return false;
}
hr = pDestList->CommitList( );
return SUCCEEDED ( hr );
}
bool AddJumpListTasks ( IObjectCollection* pObjColl )
{
wchar_t pBuf[ MAX_PATH ];
int bytes = GetModuleFileName ( NULL , pBuf , MAX_PATH );
CJumpListTask aTasks[ ] =
{
{ _T ( "https://www.google.co.uk" ) , _T ( "Home Page" ) , _T ( "Home" ) , 0 },
{ _T ( "https://www.google.co.uk" ) , _T ( "Twitter Page" ) , _T ( "Twitter" ) , 9 },
{ _T ( "https://www.google.co.uk" ) , _T ( "Facebook Page" ) , _T ( "Facebook" ) , 10 }
};
CString strBrowser;
DWORD size = 1024;
AssocQueryString ( 0 , ASSOCSTR_EXECUTABLE , L"http" , L"Open" , strBrowser.GetBufferSetLength ( size ) , &size );
for ( int i = 0; i < _countof ( aTasks ); i++ )
{
if ( !AddJumpListTask ( pObjColl , aTasks[ i ] , strBrowser , pBuf ) )
{
strBrowser.ReleaseBuffer( );
return false;
}
}
strBrowser.ReleaseBuffer( );
return true;
}
bool AddJumpListTask ( IObjectCollection* pObjColl , const CJumpListTask& rTask , LPCTSTR szExePath , LPCTSTR pBuf )
{
HRESULT hr;
CComPtr<IShellLink> pLink;
hr = pLink.CoCreateInstance ( CLSID_ShellLink , NULL , CLSCTX_INPROC_SERVER );
if ( FAILED ( hr ) )
{
return false;
}
hr = pLink->SetPath ( szExePath );
if ( FAILED ( hr ) )
{
return false;
}
hr = pLink->SetArguments ( rTask.szArgs );
if ( FAILED ( hr ) )
{
return false;
}
hr = pLink->SetIconLocation ( pBuf , rTask.nIconIndex );
if ( FAILED ( hr ) )
{
return false;
}
CComQIPtr<IPropertyStore> pPropStore = pLink;
PROPVARIANT pv;
if ( !pPropStore )
{
return false;
}
hr = InitPropVariantFromString ( CT2CW ( rTask.szTitle ) , &pv );
if ( FAILED ( hr ) )
{
return false;
}
hr = pPropStore->SetValue ( PKEY_Title , pv );
PropVariantClear ( &pv );
if ( FAILED ( hr ) )
{
return false;
}
hr = pPropStore->Commit( );
if ( FAILED ( hr ) )
{
return false;
}
hr = pObjColl->AddObject ( pLink );
return SUCCEEDED ( hr );
}
I've noticed several other applications such as CCleaner that also use this method do not function either but Microsoft applications such as Office 2013 still work so the question is how do I get this running again on Windows 10?
I'm certain this is not related to the customDestinations-ms files stored in the CustomDestinations folder as with a clean install of Windows 10 the same non functionality appears.
The taskbar task menu is created with the desired text and icon and debugging shows the correct URL is added along with the correct default browser and browser path.
Edit:
Using Visual Studio 2015 with toolset Windows XP v140_xp
As a workaround you could use, if possible for you, the MFC Class "CJumplist" from the latest Windows SDK.
We found out it would fix this issue, but only if using the latest SDK version. Using an older SDK using the same MFC class (eg Windows 7 SDK) would cause exactly the same issues you are experiencing.
This is a sample code working on Windows 10 with VC2013 and latest SDK (Target v12.0), but only when using MFC in a shared Dll. Linking with a static MFC Dll does not seem to work.
CJumpList *pJumpList = new CJumpList();
pJumpList->SetAppID(m_pszAppID);
result = pJumpList->AddTask(szPath, _T("-data1"), _T("number 4"), szPath, 0);
result = pJumpList->AddTask(szPath, _T("-data2"), _T("number 5"), szPath, 0);
pJumpList->CommitList();
delete pJumpList;
I do not know what changes Microsoft developers have done in this class to make it work. Our pure Win32 code suffers the same issues as you reported.
A little update to this, a reinstall of Windows due to other issues followed by a reinstall of VS but not checking the XP compatibility options results in the Jumplists working again, I dont need XP support anyhow but I assume this issue is related to the XP library's.

Macro not executing function

I have a macro, and i use it this way:
int GL = 0;
GL = GetLastError();
DEBUG_MESSAGE( ERR, "RegOpenKeyEx failed. Error code = '%u'. Error description = '%s'", GL, GetErrorText( GL ) );
The function GetErrorText returns a char *, which is the corresponding errortext belonging to the error code.
The problem is, that when i call my macro, it won't call GetErrorText function.
The output will be this : RegOpenKeyEx failed. Error code = '5'. Error description = ''
The Macro is defined this way:
#define DEBUG_MESSAGE( Type, debug_message, ... ) { _debugLog.message( Type, debug_message, ##__VA_ARGS__ ); }
And this is the function what the macro calls:
void log::message( int Type, const char * message, ... )
{
char MessageExpanded[ 2048 ] = { 0 };
va_list args;
int len;
write_indentation();
memset( Message, 0, sizeof( Message ) );
memset( MessageExpanded, 0, sizeof( MessageExpanded ) );
va_start( args, message );
len = _vscprintf( message, args ) + 1; // _vscprintf doesn't count terminating '\0'
vsprintf_s( Message, len, message, args );
va_end( args );
sprintf( MessageExpanded, "%s %s", Spaces, Message );
LOG( MessageExpanded, context.c_str(), "", Type, CurrentFileName );
}//log::message
Is there a way to solve this somehow?
Thanks in advance!
Update:
char * GetErrorText( DWORD dwLastError )
{
DEBUG_METHOD( INFO );
DEBUG_MESSAGE( INFO, "Argument1 = '%d'", dwLastError );
HMODULE hModule = NULL; // default to system source
LPSTR MessageBuffer;
DWORD dwBufferLength;
char Error[ SMALL ] = { 0 };
char * ErrorMsg = NULL;
DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM;
// If dwLastError is in the network range, load the message source.
if ( dwLastError >= NERR_BASE && dwLastError <= MAX_NERR )
{
hModule = LoadLibraryEx( TEXT( "netmsg.dll" ), NULL, LOAD_LIBRARY_AS_DATAFILE );
if ( hModule != NULL ) dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
}
// Call FormatMessage() to allow for message text to be acquired from the system or from the supplied module handle.
if ( dwBufferLength = FormatMessageA(
dwFormatFlags,
hModule, // module to get message from (NULL == system)
dwLastError,
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // default language
( LPSTR )&MessageBuffer,
0,
NULL
)
)
{
memset( Error, 0, sizeof( Error ) );
//printf( "\n%s", MessageBuffer );
sprintf( Error, "%s", MessageBuffer );
ErrorMsg = Error;
// Free the buffer allocated by the system.
LocalFree( MessageBuffer );
}
// If we loaded a message source, unload it.
if ( hModule != NULL ) FreeLibrary( hModule );
return ErrorMsg;
}//GetErrorText
GetErrorText() is returning a pointer to a local buffer:
char Error[ SMALL ] = { 0 };
So the pointer it returns is invalid by the time _debugLog.message() is called.

why is this value being set to 0? O_O

chMB() is a define to MessageBoxA( 0, text, "title", MB_OK );so it displays the text and I can see results. My problem is with the following codez:
CString szWow;
szWow.Format( "%u", idCandidate );
chMB( szWow );
const __int64 i64set = i64VoteAmount+1;
CString addvote;
addvote.Format( "UPDATE dbo.CONSULENTRIES set m_uVoteAmount = %u WHERE m_idCandidate = %u", i64set, idCandidate );
chMB( addvote );
chMB( szWow ); displayes 5
althought chMB( addVote ) displayes:
UPDATE dbo.CONSULENTRIES set m_uVoteAmount = 1 WHERE m_idCandidate = 0
why is idCandidate 0 on this string format??? O___O
in case you need here is teh full codez:
VOTEAPPL CConsulApplication::VoteForApplied( const u_long idVoter, const __int64 idCandidate )
{
if( idVoter && idCandidate )
{
/* Check if alredy voted */
CQuery* pQuery = new CQuery;
if( !pQuery->Connect( 3, DSN_NAME_CHARACTER01, DB_ADMIN_ID_CHARACTER01, DB_ADMIN_PASS_CHARACTER01 ) )
{
pQuery->DisConnect();
SAFE_DELETE( pQuery );
return VAPL_FAILURE;
}
CString szVoted;
szVoted.Format( "SELECT * FROM dbo.CONSULVOTE WHERE m_idVoter = %u", idVoter );
if( !pQuery->Exec( szVoted ) )
{
pQuery->DisConnect();
SAFE_DELETE( pQuery );
return VAPL_FAILURE;
}
pQuery->Fetch();
__int64 i64Voter = pQuery->GetInt64( "m_idVoter" );
if( i64Voter != 0 )
{
pQuery->DisConnect();
SAFE_DELETE( pQuery );
return VAPL_VOTED;
}
pQuery->DisConnect();
SAFE_DELETE( pQuery );
/* Get content and check if candidate exists */
CQuery* pQuery2 = new CQuery;
if( !pQuery2->Connect( 3, DSN_NAME_CHARACTER01, DB_ADMIN_ID_CHARACTER01, DB_ADMIN_PASS_CHARACTER01 ) )
{
pQuery2->DisConnect();
SAFE_DELETE( pQuery2 );
return VAPL_FAILURE;
}
CString szCandidate;
szCandidate.Format( "SELECT * FROM dbo.CONSULENTRIES WHERE m_idCandidate = %u", idCandidate );
if( !pQuery2->Exec( szCandidate ) )
{
pQuery2->DisConnect();
SAFE_DELETE( pQuery2 );
return VAPL_FAILURE;
}
pQuery2->Fetch();
__int64 i64Candidate = pQuery2->GetInt64( "m_idCandidate" );
__int64 i64VoteAmount = pQuery2->GetInt64( "m_uVoteAmount" );
if( i64Candidate != 0 )
{
/* Insert at database that this guy has voted */
CQuery* pInsertQuery = new CQuery;
if( !pInsertQuery->Connect( 3, DSN_NAME_CHARACTER01, DB_ADMIN_ID_CHARACTER01, DB_ADMIN_PASS_CHARACTER01 ) )
{
pInsertQuery->DisConnect();
SAFE_DELETE( pInsertQuery );
return VAPL_FAILURE;
}
CString szInsert;
szInsert.Format( "INSERT INTO dbo.CONSULVOTE values(%u,%u)", idVoter, idCandidate );
if( !pInsertQuery->Exec( szInsert ) )
{
pInsertQuery->DisConnect();
SAFE_DELETE( pInsertQuery );
return VAPL_FAILURE;
}
pInsertQuery->DisConnect();
SAFE_DELETE( pInsertQuery );
/* Update vote amount */
CQuery* pUpdate = new CQuery;
if( !pUpdate->Connect( 3, DSN_NAME_CHARACTER01, DB_ADMIN_ID_CHARACTER01, DB_ADMIN_PASS_CHARACTER01 ) )
{
pUpdate->DisConnect();
SAFE_DELETE( pUpdate );
return VAPL_FAILURE;
}
CString szWow;
szWow.Format( "%u", idCandidate );
chMB( szWow );
const __int64 i64set = i64VoteAmount+1;
CString addvote;
addvote.Format( "UPDATE dbo.CONSULENTRIES set m_uVoteAmount = %u WHERE m_idCandidate = %u", i64set, idCandidate );
chMB( addvote );
if( !pUpdate->Exec( addvote ) )
{
pUpdate->DisConnect();
SAFE_DELETE( pUpdate );
return VAPL_FAILURE;
}
pUpdate->DisConnect();
SAFE_DELETE( pUpdate );
return VAPL_SUCCESS;
}
pQuery2->DisConnect();
SAFE_DELETE( pQuery2 );
return VAPL_FAILURE;
}
return VAPL_FAILURE;
}
The problem is here:
addvote.Format( "UPDATE dbo.CONSULENTRIES set m_uVoteAmount = %u WHERE m_idCandidate = %u", i64set, idCandidate );
The format string contains %u while the variable after the format string (i64set) is of a wrong type (__int64).
Try changing the type (%u corresponds to type unsigned int) or the format specifier:
addvote.Format( "UPDATE dbo.CONSULENTRIES set m_uVoteAmount = %I64d WHERE m_idCandidate = %u", i64set, idCandidate );

how do i create a map and iterate between exp_tag and lhs to print them in sorted order?

extern int JAX_EXP_DEBUG_print_all_exps_in_session ( )
{
tag_t part_tag = NULL_TAG;
for ( PART_cycle_parts_in_world ( &part_tag ); part_tag; PART_cycle_parts_in_world ( &part_tag ) )
{
EXP_generic_p_t exp = NULL;
for ( exp = EXP_generic_cycle_all_exps ( part_tag, exp ); exp; exp = EXP_generic_cycle_all_exps ( part_tag, exp ) )
{
//typedef map< tag_t, const char * > Exp_Map;
Exp_Map new_map;
tag_t exp_tag = OM_ask_object_tag ( exp );
const char *lhs = exp->GetLHSInLocale ( );
logical is_kf_exp = exp->is_exp_kf ( );
logical is_system_exp = exp->is_a_system_exp ( );
logical is_geometry_exp = exp->is_geom_exp ( );
logical is_measure_exp = EXP_kf_is_measure_exp ( exp );
logical is_visible_exp = exp->is_exp_visible ( );
logical is_locked_exp = exp->is_locked ( );
logical is_edit_locked_exp = exp->is_edit_locked ( );
logical is_user_locked_exp = exp->is_user_locked ( );
const char *data_type = exp->ask_data_type ( );
const char *unit_name = EXP_kf_ask_unit_name_of_exp ( exp );
const char *rhs = exp->GetRHSInLocale ( );
new_map.insert( std::pair< tag_t, const char * >( exp_tag, lhs ) );
for ( Exp_Map::iterator iter = new_map.begin(); iter != new_map.end(); ++iter )
{
JAM_test_print_tag_start ( iter->first, iter->second, 0 );
}
JAM_test_print_method_start ( "IsKfEXP" );
JAM_test_print_param_logical ( is_kf_exp, "is_kf_exp", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "IsKfExp" );
JAM_test_print_method_start ( "IsSystemExp" );
JAM_test_print_param_logical ( is_system_exp, "is_system_exp", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "IsSystemExp" );
JAM_test_print_method_start ( "IsGeometryExp" );
JAM_test_print_param_logical ( is_geometry_exp, "is_geometry_exp", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "IsGeometryExp" );
JAM_test_print_method_start ( "IsMeasureExp" );
JAM_test_print_param_logical ( is_measure_exp, "is_measure_exp", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "IsMeasureExp" );
JAM_test_print_method_start ( "IsVisibleExp" );
JAM_test_print_param_logical ( is_visible_exp, "is_visible_exp", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "IsVisibleExp" );
JAM_test_print_method_start ( "IsLockedExp" );
JAM_test_print_param_logical ( is_locked_exp, "is_locked_exp", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "IsLockedExp" );
JAM_test_print_method_start ( "IsEditLockedExp" );
JAM_test_print_param_logical ( is_edit_locked_exp, "is_edit_locked_exp", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "IsEditLockedExp" );
JAM_test_print_method_start ( "IsUserLockedExp" );
JAM_test_print_param_logical ( is_user_locked_exp, "is_user_locked_exp", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "IsUserLockedExp" );
JAM_test_print_method_start ( "GetDataType" );
JAM_test_print_param_string ( data_type, "data_type", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "GetDataType" );
JAM_test_print_method_start ( "GetUnitName" );
JAM_test_print_param_string ( unit_name, "unit_name", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "GetUnitName" );
JAM_test_print_method_start ( "GetRightHandSide" );
JAM_test_print_param_string ( rhs, "right_hand_side", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "GetRightHandSide" );
/* <JBT> 21-Apr-2009 PR#6140162
Use double format for number values.
*/
if ( STR_compare_i ( data_type, EXP_NUMBER_TYPE ) == 0 )
{
double value = ( ( EXP_expression_p_t ) exp )->GetDoubleValue ( );
JAM_test_print_method_start ( "GetDoubleValue" );
JAM_test_print_param_double ( value, "double_value", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "GetDoubleValue" );
}
else if ( STR_compare_i ( data_type, EXP_POINT_TYPE ) == 0 )
{
PNT3_t value = ( ( ExpKf::ExpPoint * ) exp )->GetPointValue ( );
JAM_test_print_struct_start ( "GetPointValue", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_param_double ( PNT3_X ( &value ), "point_value_x", JAM_PRINT_TYPE_STRUCT_ELEM );
JAM_test_print_param_double ( PNT3_Y ( &value ), "point_value_y", JAM_PRINT_TYPE_STRUCT_ELEM );
JAM_test_print_param_double ( PNT3_Z ( &value ), "point_value_z", JAM_PRINT_TYPE_STRUCT_ELEM );
JAM_test_print_struct_end ( "GetPointValue", JAM_PRINT_TYPE_RETURN_VAL );
}
else if ( STR_compare_i ( data_type, EXP_VECTOR_TYPE ) == 0 )
{
VEC3_t value = ( ( ExpKf::ExpVector * ) exp )->GetVectorValue ( );
JAM_test_print_struct_start ( "GetVectorValue", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_param_double ( VEC3_X ( &value ), "vector_value_x", JAM_PRINT_TYPE_STRUCT_ELEM );
JAM_test_print_param_double ( VEC3_Y ( &value ), "vector_value_y", JAM_PRINT_TYPE_STRUCT_ELEM );
JAM_test_print_param_double ( VEC3_Z ( &value ), "vector_value_z", JAM_PRINT_TYPE_STRUCT_ELEM );
JAM_test_print_struct_end ( "GetVectorValue", JAM_PRINT_TYPE_RETURN_VAL );
}
else
{
TEXT_p_t text = exp->ask_value_as_text ( );
const char *value = TEXT_to_utf8 ( text );
JAM_test_print_method_start ( "GetValueAsText" );
JAM_test_print_param_string ( value, "value_as_text", JAM_PRINT_TYPE_RETURN_VAL );
JAM_test_print_method_end ( "GetValueAsText" );
TEXT_free ( text );
}
JAM_test_print_tag_end ( );
}
}
return 0;
}
You need to define your map outside of the loop in line 5 and move your printing loop (the one with JAM_test_print_tag_start) outside of that outmost loop right before the return.