Skip to content

Commit

Permalink
Merge pull request #40 from GiovanniDicanio/support-empty-strings-in-…
Browse files Browse the repository at this point in the history
…double-null-terminated-strings

Added support for empty strings inside double-null-terminated strings
  • Loading branch information
GiovanniDicanio authored Mar 24, 2021
2 parents 9b7ad93 + b5cda2d commit 023ad61
Show file tree
Hide file tree
Showing 2 changed files with 227 additions and 144 deletions.
216 changes: 108 additions & 108 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,114 +1,114 @@
# WinReg v4.0.0
## High-level C++ Wrapper Around the Low-level Windows Registry C-interface API

by Giovanni Dicanio

The Windows Registry C-interface API is _very low-level_ and _hard_ to use.

I developed some **C++ wrappers** around this low-level Win32 API, to raise the semantic level, using C++ classes like `std::wstring`, `std::vector`, etc. instead of raw C-style buffers and low-level mechanisms.

For example, the `REG_MULTI_SZ` registry type associated to double-NUL-terminated C-style strings is handled using a much easier higher-level `vector<wstring>`. My C++ code does the _translation_ between high-level C++ STL-based stuff and the low-level Win32 C-interface API.

Moreover, Win32 error codes are translated to C++ exceptions.

The Win32 registry value types are mapped to C++ higher-level types according the following table:

| Win32 Registry Type | C++ Type |
| -------------------- |:----------------------------:|
| `REG_DWORD` | `DWORD` |
| `REG_QWORD` | `ULONGLONG` |
| `REG_SZ` | `std::wstring` |
| `REG_EXPAND_SZ` | `std::wstring` |
| `REG_MULTI_SZ` | `std::vector<std::wstring>` |
| `REG_BINARY` | `std::vector<BYTE>` |


This code is currently developed using **Visual Studio 2019**. I have no longer tested the code with previous compilers. The code compiles cleanly at `/W4` in both 32-bit and 64-bit builds.

This is a **header-only** library, implemented in the **[`WinReg.hpp`](WinReg/WinReg.hpp)** header file.

`WinRegTest.cpp` contains some demo/test code for the library: check it out for some sample usage.

The library exposes three main classes:

* `RegKey`: a tiny efficient wrapper around raw Win32 `HKEY` handles
* `RegException`: an exception class to signal error conditions
* `RegResult`: a tiny wrapper around Windows Registry API `LONG` error codes, returned by some `Try` methods (like `RegKey::TryOpen`)

There are many member functions inside the `RegKey` class, that wrap many parts of the native C-interface Windows Registry API, in a convenient C++ way.

For example, you can simply open a registry key and get registry values with C++ code like this:

```c++
RegKey key{ HKEY_CURRENT_USER, L"SOFTWARE\\SomeKey" };

DWORD dw = key.GetDwordValue (L"SomeDwordValue");
wstring s = key.GetStringValue(L"SomeStringValue");
```
You can also open a registry key using a two-step construction process:
```c++
RegKey key{};
key.Open(HKEY_CURRENT_USER, L"SOFTWARE\\SomeKey");
```

The above code will throw an exception on error. If you prefer to check return codes, you can do that as well:

