//======================================================================= // // 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 #include #include #include #include "SchemaKeys.h" #include "iucommon.h" // // include IDetection interface // #ifdef _MIDL_USE_GUIDDEF_ #ifndef INITGUID #define INITGUID #include #undef INITGUID #else #include #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 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 tag, to tell the detection result. This result // should overwrite the rest of , if any // extern const LONG IUDET_INSTALLED = 0x00000010; /* mask for result */ extern const LONG IUDET_INSTALLED_NULL = 0x00000020; /* missing */ extern const LONG IUDET_UPTODATE = 0x00000040; /* mask for result */ extern const LONG IUDET_UPTODATE_NULL = 0x00000080; /* missing */ extern const LONG IUDET_NEWERVERSION = 0x00000100; /* mask for result */ extern const LONG IUDET_NEWERVERSION_NULL = 0x00000200; /* missing */ extern const LONG IUDET_EXCLUDED = 0x00000400; /* mask for result */ extern const LONG IUDET_EXCLUDED_NULL = 0x00000800; /* missing */ extern const LONG IUDET_FORCE = 0x00001000; /* mask for result */ extern const LONG IUDET_FORCE_NULL = 0x00002000; /* missing */ extern const LONG IUDET_COMPUTER = 0x00004000; // mask for result extern const LONG IUDET_COMPUTER_NULL = 0x00008000; // 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; }