|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: Hndlrmsg.cpp
//
// Contents: Takes care of handler specific messages
//
// Classes: CHndlrMsg
//
// Notes:
//
// History: 05-Nov-97 rogerg Created.
//
//--------------------------------------------------------------------------
#include "precomp.h"
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::CHndlrMsg, public
//
// Synopsis: Constructor
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
CHndlrMsg::CHndlrMsg() { m_pOneStopHandler = NULL; m_pOldOneStopHandler = NULL; m_dwSyncFlags = 0; m_pCallBack = NULL; m_cRef = 1; m_fDead = FALSE; m_fForceKilled = FALSE; m_dwNestCount = 0; m_fThreadInputAttached = FALSE; m_itemIDShowProperties = GUID_NULL;
m_dwProxyThreadId = -1; m_dwThreadId = GetCurrentThreadId(); }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::~CHndlrMsg, public
//
// Synopsis: Destructor
//
// Arguments:
//
// Returns:
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
CHndlrMsg::~CHndlrMsg() { Assert(m_dwThreadId == GetCurrentThreadId() || m_fForceKilled); Assert(0 == m_dwNestCount || m_fForceKilled); Assert(0 == m_cRef || m_fForceKilled); }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::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 CHndlrMsg::QueryInterface(REFIID riid, LPVOID FAR *ppv) { Assert(m_dwThreadId == GetCurrentThreadId());
Assert(0 == m_dwNestCount);
return E_NOINTERFACE; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::AddRef, public
//
// Synopsis: Add reference
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CHndlrMsg::AddRef() { ULONG cRefs;
Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(0 == m_dwNestCount);
m_dwNestCount++;
cRefs = InterlockedIncrement((LONG *)& m_cRef);
m_dwNestCount--; return cRefs; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::Release, public
//
// Synopsis: Release reference
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CHndlrMsg::Release() { ULONG cRefs;
Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(0 == m_dwNestCount);
m_dwNestCount++;
cRefs = InterlockedDecrement( (LONG *) &m_cRef);
if (0 == cRefs) { if (m_pCallBack) { SetupCallback(FALSE); }
Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) ); if (m_pOneStopHandler) { LPSYNCMGRSYNCHRONIZE OneStopHandler = m_pOneStopHandler;
m_pOneStopHandler = NULL; // if have a callback then revoke it
// CODE REVIEW : NOTENOTE :
// This is a valid use of try/except, but this would mask real refcounting errors in the handler callbacks,
// or elsewhere in our code where m_pOneStopHandler was overwritten..
__try { OneStopHandler->Release(); } __except(QueryHandleException()) { AssertSz(0,"Exception in Handler's release method."); } }
if (m_pOldOneStopHandler) { LPOLDSYNCMGRSYNCHRONIZE pOldOneStopHandler = m_pOldOneStopHandler;
m_pOldOneStopHandler = NULL; // if have a callback then revoke it
__try { pOldOneStopHandler->Release(); } __except(QueryHandleException()) { AssertSz(0,"Exception in Handler's release method."); } }
if (m_pHndlrQueue) { m_pHndlrQueue->Release(); m_pHndlrQueue = NULL; }
m_fDead = TRUE; m_dwNestCount--; delete this; } else { m_dwNestCount--; }
return cRefs; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::Initialize, public
//
// Synopsis: Calls Initialize method of the Handler
//
// Arguments: [dwReserved] - Reserved for now is NULL
// [dwSyncFlags] - SyncFlags
// [cbCookie] - Size of Cookie data if any
// [lpCookie] - Pointer to Cookie data
//
// Returns: Whatever the handler tells us too.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::Initialize(DWORD dwReserved, DWORD dwSyncFlags, DWORD cbCookie, BYTE const* lpCookie) { HRESULT hr = E_UNEXPECTED;
Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(0 == m_dwNestCount);
m_dwNestCount++;
m_dwSyncFlags = dwSyncFlags; Assert(m_pOneStopHandler || m_pOldOneStopHandler); Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
if (m_pOneStopHandler) { // CODE REVIEW : NOTENOTE:
// QueryHandleException() catches all exceptions - do we want to limit out exception handling code ?
__try { hr = m_pOneStopHandler->Initialize(dwReserved,dwSyncFlags,cbCookie,lpCookie); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's Initialize method."); } }
if (m_pOldOneStopHandler) { // old handlers can't handle cookie data unless it is their own
if (SYNCMGRFLAG_INVOKE != (dwSyncFlags & SYNCMGRFLAG_EVENTMASK)) { cbCookie = 0; lpCookie = NULL; }
__try { hr = m_pOldOneStopHandler->Initialize(dwReserved,dwSyncFlags,cbCookie,lpCookie); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's Initialize method."); } }
m_dwNestCount--; return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::GetHandlerInfo, public
//
// Synopsis: Calls GetHandlerInfo method of the Handler
//
// Arguments: [ppSyncMgrHandlerInfo] -
//
// Returns: Whatever the handler tells us too.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::GetHandlerInfo(LPSYNCMGRHANDLERINFO *ppSyncMgrHandlerInfo) { HRESULT hr = E_UNEXPECTED;
Assert(m_dwThreadId == GetCurrentThreadId());
Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
Assert(m_pOneStopHandler || m_pOldOneStopHandler); Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
if (m_pOneStopHandler) { __try { hr = m_pOneStopHandler->GetHandlerInfo(ppSyncMgrHandlerInfo); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's GetHandlerInfo method."); } }
if (m_pOldOneStopHandler) { __try { hr = m_pOldOneStopHandler->GetHandlerInfo(ppSyncMgrHandlerInfo); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's GetHandlerInfo method."); } }
return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::EnumOfflineItems, public
//
// Synopsis: PlaceHolder for IOfflineSynchronize Enum method.
// This shouldn't be called. AddHandlerItems should be
// called instead
//
// Arguments: [ppenumOfflineItems] - returned enumerator
//
// Returns: Whatever the handler tells us too.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::EnumSyncMgrItems(ISyncMgrEnumItems** ppenumOffineItems) { Assert(m_dwThreadId == GetCurrentThreadId()); Assert(0 == m_dwNestCount); m_dwNestCount++;
AssertSz(0,"Shouldn't call this Method"); *ppenumOffineItems = NULL;
m_dwNestCount--; return E_NOTIMPL; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::GetItemObject, public
//
// Synopsis: Calls Handler's GetItemObject method
//
// Arguments: [ItemID] - Id of the item
// [riid] - requested interface
// [ppv] - out pointer for object
//
// Returns: Whatever the handler tells us too.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::GetItemObject(REFSYNCMGRITEMID ItemID, REFIID riid, void** ppv) { HRESULT hr = E_UNEXPECTED;
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(FALSE == m_fForceKilled && FALSE == m_fDead); Assert(0 == m_dwNestCount);
m_dwNestCount++;
Assert(m_pOneStopHandler || m_pOldOneStopHandler); Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
// CODE REVIEW: NOTENOTE
// MSDN documents that this GetItemObject method is for future use, and that no client
// should be implementing it. Notice the ASSERT below
if (m_pOneStopHandler) { __try { hr = m_pOneStopHandler->GetItemObject(ItemID,riid,ppv); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's GetItemObject method."); } Assert(E_NOTIMPL == hr); // currently no one should be implementing this.
}
if (m_pOldOneStopHandler) { __try { hr = m_pOldOneStopHandler->GetItemObject(ItemID,riid,ppv); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's GetItemObject method."); } Assert(E_NOTIMPL == hr); // currently noone should be implementing this.
}
m_dwNestCount--; return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::ShowProperties, public
//
// Synopsis: Calls Handler's ShowProperties method
//
// Arguments: [hwnd] - hwnd to use as parent to dialog
// [itemID] - Identifies the Item
//
// Returns: Whatever the handler tells us.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::ShowProperties(HWND hwnd,REFSYNCMGRITEMID ItemID) { HRESULT hr = E_UNEXPECTED;
Assert(m_pOneStopHandler || m_pOldOneStopHandler); Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) ); Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
// need to setup calback if showProperties is called
// if can't setup callback then fail the ShowProperties call.
// Review, ShowPropertiesCompleted doesn't give us the ItemID back so we
// have to store it. This is fine but limits us to one ShowPropertiesCall
// at a time on the handler. if update main interfaces change
// ShowPropertiesCompleted to return the ItemID
Assert(GUID_NULL == m_itemIDShowProperties);
m_itemIDShowProperties = ItemID;
hr = SetupCallback(TRUE); // set up the callback.
if (S_OK != hr) return hr;
Assert(0 == m_dwNestCount); m_dwNestCount++;
Assert(m_pOneStopHandler || m_pOldOneStopHandler); Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
AttachThreadInput(TRUE);
if (m_pOneStopHandler) { __try { hr = m_pOneStopHandler->ShowProperties(hwnd,ItemID); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's ShowProperties method."); } }
if (m_pOldOneStopHandler) { __try { hr = m_pOldOneStopHandler->ShowProperties(hwnd,ItemID); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's ShowProperties method."); } }
m_dwNestCount--;
// if old interface need to make the callback ourselves
if ( m_pOldOneStopHandler ) { Assert(m_pCallBack); if (m_pCallBack && (S_OK == hr)) { m_pCallBack->ShowPropertiesCompleted(S_OK); } }
// if an error is returned set the showProperties guid back
if (S_OK != hr) { m_itemIDShowProperties = GUID_NULL; }
return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::SetProgressCallback, public
//
// Synopsis: PlaceHolder for SetProgressCallback. This member is currently
// not used. Instead the SetupCallback method is called
//
// Arguments: [lpCallBack] - Pointer to Callback object
//
// Returns: Whatever the handler tells us.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::SetProgressCallback(ISyncMgrSynchronizeCallback *lpCallBack) { Assert(m_dwThreadId == GetCurrentThreadId()); Assert(0 == m_dwNestCount); Assert(FALSE == m_fForceKilled && FALSE == m_fDead); m_dwNestCount++;
AssertSz(0,"Shouldn't call this method");
m_dwNestCount--; return E_NOTIMPL; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::PrepareForSync, public
//
// Synopsis: Calls Handler's ShowProperties method
//
// Arguments: [cbNumItems] - number of items so sync
// [pItemIDs] - Array of Items
// [hwnd] - Hwnd to use as the Parent of any dialogs
// [dwReserved] - Just a reserved parameter
//
// Returns: Whatever the handler tells us.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::PrepareForSync(ULONG cbNumItems,SYNCMGRITEMID *pItemIDs, HWND hwnd,DWORD dwReserved) { HRESULT hr = E_UNEXPECTED;
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(FALSE == m_fForceKilled && FALSE == m_fDead); // Assert(0 == m_dwNestCount);// may not be zero if handler has yielded
hr = SetupCallback(TRUE); // set up the callback.
if (S_OK != hr) return hr;
m_dwNestCount++;
Assert(m_pOneStopHandler || m_pOldOneStopHandler); Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
if (m_pOneStopHandler) { __try { hr = m_pOneStopHandler->PrepareForSync(cbNumItems,pItemIDs,hwnd,dwReserved); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's PrepareForSync method."); } }
if (m_pOldOneStopHandler) { __try { hr = m_pOldOneStopHandler->PrepareForSync(cbNumItems,pItemIDs,hwnd,dwReserved); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's PrepareForSync method."); } }
m_dwNestCount--;
return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::Sychronize, public
//
// Synopsis: Calls Handler's Synchronize method
//
// Arguments: [hwnd] - hwnd to use as parent to dialog
//
// Returns: Whatever the handler tells us.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::Synchronize(HWND hwnd) { HRESULT hr = E_UNEXPECTED;
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
Assert(m_pOneStopHandler || m_pOldOneStopHandler); Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) ); // Assert(0 == m_dwNestCount);
m_dwNestCount++;
if (m_pOneStopHandler) { __try { hr = m_pOneStopHandler->Synchronize(hwnd); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's Synchronize method."); } }
if (m_pOldOneStopHandler) { __try { hr = m_pOldOneStopHandler->Synchronize(hwnd); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's Synchronize method."); } }
m_dwNestCount--;
return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::SetItemStatus, public
//
// Synopsis: Calls Handler's SetItemStatus method
//
// Arguments:
//
// Returns: Whatever the handler tells us.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::SetItemStatus(REFSYNCMGRITEMID ItemID,DWORD dwSyncMgrStatus) { HRESULT hr = S_OK;
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(FALSE == m_fForceKilled && FALSE == m_fDead); Assert(m_pOneStopHandler || m_pOldOneStopHandler); Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
m_dwNestCount++; // valid for this to come in when in sync call.
if (m_pOneStopHandler) { __try { hr = m_pOneStopHandler->SetItemStatus(ItemID,dwSyncMgrStatus); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's SetItemStatus method."); } }
if (m_pOldOneStopHandler) { __try { hr = m_pOldOneStopHandler->SetItemStatus(ItemID,dwSyncMgrStatus); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's SetItemStatus method."); } }
m_dwNestCount--; return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::ShowError, public
//
// Synopsis: Calls Handler's ShowError method
//
// Arguments: [hwnd] - hwnd to use as parent to dialog
// [dwErrorID] - ErrorID passed in LogError
//
// Returns: Whatever the handler tells us.
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::ShowError(HWND hWndParent,REFSYNCMGRERRORID ErrorID) { HRESULT hr = E_UNEXPECTED; ULONG cbNumItems; SYNCMGRITEMID *pItemIDs;
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(FALSE == m_fForceKilled && FALSE == m_fDead); Assert(m_pOneStopHandler || m_pOldOneStopHandler); Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
m_dwNestCount++;
// on a ShowError enablemodeless in the callback can
// return true since user has shown an interest
if (m_pCallBack) { m_pCallBack->SetEnableModeless(TRUE); }
AttachThreadInput(TRUE);
if (m_pOneStopHandler) { __try { hr = m_pOneStopHandler->ShowError(hWndParent,ErrorID); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's ShowError method."); } }
if (m_pOldOneStopHandler) { __try { hr = m_pOldOneStopHandler->ShowError(hWndParent,ErrorID,&cbNumItems,&pItemIDs); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's ShowError method."); } }
m_dwNestCount--;
// if old interface need to make the callback ourselves
if ( m_pOldOneStopHandler ) { Assert(m_pCallBack); if (m_pCallBack && SUCCEEDED(hr)) { m_pCallBack->ShowErrorCompleted(hr,cbNumItems,pItemIDs); if ( (S_SYNCMGR_RETRYSYNC == hr) && pItemIDs) // after completion routine free the pItems since [in] param.
{ CoTaskMemFree(pItemIDs); } }
return SUCCEEDED(hr) ? S_OK : hr; }
// New interface won't have the numItems and Items Enum
// on new interface ShowError should only return S_OK so if retry or
// other success is returned then return S_OK;
return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::SetupCallback, private
//
// Synopsis: Sets up the callback for the handler
//
// Arguments: [fSet] - TRUE sets the Callbac, FALSE removes it
//
// Returns: S_OK on Success
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::SetupCallback(BOOL fSet) { HRESULT hr = E_UNEXPECTED;
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(FALSE == m_fForceKilled && FALSE == m_fDead); Assert(m_dwNestCount <= 1); // 1 since valid to be called from Release method.
m_dwNestCount++;
// possible to get called with fSet twice of true in the case
// a retrysync occurs. If we already have a callback set
// when a new request to set one comes in the just return.
if ( m_pCallBack && (TRUE == fSet)) { hr = S_OK; } else { Assert( ( (m_pCallBack) && (FALSE == fSet) ) || (TRUE == fSet)); // catch case OneStop calls this twice when already set
if (m_pCallBack) { // set the callbacks CHndlrMsg pointer to NULL in case
// object tries to call through after the release.
m_pCallBack->SetHndlrMsg(NULL,FALSE); m_pCallBack->Release(); m_pCallBack = NULL; }
if (TRUE == fSet) { // if allocation fails, progress just gets set to NULL
m_pCallBack = new COfflineSynchronizeCallback( this, m_CLSIDServer,m_dwSyncFlags, (SYNCMGRFLAG_MAYBOTHERUSER & m_dwSyncFlags) /* fAllowModeless */ ); }
Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) ); if (m_pOneStopHandler) { __try { hr = m_pOneStopHandler->SetProgressCallback( (LPSYNCMGRSYNCHRONIZECALLBACK) m_pCallBack ); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's SetProgressCallback method."); } }
if (m_pOldOneStopHandler) { __try { hr = m_pOldOneStopHandler->SetProgressCallback( (LPOLDSYNCMGRSYNCHRONIZECALLBACK) m_pCallBack ); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's SetProgressCallback method."); } }
if ( (S_OK != hr) && (m_pCallBack) ) { m_pCallBack->SetHndlrMsg(NULL,FALSE); m_pCallBack->Release(); // on an error go ahead and release our copy too.
m_pCallBack = NULL; } }
m_dwNestCount--; return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::SetHandlerInfo, private
//
// Synopsis: sets up the Handler info
//
// Arguments:
//
// Returns: S_OK on Success
//
// Modifies:
//
// History: 28-Jul-98 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::SetHandlerInfo() { LPSYNCMGRHANDLERINFO pSyncMgrHandlerInfo = NULL; HRESULT hr = E_UNEXPECTED;
Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
hr = GetHandlerInfo(&pSyncMgrHandlerInfo); if (S_OK != hr || (NULL == pSyncMgrHandlerInfo)) { return hr; } if (!IsValidSyncMgrHandlerInfo(pSyncMgrHandlerInfo)) { CoTaskMemFree(pSyncMgrHandlerInfo); return E_INVALIDARG; }
Assert(m_pHndlrQueue);
if (m_pHndlrQueue) { hr = m_pHndlrQueue->SetHandlerInfo(m_pHandlerId,pSyncMgrHandlerInfo); }
if (pSyncMgrHandlerInfo) { CoTaskMemFree(pSyncMgrHandlerInfo); }
return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::AddtoItemList, private
//
// Synopsis: Adds a single Items to the queue
//
// Arguments: [poffItem] - Pointer to Item to add
//
// Returns: S_OK on Success
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
HRESULT CHndlrMsg::AddToItemList(LPSYNCMGRITEM poffItem) { HRESULT hr = E_UNEXPECTED;
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
Assert(m_pHndlrQueue);
if (!IsValidSyncMgrItem(poffItem)) { return E_INVALIDARG; }
if (m_pHndlrQueue) { hr = m_pHndlrQueue->AddItemToHandler(m_pHandlerId,poffItem); }
return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::AddHandlerItems, private
//
// Synopsis: Calls the handlers enumerator and adds each returned item
// to the queue
//
// Arguments: [hwndList] - hwnd of ListView to add items too. (Not Used)
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::AddHandlerItems(HWND hwndList, DWORD *pcbNumItems) { HRESULT hr = E_UNEXPECTED; LPSYNCMGRENUMITEMS pEnumOffline = NULL;
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(FALSE == m_fForceKilled && FALSE == m_fDead); Assert(pcbNumItems);
*pcbNumItems = 0;
Assert(0 == m_dwNestCount); m_dwNestCount++;
SetHandlerInfo(); // setup the toplevel handler info
Assert(m_pOneStopHandler || m_pOldOneStopHandler); Assert( !(m_pOneStopHandler && m_pOldOneStopHandler) );
if (m_pOneStopHandler || m_pOldOneStopHandler) { if ( m_pOneStopHandler ) { __try { hr = m_pOneStopHandler->EnumSyncMgrItems(&pEnumOffline); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's EnumSyncMgrItems method."); } } if ( m_pOldOneStopHandler ) { __try { hr = m_pOldOneStopHandler->EnumSyncMgrItems(&pEnumOffline); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's EnumSyncMgrItems method."); } }
// Review - Make sure preferences aren't deleted
// in missing items case.
if ( (S_OK == hr || S_SYNCMGR_MISSINGITEMS == hr) && pEnumOffline) { SYNCMGRITEMNT5B2 offItem; // temporarily use NT5B2 structure since its bigger
ULONG pceltFetched;
Assert(sizeof(SYNCMGRITEMNT5B2) > sizeof(SYNCMGRITEM));
// sit in loop getting data of objects to fill list box.
// should really set up list in memory for OneStop to fill in or
// main thread could pass in a callback interface.
if (pEnumOffline) { __try { while(S_OK == pEnumOffline->Next(1,(LPSYNCMGRITEM) &offItem,&pceltFetched)) { if (S_OK == AddToItemList((LPSYNCMGRITEM) &offItem)) { ++(*pcbNumItems); } }
pEnumOffline->Release(); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's EnumOffline::Next method."); } } else { hr = E_UNEXPECTED; } } }
m_dwNestCount--; return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::CreateServer, private
//
// Synopsis: Creates and Instance of the handle
//
// Arguments: [pCLSIDServer] - CLSID of Handler
// [pHndlrQueue] - pointer to queue handler should be added too
// [wHandlerID] - ID of Handler in the queue
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::CreateServer(const CLSID *pCLSIDServer,CHndlrQueue *pHndlrQueue, HANDLERINFO *pHandlerId,DWORD dwProxyThreadId) { HRESULT hr = S_OK; LPUNKNOWN pUnk; LPSYNCMGRENUMITEMS pEnumOffline = NULL;
Assert(m_dwThreadId == GetCurrentThreadId()); Assert(FALSE == m_fForceKilled && FALSE == m_fDead); Assert(0 == m_dwNestCount); m_dwNestCount++;
m_CLSIDServer = *pCLSIDServer; m_pHndlrQueue = pHndlrQueue; m_dwProxyThreadId = dwProxyThreadId;
if (m_pHndlrQueue) { m_pHndlrQueue->AddRef(); }
m_pHandlerId = pHandlerId;
hr = CoCreateInstance(m_CLSIDServer, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **) &pUnk);
if (S_OK == hr) { __try { hr = pUnk->QueryInterface(IID_ISyncMgrSynchronize,(void **) &m_pOneStopHandler); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's IUnknown::QI method."); } __try { pUnk->Release(); } __except(QueryHandleException()) { hr = HRESULT_FROM_WIN32(GetExceptionCode()); AssertSz(0,"Exception in Handler's IUnknown::Release method."); } }
if (S_OK != hr) { m_pOneStopHandler = NULL; m_pOldOneStopHandler = NULL; }
m_dwNestCount--; return hr; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::SetHndlrQueue, private
//
// Synopsis: Assigns a new HndlrQueue.
//
// Arguments: [pHndlrQueue] - Pointer to the Queue
// [wHandlerId] - Id assigned to handler in the new queue
//
// !!!Warning - this is on the callers thread
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::SetHndlrQueue(CHndlrQueue *pHndlrQueue,HANDLERINFO *pHandlerId,DWORD dwProxyThreadId) { CLock clockCallback(this);
Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
clockCallback.Enter();
Assert(0 == m_dwNestCount); m_dwNestCount++;
if (pHndlrQueue != m_pHndlrQueue) { if (m_pHndlrQueue) { m_pHndlrQueue->Release(); }
m_pHndlrQueue = pHndlrQueue;
if (m_pHndlrQueue) { m_pHndlrQueue->AddRef(); } }
AttachThreadInput(FALSE); // make sure thread input isn't set
// update handlr id and proxy which can change even if queue is same
// which can happen first queue that gets set in choice.
m_pHandlerId = pHandlerId; m_dwProxyThreadId = dwProxyThreadId;
m_dwNestCount--;
clockCallback.Leave();
return S_OK; }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::GetHndlrQueue, private
//
// Synopsis: Gets current Queue,
// Can be called on any thread so progress callback
// gets this information.
//
// Arguments: [ppHndlrQueue] - Out param filled with Pointer to the Queue
// [pwHandlerId] - out param filled with Id assigned to handler
// in the new queue
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
void CHndlrMsg::GetHndlrQueue(CHndlrQueue **ppHndlrQueue,HANDLERINFO **ppHandlerId,DWORD *pdwProxyThreadId) { CLock clockCallback(this);
Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
clockCallback.Enter();
*ppHndlrQueue = m_pHndlrQueue; *ppHandlerId = m_pHandlerId; *pdwProxyThreadId = m_dwProxyThreadId;
if (m_pHndlrQueue) { m_pHndlrQueue->AddRef(); }
clockCallback.Leave(); }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::AttachThreadInput, private
//
// Synopsis: Attaches the thread input of this thread
// with the calling proxy so UI works correctly.
//
// Arguments: [fAttach] - Bool to indicate if should attach or not.
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 05-Nov-97 rogerg Created.
//
//----------------------------------------------------------------------------
void CHndlrMsg::AttachThreadInput(BOOL fAttach) { Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
// if request is same as current state don't do anything.
if (m_fThreadInputAttached != fAttach ) { m_fThreadInputAttached = fAttach; ::AttachThreadInput(m_dwProxyThreadId,m_dwThreadId,fAttach); } }
//+---------------------------------------------------------------------------
//
// Member: CHndlrMsg::ForceKillHandler, private
//
// Synopsis: called directly by proxy when a thread is not
// responding. Does any necessary cleanup of classes in the handler
// thread before the proxy kills the thred
//
// Arguments:
//
// Returns: Appropriate status code
//
// Modifies:
//
// History: 17-Nov-98 rogerg Created.
//
//----------------------------------------------------------------------------
STDMETHODIMP CHndlrMsg::ForceKillHandler() { Assert(FALSE == m_fForceKilled && FALSE == m_fDead);
m_fForceKilled = TRUE;
// if have a callback tell it we terminated but don't
// release it in case the handler calls the callback later.
if (m_pCallBack) { COfflineSynchronizeCallback* pCallback = m_pCallBack; m_pCallBack = NULL; pCallback->SetHndlrMsg(NULL,TRUE); }
// delete our instance since should never be called again.
delete this;
return S_OK; }
|