Error 12006 in WinHttpCrackUrl - c++

I'm trying to build an address from a variable. So I can pass it to WinHttpOpenRequest.
char *uNameAddr = (char*) ExeBaseAddress + 0x34F01C;
printf("%s \n", uNameAddr);
string url = "http://xxxx.xxxx.com/xxxx/?u=";
string username = uNameAddr;
string combine = url + username;
cout << combine << endl;
//http://xxxx.xxxx.com/xxxx/?u=MyUsername <--
URL_COMPONENTS urlComp;
LPCWSTR pwszUrl1 = (LPCWSTR)combine.c_str();
DWORD dwUrlLen = 0;
Then I have to pass it here:
hRequest = WinHttpOpenRequest( hConnect, L"GET", urlComp.lpszUrlPath,
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0);
urlComp.lpszUrlPath should be http://xxxx.xxxx.com/xxxx/?u=MyUsername
Any advice? My application crashes when it gets to process that part.
ERROR
12006 ERROR_INTERNET_UNRECOGNIZED_SCHEME
The URL scheme could not be recognized or is not supported.

LPCWSTR pwszUrl1 = (LPCWSTR)combine.c_str();
std::string::c_str returns const char *. LPCWSTR is const wchar_t *.
Casting to LPCWSTR is lying to the compiler and yourself, what combine.c_str() returns is not a pointer to a wide-character string.
You'll likely have better success with std::wstring, which represents wide-character strings.
Consider reading Unicode in the Windows API for more information.

Related

Cannot add TCHAR* to const char

Hello I'm trying to make my application to run on startup, and to do this to work on my clients PC firstly I needed to get their PC username, but when I'm trying to make this working I'm getting this error :
E2140 expression must have integral or unscoped enum type
Here's the code:
HKEY hKey;
const char* czStartName = "MY application";
TCHAR pcusername[UNLEN + 1];
DWORD pcusername_len = UNLEN + 1;
GetUserName((TCHAR*)pcusername, &pcusername_len);
const char* czExePath = "\"C:\\Users\\" + pcusername + "\\Desktop\\Myapplication.exe\" /background";
How Can I convert TCHAR* to Const Char?
As others have said in the comments, you cannot concatenate strings in C using the addition operator. You can do something like in this example:
#include <string.h>
char buf[4096];
snprintf(buf, sizeof(buf), "\"C:\\Users\\%s\\Desktop\\Myapplication.exe\" /background", username);
const char* czExePath = buf;

.c_str() doesn't behave as expected

