|
|
/************************************************************************
Copyright (c) 2000 - 2000 Microsoft Corporation
Module Name :
drizcpat.cpp
Abstract :
Compatibility wrapper against the old AU bits.
Author :
Revision History :
***********************************************************************/
#include "stdafx.h"
#if !defined(BITS_V12_ON_NT4)
#include "drizcpat.tmh"
#endif
DWORD NewJobSizeToOldSize( UINT64 NewSize ) { if ( NewSize == UINT64(-1)) return 0;
return (DWORD)NewSize; }
DWORD MapOldNotifyToNewNotify( DWORD dwOldNotify ) { // The mars interface has error on by default.
DWORD dwReturnVal = BG_NOTIFY_JOB_ERROR;
if ( dwOldNotify & ~( QM_NOTIFY_GROUP_DONE | QM_NOTIFY_DISABLE_NOTIFY ) ) throw ComError( E_NOTIMPL );
if ( dwOldNotify & QM_NOTIFY_GROUP_DONE ) dwReturnVal |= BG_NOTIFY_JOB_TRANSFERRED;
if ( dwOldNotify & QM_NOTIFY_DISABLE_NOTIFY ) dwReturnVal |= BG_NOTIFY_DISABLE;
return dwReturnVal; }
DWORD MapNewNotifyToOldNotify( DWORD dwNewNotify ) { DWORD dwReturnVal = 0;
if ( dwNewNotify & BG_NOTIFY_JOB_TRANSFERRED ) dwReturnVal |= QM_NOTIFY_GROUP_DONE;
if ( dwNewNotify & BG_NOTIFY_DISABLE ) dwReturnVal |= QM_NOTIFY_DISABLE_NOTIFY;
return dwReturnVal; }
COldGroupInterface::COldGroupInterface( CJob *pJob ) : m_refs(1), m_ServiceInstance( g_ServiceInstance ), m_NotifyPointer( NULL ), m_NotifyClsid( GUID_NULL ), m_pJob(pJob), m_pJobExternal( pJob->GetExternalInterface() ) { m_pJobExternal->AddRef(); }
COldGroupInterface::~COldGroupInterface() { m_pJobExternal->Release(); }
STDMETHODIMP COldGroupInterface::QueryInterface( REFIID iid, void** ppvObject ) { BEGIN_EXTERNAL_FUNC
LogPublicApiBegin( "iid %!guid!, ppvObject %p", &iid, ppvObject ); HRESULT Hr = S_OK; *ppvObject = NULL;
if ((iid == _uuidof(IUnknown)) || (iid == __uuidof(IBackgroundCopyGroup)) ) { *ppvObject = (IBackgroundCopyGroup *)this; ((IUnknown *)(*ppvObject))->AddRef(); } else { Hr = E_NOINTERFACE; }
LogPublicApiEnd( "iid %!guid!, ppvObject %p", &iid, ppvObject ); return Hr;
END_EXTERNAL_FUNC }
ULONG _stdcall COldGroupInterface::AddRef(void) { BEGIN_EXTERNAL_FUNC
ULONG newrefs = InterlockedIncrement(&m_refs);
LogRef( "job %p, refs = %d", m_pJob, newrefs );
return newrefs;
END_EXTERNAL_FUNC }
ULONG _stdcall COldGroupInterface::Release(void) { BEGIN_EXTERNAL_FUNC
ULONG newrefs = InterlockedDecrement(&m_refs);
LogRef( "job %p, refs = %d", m_pJob, newrefs );
if (newrefs == 0) { delete this; }
return newrefs;
END_EXTERNAL_FUNC }
STDMETHODIMP COldGroupInterface::GetPropInternal( GROUPPROP property, VARIANT * pVal ) { HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( "property %u, pVal %p", property, pVal );
WCHAR * pString = NULL;
try { ASSERT( pVal );
VariantClear( pVal );
THROW_HRESULT( LockedJob.ValidateAccess() );
switch (property) { case GROUPPROP_PRIORITY: pVal->vt = VT_INT; pVal->intVal = 1; break;
case GROUPPROP_PROTOCOLFLAGS: pVal->vt = VT_INT; pVal->intVal = QM_PROTOCOL_HTTP; break;
case GROUPPROP_NOTIFYFLAGS: pVal->vt = VT_INT; pVal->intVal = MapNewNotifyToOldNotify( LockedJob->GetNotifyFlags() ); break;
case GROUPPROP_NOTIFYCLSID: { THROW_HRESULT( StringFromIID( m_NotifyClsid, &pString ));
pVal->vt = VT_BSTR; pVal->bstrVal = SysAllocString( pString );
if ( !pVal->bstrVal ) throw ComError( E_OUTOFMEMORY );
break; }
case GROUPPROP_DISPLAYNAME: {
THROW_HRESULT( LockedJob->GetDisplayName( &pString ) );
pVal->vt = VT_BSTR; pVal->bstrVal = SysAllocString( pString );
if ( !pVal->bstrVal ) throw ComError( E_OUTOFMEMORY );
break; }
case GROUPPROP_DESCRIPTION: {
THROW_HRESULT( LockedJob->GetDescription( &pString ) );
pVal->vt = VT_BSTR; pVal->bstrVal = SysAllocString( pString );
if ( !pVal->bstrVal ) throw ComError( E_OUTOFMEMORY );
break; }
default: return E_NOTIMPL; }
} catch( ComError Error ) { Hr = Error.Error(); VariantClear( pVal ); }
CoTaskMemFree( pString );
LogPublicApiEnd( "property %u, pVal %p", property, pVal ); return Hr;
}
STDMETHODIMP COldGroupInterface::SetPropInternal( GROUPPROP property, VARIANT *pvarVal ) { HRESULT Hr = S_OK; CLockedJobWritePointer LockedJob(m_pJob); LogPublicApiBegin( "property %u, Val %p", property, pvarVal );
DWORD dwValue = -1; BSTR bstrIn = NULL;
try { if (!pvarVal) throw ComError(E_INVALIDARG);
THROW_HRESULT( LockedJob.ValidateAccess() );
//
// This is how the old code did it. Unfortunate, but compatible.
//
switch (pvarVal->vt) { case VT_I4: dwValue = (DWORD)(pvarVal->lVal < 0) ? -1 : pvarVal->lVal; break; case VT_I2: dwValue = (DWORD)(pvarVal->iVal < 0) ? -1 : pvarVal->iVal; break; case VT_UI2: dwValue = (DWORD)pvarVal->uiVal; break; case VT_UI4: dwValue = (DWORD)pvarVal->ulVal; break; case VT_INT: dwValue = (DWORD)(pvarVal->intVal < 0) ? -1 : pvarVal->intVal; break; case VT_UINT: dwValue = (DWORD)pvarVal->uintVal; break; case VT_BSTR: bstrIn = pvarVal->bstrVal; break; default: return E_INVALIDARG; }
switch (property) { case GROUPPROP_PRIORITY: //
// Only one priority was supported. No need to store it.
//
if (dwValue != 1) { throw ComError( E_NOTIMPL ); } break;
case GROUPPROP_PROTOCOLFLAGS:
//
// Only HTTP was supported. No need to store it.
//
if (dwValue != QM_PROTOCOL_HTTP) { throw ComError( E_NOTIMPL ); } break;
case GROUPPROP_NOTIFYFLAGS:
THROW_HRESULT( LockedJob->SetNotifyFlags( MapOldNotifyToNewNotify( dwValue ) ) ); break;
case GROUPPROP_NOTIFYCLSID: { if (NULL == bstrIn) { throw ComError( E_INVALIDARG ); }
GUID clsid; THROW_HRESULT( IIDFromString( bstrIn, &clsid ) );
m_NotifyClsid = clsid; break; }
case GROUPPROP_DISPLAYNAME: THROW_HRESULT( LockedJob->SetDisplayName( (WCHAR *)bstrIn ) ); break;
case GROUPPROP_DESCRIPTION: THROW_HRESULT( LockedJob->SetDescription( (WCHAR *)bstrIn ) ); break;
default: return E_NOTIMPL; }
} catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( "property %u, pVal %p", property, pvarVal ); return Hr;
}
STDMETHODIMP COldGroupInterface::GetProgressInternal( DWORD flags, DWORD * pProgress ) {
HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( "flags %u", flags );
try {
ASSERT( pProgress ); THROW_HRESULT( LockedJob.ValidateAccess() );
BG_JOB_PROGRESS JobProgress; LockedJob->GetProgress( &JobProgress );
switch( flags ) { case QM_PROGRESS_SIZE_DONE: {
*pProgress = NewJobSizeToOldSize( JobProgress.BytesTransferred ); break; }
case QM_PROGRESS_PERCENT_DONE: {
if ( ( -1 == JobProgress.BytesTotal ) || ( -1 == JobProgress.BytesTransferred ) || ( 0 == JobProgress.BytesTotal ) ) { *pProgress = 0; } else { double ratio = double(JobProgress.BytesTransferred) / double(JobProgress.BytesTotal ); *pProgress = DWORD( ratio * 100.0 ); } break; }
default: { throw ComError( E_NOTIMPL ); } } } catch( ComError Error ) { Hr = Error.Error(); *pProgress = 0; }
LogPublicApiEnd( "progress %d", *pProgress ); return Hr; }
STDMETHODIMP COldGroupInterface::GetStatusInternal( DWORD *pdwStatus, DWORD *pdwJobIndex) {
HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( "pdwStatus %p, pdwJobIndex %p", pdwStatus, pdwJobIndex );
try { ASSERT( pdwStatus && pdwJobIndex ); *pdwStatus = *pdwJobIndex = 0;
THROW_HRESULT( LockedJob.ValidateAccess() );
// Note: we never increment the JobIndex anymore
BG_JOB_STATE State = LockedJob->_GetState(); BG_JOB_PRIORITY Priority = LockedJob->_GetPriority();
if ( BG_JOB_PRIORITY_FOREGROUND == Priority ) *pdwStatus |= QM_STATUS_GROUP_FOREGROUND;
switch( State ) { case BG_JOB_STATE_QUEUED: case BG_JOB_STATE_CONNECTING: case BG_JOB_STATE_TRANSFERRING: *pdwStatus |= QM_STATUS_GROUP_INCOMPLETE; break;
case BG_JOB_STATE_SUSPENDED: *pdwStatus |= ( QM_STATUS_GROUP_SUSPENDED | QM_STATUS_GROUP_INCOMPLETE ); break;
case BG_JOB_STATE_ERROR: *pdwStatus |= ( QM_STATUS_GROUP_ERROR | QM_STATUS_GROUP_INCOMPLETE | QM_STATUS_GROUP_SUSPENDED ); break;
case BG_JOB_STATE_TRANSIENT_ERROR: *pdwStatus |= ( QM_STATUS_GROUP_INCOMPLETE ); break;
case BG_JOB_STATE_TRANSFERRED: *pdwStatus |= ( QM_STATUS_GROUP_COMPLETE | QM_STATUS_GROUP_SUSPENDED ); break;
case BG_JOB_STATE_ACKNOWLEDGED: *pdwStatus |= ( QM_STATUS_GROUP_COMPLETE | QM_STATUS_GROUP_SUSPENDED ); break;
case BG_JOB_STATE_CANCELLED: break; }
} catch( ComError Error ) { Hr = Error.Error(); *pdwStatus = 0; }
LogPublicApiEnd( "pdwStatus %p, pdwJobIndex %p", pdwStatus, pdwJobIndex ); return Hr;
}
STDMETHODIMP COldGroupInterface::GetJobInternal( GUID jobID, IBackgroundCopyJob1 **ppJob) {
HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( "jobID %!guid!, ppJob %p", &jobID, ppJob );
try { ASSERT( ppJob ); *ppJob = NULL;
THROW_HRESULT( LockedJob.ValidateAccess() );
COldJobInterface *pOldJob = m_pJob->GetOldExternalJobInterface();
if (!pOldJob) throw ComError( QM_E_ITEM_NOT_FOUND );
if (jobID != pOldJob->GetOldJobId() ) throw ComError( QM_E_ITEM_NOT_FOUND );
*ppJob = pOldJob; (*ppJob)->AddRef();
} catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( "jobID %!guid!, ppJob %p", &jobID, ppJob ); return Hr;
}
STDMETHODIMP COldGroupInterface::SuspendGroupInternal( ) {
HRESULT Hr = S_OK; CLockedJobWritePointer LockedJob(m_pJob); LogPublicApiBegin( "void" );
try { THROW_HRESULT( LockedJob.ValidateAccess() ); THROW_HRESULT( LockedJob->Suspend() ); } catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( "void" ); return Hr; }
STDMETHODIMP COldGroupInterface::ResumeGroupInternal( ) { HRESULT Hr = S_OK; CLockedJobWritePointer LockedJob(m_pJob); LogPublicApiBegin( " " );
try { THROW_HRESULT( LockedJob.ValidateAccess() );
THROW_HRESULT( LockedJob->Resume() ); } catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( " " ); return Hr; }
STDMETHODIMP COldGroupInterface::CancelGroupInternal( ) { HRESULT Hr = S_OK; CLockedJobWritePointer LockedJob(m_pJob); LogPublicApiBegin( " " );
try { THROW_HRESULT( LockedJob.ValidateAccess() ); THROW_HRESULT( LockedJob->Complete() ); } catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( " " ); return Hr; }
STDMETHODIMP COldGroupInterface::get_SizeInternal( DWORD *pdwSize ) {
HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( " " );
try { ASSERT( pdwSize );
THROW_HRESULT( LockedJob.ValidateAccess() );
BG_JOB_PROGRESS Progress; LockedJob->GetProgress( &Progress );
*pdwSize = NewJobSizeToOldSize( Progress.BytesTotal ); } catch( ComError Error ) { Hr = Error.Error(); *pdwSize = 0; }
LogPublicApiEnd( "dwSize %d", *pdwSize ); return Hr; }
STDMETHODIMP COldGroupInterface::get_GroupIDInternal( GUID *pguidGroupID ) {
HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( " " );
try { ASSERT( pguidGroupID );
THROW_HRESULT( LockedJob.ValidateAccess() );
*pguidGroupID = LockedJob->GetId();
} catch( ComError Error ) { Hr = Error.Error(); memset( pguidGroupID, 0 , sizeof(*pguidGroupID) ); }
LogPublicApiEnd( "id %!guid!", pguidGroupID ); return Hr;
}
STDMETHODIMP COldGroupInterface::CreateJobInternal( GUID guidJobID, IBackgroundCopyJob1 **ppJob ) {
HRESULT Hr = S_OK; CLockedJobWritePointer LockedJob(m_pJob); LogPublicApiBegin( "guidJobID %!guid!", &guidJobID );
try { ASSERT( ppJob ); *ppJob = NULL;
THROW_HRESULT( LockedJob.ValidateAccess() );
BG_JOB_STATE State = LockedJob->_GetState(); switch( State ) {
case BG_JOB_STATE_QUEUED: case BG_JOB_STATE_CONNECTING: case BG_JOB_STATE_TRANSFERRING: throw ComError( QM_E_INVALID_STATE ); break;
case BG_JOB_STATE_SUSPENDED: case BG_JOB_STATE_ERROR: break;
case BG_JOB_STATE_TRANSIENT_ERROR: case BG_JOB_STATE_TRANSFERRED: case BG_JOB_STATE_ACKNOWLEDGED: case BG_JOB_STATE_CANCELLED: throw ComError( QM_E_INVALID_STATE ); break;
default: throw ComError( QM_E_INVALID_STATE ); break; }
if (LockedJob->GetOldExternalJobInterface()) throw ComError( E_NOTIMPL );
COldJobInterface *pOldJob = new COldJobInterface( guidJobID, m_pJob );
LockedJob->SetOldExternalJobInterface( pOldJob );
*ppJob = pOldJob; (*ppJob)->AddRef();
g_Manager->Serialize();
} catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( "ppJob %p", *ppJob ); return Hr; }
STDMETHODIMP COldGroupInterface::EnumJobsInternal( DWORD dwFlags, IEnumBackgroundCopyJobs1 **ppEnumJobs ) {
HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( "dwFlags %u, ppEnumJobs %p", dwFlags, ppEnumJobs );
CEnumOldJobs* pEnum = NULL; try { ASSERT( ppEnumJobs ); *ppEnumJobs = NULL;
THROW_HRESULT( LockedJob.ValidateAccess() );
if (dwFlags) throw ComError( E_NOTIMPL );
pEnum = new CEnumOldJobs;
COldJobInterface *pOldJob = LockedJob->GetOldExternalJobInterface(); if (pOldJob) { GUID guid = pOldJob->GetOldJobId(); pEnum->Add( guid ); }
*ppEnumJobs = pEnum;
} catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( "dwFlags %u, ppEnumJobs %p", dwFlags, ppEnumJobs ); return Hr;
}
STDMETHODIMP COldGroupInterface::SwitchToForegroundInternal( ) {
HRESULT Hr = S_OK; CLockedJobWritePointer LockedJob(m_pJob); LogPublicApiBegin( " " );
try { THROW_HRESULT( LockedJob.ValidateAccess() );
THROW_HRESULT( LockedJob->SetPriority( BG_JOB_PRIORITY_FOREGROUND ) ); } catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( " " ); return Hr;
}
STDMETHODIMP COldGroupInterface::QueryNewJobInterface( REFIID iid, IUnknown **pUnk ) { LogInfo("QueryNewJobInterface %!guid!", &iid);
if (iid != __uuidof(IBackgroundCopyJob)) { LogError("E_NOTIMPL"); *pUnk = NULL; return E_NOTIMPL; }
*pUnk = m_pJob->GetExternalInterface(); (*pUnk)->AddRef();
LogInfo("OK"); return S_OK; }
STDMETHODIMP COldGroupInterface::SetNotificationPointer( REFIID iid, IUnknown *pUnk ) { HRESULT Hr = S_OK;
IBackgroundCopyCallback1 *pICB = NULL;
LogPublicApiBegin( "IID %!guid! ptr %p", &iid, pUnk );
if (iid != __uuidof(IBackgroundCopyCallback1)) { Hr = E_NOTIMPL; } else if ( pUnk ) { try { CNestedImpersonation imp;
//
// Gotta do it twice, because SwitchToLogonToken will fail
// if the user is not interactively logged in.
//
THROW_HRESULT( SetStaticCloaking( pUnk ) );
imp.SwitchToLogonToken();
THROW_HRESULT( SetStaticCloaking( pUnk ) );
THROW_HRESULT( pUnk->QueryInterface( iid, (void**)&pICB ) );
THROW_HRESULT( SetStaticCloaking( pICB ) );
SafeRelease( m_NotifyPointer );
m_NotifyPointer = pICB; } catch( ComError Error ) { SafeRelease( pICB ); Hr = Error.Error(); } }
LogPublicApiEnd( " " );
return Hr; }
IBackgroundCopyCallback1 * COldGroupInterface::GetNotificationPointer() { if (m_NotifyPointer) { m_NotifyPointer->AddRef(); }
return m_NotifyPointer; }
void COldGroupInterface::Serialize( HANDLE hFile ) { SafeWriteFile( hFile, m_NotifyClsid );
if ( m_pJob->GetOldExternalJobInterface() ) { SafeWriteFile( hFile, (bool)true ); m_pJob->GetOldExternalJobInterface()->Serialize( hFile ); } else { SafeWriteFile( hFile, (bool)false ); } return; }
COldGroupInterface * COldGroupInterface::UnSerialize( HANDLE hFile, CJob* Job ) { COldGroupInterface * group = NULL;
try { group = new COldGroupInterface(Job); if (!group) { throw ComError( E_OUTOFMEMORY ); }
SafeReadFile( hFile, &group->m_NotifyClsid );
bool bHasOldExternalJobInterface;
SafeReadFile( hFile, &bHasOldExternalJobInterface );
if ( bHasOldExternalJobInterface ) { COldJobInterface *OldJobInterface = COldJobInterface::Unserialize( hFile, Job ); Job->SetOldExternalJobInterface( OldJobInterface ); }
} catch ( ComError Error ) { delete group; throw; }
return group; }
COldJobInterface::COldJobInterface( GUID JobGuid, CJob *pJob ) : m_refs(1), m_ServiceInstance( g_ServiceInstance ), m_OldJobGuid( JobGuid ), m_pJob( pJob ), m_pJobExternal( pJob->GetExternalInterface() ) { m_pJobExternal->AddRef(); }
COldJobInterface::~COldJobInterface() { m_pJobExternal->Release(); }
STDMETHODIMP COldJobInterface::QueryInterface( REFIID iid, void** ppvObject ) { BEGIN_EXTERNAL_FUNC
LogPublicApiBegin( "iid %!guid!, ppvObject %p", &iid, ppvObject ); HRESULT Hr = S_OK; *ppvObject = NULL;
if ((iid == _uuidof(IUnknown)) || (iid == __uuidof(IBackgroundCopyJob1)) ) { *ppvObject = (IBackgroundCopyJob1 *)this; ((IUnknown *)(*ppvObject))->AddRef(); } else { Hr = E_NOINTERFACE; }
LogPublicApiEnd( "iid %!guid!, ppvObject %p", &iid, ppvObject ); return Hr;
END_EXTERNAL_FUNC }
ULONG _stdcall COldJobInterface::AddRef(void) { BEGIN_EXTERNAL_FUNC
ULONG newrefs = InterlockedIncrement(&m_refs);
LogRef( "job %p, refs = %d", m_pJob, newrefs );
return newrefs;
END_EXTERNAL_FUNC }
ULONG _stdcall COldJobInterface::Release(void) { BEGIN_EXTERNAL_FUNC
ULONG newrefs = InterlockedDecrement(&m_refs);
LogRef( "job %p, refs = %d", m_pJob, newrefs );
if (newrefs == 0) { delete this; }
return newrefs;
END_EXTERNAL_FUNC }
STDMETHODIMP COldJobInterface::AddFilesInternal( ULONG cFileCount, FILESETINFO **ppFileSet ) { HRESULT Hr = S_OK; CLockedJobWritePointer LockedJob(m_pJob); LogPublicApiBegin( "cFileCount %u, ppFileSet %p", cFileCount, ppFileSet );
BG_FILE_INFO *pFileInfo = NULL;
try { ASSERT( ppFileSet );
THROW_HRESULT( LockedJob.ValidateAccess() );
pFileInfo = new BG_FILE_INFO[cFileCount]; if (!pFileInfo ) { throw ComError(E_OUTOFMEMORY); }
for(ULONG c = 0; c < cFileCount; c++ ) { if ( !ppFileSet[c]) throw ComError(E_INVALIDARG);
// BSTRS act like WCHAR *
pFileInfo[c].LocalName = LPWSTR( (ppFileSet[c])->bstrLocalFile ); pFileInfo[c].RemoteName = LPWSTR( (ppFileSet[c])->bstrRemoteFile );
}
THROW_HRESULT( LockedJob->AddFileSet( cFileCount, pFileInfo ) );
} catch(ComError Error ) { Hr = Error.Error(); }
// Should handle NULL
delete[] pFileInfo;
LogPublicApiEnd( "cFileCount %u, ppFileSet %p", cFileCount, ppFileSet ); return Hr; }
STDMETHODIMP COldJobInterface::GetFileCountInternal( DWORD * pCount ) { HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( "pCount %p", pCount );
try { ASSERT( pCount );
THROW_HRESULT( LockedJob.ValidateAccess() );
BG_JOB_PROGRESS JobProgress; LockedJob->GetProgress( &JobProgress );
*pCount = JobProgress.FilesTotal;
} catch(ComError Error ) { Hr = Error.Error(); *pCount = 0; }
LogPublicApiEnd( "pCount %p", pCount ); return Hr;
}
STDMETHODIMP COldJobInterface::GetFileInternal( ULONG cFileIndex, FILESETINFO *pFileInfo ) { HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( "cFileIndex %u, pFileInfo %p", cFileIndex, pFileInfo );
WCHAR *pLocalName = NULL; WCHAR *pRemoteName = NULL; try {
ASSERT( pFileInfo ); memset( pFileInfo, 0, sizeof(FILESETINFO) );
THROW_HRESULT( LockedJob.ValidateAccess() );
CFile *pFile = LockedJob->_GetFileIndex( cFileIndex ); if (!pFile) throw ComError ( QM_E_ITEM_NOT_FOUND );
THROW_HRESULT( pFile->GetLocalName( &pLocalName ) ); THROW_HRESULT( pFile->GetRemoteName( &pRemoteName ) );
pFileInfo->bstrLocalFile = SysAllocString( pLocalName ); pFileInfo->bstrRemoteFile = SysAllocString( pRemoteName );
if ( !pFileInfo->bstrLocalFile || !pFileInfo->bstrRemoteFile ) throw ComError( E_OUTOFMEMORY );
BG_FILE_PROGRESS FileProgress; pFile->GetProgress( &FileProgress );
pFileInfo->dwSizeHint = NewJobSizeToOldSize( FileProgress.BytesTotal );
} catch ( ComError Error ) { Hr = Error.Error();
if ( pFileInfo ) { SysFreeString( pFileInfo->bstrLocalFile ); SysFreeString( pFileInfo->bstrRemoteFile ); memset( pFileInfo, 0, sizeof(FILESETINFO) ); } }
// CoTaskMemFree handles NULL
CoTaskMemFree( pLocalName ); CoTaskMemFree( pRemoteName );
LogPublicApiEnd( "cFileIndex %u, pFileInfo %p", cFileIndex, pFileInfo ); return Hr; }
STDMETHODIMP COldJobInterface::CancelJobInternal() { HRESULT Hr = E_NOTIMPL; LogPublicApiBegin( "void" ); LogPublicApiEnd( "void" ); return Hr; }
STDMETHODIMP COldJobInterface::get_JobIDInternal( GUID * pId ) { HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( "pId %p", pId );
try { ASSERT( pId ); THROW_HRESULT( LockedJob.ValidateAccess() );
*pId = GetOldJobId(); } catch(ComError Error ) { Hr = Error.Error(); memset( pId, 0, sizeof(*pId) ); }
LogPublicApiEnd( "pId %p", pId ); return Hr; }
STDMETHODIMP COldJobInterface::GetProgressInternal( DWORD flags, DWORD * pProgress ) { HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( "flags %u, pProgress %p", flags, pProgress );
try {
ASSERT( pProgress ); *pProgress = NULL;
THROW_HRESULT( LockedJob.ValidateAccess() );
BG_JOB_PROGRESS JobProgress; LockedJob->GetProgress( &JobProgress );
switch (flags) { case QM_PROGRESS_SIZE_DONE: {
*pProgress = NewJobSizeToOldSize( JobProgress.BytesTransferred ); break; }
case QM_PROGRESS_PERCENT_DONE: {
if ( ( -1 == JobProgress.BytesTotal ) || ( -1 == JobProgress.BytesTransferred ) || ( 0 == JobProgress.BytesTotal ) ) { *pProgress = 0; } else { double ratio = double(JobProgress.BytesTransferred) / double(JobProgress.BytesTotal ); *pProgress = DWORD( ratio * 100.0 ); } break; }
default: { throw ComError( E_NOTIMPL ); } }
} catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( "flags %u, pProgress %p", flags, pProgress ); return Hr; }
STDMETHODIMP COldJobInterface::SwitchToForegroundInternal() {
HRESULT Hr = S_OK; CLockedJobWritePointer LockedJob(m_pJob); LogPublicApiBegin( "void" );
try { THROW_HRESULT( LockedJob.ValidateAccess() ); Hr = E_NOTIMPL; } catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( "void" ); return Hr; }
STDMETHODIMP COldJobInterface::GetStatusInternal( DWORD *pdwStatus, DWORD *pdwWin32Result, DWORD *pdwTransportResult, DWORD *pdwNumOfRetries ) {
HRESULT Hr = S_OK; CLockedJobReadPointer LockedJob(m_pJob); LogPublicApiBegin( "pdwStatus %p, pdwWin32Result %p, pdwTransportResult %p, pdwNumOfRetries %p", pdwStatus, pdwWin32Result, pdwTransportResult, pdwNumOfRetries );
try { ASSERT( pdwStatus && pdwWin32Result && pdwTransportResult && pdwNumOfRetries );
*pdwStatus = *pdwWin32Result = *pdwTransportResult = *pdwNumOfRetries = 0;
THROW_HRESULT( LockedJob.ValidateAccess() );
BG_JOB_PRIORITY Priority = LockedJob->_GetPriority(); BG_JOB_STATE State = LockedJob->_GetState();
THROW_HRESULT( LockedJob->GetErrorCount( pdwNumOfRetries ) );
if ( BG_JOB_PRIORITY_FOREGROUND == Priority ) *pdwStatus |= QM_STATUS_JOB_FOREGROUND;
switch( State ) { case BG_JOB_STATE_QUEUED: case BG_JOB_STATE_CONNECTING: case BG_JOB_STATE_TRANSFERRING: *pdwStatus |= QM_STATUS_JOB_INCOMPLETE; break; case BG_JOB_STATE_SUSPENDED: *pdwStatus |= QM_STATUS_JOB_INCOMPLETE; break; case BG_JOB_STATE_ERROR: *pdwStatus |= QM_STATUS_JOB_ERROR; break; case BG_JOB_STATE_TRANSIENT_ERROR: *pdwStatus |= QM_STATUS_JOB_INCOMPLETE; break; case BG_JOB_STATE_TRANSFERRED: *pdwStatus |= QM_STATUS_JOB_COMPLETE; break; case BG_JOB_STATE_ACKNOWLEDGED: *pdwStatus |= QM_STATUS_JOB_COMPLETE; break; case BG_JOB_STATE_CANCELLED: break; default: ASSERT(0); break; }
if ( BG_JOB_STATE_ERROR == State ) {
const CJobError * pError = LockedJob->GetError();
ASSERT( pError );
if ( pError ) { pError->GetOldInterfaceErrors( pdwWin32Result, pdwTransportResult ); }
}
} catch( ComError Error ) { Hr = Error.Error();
*pdwStatus = 0; *pdwWin32Result = 0; *pdwTransportResult = 0; *pdwNumOfRetries = 0; }
LogPublicApiEnd( "pdwStatus %p, pdwWin32Result %p, pdwTransportResult %p, pdwNumOfRetries %p", pdwStatus, pdwWin32Result, pdwTransportResult, pdwNumOfRetries ); return Hr; }
void COldJobInterface::Serialize( HANDLE hFile ) { SafeWriteFile( hFile, m_OldJobGuid ); }
COldJobInterface * COldJobInterface::Unserialize( HANDLE hFile, CJob* Job ) { COldJobInterface * OldJob = NULL;
try { GUID OldJobGuid; SafeReadFile( hFile, &OldJobGuid ); OldJob = new COldJobInterface( OldJobGuid, Job ); if (!OldJob) { throw ComError( E_OUTOFMEMORY ); } } catch ( ComError Error ) { delete OldJob; throw; }
return OldJob; }
COldQmgrInterface::COldQmgrInterface() : m_refs(1), m_ServiceInstance( g_ServiceInstance ) { }
STDMETHODIMP COldQmgrInterface::QueryInterface( REFIID iid, void** ppvObject ) { BEGIN_EXTERNAL_FUNC
LogPublicApiBegin( "iid %!guid!, ppvObject %p", &iid, ppvObject ); HRESULT Hr = S_OK; *ppvObject = NULL;
if ((iid == _uuidof(IUnknown)) || (iid == __uuidof(IBackgroundCopyQMgr)) ) { *ppvObject = (IBackgroundCopyQMgr *)this; ((IUnknown *)(*ppvObject))->AddRef(); } else if ( iid == __uuidof(IClassFactory) ) { *ppvObject = (IClassFactory *)this; ((IUnknown *)(*ppvObject))->AddRef(); } else { Hr = E_NOINTERFACE; }
LogPublicApiEnd( "iid %!guid!, ppvObject %p", &iid, ppvObject ); return Hr;
END_EXTERNAL_FUNC }
ULONG _stdcall COldQmgrInterface::AddRef(void) { BEGIN_EXTERNAL_FUNC
ULONG newrefs = InterlockedIncrement(&m_refs);
LogRef( "new refs = %d", newrefs );
return newrefs;
END_EXTERNAL_FUNC }
ULONG _stdcall COldQmgrInterface::Release(void) { BEGIN_EXTERNAL_FUNC
ULONG newrefs = InterlockedDecrement(&m_refs);
LogRef( "new refs = %d", newrefs );
if (newrefs == 0) { delete this; }
return newrefs;
END_EXTERNAL_FUNC }
STDMETHODIMP COldQmgrInterface::CreateInstance( IUnknown * pUnkOuter, REFIID riid, void ** ppvObject ) {
BEGIN_EXTERNAL_FUNC
HRESULT hr = S_OK;
if (g_ServiceInstance != m_ServiceInstance || g_ServiceState != MANAGER_ACTIVE) { hr = CO_E_SERVER_STOPPING; } else if (pUnkOuter != NULL) { hr = CLASS_E_NOAGGREGATION; } else { if ((riid == IID_IBackgroundCopyQMgr) || (riid == IID_IUnknown)) { hr = QueryInterface(riid, ppvObject); } else { //
// This seems like an odd choice, but we keep it in case some app depends upon it.
//
hr = E_OUTOFMEMORY; } } return hr;
END_EXTERNAL_FUNC
}
STDMETHODIMP COldQmgrInterface::LockServer( BOOL fLock ) { BEGIN_EXTERNAL_FUNC
return GlobalLockServer( fLock );
END_EXTERNAL_FUNC }
STDMETHODIMP COldQmgrInterface::CreateGroupInternal( GUID id, IBackgroundCopyGroup **ppGroup ) { HRESULT Hr = S_OK; CLockedJobManagerWritePointer LockedJobManager( m_pJobManager ); LogPublicApiBegin( "id %!guid!", &id );
CJob *job = NULL;
//
// create the job
//
try {
THROW_HRESULT( LockedJobManager.ValidateAccess() );
ASSERT( ppGroup );
const WCHAR *DisplayName = L""; CLSID *CallbackClass = NULL; BG_JOB_TYPE Type = BG_JOB_TYPE_DOWNLOAD;
THROW_HRESULT( LockedJobManager->CreateJob( DisplayName, Type, id, GetThreadClientSid(), &job, true ));
THROW_HRESULT( job->SetNotifyFlags( MapOldNotifyToNewNotify(0) ) );
*ppGroup = ( IBackgroundCopyGroup * )job->GetOldExternalGroupInterface(); ASSERT( *ppGroup );
(*ppGroup)->AddRef();
}
catch( ComError exception ) { Hr = exception.Error();
if ( job ) job->Cancel(); }
LogPublicApiEnd( "id %!guid!, group %p", &id, *ppGroup ); return Hr; }
STDMETHODIMP COldQmgrInterface::GetGroupInternal( GUID id, IBackgroundCopyGroup ** ppGroup ) { HRESULT Hr = S_OK; CLockedJobManagerWritePointer LockedJobManager( m_pJobManager ); LogPublicApiBegin( "id %!guid!", &id );
CJob *pJob = NULL;
try { ASSERT( ppGroup ); *ppGroup = NULL;
THROW_HRESULT( LockedJobManager.ValidateAccess() );
Hr = LockedJobManager->GetJob( id, &pJob );
if (FAILED(Hr)) { if (Hr == BG_E_NOT_FOUND) { Hr = QM_E_ITEM_NOT_FOUND; }
throw ComError( Hr ); }
COldGroupInterface *pOldGroup = pJob->GetOldExternalGroupInterface(); if ( !pOldGroup ) throw ComError( QM_E_ITEM_NOT_FOUND );
// try to take ownership of the job/group
// this should suceed even if we are the current owner
THROW_HRESULT( pJob->TakeOwnership());
pOldGroup->AddRef();
*ppGroup = (IBackgroundCopyGroup*)pOldGroup; } catch( ComError Error ) { Hr = Error.Error(); }
LogPublicApiEnd( "id %!guid!, group %p", &id, *ppGroup ); return Hr;
}
STDMETHODIMP COldQmgrInterface::EnumGroupsInternal( DWORD flags, IEnumBackgroundCopyGroups **ppEnum ) {
HRESULT Hr = S_OK; CLockedJobManagerWritePointer LockedJobManager( m_pJobManager ); LogPublicApiBegin( "flags %u, ppEnum %p", flags, ppEnum );
CEnumOldGroups *pEnum = NULL;
try {
ASSERT( ppEnum ); *ppEnum = NULL;
THROW_HRESULT( LockedJobManager.ValidateAccess() );
if (flags) { LogWarning( "rejecting nonzero dwFlags"); throw ComError( E_NOTIMPL ); }
pEnum = new CEnumOldGroups;
for (CJobList::iterator iter = LockedJobManager->m_OnlineJobs.begin(); iter != LockedJobManager->m_OnlineJobs.end(); ++iter) {
Hr = (*iter).IsVisible(); if (FAILED(Hr)) { throw ComError( Hr ); }
if (Hr == S_FALSE) { continue; }
// Skip jobs that were not created with the old interface.
if (!(*iter).GetOldExternalGroupInterface()) { continue; }
GUID guid = (*iter).GetId(); pEnum->Add( guid ); }
*ppEnum = pEnum; } catch( ComError Error ) { Hr = Error.Error(); delete pEnum; }
LogPublicApiEnd( "flags %u, ppEnum %p", flags, ppEnum ); return Hr;
}
|