How to insert variables values in the registry with C++? [duplicate] - c++

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

Related

How to get a readable string from SetupDiGetDeviceRegistryProperty?

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.

How to convert CString to byte [] array? [duplicate]

This question already has answers here:
conversion of Cstring to BYTE
(5 answers)
Closed 4 years ago.
I am trying to convert CString to byte [] array in Visual Studio MFC. Please see the code below.
CString str_text;
GetDlgItemText(IDC_KEY_TEXT, str_text);
BYTE A[] = "hi I love stackoverflow";
BYTE A[] = str_text;
Here, BYTE A [] is a byte array.
Regardless of CString and GetDlgItemText function, if I do only (1) my program does well.
But If you type CString(str_text)(2) instead of "hi I love stackoverflow" I have a error. That's error is "it couldn't convert CString to byte array".
I would like to convert CString to byte array. Please tell me where my mistake is.
Here is the proper way of doing this. I assume you deal with Unicode strings:
CStringW str = L"Hello World";
// convert to UTF-8
CStringA utf8 = CW2A(str, CP_UTF8);
CByteArray Bytes;
const size_t nBytes = sizeof(CStringA::XCHAR) * utf8.GetLength();
Bytes.SetSize( nBytes );
std::memcpy( Bytes.GetData(), static_cast<BYTE const*>utf8, nBytes );

wstring to LPCWSTR not working with c_str() [duplicate]

This question already has answers here:
Guaranteed lifetime of temporary in C++?
(6 answers)
Closed 8 years ago.
I am currently doing DirectX11 and trying to convert a UTF8 string into a LPCWSTR. I've written a utility function to aid me in the conversion:
// Convert an UTF8 string to a wide Unicode String
std::wstring WidenString(const std::string &string)
{
int size_needed = MultiByteToWideChar(CP_UTF8, 0, string.c_str(), string.size(), NULL, 0);
std::wstring wstring(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, string.c_str(), string.size(), &wstring[0], size_needed);
return wstring;
}
I've used the debugger to verify if it works. This is working:
Debugger says wndClassEx.lpszClassName = L"Hello"
std::wstring str = WidenString("Hello");
wndClassEx.lpszClassName = str.c_str();
This is not working:
Debugger says wndClassEx.lpszClassName = L"ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ..."
wndClassEx.lpszClassName = WidenString("Hello").c_str();
Can someone explain to me what is wrong with my code?
WidenString() returns a wstring by value. In the first snippet, wndClassEx.lpszClassName will point to a valid memory location as long as the variable str remains in scope i.e. it does not get destroyed.
In the second case the return value does go out of scope at the end of the expression (at the ;) and wndClassEx.lpszClassName then points to invalid memory.

