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.
4136 lines
121 KiB
4136 lines
121 KiB
// ===========================================================================
|
|
// File: SOFTDIST.CXX
|
|
// Channel Software Distribution Unit Tag handler
|
|
//
|
|
|
|
#include <cdlpch.h>
|
|
#include <winineti.h>
|
|
#include <shlwapip.h>
|
|
#include <msxml.h>
|
|
|
|
LPCSTR szWinNT = "WinNT";
|
|
LPCSTR szWin95 = "Win95";
|
|
|
|
LPCSTR szPlatform = "Win32";
|
|
|
|
LPCOLESTR szMSInstallProgID = L"MSInstall.SoftDistExt";
|
|
|
|
const TCHAR c_szTrayUI[] = TEXT("MS_WebcheckMonitor"); // Do not change this string. LoadWC relies on it.
|
|
const TCHAR c_szTrayMenu[] = TEXT("TrayMenu");
|
|
|
|
const LPTSTR szControlSetup = _T("Status");
|
|
const DWORD dwStatusOK = 0;
|
|
const DWORD dwStatusSuspend = 1;
|
|
const DWORD dwStatusResume = 2;
|
|
const DWORD dwStatusAbort = 3;
|
|
|
|
const UM_NEEDREBOOT = WM_USER + 16;
|
|
|
|
extern char *g_szProcessorTypes[];
|
|
extern char g_szBrowserLang[];
|
|
extern int g_lenBrowserLang;
|
|
extern char g_szBrowserPrimaryLang[];
|
|
extern int g_lenBrowserPrimaryLang;
|
|
extern LCID g_lcidBrowser;
|
|
|
|
|
|
|
|
#define ERROR_EXIT(cond) if (!(cond)) { \
|
|
goto Exit;}
|
|
|
|
extern COleAutDll g_OleAutDll;
|
|
|
|
//REVIEW: This is located in cdl.cxx for page swapping reasons. (OSD's are processed
|
|
// more than CDF/<SoftDist>'s?
|
|
|
|
HRESULT ProcessImplementation(IXMLElement *pConfig,
|
|
CList<CCodeBaseHold *, CCodeBaseHold *> *pcbhList,
|
|
LCID lcidOverride,
|
|
#ifdef WX86
|
|
CMultiArch *MultiArch,
|
|
#endif
|
|
LPWSTR szBaseURL);
|
|
|
|
|
|
HRESULT
|
|
GetAbstract(HKEY hkeyAv, LPSTR *ppszAbstract)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"GetAbstract",
|
|
"%#x, %#x",
|
|
hkeyAv, ppszAbstract
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD Size,dwType;
|
|
LONG lResult;
|
|
|
|
if (ppszAbstract) {
|
|
|
|
*ppszAbstract = NULL;
|
|
|
|
if (RegQueryValueEx(hkeyAv, REGVAL_ABSTRACT_AVAILABLE, NULL, &dwType,
|
|
NULL, &Size) == ERROR_SUCCESS) {
|
|
|
|
*ppszAbstract = new char[Size];
|
|
|
|
if (!*ppszAbstract) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
if ((lResult = RegQueryValueEx(hkeyAv, REGVAL_ABSTRACT_AVAILABLE, NULL, &dwType,
|
|
(unsigned char *)*ppszAbstract, &Size) != ERROR_SUCCESS)) {
|
|
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
BOOL
|
|
IsAbstractDifferent(HKEY hkeyAv, LPSTR szNewAbstract)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Bool,
|
|
"IsAbstractDifferent",
|
|
"%#x, %.80q",
|
|
hkeyAv, szNewAbstract
|
|
));
|
|
|
|
LPSTR pszOldAbstract = NULL;
|
|
BOOL bDifferent = TRUE;
|
|
|
|
if ((GetAbstract(hkeyAv, &pszOldAbstract) == S_OK) && pszOldAbstract) {
|
|
|
|
if (szNewAbstract)
|
|
bDifferent = lstrcmp(pszOldAbstract, szNewAbstract) != 0;
|
|
|
|
delete pszOldAbstract;
|
|
|
|
|
|
}
|
|
|
|
DEBUG_LEAVE(bDifferent);
|
|
return bDifferent;
|
|
}
|
|
|
|
/******************************************************************************
|
|
Constructor, Destructor and helper methods
|
|
******************************************************************************/
|
|
|
|
CSoftDist::CSoftDist()
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
None,
|
|
"CSoftDist::CSoftDist",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
DllAddRef();
|
|
m_cRef = 1;
|
|
m_szDistUnit = NULL;
|
|
|
|
m_szCDFURL = NULL;
|
|
|
|
m_szTitle = NULL;
|
|
m_szAbstract = NULL;
|
|
m_szHREF = NULL;
|
|
|
|
m_szLanguages = NULL;
|
|
|
|
m_dwVersionMS = m_dwVersionLS = 0;
|
|
|
|
m_dwVersionAdvertisedMS = m_dwVersionAdvertisedLS = 0;
|
|
m_dwAdState = SOFTDIST_ADSTATE_NONE;
|
|
|
|
m_Style = STYLE_MSICD;
|
|
|
|
m_sdMSInstall = NULL;
|
|
m_pClientBSC = NULL;
|
|
m_szBaseURL = NULL;
|
|
|
|
memset(&m_distunitinst, 0, sizeof(DISTUNITINST));
|
|
|
|
DetermineOSAndCPUVersion();
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
CSoftDist::~CSoftDist()
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
None,
|
|
"CSoftDist::~CSoftDist",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
Assert(m_cRef == 0);
|
|
|
|
SAFERELEASE(m_sdMSInstall);
|
|
|
|
SAFEDELETE(m_szDistUnit);
|
|
|
|
SAFEDELETE(m_szCDFURL);
|
|
SAFEDELETE(m_szTitle);
|
|
SAFEDELETE(m_szAbstract);
|
|
SAFEDELETE(m_szHREF);
|
|
SAFEDELETE(m_szLanguages);
|
|
SAFEDELETE(m_pClientBSC);
|
|
SAFEDELETE(m_szBaseURL);
|
|
|
|
DllRelease();
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
/******************************************************************************
|
|
IUnknown Methods
|
|
******************************************************************************/
|
|
|
|
STDMETHODIMP CSoftDist::QueryInterface(
|
|
REFIID iid,
|
|
void** ppvObject)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::IUnknown::QueryInterface",
|
|
"this=%#x, %#x, %#x",
|
|
this, &iid, ppvObject
|
|
));
|
|
|
|
*ppvObject = NULL;
|
|
|
|
if (iid == IID_IUnknown)
|
|
{
|
|
*ppvObject = (void*)this;
|
|
}
|
|
else if (iid == IID_ISoftDistExt)
|
|
{
|
|
*ppvObject = (void*)(ISoftDistExt*)this;
|
|
}
|
|
|
|
if (*ppvObject)
|
|
{
|
|
((LPUNKNOWN)*ppvObject)->AddRef();
|
|
|
|
DEBUG_LEAVE(S_OK);
|
|
return S_OK;
|
|
}
|
|
|
|
DEBUG_LEAVE(E_NOINTERFACE);
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CSoftDist::AddRef()
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Dword,
|
|
"CSoftDist::IUnknown::AddRef",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
ULONG ulRet = ++m_cRef;
|
|
|
|
DEBUG_LEAVE(ulRet);
|
|
return ulRet;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CSoftDist::Release()
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Dword,
|
|
"CSoftDist::IUnknown::Release",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
if (--m_cRef)
|
|
{
|
|
DEBUG_LEAVE(m_cRef);
|
|
return m_cRef;
|
|
}
|
|
|
|
delete this;
|
|
|
|
DEBUG_LEAVE(0);
|
|
return 0;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
ISoftDistExt Methods
|
|
******************************************************************************/
|
|
/*
|
|
* return values:
|
|
* All success codes indicate user should be notified through channel UI.
|
|
*
|
|
* S_OK: Locally not available, Send Email (Show in channel UI)
|
|
* S_FALSE: Locally not available. Don't send Email. (But show in channel UI)
|
|
*
|
|
* ERROR_ALREADY_EXISTS:Locally already installed. Don't send email/advertise.
|
|
* ERROR: Processing error, fail.
|
|
*
|
|
* For additional information on usage flags, set dwReserved to a valid pointer
|
|
* and it will set appropriate bit fields
|
|
*
|
|
*/
|
|
STDMETHODIMP
|
|
CSoftDist::ProcessSoftDist(LPCWSTR szCDFURL, IXMLElement *pSoftDist, LPSOFTDISTINFO psdi)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::ProcessSoftDist",
|
|
"this=%#x, %.80wq, %#x, %#x",
|
|
this, szCDFURL, pSoftDist, psdi
|
|
));
|
|
|
|
HRESULT hr = S_FALSE; // default: send email, no precache
|
|
char szVersion[MAX_PATH];
|
|
char szStyle[MAX_PATH];
|
|
LPSTR szThisOS = NULL;
|
|
LPWSTR szTitle = NULL;
|
|
IXMLElement *pTitle = NULL, *pConfig = NULL, *pLang = NULL,
|
|
*pAbstract = NULL, *pUsage = NULL, *pDeleteOnInstall = NULL;
|
|
IXMLElement *pParent = NULL;
|
|
BOOL bPrecache = FALSE, bChannelUIOnly = FALSE, bAutoInstall = FALSE,
|
|
bIsPrecached = FALSE, bDeleteOnInstall = FALSE;
|
|
BOOL fFoundConfig = FALSE;
|
|
LPDWORD lpFlags = NULL;
|
|
BOOL bIsValidCDF = FALSE;
|
|
|
|
if (psdi) {
|
|
if (psdi->cbSize < sizeof(SOFTDISTINFO))
|
|
{
|
|
DEBUG_LEAVE(E_INVALIDARG);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
psdi->dwFlags = 0;
|
|
}
|
|
|
|
if (szCDFURL && FAILED((hr=::Unicode2Ansi(szCDFURL, &m_szCDFURL))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// Try to use the BASE tag from the channel.
|
|
|
|
// BUGBUG: This is a really convoluted way to get at the channel
|
|
// BASE URL, but there is no way for webcheck to pass this
|
|
// information to us w/o changing the ISoftDistExt interface.
|
|
|
|
pSoftDist->get_parent(&pParent);
|
|
if (pParent) {
|
|
DupAttribute(pParent, CHANNEL_ATTRIB_BASE, &m_szBaseURL);
|
|
SAFERELEASE(pParent);
|
|
}
|
|
|
|
hr = DupAttribute(pSoftDist, DU_ATTRIB_NAME, &m_szDistUnit);
|
|
ERROR_EXIT(SUCCEEDED(hr));
|
|
|
|
// code around assumes that MAX_PATH is MAX size of dist unit
|
|
// we try to make a key name with the distunit and that limit is
|
|
// now MAX_PATH. Hence the reasoning to limit this to MAX_PATH
|
|
|
|
if (lstrlenW(m_szDistUnit) >= MAX_PATH) {
|
|
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
goto Exit;
|
|
}
|
|
|
|
hr = DupAttributeA(pSoftDist, DU_ATTRIB_HREF, &m_szHREF);
|
|
ERROR_EXIT(SUCCEEDED(hr));
|
|
if (psdi) {
|
|
hr = Ansi2Unicode( m_szHREF, &psdi->szHREF );
|
|
if ( FAILED(hr) )
|
|
goto Exit;
|
|
}
|
|
|
|
hr = GetAttributeA(pSoftDist, DU_ATTRIB_VERSION, szVersion, MAX_PATH);
|
|
ERROR_EXIT(SUCCEEDED(hr));
|
|
|
|
if ( FAILED(GetVersionFromString(szVersion, &m_dwVersionMS, &m_dwVersionLS))){
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
if (!(m_dwVersionMS | m_dwVersionLS)) { // zero is invalid advt version
|
|
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
if (psdi) {
|
|
|
|
CHAR szTemp[MAX_PATH];
|
|
psdi->dwFlags = 0;
|
|
|
|
psdi->dwUpdateVersionMS = m_dwVersionMS;
|
|
psdi->dwUpdateVersionLS = m_dwVersionLS;
|
|
|
|
psdi->dwAdvertisedVersionMS = m_dwVersionAdvertisedMS;
|
|
psdi->dwAdvertisedVersionLS = m_dwVersionAdvertisedLS;
|
|
|
|
if (GetFirstChildTag(pSoftDist, DU_TAG_USAGE, &pUsage) == S_OK) {
|
|
|
|
VARIANT vtVal;
|
|
VariantInit(&vtVal);
|
|
|
|
if (SUCCEEDED(pUsage->getAttribute(DU_ATTRIB_VALUE, &vtVal)) && (vtVal.vt == VT_BSTR)) {
|
|
|
|
if (!StrCmpIW(vtVal.bstrVal, DU_ATTRIB_EMAIL))
|
|
psdi->dwFlags |= SOFTDIST_FLAG_USAGE_EMAIL;
|
|
|
|
// SAFESYSFREESTRING(vtVal.bstrVal);
|
|
|
|
}
|
|
VariantClear(&vtVal);
|
|
|
|
SAFERELEASE(pUsage);
|
|
}
|
|
|
|
if (SUCCEEDED(GetAttributeA(pSoftDist, DU_ATTRIB_PRECACHE, szTemp, MAX_PATH))) {
|
|
|
|
if (szTemp[0] == 'Y' || szTemp[0] == 'y') {
|
|
psdi->dwFlags |= SOFTDIST_FLAG_USAGE_PRECACHE;
|
|
bPrecache = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
if (SUCCEEDED(GetAttributeA(pSoftDist, DU_ATTRIB_AUTOINSTALL, szTemp, MAX_PATH))) {
|
|
|
|
if (szTemp[0] == 'Y' || szTemp[0] == 'y') {
|
|
psdi->dwFlags |= SOFTDIST_FLAG_USAGE_AUTOINSTALL;
|
|
bPrecache = TRUE;
|
|
bAutoInstall = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// get abstract
|
|
if(GetFirstChildTag(pSoftDist,DU_TAG_ABSTRACT, &pAbstract) == S_OK) {
|
|
|
|
BSTR bstrAbstract = NULL;
|
|
hr = pAbstract->get_text(&bstrAbstract);
|
|
ERROR_EXIT(SUCCEEDED(hr));
|
|
|
|
if (FAILED(Unicode2Ansi(bstrAbstract, &m_szAbstract))) {
|
|
hr = E_OUTOFMEMORY;
|
|
SAFESYSFREESTRING(bstrAbstract);
|
|
goto Exit;
|
|
}
|
|
|
|
if (psdi) {
|
|
psdi->szAbstract = new WCHAR[lstrlenW(bstrAbstract)+1];
|
|
if (!psdi->szAbstract) {
|
|
hr = E_OUTOFMEMORY;
|
|
SAFESYSFREESTRING(bstrAbstract);
|
|
goto Exit;
|
|
} else {
|
|
StrCpyW(psdi->szAbstract, bstrAbstract);
|
|
}
|
|
}
|
|
|
|
SAFESYSFREESTRING(bstrAbstract);
|
|
}
|
|
|
|
// get title
|
|
if(GetFirstChildTag(pSoftDist,DU_TAG_TITLE, &pTitle) == S_OK) {
|
|
BSTR bstrTitle = NULL;
|
|
hr = pTitle->get_text(&bstrTitle);
|
|
ERROR_EXIT(SUCCEEDED(hr));
|
|
|
|
if (FAILED(Unicode2Ansi(bstrTitle, &m_szTitle))) {
|
|
hr = E_OUTOFMEMORY;
|
|
SAFESYSFREESTRING(bstrTitle);
|
|
goto Exit;
|
|
}
|
|
|
|
if (psdi) {
|
|
psdi->szTitle = new WCHAR[lstrlenW(bstrTitle)+1];
|
|
if (!psdi->szTitle) {
|
|
hr = E_OUTOFMEMORY;
|
|
SAFESYSFREESTRING(bstrTitle);
|
|
goto Exit;
|
|
} else {
|
|
StrCpyW(psdi->szTitle, bstrTitle);
|
|
}
|
|
}
|
|
|
|
SAFESYSFREESTRING(bstrTitle);
|
|
}
|
|
|
|
// get langs available
|
|
if(GetFirstChildTag(pSoftDist,DU_TAG_LANG, &pLang) == S_OK) {
|
|
BSTR bstrLang = NULL;
|
|
hr = pLang->get_text(&bstrLang);
|
|
ERROR_EXIT(SUCCEEDED(hr));
|
|
|
|
DWORD len = lstrlenW(bstrLang);
|
|
m_szLanguages = new char [len+1];
|
|
if (!m_szLanguages) {
|
|
hr = E_OUTOFMEMORY;
|
|
SAFESYSFREESTRING(bstrLang);
|
|
goto Exit;
|
|
}
|
|
WideCharToMultiByte(CP_ACP, 0, bstrLang , -1, m_szLanguages,
|
|
len, NULL, NULL);
|
|
|
|
SAFESYSFREESTRING(bstrLang);
|
|
}
|
|
|
|
// <deleteoninstall />
|
|
if (GetFirstChildTag(pSoftDist, DU_TAG_DELETEONINSTALL, &pDeleteOnInstall) == S_OK) {
|
|
SAFERELEASE(pDeleteOnInstall);
|
|
bDeleteOnInstall = TRUE;
|
|
}
|
|
|
|
// style tells us who to ask
|
|
// accomodate Darwin here
|
|
if(SUCCEEDED(GetAttributeA(pSoftDist, DU_ATTRIB_STYLE, szStyle, MAX_PATH))){
|
|
|
|
(void) GetStyleFromString(szStyle, &m_Style);
|
|
|
|
if (m_Style == STYLE_UNKNOWN) {
|
|
|
|
if (m_sdMSInstall == NULL) {
|
|
|
|
CLSID clsidOther;
|
|
LPWSTR wszStyle = NULL;
|
|
|
|
if (FAILED(DupAttribute(pSoftDist, DU_ATTRIB_STYLE, &wszStyle)))
|
|
goto Exit;
|
|
|
|
if (SUCCEEDED(CLSIDFromProgID(wszStyle, &clsidOther))) {
|
|
|
|
if (FAILED(hr = CoCreateInstance(clsidOther, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ISoftDistExt, (void **)&m_sdMSInstall)))
|
|
goto Exit;
|
|
|
|
m_Style = STYLE_OTHER;
|
|
|
|
}
|
|
// If failed, continue as normal.
|
|
}
|
|
}
|
|
|
|
if (m_Style == STYLE_MSINSTALL) {
|
|
|
|
if (m_sdMSInstall == NULL) {
|
|
|
|
CLSID clsidMSInstall;
|
|
|
|
if (FAILED(hr = CLSIDFromProgID(szMSInstallProgID, &clsidMSInstall)))
|
|
goto Exit;
|
|
|
|
if (FAILED(hr = CoCreateInstance(clsidMSInstall, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ISoftDistExt, (void **)&m_sdMSInstall)))
|
|
goto Exit;
|
|
|
|
}
|
|
}
|
|
|
|
if (m_sdMSInstall != NULL) {
|
|
hr = m_sdMSInstall->ProcessSoftDist(szCDFURL, pSoftDist, psdi);
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
|
|
// get list of available languages here
|
|
|
|
hr = InitBrowserLangStrings();
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
// check if software already locally installed
|
|
hr = IsLocallyInstalled(m_szDistUnit, m_dwVersionMS, m_dwVersionLS, m_szLanguages, m_Style);
|
|
|
|
if ( psdi != NULL )
|
|
{
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
psdi->dwInstalledVersionMS = m_distunitinst.dwInstalledVersionMS;
|
|
psdi->dwInstalledVersionLS = m_distunitinst.dwInstalledVersionLS;
|
|
}
|
|
else
|
|
{
|
|
// No version.
|
|
psdi->dwInstalledVersionMS = 0xFFFFFFFF;
|
|
psdi->dwInstalledVersionLS = 0xFFFFFFFF;
|
|
}
|
|
}
|
|
|
|
if (hr != S_FALSE) {
|
|
if (hr == S_OK) {
|
|
|
|
if (psdi && bDeleteOnInstall) {
|
|
psdi->dwFlags |= SOFTDIST_FLAG_DELETE_SUBSCRIPTION;
|
|
}
|
|
|
|
hr = HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
// check here to see if Advertised already to avoid
|
|
// processing filters?
|
|
if (FAILED(hr = IsAdvertised(&bIsPrecached, &bIsValidCDF)))
|
|
goto Exit;
|
|
|
|
// If already advertised then only precache once.
|
|
if (hr == S_OK) {
|
|
if ((!bPrecache) || (!bAutoInstall && bPrecache && bIsPrecached)) {
|
|
bChannelUIOnly = TRUE;
|
|
}
|
|
}
|
|
|
|
// version doesn't already exist
|
|
// process filters to see if we can Advertise this
|
|
|
|
// look for dependency & config filters. If either fails, then we don't do Channel UI or
|
|
// email notification.
|
|
|
|
if (FAILED(hr = CheckDependency(pSoftDist)))
|
|
goto Exit;
|
|
|
|
if (FAILED(hr = CheckConfig(pSoftDist)))
|
|
goto Exit;
|
|
|
|
if (bChannelUIOnly)
|
|
{
|
|
// we record advertise again to stomp the title & abstract
|
|
if (bIsValidCDF) {
|
|
|
|
hr = Advertise(/*bFullAdvt*/FALSE);
|
|
}
|
|
|
|
// We are already advertised, we want Channel UI but not email notification.
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (bIsValidCDF) {
|
|
|
|
// Advertise software, mark as Advertised
|
|
hr = Advertise(/*bFullAdvt*/TRUE);
|
|
|
|
// We advertise in Channel UI and email notification.
|
|
hr = S_OK;
|
|
|
|
} else {
|
|
|
|
// if not an authorized CDF then we can't trigger email notification or download
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
Exit:
|
|
SAFERELEASE(pLang);
|
|
SAFERELEASE(pAbstract);
|
|
SAFERELEASE(pTitle);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSoftDist::GetFirstCodeBase(LPWSTR *szCodeBase, LPDWORD lpdwSize)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::GetFirstCodeBase",
|
|
"this=%#x, %#x, %#x",
|
|
this, szCodeBase, lpdwSize
|
|
));
|
|
|
|
HRESULT hr;
|
|
if (m_sdMSInstall != NULL)
|
|
{
|
|
hr = m_sdMSInstall->GetFirstCodeBase(szCodeBase, lpdwSize);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
m_curPos = m_cbh.GetHeadPosition();
|
|
hr = GetNextCodeBase(szCodeBase, lpdwSize);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSoftDist::GetNextCodeBase(LPWSTR *szCodeBase, LPDWORD lpdwSize)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::GetNextCodeBase",
|
|
"this=%#x, %#x, %#x",
|
|
this, szCodeBase, lpdwSize
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
CCodeBaseHold *cbh = NULL;
|
|
|
|
if (m_sdMSInstall != NULL)
|
|
{
|
|
hr = m_sdMSInstall->GetNextCodeBase(szCodeBase, lpdwSize);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
if (szCodeBase == NULL || lpdwSize == NULL) {
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
*szCodeBase = NULL;
|
|
*lpdwSize = 0;
|
|
|
|
if (m_curPos == NULL) {
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
cbh = m_cbh.GetNext(m_curPos);
|
|
|
|
hr = CDLDupWStr( szCodeBase, cbh->wszCodeBase );
|
|
*lpdwSize = cbh->dwSize;
|
|
|
|
Exit:
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSoftDist::AsyncInstallDistributionUnit(IBindCtx *pbc, LPVOID pvReserved, DWORD dwFlags, LPCODEBASEHOLD lpcbh)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::AsyncInstallDistributionUnit",
|
|
"this=%#x, %#x, %#x, %#x, %#x",
|
|
this, pbc, pvReserved, dwFlags, lpcbh
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
LPWSTR szCodeBase = NULL;
|
|
DWORD dwSize;
|
|
|
|
|
|
if ((lpcbh) && (lpcbh->cbSize == sizeof(CODEBASEHOLD)))
|
|
{
|
|
hr = ::AsyncInstallDistributionUnit(
|
|
lpcbh->szDistUnit,
|
|
NULL,
|
|
NULL,
|
|
lpcbh->dwVersionMS,
|
|
lpcbh->dwVersionLS,
|
|
lpcbh->szCodeBase, // URL of code base
|
|
pbc,
|
|
NULL,
|
|
0);
|
|
|
|
} else if (m_Style == STYLE_MSICD) {
|
|
|
|
if (SUCCEEDED(GetFirstCodeBase(&szCodeBase, &dwSize))) {
|
|
CCodeBaseHold *pcbh;
|
|
|
|
pcbh = m_cbh.GetHead();
|
|
pcbh->dwFlags |= CBH_FLAGS_DOWNLOADED;
|
|
hr = ::AsyncInstallDistributionUnit(
|
|
m_szDistUnit,
|
|
NULL,
|
|
NULL,
|
|
m_dwVersionMS,
|
|
m_dwVersionLS,
|
|
szCodeBase, // URL of code base
|
|
pbc,
|
|
NULL,
|
|
0);
|
|
|
|
// NOTE: EAX should be MK_S_ASYNC (0x401E8)
|
|
|
|
} else
|
|
hr = E_FAIL;
|
|
|
|
// Return successful no matter what
|
|
|
|
} else if (m_Style == STYLE_MSINSTALL || m_Style == STYLE_OTHER) {
|
|
|
|
if (m_sdMSInstall == NULL) {
|
|
|
|
hr = E_FAIL; // Interfaces should be here but aren't.
|
|
|
|
} else {
|
|
|
|
hr = m_sdMSInstall->AsyncInstallDistributionUnit(pbc, pvReserved, dwFlags, lpcbh);
|
|
|
|
}
|
|
|
|
} else if (m_Style == STYLE_ACTIVE_SETUP) {
|
|
|
|
if (SUCCEEDED(GetFirstCodeBase(&szCodeBase, &dwSize))) {
|
|
|
|
CActiveSetupBinding *pasb = NULL;
|
|
IBindStatusCallback *pbsc = NULL;
|
|
|
|
if (SUCCEEDED(pbc->GetObjectParam(REG_BSCB_HOLDER, (IUnknown **)&pbsc))) {
|
|
|
|
pasb = new CActiveSetupBinding(pbc, pbsc, szCodeBase, m_szDistUnit, &hr);
|
|
if (pasb && FAILED(hr)) {
|
|
|
|
SAFERELEASE(pasb); // deletes itself
|
|
|
|
}
|
|
|
|
SAFERELEASE(pbsc);
|
|
|
|
// NOTE: This is not a memory leak, the object will clean itself up when it
|
|
// is done the binding operation.
|
|
|
|
}
|
|
else
|
|
hr = E_FAIL;
|
|
}
|
|
else
|
|
hr = E_FAIL;
|
|
|
|
} else if (m_Style == STYLE_LOGO3) {
|
|
CCodeBaseHold *pcbhCur = NULL;
|
|
|
|
m_curPos = m_cbh.GetHeadPosition();
|
|
if (m_curPos == 0) {
|
|
goto Exit;
|
|
}
|
|
pcbhCur = m_cbh.GetAt(m_curPos);
|
|
if (pcbhCur == NULL) {
|
|
goto Exit;
|
|
}
|
|
|
|
CDLDupWStr(&szCodeBase, pcbhCur->wszCodeBase);
|
|
dwSize = pcbhCur->dwSize;
|
|
pcbhCur->dwFlags |= CBH_FLAGS_DOWNLOADED;
|
|
|
|
if (pbc != NULL) {
|
|
pbc->GetObjectParam(REG_BSCB_HOLDER, (IUnknown **)&m_pClientBSC);
|
|
}
|
|
|
|
hr = Logo3Download(szCodeBase);
|
|
|
|
} else {
|
|
|
|
hr = E_NOTIMPL;
|
|
|
|
}
|
|
|
|
Exit:
|
|
|
|
SAFEDELETE(szCodeBase);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
/******************************************************************************
|
|
CheckDependency
|
|
******************************************************************************/
|
|
/* This checks for filter criteria in <Config> tags.
|
|
*
|
|
* <!ELEMENT Dependency (SoftDist)* | Language | Processor | Platform>
|
|
*
|
|
* Returns: E_ERROR code if Dependency check fails or badly formatted.
|
|
*
|
|
*/
|
|
HRESULT
|
|
CSoftDist::CheckDependency(IXMLElement *pSoftDist)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::CheckDependency",
|
|
"this=%#x, %#x",
|
|
this, pSoftDist
|
|
));
|
|
|
|
int nLastChildTag = -1;
|
|
LPSTR szLanguages = NULL;
|
|
LPWSTR szCoreDist = NULL;
|
|
IXMLElement *pDepend = NULL, *pCoreDist = NULL;
|
|
IXMLElement *pProcessor = NULL, *pPlatform = NULL, *pLang = NULL;
|
|
HRESULT hr = S_OK;
|
|
DWORD style;
|
|
|
|
while (GetNextChildTag(pSoftDist, DU_TAG_DEPENDENCY, &pDepend, nLastChildTag) == S_OK) {
|
|
|
|
LPWSTR szCoreDist = NULL;
|
|
union {
|
|
char szVersion[MAX_PATH];
|
|
char szStyle[MAX_PATH];
|
|
char szProcessor[MAX_PATH];
|
|
char szPlatformAttr[MAX_PATH];
|
|
};
|
|
|
|
// check for 'softdist' tag and version info.
|
|
int nLastSoftDist = -1;
|
|
while (GetNextChildTag(pDepend, DU_TAG_SOFTDIST, &pCoreDist, nLastSoftDist) == S_OK) {
|
|
|
|
// default values if attributes are not specified.
|
|
DWORD dwVersionMS = 0, dwVersionLS = 0, style = m_Style;
|
|
|
|
// look for language tag (if present), otherwise NULL.
|
|
SAFEDELETE(szLanguages);
|
|
if (GetFirstChildTag(pCoreDist, DU_TAG_LANG, &pLang) == S_OK) {
|
|
BSTR bstrLang = NULL;
|
|
pLang->get_text(&bstrLang);
|
|
|
|
DWORD len = lstrlenW(bstrLang);
|
|
szLanguages = new char[len+1];
|
|
if (!szLanguages) {
|
|
hr = E_OUTOFMEMORY;
|
|
SAFESYSFREESTRING(bstrLang);
|
|
goto Exit;
|
|
}
|
|
WideCharToMultiByte(CP_ACP, 0, bstrLang , -1, szLanguages,
|
|
len, NULL, NULL);
|
|
|
|
SAFESYSFREESTRING(bstrLang);
|
|
}
|
|
|
|
if (FAILED(hr = DupAttribute(pCoreDist, DU_ATTRIB_NAME, &szCoreDist)))
|
|
goto Exit;
|
|
|
|
if (SUCCEEDED(GetAttributeA(pCoreDist, DU_ATTRIB_VERSION, szVersion, MAX_PATH))) {
|
|
|
|
if (FAILED(GetVersionFromString(szVersion, &dwVersionMS, &dwVersionLS))) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
|
|
if (SUCCEEDED(GetAttributeA(pCoreDist, DU_ATTRIB_STYLE, szStyle, MAX_PATH))) {
|
|
|
|
// return is not required
|
|
(void) GetStyleFromString(szStyle, &style);
|
|
|
|
}
|
|
|
|
hr = IsLocallyInstalled(szCoreDist, dwVersionMS, dwVersionLS,
|
|
szLanguages != NULL ? szLanguages : m_szLanguages, style);
|
|
SAFEDELETE(szCoreDist);
|
|
|
|
// core product doesn't exist, or version is lower than required.
|
|
if (hr != S_OK) {
|
|
hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
|
|
goto Exit;
|
|
}
|
|
SAFERELEASE(pCoreDist);
|
|
|
|
} // while for softdist
|
|
|
|
// check processor
|
|
if (GetFirstChildTag(pDepend, DU_TAG_PROCESSOR, &pProcessor) == S_OK) {
|
|
|
|
if (FAILED(hr = GetAttributeA(pProcessor, DU_ATTRIB_VALUE, szProcessor, MAX_PATH)))
|
|
goto Exit;
|
|
|
|
#ifdef WX86
|
|
char *szPreferredArch;
|
|
char *szAlternateArch;
|
|
HRESULT hrArch;
|
|
|
|
GetMultiArch()->SelectArchitecturePreferences(
|
|
g_szProcessorTypes[g_CPUType],
|
|
g_szProcessorTypes[PROCESSOR_ARCHITECTURE_INTEL],
|
|
&szPreferredArch,
|
|
&szAlternateArch);
|
|
|
|
if (lstrcmpi(szPreferredArch, szProcessor) == 0) {
|
|
hrArch = GetMultiArch()->RequirePrimaryArch();
|
|
Assert(SUCCEEDED(hrArch));
|
|
} else if (szAlternateArch && lstrcmpi(szAlternateArch, szProcessor) == 0) {
|
|
hrArch = GetMultiArch()->RequireAlternateArch();
|
|
Assert(SUCCEEDED(hrArch));
|
|
} else {
|
|
//
|
|
// Processor type is neither perferred nor alternate.
|
|
//
|
|
hr = HRESULT_FROM_WIN32(ERROR_EXE_MACHINE_TYPE_MISMATCH);
|
|
goto Exit;
|
|
}
|
|
#else
|
|
if (lstrcmpi(g_szProcessorTypes[g_CPUType],szProcessor) != 0) {
|
|
hr = HRESULT_FROM_WIN32(ERROR_EXE_MACHINE_TYPE_MISMATCH);
|
|
goto Exit;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
// check platform
|
|
if (GetFirstChildTag(pDepend, DU_TAG_PLATFORM, &pPlatform) == S_OK) {
|
|
|
|
if (FAILED(hr = GetAttributeA(pPlatform, DU_ATTRIB_VALUE, szPlatformAttr, MAX_PATH)))
|
|
goto Exit;
|
|
|
|
if (lstrcmpi(szPlatform, szPlatformAttr) != 0) {
|
|
hr = HRESULT_FROM_WIN32(ERROR_EXE_MACHINE_TYPE_MISMATCH);
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
|
|
SAFERELEASE(pDepend);
|
|
|
|
} // dependency check loop
|
|
Exit:
|
|
SAFERELEASE(pDepend);
|
|
SAFERELEASE(pCoreDist);
|
|
SAFERELEASE(pProcessor);
|
|
SAFERELEASE(pPlatform);
|
|
SAFERELEASE(pLang);
|
|
|
|
SAFEDELETE(szLanguages);
|
|
SAFEDELETE(szCoreDist);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
/******************************************************************************
|
|
CheckConfig
|
|
******************************************************************************/
|
|
/* This checks for filter criteria in <Config> tags.
|
|
*
|
|
* <!ELEMENT Config (CodeBase)*>
|
|
* <!ATTLIST Config Language CDATA #IMPLIED>
|
|
* <!ATTLIST Config (OS OSVersion) CDATA #IMPLIED>
|
|
* <!ATTLIST Config Processor CDATA #IMPLIED>
|
|
*/
|
|
HRESULT
|
|
CSoftDist::CheckConfig(IXMLElement *pSoftDist)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::CheckConfig",
|
|
"this=%#x, %#x",
|
|
this, pSoftDist
|
|
));
|
|
|
|
IXMLElement *pConfig = NULL;
|
|
IXMLElement *pCodeBase = NULL;
|
|
BOOL fFoundMatchingConfig = FALSE;
|
|
BOOL fFoundAnyConfig = FALSE;
|
|
HRESULT hr = S_OK;
|
|
int nLastChildTag = -1;
|
|
int nLastChildCodeBase = -1;
|
|
WCHAR szResult[INTERNET_MAX_URL_LENGTH];
|
|
DWORD dwSize = 0;
|
|
|
|
// Process CONFIG tags
|
|
while (GetNextChildTag(pSoftDist, DU_TAG_CONFIG, &pConfig, nLastChildTag) == S_OK) {
|
|
|
|
fFoundAnyConfig = TRUE;
|
|
|
|
if (ProcessImplementation(pConfig, &m_cbh, GetThreadLocale(),
|
|
#ifdef WX86
|
|
GetMultiArch(),
|
|
#endif
|
|
m_szBaseURL) == S_OK) {
|
|
fFoundMatchingConfig = TRUE;
|
|
break;
|
|
}
|
|
|
|
SAFERELEASE(pConfig);
|
|
}
|
|
|
|
// if at least one config and none match, return with error.
|
|
if (fFoundAnyConfig && !fFoundMatchingConfig) {
|
|
hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
SAFERELEASE(pConfig);
|
|
SAFERELEASE(pCodeBase);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
typedef HRESULT (STDAPICALLTYPE *PFNLCIDTORFC1766)(LCID, LPSTR, DWORD);
|
|
|
|
HRESULT
|
|
GetLangStringMod(HMODULE hMod, LCID localeID, char *szThisLang, int iLen)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"GetLangStringMod",
|
|
"%#x, %#x, %.80q",
|
|
hMod, localeID, szThisLang
|
|
));
|
|
|
|
PFNLCIDTORFC1766 pfnLCIDToRFC1766 = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
#ifdef UNICODE
|
|
pfnLCIDToRFC1766 = (PFNLCIDTORFC1766)GetProcAddress(hMod, "LcidToRfc1766W");
|
|
#else
|
|
pfnLCIDToRFC1766 = (PFNLCIDTORFC1766)GetProcAddress(hMod, "LcidToRfc1766A");
|
|
#endif
|
|
|
|
if (pfnLCIDToRFC1766) {
|
|
|
|
hr = pfnLCIDToRFC1766(localeID, szThisLang, iLen);
|
|
|
|
} else {
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetLangString(LCID localeID, char *szThisLang, int iLen)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"GetLangString",
|
|
"%#x, %.80q",
|
|
localeID, szThisLang
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
HMODULE hMod = 0;
|
|
LCID lcidPrimaryBrowser = PRIMARYLANGID(LANGIDFROMLCID(g_lcidBrowser));
|
|
|
|
|
|
// use cached copies of browser lang string
|
|
if ( (localeID == g_lcidBrowser) && g_szBrowserLang[0] ) {
|
|
|
|
StrNCpy(szThisLang, g_szBrowserLang, iLen);
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
if ( (localeID == lcidPrimaryBrowser) && g_szBrowserPrimaryLang[0] ) {
|
|
|
|
StrNCpy(szThisLang, g_szBrowserPrimaryLang, iLen);
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
hMod = LoadLibrary("mlang.dll");
|
|
|
|
if (!hMod) {
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
hr = GetLangStringMod(hMod, localeID, szThisLang, iLen);
|
|
|
|
Exit:
|
|
|
|
if (hMod)
|
|
FreeLibrary(hMod);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
// globals for code downloader
|
|
extern CMutexSem g_mxsCodeDownloadGlobals;
|
|
BOOL g_bLangInit = FALSE;
|
|
|
|
HRESULT
|
|
InitBrowserLangStrings()
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"InitBrowserLangStrings",
|
|
NULL
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
CLock lck(g_mxsCodeDownloadGlobals);
|
|
static const char *cszSHDOCVW = "\\shdocvw.dll";
|
|
|
|
if (g_bLangInit)
|
|
{
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
g_bLangInit = TRUE;
|
|
|
|
CLocalComponentInfo lci;
|
|
DWORD dwVerMS, dwVerLS;
|
|
|
|
GetSystemDirectory(lci.szExistingFileName, MAX_PATH);
|
|
|
|
StrCatBuff(lci.szExistingFileName, cszSHDOCVW, sizeof(lci.szExistingFileName));
|
|
if (SUCCEEDED(GetFileVersion(&lci, &dwVerMS, &dwVerLS))) {
|
|
if (lci.lcid) {
|
|
|
|
g_lcidBrowser = lci.lcid;
|
|
|
|
}
|
|
}
|
|
|
|
HMODULE hMod = LoadLibrary("mlang.dll");
|
|
LCID lcidPrimaryBrowser = PRIMARYLANGID(LANGIDFROMLCID(g_lcidBrowser));
|
|
|
|
if (hMod) {
|
|
|
|
hr = GetLangStringMod(hMod, g_lcidBrowser, g_szBrowserLang, g_lenBrowserLang);
|
|
hr = GetLangStringMod(hMod, lcidPrimaryBrowser, g_szBrowserPrimaryLang, g_lenBrowserPrimaryLang);
|
|
FreeLibrary(hMod);
|
|
} else {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
/******************************************************************************
|
|
CheckLanguage
|
|
******************************************************************************/
|
|
/* The languages string is of the form,
|
|
* lang1;lang2;lang3;...
|
|
*
|
|
* OR = '*' (the first character is an asterick).
|
|
*
|
|
* This routine will scan the LocaleID string (as saved from registry, GetLocaleInfo)
|
|
* for an occurrence in the szLanguage string. If found, it returns true. If '*'
|
|
* is specified, the result is always true. Regular expressions are otherwise
|
|
* not supported.
|
|
*
|
|
*/
|
|
HRESULT CheckLanguage(LCID localeID, LPTSTR szLanguage)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CheckLanguage",
|
|
"%#x, %.80q",
|
|
localeID, szLanguage
|
|
));
|
|
|
|
LCID lcidPrimaryBrowser = PRIMARYLANGID(LANGIDFROMLCID(g_lcidBrowser));
|
|
CHAR szThisLang[MAX_PATH];
|
|
int i;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (szLanguage == NULL)
|
|
{
|
|
DEBUG_LEAVE(S_OK);
|
|
return S_OK;
|
|
}
|
|
if (*szLanguage == '*')
|
|
{
|
|
DEBUG_LEAVE(S_OK);
|
|
return S_OK;
|
|
}
|
|
hr = GetLangString(localeID, (char *)szThisLang, sizeof(szThisLang));
|
|
|
|
if (FAILED(hr)) {
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
if (AreAllLanguagesPresent((char *)szThisLang, szLanguage)) {
|
|
DEBUG_LEAVE(S_OK);
|
|
return S_OK;
|
|
}
|
|
|
|
// check with primary language
|
|
localeID = PRIMARYLANGID(LANGIDFROMLCID(localeID));
|
|
|
|
hr = GetLangString(localeID, (char *)szThisLang, sizeof(szThisLang));
|
|
|
|
if (FAILED(hr)) {
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
if (AreAllLanguagesPresent((char *)szThisLang, szLanguage)) {
|
|
DEBUG_LEAVE(S_OK);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
hr = HRESULT_FROM_WIN32(ERROR_RESOURCE_LANG_NOT_FOUND);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::IsLocallyInstalled(LPCWSTR szDistUnit, DWORD dwVersionMS, DWORD dwVersionLS, LPCSTR szLanguages, DWORD Style)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::IsLocallyInstalled",
|
|
"this=%#x, %.80wq, %#x, %#x, %.80q, %#x",
|
|
this, szDistUnit, dwVersionMS, dwVersionLS, szLanguages, Style
|
|
));
|
|
|
|
Assert(szDistUnit);
|
|
HRESULT hr = S_OK;
|
|
if (Style == STYLE_MSICD)
|
|
hr = IsICDLocallyInstalled(szDistUnit, dwVersionMS, dwVersionLS, szLanguages);
|
|
else if (Style == STYLE_ACTIVE_SETUP)
|
|
hr = IsActSetupLocallyInstalled(szDistUnit, dwVersionMS, dwVersionLS, szLanguages);
|
|
else if (Style == STYLE_LOGO3)
|
|
hr = IsLogo3LocallyInstalled(szDistUnit, dwVersionMS, dwVersionLS, szLanguages);
|
|
else
|
|
hr = E_UNEXPECTED;
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::IsLogo3LocallyInstalled(LPCWSTR szDistUnit, DWORD dwVersionMS, DWORD dwVersionLS, LPCSTR szLanguages)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::IsLogo3LocallyInstalled",
|
|
"this=%#x, %.80wq, %#x, %#x, %.80q",
|
|
this, szDistUnit, dwVersionMS, dwVersionLS, szLanguages
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD dwInstVersionMS = 0;
|
|
DWORD dwInstVersionLS = 0;
|
|
DWORD dwType = 0;
|
|
DWORD dwLen = 0;
|
|
LPSTR szDU = NULL;
|
|
HKEY hkeyLogo3 = 0;
|
|
HKEY hkeyDist = 0;
|
|
|
|
// No LOGO3 language information is stored, so language checking is not
|
|
// possible yet.
|
|
|
|
Assert(szDistUnit);
|
|
if (!szDistUnit) {
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
dwLen = WideCharToMultiByte(CP_ACP,0, szDistUnit, -1, NULL, 0, NULL, NULL);
|
|
szDU = new char [dwLen];
|
|
if (szDU == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, szDistUnit , -1, szDU,
|
|
dwLen, NULL, NULL);
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_LOGO3_SETTINGS,
|
|
0, KEY_READ, &hkeyLogo3) != ERROR_SUCCESS) {
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
if (RegOpenKeyEx(hkeyLogo3, szDU, 0, KEY_READ, &hkeyDist) != ERROR_SUCCESS) {
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
dwLen = sizeof(DWORD);
|
|
if (RegQueryValueEx(hkeyDist, REGVAL_LOGO3_MAJORVERSION, 0, &dwType,
|
|
(LPBYTE)&dwInstVersionMS, &dwLen) != ERROR_SUCCESS) {
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
dwLen = sizeof(DWORD);
|
|
if (RegQueryValueEx(hkeyDist, REGVAL_LOGO3_MINORVERSION, 0, &dwType,
|
|
(LPBYTE)&dwInstVersionLS, &dwLen) != ERROR_SUCCESS) {
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
m_distunitinst.dwInstalledVersionMS = dwInstVersionMS;
|
|
m_distunitinst.dwInstalledVersionLS = dwInstVersionLS;
|
|
|
|
if (dwInstVersionMS > dwVersionMS ||
|
|
(dwInstVersionMS == dwVersionMS && dwInstVersionLS >= dwVersionLS)) {
|
|
hr = S_OK;
|
|
} else {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (hkeyLogo3) {
|
|
RegCloseKey(hkeyLogo3);
|
|
}
|
|
|
|
if (hkeyDist) {
|
|
RegCloseKey(hkeyDist);
|
|
}
|
|
|
|
if (szDU) {
|
|
delete [] szDU;
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::IsICDLocallyInstalled(LPCWSTR szDistUnit, DWORD dwVersionMS, DWORD dwVersionLS, LPCSTR szLanguages)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::IsICDLocallyInstalled",
|
|
"this=%#x, %.80wq, %#x, %#x, %.80q",
|
|
this, szDistUnit, dwVersionMS, dwVersionLS, szLanguages
|
|
));
|
|
|
|
Assert(szDistUnit);
|
|
CLSID inclsid = CLSID_NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
CLocalComponentInfo* plci = NULL;
|
|
|
|
plci = new CLocalComponentInfo();
|
|
if(!plci) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
// if fails szDistUnit is not clsid
|
|
CLSIDFromString((LPOLESTR)szDistUnit, &inclsid);
|
|
|
|
// check to see if locally installed.
|
|
if ((hr = IsControlLocallyInstalled(NULL,
|
|
(LPCLSID)&inclsid, szDistUnit,
|
|
dwVersionMS, dwVersionLS, plci, NULL)) != S_FALSE) {
|
|
|
|
// S_OK if local version OK
|
|
// ERROR, fail
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
// check for other hooks like Active Setup, Add/Remove Programs here
|
|
|
|
Exit:
|
|
if (plci)
|
|
{
|
|
m_distunitinst.dwInstalledVersionMS = plci->dwLocFVMS;
|
|
m_distunitinst.dwInstalledVersionLS = plci->dwLocFVLS;
|
|
}
|
|
|
|
SAFEDELETE(plci);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::IsAdvertised(LPBOOL lpfIsPrecached, LPBOOL lpfIsAuthorizedCDF)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::IsAdvertised",
|
|
"this=%#x, %#x, %#x",
|
|
this, lpfIsPrecached, lpfIsAuthorizedCDF
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
if (m_Style == STYLE_MSICD)
|
|
hr = IsICDAdvertised(lpfIsPrecached, lpfIsAuthorizedCDF);
|
|
else if (m_Style == STYLE_ACTIVE_SETUP)
|
|
hr = IsActSetupAdvertised(lpfIsPrecached, lpfIsAuthorizedCDF);
|
|
else if (m_Style == STYLE_LOGO3)
|
|
hr = IsLogo3Advertised(lpfIsPrecached, lpfIsAuthorizedCDF);
|
|
else
|
|
hr = E_UNEXPECTED;
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::IsLogo3Advertised(LPBOOL lpfIsPrecached, LPBOOL lpfIsAuthorizedCDF)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::IsLogo3Advertised",
|
|
"this=%#x, %#x, %#x",
|
|
this, lpfIsPrecached, lpfIsAuthorizedCDF
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
HKEY hkeyDistInfo = 0;
|
|
HKEY hkeyAdvertisedVersion = 0;
|
|
HKEY hkeyAuthCDF = 0;
|
|
HKEY hkeyLogo3 = 0;
|
|
DWORD lResult = 0;
|
|
DWORD dwSize = 0;
|
|
DWORD dwType;
|
|
LPSTR szDU = NULL;
|
|
DWORD dwLen = 0;
|
|
DWORD dwCurAdvMS = 0;
|
|
DWORD dwCurAdvLS = 0;
|
|
char szBuffer[MAX_REGSTR_LEN];
|
|
char szVersionBuf[MAX_PATH];
|
|
static const char *szPrecache = "Precache";
|
|
static const char *szAbstract = "Abstract";
|
|
static const char *szAuthorizedCDF = "AuthorizedCDFPrefix";
|
|
static const char *szHREF = "HREF";
|
|
static const char *szTITLE = "TITLE";
|
|
|
|
ASSERT(lpfIsPrecached && lpfIsAuthorizedCDF);
|
|
|
|
if (!lpfIsPrecached || !lpfIsAuthorizedCDF) {
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
*lpfIsPrecached = FALSE;
|
|
*lpfIsAuthorizedCDF = FALSE;
|
|
|
|
if (m_szDistUnit) {
|
|
if (FAILED(Unicode2Ansi(m_szDistUnit, &szDU))) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
}
|
|
else {
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
wnsprintf(szBuffer, sizeof(szBuffer)-1, "%s\\%s", REGSTR_PATH_LOGO3_SETTINGS, szDU);
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szBuffer, 0, KEY_READ,
|
|
&hkeyLogo3) != ERROR_SUCCESS) {
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
*lpfIsAuthorizedCDF = IsAuthorizedCDF(hkeyLogo3);
|
|
|
|
if (RegOpenKeyEx(hkeyLogo3, "AvailableVersion", 0, KEY_READ,
|
|
&hkeyDistInfo) != ERROR_SUCCESS) {
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
dwSize = sizeof(DWORD);
|
|
if (RegQueryValueEx(hkeyDistInfo, szPrecache, 0, &dwType,
|
|
(unsigned char *)&lResult, &dwSize) == ERROR_SUCCESS) {
|
|
// Precached value was the code download HR
|
|
*lpfIsPrecached = (SUCCEEDED(lResult)) ? (TRUE) : (FALSE);
|
|
}
|
|
|
|
// This key is optionally present.
|
|
dwSize = MAX_PATH;
|
|
if (RegQueryValueEx(hkeyDistInfo, REGSTR_LOGO3_ADVERTISED_VERSION, NULL, &dwType,
|
|
(unsigned char *)szVersionBuf, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
GetVersionFromString(szVersionBuf, &m_dwVersionAdvertisedMS, &m_dwVersionAdvertisedLS);
|
|
}
|
|
|
|
// Get the AdState, if any
|
|
dwSize = sizeof(DWORD);
|
|
RegQueryValueEx(hkeyDistInfo, REGVAL_ADSTATE, NULL, NULL, (LPBYTE)&m_dwAdState, &dwSize);
|
|
|
|
if (!m_szAbstract) {
|
|
if (RegQueryValueEx(hkeyDistInfo, szAbstract, NULL, &dwType,
|
|
NULL, &dwSize) == ERROR_SUCCESS) {
|
|
|
|
m_szAbstract = new char[dwSize];
|
|
if (!m_szAbstract) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
if (RegQueryValueEx(hkeyDistInfo, szAbstract, NULL, &dwType,
|
|
(unsigned char *)m_szAbstract, &dwSize) != ERROR_SUCCESS) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (!m_szHREF) {
|
|
if (RegQueryValueEx(hkeyDistInfo, szHREF, NULL, &dwType,
|
|
NULL, &dwSize) == ERROR_SUCCESS) {
|
|
|
|
m_szHREF = new char[dwSize];
|
|
if (!m_szHREF) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
if (RegQueryValueEx(hkeyDistInfo, szHREF, NULL, &dwType,
|
|
(unsigned char *)m_szHREF, &dwSize) != ERROR_SUCCESS) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (!m_szTitle) {
|
|
if (RegQueryValueEx(hkeyDistInfo, szTITLE, NULL, &dwType,
|
|
NULL, &dwSize) == ERROR_SUCCESS) {
|
|
|
|
m_szTitle = new char[dwSize];
|
|
if (!m_szHREF) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
if (RegQueryValueEx(hkeyDistInfo, szTITLE, NULL, &dwType,
|
|
(unsigned char *)m_szTitle, &dwSize) != ERROR_SUCCESS) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
dwSize = MAX_PATH;
|
|
if (RegQueryValueEx(hkeyDistInfo, NULL, NULL, &dwType,
|
|
(unsigned char *)szVersionBuf, &dwSize) != ERROR_SUCCESS) {
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
if ( FAILED(GetVersionFromString(szVersionBuf, &dwCurAdvMS, &dwCurAdvLS))){
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
if (!(m_dwVersionMS|m_dwVersionLS)) {
|
|
m_dwVersionMS = dwCurAdvMS;
|
|
m_dwVersionLS = dwCurAdvLS;
|
|
}
|
|
|
|
if (IsCDFNewerVersion(dwCurAdvMS, dwCurAdvLS)) {
|
|
hr = S_FALSE;
|
|
}
|
|
else {
|
|
hr = S_OK;
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (hkeyDistInfo) {
|
|
RegCloseKey(hkeyDistInfo);
|
|
}
|
|
|
|
if (hkeyAdvertisedVersion) {
|
|
RegCloseKey(hkeyAdvertisedVersion);
|
|
}
|
|
|
|
if (hkeyLogo3) {
|
|
RegCloseKey(hkeyLogo3);
|
|
}
|
|
|
|
if (hkeyAuthCDF) {
|
|
RegCloseKey(hkeyAuthCDF);
|
|
}
|
|
|
|
SAFEDELETE(szDU);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
// **** IsICDAdvertised ****
|
|
// returns: S_FALSE for not advertised (or newest version not advertised)
|
|
// S_OK for advertised
|
|
|
|
HRESULT
|
|
CSoftDist::IsICDAdvertised(LPBOOL lpfIsPrecached, LPBOOL lpfIsAuthorizedCDF)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::IsICDAdvertised",
|
|
"this=%#x, %#x, %#x",
|
|
this, lpfIsPrecached, lpfIsAuthorizedCDF
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
LONG lResult = ERROR_SUCCESS;
|
|
HKEY hkeyDist =0;
|
|
HKEY hkeyThisDist = 0;
|
|
HKEY hkeyVersion = 0;
|
|
HKEY hkeyAdvertisedVersion = 0;
|
|
DWORD Size = MAX_PATH;
|
|
DWORD SizeDword = sizeof(DWORD);
|
|
DWORD dwType;
|
|
|
|
DWORD dwCurAdvMS = 0;
|
|
DWORD dwCurAdvLS = 0;
|
|
|
|
const static char * szAvailableVersion = "AvailableVersion";
|
|
const static char * szHREF = "HREF";
|
|
const static char * szABSTRACT = "Abstract";
|
|
const static char * szPrecache = "Precache";
|
|
const static char * szAuthorizedCDF = "AuthorizedCDFPrefix";
|
|
|
|
LPSTR pszDist = NULL;
|
|
|
|
char szVersionBuf[MAX_PATH];
|
|
|
|
ASSERT(lpfIsPrecached && lpfIsAuthorizedCDF);
|
|
if (!lpfIsPrecached || !lpfIsAuthorizedCDF) {
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
*lpfIsPrecached = FALSE;
|
|
*lpfIsAuthorizedCDF = TRUE;
|
|
|
|
if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGSTR_PATH_DIST_UNITS,
|
|
0, KEY_ALL_ACCESS, &hkeyDist)) != ERROR_SUCCESS) {
|
|
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
if (FAILED((hr=::Unicode2Ansi(m_szDistUnit, &pszDist))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// open the dist unit key for this dist unit.
|
|
if (RegOpenKeyEx( hkeyDist, pszDist,
|
|
0, KEY_ALL_ACCESS, &hkeyThisDist) != ERROR_SUCCESS) {
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
*lpfIsAuthorizedCDF = IsAuthorizedCDF(hkeyThisDist, /*bOptional*/TRUE);
|
|
|
|
if (RegOpenKeyEx( hkeyThisDist, szAvailableVersion,
|
|
0, KEY_ALL_ACCESS, &hkeyVersion) != ERROR_SUCCESS) {
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
if (RegQueryValueEx(hkeyVersion, szPrecache, 0, &dwType,
|
|
(unsigned char *)&lResult, &SizeDword) == ERROR_SUCCESS) {
|
|
|
|
// check for success or common error conditions which indicate we have bits.
|
|
if (SUCCEEDED(lResult)) {
|
|
*lpfIsPrecached = TRUE;
|
|
} else {
|
|
*lpfIsPrecached = FALSE;
|
|
}
|
|
}
|
|
|
|
// This key is optionally present.
|
|
if ( RegOpenKeyEx( hkeyThisDist, REGKEY_MSICD_ADVERTISED_VERSION,
|
|
0, KEY_ALL_ACCESS, &hkeyAdvertisedVersion) == ERROR_SUCCESS )
|
|
{
|
|
Size = MAX_PATH;
|
|
|
|
if (RegQueryValueEx(hkeyAdvertisedVersion, NULL, NULL, &dwType,
|
|
(unsigned char *)szVersionBuf, &Size) == ERROR_SUCCESS)
|
|
GetVersionFromString(szVersionBuf, &m_dwVersionAdvertisedMS, &m_dwVersionAdvertisedLS);
|
|
// Get the AdState, if any
|
|
SizeDword = sizeof(DWORD);
|
|
RegQueryValueEx( hkeyAdvertisedVersion, REGVAL_ADSTATE, NULL, NULL, (LPBYTE)&m_dwAdState, &SizeDword);
|
|
}
|
|
|
|
// save away the advt info like Title, href, abstract
|
|
// if called from GetDistributionUnitAdvt()
|
|
if (!m_szTitle) {
|
|
if (RegQueryValueEx(hkeyThisDist, NULL, NULL, &dwType,
|
|
NULL, &Size) == ERROR_SUCCESS) {
|
|
|
|
m_szTitle = new char[Size];
|
|
|
|
if (!m_szTitle) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
if (RegQueryValueEx(hkeyThisDist, NULL, NULL, &dwType,
|
|
(unsigned char *)m_szTitle, &Size) != ERROR_SUCCESS) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (!m_szAbstract) {
|
|
if (RegQueryValueEx(hkeyVersion, szABSTRACT, NULL, &dwType,
|
|
NULL, &Size) == ERROR_SUCCESS) {
|
|
|
|
m_szAbstract = new char[Size];
|
|
|
|
if (!m_szAbstract) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
if (RegQueryValueEx(hkeyVersion, szABSTRACT, NULL, &dwType,
|
|
(unsigned char *)m_szAbstract, &Size) != ERROR_SUCCESS) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (!m_szHREF) {
|
|
if (RegQueryValueEx(hkeyVersion, szHREF, NULL, &dwType,
|
|
NULL, &Size) == ERROR_SUCCESS) {
|
|
|
|
m_szHREF = new char[Size];
|
|
|
|
if (!m_szHREF) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
if (RegQueryValueEx(hkeyVersion, szHREF, NULL, &dwType,
|
|
(unsigned char *)m_szHREF, &Size) != ERROR_SUCCESS) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (RegQueryValueEx(hkeyVersion, NULL, NULL, &dwType,
|
|
(unsigned char *)szVersionBuf, &Size) != ERROR_SUCCESS) {
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
if ( FAILED(GetVersionFromString(szVersionBuf, &dwCurAdvMS, &dwCurAdvLS))){
|
|
hr = S_FALSE;
|
|
goto Exit;
|
|
}
|
|
|
|
if (!(m_dwVersionMS|m_dwVersionLS)) {
|
|
m_dwVersionMS = dwCurAdvMS;
|
|
m_dwVersionLS = dwCurAdvLS;
|
|
}
|
|
|
|
if (IsCDFNewerVersion(dwCurAdvMS, dwCurAdvLS))
|
|
hr = S_FALSE;
|
|
else
|
|
hr = S_OK;
|
|
|
|
Exit:
|
|
SAFEDELETE(pszDist);
|
|
|
|
SAFEREGCLOSEKEY(hkeyVersion);
|
|
SAFEREGCLOSEKEY(hkeyAdvertisedVersion);
|
|
SAFEREGCLOSEKEY(hkeyDist);
|
|
SAFEREGCLOSEKEY(hkeyThisDist);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::Advertise(BOOL bFullAdvt)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::Advertise",
|
|
"this=%#x, %B",
|
|
this, bFullAdvt
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
if (m_Style == STYLE_MSICD)
|
|
hr = ICDAdvertise(bFullAdvt);
|
|
else if (m_Style == STYLE_ACTIVE_SETUP)
|
|
hr = ActSetupAdvertise(bFullAdvt);
|
|
else if (m_Style == STYLE_LOGO3)
|
|
hr = Logo3Advertise(bFullAdvt);
|
|
else
|
|
hr = E_UNEXPECTED;
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::Logo3Advertise(BOOL bFullAdvt)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::Logo3Advertise",
|
|
"this=%#x, %B",
|
|
this, bFullAdvt
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD dwLen = 0;
|
|
DWORD lResult = 0;
|
|
LPSTR szDU = NULL;
|
|
HKEY hkeyLogo3 = 0;
|
|
HKEY hkeyDist = 0;
|
|
HKEY hkeyAvailVersion = 0;
|
|
DWORD dwAdState;
|
|
static const char *szAvailableVersion = "AvailableVersion";
|
|
static const char *szPrecache = "Precache";
|
|
static const char *szHREF = "HREF";
|
|
static const char *szTitle = "Title";
|
|
char szVersionBuf[MAX_PATH];
|
|
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_LOGO3_SETTINGS,
|
|
0, KEY_ALL_ACCESS, &hkeyLogo3) != ERROR_SUCCESS) {
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
dwLen = WideCharToMultiByte(CP_ACP,0, m_szDistUnit, -1, NULL, 0, NULL, NULL);
|
|
szDU = new char [dwLen];
|
|
if (szDU == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, m_szDistUnit , -1, szDU, dwLen, NULL, NULL);
|
|
|
|
if (RegOpenKeyEx(hkeyLogo3, szDU, 0, KEY_ALL_ACCESS, &hkeyDist) != ERROR_SUCCESS) {
|
|
// Create key if it doesn't exist
|
|
if ((lResult = RegCreateKey(hkeyLogo3, szDU, &hkeyDist)) != ERROR_SUCCESS) {
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (RegOpenKeyEx(hkeyDist, szAvailableVersion, 0, KEY_ALL_ACCESS,
|
|
&hkeyAvailVersion) != ERROR_SUCCESS) {
|
|
if ((lResult = RegCreateKey(hkeyDist, szAvailableVersion, &hkeyAvailVersion)) != ERROR_SUCCESS) {
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
wsprintf(szVersionBuf, "%d,%d,%d,%d",
|
|
(m_dwVersionMS & 0xffff0000)>>16,
|
|
(m_dwVersionMS & 0xffff),
|
|
(m_dwVersionLS & 0xffff0000)>>16,
|
|
(m_dwVersionLS & 0xffff));
|
|
|
|
lResult = ::RegSetValueEx(hkeyAvailVersion, NULL, NULL, REG_SZ,
|
|
(unsigned char *)szVersionBuf,
|
|
lstrlen(szVersionBuf) + 1);
|
|
|
|
if (bFullAdvt || IsAbstractDifferent(hkeyAvailVersion, m_szAbstract)) {
|
|
// Clear previous AdState, if any
|
|
dwAdState = SOFTDIST_ADSTATE_NONE;
|
|
// Don't panic if this fails
|
|
lResult = ::RegSetValueEx(hkeyAvailVersion, REGVAL_ADSTATE, NULL,
|
|
REG_DWORD, (unsigned char *)&dwAdState, sizeof(DWORD));
|
|
|
|
// save HREF
|
|
if ((lResult == ERROR_SUCCESS) && m_szHREF) {
|
|
lResult = ::RegSetValueEx(hkeyAvailVersion, szHREF, NULL, REG_SZ,
|
|
(unsigned char *)m_szHREF,
|
|
lstrlen(m_szHREF) + 1);
|
|
}
|
|
|
|
// save Abstract
|
|
if ((lResult == ERROR_SUCCESS) && m_szAbstract) {
|
|
lResult = RegSetValueEx(hkeyAvailVersion, REGVAL_ABSTRACT_AVAILABLE,
|
|
NULL, REG_SZ, (unsigned char *)m_szAbstract,
|
|
lstrlen(m_szAbstract) + 1);
|
|
}
|
|
|
|
// save Title
|
|
if ((lResult == ERROR_SUCCESS) && m_szTitle) {
|
|
lResult = ::RegSetValueEx(hkeyAvailVersion, szTitle, NULL, REG_SZ,
|
|
(unsigned char *)m_szTitle,
|
|
lstrlen(m_szTitle) + 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
|
|
// new advertisement, remove old precache
|
|
if (bFullAdvt)
|
|
::RegDeleteValue(hkeyAvailVersion, szPrecache);
|
|
|
|
|
|
Exit:
|
|
|
|
if (hkeyLogo3) {
|
|
RegCloseKey(hkeyLogo3);
|
|
}
|
|
|
|
if (hkeyDist) {
|
|
RegCloseKey(hkeyDist);
|
|
}
|
|
|
|
if (hkeyAvailVersion) {
|
|
RegCloseKey(hkeyAvailVersion);
|
|
}
|
|
|
|
if (szDU) {
|
|
delete [] szDU;
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::ICDAdvertise(BOOL bFullAdvt)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::ICDAdvertise",
|
|
"this=%#x, %B",
|
|
this, bFullAdvt
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
LONG lResult = ERROR_SUCCESS;
|
|
HKEY hkeyDist =0;
|
|
HKEY hkeyThisDist = 0;
|
|
HKEY hkeyDownloadInfo = 0;
|
|
|
|
HKEY hkeyVersion = 0;
|
|
HKEY hkeyAdvertisedVersion = 0;
|
|
|
|
const static char * szAvailableVersion = "AvailableVersion";
|
|
const static char * szDownloadInfo = "DownloadInformation";
|
|
const static char * szCODEBASE = "CODEBASE";
|
|
const static char * szLOCALCDF = "CDF";
|
|
const static char * szINSTALLER = "Installer";
|
|
const static char * szMSICD = "MSICD";
|
|
const static char * szHREF = "HREF";
|
|
const static char * szPrecache = "Precache";
|
|
char szTmpCodeBase[MAX_PATH+sizeof(szCODEBASE)+5];
|
|
LPSTR pszCodeBase = NULL;
|
|
int numCodeBase;
|
|
POSITION pos;
|
|
|
|
LPSTR pszDist = NULL;
|
|
|
|
char szVersionBuf[MAX_PATH];
|
|
|
|
if ((lResult = RegOpenKeyEx( HKEY_LOCAL_MACHINE, REGSTR_PATH_DIST_UNITS,
|
|
0, KEY_ALL_ACCESS, &hkeyDist)) != ERROR_SUCCESS) {
|
|
if ((lResult = RegCreateKey( HKEY_LOCAL_MACHINE,
|
|
REGSTR_PATH_DIST_UNITS, &hkeyDist)) != ERROR_SUCCESS) {
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (FAILED((hr=::Unicode2Ansi(m_szDistUnit, &pszDist))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
// open/create the dist unit key for this dist unit.
|
|
if (RegOpenKeyEx( hkeyDist, pszDist,
|
|
0, KEY_ALL_ACCESS, &hkeyThisDist) != ERROR_SUCCESS) {
|
|
if ((lResult = RegCreateKey( hkeyDist,
|
|
pszDist, &hkeyThisDist)) != ERROR_SUCCESS) {
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (m_szTitle &&
|
|
((lResult = ::RegSetValueEx(hkeyThisDist, NULL, NULL, REG_SZ,
|
|
(unsigned char *)m_szTitle,
|
|
lstrlen(m_szTitle)+1)) != ERROR_SUCCESS)){
|
|
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
|
|
lResult = ::RegSetValueEx(hkeyThisDist, szINSTALLER, NULL, REG_SZ,
|
|
(unsigned char *)szMSICD, sizeof(szMSICD)+1);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
// open/create the download info key for this dist unit.
|
|
if (RegOpenKeyEx( hkeyThisDist, szDownloadInfo,
|
|
0, KEY_ALL_ACCESS, &hkeyDownloadInfo) != ERROR_SUCCESS) {
|
|
if ((lResult = RegCreateKey( hkeyThisDist,
|
|
szDownloadInfo, &hkeyDownloadInfo)) != ERROR_SUCCESS) {
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
// set download info params
|
|
if (GetCDF() && (lResult = ::RegSetValueEx(hkeyDownloadInfo,
|
|
szLOCALCDF, NULL, REG_SZ, (unsigned char *)GetCDF(), lstrlen(GetCDF())+1)) != ERROR_SUCCESS) {
|
|
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
|
|
pos = m_cbh.GetHeadPosition();
|
|
numCodeBase = 1;
|
|
while (pos != NULL) {
|
|
|
|
CCodeBaseHold *cbh = m_cbh.GetNext(pos);
|
|
if (numCodeBase <= 1)
|
|
lstrcpy((char *)szTmpCodeBase, szCODEBASE);
|
|
else
|
|
wsprintf(szTmpCodeBase, "%s%d", szCODEBASE, numCodeBase);
|
|
|
|
if (FAILED(::Unicode2Ansi(cbh->wszCodeBase,&pszCodeBase))) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
if ((lResult = ::RegSetValueEx(hkeyDownloadInfo, szTmpCodeBase,
|
|
NULL, REG_SZ, (unsigned char *)pszCodeBase, strlen(pszCodeBase))) != ERROR_SUCCESS) {
|
|
|
|
SAFEDELETE(pszCodeBase);
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
|
|
SAFEDELETE(pszCodeBase);
|
|
numCodeBase ++;
|
|
}
|
|
|
|
// Note Version
|
|
wsprintf(szVersionBuf, "%d,%d,%d,%d",
|
|
(m_dwVersionMS & 0xffff0000)>>16,
|
|
(m_dwVersionMS & 0xffff),
|
|
(m_dwVersionLS & 0xffff0000)>>16,
|
|
(m_dwVersionLS & 0xffff));
|
|
|
|
if (RegOpenKeyEx( hkeyThisDist, szAvailableVersion,
|
|
0, KEY_ALL_ACCESS, &hkeyVersion) != ERROR_SUCCESS) {
|
|
if ((lResult = RegCreateKey( hkeyThisDist,
|
|
szAvailableVersion, &hkeyVersion)) != ERROR_SUCCESS) {
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
if (bFullAdvt || IsAbstractDifferent(hkeyVersion, m_szAbstract)) {
|
|
|
|
// Clear previous AdState, if any
|
|
if (RegOpenKey(hkeyThisDist, REGKEY_MSICD_ADVERTISED_VERSION, &hkeyAdvertisedVersion) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwAdState = SOFTDIST_ADSTATE_NONE;
|
|
|
|
// Don't panic if this fails
|
|
lResult = ::RegSetValueEx(hkeyAdvertisedVersion, REGVAL_ADSTATE, NULL, REG_DWORD,
|
|
(unsigned char *)&dwAdState, sizeof(DWORD) );
|
|
}
|
|
}
|
|
|
|
// new advertisement, remove old precache
|
|
if (bFullAdvt)
|
|
::RegDeleteValue(hkeyVersion, szPrecache);
|
|
|
|
lResult = ::RegSetValueEx(hkeyVersion, NULL, NULL, REG_SZ,
|
|
(unsigned char *)szVersionBuf, lstrlen(szVersionBuf)+1);
|
|
// save HREF
|
|
if ( (lResult == ERROR_SUCCESS) && m_szHREF)
|
|
lResult = ::RegSetValueEx(hkeyVersion, szHREF, NULL, REG_SZ,
|
|
(unsigned char *)m_szHREF, lstrlen(m_szHREF)+1);
|
|
// save Abstract
|
|
if ( (lResult == ERROR_SUCCESS) && m_szAbstract)
|
|
lResult = ::RegSetValueEx(hkeyVersion, REGVAL_ABSTRACT_AVAILABLE, NULL, REG_SZ,
|
|
(unsigned char *)m_szAbstract, lstrlen(m_szAbstract)+1);
|
|
|
|
if (lResult != ERROR_SUCCESS) {
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
goto Exit;
|
|
}
|
|
|
|
Exit:
|
|
SAFEDELETE(pszDist);
|
|
SAFEDELETE(pszCodeBase);
|
|
SAFEREGCLOSEKEY(hkeyDownloadInfo);
|
|
SAFEREGCLOSEKEY(hkeyVersion);
|
|
SAFEREGCLOSEKEY(hkeyDist);
|
|
SAFEREGCLOSEKEY(hkeyThisDist);
|
|
SAFEREGCLOSEKEY(hkeyAdvertisedVersion);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
BOOL
|
|
CSoftDist::IsAuthorizedCDF(HKEY hkeyRootDU, BOOL bOptional)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Bool,
|
|
"CSoftDist::IsAuthorizedCDF",
|
|
"this=%#x, %#x, %B",
|
|
this, hkeyRootDU, bOptional
|
|
));
|
|
|
|
const static char *szAuthorizedCDF="AuthorizedCDFPrefix";
|
|
BOOL fResult = FALSE;
|
|
HRESULT hr;
|
|
int iValue = 0;
|
|
CHAR szEnumCDF[MAX_PATH];
|
|
DWORD dwValueSize = MAX_PATH;
|
|
LPWSTR wzCDFURL = 0;
|
|
IInternetSecurityManager *pism = 0;
|
|
DWORD dwZone = 0, dwType = 0;
|
|
HKEY hkeyAuthCDF = 0;
|
|
DWORD dwPolicy = 0;
|
|
DWORD dwContext = 0;
|
|
|
|
if (!hkeyRootDU) {
|
|
goto Exit;
|
|
}
|
|
|
|
if (!m_szCDFURL) {
|
|
goto Exit;
|
|
}
|
|
|
|
if (FAILED(CoInternetCreateSecurityManager(NULL, &pism, 0)) || !pism) {
|
|
goto Exit;
|
|
}
|
|
|
|
if (FAILED(Ansi2Unicode(m_szCDFURL, &wzCDFURL))) {
|
|
goto Exit;
|
|
}
|
|
|
|
pism->ProcessUrlAction(wzCDFURL, URLACTION_CHANNEL_SOFTDIST_PERMISSIONS,
|
|
(BYTE *)&dwPolicy, sizeof(dwPolicy),
|
|
(BYTE *)&dwContext, sizeof(dwContext),
|
|
PUAF_NOUI, 0);
|
|
|
|
if (dwPolicy == URLPOLICY_CHANNEL_SOFTDIST_AUTOINSTALL)
|
|
{
|
|
fResult = TRUE;
|
|
goto Exit;
|
|
}
|
|
|
|
// if no "AuthorizedCDF" key exists we don't do any prefix checking
|
|
if (RegOpenKeyEx( hkeyRootDU, szAuthorizedCDF,
|
|
0, KEY_READ, &hkeyAuthCDF) != ERROR_SUCCESS) {
|
|
|
|
if (bOptional)
|
|
fResult = TRUE;
|
|
goto Exit;
|
|
}
|
|
|
|
iValue = 0;
|
|
while (RegEnumValue(hkeyAuthCDF, iValue++,
|
|
szEnumCDF, &dwValueSize, 0, &dwType, NULL, NULL) == ERROR_SUCCESS) {
|
|
|
|
dwValueSize = MAX_PATH; // reset
|
|
|
|
// check for partial match, if found return true.
|
|
if (StrCmpNI(szEnumCDF, m_szCDFURL, min(lstrlenA(szEnumCDF), lstrlenA(m_szCDFURL))) == 0) {
|
|
fResult = TRUE;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
SAFERELEASE(pism);
|
|
SAFEDELETE(wzCDFURL);
|
|
|
|
if (hkeyAuthCDF)
|
|
RegCloseKey(hkeyAuthCDF);
|
|
|
|
DEBUG_LEAVE(fResult);
|
|
return fResult;
|
|
}
|
|
|
|
BOOL
|
|
CSoftDist::IsCDFNewerVersion(DWORD dwLocFVMS, DWORD dwLocFVLS)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Bool,
|
|
"CSoftDist::IsCDFNewerVersion",
|
|
"this=%#x, %#x, %#x",
|
|
this, dwLocFVMS, dwLocFVLS
|
|
));
|
|
|
|
BOOL fRet = ((m_dwVersionMS > dwLocFVMS) ||
|
|
((m_dwVersionMS == dwLocFVMS) &&
|
|
(m_dwVersionLS > dwLocFVLS)));
|
|
|
|
DEBUG_LEAVE(fRet);
|
|
return fRet;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CSoftDist::IsActSetupLocallyInstalled(LPCWSTR szDistUnit, DWORD dwVersionMS, DWORD dwVersionLS, LPCSTR szLanguages)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::IsActSetupLocallyInstalled",
|
|
"this=%#x, %.80wq, %#x, %#x, %.80q",
|
|
this, szDistUnit, dwVersionMS, dwVersionLS, szLanguages
|
|
));
|
|
|
|
Assert(szDistUnit);
|
|
HRESULT hr = S_FALSE, hr2; // Not installed by active setup.
|
|
LONG lResult = ERROR_SUCCESS;
|
|
LPSTR pszKey = NULL;
|
|
BOOL bAllocedKey = FALSE;
|
|
int nKey;
|
|
|
|
//we've done this at THREE other places in the code, so let's raise this from 1 to 2 *MAX_PATH
|
|
char szKey[2*MAX_PATH];
|
|
char szVersion[MAX_PATH];
|
|
HKEY hKey = NULL;
|
|
DWORD dwSize;
|
|
DWORD dwValue;
|
|
DWORD dwType;
|
|
BOOL fIsInstalled = FALSE;
|
|
WORD wVersion[4];
|
|
LPSTR pszDist = NULL;
|
|
DWORD dwCurMS = 0;
|
|
DWORD dwCurLS = 0;
|
|
|
|
const static char * szLocale = "Locale";
|
|
const static char * szIsInstalled = "IsInstalled";
|
|
const static char * szActVersion = "Version";
|
|
|
|
if (FAILED((hr2=::Unicode2Ansi(szDistUnit, &pszDist))))
|
|
{
|
|
hr = hr2;
|
|
goto Exit;
|
|
}
|
|
|
|
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)
|
|
{
|
|
// Check for the installed language. And see if it fits the availabel szLanguages
|
|
dwSize = sizeof(szVersion);
|
|
if (RegQueryValueEx( hKey, szLocale, NULL, NULL, (LPBYTE)szVersion, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
if (szLanguages && !AreAllLanguagesPresent(szVersion, szLanguages))
|
|
goto Exit;
|
|
}
|
|
|
|
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)
|
|
{
|
|
dwSize = sizeof(szVersion);
|
|
if ( (lResult = RegQueryValueEx(hKey, szActVersion, NULL, &dwType, (LPBYTE)szVersion, &dwSize)) == ERROR_SUCCESS )
|
|
{
|
|
if (dwType == REG_SZ)
|
|
{
|
|
if ( SUCCEEDED(GetVersionFromString(szVersion, &dwCurMS, &dwCurLS)))
|
|
{
|
|
m_distunitinst.dwInstalledVersionMS = dwCurMS;
|
|
m_distunitinst.dwInstalledVersionLS = dwCurLS;
|
|
|
|
if (dwCurMS > dwVersionMS ||
|
|
(dwCurMS == dwVersionMS && dwCurLS >= dwVersionLS)) {
|
|
hr = S_OK;
|
|
} else {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dwSize = 4 * sizeof(WORD);
|
|
if ( (lResult = RegQueryValueEx(hKey, szActVersion, NULL, NULL, (LPBYTE)wVersion, &dwSize)) == ERROR_SUCCESS )
|
|
{
|
|
// The registry version number is saved hi-word MS lo-word MS hi-word LS lo-word LS
|
|
// therefore we need to put the data manualy into the DWORDs
|
|
dwCurMS = (DWORD)wVersion[0] << 16; // Make hi word of MS version
|
|
dwCurMS += (DWORD)wVersion[1]; // Make lo word of MS version
|
|
dwCurLS = (DWORD)wVersion[2] << 16; // Make hi word of LS version
|
|
dwCurLS += (DWORD)wVersion[3]; // Make lo word of LS version
|
|
if (dwCurMS > dwVersionMS ||
|
|
(dwCurMS == dwVersionMS && dwCurLS >= dwVersionLS)) {
|
|
hr = S_OK;
|
|
} else {
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
}
|
|
else
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
}
|
|
}
|
|
// If "Version" doesn't exist we assume its been advertised
|
|
// but not locally installed.
|
|
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (bAllocedKey)
|
|
{
|
|
delete [] pszKey;
|
|
}
|
|
|
|
SAFEREGCLOSEKEY(hKey);
|
|
SAFEDELETE(pszDist);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSoftDist::ActSetupAdvertise(BOOL bFullAdvt)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::ActSetupAdvertise",
|
|
"this=%#x, %B",
|
|
this, bFullAdvt
|
|
));
|
|
|
|
LPSTR pszKey = NULL;
|
|
BOOL bAllocedKey = FALSE;
|
|
int nKey;
|
|
|
|
char szKey[2*MAX_PATH];
|
|
HKEY hKey;
|
|
HRESULT hr = S_OK;
|
|
LPSTR pszDist = NULL;
|
|
LONG lResult = ERROR_SUCCESS;
|
|
static const char *szPrecache = "Precache";
|
|
|
|
if (FAILED((hr=::Unicode2Ansi(m_szDistUnit, &pszDist))))
|
|
{
|
|
goto Exit;
|
|
}
|
|
|
|
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 (RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE,
|
|
KEY_READ|KEY_SET_VALUE, NULL, &hKey, NULL) == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwAdStateInit = SOFTDIST_ADSTATE_NONE;
|
|
|
|
// Note Version
|
|
wsprintf(pszKey, "%d,%d,%d,%d",
|
|
(m_dwVersionMS & 0xffff0000)>>16,
|
|
(m_dwVersionMS & 0xffff),
|
|
(m_dwVersionLS & 0xffff0000)>>16,
|
|
(m_dwVersionLS & 0xffff));
|
|
lResult = ::RegSetValueEx(hKey, REGVAL_VERSION_AVAILABLE, NULL, REG_SZ,
|
|
(unsigned char *)pszKey, lstrlen(pszKey)+1);
|
|
|
|
if (bFullAdvt || IsAbstractDifferent(hKey, m_szAbstract)) {
|
|
// (re)set the ad state
|
|
lResult = ::RegSetValueEx(hKey, REGVAL_ADSTATE, NULL, REG_DWORD,
|
|
(unsigned char *)&dwAdStateInit, sizeof(DWORD) );
|
|
|
|
|
|
if( (lResult == ERROR_SUCCESS) && m_szTitle)
|
|
lResult=RegSetValueEx(hKey,REGVAL_TITLE_AVAILABLE, NULL, REG_SZ,
|
|
(unsigned char *)m_szTitle, lstrlen(m_szTitle)+1);
|
|
|
|
if( (lResult == ERROR_SUCCESS) && m_szAbstract)
|
|
lResult=RegSetValueEx(hKey,REGVAL_ABSTRACT_AVAILABLE, NULL,
|
|
REG_SZ, (unsigned char *)m_szAbstract, lstrlen(m_szAbstract)+1);
|
|
|
|
if( (lResult == ERROR_SUCCESS) && m_szHREF) {
|
|
//
|
|
// Check if this is the IE4 GUID. If so, change IE's
|
|
// First Home Page to point to this HREF.
|
|
/*
|
|
// This is no longer being used because we pop up a dialog instead
|
|
|
|
if (lstrcmpi(pszDist, DISTUNIT_NAME_IE4) == 0) {
|
|
HKEY hKeyIE = 0;
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_IE_MAIN, 0, KEY_SET_VALUE, &hKeyIE) == ERROR_SUCCESS) {
|
|
|
|
RegSetValueEx(hKeyIE,REGVAL_FIRST_HOME_PAGE, NULL,
|
|
REG_SZ, (unsigned char *)m_szHREF, lstrlen(m_szHREF)+1);
|
|
RegCloseKey(hKeyIE);
|
|
}
|
|
}
|
|
*/
|
|
|
|
lResult =RegSetValueEx(hKey,REGVAL_HREF_AVAILABLE, NULL, REG_SZ,
|
|
(unsigned char *)m_szHREF, lstrlen(m_szHREF)+1);
|
|
}
|
|
|
|
}
|
|
|
|
if (lResult != ERROR_SUCCESS)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(lResult);
|
|
}
|
|
|
|
// new advertisement, remove old precache
|
|
if (bFullAdvt)
|
|
::RegDeleteValue(hKey, szPrecache);
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
}
|
|
|
|
Exit:
|
|
|
|
if (bAllocedKey)
|
|
{
|
|
delete [] pszKey;
|
|
}
|
|
|
|
SAFEDELETE(pszDist);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CSoftDist::IsActSetupAdvertised(LPBOOL lpfIsPrecached, LPBOOL lpfIsAuthorized)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::IsActSetupAdvertised",
|
|
"this=%#x, %#x, %#x",
|
|
this, lpfIsPrecached, lpfIsAuthorized
|
|
));
|
|
|
|
HKEY hKey;
|
|
|
|
LPSTR pszTmp = NULL;
|
|
BOOL bAllocedTmp = FALSE;
|
|
int nTmp;
|
|
|
|
char szTmp[2*MAX_PATH];
|
|
DWORD dwSize;
|
|
DWORD dwCurAdvMS = 0;
|
|
DWORD dwCurAdvLS = 0;
|
|
HRESULT hr = S_FALSE, hr2;
|
|
LPSTR pszDist = NULL;
|
|
LONG lResult = ERROR_SUCCESS;
|
|
|
|
const static char * szPrecache = "Precache";
|
|
|
|
ASSERT(lpfIsPrecached && lpfIsAuthorized);
|
|
if (!lpfIsPrecached || !lpfIsAuthorized) {
|
|
hr = E_INVALIDARG;
|
|
goto Exit;
|
|
}
|
|
|
|
*lpfIsPrecached = FALSE;
|
|
*lpfIsAuthorized = TRUE;
|
|
|
|
if (FAILED((hr2=::Unicode2Ansi(m_szDistUnit, &pszDist))))
|
|
{
|
|
hr = hr2;
|
|
goto Exit;
|
|
}
|
|
|
|
hr = S_FALSE; // reset: assume not advertised
|
|
|
|
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(szTmp))
|
|
{
|
|
pszTmp = new CHAR[ulenDist+ulenConst];
|
|
}
|
|
|
|
if (pszTmp)
|
|
{
|
|
bAllocedTmp = TRUE;
|
|
nTmp = ulenDist + ulenConst;
|
|
}
|
|
else
|
|
{
|
|
pszTmp = szTmp;
|
|
nTmp = sizeof(szTmp);
|
|
}
|
|
|
|
StrNCpy(pszTmp, REGKEY_ACTIVESETUP_COMPONENTS, nTmp);
|
|
StrCatBuff(pszTmp, "\\", nTmp);
|
|
StrCatBuff(pszTmp, pszDist, nTmp);
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszTmp, 0, KEY_READ, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
*lpfIsAuthorized = IsAuthorizedCDF(hKey);
|
|
|
|
dwSize = sizeof(szTmp);
|
|
if (RegQueryValueEx( hKey, REGVAL_VERSION_AVAILABLE, NULL, NULL, (LPBYTE)szTmp, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
DWORD Size;
|
|
DWORD dwType;
|
|
char szVersionAdvertised[MAX_PATH];
|
|
DWORD SizeDword = sizeof(DWORD);
|
|
|
|
// check for precache registry key
|
|
if (RegQueryValueEx(hKey, szPrecache, 0, &dwType,
|
|
(unsigned char *)&lResult, &SizeDword) == ERROR_SUCCESS) {
|
|
|
|
// check for success or common error conditions which indicate we have bits.
|
|
if (SUCCEEDED(lResult)) {
|
|
*lpfIsPrecached = TRUE;
|
|
} else {
|
|
*lpfIsPrecached = FALSE;
|
|
}
|
|
|
|
}
|
|
|
|
dwSize = sizeof(szVersionAdvertised);
|
|
m_dwVersionAdvertisedMS = 0;
|
|
m_dwVersionAdvertisedLS = 0;
|
|
// read in the advertised version, if any
|
|
if (RegQueryValueEx( hKey, REGVAL_VERSION_ADVERTISED, NULL, NULL,
|
|
(LPBYTE)szVersionAdvertised, &dwSize) == ERROR_SUCCESS)
|
|
{
|
|
if ( SUCCEEDED(GetVersionFromString(szTmp, &dwCurAdvMS, &dwCurAdvLS)))
|
|
{
|
|
m_dwVersionAdvertisedMS = dwCurAdvMS;
|
|
m_dwVersionAdvertisedLS = dwCurAdvLS;
|
|
}
|
|
SizeDword = sizeof(DWORD);
|
|
RegQueryValueEx( hKey, REGVAL_ADSTATE, NULL, NULL, (LPBYTE)&m_dwAdState, &SizeDword);
|
|
}
|
|
|
|
dwCurAdvMS = 0;
|
|
dwCurAdvLS = 0;
|
|
|
|
// save away the advt info like Title, href, abstract
|
|
// if called from GetDistributionUnitAdvt()
|
|
if (!m_szHREF) {
|
|
if (RegQueryValueEx(hKey, REGVAL_HREF_AVAILABLE, NULL, &dwType,
|
|
NULL, &Size) == ERROR_SUCCESS) {
|
|
|
|
m_szHREF = new char[Size];
|
|
|
|
if (!m_szHREF) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
if (RegQueryValueEx(hKey, REGVAL_HREF_AVAILABLE, NULL, &dwType,
|
|
(unsigned char *)m_szHREF, &Size) != ERROR_SUCCESS) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
if (!m_szTitle) {
|
|
if (RegQueryValueEx(hKey, REGVAL_TITLE_AVAILABLE, NULL, &dwType,
|
|
NULL, &Size) == ERROR_SUCCESS) {
|
|
|
|
m_szTitle = new char[Size];
|
|
|
|
if (!m_szTitle) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
if (RegQueryValueEx(hKey, REGVAL_TITLE_AVAILABLE, NULL, &dwType,
|
|
(unsigned char *)m_szTitle, &Size) != ERROR_SUCCESS) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
if (!m_szAbstract) {
|
|
if (RegQueryValueEx(hKey, REGVAL_ABSTRACT_AVAILABLE, NULL, &dwType,
|
|
NULL, &Size) == ERROR_SUCCESS) {
|
|
|
|
m_szAbstract = new char[Size];
|
|
|
|
if (!m_szAbstract) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
if (RegQueryValueEx(hKey, REGVAL_ABSTRACT_AVAILABLE, NULL, &dwType,
|
|
(unsigned char *)m_szAbstract, &Size) != ERROR_SUCCESS) {
|
|
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto Exit;
|
|
}
|
|
|
|
}
|
|
}
|
|
// If we have a Version available, we are done.
|
|
if ( SUCCEEDED(GetVersionFromString(szTmp, &dwCurAdvMS, &dwCurAdvLS)))
|
|
{
|
|
if (!(m_dwVersionMS|m_dwVersionLS)) {
|
|
m_dwVersionMS = dwCurAdvMS;
|
|
m_dwVersionLS = dwCurAdvLS;
|
|
}
|
|
|
|
if (IsCDFNewerVersion(dwCurAdvMS, dwCurAdvLS)) {
|
|
hr = S_FALSE;
|
|
} else {
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Exit:
|
|
|
|
if (bAllocedTmp)
|
|
{
|
|
delete [] pszTmp;
|
|
}
|
|
|
|
SAFEDELETE(pszDist);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi )
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::GetSoftwareUpdateInfo",
|
|
"this=%#x, %.80wq, %#x",
|
|
this, szDistUnit, psdi
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD dwStyle = STYLE_MSICD;
|
|
BOOL bIsPrecached = FALSE;
|
|
BOOL bIsAuthorized = FALSE;
|
|
|
|
if ( psdi != NULL )
|
|
{
|
|
psdi->szTitle = NULL;
|
|
psdi->szAbstract = NULL;
|
|
psdi->szHREF = NULL;
|
|
}
|
|
|
|
hr = PrepSoftwareUpdate( szDistUnit, &dwStyle );
|
|
if ( FAILED(hr) )
|
|
goto Exit;
|
|
|
|
if (dwStyle == STYLE_MSICD) {
|
|
hr = IsICDAdvertised(&bIsPrecached, &bIsAuthorized);
|
|
} else if (dwStyle == STYLE_LOGO3) {
|
|
hr = IsLogo3Advertised(&bIsPrecached, &bIsAuthorized);
|
|
} else {
|
|
hr = IsActSetupAdvertised(&bIsPrecached, &bIsAuthorized);
|
|
}
|
|
|
|
if ( hr == S_OK ) {
|
|
BOOL bUpdateIsNewer = IsCDFNewerVersion(m_distunitinst.dwInstalledVersionMS, m_distunitinst.dwInstalledVersionLS);
|
|
|
|
if ( psdi != NULL )
|
|
{
|
|
psdi->dwFlags = 0;
|
|
psdi->dwInstalledVersionMS = m_distunitinst.dwInstalledVersionMS;
|
|
psdi->dwInstalledVersionLS = m_distunitinst.dwInstalledVersionLS;
|
|
psdi->dwUpdateVersionMS = m_dwVersionMS;
|
|
psdi->dwUpdateVersionLS = m_dwVersionLS;
|
|
psdi->dwAdvertisedVersionMS = m_dwVersionAdvertisedMS;
|
|
psdi->dwAdvertisedVersionLS = m_dwVersionAdvertisedLS;
|
|
psdi->dwAdState = m_dwAdState;
|
|
// conjure up the flags
|
|
// Note: we never set the e-mail flag.
|
|
if ( bIsPrecached )
|
|
psdi->dwFlags |= SOFTDIST_FLAG_USAGE_PRECACHE;
|
|
|
|
// REVIEW: Is this true?
|
|
// If we're precached and the update version matches the installed version,
|
|
// then we've already auto-installed, or close enough for the purposes of
|
|
// advertisement.
|
|
if ( psdi->dwInstalledVersionMS == psdi->dwUpdateVersionMS &&
|
|
psdi->dwInstalledVersionLS == psdi->dwUpdateVersionLS )
|
|
psdi->dwFlags |= SOFTDIST_FLAG_USAGE_AUTOINSTALL;
|
|
|
|
if (m_szTitle)
|
|
{
|
|
hr = Ansi2Unicode( m_szTitle, &psdi->szTitle );
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
}
|
|
|
|
if (m_szAbstract)
|
|
{
|
|
hr = Ansi2Unicode( m_szAbstract, &psdi->szAbstract );
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
}
|
|
|
|
if (m_szHREF)
|
|
{
|
|
hr = Ansi2Unicode( m_szHREF, &psdi->szHREF );
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
}
|
|
} // if caller wants SOFTDISTINFO
|
|
|
|
if ( bUpdateIsNewer )
|
|
hr = S_OK;
|
|
else
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
// return at least the current version in this situation
|
|
if ( psdi != NULL )
|
|
{
|
|
psdi->dwFlags = 0;
|
|
psdi->dwInstalledVersionMS = m_distunitinst.dwInstalledVersionMS;
|
|
psdi->dwInstalledVersionLS = m_distunitinst.dwInstalledVersionLS;
|
|
psdi->dwUpdateVersionMS = 0;
|
|
psdi->dwUpdateVersionLS = 0;
|
|
psdi->dwAdvertisedVersionMS = 0;
|
|
psdi->dwAdvertisedVersionLS = 0;
|
|
psdi->dwAdState = 0;
|
|
}
|
|
|
|
hr = E_INVALIDARG; // szDistUnit has no advertising data, not subscribed?
|
|
// BUGBUG: we want to be able to populate the SOFTDISTINFO before the first
|
|
// advertised update, but this class won't scoop up the necessary goo
|
|
// prior.
|
|
|
|
}
|
|
|
|
Exit:
|
|
|
|
if ( FAILED(hr) && psdi != NULL )
|
|
{
|
|
SAFEDELETE(psdi->szTitle);
|
|
SAFEDELETE(psdi->szAbstract);
|
|
SAFEDELETE(psdi->szHREF);
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::SetSoftwareUpdateAdvertisementState( LPCWSTR szDistUnit,
|
|
DWORD dwAdState,
|
|
DWORD dwAdvertisedVersionMS,
|
|
DWORD dwAdvertisedVersionLS )
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::SetSoftwareUpdateAdvertisementState",
|
|
"this=%#x, %.80wq, %#x, %#x, %#x",
|
|
this, szDistUnit, dwAdState, dwAdvertisedVersionMS, dwAdvertisedVersionLS
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD dwStyle;
|
|
TCHAR *pszDU = NULL;
|
|
|
|
hr = Unicode2Ansi( szDistUnit, &pszDU );
|
|
|
|
// code around assumes that MAX_PATH is MAX size of dist unit
|
|
// we try to make a key name with the distunit and that limit is
|
|
// now MAX_PATH. Hence the reasoning to limit this to MAX_PATH
|
|
if (FAILED(hr) || (lstrlenW(szDistUnit) > MAX_PATH)) {
|
|
if (SUCCEEDED(hr)) {
|
|
hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
|
|
}
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
// BUFFER OVERRUN : limit size in of distunit
|
|
hr = PrepSoftwareUpdate( szDistUnit, &dwStyle );
|
|
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
if (dwStyle == STYLE_MSICD)
|
|
{
|
|
LONG lResult = ERROR_SUCCESS;
|
|
HKEY hkeyDist =0;
|
|
HKEY hkeyThisDist = 0;
|
|
HKEY hkeyAdvertisedVersion = 0;
|
|
|
|
char szTmp[2*MAX_PATH];
|
|
wnsprintf( szTmp, sizeof(szTmp)-1, "%s\\%s\\%s", REGSTR_PATH_DIST_UNITS, pszDU, REGKEY_MSICD_ADVERTISED_VERSION );
|
|
|
|
if (RegCreateKey(HKEY_LOCAL_MACHINE, szTmp, &hkeyAdvertisedVersion) == ERROR_SUCCESS)
|
|
{
|
|
// Note Version
|
|
wsprintf(szTmp, "%d,%d,%d,%d",
|
|
(dwAdvertisedVersionMS & 0xffff0000)>>16,
|
|
(dwAdvertisedVersionMS & 0xffff),
|
|
(dwAdvertisedVersionLS & 0xffff0000)>>16,
|
|
(dwAdvertisedVersionLS & 0xffff));
|
|
lResult = ::RegSetValueEx(hkeyAdvertisedVersion, NULL, NULL, REG_SZ,
|
|
(unsigned char *)szTmp, lstrlen(szTmp)+1);
|
|
if ( lResult == ERROR_SUCCESS )
|
|
{
|
|
lResult = ::RegSetValueEx(hkeyAdvertisedVersion, REGVAL_ADSTATE, NULL, REG_DWORD,
|
|
(unsigned char *)&dwAdState, sizeof(DWORD) );
|
|
if ( lResult != ERROR_SUCCESS )
|
|
hr = HRESULT_FROM_WIN32( lResult );
|
|
}
|
|
else
|
|
hr = HRESULT_FROM_WIN32( lResult );
|
|
|
|
RegCloseKey( hkeyAdvertisedVersion );
|
|
}
|
|
}
|
|
else if (dwStyle == STYLE_LOGO3)
|
|
{
|
|
LONG lResult = ERROR_SUCCESS;
|
|
HKEY hkeyDist =0;
|
|
HKEY hkeyThisDist = 0;
|
|
HKEY hkeyAvailableVersion = 0;
|
|
|
|
char szTmp[2*MAX_PATH];
|
|
wnsprintf( szTmp, sizeof(szTmp)-1, "%s\\%s\\%s", REGSTR_PATH_LOGO3_SETTINGS, pszDU, REGKEY_LOGO3_AVAILABLE_VERSION );
|
|
|
|
if (RegCreateKey(HKEY_LOCAL_MACHINE, szTmp, &hkeyAvailableVersion) == ERROR_SUCCESS)
|
|
{
|
|
// Note Version
|
|
wsprintf(szTmp, "%d,%d,%d,%d",
|
|
(dwAdvertisedVersionMS & 0xffff0000)>>16,
|
|
(dwAdvertisedVersionMS & 0xffff),
|
|
(dwAdvertisedVersionLS & 0xffff0000)>>16,
|
|
(dwAdvertisedVersionLS & 0xffff));
|
|
lResult = ::RegSetValueEx(hkeyAvailableVersion, REGSTR_LOGO3_ADVERTISED_VERSION, NULL, REG_SZ,
|
|
(unsigned char *)szTmp, lstrlen(szTmp)+1);
|
|
if ( lResult == ERROR_SUCCESS )
|
|
{
|
|
lResult = ::RegSetValueEx(hkeyAvailableVersion, REGVAL_ADSTATE, NULL, REG_DWORD,
|
|
(unsigned char *)&dwAdState, sizeof(DWORD) );
|
|
if ( lResult != ERROR_SUCCESS )
|
|
hr = HRESULT_FROM_WIN32( lResult );
|
|
}
|
|
else
|
|
hr = HRESULT_FROM_WIN32( lResult );
|
|
|
|
RegCloseKey( hkeyAvailableVersion );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LPSTR pszKey = NULL;
|
|
BOOL bAllocedKey = FALSE;
|
|
int nKey;
|
|
|
|
CHAR szKey[2*MAX_PATH];
|
|
HKEY hKey;
|
|
LONG lResult = ERROR_SUCCESS;
|
|
|
|
ULONG ulenDist = lstrlenA(pszDU);
|
|
//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, pszDU, nKey);
|
|
if (RegOpenKeyEx( HKEY_LOCAL_MACHINE, pszKey, 0, KEY_WRITE , &hKey ) == ERROR_SUCCESS)
|
|
{
|
|
// Note Version
|
|
wsprintf(pszKey, "%d,%d,%d,%d",
|
|
(dwAdvertisedVersionMS & 0xffff0000)>>16,
|
|
(dwAdvertisedVersionMS & 0xffff),
|
|
(dwAdvertisedVersionLS & 0xffff0000)>>16,
|
|
(dwAdvertisedVersionLS & 0xffff));
|
|
lResult = ::RegSetValueEx(hKey, REGVAL_VERSION_ADVERTISED, NULL, REG_SZ,
|
|
(unsigned char *)pszKey, lstrlen(pszKey)+1);
|
|
if ( lResult == ERROR_SUCCESS )
|
|
{
|
|
lResult = ::RegSetValueEx(hKey, REGVAL_ADSTATE, NULL, REG_DWORD,
|
|
(unsigned char *)&dwAdState, sizeof(DWORD) );
|
|
if ( lResult != ERROR_SUCCESS )
|
|
hr = HRESULT_FROM_WIN32( lResult );
|
|
}
|
|
else
|
|
hr = HRESULT_FROM_WIN32( lResult );
|
|
|
|
RegCloseKey( hKey );
|
|
}
|
|
|
|
if (bAllocedKey)
|
|
{
|
|
delete [] pszKey;
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
SAFEDELETE(pszDU);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CSoftDist::PrepSoftwareUpdate( LPCWSTR szDistUnit, DWORD *pdwStyle )
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::PrepSoftwareUpdate",
|
|
"this=%#x, %.80wq, %#x",
|
|
this, szDistUnit, pdwStyle
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
*pdwStyle = STYLE_MSICD;
|
|
|
|
hr = CDLDupWStr( &m_szDistUnit, szDistUnit );
|
|
if ( FAILED(hr) )
|
|
goto Exit;
|
|
|
|
hr = IsICDLocallyInstalled(m_szDistUnit, m_dwVersionMS, m_dwVersionLS, m_szLanguages);
|
|
if (FAILED(hr))
|
|
goto Exit;
|
|
|
|
if (!IsAnyInstalled()) {
|
|
|
|
hr = IsActSetupLocallyInstalled(m_szDistUnit, m_dwVersionMS, m_dwVersionLS, m_szLanguages);
|
|
if (FAILED(hr))
|
|
{
|
|
goto Exit;
|
|
}
|
|
else if (hr == S_OK)
|
|
{
|
|
*pdwStyle = STYLE_ACTIVE_SETUP;
|
|
goto Exit;
|
|
}
|
|
|
|
if (!IsAnyInstalled()) {
|
|
hr = IsLogo3LocallyInstalled(m_szDistUnit, m_dwVersionMS, m_dwVersionLS, m_szLanguages);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
if (!IsAnyInstalled()) {
|
|
// some prev version must be installed for this to succeed
|
|
hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
|
|
goto Exit;
|
|
}
|
|
}
|
|
else if (hr == S_OK)
|
|
{
|
|
*pdwStyle = STYLE_LOGO3;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
Exit:
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CSoftDist::Logo3DownloadNext()
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::Logo3DownloadNext",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
HRESULT hr = S_FALSE;
|
|
FILETIME ftExpireTime;
|
|
FILETIME ftTime;
|
|
LPWSTR wszCodeBase = NULL;
|
|
LPSTR szDownloadedCodeBase = NULL;
|
|
LPSTR szMainCodeBase = NULL;
|
|
LPSTR szDownloadedFile = NULL;
|
|
LPSTR pszExtn = NULL;
|
|
DWORD dwSize = 0;
|
|
DWORD dwBytes;
|
|
CCodeBaseHold *pcbhPrev = NULL;
|
|
CCodeBaseHold *pcbhCur = NULL;
|
|
LISTPOSITION lpos = 0, lposOld = 0;
|
|
BOOL bFound = FALSE;
|
|
BOOL bFakeCacheEntry;
|
|
TCHAR achFileName[MAX_PATH];
|
|
LPINTERNET_CACHE_ENTRY_INFO lpCacheEntryInfo = NULL;
|
|
char achBuffer[MAX_CACHE_ENTRY_INFO_SIZE];
|
|
|
|
pcbhPrev = m_cbh.GetAt(m_curPos);
|
|
Assert(pcbhPrev);
|
|
|
|
if (FAILED(hr = Unicode2Ansi(pcbhPrev->wszCodeBase, &szDownloadedCodeBase))) {
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFO)achBuffer;
|
|
dwSize = MAX_CACHE_ENTRY_INFO_SIZE;
|
|
if (!GetUrlCacheEntryInfo(szDownloadedCodeBase, lpCacheEntryInfo, &dwSize)) {
|
|
// this should never happen
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
|
|
szDownloadedFile = new char[lstrlen(lpCacheEntryInfo->lpszLocalFileName) + 1];
|
|
if (szDownloadedFile == NULL) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
lstrcpy(szDownloadedFile, lpCacheEntryInfo->lpszLocalFileName);
|
|
|
|
GetSystemTimeAsFileTime(&ftTime);
|
|
ftExpireTime.dwLowDateTime = (DWORD)0;
|
|
ftExpireTime.dwHighDateTime = (DWORD)0;
|
|
|
|
// Mark all CCodeBaseHold's with same group as downloaded and find
|
|
// main codebase
|
|
|
|
bFakeCacheEntry = TRUE;
|
|
szMainCodeBase = NULL;
|
|
lpos = m_cbh.GetHeadPosition();
|
|
while (lpos) {
|
|
pcbhCur = m_cbh.GetNext(lpos);
|
|
|
|
if (pcbhCur->dwFlags & CBH_FLAGS_MAIN_CODEBASE) {
|
|
Assert(szMainCodeBase == NULL); // we should only get here once
|
|
if (FAILED(Unicode2Ansi(pcbhCur->wszCodeBase, &szMainCodeBase))) {
|
|
hr = E_FAIL;
|
|
goto Exit;
|
|
}
|
|
if (pcbhCur == pcbhPrev || StrCmpW(pcbhCur->wszDLGroup, pcbhPrev->wszDLGroup)) {
|
|
bFakeCacheEntry = FALSE;
|
|
}
|
|
}
|
|
|
|
if (pcbhCur == pcbhPrev) {
|
|
continue;
|
|
}
|
|
if (!StrCmpW(pcbhPrev->wszDLGroup, pcbhCur->wszDLGroup)) {
|
|
pcbhCur->dwFlags |= CBH_FLAGS_DOWNLOADED;
|
|
}
|
|
}
|
|
|
|
// Fake a cache entry for this
|
|
if (bFakeCacheEntry) {
|
|
Assert(szMainCodeBase != NULL);
|
|
|
|
lpCacheEntryInfo = (LPINTERNET_CACHE_ENTRY_INFO)achBuffer;
|
|
dwSize = MAX_CACHE_ENTRY_INFO_SIZE;
|
|
if (!GetUrlCacheEntryInfo(szMainCodeBase, lpCacheEntryInfo, &dwSize)) {
|
|
pszExtn = PathFindExtension(szMainCodeBase) + 1;
|
|
if (CreateUrlCacheEntry((LPCSTR)szMainCodeBase, 0, pszExtn,
|
|
achFileName, 0)) {
|
|
CopyFile(szDownloadedFile, achFileName, FALSE);
|
|
CommitUrlCacheEntry(szMainCodeBase, achFileName, ftExpireTime,
|
|
ftTime, NORMAL_CACHE_ENTRY, NULL, 0,
|
|
pszExtn, szDownloadedCodeBase);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Iterate list until we get a new group
|
|
|
|
pcbhCur = NULL;
|
|
lpos = m_cbh.GetHeadPosition();
|
|
while (lpos) {
|
|
lposOld = lpos;
|
|
pcbhCur = m_cbh.GetNext(lpos);
|
|
|
|
if (!(pcbhCur->dwFlags & CBH_FLAGS_DOWNLOADED)) {
|
|
m_curPos = lposOld;
|
|
bFound = TRUE;
|
|
pcbhCur->dwFlags |= CBH_FLAGS_DOWNLOADED;
|
|
hr = CDLDupWStr(&wszCodeBase, pcbhCur->wszCodeBase);
|
|
break;
|
|
}
|
|
}
|
|
|
|
hr = (bFound) ? (Logo3Download(wszCodeBase)) : (S_FALSE);
|
|
|
|
Exit:
|
|
|
|
SAFEDELETE(szDownloadedCodeBase);
|
|
SAFEDELETE(szDownloadedFile);
|
|
SAFEDELETE(szMainCodeBase);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CSoftDist::Logo3DownloadRedundant()
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::Logo3DownloadRedundant",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
HRESULT hr = S_FALSE;
|
|
LPWSTR szCodeBase = NULL;
|
|
DWORD dwSize = 0;
|
|
CCodeBaseHold *pcbhPrev = NULL;
|
|
CCodeBaseHold *pcbhCur = NULL;
|
|
LISTPOSITION lpos = 0, lposOld = 0;
|
|
BOOL bFound = FALSE;
|
|
|
|
pcbhPrev = m_cbh.GetAt(m_curPos);
|
|
Assert(pcbhPrev);
|
|
|
|
// Find first undownloaded codebase of the same group
|
|
|
|
lpos = m_cbh.GetHeadPosition();
|
|
while (lpos) {
|
|
lposOld = lpos;
|
|
pcbhCur = m_cbh.GetNext(lpos);
|
|
if (!(pcbhCur->dwFlags & CBH_FLAGS_DOWNLOADED) &&
|
|
!StrCmpW(pcbhCur->wszDLGroup, pcbhPrev->wszDLGroup)) {
|
|
bFound = TRUE;
|
|
m_curPos = lposOld;
|
|
pcbhCur->dwFlags |= CBH_FLAGS_DOWNLOADED;
|
|
hr = CDLDupWStr(&szCodeBase, pcbhCur->wszCodeBase);
|
|
dwSize = pcbhCur->dwSize;
|
|
break;
|
|
}
|
|
}
|
|
|
|
hr = (bFound) ? (Logo3Download(szCodeBase)) : (S_FALSE);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CSoftDist::Logo3Download(LPWSTR szCodeBase)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CSoftDist::Logo3Download",
|
|
"this=%#x, %.80wq",
|
|
szCodeBase
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD dwLen = 0;
|
|
char achCodeBase[INTERNET_MAX_PATH_LENGTH];
|
|
IMoniker *pmk = NULL;
|
|
Logo3CodeDLBSC *pCDLBSC = NULL;
|
|
IBindCtx *pabc = NULL;
|
|
IBindStatusCallback *pbscOld = NULL;
|
|
IUnknown *pUnk = NULL;
|
|
|
|
hr = CreateURLMoniker(NULL, szCodeBase, &pmk);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
dwLen = INTERNET_MAX_PATH_LENGTH;
|
|
WideCharToMultiByte(CP_ACP, 0, szCodeBase , -1, achCodeBase,
|
|
dwLen, NULL, NULL);
|
|
|
|
Assert(m_pClientBSC);
|
|
|
|
pCDLBSC = new Logo3CodeDLBSC(this, m_pClientBSC, achCodeBase,
|
|
m_szDistUnit);
|
|
if (pCDLBSC == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
SAFERELEASE(pmk);
|
|
m_pClientBSC->Release();
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
hr = CreateBindCtx(0, &pabc);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = RegisterBindStatusCallback(pabc, pCDLBSC, &pbscOld, 0);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pCDLBSC->SetBindCtx(pabc);
|
|
hr = pmk->BindToStorage(pabc, NULL, IID_IUnknown, (void **)&pUnk);
|
|
if (FAILED(hr) && hr != E_PENDING)
|
|
{
|
|
RevokeBindStatusCallback(pabc, pCDLBSC);
|
|
}
|
|
}
|
|
|
|
if (pUnk) {
|
|
pUnk->Release();
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
|
|
SAFERELEASE(pCDLBSC);
|
|
SAFERELEASE(pabc);
|
|
SAFERELEASE(pbscOld);
|
|
SAFERELEASE(pmk);
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
// Replace the ';' separator with '\0' and count the number of languages in the string.
|
|
void PrepareLanguage(LPSTR lpLang)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
None,
|
|
"PrepareLanguage",
|
|
"%.80q",
|
|
lpLang
|
|
));
|
|
|
|
LPSTR lpTmp;
|
|
int index = 0;
|
|
|
|
if (lpLang)
|
|
{
|
|
index = 1;
|
|
lpTmp = lpLang;
|
|
while (*lpTmp)
|
|
{
|
|
if (*lpTmp == ';')
|
|
{
|
|
*lpTmp = '\0';
|
|
index++;
|
|
}
|
|
lpTmp = CharNext(lpTmp);
|
|
}
|
|
}
|
|
|
|
DEBUG_LEAVE(0);
|
|
return;
|
|
}
|
|
|
|
// Checks if all languages in the semicolon separated list of lpszLang1 are also in lpszLang2
|
|
BOOL AreAllLanguagesPresent(LPCSTR lpszLang1, LPCSTR lpszLang2)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Bool,
|
|
"AreAllLanguagesPresent",
|
|
"%.80q, %.80q",
|
|
lpszLang1, lpszLang2
|
|
));
|
|
|
|
LPSTR lpLang1 = NULL;
|
|
LPSTR lpLang2 = NULL;
|
|
LPSTR lpTmp1; // Pointer into lpLang1
|
|
LPSTR lpTmp2; // pointer into lpLang2
|
|
BOOL bAllPresent = FALSE;
|
|
BOOL bFoundOne = TRUE;
|
|
|
|
if (lpszLang2 == NULL) // No language in the CDF, assume all languages are OK
|
|
{
|
|
DEBUG_LEAVE(TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
// Make a copy of the language strings
|
|
lpLang1 = new char[lstrlen(lpszLang1) + 2];
|
|
lpLang2 = new char[lstrlen(lpszLang2) + 2];
|
|
|
|
if ((lpLang1) && (lpLang2))
|
|
{
|
|
strcpy(lpLang1, lpszLang1);
|
|
strcpy(lpLang2, lpszLang2);
|
|
PrepareLanguage(lpLang1);
|
|
PrepareLanguage(lpLang2);
|
|
lpTmp1 = lpLang1;
|
|
while ((*lpTmp1) && (bFoundOne))
|
|
{
|
|
lpTmp2 = lpLang2;
|
|
bFoundOne = FALSE;
|
|
while ((*lpTmp2) && !bFoundOne)
|
|
{
|
|
bFoundOne = (lstrcmpi(lpTmp1, lpTmp2) == 0);
|
|
lpTmp2 += lstrlen(lpTmp2) + 1;
|
|
}
|
|
lpTmp1 += lstrlen(lpTmp1) + 1;
|
|
}
|
|
bAllPresent = bFoundOne;
|
|
}
|
|
|
|
SAFEDELETE(lpLang1);
|
|
SAFEDELETE(lpLang2);
|
|
|
|
DEBUG_LEAVE(bAllPresent);
|
|
return bAllPresent;
|
|
}
|
|
|
|
STDAPI GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi )
|
|
{
|
|
DEBUG_ENTER_API((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"GetSoftwareUpdateInfo",
|
|
"%.80wq, %#x",
|
|
szDistUnit, psdi
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if ( psdi == NULL ||
|
|
(psdi->cbSize == sizeof(SOFTDISTINFO) && psdi->dwReserved == 0) )
|
|
{
|
|
CSoftDist *pSoftDist = new CSoftDist();
|
|
|
|
if (!pSoftDist) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
hr = pSoftDist->GetSoftwareUpdateInfo(szDistUnit, psdi);
|
|
|
|
SAFERELEASE(pSoftDist);
|
|
|
|
}
|
|
else
|
|
hr = E_INVALIDARG;
|
|
|
|
Exit:
|
|
|
|
DEBUG_LEAVE_API(hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDAPI SetSoftwareUpdateAdvertisementState( LPCWSTR szDistUnit,
|
|
DWORD dwAdState,
|
|
DWORD dwAdvertisedVersionMS,
|
|
DWORD dwAdvertisedVersionLS )
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"SetSoftwareUpdateAdvertisementState",
|
|
"%.80wq, %#x, %#x, %#x",
|
|
szDistUnit, dwAdState, dwAdvertisedVersionMS, dwAdvertisedVersionLS
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
CSoftDist *pSoftDist = new CSoftDist();
|
|
|
|
if (!pSoftDist) {
|
|
hr = E_OUTOFMEMORY;
|
|
goto Exit;
|
|
}
|
|
|
|
hr = pSoftDist->SetSoftwareUpdateAdvertisementState( szDistUnit,
|
|
dwAdState,
|
|
dwAdvertisedVersionMS,
|
|
dwAdvertisedVersionLS );
|
|
SAFERELEASE(pSoftDist);
|
|
|
|
Exit:
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetStyleFromString(LPSTR szStyle, LPDWORD lpdwStyle)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"GetStyleFromString",
|
|
"%.80q, %#x",
|
|
szStyle, lpdwStyle
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
if (szStyle == NULL || lpdwStyle == NULL) {
|
|
hr = E_INVALIDARG;
|
|
} else if (lstrcmpi(szStyle,DU_STYLE_MSICD) == 0) {
|
|
*lpdwStyle = STYLE_MSICD;
|
|
} else if (lstrcmpi(szStyle,DU_STYLE_ACTIVE_SETUP) == 0) {
|
|
*lpdwStyle = STYLE_ACTIVE_SETUP;
|
|
} else if (lstrcmpi(szStyle,DU_STYLE_MSINSTALL) == 0) {
|
|
*lpdwStyle = STYLE_MSINSTALL;
|
|
} else if (lstrcmpi(szStyle,DU_STYLE_LOGO3) == 0 ) {
|
|
*lpdwStyle = STYLE_LOGO3;
|
|
} else {
|
|
*lpdwStyle = STYLE_UNKNOWN;
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
//*******************************************************************************************
|
|
// CActiveSetupBinding : Wrapper class to simulate control over client binding operation when
|
|
// we are actually dealing with an EXE.
|
|
//*******************************************************************************************
|
|
DWORD WINAPI StartActiveSetup(void *dwArg)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Dword,
|
|
"StartActiveSetup",
|
|
"%#x",
|
|
dwArg
|
|
));
|
|
|
|
CActiveSetupBinding *pasb = (CActiveSetupBinding *)dwArg;
|
|
|
|
ASSERT(pasb);
|
|
pasb->StartActiveSetup();
|
|
|
|
// Should never return.
|
|
ASSERT(FALSE);
|
|
|
|
DEBUG_LEAVE(-1);
|
|
return -1;
|
|
}
|
|
|
|
CActiveSetupBinding::CActiveSetupBinding(IBindCtx *pbc,
|
|
IBindStatusCallback *pbsc, LPWSTR szCodeBase,
|
|
LPWSTR szDistUnit, HRESULT *phr)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
None,
|
|
"CActiveSetupBinding::CActiveSetupBinding",
|
|
"this=%#x, %#x, %#x, %.80wq, %.80wq, %#x",
|
|
this, pbc, pbsc, szCodeBase, szDistUnit, phr
|
|
));
|
|
|
|
HKEY hkAppPath = NULL;
|
|
|
|
ASSERT(pbc);
|
|
ASSERT(pbsc);
|
|
ASSERT(phr);
|
|
|
|
*phr = S_OK;
|
|
fSilent = FALSE;
|
|
|
|
m_pbc = pbc;
|
|
m_pbc->AddRef();
|
|
m_pbsc = pbsc;
|
|
m_pbsc->AddRef();
|
|
|
|
m_dwRef = 1;
|
|
m_hWaitThread = NULL;
|
|
memset(&m_piChild, 0, sizeof(m_piChild));
|
|
|
|
if (FAILED(Unicode2Ansi(szCodeBase, &m_szCodeBase)))
|
|
goto Exit;
|
|
|
|
if (FAILED(Unicode2Ansi(szDistUnit, &m_szDistUnit)))
|
|
goto Exit;
|
|
|
|
ASSERT(m_szCodeBase);
|
|
|
|
// Get actsetup.exe path.
|
|
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
|
|
"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE",
|
|
0, KEY_READ, &hkAppPath) == ERROR_SUCCESS) {
|
|
|
|
long dwSize = MAX_PATH;
|
|
m_szActSetupPath[0] = '\0';
|
|
|
|
if (RegQueryValueA(hkAppPath, NULL, (LPSTR)m_szActSetupPath, &dwSize) == ERROR_SUCCESS) {
|
|
|
|
if ((dwSize <= 1) || (m_szActSetupPath[0] == '\0'))
|
|
goto Exit;
|
|
|
|
LPSTR szCur = &m_szActSetupPath[dwSize-2]; // points to last character
|
|
while (szCur>m_szActSetupPath) {
|
|
if (*szCur == '\\')
|
|
break;
|
|
szCur--;
|
|
}
|
|
|
|
*(++szCur) = '\0'; // Prematurely truncate string (chop off IEXPLORE.EXE)
|
|
|
|
} else
|
|
goto Exit;
|
|
|
|
} else
|
|
goto Exit;
|
|
|
|
// Create thread to monitor status of Active Setup executable.
|
|
m_hWaitThread = CreateThread(NULL, 0, &(::StartActiveSetup), (LPVOID)this, 0, &dwThreadID);
|
|
|
|
Exit:
|
|
*phr = (m_hWaitThread != NULL) ? S_OK : E_FAIL;
|
|
|
|
SAFEREGCLOSEKEY(hkAppPath);
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
CActiveSetupBinding::~CActiveSetupBinding()
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
None,
|
|
"CActiveSetupBinding::~CActiveSetupBinding",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
ASSERT(m_dwRef == 0);
|
|
|
|
SAFERELEASE(m_pbsc);
|
|
SAFERELEASE(m_pbc);
|
|
SAFEDELETE(m_szCodeBase);
|
|
SAFEDELETE(m_szDistUnit);
|
|
|
|
if (m_hWaitThread)
|
|
CloseHandle(m_hWaitThread);
|
|
|
|
if (m_piChild.hProcess)
|
|
CloseHandle(m_piChild.hProcess);
|
|
|
|
if (m_piChild.hThread)
|
|
CloseHandle(m_piChild.hThread);
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
void CActiveSetupBinding::StartActiveSetup(void)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
None,
|
|
"CActiveSetupBinding::StartActiveSetup",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
CHAR szCmdLine[2*MAX_PATH];
|
|
STARTUPINFO si;
|
|
DWORD dwResult;
|
|
LPSTR szSite;
|
|
|
|
//REVIEW: Change to some other suitable value?
|
|
const DWORD dwTimeOut = 100*60*5; // every 5 minutes
|
|
|
|
memset(&si, 0, sizeof(si));
|
|
si.cb = sizeof(STARTUPINFO); // ActSetup.Exe can take care of itself.
|
|
|
|
BINDINFO bi;
|
|
DWORD dwBindf = 0;
|
|
memset(&bi, 0, sizeof(BINDINFO));
|
|
bi.cbSize = sizeof(BINDINFO);
|
|
|
|
m_pbsc->GetBindInfo(&dwBindf, &bi);
|
|
fSilent = (dwBindf & BINDF_SILENTOPERATION) ? TRUE : FALSE;
|
|
|
|
szSite = StrChr(m_szCodeBase, ';');
|
|
if (szSite) {
|
|
*szSite = '\0';
|
|
szSite++;
|
|
SetDefaultDownloadSite(szSite);
|
|
}
|
|
|
|
// compose the pathname for actsetup.exe and then check for
|
|
// file existence before spawning process
|
|
wnsprintfA(szCmdLine, sizeof(szCmdLine)-1, "%sactsetup.exe", m_szActSetupPath);
|
|
|
|
if (GetFileAttributes(szCmdLine) == -1) {
|
|
DoCleanUp(E_NOTIMPL); // auto install or pre download not impl
|
|
delete this;
|
|
goto Exit;
|
|
}
|
|
|
|
// Create proper command line
|
|
|
|
// /r:n - no reboot
|
|
// /d - download only
|
|
// /q - silent mode (does not require user input)
|
|
|
|
wnsprintfA(szCmdLine, sizeof(szCmdLine)-1, "\"%sactsetup.exe\" /J:job.ie4 /r:n /q %s /s:\"%s\" ",
|
|
m_szActSetupPath, fSilent ? "/d" : "", m_szCodeBase);
|
|
|
|
// Use ansi version since Win95 doesn't support unicode version.
|
|
|
|
if (!CreateProcessA(NULL, // lpApplicationName
|
|
szCmdLine, // lpCommandLine
|
|
NULL, // lpProcessAttributes
|
|
NULL, // lpThreadAttributes
|
|
FALSE, // Inherit Handles
|
|
0, // dwCreationFlags
|
|
NULL, // Environment block (inherit callers)
|
|
NULL, // Current directory
|
|
&si, // STARTUPINFO record
|
|
&m_piChild)) { // PROCESSINFOMRATION record
|
|
|
|
delete this;
|
|
goto Exit;
|
|
}
|
|
|
|
// REVIEW: Localize status messages? Messages aren't currently used for anything useful.
|
|
|
|
if (FAILED(m_pbsc->OnStartBinding(0,(IBinding *)this)))
|
|
goto Exit;
|
|
|
|
while ((dwResult = WaitForSingleObject(m_piChild.hProcess, dwTimeOut)) == WAIT_TIMEOUT) {
|
|
|
|
(void) m_pbsc->OnProgress(0,0,BINDSTATUS_DOWNLOADINGDATA, L"ActiveSetup Running");
|
|
|
|
}
|
|
ASSERT(dwResult == WAIT_OBJECT_O);
|
|
|
|
if (GetExitCodeProcess(m_piChild.hProcess, &dwResult)) {
|
|
|
|
//REVIEW: Check for partial return codes.
|
|
|
|
SaveHresult(dwResult);
|
|
|
|
if (SUCCEEDED(dwResult)) {
|
|
|
|
(void) m_pbsc->OnStopBinding(S_OK, NULL);
|
|
|
|
} else {
|
|
|
|
DoCleanUp(dwResult);
|
|
goto Exit;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Install failed, abort process.
|
|
DoCleanUp(E_FAIL);
|
|
goto Exit;
|
|
}
|
|
|
|
delete this;
|
|
|
|
Exit:
|
|
// BINDINFO_FIX(LaszloG) 8/15/96
|
|
ReleaseBindInfo(&bi);
|
|
|
|
DEBUG_LEAVE(0);
|
|
ExitThread(-1);
|
|
}
|
|
|
|
STDMETHODIMP CActiveSetupBinding::QueryInterface(REFIID riid,void ** ppv)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CActiveSetupBinding::IUnknown::QueryInterface",
|
|
"this=%#x, %#x, %#x",
|
|
this, &riid, ppv
|
|
));
|
|
|
|
if ((riid == IID_IUnknown) || (riid == IID_IBinding))
|
|
{
|
|
*ppv = (IBinding *) this;
|
|
AddRef();
|
|
|
|
DEBUG_LEAVE(S_OK);
|
|
return S_OK;
|
|
}
|
|
else
|
|
{
|
|
DEBUG_LEAVE(E_NOINTERFACE);
|
|
return E_NOINTERFACE;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CActiveSetupBinding::AddRef()
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Dword,
|
|
"CActiveSetupBinding::IUnknown::AddRef",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
ULONG ulRet = m_dwRef++;
|
|
|
|
DEBUG_LEAVE(ulRet);
|
|
return ulRet;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CActiveSetupBinding::Release()
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Dword,
|
|
"CActiveSetupBinding::IUnknown::Release",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
if (--m_dwRef == 0) {
|
|
delete this;
|
|
|
|
DEBUG_LEAVE(0);
|
|
return 0;
|
|
}
|
|
|
|
DEBUG_LEAVE(m_dwRef);
|
|
return m_dwRef;
|
|
}
|
|
|
|
HRESULT CActiveSetupBinding::SetDefaultDownloadSite(LPSTR szSite)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CActiveSetupBinding::SetDefaultDownloadSite",
|
|
"this=%#x, %.80q",
|
|
this, szSite
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
const static char * szRegion = "DownloadSiteRegion";
|
|
CHAR szTmp[MAX_PATH];
|
|
DWORD dwSize = 0, dwType = REG_SZ, dwResult;
|
|
HKEY hKey = 0;
|
|
|
|
//static known sizes of buffers.
|
|
|
|
lstrcpy(szTmp, REGKEY_ACTIVESETUP);
|
|
lstrcat(szTmp, "\\Jobs\\Job.IE4");
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szTmp, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
|
|
if (RegQueryValueEx(hKey, szRegion, 0, &dwType, NULL, &dwSize) != ERROR_SUCCESS)
|
|
{
|
|
hr = RegSetValueEx(hKey, szRegion, 0, REG_SZ, (LPBYTE)szSite, strlen(szSite));
|
|
}
|
|
|
|
::RegCloseKey(hKey);
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CActiveSetupBinding::Abort(void)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CActiveSetupBinding::IBinding::Abort",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
HRESULT hr = E_FAIL;
|
|
DWORD dwSize, dwResult;
|
|
HKEY hKey = 0;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_ACTIVESETUP, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
hr = RegSetValueEx(hKey, szControlSetup, 0, REG_DWORD, (LPBYTE)&dwStatusAbort, sizeof(DWORD));
|
|
|
|
::RegCloseKey(hKey);
|
|
}
|
|
|
|
if (SUCCEEDED(hr) && m_hWaitThread)
|
|
{
|
|
// The child thread will terminate when Active Setup finishes and post message
|
|
// to tray agent to terminate.
|
|
}
|
|
else
|
|
{
|
|
// terminate waiting thread
|
|
TerminateThread(m_hWaitThread, E_ABORT);
|
|
|
|
// terminate active setup process
|
|
TerminateProcess(m_piChild.hProcess, E_ABORT);
|
|
|
|
DoCleanUp(E_ABORT);
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CActiveSetupBinding::SaveHresult(HRESULT hrResult)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CActiveSetupBinding::SaveHresult",
|
|
"this=%#x, %#x",
|
|
this, hrResult
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
const static char * szPrecache = "Precache";
|
|
HKEY hKey = 0;
|
|
LPSTR pszTmp = NULL;
|
|
BOOL bAllocedTmp = FALSE;
|
|
int nTmp;
|
|
CHAR szTmp[2*MAX_PATH];
|
|
DWORD dwSize;
|
|
HWND hwnd = 0;
|
|
|
|
ULONG ulenDist = lstrlenA(m_szDistUnit);
|
|
//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(szTmp))
|
|
{
|
|
pszTmp = new CHAR[ulenDist+ulenConst];
|
|
}
|
|
|
|
if (pszTmp)
|
|
{
|
|
bAllocedTmp = TRUE;
|
|
nTmp = ulenDist + ulenConst;
|
|
}
|
|
else
|
|
{
|
|
pszTmp = szTmp;
|
|
nTmp = sizeof(szTmp);
|
|
}
|
|
|
|
StrNCpy(pszTmp, REGKEY_ACTIVESETUP_COMPONENTS, nTmp);
|
|
StrCatBuff(pszTmp, "\\", nTmp);
|
|
StrCatBuff(pszTmp, m_szDistUnit, nTmp);
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, pszTmp, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
// if silent mode or autoinstall / failed then record as precache attempt
|
|
|
|
if (fSilent || (!fSilent && FAILED(hrResult)))
|
|
{
|
|
// for silent (download only), record precache result
|
|
hr = RegSetValueEx(hKey, szPrecache, 0, REG_DWORD, (LPBYTE)&hrResult, sizeof(HRESULT));
|
|
}
|
|
else
|
|
{
|
|
// for non-silent (autoinstall), kill the precache key
|
|
hr = RegDeleteValue(hKey, szPrecache);
|
|
}
|
|
|
|
::RegCloseKey(hKey);
|
|
}
|
|
|
|
// if reboot required, post a message to tray agent message pump if we can find it.
|
|
if (hrResult == ERROR_SUCCESS_REBOOT_REQUIRED)
|
|
{
|
|
hwnd = FindWindow(c_szTrayUI, NULL);
|
|
if (hwnd)
|
|
{
|
|
(void) SendNotifyMessage(hwnd, WM_USER, 0, UM_NEEDREBOOT);
|
|
}
|
|
}
|
|
|
|
if (bAllocedTmp)
|
|
{
|
|
delete [] pszTmp;
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
void CActiveSetupBinding::DoCleanUp(DWORD dwExitCode)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
None,
|
|
"CActiveSetupBinding::DoCleanUp",
|
|
"this=%#x, %#x",
|
|
this, dwExitCode
|
|
));
|
|
|
|
m_pbsc->OnStopBinding(dwExitCode, NULL);
|
|
|
|
SAFERELEASE(m_pbsc);
|
|
SAFERELEASE(m_pbc);
|
|
|
|
// at this point, BindCtx loses all references, deletes itself and
|
|
// its reference to BindStatusCallback. BSC loses all references are
|
|
// deletes its reference to us, so we have no more references &
|
|
// this invokes our destructor which cleans up by closing handles,
|
|
// then do returns on stack to calling point.
|
|
|
|
// we should be implicitly history at this point.
|
|
|
|
DEBUG_LEAVE(0);
|
|
}
|
|
|
|
|
|
STDMETHODIMP CActiveSetupBinding::Suspend(void)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CActiveSetupBinding::IBinding::Suspend",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD dwSize;
|
|
HKEY hKey = 0;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_ACTIVESETUP, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
hr = RegSetValueEx(hKey, szControlSetup, 0, REG_DWORD, (LPBYTE)&dwStatusSuspend, sizeof(DWORD));
|
|
|
|
::RegCloseKey(hKey);
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CActiveSetupBinding::Resume(void)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CActiveSetupBinding::IBinding::Resume",
|
|
"this=%#x",
|
|
this
|
|
));
|
|
|
|
HRESULT hr = S_OK;
|
|
DWORD dwSize;
|
|
HKEY hKey = 0;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY_ACTIVESETUP, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
|
|
{
|
|
hr = RegSetValueEx(hKey, szControlSetup, 0, REG_DWORD, (LPBYTE)&dwStatusResume, sizeof(DWORD));
|
|
|
|
::RegCloseKey(hKey);
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CActiveSetupBinding::SetPriority(LONG nPriority)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CActiveSetupBinding::IBinding::SetPriority",
|
|
"this=%#x, %#x",
|
|
this, nPriority
|
|
));
|
|
|
|
DEBUG_LEAVE(E_NOTIMPL);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP CActiveSetupBinding::GetPriority(LONG *pnPriority)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CActiveSetupBinding::IBinding::GetPriority",
|
|
"this=%#x, %#x",
|
|
this, pnPriority
|
|
));
|
|
|
|
DEBUG_LEAVE(E_NOTIMPL);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
STDMETHODIMP CActiveSetupBinding::GetBindResult(CLSID *pclsidProtocol,
|
|
DWORD *pdwResult, LPWSTR *pszResult,DWORD *pdwReserved)
|
|
{
|
|
DEBUG_ENTER((DBG_DOWNLOAD,
|
|
Hresult,
|
|
"CActiveSetupBinding::IBinding::GetBindResult",
|
|
"this=%#x, %#x, %#x, %#x, %#x",
|
|
this, pclsidProtocol, pdwResult, pszResult, pdwReserved
|
|
));
|
|
|
|
HRESULT hr = NOERROR;
|
|
|
|
if (!pdwResult || !pszResult || pdwReserved)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
*pdwResult = NOERROR;
|
|
*pszResult = NULL;
|
|
}
|
|
|
|
DEBUG_LEAVE(hr);
|
|
return hr;
|
|
}
|