|
|
//=======================================================================
//
// Copyright (c) 1998-2000 Microsoft Corporation. All Rights Reserved.
//
// File: expression.CPP
//
// Author: Charles Ma
// 2000.10.27
//
// Description:
//
// Implement function related to detection expressions
//
//=======================================================================
#include "iuengine.h"
#include "SchemaMisc.h"
#include "expression.h"
#include <RegUtil.h>
#include <FileUtil.h>
#include <StringUtil.h>
#include <shlwapi.h>
#include "SchemaKeys.h"
#include "iucommon.h"
//
// include IDetection interface
//
#ifdef _MIDL_USE_GUIDDEF_
#ifndef INITGUID
#define INITGUID
#include <guiddef.h>
#undef INITGUID
#else
#include <guiddef.h>
#endif
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)
#else // !_MIDL_USE_GUIDDEF_
#ifndef __IID_DEFINED__
#define __IID_DEFINED__
typedef struct _IID { unsigned long x; unsigned short s1; unsigned short s2; unsigned char c[8]; } IID;
#endif // __IID_DEFINED__
#ifndef CLSID_DEFINED
#define CLSID_DEFINED
typedef IID CLSID; #endif // CLSID_DEFINED
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
#endif !_MIDL_USE_GUIDDEF_
MIDL_DEFINE_GUID(IID, IID_IDetection,0x8E2EF6DC,0x0AB8,0x4FE0,0x90,0x49,0x3B,0xEA,0x45,0x06,0xBF,0x8D);
#ifndef __IDetection_FWD_DEFINED__
#define __IDetection_FWD_DEFINED__
typedef interface IDetection IDetection; #endif /* __IDetection_FWD_DEFINED__ */
#ifndef __IDetection_INTERFACE_DEFINED__
#define __IDetection_INTERFACE_DEFINED__
/* interface IDetection */ /* [unique][helpstring][dual][uuid][object] */
EXTERN_C const IID IID_IDetection;
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("8E2EF6DC-0AB8-4FE0-9049-3BEA4506BF8D") IDetection : public IDispatch { public: virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Detect( /* [in] */ BSTR bstrXML, /* [out] */ DWORD *pdwDetectionResult) = 0; }; #else /* C style interface */
typedef struct IDetectionVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IDetection * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IDetection * This); ULONG ( STDMETHODCALLTYPE *Release )( IDetection * This); HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( IDetection * This, /* [out] */ UINT *pctinfo); HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( IDetection * This, /* [in] */ UINT iTInfo, /* [in] */ LCID lcid, /* [out] */ ITypeInfo **ppTInfo); HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( IDetection * This, /* [in] */ REFIID riid, /* [size_is][in] */ LPOLESTR *rgszNames, /* [in] */ UINT cNames, /* [in] */ LCID lcid, /* [size_is][out] */ DISPID *rgDispId); /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( IDetection * This, /* [in] */ DISPID dispIdMember, /* [in] */ REFIID riid, /* [in] */ LCID lcid, /* [in] */ WORD wFlags, /* [out][in] */ DISPPARAMS *pDispParams, /* [out] */ VARIANT *pVarResult, /* [out] */ EXCEPINFO *pExcepInfo, /* [out] */ UINT *puArgErr); /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *Detect )( IDetection * This, /* [in] */ BSTR bstrXML, /* [out] */ DWORD *pdwDetectionResult); END_INTERFACE } IDetectionVtbl;
interface IDetection { CONST_VTBL struct IDetectionVtbl *lpVtbl; };
#ifdef COBJMACROS
#define IDetection_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IDetection_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define IDetection_Release(This) \
(This)->lpVtbl -> Release(This)
#define IDetection_GetTypeInfoCount(This,pctinfo) \
(This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)
#define IDetection_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \
(This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)
#define IDetection_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \
(This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)
#define IDetection_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \
(This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)
#define IDetection_Detect(This,bstrXML,pdwDetectionResult) \
(This)->lpVtbl -> Detect(This,bstrXML,pdwDetectionResult)
#endif /* COBJMACROS */
#endif /* C style interface */
/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IDetection_Detect_Proxy( IDetection * This, /* [in] */ BSTR bstrXML, /* [out] */ DWORD *pdwDetectionResult);
void __RPC_STUB IDetection_Detect_Stub( IRpcStubBuffer *This, IRpcChannelBuffer *_pRpcChannelBuffer, PRPC_MESSAGE _pRpcMessage, DWORD *_pdwStubPhase);
#endif /* __IDetection_INTERFACE_DEFINED__ */
//
// deckare the constants used to manipulate the result of Detect() method
//
//
// First group, used in <expression> tag, to tell the detection result. This result
// should combined with other expression(s) at the same level
//
const DWORD IUDET_BOOL = 0x00000001; // mask
const DWORD IUDET_FALSE = 0x00000000; // expression detect FALSE
const DWORD IUDET_TRUE = 0x00000001; // expression detect TRUE
const DWORD IUDET_NULL = 0x00000002; // expression detect data missing
//
// Second group, used in <detection> tag, to tell the detection result. This result
// should overwrite the rest of <expression>, if any
//
extern const LONG IUDET_INSTALLED = 0x00000010; /* mask for <installed> result */ extern const LONG IUDET_INSTALLED_NULL = 0x00000020; /* <installed> missing */ extern const LONG IUDET_UPTODATE = 0x00000040; /* mask for <upToDate> result */ extern const LONG IUDET_UPTODATE_NULL = 0x00000080; /* <upToDate> missing */ extern const LONG IUDET_NEWERVERSION = 0x00000100; /* mask for <newerVersion> result */ extern const LONG IUDET_NEWERVERSION_NULL = 0x00000200; /* <newerVersion> missing */ extern const LONG IUDET_EXCLUDED = 0x00000400; /* mask for <excluded> result */ extern const LONG IUDET_EXCLUDED_NULL = 0x00000800; /* <excluded> missing */ extern const LONG IUDET_FORCE = 0x00001000; /* mask for <force> result */ extern const LONG IUDET_FORCE_NULL = 0x00002000; /* <force> missing */ extern const LONG IUDET_COMPUTER = 0x00004000; // mask for <computerSystem> result
extern const LONG IUDET_COMPUTER_NULL = 0x00008000; // <computerSystem> missing
#define GotoCleanupIfNull(p) if (NULL==p) goto CleanUp
#define GotoCleanupHR(hrCode) hr = hrCode; LOG_ErrorMsg(hr); goto CleanUp
// ----------------------------------------------------------------------
//
// public helper function to convert a bstr value to
// version status enum value, if possible
//
// ----------------------------------------------------------------------
BOOL ConvertBstrVersionToEnum(BSTR bstrVerVerb, _VER_STATUS *pEnumVerVerb) { //
// convert the versionStatus in bstr into enum
//
if (CompareBSTRsEqual(bstrVerVerb, KEY_VERSTATUS_HI)) { *pEnumVerVerb = DETX_HIGHER; } else if (CompareBSTRsEqual(bstrVerVerb,KEY_VERSTATUS_HE)) { *pEnumVerVerb = DETX_HIGHER_OR_EQUAL; } else if (CompareBSTRsEqual(bstrVerVerb, KEY_VERSTATUS_EQ)) { *pEnumVerVerb = DETX_SAME; } else if (CompareBSTRsEqual(bstrVerVerb, KEY_VERSTATUS_LE)) { *pEnumVerVerb = DETX_LOWER_OR_EQUAL; } else if (CompareBSTRsEqual(bstrVerVerb, KEY_VERSTATUS_LO)) { *pEnumVerVerb = DETX_LOWER; } else { return FALSE; }
return TRUE; }
//----------------------------------------------------------------------
//
// public function DetectExpression()
// retrieve the data from the express node,
// and do actual detection work
//
// Input:
// expression node
// LPCTSTR lpcsDllPath, // path that this provider saved the cust detection Dll
//
// Return:
// TRUE/FALSE, detection result
//
//----------------------------------------------------------------------
HRESULT DetectExpression(IXMLDOMNode* pExpression, BOOL *pfResult) { HRESULT hr = E_INVALIDARG; int iRet = -1; BOOL fRet = TRUE; IXMLDOMNodeList* pChildList = NULL; IXMLDOMNode* pCandidate = NULL;
BSTR bstrName = NULL; BSTR bstrKey = NULL, bstrEntry = NULL, bstrValue = NULL; LPCTSTR lpszKeyComputer = NULL;
LOG_Block("DetectExpression()");
USES_IU_CONVERSION;
if (NULL == pExpression || NULL == pfResult) { LOG_ErrorMsg(hr); return hr; }
*pfResult = TRUE;
//
// retrieve all child nodes
//
(void)pExpression->get_childNodes(&pChildList); if (NULL == pChildList) { LOG_XML(_T("Empty expression found!")); GotoCleanupHR(E_INVALIDARG); }
//
// get the first child
//
(void)pChildList->nextNode(&pCandidate); if (NULL == pCandidate) { LOG_XML(_T("empty child list for passed in expresson node!")); GotoCleanupHR(E_INVALIDARG); }
//
// loop through each child node, find out the type
// of node, call actual detection func accordingly
//
lpszKeyComputer = OLE2T(KEY_COMPUTERSYSTEM); CleanUpFailedAllocSetHrMsg(lpszKeyComputer);
while (NULL != pCandidate) { CleanUpIfFailedAndSetHrMsg(pCandidate->get_nodeName(&bstrName));
LPTSTR lpszName = OLE2T(bstrName); CleanUpFailedAllocSetHrMsg(lpszName);
if (CSTR_EQUAL == CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, lpszName, -1, KEY_REGKEYEXISTS, -1)) { //
// call detection function
//
hr = DetectRegKeyExists(pCandidate, pfResult); } else if (CSTR_EQUAL == CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, lpszName, -1, KEY_REGKEYVALUE, -1)) { //
// process RegKeyValue expression
//
hr = DetectRegKeyValue(pCandidate, pfResult); } else if (CSTR_EQUAL == CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, lpszName, -1, KEY_REGKEYSUBSTR, -1)) { //
// process RegKeySubstring expression
//
hr = DetectRegKeySubstring(pCandidate, pfResult); } else if (CSTR_EQUAL == CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, lpszName, -1, KEY_REGKEYVERSION, -1)) { //
// process RegVersion expression
//
hr = DetectRegVersion(pCandidate, pfResult); } else if (CSTR_EQUAL == CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, lpszName, -1, KEY_FILEVERSION, -1)) { //
// process FileVersion expression
//
hr = DetectFileVersion(pCandidate, pfResult); } else if (CSTR_EQUAL == CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, lpszName, -1, KEY_FILEEXISTS, -1)) { //
// process FileExists expression
//
hr = DetectFileExists(pCandidate, pfResult); } else if (CSTR_EQUAL == CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, lpszName, -1, lpszKeyComputer, -1)) { //
// process computerSystem check
//
hr = DetectComputerSystem(pCandidate, pfResult); } else if (CSTR_EQUAL == CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, lpszName, -1, KEY_AND, -1)) { //
// process AND expression
//
IXMLDOMNodeList* pSubExpList = NULL; IXMLDOMNode* pSubExp = NULL; long lLen = 0;
//
// get child list
//
pCandidate->get_childNodes(&pSubExpList); if (NULL == pSubExpList) { LOG_XML(_T("Found no children of AND expression")); GotoCleanupHR(E_INVALIDARG); }
pSubExpList->get_length(&lLen); fRet = TRUE; for (long i = 0; i < lLen && fRet; i++) { //
// each child should be an expression
// process it. if false, then short-cut.
//
pSubExpList->get_item(i, &pSubExp); if (NULL == pSubExp) { pSubExpList->Release(); pSubExpList = NULL; LOG_XML(_T("Failed to get the #%d sub-expression in this AND expression"), i); GotoCleanupHR(E_INVALIDARG); } hr = DetectExpression(pSubExp, &fRet); SafeReleaseNULL(pSubExp); if (FAILED(hr)) { //
// if found something wrong in recursion, don't continue
//
break; } } SafeReleaseNULL(pSubExpList); *pfResult = fRet; } else if (CSTR_EQUAL == CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, lpszName, -1, KEY_OR, -1)) { //
// process OR expression
//
IXMLDOMNodeList* pSubExpList = NULL; IXMLDOMNode* pSubExp = NULL; long lLen = 0;
//
// get child list
//
pCandidate->get_childNodes(&pSubExpList); if (NULL == pSubExpList) { LOG_XML(_T("Found no children of OR expression")); GotoCleanupHR(E_INVALIDARG); }
pSubExpList->get_length(&lLen); fRet = FALSE; for (long i = 0; i < lLen && !fRet; i++) { //
// each child is one expression
// do it one by one
//
pSubExpList->get_item(i, &pSubExp); if (NULL == pSubExp) { pSubExpList->Release(); pSubExpList = NULL; LOG_XML(_T("Failed to get the #%d sub-expression in this OR expression"), i); GotoCleanupHR(E_INVALIDARG); } hr = DetectExpression(pSubExp, &fRet); SafeReleaseNULL(pSubExp);
if (FAILED(hr)) { //
// if found something wrong in recursion, don't continue
//
break; } } SafeReleaseNULL(pSubExpList); *pfResult = fRet;
} else if (CSTR_EQUAL == CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, lpszName, -1, KEY_NOT, -1)) { //
// process NOT expression
//
IXMLDOMNode* pSubExp = NULL; //
// get the only child
//
pCandidate->get_firstChild(&pSubExp); if (NULL == pSubExp) { LOG_XML(_T("Failed to get first child in NOT expression")); GotoCleanupHR(E_INVALIDARG); } //
// the child must be an expression, process it
//
hr = DetectExpression(pSubExp, &fRet); if (SUCCEEDED(hr)) { fRet = !fRet; // flip the result for NOT expression
*pfResult = fRet; } else { LOG_ErrorMsg(hr); } SafeReleaseNULL(pSubExp); }
if (FAILED(hr)) { goto CleanUp; }
if (!*pfResult) { //
// if found one expression FALSE, the whole thing false, so
// no need to continue
//
break; } SafeReleaseNULL(pCandidate); pChildList->nextNode(&pCandidate); SafeSysFreeString(bstrName); }
CleanUp: SafeReleaseNULL(pCandidate); SafeReleaseNULL(pChildList); SysFreeString(bstrName); SysFreeString(bstrKey); SysFreeString(bstrEntry); SysFreeString(bstrValue);
return hr; }
//----------------------------------------------------------------------
//
// Helper function DetectRegKeyExists()
// retrieve the data from the node,
// and do actual detection work
//
// Input:
// RegKeyExists node
//
// Return:
// int - detection result: -1=none, 0=FALSE, 1=TRUE
//
// Assumption:
// input parameter not NULL
//
//----------------------------------------------------------------------
HRESULT DetectRegKeyExists( IXMLDOMNode* pRegKeyExistsNode, BOOL *pfResult ) { LOG_Block("DetectRegKeyExists"); HRESULT hr = E_INVALIDARG; BOOL fRet = FALSE; LPTSTR lpszKey = NULL, lpszEntry = NULL; BSTR bstrKey = NULL, bstrEntry = NULL;
USES_IU_CONVERSION;
//
// find the key value
//
if (FindNodeValue(pRegKeyExistsNode, KEY_KEY, &bstrKey)) { lpszKey = OLE2T(bstrKey); CleanUpFailedAllocSetHrMsg(lpszKey);
//
// find the optional entry value
//
if (FindNodeValue(pRegKeyExistsNode, KEY_ENTRY, &bstrEntry)) { lpszEntry = OLE2T(bstrEntry); CleanUpFailedAllocSetHrMsg(lpszEntry); }
*pfResult = RegKeyExists(lpszKey, lpszEntry);
hr = S_OK; }
CleanUp: SysFreeString(bstrKey); SysFreeString(bstrEntry);
return hr; }
//----------------------------------------------------------------------
//
// Helper function DetectRegKeyExists()
// retrieve the data from the node,
// and do actual detection work
//
// Input:
// RegKeyValue node
//
// Return:
// int - detection result: -1=none, 0=FALSE, 1=TRUE
//
// Assumption:
// input parameter not NULL
//
//----------------------------------------------------------------------
HRESULT DetectRegKeyValue( IXMLDOMNode* pRegKeyValueNode, BOOL *pfResult ) { LOG_Block("DetectRegKeyValue");
HRESULT hr = E_INVALIDARG; BOOL fRet = FALSE; LPTSTR lpszKey = NULL, lpszEntry = NULL, lpszValue = NULL; BSTR bstrKey = NULL, bstrEntry = NULL, bstrValue = NULL;
USES_IU_CONVERSION;
//
// find the key value
//
if (!FindNodeValue(pRegKeyValueNode, KEY_KEY, &bstrKey)) { LOG_ErrorMsg(hr); goto CleanUp; }
lpszKey = OLE2T(bstrKey); CleanUpFailedAllocSetHrMsg(lpszKey);
//
// find the optional entry value
//
if (FindNodeValue(pRegKeyValueNode, KEY_ENTRY, &bstrEntry)) { lpszEntry = OLE2T(bstrEntry); CleanUpFailedAllocSetHrMsg(lpszEntry); }
//
// find the value to compare
//
if (!FindNodeValue(pRegKeyValueNode, KEY_VALUE, &bstrValue)) { LOG_ErrorMsg(hr); goto CleanUp; }
lpszValue = OLE2T(bstrValue); CleanUpFailedAllocSetHrMsg(lpszValue);
*pfResult = RegKeyValueMatch((LPCTSTR)lpszKey, (LPCTSTR)lpszEntry, (LPCTSTR)lpszValue); hr = S_OK; CleanUp:
SysFreeString(bstrKey); SysFreeString(bstrEntry); SysFreeString(bstrValue);
return hr;
}
//----------------------------------------------------------------------
//
// Helper function DetectRegKeySubstring()
// retrieve the data from the node,
// and do actual detection work
//
// Input:
// RegKeyValue node
//
// Return:
// int - detection result: -1=none, 0=FALSE, 1=TRUE
//
// Assumption:
// input parameter not NULL
//
//----------------------------------------------------------------------
HRESULT DetectRegKeySubstring( IXMLDOMNode* pRegKeySubstringNode, BOOL *pfResult ) { LOG_Block("DetectRegKeySubstring");
HRESULT hr = E_INVALIDARG; BOOL fRet = FALSE; LPTSTR lpszKey = NULL, lpszEntry = NULL, lpszValue = NULL; BSTR bstrKey = NULL, bstrEntry = NULL, bstrValue = NULL;
USES_IU_CONVERSION;
//
// find the key value
//
if (!FindNodeValue(pRegKeySubstringNode, KEY_KEY, &bstrKey)) { LOG_ErrorMsg(hr); goto CleanUp; }
lpszKey = OLE2T(bstrKey); CleanUpFailedAllocSetHrMsg(lpszKey);
//
// find the optional entry value
//
if (FindNodeValue(pRegKeySubstringNode, KEY_ENTRY, &bstrEntry)) { lpszEntry = OLE2T(bstrEntry); CleanUpFailedAllocSetHrMsg(lpszEntry); }
//
// find the value to compare
//
if (!FindNodeValue(pRegKeySubstringNode, KEY_VALUE, &bstrValue)) { LOG_ErrorMsg(hr); goto CleanUp; }
lpszValue = OLE2T(bstrValue); CleanUpFailedAllocSetHrMsg(lpszValue);
*pfResult = RegKeySubstring((LPCTSTR)lpszKey, (LPCTSTR)lpszEntry, (LPCTSTR)lpszValue);
hr = S_OK;
CleanUp:
SysFreeString(bstrKey); SysFreeString(bstrEntry); SysFreeString(bstrValue);
return hr; }
//----------------------------------------------------------------------
//
// Helper function DetectFileVersion()
// retrieve the data from the node,
// and do actual detection work
//
// Input:
// RegKeyValue node
//
// Return:
// int - detection result: -1=none, 0=FALSE, 1=TRUE
//
// Assumption:
// input parameter not NULL
//
//----------------------------------------------------------------------
HRESULT DetectRegVersion( IXMLDOMNode* pRegKeyVersionNode, BOOL *pfResult ) { HRESULT hr = E_INVALIDARG; BOOL fRet = FALSE; LPTSTR lpszKey = NULL, lpszEntry = NULL, lpszVersion = NULL; BSTR bstrVerVerb = NULL, bstrKey = NULL, bstrEntry = NULL, bstrVersion = NULL;
_VER_STATUS verStatus;
LOG_Block("DetectRegVersion()");
USES_IU_CONVERSION;
//
// find the key value
//
if (!FindNodeValue(pRegKeyVersionNode, KEY_KEY, &bstrKey)) { LOG_ErrorMsg(hr); goto CleanUp; }
lpszKey = OLE2T(bstrKey); CleanUpFailedAllocSetHrMsg(lpszKey);
LOG_XML(_T("Found Key=%s"), lpszKey);
//
// find the optional entry value
//
if (FindNodeValue(pRegKeyVersionNode, KEY_ENTRY, &bstrEntry)) { lpszEntry = OLE2T(bstrEntry); CleanUpFailedAllocSetHrMsg(lpszEntry); LOG_XML(_T("Found optional entry=%s"), lpszEntry); }
//
// find the value to compare
//
if (!FindNodeValue(pRegKeyVersionNode, KEY_VERSION, &bstrVersion)) { goto CleanUp; }
lpszVersion = OLE2T(bstrVersion); CleanUpFailedAllocSetHrMsg(lpszVersion); LOG_XML(_T("Version found from node: %s"), lpszVersion);
//
// get the attribute versionStatus, a version compare verb
//
if (S_OK != (hr = GetAttribute(pRegKeyVersionNode, KEY_VERSIONSTATUS, &bstrVerVerb))) { LOG_ErrorMsg(hr); goto CleanUp; } LOG_XML(_T("Version verb found from node: %s"), OLE2T(bstrVerVerb));
//
// convert the versionStatus in bstr into enum
//
if (!ConvertBstrVersionToEnum(bstrVerVerb, &verStatus)) { SafeSysFreeString(bstrVerVerb); goto CleanUp; }
*pfResult = RegKeyVersion((LPCTSTR)lpszKey, (LPCTSTR)lpszEntry, (LPCTSTR)lpszVersion, verStatus);
hr = S_OK;
CleanUp:
SysFreeString(bstrKey); SysFreeString(bstrEntry); SysFreeString(bstrVersion); SysFreeString(bstrVerVerb); return hr; }
//----------------------------------------------------------------------
//
// Helper function DetectFileVersion()
// retrieve the data from the node,
// and do actual detection work
//
// Input:
// RegKeyValue node
//
// Return:
// int - detection result: -1=none, 0=FALSE, 1=TRUE
//
// Assumption:
// input parameter not NULL
//
//----------------------------------------------------------------------
HRESULT DetectFileVersion( IXMLDOMNode* pFileVersionNode, BOOL *pfResult ) { BOOL fRet = FALSE; BOOL fFileExists = FALSE; HRESULT hr = E_INVALIDARG; IXMLDOMNode* pFilePathNode = NULL; TCHAR szFilePath[MAX_PATH]; int iFileVerComp; LPTSTR lpszTimeStamp = NULL, lpszVersion = NULL; BSTR bstrTime = NULL, bstrVersion = NULL, bstrVerState= NULL;
FILE_VERSION fileVer; _VER_STATUS verStatus;
LOG_Block("DetectFileVersion()");
USES_IU_CONVERSION;
if (NULL == pfResult || NULL == pFileVersionNode) { LOG_ErrorMsg(hr); return hr; }
*pfResult = FALSE;
//
// find the version value
//
if (!FindNodeValue(pFileVersionNode, KEY_VERSION, &bstrVersion)) { LOG_ErrorMsg(hr); return hr; }
if (NULL == (lpszVersion = OLE2T(bstrVersion))) { LOG_ErrorMsg(E_OUTOFMEMORY); goto CleanUp; } LOG_XML(_T("Version=%s"), lpszVersion);
if (!ConvertStringVerToFileVer(T2A(lpszVersion), &fileVer)) { LOG_ErrorMsg(hr); goto CleanUp; // bad version string
}
//
// find the file path value
//
//if (!FindNodeValue(pFileVersionNode, KEY_FILEPATH, &bstrFile))
if (!FindNode(pFileVersionNode, KEY_FILEPATH, &pFilePathNode) || NULL == pFilePathNode || FAILED(hr = GetFullFilePathFromFilePathNode(pFilePathNode, szFilePath))) { LOG_ErrorMsg(hr); goto CleanUp; // no file path found!
}
LOG_XML(_T("File=%s"), szFilePath);
//
// check if file exist
//
fFileExists = FileExists(szFilePath);
//
// get the attribute versionStatus, a version compare verb
//
if (S_OK != GetAttribute(pFileVersionNode, KEY_VERSIONSTATUS, &bstrVerState)) { goto CleanUp; // no version status found
} LOG_XML(_T("VersionStatus=%s"), OLE2T(bstrVerState));
if (!ConvertBstrVersionToEnum(bstrVerState, &verStatus)) { //
// bad version enum, shouldn't happen since the manifest has
// been loaded into XMLDOM
//
LOG_ErrorMsg(hr); goto CleanUp; }
//
// get optional timestamp
//
if (S_OK == GetAttribute(pFileVersionNode, KEY_TIMESTAMP, &bstrTime)) { TCHAR szFileTimeStamp[20]; LPTSTR lpXmlTimeStamp = OLE2T(bstrTime); CleanUpFailedAllocSetHrMsg(lpXmlTimeStamp);
//
// find out the file creation time stamp
//
int iCompare; if (!fFileExists || !GetFileTimeStamp(szFilePath, szFileTimeStamp, 20)) { //szFileTimeStamp[0] = '\0'; // we don't have a timestamp to compare
//
// for timestamp compare, it's date/time ISO format compare, i.e.,
// in alphabetical order, so empty timestamp always smaller.
//
iCompare = -1; } else {
//
// compare file timestamp, if szFileTimeStamp < lpXmlTimeStamp, -1
//
int iCompVal = CompareString( MAKELCID(0x0409, SORT_DEFAULT), NORM_IGNORECASE, szFileTimeStamp, -1, lpXmlTimeStamp, -1); iCompare = (CSTR_EQUAL == iCompVal) ? 0 : ((CSTR_LESS_THAN == iCompVal) ? -1 : +1); }
switch (verStatus) { case DETX_LOWER: fRet = (iCompare < 0); break; case DETX_LOWER_OR_EQUAL: fRet = (iCompare <= 0); break; case DETX_SAME: fRet = (iCompare == 0); break; case DETX_HIGHER_OR_EQUAL: fRet = (iCompare >= 0); break; case DETX_HIGHER: fRet = (iCompare > 0); break; } *pfResult = fRet;
if (!fRet) { //
// false, not need to continue
//
hr = S_OK; goto CleanUp; } } //
// compare file version: if a < b, -1; a > b, +1
//
if (!fFileExists || (FAILED(CompareFileVersion((LPCTSTR)szFilePath, fileVer, &iFileVerComp)))) { //
// failed to compare version - file may doesn't have a version data.
// in this case, we assume the file need to compare have version 0,0,0,0, and force
// the comparision oontinue.
//
FILE_VERSION verNoneExists = {0,0,0,0}; iFileVerComp = CompareFileVersion(verNoneExists, fileVer); }
switch (verStatus) { case DETX_LOWER: fRet = (iFileVerComp < 0); break; case DETX_LOWER_OR_EQUAL: fRet = (iFileVerComp <= 0); break; case DETX_SAME: fRet = (iFileVerComp == 0); break; case DETX_HIGHER_OR_EQUAL: fRet = (iFileVerComp >= 0); break; case DETX_HIGHER: fRet = (iFileVerComp > 0); break; }
*pfResult = fRet;
hr = S_OK;
CleanUp: SysFreeString(bstrTime); SysFreeString(bstrVersion); SysFreeString(bstrVerState); SafeReleaseNULL(pFilePathNode); return hr; }
//----------------------------------------------------------------------
//
// Helper function DetectFileExists()
// retrieve the data from the node,
// and do actual detection work
//
// Input:
// RegKeyValue node
//
// Return:
// int - detection result: -1=none, 0=FALSE, 1=TRUE
//
// Assumption:
// input parameter not NULL
//
//----------------------------------------------------------------------
HRESULT DetectFileExists( IXMLDOMNode* pFileExistsNode, BOOL *pfResult ) { BOOL fRet = FALSE; HRESULT hr = E_INVALIDARG; TCHAR szFilePath[MAX_PATH]; IXMLDOMNode* pFilePathNode = NULL; _VER_STATUS verStatus;
USES_IU_CONVERSION;
LOG_Block("DetectFileExists()");
if (NULL == pFileExistsNode || NULL == pfResult) { return E_INVALIDARG; }
//
// find the version value
//
if (!FindNode(pFileExistsNode, KEY_FILEPATH, &pFilePathNode) || NULL == pFilePathNode || FAILED(hr = GetFullFilePathFromFilePathNode(pFilePathNode, szFilePath))) { LOG_ErrorMsg(hr); } else { *pfResult = FileExists((LPCTSTR)szFilePath); hr = S_OK; }
SafeReleaseNULL(pFilePathNode);
return hr; }
//----------------------------------------------------------------------
//
// Helper function DetectComputerSystem()
// retrieve the data from the node,
// and do actual detection work
//
// Input:
// computerSystem node
//
// Return:
// detection result TRUE/FALSE
//
// Assumption:
// input parameter not NULL
//
//----------------------------------------------------------------------
HRESULT DetectComputerSystem( IXMLDOMNode* pComputerSystemNode, BOOL *pfResult ) { HRESULT hr = E_INVALIDARG;
LOG_Block("DetectComputerSystem()");
BSTR bstrManufacturer = NULL; BSTR bstrModel = NULL; BSTR bstrSupportURL = NULL; BSTR bstrXmlManufacturer = NULL; BSTR bstrXmlModel = NULL;
if (NULL == pComputerSystemNode || NULL == pfResult) { LOG_ErrorMsg(hr); return hr; }
*pfResult = FALSE; // anything wrong, result should be FALSE and return error
//
// get manufecturer and model from XML node
//
hr = GetAttribute(pComputerSystemNode, KEY_MANUFACTURER, &bstrXmlManufacturer); CleanUpIfFailedAndMsg(hr);
//
// optional model
//
GetAttribute(pComputerSystemNode, KEY_MODEL, &bstrXmlModel); //
// find out real manufectuer and model of this machine
//
hr = GetOemBstrs(bstrManufacturer, bstrModel, bstrSupportURL); CleanUpIfFailedAndMsg(hr);
//
// compare to see if manufacturer and model match.
// mafufacturer match required. If no model provided in xml
// then no check on model performed.
//
// definition of match: both empty or bstr compare equal
// definition of empty: bstr NULL or string length zero
//
*pfResult = ( (((NULL == bstrXmlManufacturer || SysStringLen(bstrXmlManufacturer) == 0) && // xml data empty and
(NULL == bstrManufacturer || SysStringLen(bstrManufacturer) == 0)) || // machine manufecturer empty, or
CompareBSTRsEqual(bstrManufacturer, bstrXmlManufacturer)) && // manufacturer same as xml data, also,
((NULL == bstrXmlModel) || // xml data empty or
CompareBSTRsEqual(bstrModel, bstrXmlModel))); // model matches xml data
LOG_Out(_T("XML: %ls (%ls), Machine: %ls (%ls), Return: %hs"), (LPCWSTR)bstrManufacturer, (LPCWSTR)bstrModel, (LPCWSTR)bstrXmlManufacturer, (LPCWSTR)bstrXmlModel, ((*pfResult) ? "True" : "False"));
CleanUp:
SysFreeString(bstrManufacturer); SysFreeString(bstrModel); SysFreeString(bstrSupportURL); SysFreeString(bstrXmlManufacturer); SysFreeString(bstrXmlModel);
return hr; }
|