URL escaping MFC strings - c++

How do you URL escape an MFC CString?

InternetCanonicalizeUrl()

I created a wrapper function for others who may come across this solution. Also requires linking to Wininet.lib and including wininet.h
bool EscapeURL ( CString& url, DWORD options = ICU_DECODE | ICU_ENCODE_PERCENT )
{
DWORD bytes = url.GetLength () + 1;
LPTSTR escapedString = new TCHAR[bytes + 1];
escapedString[0] = 0;
// First read will generate the correct byte count for the return string
//
bool result = InternetCanonicalizeUrl ( url.GetBuffer (), escapedString, &bytes, options );
if ( !result )
{
// Resize the String
//
delete [] escapedString;
escapedString = new TCHAR[bytes];
escapedString[0] = 0;
result = InternetCanonicalizeUrl ( url.GetBuffer (), escapedString, &bytes, options );
}
if ( result )
{
url = escapedString;
delete [] escapedString; // Thanks The Steve
}
else
{
// Optional
// If the call fails return the message in the url
//
DWORD errorMessageID = ::GetLastError ();
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message ( messageBuffer, size );
LocalFree ( messageBuffer );
url = message.c_str ();
}
return result;
}
Usage
CString internetUse = "The Internet is %%4 <pr0n>";
EscapeURL ( internetUse );
// internetUse = 0x01538890 "The%20Internet%20is%20%25%254%20%3Cpr0n%3E"

Related

change the use of SHBrowseForFolder and struct BROWSEINFO TO - IFileOpenDialog