```c++
RegKey key;
RegResult result = key.TryOpen(HKEY_CURRENT_USER, L"SOFTWARE\\SomeKey");
if (! result)
{
//
# WinReg v4.1.0
## High-level C++ Wrapper Around the Low-level Windows Registry C-interface API

by Giovanni Dicanio

The Windows Registry C-interface API is _very low-level_ and _hard_ to use.

I developed some **C++ wrappers** around this low-level Win32 API, to raise the semantic level, using C++ classes like `std::wstring`, `std::vector`, etc. instead of raw C-style buffers and low-level mechanisms.

For example, the `REG_MULTI_SZ` registry type associated to double-NUL-terminated C-style strings is handled using a much easier higher-level `vector<wstring>`. My C++ code does the _translation_ between high-level C++ STL-based stuff and the low-level Win32 C-interface API.

Moreover, Win32 error codes are translated to C++ exceptions.

The Win32 registry value types are mapped to C++ higher-level types according the following table:

| Win32 Registry Type | C++ Type |
| -------------------- |:----------------------------:|
| `REG_DWORD` | `DWORD` |
| `REG_QWORD` | `ULONGLONG` |
| `REG_SZ` | `std::wstring` |
| `REG_EXPAND_SZ` | `std::wstring` |
| `REG_MULTI_SZ` | `std::vector<std::wstring>` |
| `REG_BINARY` | `std::vector<BYTE>` |


This code is currently developed using **Visual Studio 2019**. I have no longer tested the code with previous compilers. The code compiles cleanly at `/W4` in both 32-bit and 64-bit builds.

This is a **header-only** library, implemented in the **[`WinReg.hpp`](WinReg/WinReg.hpp)** header file.

`WinRegTest.cpp` contains some demo/test code for the library: check it out for some sample usage.

The library exposes three main classes:

* `RegKey`: a tiny efficient wrapper around raw Win32 `HKEY` handles
* `RegException`: an exception class to signal error conditions
* `RegResult`: a tiny wrapper around Windows Registry API `LONG` error codes, returned by some `Try` methods (like `RegKey::TryOpen`)

There are many member functions inside the `RegKey` class, that wrap many parts of the native C-interface Windows Registry API, in a convenient C++ way.

For example, you can simply open a registry key and get registry values with C++ code like this:

```c++
RegKey key{ HKEY_CURRENT_USER, L"SOFTWARE\\SomeKey" };

DWORD dw = key.GetDwordValue (L"SomeDwordValue");
wstring s = key.GetStringValue(L"SomeStringValue");
```
You can also open a registry key using a two-step construction process:
```c++
RegKey key{};
key.Open(HKEY_CURRENT_USER, L"SOFTWARE\\SomeKey");
```

The above code will throw an exception on error. If you prefer to check return codes, you can do that as well:

```c++
RegKey key;
RegResult result = key.TryOpen(HKEY_CURRENT_USER, L"SOFTWARE\\SomeKey");
if (! result)
{
//
// Open failed.
//
// You can invoke the RegResult::Code and RegResult::ErrorMessage methods
// for further details.
//
...
}
```

You can also enumerate all the values under a given key with simple C++ code like this:

```c++
auto values = key.EnumValues();

for (const auto & v : values)
{
//
// Process current value:
//
// - v.first (wstring) is the value name
// - v.second (DWORD) is the value type
//
...
}
```

In addition, you can also use the `RegKey::TryGet...Value` methods, that return `std::optional` instead of throwing on errors:

```c++
// RegKey::TryGetDwordValue() returns a std::optional<DWORD>;
// the returned std::optional contains no value on error.

if (auto dw = key.TryGetDwordValue(L"SomeDwordValue"))
{
// All right: Process the returned value ...
}
else
{
// The method has failed: The returned std::optional contains no value.
}
```


You can take a look at the test code in `WinRegTest.cpp` for some sample usage.

The library stuff lives under the `winreg` namespace.

See the [**`WinReg.hpp`**](WinReg/WinReg.hpp) header for more details and **documentation**.

Thanks to everyone who contributed to this project with some additional features and constructive comments and suggestions.

}
```

You can also enumerate all the values under a given key with simple C++ code like this:

```c++
auto values = key.EnumValues();

for (const auto & v : values)
{
//
// Process current value:
//
// - v.first (wstring) is the value name
// - v.second (DWORD) is the value type
//
...
}
```

In addition, you can also use the `RegKey::TryGet...Value` methods, that return `std::optional` instead of throwing on errors:

```c++
// RegKey::TryGetDwordValue() returns a std::optional<DWORD>;
// the returned std::optional contains no value on error.

if (auto dw = key.TryGetDwordValue(L"SomeDwordValue"))
{
// All right: Process the returned value ...
}
else
{
// The method has failed: The returned std::optional contains no value.
}
```


You can take a look at the test code in `WinRegTest.cpp` for some sample usage.

The library stuff lives under the `winreg` namespace.

See the [**`WinReg.hpp`**](WinReg/WinReg.hpp) header for more details and **documentation**.

Thanks to everyone who contributed to this project with some additional features and constructive comments and suggestions.

Loading

0 comments on commit 023ad61

Please sign in to comment.