Writing string (REG_SZ) values to the registry in C++ - c++

I've got most of the code for writing a value to the windows registry, however when I change the path to a dummy key and value that I've set up for testing it fails. My code is below:
HKEY hKey;
LPCTSTR sk = TEXT("SOFTWARE\TestSoftware");
LONG openRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sk, 0, KEY_ALL_ACCESS , &hKey);
if (openRes==ERROR_SUCCESS) {
printf("Success opening key.");
} else {
printf("Error opening key.");
}
LPCTSTR value = TEXT("TestSoftwareKey");
LPCTSTR data = "TestData\0";
LONG setRes = RegSetValueEx (hKey, value, 0, REG_SZ, (LPBYTE)data, strlen(data)+1);
if (setRes == ERROR_SUCCESS) {
printf("Success writing to Registry.");
} else {
printf("Error writing to Registry.");
}
LONG closeOut = RegCloseKey(hKey);
if (closeOut == ERROR_SUCCESS) {
printf("Success closing key.");
} else {
printf("Error closing key.");
}
All three tests yield error statuses.
The part that confuses me is that I was able to run this code when pointing it at other portions of the registry. Any ideas?
thanks,
brian

I feel silly. The solution is that need to properly escape the slash in the string as follows:
LPCTSTR sk = TEXT("SOFTWARE\\TestSoftware");
Hopefully someone finds this useful...

HKEY OpenKey(HKEY hRootKey, char* strKey)
{
HKEY hKey;
LONG nError = RegOpenKeyEx(hRootKey, strKey, NULL, KEY_ALL_ACCESS, &hKey);
if (nError==ERROR_FILE_NOT_FOUND)
{
cout << "Creating registry key: " << strKey << endl;
nError = RegCreateKeyEx(hRootKey, strKey, NULL, NULL, REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL, &hKey, NULL);
}
if (nError)
cout << "Error: " << nError << " Could not find or create " << strKey << endl;
return hKey;
}
void SetintVal(HKEY hKey, LPCTSTR lpValue, DWORD data)
{
LONG nError = RegSetValueEx(hKey, lpValue, NULL, REG_DWORD, (LPBYTE)&data, sizeof(DWORD));
if (nError)
cout << "Error: " << nError << " Could not set registry value: " << (char*)lpValue << endl;
}
DWORD GetintVal(HKEY hKey, LPCTSTR lpValue)
{
DWORD data;
DWORD size = sizeof(data);
DWORD type = REG_DWORD;
LONG nError = RegQueryValueEx(hKey, lpValue, NULL, &type, (LPBYTE)&data, &size);
if (nError==ERROR_FILE_NOT_FOUND)
data = 0;
SetVal() is called.
else if (nError)
cout << "Error: " << nError << " Could not get registry value " << (char*)lpValue << endl;
return data;
}
BOOL SetcharVal(HKEY Key,char* subkey,char* StringName,char* Stringdata)
{
HKEY hKey = OpenKey(Key,subkey);
LONG openRes = RegOpenKeyEx(Key, subkey, 0, KEY_ALL_ACCESS , &hKey);
if (openRes==ERROR_SUCCESS) {
} else {
printf("Error opening key.");
}
LONG setRes = RegSetValueEx (hKey, StringName, 0, REG_SZ, (LPBYTE)Stringdata, strlen(Stringdata)+1);
if (setRes == ERROR_SUCCESS) {
} else {
printf("Error writing to Registry.");
}
LONG closeOut = RegCloseKey(hKey);
if (closeOut == ERROR_SUCCESS) {
} else {
printf("Error closing key.");
}
}
char* GetCharVal(HKEY Key,char* subkey,char* StringName)
{
DWORD dwType = REG_SZ;
HKEY hKey = 0;
char value[1024];
DWORD value_length = 1024;
RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey);
RegQueryValueEx(hKey, StringName, NULL, &dwType, (LPBYTE)&value, &value_length);
RegCloseKey(hKey);
return value;
}
I am using this code.

