⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 koala.cpp

📁 英文版的 想要的话可以下载了 为大家服务
💻 CPP
字号:
/*
 * KOALA.CPP
 * Koala Object with Custom Marshaling, Chapter 6
 *
 * Implementation of the CKoala object with a custom interface
 * to demonstrate local/remote transparency.
 *
 * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
 *
 * Kraig Brockschmidt, Microsoft
 * Internet  :  kraigb@microsoft.com
 * Compuserve:  >INTERNET:kraigb@microsoft.com
 */


#include "koala.h"


/*
 * ObjectWndProc
 *
 * Purpose:
 *  Standard window class procedure for each object.
 */

LRESULT APIENTRY ObjectWndProc(HWND hWnd, UINT iMsg
    , WPARAM wParam, LPARAM lParam)
    {
    PCKoala     pKoala;

    pKoala=(PCKoala)GetWindowLong(hWnd, OBJECTWL_STRUCTURE);

    switch (iMsg)
        {
        case WM_NCCREATE:
            pKoala=(PCKoala)(((LPCREATESTRUCT)lParam)->lpCreateParams);
            SetWindowLong(hWnd, OBJECTWL_STRUCTURE, (LONG)pKoala);
            return (DefWindowProc(hWnd, iMsg, wParam, lParam));

        case WM_COMMAND:
            //Dispatch the call to the right object
            return pKoala->HandleCall(LOWORD(wParam), lParam);

        default:
            return (DefWindowProc(hWnd, iMsg, wParam, lParam));
        }

    return 0L;
    }





/*
 * CKoala::CKoala
 * CKoala::~CKoala
 *
 * Parameters (Constructor):
 *  pfnDestroy      PFNDESTROYED to call when an object
 *                  is destroyed.
 */

CKoala::CKoala(PFNDESTROYED pfnDestroy)
    {
    m_cRef=0;
    m_pfnDestroy=pfnDestroy;

    m_fJustAte=FALSE;
    m_cSleepAfterEat=0;
    return;
    }


CKoala::~CKoala(void)
    {
    if (NULL!=m_hWnd)
        DestroyWindow(m_hWnd);

    return;
    }



/*
 * CKoala::Init
 *
 * Purpose:
 *  Performs any intiailization of a CKoala that's prone to failure
 *  that we also use internally before exposing the object outside.
 *
 * Parameters:
 *  hInst           HINSTANCE of the application.
 *  hWndParent      HWND in which to create our window
 *
 * Return Value:
 *  BOOL            TRUE if the function is successful,
 *                  FALSE otherwise.
 */

BOOL CKoala::Init(HINSTANCE hInst, HWND hWndParent)
    {
    //Create our window that receives marshaling calls
    m_hWnd=CreateWindow(TEXT("KoalaObject"), TEXT("KoalaObject")
        , WS_CHILD, 35, 35, 35, 25, hWndParent, NULL
        , hInst, this);

    if (NULL==m_hWnd)
        return FALSE;

    return TRUE;
    }





/*
 * CKoala::HandleCall
 *
 * Purpose:
 *  Handles messages sent via custom marshaling from the client
 *  side proxy.
 *
 * Parameters:
 *  iMsg            UINT identifying the call made.
 *  lParam          LPARAM with extra information.
 *
 * Return Value:
 *  DWORD           Value to return to the proxy which it uses
 *                  in whatever way it must to return a value to
 *                  the client.
 */

DWORD CKoala::HandleCall(UINT iMsg, LPARAM lParam)
    {
    DWORD       dw;
    short       iRet=0;

    /*
     * You'll notice that all the important server-side
     * implementation of the object exists here instead of
     * separate interface implementations.  Everything
     * else is contained in the client-side proxy, who knows
     * when there's no point at all in calling a function
     * on the server side (such as with some of the IKoala
     * functions that don't do anything.
     */

    switch (iMsg)
        {
        case MSG_RELEASE:          //Last IUnknown::Release
            /*
             * There is only one reference count from
             * IClassFactory::CreateInstance, which the proxy
             * will own.  The proxy sends this message when
             * it detects the last Release from the client.
             * Otherwise it doesn't forward AddRef/Release calls.
             */
            Release();
            break;

        case MSG_EAT:
            m_fJustAte=TRUE;
            break;

        case MSG_SLEEP:            //IAnimal::Sleep
            //Client's in-parameter in LOWORD(lParam)
            iRet=LOWORD(lParam)+m_cSleepAfterEat;
            m_fJustAte=FALSE;     //Probably want to eat again
            break;

        case MSG_PROCREATE:        //IAnimal::Procreate
            dw=GetTickCount()/100;

            iRet=((dw/10)*10==dw) ? 1 : 0;
            break;

        case MSG_SLEEPAFTEREATING: //IKoala::SleepAfterEating
            m_cSleepAfterEat=LOWORD(lParam);
            break;

        default:
            break;
        }

    return iRet;
    }





/*
 * CKoala::QueryInterface
 * CKoala::AddRef
 * CKoala::Release
 *
 * Purpose:
 *  IUnknown members for CKoala object.
 */

STDMETHODIMP CKoala::QueryInterface(REFIID riid, PPVOID ppv)
    {
    *ppv=NULL;

    if (IID_IUnknown==riid || IID_IMarshal==riid
        || IID_IAnimal==riid || IID_IKoala==riid)
        *ppv=this;

    if (NULL!=*ppv)
        {
        ((LPUNKNOWN)*ppv)->AddRef();
        return NOERROR;
        }

    return ResultFromScode(E_NOINTERFACE);
    }


STDMETHODIMP_(ULONG) CKoala::AddRef(void)
    {
    return ++m_cRef;
    }


