/*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M Method: CFBall::Release Summary: Release of the CFBall non-delegating IUnknown implementation. Args: void Modifies: m_cRefs. Returns: ULONG New value of m_cRefs (COM object's reference count). M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/ STDMETHODIMP_(ULONG) CFBall::Release(void) { ULONG cRefs = 0; if (OwnThis()) { cRefs = --m_cRefs; if (0 == cRefs) { // We've reached a zero reference count for this COM object. // So we tell the server housing to decrement its global object // count so that the server will be unloaded if appropriate. if (NULL != m_pServer) m_pServer->ObjectsDown(); // We artificially bump the main ref count to prevent reentrancy // via the main object destructor. Not really needed in this // CFBall but a good practice because we are aggregatable and // may at some point in the future add something entertaining like // some Releases to the CFBall destructor. m_cRefs++; UnOwnThis(); delete this; } else UnOwnThis(); } return cRefs; }
/*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M Method: CFBall::QueryInterface Summary: QueryInterface of the CFBall non-delegating IUnknown implementation. Args: REFIID riid, [in] GUID of the Interface being requested. PPVOID ppv) [out] Address of the caller's pointer variable that will receive the requested interface pointer. Modifies: . Returns: HRESULT M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/ STDMETHODIMP CFBall::QueryInterface( REFIID riid, PPVOID ppv) { HRESULT hr = E_NOINTERFACE; if (OwnThis()) { *ppv = NULL; if (IID_IUnknown == riid) *ppv = this; else if (IID_IClassFactory == riid) *ppv = &m_ImpIClassFactory; if (NULL != *ppv) { // We've handed out a pointer to the interface so obey the COM rules // and AddRef the reference count. ((LPUNKNOWN)*ppv)->AddRef(); hr = NOERROR; } UnOwnThis(); } return (hr); }
/*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M Method: COBall::CImpIBall::GetBall Summary: The GetBall member method of this IBall interface implementation. Called by outside clients of a COBall object to get the necessary data on the moving ball to enable GUI display of an actual image of this virtual ball. This COBall is a data entity only that is kept alive by client threads that call Move. A GUI client can independently call GetBall to allow it to display some visual representation of the Ball. Args: POINT* pOrg, Pointer to a point that will contain the current origin position of the ball. POINT* pExt, Pointer to a point that will contain the current extent size of the ball. COLORREF* pcrColor) Pointer to a COLORREF that will contain the current color of the ball. This color is determined by the last thread that was executing in the ball before this call is made. Modifies: ... Returns: void M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/ STDMETHODIMP COBall::CImpIBall::get_Ball( POINT* pOrg, POINT* pExt, COLORREF* pcrColor) { HRESULT hr = E_FAIL; if (OwnThis()) { *pcrColor = m_crColor; pOrg->x = 0; pOrg->y = 0; m_XForm.Point(pOrg); pExt->x = m_nWidth; pExt->y = m_nHeight; m_XForm.Point(pExt); hr = NOERROR; UnOwnThis(); } return hr; }
/*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M Method: COBall::CImpIBall::Reset Summary: The Reset member method of the IBall interface implementation. Called by outside clients of a COBall object to reset the virtual ball. It is restored to the upper left corner. Args: RECT* pNewRect, Pointer to a RECT structure. Tells the COBall the bounding rectangle within which the ball can move. short nBallSize, The size of the ball in pixels. nBallSize == Width == Height meaning that a circle is assumed. Modifies: ... Returns: void M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/ STDMETHODIMP COBall::CImpIBall::Reset( RECT* pNewRect, short nBallSize) { HRESULT hr = E_FAIL; int nDim, xDirection, yDirection; if (OwnThis()) { // Find the thread who is executing this and remember its color. FindThread(); m_xSkew = m_ySkew = BALL_MOVE_SKEW; m_WinRect.left = pNewRect->left; m_WinRect.top = pNewRect->top; m_WinRect.right = pNewRect->right; m_WinRect.bottom = pNewRect->bottom; nDim = nBallSize ? nBallSize : max(5, m_WinRect.right / 13); SetDimensions(nDim, nDim); SetPosition(0, 0); xDirection = ((lRandom() % m_xSkew) + m_xSkew); yDirection = ((lRandom() % m_ySkew) + m_ySkew); SetDirection(xDirection, yDirection); hr = NOERROR; UnOwnThis(); } return hr; }
void CaComServer::Lock() { if (OwnThis()) { m_cLocks += 1; UnOwnThis(); } }
void CaComServer::ObjectsUp() { if (OwnThis()) { m_cObjects += 1; UnOwnThis(); } }
/*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M Method: CFBall::AddRef Summary: AddRef of the CFBall non-delegating IUnknown implementation. Args: void Modifies: m_cRefs. Returns: ULONG New value of m_cRefs (COM object's reference count). M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/ STDMETHODIMP_(ULONG) CFBall::AddRef(void) { ULONG cRefs = 0; if (OwnThis()) { cRefs = ++m_cRefs; UnOwnThis(); } return cRefs; }
void CaComServer::ObjectsDown() { if (OwnThis()) { if (m_cObjects > 0) m_cObjects -= 1; // // If no more living objects and no locks then shut down the server. if (0L == m_cObjects && 0L == m_cLocks ) { // // Destroy all the sessions in the cache theApp.GetSessionManager().Cleanup(); } UnOwnThis(); } }
void CaComServer::Unlock() { if (OwnThis()) { m_cLocks -= 1; if (m_cLocks < 0) m_cLocks = 0; // // If no more living objects and no locks then shut down the server. if (0L == m_cObjects && 0L == m_cLocks && IsWindow(m_hWndServer)) { // // Post a message to this local server's message queue requesting // a close of the application. This will force a termination of // all apartment threads. PostMessage(m_hWndServer, WM_CLOSE, 0, 0L); } UnOwnThis(); } }
/*M+M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M+++M Method: COBall::CImpIBall::Move Summary: The Move member method of this IBall interface implementation. Called by outside clients of a COBall object to advance the "motion" of this COBall virtual ball entity. Args: BOOL bAlive TRUE means stay alive; FALSE means don't move but die. Modifies: m_bAlive. Returns: BOOL TRUE means the move was done and the ball is still alive. FALSE means the move was not done and the ball has been killed. M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M---M-M*/ STDMETHODIMP COBall::CImpIBall::Move(BOOL bAlive, BOOL* bRet) { *bRet = FALSE; if (OwnThis()) { if (bAlive) { // Find thread that is now executing this code. Remember its Id and // assign it a color. If this thread previously visited here then // use its remembered values. In any case, set a color value in // m_crColor of its existing or newly assigned color. FindThread(); // Ask the Ball if it has hit any of the edges of the current window // rectangle. If so, it will recalculate its position and direction to // achieve a "bounce" effect in its motion the next time it is painted. CheckBounce(); // Calculate and set new ball position. if(m_bNewPosition) { m_bNewPosition = FALSE; m_XForm.Clear(); m_XForm.Trans(m_xPosition, m_yPosition); } else m_XForm.Trans(m_xDirection, m_yDirection); } else m_bAlive = FALSE; *bRet = m_bAlive; UnOwnThis(); } return S_OK; }