I'm trying to get a human readable string from SetupDiGetDeviceRegistryPropertyA() function.
My code is:
size_t strSize = RequiredSize / sizeof(wchar_t) + 1;
wchar_t* DevName = new wchar_t[strSize];
Name = new CHAR[strSize];
Result = SetupDiGetDeviceRegistryPropertyA(InfoSet, &InfoData, SPDRP_DEVICEDESC, &Type, reinterpret_cast<PBYTE>(DevName), RequiredSize, &RequiredSize);
If Result is true, I want to convert the DevName value to a string using the following code:
size_t sizeCon;
wcstombs_s(&sizeCon, Name, strSize, DevName, strSize);
But in "Name" I always get null and sizeCon is always '0'.
If I use a wide string (for example: wchar_t b[] = L"984567";) instead of the parameter DevName, I get a correct translation of the wide string to a character string.
In the Documenation of SetupDiGetDeviceRegistryPropertyA the PropertyBuffer parameter is described as a PBYTE.
In all code examples, which I saw, the code examples uses a wchar variable. This wchar variable which will be casted to a PBYTE, like I do.
Now I am confused.
Why in the code examples is a wchar variable used, when the type of PropertyBuffer is PBYTE?
What is the correct type to use in SetupDiGetDeviceRegistryPropertyA to get a string?
If I need to use a wchar variable, why the wcstombs_s function cannot convert the wchar variable to a char string?
Can someone help me to get the correct string from SetupDiGetDeviceRegistryPropertyA?
Thank you.
Related
My goal is to get this:
BYTE Data1[] = {0x6b,0x65,0x79};
BYTE Data2[] = {0x6D,0x65,0x73,0x73,0x61,0x67,0x65};
But my starting point is:
std::string msg = "message";
std::string key = "key";
I am not able to get from std::string to BYTE[].
I tried the following:
std::vector<BYTE> msgbytebuffer(msg.begin(), msg.end());
BYTE* Data1 = &msgbytebuffer[0];
This didn't cause compile or run time error. However, the end result (I feed this to a winapi function - crypto api) was not the same as when I used the actual byte array like in top most ({0x6D,0x65,0x73,0x73,0x61,0x67,0x65}).
You can use string::c_str() function which returns a pointer to c style string that can be passed to winapi functions like:
foo(string.c_str());
What it actually does is that it returns a pointer to an array that contains a null-terminated sequence of characters.
I suppose BYTE[] is actually a char array. You can assign your std::string to char array by doing:
std::string str = "hello";
BYTE byte[6]; // null terminated string;
strcpy(byte, str.c_str()); // copy from str to byte[]
If you want to copy the str without the 0 at the end, use strncpy instead:
BYTE byte[5];
strncpy(byte, str.c_str(), str.length());
Seems me that winapi is waiting a null terminated c-string. You can achieve that by using:
msg.c_str();
or, using your BYTE type, something like that:
std::vector<BYTE> msgbytebuffer(msg.length() + 1, 0);
std::copy(msg.begin(), msg.end(), msgbytebuffer.begin());
I am trying to get a substring from a CString using C++. For that I am using strstr function. But it is not working at al
CString str = m_sectionDataList->GetNext(pos);
char* chToMatch = (char*)(LPCTSTR)str;
char *match = "=";
//char * sMatched = strstr(ch, match);
if (strstr(match, chToMatch) != NULL) {
MessageBox(NULL, str, L"Done", 1);
}
You are passing arguments in the incorrect order. strstr expects first argument to be scanned string, and second should be a match. Right now you are searching your target string in the one byte = template, which will most certainly fail.
Finally I've found it. Need to use a macro of C++ and you will found it converted.
CT2A ascii(str, CP_UTF8);
now you can just access it using ascii.m_psz and its buffer also.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Char array gives error when initializing
I want to insert an environment variable in the windows registry, so i tied the following C++ code :
string appDataPath = getenv("appdata");
HKEY hkey;
char value[] = appDataPath.c_str();
RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\Currentversion\\Run", 0, KEY_SET_VALUE, &hkey);
RegSetValueEx (hkey, "MyProgram", 0, REG_SZ, (LPBYTE) value, strlen(value) + 1);
RegCloseKey(hkey);
The codeblock debug output tell me : error: initializer fails to determine size of 'value'
I think it's because the compilator need to know the size of my variable before compiling, however i don't know how to fix that...
Thanks !
c_str() returns a const char*, not a char[]. Change
char value[] = appDataPath.c_str();
to
const char* value = appDataPath.c_str();
The compiler is giving the error because an array variable requires a length - which is not being provided.
Use
const char * value = appDataPath.c_str();
(Read the < string > reference to find the return type of c_str(), it will tell you that it is indeed const char *.)
Regarding your question of how to concatenate two strings:
Do that with C++ strings rather than with char *s and convert them later:
string newstring = appDataPath;
newstring.append("some text");
const char * value = newstring.c_str();
I'm developing a tiny Win32 app in C++.
I've studied C++ fundamentals long time ago, so now I completely confused because of character strings in C++. There were no WCHAR or TCHAR only char and String.
After a little investigation I've decided not to use TCHAR.
My issue is very simple I think, but I can't find clear guide how to manipulate strings in C++. Affected by PHP coding last few years I've expected something simple with strings manipulations and was wrong!
Simply, all I need is to put new data to a character string.
WCHAR* cs = L"\0";
swprintf( cs, "NEW DATA" );
This was my first attempt. When debugging my app I've investigated that swprintf puts only first 2 chars to my cs var. I've resolved my problem this way:
WCHAR cs[1000];
swprintf( cs, "NEW DATA" );
But generally this trick could fail, because in my case new data is not constant value but another variable, that could potentialy be wider, than 1000 chars long. And my code is looks like this:
WCHAR cs[1000];
WCHAR* nd1;
WCHAR* nd2;
wcscpy(nd1, L"Some value");
wcscpy(nd2, L"Another value"); // Actually these vars stores the path for user selected folder
swprintf( cs, "The paths are %s and %s", nd1, nd2);
In this case there is possibility than nd1 and nd2 total character count could be greater than 1000 chars so critical data will be lost.
The question is how can I copy all data I need to WCHAR string declared this way WCHAR* wchar_var; without losing anything?
P.S. Since I'm Russian the question may be unclear. Let me now about that, and I'll try to explain my issue more clear and complex.
In modern Windows programming, it's OK to just ignore TCHAR and instead use wchar_t (WCHAR) and Unicode UTF-16.
(TCHAR is a model of the past, when you wanted to have a single code base, and produce both ANSI/MBCS and Unicode builds changing some preprocessor switches like _UNICODE and UNICODE.)
In any case, you should use C++ and convenient string classes to simplify your code. You can use ATL::CString (which corresponds to CStringW in Unicode builds, which are the default since VS2005), or STL's std::wstring.
Using CString, you can do:
CString str1 = L"Some value";
CString str2 = L"Another value";
CString cs;
cs.Format(L"The paths are %s and %s", str1.GetString(), str2.GetString());
CString also provides proper overloads of operator+ to concatenate strings (so you don't have to calculate the total length of the resulting string, dynamically allocate a buffer for the destination string or check existing buffer size, call wcscpy, wcscat, don't forget to release the buffer, etc.)
And you can simply pass instances of CString to Win32 APIs expecting const wchar_t* (LPCWSTR/PCWSTR) parameters, since CString offers an implicit conversion operator to const wchar_t*.
When you're using a WCHAR*, you are invoking undefined behavior because you have a pointer but have not made it point to anything valid. You need to find out how long the resulting string will be and dynamically allocate space for the string. For example:
WCHAR* cs;
WCHAR* nd1;
WCHAR* nd2;
nd1 = new WCHAR[lstrlen(L"Some value") + 1]; // +1 for the null terminator
nd2 = new WCHAR[lstrlen(L"Another value") + 1];
cs = new WCHAR[lstrlen(L"The paths are and ") + lstrlen(nd1) + lstrlen(nd2) + 1];
wcscpy(nd1, L"Some value");
wcscpy(nd2, L"Another value"); // Actually these vars stores the path for user selected folder
swprintf( cs, L"The paths are %s and %s", nd1, nd2);
delete[] nd1;
delete[] nd2;
delete[] cs;
But this is very ugly and error-prone. As noted, you should be using std::wstring instead, something like this:
std::wstring cs;
std::wstring nd1;
std::wstring nd2;
nd1 = L"Some value";
nd2 = L"Another value";
cs = std::wstring(L"The paths are ") + nd1 + L" and " + nd2;
Suggest to use ATL CStringW class instead of raw WCHAR, it's much more handy. CString is wrapper for dynamically allocated C-string. It will manage string length & allocated memory buffer appropriately after each operation so you wouldn't care on it.
Typical usage:
#include <atlstr.h>
CStringW s;
s.Format(L"The paths are %s and %s", L"Some value", L"Another value");
const WCHAR* wstr = s.GetString(); // To pass to some API that need WCHAR
or
#include <atlstr.h>
CStringW s(L"The paths are ");
s += L"Some value";
s += L" and ";
s += L"Another value";
const WCHAR* wstr = s.GetString(); // To pass to some API that need WCHAR
I googled it for 2 hours now, and i can't find an answer for my problem: i need to get a registry REG_SZ value and pass it to a char*.
char host_val[1024];
DWORD hostVal_size = 1024;
char* hostName;
DWORD dwType = REG_SZ;
RegOpenKeyEx(//no problem here);
if( RegQueryValueEx( hKey, TEXT("HostName"), 0, &dwType, (LPBYTE)&host_val, &hostVal_size ) == ERROR_SUCCESS )
{
//hostName = host_val;
}
How should i do this conversion hostName = host_val?
The resulting host_val is a possibly non-null-terminated string (see "Remarks"), so you should copy it to a newly allocated string with memcpy, and ensure it's null-terminated:
hostName = new char[hostVal_size + 1];
// host_val may or may not be null-terminated
memcpy(hostName, host_val, hostVal_size);
hostName[hostVal_size] = '\0';
You will need to delete[] the hostName later.
use the ANSI version of the function
RegQueryValueExA
that way you don't need to convert.
If you're compiling with Unicode you're copying a Unicode string (that is possibly NOT terminated) into a narrow char buffer. the first character in the unicode string will be 0x3100 (accounting for the endianness on your machine, which is likely little-endian, and the fact that you said the IP address is 192....)
That value stuffed into the char[] array will report back as a single-char-null-terminated string. You have two options.
Use RegQueryValueExA, everything else stays the same, or
Change your char[] array to a wchar_t[] array, do what you're currently doing, then convert to narrow using WideCharToMultiByte(docs are in the SDK).
For obvious reasons, I'd take the former of those two options.