C++ RegSetValueEx is giving problems - c++

I'm using RegSetValueEx to set a Registry key. The problem is that it only writes the first 2 characters. I can get the RegSetValueExA (ANSI version) to work, but my Project is set to Unicode in properties so I would like to use either RegSetValueEx or RegSetValueExW.
#include <iostream>
#include <Windows.h>
HKEY hKey;
int main()
{
RegCreateKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\stuff", 0, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, NULL);
RegSetValueEx(hKey, L"Test", 0, REG_SZ, (const BYTE*)L"test", strlen("test"));
system("PAUSE");
return 0;
}
Output in registry is "te" instead of "test".

The final parameter to RegSetValueEx has to be the size in bytes of the value, including the terminating null. You're giving the length in characters (and each character needs two bytes) and not including the null.
sizeof(L"test") would work, I think, or you could use (strlen("test")+1) * sizeof(wchar_t)
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms724923(v=vs.85).aspx

Related

Error writing to Windows 10 registry with WindowsAPI/C (strange situation)

I am trying to write to my Windows 10 registry, to include a program in Startup.
At the moment I have written the following code, which is not wroking:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winnt.h>
#include <winreg.h>
int main()
{
const TCHAR* path = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
LPDWORD holdResult;
PHKEY hKey;
int lResult;
//lResult = RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_READ, &hKey);
lResult = RegCreateKeyExA(HKEY_CURRENT_USER, "myprogram", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &holdResult);
if (lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_FILE_NOT_FOUND) {
printf("Key not found.\n");
return TRUE;
}
else {
printf("Error opening key.\n");
return FALSE;
}
}
printf("Key already existed or not: %p\n", holdResult);
char* szPath = "C:\\Users\\Myname\\Documents\\coolprogram.exe";
lResult = RegSetValueExA(hKey, "program", 0, REG_SZ,(LPBYTE)szPath, sizeof(wchar_t)*(wcslen(szPath)+1));
printf("Key successfully set or not: %d\n", lResult);
RegCloseKey(hKey);
return 0;
}
The strange thing is, although the code does not write anything to the registry, I get no error message, and the program executes as successful!
This is what gets printed to the terminal when I run the code:
Key already existed or not: 0000000000000002
Key successfully set or not: 0
So, the key had already been previously created, and was succesfully set, which did not happen, there is nothing in my registry.
I believe this is a permissions problem, because for some reason I cannot alter my registry permissions manually, even after setting myself as owner, it is impossible for me to allow "Full Control" to myself.
But I expected some sort of error, such as "ACCESS DENIED: INSUFFICIENT PERMISSIONS", but I am getting a success. Strange.
You are passing the wrong key path to RegCreateKeyEx(). You are trying to write your program value to HKCU\myprogram rather than to HKCU\SOFTWARE\Microsoft\...\Run.
You are also passing invalid pointers to RegCreateKeyEx(). Its last 2 parameters expect pointers to HKEY and DWORD variables, but you are passing in pointers to HKEY* and DWORD* variables instead.
You are also passing an incorrect parameter to RegSetValueExA(), too. You are giving it an ANSI string (OK, since it is an ANSI function), but are passing in a Unicode string length that is 2x the byte size of the actual ANSI string (bad).
In fact, your code shouldn't even compile as shown.
Try this instead:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winnt.h>
#include <winreg.h>
int main()
{
const char* szKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
const char* szPath = "C:\\Users\\Myname\\Documents\\coolprogram.exe";
DWORD dwDisposition;
HKEY hKey;
LSTATUS lResult;
//lResult = RegOpenKeyExA(HKEY_CURRENT_USER, szKey, 0, KEY_QUERY_VALUE, &hKey);
lResult = RegCreateKeyExA(HKEY_CURRENT_USER, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, &dwDisposition);
if (lResult != ERROR_SUCCESS)
{
printf("Error creating key: %ld\n", lResult);
return 0;
}
printf("Key already existed or not: %lu\n", dwDisposition);
lResult = RegSetValueExA(hKey, "program", 0, REG_SZ, (LPBYTE)szPath, sizeof(TCHAR)*(strlen(szPath)+1));
printf("Key successfully set or not: %ld\n", lResult);
RegCloseKey(hKey);
return 0;
}

RegSetValueEx with RRF_RT_REG_SZ makes REG_EXPAND_SZ in the registry?

The title pretty much says it all, when I try to use RegSetValueEx to make a REG_SZ size entry, I get a REG_EXPAND_SZ when I look at the registry.
Here is the code I'm using
const char REG_KEY_PATH[] = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
const char REG_VALUE_NAME[] = "Scroff";
// Get where the app lives
char appLoc[MAX_PATH];
GetModuleFileNameA(NULL, appLoc, MAX_PATH);
// Create the key value
HKEY regKey = 0;
RegCreateKeyExA(HKEY_LOCAL_MACHINE, REG_KEY_PATH, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_READ | KEY_WRITE | KEY_WOW64_64KEY,
NULL, &regKey, NULL);
RegSetValueExA(regKey, REG_VALUE_NAME, 0, RRF_RT_REG_SZ, (unsigned char*)appLoc, strlen(appLoc));
The code works, but instead of the registry having a REG_SZ type, it's REG_EXPAND_SZ. Why would this be, and how can I fix it?
I am running on Windows 10, using VS 2015 Enterprise.
Thanks.
You need to pass the REG_SZ flag as the 4th parameter of RegSetValueEx() to create a REG_SZ value. RRF_RT_XXX flags are only valid with RegGetValue().
Your code is creating a REG_EXPAND_SZ value because the value of the RRF_RT_REG_SZ flag is 2, which is coincidentally the same value as the REG_EXPAND_SZ flag.

