Leaked source code of windows server 2003
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.
 
 
 
 
 
 

584 lines
16 KiB

// ---------------------------------------------------------------------------
// DETECT.CPP
// ---------------------------------------------------------------------------
// Copyright (c) 1999 Microsoft Corporation
//
// Helper functions to detect installed versions of WAB / OE
//
// ---------------------------------------------------------------------------
#include "pch.hxx"
#include <strings.h>
#include "main.h"
#include "detect.h"
const LPCTSTR c_szVers[] = { c_szVERnone, c_szVER1_0, c_szVER1_1, c_szVER4_0, c_szVER5B1 };
const LPCTSTR c_szBlds[] = { c_szBLDnone, c_szBLD1_0, c_szBLD1_1, c_szBLD4_0, c_szBLD5B1 };
#define FORCE_DEL(_sz) { \
if ((dwAttr = GetFileAttributes(_sz)) != 0xFFFFFFFF) \
{ \
SetFileAttributes(_sz, dwAttr & ~FILE_ATTRIBUTE_READONLY); \
DeleteFile(_sz); \
} }
/*******************************************************************
NAME: TranslateVers
SYNOPSIS: Takes 5.0B1 versions and translates to bld numbers
********************************************************************/
BOOL TranslateVers(OUT SETUPVER *psv,
OUT LPTSTR pszVer,
IN int cch)
{
BOOL fTranslated = FALSE;
// Validate params
Assert(pszVer);
// Initialize out params
*psv = VER_NONE;
// Special case builds 624-702
if (!lstrcmp(pszVer, c_szVER5B1old))
{
StrCpyN(pszVer, c_szBlds[VER_5_0_B1], cch);
*psv = VER_5_0_B1;
fTranslated = TRUE;
}
else
{
for (int i = VER_NONE; i < VER_5_0; i++)
{
if (!lstrcmp(c_szVers[i], pszVer))
{
StrCpyN(pszVer, c_szBlds[i], cch);
*psv = (SETUPVER)i;
fTranslated = TRUE;
break;
}
}
}
return fTranslated;
}
/*******************************************************************
NAME: ConvertStrToVer
********************************************************************/
void ConvertStrToVer(IN LPCSTR pszStr,
OUT WORD *pwVer)
{
int i;
// Validate Params
Assert(pszStr);
Assert(pwVer);
// Initialize out param
ZeroMemory(pwVer, 4 * sizeof(*pwVer));
for (i=0; i<4; i++)
{
while (*pszStr && (*pszStr != ',') && (*pszStr != '.'))
{
pwVer[i] *= 10;
pwVer[i] = (WORD)(pwVer[i] + (*pszStr - '0'));
pszStr++;
}
if (*pszStr)
pszStr++;
}
return;
}
/*******************************************************************
NAME: ConvertVerToEnum
********************************************************************/
SETUPVER ConvertVerToEnum(IN WORD *pwVer)
{
SETUPVER sv;
// Validate params
Assert(pwVer);
switch (pwVer[0])
{
case 0:
sv = VER_NONE;
break;
case 1:
if (0 == pwVer[1])
sv = VER_1_0;
else
sv = VER_1_1;
break;
case 4:
sv = VER_4_0;
break;
case 5:
sv = VER_5_0;
break;
default:
sv = VER_MAX;
}
return sv;
}
/*******************************************************************
NAME: GetASetupVer
********************************************************************/
BOOL GetASetupVer(IN LPCTSTR pszGUID,
OUT WORD *pwVer, // OPTIONAL
OUT LPTSTR pszVer, // OPTIONAL
IN int cch) // OPTIONAL
{
BOOL fInstalled = FALSE;
DWORD dwValue, cb;
HKEY hkey;
TCHAR szPath[MAX_PATH], szVer[64];
// Validate Params
Assert(pszGUID);
// Initialize out params
if (pszVer)
pszVer[0] = 0;
if (pwVer)
ZeroMemory(pwVer, 4 * sizeof(*pwVer));
wnsprintf(szPath, ARRAYSIZE(szPath), c_szPathFileFmt, c_szRegASetup, pszGUID);
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, szPath, 0, KEY_QUERY_VALUE, &hkey))
{
cb = sizeof(dwValue);
if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szIsInstalled, 0, NULL, (LPBYTE)&dwValue, &cb))
{
if (1 == dwValue)
{
cb = sizeof(szVer);
if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szValueVersion, 0, NULL, (LPBYTE)szVer, &cb))
{
if (pwVer)
ConvertStrToVer(szVer, pwVer);
if (pszVer)
StrCpyN(pszVer, szVer, cch);
fInstalled = TRUE;
}
}
}
RegCloseKey(hkey);
}
return fInstalled;
}
/*******************************************************************
NAME: GetExePath
********************************************************************/
BOOL GetExePath(IN LPCTSTR szExe,
OUT TCHAR *szPath,
IN DWORD cch,
IN BOOL fDirOnly)
{
BOOL fRet = FALSE;
HKEY hkey;
DWORD dwType, cb;
TCHAR sz[MAX_PATH], szT[MAX_PATH];
// Validate params
Assert(szExe != NULL);
Assert(szPath != NULL);
Assert(cch);
wnsprintf(sz, ARRAYSIZE(sz), c_szPathFileFmt, c_szAppPaths, szExe);
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, sz, 0, KEY_QUERY_VALUE, &hkey))
{
cb = sizeof(szT);
if (ERROR_SUCCESS == RegQueryValueEx(hkey, fDirOnly ? c_szRegPath : NULL, 0, &dwType, (LPBYTE)szT, &cb) && cb)
{
if (REG_EXPAND_SZ == dwType)
{
cb = ExpandEnvironmentStrings(szT, szPath, cch);
if (cb != 0 && cb <= cch)
fRet = TRUE;
}
else
{
Assert(REG_SZ == dwType);
StrCpyN(szPath, szT, cch);
fRet = TRUE;
}
}
RegCloseKey(hkey);
}
return(fRet);
}
/*******************************************************************
NAME: GetFileVer
********************************************************************/
HRESULT GetFileVer(IN LPCTSTR pszExePath,
OUT LPTSTR pszVer,
IN DWORD cch)
{
DWORD dwVerInfoSize, dwVerHnd;
HRESULT hr = S_OK;
LPSTR pszInfo = NULL;
LPSTR pszVersion;
LPWORD pwTrans;
TCHAR szGet[MAX_PATH];
UINT uLen;
// Validate Parameters
Assert(pszExePath);
Assert(pszVer);
Assert(cch);
// Initialize out parameters
pszVer[0] = TEXT('\0');
// Allocate space for version info block
if (0 == (dwVerInfoSize = GetFileVersionInfoSize(const_cast<LPTSTR> (pszExePath), &dwVerHnd)))
{
hr = E_FAIL;
TraceResult(hr);
goto exit;
}
IF_NULLEXIT(pszInfo = (LPTSTR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwVerInfoSize));
// Get Version info block
IF_FALSEEXIT(GetFileVersionInfo(const_cast<LPTSTR> (pszExePath), dwVerHnd, dwVerInfoSize, pszInfo), E_FAIL);
// Figure out language for version info
IF_FALSEEXIT(VerQueryValue(pszInfo, "\\VarFileInfo\\Translation", (LPVOID *)&pwTrans, &uLen) && uLen >= (2 * sizeof(WORD)), E_FAIL);
// Set up buffer with correct language and get version
wnsprintf(szGet, ARRAYSIZE(szGet), "\\StringFileInfo\\%04X%04X\\FileVersion", pwTrans[0], pwTrans[1]);
IF_FALSEEXIT(VerQueryValue(pszInfo, szGet, (LPVOID *)&pszVersion, &uLen) && uLen, E_FAIL);
// Copy version out of version block, into out param
Assert(pszVersion);
StrCpyN(pszVer, pszVersion, cch);
exit:
if (pszInfo)
GlobalFree((HGLOBAL)pszInfo);
return hr;
}
/*******************************************************************
NAME: GetExeVer
********************************************************************/
HRESULT GetExeVer(IN LPCTSTR pszExeName,
OUT WORD *pwVer, // OPTIONAL
OUT LPTSTR pszVer, // OPTIONAL
IN int cch) // OPTIONAL
{
HRESULT hr = S_OK;
TCHAR szPath[MAX_PATH];
TCHAR szVer[64];
// Validate params
Assert(pszExeName);
// Initialize out params
if (pszVer)
{
Assert(cch);
pszVer[0] = 0;
}
if (pwVer)
// Version is an array of 4 words
ZeroMemory(pwVer, 4 * sizeof(*pwVer));
// Find the exe
IF_FALSEEXIT(GetExePath(pszExeName, szPath, ARRAYSIZE(szPath), FALSE), E_FAIL);
// Get the string representation of the version
IF_FAILEXIT(hr = GetFileVer(szPath, szVer, ARRAYSIZE(szVer)));
// Fill in out params
if (pwVer)
ConvertStrToVer(szVer, pwVer);
if (pszVer)
StrCpyN(pszVer, szVer, cch);
exit:
return hr;
}
/*******************************************************************
NAME: DetectPrevVer
SYNOPSIS: Called when there is no ver info for current app
********************************************************************/
SETUPVER DetectPrevVer(IN SETUPAPP saApp,
OUT LPTSTR pszVer,
IN int cch)
{
DWORD dwAttr;
SETUPVER sv;
TCHAR szVer[VERLEN] = {0};
TCHAR szFile[MAX_PATH];
TCHAR szFile2[MAX_PATH];
UINT uLen, uLen2;
WORD wVer[4];
// Validate params
Assert(pszVer);
uLen = GetSystemDirectory(szFile, ARRAYSIZE(szFile));
if ('\\' != *CharPrev(szFile, szFile + uLen))
szFile[uLen++] = '\\';
switch (saApp)
{
case APP_OE:
StrCpyN(&szFile[uLen], c_szMAILNEWS, ARRAYSIZE(szFile) - uLen);
// See what version we've told IE Setup, is installed
// Or what version msimn.exe is (to cover the case in which the
// ASetup info has been damaged - OE 5.01 80772)
if (GetASetupVer(c_szOEGUID, wVer, szVer, ARRAYSIZE(szVer)) ||
SUCCEEDED(GetExeVer(c_szOldMainExe, wVer, szVer, ARRAYSIZE(szVer))))
sv = ConvertVerToEnum(wVer);
else
{
// 1.0 or none
// Does mailnews.dll exist?
if(0xFFFFFFFF == GetFileAttributes(szFile))
sv = VER_NONE;
else
sv = VER_1_0;
}
// If active setup, these will be rollably deleted
FORCE_DEL(szFile);
break;
case APP_WAB:
StrCpyN(&szFile[uLen], c_szWAB32, ARRAYSIZE(szFile) - uLen);
uLen2 = GetWindowsDirectory(szFile2, ARRAYSIZE(szFile2));
if ('\\' != *CharPrev(szFile2, szFile2 + uLen2))
szFile2[uLen2++] = '\\';
StrCpyN(&szFile2[uLen2], c_szWABEXE, ARRAYSIZE(szFile2) - uLen2);
if (GetASetupVer(c_szWABGUID, wVer, szVer, ARRAYSIZE(szVer)))
{
// 5.0 or later
if (5 == wVer[0])
sv = VER_5_0;
else
sv = VER_MAX;
}
else if (GetASetupVer(c_szOEGUID, wVer, szVer, ARRAYSIZE(szVer)) ||
SUCCEEDED(GetExeVer(c_szOldMainExe, wVer, szVer, ARRAYSIZE(szVer))))
{
// 4.0x or 5.0 Beta 1
if (5 == wVer[0])
sv = VER_5_0_B1;
else if (4 == wVer[0])
sv = VER_4_0;
else
sv = VER_MAX;
}
else
{
// 1.0, 1.1 or none
// WAB32.dll around?
if(0xFFFFFFFF == GetFileAttributes(szFile))
sv = VER_NONE;
else
{
// \Windows\Wab.exe around?
if(0xFFFFFFFF == GetFileAttributes(szFile2))
sv = VER_1_0;
else
sv = VER_1_1;
}
}
// If active setup, these will be rollably deleted
FORCE_DEL(szFile);
FORCE_DEL(szFile2);
break;
default:
sv = VER_NONE;
}
// Figure out the build number for this ver
if (szVer[0])
// Use real ver
StrCpyN(pszVer, szVer, cch);
else
// Fake Ver
StrCpyN(pszVer, c_szBlds[sv], cch);
return sv;
}
/*******************************************************************
NAME: LookForApp
********************************************************************/
BOOL LookForApp(IN SETUPAPP saApp,
OUT LPTSTR pszVer,
IN int cch,
OUT SETUPVER svInterimVer)
{
BOOL fReg = FALSE;
DWORD cb;
HKEY hkey;
LPCTSTR pszVerInfo;
SETUPVER svCurr = VER_MAX, svPrev = VER_MAX;
TCHAR szCurrVer[VERLEN]={0};
TCHAR szPrevVer[VERLEN]={0};
LPTSTR psz = szCurrVer;
WORD wVer[4];
// Validate Params
Assert(pszVer);
Assert(cch);
// Initialize out params
svInterimVer = VER_NONE;
*pszVer = TEXT('\0');
switch (saApp)
{
case APP_OE:
pszVerInfo = c_szRegVerInfo;
break;
case APP_WAB:
pszVerInfo = c_szRegWABVerInfo;
break;
default:
// Should never happen
AssertFalseSz("Looking up an unknown app?");
goto exit;
}
// Always try to use the version info
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszVerInfo, 0, KEY_QUERY_VALUE, &hkey))
{
cb = sizeof(szPrevVer);
RegQueryValueEx(hkey, c_szRegPrevVer, NULL, NULL, (LPBYTE)szPrevVer, &cb);
// Change to a bld # if needed
if (!TranslateVers(&svPrev, szPrevVer, ARRAYSIZE(szPrevVer)))
{
// Convert bld to enum
ConvertStrToVer(szPrevVer, wVer);
svPrev = ConvertVerToEnum(wVer);
}
// If version info shows that a ver info aware version was uninstalled, throw out the info
// and redetect
if (VER_NONE == svPrev)
// Sniff the machine for current version
svCurr = DetectPrevVer(saApp, szCurrVer, ARRAYSIZE(szCurrVer));
else
{
// There was previous version reg goo - and it's legit
fReg = TRUE;
cb = sizeof(szCurrVer);
RegQueryValueEx(hkey, c_szRegCurrVer, NULL, NULL, (LPBYTE)szCurrVer, &cb);
// Change to a bld # if needed
if (!TranslateVers(&svCurr, szCurrVer, ARRAYSIZE(szCurrVer)))
{
// Convert bld to enum
ConvertStrToVer(szCurrVer, wVer);
svCurr = ConvertVerToEnum(wVer);
}
}
RegCloseKey(hkey);
}
else
{
// Sniff the machine for current version
svCurr = DetectPrevVer(saApp, szCurrVer, ARRAYSIZE(szCurrVer));
}
// Should we change the previous version entry?
if (VER_5_0 != svCurr)
{
// Know this is B1 OE if we translated
// Know this is B1 WAB if we detected it
if (VER_5_0_B1 == svCurr)
{
svInterimVer = svCurr;
// Did we read a previous value?
if (fReg)
// As there were reg entries, just translate the previous entry
psz = szPrevVer;
else
{
// We don't have a bld number and yet we are B1, better be the WAB
Assert(APP_WAB == saApp);
// Peek at OE's ver info
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegVerInfo, 0, KEY_QUERY_VALUE, &hkey))
{
cb = sizeof(szPrevVer);
// Read a build or a string
RegQueryValueExA(hkey, c_szRegPrevVer, NULL, NULL, (LPBYTE)szPrevVer, &cb);
// If it's a string, convert it to a build
TranslateVers(&svPrev, szPrevVer, ARRAYSIZE(szPrevVer));
// We'll use the build (translated or direct)
psz = szPrevVer;
RegCloseKey(hkey);
}
}
}
// Fill in out param
StrCpyN(pszVer, psz, cch);
}
exit:
return (VER_NONE != svCurr);
}