Cannot get user level registry value even using RegOpenCurrentUser from system service - c++

I wrote a system service, in which I want to get the active user's one registry value under HKEY_CURRENT_USER. I wrote the code as below. However, it seems it can only get the system level registry value, cannot get the active user's registry value. See the code below. Where is the problem? Something missing?
void GetUserRegistryFromSystemService()
{
#ifdef Q_OS_WIN
DWORD sessionId = WTSGetActiveConsoleSessionId();
qInfo() << "Session ID = " << sessionId;
wchar_t * ppUserName[100];
DWORD sizeOfUserName;
WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSUserName, ppUserName, &sizeOfUserName);
qInfo() << "Windows User Name = " << QString::fromWCharArray(*ppUserName);
std::wstring strValueOfBinDir = L"Unknown Value";
LONG regOpenResult = ERROR_SUCCESS;
HANDLE hUserToken = NULL;
HANDLE hFakeToken = NULL;
if (WTSQueryUserToken(sessionId, &hUserToken))
{
if (DuplicateTokenEx(hUserToken, TOKEN_ASSIGN_PRIMARY | TOKEN_ALL_ACCESS, 0, SecurityImpersonation, TokenPrimary, &hFakeToken) == TRUE)
{
qInfo() << "Before ImpersonateLoggedOnUser()......";
if (ImpersonateLoggedOnUser(hFakeToken))
{
HKEY hKey;
regOpenResult = RegOpenCurrentUser(KEY_READ, &hKey);
if (regOpenResult != ERROR_SUCCESS)
{
qCritical() << "Failed to call RegOpenCurrentUser(), Error is " << regOpenResult;
}
// Fails to get this hive, will get the default value "Unkown"
RegOpenKeyEx(HKEY_CURRENT_USER,
TEXT("Software\\Baidu\\BaiduYunGuanjia"),
0,
KEY_READ,
&hKey);
GetStringRegKey(hKey, TEXT("installDir"), strValueOfBinDir, TEXT("Unknown"));
// It can get the following hive successfully
// RegOpenKeyEx(HKEY_LOCAL_MACHINE,
// TEXT("Software\\GitForWindows"),
// 0,
// KEY_READ,
// &hKey);
// GetStringRegKey(hKey, TEXT("InstallPath"), strValueOfBinDir, TEXT("Unknown"));
RevertToSelf();
}
else
{
qCritical() << "Failed to ImpersonateLoggedOnUser...";
}
CloseHandle(hFakeToken);
}
else
{
qCritical() << "Failed to call DuplicateTokenEx...";
}
CloseHandle(hUserToken);
}
else
{
qCritical() << "Failed to get the user token of session " << sessionId;
}
qInfo() << "The value of Registry is " << QString::fromWCharArray( strValueOfBinDir.c_str() );
#endif
}

You should use HKEY handle received from RegOpenCurrentUser in the RegOpenKeyEx instead of HKEY_CURRENT_USER:
regOpenResult = RegOpenCurrentUser(KEY_READ, &hKey);
if (regOpenResult != ERROR_SUCCESS)
{
qCritical() << "Failed to call RegOpenCurrentUser(), Error is " << regOpenResult;
}
HKEY hSubKey;
// Fails to get this hive, will get the default value "Unkown"
RegOpenKeyEx(hKey, TEXT("Software\\Baidu\\BaiduYunGuanjia"), 0, KEY_READ, &hSubKey);

Related

How can I create new key in a registry and set its value in C++?