C++ Read a Registry String Value in char* [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to compare strings
I want to Compare to registry string values and if they were the same an messagebox appears
Currently I'm using this functions , It returns the value correctly but whenever I want to compare them, The compare result is always wrong
char* GetRegistry(char* StringName)
{
DWORD dwType = REG_SZ;
HKEY hKey = 0;
char value[1024];
DWORD value_length = 1024;
const char* subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI\\Player";
RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey);
RegQueryValueEx(hKey, StringName, NULL, &dwType, (LPBYTE)&value, &value_length);
return value;
}
I use this to compare them
if (GetRegistry("First") == GetRegistry("Second"))
{
MessageBox(NULL,":|",":|",1);
}
But the MessageBox appears how ever The values are different
Any help is appreciated.
By using std::string, comparison would behave as you expected. Also that would fix another bug that the function returns a pointer to a local buffer.
std::string GetRegistry(const char* StringName)
{
....
return std::string(value);
}
GetRegistry() returns a char*, so you are actually comparing pointers with operator==.
You should use strcmp() to do raw C-like char* string comparisons, or better use a robust C++ string class, like CString or std::[w]string.
Here is a possible rewrite of your function using ATL's CString:
#include <atlbase.h>
#include <atlstr.h>
CString GetRegistry(LPCTSTR pszValueName)
{
// Try open registry key
HKEY hKey = NULL;
LPCTSTR pszSubkey = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI Extensions");
if ( RegOpenKey(HKEY_LOCAL_MACHINE, pszSubkey, &hKey) != ERROR_SUCCESS )
{
// Error:
// throw an exception or something...
//
// (In production code a custom C++ exception
// derived from std::runtime_error could be used)
AtlThrowLastWin32();
}
// Buffer to store string read from registry
TCHAR szValue[1024];
DWORD cbValueLength = sizeof(szValue);
// Query string value
if ( RegQueryValueEx(
hKey,
pszValueName,
NULL,
NULL,
reinterpret_cast<LPBYTE>(&szValue),
&cbValueLength)
!= ERROR_SUCCESS )
{
// Error
// throw an exception or something...
AtlThrowLastWin32();
}
// Create a CString from the value buffer
return CString(szValue);
}
And then you can call it like this:
if ( GetRegistry(_T("First")) == GetRegistry(_T("Second")) )
...
Note that this code will compile in both ANSI/MBCS and Unicode builds (it's based on Win32 TCHAR model).
You have a couple of problems with this source code.
First of all you have a function with a local variable, a variable on the stack, which is returning the address of that variable yet when the function returns, the variable disappears and the address is no longer valid.
The next problem is that you are not comparing the character strings. You are instead comparing the address returned by the function and if you get lucky, the address could be the same. Since you are calling the function twice in succession, you are getting lucky so the address is the same.
I suggest you do the following: (1) create two local character strings in your function which is calling the function GetRegistry() and (2) modify the GetRegistry() function so that it uses those buffers rather than its own. So the code would look something like:
char registryEntryOne[1024];
char registryEntryTwo[1024];
DWORD dwRegistryEntryOneLen;
DWORD dwRegistryEntryTwoLen;
registryEntryOne[0] = 0; // init the registry entry to zero length string
registryEntryTwo[0] = 0;
dwRegistryEntryOneLen = sizeof(registryEntryOne);
GetRegistry ("First", registryEntryOne, &dwRegistryEntryOneLen);
dwRegistryEntryTwoLen = sizeof(registryEntryTwo);
GetRegistry ("Second", registryEntryTwo, &dwRegistryEntryTwoLen);
// two strings are equal if:
// the lengths are the same
// at least one of the lengths is non-zero
// the bytes are the same in the same order
if (dwRegistryEntryOneLen && dwRegistryEntryOneLen == dwRegistryEntryTwoLen && memcmp (registryEntryOne, registryEntryTwo, dwRegistryEntryOneLen) == 0) {
// strings are equal
} else {
// strings are not equal
}
The GetRegistry() function would look something like:
char* GetRegistry(char* StringName, char *valueBuffer, DWORD *value_length)
{
DWORD dwType = REG_SZ;
HKEY hKey = 0;
const char* subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI\\Player";
RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey);
RegQueryValueEx(hKey, StringName, NULL, &dwType, (LPBYTE)valueBuffer, value_length);
return valueBuffer;
}

convert an unsigned char to LPCSTR

Hi i'm using VS2010 and MBCS. Can anyone tell me how to convert an unsigned char to LPCSTR? Sorry i'm only new to c++...:) Thanks
This is the code it is failing on:
hr = MsiSetProperty(hInstall, "LOCKCODE", szLockCode);
ExitOnFailure(hr, "failed to set LOCKCODE");
szLockCode is the variable that needs to be converted.
An unsigned char array (unsigned char szLockCode[10] for instance) is technically already an LPCSTR. If you're using an array already then conversion is not the issue, if not, then you need an array. If you want a single character string, then you need an array of length 2. The character goes in the first position (szLockCode[0]) and the value 0 goes in the second position (szLockCode[1]).
You probably get error message like:
cannot convert parameter 3 from 'const char *' to 'LPCWSTR'
To avoid it you should either do type convertion:
hr = MsiSetProperty(hInstall, "LOCKCODE", (LPCSTR)szLockCode);
or use L prefix before string:
LPCSTR szLockCode = L"Some error";
hr = MsiSetProperty(hInstall, "LOCKCODE", szLockCode );
Here is a good explanation of what LPCSTR stand for:
LPCSTR, LPCTSTR and LPTSTR