c++ RegCreateKeyEx LPCWSTR from std::string

I'm writting few operations in registry and I got stuck for two days at this. Really don't know how to solve that. So, its my code:
HKEY hkey;
DWORD dwDisposition;
string address = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
QString qAddr= ui->networkCard->itemData(ui->networkCard->currentIndex()).toString();
address += qAddr.toStdString();
string sAddr = qAddr.toStdString();
cout << address; // here is the value I want to proceed as 2nd arg in RegCreateKeyEx
size_t size = address.size();
wchar_t szBuff[size];
swprintf(szBuff, size, L"%s", address.c_str());
cout << szBuff << endl; // but after conversion I get some hex data like 0x28d172 :(
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, szBuff, 0, NULL, 0, KEY_WRITE, NULL, &hkey, &dwDisposition) == ERROR_SUCCESS){
DWORD dwType, dwSize;
dwType = REG_DWORD;
....
RegCreateKeyEx requires a LPCWSTR arg, but I really don't know how to do it from a std::string. Can u help me fixing this? :)
Thank you!
RegCreateKeyEx requires LPCWSTR only if your project is set to unicode. If you want a unicode project then use std::wstring instead of std::string. If you don't want a unicode project then change the project Character Set setting to Multi-Byte Character Set, which will let you use std::string.

strange characters with RegQueryValueEx

I'm creating a NPAPI dll file and I need to get some information from the registry, but when I use RegQueryValueEx, I get some strange characters.
For instance, my computer model is "N310", but I get "Nfb1fb1" or "N$(".
I'm pretty sure that it's a charset issue, but I'm new with C++ and I need some help.
I'm using Visual Studio 2010 and my project is using the UNICODE charset.
Here is my code:
char lszValue[255];
std::string cadena;
HKEY hKey;
LONG returnStatus;
DWORD dwType=REG_SZ;
DWORD dwSize=255;
returnStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", NULL, KEY_READ, &hKey);
if (returnStatus == ERROR_SUCCESS) {
returnStatus = RegQueryValueEx(hKey, L"SystemProductName", NULL, &dwType,(LPBYTE)&lszValue, &dwSize);
lszValue[dwSize] = 0;
cadena.assign(lszValue, dwSize);
return cadena;
}
Thank you very much and thanks for advance.
If your project uses UNICODE charset, then probably all WINAPI functions are bound to unicode strings, that is, RegQueryValueEx is actually RegQueryValueExW that takes wchar_t array, not char array.
When using non-Unicode, single-byte projects, the function would be RegQueryValueExA and it would work with char[].
To make your project (non)unicode-safe, use TCHAR macro instead of char.
try this code:
DWORD const dwSize=255;
TCHAR lszValue[dwSize];
std::wstring cadena;
HKEY hKey;
LONG returnStatus;
DWORD dwType=REG_SZ;
returnStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\BIOS", NULL, KEY_READ, &hKey);
if (returnStatus == ERROR_SUCCESS)
{
returnStatus = RegQueryValueEx(hKey, L"SystemProductName", NULL, &dwType, (LPBYTE)&lszValue, &dwSize);
lszValue[dwSize] = 0;
cadena.assign(lszValue, dwSize);
return cadena;
}
I've changed just the types. There may be other errors/typos. Just remember that std::wstring is for wchar_t

Accessing windows registry under GCC/C++

I'm trying to access windows registry using standard windows api.
I'm using mingw c++ compiller.
Please tell why this code crases at line (X)
HKEY hKey;
DWORD dwDisp = 0;
LPDWORD lpdwDisp = &dwDisp;
QString value = "String Value";
LONG iSuccess = RegCreateKeyEx(
HKEY_CURRENT_USER,
TEXT("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"),
0L,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKey,
lpdwDisp);
if(iSuccess == ERROR_SUCCESS)
{
(X) RegSetValueEx(hKey, TEXT("1234"), 0, REG_SZ, (LPBYTE)4, 4+1);
}
Debugger shows Segmantation fault at this line.
Thank you very much for help. I'm new to windows API.
Take a look at the function description again.
If you want to set the default value for the key you need to do something like this:
TCHAR szData[] = TEXT("1234")
RegSetValueEx(hKey, NULL, 0, REG_SZ, (LPBYTE)szData, sizeof(szData));
If you actually want to specify the value name:
TCHAR szData[] = TEXT("1234")
RegSetValueEx(hKey, TEXT("valuename"), 0, REG_SZ, (LPBYTE)szData, sizeof(szData));
The registry has a somewhat confusing terminology. The key in this context basically means "folder". Each folder has a default value, and can contain other values with specified names. You pass null if you want to set the default value, and a string if you want to name the value. These values shows up as "files" in the key "folder" when you look in the register editor.
Casts are bad.
What do you expect (LPBYTE)3 to do? Why do you think you need it?
Isn't that where value should be used? Perhaps as value.ascii() or value.constData() (depending on whether UNICODE is defined)? (NOTE: QString value mysteriously disappeared from the question)
Remove HKEY_LOCAL_MACHINE\ from the second parameter and it should work fine.
HKEY_LOCAL_MACHINE should be set in the first param.