until now- in order to open a dialog box I used SHBrowseForFolder function. It causes some bugs and I was told to use IFileOpenDialog.
here is the code I need to replace:
bool wvFM::SelectFileSystemObjectDialogTree(const WCDialogCreationOptions& in_options,
WCDialogReply& out_Reply)
{
AUTO_FUNC_DEBUG;
DWORD osErr = NO_ERROR;
WTErr wtErr = eNoErr;
out_Reply.accept = false;
if(in_options.m_flags[WCDialogCreationOptions::eSelectFolder]) {
BROWSEINFO bi = {0};
bi.hwndOwner = (HWND)in_options.m_owner;
bi.pidlRoot = NULL; // TBD by callback BrowseCallbackProc
bi.lpszTitle = in_options.m_windowTitle.c_str();
bi.ulFlags = BIF_USENEWUI; // to enable pasting path
bi.lpfn = BrowseCallbackProc; // for initial dir option
WTPathString initialLocationPathString(
in_options.m_InitialDir.GetNativePathString());
bi.lParam = in_options.m_InitialDir.IsValid()
? (LPARAM)initialLocationPathString.c_str()
: NULL;
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);
// returns focus to the internal window of the plug
::SetFocus((HWND)in_options.m_owner);
if(pidl != NULL) {
TCHAR szPath[MAX_PATH];
SHGetPathFromIDList(pidl, szPath);
out_Reply.m_filePathRef = wvFM::WCStPath((char*)szPath);
out_Reply.accept = true;
IMalloc* imalloc = 0;
if(SUCCEEDED(SHGetMalloc(&imalloc))) {
imalloc->Free(pidl);
imalloc->Release();
}
}
return true;
}
I am not so sure of how to make that conversion.
Thanks to anyone who will help!
You are clearly using a 3rd party library with some kind of custom string type, but you did not provide any details about what that string type actually is. I'm guessing that string type is char-based, given that you are type-casting the result of SHGetPathFromIDList() to char* when assigning it to out_Reply.m_filePathRef, so you are likely compiling your project with UNICODE undefined so that TCHAR maps to char and not wchar_t. In which case, SHBrowseForFolder() would be calling SHBrowseForFolderA() and not SHBrowseForFolderW().
IFileOpenDialog does not deal with ANSI strings at all, only UNICODE strings, so you will have to convert back and forth between your 3rd party string type and Windows UTF-16 strings as needed.
The conversion of SHBrowseForFolder() to IFileOpenDialog would look roughly like the following (where YourStringType in toWString() is the 3rd party string type - make whatever adjustments you need where indicated):
std::wstring toWString(const YourStringType &str)
{
const char pStr = ... pointer to str's characters ...;
int sLen = ... length of str in chars, not counting the null terminator ...;
std::wstring ws;
int wLen = MultiByteToWideChar(CP_ACP, 0, pStr, slen, NULL, 0);
if (wLen > 0)
{
ws.resize(wLen);
MultiByteToWideChar(CP_ACP, 0, pStr, sLen, ws.data(), wLen);
}
return ws;
}
std::string toString(const wchar_t *ws)
{
std::string s;
int wLen = lstrlenW(s);
int sLen = WideCharToMultiByte(CP_ACP, 0, ws, wLen, NULL, 0, NULL, NULL);
if (sLen > 0)
{
s.resize(sLen);
WideCharToMultiByte(CP_ACP, 0, ws, wLen, s.data(), sLen, NULL, NULL);
}
return s;
}
IShellItem* toShellItem(const YourStringType &path)
{
IShellItem *pItem = NULL;
if (FAILED(SHCreateItemFromParsingName(toWString(path).c_str(), NULL, IID_PPV_ARGS(&pItem))))
pItem = NULL;
return pItem;
}
bool wvFM::SelectFileSystemObjectDialogTree(const WCDialogCreationOptions& in_options,
WCDialogReply& out_Reply)
{
AUTO_FUNC_DEBUG;
out_Reply.accept = false;
if (in_options.m_flags[WCDialogCreationOptions::eSelectFolder]) {
IFileOpenDialog *pFileOpen = NULL;
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_PPV_ARGS(&pFileOpen))))
return false;
FILEOPENDIALOGOPTIONS opts = 0;
pFileOpen->GetOptions(&opts);
pFileOpen->SetTitle(toWString(in_options.m_windowTitle).c_str());
pFileOpen->SetOptions(opts | FOS_PICKFOLDERS);
IShellItem *pItem = toShellItem(in_options.m_InitialDir);
if (pItem)
{
pFileOpen->SetFolder(pItem);
pItem->Release();
}
HWND hwndOwner = (HWND) in_options.m_owner;
HRESULT hr = pFileOpen->Show(hwndOwner);
::SetFocus(hwndOwner);
if (SUCCEEDED(hr))
{
if (SUCCEEDED(pFileOpen->GetResult(&pItem)))
{
PWSTR pszFilePath;
if (SUCCEEDED(pItem->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath)))
{
out_Reply.m_filePathRef = wvFM::WCStPath(toString(pszFilePath).c_str());
out_Reply.accept = true;
CoTaskMemFree(pszFilePath);
}
pItem->Release();
}
}
pFileOpen->Release();
return true;
}
...
}

How to validate credentials with CredUIPromptForWindowsCredentials

I don't know why I can't unpack the authentification buffer used in CredUIPromptForWindowsCredentials with CredUnPackAuthenticationBufferW, I always get ERROR_INSUFFICIENT_BUFFER error.
I will appreciate your help.
std::wstring caption = L"Caption";
std::wstring msg= L"Msg";
CREDUI_INFOW credui = {};
credui.cbSize = sizeof(credui);
credui.hwndParent = nullptr;
credui.pszMessageText = msg.c_str();
credui.pszCaptionText = caption.c_str();
credui.hbmBanner = nullptr;
ULONG authPackage = 0;
LPVOID outCredBuffer = nullptr;
ULONG outCredSize = 0;
BOOL save = false;
LPWSTR pszUserName = nullptr;
DWORD pcchlMaxUserName = 0;
LPWSTR pszDomainName = nullptr;
DWORD pcchMaxDomainName = 0;
LPWSTR pszPassword = nullptr;
DWORD pcchMaxPassword = 0;
DWORD result = CredUIPromptForWindowsCredentialsW(&credui,
0,
&authPackage,
nullptr,
0,
&outCredBuffer,
&outCredSize,
&save,
CREDUIWIN_ENUMERATE_ADMINS);
std::cout <<CredUnPackAuthenticationBufferW(CRED_PACK_PROTECTED_CREDENTIALS
,outCredBuffer
,outCredSize
,pszUserName
,&pcchlMaxUserName
,pszDomainName
,&pcchMaxDomainName
,pszPassword
,&pcchMaxPassword) << std::endl;
std::cout << GetLastError() << std::endl; // out put 122 == ERROR_INSUFFICIENT_BUFFER
this is typical winapi pattern - api must return some information in the memory buffer. but instead allocate buffer yourself - it obligate caller to allocate buffer.
so caller must allocate buffer itself and pass it pointer and size to api.
api check buffer size - if it large enough fill information to buffer, otherwise return ERROR_INSUFFICIENT_BUFFER (assume that no another errors) or sometime ERROR_MORE_DATA. which which concrete error reurned ERROR_INSUFFICIENT_BUFFER or ERROR_MORE_DATA usual direct documented for api call. different between this 2 errors: ERROR_INSUFFICIENT_BUFFER - mean no any info filled to buffer at all, when ERROR_MORE_DATA mean some data is returned, but incomplete.
and api return to user, via some out parameter, required buffer size in this case. frequently this is done via the same inout parameter - pointer to DWORD. in input specifies the size of user allocated buffer, in output - specifies the required size of buffer or size of returned data
frequently which buffer size is required - unknown at begin. so we need or call api with 0 size buffers(s) first, or allocate some, supposedly sufficient buffer size. if buffer will be insuffient - reallocate or extend it and call api again. for some api (like CredUnPackAuthenticationBufferW) the required output buffer does not change with time (if input parameters not changed), but usual output buffer size may change between calls - even second call with buffer size returned by first call can fail with buffer size error (because returned data may grow between calls). in this case need call api in do/while(error == ERROR_INSUFFICIENT_BUFFER/ERROR_MORE_DATA) loop. but even in case output buffer does not change with time we can better do this is loop with single api call inside, instead 2 api calls.
for concrete case code can look like
ULONG cred()
{
CREDUI_INFO ci = { sizeof(ci) };
BOOL bSave = FALSE;
PVOID pvOutAuthBuffer;
ULONG ulOutAuthBufferSize;
ULONG ulAuthPackage = 0;
ULONG dwError = CredUIPromptForWindowsCredentials(
&ci, NOERROR, &ulAuthPackage, 0, 0,
&pvOutAuthBuffer, &ulOutAuthBufferSize,
&bSave, CREDUIWIN_ENUMERATE_ADMINS );
if (dwError == NOERROR)
{
ULONG cchUserName = 0;
ULONG cchPassword = 0;
ULONG cchDomain = 0;
static volatile UCHAR guz = 0;
PWSTR stack = (PWSTR)alloca(guz);
PWSTR szUserName = 0, szPassword = 0, szDomainName = 0;
ULONG cchNeed, cchAllocated = 0;
do
{
if (cchAllocated < (cchNeed = cchUserName + cchPassword + cchDomain))
{
szUserName = (PWSTR)alloca((cchNeed - cchAllocated) * sizeof(WCHAR));
cchAllocated = (ULONG)(stack - szUserName);
szPassword = szUserName + cchUserName;
szDomainName = szPassword + cchPassword;
}
dwError = CredUnPackAuthenticationBuffer(
CRED_PACK_PROTECTED_CREDENTIALS,
pvOutAuthBuffer, ulOutAuthBufferSize,
szUserName, &cchUserName,
szDomainName, &cchDomain,
szPassword, &cchPassword)
? NOERROR : GetLastError();
if (dwError == NOERROR)
{
DbgPrint("%S#%S %S\n", szDomainName, szUserName, szPassword);
break;
}
} while (dwError == ERROR_INSUFFICIENT_BUFFER);
CoTaskMemFree(pvOutAuthBuffer);
}
return dwError;
}
#RbMm - you're right! I tested it with LogonUser, and it works perfectly. Thanks.
And for a ready solution, I got this :
bool Authenticate_ADMIN_User(std::wstring caption, std::wstring msg, int maxReAsks = 0)
{
CREDUI_INFOW credui = {};
credui.cbSize = sizeof(credui);
credui.hwndParent = nullptr;
credui.pszMessageText = msg.c_str();
credui.pszCaptionText = caption.c_str();
credui.hbmBanner = nullptr;
ULONG authPackage = 0,
outCredSize = 0;
LPVOID outCredBuffer = nullptr;
BOOL save = false;
DWORD err = 0;
int tries = 0;
bool reAsk = false;
do
{
tries++;
if(CredUIPromptForWindowsCredentialsW(&credui,
err,
&authPackage,
nullptr,
0,
&outCredBuffer,
&outCredSize,
&save,
CREDUIWIN_ENUMERATE_ADMINS)
!= ERROR_SUCCESS)
return false;
ULONG cchUserName = 0;
ULONG cchPassword = 0;
ULONG cchDomain = 0;
ULONG cchNeed, cchAllocated = 0;
static volatile UCHAR guz = 0;
PWSTR stack = (PWSTR)alloca(guz);
PWSTR szUserName = nullptr, szPassword = nullptr, szDomainName = nullptr;
BOOL ret;
do{
if (cchAllocated < (cchNeed = cchUserName + cchPassword + cchDomain))
{
szUserName = (PWSTR)alloca((cchNeed - cchAllocated) * sizeof(WCHAR));
cchAllocated = (ULONG)(stack - szUserName);
szPassword = szUserName + cchUserName;
szDomainName = szPassword + cchPassword;
}
ret = CredUnPackAuthenticationBuffer(
CRED_PACK_PROTECTED_CREDENTIALS , outCredBuffer, outCredSize, szUserName, &cchUserName,
szDomainName, &cchDomain, szPassword,
&cchPassword);
}while(!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
SecureZeroMemory(outCredBuffer, outCredSize);
CoTaskMemFree(outCredBuffer);
HANDLE handle = nullptr;
if (LogonUser(szUserName,
szDomainName,
szPassword,
LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT,
&handle))
{
CloseHandle(handle);
return true;
}
else
{
err = ERROR_LOGON_FAILURE;
reAsk = true;
}
}while(reAsk && tries < maxReAsks);
return false;
}

C++ Open file dialog in window

I have C++ code to show dialog chooser file. I want to the user can only chooser type file specified. My dialog can show type file specified but the user can input other type file in File name like my picture
So, how can I make the user only input File name and search type file specified in lpstrFilter? OR Can i disable File name box?
This is my code:
const wchar_t* ChooserFile(const char* typeFile)
{
try
{
ZeroMemory( &sfn , sizeof( sfn));
sfn.lStructSize = sizeof ( sfn );
sfn.hwndOwner = NULL ;
wchar_t w_syFile[MAX_PATH];
//mbstowcs(w_syFile, syFile, strlen(syFile)+1);//Plus null
size_t convertedChars = 0;
mbstowcs_s(&convertedChars, w_syFile, MAX_PATH, syFile, _TRUNCATE);
sfn.lpstrFile = w_syFile ;
sfn.lpstrFile[0] = _T('\0');
sfn.nMaxFile = sizeof( syFile );
//TypeFile
sfn.lpstrFilter = TEXT("Microsoft Office Word Documents (*.xlsx)\0*.XLSX\0");
sfn.nFilterIndex =1;
sfn.lpstrFileTitle = NULL ;
sfn.nMaxFileTitle = 0 ;
sfn.lpstrInitialDir=NULL;
//sfn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT|OFN_EXPLORER | OFN_ENABLEHOOK ;
sfn.Flags = OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST|OFN_NOVALIDATE|OFN_HIDEREADONLY ;
if (GetOpenFileName( &sfn ) != TRUE)
{
wstrPathFile = TEXT("");
return wstrPathFile.c_str();
}
DWORD retval=0;
//BOOL success;
TCHAR buffer[BUFSIZE]=TEXT("");
TCHAR buf[BUFSIZE]=TEXT("");
TCHAR** lppPart={NULL};
wchar_t wstrPath[BUFSIZE];
retval = GetFullPathNameW(sfn.lpstrFile,sfn.nMaxFile,wstrPath,lppPart);
if (retval==0)
{
wstrPathFile = TEXT("");
return wstrPathFile.c_str();
}
std::wstring s(wstrPath);
wstrPathFile = s;
wcout<<wstrPathFile<<endl;
return wstrPathFile.c_str();
}
catch (...)
{
PrintToFile("ChooserFile","Error");
wstrPathFile = TEXT("");
return wstrPathFile.c_str();
}
}
I want to the user can only chooser type file specified.
You can't stop the user choosing whatever file they like by typing into the file name edit control. So, you should simply let them do that and instead validate that the file name matches your requirements.
You have a couple of options to do that:
Let the dialog return and if the file name does not meet your requirements, present the user with an error dialog letting them know what went wrong.
Supply a hook procedure in the lpfnHook member of the OPENFILENAME struct. That will get sent a CDN_FILEOK notification message when the user attempts to accept a file. Perform your validation in response to that message. If the file name does not meet requirements, show a message to that effect and return a non-zero value to force the dialog to remain open.
Your code is commenting out the OFN_EXPLORER and OFN_ENABLEHOOK flags, so you must already know about the existence of Explorer-style hooking. As others have told you, you can use that hook to catch the CDN_FILEOK notification to accept/reject a selected filename. For example:
UINT_PTR CALLBACK MyOFNHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
if (uiMsg == WM_NOTIFY)
{
LPOFNOTIFY ofn = (LPOFNOTIFY) lParam;
if (ofn->hdr.code == CDN_FILEOK)
{
LPOPENFILENAMEW lpOFN = (LPOPENFILENAMEW) ofn->lpOFN;
LPWSTR lpExt = PathFindExtensionW(lpOFN->lpstrFile);
if (lstrcmpiW(lpExt, L".XLSX") != 0)
{
SetWindowLongPtr(hdlg, DWL_MSGRESULT, 1);
return 1;
}
}
}
return 0;
}
std::wstring ChooserFile(const char* typeFile)
{
OPENFILEAMEW sfn = {0};
wchar_t w_syFile[MAX_PATH+1] = {0};
size_t convertedChars = 0;
sfn.lStructSize = sizeof(sfn);
sfn.hwndOwner = NULL;
mbstowcs_s(&convertedChars, w_syFile, MAX_PATH, syFile, _TRUNCATE);
sfn.lpstrFile = w_syFile;
sfn.nMaxFile = MAX_PATH;
//TypeFile
sfn.lpstrFilter = L"Microsoft Office Word Documents (*.xlsx)\0*.XLSX\0";
sfn.nFilterIndex = 1;
sfn.lpstrFileTitle = NULL;
sfn.nMaxFileTitle = 0;
sfn.lpstrInitialDir = NULL;
sfn.lpfnHook = &MyOFNHookProc;
sfn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOVALIDATE | OFN_HIDEREADONLY | OFN_EXPLORER | OFN_ENABLEHOOK;
if (!GetOpenFileNameW(&sfn))
return L"";
WCHAR szPath[MAX_PATH+1] = {0};
DWORD retval = GetFullPathNameW(sfn.lpstrFile, MAX_PATH, szPath, NULL);
if ((retval == 0) || (retval > MAX_PATH))
return L"";
std::wstring wstrPath(szPath, retval);
std::wcout << wstrPath << endl;
return wstrPath;
}

