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.
1058 lines
26 KiB
1058 lines
26 KiB
// ClientCaps.cpp : Implementation of CClientCaps
|
|
#include "headers.h"
|
|
|
|
#pragma MARK_DATA(__FILE__)
|
|
#pragma MARK_CODE(__FILE__)
|
|
#pragma MARK_CONST(__FILE__)
|
|
#include "iextag.h"
|
|
#include "ccaps.h"
|
|
|
|
typedef HRESULT STDAPICALLTYPE SHOWHTMLDIALOGFN (HWND hwndParent, IMoniker *pmk,
|
|
VARIANT *pvarArgIn, WCHAR* pchOptions,
|
|
VARIANT *pvArgOut);
|
|
#define REGKEY_ACTIVESETUP "Software\\Microsoft\\Active Setup"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CClientCaps
|
|
|
|
|
|
STDMETHODIMP CClientCaps::get_javaEnabled(VARIANT_BOOL * pVal)
|
|
{
|
|
IOmNavigator *pClientInformation;
|
|
HRESULT hr = GetClientInformation(&pClientInformation);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pClientInformation->javaEnabled(pVal);
|
|
pClientInformation->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_cookieEnabled(VARIANT_BOOL * pVal)
|
|
{
|
|
IOmNavigator *pClientInformation;
|
|
HRESULT hr = GetClientInformation(&pClientInformation);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pClientInformation->get_cookieEnabled(pVal);
|
|
pClientInformation->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_cpuClass(BSTR * p)
|
|
{
|
|
IOmNavigator *pClientInformation;
|
|
HRESULT hr = GetClientInformation(&pClientInformation);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pClientInformation->get_cpuClass(p);
|
|
pClientInformation->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_systemLanguage(BSTR * p)
|
|
{
|
|
IOmNavigator *pClientInformation;
|
|
HRESULT hr = GetClientInformation(&pClientInformation);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pClientInformation->get_systemLanguage(p);
|
|
pClientInformation->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_userLanguage(BSTR * p)
|
|
{
|
|
IOmNavigator *pClientInformation;
|
|
HRESULT hr = GetClientInformation(&pClientInformation);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pClientInformation->get_userLanguage(p);
|
|
pClientInformation->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_platform(BSTR * p)
|
|
{
|
|
IOmNavigator *pClientInformation;
|
|
HRESULT hr = GetClientInformation(&pClientInformation);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pClientInformation->get_platform(p);
|
|
pClientInformation->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_connectionSpeed(long * p)
|
|
{
|
|
IOmNavigator *pClientInformation;
|
|
HRESULT hr = GetClientInformation(&pClientInformation);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pClientInformation->get_connectionSpeed(p);
|
|
pClientInformation->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_onLine(VARIANT_BOOL *p)
|
|
{
|
|
IOmNavigator *pClientInformation;
|
|
HRESULT hr = GetClientInformation(&pClientInformation);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pClientInformation->get_onLine(p);
|
|
pClientInformation->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_colorDepth(long * p)
|
|
{
|
|
IHTMLScreen *pScreen;
|
|
HRESULT hr = GetScreen(&pScreen);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pScreen->get_colorDepth(p);
|
|
pScreen->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_bufferDepth(long * p)
|
|
{
|
|
IHTMLScreen *pScreen;
|
|
HRESULT hr = GetScreen(&pScreen);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pScreen->get_bufferDepth(p);
|
|
pScreen->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_width(long * p)
|
|
{
|
|
IHTMLScreen *pScreen;
|
|
HRESULT hr = GetScreen(&pScreen);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pScreen->get_width(p);
|
|
pScreen->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_height(long * p)
|
|
{
|
|
IHTMLScreen *pScreen;
|
|
HRESULT hr = GetScreen(&pScreen);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pScreen->get_height(p);
|
|
pScreen->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_availHeight(long * p)
|
|
{
|
|
IHTMLScreen *pScreen;
|
|
HRESULT hr = GetScreen(&pScreen);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pScreen->get_availHeight(p);
|
|
pScreen->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_availWidth(long * p)
|
|
{
|
|
IHTMLScreen *pScreen;
|
|
HRESULT hr = GetScreen(&pScreen);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pScreen->get_availWidth(p);
|
|
pScreen->Release();
|
|
}
|
|
return hr;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::get_connectionType(BSTR *pbstr)
|
|
{
|
|
DWORD dwFlags = 0;
|
|
BOOL bConnected;
|
|
HRESULT hr = S_OK;
|
|
DWORD dwState = 0;
|
|
DWORD dwSize = sizeof(dwState);
|
|
BOOL bGlobalOffline = FALSE ; // Has the user gone into offline mode, inspite of having a connection.
|
|
|
|
if (InternetQueryOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &dwState, &dwSize))
|
|
{
|
|
if (dwState & INTERNET_STATE_DISCONNECTED_BY_USER)
|
|
bGlobalOffline = TRUE;
|
|
}
|
|
|
|
bConnected = InternetGetConnectedStateEx(&dwFlags, NULL, 0, 0);
|
|
|
|
|
|
// NOTE: We use literal strings in code and resources so these don't get localized.
|
|
if (bConnected && !bGlobalOffline)
|
|
{
|
|
// If we are connected figure out how.
|
|
if (dwFlags & INTERNET_CONNECTION_MODEM )
|
|
{
|
|
*pbstr = SysAllocString(L"modem");
|
|
}
|
|
else if (dwFlags & INTERNET_CONNECTION_LAN )
|
|
{
|
|
*pbstr = SysAllocString(L"lan");
|
|
}
|
|
else
|
|
{
|
|
// Don't know what to do here.
|
|
*pbstr = SysAllocString(L"");
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pbstr = SysAllocString(L"offline");
|
|
}
|
|
|
|
if (!*pbstr)
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::isComponentInstalled(BSTR bstrName, BSTR bstrType, BSTR bstrVersion, VARIANT_BOOL *pVal)
|
|
{
|
|
|
|
if (pVal == NULL)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
DWORD dwVersionMS;
|
|
DWORD dwVersionLS;
|
|
HRESULT hr = GetVersion(bstrName, bstrType, &dwVersionMS, &dwVersionLS);
|
|
HRESULT hrRet;
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
if (bstrVersion && bstrVersion[0] != L'\0')
|
|
{
|
|
// User wants us to check for minimum version number.
|
|
DWORD dwVersionReqdMS;
|
|
DWORD dwVersionReqdLS;
|
|
hr = GetVersionFromString(bstrVersion, &dwVersionReqdMS, &dwVersionReqdLS);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if ( (dwVersionMS > dwVersionReqdMS) ||
|
|
(dwVersionMS == dwVersionReqdMS && dwVersionLS >= dwVersionReqdLS)
|
|
)
|
|
{
|
|
*pVal = TRUE;
|
|
}
|
|
else
|
|
{
|
|
*pVal = FALSE;
|
|
}
|
|
hrRet = S_OK;
|
|
}
|
|
else
|
|
{
|
|
*pVal = FALSE;
|
|
hrRet = S_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*pVal = TRUE;
|
|
hrRet = S_OK;
|
|
}
|
|
}
|
|
else if (hr == S_FALSE)
|
|
{
|
|
*pVal = FALSE;
|
|
hrRet = S_OK;
|
|
}
|
|
else
|
|
{
|
|
// This is really an error, but to avoid script error dialogs we still return a success
|
|
// code, but indicate that the component is not installed.
|
|
*pVal = FALSE;
|
|
hrRet = S_FALSE;
|
|
}
|
|
|
|
return hrRet;
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::getComponentVersion(BSTR bstrName, BSTR bstrType, BSTR* pbstrVersion)
|
|
{
|
|
if (pbstrVersion == NULL)
|
|
return E_POINTER;
|
|
|
|
DWORD dwVersionMS;
|
|
DWORD dwVersionLS;
|
|
HRESULT hr = GetVersion(bstrName, bstrType, &dwVersionMS, &dwVersionLS);
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
hr = GetStringFromVersion(dwVersionMS, dwVersionLS, pbstrVersion);
|
|
}
|
|
else
|
|
{
|
|
*pbstrVersion = SysAllocString(L"");
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::compareVersions(BSTR bstrVer1, BSTR bstrVer2, long *p)
|
|
{
|
|
if ( p == NULL)
|
|
return E_POINTER;
|
|
|
|
HRESULT hr = S_OK;
|
|
if (bstrVer1 == NULL || bstrVer2 == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
DWORD dwMS1 = 0 , dwLS1 = 0, dwMS2 = 0, dwLS2 = 0;
|
|
|
|
HRESULT hr1 = GetVersionFromString(bstrVer1, &dwMS1, &dwLS1);
|
|
HRESULT hr2 = GetVersionFromString(bstrVer2, &dwMS2, &dwLS2);
|
|
|
|
if (SUCCEEDED(hr1) && SUCCEEDED(hr2))
|
|
{
|
|
if (dwMS1 > dwMS2)
|
|
*p = 1;
|
|
else if (dwMS1 < dwMS2)
|
|
*p = -1;
|
|
else /* dwMS1 == dwMS2 */
|
|
{
|
|
if (dwLS1 > dwLS2)
|
|
*p = 1;
|
|
else if (dwLS1 < dwLS2)
|
|
*p = -1;
|
|
else
|
|
*p = 0;
|
|
}
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
*p = 1; // ISSUE: what is the right thing to do here.
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CClientCaps::addComponentRequest(BSTR bstrName, BSTR bstrType, BSTR bstrVer)
|
|
// Checks if the passed component is installed (optionally at or above the passed version)
|
|
// and if not, adds it to a list of components to be added at a call to DoComponentRequest
|
|
{
|
|
HRESULT hr = 0;
|
|
VARIANT_BOOL bInstalled;
|
|
uCLSSPEC classspec;
|
|
int iLength;
|
|
int iRes;
|
|
LPWSTR pwszComponentID = NULL;
|
|
|
|
LPSTR pszComponentID = NULL;
|
|
|
|
|
|
|
|
hr = isComponentInstalled(bstrName, bstrType, bstrVer, &bInstalled);
|
|
|
|
// Unknown Error
|
|
if(! SUCCEEDED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
// Component is already installed
|
|
if(bInstalled)
|
|
{
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
// otherwise, add the comnponent to the list of components to be installed
|
|
|
|
|
|
// First figure out the type of the component and populate the CLSSPEC appropriately.
|
|
if (0 == StrCmpICW(bstrType, L"mimetype"))
|
|
{
|
|
classspec.tyspec = TYSPEC_MIMETYPE;
|
|
classspec.tagged_union.pMimeType = bstrName;
|
|
}
|
|
else if (0 == StrCmpICW(bstrType, L"progid"))
|
|
{
|
|
classspec.tyspec = TYSPEC_PROGID;
|
|
classspec.tagged_union.pProgId = bstrName;
|
|
}
|
|
else if (0 == StrCmpICW(bstrType, L"clsid"))
|
|
{
|
|
classspec.tyspec = TYSPEC_CLSID;
|
|
// Convert class-id string to GUID.
|
|
hr = CLSIDFromString(bstrName, &classspec.tagged_union.clsid);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
}
|
|
else if (0 == StrCmpICW(bstrType, L"componentid")) //internally called a FeatureID
|
|
{
|
|
classspec.tyspec = TYSPEC_FILENAME;
|
|
classspec.tagged_union.pFileName = bstrName;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
// Get a ComponentID from the uCLSSPEC
|
|
hr = GetComponentIDFromCLSSPEC(&classspec, &pszComponentID);
|
|
if(FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
// Convert the ComponentID to a wide character string (wide expected by ShowHTMLDialog)
|
|
iLength = lstrlenA(pszComponentID) + 1;
|
|
pwszComponentID = new WCHAR[iLength];
|
|
if(pwszComponentID == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
iRes = MultiByteToWideChar(CP_ACP,0,pszComponentID, iLength,
|
|
pwszComponentID, iLength);
|
|
if(iRes == 0)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
if(pwszComponentID)
|
|
{
|
|
delete [] pwszComponentID;
|
|
pwszComponentID = NULL;
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
// initialize array for first time
|
|
if(ppwszComponents == NULL)
|
|
{
|
|
// Hard coded initial size of 10; It's in the right order of magnitude
|
|
// Maybe this should be in a constant, but that seems a lot of overhead
|
|
// for such a small feature
|
|
ppwszComponents = new LPWSTR[10];
|
|
iComponentNum = 0;
|
|
iComponentCap = 10;
|
|
}
|
|
|
|
// Resizing the array of Components
|
|
if(iComponentNum >= iComponentCap)
|
|
{
|
|
iComponentCap *= 2;
|
|
LPWSTR * ppwszOldComponents = ppwszComponents;
|
|
ppwszComponents = NULL;
|
|
ppwszComponents = new LPWSTR[iComponentCap];
|
|
if(ppwszComponents == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
ppwszComponents = ppwszOldComponents;
|
|
if(pwszComponentID)
|
|
{
|
|
delete [] pwszComponentID;
|
|
pwszComponentID = NULL;
|
|
}
|
|
goto Exit;
|
|
}
|
|
for(int i = 0; i < iComponentNum; i++)
|
|
{
|
|
ppwszComponents[i] = ppwszOldComponents[i];
|
|
}
|
|
delete [] ppwszOldComponents;
|
|
}
|
|
|
|
ppwszComponents[iComponentNum++] = pwszComponentID;
|
|
hr = S_OK;
|
|
|
|
Exit:
|
|
|
|
if(pszComponentID)
|
|
{
|
|
CoTaskMemFree(pszComponentID);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::doComponentRequest(VARIANT_BOOL * pVal)
|
|
// Uses the url in HKLM\Software\Microsoft\Active Setup\JITSetupPage
|
|
// to add the list of components logged using AddComponentRequest
|
|
{
|
|
SHOWHTMLDIALOGFN *pfnShowHTMLDialog = NULL;
|
|
HINSTANCE hInst = 0;
|
|
HRESULT hr = 0;
|
|
LPWSTR pwszFeatures = NULL;
|
|
IMoniker *pMk = NULL;
|
|
VARIANT vtDialogArg;
|
|
VariantInit(&vtDialogArg);
|
|
VARIANT vtRetVal;
|
|
VariantInit(&vtRetVal);
|
|
int i,j,k,iFeatureArgLength;
|
|
TCHAR *pszSETUPPAGE = _T("JITSetupPage");
|
|
WCHAR wszDownLoadPage[MAX_PATH];
|
|
WCHAR wszDownLoadPageReg[MAX_PATH];
|
|
// LPWSTR pwszDownLoadPage = NULL;
|
|
HKEY hkeyActiveSetup = 0;
|
|
LONG lResult = 0;
|
|
DWORD dwType;
|
|
DWORD dwSize = INTERNET_MAX_URL_LENGTH;
|
|
int iLength = 0;
|
|
int iRes = 0;
|
|
OSVERSIONINFO osvi;
|
|
|
|
|
|
// NT5 should never show JIT dialog.
|
|
|
|
osvi.dwOSVersionInfoSize = sizeof(osvi);
|
|
GetVersionEx(&osvi);
|
|
|
|
if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
|
|
osvi.dwMajorVersion >= 5) {
|
|
hr = E_ACCESSDENIED;
|
|
goto Exit;
|
|
}
|
|
|
|
// No Component Requests to process. Return success and exit
|
|
if(iComponentNum <= 0)
|
|
{
|
|
if(pVal)
|
|
*pVal = TRUE;
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
// calculate space needed
|
|
iFeatureArgLength = 0;
|
|
// Length for the characters in the ComponentIDs
|
|
for(k = 0; k < iComponentNum; k++)
|
|
{
|
|
iFeatureArgLength += lstrlenW(ppwszComponents[k]);
|
|
}
|
|
iFeatureArgLength += 9*iComponentNum - 1; // "Feature="s and &'s
|
|
iFeatureArgLength += 10; // breathing room
|
|
pwszFeatures = new WCHAR[iFeatureArgLength];
|
|
if(!pwszFeatures)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
// copy the individual strings to one big string, seperated by "&feature="
|
|
// i.e. "feature=JavaVM&feature=MOBILEPKx86"
|
|
// i is the position in the full string
|
|
// k is the current substring
|
|
for(i = k = 0; k < iComponentNum; k++)
|
|
{
|
|
// "feature="
|
|
StrCpyW(pwszFeatures + i, L"feature=");
|
|
i += 8;
|
|
iLength = lstrlenW(ppwszComponents[k]);
|
|
// componentID
|
|
StrCpyW(pwszFeatures + i, ppwszComponents[k]);
|
|
i += iLength;
|
|
// "&" || '\0'
|
|
if(k + 1 < iComponentNum)
|
|
{
|
|
pwszFeatures[i] = L'&';
|
|
i++;
|
|
}
|
|
else
|
|
{
|
|
pwszFeatures[i] = L'\0';
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// Change string to variant
|
|
vtDialogArg.vt = VT_BSTR;
|
|
vtDialogArg.bstrVal = SysAllocString(pwszFeatures);
|
|
if(! vtDialogArg.bstrVal)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
// get the download dialog page from the registry
|
|
if ((lResult = RegOpenKeyExA( HKEY_LOCAL_MACHINE,
|
|
REGKEY_ACTIVESETUP, 0, KEY_READ,
|
|
&hkeyActiveSetup)) != ERROR_SUCCESS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
|
|
if (lResult = SHQueryValueEx(hkeyActiveSetup, pszSETUPPAGE, NULL,
|
|
&dwType, wszDownLoadPageReg, &dwSize) != ERROR_SUCCESS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
|
|
if (wszDownLoadPageReg) {
|
|
WCHAR *wszDownLoadPageFile = NULL;
|
|
|
|
wszDownLoadPageFile = PathFindFileNameW(wszDownLoadPageReg);
|
|
hr = SHGetWebFolderFilePathW(wszDownLoadPageFile, wszDownLoadPage, MAX_PATH);
|
|
if (FAILED(hr)) {
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
/* iLength = lstrlenA(szDownLoadPage) + 1;
|
|
pwszDownLoadPage = new WCHAR[iLength];
|
|
iRes = MultiByteToWideChar(CP_ACP,0,szDownLoadPage, iLength,
|
|
pwszDownLoadPage, iLength);
|
|
if(iRes == 0)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
*/
|
|
// Get Moniker to The JIT Dialog page
|
|
hr = CreateURLMoniker(NULL, wszDownLoadPage, &pMk);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
|
|
// Get the ShowHTMLDialog function from the mshtml dll
|
|
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;
|
|
}
|
|
|
|
|
|
// Show the JIT download page; the rest of the work is accomplished there
|
|
hr = (*pfnShowHTMLDialog)(NULL, pMk, &vtDialogArg, NULL, &vtRetVal);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
// Process the return value
|
|
if ((vtRetVal.vt == VT_I4) && vtRetVal.lVal != S_OK )
|
|
{
|
|
hr = S_FALSE;
|
|
if(pVal)
|
|
*pVal = FALSE;
|
|
}
|
|
else if(vtRetVal.vt != VT_I4)
|
|
{
|
|
hr = S_FALSE;
|
|
if(pVal)
|
|
*pVal = FALSE;
|
|
}
|
|
else
|
|
{
|
|
hr = S_OK;
|
|
if(pVal)
|
|
*pVal = TRUE;
|
|
}
|
|
|
|
// Since everything was successful, clear the component list
|
|
clearComponentRequest();
|
|
|
|
|
|
|
|
Exit: // Goto needed because these resources must be cleaned up on all errors and successes
|
|
|
|
// clear string
|
|
if(pwszFeatures)
|
|
delete [] pwszFeatures;
|
|
if(pMk)
|
|
{
|
|
pMk->Release();
|
|
}
|
|
// if(pwszDownLoadPage)
|
|
// {
|
|
// delete [] pwszDownLoadPage;
|
|
// pwszDownLoadPage = NULL;
|
|
// }
|
|
VariantClear(&vtRetVal);
|
|
VariantClear(&vtDialogArg);
|
|
if(hInst)
|
|
{
|
|
FreeLibrary(hInst);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::clearComponentRequest()
|
|
// Clears the list of components logged using AddComponentRequest
|
|
{
|
|
int i;
|
|
for(i = 0; i < iComponentNum; i++)
|
|
{
|
|
if(ppwszComponents[i] != NULL)
|
|
{
|
|
// delete the wide string
|
|
delete [] ppwszComponents[i];
|
|
ppwszComponents[i] = NULL;
|
|
}
|
|
}
|
|
iComponentNum = 0;
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// IElementBehavior methods
|
|
|
|
STDMETHODIMP CClientCaps::Init(IElementBehaviorSite *pSite)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (pSite != NULL)
|
|
{
|
|
m_pSite = pSite;
|
|
m_pSite->AddRef();
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::Notify(LONG lNotify, VARIANT * pVarNotify)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
// Helper functions for internal use only
|
|
|
|
STDMETHODIMP CClientCaps::GetHTMLDocument(IHTMLDocument2 **ppDoc)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (m_pSite != NULL)
|
|
{
|
|
IHTMLElement *pElement = NULL;
|
|
hr = m_pSite->GetElement(&pElement);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IDispatch * pDispDoc = NULL;
|
|
hr = pElement->get_document(&pDispDoc);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pDispDoc->QueryInterface(IID_IHTMLDocument2, (void **)ppDoc);
|
|
pDispDoc->Release();
|
|
}
|
|
pElement->Release();
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CClientCaps::GetHTMLWindow(IHTMLWindow2 **ppWindow)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IHTMLDocument2 *pDoc = NULL;
|
|
|
|
hr = GetHTMLDocument(&pDoc);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pDoc->get_parentWindow(ppWindow);
|
|
pDoc->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::GetClientInformation(IOmNavigator **ppNav)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IHTMLWindow2 *pWindow = NULL;
|
|
|
|
hr = GetHTMLWindow(&pWindow);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pWindow->get_clientInformation(ppNav);
|
|
pWindow->Release();
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
STDMETHODIMP CClientCaps::GetScreen(IHTMLScreen **ppScreen)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IHTMLWindow2 *pWindow = NULL;
|
|
|
|
hr = GetHTMLWindow(&pWindow);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pWindow->get_screen(ppScreen);
|
|
pWindow->Release();
|
|
}
|
|
|
|
return hr ;
|
|
}
|
|
|
|
// Returns S_OK if component is installed and the version # in pbstrVersion.
|
|
// Returns S_FALSE if component is not installed.
|
|
// E_INVALIDARG if the input args are ill-formed or not an IE component.
|
|
// E_* if it encounters an error.
|
|
|
|
STDMETHODIMP CClientCaps::GetVersion(BSTR bstrName, BSTR bstrType, LPDWORD pdwFileVersionMS, LPDWORD pdwFileVersionLS)
|
|
{
|
|
if (bstrName == NULL || bstrType == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
uCLSSPEC classspec;
|
|
HRESULT hr = E_FAIL;
|
|
QUERYCONTEXT qc = {0};
|
|
|
|
// First figure out the type of the component and populate the CLSSPEC appropriately.
|
|
if (0 == StrCmpICW(bstrType, L"mimetype"))
|
|
{
|
|
classspec.tyspec = TYSPEC_MIMETYPE;
|
|
classspec.tagged_union.pMimeType = bstrName;
|
|
}
|
|
else if (0 == StrCmpICW(bstrType, L"progid"))
|
|
{
|
|
classspec.tyspec = TYSPEC_PROGID;
|
|
classspec.tagged_union.pProgId = bstrName;
|
|
}
|
|
else if (0 == StrCmpICW(bstrType, L"clsid"))
|
|
{
|
|
classspec.tyspec = TYSPEC_CLSID;
|
|
// Convert class-id string to GUID.
|
|
hr = CLSIDFromString(bstrName, &classspec.tagged_union.clsid);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
}
|
|
else if (0 == StrCmpICW(bstrType, L"componentid"))
|
|
{
|
|
classspec.tyspec = TYSPEC_FILENAME;
|
|
classspec.tagged_union.pFileName = bstrName;
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
hr = FaultInIEFeature(NULL, &classspec, &qc, FIEF_FLAG_PEEK);
|
|
|
|
if (hr == S_OK || (qc.dwVersionHi != 0 || qc.dwVersionLo != 0))
|
|
{
|
|
// Put the version #'s that we found in the out args.
|
|
if (pdwFileVersionMS != NULL)
|
|
*pdwFileVersionMS = qc.dwVersionHi;
|
|
if (pdwFileVersionLS != NULL)
|
|
*pdwFileVersionLS = qc.dwVersionLo;
|
|
|
|
hr = S_OK;
|
|
}
|
|
else if ( hr == S_FALSE)
|
|
{
|
|
// this implies the component is not recognized as an IE component.
|
|
// The input argument must be incorrect in this case.
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if ( hr == HRESULT_FROM_WIN32(ERROR_PRODUCT_UNINSTALLED))
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// %%Function: GetVersionFromString
|
|
//
|
|
// converts version in text format (a,b,c,d) into two dwords (a,b), (c,d)
|
|
// The printed version number is of format a.b.d (but, we don't care)
|
|
// ---------------------------------------------------------------------------
|
|
HRESULT
|
|
CClientCaps::GetVersionFromString(LPCOLESTR szBuf, LPDWORD pdwFileVersionMS, LPDWORD pdwFileVersionLS)
|
|
{
|
|
LPCOLESTR pch = szBuf;
|
|
OLECHAR ch;
|
|
|
|
*pdwFileVersionMS = 0;
|
|
*pdwFileVersionLS = 0;
|
|
|
|
if (!pch) // default to zero if none provided
|
|
return S_OK;
|
|
|
|
if (StrCmpCW(pch, L"-1,-1,-1,-1") == 0) {
|
|
*pdwFileVersionMS = 0xffffffff;
|
|
*pdwFileVersionLS = 0xffffffff;
|
|
return S_OK;
|
|
}
|
|
|
|
USHORT n = 0;
|
|
|
|
USHORT a = 0;
|
|
USHORT b = 0;
|
|
USHORT c = 0;
|
|
USHORT d = 0;
|
|
|
|
enum HAVE { HAVE_NONE, HAVE_A, HAVE_B, HAVE_C, HAVE_D } have = HAVE_NONE;
|
|
|
|
|
|
for (ch = *pch++;;ch = *pch++) {
|
|
|
|
if ((ch == L',') || (ch == L'\0')) {
|
|
|
|
switch (have) {
|
|
|
|
case HAVE_NONE:
|
|
a = n;
|
|
have = HAVE_A;
|
|
break;
|
|
|
|
case HAVE_A:
|
|
b = n;
|
|
have = HAVE_B;
|
|
break;
|
|
|
|
case HAVE_B:
|
|
c = n;
|
|
have = HAVE_C;
|
|
break;
|
|
|
|
case HAVE_C:
|
|
d = n;
|
|
have = HAVE_D;
|
|
break;
|
|
|
|
case HAVE_D:
|
|
return E_INVALIDARG; // invalid arg
|
|
}
|
|
|
|
if (ch == L'\0') {
|
|
// all done convert a,b,c,d into two dwords of version
|
|
|
|
*pdwFileVersionMS = ((a << 16)|b);
|
|
*pdwFileVersionLS = ((c << 16)|d);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
n = 0; // reset
|
|
|
|
} else if ( (ch < L'0') || (ch > L'9'))
|
|
return E_INVALIDARG; // invalid arg
|
|
else
|
|
n = n*10 + (ch - L'0');
|
|
|
|
|
|
} /* end forever */
|
|
|
|
// NEVERREACHED
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// %%Function: GetStringFromVersion
|
|
//
|
|
// converts version from two DWORD's to the string format a,b,c,d
|
|
// ---------------------------------------------------------------------------
|
|
|
|
HRESULT CClientCaps::GetStringFromVersion(DWORD dwVersionMS, DWORD dwVersionLS, BSTR *pbstrVersion)
|
|
{
|
|
if (pbstrVersion == NULL)
|
|
return E_POINTER;
|
|
|
|
// 16-bits is a max of 5 decimal digits * 4 + 3 ','s + null terminator
|
|
const int maxStringSize = 5 * 4 + 3 * 1 + 1;
|
|
OLECHAR rgch[maxStringSize];
|
|
|
|
USHORT a = (USHORT)(dwVersionMS >> 16);
|
|
USHORT b = (USHORT)(dwVersionMS & 0xffff);
|
|
USHORT c = (USHORT)(dwVersionLS >> 16);
|
|
USHORT d = (USHORT)(dwVersionLS & 0xffff);
|
|
|
|
OLECHAR rgchFormat[] = L"%hu,%hu,%hu,%hu";
|
|
|
|
int nRet = wnsprintfW(rgch, maxStringSize, rgchFormat, a, b, c, d);
|
|
|
|
HRESULT hr;
|
|
if (nRet < 7 ) // 0,0,0,0
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
{
|
|
*pbstrVersion = SysAllocString(rgch);
|
|
if (*pbstrVersion == NULL)
|
|
hr = E_OUTOFMEMORY;
|
|
else
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|