STDMETHODIMP_(ULONG) CKoala::Release(void)
    {
    if (0L!=--m_cRef)
        return m_cRef;

    if (NULL!=m_pfnDestroy)
        (*m_pfnDestroy)();

    delete this;
    return 0;
    }





/*
 * CKoala::GetUnmarshalClass
 *
 * Purpose:
 *  Determines the class of object to be used to create an
 *  uninitalized proxy in the unmarshaling process.
 *
 * Parameters:
 *  riid            REFIID of the interface to be marshaled.
 *  pv              LPVOID to the interface to be marshaled.
 *  dwCtx           DWORD specifying the relation of the processes
 *                  between which the marshaling is occuring, from the
 *                  MSHCTX enumeration.
 *  pvCtx           LPVOID Reserved for future MSHCTX values.
 *  dwFlags         DWORD specifying why marshaling is taking place.
 *  pClsID          LPCLSID in which to store the proxy CLSID.
 */

STDMETHODIMP CKoala::GetUnmarshalClass(REFIID riid
    , LPVOID pv, DWORD dwCtx, LPVOID pvCtx, DWORD dwFlags
    , LPCLSID pClsID)
    {
   #ifdef WIN32
    /*
     * If the context is on a different machine we cannot use
     * our custom marshaling based on SendMessage.
     */
    if (dwCtx & MSHCTX_DIFFERENTMACHINE)
        return ResultFromScode(E_FAIL);
   #endif

    //Same proxy for all interfaces.
    *pClsID=CLSID_KoalaProxy;
    return NOERROR;
    }




/*
 * CKoala::GetMarshalSizeMax
 *
 * Purpose:
 *  Returns the upper memory bound needed to write data into a stream
 *  for IMarshal::MarshalInterface.
 *
 * Parameters:
 *  riid            REFIID of the interface to be marshaled.
 *  pv              LPVOID of the interface to be marshaled.
 *  dwDestCtx       DWORD with the destination context from MSHCTX.
 *  pvDestCtx       LPVOID reserved for future MSHCTX flags.
 *  dwFlags         DWORD specifying why marshaling is taking place.
 *  pdwSize         LPDWORD in which the size is returned.
 */

STDMETHODIMP CKoala::GetMarshalSizeMax(REFIID riid, LPVOID pv
    , DWORD dwDestCtx, LPVOID pvDestCtx, DWORD dwFlags
    , LPDWORD pdwSize)
    {
   #ifdef WIN32
    if (dwDestCtx & MSHCTX_DIFFERENTMACHINE)
        return ResultFromScode(E_FAIL);
   #endif

    *pdwSize=sizeof(KOALAMARSHAL);
    return NOERROR;
    }





/*
 * CKoala::MarshalInterface
 *
 * Purpose:
 *  Stores a marshaling packet in a stream for use by a client-side
 *  proxy.
 *
 * Parameters:
 *  pStm            LPSTREAM into which to marshal the interface.
 *  riid            REFIID of the interface to be marshaled.
 *  pv              LPVOID of the interface to be marshaled.
 *  dwDestCtx       DWORD with the destination context from MSHCTX.
 *  pvDestCtx       LPVOID reserved for future MSHCTX flags.
 *  dwFlags         DWORD specifying why marshaling is taking place.
 */

STDMETHODIMP CKoala::MarshalInterface(LPSTREAM pstm
    , REFIID riid, LPVOID pv, DWORD dwDestCtx, LPVOID pvDestCtx
    , DWORD dwFlags)
    {
    KOALAMARSHAL        km;

   #ifdef WIN32
    if (dwDestCtx & MSHCTX_DIFFERENTMACHINE)
        return ResultFromScode(E_FAIL);
   #endif

    //Proxy only needs to know where to send messages
    km.hWnd=m_hWnd;

    //This is for the client who will call Release when needed
    AddRef();

    //Write the marshaling packet to the stream
    return pstm->Write((void *)&km, sizeof(KOALAMARSHAL), NULL);
    }





/*
 * CKoala::UnmarshalInterface
 *
 * Purpose:
 *  Initializes a newly created proxy the marshaling packet in
 *  the stream created in the server-side implementation of
 *  MarshalInterface.  This is the primary member of this interface
 *  used on the client side proxy.
 *
 * Parameters:
 *  pStm            LPSTREAM to the stream containing marshal
 *                  data.
 *  riid            REFIID of the interface to be marshaled.
 *  pv              LPVOID of the interface to be marshaled.
 */

STDMETHODIMP CKoala::UnmarshalInterface(LPSTREAM pstm
    , REFIID riid, LPVOID *pv)
    {
    //No need to implement on server side
    return ResultFromScode(E_NOTIMPL);
    }






/*
 * CKoala::ReleaseMarshalData
 *
 * Purpose:
 *  Destroy a marshaled data packet, client-side only.
 *
 * Parameters:
 *  pStm            LPSTREAM containing the data to release.
 */

STDMETHODIMP CKoala::ReleaseMarshalData(LPSTREAM pstm)
    {
    //Client-side function
    return ResultFromScode(E_NOTIMPL);
    }






/*
 * CKoala::Disconnect
 *
 * Purpose:
 *  Instructs an object with custom marshaling that it's being
 *  disconnected.
 *
 * Parameters:
 *  dwReserved      DWORD reserved.
 */

STDMETHODIMP CKoala::DisconnectObject(DWORD dwReserved)
    {
    /*
     * This is generated from within CoDisconnectObject, which
     * our server doesn't call itself.  This would give the object
     * a chance to close its connection and cleanup before going
     * away since the proxy will no longer be calling it.
     * This should also be used to block any additional calls
     * made after this point.
     */

    return NOERROR;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -