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.
 
 
 
 
 
 

1892 lines
54 KiB

// ===========================================================================
// File: JIT.CXX
// The Just In Time setup of IE addon components
//
#include <cdlpch.h>
#include <mshtmhst.h>
#include <shlwapi.h>
#include <shlwapip.h>
#include <commctrl.h>
#include <shfusion.h>
#include <inseng.h>
#include "webjit.h"
#include "webjitres.h"
#include "mluisupp.h"
#include "shellapi.h"
#define IDD_JAVAVMJITDIALOG 20001
#define IDC_NOMOREDIALOG 20002
#define IDC_MOREINFO 20003
#define IDC_STATIC -1
#define IDS_JAVAVMFAQURL 20005
const CLSID CLSID_AppletOCX = { 0x08B0e5c0, 0x4FCB, 0x11CF, 0xAA, 0xA5, 0x00, 0x40, 0x1C, 0x60, 0x85, 0x01 };
const char *g_pszCLSID_AppletOCX = "{08B0e5c0-4FCB-11CF-AAA5-00401C608501}";
const WCHAR *g_pwszCLSID_AppletOCX = L"{08B0e5c0-4FCB-11CF-AAA5-00401C608501}";
#ifdef UNIX
#include <unixfile.h>
#endif /* UNIX */
extern HINSTANCE g_hInst;
HRESULT
GetComponentIDFromIEFeature(LPCSTR pszIEFeature, LPSTR *ppszComponentID)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"GetComponentIDFromIEFeature",
"%.80q, %#x",
pszIEFeature, ppszComponentID
));
HRESULT hr = S_OK;
HKEY hkeyFeatureComponentID =0;
DWORD lResult;
char szComponentID[MAX_PATH];
DWORD dwSize = MAX_PATH;
DWORD dwType;
*ppszComponentID = NULL;
if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
REGKEY_ACTIVESETUP_FEATURECOMPID, 0, KEY_READ,
&hkeyFeatureComponentID)) != ERROR_SUCCESS) {
hr = HRESULT_FROM_WIN32(lResult);
goto Exit;
}
szComponentID[0] = '\0';
if (SHQueryValueEx(hkeyFeatureComponentID, pszIEFeature, NULL, &dwType,
(unsigned char *)szComponentID, &dwSize) == ERROR_SUCCESS) {
*ppszComponentID = new char [dwSize+1];
if (*ppszComponentID == NULL) {
hr = E_OUTOFMEMORY;
goto Exit;
}
lstrcpy(*ppszComponentID, szComponentID);
// FALLTHROUGH to exit
} else {
hr = E_UNEXPECTED;
// FALLTHROUGH to exit
}
Exit:
if (hkeyFeatureComponentID)
::RegCloseKey(hkeyFeatureComponentID);
DEBUG_LEAVE(hr);
return hr;
}
HRESULT GetComponentIDFromCLSSPEC(uCLSSPEC *pClassspec, LPSTR * ppszComponentID)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"GetComponentIDFromCLSSPEC",
"%#x, %#x",
pClassspec, ppszComponentID
));
HRESULT hr = S_OK;
*ppszComponentID = NULL;
LPWSTR pwszIEFeature = NULL;
LPSTR pszIEFeature = NULL;
LPCWSTR pwszMimeType = NULL;
CLSID inclsid = CLSID_NULL;
QUERYCONTEXT qcInternal;
memset(&qcInternal, 0, sizeof(QUERYCONTEXT));
BOOL bUnknown = FALSE;
int iRes = 0;
int length = 0;
switch(pClassspec->tyspec)
{
case TYSPEC_PROGID:
// BUGBUG: we don't have JIT tables for progid to feature id
// so this will only work for PEEK for installed versions
if (FAILED((hr=CLSIDFromProgID(pClassspec->tagged_union.pProgId,
&inclsid))))
goto Exit;
hr = GetIEFeatureFromClass(&pwszIEFeature, inclsid, &qcInternal);
if (hr != S_OK)
goto Exit;
break;
case TYSPEC_CLSID:
inclsid = pClassspec->tagged_union.clsid;
hr = GetIEFeatureFromClass(&pwszIEFeature, inclsid, &qcInternal);
if (hr != S_OK)
goto Exit;
break;
case TYSPEC_MIMETYPE:
pwszMimeType = (LPCWSTR) pClassspec->tagged_union.pMimeType;
hr = GetIEFeatureFromMime(&pwszIEFeature, pwszMimeType, &qcInternal);
if (hr != S_OK)
goto Exit;
break;
case TYSPEC_FILENAME:
// overload filename to be Active Setup feature ID
hr = CDLDupWStr( &pwszIEFeature, pClassspec->tagged_union.pFileName);
if (hr != S_OK)
goto Exit;
break;
default:
hr = E_INVALIDARG;
goto Exit;
}
if(pwszIEFeature == NULL)
{
hr = E_UNEXPECTED;
goto Exit;
}
// Change the wide character IEFeature to a multibyte string
length = lstrlenW(pwszIEFeature) + 1;
pszIEFeature = new CHAR[length];
if(pszIEFeature == NULL)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
bUnknown = FALSE;
iRes = WideCharToMultiByte(CP_ACP, 0, pwszIEFeature,length,
pszIEFeature, length,NULL,&bUnknown);
// unknown multibyte character
if(bUnknown == TRUE)
{
hr = E_INVALIDARG;
goto Exit;
}
// failed for other reason
if(iRes == 0)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}
// Get a ComponentID from the FeatureID
hr = GetComponentIDFromIEFeature(pszIEFeature, ppszComponentID);
if(FAILED(hr))
{
goto Exit;
}
hr = S_OK;
Exit:
SAFEDELETE(pszIEFeature);
SAFEDELETE(pwszIEFeature);
DEBUG_LEAVE(hr);
return hr;
}
#define FEATURE_VERSION_SEPARATOR ';'
#define ALT_FEATURE_VERSION_SEPARATOR '!'
// if the IE Feature for this mime/clsid has an IE recommended version
// then modify the querycontext to reflect this as if the caller wanted this
// version. If the caller already has specifies a version that overrides
// the recommnedation.
// format: featurename;a,b,c,d
HRESULT
ParseIEFeature(LPSTR pszIEFeatureWithVersion,
QUERYCONTEXT *pQuery,
LPWSTR *ppwszIEFeature,
QUERYCONTEXT *pQueryRec)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"ParseIEFeature",
"%.80q, %#x, %#x, %#x",
pszIEFeatureWithVersion, pQuery, ppwszIEFeature, pQueryRec
));
HRESULT hr = S_OK;
DWORD dwIERecommendedVersionHi = 0;
DWORD dwIERecommendedVersionLo = 0;
LPSTR pchVersion = StrChr(pszIEFeatureWithVersion, FEATURE_VERSION_SEPARATOR);
if (!pchVersion)
{
pchVersion = StrChr(pszIEFeatureWithVersion, ALT_FEATURE_VERSION_SEPARATOR);
}
if (pchVersion)
{
*pchVersion = '\0'; // stomp version separator so
// pszIEFetaureWithVersion has just the feature name
pchVersion++;
if (*pchVersion
&& ((!(pQuery->dwVersionHi|pQuery->dwVersionLo))
|| pQueryRec))
{
// now pointing at version string
// of format a,b,c,d
hr = GetVersionFromString(pchVersion,
&dwIERecommendedVersionHi, &dwIERecommendedVersionLo);
if ( SUCCEEDED(hr))
{
if (!(pQuery->dwVersionHi|pQuery->dwVersionLo))
{
pQuery->dwVersionHi = dwIERecommendedVersionHi;
pQuery->dwVersionLo = dwIERecommendedVersionLo;
}
if (pQueryRec)
{
pQueryRec->dwVersionHi = dwIERecommendedVersionHi;
pQueryRec->dwVersionLo = dwIERecommendedVersionLo;
}
}
else if (pQuery->dwVersionHi|pQuery->dwVersionLo)
{
hr = S_OK; //don't introduce new error codes into path if query already has version (COMPAT)
}
}
}
if ( SUCCEEDED(hr) && ppwszIEFeature)
hr=Ansi2Unicode(pszIEFeatureWithVersion, ppwszIEFeature);
DEBUG_LEAVE(hr);
return hr;
}
HRESULT
GetIEFeatureFromMime(LPWSTR *ppwszIEFeature, LPCWSTR pwszMimeType, QUERYCONTEXT *pQuery, QUERYCONTEXT* pQueryRec)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"GetIEFeatureFromMime",
"%#x, %.80wq, %#x, %#x",
ppwszIEFeature, pwszMimeType, pQuery, pQueryRec
));
HRESULT hr = S_OK;
HKEY hkeyMimeFeature =0;
LPSTR pszMime = NULL;
DWORD lResult;
char szFeature[MAX_PATH];
DWORD dwSize = MAX_PATH;
DWORD dwType;
if (FAILED((hr=::Unicode2Ansi(pwszMimeType, &pszMime))))
{
goto Exit;
}
if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
REGKEY_ACTIVESETUP_MIMEFEATURE, 0, KEY_READ,
&hkeyMimeFeature)) != ERROR_SUCCESS)
{
#if JIT_IN_BUILD
hr = HRESULT_FROM_WIN32(lResult);
#else
hr = S_FALSE;
#endif
goto Exit;
}
szFeature[0] = '\0';
if (SHQueryValueEx(hkeyMimeFeature, pszMime, NULL, &dwType,
(unsigned char *)szFeature, &dwSize) == ERROR_SUCCESS)
{
if (dwSize > MAX_PATH)
{
// limit the feature name to MAX_PATH as buffer overrun protection
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
goto Exit;
}
hr = ParseIEFeature(szFeature, pQuery, ppwszIEFeature, pQueryRec);
// FALLTHROUGH to exit
}
else
{
hr = S_FALSE;
// FALLTHROUGH to exit
}
Exit:
if (hkeyMimeFeature)
::RegCloseKey(hkeyMimeFeature);
delete[] pszMime;
DEBUG_LEAVE(hr);
return hr;
}
HRESULT
GetIEFeatureFromClass(LPWSTR *ppwszIEFeature, REFCLSID clsid, QUERYCONTEXT *pQuery, QUERYCONTEXT *pQueryRec)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"GetIEFeatureFromClass",
"%#x, %#x, %#x",
ppwszIEFeature, &clsid, pQuery, pQueryRec
));
HRESULT hr = S_OK;
LPOLESTR pwcsClsid = NULL;
LPSTR pszClsid = NULL;
HKEY hkeyClsidFeature =0;
DWORD lResult;
char szFeature[MAX_PATH];
DWORD dwSize = MAX_PATH;
DWORD dwType;
// return if we can't get a valid string representation of the CLSID
if (FAILED((hr=StringFromCLSID(clsid, &pwcsClsid))))
goto Exit;
if (FAILED((hr=::Unicode2Ansi(pwcsClsid, &pszClsid))))
{
goto Exit;
}
if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
REGKEY_ACTIVESETUP_CLSIDFEATURE, 0, KEY_READ,
&hkeyClsidFeature)) != ERROR_SUCCESS)
{
#if JIT_IN_BUILD
hr = HRESULT_FROM_WIN32(lResult);
#else
hr = S_FALSE;
#endif
goto Exit;
}
szFeature[0] = '\0';
if (SHQueryValueEx(hkeyClsidFeature, pszClsid, NULL, &dwType,
(unsigned char *)szFeature, &dwSize) == ERROR_SUCCESS)
{
if (dwSize > MAX_PATH)
{
// limit the feature name to MAX_PATH as buffer overrun protection
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
goto Exit;
}
hr = ParseIEFeature(szFeature, pQuery, ppwszIEFeature, pQueryRec);
// FALLTHROUGH to exit
}
else
{
hr = S_FALSE;
// FALLTHROUGH to exit
}
Exit:
if (hkeyClsidFeature)
::RegCloseKey(hkeyClsidFeature);
SAFEDELETE(pwcsClsid);
SAFEDELETE(pszClsid);
DEBUG_LEAVE(hr);
return hr;
}
HRESULT
IsActiveSetupFeatureLocallyInstalled(
LPCSTR pszDist,
QUERYCONTEXT *pQuery,
LPSTR *ppszComponentID,
DWORD *pdwVersionHi,
DWORD *pdwVersionLo,
DWORD dwFlags)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"IsActiveSetupFeatureLocallyInstalled",
"%.80q, %#x, %#x, %#x, %#x, %#x",
pszDist, pQuery, ppszComponentID, pdwVersionHi, pdwVersionLo, dwFlags
));
HRESULT hr = S_FALSE; // Not installed by active setup.
LONG lResult = ERROR_SUCCESS;
CHAR* pszKey = NULL;
BOOL bAllocedKey = FALSE;
int nKey;
char szKey[2*MAX_PATH];
char szVersion[MAX_PATH];
HKEY hKey = NULL;
DWORD dwSize;
DWORD dwValue;
DWORD dwType;
BOOL fIsInstalled = FALSE;
WORD wVersion[4];
DWORD dwCurMS = 0;
DWORD dwCurLS = 0;
const static char * szLocale = "Locale";
const static char * szIsInstalled = "IsInstalled";
const static char * szActVersion = "Version";
const static char * szCOMPONENTID = "ComponentID";
const static char * szKEYFILENAME = "KeyFileName";
if (pdwVersionHi && pdwVersionLo)
{
*pdwVersionHi = 0;
*pdwVersionLo = 0;
}
if (ppszComponentID)
{
// if we need a componentID
GetComponentIDFromIEFeature(pszDist, ppszComponentID);
}
ULONG ulenDist = lstrlenA(pszDist);
//sizeof counts terminating NULL also, so subtract 2, and add 1 for the final NULL
ULONG ulenConst = sizeof(REGKEY_ACTIVESETUP_COMPONENTS)/sizeof(CHAR) + sizeof("\\")/sizeof(CHAR) - 2 + 1;
if ((ulenDist+ulenConst) > sizeof(szKey))
{
pszKey = new CHAR[ulenDist+ulenConst];
}
if (pszKey)
{
bAllocedKey = TRUE;
nKey = ulenDist+ulenConst;
}
else
{
pszKey = szKey;
nKey = sizeof(szKey);
}
StrNCpy(pszKey, REGKEY_ACTIVESETUP_COMPONENTS, nKey);
StrCatBuff(pszKey, "\\", nKey);
StrCatBuff(pszKey, pszDist, nKey);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(dwValue);
// Old format of the Installed components did not have the IsInstalled value.
if (RegQueryValueEx( hKey, szIsInstalled, NULL, NULL, (LPBYTE)&dwValue, &dwSize) != ERROR_SUCCESS)
{
dwValue = 0;
}
fIsInstalled = (dwValue != 0);
if (fIsInstalled)
{
hr = S_OK;
}
else
{
// hr is S_FALSE;
goto Exit;
}
if (pQuery && ((pQuery->dwVersionHi|pQuery->dwVersionLo) ||
(dwFlags & FIEF_FLAG_PEEK)) )
{
dwSize = sizeof(szVersion);
if ( (lResult = RegQueryValueEx(hKey, szActVersion, NULL, &dwType, (LPBYTE)szVersion, &dwSize)) == ERROR_SUCCESS )
{
Assert(dwType == REG_SZ);
if ( SUCCEEDED(GetVersionFromString(szVersion, &dwCurMS, &dwCurLS)))
{
if (dwCurMS > pQuery->dwVersionHi ||
(dwCurMS == pQuery->dwVersionHi && dwCurLS >= pQuery->dwVersionLo))
{
hr = S_OK;
}
else
{
hr = S_FALSE;
}
if (pdwVersionHi && pdwVersionLo)
{
*pdwVersionHi = dwCurMS;
*pdwVersionLo = dwCurLS;
}
}
else
{
hr = S_FALSE;
}
}
else
{
hr = S_FALSE;
}
}
if (hr == S_OK)
{
// we think it is installed
// robustify with key file presence check
dwSize = sizeof(szVersion);
dwType = REG_SZ;
if ( SHQueryValueEx(hKey, szKEYFILENAME, NULL, &dwType, (LPBYTE)szVersion, &dwSize) == ERROR_SUCCESS )
{
// value present, check if file is present
if (GetFileAttributes(szVersion) == -1)
hr = S_FALSE;
}
}
}
Exit:
if (bAllocedKey)
{
delete [] pszKey;
}
SAFEREGCLOSEKEY(hKey);
DEBUG_LEAVE(hr);
return hr;
}
HRESULT
GetInstalledVersion(
LPCWSTR pwszIEFeature,
QUERYCONTEXT *pQuery)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"GetInstalledVersion",
"%.100wq, %#x",
pwszIEFeature, pQuery
));
HRESULT hr = E_FAIL;
LPSTR pszIEFeature = NULL;
HKEY hKey = NULL;
LONG lResult = ERROR_SUCCESS;
CHAR* pszKey = NULL;
BOOL bAllocedKey = FALSE;
int nKey;
char szKey[2*MAX_PATH];
char szVersion[MAX_PATH];
DWORD dwSize, dwType;
DWORD dwCurMS, dwCurLS;
const static char * szActVersion = "Version";
if (FAILED((hr=::Unicode2Ansi(pwszIEFeature, &pszIEFeature))))
{
goto Exit;
}
ULONG ulenDist = lstrlenA(pszIEFeature);
//sizeof counts terminating NULL also, so subtract 2, and add 1 for the final NULL
ULONG ulenConst = sizeof(REGKEY_ACTIVESETUP_COMPONENTS)/sizeof(CHAR) + sizeof("\\")/sizeof(CHAR) - 2 + 1;
if ((ulenDist+ulenConst) > sizeof(szKey))
{
pszKey = new CHAR[ulenDist+ulenConst];
}
if (pszKey)
{
bAllocedKey = TRUE;
nKey = ulenDist + ulenConst;
}
else
{
pszKey = szKey;
nKey = sizeof(szKey);
}
StrNCpy(pszKey, REGKEY_ACTIVESETUP_COMPONENTS, nKey);
StrCatBuff(pszKey, "\\", nKey);
StrCatBuff(pszKey, pszIEFeature, nKey);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
{
dwSize = sizeof(szVersion);
if ( (lResult = RegQueryValueEx(hKey, szActVersion, NULL, &dwType, (LPBYTE)szVersion, &dwSize)) == ERROR_SUCCESS )
{
Assert(dwType == REG_SZ);
if ( SUCCEEDED(GetVersionFromString(szVersion, &dwCurMS, &dwCurLS)))
{
if (pQuery)
{
pQuery->dwVersionHi = dwCurMS;
pQuery->dwVersionLo = dwCurLS;
hr = S_OK;
}
}
}
}
Exit:
if (bAllocedKey)
{
delete [] pszKey;
}
if (pszIEFeature)
{
delete [] pszIEFeature;
}
SAFEREGCLOSEKEY(hKey);
DEBUG_LEAVE(hr);
return hr;
}
typedef HRESULT (*PFNGETICIFFILEFROMFILE)(ICifFile **, LPCSTR pszFile);
HRESULT
IsCIFVersionGoodEnough(
QUERYCONTEXT *pQuery,
LPCSTR pszID)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"IsCIFVersionGoodEnough",
"%#x, %.80q",
pQuery, pszID
));
// BUGBUG: not side by side aware!!!
const static char * szCIFPATH = "iesetup.cif";
HRESULT hr = S_OK;
ICifFile *pcif;
ICifComponent *pcomp;
DWORD dwVersionHi = 0;
DWORD dwVersionLo = 0;
PFNGETICIFFILEFROMFILE pfnGetICifFileFromFile = NULL;
HMODULE hMod = LoadLibrary("inseng.dll");
if ( !hMod ||
(!(pfnGetICifFileFromFile = (PFNGETICIFFILEFROMFILE)GetProcAddress(hMod,
"GetICifFileFromFile")))) {
DEBUG_LEAVE(E_UNEXPECTED);
return E_UNEXPECTED;
}
if(SUCCEEDED(pfnGetICifFileFromFile(&pcif, szCIFPATH))) // szCifPath is full path to cif, or 8.3 and it defaults to look in ie dir for it
{
if(SUCCEEDED(pcif->FindComponent(pszID, &pcomp))) // pszID is id of what you are interested in
{
pcomp->GetVersion(&dwVersionHi, &dwVersionLo);
// BUGBUG: ?
// pcomp->Release();
if (pQuery->dwVersionHi > dwVersionHi ||
(dwVersionHi == pQuery->dwVersionHi && pQuery->dwVersionLo > dwVersionLo)) {
hr = HRESULT_FROM_WIN32(ERROR_UNKNOWN_REVISION);
}
}
pcif->Release();
}
if (hMod)
FreeLibrary(hMod);
DEBUG_LEAVE(hr);
return hr;
}
/* Returns:
*
* S_OK: Is Installed
* S_FALSE: Is Available, Needs to be faulted in.
* ERROR
*
*/
HRESULT
IsIEFeatureInstalled(
LPCWSTR pwszIEFeature,
QUERYCONTEXT *pQuery,
LPWSTR *ppwszSetupPage,
LPWSTR *ppwszCompID,
DWORD dwFlags,
BOOL *pbWebJit,
LPSTR *ppszWebJitUrl,
BOOL fOnlyCheckInstall
)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"IsIEFeatureInstalled",
"%.80wq, %#x, %#x, %#x, %#x, %B",
pwszIEFeature, pQuery, ppwszSetupPage, ppwszCompID, dwFlags, fOnlyCheckInstall
));
HRESULT hr = S_FALSE; // assume need to fault in
LPSTR pszIEFeature = NULL;
LPSTR pszComponentID = NULL;
const static char * szSETUPPAGE = "JITSetupPage";
const static char * szQUERYFEATURE = "feature=";
LONG lResult;
HKEY hkeyActiveSetup = 0;
HKEY hkeyWebJitUrls = 0;
char szJITPage[INTERNET_MAX_URL_LENGTH];
DWORD dwType;
DWORD dwSize = INTERNET_MAX_URL_LENGTH;
DWORD dwInstalledVersionHi =0;
DWORD dwInstalledVersionLo =0;
BOOL bComponentDeclined = FALSE;
#ifdef UNIX
{
/* Unix special handling for features like java VM
* For instance, libmsjava.so will always be installed.
* But, is the Sun VM installed?
*/
hr = CheckIEFeatureOnUnix(pwszIEFeature, &dwInstalledVersionHi, &dwInstalledVersionLo, dwFlags);
if (hr == S_OK || hr == ERROR_PRODUCT_UNINSTALLED)
goto Exit; /* Found on Unix and Handled */
}
#endif /* UNIX */
if (FAILED((hr=::Unicode2Ansi(pwszIEFeature, &pszIEFeature))))
{
goto Exit;
}
hr = IsActiveSetupFeatureLocallyInstalled(pszIEFeature, pQuery, fOnlyCheckInstall ? NULL : &pszComponentID, &dwInstalledVersionHi, &dwInstalledVersionLo, dwFlags);
if (fOnlyCheckInstall)
{
goto Exit;
}
if (hr == S_FALSE)
{
// not installed, need to JIT
// find out if this is JITDeclined
if (SHRegGetUSValue( REGKEY_DECLINED_IOD, pszIEFeature, NULL, NULL, NULL, 0,NULL,0) == ERROR_SUCCESS)
{
bComponentDeclined = TRUE;
}
}
if (((hr != S_OK) || dwFlags & FIEF_FLAG_SKIP_INSTALLED_VERSION_CHECK)
&& ppwszSetupPage && ppwszCompID)
{
if (pszComponentID && ppszWebJitUrl && pbWebJit)
{
if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
REGKEY_WEBJITURLS, 0, KEY_READ,
&hkeyWebJitUrls)) == ERROR_SUCCESS)
{
//reuse temporary array for WebJITURL
szJITPage[0] = '\0';
if (SHQueryValueEx(hkeyWebJitUrls, pszComponentID, NULL, &dwType,
(unsigned char *)szJITPage, &dwSize) == ERROR_SUCCESS)
{
LPSTR pszWebJitUrl = new CHAR[dwSize+1];
if (!pszWebJitUrl)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
lstrcpy(pszWebJitUrl, szJITPage);
*ppszWebJitUrl = pszWebJitUrl;
*pbWebJit = TRUE;
HRESULT hr1 = ::Ansi2Unicode(pszComponentID, ppwszCompID);
if (FAILED(hr1))
{
hr = hr1;
}
goto Exit;
}
}
*pbWebJit = FALSE;
}
if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
REGKEY_ACTIVESETUP, 0, KEY_READ,
&hkeyActiveSetup)) != ERROR_SUCCESS)
{
hr = HRESULT_FROM_WIN32(lResult);
goto Exit;
}
szJITPage[0] = '\0';
if (SHQueryValueEx(hkeyActiveSetup, szSETUPPAGE, NULL, &dwType,
(unsigned char *)szJITPage, &dwSize) == ERROR_SUCCESS)
{
HRESULT hr1 = ::Ansi2Unicode(szJITPage, ppwszSetupPage);
if(FAILED(hr1))
hr = hr1; // else hr still = S_FALSE;
if (pszComponentID)
{
if ((sizeof(szQUERYFEATURE) + lstrlen(pszComponentID) +1)
< INTERNET_MAX_URL_LENGTH)
{
lstrcpy(szJITPage, szQUERYFEATURE);
lstrcat(szJITPage, pszComponentID);
if ( (dwFlags & FIEF_FLAG_CHECK_CIFVERSION) &&
pQuery &&
(pQuery->dwVersionHi|pQuery->dwVersionLo))
{
hr1=IsCIFVersionGoodEnough(pQuery, pszComponentID);
if (FAILED(hr1))
{
hr = hr1;
goto Exit;
}
}
HRESULT hr1 = ::Ansi2Unicode(szJITPage, ppwszCompID);
if(FAILED(hr1))
hr = hr1; // else hr still = S_FALSE;
}
else
{
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
}
}
}
}
Exit:
if (pQuery && (dwFlags & FIEF_FLAG_PEEK))
{
pQuery->dwVersionHi = dwInstalledVersionHi;
pQuery->dwVersionLo = dwInstalledVersionLo;
}
SAFEDELETE(pszIEFeature);
SAFEDELETE(pszComponentID);
if (hkeyActiveSetup)
RegCloseKey(hkeyActiveSetup);
if (hkeyWebJitUrls)
RegCloseKey(hkeyWebJitUrls);
if (bComponentDeclined)
{
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
}
DEBUG_LEAVE(hr);
return hr;
}
HRESULT
IsJITRestricted(BOOL bWebJit)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"IsJITRestricted",
"%B",
bWebJit
));
HKEY hkeyRest = 0;
BOOL bJITRest = FALSE;
DWORD dwValue = 0;
DWORD dwLen = sizeof(DWORD);
HRESULT hr = S_OK;
OSVERSIONINFO osvi;
// BUGBUG: NT RAID #216898--when you install IE5 and the shell cabs
// on NT5, the NoJITSetup reg value is blown away, but we can't figure
// out who is doing this. JIT should not occur for NT5. This hack
// is a work-around so JIT does not occur under NT5 and above.
if (!bWebJit)
{
osvi.dwOSVersionInfoSize = sizeof(osvi);
GetVersionEx(&osvi);
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
osvi.dwMajorVersion >= 5) {
hr = E_ACCESSDENIED;
goto Exit;
}
}
// per-machine JIT off policy
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_INFODEL_REST, 0, KEY_READ, &hkeyRest) == ERROR_SUCCESS)
{
if (!bWebJit)
{
if (RegQueryValueEx( hkeyRest, REGVAL_JIT_REST, NULL, NULL,
(LPBYTE)&dwValue, &dwLen) == ERROR_SUCCESS && dwValue)
hr = E_ACCESSDENIED;
}
else
{
if (RegQueryValueEx( hkeyRest, REGVAL_WEBJIT_REST, NULL, NULL,
(LPBYTE)&dwValue, &dwLen) == ERROR_SUCCESS && dwValue)
hr = E_ACCESSDENIED;
}
RegCloseKey(hkeyRest);
}
if (SUCCEEDED(hr))
{
// Check to see if the user has turned it off under advanced options
// make this appear in UI similar to the admin restricted case
// hence the return value of access_denied
dwValue = 0;
dwLen = sizeof(DWORD);
if (!bWebJit)
{
if (SHRegGetUSValue( REGSTR_PATH_IE_MAIN, REGVAL_JIT_REST, NULL, (LPBYTE)&dwValue, &dwLen, 0,NULL,0) == ERROR_SUCCESS && dwValue)
hr = E_ACCESSDENIED;
}
else
{
if (SHRegGetUSValue( REGSTR_PATH_IE_MAIN, REGVAL_WEBJIT_REST, NULL, (LPBYTE)&dwValue, &dwLen, 0,NULL,0) == ERROR_SUCCESS && dwValue)
hr = E_ACCESSDENIED;
}
}
Exit:
DEBUG_LEAVE(hr);
return hr;
}
HRESULT
SetJITDeclined(
LPCWSTR pwszIEFeature)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"SetJITDeclined",
"%.80wq",
pwszIEFeature
));
HRESULT hr = S_FALSE; // assume need to fault in
LPSTR pszIEFeature = NULL;
LONG lResult = ERROR_SUCCESS;
HKEY hKey = NULL;
DWORD dwSize;
DWORD dwValue;
LPSTR szNull = "";
if (FAILED((hr=::Unicode2Ansi(pwszIEFeature, &pszIEFeature))))
{
goto Exit;
}
if (RegOpenKeyEx(HKEY_CURRENT_USER, REGKEY_DECLINED_IOD, 0, KEY_WRITE, &hKey) != ERROR_SUCCESS)
{
if ((lResult = RegCreateKey( HKEY_CURRENT_USER,
REGKEY_DECLINED_IOD, &hKey)) != ERROR_SUCCESS) {
hr = HRESULT_FROM_WIN32(lResult);
goto Exit;
}
}
if (((lResult = RegSetValueEx (hKey, pszIEFeature, 0, REG_SZ,
(unsigned char *)szNull, 1))) != ERROR_SUCCESS) {
hr = HRESULT_FROM_WIN32(lResult);
}
Exit:
if (hKey)
RegCloseKey(hKey);
SAFEDELETE(pszIEFeature);
DEBUG_LEAVE(hr);
return hr;
}
HRESULT
HasFeatureAlreadyBeenRejected(
LPCWSTR szDistUnit)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"HasFeatureAlreadyBeenRejected",
"%.80wq",
szDistUnit
));
HRESULT hr = S_OK;
LISTPOSITION curpos;
LPCWSTR pwszRejectedFeature = NULL;
int iNumRejected;
int i;
CUrlMkTls tls(hr); // hr passed by reference!
if (FAILED(hr))
goto Exit;
iNumRejected = tls->pRejectedFeaturesList->GetCount();
curpos = tls->pRejectedFeaturesList->GetHeadPosition();
// walk thru all the rejected features in the thread and check for match
for (i=0; i < iNumRejected; i++) {
pwszRejectedFeature = tls->pRejectedFeaturesList->GetNext(curpos);
if (StrCmpIW(szDistUnit, pwszRejectedFeature) == 0) {
hr = S_FALSE;
break;
}
}
Exit:
DEBUG_LEAVE(hr);
return hr;
}
HRESULT
RelinquishCodeDownloadCookies()
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"RelinquishCodeDownloadCookies",
NULL
));
HRESULT hr = S_OK;
CUrlMkTls tls(hr); // hr passed by reference!
if (FAILED(hr))
goto Exit;
Assert(tls->pTrustCookie);
Assert(tls->pSetupCookie);
if (!tls->pTrustCookie || !tls->pSetupCookie) {
hr = E_UNEXPECTED;
goto Exit;
}
tls->pSetupCookie->JITRelinquish();
tls->pTrustCookie->JITRelinquish();
Exit:
DEBUG_LEAVE(hr);
return hr;
}
HRESULT
AcquireCodeDownloadCookies()
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"AcquireCodeDownloadCookies",
NULL
));
HRESULT hr = S_OK;
HRESULT hrJITTrustCookie = E_FAIL;
HRESULT hrJITSetupCookie = E_FAIL;
CUrlMkTls tls(hr); // hr passed by reference!
if (FAILED(hr))
goto Exit;
// are both cookies free?
if (!(tls->pTrustCookie->IsFree() && tls->pSetupCookie->IsFree())) {
hr = E_FAIL;
goto Exit;
}
// if both cookies are free, grab them
// thius will ensure that code downloads are
// frozen or pended to the point JIT completes
hrJITTrustCookie = tls->pTrustCookie->JITAcquire();
if (FAILED(hrJITTrustCookie)) {
Assert(TRUE);
hr = hrJITTrustCookie;
goto Exit;
}
hrJITSetupCookie = tls->pSetupCookie->JITAcquire();
if (FAILED(hrJITSetupCookie)) {
Assert(TRUE);
hr = hrJITSetupCookie;
goto Exit;
}
// taken both the cookies
Exit:
if (FAILED(hr)) {
if (SUCCEEDED(hrJITSetupCookie))
tls->pSetupCookie->JITRelinquish();
if (SUCCEEDED(hrJITTrustCookie))
tls->pTrustCookie->JITRelinquish();
}
DEBUG_LEAVE(hr);
return hr;
}
HRESULT
GetDialogArgs(LPCWSTR pwszCompID, DWORD dwFlags, VARIANT& vtDialogArg)
{
DEBUG_ENTER((DBG_DOWNLOAD,
Hresult,
"GetDialogArgs",
"%.80wq, %#x, %#x",
pwszCompID, dwFlags, &vtDialogArg
));
HRESULT hr = S_OK;
WCHAR pwszFLAGS[] = L"&flag=forceUI";
WCHAR pwszArgs[INTERNET_MAX_URL_LENGTH];// large buffer
StrCpyNW(pwszArgs, pwszCompID, INTERNET_MAX_URL_LENGTH);
if (dwFlags & FIEF_FLAG_FORCE_JITUI) {
StrCatBuffW(pwszArgs, pwszFLAGS, INTERNET_MAX_URL_LENGTH);
}
vtDialogArg.bstrVal = SysAllocString(pwszArgs);
ASSERT(vtDialogArg.bstrVal);
if(vtDialogArg.bstrVal)
{
vtDialogArg.vt = VT_BSTR;
}
else
{
hr = E_OUTOFMEMORY;
goto Exit;
}
Exit:
DEBUG_LEAVE(hr);
return hr;
}
//for WebJit
#define MAX_URL_STRING INTERNET_MAX_URL_LENGTH
VOID URLSubstitution(LPCSTR pszUrlIn, LPSTR pszUrlOut, DWORD cchSize, DWORD dwSubstitutions);
#define URLSUB_OLCID 0x00000040 // The hexadecimal Locale ID (LCID) or Language ID (LID) of the operating system.
#define URLSUB_CLCID 0x00000080 // The hexadecimal Locale ID (LCID) or Language ID (LID) of the current user?s Regional Setting (as in Control Panel).
#define URLSUB_ALL 0xFFFFFFFF
BOOL CALLBACK JavaVMJitProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDOK:
if (SendDlgItemMessage(hwndDlg, IDC_NOMOREDIALOG, BM_GETSTATE, 0, 0) == BST_CHECKED)
{
//Never ask again
SetJITDeclined(g_pwszCLSID_AppletOCX);
}
EndDialog(hwndDlg, wParam);
return TRUE;
case IDC_MOREINFO:
if (HIWORD(wParam) == BN_CLICKED)
{
TCHAR szJavaFAQRegUrl[1024], szJavaFAQUrl[1024];
if (0 < LoadString(g_hInst, IDS_JAVAVMFAQURL, szJavaFAQRegUrl, sizeof(szJavaFAQRegUrl)/sizeof(szJavaFAQRegUrl[0])))
{
URLSubstitution(szJavaFAQRegUrl, szJavaFAQUrl, sizeof(szJavaFAQRegUrl)/sizeof(szJavaFAQRegUrl[0]), URLSUB_OLCID|URLSUB_CLCID);
ShellExecute(hwndDlg, NULL, szJavaFAQUrl, NULL, NULL, SW_SHOWDEFAULT);
}
}
break;
}
}
return FALSE;
}
/*
* FaultInIEFeature
*
* Description:
*
* Synchronous API that is to be invoked by client of an IE feature before
* accessing the feature. If the feature is already installed then it
* succeeds and the client should attempt to access the feature. Success
* return by the API does not guarantee that the feature is fully installed
* or will work. The client should still robustify access to the feature
* with proper error checking.
* If the API detects that the feature is missing on the client then it
* maps the feature identified by a clsid or mimetype (in the classspec)
* into a feature name/id and then invokes a HTML dialog with the feature
* name in the form of http://...../setuppage.htm?FeatureName=<featurename>
* The page can communicate back a return value thru
* window.external.returnValue. The following are recognized now:
*
* #define JITPAGE_RETVAL_SUCCESS 0x0 // successfully installed
* #define JITPAGE_RETVAL_CANCELLED 0x1 // was cancelled by user
* #define JITPAGE_RETVAL_DONTASK_THISWINDOW 0x2 // don't ask again in this
*
* Parameters:
*
* hWnd: parent hwnd for htmldialog
* pClassSpec: ptr to union {clsid, mimetype ...}
* querycontext: to specify version, lcid of feature(lcid not impl)
* This is an IN/OUT param. The installed version
* number is returned is FIEF_FLAG_PEEK is passed in
* dwFlags: control behaviour such as UI/no UI, peek versus faultin
* FIEF_FLAG_PEEK
*
* FIEF_FLAG_FORCE_JITUI
* Force JIT even if user has cancelled a previous JIT in
* the same session or even asked to Never JIT this feature.
*
* FIEF_FLAG_PEEK
* Don't fault in just peek. Peek has the side effect of
* returning currently installed version in the querycontext
*
* FIEF_FLAG_SKIP_INSTALLED_VERSION_CHECK
* Ignore local version being satisfactory and force JIT
* download. Typically called by code download or other caller
* after a CoCreateInstance call has failed with
* REGDB_E_CLASSNOTREG or ERROR_MOD_NOT_FOUND (missing
* dependency dll). The registry probably still looks like
* this feature is installed, but really isn't or is damaged.
*
*
* Returns:
*
* S_OK: Is Installed. Caller needs to CoCreate or BindToObject or some
* other system service to invoke the class or mime handler.
* S_FALSE: Class or Mime is not part of an IE feature. Caller needs to
* CoCreate or BindToObject or some other system service to
* invoke the class or mime handler.
* E_ACCESSDENIED
* Admin has turned off JIT feature.
* HRESULT_FROM_WIN32(ERROR_CANCELLED):
* Could have been cancelled by the user or has been requested
* by user not to bother again in this browser window.
* HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED):
* Returned if the feature is not installed, but FIEF_FLAG_PEEK
* was specified
* HRESULT_FROM_WIN32(ERROR_REVISION_UNKNOWN);
* Returned when dwFlag FIEF_FLAG_CHECK_CIFVERSION is passed and
* the local version is not good enough AND the version in the CIF
* that would get JIT installed is also less then the version
* requested by the caller. This flag is typically passed by a
* caller such as code download in URLMON that has the means to
* get the requested version by installing the CODEBASE object.
*
* ERROR:
* Other error.
*
*/
#define HELP_CLSID L"{45ea75a0-a269-11d1-b5bf-0000f8051515}"
BOOL IsWin32X86();
STDAPI
FaultInIEFeature(
HWND hWnd,
uCLSSPEC *pClassSpec,
QUERYCONTEXT *pQuery,
DWORD dwFlags
)
{
DEBUG_ENTER_API((DBG_DOWNLOAD,
Hresult,
"FaultInIEFeature",
"%#x, %#x, %#x, %#x",
hWnd, pClassSpec, pQuery, dwFlags
));
HRESULT hr = S_OK;
HRESULT hrCDLCookies=E_FAIL;
WCHAR *pwszMUISetupFile = NULL;
WCHAR pwszMUISetupPage[MAX_PATH];
CLSID inclsid = CLSID_NULL;
LPCWSTR pwszDistUnit=NULL;
LPCWSTR pwszFileExt=NULL;
LPCWSTR pwszMimeType=NULL;
LPWSTR pwszIEFeature=NULL;
LPWSTR pwszSetupPage=NULL;
LPWSTR pwszCompID=NULL;
HINSTANCE hInst = 0;
IMoniker *pMk = NULL;
SHOWHTMLDIALOGFN *pfnShowHTMLDialog = NULL;
VARIANT vtRetVal;
VARIANT vtDialogArg;
VariantInit(&vtRetVal);
VariantInit(&vtDialogArg);
QUERYCONTEXT qcInternal;
BOOL bShowHelp = FALSE;
LPWSTR pwszHelpFeature=NULL;
LPWSTR pwszHelpSetupPage=NULL;
LPWSTR pwszHelpCompID=NULL;
CLSID HelpCLSID = CLSID_NULL;
QUERYCONTEXT qcHelp;
LPSTR pszWebJitRegUrl = 0;
LPSTR pszWebJitUrl = 0;
BOOL bWebJit = FALSE;
QUERYCONTEXT qcRequested;
QUERYCONTEXT qcRecommended;
QUERYCONTEXT* pQueryInstalled = NULL;
ULONG_PTR uCookie = 0;
// setup the per thread tls list for rejected features, so we
// don't bother the user multiple times for the same feature
// needs review on whether this is per thread or per process
CUrlMkTls tls(hr); // hr passed by reference!
if (FAILED(hr))
goto Exit;
hr = SetCodeDownloadTLSVars();
if (FAILED(hr))
goto Exit;
if (pQuery)
{
memcpy(&qcInternal, pQuery, sizeof(QUERYCONTEXT));
}
else
{
memset(&qcInternal, 0, sizeof(QUERYCONTEXT));
}
memset(&qcRecommended, 0, sizeof(QUERYCONTEXT));
// Get the class spec.
if(pClassSpec != NULL)
{
switch(pClassSpec->tyspec)
{
case TYSPEC_PROGID:
// BUGBUG: we don't have JIT tables for progid to feature id
// so this will only work for PEEK for installed versions
if (FAILED((hr=CLSIDFromProgID(pClassSpec->tagged_union.pProgId,
&inclsid))))
goto Exit;
hr = GetIEFeatureFromClass(&pwszIEFeature, inclsid, &qcInternal, &qcRecommended);
if (hr != S_OK)
goto Exit;
break;
case TYSPEC_CLSID:
inclsid = pClassSpec->tagged_union.clsid;
hr = GetIEFeatureFromClass(&pwszIEFeature, inclsid, &qcInternal, &qcRecommended);
if (hr != S_OK)
goto Exit;
break;
case TYSPEC_MIMETYPE:
pwszMimeType = (LPCWSTR) pClassSpec->tagged_union.pMimeType;
hr = GetIEFeatureFromMime(&pwszIEFeature, pwszMimeType, &qcInternal, &qcRecommended);
if (hr != S_OK)
goto Exit;
break;
case TYSPEC_FILENAME:
// overload filename to be Active Setup feature ID
hr = CDLDupWStr( &pwszIEFeature, pClassSpec->tagged_union.pFileName);
if (hr != S_OK)
goto Exit;
break;
default:
hr = E_INVALIDARG;
goto Exit;
}
}
else
{
hr = E_INVALIDARG;
goto Exit;
}
// We have a feature now
ASSERT(pwszIEFeature);
if (!pwszIEFeature)
{
hr = E_UNEXPECTED;
goto Exit;
}
// copy over the recommended or the user-desired version, before it may be stomped by IsIEFeatureInstalled.
memcpy(&qcRequested, &qcInternal, sizeof(QUERYCONTEXT));
hr = IsIEFeatureInstalled(pwszIEFeature, &qcInternal, &pwszSetupPage, &pwszCompID, dwFlags, &bWebJit, &pszWebJitRegUrl, FALSE);
if ((dwFlags & FIEF_FLAG_PEEK) && pQuery)
{
memcpy(pQuery, &qcInternal, sizeof(QUERYCONTEXT));
}
if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
{
if (!(dwFlags & FIEF_FLAG_FORCE_JITUI))
goto Exit;
else
hr = S_FALSE;
}
if (bWebJit
&& (hr == S_FALSE)
&& (qcRecommended.dwVersionHi || qcRecommended.dwVersionLo)
&& ((qcRequested.dwVersionHi > qcRecommended.dwVersionHi)
|| ((qcRequested.dwVersionLo > qcRecommended.dwVersionLo)
&& (qcRequested.dwVersionHi == qcRecommended.dwVersionHi))))
{
//Don't WEBJIT if the requested version < recommeded version.
hr = HRESULT_FROM_WIN32(ERROR_UNKNOWN_REVISION);
}
if (FAILED(hr) || (hr == S_OK && !(dwFlags & FIEF_FLAG_SKIP_INSTALLED_VERSION_CHECK)))
goto Exit;
if (SUCCEEDED(hr) && pwszSetupPage && !bWebJit)
{
pwszMUISetupFile = PathFindFileNameW(pwszSetupPage);
hr = SHGetWebFolderFilePathW(pwszMUISetupFile, pwszMUISetupPage, MAX_PATH);
}
hr = IsJITRestricted(bWebJit);
if (hr == E_ACCESSDENIED
|| ((hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))
&& (!(dwFlags & FIEF_FLAG_FORCE_JITUI))
)
)
{
goto Exit;
}
if (!(dwFlags & FIEF_FLAG_FORCE_JITUI))
{
hr = HasFeatureAlreadyBeenRejected(pwszIEFeature);
if (hr == S_FALSE)
{
// already been rejected
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
goto Exit;
}
}
// We have a setup page for the feature now
// need to faultin feature
if (dwFlags & FIEF_FLAG_PEEK)
{
hr = HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED);
goto Exit;
}
if (!pwszCompID)
{
hr = E_UNEXPECTED;
goto Exit;
}
// faultin feature
// now we need to acuire some code download cookies
// trust and setup. This is to make sure that we don't
// have a JIT and WVT dialog up at the same time
// we aslo want to avoid having to do a JIT and a code download
// restart machine dialog come up in the middle
hrCDLCookies = AcquireCodeDownloadCookies();
//if (FAILED(hrCDLCookies))
{
// Just try and make the new JIT dialog plaster on top of the
// WVT dialog, but make the WVT dialog disabled while JIT is up
// this can be done by hopefully just parenting the JIT with the
// trust dialog instead of the one passed in.
HWND hWndParent = hWnd;
HWND hWndTop = hWnd;
while ( (hWndParent = GetParent(hWndParent)) != NULL)
{
hWndTop = hWndParent;
}
hWnd = GetLastActivePopup(hWndTop);
}
//VENKATK
DWORD dwRetVal;
if (!bWebJit)
{
hr = GetDialogArgs(pwszCompID, dwFlags, vtDialogArg);
if (FAILED(hr))
goto Exit;
//#81608: Do not show the "?" help icon if Help is not installed
CLSIDFromString(HELP_CLSID, &HelpCLSID);
memset(&qcHelp, 0, sizeof(QUERYCONTEXT));
GetIEFeatureFromClass(&pwszHelpFeature, HelpCLSID, &qcHelp);
if (pwszHelpFeature && *pwszHelpFeature)
{
if (IsIEFeatureInstalled(pwszHelpFeature, &qcHelp, &pwszHelpSetupPage, &pwszHelpCompID, 0, NULL, NULL, FALSE) == S_OK)
{
// Help Feature is installed. Turn on the "?" flag.
bShowHelp = TRUE;
}
}
hr = CreateURLMoniker(NULL, pwszMUISetupPage, &pMk);
if (FAILED(hr))
goto Exit;
hInst = LoadLibraryEx(TEXT("MSHTML.DLL"), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (!hInst)
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}
pfnShowHTMLDialog = (SHOWHTMLDIALOGFN *)GetProcAddress(hInst, "ShowHTMLDialog");
if (!pfnShowHTMLDialog) {
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}
DEBUG_ENTER((DBG_DOWNLOAD,
Dword,
"EXTERNAL::ShowHTMLDialog",
"%#x, %#x, %.200wq",
hWnd, pMk, pwszMUISetupPage
));
if (bShowHelp)
(*pfnShowHTMLDialog)(hWnd, pMk, &vtDialogArg, NULL, &vtRetVal);
else
(*pfnShowHTMLDialog)(hWnd, pMk, &vtDialogArg, L"help:no;", &vtRetVal);
// below to release inseng.dll and asctrls.ocx the setup helper and
// control used in the JIT setup page. This is to help people
// running iesetup for the next build after they have had a JIT
// to not require a reboot
dwRetVal = (vtRetVal.vt == VT_I4) ? vtRetVal.lVal : 0;
DEBUG_LEAVE(dwRetVal);
CoFreeUnusedLibraries();
}
else
{
//WEBJIT
WEBJIT_PARAM sWebJitParam;
if (!IsWin32X86())
{
hr = HRESULT_FROM_WIN32(ERROR_INSTALL_PLATFORM_UNSUPPORTED);
goto Exit;
}
//KV-should we do this? Is a NULL handle value being used to indicate no UI? - Verify.
if (!hWnd)
{
hWnd = GetActiveWindow();
}
//We do not want to jit Java VM
if (IsEqualIID(inclsid, CLSID_AppletOCX))
{
if (ERROR_SUCCESS != SHRegGetUSValue( REGKEY_DECLINED_IOD, g_pszCLSID_AppletOCX, NULL, NULL, NULL, 0, NULL, 0))
{
//Pop up the dialog box if this has not been declined;
DialogBox(g_hInst, MAKEINTRESOURCE(IDD_JAVAVMJITDIALOG), hWnd, (DLGPROC)JavaVMJitProc);
}
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
goto Exit;
}
pszWebJitUrl = new CHAR[MAX_URL_STRING];
if (!pszWebJitUrl)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
pQueryInstalled = new QUERYCONTEXT;
if (pQueryInstalled
&& (SUCCEEDED(GetInstalledVersion(pwszIEFeature, pQueryInstalled))))
{
sWebJitParam.pQueryInstalled = pQueryInstalled;
}
else
{
sWebJitParam.pQueryInstalled = NULL;
}
URLSubstitution(pszWebJitRegUrl, pszWebJitUrl, MAX_URL_STRING, URLSUB_OLCID|URLSUB_CLCID);
sWebJitParam.lpszResource = pszWebJitUrl;
sWebJitParam.dwFlags = dwFlags;
sWebJitParam.pwszComponentId = pwszCompID;
sWebJitParam.hWndParent = hWnd;
CWebJit* pWebJit = new CWebJit(&sWebJitParam);
if (!pWebJit)
{
hr = E_OUTOFMEMORY;
goto Exit;
}
if (!pWebJit->InitCommonControlsForWebJit())
{
hr = HRESULT_FROM_WIN32(GetLastError());
goto Exit;
}
DEBUG_ENTER((DBG_DOWNLOAD,
Dword,
"EXTERNAL::DialogBoxParamA",
"%#x, %.200wq, %.200q, %.200q, %#x",
hWnd, pwszCompID, pszWebJitRegUrl, pszWebJitUrl, dwFlags
));
SHActivateContext(&uCookie);
sWebJitParam.pWebJit = pWebJit;
DialogBoxParamA(MLGetHinst(), MAKEINTRESOURCE(IDD_WEBJIT), hWnd, WebJitProc, (LPARAM)&sWebJitParam);
dwRetVal = pWebJit->GetResult();
if (uCookie)
{
SHDeactivateContext(uCookie);
}
DEBUG_LEAVE(dwRetVal);
//Need to set hr to SUCCESS if install succeeded.
if (dwRetVal == S_OK)
{
QUERYCONTEXT qcInternal2;
memcpy(&qcInternal2, &qcRequested, sizeof(QUERYCONTEXT));
hr = IsIEFeatureInstalled(pwszIEFeature, &qcInternal2, NULL, NULL, 0, NULL, NULL, TRUE);
//hr now has either S_OK or S_FALSE from IsIEFeatureInstalled
}
pWebJit->Release();
}
if (dwRetVal == JITPAGE_RETVAL_CANCELLED)
{
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
}
else if (dwRetVal == JITPAGE_RETVAL_NEED_REBOOT)
{
hr = HRESULT_FROM_WIN32(ERROR_SUCCESS_REBOOT_REQUIRED);
}
else if (dwRetVal == JITPAGE_RETVAL_DONTASK_THISWINDOW)
{
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
tls->pRejectedFeaturesList->AddHead(pwszIEFeature);
pwszIEFeature = NULL;
}
else if (dwRetVal == JITPAGE_RETVAL_DONTASK_EVER)
{
SetJITDeclined(pwszIEFeature);
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
}
else if (FAILED(dwRetVal))
{
hr = (HRESULT)dwRetVal;
}
Exit:
if (SUCCEEDED(hrCDLCookies))
{
HRESULT hr1 = RelinquishCodeDownloadCookies();
if (FAILED(hr1) && SUCCEEDED(hr))
hr = hr1;
}
SAFERELEASE(pMk);
SAFEDELETE(pwszIEFeature);
SAFEDELETE(pwszSetupPage);
SAFEDELETE(pwszCompID);
VariantClear(&vtDialogArg);
SAFEDELETE(pwszHelpFeature);
SAFEDELETE(pwszHelpSetupPage);
SAFEDELETE(pwszHelpCompID);
SAFEDELETE(pszWebJitRegUrl);
SAFEDELETE(pszWebJitUrl);
SAFEDELETE(pQueryInstalled);
if (hInst)
FreeLibrary(hInst);
DEBUG_LEAVE_API(hr);
return hr;
}
//This won't work for WebJit but nobody seems to call this anywhere in the codebase.
STDAPI_(BOOL) IsJITInProgress()
{
DEBUG_ENTER((DBG_DOWNLOAD,
Bool,
"IsJITInProgress",
NULL
));
HWND hwnd;
hwnd = FindWindow(JIT_DIALOG_CLASS_NAME, JIT_DIALOG_CAPTION);
DEBUG_LEAVE(hwnd != NULL);
return (hwnd != NULL); // not a typo (FindWindow returns NULL for unfound)
}
//This is an abbreviated part of the code in shdocvw.
#define MAX_SUBSTR_SIZE 100
typedef struct tagURLSub
{
LPCTSTR szTag;
DWORD dwType;
}
URLSUB;
const static URLSUB c_UrlSub[] =
{
{TEXT("{SUB_OLCID}"), URLSUB_OLCID},
{TEXT("{SUB_CLCID}"), URLSUB_CLCID},
};
VOID URLSubstitution(LPCSTR pszUrlIn, LPSTR pszUrlOut, DWORD cchSize, DWORD dwSubstitutions)
{
DWORD dwIndex;
CHAR szTempUrl[MAX_URL_STRING];
ASSERT(cchSize <= ARRAYSIZE(szTempUrl)); // We will truncate anything longer than MAX_URL_STRING
StrCpyN(szTempUrl, pszUrlIn, ARRAYSIZE(szTempUrl));
for (dwIndex = 0; dwIndex < ARRAYSIZE(c_UrlSub); dwIndex++)
{
while (dwSubstitutions & c_UrlSub[dwIndex].dwType)
{
LPSTR pszTag = StrStr(szTempUrl, c_UrlSub[dwIndex].szTag);
if (pszTag)
{
CHAR szCopyUrl[MAX_URL_STRING];
CHAR szSubStr[MAX_SUBSTR_SIZE]; // The Substitution
// Copy URL Before Substitution.
StrCpyN(szCopyUrl, szTempUrl, (int)(pszTag-szTempUrl+1));
pszTag += lstrlen(c_UrlSub[dwIndex].szTag);
switch (c_UrlSub[dwIndex].dwType)
{
case URLSUB_OLCID:
wnsprintf(szSubStr, ARRAYSIZE(szSubStr), _T("%#04lx"), GetSystemDefaultLCID());
break;
case URLSUB_CLCID:
wnsprintf(szSubStr, ARRAYSIZE(szSubStr), _T("%#04lx"), GetUserDefaultLCID());
break;
}
// Add the Substitution String to the end (will become the middle)
StrCatBuff(szCopyUrl, szSubStr, ARRAYSIZE(szCopyUrl));
// Add the rest of the URL after the substitution substring.
StrCatBuff(szCopyUrl, pszTag, ARRAYSIZE(szCopyUrl));
StrCpyN(szTempUrl, szCopyUrl, ARRAYSIZE(szTempUrl));
}
else
break; // This will allow us to replace all the occurances of this string.
}
}
StrCpyN(pszUrlOut, szTempUrl, cchSize);
return;
}