I've been trying to do it for over a week but I still don't know how to do it. I want to create new key in LOCAL_MACHINE in registry. This is my code:
#include <iostream>
#include <windows.h>
using namespace std;
int main() {
HKEY hKey;
LPCSTR sk = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
LONG openRes = RegCreateKeyExA(
HKEY_LOCAL_MACHINE,
sk,
NULL,
NULL,
REG_OPTION_CREATE_LINK,
WRITE_OWNER,
NULL,
&hKey,
NULL);
if (openRes == ERROR_SUCCESS) {
cout << "Success creating key" << endl;
} else {
cout << "Error creating key" << endl;
}
LPCSTR val = "example_value";
LPCSTR data = "example_data";
LONG setRes = RegSetValueExA(hKey, val, 0, REG_SZ, (LPBYTE)data, (strlen(data) + 1) * sizeof(char));
if (setRes == ERROR_SUCCESS) {
cout << "Success writing to Registry" << endl;
} else {
cout << "Error writing to Registry" << endl;
}
RegCloseKey(hKey);
cin.get();
return 0;
}
I also run the app as an administrator so I thought it shouldn't be a problem to create a key, but it actually is. Kind of result is "Success creating key" and "Success writing to Registry", but when I look into the registry, I don't see any changes. Has anybody got an idea what's going on?

WINAPI Read all access rights for a custom file or a folder

I have a task based on an algorithm to receive the access rights for a certain file or folder and I've tried to implement it but some parts don't seem to be clear.
What I've been asked for:
1) Use the function GetNamedSecurityInfo(), for example:
GetNamedSecurityInfo(path,SE_FILE_OBJECT,DACL_SECURITY_INFORMATION,NULL,
NULL,&a,NULL, &pSD)
2) Futher, use an SID to receive the rights: Use
these functions to receive the SID: GetAclInformation(), then GetAce().
3) Now you can use the LookupAccountSid() function and if is was
successfull, compare pACE->Mask with all the constants, for example
"GENERIC_ALL, GENERIC_READ, GENERIC_WRITE, GENERIC_EXECUTE for files
etc." displaying the access rights.
And how I tried to implement this algorithm: // First getting process SID
PSID g_pSID;
BOOL GetCurrentProcessSID()
{
DWORD dwSize = 0, dwError, dwResult = 0;
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
printf("OpenProcessToken Error %u\n", GetLastError());
return FALSE;
}
// Call GetTokenInformation to get the buffer size.
TOKEN_USER tU;
if (!GetTokenInformation(hToken, TokenUser, &tU, 0, &dwSize))
{
dwError = GetLastError();
if (dwError != ERROR_INSUFFICIENT_BUFFER)
{
std::cout << "GetTokenInformation failed, error " << dwError;
CloseHandle(hToken);
return 0;
}
}
PTOKEN_OWNER to = (PTOKEN_OWNER)LocalAlloc(LPTR, dwSize);
if (!to)
{
dwError = GetLastError();
std::cout << "LocalAlloc failed, error " << dwError;
CloseHandle(hToken);
return 0;
}
if (!GetTokenInformation(hToken, TokenOwner, to, dwSize, &dwSize))
{
dwError = GetLastError();
std::cout << "GetTokenInformation failed, error " << dwError;
LocalFree(to);
CloseHandle(hToken);
return 0;
}
g_pSID = to->Owner;
return TRUE;
}
//Then I used the iteration through the ACL list:
std::stringstream g_TestSecurityResult;
void TestSecurity( wchar_t* path )
{
g_TestSecurityResult = std::stringstream();
GetCurrentProcessSID();
PACL pDacl;
PSECURITY_DESCRIPTOR pSD;
GetNamedSecurityInfoW(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pDacl, NULL, &pSD);
ACL_SIZE_INFORMATION aclSizeInfo = { sizeof(ACL) };
BOOL fResult = GetAclInformation( pDacl, &aclSizeInfo, sizeof(ACL_SIZE_INFORMATION), ACL_INFORMATION_CLASS::AclSizeInformation );
if (fResult)
{
for (DWORD dwIndex = 0; dwIndex < aclSizeInfo.AceCount; ++dwIndex)
{
LPVOID pTempAce = nullptr;
fResult = ::GetAce(pDacl, dwIndex, &pTempAce);
if (fResult)
{
PSID pSid = &((ACCESS_ALLOWED_ACE*)pTempAce)->SidStart;
if (EqualSid(pSid, &g_pSID))
{
g_TestSecurityResult << "User: " << userNameFromSid(&g_pSID) << std::endl;
g_TestSecurityResult << "\tAccess mode: " << ((EXPLICIT_ACCESS*)pTempAce)->grfAccessMode << "\n";
g_TestSecurityResult << "\tAccess permissions: " << ((EXPLICIT_ACCESS*)pTempAce)->grfAccessPermissions << "\n";
g_TestSecurityResult << "\tInheritance: " << ((EXPLICIT_ACCESS*)pTempAce)->grfInheritance << "\n";
g_TestSecurityResult << std::endl;
}
}
else
{
g_TestSecurityResult << "GetAce() failed." << GetLastError();
break;
}
}
} else {
g_TestSecurityResult << "Error in GetAclInformation(): " << GetLastError();
}
}
std::string userNameFromSid(PSID userSid)
{
char buffName[MAX_BUFF_SIZE];
DWORD buffNameSize = MAX_BUFF_SIZE;
char buffDomain[MAX_BUFF_SIZE];
DWORD buffDomainSize = MAX_BUFF_SIZE;
SID_NAME_USE SidType;
if (LookupAccountSid(NULL, userSid, buffName, &buffNameSize, buffDomain, &buffDomainSize, &SidType)) {
return buffName;
} else {
DWORD dwResult = GetLastError();
printf("GetTokenInformation Error %u\n", dwResult);
}
/*Here some code to print error in a Message box*/
return "";
}
The problem: The code is working but at the line if (EqualSid(pSid, &g_pSID)) debugger goes through and skips the SID that I've received from my process. In other words, I can't get any information from the ACL list, even though I'm running the process and Visual Studio under Administrator account (not using the "Run as Administrator", and I'll try it but still... The received SID is valid and I can get the name of the process owner using the above function. What could be something that I'm doing wrong here?
Code sources:
https://gist.github.com/m4x1m1l14n/37f39c5d25855c2b1d3a6334851f7549
How to get the logged-on user's SID in Windows
GetTokenInformation, TOKEN_OWNER, и LookupAccountSidA
Thanks to #(Rita Han - MSFT) comment, I've forgotten to remove the ampersand mark from the pSID comparison
EqualSid(pSid, g_pSID);
instead of
EqualSid(pSid, &g_pSID);
And It's properly working for now

