windows-nt/Source/XPSP1/NT/admin/pchealth/helpctr/hcdetect/hcdetect.cpp
2020-09-26 16:20:57 +08:00

298 lines
8.5 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// HCDetect.cpp
//
// Copyright (C) Microsoft Corp. 1999
// All rights reserved
//
/////////////////////////////////////////////////////////////////////////////
//
// Description:
// DLL loaded by the install engine that exposes entry points
// that can determines the installation status of legacy or complex
// components. The dll name and entry points are specified for a
// component in the CIF file.
/////////////////////////////////////////////////////////////////////////////
#include <atlbase.h>
#include "hcdetect.h"
#include <initguid.h>
//
// From HelpServiceTypeLib.idl
//
#include <HelpServiceTypeLib.h>
#include <HelpServiceTypeLib_i.c>
//
// Defines
//
#define IsDigit(c) ((c) >= '0' && (c) <= '9')
#define MAX_ID 1024
/////////////////////////////////////////////////////////////////////////////
HRESULT getVersion( BSTR bstrVendorID ,
BSTR bstrProductID ,
CComBSTR& bstrValue )
{
TCHAR szWinDir[MAX_PATH];
CComVariant cvVersionPathname;
CComPtr <IXMLDOMDocument> pXMLDoc;
CComPtr <IXMLDOMElement> pXMLRootElem;
CComPtr <IXMLDOMNode> pXMLVersionNode;
//
// get windows directory
//
if(::GetWindowsDirectory( szWinDir, MAX_PATH ) == 0)
{
return E_FAIL;
}
_tcscat( szWinDir, "\\pchealth\\helpctr\\config\\pchver.xml" );
if(SUCCEEDED(::CoCreateInstance( CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument, (void**)&pXMLDoc )))
{
CComVariant cvVersionPathname = szWinDir;
VARIANT_BOOL vBool;
if(SUCCEEDED(pXMLDoc->load( cvVersionPathname, &vBool )) && vBool == VARIANT_TRUE)
{
if(SUCCEEDED(pXMLDoc->get_documentElement( &pXMLRootElem )) && pXMLRootElem)
{
CComBSTR bstrQuery;
bstrQuery.Append( "VENDORS/VENDOR[@ID=\"" );
bstrQuery.Append( bstrVendorID );
bstrQuery.Append( "\"]/PRODUCT[@ID=\"" );
bstrQuery.Append( bstrProductID );
bstrQuery.Append( "\"]/VERSION" );
if(SUCCEEDED(pXMLRootElem->selectSingleNode( bstrQuery, &pXMLVersionNode )))
{
CComQIPtr<IXMLDOMElement> elem = pXMLVersionNode;
CComVariant vValue;
if(elem && SUCCEEDED(elem->getAttribute( CComBSTR("VALUE"), &vValue )))
{
vValue.ChangeType( VT_BSTR );
bstrValue = vValue.bstrVal;
return S_OK;
}
}
}
}
}
return E_FAIL;
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// fCompareVersion
//
// Returns: 1,0,-1 depending on whether dwVersion1 is greater than, equal, or
// less than dwVersion2.
/////////////////////////////////////////////////////////////////////////////
inline int nCompareVersion(IN DWORD dwVer1,
IN DWORD dwBuild1,
IN DWORD dwVer2,
IN DWORD dwBuild2)
{
int nResult = 0;
if ( dwVer1 > dwVer2 )
{
nResult = 1;
}
else if ( dwVer1 < dwVer2 )
{
nResult = -1;
}
else if ( dwBuild1 > dwBuild2 ) // dwVer1 == dwVer2
{
nResult = 1;
}
else if ( dwBuild1 < dwBuild2 ) // dwVer1 == dwVer2
{
nResult = -1;
}
return nResult;
}
/////////////////////////////////////////////////////////////////////////////
// ConvertDotVersionStrToDwords
/////////////////////////////////////////////////////////////////////////////
bool fConvertDotVersionStrToDwords(LPSTR pszVer, LPDWORD pdwVer, LPDWORD pdwBuild)
{
DWORD grVerFields[4] = {0,0,0,0};
char *pch = pszVer;
if (!pszVer || !pdwVer || !pdwBuild)
return false;
grVerFields[0] = atol(pch);
for ( int index = 1; index < 4; index++ )
{
while ( IsDigit(*pch) && (*pch != '\0') )
pch++;
if ( *pch == '\0' )
break;
pch++;
grVerFields[index] = atol(pch);
}
*pdwVer = (grVerFields[0] << 16) + grVerFields[1];
*pdwBuild = (grVerFields[2] << 16) + grVerFields[3];
return true;
}
/////////////////////////////////////////////////////////////////////////////
// GetCifEntry
// Get an entry from the CIF file.
//
// Comments :
// We get the value differently depending on whether we are being
// called by IE 4 or IE 5 Active Setup.
/////////////////////////////////////////////////////////////////////////////
inline bool FGetCifEntry(DETECTION_STRUCT *pDetection,
char *pszParamName,
char *pszParamValue,
DWORD cbParamValue)
{
return (ERROR_SUCCESS == pDetection->pCifComp->GetCustomData(pszParamName,
pszParamValue,
cbParamValue));
}
/////////////////////////////////////////////////////////////////////////////
// RegKeyExists (EXPORT)
// This API will determine if an application exists based on the
// existence of a registry key and perhaps a value.
//
// Parameters:
//
// Comments :
/////////////////////////////////////////////////////////////////////////////
DWORD WINAPI HelpPkgVersion(DETECTION_STRUCT *pDetection)
{
USES_CONVERSION;
HRESULT hr;
DWORD dwInstallStatus = DET_INSTALLED;
TCHAR szVendorID[MAX_ID];
TCHAR szProductID[MAX_ID];
TCHAR szVersion[MAX_PATH];
IPCHUpdate *pPCHUpdate = NULL;
//
// Initialize COM just in case
//
::CoInitialize(NULL);
//
// make sure the struct is of the expected size
//
if ((pDetection->dwSize >= sizeof(DETECTION_STRUCT)))
{
CComBSTR bstrLatestVersion;
DWORD dwCurrVersion, dwCurrBuild;
DWORD dwLatestVersion, dwLatestBuild;
//
// get the version number from the components section of the CIF file.
//
if (!((FGetCifEntry(pDetection, "VendorID", szVendorID, sizeof(szVendorID))) &&
(FGetCifEntry(pDetection, "ProductID", szProductID, sizeof(szProductID))) &&
(FGetCifEntry(pDetection, "Version", szVersion, sizeof(szVersion)))))
{
goto end;
}
//
// Convert it to build and version number
//
fConvertDotVersionStrToDwords(szVersion, &dwCurrVersion, &dwCurrBuild);
// //
// // create the IPCHUpdate object
// //
// if (FAILED(hr = CoCreateInstance(CLSID_PCHUpdate, NULL, CLSCTX_LOCAL_SERVER, IID_IPCHUpdate, (void**)&pPCHUpdate)))
// {
// goto end;
// }
//
// //
// // call to get the version number
// //
// if (FAILED(pPCHUpdate->LatestVersion(CComBSTR(szVendorID), CComBSTR(szProductID), &bstrLatestVersion)))
// {
// goto end;
// }
if(FAILED(getVersion( CComBSTR( szVendorID ), CComBSTR( szProductID ), bstrLatestVersion )))
{
dwInstallStatus = DET_NOTINSTALLED;
goto end;
}
//
// check if there is a version number, if not, return as not installed
//
if (bstrLatestVersion.Length() == 0)
{
dwInstallStatus = DET_NOTINSTALLED;
goto end;
}
//
// Convert it to build and version number
//
fConvertDotVersionStrToDwords(OLE2A(bstrLatestVersion), &dwLatestVersion, &dwLatestBuild);
//
// Compare versions, recommend that it is not installed only if current version
// is greater than latest version installed on the client machine
//
if (nCompareVersion(dwCurrVersion, dwCurrBuild, dwLatestVersion, dwLatestBuild) == 1)
{
dwInstallStatus = DET_NOTINSTALLED;
}
}
end:
//
// Cleanup
//
if (pPCHUpdate)
pPCHUpdate->Release();
::CoUninitialize();
return dwInstallStatus;
}
//DWORD WINAPI Test()
//{
// CComBSTR bstrVendorID = "CN=Microsoft Corporation,L=Redmond,S=Washington,C=US";
// CComBSTR bstrProductID = "Microsoft Core Help Center Content";
// CComBSTR bstrValue;
// HRESULT hr;
//
// ::CoInitialize(NULL);
//
// hr = getVersion( bstrVendorID, bstrProductID, bstrValue );
//
// ::CoUninitialize();
//
// return hr;
//}