Cannot add TCHAR* to const char - c++

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;

Related

Libwesockets.h: Issue with lws_write: C++ string to C conversion and send

I'm using g++.
Code:
std::string str = "{\"action\":3,\"data\":{\"account\":\"somehashgoeshear\",\"someint\":0,\"id\":1,\"moreint\":0,\"name\":\"demo\"}}";
char *cstr = strdup(str.c_str());
lwsl_notice("\n%s", cstr);
return lws_write(wsi, (unsigned char*)cstr, strlen(cstr), LWS_WRITE_TEXT);
This also doesn't work:
std::string str = "{\"action\":3,\"data\":{\"account\":\"somehashgoeshear\",\"someint\":0,\"id\":1,\"moreint\":0,\"name\":\"demo\"}}";
return lws_write(wsi, (unsigned char*)str.c_str(), strlen(str.c_str()), LWS_WRITE_TEXT);
But this works fine (runs many times without some error):
char cstr[96] = "{\"action\":3,\"data\":{\"account\":\"somehashgoeshear\",\"someint\":0,\"id\":1,\"moreint\":0,\"name\":\"demo\"}}";
return lws_write(wsi, (unsigned char*)cstr, strlen(cstr), LWS_WRITE_TEXT);
Tried also to create string with malloc but this doesn't work as well:
std::string str = "{\"action\":3,\"data\":{\"account\":\"somehashgoeshear\",\"someint\":0,\"id\":1,\"moreint\":0,\"name\":\"demo\"}}";
char *cstr = (char *)malloc((str.length() + 1) * sizeof(char));
strcpy(cstr, str.c_str());
lwsl_notice("\n%s", cstr);
return lws_write(wsi, (unsigned char*)cstr, strlen(cstr), LWS_WRITE_TEXT);
I can run this code couple times but eventually I'm getting this error:
free(): invalid next size (fast)
(fails after data was sent)
I tried also couple experiments with LWS_PRE but when I add this to the string it adds couple symbols at the start of message like: a":
When I try free(cstr) after sending the data it fails immediately with double free or corruption (out) error.
lws version: 1.7.1
os: ubuntu x64
According to documentation https://libwebsockets.org/lws-api-doc-master/html/group__sending-data.html#gafd5fdd285a0e25ba7e3e1051deec1001
IMPORTANT NOTICE!
When sending with websocket protocol
LWS_WRITE_TEXT, LWS_WRITE_BINARY, LWS_WRITE_CONTINUATION,
LWS_WRITE_PING, LWS_WRITE_PONG,
or sending on http/2,
the send buffer has to have LWS_PRE bytes valid BEFORE the buffer
pointer you pass to lws_write().
This means that you have to allocate extra LWS_PRE bytes for your buffer i.e
std::string str(LWS_PRE, ' '); //Allocate LWS_PRE bytes
str += "{\"action\":3,\"data\":{\"account\":\"somehashgoeshear\",\"someint\":0,\"id\":1,\"moreint\":0,\"name\":\"demo\"}}"
return lws_write(wsi, (unsigned char*)&str[LWS_PRE], str.size(), LWS_WRITE_TEXT);
Using malloc
char* createMessage() {
std::string str = "{\"action\":3,\"data\":{\"account\":\"somehashgoeshear\",\"someint\":0,\"id\":1,\"moreint\":0,\"name\":\"demo\"}}";
char *cstr = (char *)malloc(LWS_PRE + (str.length() + 1) * sizeof(char));
cstr += LWS_PRE;
strcpy(cstr, str.c_str());
lwsl_notice("\n%s", cstr);
return cstr;
}
...
char* msg = createMessage();
lws_write(wsi,
(unsigned char*)msg,
strlen(msg) /* add 1 if receiver expects the null character*/,
LWS_WRITE_TEXT);
free(msg - LWS_PRE);
Simple way to send C++ strings with libwebsockets:
std::string payload = "Some sample string.";
// prepare payload with lws header
std::string buffer(LWS_SEND_BUFFER_PRE_PADDING + payload.size(), ' ');
buffer.insert(LWS_SEND_BUFFER_PRE_PADDING, payload);
// send message
lws_write(wsi, (unsigned char*) &buffer[LWS_SEND_BUFFER_PRE_PADDING], payload.size(), LWS_WRITE_TEXT);

WideCharToMultiByte std analog UTF8

