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
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;
|
|
}
|
|
|