For UNICODE environment:
//Writing to registry
HKEY hKey;
LPCTSTR sk = TEXT("SOFTWARE\\Microsoft\\Windows");
LONG openRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sk, 0, KEY_ALL_ACCESS, &hKey);
if (openRes == ERROR_SUCCESS) {
printf("Success opening key.");
}
else {
printf("Error opening key.");
}
LPCTSTR value = TEXT("Sample");
WCHAR path[80] = TEXT("C:\\samples\\app.exe");
LONG setRes = RegSetValueEx(hKey, value, 0, REG_SZ, (LPBYTE)path, sizeof(path));
if (setRes == ERROR_SUCCESS) {
printf("Success writing to Registry.");
}
else {
printf("Error writing to Registry.");
}
LONG closeOut = RegCloseKey(hKey);
if (closeOut == ERROR_SUCCESS) {
printf("Success closing key.");
}
else {
printf("Error closing key.");
}

Related

Why does my registry reading function in c++ return incorrect strings?

I have a function which I will show at the end which is asked to retrieve a value from the registry and return it in the form of a string. If the value was "abcdefghijklmnopqrstuvwxyz" the function returns the string as "acegikmoqsuwy". Any help would be appreciated.
string Tools::ReadRegValue(HKEY root, string key, string name)
{
HKEY hKey;
if (RegOpenKeyEx(root, key.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
throw "Could not open registry key";
DWORD type;
DWORD cbData;
if (RegQueryValueEx(hKey, name.c_str(), NULL, &type, NULL, &cbData) != ERROR_SUCCESS)
{
RegCloseKey(hKey);
throw "Could not read registry value";
}
if (type != REG_SZ)
{
RegCloseKey(hKey);
throw "Incorrect registry value type";
}
string value(cbData / sizeof(wchar_t), L'\0');
if (RegQueryValueEx(hKey, name.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(&value[0]), &cbData) != ERROR_SUCCESS)
{
RegCloseKey(hKey);
throw "Could not read registry value";
}
RegCloseKey(hKey);
size_t firstNull = value.find_first_of('\0');
if (firstNull != string::npos)
value.resize(firstNull);
return value;
}

Generation RSA-2048 keys (public and private)

I'm making simple implementation RSA-2048. I found some code on another forum.
#include <string>
#include <iostream>
#include <windows.h>
#include <Wincrypt.h>
using namespace std;
#pragma comment (lib, "Crypt32.lib")
BYTE* Crypt(const string& _str, DWORD* _outLength);
BYTE* Decrypt(BYTE* _encryptedData, DWORD* _length);
const char* szPemPrivKey =
"-----BEGIN RSA PRIVATE KEY-----"
"MIICWwIBAAKBgQCn7fL/1qsWkJkUtXKZIJNqYfnVByVhK/LzQecPhVR7r+4ng1nZ"
"Bxg44SexS63iYlnodqDWkH/Hi82Uc0UmugY/Ow39uEGeoiYqWl5BLM8pfRAGqzxb"
"h600Qd/Oc5kYdg8hP0D/gAHXwutL74fygpB6xb8EZl2BHKvpDR80GYFlrQIDAQAB"
"AoGAZ4ZHsfTTEFwgIyYg+cmdV44DCJMZNihz5AcSvPzDMmUo+m79as/23MnhQGmZ"
"TuC28JqBWQVH4OqM2CGf1doEkuLZ/rcgxDipRqbLkEW3T/q+kJ2m9A652ePbHUKX"
"ayozDQrWtL4wkvAQQ9Il6vx+AJUzT41hv1PKZ5KWxONiJDkCQQDRsObUVVc6exb+"
"YUWVgN0pivHudKIwGUN3js09MjHoen9LbUcvupO3seAUhnNQ17t+1XxsrnPKabQQ"
"OimcPK3XAkEAzQQEI++NdoLYJv1oKYADzOUbDAmfoZ/szN6z//53h8zt5ni+6Q0n"
"k7nyrVXWuLeP0rEvD0hMOzI0mfUMwbtwGwJAMUYId8y1+qAB/zSMTV1CmwhzYT02"
"/2ZwXB/KSp8I60AduXOsTqLhI0FBDpGpd026WUuBOWik/ONp1IZWUMhRcQJAHI+U"
"rBTxVjNAPZ5L5owo+2BndjPZA0EuUhQsa1td95M7CUKFBh6JBvF+t1sgALfB145L"
"igt+YzjJTzFuR4b/RQJATgZuFyBiuLHrMES2vAtmLRlF6uTzsrNZLLUko2Rfzkzh"
"qR4inQOWWZLFzjqp3ha9rzCSVY+nBw+xD+B9hBlsNw=="
"-----END RSA PRIVATE KEY-----";
const char* szPemPublicKey =
"-----BEGIN PUBLIC KEY-----"
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCn7fL/1qsWkJkUtXKZIJNqYfnV"
"ByVhK/LzQecPhVR7r+4ng1nZBxg44SexS63iYlnodqDWkH/Hi82Uc0UmugY/Ow39"
"uEGeoiYqWl5BLM8pfRAGqzxbh600Qd/Oc5kYdg8hP0D/gAHXwutL74fygpB6xb8E"
"Zl2BHKvpDR80GYFlrQIDAQAB"
"-----END PUBLIC KEY-----";
int main()
{
string str_data = "test RSA implementation";
DWORD encryptedDataLen;
BYTE* encrytedData = Crypt(str_data, &encryptedDataLen);
cout << encrytedData << endl;
cout << endl;
BYTE* decryptedData = Decrypt(encrytedData, &encryptedDataLen);
cout << decryptedData << endl;
delete(encrytedData);
delete(decryptedData);
return 0;
}
BYTE* Crypt(const string& _str, DWORD* _outLength)
{
char pemPubKey[2048];
memcpy((void*)pemPubKey, szPemPublicKey, strlen(szPemPublicKey));
char derPubKey[2048];
DWORD derPubKeyLen = 2048;
CERT_PUBLIC_KEY_INFO* publicKeyInfo;
DWORD publicKeyInfoLen;
HANDLE hFile;
HCRYPTPROV hProv = 0;
HCRYPTKEY hKey = 0;
// Convert from PEM format to DER format - removes header and footer and decodes from base64
if (!CryptStringToBinaryA(pemPubKey, 0, CRYPT_STRING_BASE64HEADER, (BYTE*)derPubKey, &derPubKeyLen, NULL, NULL))
{
fprintf(stderr, "CryptStringToBinary failed. Err: %d\n", GetLastError());
return NULL;
}
// Decode from DER format to CERT_PUBLIC_KEY_INFO
if (!CryptDecodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, (BYTE*)derPubKey, derPubKeyLen,
CRYPT_ENCODE_ALLOC_FLAG, NULL, &publicKeyInfo, &publicKeyInfoLen))
{
fprintf(stderr, "CryptDecodeObjectEx 1 failed. Err: %p\n", GetLastError());
return NULL;
}
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
{
printf("CryptAcquireContext failed - err=0x%x.\n", GetLastError());
return NULL;
}
}
if (!CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING, publicKeyInfo, &hKey))
{
fprintf(stderr, "CryptImportPublicKeyInfo failed. error: %d\n", GetLastError());
return NULL;
}
// LocalFree( publicKeyInfo );
// get size of buffer
DWORD strLen = _str.length() * sizeof(char);
DWORD bufLen = strLen;
if (!CryptEncrypt(hKey, 0, true, 0, 0, &bufLen, strLen))
{
cout << "CryptEncrypt() failed with error " << GetLastError() << endl;
return NULL;
}
// Crypt string data
BYTE* cipherBlock = new BYTE[bufLen];
memset((void*)cipherBlock, 0, bufLen);
memcpy((void*)cipherBlock, _str.c_str(), strLen);
if (!CryptEncrypt(hKey, 0, TRUE, 0, cipherBlock, &strLen, bufLen))
{
cout << "CryptEncrypt() failed with error " << GetLastError() << endl;
return NULL;
}
*_outLength = bufLen;
return cipherBlock;
}
BYTE* Decrypt(BYTE* _encryptedData, DWORD* _length)
{
DWORD dwBufferLen = 0, cbKeyBlob = 0, cbSignature = 0/*,i*/;
LPBYTE pbBuffer = NULL, pbKeyBlob = NULL, pbSignature = NULL;
HCRYPTPROV hProv = NULL;
HCRYPTKEY hKey = NULL;
HCRYPTHASH hHash = NULL;
if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, NULL, &dwBufferLen, NULL, NULL))
{
cout << "Failed to convert BASE64 private key. Error " << GetLastError() << endl;
return NULL;
}
pbBuffer = (LPBYTE)LocalAlloc(0, dwBufferLen);
if (!CryptStringToBinaryA(szPemPrivKey, 0, CRYPT_STRING_BASE64HEADER, pbBuffer, &dwBufferLen, NULL, NULL))
{
cout << "Failed to convert BASE64 private key. Error " << GetLastError() << endl;
return NULL;
}
if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, NULL, &cbKeyBlob))
{
cout << "Failed to parse private key. Error " << GetLastError() << endl;
return NULL;
}
pbKeyBlob = (LPBYTE)LocalAlloc(0, cbKeyBlob);
if (!CryptDecodeObjectEx(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_RSA_PRIVATE_KEY, pbBuffer, dwBufferLen, 0, NULL, pbKeyBlob, &cbKeyBlob))
{
cout << "Failed to parse private key. Error " << GetLastError() << endl;
return NULL;
}
if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, 0))
{
if (GetLastError() == NTE_BAD_KEYSET)
{
if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
cout << "CryptAcquireContext() failed with error " << GetLastError() << endl;
return NULL;
}
}
else
{
cout << "CryptAcquireContext() failed with error " << GetLastError() << endl;
return NULL;
}
}
if (!CryptImportKey(hProv, pbKeyBlob, cbKeyBlob, NULL, 0, &hKey))
{
cout << "CryptImportKey() failed with error " << GetLastError() << endl;
return NULL;
}
// Decrypt
DWORD bufLen = *_length + 1;
BYTE* cipherBlock = new BYTE[bufLen];
memset((void*)cipherBlock, 0, bufLen);
memcpy((void*)cipherBlock, _encryptedData, *_length);
if (!CryptDecrypt(hKey, 0, TRUE, 0, cipherBlock, _length))
{
cout << "CryptDecrypt() failed with error " << GetLastError() << endl;
return NULL;
}
// Decrypted data
BYTE* decryptedData = new BYTE[*_length + 1];
decryptedData[*_length] = 0;
memcpy((void*)decryptedData, cipherBlock, *_length);
delete(cipherBlock);
if (pbBuffer) LocalFree(pbBuffer);
if (pbKeyBlob) LocalFree(pbKeyBlob);
if (pbSignature) LocalFree(pbSignature);
if (hHash) CryptDestroyHash(hHash);
if (hKey) CryptDestroyKey(hKey);
if (hProv) CryptReleaseContext(hProv, 0);
return decryptedData;
}
So, encryption\decryption works perfectly well.
I need to change keys.
How can I generate keys for this code?
I tried this online generator but it doen't work.
https://travistidwell.com/jsencrypt/demo/
and other online generators
NCryptCreatePersistedKey . Please abandon old Crypt* functions in favor of NCrypt and BCrypt* variants. If you insist on the old API, use this.