SHGetValue returns 2 when querying UAC value

I would like to check the UAC configuration settings of windows. And thus recover the parameters of the UAC in the registry keys.
I used the windows SHGetValue function but the status always returns me 2 without any information.
I use C++11, MinGW and windows.
My code is :
DWORD dwStatus;
LPCSTR pszSubKey= "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
LPCSTR pszValue="";
DWORD pdwType=REG_SZ;
PVOID pvData[63];
DWORD pcbData;
pcbData=sizeof(pvData);
dwStatus=SHGetValueA(HKEY_LOCAL_MACHINE, pszSubKey, pszValue, &pdwType, pvData, &pcbData);
//Here dwStatus = 2
// pvData = 0x11fd0b2
// pcbData = 504
What specific key you are trying to read? I am not an expert on win32 API so I don't know whether there is a way to read a set of keys at once (Edit: I think there areRegEnumValue/RegEnumValueA functions for this purpose). Here is an example that shows how you can read "EnableLUA" or any other key from that path:
#include <windows.h>
#include <iostream>
#include <shlwapi.h>
bool ReadUACRegistryKey(char* key, DWORD &keyValue)
{
LPCTSTR pszSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
LPCTSTR pszValue = key;
// don't care
DWORD dwType = 0;
DWORD dwValue = 0;
//
DWORD dwValueSize = sizeof(dwValue);
int retval = SHGetValue( HKEY_LOCAL_MACHINE, pszSubKey, key, &dwType, &dwValue, &dwValueSize);
if ( retval != ERROR_SUCCESS)
{
return false;
}
keyValue = dwValue;
return true;
}
int main()
{
DWORD keyValue;
char* key = "EnableLUA"; // "EnableSecureUIAPaths" etc..;
if (ReadUACRegistryKey(key, keyValue))
{
std::cout << "Successfully readed key " << key << ", value:" << keyValue << std::endl;
}
else
{
std::cout << "Unable to read value of key " << key << std::endl;
}
return 0;
}
Also keep in mind that value of read key value is stored in value parameter, not in the return value of the function.
Edit: Answer of the the op's comment "I want use FilterAdministratorToken but is disable by default how give it back enable .?". Keep in mind that your process need to have admin rights to perform these operation.
#include <windows.h>
#include <iostream>
#include <shlwapi.h>
bool ReadUACRegistryKey(char* key, DWORD &keyValue)
{
LPCTSTR pszSubKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
LPCTSTR pszValue = key;
// don't care
DWORD dwType = 0;
DWORD dwValue = 0;
//
DWORD dwValueSize = sizeof(dwValue);
int retval = SHGetValue( HKEY_LOCAL_MACHINE, pszSubKey, key, &dwType, &dwValue, &dwValueSize);
if ( retval != ERROR_SUCCESS)
{
return false;
}
keyValue = dwValue;
return true;
}
bool EnableFilterAdministratorToken()
{
// first check if its already enabled or not
DWORD val;
if (ReadUACRegistryKey("FilterAdministratorToken", val))
{
if (val == 1)
{
std::cout << "FilterAdministratorToken is already enabled" << std::endl;
return true;
}
}
else
{
std::cout << "Unable to read key" << std::endl;
return false;
}
// its not enabled, we need to enable it manually
// obtain a handle to reg key
HKEY hKey;
int retval = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", 0, KEY_SET_VALUE, &hKey);
if (retval != ERROR_SUCCESS)
{
// we are unable to obtain a handle to reg key
std::cout << "Unable to obtain handle to reg key" << std::endl;
return false;
}
DWORD enabledValue = 1;
retval = RegSetValueExA(hKey, "FilterAdministratorToken", 0, REG_DWORD, (BYTE*) &enabledValue, sizeof(DWORD));
if (retval != ERROR_SUCCESS)
{
// some error occured
std::cout << "Some error occured during setting the key value" << std::endl;
RegCloseKey(hKey);
return false;
}
std::cout << "Successfully changed key value" << std::endl;
RegCloseKey(hKey);
return true;
}
int main()
{
if (EnableFilterAdministratorToken())
{
std::cout << "OK" << std::endl;
}
else
{
std::cout << "FAIL" << std::endl;
}
return 0;
}

