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;
}
Related
How can I check through C++ code if the Internet Date and Time setting is enabled or not:
Control Panel>"Date and Time">"Set the time and date">"Internet Time">"Change settings…"
This setting:
Here is one of the check methods via WinAPI and the registry.
We will look for HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer values (check https://techlibrary.hpe.com/docs/otlink-wo/How-to-Configure-a-Local-NTP-Server.html for more info).
There is one Enabled value that we are looking for.
So, here is a little non-optimized code with some checks (hope it works...):
#include <iostream>
#include <Windows.h>
bool is_ntp_enabled(void)
{
HKEY key;
const auto sub_key{ TEXT("SYSTEM\\CurrentControlSet\\Services\\W32Time\\TimeProviders\\NtpServer") };
if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, sub_key, NULL, KEY_QUERY_VALUE, &key)) {
std::cerr << "No registry access" << std::endl;
return false;
}
DWORD buff;
const DWORD buff_type{ KEY_READ };
const DWORD buff_size{ sizeof(buff) };
if (ERROR_SUCCESS != RegQueryValueEx(key, TEXT("Enabled"), NULL, (LPDWORD)&buff_type, (LPBYTE)&buff, (LPDWORD)&buff_size)) {
std::cerr << "No registry value access" << std::endl;
return false;
}
if (buff == 0)
return false;
else
return true;
}
int main()
{
std::cout << is_ntp_enabled() << std::endl;
}
The below code can correctly read Registry values from various different keys, however whenever I try to read a value from a key under Winlogon it will either come up as "not found" or it will return a completely wrong value. The code is ran as admin, and compiled with Visual Studio 2017.
HKEY registryHandle = NULL;
int registryResult = NULL;
DWORD dataType;
TCHAR dataBuffer[1024] = {};
DWORD bufferSize = sizeof(dataBuffer);
registryResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 0, KEY_QUERY_VALUE, ®istryHandle);
if (registryResult != ERROR_SUCCESS) {
std::cout << "Error: " << registryResult << std::endl;
return false;
}
registryResult = RegQueryValueEx(registryHandle, L"LastUsedUsername", NULL, NULL, (LPBYTE)dataBuffer, &bufferSize);
if (registryResult != ERROR_SUCCESS) {
std::cout << "Error2: " << registryResult << std::endl;
return false;
}
std::cout << "Data Size: " << bufferSize << std::endl;
for (int i = 0; i < 256; i++) {
if (dataBuffer[i] == NULL) { break; }
std::cout << (char)dataBuffer[i];
}
std::cin.get();
RegCloseKey(registryHandle);
Registry value that I'm trying to read:
Below refers to Remy's suggested solution.
RegQueryValueEx Returns a buffer size of 4 with an output of 18754 17236 0 52428
You are clearly calling the Unicode version of the Registry functions, so you should be using WCHAR instead of TCHAR for your data buffer.
And you should not be truncating the characters to char at all. Use std::wcout instead of std::cout for printing out Unicode strings. And use the returned bufferSize to know how many WCHARs were actually output. Your printing loop is ignoring the bufferSize completely, so it is possible that you are actually printing out random garbage that RegQueryValueEx() did not actually intend for you to use (hence why lpcbData parameter is an in/out parameter, so you know how many bytes are actually valid).
You are also leaking the opened HKEY handle if RegQueryValueEx() fails.
Try something more like this instead:
HKEY registryHandle;
int registryResult;
registryResult = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", 0, KEY_QUERY_VALUE, ®istryHandle);
if (registryResult != ERROR_SUCCESS) {
std::cout << "Error: " << registryResult << std::endl;
return false;
}
WCHAR dataBuffer[1024];
DWORD bufferSize = sizeof(dataBuffer);
// TODO: consider using RegGetValueW() instead, which is safer
// when it comes to reading string values from the Registry...
registryResult = RegQueryValueExW(registryHandle, L"LastUsedUsername", NULL, NULL, (LPBYTE)dataBuffer, &bufferSize);
RegCloseKey(registryHandle);
if (registryResult != ERROR_SUCCESS) {
std::cout << "Error2: " << registryResult << std::endl;
return false;
}
DWORD len = bufferSize / sizeof(WCHAR);
if ((len > 0) && (dataBuffer[len-1] == L'\0')) {
--len;
}
std::cout << "Data Byte Size: " << bufferSize << std::endl;
std::cout << "Data Character Length: " << len << std::endl;
std::wcout.write(dataBuffer, len);
std::cin.get();
return true;
That being said, on my machine, there is no LastUsedUsername value in the Winlogon key you are accessing, so getting a "not found" error is a very likely possibility. But you definately need to handle
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
So I'm trying to read Memory out of a running exe with ReadProcessMemory() as you can see in the code provided below.
The only problem I constantly run into is that I receive the Error 3E6 / 998 which seems to be NOACCESS but I cant find a solution to fix this.
And yes I tried to run the exe in Admin Mode without success...
#include <Windows.h>
#include <iostream>
#include <string>
#include <tlhelp32.h>
#include <Psapi.h>
#include <tchar.h>
using namespace std;
int id = NULL;
HANDLE hProcess = NULL;
int getPID(const string name);
bool setHandle(int id, HANDLE &out);
DWORD64 GetModule(const string name);
int main()
{
bool success = false;
id = getPID("sample.exe");
string name = "SAMPLE";
cout << "Process Name: " << name << endl;
cout << "Process ID: " << id << endl;
success = setHandle(id, hProcess);
if (success)
{
cout << "Handle set..." << endl;
}
else if (!success)
{
cout << "You need to have SOMETHING opened..." << endl;
cout << "ERROR CODE: " << GetLastError() << endl;
system("pause");
return 1;
}
success = false;
DWORD64 baseAddress = GetModule("sample.exe");
DWORD64 ammo = 0x24ED13273A8;
DWORD64 addr = baseAddress + ammo;
cout << "Base Address: " << hex << uppercase << "0x" << baseAddress << endl;
cout << "Ammo Address: " << hex << uppercase << "0x" << ammo << endl;
cout << "Complete Address: " << hex << uppercase << "0x" << addr << endl;
int buffer = 0;
success = ReadProcessMemory(hProcess, (LPCVOID)addr, (LPVOID)&buffer, sizeof(&buffer), NULL);
if (success)
{
cout << "ReadProccess succeeded..." << endl;
system("pause");
return 0;
}
else if (!success)
{
cout << "ERROR CODE: " << GetLastError() << endl;
system("pause");
return 1;
}
system("pause");
return 0;
}
bool setHandle(int id, HANDLE &out)
{
out = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
if (!out) return false;
return true;
}
int getPID(const string name)
{
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (!Process32First(snapshot, &entry)) return NULL;
do
{
if (strcmp(entry.szExeFile, name.c_str()) == 0)
{
CloseHandle(snapshot);
return entry.th32ProcessID;
}
} while (Process32Next(snapshot, &entry));
CloseHandle(snapshot);
return NULL;
}
DWORD64 GetModule(const string name)
{
HMODULE hMods[1024];
DWORD cbNeeded;
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
string modName = szModName;
if (modName.find(name) != string::npos)
{
return (DWORD64)hMods[i];
}
}
}
}
return NULL;
}
I'm kinda new to c++... so sry? :)
There are actually two basic mistakes in your code, both of which, unfortunately for you, me and the rest of the civilised world, generate the same error code. Was it ever thus. There is also a logic error, but you are lucky enough to be getting away with it (just about). I commented the fix in the code I posted below.
There are also a number of 'good practise' shortcomings in your code, specifically:
NULL should not be used to represent integer zero
All error conditions should be checked for and (sensibly!) reported
You use the same string literal in two different places (so if you ever change it, you would need to change it in both places, and you might forget). So don't do that.
using namespace std; is widely frowned upon (because it causes such a lot of namespace pollution)
Why are id and hProcess global variables? This is just plain unnecessary.
You should give your functions more descriptive names, setHandle being the one I particularly have in mind. I got rid of that one completely.
When passing a std::string as a read-only function parameter, it is usually best to pass it as const ref, then it doesn't need to be copied.
Only use std::endl when you actually want to flush the buffer. It is inefficient.
Clean up after you (in this case, close any open handles). I know this is just a throwaway program but it's a good habit to get into.
OK, so here's some code that works (I have posted my own because I cleaned up all of the above). The substantive changes are:
To read the memory of another process, you need to give your user token the SE_DEBUG_NAME privilege. This in turn means you need to run your program as Administrator (aka elevated).
You cannot (obviously) read from a nonsense address in the target process so I just quietly fixed that.
Like I say, both of these generate the same error code. Huh!
OK, here you go. Enjoy:
#include <Windows.h>
#include <iostream>
#include <string>
#include <tlhelp32.h>
#include <Psapi.h>
#include <tchar.h>
int getPID(const std::string& name);
DWORD64 GetModule(HANDLE hProcess, const std::string& name);
// Stolen from: https://learn.microsoft.com/en-gb/windows/desktop/SecAuthZ/enabling-and-disabling-privileges-in-c--
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
constexpr const char* theProcess = "notepad.exe";
int main()
{
HANDLE hToken;
BOOL ok = OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
if (!ok)
{
std::cout << "OpenProcessToken failed, error " << GetLastError() << "\n";
return 255;
}
ok = SetPrivilege (hToken, SE_DEBUG_NAME, TRUE);
if (!ok)
{
CloseHandle (hToken);
return 1;
}
int pid = getPID (theProcess);
HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess == NULL)
{
std::cout << "OpenProcess failed, error " << GetLastError() << "\n";
CloseHandle (hToken);
return 1;
}
DWORD64 baseAddress = GetModule(hProcess, theProcess);
std::cout << "Base Address: " << std::hex << std::uppercase << "0x" << baseAddress << "\n";
int buffer = 0; // Note: sizeof (buffer) below, not sizeof (&buffer)
ok = ReadProcessMemory(hProcess, (LPCVOID)baseAddress, (LPVOID)&buffer, sizeof(buffer), NULL);
CloseHandle (hProcess);
CloseHandle (hToken);
if (ok)
{
std::cout << "ReadProcessMemory succeeded, buffer = " << buffer << "\n";
system("pause");
return 0;
}
std::cout << "ReadProcessMemory failed, error " << GetLastError() << "\n";
system("pause");
return 1;
}
int getPID(const std::string& name)
{
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (!Process32First(snapshot, &entry)) return NULL;
do
{
if (strcmp(entry.szExeFile, name.c_str()) == 0)
{
CloseHandle(snapshot);
return entry.th32ProcessID;
}
} while (Process32Next(snapshot, &entry));
CloseHandle(snapshot);
return NULL;
}
DWORD64 GetModule(HANDLE hProcess, const std::string& name)
{
HMODULE hMods[1024];
DWORD cbNeeded;
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
std::string modName = szModName;
if (modName.find(name) != std::string::npos)
{
return (DWORD64)hMods[i];
}
}
}
}
return NULL;
}
Output (when run as Administrator):
Base Address: 0x7FF6D8470000
ReadProcessMemory succeeded, buffer = 905A4D
Output (when run as a normal user):
The token does not have the specified privilege.
You can also grab some code over at GitHub.
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.