You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
271 lines
7.4 KiB
271 lines
7.4 KiB
// Copyright (c) 1997-1999 Microsoft Corporation
|
|
//
|
|
// System Registry Class
|
|
//
|
|
// 7-9-98 sburns
|
|
|
|
|
|
|
|
#ifndef REGISTRY_HPP_INCLUDED
|
|
#define REGISTRY_HPP_INCLUDED
|
|
|
|
|
|
|
|
class RegistryKey
|
|
{
|
|
public:
|
|
|
|
RegistryKey();
|
|
~RegistryKey();
|
|
|
|
HRESULT
|
|
Close();
|
|
|
|
HRESULT
|
|
Create(
|
|
HKEY parentKey,
|
|
const String& subkeyName,
|
|
DWORD options = REG_OPTION_NON_VOLATILE,
|
|
REGSAM desiredAccess = KEY_WRITE,
|
|
SECURITY_ATTRIBUTES* securityAttrs = 0,
|
|
DWORD* disposition = 0);
|
|
|
|
HRESULT
|
|
Open(
|
|
HKEY parentKey,
|
|
const String& subkeyName,
|
|
REGSAM desiredAccess = KEY_READ);
|
|
|
|
// Returns Win32ToHresult(ERROR_INVALID_FUNCTION) if the type of the value
|
|
// is not REG_DWORD, REG_DWORD_LITTLE_ENDIAN, or REG_DWORD_BIG_ENDIAN.
|
|
|
|
HRESULT
|
|
GetValue(
|
|
const String& valueName,
|
|
DWORD& value);
|
|
|
|
// Retrieves the contents of the named value, and whether the type of the
|
|
// key is REG_SZ or REG_EXPAND_SZ. Returns
|
|
// Win32ToHresult(ERROR_INVALID_FUNCTION) if the type of the value is not
|
|
// REG_SZ or REG_EXPAND_SZ
|
|
//
|
|
// valueName - name of the value.
|
|
//
|
|
// value - receives the contents of the value, if the read was successful.
|
|
// cleared on failure.
|
|
//
|
|
// isExpandSz - set to true if the value is of type REG_EXPAND_SZ, false
|
|
// if the type is REG_SZ (or an error ocurred).
|
|
|
|
HRESULT
|
|
GetValue(
|
|
const String& valueName,
|
|
String& value,
|
|
bool& isExpandSz);
|
|
|
|
// Calls GetValue(), and throws away the isExpandSz result.
|
|
|
|
HRESULT
|
|
GetValue(
|
|
const String& valueName,
|
|
String& value);
|
|
|
|
// Inserts strings from a REG_MULTI_SZ value into any container from
|
|
// which a std::BackInsertionSequence can be constructed, the elements
|
|
// of which must be constructable from an PWSTR.
|
|
//
|
|
// BackInsertionSequence - any type that supports the construction of
|
|
// a back_insert_iterator on itself, and has a value type that can be
|
|
// constructed from an PWSTR.
|
|
//
|
|
// valueName - name of REG_MULTI_SZ value to retrieve.
|
|
//
|
|
// bii - a reference to a back_insert_iterator of the
|
|
// BackInsertionSequence template parameter. The simplest way to make
|
|
// one of these is to use the back_inserter helper function.
|
|
//
|
|
// Example:
|
|
//
|
|
// StringList container;
|
|
// hr = key.GetValue(L"myValue", back_inserter(container));
|
|
//
|
|
// StringVector container;
|
|
// hr = key.GetValue(L"myValue", back_inserter(container));
|
|
|
|
template <class BackInsertableContainer>
|
|
HRESULT
|
|
GetValue(
|
|
const String& valueName,
|
|
std::back_insert_iterator<BackInsertableContainer>& bii)
|
|
{
|
|
LOG_FUNCTION2(RegistryKey::GetValue-MultiString, valueName);
|
|
ASSERT(!valueName.empty());
|
|
ASSERT(key);
|
|
|
|
DWORD type = 0;
|
|
DWORD size = 0;
|
|
|
|
// REVIEWED-2002/02/22-sburns This QueryValue call is ok.
|
|
|
|
HRESULT hr = Win::RegQueryValueEx(key, valueName, &type, 0, &size);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (type == REG_MULTI_SZ)
|
|
{
|
|
// now that we know the size, read the contents
|
|
// add space for two null characters
|
|
|
|
BYTE* buf = new BYTE[size + (2 * sizeof WCHAR)];
|
|
|
|
// REVIEWED-2002/04/03-sburns correct byte count passed.
|
|
|
|
::ZeroMemory(buf, size + (2 * sizeof WCHAR));
|
|
|
|
type = 0;
|
|
|
|
hr = Win::RegQueryValueEx(key, valueName, &type, buf, &size);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// pull off each of the null-terminated strings
|
|
|
|
// the container values can be any type that can be constructed
|
|
// from PWSTR...
|
|
|
|
wchar_t* newbuf = reinterpret_cast<PWSTR>(buf);
|
|
while (*newbuf)
|
|
{
|
|
// REVIEWED-2002/04/03-sburns this wcslen call is safe
|
|
// because we arranged for the buffer to be null-terminated
|
|
|
|
size_t len = wcslen(newbuf);
|
|
|
|
//lint --e(*) lint does not grok back_insert_iterator
|
|
*bii++ = String(newbuf, len);
|
|
|
|
// move to the next string, + 1 to skip the terminating null
|
|
newbuf += len + 1;
|
|
};
|
|
|
|
delete[] buf;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// caller requested a string from a non-multi-string key
|
|
hr = Win32ToHresult(ERROR_INVALID_FUNCTION);
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Calls GetValue and returns the result, or an empty string on failure.
|
|
|
|
String
|
|
GetString(const String& valueName);
|
|
|
|
// Creates and/or sets a value under the currently open key. Returns
|
|
// S_OK on success.
|
|
//
|
|
// valueName - name of the value. If the value is not already present, it
|
|
// is created with a REG_DWORD type.
|
|
//
|
|
// value - the value to br written.
|
|
|
|
HRESULT
|
|
SetValue(
|
|
const String& valueName,
|
|
DWORD value);
|
|
|
|
// Creates and/or sets a value under the currently open key. Returns
|
|
// S_OK on success.
|
|
//
|
|
// valueName - name of the value. If the value is not already present, it
|
|
// is created.
|
|
//
|
|
// value - the value to br written.
|
|
//
|
|
// expand - if true, the value type is REG_EXPAND_SZ, if false, the value
|
|
// type is REG_SZ.
|
|
|
|
HRESULT
|
|
SetValue(
|
|
const String& valueName,
|
|
const String& value,
|
|
bool expand = false);
|
|
|
|
template<class ForwardIterator>
|
|
HRESULT
|
|
SetValue(
|
|
const String& valueName,
|
|
ForwardIterator first,
|
|
ForwardIterator last)
|
|
{
|
|
LOG_FUNCTION2(RegistryKey::SetValue--MultiString, valueName);
|
|
ASSERT(!valueName.empty());
|
|
|
|
// determine the size of the buffer to write
|
|
|
|
size_t bufSizeInBytes = 0;
|
|
for (
|
|
ForwardIterator f = first, l = last;
|
|
f != l;
|
|
++f)
|
|
{
|
|
// + 1 for null terminator
|
|
|
|
bufSizeInBytes += (f->length() + 1) * sizeof(wchar_t);
|
|
}
|
|
|
|
// + 2 bytes for double-null terminator at very end
|
|
|
|
bufSizeInBytes += 2;
|
|
|
|
BYTE* buf = new BYTE[bufSizeInBytes];
|
|
|
|
// REVIEWED-2002/02/27-sburns correct byte count passed. I know
|
|
// BYTE is size 1, but what if that changed due to some screw up?
|
|
|
|
::ZeroMemory(buf, bufSizeInBytes * sizeof BYTE);
|
|
|
|
// copy the elements of the container into the buffer
|
|
|
|
wchar_t* newbuf = reinterpret_cast<wchar_t*>(buf);
|
|
wchar_t* copyPos = newbuf;
|
|
for (
|
|
f = first, l = last;
|
|
f != l;
|
|
++f)
|
|
{
|
|
copyPos = std::copy(f->begin(), f->end(), copyPos);
|
|
|
|
// skip a character for terminating null
|
|
|
|
copyPos++;
|
|
}
|
|
|
|
// write the buffer to the registry
|
|
// REVIEWED-2002/02/27-sburns correct byte count passed.
|
|
|
|
HRESULT hr =
|
|
Win::RegSetValueEx(
|
|
key,
|
|
valueName,
|
|
REG_MULTI_SZ,
|
|
buf,
|
|
bufSizeInBytes);
|
|
|
|
delete[] buf;
|
|
|
|
return hr;
|
|
}
|
|
|
|
private:
|
|
|
|
HKEY key;
|
|
};
|
|
|
|
|
|
|
|
#endif // REGISTRY_HPP_INCLUDED
|
|
|