I want to create a process to read out some serial port. However the user should be able to change the path where the program is located in the future. This is why I would like to include the variable BasePathFile, which is set to the default value durin the initialization of the class:
const std::string BP = "C:\\aerospec_developement\\";
...
BasePathFile = BP;
...
Can someone explain why //1 doesn't work, but //2 is fine
void AerospecGUI::ReadPressure()
{
//1 const char *Args = ("C:\\Windows\\System32\\cmd.exe /C powershell /C "+ BasePathFile+"sourcecode\\pressure.ps1 -comport COM4 -baud 1200 -parity None -data 8 -stopbits one").c_str();
//2 const char *Args = "C:\\Windows\\System32\\cmd.exe /C powershell /C C:\\aerospec_developement\\sourcecode\\pressure.ps1 -comport COM4 -baud 1200 -parity None -data 8 -stopbits one";
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
memset(&StartupInfo, 0, sizeof(StartupInfo));
memset(&ProcessInfo, 0, sizeof(ProcessInfo));
StartupInfo.cb = sizeof(StartupInfo);
wchar_t wargs[1000];
mbstowcs(wargs, Args, strlen(Args)+1);//Plus null
LPWSTR argsptr = wargs;
bool result = CreateProcess(NULL, argsptr, NULL, NULL, FALSE, NULL, NULL, NULL,
&StartupInfo, &ProcessInfo);
...
Further, the author wrote a very similar line in another function. But this one worked.
bool AerospecGUI::FTP(std::string command, std::string file)
{
// This function executes a batch script with the given parameters. The batch script
// generates a .ftp file which contains the commands to perform the action given by "command"
// (get, put, delete).
const char *Args = ("C:\\Windows\\System32\\cmd.exe /C "+BasePathFile +"FTP\\FileTransfer.bat " + ServerURL + " root password " + command + " " + BasePathFile + "FTP\\ " + file +" " + BasePathFile + "FTP\\" + file.substr(0,file.size()-4)+".ftp").c_str();
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
memset(&StartupInfo, 0, sizeof(StartupInfo));
memset(&ProcessInfo, 0, sizeof(ProcessInfo));
StartupInfo.cb = sizeof(StartupInfo);
wchar_t wargs[1000];
mbstowcs(wargs, Args, strlen(Args)+1);//Plus null
LPWSTR argsptr = wargs;
...
1 and the original author code are wrong: c_str() returns a pointer to a C-like string, but it's a member function of the std::string class (see docs). Dereferencing its pointer after the std::string object has expired is undefined behavior (may or may not work).
2 works fine instead
const char *Args = "C:\\... one";
since it's a string literal and its lifetime spans for the entire program execution.
For 1 you create a temporary std::string object, and gets a pointer to its internal string. Once the temporary object is destructed the string ceases to exist and the pointer will not be pointing anywhere valid.
For 2 you have an actual constant string literal, who has a lifetime of the program and will never cease to exist.
That is seems to be working for your second example is just a fluke. What you have with the stray invalid pointer is undefined behavior and sometimes those might seem to work just fine.

I want to copy the data in (wchar_t *)buffer but i am unable to do so bcz there are other incompatible types,typecasting but not getting the result?

I want to print buffer data at one instance avoiding all other wprintf instances but unable to convert data in compatible type with buffer.
Have a look at code:
Kindly tell me how to get through it:
DWORD PrintEvent(EVT_HANDLE hEvent)
{
DWORD status = ERROR_SUCCESS;
PEVT_VARIANT pRenderedValues = NULL;
WCHAR wsGuid[50];
LPWSTR pwsSid = NULL;
//
// Beginning of functional Logic
//
for (;;)
{
if (!EvtRender(hContext, hEvent, EvtRenderEventValues, dwBufferSize, pRenderedValues, &dwBufferUsed, &dwPropertyCount))
{
if (ERROR_INSUFFICIENT_BUFFER == (status = GetLastError()))
{
dwBufferSize = dwBufferUsed;
dwBytesToWrite = dwBufferSize;
pRenderedValues = (PEVT_VARIANT)malloc(dwBufferSize);
if (pRenderedValues)
{
EvtRender(hContext, hEvent, EvtRenderEventValues, dwBufferSize, pRenderedValues, &dwBufferUsed, &dwPropertyCount);
}
else
{
printf("malloc failed\n");
status = ERROR_OUTOFMEMORY;
break;
}
}
}
Buffer = (wchar_t*) malloc (1*wcslen(pRenderedValues[EvtSystemProviderName].StringVal));
//
// Print the values from the System section of the element.
wcscpy(Buffer,pRenderedValues[EvtSystemProviderName].StringVal);
int i = wcslen(Buffer);
if (NULL != pRenderedValues[EvtSystemProviderGuid].GuidVal)
{
StringFromGUID2(*(pRenderedValues[EvtSystemProviderGuid].GuidVal), wsGuid, sizeof(wsGuid)/sizeof(WCHAR));
wcscpy(Buffer+i,(wchar_t*)pRenderedValues[EvtSystemProviderGuid].GuidVal);
wprintf(L"Provider Guid: %s\n", wsGuid);
}
//Getting "??????" on screen after inclusion of guidval tell me the correct way to copy it??
wprintf(L"Buffer = %ls",Buffer);
//Also tell the way to copy unsigned values into buffer
wprintf(L"EventID: %lu\n", EventID);
wprintf(L"Version: %u\n", pRenderedValues[EvtSystemVersion].ByteVal);
wprintf(L"Level: %u\n", pRenderedValues[EvtSystemLevel].ByteVal);
wprintf(L"EventRecordID: %I64u\n", pRenderedValues[EvtSystemEventRecordId].UInt64Val);
if (EvtVarTypeNull != pRenderedValues[EvtSystemActivityID].Type)
{
StringFromGUID2(*(pRenderedValues[EvtSystemActivityID].GuidVal), wsGuid, sizeof(wsGuid)/sizeof(WCHAR));
wprintf(L"Correlation ActivityID: %s\n", wsGuid);
}
if (EvtVarTypeNull != pRenderedValues[EvtSystemRelatedActivityID].Type)
{
StringFromGUID2(*(pRenderedValues[EvtSystemRelatedActivityID].GuidVal), wsGuid, sizeof(wsGuid)/sizeof(WCHAR));
wprintf(L"Correlation RelatedActivityID: %s\n", wsGuid);
}
wprintf(L"Execution ProcessID: %lu\n", pRenderedValues[EvtSystemProcessID].UInt32Val);
wprintf(L"Execution ThreadID: %lu\n", pRenderedValues[EvtSystemThreadID].UInt32Val);
wprintf(L"Channel: %s\n",pRenderedValues[EvtSystemChannel].StringVal);
wprintf(L"Computer: %s\n", pRenderedValues[EvtSystemComputer].StringVal);
//
// Final Break Point
//
break;
}
}
The first error is when starting to write to the buffer:
Buffer = (wchar_t*) malloc (1*wcslen(pRenderedValues[EvtSystemProviderName].StringVal));
wcscpy(Buffer,pRenderedValues[EvtSystemProviderName].StringVal);
StringVal points to a wide character string with a trailing null byte, so you should
Buffer = malloc (sizeof(wchar_t)*(wcslen(pRenderedValues[EvtSystemProviderName].StringVal)+1));
or even better
Buffer = wcsdup(pRenderedValues[EvtSystemProviderName].StringVal);
Second error is when appending the GUID.
You are not allocating enough memory, you are just appending to the already full Buffer. And you are appending the raw GUID, not the GUID string. You should replace
int i = wcslen(Buffer);
wcscpy(Buffer+i,(wchar_t*)pRenderedValues[EvtSystemProviderGuid].GuidVal);
with something like
// Attention: memory leak if realloc returns NULL! So better use a second variable for the return code and check that before assigning to Buffer.
Buffer = realloc(Buffer, wcslen(Buffer) + wcslen(wsGuid) + 1);
wcscat(Buffer,wsGuid);
Also:
Besides, you should do better error checking for EvtRender. And you should check dwPropertyCount before accessing pRenderedValues[i].
BTW, wprintf(L"Buffer = %s",Buffer); (with %s instead of %ls) is sufficient with wprintf.
And to your last question: if you want to append unsigned values to a buffer you can use wsprintf to write to a string. If you can do it C++-only then you should consider using std::wstring. This is much easier for you with regard to allocating the buffers the right size.

C++ chars stored in the LPCSTR .. broken?

LPCSTR dllPath = ExePath().append("\\").append(DEF_INJECT_DLL).c_str();
DWORD dwBufSize = (DWORD)(strlen(dllPath) + 1) * sizeof(LPCSTR);
/* test */
char tbuf[1024]= {0,};
sprintf_s(tbuf, "dllPath : %s\r\ndwBufSize : %d", dllPath, dwBufSize);
MessageBoxA(NULL, tbuf, "TEST", MB_OK);
part of the code to inject my dll.
ExePath() is a function to get AbsolutePath of std::string data type using GetModuleFileNameA API and so on.
DEF_INJECT_DLL is defined by #define "MyDll.dll"
But when I run this code, it shows me broken strings....
And, when I change the MessageBoxA to this:
MessageBoxA(NULL,
ExePath().append("\\").append(DEF_INJECT_DLL).c_str(),
"TEST",
MB_OK);
it shows properly?
Also, I tried in this way:
MessageBoxA(NULL,dllPath, "TEST", MB_OK);
but it shows to me like first screenshot.
What is the problem?
The problem is in this line:
LPCSTR dllPath = ExePath().append("\\").append(DEF_INJECT_DLL).c_str();
here you call ExePath(), which returns a std::string instance, modify it, and finally call c_str() to get the raw data buffer.
However, the return value is a temporary object. After that line, the returned std::string is deleted, and will clean its memory. Therefore, the address where dllPath points to is no longer valid!
You could store the return value in a local instance, e.g.
std::string str = ExePath().append("\\").append(DEF_INJECT_DLL);
LPCSTR dllPath = str.c_str();

C++ Get Program files dir, append extra path and execute

I'm trying to write a few simple lines of code that will get the 'Program Files' dir path on both XP and Vista/7 (on vista/7 I need the path to the x86 folder), add some extra path to an application and execute it.
This is what I have so far, but it's not executing the external program, not giving an error as well..
wchar_t localAppData[MAX_PATH];
STARTUPINFO sInfo;
PROCESS_INFORMATION pInfo;
SHGetFolderPath(NULL, CSIDL_PROGRAM_FILESX86, 0, NULL, localAppData);
std::wstringstream ss;
ss << localAppData << L"/MyApp/MyExe.exe";
LPCWSTR str = ss.str().c_str();
CreateProcess(str, NULL,NULL, NULL,FALSE,NULL,NULL,NULL,&sInfo,&pInfo);
return str;
I've updated my code to this according to hmjd's suggestion:
wchar_t localAppData[MAX_PATH];
STARTUPINFO sInfo = { sizeof(STARTUPINFO), NULL, L"winsta0\\default" };
PROCESS_INFORMATION pInfo;
SHGetFolderPath(NULL, CSIDL_PROGRAM_FILESX86, 0, NULL, localAppData);
std::wstringstream ss;
ss << localAppData << L"/PacificPoker/bin/888poker.exe";
std::wstring ss_str = ss.str();
wchar_t* path = new wchar_t[ss_str.length() + 1]();
std::copy(ss_str.begin(), ss_str.end(), path);
CreateProcess(path, NULL,NULL, NULL,FALSE,NULL,NULL,NULL,&sInfo,&pInfo);
delete[] path;
return GetLastError();
Still getting '3' for GetLastError, but I can confirm that C:\Program Files\MyApp\MyExe.exe exists..
A few problems with the code:
sInfo is not initialised, you at least need to set the cb member
STARTUPINFO sInfo = { sizeof(STARTUPINFO), // 'cb'
NULL, // 'lpReserved'
L"winsta0\\default" };// 'lpDesktop'
See STARTUPINFO for more details.
the first argument to CreateProcess() should be non-const, but is being passed c_str() which would be a const if it was not a dangling pointer. The ss.str() method returns a std::string, and the c_str() is returning a pointer into that std::string but it is a temporary object and is destroyed at the end of the expression (the ;), making str a dangling pointer. Change to:
std::wstring ss_str = ss.str();
wchar_t* path = new wchar_t[ss_str.length() + 1]();
std::copy(ss_str.begin(), ss_str.end(), path);
CreateProcess(path, ...);
delete[] path;
Check return values of all your functions and query GetLastError() to determine failure reason.
You've probably tried this, but does localAppData get a valid string if you set the CSIDL to CSIDL_PROGRAM_FILES instead of CSIDL_PROGRAM_FILESX86?
If you're testing under XP, I don't know what CSIDL_PROGRAM_FILESX86 will return.