681 lines
17 KiB
C++
681 lines
17 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
//
|
|
// Copyright (C) Microsoft Corporation, 2000
|
|
//
|
|
// File: catalog.cpp
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
extern CLIENT_HANDLES ghClientHandles;
|
|
extern ENGINE_EVENTS EngineEvents;
|
|
|
|
const WCHAR AUJOBNAME[] = L"Windows Update";
|
|
|
|
|
|
void DoDownloadStatus(
|
|
DWORD dwDownloadMsg,
|
|
IBackgroundCopyJob *pBGJob,
|
|
IBackgroundCopyError *pBGErr)
|
|
{
|
|
DEBUGMSG("WUAUENG DoDownloadStatus!");
|
|
|
|
switch(dwDownloadMsg)
|
|
{
|
|
case CATMSG_TRANSIENT_ERROR:
|
|
{
|
|
#ifdef DBG
|
|
if (NULL == pBGErr &&
|
|
S_OK != pBGJob->GetError(&pBGErr))
|
|
{
|
|
// break;
|
|
}
|
|
else
|
|
{
|
|
HRESULT hrErr;
|
|
BG_ERROR_CONTEXT bgErrContext;
|
|
|
|
// Formulate error message
|
|
(void) pBGErr->GetError(&bgErrContext, &hrErr);
|
|
DEBUGMSG("WUAUENG DoDownloadStatus - TRANSIENT_ERROR %#lx (context=%d)", hrErr, bgErrContext);
|
|
pBGErr->Release();
|
|
}
|
|
#endif
|
|
EngineEvents.SetEvent(IDOWNLOAD_TRANSIENT_ERROR_EVT);
|
|
}
|
|
break;
|
|
case CATMSG_DOWNLOAD_IN_PROGRESS:
|
|
{
|
|
DEBUGMSG("WUAUENG DoDownloadStatus - DOWNLOAD_IN_PROGRESS");
|
|
EngineEvents.SetEvent(IDOWNLOAD_DOWNLOAD_IN_PROGRESS);
|
|
}
|
|
break;
|
|
case CATMSG_DOWNLOAD_COMPLETE: // Ping required
|
|
{
|
|
// Send ping for each successfully downloaded item.
|
|
DEBUGMSG("WUAUENG DoDownloadStatus - file download done");
|
|
EngineEvents.SetEvent(IDOWNLOAD_COMPLETE_EVT);
|
|
}
|
|
break;
|
|
case CATMSG_DOWNLOAD_ERROR:
|
|
{
|
|
DEBUGMSG("WUAUENG DoDownloadStatus - DOWNLOAD_ERROR");
|
|
//DEBUGMSG("WUAUENG DoDownloadStatus() ping error puid %d and error description %S", ptDownloadStatusData->m_errPuid, ptDownloadStatusData->m_tszErrDesc);
|
|
|
|
IBackgroundCopyFile *pBGFile = NULL;
|
|
|
|
// Found out which item caused the download error
|
|
if (SUCCEEDED(pBGErr->GetFile(&pBGFile)))
|
|
{
|
|
BSTR bstrErrorItemId; // only used if dwDownloadMsg == CATMSG_DOWNLOAD_ERROR
|
|
LPWSTR pwszLocalFileName = NULL;
|
|
|
|
(void) pBGFile->GetLocalName(&pwszLocalFileName);
|
|
|
|
// Ping for download failure
|
|
if (NULL != (bstrErrorItemId = gpAUcatalog->FindItemIdByLocalFileName(pwszLocalFileName)))
|
|
{
|
|
HRESULT hrErr;
|
|
BG_ERROR_CONTEXT bgErrContext;
|
|
TCHAR tszMessage[30];
|
|
|
|
// Formulate error message
|
|
(void) pBGErr->GetError(&bgErrContext, &hrErr);
|
|
(void)StringCchPrintfEx(tszMessage, ARRAYSIZE(tszMessage), NULL, NULL, MISTSAFE_STRING_FLAGS, _T("ctx=%d"), bgErrContext);
|
|
gPingStatus.PingDownload(
|
|
FALSE,
|
|
URLLOGSTATUS_Failed,
|
|
hrErr,
|
|
W2T(bstrErrorItemId),
|
|
NULL,
|
|
tszMessage);
|
|
}
|
|
CoTaskMemFree(pwszLocalFileName);
|
|
|
|
pBGFile->Release();
|
|
}
|
|
#ifdef DBG
|
|
else
|
|
{
|
|
DEBUGMSG("WUAUENG DoDownloadStatus failed to get IBackgroundCopyFile object");
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
default:
|
|
DEBUGMSG("WUAUENG DoDownloadStatus - invalid message");
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
CAUDownloader::~CAUDownloader()
|
|
{
|
|
IBackgroundCopyJob * pjob;
|
|
HRESULT hr ;
|
|
// fixcode optimization check if m_refs != 0
|
|
DEBUGMSG("CAUDownloader::~CAUDownloader() starts");
|
|
|
|
if ( SUCCEEDED(FindDownloadJob(&pjob)))
|
|
{
|
|
DEBUGMSG("Found bits notify interface to release");
|
|
if (FAILED(hr = pjob->SetNotifyInterface(NULL)))
|
|
{
|
|
DEBUGMSG(" failed to delete job notification interface %#lx", hr);
|
|
}
|
|
pjob->Release();
|
|
}
|
|
|
|
if ( FAILED(hr = CoDisconnectObject((IUnknown *)this, 0)) )
|
|
{
|
|
DEBUGMSG("CoDisconnectObject() failed %#lx", hr);
|
|
}
|
|
|
|
DEBUGMSG("WUAUENG: CAUDownloader destructed with m_refs = %d", m_refs);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// when service starts up, find last download job if there is one and reconnect AU to drizzle
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAUDownloader::ContinueLastDownloadJob(/*const GUID & downloadid*/)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IBackgroundCopyJob * pjob = NULL;
|
|
DEBUGMSG("CAUDownloader::ContinueLastDownloadJob() starts");
|
|
if (GUID_NULL != m_DownloadId)
|
|
{
|
|
if (SUCCEEDED(hr = FindDownloadJob(&pjob)) && SUCCEEDED(hr = ReconnectDownloadJob()))
|
|
{
|
|
DEBUGMSG("found and connected to previous download job ");
|
|
goto done;
|
|
}
|
|
else
|
|
{
|
|
DEBUGMSG("fail to find or connect to previous download job");
|
|
m_DownloadId = GUID_NULL;
|
|
}
|
|
}
|
|
done:
|
|
SafeRelease(pjob);
|
|
DEBUGMSG("CAUDownloader::ContinueLastDownloadJob() ends");
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAUDownloader::CreateDownloadJob(IBackgroundCopyJob **ppjob)
|
|
{
|
|
IBackgroundCopyManager * pmanager = NULL;
|
|
HRESULT hr;
|
|
|
|
*ppjob = NULL;
|
|
m_DownloadId = GUID_NULL;
|
|
if (FAILED(hr = CoCreateInstance(__uuidof(BackgroundCopyManager),
|
|
NULL,
|
|
CLSCTX_LOCAL_SERVER,
|
|
__uuidof(IBackgroundCopyManager),
|
|
(void **)&pmanager )))
|
|
{
|
|
DEBUGMSG("CreateDownloadJob : create manager failed %x ", hr);
|
|
goto done;
|
|
}
|
|
|
|
if (FAILED(hr=pmanager->CreateJob( AUJOBNAME ,
|
|
BG_JOB_TYPE_DOWNLOAD,
|
|
&m_DownloadId,
|
|
ppjob )))
|
|
{
|
|
DEBUGMSG("CreateDownloadJob : create job failed %x ", hr);
|
|
goto done;
|
|
}
|
|
|
|
{
|
|
DWORD fFullBandwidth = 0;;
|
|
|
|
// change job priority to full bandwidth if appropriate reg key set.
|
|
if ( SUCCEEDED(GetRegDWordValue(L"FullBandwidth", &fFullBandwidth)) && fFullBandwidth )
|
|
{
|
|
HRESULT hr1 = (*ppjob)->SetPriority(BG_JOB_PRIORITY_FOREGROUND);
|
|
DEBUGMSG("CAUDownloader::CreateDownloadJob -- FULL BANDWIDTH, hr = %#lx", hr1);
|
|
}
|
|
}
|
|
|
|
#ifdef DBG
|
|
WCHAR szGUID[50]; //really need 39 bytes
|
|
int iret;
|
|
|
|
iret = StringFromGUID2(m_DownloadId, //GUID to be converted
|
|
szGUID, //Pointer to resulting string
|
|
ARRAYSIZE(szGUID));//Size of array at lpsz
|
|
if (0 != iret)
|
|
{
|
|
DEBUGMSG("WUAUENG m_DownloadId = %S", szGUID);
|
|
}
|
|
#endif
|
|
|
|
if (FAILED(hr = SetDrizzleNotifyInterface()))
|
|
{
|
|
DEBUGMSG("CreateDownloadJob : set notification interface failed %x", hr);
|
|
}
|
|
done:
|
|
SafeRelease(pmanager);
|
|
if (FAILED(hr))
|
|
{
|
|
Reset();
|
|
SafeReleaseNULL(*ppjob);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAUDownloader::FindDownloadJob(IBackgroundCopyJob ** ppjob)
|
|
{
|
|
IBackgroundCopyManager * pmanager = NULL;
|
|
HRESULT hr;
|
|
|
|
if (FAILED(hr = CoCreateInstance(__uuidof(BackgroundCopyManager),
|
|
NULL,
|
|
CLSCTX_LOCAL_SERVER,
|
|
__uuidof(IBackgroundCopyManager),
|
|
(void **)&pmanager )))
|
|
{
|
|
DEBUGMSG("FindDownloadJob : create manager failed %x ", hr);
|
|
goto done;
|
|
}
|
|
|
|
if (FAILED(hr=pmanager->GetJob(m_DownloadId, ppjob )))
|
|
{
|
|
// DEBUGMSG("FindDownloadJob : get job failed %x ", hr); //might be expected
|
|
}
|
|
done:
|
|
SafeRelease(pmanager);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CAUDownloader::JobTransferred(
|
|
IBackgroundCopyJob * pjob
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
#if DBG
|
|
//
|
|
// Make sure the right job is finished.
|
|
//
|
|
{
|
|
GUID jobId;
|
|
|
|
if (FAILED( hr= pjob->GetId( &jobId )))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if ( jobId != m_DownloadId )
|
|
{
|
|
DEBUGMSG("notified of completion of a download job that I don't own");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Transfer file ownership from downloader to catalogue.
|
|
//
|
|
if (FAILED(hr= pjob->Complete()))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
m_DoDownloadStatus(CATMSG_DOWNLOAD_COMPLETE, pjob);
|
|
|
|
m_dwJobState = NO_BG_JOBSTATE;
|
|
m_DownloadId = GUID_NULL;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CAUDownloader::JobError(
|
|
IBackgroundCopyJob * pjob,
|
|
IBackgroundCopyError * perror
|
|
)
|
|
{
|
|
// download encounter error
|
|
m_DoDownloadStatus(CATMSG_DOWNLOAD_ERROR, pjob, perror);
|
|
|
|
HRESULT hr;
|
|
BG_ERROR_CONTEXT bgEContext;
|
|
if (SUCCEEDED(perror->GetError(&bgEContext, &hr)))
|
|
{
|
|
DEBUGMSG("WUAUNEG JobError callback Context = %d, hr = 0x%x",bgEContext, hr);
|
|
}
|
|
|
|
Reset();
|
|
m_FinishReason = JOB_ERROR;
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CAUDownloader::JobModification(
|
|
IBackgroundCopyJob * pjob,
|
|
DWORD /*dwReserved*/
|
|
)
|
|
{
|
|
BG_JOB_STATE state;
|
|
HRESULT hr;
|
|
if (FAILED(hr= pjob->GetState(&state)))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (m_dwJobState == state)
|
|
{
|
|
goto Done;
|
|
}
|
|
DEBUGMSG("WUAUENG JobModification callback");
|
|
switch (state)
|
|
{
|
|
case BG_JOB_STATE_QUEUED:
|
|
DEBUGMSG("WUAUENG JobModification: Drizzle notified BG_JOB_STATE_QUEUED");
|
|
ghClientHandles.ClientRemoveTrayIcon();
|
|
break;
|
|
case BG_JOB_STATE_TRANSFERRING:
|
|
DEBUGMSG("WUAUENG JobModification: Drizzle notified BG_JOB_STATE_TRANSFERRING");
|
|
m_DoDownloadStatus(CATMSG_DOWNLOAD_IN_PROGRESS, pjob);
|
|
ghClientHandles.ClientAddTrayIcon();
|
|
break;
|
|
case BG_JOB_STATE_TRANSIENT_ERROR:
|
|
{
|
|
DEBUGMSG("WUAUENG JobModification: Drizzle notified BG_JOB_STATE_TRANSIENT_ERROR");
|
|
m_DoDownloadStatus(CATMSG_TRANSIENT_ERROR, pjob);
|
|
break;
|
|
}
|
|
case BG_JOB_STATE_SUSPENDED:
|
|
case BG_JOB_STATE_ERROR: //What about BG_JOB_STATE_ERROR ?
|
|
case BG_JOB_STATE_TRANSFERRED:
|
|
case BG_JOB_STATE_ACKNOWLEDGED:
|
|
case BG_JOB_STATE_CONNECTING:
|
|
{
|
|
DEBUGMSG("WUAUENG JobModification: Drizzle notified BG_JOB_STATE = %d", state);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
DEBUGMSG("WUAUENG Drizzle notified unexpected BG_JOB_STATE %d",state);
|
|
}
|
|
}
|
|
m_dwJobState = state;
|
|
Done:
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CAUDownloader::SetDrizzleNotifyInterface()
|
|
{
|
|
HRESULT hr ;
|
|
IBackgroundCopyJob * pjob = NULL;
|
|
|
|
if (FAILED(hr = FindDownloadJob(&pjob)))
|
|
{
|
|
DEBUGMSG("CAUDownloader::SetDrizzleNotifyInterface() got no download job with error %#lx", hr);
|
|
goto done;
|
|
}
|
|
if (FAILED(hr = pjob->SetNotifyFlags(DRIZZLE_NOTIFY_FLAGS)))
|
|
{
|
|
DEBUGMSG("WUAUENG SetDrizzleNotifyInterface: set notification flags failed %#lx", hr);
|
|
}
|
|
else if (FAILED(hr = pjob->SetNotifyInterface(this)))
|
|
{
|
|
DEBUGMSG("WUAUENG SetDrizzleNotifyInterface: set notification interface failed %#lx", hr);
|
|
}
|
|
|
|
done:
|
|
SafeRelease(pjob);
|
|
return hr;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////
|
|
// helper function to connect AU to the job got using its GUID
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CAUDownloader::ReconnectDownloadJob()
|
|
{
|
|
BG_JOB_STATE state;
|
|
HRESULT hr = E_FAIL;
|
|
IBackgroundCopyJob * pjob = NULL;
|
|
|
|
DEBUGMSG("ReconnectDownloadJob() starts");
|
|
if ( (FAILED(hr = FindDownloadJob(&pjob)))
|
|
|| FAILED(hr = pjob->GetState(&state)))
|
|
{
|
|
DEBUGMSG("get no download job or fail to get job state");
|
|
goto Done;
|
|
}
|
|
switch (state)
|
|
{
|
|
case BG_JOB_STATE_QUEUED:
|
|
case BG_JOB_STATE_TRANSFERRING:
|
|
case BG_JOB_STATE_CONNECTING:
|
|
case BG_JOB_STATE_TRANSIENT_ERROR:
|
|
case BG_JOB_STATE_SUSPENDED:
|
|
case BG_JOB_STATE_ERROR:
|
|
{
|
|
DEBUGMSG("WUAUENG Trying to connect to drizzle again");
|
|
if (FAILED(hr = SetDrizzleNotifyInterface()))
|
|
{
|
|
goto Done;
|
|
}
|
|
//fixcode: why need resume if error?
|
|
if (BG_JOB_STATE_ERROR == state)
|
|
{
|
|
pjob->Resume(); //REVIEW, Is this really what we want to do?
|
|
}
|
|
break;
|
|
}
|
|
case BG_JOB_STATE_TRANSFERRED:
|
|
{
|
|
DEBUGMSG("WUAUENG Got BG_JOB_STATE_TRANSFERRED should work ok");
|
|
if (FAILED(hr = pjob->Complete()))
|
|
{
|
|
goto Done;
|
|
}
|
|
m_DoDownloadStatus(CATMSG_DOWNLOAD_COMPLETE, pjob);
|
|
|
|
break;
|
|
}
|
|
case BG_JOB_STATE_ACKNOWLEDGED:
|
|
{
|
|
//If the job was already acknowledged, we are assuming that the engine can continue
|
|
DEBUGMSG("WUAUENG : Got BG_JOB_STATE_ACKNOWLEDGED should work ok");
|
|
break;
|
|
}
|
|
case BG_JOB_STATE_CANCELLED:
|
|
{
|
|
DEBUGMSG("WUAUENG : Got BG_JOB_STATE_CANCELLED, should start again");
|
|
goto Done;
|
|
}
|
|
default:
|
|
{
|
|
DEBUGMSG("WUAUENG Drizzle notified unexpected BG_JOB_STATE");
|
|
}
|
|
}
|
|
hr = S_OK;
|
|
m_dwJobState = state;
|
|
Done:
|
|
SafeRelease(pjob);
|
|
if (FAILED(hr))
|
|
{
|
|
Reset();
|
|
}
|
|
DEBUGMSG("ReconnectDownloadJob() ends with result %#lx", hr);
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/*****
|
|
CAUDownloader::QueueDownloadFile() adds a file to download to drizzle's
|
|
|
|
RETURNS:
|
|
S_OK:
|
|
*****/
|
|
HRESULT CAUDownloader::QueueDownloadFile(LPCTSTR pszServerUrl, // full http url
|
|
LPCTSTR pszLocalFile // local file name
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
DEBUGMSG("CAUDownloader::DownloadFile() starts");
|
|
|
|
IBackgroundCopyJob * pjob = NULL;
|
|
if (FAILED(hr = FindDownloadJob(&pjob)))
|
|
{
|
|
DEBUGMSG("no existing download job, create one ");
|
|
if (FAILED(hr = CreateDownloadJob(&pjob)))
|
|
{
|
|
DEBUGMSG("fail to create a new download job");
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
//fixcode: do we need to pause job first before adding files
|
|
|
|
//
|
|
// Add the file to the download job.
|
|
//
|
|
hr = pjob->AddFile( pszServerUrl, pszLocalFile);
|
|
if (FAILED(hr))
|
|
{
|
|
DEBUGMSG(" adding file failed with %#lx", hr);
|
|
goto done;
|
|
}
|
|
|
|
done:
|
|
SafeRelease(pjob);
|
|
if ( FAILED(hr) )
|
|
{
|
|
Reset();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CAUDownloader::StartDownload()
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
IBackgroundCopyJob * pjob = NULL;
|
|
|
|
if (FAILED(hr = FindDownloadJob(&pjob)))
|
|
{
|
|
DEBUGMSG(" fail to get download job with error %#lx", hr);
|
|
goto done;
|
|
}
|
|
if (FAILED(hr = pjob->Resume()))
|
|
{
|
|
DEBUGMSG(" failed to start the download job");
|
|
}
|
|
done:
|
|
SafeRelease(pjob);
|
|
if (FAILED(hr))
|
|
{
|
|
Reset();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
// cancel the job and reset CAUDownloader's state
|
|
/////////////////////////////////////////////////////////////////////////////////
|
|
void CAUDownloader::Reset()
|
|
{
|
|
IBackgroundCopyJob * pjob = NULL;
|
|
|
|
if (SUCCEEDED(FindDownloadJob(&pjob)))
|
|
{
|
|
pjob->Cancel();
|
|
pjob->Release();
|
|
EngineEvents.SetEvent(IDOWNLOAD_DOWNLOAD_CANCELED);
|
|
DEBUGMSG("Reset() job cancelled and released");
|
|
}
|
|
m_DownloadId = GUID_NULL;
|
|
}
|
|
|
|
HRESULT CAUDownloader::DrizzleOperation(DRIZZLEOPS dop)
|
|
{
|
|
HRESULT hrRet;
|
|
IBackgroundCopyJob * pjob = NULL;
|
|
if (FAILED(hrRet = FindDownloadJob(&pjob)))
|
|
{
|
|
DEBUGMSG("CAUDownloader::DrizzleOperation() on an invalid job");
|
|
goto done;
|
|
}
|
|
switch (dop)
|
|
{
|
|
case DRIZZLEOPS_CANCEL:
|
|
DEBUGMSG("Catalog: Canceling Drizzle Job");
|
|
hrRet =pjob->Cancel();
|
|
EngineEvents.SetEvent(IDOWNLOAD_DOWNLOAD_CANCELED);
|
|
break;
|
|
case DRIZZLEOPS_PAUSE:
|
|
DEBUGMSG("Catalog: Pausing Drizzle Job");
|
|
hrRet = pjob->Suspend();
|
|
break;
|
|
case DRIZZLEOPS_RESUME:
|
|
DEBUGMSG("Catalog: Resuming Drizzle Job");
|
|
hrRet = pjob->Resume();
|
|
break;
|
|
}
|
|
done:
|
|
SafeRelease(pjob);
|
|
return hrRet;
|
|
}
|
|
|
|
/// pdwstatus actually contains the jobstate
|
|
HRESULT CAUDownloader::getStatus(DWORD *pdwPercent, DWORD *pdwstatus)
|
|
{
|
|
BG_JOB_PROGRESS progress;
|
|
BG_JOB_STATE state;
|
|
HRESULT hr = S_OK;
|
|
IBackgroundCopyJob * pjob = NULL;
|
|
|
|
if (FAILED(hr = FindDownloadJob(&pjob)))
|
|
{
|
|
DEBUGMSG(" getStatus : no download job with error %#lx", hr);
|
|
goto done;
|
|
}
|
|
|
|
if (FAILED(hr = pjob->GetState( &state )))
|
|
{
|
|
DEBUGMSG("WUAUENG: job->GetState failed");
|
|
state = BG_JOB_STATE_QUEUED;
|
|
goto done;
|
|
}
|
|
|
|
if (FAILED(hr = pjob->GetProgress( &progress )))
|
|
{
|
|
DEBUGMSG("WUAUENG: job->GetProgress failed");
|
|
goto done;
|
|
}
|
|
|
|
if (progress.BytesTotal != BG_SIZE_UNKNOWN )
|
|
{
|
|
*pdwPercent = DWORD( 100 * float(progress.BytesTransferred) / float(progress.BytesTotal) );
|
|
DEBUGMSG("getStatus is %d percent", *pdwPercent);
|
|
}
|
|
else
|
|
{
|
|
DEBUGMSG("getStatus, progress.BytesTotal= BG_SIZE_UNKNOWN, BytesTransfered = %d",progress.BytesTransferred);
|
|
*pdwPercent = 0;
|
|
}
|
|
|
|
*pdwstatus = state;
|
|
|
|
done:
|
|
SafeRelease(pjob);
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT STDMETHODCALLTYPE
|
|
CAUDownloader::QueryInterface(
|
|
REFIID riid,
|
|
void __RPC_FAR *__RPC_FAR *ppvObject
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
*ppvObject = NULL;
|
|
|
|
if (riid == __uuidof(IUnknown) ||
|
|
riid == __uuidof(IBackgroundCopyCallback) )
|
|
{
|
|
*ppvObject = (IBackgroundCopyCallback *)this;
|
|
((IUnknown *)(*ppvObject))->AddRef();
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE
|
|
CAUDownloader::AddRef()
|
|
{
|
|
long cRef = InterlockedIncrement(&m_refs);
|
|
DEBUGMSG("CAUDownloader AddRef = %d", cRef);
|
|
return cRef;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE
|
|
CAUDownloader::Release()
|
|
{
|
|
long cRef = InterlockedDecrement(&m_refs);
|
|
DEBUGMSG("CAUDownloader Release = %d", cRef);
|
|
return cRef;
|
|
}
|
|
|