Skip to content
This repository has been archived by the owner on Dec 2, 2024. It is now read-only.

Commit

Permalink
Update README, add new solution and source files
Browse files Browse the repository at this point in the history
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
Arteiii committed Feb 4, 2024
1 parent 22efd03 commit 701e97e
Show file tree
Hide file tree
Showing 7 changed files with 489 additions and 1 deletion.
74 changes: 73 additions & 1 deletion README.md
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.
38 changes: 38 additions & 0 deletions RegistryHelper.sln
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
124 changes: 124 additions & 0 deletions RegistryHelper/RegistryHelper.cpp
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;
}
41 changes: 41 additions & 0 deletions RegistryHelper/RegistryHelper.h
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
};
Loading

0 comments on commit 701e97e

Please sign in to comment.