long GetRegValuePtr(const char* strKey, const char* strName, T1* pBuffer, bool bAllocate, T2* pRet = THROW_ERROR, DWORD* pType = NULL) throw(...)
{
long lErr;
bool bBufferIsCString, bRetIsCString;
bool bBufferIsChar, bRetIsChar;
DWORD nBufferSize, nRetSize;
bBufferIsCString = bRetIsCString = bBufferIsChar = bRetIsChar = false;
// Buffer size
if ( typeid(pBuffer) == typeid(const char*) ||
typeid(pBuffer) == typeid(char*) )
{
nBufferSize = (DWORD)strlen((const char*)pBuffer);
bBufferIsChar = true;
}
else if ( typeid(pBuffer) == typeid(CString*) )
{
nBufferSize = ((CString*)pBuffer)->GetLength() + 1;
bBufferIsCString = true;
}
else
nBufferSize = sizeof(*pBuffer);
// Return size
if ( typeid(pRet) == typeid(const char*) ||
typeid(pRet) == typeid(char*) )
{
nRetSize = (DWORD)strlen((const char*)pRet);
bRetIsChar = true;
}
else if ( typeid(pBuffer) == typeid(CString*) )
{
nRetSize = ((CString*)pRet)->GetLength() + 1;
bRetIsCString = true;
}
else
nRetSize = sizeof(*pRet);
try
{
lErr = OpenKey(strKey, true);
if (lErr != ERROR_SUCCESS) return ThrowError(lErr);
}
catch(long lErr)
{
if (lErr != ERROR_FILE_NOT_FOUND) return ThrowError(lErr);
goto File_Not_Found;
}
DWORD dwType, nRequiredAmount;
lErr = RegQueryValueEx(m_hKey, strName, NULL, &dwType, NULL, &nRequiredAmount);
if (lErr == ERROR_FILE_NOT_FOUND)
goto File_Not_Found;
else if (lErr != S_OK)
return ThrowError(lErr);
// To make sure if no buffer is provided, go no further.
if (pBuffer == NULL) return ERROR_FILE_NOT_FOUND;
if (pType) *pType = dwType;
BYTE* pNewBuffer;
if (dwType == REG_SZ)
{
// If the registry value type is REG_SZ (string), then the buffer must be char*,
// const char* or CString* to hold the data.
ASSERT(bBufferIsCString || bBufferIsChar);
if (bAllocate)
{
// Means that we should create the buffer
// Make sure a compatible buffer has been passed
ASSERT( typeid(pBuffer) == typeid(CString*) || typeid(pBuffer) == typeid(char**) ||
typeid(pBuffer) == typeid(const char**) );
if ( typeid(pBuffer) == typeid(CString*) )
pNewBuffer = (BYTE*)((CString*)pBuffer)->GetBuffer(nRequiredAmount);
else
{
BYTE** pTempBuffer = (BYTE**)pBuffer;
*pTempBuffer = new BYTE[nRequiredAmount];
pNewBuffer = *pTempBuffer;
}
nBufferSize = nRequiredAmount;
}
}
else
pNewBuffer = (BYTE*)pBuffer;
// Must have enough data in buffer if we're not allocating.
ASSERT(nBufferSize >= nRequiredAmount);
lErr = RegQueryValueEx(m_hKey, strName, NULL, &dwType, (BYTE*)pNewBuffer, &nBufferSize);
if (bBufferIsCString)
{
try
{
((CString*)pBuffer)->ReleaseBuffer();
}
catch(...)
{
// Bad data aquired from registry.
((CString*)pBuffer)->Empty();
if ((int)(__int64)pRet != THROW_ERROR) goto File_Not_Found;
else return ThrowError(ERROR_INVALID_DATA);
}
}
if (lErr != ERROR_SUCCESS) return ThrowError(lErr);
if (lErr == ERROR_FILE_NOT_FOUND) goto File_Not_Found;
return ERROR_SUCCESS;
File_Not_Found:
if ((int)(__int64)pRet == THROW_ERROR) return ThrowError(lErr);
if ( typeid(pBuffer) != typeid(CString*) )
{
// The buffer provided must be large enough to hold the return data!
ASSERT(nBufferSize >= nRetSize);
memcpy((void*)pBuffer, pRet, nRetSize);
}
else
{
CString* pString = (CString*)pBuffer;
memcpy(pString->GetBuffer(nRetSize), pRet, nRetSize);
pString->ReleaseBuffer();
}
return ERROR_FILE_NOT_FOUND;
}