Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jlib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
captainwong
jlib
Commits
73faa990
Commit
73faa990
authored
Aug 15, 2018
by
captainwong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update for unicode; re-format
parent
e91a1a4a
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
613 additions
and
633 deletions
+613
-633
Registry.hpp
jlib/3rdparty/win32/Registry.hpp
+613
-633
No files found.
jlib/3rdparty/win32/Registry.hpp
View file @
73faa990
...
...
@@ -60,11 +60,11 @@ class RegKey;
// Wrappers for getting registry values
//
DWORD
RegGetDword
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
);
ULONGLONG
RegGetQword
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
);
std
::
wstring
RegGetString
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
);
std
::
vector
<
std
::
wstring
>
RegGetMultiString
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
);
std
::
vector
<
BYTE
>
RegGetBinary
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
);
DWORD
RegGetDword
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
);
ULONGLONG
RegGetQword
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
);
std
::
wstring
RegGetString
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
);
std
::
vector
<
std
::
wstring
>
RegGetMultiString
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
);
std
::
vector
<
BYTE
>
RegGetBinary
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
);
//
...
...
@@ -85,19 +85,19 @@ std::vector<std::wstring> RegEnumSubKeys(HKEY hKey);
//
RegKey
RegCreateKey
(
HKEY
hKeyParent
,
const
std
::
wstring
&
keyName
,
LPTSTR
keyClass
=
REG_NONE
,
DWORD
options
=
REG_OPTION_NON_VOLATILE
,
REGSAM
access
=
KEY_READ
|
KEY_WRITE
,
SECURITY_ATTRIBUTES
*
securityAttributes
=
nullptr
,
DWORD
*
disposition
=
nullptr
HKEY
hKeyParent
,
const
std
::
wstring
&
keyName
,
LPTSTR
keyClass
=
REG_NONE
,
DWORD
options
=
REG_OPTION_NON_VOLATILE
,
REGSAM
access
=
KEY_READ
|
KEY_WRITE
,
SECURITY_ATTRIBUTES
*
securityAttributes
=
nullptr
,
DWORD
*
disposition
=
nullptr
);
RegKey
RegOpenKey
(
HKEY
hKeyParent
,
const
std
::
wstring
&
keyName
,
REGSAM
access
=
KEY_READ
|
KEY_WRITE
HKEY
hKeyParent
,
const
std
::
wstring
&
keyName
,
REGSAM
access
=
KEY_READ
|
KEY_WRITE
);
...
...
@@ -128,201 +128,198 @@ class RegKey
{
public
:
//
// Initialize as an empty key handle
//
RegKey
()
noexcept
=
default
;
//
// Take ownership of the input raw key handle
//
explicit
RegKey
(
HKEY
hKey
)
noexcept
:
m_hKey
{
hKey
}
{}
//
// Take ownership of the input key handle.
// The input key handle wrapper is reset to an empty state
//
RegKey
(
RegKey
&&
other
)
noexcept
:
m_hKey
{
other
.
m_hKey
}
{
//
// Other doesn't own the raw handle anymore
//
other
.
m_hKey
=
nullptr
;
}
//
// Move-assign from the input key handle.
// Properly check against self-move-assign (which is safe and does nothing).
//
RegKey
&
operator
=
(
RegKey
&&
other
)
noexcept
{
//
// Prevent self-move-assign
//
if
((
this
!=
&
other
)
&&
(
m_hKey
!=
other
.
m_hKey
))
{
Close
();
//
// Move from other
//
m_hKey
=
other
.
m_hKey
;
other
.
m_hKey
=
nullptr
;
}
return
*
this
;
}
//
// Ban copy
//
RegKey
(
const
RegKey
&
)
=
delete
;
RegKey
&
operator
=
(
const
RegKey
&
)
=
delete
;
//
// Safely close the wrapped key handle (if any)
//
~
RegKey
()
noexcept
{
Close
();
}
//
// Give read-only access to the wrapped HKEY handle
//
HKEY
Get
()
const
noexcept
{
return
m_hKey
;
}
//
// Close current HKEY handle.
// If key wasn't open, does nothing.
//
void
Close
()
noexcept
{
if
(
IsValid
())
{
::
RegCloseKey
(
m_hKey
);
m_hKey
=
nullptr
;
}
}
//
// Is the wrapped HKEY handle valid?
//
bool
IsValid
()
const
noexcept
{
return
m_hKey
!=
nullptr
;
}
//
// Has the same semantic of IsValid, but allows a short "if (regKey)" syntax
//
explicit
operator
bool
()
const
noexcept
{
return
IsValid
();
}
//
// Transfer ownership of current HKEY to the caller.
// Note that the caller is responsible for closing the key raw handle!
//
HKEY
Detach
()
noexcept
{
HKEY
hKey
=
m_hKey
;
//
// We don't own the HKEY handle anymore
//
m_hKey
=
nullptr
;
//
// Transfer ownership of the raw handle to the caller
//
return
hKey
;
}
//
// Take ownership of the HKEY handle.
// Safely close any previously open handle.
// Input key handle can be nullptr; in this case this wrapper wraps an empty handle.
//
void
Attach
(
HKEY
hKey
)
noexcept
{
//
// Prevent self-attach
//
if
(
m_hKey
!=
hKey
)
{
Close
();
//
// Take ownership of hKey
//
m_hKey
=
hKey
;
}
}
//
// Non-throwing swap
//
friend
void
swap
(
RegKey
&
a
,
RegKey
&
b
)
noexcept
{
//
// Enable ADL (not necessary in this case, but good practice)
//
using
std
::
swap
;
//
// Swap the raw handle members
//
swap
(
a
.
m_hKey
,
b
.
m_hKey
);
}
//
// Overload comparison and relational operators
//
friend
bool
operator
==
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
==
b
.
m_hKey
;
}
friend
bool
operator
!=
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
!=
b
.
m_hKey
;
}
friend
bool
operator
<
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
<
b
.
m_hKey
;
}
friend
bool
operator
<=
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
<=
b
.
m_hKey
;
}
friend
bool
operator
>
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
>
b
.
m_hKey
;
}
friend
bool
operator
>=
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
>=
b
.
m_hKey
;
}
//
// Initialize as an empty key handle
//
RegKey
()
noexcept
=
default
;
//
// Take ownership of the input raw key handle
//
explicit
RegKey
(
HKEY
hKey
)
noexcept
:
m_hKey
{
hKey
}
{}
//
// Take ownership of the input key handle.
// The input key handle wrapper is reset to an empty state
//
RegKey
(
RegKey
&&
other
)
noexcept
:
m_hKey
{
other
.
m_hKey
}
{
//
// Other doesn't own the raw handle anymore
//
other
.
m_hKey
=
nullptr
;
}
//
// Move-assign from the input key handle.
// Properly check against self-move-assign (which is safe and does nothing).
//
RegKey
&
operator
=
(
RegKey
&&
other
)
noexcept
{
//
// Prevent self-move-assign
//
if
((
this
!=
&
other
)
&&
(
m_hKey
!=
other
.
m_hKey
))
{
Close
();
//
// Move from other
//
m_hKey
=
other
.
m_hKey
;
other
.
m_hKey
=
nullptr
;
}
return
*
this
;
}
//
// Ban copy
//
RegKey
(
const
RegKey
&
)
=
delete
;
RegKey
&
operator
=
(
const
RegKey
&
)
=
delete
;
//
// Safely close the wrapped key handle (if any)
//
~
RegKey
()
noexcept
{
Close
();
}
//
// Give read-only access to the wrapped HKEY handle
//
HKEY
Get
()
const
noexcept
{
return
m_hKey
;
}
//
// Close current HKEY handle.
// If key wasn't open, does nothing.
//
void
Close
()
noexcept
{
if
(
IsValid
())
{
::
RegCloseKey
(
m_hKey
);
m_hKey
=
nullptr
;
}
}
//
// Is the wrapped HKEY handle valid?
//
bool
IsValid
()
const
noexcept
{
return
m_hKey
!=
nullptr
;
}
//
// Has the same semantic of IsValid, but allows a short "if (regKey)" syntax
//
explicit
operator
bool
()
const
noexcept
{
return
IsValid
();
}
//
// Transfer ownership of current HKEY to the caller.
// Note that the caller is responsible for closing the key raw handle!
//
HKEY
Detach
()
noexcept
{
HKEY
hKey
=
m_hKey
;
//
// We don't own the HKEY handle anymore
//
m_hKey
=
nullptr
;
//
// Transfer ownership of the raw handle to the caller
//
return
hKey
;
}
//
// Take ownership of the HKEY handle.
// Safely close any previously open handle.
// Input key handle can be nullptr; in this case this wrapper wraps an empty handle.
//
void
Attach
(
HKEY
hKey
)
noexcept
{
//
// Prevent self-attach
//
if
(
m_hKey
!=
hKey
)
{
Close
();
//
// Take ownership of hKey
//
m_hKey
=
hKey
;
}
}
//
// Non-throwing swap
//
friend
void
swap
(
RegKey
&
a
,
RegKey
&
b
)
noexcept
{
//
// Enable ADL (not necessary in this case, but good practice)
//
using
std
::
swap
;
//
// Swap the raw handle members
//
swap
(
a
.
m_hKey
,
b
.
m_hKey
);
}
//
// Overload comparison and relational operators
//
friend
bool
operator
==
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
==
b
.
m_hKey
;
}
friend
bool
operator
!=
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
!=
b
.
m_hKey
;
}
friend
bool
operator
<
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
<
b
.
m_hKey
;
}
friend
bool
operator
<=
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
<=
b
.
m_hKey
;
}
friend
bool
operator
>
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
>
b
.
m_hKey
;
}
friend
bool
operator
>=
(
const
RegKey
&
a
,
const
RegKey
&
b
)
noexcept
{
return
a
.
m_hKey
>=
b
.
m_hKey
;
}
private
:
//
// The wrapped registry key handle
//
HKEY
m_hKey
=
nullptr
;
//
// The wrapped registry key handle
//
HKEY
m_hKey
=
nullptr
;
};
...
...
@@ -332,18 +329,18 @@ private:
class
RegistryError
:
public
std
::
runtime_error
{
public
:
RegistryError
(
const
char
*
message
,
LONG
errorCode
)
:
std
::
runtime_error
{
message
}
,
m_errorCode
{
errorCode
}
{}
RegistryError
(
const
char
*
message
,
LONG
errorCode
)
:
std
::
runtime_error
{
message
}
,
m_errorCode
{
errorCode
}
{}
LONG
ErrorCode
()
const
noexcept
{
return
m_errorCode
;
}
LONG
ErrorCode
()
const
noexcept
{
return
m_errorCode
;
}
private
:
LONG
m_errorCode
;
LONG
m_errorCode
;
};
...
...
@@ -353,464 +350,447 @@ private:
inline
DWORD
RegGetDword
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
)
{
//
// Read a 32-bit DWORD value from the registry
//
DWORD
data
{};
DWORD
dataSize
=
sizeof
(
data
);
LONG
retCode
=
::
RegGetValue
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_DWORD
,
nullptr
,
&
data
,
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read DWORD from registry."
,
retCode
};
}
return
data
;
//
// Read a 32-bit DWORD value from the registry
//
DWORD
data
{};
DWORD
dataSize
=
sizeof
(
data
);
LONG
retCode
=
::
RegGetValueW
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_DWORD
,
nullptr
,
&
data
,
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read DWORD from registry."
,
retCode
};
}
return
data
;
}
inline
ULONGLONG
RegGetQword
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
)
{
//
// Read a 64-bit QWORD value from the registry
//
ULONGLONG
data
{};
DWORD
dataSize
=
sizeof
(
data
);
LONG
retCode
=
::
RegGetValue
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_QWORD
,
nullptr
,
&
data
,
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read QWORD from registry."
,
retCode
};
}
return
data
;
//
// Read a 64-bit QWORD value from the registry
//
ULONGLONG
data
{};
DWORD
dataSize
=
sizeof
(
data
);
LONG
retCode
=
::
RegGetValueW
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_QWORD
,
nullptr
,
&
data
,
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read QWORD from registry."
,
retCode
};
}
return
data
;
}
inline
std
::
wstring
RegGetString
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
)
{
//
// Request the size of the string, in bytes
//
DWORD
dataSize
{};
LONG
retCode
=
::
RegGetValue
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_SZ
,
nullptr
,
nullptr
,
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read string from registry"
,
retCode
};
}
//
// Allocate room for the result string.
//
// Note that dataSize is in bytes, but wstring::resize() expects length in wchar_ts,
// so must convert from bytes to wchar_t count first.
//
std
::
wstring
data
;
data
.
resize
(
dataSize
/
sizeof
(
wchar_t
));
//
// Read the string from the registry into local wstring object
//
retCode
=
::
RegGetValue
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_SZ
,
nullptr
,
&
data
[
0
],
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read string from registry"
,
retCode
};
}
//
// On return, RegGetValue() writes in dataSize the actual size of the string, in bytes.
// We must resize the wstring object to the proper string size.
// Note that dataSize is expressed in bytes, and includes the terminating NUL; so we have to
// subtract the NUL from the total string length, as wstring objects are already NUL-terminated.
//
DWORD
stringLengthInWchars
=
dataSize
/
sizeof
(
wchar_t
);
stringLengthInWchars
--
;
// exclude the NUL written by the Win32 API
data
.
resize
(
stringLengthInWchars
);
return
data
;
{
//
// Request the size of the string, in bytes
//
DWORD
dataSize
{};
LONG
retCode
=
::
RegGetValueW
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_SZ
,
nullptr
,
nullptr
,
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read string from registry"
,
retCode
};
}
//
// Allocate room for the result string.
//
// Note that dataSize is in bytes, but wstring::resize() expects length in wchar_ts,
// so must convert from bytes to wchar_t count first.
//
std
::
wstring
data
;
data
.
resize
(
dataSize
/
sizeof
(
wchar_t
));
//
// Read the string from the registry into local wstring object
//
retCode
=
::
RegGetValueW
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_SZ
,
nullptr
,
&
data
[
0
],
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read string from registry"
,
retCode
};
}
//
// On return, RegGetValue() writes in dataSize the actual size of the string, in bytes.
// We must resize the wstring object to the proper string size.
// Note that dataSize is expressed in bytes, and includes the terminating NUL; so we have to
// subtract the NUL from the total string length, as wstring objects are already NUL-terminated.
//
DWORD
stringLengthInWchars
=
dataSize
/
sizeof
(
wchar_t
);
stringLengthInWchars
--
;
// exclude the NUL written by the Win32 API
data
.
resize
(
stringLengthInWchars
);
return
data
;
}
inline
std
::
vector
<
std
::
wstring
>
inline
std
::
vector
<
std
::
wstring
>
RegGetMultiString
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
)
{
//
// Request the size of the multi-string, in bytes
//
DWORD
dataSize
{};
LONG
retCode
=
::
RegGetValue
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_MULTI_SZ
,
nullptr
,
nullptr
,
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read multi-string from registry"
,
retCode
};
}
//
// Allocate room for the result multi-string.
//
// Note that dataSize is in bytes, but our vector<wchar_t> object has size expressed in wchar_ts.
//
std
::
vector
<
wchar_t
>
data
;
data
.
resize
(
dataSize
/
sizeof
(
wchar_t
));
//
// Read the multi-string from the registry into the vector object
//
retCode
=
::
RegGetValue
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_MULTI_SZ
,
nullptr
,
&
data
[
0
],
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read multi-string from registry"
,
retCode
};
}
//
// Resize vector to the actual size returned by GetRegValue().
// Note that the vector is a vector of wchar_ts, instead the size returned by GetRegValue()
// is in bytes, so we have to scale from bytes to wchar_t count.
//
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
[
0
];
while
(
*
currStringPtr
!=
L'\0'
)
{
// Current string is NUL-terminated, so get its length with wcslen()
const
size_t
currStringLength
=
wcslen
(
currStringPtr
);
// Add current string to result vector
result
.
push_back
(
std
::
wstring
{
currStringPtr
,
currStringLength
});
// Move to the next string
currStringPtr
+=
currStringLength
+
1
;
}
return
result
;
//
// Request the size of the multi-string, in bytes
//
DWORD
dataSize
{};
LONG
retCode
=
::
RegGetValueW
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_MULTI_SZ
,
nullptr
,
nullptr
,
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read multi-string from registry"
,
retCode
};
}
//
// Allocate room for the result multi-string.
//
// Note that dataSize is in bytes, but our vector<wchar_t> object has size expressed in wchar_ts.
//
std
::
vector
<
wchar_t
>
data
;
data
.
resize
(
dataSize
/
sizeof
(
wchar_t
));
//
// Read the multi-string from the registry into the vector object
//
retCode
=
::
RegGetValueW
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_MULTI_SZ
,
nullptr
,
&
data
[
0
],
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read multi-string from registry"
,
retCode
};
}
//
// Resize vector to the actual size returned by GetRegValue().
// Note that the vector is a vector of wchar_ts, instead the size returned by GetRegValue()
// is in bytes, so we have to scale from bytes to wchar_t count.
//
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
[
0
];
while
(
*
currStringPtr
!=
L'\0'
)
{
// Current string is NUL-terminated, so get its length with wcslen()
const
size_t
currStringLength
=
wcslen
(
currStringPtr
);
// Add current string to result vector
result
.
push_back
(
std
::
wstring
{
currStringPtr
,
currStringLength
});
// Move to the next string
currStringPtr
+=
currStringLength
+
1
;
}
return
result
;
}
inline
std
::
vector
<
BYTE
>
RegGetBinary
(
HKEY
hKey
,
const
std
::
wstring
&
subKey
,
const
std
::
wstring
&
value
)
{
//
// Request the size of the binary data, in bytes
//
DWORD
dataSize
{};
LONG
retCode
=
::
RegGetValue
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_BINARY
,
nullptr
,
nullptr
,
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read binary data from registry"
,
retCode
};
}
//
// Allocate room for the result binary data
//
std
::
vector
<
BYTE
>
data
;
data
.
resize
(
dataSize
);
//
// Read the binary data from the registry into the vector object
//
retCode
=
::
RegGetValue
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_BINARY
,
nullptr
,
&
data
[
0
],
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read binary data from registry"
,
retCode
};
}
//
// Resize vector to the actual size returned by GetRegValue().
//
data
.
resize
(
dataSize
);
return
data
;
//
// Request the size of the binary data, in bytes
//
DWORD
dataSize
{};
LONG
retCode
=
::
RegGetValueW
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_BINARY
,
nullptr
,
nullptr
,
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read binary data from registry"
,
retCode
};
}
//
// Allocate room for the result binary data
//
std
::
vector
<
BYTE
>
data
;
data
.
resize
(
dataSize
);
//
// Read the binary data from the registry into the vector object
//
retCode
=
::
RegGetValueW
(
hKey
,
subKey
.
c_str
(),
value
.
c_str
(),
RRF_RT_REG_BINARY
,
nullptr
,
&
data
[
0
],
&
dataSize
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot read binary data from registry"
,
retCode
};
}
//
// Resize vector to the actual size returned by GetRegValue().
//
data
.
resize
(
dataSize
);
return
data
;
}
inline
std
::
vector
<
std
::
pair
<
std
::
wstring
,
DWORD
>>
RegEnumValues
(
HKEY
hKey
)
{
//
// Get useful pre-enumeration info, like the total number of values
// and the maximum length of the value names
//
DWORD
valueCount
{};
DWORD
maxValueNameLen
{};
LONG
retCode
=
::
RegQueryInfoKey
(
hKey
,
nullptr
,
// no user-defined class
nullptr
,
// no user-defined class size
nullptr
,
// reserved
nullptr
,
// no subkey count
nullptr
,
// no subkey max length
nullptr
,
// no subkey class length
&
valueCount
,
&
maxValueNameLen
,
nullptr
,
// no max value length
nullptr
,
// no security descriptor
nullptr
// no last write time
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"RegQueryInfoKey failed while preparing for value enumeration."
,
retCode
};
}
//
// NOTE: According to the MSDN documentation, the size returned for value name max length
// does *not* include the terminating NUL, so let's add +1 to take it into account
// when I allocate the buffer for reading value names.
//
maxValueNameLen
++
;
//
// Preallocate a buffer for the value names
//
auto
nameBuffer
=
std
::
make_unique
<
wchar_t
[]
>
(
maxValueNameLen
);
//
// The value names and types will be stored here
//
std
::
vector
<
std
::
pair
<
std
::
wstring
,
DWORD
>>
valueInfo
;
//
// Enumerate all the values
//
for
(
DWORD
index
=
0
;
index
<
valueCount
;
index
++
)
{
//
// Get the name and the type of the current value
//
DWORD
valueNameLen
=
maxValueNameLen
;
DWORD
valueType
{};
retCode
=
::
RegEnumValue
(
hKey
,
index
,
nameBuffer
.
get
(),
&
valueNameLen
,
nullptr
,
// reserved
&
valueType
,
nullptr
,
// no data
nullptr
// no data size
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot enumerate values: RegEnumValue failed."
,
retCode
};
}
//
// On success, the RegEnumValue API writes the length of the
// value name in the valueNameLen output parameter
// (not including the terminating NUL).
// So we can build a wstring based on that length.
//
// The value info pair is made by the value's name and the value's type.
//
valueInfo
.
push_back
(
std
::
make_pair
(
std
::
wstring
{
nameBuffer
.
get
(),
valueNameLen
},
valueType
));
}
return
valueInfo
;
//
// Get useful pre-enumeration info, like the total number of values
// and the maximum length of the value names
//
DWORD
valueCount
{};
DWORD
maxValueNameLen
{};
LONG
retCode
=
::
RegQueryInfoKey
(
hKey
,
nullptr
,
// no user-defined class
nullptr
,
// no user-defined class size
nullptr
,
// reserved
nullptr
,
// no subkey count
nullptr
,
// no subkey max length
nullptr
,
// no subkey class length
&
valueCount
,
&
maxValueNameLen
,
nullptr
,
// no max value length
nullptr
,
// no security descriptor
nullptr
// no last write time
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"RegQueryInfoKey failed while preparing for value enumeration."
,
retCode
};
}
//
// NOTE: According to the MSDN documentation, the size returned for value name max length
// does *not* include the terminating NUL, so let's add +1 to take it into account
// when I allocate the buffer for reading value names.
//
maxValueNameLen
++
;
//
// Preallocate a buffer for the value names
//
auto
nameBuffer
=
std
::
make_unique
<
wchar_t
[]
>
(
maxValueNameLen
);
//
// The value names and types will be stored here
//
std
::
vector
<
std
::
pair
<
std
::
wstring
,
DWORD
>>
valueInfo
;
//
// Enumerate all the values
//
for
(
DWORD
index
=
0
;
index
<
valueCount
;
index
++
)
{
//
// Get the name and the type of the current value
//
DWORD
valueNameLen
=
maxValueNameLen
;
DWORD
valueType
{};
retCode
=
::
RegEnumValueW
(
hKey
,
index
,
nameBuffer
.
get
(),
&
valueNameLen
,
nullptr
,
// reserved
&
valueType
,
nullptr
,
// no data
nullptr
// no data size
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot enumerate values: RegEnumValue failed."
,
retCode
};
}
//
// On success, the RegEnumValue API writes the length of the
// value name in the valueNameLen output parameter
// (not including the terminating NUL).
// So we can build a wstring based on that length.
//
// The value info pair is made by the value's name and the value's type.
//
valueInfo
.
push_back
(
std
::
make_pair
(
std
::
wstring
{
nameBuffer
.
get
(),
valueNameLen
},
valueType
));
}
return
valueInfo
;
}
inline
std
::
vector
<
std
::
wstring
>
RegEnumSubKeys
(
HKEY
hKey
)
{
//
// Get some useful pre-enumeration info, like the total number of subkeys
// and the maximum length of the subkey names
//
DWORD
subKeyCount
{};
DWORD
maxSubKeyNameLen
{};
LONG
retCode
=
::
RegQueryInfoKey
(
hKey
,
nullptr
,
// no user-defined class
nullptr
,
// no user-defined class size
nullptr
,
// reserved
&
subKeyCount
,
&
maxSubKeyNameLen
,
nullptr
,
// no subkey class length
nullptr
,
// no value count
nullptr
,
// no value name max length
nullptr
,
// no max value length
nullptr
,
// no security descriptor
nullptr
// no last write time
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"RegQueryInfoKey failed while preparing for subkey enumeration."
,
retCode
};
}
//
// NOTE: According to the MSDN documentation, the size returned for subkey name max length
// does *not* include the terminating NUL, so let's add +1 to take it into account
// when I allocate the buffer for reading subkey names.
//
maxSubKeyNameLen
++
;
//
// Preallocate a buffer for the subkey names
//
auto
nameBuffer
=
std
::
make_unique
<
wchar_t
[]
>
(
maxSubKeyNameLen
);
//
// The subkey names will be stored here
//
std
::
vector
<
std
::
wstring
>
subkeyNames
;
//
// Enumerate all the subkeys
//
for
(
DWORD
index
=
0
;
index
<
subKeyCount
;
index
++
)
{
//
// Get the name of the current subkey
//
DWORD
subKeyNameLen
=
maxSubKeyNameLen
;
retCode
=
::
RegEnumKeyEx
(
hKey
,
index
,
nameBuffer
.
get
(),
&
subKeyNameLen
,
nullptr
,
// reserved
nullptr
,
// no class
nullptr
,
// no class
nullptr
// no last write time
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot enumerate subkeys: RegEnumKeyEx failed."
,
retCode
};
}
//
// On success, the ::RegEnumKeyEx API writes the length of the
// subkey name in the subKeyNameLen output parameter
// (not including the terminating NUL).
// So I can build a wstring based on that length.
//
subkeyNames
.
push_back
(
std
::
wstring
{
nameBuffer
.
get
(),
subKeyNameLen
});
}
return
subkeyNames
;
//
// Get some useful pre-enumeration info, like the total number of subkeys
// and the maximum length of the subkey names
//
DWORD
subKeyCount
{};
DWORD
maxSubKeyNameLen
{};
LONG
retCode
=
::
RegQueryInfoKey
(
hKey
,
nullptr
,
// no user-defined class
nullptr
,
// no user-defined class size
nullptr
,
// reserved
&
subKeyCount
,
&
maxSubKeyNameLen
,
nullptr
,
// no subkey class length
nullptr
,
// no value count
nullptr
,
// no value name max length
nullptr
,
// no max value length
nullptr
,
// no security descriptor
nullptr
// no last write time
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"RegQueryInfoKey failed while preparing for subkey enumeration."
,
retCode
};
}
//
// NOTE: According to the MSDN documentation, the size returned for subkey name max length
// does *not* include the terminating NUL, so let's add +1 to take it into account
// when I allocate the buffer for reading subkey names.
//
maxSubKeyNameLen
++
;
//
// Preallocate a buffer for the subkey names
//
auto
nameBuffer
=
std
::
make_unique
<
wchar_t
[]
>
(
maxSubKeyNameLen
);
//
// The subkey names will be stored here
//
std
::
vector
<
std
::
wstring
>
subkeyNames
;
//
// Enumerate all the subkeys
//
for
(
DWORD
index
=
0
;
index
<
subKeyCount
;
index
++
)
{
//
// Get the name of the current subkey
//
DWORD
subKeyNameLen
=
maxSubKeyNameLen
;
retCode
=
::
RegEnumKeyExW
(
hKey
,
index
,
nameBuffer
.
get
(),
&
subKeyNameLen
,
nullptr
,
// reserved
nullptr
,
// no class
nullptr
,
// no class
nullptr
// no last write time
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot enumerate subkeys: RegEnumKeyEx failed."
,
retCode
};
}
//
// On success, the ::RegEnumKeyEx API writes the length of the
// subkey name in the subKeyNameLen output parameter
// (not including the terminating NUL).
// So I can build a wstring based on that length.
//
subkeyNames
.
push_back
(
std
::
wstring
{
nameBuffer
.
get
(),
subKeyNameLen
});
}
return
subkeyNames
;
}
inline
RegKey
RegCreateKey
(
HKEY
hKeyParent
,
const
std
::
wstring
&
keyName
,
LPT
STR
keyClass
,
DWORD
options
,
REGSAM
access
,
SECURITY_ATTRIBUTES
*
securityAttributes
,
DWORD
*
disposition
HKEY
hKeyParent
,
const
std
::
wstring
&
keyName
,
LPW
STR
keyClass
,
DWORD
options
,
REGSAM
access
,
SECURITY_ATTRIBUTES
*
securityAttributes
,
DWORD
*
disposition
)
{
//
// Create the key invoking the native RegCreateKeyEx Win32 API
//
HKEY
hKey
=
nullptr
;
LONG
retCode
=
::
RegCreateKeyEx
(
hKeyParent
,
keyName
.
c_str
(),
0
,
// reserved
keyClass
,
options
,
access
,
securityAttributes
,
&
hKey
,
disposition
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot create registry key: RegCreateKeyEx failed."
,
retCode
};
}
//
// Return the raw key handle safely wrapped in the C++ key resource manager
//
return
RegKey
{
hKey
};
//
// Create the key invoking the native RegCreateKeyEx Win32 API
//
HKEY
hKey
=
nullptr
;
LONG
retCode
=
::
RegCreateKeyExW
(
hKeyParent
,
keyName
.
c_str
(),
0
,
// reserved
keyClass
,
options
,
access
,
securityAttributes
,
&
hKey
,
disposition
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot create registry key: RegCreateKeyEx failed."
,
retCode
};
}
//
// Return the raw key handle safely wrapped in the C++ key resource manager
//
return
RegKey
{
hKey
};
}
inline
RegKey
RegOpenKey
(
HKEY
hKeyParent
,
const
std
::
wstring
&
keyName
,
REGSAM
access
HKEY
hKeyParent
,
const
std
::
wstring
&
keyName
,
REGSAM
access
)
{
//
// Open the key invoking the native RegOpenKeyEx Win32 API
//
HKEY
hKey
=
nullptr
;
LONG
retCode
=
::
RegOpenKeyEx
(
hKeyParent
,
keyName
.
c_str
(),
0
,
// default options
access
,
&
hKey
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot open registry key: RegOpenKeyEx failed."
,
retCode
};
}
//
// Return the raw key handle safely wrapped in the C++ key resource manager
//
return
RegKey
{
hKey
};
//
// Open the key invoking the native RegOpenKeyEx Win32 API
//
HKEY
hKey
=
nullptr
;
LONG
retCode
=
::
RegOpenKeyExW
(
hKeyParent
,
keyName
.
c_str
(),
0
,
// default options
access
,
&
hKey
);
if
(
retCode
!=
ERROR_SUCCESS
)
{
throw
RegistryError
{
"Cannot open registry key: RegOpenKeyEx failed."
,
retCode
};
}
//
// Return the raw key handle safely wrapped in the C++ key resource manager
//
return
RegKey
{
hKey
};
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment