Leaked source code of windows server 2003
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.
 
 
 
 
 
 

371 lines
10 KiB

#include "precomp.h"
#include "regins.h"
/////////////////////////////////////////////////////////////////////////////
// CRegInsMap operations
HRESULT CRegInsMap::PerformAction(HKEY *phk /*= NULL*/)
{
(void)phk;
return E_NOTIMPL;
}
HRESULT CRegInsMap::RegToIns(HKEY *phk /*= NULL*/, BOOL fClear /*= FALSE*/)
{
TCHAR szBuffer[MAX_PATH];
VARIANT var;
HKEY hk;
HRESULT hr;
DWORD cBuffer, dwType;
LONG lResult;
if ((phk != NULL && *phk == NULL) && m_pszRegKey == NULL)
return E_INVALIDARG;
//----- Special cases processing -----
//_____ Close cached reg key _____
if ((phk != NULL && *phk != NULL) && (m_pszRegKey == NULL && m_pszRegValue == NULL)) {
ASSERT(!fClear);
ASSERT(m_pszInsSection == NULL && m_pszInsKey == NULL);
SHCloseKey(*phk);
*phk = NULL;
return S_FALSE;
}
//_____ Clear ins file entry (not even necessary to open reg key) _____
ASSERT(m_pszInsSection != NULL && m_pszInsKey != NULL);
if (fClear) {
ASSERT(phk == NULL);
// REVIEW: (andrewgu) if i'm clearing and when last entry is gone see if section is gone
// as well and if it is not, do getprivateprofilesection to see if section is empty and
// delete it if it is.
WritePrivateProfileString(m_pszInsSection, m_pszInsKey, NULL, s_pszIns);
return S_FALSE;
}
//----- Main processing -----
hk = (phk != NULL) ? *phk : NULL;
openRegKey(&hk);
if (hk == NULL)
return E_FAIL;
//_____ Special case of caching reg key _____
if (m_pszInsSection == NULL) {
ASSERT(m_pszInsKey == NULL);
if (phk == NULL)
return E_INVALIDARG;
*phk = hk;
return S_FALSE;
}
szBuffer[0] = TEXT('\0');
cBuffer = sizeof(szBuffer);
lResult = SHQueryValueEx(hk, m_pszRegValue, NULL, &dwType, szBuffer, &cBuffer);
if (phk != NULL && *phk != hk)
SHCloseKey(hk);
if (lResult != ERROR_SUCCESS)
return E_UNEXPECTED;
//----- Convert szBuffer into var with proper type -----
hr = S_OK;
VariantClear(&var);
switch (dwType) {
case REG_BINARY:
if (cBuffer > sizeof(int)) {
hr = E_UNEXPECTED;
break;
}
// fall through
// case REG_DWORD_LITTLE_ENDIAN:
case REG_DWORD:
var.vt = VT_I4;
var.lVal = *(PINT)szBuffer;
break;
case REG_SZ:
case REG_EXPAND_SZ:
var.vt = VT_BSTR;
var.bstrVal = T2BSTR(szBuffer);
break;
// case REG_DWORD_BIG_ENDIAN:
// case REG_LINK:
// case REG_MULTI_SZ:
// case REG_NONE:
// case REG_RESOURCE_LIST:
default:
hr = E_FAIL;
}
if (FAILED(hr))
return hr;
//----- Convert var into szBuffer appropriate for WritePrivateProfileString -----
switch (var.vt) {
case VT_I4:
wnsprintf(szBuffer, countof(szBuffer), TEXT("%l"), var.lVal);
break;
case VT_I2:
wnsprintf(szBuffer, countof(szBuffer), TEXT("%i"), var.iVal);
break;
case VT_UI1:
wnsprintf(szBuffer, countof(szBuffer), TEXT("%u"), (UINT)var.bVal);
break;
case VT_BOOL:
wnsprintf(szBuffer, countof(szBuffer), TEXT("%u"), (UINT)var.boolVal);
break;
case VT_BSTR:
W2Tbuf(var.bstrVal, szBuffer, countof(szBuffer));
break;
// too many cases to enumerate that are invalid
default:
hr = E_FAIL;
}
if (FAILED(hr))
return hr;
WritePrivateProfileString(m_pszInsSection, m_pszInsKey, szBuffer, s_pszIns);
return S_OK;
}
HRESULT CRegInsMap::InsToReg(HKEY *phk /*= NULL*/, BOOL fClear /*= FALSE*/)
{
(void)phk; (void)fClear;
return E_NOTIMPL;
}
HRESULT CRegInsMap::RegToInsArray(CRegInsMap *prg, UINT cEntries, BOOL fClear /*= FALSE*/)
{
HKEY hk,
*rghkStack;
HRESULT hr;
UINT i, cStackDepth;
BOOL fContinueOnFailure,
fTotalSuccess, fBufferOverrun;
if (prg == NULL)
return E_INVALIDARG;
if (cEntries == 0)
return S_OK;
hr = S_OK;
fContinueOnFailure = TRUE;
fTotalSuccess = TRUE;
fBufferOverrun = FALSE;
if (fClear) {
for (i = 0; i < cEntries; i++) {
hr = prg->RegToIns(NULL, fClear);
if (FAILED(hr)) {
fTotalSuccess = FALSE;
if (!fContinueOnFailure)
break;
}
}
if (FAILED(hr))
return hr;
return fTotalSuccess ? S_OK : S_FALSE;
}
rghkStack = new HKEY[cEntries/2 + 1];
if (rghkStack == NULL)
return E_OUTOFMEMORY;
cStackDepth = 0;
for (i = 0; i < cEntries; i++) {
if (cStackDepth == 0)
hk = NULL;
else {
hk = rghkStack[cStackDepth-1];
ASSERT(hk != NULL);
}
hr = prg->RegToIns(&hk);
if (FAILED(hr)) {
fTotalSuccess = FALSE;
if (fContinueOnFailure)
continue;
else
break;
}
if (hk != NULL) {
if (hk != rghkStack[cStackDepth-1]) {
if (cStackDepth >= cEntries/2 + 1) {
SHCloseKey(hk);
hr = E_UNEXPECTED;
fTotalSuccess = FALSE;
fBufferOverrun = TRUE;
break;
}
rghkStack[cStackDepth++] = hk;
}
}
else
if (cStackDepth > 0)
rghkStack[--cStackDepth] = NULL;
}
if (FAILED(hr)) {
ASSERT(!fTotalSuccess);
for (i = 0; i < cEntries/2 + 1; i++)
if (rghkStack[i] != NULL) {
SHCloseKey(rghkStack[i]);
rghkStack[i] = NULL;
}
cStackDepth = 0;
}
ASSERT(cStackDepth == 0);
delete[] rghkStack;
if (!fBufferOverrun)
if (fContinueOnFailure && !fTotalSuccess)
hr = S_FALSE;
return hr;
}
HRESULT CRegInsMap::InsToRegArray(CRegInsMap *prg, UINT cEntries, BOOL fClear /*= FALSE*/)
{
(void)prg; (void)cEntries; (void)fClear;
return E_NOTIMPL;
}
/////////////////////////////////////////////////////////////////////////////
// CRegInsMap implementation helper routines
void CRegInsMap::openRegKey(HKEY *phk)
{
LPCTSTR pszRegKey;
HRESULT hr;
LONG lResult;
ASSERT(phk != NULL);
if (*phk != NULL && m_pszRegKey == NULL)
return;
ASSERT(m_pszRegKey != NULL);
if (*phk == NULL) {
hr = getHive(phk, &pszRegKey);
if (FAILED(hr)) {
ASSERT(*phk == NULL && pszRegKey == NULL);
return;
}
ASSERT(*phk != NULL && pszRegKey != NULL);
}
else {
ASSERT(getHive(NULL, NULL, GH_LOOKUPONLY) != S_OK);
pszRegKey = m_pszRegKey;
}
lResult = SHOpenKey(*phk, pszRegKey, KEY_QUERY_VALUE, phk);
if (lResult != ERROR_SUCCESS) {
ASSERT(*phk == NULL);
}
}
HRESULT CRegInsMap::getHive(HKEY *phk, LPCTSTR *ppszRegKey, WORD wFlags /*= GH_DEFAULT*/)
{
LPCTSTR pszSlash;
if (!(wFlags & GH_LOOKUPONLY)) {
if (phk == NULL || ppszRegKey == NULL)
return E_INVALIDARG;
*phk = NULL;
*ppszRegKey = NULL;
}
pszSlash = StrChr(m_pszRegKey, TEXT('\\'));
if (pszSlash == NULL)
return E_FAIL;
ASSERT(*(pszSlash+1) != TEXT('\0'));
struct {
HKEY hk;
LPCTSTR pszHive;
} map[] = {
{ HKEY_CLASSES_ROOT, RH_HKCR },
{ HKEY_CURRENT_USER, RH_HKCU },
{ HKEY_LOCAL_MACHINE, RH_HKLM },
{ HKEY_USERS, RH_HKU }
};
for (UINT i = 0; i < countof(map); i++)
if (StrCmpNI(m_pszRegKey, map[i].pszHive, INT(m_pszRegKey-pszSlash) + 1) == 0)
break;
if (i >= countof(map)) {
if (!(wFlags & GH_LOOKUPONLY))
*ppszRegKey = m_pszRegKey;
return S_FALSE;
}
if (!(wFlags & GH_LOOKUPONLY)) {
*phk = map[i].hk;
*ppszRegKey = pszSlash + 1;
}
return S_OK;
}
// HINTS: (andrewgu) on optimization
// 1. to start a regkey optimization section (i.e. to cache a reg key) have InsSection set to
// NULL, at the same time InsKey is ASSERTed NULL, meaning it better be NULL too;
// 2. to close last cached key, have RegKey and RegValue equal NULL. also InsSection and InsKey
// are ASSERTed NULL, so they also should be NULL;
// 3. if in optimization section and reg key is not empty current cached hk will be combined with
// regkey, it'll ASSERT if finds hive in RegKey;
// 4. if hive is not found in RegKey and the object is not in the optimization section it's an error
// 5. nested optimization sections are allowed
/*
LPCTSTR CRegInsMap::s_pszIns = TEXT("c:\foo.ini");
CRegInsMap rgTest1 = { TEXT("HKLM\\RegKey0"), TEXT("RegValue0"), 0L, NULL, NULL };
CRegInsMap rgTest[] = {
{ RH_HKLM TEXT("RegKey0"), NULL, 0L, NULL, NULL },
{ TEXT("RegKey1"), TEXT("RegValue1"), 0L, TEXT("InsSection1"), TEXT("InsKey1") },
{ NULL , TEXT("RegValue2"), 0L, TEXT("InsSection1"), TEXT("InsKey2") },
{ NULL, NULL, 0L, NULL, NULL },
{ RH_HKCR RK_IEAK, RV_TOOLBARBMP, 0L, IS_BRANDING, IK_TOOLBARBMP },
{ TEXT("RegKey4"), TEXT("RegValue4"), 0L, TEXT("InsSection4"), TEXT("InsKey4") },
{ TEXT("RegKey5"), TEXT("RegValue5"), 0L, TEXT("InsSection5"), TEXT("InsKey5") },
{ TEXT("RegKey6"), TEXT("RegValue6"), 0L, TEXT("InsSection6"), TEXT("InsKey6") },
{ TEXT("RegKey7"), TEXT("RegValue7"), 0L, TEXT("InsSection7"), TEXT("InsKey7") },
{ TEXT("RegKey8"), TEXT("RegValue8"), 0L, TEXT("InsSection8"), TEXT("InsKey8") },
{ TEXT("RegKey9"), TEXT("RegValue9"), 0L, TEXT("InsSection9"), TEXT("InsKey9") }
};
// Example usage
rgTest[0].RegToInsArray(rgTest, countof(rgTest));
*/