KOALA.CPP
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:10k
源码类别:
Windows编程
开发平台:
Visual C++
- /*
- * 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;
- }