How do I read/change the registry values that another windows service created?

So basically I have a service which is meant to act as my Program Update Manager. This is all in my efforts to make an automatically updating program that doesn't need the user to be signed in.
So my update manager when installed creates some initial registry values/structures with the following code:
LPCWSTR strInITKeyName = L"SOFTWARE\\InIT\\";
DWORD rtime = 0;
HKEY InITKey;
LONG nInITError;
nInITError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0, 0, &InITKey);
if (ERROR_NO_MATCH == nInITError || ERROR_FILE_NOT_FOUND == nInITError)
{
std::cout << "Registry key not found. Setting up..." << std::endl;
long nError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &InITKey, NULL);
if (ERROR_SUCCESS != nError)
std::cout << "Error: Could not create registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nError << std::endl;
else
{
std::cout << "Successfully created registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl;
// See https://www.experts-exchange.com/questions/10171094/Using-RegSetKeySecurity.html for example
//SECURITY_DESCRIPTOR sd;
//PACL pDacl = NULL;
//RegSetKeySecurity(InITKey);
}
}
else if (nInITError == ERROR_ACCESS_DENIED)
{
long nError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &InITKey, NULL);
if (ERROR_SUCCESS != nError)
std::cout << "Error: Could not create registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nError << std::endl;
else
std::cout << "Successfully created registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl;
}
else if (ERROR_SUCCESS != nInITError)
{
std::cout << "Cannot open registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nInITError << std::endl;
rtime = 0;
}
// Generate guid
//
GUID guid;
HRESULT hr = CoCreateGuid(&guid);
// Convert the GUID to a string
OLECHAR* guidString;
StringFromCLSID(guid, &guidString);
// Setup registry values
// Sets clientguid value and ties to strInITKeyName
std::wstring clientguid = guidString; // InITKey
clientguid = clientguid.substr(1, 36);
LONG nClientGUIDError = RegSetValueEx(InITKey, L"clientguid", NULL, REG_SZ, (const BYTE*)clientguid.c_str(), (clientguid.size() + 1) * sizeof(wchar_t));
if (nClientGUIDError)
std::cout << "Error: " << nClientGUIDError << " Could not set registry value: " << "clientguid" << std::endl;
else
std::wcout << "Successfully set InIT clientguid to " << clientguid << std::endl;
// ensure memory is freed
::CoTaskMemFree(guidString);
RegCloseKey(InITKey);
When it is uninstalled, it then deletes the registry values. My actual program is a windows service that will be running on the installed computer which needs to access some of those registry values.
Previously I did not have this update manager, and instead was setting the values in the registry in the actual program service. Reading, and writing worked just fine then. But since I've switched to having my Update Manager set these initial values and intend for my main windows service to access them.
When I try to do this, I've without fail, every time, received an ERROR_ACCESS_DENIED error, despite trying all kinds of different Security tokens like KEY_READ || KEY_WOW64_64KEY and others in many combinations when trying to open the key. As you saw above, I am or-ing KEY_ALL_ACCESS when setting the token. I would think I should be able to access it fine, but it doesn't let me. The only conclusion I can come to is that somehow my Update manager has ownership over the keys/values in the registry.
What would the right code be to access these registry files from my main windows service?
My current code for accessing those registry values (the clientguid that I generate on install of the Update Manager see above code):
// Log a service start message to the Application log.
WriteEventLogEntry(L"InITService Starting in OnStart", EVENTLOG_INFORMATION_TYPE);
this->m_ServiceLogger->info("Initialized logger bruh");
// Query clientguid from registry
HKEY InITKey;
std::wstring valuename;
ULONG nError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\InIT\\", 0, KEY_READ || KEY_WOW64_64KEY, &InITKey);
DWORD dwBufferSize = TOTALBYTES;
DWORD cbData;
WCHAR *wcBuffer = (WCHAR*)malloc(dwBufferSize);
cbData = dwBufferSize;
if (nError == ERROR_SUCCESS)
this->m_ServiceLogger->info("Getting reg");
if (nError == ERROR_SUCCESS)
{
std::wstring clientguid;
clientguid = L"";
valuename = L"clientguid";
nError = RegQueryValueExW(HKEY_LOCAL_MACHINE, valuename.c_str(), 0, NULL, (LPBYTE) wcBuffer, &cbData);
while (nError == ERROR_MORE_DATA) // Get a buffer that is big enough if not already
{
this->m_ServiceLogger->info("Increasing clientguid buffer size");
dwBufferSize += BYTEINCREMENT;
wcBuffer = (WCHAR*) realloc( wcBuffer, dwBufferSize );
cbData = dwBufferSize;
nError = RegQueryValueExW(HKEY_LOCAL_MACHINE, valuename.c_str(), 0, NULL, (LPBYTE)wcBuffer, &cbData);
}
if (ERROR_SUCCESS == nError)
{
clientguid = wcBuffer;
std::string cg(clientguid.begin(), clientguid.end());
this->m_ClientGuid = cg;
this->m_ServiceLogger->info("Clientguid yo: " + cg);
}
else if (nError = ERROR_ACCESS_DENIED)
this->m_ServiceLogger->info("ClientGUID: Access Denied");
if (!this->checkRegistryValues())
{
this->generateRegistry();
}
}
else
{
std::stringstream errstr;
errstr << nError;
this->m_ServiceLogger->info("Error: " + errstr.str() + " RegOpenKeyEx failed");
}
this->setSchedulingUtility(); // Hardcoded to set scheduled update at 1:00 AM
WriteEventLogEntry(L"InITService Initialized Schedule in OnStart", EVENTLOG_INFORMATION_TYPE);
this->m_ServiceLogger->info("Initialized ClientGUID: " + this->m_ClientGuid);
this->m_ServiceLogger->info("Initialized CurrentVersion: " + this->m_CurrentVersion);
this->m_ServiceLogger->info("Initialized WebServerURL: " + this->m_POSTAddress);
this->m_ServiceLogger->flush();
RegCloseKey(InITKey);
// Queue the main service function for execution in a worker thread.
CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this);
When calling RegOpenKeyEx(), you need to use the BITWISE OR (|) operator instead of the LOGICAL OR (||) operator. Change:
KEY_READ || KEY_WOW64_64KEY
To:
KEY_READ | KEY_WOW64_64KEY
However, when your Update Manager calls RegOpenKeyEx(), it is not specifying any access rights at all, it is setting the samDesired parameter to 0. It should be setting it to at least KEY_SET_VALUE instead. When it calls RegCreateKeyEx() if RegOpenKeyEx() fails, it is setting the samDesired to KEY_ALL_ACCESS. Don't do that. Use only the access rights that you actually need (KEY_SET_VALUE, etc).
In any case, there is no need to call both RegOpenKeyEx() and RegCreateKeyEx() anyway. Just call RegCreateKeyEx() by itself. It will open an existing key, and create a non-existing key. Its dwDisposition output parameter will tell you which happened.
There are other mistakes in this code, too. Like passing the wrong HKEY to RegQueryValueEx(), and not checking for the ERROR_ACCESS_DENIED error code correctly (using the = assignment operator instead of the == comparison operator). And memory leaks.
Try something more like this instead:
Update Manager:
LPCWSTR strInITKeyName = L"SOFTWARE\\InIT\\";
HKEY InITKey;
DWORD dwDisposition;
LONG nError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE | KEY_WOW64_64KEY, NULL, &InITKey, &dwDisposition);
if (ERROR_SUCCESS != nError)
{
std::cout << "Error: Could not open/create registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nError << std::endl;
}
else
{
std::cout << "Successfully " << ((REG_CREATED_NEW_KEY == dwDisposition) ? "created" : "opened") << " registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl;
// Generate guid and convert to a string
//
std::wstring clientguid;
GUID guid;
HRESULT hr = CoCreateGuid(&guid);
if (FAILED(hr))
{
std::cout << "Error: Could not generate clientguid" << std::endl << "\tERROR: " << (int)hr << std::endl;
}
else
{
WCHAR guidString[40] = {0};
int len = StringFromGUID2(guid, guidString, 40);
if (len > 2)
{
// Sets clientguid value and ties to strInITKeyName
clientguid.assign(&guidString[1], len-2);
}
}
// Setup registry values
nError = RegSetValueEx(InITKey, L"clientguid", NULL, REG_SZ, (const BYTE*) clientguid.c_str(), (clientguid.size() + 1) * sizeof(wchar_t));
if (ERROR_SUCCESS != nError)
std::cout << "Error: Could not set registry value: clientguid" << std::endl << "\tERROR: " << nError << std::endl;
else
std::wcout << "Successfully set InIT clientguid to " << clientguid << std::endl;
RegCloseKey(InITKey);
}
Program Service:
...
// Query clientguid from registry
HKEY InITKey;
LONG nError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\InIT\\", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &InITKey);
if (ERROR_SUCCESS != nError)
{
std::stringstream errstr;
errstr << nError;
this->m_ServiceLogger->info("Error: " + errstr.str() + " RegOpenKeyEx failed");
}
else
{
this->m_ServiceLogger->info("Getting reg");
std::vector<BYTE> buffer(TOTALBYTES + sizeof(wchar_t), 0); // extra room for a null terminator, in case it is missing in the Registry data
DWORD cbData = TOTALBYTES;
do
{
nError = RegQueryValueExW(InITKey, L"clientguid", 0, NULL, &buffer[0], &cbData);
if (ERROR_MORE_DATA != nError)
break;
// Get a buffer that is big enough if not already
this->m_ServiceLogger->info("Resizing clientguid buffer");
buffer.resize(cbData + sizeof(wchar_t));
}
while (true);
if (ERROR_SUCCESS == nError)
{
std::wstring clientguid = (WCHAR*) &buffer[0];
std::string cg(clientguid.begin(), clientguid.end());
this->m_ClientGuid = cg;
this->m_ServiceLogger->info("Clientguid yo: " + cg);
}
else if (ERROR_ACCESS_DENIED == nError)
{
this->m_ServiceLogger->info("ClientGUID: Access Denied");
}
else
{
std::stringstream errstr;
errstr << nError;
this->m_ServiceLogger->info("Error: " + errstr.str() + " RegQueryValueEx failed");
}
RegCloseKey(InITKey);
if (!this->checkRegistryValues())
{
this->generateRegistry();
}
}
...