Invalid DWORD value in Registry after writing a DWORD as REG_DWORD?

I'm pretty sure my RegSetSetValueExA works fine, My data I'm writing is (CONST BYTE*)&setValue. My setvalue is a DWORD and I've already wrote to the registry with this with RegOpenKeyExA and it works fine.
I think the problem is coming from RegCreateKeyExA because I'm creating my new key from that.
Also, my REG_DWORD requires me to write in Binary for some reason
https://gyazo.com/e418587d579a3e540656f06a2524901f
I've tried looking at other threads but everyone's problem seems different to mine because they're using RegOpenKeyExA.
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <Windows.h>
#include <cstdio>
#include "Strsafe.h"
// Stolen microsoft error code credits:msdn
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
// end of stolen code
int main()
{
DWORD Disposition = REG_CREATED_NEW_KEY;
BYTE lpData[32];
DWORD setValue = 2;
PHKEY throwAwayKey = 0;
DWORD lpType = { REG_DWORD };
DWORD lpcbData = { sizeof(lpData) };
HKEY hKey = 0;
char regPath[64] = "Software\\Policies\\Microsoft\\Windows\\System";
char lpValueName[32] = "DisableCMD";
long RegCKExA = RegCreateKeyExA(HKEY_CURRENT_USER, regPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &Disposition);
if (RegCKExA == ERROR_SUCCESS)
{
std::cout << "Successfully executed RegCreatKeyExA\n";
}
else
{
std::cout << "An error has occurred while executing RRegCreateKeyExA. Error code: ";
ErrorExit((LPTSTR)TEXT("RegCreateKeyExA"));
getchar();
return EXIT_FAILURE;
}
long regQVExA = RegQueryValueExA(hKey, lpValueName, NULL, &lpType, (LPBYTE)lpData, &lpcbData);
if (regQVExA == ERROR_SUCCESS)
{
std::cout << "Successfully executed RegQueryValueExA and DisableCMD is already on this computer. Press ENTER to continute\n";
getchar();
return ERROR_SUCCESS; // Difference is it returns here if DisableCMD exists
}
else
std::cout << "DisableCMD not found. Starting creation of DisableCMD registry value. Press ENTER to continue";
getchar();
auto regSVExA = RegSetValueExA(hKey, lpValueName, 0, REG_DWORD, (CONST BYTE*)&setValue, lpcbData);
if (regSVExA == ERROR_SUCCESS)
{
std::cout << "Successfully executed RegSetValueExA\n";
getchar();
}
else
{
std::cout << "An error has occurred while executing RegSetValueExA. Error code: ";
getchar();
return EXIT_FAILURE;
}
RegCloseKey(hKey);
return 0;
}
I refactored your functions as WriteDWORD and ReadDWORD.
Note that the code is actually VERY SIMILAR to your code. So why did I bother? Well, there is one subtle difference in that I made DWORD the input/output type instead of the BYTE array you had.
LSTATUS WriteDWORD(LPCSTR lpPath, LPCSTR lpValueName, DWORD dwData)
{
LSTATUS status = ERROR_SUCCESS;
HKEY hKey = NULL;
DWORD dwDisposition = 0;
status = RegCreateKeyExA(HKEY_CURRENT_USER, lpPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition);
if (status != ERROR_SUCCESS)
{
return status;
}
status = RegSetValueExA(hKey, lpValueName, 0, REG_DWORD, (CONST BYTE*) &dwData, sizeof(DWORD));
RegCloseKey(hKey);
return status;
}
LSTATUS ReadDWORD(LPCSTR lpPath, LPCSTR lpValueName, DWORD* pdwData)
{
LSTATUS status = ERROR_SUCCESS;
HKEY hKey = NULL;
DWORD dwDisposition = 0;
status = RegCreateKeyExA(HKEY_CURRENT_USER, lpPath, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition);
if (status != ERROR_SUCCESS)
{
return status;
}
DWORD dwType = 0;
DWORD cbData = sizeof(DWORD);
status = RegQueryValueExA(hKey, lpValueName, NULL, &dwType, (LPBYTE)pdwData, &cbData);
RegCloseKey(hKey);
return status;
}
Here is a sample usage:
int main()
{
char szPath[64] = "Software\\Policies\\Microsoft\\Windows\\System";
char szValueName[32] = "DisableCMD";
WriteDWORD(szPath, szValueName, 1234);
DWORD dwValue = 0;
ReadDWORD(szPath, szValueName, &dwValue); // dwValue now contains 1234
return 0;
}
Note that I did a few things:
I used DWORD dwData for the writer but DWORD* pdwData for the reader.
I preinitialized DWORD cbData = sizeof(DWORD); (i.e. 4)
I hope this gives you insight to the "Binary" part of your question. A DWORD is 4 bytes. When you wrote it to the registry, you are telling it to store a DWORD which is a 32 bit number or 4 bytes. When you read it back from registry, to reconstitute in your app you should supply a pointer to a DWORD. Since you gave it a byte array, the 32 bit number populated the first 4 bytes of the array you supplied. You may not have understood it but it is the correct behavior.
If you used std::cout you will find that it reacts differently to the same 4 bytes because of the overloaded C++ type. If you had used a DWORD you would have seen your number. However, since you have it in your byte array, it will be binary gibberish.

