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.
476 lines
12 KiB
476 lines
12 KiB
#include <windows.h>
|
|
#include <fusenetincludes.h>
|
|
|
|
#define REGISTRY_BASE_LOCATION L"Software\\Microsoft\\Fusion\\Installer\\"
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Emitter
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CRegEmit ctor
|
|
// ---------------------------------------------------------------------------
|
|
CRegEmit::CRegEmit()
|
|
: _hr(S_OK), _hBaseKey((HKEY) INVALID_HANDLE_VALUE)
|
|
{}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CRegEmit dtor
|
|
// ---------------------------------------------------------------------------
|
|
CRegEmit::~CRegEmit()
|
|
{
|
|
if (_hBaseKey != INVALID_HANDLE_VALUE)
|
|
IF_FAILED_EXIT(RegCloseKey(_hBaseKey));
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CRegEmit::Create
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegEmit::Create(CRegEmit **ppEmit, LPCWSTR pwzRelKeyPath,
|
|
CRegEmit* pParentEmit)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
HKEY hKey = (HKEY) INVALID_HANDLE_VALUE;
|
|
|
|
LONG lReturn = 0;
|
|
DWORD dwDisposition = 0;
|
|
|
|
CString sBasePath;
|
|
CRegEmit *pEmit = NULL;
|
|
|
|
if (!pParentEmit)
|
|
{
|
|
IF_FAILED_EXIT(sBasePath.Assign(REGISTRY_BASE_LOCATION));
|
|
if (pwzRelKeyPath)
|
|
IF_FAILED_EXIT(sBasePath.Append(pwzRelKeyPath));
|
|
hKey = HKEY_CURRENT_USER;
|
|
}
|
|
else
|
|
{
|
|
IF_NULL_EXIT(pwzRelKeyPath, E_INVALIDARG);
|
|
sBasePath.Assign(pwzRelKeyPath);
|
|
hKey = pParentEmit->_hBaseKey;
|
|
}
|
|
IF_ALLOC_FAILED_EXIT(pEmit = new CRegEmit);
|
|
|
|
lReturn = RegCreateKeyEx(
|
|
hKey,
|
|
sBasePath._pwz,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&pEmit->_hBaseKey,
|
|
&dwDisposition);
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
*ppEmit = pEmit;
|
|
|
|
exit:
|
|
if (FAILED(hr))
|
|
SAFEDELETE(pEmit);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// WriteDword
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegEmit::WriteDword(LPCWSTR pwzValue, DWORD dwData)
|
|
{
|
|
LONG lReturn = 0;
|
|
|
|
lReturn = RegSetValueEx(_hBaseKey, pwzValue, 0, REG_DWORD, (LPBYTE) &dwData, sizeof(DWORD));
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
exit:
|
|
|
|
return _hr;
|
|
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// WriteString
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegEmit::WriteString(LPCWSTR pwzValue, LPCWSTR pwzData, DWORD ccData)
|
|
{
|
|
LONG lReturn = 0;
|
|
DWORD cbData = 0;
|
|
|
|
IF_FALSE_EXIT(pwzData, E_INVALIDARG);
|
|
|
|
if (ccData)
|
|
cbData = ccData * sizeof(WCHAR);
|
|
else
|
|
cbData = (lstrlen(pwzData) + 1) * sizeof(WCHAR);
|
|
|
|
lReturn = RegSetValueEx(_hBaseKey, pwzValue, 0, REG_SZ, (LPBYTE) pwzData, cbData);
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
exit:
|
|
|
|
return _hr;
|
|
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// WriteString
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegEmit::WriteString(LPCWSTR pwzValue, CString &sData)
|
|
{
|
|
return WriteString(pwzValue, sData._pwz, sData._cc);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// DeleteKey
|
|
// The one and only place we use the lousy Shlwapi apis.
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegEmit::DeleteKey(LPCWSTR pwzSubKey)
|
|
{
|
|
IF_FAILED_EXIT(SHDeleteKey(_hBaseKey, pwzSubKey));
|
|
|
|
exit:
|
|
return _hr;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Importer
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CRegImport ctor
|
|
// ---------------------------------------------------------------------------
|
|
CRegImport::CRegImport()
|
|
: _hr(S_OK), _hBaseKey((HKEY) INVALID_HANDLE_VALUE)
|
|
{}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CRegImport dtor
|
|
// ---------------------------------------------------------------------------
|
|
CRegImport::~CRegImport()
|
|
{
|
|
if (_hBaseKey != INVALID_HANDLE_VALUE)
|
|
IF_FAILED_EXIT(RegCloseKey(_hBaseKey));
|
|
|
|
exit:
|
|
return;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CRegImport::Create
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegImport::Create(CRegImport **ppImport, LPCWSTR pwzRelKeyPath,
|
|
CRegImport *pParentImport)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
HKEY hKey = (HKEY) INVALID_HANDLE_VALUE;
|
|
|
|
LONG lReturn = 0;
|
|
DWORD dwDisposition = 0;
|
|
|
|
CString sBasePath;
|
|
CRegImport *pImport = NULL;
|
|
|
|
if (!pParentImport)
|
|
{
|
|
IF_FAILED_EXIT(sBasePath.Assign(REGISTRY_BASE_LOCATION));
|
|
|
|
if (pwzRelKeyPath)
|
|
IF_FAILED_EXIT(sBasePath.Append(pwzRelKeyPath));
|
|
hKey = HKEY_CURRENT_USER;
|
|
}
|
|
else
|
|
{
|
|
IF_NULL_EXIT(pwzRelKeyPath, E_INVALIDARG);
|
|
sBasePath.Assign(pwzRelKeyPath);
|
|
hKey = pParentImport->_hBaseKey;
|
|
}
|
|
|
|
IF_ALLOC_FAILED_EXIT(pImport = new CRegImport);
|
|
|
|
lReturn = RegOpenKeyEx(
|
|
hKey,
|
|
sBasePath._pwz,
|
|
0,
|
|
KEY_READ,
|
|
&pImport->_hBaseKey);
|
|
|
|
if (lReturn == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
hr = S_FALSE;
|
|
*ppImport = NULL;
|
|
goto exit;
|
|
}
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
*ppImport = pImport;
|
|
|
|
exit:
|
|
if (FAILED(hr))
|
|
SAFEDELETE(pImport);
|
|
return hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// CRegImport::Create
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegImport::Create(CRegImport **ppImport, LPCWSTR pwzRelKeyPath,
|
|
HKEY hkeyRoot)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
MAKE_ERROR_MACROS_STATIC(hr);
|
|
|
|
LONG lReturn = 0;
|
|
DWORD dwDisposition = 0;
|
|
|
|
CString sBasePath;
|
|
CRegImport *pImport = NULL;
|
|
|
|
IF_NULL_EXIT(pwzRelKeyPath, E_INVALIDARG);
|
|
|
|
IF_FAILED_EXIT(sBasePath.Assign(pwzRelKeyPath));
|
|
|
|
IF_ALLOC_FAILED_EXIT(pImport = new CRegImport);
|
|
|
|
lReturn = RegOpenKeyEx(
|
|
hkeyRoot,
|
|
sBasePath._pwz,
|
|
0,
|
|
KEY_READ,
|
|
&pImport->_hBaseKey);
|
|
|
|
if (lReturn == ERROR_FILE_NOT_FOUND)
|
|
{
|
|
hr = S_FALSE;
|
|
*ppImport = NULL;
|
|
goto exit;
|
|
}
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
*ppImport = pImport;
|
|
|
|
exit:
|
|
if (FAILED(hr))
|
|
SAFEDELETE(pImport);
|
|
return hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Check
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegImport::Check(LPCWSTR pwzValue, BOOL &bExist)
|
|
{
|
|
LONG lReturn = 0;
|
|
|
|
bExist = FALSE;
|
|
|
|
lReturn = RegQueryValueEx(_hBaseKey, pwzValue, NULL, NULL, NULL, NULL);
|
|
|
|
IF_TRUE_EXIT(lReturn == ERROR_FILE_NOT_FOUND, S_FALSE);
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
bExist = TRUE;
|
|
|
|
exit:
|
|
return _hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ReadDword
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegImport::ReadDword(LPCWSTR pwzValue, LPDWORD pdwData)
|
|
{
|
|
LONG lReturn = 0;
|
|
DWORD dwType = REG_DWORD;
|
|
DWORD cbData = sizeof(DWORD);
|
|
|
|
lReturn = RegQueryValueEx(_hBaseKey, pwzValue, NULL, &dwType, (LPBYTE) pdwData, &cbData);
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
// Validate reg value type
|
|
IF_FALSE_EXIT(dwType == REG_DWORD || dwType == REG_DWORD_LITTLE_ENDIAN, E_UNEXPECTED);
|
|
|
|
exit:
|
|
|
|
return _hr;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// ReadString
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegImport::ReadString(LPCWSTR pwzValue, CString& sData)
|
|
{
|
|
LONG lReturn = 0;
|
|
DWORD dwType = REG_SZ;
|
|
DWORD cbData = 0;
|
|
DWORD dwCC = 0;
|
|
DWORD dwBufLen = 0;
|
|
CStringAccessor<CString> acc;
|
|
LPWSTR pwzData = NULL;
|
|
|
|
// IF_FALSE_EXIT(pwzValue, E_INVALIDARG); // if pwzValue == NULL or "", the "default" value is returned
|
|
|
|
lReturn = RegQueryValueEx(_hBaseKey, pwzValue, NULL, &dwType, NULL, &cbData);
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
IF_FALSE_EXIT(cbData, E_FAIL);
|
|
|
|
// Validate reg value type
|
|
IF_FALSE_EXIT(dwType == REG_SZ || dwType == REG_EXPAND_SZ, E_UNEXPECTED);
|
|
|
|
// Allocate for call to RQEX, with one extra char in case
|
|
// returned buffer is not null terminated.
|
|
dwCC = cbData / sizeof(WCHAR);
|
|
dwBufLen = dwCC+1;
|
|
|
|
// check overflow
|
|
IF_FALSE_EXIT(dwBufLen > dwCC, HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW));
|
|
|
|
IF_ALLOC_FAILED_EXIT(pwzData = new WCHAR[dwBufLen]);
|
|
|
|
lReturn = RegQueryValueEx(_hBaseKey, pwzValue, NULL, &dwType, (LPBYTE) pwzData, &cbData);
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
// Null terminate returned buffer.
|
|
*(pwzData + dwCC) = L'\0';
|
|
|
|
if (*(pwzData + dwCC - 1) != L'\0')
|
|
dwCC++;
|
|
|
|
sData.FreeBuffer();
|
|
|
|
// Attach accessor, set buffer, detach with corrected length.
|
|
IF_FAILED_EXIT(acc.Attach(sData));
|
|
*(&acc) = pwzData;
|
|
|
|
// Buffer size could be dwCC+1
|
|
IF_FAILED_EXIT(acc.Detach(dwCC));
|
|
// If Detach succeeds, reset pointer so that it is freed once.
|
|
pwzData = NULL;
|
|
|
|
exit:
|
|
|
|
SAFEDELETEARRAY(pwzData);
|
|
return _hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// EnumKeys
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegImport::EnumKeys(DWORD n, CString &sSubKey)
|
|
{
|
|
LONG lReturn = 0;
|
|
|
|
DWORD cSubKeys = 0, ccMaxSubKeyLen = 0, cValues = 0,
|
|
cMaxValueNameLen = 0, cMaxValueLen = 0;
|
|
|
|
DWORD ccSubKey = 0;
|
|
LPWSTR pwzSubKey = NULL;
|
|
|
|
// ISSUE-2002/03/04-adriaanc
|
|
// A race condition exists where a key could be added
|
|
// between RegQueryInfoKey and RegEnumKey. If a key
|
|
// greater than ccMaxSubKeyLen is added this will cause
|
|
// the enum call to fail. Need synchronization.
|
|
lReturn = RegQueryInfoKey(
|
|
_hBaseKey,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&cSubKeys,
|
|
&ccMaxSubKeyLen,
|
|
NULL,
|
|
&cValues,
|
|
&cMaxValueNameLen,
|
|
&cMaxValueLen,
|
|
NULL,
|
|
NULL);
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
ccSubKey = ccMaxSubKeyLen + 1;
|
|
IF_ALLOC_FAILED_EXIT(pwzSubKey = new WCHAR[ccSubKey]);
|
|
|
|
lReturn = RegEnumKeyEx(
|
|
_hBaseKey,
|
|
n,
|
|
pwzSubKey,
|
|
&ccSubKey,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (lReturn == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
_hr = S_FALSE;
|
|
goto exit;
|
|
}
|
|
|
|
IF_WIN32_FAILED_EXIT(lReturn);
|
|
|
|
sSubKey.Assign(pwzSubKey);
|
|
|
|
exit:
|
|
|
|
SAFEDELETEARRAY(pwzSubKey);
|
|
|
|
return _hr;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// EnumKeys
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT CRegImport::EnumKeys(DWORD n, CRegImport **ppImport)
|
|
{
|
|
CString sSubKey;
|
|
CRegImport *pImport = NULL;
|
|
|
|
IF_FAILED_EXIT(EnumKeys(n, sSubKey));
|
|
|
|
if (_hr == S_FALSE)
|
|
{
|
|
*ppImport = NULL;
|
|
goto exit;
|
|
}
|
|
|
|
IF_FAILED_EXIT(CRegImport::Create(&pImport, sSubKey._pwz, this));
|
|
|
|
*ppImport = pImport;
|
|
|
|
exit:
|
|
|
|
return _hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
|