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.
 
 
 
 
 
 

707 lines
18 KiB

#include <pch.hxx>
#include <shlwapi.h>
#include <shlwapip.h>
#include "propbckt.h"
#include "optbckt.h"
#include "demand.h"
MSOEACCTAPI CreateOptionBucketEx(IOptionBucketEx **ppOptBckt)
{
COptionBucket *pBckt;
Assert(ppOptBckt != NULL);
pBckt = new COptionBucket;
*ppOptBckt = (IOptionBucketEx *)pBckt;
return(pBckt == NULL ? E_OUTOFMEMORY : S_OK);
}
COptionBucket::COptionBucket(void)
{
m_cRef = 1;
m_pProp = NULL;
m_pNotify = NULL;
m_fNotify = TRUE;
m_idNotify = 0;
m_rgInfo = NULL;
m_cInfo = 0;
m_cpszRegKey = 0;
m_pszRegKeyBase = NULL;
}
COptionBucket::~COptionBucket(void)
{
int i;
if (m_pProp != NULL)
m_pProp->Release();
if (m_pNotify != NULL)
m_pNotify->Release();
Assert(m_cpszRegKey <= CKEYMAX);
for (i = 0; i < m_cpszRegKey; i++)
MemFree(m_rgpszRegKey[i]);
if (m_pszRegKeyBase != NULL)
MemFree(m_pszRegKeyBase);
}
STDMETHODIMP COptionBucket::QueryInterface(REFIID riid, LPVOID *ppv)
{
if (ppv == NULL)
return(E_INVALIDARG);
if (IID_IUnknown == riid)
{
*ppv = (IUnknown *)this;
}
else if (IID_IOptionBucketEx == riid)
{
*ppv = (IOptionBucketEx *)this;
}
else if (IID_IOptionBucket == riid)
{
*ppv = (IOptionBucket *)this;
}
else if (IID_IPropertyBucket == riid)
{
*ppv = (IPropertyBucket *)this;
}
else
{
*ppv = NULL;
return(E_NOINTERFACE);
}
((IUnknown *)*ppv)->AddRef();
return(S_OK);
}
STDMETHODIMP_(ULONG) COptionBucket::AddRef(void)
{
return((ULONG)InterlockedIncrement(&m_cRef));
}
STDMETHODIMP_(ULONG) COptionBucket::Release(void)
{
LONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef)
delete this;
return((ULONG)cRef);
}
#define REG_INVALID 0xffffffff
DWORD RegTypeFromVarType(VARTYPE vt)
{
DWORD type;
switch (vt)
{
case VT_UI4:
type = REG_DWORD;
break;
case VT_LPSTR:
case VT_LPWSTR:
type = REG_SZ;
break;
case VT_BLOB:
type = REG_BINARY;
break;
default:
Assert(FALSE);
type = REG_INVALID;
break;
}
return(type);
}
STDMETHODIMP COptionBucket::GetProperty(LPCSTR pszProp, LPPROPVARIANT pVar, DWORD dwReserved)
{
HRESULT hr;
LPCOPTIONINFO pInfo;
DWORD cb,
type = REG_INVALID,
dw;
LPBYTE pbT = NULL;
LPCSTR pszKey,
pszValue;
LPWSTR pwszValue = NULL;
HKEY hkey = 0;
BOOL fSucceeded = FALSE;
if (pszProp == NULL || pVar == NULL || dwReserved != 0)
IF_FAILEXIT(hr = E_INVALIDARG);
Assert(m_pProp != NULL);
hr = m_pProp->GetProperty(pszProp, pVar, dwReserved);
if (hr == E_PROP_NOT_FOUND) // the property hasn't been set yet
{
hr = S_OK;
pbT = NULL;
pInfo = NULL;
pInfo = GetOptionInfo(pszProp);
if (pInfo == NULL)
IF_FAILEXIT(hr = E_PROP_NOT_FOUND);
Assert(pInfo->iszRegKey < m_cpszRegKey);
#pragma prefast(disable:11, "noise")
pszKey = m_rgpszRegKey[pInfo->iszRegKey];
pszValue = pInfo->pszRegValue;
if (pszValue && (ERROR_SUCCESS == RegOpenKeyEx(m_hkey, pszKey, 0, KEY_READ, &hkey)))
{
if (VT_LPWSTR == pInfo->vt)
{
#pragma prefast(enable:11, "noise")
IF_NULLEXIT(pwszValue = PszToUnicode(CP_ACP, pszValue));
if (ERROR_SUCCESS == RegQueryValueExWrapW(hkey, pwszValue, NULL, &type, NULL, &cb))
{
Assert(cb > 0);
IF_NULLEXIT(MemAlloc((void **)&pbT, cb));
fSucceeded = (ERROR_SUCCESS == RegQueryValueExWrapW(hkey, pwszValue, NULL, &type, pbT, &cb));
}
}
else
{
if (ERROR_SUCCESS == RegQueryValueEx(hkey, pszValue, NULL, &type, NULL, &cb))
{
Assert(cb > 0);
IF_NULLEXIT(MemAlloc((void **)&pbT, cb));
fSucceeded = (ERROR_SUCCESS == RegQueryValueEx(hkey, pszValue, NULL, &type, pbT, &cb));
}
}
if (fSucceeded)
{
if (pInfo != NULL && pInfo->vt == VT_UI4 && type == REG_BINARY)
{
// values set via the INF file may have type REG_BINARY instead of REG_DWORD
// but we need them to be REG_DWORD. the next time the value is set in the registry
// it will be set as REG_DWORD and everything will be cool from that point on...
Assert(cb >= 4);
pVar->vt = VT_UI4;
}
else
{
// Either we didn't find the entry, or the regtypes match.
Assert(type == RegTypeFromVarType(pInfo->vt));
pVar->vt = pInfo->vt;
}
if (pVar->vt == VT_ILLEGAL)
IF_FAILEXIT(hr = E_INVALID_PROP_TYPE);
}
else if (pInfo) // the property isn't set in the registry yet so grab default
{
IF_FAILEXIT(hr = GetPropertyDefault(SzToPropId(pszProp), pVar, dwReserved));
goto exit;
}
}
if (!fSucceeded)
{
hr = E_PROP_NOT_FOUND;
goto exit;
}
switch (pVar->vt)
{
case VT_UI4:
pVar->ulVal = *((DWORD *)pbT);
break;
case VT_LPSTR:
pVar->pszVal = (LPSTR)pbT;
break;
case VT_LPWSTR:
pVar->pwszVal = (LPWSTR)pbT;
break;
case VT_BLOB:
pVar->blob.cbSize = cb;
pVar->blob.pBlobData = pbT;
break;
default:
Assert(FALSE);
IF_FAILEXIT(hr = E_INVALID_PROP_TYPE);
break;
}
IF_FAILEXIT(hr = m_pProp->SetProperty(pszProp, pVar, 0));
if (pVar->vt != VT_UI4)
{
// we're handing this memory off to the caller, so don't free it
pbT = NULL;
}
}
else
IF_FAILEXIT(hr);
exit:
MemFree(pbT);
MemFree(pwszValue);
if (hkey)
RegCloseKey(hkey);
return(hr);
}
STDMETHODIMP COptionBucket::SetProperty(LPCSTR pszProp, LPCPROPVARIANT pVar, DWORD dwReserved)
{
if (pszProp == NULL || pVar == NULL || dwReserved != 0)
return(E_INVALIDARG);
return(ISetProperty(NULL, pszProp, pVar, 0));
}
STDMETHODIMP COptionBucket::ISetProperty(HWND hwnd, LPCSTR pszProp, LPCPROPVARIANT pVar, DWORD dwFlags)
{
HRESULT hr;
DWORD type,
cb;
LPBYTE pb;
LPCSTR pszKey,
pszValue;
LPWSTR pwszValue = NULL;
LPCOPTIONINFO pInfo;
LONG lRet;
HKEY hkey = 0;
if (pszProp == NULL || pVar == NULL)
IF_FAILEXIT(hr = E_INVALIDARG);
type = RegTypeFromVarType(pVar->vt);
if (type == REG_INVALID)
IF_FAILEXIT(hr = E_INVALID_PROP_TYPE);
Assert(m_pProp != NULL);
IF_FAILEXIT(hr = m_pProp->SetProperty(pszProp, pVar, 0));
if (hr != S_NO_CHANGE)
{
pInfo = GetOptionInfo(pszProp);
Assert(pInfo != NULL);
Assert(pInfo->iszRegKey < m_cpszRegKey);
pszKey = m_rgpszRegKey[pInfo->iszRegKey];
pszValue = pInfo->pszRegValue;
switch (pVar->vt)
{
case VT_UI4:
pb = (BYTE *)&pVar->ulVal;
cb = sizeof(DWORD);
break;
case VT_LPSTR:
pb = (BYTE *)pVar->pszVal;
cb = lstrlen(pVar->pszVal) + 1;
break;
case VT_LPWSTR:
pb = (BYTE *)pVar->pwszVal;
cb = (lstrlenW(pVar->pwszVal) + 1) * sizeof(WCHAR);
break;
case VT_BLOB:
pb = pVar->blob.pBlobData;
cb = pVar->blob.cbSize;
break;
default:
Assert(FALSE);
break;
}
if (pszValue != NULL)
{
if ((REG_BINARY == type) && (0 == cb))
{
SHDeleteValue(m_hkey, pszKey, pszValue);
lRet = ERROR_SUCCESS; // failure on delete is probably just NOT_FOUND
}
else
{
lRet= RegOpenKeyEx(m_hkey, pszKey, 0, KEY_WRITE, &hkey);
if (ERROR_SUCCESS == lRet)
{
if (VT_LPWSTR == pVar->vt)
{
IF_NULLEXIT(pwszValue = PszToUnicode(CP_ACP, pszValue));
lRet = RegSetValueExWrapW(hkey, pwszValue, NULL, type, pb, cb);
}
else
{
lRet = RegSetValueEx(hkey, pszValue, NULL, type, pb, cb);
}
}
}
if (ERROR_SUCCESS == lRet)
{
Assert(IsPropId(pszProp));
if (m_pNotify != NULL)
{
if (m_fNotify)
{
m_pNotify->DoNotification((IOptionBucketEx *)this, hwnd, SzToPropId(pszProp));
}
else
{
if (m_idNotify == 0)
m_idNotify = SzToPropId(pszProp);
else
m_idNotify = 0xffffffff;
}
}
}
else
IF_FAILEXIT(hr = E_FAIL);
}
}
exit:
if (hkey)
RegCloseKey(hkey);
MemFree(pwszValue);
return(hr);
}
STDMETHODIMP COptionBucket::ValidateProperty(PROPID id, LPCPROPVARIANT pVar, DWORD dwReserved)
{
HRESULT hr;
LPCOPTIONINFO pInfo;
if (pVar == NULL || dwReserved != 0)
return(E_INVALIDARG);
pInfo = GetOptionInfo(MAKEPROPSTRING(id));
if (pInfo == NULL)
hr = E_PROP_NOT_FOUND;
else if (pInfo->vt != pVar->vt)
hr = E_INVALID_PROP_TYPE;
else if (pInfo->pfnValid != NULL)
hr = pInfo->pfnValid(id, pVar);
else if (pVar->vt == VT_UI4 &&
(pInfo->dwMin != 0 || pInfo->dwMax != 0))
hr = (pVar->ulVal >= pInfo->dwMin && pVar->ulVal <= pInfo->dwMax) ? S_OK : E_INVALID_PROP_VALUE;
else
hr = S_OK;
return(hr);
}
STDMETHODIMP COptionBucket::GetPropertyDefault(PROPID id, LPPROPVARIANT pVar, DWORD dwReserved)
{
LPCOPTIONINFO pInfo;
HRESULT hr = S_OK;
LPBYTE pb = NULL;
DWORD cb = 0;
if (NULL == pVar || 0 != dwReserved)
IF_FAILEXIT(hr = E_INVALIDARG);
pInfo = GetOptionInfo(MAKEPROPSTRING(id));
if (NULL == pInfo)
IF_FAILEXIT(hr = E_PROP_NOT_FOUND);
pVar->vt = pInfo->vt;
if (pVar->vt == VT_UI4)
{
pVar->ulVal = (DWORD)PtrToUlong(pInfo->pszDef);
}
else
{
if (pInfo->pszDef)
{
switch (pVar->vt)
{
case VT_LPSTR:
cb = lstrlen(pInfo->pszDef) + 1;
break;
case VT_LPWSTR:
cb = (lstrlenW((LPWSTR)pInfo->pszDef) + 1) * sizeof(WCHAR);
break;
case VT_BLOB:
cb = pInfo->cbDefBinary;
break;
default:
Assert(FALSE);
break;
}
IF_NULLEXIT(MemAlloc((void **)&pb, cb));
CopyMemory(pb, pInfo->pszDef, cb);
switch (pVar->vt)
{
case VT_LPSTR:
pVar->pszVal = (LPSTR)pb;
break;
case VT_LPWSTR:
pVar->pwszVal = (LPWSTR)pb;
break;
case VT_BLOB:
pVar->blob.cbSize = cb;
pVar->blob.pBlobData = pb;
break;
}
}
else
// Since this happens quite often, don't trace it.
hr = E_NO_DEFAULT_VALUE;
}
pb = NULL;
exit:
MemFree(pb);
return(hr);
}
STDMETHODIMP COptionBucket::GetPropertyInfo(PROPID id, PROPINFO *pPropInfo, DWORD dwReserved)
{
LPCOPTIONINFO pInfo;
HRESULT hr = S_OK;
LPBYTE pb;
DWORD cb;
if (pPropInfo == NULL || pPropInfo->cbSize < sizeof(PROPINFO))
IF_FAILEXIT(hr = E_INVALIDARG);
#pragma prefast(disable:11, "noise")
pPropInfo->uMin = 0;
pPropInfo->uMax = 0;
#pragma prefast(enable:11, "noise")
pInfo = GetOptionInfo(MAKEPROPSTRING(id));
if (NULL == pInfo)
IF_FAILEXIT(hr = E_PROP_NOT_FOUND);
#pragma prefast(disable:11, "noise")
pPropInfo->vt = pInfo->vt;
switch (pPropInfo->vt)
{
case VT_LPSTR:
case VT_LPWSTR:
pPropInfo->cchMax = pInfo->dwMax;
break;
case VT_UI4:
pPropInfo->uMin = pInfo->dwMin;
pPropInfo->uMax = pInfo->dwMax;
break;
}
#pragma prefast(enable:11, "noise")
exit:
return(hr);
}
LPSTR DupPath(LPCSTR sz, LPCSTR szSubDir)
{
LPSTR szT = NULL;
if (MemAlloc((void **)&szT, MAX_PATH))
{
StrCpyN(szT, sz, MAX_PATH);
if (szSubDir != NULL)
PathAppend(szT, szSubDir);
}
else
TraceResult(E_OUTOFMEMORY);
return(szT);
}
STDMETHODIMP COptionBucket::Initialize(LPCOPTBCKTINIT pInit)
{
int i;
HRESULT hr = S_OK;
Assert(pInit != NULL);
Assert(pInit->rgInfo != NULL);
Assert(pInit->cInfo > 0);
Assert(pInit->pszRegKeyBase != NULL);
Assert(pInit->cszRegKey <= CKEYMAX);
Assert(pInit->hkey != NULL);
Assert(m_pProp == NULL);
m_rgInfo = pInit->rgInfo;
m_cInfo = pInit->cInfo;
#ifdef DEBUG
for (i = 0; i < m_cInfo - 1; i++)
{
Assert(m_rgInfo[i].id < m_rgInfo[i + 1].id);
}
#endif // DEBUG
m_hkey = pInit->hkey;
IF_NULLEXIT(m_pszRegKeyBase = PszDup(pInit->pszRegKeyBase));
Assert(m_cpszRegKey == 0);
if (pInit->cszRegKey == 0)
{
IF_NULLEXIT(m_rgpszRegKey[0] = PszDup(m_pszRegKeyBase));
m_cpszRegKey = 1;
}
else
{
for (i = 0; i < pInit->cszRegKey; i++)
{
IF_NULLEXIT(m_rgpszRegKey[i] = DupPath(m_pszRegKeyBase, pInit->rgpszRegSubKey[i]));
m_cpszRegKey++;
}
}
IF_NULLEXIT(m_pProp = new CPropertyBucket);
exit:
return hr;
}
LPCOPTIONINFO COptionBucket::GetOptionInfo(LPCSTR pszProp)
{
int left, right, x;
LPCOPTIONINFO pInfo;
PROPID id;
Assert(pszProp != NULL);
Assert(IsPropId(pszProp));
id = SzToPropId(pszProp);
left = 0;
right = m_cInfo - 1;
do
{
x = (left + right) / 2;
pInfo = &m_rgInfo[x];
if (id == pInfo->id)
return(pInfo);
else if (id < pInfo->id)
right = x - 1;
else
left = x + 1;
}
while (right >= left);
return(NULL);
}
STDMETHODIMP COptionBucket::SetNotification(IOptionBucketNotify *pNotify)
{
if (m_pNotify != NULL)
{
m_pNotify->Release();
m_pNotify = NULL;
}
if (pNotify != NULL)
{
m_pNotify = pNotify;
pNotify->AddRef();
}
return(S_OK);
}
STDMETHODIMP COptionBucket::EnableNotification(BOOL fEnable)
{
Assert(m_fNotify != fEnable);
m_fNotify = fEnable;
if (m_fNotify && m_pNotify && m_idNotify != 0)
{
m_pNotify->DoNotification((IOptionBucketEx *)this, 0, m_idNotify);
m_idNotify = 0;
}
return(S_OK);
}
// WARNING!!! This function doesn't handle getting values that are unicode.
STDMETHODIMP_(LONG) COptionBucket::GetValue(LPCSTR szSubKey, LPCSTR szValue, DWORD *ptype, LPBYTE pb, DWORD *pcb)
{
char szKey[MAX_PATH];
LONG lRet;
Assert(ptype != NULL);
Assert(szValue != NULL);
Assert(pcb != NULL);
if (szSubKey != NULL)
{
StrCpyN(szKey, m_pszRegKeyBase, ARRAYSIZE(szKey));
PathAppend(szKey, szSubKey);
szSubKey = szKey;
}
else
{
szSubKey = m_pszRegKeyBase;
}
lRet = SHGetValue(m_hkey, szSubKey, szValue, ptype, pb, pcb);
return(lRet);
}
// WARNING!!! This function doesn't handle setting values that are unicode.
STDMETHODIMP_(LONG) COptionBucket::SetValue(LPCSTR szSubKey, LPCSTR szValue, DWORD type, LPBYTE pb, DWORD cb)
{
char szKey[MAX_PATH];
LONG lRet;
Assert(szValue != NULL);
if (szSubKey != NULL)
{
StrCpyN(szKey, m_pszRegKeyBase, ARRAYSIZE(szKey));
PathAppend(szKey, szSubKey);
szSubKey = szKey;
}
else
{
szSubKey = m_pszRegKeyBase;
}
if (pb == NULL)
{
Assert(cb == 0);
lRet = SHDeleteValue(m_hkey, szSubKey, szValue);
}
else
{
Assert(cb > 0);
lRet = SHSetValue(m_hkey, szSubKey, szValue, type, pb, cb);
}
return(lRet);
}