Cannot read string from Windows registry

My goal is to get the current SetupPath of the installed Outlook Version.
I use the following code in order to achieve that:
HKEY hKey;
LONG lReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\OUTLOOK.EXE"),
0L,
KEY_ALL_ACCESS,
&hKey);
if (lReturn == ERROR_SUCCESS)
{
CString strData;
DWORD dwSize = 1024;
DWORD dwType;
lReturn = RegQueryValueEx(hKey,
_T("Path"),
0L,
&dwType,
(BYTE *)strData.GetBufferSetLength((int)dwSize),
&dwSize);
if (lReturn == ERROR_SUCCESS)
{
cout << strData;
}
else {
cout << "Read DWORD failed";
}
}
else {
cout << "Open Key failed";
}
RegCloseKey(hKey);
But however this won't work. It fails at opening the Key.
EDIT
I found that the "open key failed" Output was simply an Acces Denied caused by non admin rights. But however if i run it in Admin mode the output is a Hexadecimal Value which will change everytime.
First, since you are using C++, consider making your coding life simpler, defining a simple class that automatically calls RegCloseKey() on the open key.
Then, when you open the key, consider the minimum flag you need for access: in particular, this sounds like KEY_READ in your case.
Moreover, I would call RegGetValue() instead of RegQueryValueEx(), as the former makes sure that the returned string is NUL-terminated (simplifying your code a little bit).
Moreover, when you print the CString, consider calling its GetString() method, to get the const wchar_t* C-style string pointer, instead of passing the CString object to cout.
Finally, I've simplified your code using wchar_t instead of TCHAR.
Compilable code follows (I used VS2015 and tested it on Windows 10):
#include <Windows.h>
#include <atlbase.h>
#include <atlstr.h>
#include <iostream>
using namespace std;
class ScopedKey
{
public:
explicit ScopedKey(HKEY hKey)
: m_hKey(hKey)
{
}
~ScopedKey()
{
::RegCloseKey(m_hKey);
}
HKEY Get() const
{
return m_hKey;
}
// Ban copy
ScopedKey(const ScopedKey&) = delete;
ScopedKey& operator=(const ScopedKey&) = delete;
private:
HKEY m_hKey;
};
int main()
{
constexpr int kExitOk = 0;
constexpr int kExitError = 1;
//
// Open the registry key
//
HKEY hKey;
LONG retCode = ::RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\OUTLOOK.EXE",
0,
KEY_READ,
&hKey
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegOpenKeyEx() failed; error code = " << retCode << '\n';
return kExitError;
}
// Auto-close the registry key
ScopedKey key(hKey);
//
// Get the size of the path string
//
const wchar_t* valueName = L"Path";
DWORD dataSizeInBytes = 0;
retCode = ::RegGetValue(
hKey,
nullptr,
valueName,
RRF_RT_REG_SZ,
nullptr,
nullptr,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
//
// Read the path string from the registry
//
const DWORD sizeInWchars = dataSizeInBytes / sizeof(wchar_t);
CStringW str;
wchar_t* buffer = str.GetBuffer(sizeInWchars);
retCode = ::RegGetValue(
hKey,
nullptr,
valueName,
RRF_RT_REG_SZ,
nullptr,
buffer,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
str.ReleaseBuffer();
wcout << L"Path = [" << str.GetString() << L"]\n";
// Auto-closed at end of scope
// ::RegCloseKey(hKey);
return kExitOk;
}
Output:
Path = [C:\Program Files (x86)\Microsoft Office\Root\Office16\]
In addition, you can even use RegGetValue() to automatically open (and close) the registry key for you, e.g.:
#include <Windows.h>
#include <atlbase.h>
#include <atlstr.h>
#include <iostream>
using namespace std;
int main()
{
constexpr int kExitOk = 0;
constexpr int kExitError = 1;
//
// Get the size of the path string
//
const wchar_t* subKey = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\OUTLOOK.EXE";
const wchar_t* valueName = L"Path";
DWORD dataSizeInBytes = 0;
LONG retCode = ::RegGetValue(
HKEY_LOCAL_MACHINE,
subKey,
valueName,
RRF_RT_REG_SZ,
nullptr,
nullptr,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
//
// Read the path string from the registry
//
const DWORD sizeInWchars = dataSizeInBytes / sizeof(wchar_t);
CStringW str;
wchar_t* buffer = str.GetBuffer(sizeInWchars);
retCode = ::RegGetValue(
HKEY_LOCAL_MACHINE,
subKey,
valueName,
RRF_RT_REG_SZ,
nullptr,
buffer,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
str.ReleaseBuffer();
wcout << L"Path = [" << str.GetString() << L"]\n";
return kExitOk;
}

Manipulating Windows Registry

I want every time my program runs make this process:
1- Check if there is a windows registry key called "foo"
2- If it not exists create with the value 10
3- If it exists decrement its value
4- If its value == 0 close de program
I know that i will use this functions, but i don't know how to use them:
RegCreateKeyA, RegSetValueExA
The function to create the key worked, but I can not to set the values and do not know how to do what I need.
HKEY key;
RegCreateKeyA(HKEY_CURRENT_USER,"foo",&key);
RegOpenKeyExA(HKEY_CURRENT_USER,"foo", 0, KEY_ALL_ACCESS, &key);
RegSetValueExA(key,"bar",0,REG_DWORD,(LPBYTE)10,sizeof(10));
Try something like this:
HKEY key;
DWORD disposition;
LONG lRet = RegCreateKeyEx(HKEY_CURRENT_USER, TEXT("foo"), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE | KEY_SET_VALUE, NULL, &key, &disposition);
if (lRet != 0)
{
// error handling...
}
else
{
DWORD value;
if (disposition == REG_CREATED_NEW_KEY)
{
value = 10;
lRet = RegSetValueEx(key, TEXT("bar"), 0, REG_DWORD, (LPBYTE)&value, sizeof(value));
if (lRet != 0)
{
// error handling...
}
}
else
{
DWORD size = sizeof(value);
lRet = RegQueryValueEx(key, TEXT("bar"), NULL, NULL, (LPBYTE)&value, &size);
if (lRet != 0)
{
// error handling...
}
else
{
if (value != 0)
{
--value;
lRet = RegSetValueEx(key, TEXT("bar"), 0, REG_DWORD, (LPBYTE)&value, sizeof(value));
if (lRet != 0)
{
// error handling...
}
}
if (value == 0)
{
// signal app to terminate...
}
}
}
RegCloseKey(key);
}