//+------------------------------------------------------------------------- // // 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 } }