windows-nt/Source/XPSP1/NT/com/mobile/syncmgr/exe/callback.cpp
2020-09-26 16:20:57 +08:00

586 lines
15 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: Callback.cpp
//
// Contents: Calback implementation
//
// Classes: COfflineSynchronizeCallback
//
// Notes:
//
// History: 05-Nov-97 rogerg Created.
//
//--------------------------------------------------------------------------
#include "precomp.h"
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::COfflineSynchronizeCallback, public
//
// Synopsis: Constructor
//
// Arguments: [pHndlrMsg] - pointer to CHndlrMsg class this callback belongs too.
//
// Returns:
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
COfflineSynchronizeCallback::COfflineSynchronizeCallback(CHndlrMsg *pHndlrMsg
,CLSID CLSIDServer
,DWORD dwSyncFlags
,BOOL fAllowModeless)
{
Assert(NULL != pHndlrMsg);
m_pHndlrMsg = pHndlrMsg;
m_CLSIDServer = CLSIDServer;
m_dwSyncFlags = dwSyncFlags;
m_cRef = 1;
m_fSynchronizeCompleted = FALSE;
m_fAllowModeless = fAllowModeless;
m_fForceKilled = FALSE;
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::~COfflineSynchronizeCallback, public
//
// Synopsis: Destructor
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
COfflineSynchronizeCallback::~COfflineSynchronizeCallback()
{
Assert(FALSE == m_fForceKilled); // should never get cleaned up of force killed.
Assert(NULL == m_pHndlrMsg);
Assert(0 == m_cRef);
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::QueryInterface, public
//
// Synopsis: Standard QueryInterface
//
// Arguments: [iid] - Interface ID
// [ppvObj] - Object return
//
// Returns: Appropriate status code
//
// Modifies: [ppvObj]
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP COfflineSynchronizeCallback::QueryInterface (REFIID riid, LPVOID * ppvObj)
{
*ppvObj = NULL;
if( IsEqualIID( riid, IID_IUnknown ) )
*ppvObj = (LPVOID) this;
else if ( IsEqualIID( riid, IID_ISyncMgrSynchronizeCallback ) )
*ppvObj = (LPVOID)(LPSYNCMGRSYNCHRONIZECALLBACK) this;
else if ( IsEqualIID( riid, IID_IOldSyncMgrSynchronizeCallback ) )
{
// This is for the Old IDL This is the old IE 5.0 Beta1 interface
// no one shipped using it so it can safely be removed.
*ppvObj = (LPVOID)(LPOLDSYNCMGRSYNCHRONIZECALLBACK) this;
}
else
return E_NOINTERFACE;
AddRef();
return NOERROR;
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::AddRef, public
//
// Synopsis: Add reference
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
DWORD COfflineSynchronizeCallback::AddRef()
{
ULONG cRefs;
cRefs = InterlockedIncrement((LONG *)& m_cRef);
return cRefs;
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::Release, public
//
// Synopsis: Release reference
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
DWORD COfflineSynchronizeCallback::Release()
{
ULONG cRefs;
cRefs = InterlockedDecrement( (LONG *) &m_cRef);
if (0 == cRefs)
{
delete this;
}
return cRefs;
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::EnableModeless, public
//
// Synopsis: EnableModeless method - Currently always returns NOERROR
//
// Arguments: [fEnable] - Boolean (TRUE == request to bring up dialog,
// FALSE == the dialog has been dismissed.
//
// Returns: S_OK if handler can perform the request
// S_FALSE if dialog shouldn't be displayed.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP COfflineSynchronizeCallback::EnableModeless(BOOL fEnable)
{
HRESULT hr = S_OK;
if (m_fForceKilled)
{
return S_FALSE;
}
if (!m_fAllowModeless && fEnable)
{
hr = S_FALSE;
}
if (m_pHndlrMsg)
{
BOOL fAttach = FALSE;
if (fEnable && (S_OK == hr)) // Attach Thread input if want dialog and it was granted.
{
fAttach = TRUE;
}
m_pHndlrMsg->AttachThreadInput(fAttach);
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::Progress, public
//
// Synopsis: Called by Handlers to update progress information.
//
// Arguments: [ItemID] - Identifies Item Progress information pertains to
// [lpSyncProgressItem] - Pointer to ProgressItem Structure.
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP COfflineSynchronizeCallback::Progress(REFSYNCMGRITEMID ItemID,
LPSYNCMGRPROGRESSITEM lpSyncProgressItem)
{
HRESULT hr = E_UNEXPECTED;
CHndlrQueue *pHndlrQueue = NULL;
HANDLERINFO *pHandlerID = 0;
DWORD dwProxyThreadId;
CLock clockCallback(this);
if (m_fForceKilled)
{
return S_SYNCMGR_CANCELALL;
}
clockCallback.Enter();
Assert(NULL != m_pHndlrMsg);
if (m_pHndlrMsg)
{
m_pHndlrMsg->GetHndlrQueue(&pHndlrQueue,&pHandlerID,&dwProxyThreadId);
}
clockCallback.Leave();
if (pHndlrQueue)
{
hr = pHndlrQueue->Progress(pHandlerID,
ItemID,lpSyncProgressItem);
pHndlrQueue->Release(); // release our reference put on by GetHndlrQueue
}
return hr;
}
STDMETHODIMP COfflineSynchronizeCallback::PrepareForSyncCompleted(HRESULT hCallResult)
{
CallCompletionRoutine(ThreadMsg_PrepareForSync,hCallResult,0,NULL);
return NOERROR;
}
STDMETHODIMP COfflineSynchronizeCallback::SynchronizeCompleted(HRESULT hCallResult)
{
CallCompletionRoutine(ThreadMsg_Synchronize,hCallResult,0,NULL);
return NOERROR;
}
STDMETHODIMP COfflineSynchronizeCallback::ShowPropertiesCompleted(HRESULT hCallResult)
{
CallCompletionRoutine(ThreadMsg_ShowProperties,hCallResult,0,NULL);
return NOERROR;
}
STDMETHODIMP COfflineSynchronizeCallback::ShowErrorCompleted(HRESULT hCallResult,ULONG cbNumItems,SYNCMGRITEMID *pItemIDs)
{
CallCompletionRoutine(ThreadMsg_ShowError,hCallResult,cbNumItems,pItemIDs);
return NOERROR;
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::LogError, public
//
// Synopsis: Called by Handlers to log and Error.
//
// Arguments: [dwErrorLevel] - ErrorLevel of the Log
// [lpcErrorText] - Text Associated with the error.
// [lpSyncLogError] - Additional Error information.
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP COfflineSynchronizeCallback::LogError(DWORD dwErrorLevel,
const WCHAR *lpcErrorText,LPSYNCMGRLOGERRORINFO lpSyncLogError)
{
HRESULT hr = E_UNEXPECTED;
CHndlrQueue *pHndlrQueue = NULL;
HANDLERINFO *pHandlerID = 0;
DWORD dwProxyThreadId;
CLock clockCallback(this);
if (m_fForceKilled)
{
return NOERROR;
}
clockCallback.Enter();
Assert(NULL != m_pHndlrMsg);
if (m_pHndlrMsg)
{
m_pHndlrMsg->GetHndlrQueue(&pHndlrQueue,&pHandlerID,&dwProxyThreadId);
}
clockCallback.Leave();
if (pHndlrQueue)
{
hr = pHndlrQueue->LogError(pHandlerID,
dwErrorLevel, lpcErrorText,lpSyncLogError);
pHndlrQueue->Release(); // release our reference put on by GetHndlrQueue
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::LogError, public
//
// Synopsis: Called by Handlers to delete an error that
// was previously logged.
//
// Arguments:
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 13-Mar-98 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP COfflineSynchronizeCallback::DeleteLogError(REFSYNCMGRERRORID ErrorID,DWORD dwReserved)
{
HRESULT hr = E_UNEXPECTED;
CHndlrQueue *pHndlrQueue = NULL;
HANDLERINFO *pHandlerID = 0;
DWORD dwProxyThreadId;
CLock clockCallback(this);
if (m_fForceKilled)
{
return NOERROR;
}
if (dwReserved)
{
AssertSz(0,"DeleteLogError Reserved must be zero");
return E_INVALIDARG;
}
clockCallback.Enter();
Assert(NULL != m_pHndlrMsg);
if (m_pHndlrMsg)
{
m_pHndlrMsg->GetHndlrQueue(&pHndlrQueue,&pHandlerID,&dwProxyThreadId);
}
clockCallback.Leave();
if (pHndlrQueue)
{
hr = pHndlrQueue->DeleteLogError(pHandlerID,ErrorID,dwReserved);
pHndlrQueue->Release(); // release our reference put on by GetHndlrQueue
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::EstablishConnection
//
// Synopsis: Called by Handlers to establish a net connection
//
// Arguments: [lpwszConnection] -- Connection string
// [dwReserved] -- Must be zero for now
//
// History: 28-Jul-98 SitaramR Created
//
//----------------------------------------------------------------------------
STDMETHODIMP COfflineSynchronizeCallback::EstablishConnection( WCHAR const * lpwszConnection,
DWORD dwReserved)
{
if (m_fForceKilled)
{
return S_FALSE;
}
if ( dwReserved != 0 )
{
Assert( dwReserved == 0 );
return E_INVALIDARG;
}
HRESULT hr = E_UNEXPECTED;
CHndlrQueue *pHndlrQueue = NULL;
HANDLERINFO *pHandlerID = 0;
DWORD dwProxyThreadId;
CLock clockCallback(this);
clockCallback.Enter();
Assert(NULL != m_pHndlrMsg);
if (m_pHndlrMsg)
{
m_pHndlrMsg->GetHndlrQueue(&pHndlrQueue,&pHandlerID,&dwProxyThreadId);
}
clockCallback.Leave();
if (pHndlrQueue)
{
hr = pHndlrQueue->EstablishConnection( pHandlerID,
lpwszConnection,
dwReserved);
pHndlrQueue->Release(); // release our reference put on by GetHndlrQueue
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::SetHndlrMsg, public
//
// Synopsis: Called by CHndlrMsg to update the CHndlrMsg that owns the
// callback. This currently should only be called with a paramater
// of NULL for when the HndlrMsg is being destroyed.
//
// Arguments: [pHndlrMsg] - New CHndlrMsg the Callback belongs too.
// [fForceKilled] - Set to True if HndlrMsg is removed because of a forcekill
//
// Returns:
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
void COfflineSynchronizeCallback::SetHndlrMsg(CHndlrMsg *pHndlrMsg,BOOL fForceKilled)
{
CLock clockCallback(this);
Assert(NULL == pHndlrMsg);
Assert(FALSE == m_fForceKilled); // shouldn't get force killed twice
clockCallback.Enter();
m_pHndlrMsg = pHndlrMsg;
m_fForceKilled = fForceKilled;
clockCallback.Leave();
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::SetEnableModeless, private
//
// Synopsis: Called by CHndlrMsg to update inform the callback if
// it is allowed to enablemodelsss.
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
void COfflineSynchronizeCallback::SetEnableModeless(BOOL fAllowModeless)
{
CLock clockCallback(this);
clockCallback.Enter();
m_fAllowModeless = fAllowModeless;
clockCallback.Leave();
}
//+---------------------------------------------------------------------------
//
// Member: COfflineSynchronizeCallback::CallCompletionRoutine, private
//
// Synopsis: Private helper method for calling completion routine.
//
// Arguments:
// DWORD dwThreadMsg - Identifies message belongs too.
// HRESULT hCallResult - result of call
// ULONG *pcbNumItems - only applies to ShowError
// SYNCMGRITEMID **pItemIDs - only applies to ShowError
//
// Returns:
//
// Modifies:
//
// History: 02-Jun-98 rogerg Created.
//
//----------------------------------------------------------------------------
void COfflineSynchronizeCallback::CallCompletionRoutine(DWORD dwThreadMsg,HRESULT hCallResult,ULONG cbNumItems,SYNCMGRITEMID *pItemIDs)
{
CHndlrQueue *pHndlrQueue = NULL;
HANDLERINFO *pHandlerID = 0;
DWORD dwProxyThreadId;
SYNCMGRITEMID itemIDShowProperties;
CLock clockCallback(this);
if (m_fForceKilled)
{
return;
}
clockCallback.Enter();
Assert(NULL != m_pHndlrMsg);
if (m_pHndlrMsg)
{
// if this is a ShowProperties, fix up the item
if (ThreadMsg_ShowProperties == dwThreadMsg)
{
cbNumItems = 1;
itemIDShowProperties = m_pHndlrMsg->m_itemIDShowProperties;
pItemIDs = &itemIDShowProperties;
m_pHndlrMsg->m_itemIDShowProperties = GUID_NULL;
}
m_pHndlrMsg->GetHndlrQueue(&pHndlrQueue,&pHandlerID,&dwProxyThreadId);
m_pHndlrMsg->AttachThreadInput(FALSE); // release any thread input that was set.
}
clockCallback.Leave();
if (pHndlrQueue)
{
pHndlrQueue->CallCompletionRoutine(pHandlerID,dwThreadMsg,hCallResult,cbNumItems,pItemIDs);
pHndlrQueue->Release(); // release our reference put on by GetHndlrQueue
}
}