This repository has been archived by the owner on Dec 2, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update README, add new solution and source files
Modified: - README.md Added: - RegistryHelper.sln - RegistryHelper/RegistryHelper.cpp - RegistryHelper/RegistryHelper.h - RegistryHelper/RegistryHelper.vcxproj - RegistryHelper/RegistryHelper.vcxproj.filters - RegistryHelper/main.cpp"
- Loading branch information
Showing
7 changed files
with
489 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,73 @@ | ||
# RegistryHelper | ||
# RegistryHelper - Accessing the Windows Registry with Modern C++ | ||
|
||
This project provides a `RegistryHelper` class for accessing the Windows Registry using Modern C++. The implementation is based on the Microsoft Dev Blog post "[Use Modern C++ to Access the Windows Registry](https://learn.microsoft.com/en-us/archive/msdn-magazine/authors/giovanni_dicanio)" by [Giovanni Dicanio](https://learn.microsoft.com/en-us/archive/msdn-magazine/2017/may/%5Carchive%5Cmsdn-magazine%5Cauthors%5CGiovanni_Dicanio). | ||
|
||
## Overview | ||
|
||
The `RegistryHelper` class allows you to read DWORD, string, and multi-string values from the Windows Registry in a convenient and modern C++ manner. | ||
|
||
## Usage | ||
|
||
To use the `RegistryHelper` class in your project, follow these steps: | ||
|
||
1. Include the "RegistryHelper.h" header file in your project. | ||
2. Add the "RegistryHelper.cpp" source file to your project. | ||
|
||
### Example Usage | ||
|
||
```cpp | ||
#include "RegistryHelper.h" | ||
#include <iostream> | ||
|
||
int | ||
main() | ||
{ | ||
try { | ||
RegistryHelper registryHelper; | ||
std::wstring subKey = L"SYSTEM\\CurrentControlSet\\Control"; | ||
HKEY hKey = HKEY_LOCAL_MACHINE; | ||
|
||
// Example 1: Reading DWORD value (REG_DWORD) | ||
std::wstring valueNameDword = L"BootDriverFlags"; | ||
|
||
DWORD dwordValue = registryHelper.RegGetDword(hKey, subKey, valueNameDword); | ||
std::wcout << L"DWORD Value: " << dwordValue << std::endl; | ||
|
||
// Example 2: Reading String value (REG_SZ) | ||
std::wstring subKeyString = L"SYSTEM\\CurrentControlSet\\Control"; | ||
std::wstring valueNameString = L"CurrentUser"; | ||
|
||
std::wstring stringValue = | ||
registryHelper.RegGetString(hKey, subKey, valueNameString); | ||
std::wcout << L"String Value: " << stringValue << std::endl; | ||
|
||
// Example 3: Reading Multi-String value (REG_MULTI_SZ) | ||
std::wstring valueNameMultiString = L"PreshutdownOrder"; | ||
|
||
std::vector<std::wstring> multiStringValue = | ||
registryHelper.RegGetMultiString(hKey, subKey, valueNameMultiString); | ||
|
||
std::wcout << L"Multi-String Values: " << std::endl; | ||
for (const auto& str : multiStringValue) { | ||
std::wcout << L" " << str << std::endl; | ||
} | ||
} catch (const RegistryError& ex) { | ||
std::cerr << "Registry Error: " << ex.what() | ||
<< " (Error Code: " << ex.ErrorCode() << ")" << std::endl; | ||
} catch (const std::exception& ex) { | ||
std::cerr << "Error: " << ex.what() << std::endl; | ||
} | ||
|
||
return 0; | ||
} | ||
``` | ||
|
||
Adjust the registry keys, subkeys, and value names based on your specific use case. | ||
|
||
## Credits | ||
|
||
This project is inspired by the Microsoft Dev Blog post "Use Modern C++ to Access the Windows Registry" by Giovanni Dicanio. The original blog post can be found [here](https://learn.microsoft.com/en-us/archive/msdn-magazine/2017/may/c-use-modern-c-to-access-the-windows-registry). | ||
|
||
## License | ||
|
||
This project is provided under the MIT License. See the LICENSE file for details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 17 | ||
VisualStudioVersion = 17.9.34526.213 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RegistryHelper", "RegistryHelper\RegistryHelper.vcxproj", "{7144564F-FE5B-4B24-A6A9-C83F18969BBB}" | ||
EndProject | ||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3587BC45-E1D1-4FCE-9F36-D4BD660FB262}" | ||
ProjectSection(SolutionItems) = preProject | ||
.gitignore = .gitignore | ||
LICENSE.md = LICENSE.md | ||
README.md = README.md | ||
EndProjectSection | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|x64 = Debug|x64 | ||
Debug|x86 = Debug|x86 | ||
Release|x64 = Release|x64 | ||
Release|x86 = Release|x86 | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{7144564F-FE5B-4B24-A6A9-C83F18969BBB}.Debug|x64.ActiveCfg = Debug|x64 | ||
{7144564F-FE5B-4B24-A6A9-C83F18969BBB}.Debug|x64.Build.0 = Debug|x64 | ||
{7144564F-FE5B-4B24-A6A9-C83F18969BBB}.Debug|x86.ActiveCfg = Debug|Win32 | ||
{7144564F-FE5B-4B24-A6A9-C83F18969BBB}.Debug|x86.Build.0 = Debug|Win32 | ||
{7144564F-FE5B-4B24-A6A9-C83F18969BBB}.Release|x64.ActiveCfg = Release|x64 | ||
{7144564F-FE5B-4B24-A6A9-C83F18969BBB}.Release|x64.Build.0 = Release|x64 | ||
{7144564F-FE5B-4B24-A6A9-C83F18969BBB}.Release|x86.ActiveCfg = Release|Win32 | ||
{7144564F-FE5B-4B24-A6A9-C83F18969BBB}.Release|x86.Build.0 = Release|Win32 | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
GlobalSection(ExtensibilityGlobals) = postSolution | ||
SolutionGuid = {6B012E4D-3A77-4E50-83D9-5040920D82DE} | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
#include "RegistryHelper.h" | ||
|
||
// Constructor initializes the error code to ERROR_SUCCESS | ||
RegistryHelper::RegistryHelper() | ||
: m_errorCode(ERROR_SUCCESS) | ||
{ | ||
} | ||
|
||
// Read a DWORD value from the registry. This function is marked as noexcept | ||
// to indicate that it does not throw exceptions during its execution. | ||
DWORD | ||
RegistryHelper::RegGetDword(HKEY hKey, | ||
const std::wstring& subKey, | ||
const std::wstring& value) noexcept | ||
{ | ||
DWORD data{}; | ||
DWORD dataSize = sizeof(data); | ||
|
||
// Use specifier to indicate that the function doesn't throw | ||
// exceptions | ||
m_errorCode = ::RegGetValue(hKey, | ||
subKey.c_str(), | ||
value.c_str(), | ||
RRF_RT_REG_DWORD, | ||
nullptr, | ||
&data, | ||
&dataSize); | ||
|
||
if (m_errorCode != ERROR_SUCCESS) { | ||
// Throw a RegistryError exception if an error occurs | ||
throw RegistryError("Cannot read DWORD from registry.", m_errorCode); | ||
} | ||
|
||
return data; | ||
} | ||
|
||
// Read a string value from the registry | ||
std::wstring | ||
RegistryHelper::RegGetString(HKEY hKey, | ||
const std::wstring& subKey, | ||
const std::wstring& value) noexcept | ||
{ | ||
DWORD dataSize{}; | ||
m_errorCode = ::RegGetValue(hKey, | ||
subKey.c_str(), | ||
value.c_str(), | ||
RRF_RT_REG_SZ, | ||
nullptr, | ||
nullptr, | ||
&dataSize); | ||
|
||
if (m_errorCode != ERROR_SUCCESS) { | ||
throw RegistryError("Cannot read string from registry", m_errorCode); | ||
} | ||
|
||
// Use smart pointers for automatic memory management | ||
std::vector<wchar_t> data(dataSize / sizeof(wchar_t)); | ||
|
||
m_errorCode = ::RegGetValue(hKey, | ||
subKey.c_str(), | ||
value.c_str(), | ||
RRF_RT_REG_SZ, | ||
nullptr, | ||
data.data(), | ||
&dataSize); | ||
|
||
if (m_errorCode != ERROR_SUCCESS) { | ||
throw RegistryError("Cannot read string from registry", m_errorCode); | ||
} | ||
|
||
// Resize the vector based on the actual size of the string | ||
data.resize(dataSize / sizeof(wchar_t) - 1); | ||
|
||
return std::wstring(data.begin(), data.end()); | ||
} | ||
|
||
// Read a multi-string value from the registry | ||
std::vector<std::wstring> | ||
RegistryHelper::RegGetMultiString(HKEY hKey, | ||
const std::wstring& subKey, | ||
const std::wstring& value) noexcept | ||
{ | ||
DWORD dataSize{}; | ||
m_errorCode = ::RegGetValue(hKey, | ||
subKey.c_str(), | ||
value.c_str(), | ||
RRF_RT_REG_MULTI_SZ, | ||
nullptr, | ||
nullptr, | ||
&dataSize); | ||
|
||
if (m_errorCode != ERROR_SUCCESS) { | ||
throw RegistryError("Cannot read multi-string from registry", m_errorCode); | ||
} | ||
|
||
// Use smart pointers for automatic memory management | ||
std::vector<wchar_t> data(dataSize / sizeof(wchar_t)); | ||
|
||
m_errorCode = ::RegGetValue(hKey, | ||
subKey.c_str(), | ||
value.c_str(), | ||
RRF_RT_REG_MULTI_SZ, | ||
nullptr, | ||
data.data(), | ||
&dataSize); | ||
|
||
if (m_errorCode != ERROR_SUCCESS) { | ||
throw RegistryError("Cannot read multi-string from registry", m_errorCode); | ||
} | ||
|
||
// Resize the vector based on the actual size of the multi-string | ||
data.resize(dataSize / sizeof(wchar_t)); | ||
|
||
// Parse the double-NUL-terminated string into a vector<wstring> | ||
std::vector<std::wstring> result; | ||
const wchar_t* currStringPtr = data.data(); | ||
while (*currStringPtr != L'\0') { | ||
const size_t currStringLength = wcslen(currStringPtr); | ||
result.push_back(std::wstring{ currStringPtr, currStringLength }); | ||
currStringPtr += currStringLength + 1; | ||
} | ||
|
||
return result; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#pragma once | ||
|
||
#include <Windows.h> | ||
#include <stdexcept> | ||
#include <string> | ||
#include <vector> | ||
|
||
class RegistryError : public std::runtime_error | ||
{ | ||
public: | ||
RegistryError(const char* message, LONG errorCode) | ||
: std::runtime_error{ message } | ||
, m_errorCode{ errorCode } | ||
{ | ||
} | ||
|
||
LONG ErrorCode() const noexcept { return m_errorCode; } | ||
|
||
private: | ||
LONG m_errorCode; | ||
}; | ||
|
||
class RegistryHelper | ||
{ | ||
public: | ||
RegistryHelper(); | ||
|
||
DWORD RegGetDword(HKEY hKey, | ||
const std::wstring& subKey, | ||
const std::wstring& value) noexcept; | ||
std::wstring RegGetString(HKEY hKey, | ||
const std::wstring& subKey, | ||
const std::wstring& value) noexcept; | ||
std::vector<std::wstring> RegGetMultiString( | ||
HKEY hKey, | ||
const std::wstring& subKey, | ||
const std::wstring& value) noexcept; | ||
|
||
private: | ||
LONG m_errorCode; // store the last error code | ||
}; |
Oops, something went wrong.