Grabby/CommonCfg/RegHelper.c

280 lines
5.5 KiB
C
Raw Normal View History

#include "stdafx.h"
#define STRSAFE_NO_DEPRECATE
#include <Strsafe.h>
// Used by CopyRegValue specifically for copying
// REG_MULTI_SZ values, because those in particular are
// really funky.
static BOOL
CopyMultiValue(HKEY hKey,
PVOID pVal,
LPCTSTR szName,
DWORD dwSize)
{
int iStrCount = 0;
LPTSTR szMulti = NULL,
ptr;
BOOL bWasNull = FALSE;
LONG lRes;
MultiString *msData = (MultiString *)pVal;
HANDLE hHeap = GetProcessHeap();
szMulti = HeapAlloc(hHeap,
HEAP_ZERO_MEMORY,
dwSize + sizeof(TCHAR));
if (!szMulti) return FALSE;
// Get the multi-string value
if (!(lRes = RegQueryValueEx(hKey,
szName,
0,
NULL,
szMulti,
&dwSize)))
{
HeapFree(hHeap, 0, szMulti);
SetLastError(lRes);
return FALSE;
}
for (ptr = szMulti; (ptr - szMulti) < (LONG)dwSize; ptr++) {
if (*ptr == 0) {
if (bWasNull) {
// Two NULLs in a row, we're done!
break;
} else {
// End of string, add to the list
bWasNull = TRUE;
iStrCount++;
}
}
bWasNull = FALSE;
}
if (!bWasNull) {
// Not properly NULL terminated, sigh...
// Make sure to count the last string.
iStrCount++;
}
if (!MultiString_Init(msData, iStrCount)) {
HeapFree(hHeap, 0, szMulti);
return FALSE;
} else {
int i;
for (i = 0, ptr = szMulti; i < iStrCount; i++, ptr += strlen(ptr) + 1) {
if (!MultiString_Append(msData, ptr)) {
DWORD err = GetLastError();
HeapFree(hHeap, 0, szMulti);
MultiString_Dispose(msData);
SetLastError(err);
return FALSE;
}
}
}
HeapFree(hHeap, 0, szMulti);
return TRUE;
}
BOOL
CopyRegValue(HKEY hKey,
PVOID pVal,
LPCTSTR szName,
DWORD dwType,
DWORD dwSize)
{
HANDLE hHeap = GetProcessHeap();
PVOID pData = pVal;
LONG lRes;
if (pVal == NULL ||
szName == NULL ||
hKey == NULL) {
return FALSE;
}
if (dwType == REG_BINARY ||
dwType == REG_SZ) {
pData = HeapAlloc(hHeap, HEAP_ZERO_MEMORY, dwSize);
if (!pData) return FALSE;
*(PVOID *)pVal = pData;
} else if (dwType == REG_MULTI_SZ) {
// REG_MULTI_SZ is complex enough to warrant its own
// function
return CopyMultiValue(hKey, pVal, szName, dwSize);
}
if ((lRes = RegQueryValueEx(hKey,
szName,
NULL,
NULL,
pData,
&dwSize)) != ERROR_SUCCESS)
{
SetLastError(lRes);
return FALSE;
}
return TRUE;
}
// Enumerates across all values in a key, running the given
// RegEnumCallback. Use `pData` to pass application-defined
// data to your enumerator callback.
BOOL RegGetAllValues(HKEY hKey,
RegEnumCallback cb,
PVOID pData)
{
LONG lRes;
TCHAR szValName[512];
DWORD dwNameLen = 512,
dwIdx,
dwValType,
dwValSize;
if (!hKey || !cb) return FALSE;
for (dwIdx = 0;
dwNameLen = 512, // reset dwNameLen first
!(lRes = RegEnumValue(hKey,
dwIdx,
szValName,
&dwNameLen,
0,
&dwValType,
NULL,
&dwValSize));
dwIdx++) {
// Enforce null termination
szValName[min(511, dwNameLen)] = 0;
// pass to callback
if (!cb(hKey,
szValName,
dwValSize,
dwValType,
pData)) {
// Callback returned failure, bail out
return FALSE;
}
}
if (lRes != ERROR_NO_MORE_ITEMS) {
// Some enumeration error happened, store it
// and report the failure
SetLastError(lRes);
return FALSE;
}
return TRUE;
}
BOOL
RegStoreMultiString(HKEY hKey,
LPTSTR szValName,
MultiString *msData)
{
LPTSTR szMulti;
DWORD dwMultiSize;
LONG lRes;
HANDLE hHeap = GetProcessHeap();
if (!msData->TotalLength) return FALSE;
// Total size + second NULL terminator
dwMultiSize = (DWORD)msData->TotalLength + 1;
szMulti = HeapAlloc(hHeap,
HEAP_ZERO_MEMORY,
dwMultiSize * sizeof(TCHAR));
if (!szMulti) return FALSE;
// Copy all the strings into one buffer, as per REG_MULTI_SZ
{
DWORD i, dwCurLen;
for (i = 0, dwCurLen = 0;
i < msData->Count && dwCurLen < dwMultiSize;
dwCurLen += (DWORD)_tcslen(msData->Values[i++]) + 1) {
HRESULT hrRes = StringCchCopy(&szMulti[dwCurLen],
_tcslen(msData->Values[i]) + 1,
msData->Values[i]);
if (FAILED(hrRes)) {
HeapFree(hHeap, 0, szMulti);
return FALSE;
}
}
}
lRes = RegSetValueEx(hKey,
szValName,
0,
REG_MULTI_SZ,
szMulti,
dwMultiSize);
HeapFree(hHeap, 0, szMulti);
if (lRes != ERROR_SUCCESS) {
SetLastError(lRes);
return FALSE;
}
return TRUE;
}
// Stores a value in the registry, making assumptions based on the
// key type.
BOOL
RegStoreValue(HKEY hKey,
LPTSTR szValName,
PVOID pData,
DWORD dwValType)
{
DWORD dwStoreSize;
LONG lRes;
if (!hKey || !szValName || !pData) return FALSE;
switch (dwValType) {
case REG_SZ:
case REG_EXPAND_SZ:
dwStoreSize = (DWORD)_tcslen((LPTSTR)pData) + sizeof(TCHAR);
break;
case REG_DWORD:
dwStoreSize = sizeof(DWORD);
break;
#ifdef QWORD
case REG_QWORD:
dwStoreSize = sizeof(QWORD);
break;
#endif
case REG_BINARY:
// TODO: handle REG_BINARY? will we ever use it?
OutputDebugString(_T("REG_BINARY attempted to be stored! Unsupported"));
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
case REG_MULTI_SZ:
return RegStoreMultiString(hKey,
szValName,
(MultiString *)pData);
default:
// ignore
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
lRes = RegSetValueEx(hKey,
szValName,
0,
dwValType,
pData,
dwStoreSize);
if (lRes != ERROR_SUCCESS) {
SetLastError(lRes);
return FALSE;
}
return TRUE;
}