windows-nt/Source/XPSP1/NT/net/upnp/common/upbase/ncregq.cpp
2020-09-26 16:20:57 +08:00

588 lines
17 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: N C R E G Q . C P P
//
// Contents: HrRegQuery functions.
//
// Notes:
//
// Author: shaunco 5 Jun 1998
//
//----------------------------------------------------------------------------
#include <pch.h>
#pragma hdrstop
#include "ncdebug.h"
#include "ncreg.h"
//+---------------------------------------------------------------------------
//
// Function: HrRegQueryDword
//
// Purpose: Gets a DWORD from the registry. Checks that its type and
// size are correct. Easier to understand than HrRegQueryValueEx
// with 5 parameters. Type safe (no LPBYTE stuff).
//
// Arguments:
// hkey [in] The registry key.
// pszValueName [in] The name of the value to get.
// pdwValue [out] The returned DWORD value if successful. Zero
// if not.
//
// Returns: S_OK or HRESULT_FROM_WIN32.
//
// Author: shaunco 27 Mar 1997
//
// Side Effects: On error, the output DWORD is set to zero to line-up
// with the rules of COM in this regard.
//
HRESULT
HrRegQueryDword (
HKEY hkey,
PCTSTR pszValueName,
LPDWORD pdwValue)
{
Assert (hkey);
Assert (pszValueName);
Assert (pdwValue);
// Get the value.
DWORD dwType;
DWORD cbData = sizeof(DWORD);
HRESULT hr = HrRegQueryValueEx (hkey, pszValueName, &dwType,
(LPBYTE)pdwValue, &cbData);
// It's type should be REG_DWORD. (duh).
//
if ((S_OK == hr) && (REG_DWORD != dwType))
{
TraceTag (ttidError, "Expected a type of REG_DWORD for %S.",
pszValueName);
hr = HRESULT_FROM_WIN32 (ERROR_INVALID_DATATYPE);
}
// It's size should be correct too.
//
AssertSz (FImplies(S_OK == hr, sizeof(DWORD) == cbData),
"Expected sizeof(DWORD) bytes to be returned.");
// Make sure we initialize the output value on error.
// (We don't know for sure that RegQueryValueEx does this.)
//
if (S_OK != hr)
{
*pdwValue = 0;
}
TraceHr (ttidError, FAL, hr,
(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr),
"HrRegQueryDword");
return hr;
}
#if 0
//+---------------------------------------------------------------------------
//
// Function: HrRegQueryExpandString
//
// Purpose: Query a REG_EXPAND_SZ value from the registry and
// expand it using ExpandEnvironmentStrings. Return the
// result in a tstring.
//
// Arguments:
// hkey [in] The parent HKEY of szValueName
// pszValueName [in] The name of the value to query.
// pstrValue [out] The returned (expanded) value.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 6 Jun 1998
//
// Notes:
//
HRESULT
HrRegQueryExpandString (
HKEY hkey,
PCTSTR pszValueName,
tstring* pstrValue)
{
Assert (hkey);
Assert (pszValueName);
Assert (pstrValue);
tstring strToExpand;
HRESULT hr = HrRegQueryTypeString (hkey, pszValueName,
REG_EXPAND_SZ, &strToExpand);
if (S_OK == hr)
{
ExpandEnvironmentStringsIntoTstring (strToExpand.c_str(), pstrValue);
}
TraceHr (ttidError, FAL, hr,
(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) ||
(HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE) == hr),
"HrRegQueryExpandString");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRegQueryInfoKey
//
// Purpose: Retrieves information about a registry key by calling
// RegQueryInfoKey.
//
// Arguments:
// hkey [in]
// pszClass [out]
// pcbClass [inout]
// pcSubKeys [out]
// pcbMaxSubKeyLen [out] See the Win32 documentation for the
// pcbMaxClassLen [out] RegQueryInfoKey function.
// pcValues [out]
// pcbMaxValueNameLen [out]
// pcbMaxValueLen [out]
// pcbSecurityDescriptor [out]
// pftLastWriteTime [out]
//
// Returns: S_OK or an HRESULT_FROM_WIN32 error code.
//
// Author: BillBe 28 Aug 1998
//
// Notes: Note that pcbClass is an *in/out* param. Set this to the size
// of the buffer pointed to by pszClass *before* calling this
// function!
//
HRESULT
HrRegQueryInfoKey (
IN HKEY hkey,
OUT PWSTR pszClass,
IN OUT LPDWORD pcbClass,
OUT LPDWORD pcSubKeys,
OUT LPDWORD pcbMaxSubKeyLen,
OUT LPDWORD pcbMaxClassLen,
OUT LPDWORD pcValues,
OUT LPDWORD pcbMaxValueNameLen,
OUT LPDWORD pcbMaxValueLen,
OUT LPDWORD pcbSecurityDescriptor,
OUT PFILETIME pftLastWriteTime)
{
Assert(hkey);
LONG lr = RegQueryInfoKeyW(hkey, pszClass, pcbClass, NULL,pcSubKeys,
pcbMaxSubKeyLen, pcbMaxClassLen, pcValues, pcbMaxValueNameLen,
pcbMaxValueLen, pcbSecurityDescriptor, pftLastWriteTime);
HRESULT hr = HRESULT_FROM_WIN32 (lr);
TraceHr (ttidError, FAL, hr, FALSE, "HrRegQueryInfoKey");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRegQueryStringAsUlong
//
// Purpose: Reads a REG_SZ from the registry and converts it to a ulong
// before returning
//
// Arguments:
// hkey [in] The registry key.
// pszValueName [in] The name of the value to get.
// nBase [in] The numeric base to convert to
// pulValue [out] The returned converted string if successful.
//
// Returns: S_OK or an HRESULT_FROM_WIN32 error code.
//
// Author: billbe 13 Jun 1997
//
// Notes:
//
//
HRESULT
HrRegQueryStringAsUlong (
IN HKEY hkey,
IN PCTSTR pszValueName,
IN int nBase,
OUT ULONG* pulValue)
{
Assert (hkey);
Assert (pszValueName);
Assert (nBase);
Assert (pulValue);
// Get the value.
//
tstring strValue;
HRESULT hr = HrRegQueryString (hkey, pszValueName, &strValue);
if (S_OK == hr)
{
// Convert and assign the output parameters.
PWSTR pszStopString;
*pulValue = wcstoul (strValue.c_str(), &pszStopString, nBase);
}
else
{
*pulValue = 0;
}
TraceHr (ttidError, FAL, hr,
(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr),
"HrRegQueryStringAsUlong");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRegQueryTypeString
//
// Purpose: Query a REG_SZ or REG_EXPAND_SZ value and returns it
// in a tstring.
//
// Arguments:
// hkey [in] The parent HKEY of szValueName
// pszValueName [in] The name of the value to query.
// dwType [in] REG_SZ or REG_EXPAND_SZ
// pstr [out] The returned value.
//
// Returns: S_OK or an error code.
//
// Author: shaunco 6 Jun 1998
//
// Notes: REG_EXPAND_SZ values ARE NOT expanded using
// ExpandEnvironentStrings. Use HrRegQueryExpandString instead.
//
HRESULT
HrRegQueryTypeString (
IN HKEY hkey,
IN PCTSTR pszValueName,
IN DWORD dwType,
OUT tstring* pstr)
{
Assert (hkey);
Assert (pszValueName);
Assert (pstr);
AssertSz ((REG_SZ == dwType) ||
(REG_EXPAND_SZ == dwType), "Only REG_SZ or REG_EXPAND_SZ "
"types accepted.");
BOOL fErase = TRUE;
// Get size of the data.
//
DWORD dwTypeRet;
DWORD cbData = 0;
HRESULT hr = HrRegQueryValueEx (hkey, pszValueName, &dwTypeRet,
NULL, &cbData);
// Make sure it has the correct type.
//
if ((S_OK == hr) && (dwTypeRet != dwType))
{
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE);
}
if (S_OK == hr)
{
// Compute the number of characters in the data including the
// NULL terminator. After dividing the number of bytes by
// the sizeof a TCHAR, add 1 if there is a remainder. If we didn't,
// and the number of bytes was not a multiple of the sizeof a TCHAR,
// we'd come up short because integer division rounds down.
// (The only time I can think of cbData would not be a multiple
// of sizeof(TCHAR) is if the registry data were somehow corrupted.
// It's not that I think corruption deserves a special case, but
// we shouldn't AV in light of it.)
//
DWORD cchIncludingNull;
cchIncludingNull = cbData / sizeof(TCHAR);
if (cbData % sizeof(TCHAR))
{
cchIncludingNull++;
}
// If we have more than just the terminator, allocate and
// get the string. Otherwise, we want it empty.
//
if (cchIncludingNull > 1)
{
// Reserve room for the correct number of characters.
// cch is the count of characters without the terminator
// since that is what tstring operates with.
//
DWORD cch = cchIncludingNull - 1;
Assert (cch > 0);
// assign will reserve cch characters and set them all to 0.
// checking capacity afterwards ensures the allocation made
// internally didn't fail.
//
pstr->assign (cch, 0);
if (cch <= pstr->capacity ())
{
hr = HrRegQueryValueEx (hkey, pszValueName, &dwType,
(LPBYTE)pstr->data (), &cbData);
if (S_OK == hr)
{
// If everything went according to plan, the length
// of the string should now match what wcslen
// returns on the string itself. The reason it will
// match is because we passed cch to assign.
//
Assert (pstr->length() == (size_t)wcslen (pstr->c_str()));
fErase = FALSE;
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
// Empty the output string on failure or if we think it should be
// empty.
//
if (FAILED(hr) || fErase)
{
pstr->erase();
}
TraceHr (ttidError, FAL, hr,
(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) ||
(HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE) == hr),
"HrRegQueryTypeString");
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRegQueryTypeSzBuffer
//
// Purpose: Gets a string from the registry using the given buffer. Checks
// that its type is correct. Type safe (no LPBYTE stuff).
//
// Arguments:
// hkey [in] The registry key.
// pszValueName [in] The name of the value to get.
// dwType [in] Desired type. (REG_SZ, REG_EXPAND_SZ, etc.)
// szData [out] String buffer to hold the data.
// pcbData [in,out] IN: Number of *bytes* in buffer pointed to by
// szData. OUT: Number of bytes actually copied
// into the buffer.
//
// Returns: S_OK or an HRESULT_FROM_WIN32 error code.
//
// Author: danielwe 3 Apr 1997
//
// Notes: If the function fails, the buffer passed in is guaranteed to
// be an empty string.
//
HRESULT
HrRegQueryTypeSzBuffer (
IN HKEY hkey,
IN PCTSTR pszValueName,
IN DWORD dwType,
OUT PWSTR pszData,
OUT DWORD* pcbData)
{
Assert (hkey);
Assert (pszValueName);
Assert (pcbData);
DWORD dwTypeRet;
HRESULT hr = HrRegQueryValueEx (hkey, pszValueName, &dwTypeRet,
(LPBYTE)pszData, pcbData);
if ((S_OK == hr) && (dwTypeRet != dwType))
{
TraceTag (ttidError, "Expected a type of 0x%x for %S.",
dwType, pszValueName);
hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATATYPE);
}
if (FAILED(hr) && pszData)
{
// Make sure empty string is returned on failure.
//
*pszData = 0;
}
TraceHr (ttidError, FAL, hr,
(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr),
"HrRegQueryTypeSzBuffer");
return hr;
}
#endif
//+---------------------------------------------------------------------------
//
// Function: HrRegQueryValueEx
//
// Purpose: Retrieves the data from the given registry value by calling
// RegQueryValueEx.
//
// Arguments:
// hkey [in]
// pszValueName [in]
// pdwType [out] See the Win32 documentation for the
// pbData [out] RegQueryValueEx function.
// pcbData [in,out]
//
// Returns: S_OK or an HRESULT_FROM_WIN32 error code.
//
// Author: shaunco 25 Feb 1997
//
// Notes: Note that pcbData is an *in/out* param. Set this to the size
// of the buffer pointed to by pbData *before* calling this
// function!
//
HRESULT
HrRegQueryValueEx (
IN HKEY hkey,
IN PCTSTR pszValueName,
OUT LPDWORD pdwType,
OUT LPBYTE pbData,
OUT LPDWORD pcbData)
{
Assert (hkey);
AssertSz (FImplies(pbData && pcbData, pdwType),
"pdwType not provided to HrRegQueryValueEx. You should be "
"retrieving the type as well so you can make sure it is "
"correct.");
LONG lr = RegQueryValueEx (hkey, pszValueName, NULL, pdwType,
pbData, pcbData);
HRESULT hr = HRESULT_FROM_WIN32 (lr);
TraceHr (ttidError, FAL, hr,
(ERROR_MORE_DATA == lr) || (ERROR_FILE_NOT_FOUND == lr),
"HrRegQueryValueEx (%S)", pszValueName);
return hr;
}
//+---------------------------------------------------------------------------
//
// Function: HrRegQueryValueWithAlloc
//
// Purpose: Retrieve a registry value in a buffer allocated by this
// function. This goes through the mess of checking the value
// size, allocating the buffer, and then calling back to get the
// actual value. Returns the buffer to the user.
//
// Arguments:
// hkey [in] An open HKEY (the one that contains the value
// to be read)
// pszValueName [in] Name of the registry value
// pdwType [in/out] The REG_ type that we plan to be reading
// ppbBuffer [out] Pointer to an LPBYTE buffer that will contain
// the registry value
// pdwSize [out] Pointer to a DWORD that will contain the size
// of the ppbBuffer.
//
// Returns: S_OK or an HRESULT_FROM_WIN32 error code.
//
// Author: jeffspr 27 Mar 1997
//
HRESULT
HrRegQueryValueWithAlloc (
IN HKEY hkey,
IN PCTSTR pszValueName,
LPDWORD pdwType,
LPBYTE* ppbBuffer,
LPDWORD pdwSize)
{
HRESULT hr;
BYTE abData [256];
DWORD cbData;
BOOL fReQuery = FALSE;
Assert (hkey);
Assert (pdwType);
Assert (ppbBuffer);
// Initialize the output parameters.
//
*ppbBuffer = NULL;
if (pdwSize)
{
*pdwSize = 0;
}
// Get the size of the data, and if it will fit, the data too.
//
cbData = sizeof(abData);
hr = HrRegQueryValueEx (
hkey,
pszValueName,
pdwType,
abData,
&cbData);
if (HRESULT_FROM_WIN32(ERROR_MORE_DATA) == hr)
{
// The data didn't fit, so we'll have to requery for it after
// we allocate our buffer.
//
fReQuery = TRUE;
hr = S_OK;
}
if (S_OK == hr)
{
// Allocate the buffer for the required size.
//
BYTE* pbBuffer = (BYTE*)MemAlloc (cbData);
if (pbBuffer)
{
if (fReQuery)
{
hr = HrRegQueryValueEx (
hkey,
pszValueName,
pdwType,
pbBuffer,
&cbData);
}
else
{
CopyMemory (pbBuffer, abData, cbData);
}
if (S_OK == hr)
{
// Fill in the return values.
//
*ppbBuffer = pbBuffer;
if (pdwSize)
{
*pdwSize = cbData;
}
}
else
{
MemFree (pbBuffer);
}
}
else
{
hr = E_OUTOFMEMORY;
}
}
TraceHr (ttidError, FAL, hr,
(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr),
"HrRegQueryValueWithAlloc");
return hr;
}