This code is workng properly for me:
std::wstring wmsg_text = L"キエオイウカクケコサシスセソタチツテア";
char buffer[100] = { 0 };
WideCharToMultiByte(CP_UTF8, 0, wmsg_text.data(), wmsg_text.size(), buffer, sizeof(buffer)-1, NULL, NULL);
I wonder the cross platform analog of this code. I look to std::wcstombs with std::codecvt_utf8, but can't guess how to use this by right way.
You want to use std::wcsrtombs, something like:
std::wstring wmsg_text = L"キエオイウカクケコサシスセソタチツテア";
const wchar_t* wstr = wmsg_text.data();
std::mbstate_t state = std::mbstate_t();
int len = 1 + std::wcsrtombs(nullptr, &wstr, 0, &state);
std::vector<char> mbstr(len);
std::wcsrtombs(&mbstr[0], &wstr, mbstr.size(), &state);
char* buffer = mbstr.data();
This code is working properly, too:
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
std::string u8str = conv.to_bytes(msg);

Simple C++ connection to mysql database

I just started with c++, after reading some tutorials I'm trying to create a simple myqsl connection with a database. Keep in mind that I'm mainly a web developer hence this is a new thing for me. My current code (taken from a tutorial) is this:
#include <mysql.h>
#include <stdio.h>
#include <stdlib.h>
//#include <string>
using namespace std;
struct connection_details
{
char *server;
char *user;
char *password;
char *database;
};
MYSQL* mysql_connection_setup(struct connection_details mysql_details) {
MYSQL *connection = mysql_init(NULL);
if (!mysql_real_connect(connection,mysql_details.server, mysql_details.user, mysql_details.password, mysql_details.database, 0, NULL, 0)) {
printf("Conection error : %s\n", mysql_error(connection));
exit(1);
}
return connection;
}
MYSQL_RES* mysql_perform_query(MYSQL *connection, char *sql_query) {
if (mysql_query(connection, sql_query)) {
printf("MySQL query error : %s\n", mysql_error(connection));
exit(1);
}
return mysql_use_result(connection);
}
int main() {
MYSQL *conn; // the connection
MYSQL_RES *res; // the results
MYSQL_ROW row; // the results row (line by line)
struct connection_details mysqlD;
mysqlD.server = "localhost"; // line 46
mysqlD.user = "root"; // line 47
mysqlD.password = "root"; // line 48
mysqlD.database = "backseat"; // line 49
conn = mysql_connection_setup(mysqlD);
res = mysql_perform_query(conn, "show tables"); // line 53
printf("MySQL Tables in mysql database:\n");
while ((row = mysql_fetch_row(res)) !=NULL)
printf("%s\n", row[0]);
mysql_free_result(res);
mysql_close(conn);
return 0;
}
however g++ gives me the followign warning:
main.cpp:46:19: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
main.cpp:47:17: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
main.cpp:48:21: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
main.cpp:49:21: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
main.cpp:53:48: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
Which is beyond my understanding at the time being, although the program works.
What I did in order to remove the warning was the following:
char s[] = "localhost";
char u[] = "root";
char p[] = "root";
char d[] = "backseat";
and then
mysqlD.server = s;
mysqlD.user = u;
mysqlD.password = p;
mysqlD.database = d;
That took care of the warning but I assume there must be a better way & explanation on how I should take care of this.
Moreover I tried to use:
struct connection_details
{
string *server;
string *user;
string *password;
string *database;
};
But that didn't take care the warning on line 53 plus all hell broke loose after doing this.
My question is how should I be approaching simple mysql connection, why did those warnings came up and was it a bad idea to use strings in the struct?
I'm sorry for the long post, but I'm on a learning curve here and there a lot of things to take in.
PS: Any good tutorials / guides will be appreciated. Thank you.
You're missing some basics. I don't know about good tutorials to link to, but I'll explain what you're doing wrong:
First of all, when you're writing C++, you should use string rather than char*. You should read up the details of char*; it's a pointer and handling it is therefore significantly different from handling a string.
What happens in your code is that you assign the address of a string literal like "localhost" to a char* (because it's a pointer). The problem is, gcc converts string literals to constants, which are read-only (as the warning tells you). The type char* however implies that the contents of the string can be changed. Change the type to const char* to get rid of the warning.
Here's some code to illustrate the issue:
char* a;
const char* b;
a = "foo";
b = "bar";
a[0] = 'a'; // you're changing the constant string!
b[0] = 'b'; // compiler error; b is const
a = "foz"; // both allowed because you're not changing
b = "baz"; // the string, but only the pointer
The easier option is to use string:
struct connection_details
{
string server;
string user;
string password;
string database;
}
You shouldn't use pointers here. string manages the low-level memory stuff internally. Now the problem is that you're using the C-level MySQL binding, which expects char* rather than string. To call it when you're using strings in your code, use c_str() for conversion:
connection.server.c_str()
and so on.
Alternatively, you might want to use a higher-level C++ API to connect to MySQL. If you're learning C++, you'll be better off avoiding C APIs if possible. There is, for example, MySQL++, but I don't know it and therefore cannot recommend it. A higher-level API is provided by SOCI, which works with multiple database backends (including MySQL).

Error 12006 in WinHttpCrackUrl

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.

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();