Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1382 lines
38 KiB

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