windows-nt/Source/XPSP1/NT/admin/services/drizzle/newjob/drizcpat.cpp
2020-09-26 16:20:57 +08:00

1701 lines
37 KiB
C++

/************************************************************************
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
{
// BUGBUG why this error coed?
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->AssignOwnership( GetThreadClientSid() ) );
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;
}