365 lines
11 KiB
C++
365 lines
11 KiB
C++
|
//
|
||
|
// MODULE: DOWNLOAD.CPP
|
||
|
//
|
||
|
// PURPOSE: Downloads and installs the latest trouble shooters.
|
||
|
//
|
||
|
// PROJECT: Generic Troubleshooter DLL for Microsoft AnswerPoint
|
||
|
//
|
||
|
// COMPANY: Saltmine Creative, Inc. (206)-633-4743 support@saltmine.com
|
||
|
//
|
||
|
// AUTHOR: Roman Mach
|
||
|
//
|
||
|
// ORIGINAL DATE: 6/4/96
|
||
|
//
|
||
|
// NOTES:
|
||
|
// 1. Based on PROGRESS.CPP from Microsoft Platform Preview SDK
|
||
|
//
|
||
|
// Version Date By Comments
|
||
|
//--------------------------------------------------------------------
|
||
|
// V0.1 - RM Original
|
||
|
// V0.3 04/09/98 JM/OK+ Local Version for NT5
|
||
|
//
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
|
||
|
class CTSHOOTCtrl;
|
||
|
|
||
|
|
||
|
#include "download.h"
|
||
|
#include "dnldlist.h"
|
||
|
|
||
|
#include "TSHOOT.h"
|
||
|
#include "time.h"
|
||
|
|
||
|
#include "apgts.h"
|
||
|
#include "ErrorEnums.h"
|
||
|
#include "BasicException.h"
|
||
|
#include "apgtsfst.h"
|
||
|
#include "ErrorEnums.h"
|
||
|
#include "bnts.h"
|
||
|
#include "BackupInfo.h"
|
||
|
#include "cachegen.h"
|
||
|
#include "apgtsinf.h"
|
||
|
#include "apgtscmd.h"
|
||
|
#include "apgtshtx.h"
|
||
|
#include "apgtscls.h"
|
||
|
|
||
|
#include "TSHOOTCtl.h"
|
||
|
|
||
|
// ===========================================================================
|
||
|
// CBindStatusCallback Implementation
|
||
|
// ===========================================================================
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::CBindStatusCallback
|
||
|
// ---------------------------------------------------------------------------
|
||
|
CBindStatusCallback::CBindStatusCallback(CTSHOOTCtrl *pEvent, DLITEMTYPES dwItem)
|
||
|
{
|
||
|
m_pbinding = NULL;
|
||
|
m_pstm = NULL;
|
||
|
m_cRef = 1;
|
||
|
|
||
|
m_pEvent = pEvent;
|
||
|
m_data = NULL;
|
||
|
m_datalen = 0;
|
||
|
m_dwItem = dwItem;
|
||
|
|
||
|
} // CBindStatusCallback
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::~CBindStatusCallback
|
||
|
// ---------------------------------------------------------------------------
|
||
|
CBindStatusCallback::~CBindStatusCallback()
|
||
|
{
|
||
|
if (m_data)
|
||
|
delete[] m_data;
|
||
|
} // ~CBindStatusCallback
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::QueryInterface
|
||
|
// ---------------------------------------------------------------------------
|
||
|
STDMETHODIMP
|
||
|
CBindStatusCallback::QueryInterface(REFIID riid, void** ppv)
|
||
|
{
|
||
|
*ppv = NULL;
|
||
|
|
||
|
if (riid==IID_IUnknown || riid==IID_IBindStatusCallback)
|
||
|
{
|
||
|
*ppv = this;
|
||
|
AddRef();
|
||
|
return S_OK;
|
||
|
}
|
||
|
return E_NOINTERFACE;
|
||
|
} // CBindStatusCallback::QueryInterface
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::OnStartBinding
|
||
|
// ---------------------------------------------------------------------------
|
||
|
STDMETHODIMP
|
||
|
CBindStatusCallback::OnStartBinding(DWORD dwReserved, IBinding* pbinding)
|
||
|
{
|
||
|
if (m_pbinding != NULL)
|
||
|
m_pbinding->Release();
|
||
|
m_pbinding = pbinding;
|
||
|
if (m_pbinding != NULL)
|
||
|
{
|
||
|
m_pbinding->AddRef();
|
||
|
//m_pEvent->StatusEventHelper(m_dwItem, LTSC_STARTBIND);
|
||
|
}
|
||
|
return S_OK;
|
||
|
} // CBindStatusCallback::OnStartBinding
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::GetPriority
|
||
|
// ---------------------------------------------------------------------------
|
||
|
STDMETHODIMP
|
||
|
CBindStatusCallback::GetPriority(LONG* pnPriority)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
} // CBindStatusCallback::GetPriority
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::OnLowResource
|
||
|
// ---------------------------------------------------------------------------
|
||
|
STDMETHODIMP
|
||
|
CBindStatusCallback::OnLowResource(DWORD dwReserved)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
} // CBindStatusCallback::OnLowResource
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::OnProgress
|
||
|
// ---------------------------------------------------------------------------
|
||
|
STDMETHODIMP
|
||
|
CBindStatusCallback::OnProgress(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
|
||
|
{
|
||
|
m_pEvent->ProgressEventHelper(m_dwItem, ulProgress, (ulProgress>ulProgressMax)?ulProgress:ulProgressMax);
|
||
|
|
||
|
return(NOERROR);
|
||
|
} // CBindStatusCallback::OnProgress
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::OnStopBinding
|
||
|
// ---------------------------------------------------------------------------
|
||
|
STDMETHODIMP
|
||
|
CBindStatusCallback::OnStopBinding(HRESULT hrStatus, LPCWSTR pszError)
|
||
|
{
|
||
|
if (hrStatus)
|
||
|
m_pEvent->StatusEventHelper(m_dwItem, LTSCERR_STOPBINDINT, hrStatus & 0xFFFF, TRUE);
|
||
|
else
|
||
|
{
|
||
|
DLSTATTYPES dwStat = m_pEvent->ProcessReceivedData(m_dwItem, m_data, m_datalen);
|
||
|
|
||
|
if (dwStat == LTSC_OK)
|
||
|
m_pEvent->StatusEventHelper(m_dwItem, LTSC_STOPBIND, 0, TRUE);
|
||
|
else
|
||
|
m_pEvent->StatusEventHelper(m_dwItem, LTSCERR_STOPBINDPROC, dwStat, TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
if (m_pbinding)
|
||
|
{
|
||
|
m_pbinding->Release();
|
||
|
m_pbinding = NULL;
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
} // CBindStatusCallback::OnStopBinding
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::GetBindInfo
|
||
|
// ---------------------------------------------------------------------------
|
||
|
STDMETHODIMP
|
||
|
CBindStatusCallback::GetBindInfo(DWORD* pgrfBINDF, BINDINFO* pbindInfo)
|
||
|
{
|
||
|
*pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA;
|
||
|
*pgrfBINDF |= BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE;
|
||
|
pbindInfo->cbSize = sizeof(BINDINFO);
|
||
|
pbindInfo->szExtraInfo = NULL;
|
||
|
memset(&pbindInfo->stgmedData, 0, sizeof(STGMEDIUM));
|
||
|
pbindInfo->grfBindInfoF = 0;
|
||
|
pbindInfo->dwBindVerb = BINDVERB_GET;
|
||
|
pbindInfo->szCustomVerb = NULL;
|
||
|
return S_OK;
|
||
|
} // CBindStatusCallback::GetBindInfo
|
||
|
|
||
|
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::OnDataAvailable
|
||
|
// ---------------------------------------------------------------------------
|
||
|
STDMETHODIMP
|
||
|
CBindStatusCallback::OnDataAvailable(DWORD grfBSCF, DWORD dwSize, FORMATETC* pfmtetc, STGMEDIUM* pstgmed)
|
||
|
{
|
||
|
HRESULT hr=S_OK;
|
||
|
DWORD dStrlength=0;
|
||
|
|
||
|
//m_pEvent->StatusEventHelper(m_dwItem, LTSC_START);
|
||
|
|
||
|
// Get the Stream passed
|
||
|
if (BSCF_FIRSTDATANOTIFICATION & grfBSCF)
|
||
|
{
|
||
|
if (!m_pstm && pstgmed->tymed == TYMED_ISTREAM)
|
||
|
{
|
||
|
m_pstm = pstgmed->pstm;
|
||
|
if (m_pstm)
|
||
|
m_pstm->AddRef();
|
||
|
//m_pEvent->StatusEventHelper(m_dwItem, LTSC_FIRST);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If there is some data to be read then go ahead and read them
|
||
|
if (m_pstm && dwSize)
|
||
|
{
|
||
|
DWORD dwActuallyRead = 0; // Placeholder for amount read during this pull
|
||
|
|
||
|
do
|
||
|
{
|
||
|
TCHAR * pNewstr = new TCHAR[dwSize + 1 + m_datalen];
|
||
|
|
||
|
if (pNewstr==NULL)
|
||
|
{
|
||
|
hr = S_FALSE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
hr = m_pstm->Read(&pNewstr[m_datalen], dwSize, &dwActuallyRead);
|
||
|
|
||
|
if (dwActuallyRead)
|
||
|
{
|
||
|
pNewstr[m_datalen + dwActuallyRead] = 0;
|
||
|
|
||
|
if (m_data && m_datalen)
|
||
|
{
|
||
|
memcpy(pNewstr, m_data, m_datalen);
|
||
|
delete[] m_data;
|
||
|
m_data = NULL;
|
||
|
}
|
||
|
|
||
|
//m_pEvent->StatusEventHelper(m_dwItem, LTSC_RCVDATA);
|
||
|
|
||
|
m_data = pNewstr;
|
||
|
m_datalen += dwActuallyRead;
|
||
|
}
|
||
|
else
|
||
|
delete[] pNewstr;
|
||
|
|
||
|
} while (!(hr == E_PENDING || hr == S_FALSE) && SUCCEEDED(hr));
|
||
|
}
|
||
|
|
||
|
if (BSCF_LASTDATANOTIFICATION & grfBSCF)
|
||
|
{
|
||
|
if (m_pstm)
|
||
|
m_pstm->Release();
|
||
|
|
||
|
hr=S_OK; // If it was the last data then we should return S_OK as we just finished reading everything
|
||
|
|
||
|
//m_pEvent->StatusEventHelper(m_dwItem, LTSC_DATADONE);
|
||
|
}
|
||
|
|
||
|
//m_pEvent->StatusEventHelper(m_dwItem, LTSC_STOP);
|
||
|
|
||
|
return hr;
|
||
|
} // CBindStatusCallback::OnDataAvailable
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CBindStatusCallback::OnObjectAvailable
|
||
|
// ---------------------------------------------------------------------------
|
||
|
STDMETHODIMP
|
||
|
CBindStatusCallback::OnObjectAvailable(REFIID riid, IUnknown* punk)
|
||
|
{
|
||
|
return E_NOTIMPL;
|
||
|
} // CBindStatusCallback::OnObjectAvailable
|
||
|
|
||
|
|
||
|
// ===========================================================================
|
||
|
// CDownload Implementation
|
||
|
// ===========================================================================
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CDownload::CDownload
|
||
|
// ---------------------------------------------------------------------------
|
||
|
CDownload::CDownload()
|
||
|
{
|
||
|
m_pmk = 0;
|
||
|
m_pbc = 0;
|
||
|
m_pbsc = 0;
|
||
|
} // CDownload
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CDownload::~CDownload
|
||
|
// ---------------------------------------------------------------------------
|
||
|
CDownload::~CDownload()
|
||
|
{
|
||
|
if (m_pmk)
|
||
|
m_pmk->Release();
|
||
|
if (m_pbc)
|
||
|
m_pbc->Release();
|
||
|
if (m_pbsc)
|
||
|
m_pbsc->Release();
|
||
|
} // ~CDownload
|
||
|
|
||
|
// ---------------------------------------------------------------------------
|
||
|
// %%Function: CDownload::DoDownload
|
||
|
// ---------------------------------------------------------------------------
|
||
|
HRESULT
|
||
|
CDownload::DoDownload(CTSHOOTCtrl *pEvent, LPCTSTR pURL, DLITEMTYPES dwItem)
|
||
|
{
|
||
|
IStream* pstm = NULL;
|
||
|
HRESULT hr;
|
||
|
#ifndef _UNICODE
|
||
|
WCHAR rgwchPath[MAX_PATH];
|
||
|
MultiByteToWideChar(CP_ACP, 0, pURL, -1, rgwchPath, MAX_PATH);
|
||
|
hr = CreateURLMoniker(NULL, rgwchPath, &m_pmk);
|
||
|
#else
|
||
|
hr = CreateURLMoniker(NULL, pURL, &m_pmk);
|
||
|
#endif
|
||
|
if (FAILED(hr))
|
||
|
goto LErrExit;
|
||
|
|
||
|
m_pbsc = new CBindStatusCallback(pEvent, dwItem);
|
||
|
if (m_pbsc == NULL)
|
||
|
{
|
||
|
hr = E_OUTOFMEMORY;
|
||
|
goto LErrExit;
|
||
|
}
|
||
|
hr = CreateBindCtx(0, &m_pbc);
|
||
|
if (FAILED(hr))
|
||
|
goto LErrExit;
|
||
|
hr = RegisterBindStatusCallback(m_pbc,
|
||
|
m_pbsc,
|
||
|
0,
|
||
|
0L);
|
||
|
if (FAILED(hr))
|
||
|
goto LErrExit;
|
||
|
hr = m_pmk->BindToStorage(m_pbc, 0, IID_IStream, (void**)&pstm);
|
||
|
if (FAILED(hr))
|
||
|
goto LErrExit;
|
||
|
return hr;
|
||
|
while (S_OK == m_pmk->IsRunning(m_pbc, NULL, NULL));
|
||
|
Sleep(200);
|
||
|
LErrExit:
|
||
|
if (m_pbc != NULL)
|
||
|
{
|
||
|
m_pbc->Release();
|
||
|
m_pbc = NULL;
|
||
|
}
|
||
|
if (m_pbsc != NULL)
|
||
|
{
|
||
|
m_pbsc->Release();
|
||
|
m_pbsc = NULL;
|
||
|
}
|
||
|
if (m_pmk != NULL)
|
||
|
{
|
||
|
m_pmk->Release();
|
||
|
m_pmk = NULL;
|
||
|
}
|
||
|
if (pstm)
|
||
|
{
|
||
|
pstm->Release();
|
||
|
pstm = NULL;
|
||
|
}
|
||
|
return hr;
|
||
|
} // CDownload::DoDownload
|
||
|
|