C++ Writing a DWORD value to all subkeys of a certain registry key

I have trouble making this code I found work for me.
Now: It adds 2 DWORD values the the Interface folder (registry key) in registry.
Desired: I would want it to add those 2 DWORD values to ALL the subkeys (subfolders) of the Interface registry key (folder).
I have got this pseudo code:
Open the parent key with RegOpenKey or RegOpenKeyEx
Enumerate all of the child keys of the parent using RegEnumKey or RegEnumKeyEx in a loop
For each child key, set the desired value with RegSetValueEx
Close the parent key with RegCloseKey
I'll keep trying to get this sorted, but maybe someone can help?
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <iostream>
using std::cout;
using std::endl;
HKEY OpenKey(HKEY hRootKey, wchar_t* 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 SetVal(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 GetVal(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; // The value will be created and set to data next time SetVal() is called.
}
else if(nError)
{
cout << "Error: " << nError << " Could not get registry value " << (char*)lpValue << endl;
}
return data;
}
int main()
{
static DWORD v1, v2;
HKEY hKey = OpenKey(HKEY_LOCAL_MACHINE,L"SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces\\");
v1 = GetVal(hKey, L"Registry Value1");
v2 = GetVal(hKey, L"Registry Value2");
v1 += 5;
v2 += 2;
SetVal(hKey, L"Registry Value1", v1);
SetVal(hKey, L"Registry Value2", v2);
RegCloseKey(hKey);
return 0;
}
Here's a bare minimum example without any extras:
// open desired key whose subkeys shall be enumerated
HKEY hKey={0};
LPCTSTR path=TEXT("SYSTEM\\CurrentControlSet\\services\\Tcpip\\Parameters\\Interfaces");
if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,path,0,KEY_ENUMERATE_SUB_KEYS,&hKey) != ERROR_SUCCESS)
return; // failed to open
DWORD index=0; // enumeration index
TCHAR keyName[256]={0}; // buffer to store enumerated subkey name
DWORD keyLen=256; // buffer length / number of TCHARs copied to keyName
// enumerate subkey names of hKey, result stored in keyName, keyLen set to strlen(keyName)
while(RegEnumKeyEx(hKey,index++,keyName,&keyLen,0,0,0,0) == ERROR_SUCCESS) {
keyLen=256; // reset buffer length (RegEnumKeyEx changes this value)
// open the subkey and set the desired value(s)
HKEY hSubKey={0};
if(RegOpenKeyEx(hKey,keyName,0,KEY_SET_VALUE,&hSubKey) == ERROR_SUCCESS) {
// set desired value(s):
DWORD myValue = 0xCAFEBABE;
//RegSetValueEx(hSubKey,TEXT("MyValueName"),0,REG_DWORD,(LPBYTE)&myValue,sizeof(DWORD));
RegCloseKey(hSubKey); // close sub key
}
// else: failed to open subkey
}
// RegEnumKeyEx either returns ERROR_SUCCESS, ERROR_NO_MORE_ITEMS, or a system error code
RegCloseKey(hKey); // close key
Please note, this example does not evaluate error codes. It simply demonstrates the process of enumerating sub keys and setting a value. The RegOpenKeyEx access rights are set to the minimum required to perform this task (set them to whatever you wish to do with the opened keys). The while loop does not distinct from ERROR_NO_MORE_ITEMS (once there are no more subkeys to enumerate) or an actual error. RegSetValueEx is commented out for safety and its return value is ignored.