WinHttpReceiveResponse function return an error

Can someone tell me what is wrong in the code below?
void Mess(LPCWSTR Str)
{
MessageBox(0, Str, L"Hi", 0);
}
int main()
{
// HttpOpen
HINTERNET hHttp = NULL;
LPCWSTR lpcwAgent = L"UserAgent";
DWORD dwAccessType = WINHTTP_ACCESS_TYPE_NO_PROXY;
LPCWSTR lpcwProxyName = WINHTTP_NO_PROXY_NAME;
LPCWSTR lpcwProxyByPass = WINHTTP_NO_PROXY_BYPASS;
DWORD dwFlag = 0;
// HttpConnect
HINTERNET hConnect = NULL;
LPCWSTR lpcwServerName = L"localhost";
INTERNET_PORT Port = INTERNET_DEFAULT_HTTP_PORT;
DWORD dwReserved = 0; //must be 0
// HttpOpenRequest
HINTERNET hRequest = NULL;
LPCWSTR lpcwVerb = L"GET"; // or POST, PUT
LPCWSTR lpcwObjectName = L"/index.php";
LPCWSTR lpcwVersion = NULL; //NULL == HTTP/1.1
LPCWSTR lpcwReferrer = WINHTTP_NO_REFERER; // It mean there's no referrer
LPCWSTR* plpcwAccept = WINHTTP_DEFAULT_ACCEPT_TYPES; // For more information: Media types (http://www.iana.org/assi gnments/medi a-types)
DWORD dwRequestFlag = 0;
// HttpSendRequest
bool bSendRequest = false;
LPCWSTR lpcwHeaders = WINHTTP_NO_ADDITIONAL_HEADERS; // Additional headers to append to the request
DWORD dwHeaderLength = 0;
LPVOID lpvOptional = WINHTTP_NO_REQUEST_DATA; //The data which is used for POST or PUT
DWORD dwOptionalLength = 0;
DWORD dwTotalLength = 0;
DWORD_PTR pdwContext = NULL;
// HttpReceiveResponse
bool bReceiveResponse = false;
HINTERNET _hRequest = NULL; // Will be set again after HttpOpenRequest are completed
LPVOID lpvReserved = NULL;
hHttp = WinHttpOpen(lpcwAgent, dwAccessType, lpcwProxyName, lpcwProxyByPass, dwFlag);
if ( hHttp == NULL )
{
Mess(L"Unable to open a connection");
}
else
{
hConnect = WinHttpConnect(hHttp, lpcwServerName, Port, dwReserved);
if ( hConnect == NULL )
{
Mess(L"Unable to Connecting");
}
else
{
hRequest = WinHttpOpenRequest(hConnect, lpcwVerb, lpcwObjectName, lpcwVersion, lpcwReferrer, plpcwAccept, dwRequestFlag);
if ( hRequest == NULL )
{
Mess(L"Unable to open the request");
}
else
{
bSendRequest = WinHttpSendRequest(hRequest, lpcwHeaders, dwHeaderLength, lpvOptional, dwOptionalLength, dwTotalLength, pdwContext);
if ( !bSendRequest )
{
Mess(L"Failed to send the request");
}
else
{
bReceiveResponse = WinHttpReceiveResponse(_hRequest, lpvReserved);
if ( !bReceiveResponse )
{
Mess(L"Unable to receive the response");
}
else
{
Mess(L"Ok");
}
}
}
}
}
if ( hRequest != NULL )
WinHttpCloseHandle(hRequest);
if ( hConnect != NULL )
WinHttpCloseHandle(hConnect);
if ( hHttp != NULL )
WinHttpCloseHandle(hHttp);
return 0;
}
I don't understand WINHTTP much but I'm trying.
When I excute the program, I get
Unable to receive the response
then, I use GetLastError() to get the code of the error that always is 6. I can't find anything about code 6?
Error code 6 is ERROR_INVALID_HANDLE "The handle is invalid."
The problem is that you use wrong variable for the request handle: _hRequest whereas you were to use hRequest instead.
WinHttpReceiveResponse(_hRequest, ...

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.