mirror of https://github.com/tongzx/nt5src
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.
784 lines
18 KiB
784 lines
18 KiB
//=======================================================================
|
|
//
|
|
// Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// File: RegUtil.CPP
|
|
// Author: Charles Ma, 10/20/2000
|
|
//
|
|
// Revision History:
|
|
//
|
|
//
|
|
//
|
|
//
|
|
// Description:
|
|
//
|
|
// Implement IU registry accessing utility library
|
|
//
|
|
//=======================================================================
|
|
|
|
#include <windows.h>
|
|
#include <tchar.h>
|
|
#include <logging.h>
|
|
#include <memutil.h>
|
|
#include <fileutil.h>
|
|
#include <stringutil.h>
|
|
#include <shlwapi.h>
|
|
#include "wusafefn.h"
|
|
#include <regutil.h>
|
|
#include<iucommon.h>
|
|
#include <MISTSAFE.h>
|
|
|
|
const int REG_BUF_SIZE = 1024;
|
|
|
|
|
|
const LPCTSTR REG_ROOTKEY_STR[7] = {
|
|
_T("HKEY_LOCAL_MACHINE"),
|
|
_T("HKEY_CLASSES_ROOT"),
|
|
_T("HKEY_CURRENT_USER"),
|
|
_T("HKEY_CURRENT_CONFIG"),
|
|
_T("HKEY_USERS"),
|
|
_T("HKEY_PERFORMANCE_DATA"), // NT only
|
|
_T("HKEY_DYN_DATA") // W9x only
|
|
};
|
|
|
|
const HKEY REG_ROOTKEY[7] = {
|
|
HKEY_LOCAL_MACHINE,
|
|
HKEY_CLASSES_ROOT,
|
|
HKEY_CURRENT_USER,
|
|
HKEY_CURRENT_CONFIG,
|
|
HKEY_USERS,
|
|
HKEY_PERFORMANCE_DATA,
|
|
HKEY_DYN_DATA
|
|
};
|
|
|
|
|
|
typedef BOOL (WINAPI * PFN_StrToInt64Ex)(LPCTSTR pszString,
|
|
DWORD dwFlags,
|
|
LONGLONG * pllRet);
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// private function to split a full reg path into
|
|
// two parts: root key and subkey
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
LPCTSTR SplitRegPath(LPCTSTR lpsRegPath, HKEY* phRootKey)
|
|
{
|
|
LPTSTR lpSubKey = NULL;
|
|
for (int i = 0; i < sizeof(REG_ROOTKEY)/sizeof(HKEY); i++)
|
|
{
|
|
if ((lpSubKey = StrStrI(lpsRegPath, REG_ROOTKEY_STR[i])) == lpsRegPath)
|
|
{
|
|
*phRootKey = REG_ROOTKEY[i];
|
|
lpSubKey += lstrlen(REG_ROOTKEY_STR[i]);
|
|
lpSubKey = CharNext(lpSubKey); // skip past "\", if any (or remain on NULL)
|
|
return lpSubKey;
|
|
}
|
|
}
|
|
//
|
|
// if come to here, must be no right root key
|
|
//
|
|
*phRootKey = 0;
|
|
return lpsRegPath;
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// public function to tell if a reg key exists
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL RegKeyExists(
|
|
LPCTSTR lpsKeyPath, // key path
|
|
LPCTSTR lpsValName // optional value name
|
|
)
|
|
{
|
|
LOG_Block("RegKeyExists()");
|
|
|
|
HKEY hRootKey = 0, hKey = 0;
|
|
LPCTSTR lpsSubKey = NULL;
|
|
BOOL rc = FALSE;
|
|
DWORD dwType = 0x0;
|
|
|
|
if (NULL == lpsKeyPath)
|
|
{
|
|
LOG_ErrorMsg(E_INVALIDARG);
|
|
return FALSE;
|
|
}
|
|
|
|
LOG_Out(_T("Parameters: (%s, %s)"), lpsKeyPath, lpsValName);
|
|
|
|
lpsSubKey = SplitRegPath(lpsKeyPath, &hRootKey);
|
|
if (hRootKey && ERROR_SUCCESS == RegOpenKeyEx(hRootKey, lpsSubKey, 0, KEY_QUERY_VALUE, &hKey))
|
|
{
|
|
rc = (NULL == lpsValName) ||
|
|
(ERROR_SUCCESS == RegQueryValueEx(hKey, lpsValName, NULL, &dwType, NULL, NULL));
|
|
}
|
|
|
|
if (hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
LOG_Out(_T("Result: %s"), rc ? _T("TRUE") : _T("FALSE"));
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// public function to tell is a reg value in reg matches given value
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL RegKeyValueMatch(
|
|
LPCTSTR lpsKeyPath, // key path
|
|
LPCTSTR lpsValName, // optional value name
|
|
LPCTSTR lpsValue // value value
|
|
)
|
|
{
|
|
LOG_Block("RegKeyValueMatch()");
|
|
|
|
HKEY hRootKey = 0, hKey = 0;
|
|
LPCTSTR lpsSubKey = NULL;
|
|
BOOL rc = FALSE;
|
|
BYTE btBuffer[REG_BUF_SIZE];
|
|
LPBYTE pBuffer = btBuffer;
|
|
LPCTSTR lpCurStr;
|
|
DWORD dwType = 0x0;
|
|
DWORD dwSize = sizeof(btBuffer);
|
|
DWORD dwCode = 0x0;
|
|
HRESULT hr=S_OK;
|
|
|
|
USES_MY_MEMORY;
|
|
|
|
if (NULL == lpsKeyPath || NULL == lpsValue)
|
|
{
|
|
LOG_ErrorMsg(E_INVALIDARG);
|
|
goto CleanUp;
|
|
}
|
|
|
|
LOG_Out(_T("Parameters: (%s, %s, %s)"), lpsKeyPath, lpsValName, lpsValue);
|
|
|
|
|
|
lpsSubKey = SplitRegPath(lpsKeyPath, &hRootKey);
|
|
if (0 == hRootKey || (ERROR_SUCCESS != RegOpenKeyEx(hRootKey, lpsSubKey, 0, KEY_QUERY_VALUE, &hKey)))
|
|
{
|
|
goto CleanUp;
|
|
}
|
|
|
|
//
|
|
// try to query the value with existing buffer.
|
|
//
|
|
dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, btBuffer, &dwSize);
|
|
if (ERROR_MORE_DATA == dwCode)
|
|
{
|
|
//
|
|
// if found the existing buffer not large enough,
|
|
// then allocate memory large enough to store the data now
|
|
//
|
|
if (NULL == (pBuffer = (LPBYTE) MemAlloc(dwSize)))
|
|
{
|
|
goto CleanUp;
|
|
}
|
|
dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, pBuffer, &dwSize);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != dwCode)
|
|
{
|
|
goto CleanUp;
|
|
}
|
|
|
|
//
|
|
// since the value to compare was read from XML doc, obviously only
|
|
// the following 4 types possible to compare with
|
|
//
|
|
|
|
switch (dwType)
|
|
{
|
|
case REG_DWORD:
|
|
{
|
|
int x, y = *((int *) pBuffer);
|
|
DWORD dwFlag = STIF_DEFAULT;
|
|
//
|
|
// check if the value from manifest is a hex value:
|
|
// starts with x, or starts with 0x
|
|
//
|
|
LPCTSTR lpSecondChar = lpsValue + 1;
|
|
if (_T('0') == *lpsValue && (_T('x') == *lpSecondChar || _T('X') == *lpSecondChar))
|
|
{
|
|
dwFlag = STIF_SUPPORT_HEX;
|
|
}
|
|
|
|
if (StrToIntEx(lpsValue, dwFlag, &x))
|
|
{
|
|
rc = ( x == y);
|
|
}
|
|
}
|
|
break;
|
|
case REG_SZ:
|
|
case REG_EXPAND_SZ: // for mult-string, we only compair its first substring
|
|
rc = (lstrcmpi((LPCTSTR)lpsValue, (LPCTSTR) pBuffer) == 0);
|
|
if (!rc)
|
|
{
|
|
//
|
|
// if the ressult is not equal, it's possibly caused by
|
|
// path variables
|
|
//
|
|
// ASSUMPTION: these reg strings are for file path only, so we only
|
|
// handle cases not longer than MAX_PATH.
|
|
//
|
|
TCHAR szRegStr[MAX_PATH], szValStr[MAX_PATH];
|
|
|
|
if (dwSize >= MAX_PATH || lstrlen(lpsValue) >= MAX_PATH)
|
|
{
|
|
break;
|
|
}
|
|
|
|
if (SUCCEEDED(ExpandFilePath(lpsValue, szValStr, sizeof(szValStr)/sizeof(szValStr[0]))))
|
|
{
|
|
//
|
|
// if we can expand the given sub-string,
|
|
// then try to expand the reg string if QueryRegValue says
|
|
// this string is expandable. Otherwise, use the
|
|
// string retrieved only.
|
|
//
|
|
if (REG_EXPAND_SZ == dwType)
|
|
{
|
|
ExpandFilePath((LPCTSTR)pBuffer, szRegStr, sizeof(szRegStr)/sizeof(szRegStr[0]));
|
|
}
|
|
else
|
|
{
|
|
|
|
|
|
hr=StringCchCopyEx(szRegStr,ARRAYSIZE(szRegStr),(LPTSTR) pBuffer,NULL,NULL,MISTSAFE_STRING_FLAGS);
|
|
if(FAILED(hr)) break;
|
|
|
|
}
|
|
|
|
//
|
|
// compare in expanded mode
|
|
//
|
|
rc = (lstrcmpi((LPCTSTR)szRegStr, szValStr) == 0);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case REG_MULTI_SZ:
|
|
{
|
|
TCHAR szRegStr[MAX_PATH], szValStr[MAX_PATH];
|
|
|
|
szValStr[0] = '\0';
|
|
lpCurStr = (LPCTSTR)pBuffer;
|
|
//
|
|
// try to match each SZ in this multi sz.
|
|
//
|
|
do
|
|
{
|
|
//
|
|
// see if the value contains the substring passed in
|
|
//
|
|
rc = (lstrcmpi((LPCTSTR)lpsValue, (LPCTSTR)pBuffer) == 0);
|
|
|
|
//
|
|
// if not found, it's possibly caused by
|
|
// path variable or environment variable embedded
|
|
//
|
|
if (!rc && _T('\0') == szValStr[0])
|
|
{
|
|
if (FAILED(ExpandFilePath(lpsValue, szValStr, sizeof(szValStr)/sizeof(szValStr[0]))))
|
|
{
|
|
szValStr[0] = '\0';
|
|
}
|
|
}
|
|
|
|
//
|
|
// compare expanded XML str with current reg str expanded
|
|
// since this is REG_MULTI_SZ type, we have no way to tell
|
|
// if this SZ inside MULTI_SZ is expandable or not, we
|
|
// we will always try to expand it.
|
|
//
|
|
if (!rc && _T('\0') != szValStr[0])
|
|
{
|
|
rc = (SUCCEEDED(ExpandFilePath((LPCTSTR)lpCurStr, szRegStr, sizeof(szRegStr)/sizeof(szRegStr[0])))) &&
|
|
(lstrcmpi((LPCTSTR)szRegStr, szValStr) == 0);
|
|
}
|
|
|
|
if (!rc)
|
|
{
|
|
//
|
|
// move to next string
|
|
//
|
|
lpCurStr += (lstrlen(lpCurStr) + 1);
|
|
if (_T('\0') == *lpCurStr)
|
|
{
|
|
break; // no more string to read
|
|
}
|
|
}
|
|
} while (!rc); // repeat to next string
|
|
|
|
}
|
|
break;
|
|
case REG_QWORD:
|
|
{
|
|
HMODULE hLib = LoadLibraryFromSystemDir(_T("Shlwapi.dll"));
|
|
if (hLib)
|
|
{
|
|
#if defined(UNICODE) || defined(_UNICODE)
|
|
PFN_StrToInt64Ex pfnStrToInt64Ex = (PFN_StrToInt64Ex) GetProcAddress(hLib, "StrToInt64ExW");
|
|
#else
|
|
PFN_StrToInt64Ex pfnStrToInt64Ex = (PFN_StrToInt64Ex) GetProcAddress(hLib, "StrToInt64ExA");
|
|
#endif
|
|
if (pfnStrToInt64Ex)
|
|
{
|
|
LONGLONG llNum;
|
|
rc = (pfnStrToInt64Ex((LPCTSTR)lpsValue, STIF_DEFAULT, &llNum) &&
|
|
(llNum == (LONGLONG)pBuffer));
|
|
}
|
|
FreeLibrary(hLib);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case REG_BINARY:
|
|
rc = (CmpBinaryToString(pBuffer, dwSize, lpsValue) == 0);
|
|
break;
|
|
default:
|
|
rc = FALSE;
|
|
}
|
|
|
|
CleanUp:
|
|
|
|
if (hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
LOG_Out(_T("Result: %s"), rc ? _T("TRUE") : _T("FALSE"));
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// public function to tell is a reg key has a string type value
|
|
// that contains given string
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL RegKeySubstring(
|
|
LPCTSTR lpsKeyPath, // key path
|
|
LPCTSTR lpsValName, // optional value name
|
|
LPCTSTR lpsSubString // substring to see if contained in value
|
|
)
|
|
{
|
|
LOG_Block("RegKeySubstring()");
|
|
|
|
HKEY hRootKey = 0, hKey = 0;
|
|
LPCTSTR lpsSubKey = NULL;
|
|
BOOL rc = FALSE;
|
|
BYTE btBuffer[REG_BUF_SIZE];
|
|
LPBYTE pBuffer = btBuffer;
|
|
LPTSTR lpCurStr = (LPTSTR) pBuffer;
|
|
DWORD dwType = 0x0;
|
|
DWORD dwSize = sizeof(btBuffer);
|
|
DWORD dwCode = 0x0;
|
|
TCHAR szRegStr[MAX_PATH];
|
|
TCHAR szValStr[MAX_PATH]; // buffer for expanding
|
|
|
|
USES_MY_MEMORY;
|
|
|
|
if (NULL == lpsKeyPath || NULL == lpsSubString)
|
|
{
|
|
LOG_ErrorMsg(E_INVALIDARG);
|
|
return FALSE;
|
|
}
|
|
|
|
LOG_Out(_T("Parameters: (%s, %s, %s)"), lpsKeyPath, lpsValName, lpsSubString);
|
|
|
|
|
|
lpsSubKey = SplitRegPath(lpsKeyPath, &hRootKey);
|
|
if (0 == hRootKey || (ERROR_SUCCESS != RegOpenKeyEx(hRootKey, lpsSubKey, 0, KEY_QUERY_VALUE, &hKey)))
|
|
{
|
|
goto CleanUp;
|
|
}
|
|
|
|
//
|
|
// try to query the value with existing buffer.
|
|
//
|
|
dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, btBuffer, &dwSize);
|
|
if (ERROR_MORE_DATA == dwCode)
|
|
{
|
|
//
|
|
// if found the existing buffer not large enough,
|
|
// then allocate memory large enough to store the data now
|
|
//
|
|
if (NULL == (pBuffer = (LPBYTE) MemAlloc(dwSize)))
|
|
{
|
|
goto CleanUp;
|
|
}
|
|
lpCurStr = (LPTSTR) pBuffer;
|
|
dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, pBuffer, &dwSize);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != dwCode || REG_SZ != dwType && REG_EXPAND_SZ != dwType && REG_MULTI_SZ != dwType)
|
|
{
|
|
goto CleanUp;
|
|
}
|
|
|
|
szValStr[0] = _T('\0');
|
|
|
|
do
|
|
{
|
|
//
|
|
// see if the value contains the substring passed in
|
|
//
|
|
rc = (StrStrI((LPCTSTR)lpCurStr, lpsSubString) != NULL);
|
|
|
|
//
|
|
// if not found, it's possibly caused by
|
|
// path variable or environment variable embedded
|
|
//
|
|
if (!rc && _T('\0') == szValStr[0])
|
|
{
|
|
if (FAILED(ExpandFilePath(lpsSubString, szValStr, sizeof(szValStr)/sizeof(szValStr[0]))))
|
|
{
|
|
break;
|
|
}
|
|
rc = StrStrI((LPCTSTR)szRegStr, szValStr) != NULL;
|
|
}
|
|
|
|
if (!rc && _T('\0') != szValStr[0] && (REG_EXPAND_SZ == dwType ))
|
|
{
|
|
//
|
|
// try to expand string from reg if this string is expandable
|
|
//
|
|
rc = (SUCCEEDED(ExpandFilePath((LPCTSTR)lpCurStr, szRegStr, sizeof(szRegStr)/sizeof(szRegStr[0])))) &&
|
|
(StrStrI((LPCTSTR)szRegStr, szValStr) != NULL);
|
|
|
|
} // if not found
|
|
|
|
if (!rc && REG_MULTI_SZ == dwType)
|
|
{
|
|
//
|
|
// move to next string
|
|
//
|
|
lpCurStr += (lstrlen(lpCurStr) + 1);
|
|
if (_T('\0') == *lpCurStr)
|
|
{
|
|
break; // no more string to read
|
|
}
|
|
}
|
|
} while (!rc && REG_MULTI_SZ == dwType); // repeat to next string if REG_MULTI_SZ
|
|
|
|
CleanUp:
|
|
|
|
if (hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
LOG_Out(_T("Result: %s"), rc ? _T("TRUE") : _T("FALSE"));
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------
|
|
//
|
|
// public function to tell is a reg key has a string type value
|
|
// that contains given string
|
|
//
|
|
// since this is a comparision function, rather than to check existance,
|
|
// anything wrong to get the reg version will make the reg having default
|
|
// version: 0.0.0.0
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
BOOL RegKeyVersion(
|
|
LPCTSTR lpsKeyPath, // key path
|
|
LPCTSTR lpsValName, // optional value name
|
|
LPCTSTR lpsVersion, // version in string to compare
|
|
_VER_STATUS CompareVerb // how to compair
|
|
)
|
|
{
|
|
LOG_Block("RegKeyVersion()");
|
|
|
|
HKEY hRootKey = 0, hKey = 0;
|
|
LPCTSTR lpsSubKey = NULL;
|
|
BOOL rc = FALSE;
|
|
BYTE btBuffer[REG_BUF_SIZE];
|
|
LPBYTE pBuffer = btBuffer;
|
|
DWORD dwType = 0x0;
|
|
DWORD dwSize = sizeof(btBuffer);
|
|
DWORD dwCode = 0x0;
|
|
FILE_VERSION verReg, verXml;
|
|
int verCompare;
|
|
HRESULT hr=S_OK;
|
|
|
|
USES_IU_CONVERSION;
|
|
|
|
|
|
if (NULL == lpsKeyPath || NULL == lpsVersion)
|
|
{
|
|
LOG_ErrorMsg(E_INVALIDARG);
|
|
return FALSE;
|
|
}
|
|
|
|
LOG_Out(_T("Parameters: (%s, %s, %s, %d)"), lpsKeyPath, lpsValName, lpsVersion, (int)CompareVerb);
|
|
|
|
//
|
|
// initialize the reg version string buffer
|
|
//
|
|
|
|
|
|
//The buffer size of btBuffer is sufficient to hold the source string
|
|
if(FAILED(hr=StringCchCopyEx((LPTSTR)btBuffer,ARRAYSIZE(btBuffer)/sizeof(TCHAR),_T("0.0.0.0"),NULL,NULL,MISTSAFE_STRING_FLAGS)))
|
|
{
|
|
LOG_ErrorMsg(hr);
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
lpsSubKey = SplitRegPath(lpsKeyPath, &hRootKey);
|
|
if (0 == hRootKey || (ERROR_SUCCESS != RegOpenKeyEx(hRootKey, lpsSubKey, 0, KEY_QUERY_VALUE, &hKey)))
|
|
{
|
|
// LOG_ErrorMsg(ERROR_BADKEY); don't log error since we don't know if this key HAS to be there or not
|
|
goto GotVersion;
|
|
}
|
|
|
|
//
|
|
// try to query the value with existing buffer.
|
|
//
|
|
dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, btBuffer, &dwSize);
|
|
if (ERROR_MORE_DATA == dwCode)
|
|
{
|
|
//
|
|
// if found the existing buffer not large enough,
|
|
// then allocate memory large enough to store the data now
|
|
//
|
|
pBuffer = (LPBYTE) MemAlloc(dwSize);
|
|
if (NULL == pBuffer)
|
|
{
|
|
goto GotVersion;
|
|
}
|
|
dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, pBuffer, &dwSize);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != dwCode || REG_SZ != dwType)
|
|
{
|
|
|
|
|
|
hr=StringCchCopyEx((LPTSTR)pBuffer,dwSize/sizeof(TCHAR),_T("0.0.0.0"),NULL,NULL,MISTSAFE_STRING_FLAGS);
|
|
if(FAILED(hr))
|
|
{
|
|
LOG_ErrorMsg(hr);
|
|
goto CleanUp;
|
|
}
|
|
|
|
}
|
|
|
|
GotVersion:
|
|
|
|
//
|
|
// convert the retrieved reg value to version
|
|
//
|
|
if (!ConvertStringVerToFileVer(T2CA((LPCTSTR) pBuffer), &verReg) ||
|
|
!ConvertStringVerToFileVer(T2CA((LPCTSTR) lpsVersion), &verXml))
|
|
{
|
|
goto CleanUp;
|
|
}
|
|
|
|
//
|
|
// maybe we successfully read data from reg, but that data can't be converted
|
|
// into version at all. In this case, we still want to use the default version
|
|
// for comparision
|
|
//
|
|
if (0 > verReg.Major)
|
|
{
|
|
verReg.Major = verReg.Minor = verReg.Build = verReg.Ext = 0;
|
|
}
|
|
|
|
//
|
|
// compare version number. if a < b, -1; a > b, +1
|
|
//
|
|
verCompare = CompareFileVersion(verReg, verXml);
|
|
switch (CompareVerb)
|
|
{
|
|
case DETX_LOWER:
|
|
//
|
|
// if reg key version less than XML version
|
|
//
|
|
rc = (verCompare < 0);
|
|
break;
|
|
case DETX_LOWER_OR_EQUAL:
|
|
//
|
|
// if reg key version less than or equal to XML version
|
|
//
|
|
rc = (verCompare <= 0);
|
|
break;
|
|
case DETX_SAME:
|
|
//
|
|
// if reg key version same as XML version
|
|
//
|
|
rc = (0 == verCompare);
|
|
break;
|
|
case DETX_HIGHER_OR_EQUAL:
|
|
//
|
|
// if reg key version higher than or equal to XML version
|
|
//
|
|
rc = (verCompare >= 0);
|
|
break;
|
|
case DETX_HIGHER:
|
|
//
|
|
// if reg key versiong higher than XML version
|
|
//
|
|
rc = (verCompare > 0);
|
|
break;
|
|
default:
|
|
//
|
|
// should never happen
|
|
//
|
|
rc = FALSE;
|
|
break;
|
|
}
|
|
|
|
CleanUp:
|
|
|
|
if (hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
LOG_Out(_T("Result: %s"), rc ? _T("TRUE") : _T("FALSE"));
|
|
return rc;
|
|
}
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------------
|
|
//
|
|
// public function to find out the file path based on reg
|
|
// assumption:
|
|
// lpsFilePath points to a buffer at least MAX_PATH long.
|
|
//
|
|
// ----------------------------------------------------------------------------------
|
|
BOOL GetFilePathFromReg(
|
|
LPCTSTR lpsKeyPath, // key path
|
|
LPCTSTR lpsValName, // optional value name
|
|
LPCTSTR lpsRelativePath,// optional additonal relative path to add to path in reg
|
|
LPCTSTR lpsFileName, // optional file name to append to path
|
|
LPTSTR lpsFilePath
|
|
)
|
|
{
|
|
LOG_Block("GetFilePathFromReg()");
|
|
|
|
HKEY hRootKey = 0, hKey = 0;
|
|
LPCTSTR lpsSubKey = NULL;
|
|
BOOL rc = FALSE;
|
|
BYTE btBuffer[REG_BUF_SIZE];
|
|
LPBYTE pBuffer = btBuffer;
|
|
DWORD dwType = 0x0;
|
|
DWORD dwSize = sizeof(btBuffer);
|
|
DWORD dwCode = 0x0;
|
|
FILE_VERSION verReg, verXml;
|
|
int verCompare;
|
|
HRESULT hr=S_OK;
|
|
|
|
USES_IU_CONVERSION;
|
|
|
|
if (NULL == lpsKeyPath || NULL == lpsFilePath)
|
|
{
|
|
LOG_ErrorMsg(E_INVALIDARG);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// initialize file path
|
|
//
|
|
*lpsFilePath = '\0';
|
|
|
|
LOG_Out(_T("Parameters: (%s, %s, %s, %s)"), lpsKeyPath, lpsValName, lpsRelativePath, lpsFileName);
|
|
|
|
lpsSubKey = SplitRegPath(lpsKeyPath, &hRootKey);
|
|
if (0 == hRootKey || (ERROR_SUCCESS != RegOpenKeyEx(hRootKey, lpsSubKey, 0, KEY_QUERY_VALUE, &hKey)))
|
|
{
|
|
// LOG_ErrorMsg(ERROR_BADKEY); --- key probably not required to exist!
|
|
goto CleanUp;
|
|
}
|
|
|
|
//
|
|
// try to query the value with existing buffer.
|
|
//
|
|
dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, btBuffer, &dwSize);
|
|
if (ERROR_MORE_DATA == dwCode)
|
|
{
|
|
//
|
|
// if found the existing buffer not large enough,
|
|
// then allocate memory large enough to store the data now
|
|
//
|
|
if (NULL == (pBuffer = (LPBYTE) MemAlloc(dwSize + sizeof(TCHAR))))
|
|
{
|
|
goto CleanUp;
|
|
}
|
|
dwCode = RegQueryValueEx(hKey, lpsValName, NULL, &dwType, pBuffer, &dwSize);
|
|
}
|
|
|
|
if (ERROR_SUCCESS != dwCode || REG_SZ != dwType)
|
|
{
|
|
LOG_ErrorMsg(ERROR_BADKEY);
|
|
goto CleanUp;
|
|
}
|
|
|
|
//
|
|
// validate the to-be-combined path can fit into the buffer
|
|
//
|
|
if (lstrlen(lpsRelativePath) + lstrlen(lpsFileName) + dwSize/sizeof(TCHAR) >= MAX_PATH)
|
|
{
|
|
LOG_ErrorMsg(ERROR_BUFFER_OVERFLOW);
|
|
goto CleanUp;
|
|
}
|
|
|
|
//
|
|
// combile the path with optional relative path and file name
|
|
//
|
|
|
|
//The size of lpsFilePath is not available for using Safe String Functions
|
|
|
|
|
|
hr=StringCchCopyEx(lpsFilePath,MAX_PATH,(LPCTSTR) pBuffer,NULL,NULL,MISTSAFE_STRING_FLAGS);
|
|
if ( SUCCEEDED(hr) && (NULL == lpsRelativePath || SUCCEEDED(PathCchAppend(lpsFilePath,MAX_PATH,lpsRelativePath)) ) && (NULL == lpsFileName || SUCCEEDED(PathCchAppend(lpsFilePath,MAX_PATH,lpsFileName)) ))
|
|
{
|
|
rc = TRUE;
|
|
}
|
|
|
|
CleanUp:
|
|
|
|
if (hKey)
|
|
{
|
|
RegCloseKey(hKey);
|
|
}
|
|
if (!rc)
|
|
{
|
|
//
|
|
// make sure the buffer is set to empty string if error
|
|
//
|
|
*lpsFilePath = _T('\0');
|
|
}
|
|
else
|
|
{
|
|
LOG_Out(_T("Found path: %s"), lpsFilePath);
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
|