dynamic vtable sink.cpp
上传用户:bjlvip
上传日期:2010-02-08
资源大小:744k
文件大小:4k
源码类别:
Windows编程
开发平台:
Visual C++
- // client.cpp
- #define _WIN32_DCOM
- #include <olectl.h>
- #include <conio.h>
- #include <iostream.h>
- #include "Componentcomponent.h"
- // This sink can implement any interface at runtime
- // In C++, struct == public class
- struct CStink // class for the generic sink object
- {
- // The First item must be a pointer to the vtbl of the sink object
- // Here we can see the binary standard that defines COM
- void (__stdcall **pVtbl)(); // Declared as a pointer to one or more function pointers
- // Next comes the object's data
- long m_cRef; // reference counting variable
- };
- // Non-static methods in a class always have an implicit 'this' argument that points to the current object
- // Since these methods are not part of a class we make beleive...
- // Every method in the interface must pretend to have a 'this' argument as all callers will provide it
- ULONG __stdcall CStink_AddRef(CStink* me)
- {
- // me is a stand-in for 'this', a reserved keyword in C++
- // Everything must be explicitly accessed through the pointer to the object
- // Now we can appreciate what C++ does automatically
- return ++me->m_cRef;
- }
- ULONG __stdcall CStink_Release(CStink* me)
- {
- if(--me->m_cRef != 0)
- return me->m_cRef;
- delete me; // We can even use delete
- return 0;
- }
- HRESULT __stdcall CStink_QueryInterface(CStink* me, REFIID riid, void** ppv)
- {
- if(riid == IID_IUnknown || riid == IID_IOutGoing)
- *ppv = &me->pVtbl; // Here's a pointer to our interface
- else
- {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
- CStink_AddRef(me);
- return S_OK;
- }
- // This method could be generated dynamically based on type information
- HRESULT __stdcall GotMessage(CStink *me, int Message)
- {
- MessageBeep(MB_OK);
- cout << "StinkGotMessage() is " << (char)Message << endl;
- return S_OK;
- }
- void main()
- {
- cout << "Client: Calling CoInitialize()" << endl;
- CoInitializeEx(NULL, COINIT_MULTITHREADED);
- IUnknown* pUnknown;
- cout << "Client: Calling CoCreateInstance() " << endl;
- CoCreateInstance(CLSID_InsideCOM, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pUnknown);
- IConnectionPointContainer* pConnectionPointContainer;
- HRESULT hr = pUnknown->QueryInterface(IID_IConnectionPointContainer, (void**)&pConnectionPointContainer);
- if(FAILED(hr))
- cout << "Not a connectable object, going to crash now" << endl;
- IConnectionPoint* pConnectionPoint;
- hr = pConnectionPointContainer->FindConnectionPoint(IID_IOutGoing, &pConnectionPoint);
- cout << "FindConnectionPoint returns " << hr << " pConnectionPoint = " << pConnectionPoint << endl;
- // Instantiate the object, sort of...
- CStink* mySink = new CStink;
- int num_methods = 4; // 3 for IUnknown + number of methods in outgoing interfaces
- // Allocate memory for the vtbl and cast the returned void* to a pointer to a bunch of funcion pointers
- void (__stdcall **IStink)() = (void (__stdcall **)())CoTaskMemAlloc(num_methods * sizeof(void*)); // 4 bytes per pointer
- // Initialize the vtbl to point to our implementations
- // These three always come first! (in this order)
- *(IStink + 0) = (void (__stdcall *)())CStink_QueryInterface;
- *(IStink + 1) = (void (__stdcall *)())CStink_AddRef;
- *(IStink + 2) = (void (__stdcall *)())CStink_Release;
- // Now add any additional methods to the vtbl based on the available type
- // information for the outgoing interface
- *(IStink + 3) = (void (__stdcall *)())GotMessage; // IOutGoing only has one additional method
- // Give the sink a brain
- mySink->pVtbl = IStink;
- // Initialize the sink's reference counter
- mySink->m_cRef = 0;
- DWORD dwCookie;
- hr = pConnectionPoint->Advise((IUnknown*)mySink, &dwCookie);
- cout << "Client: IConnectionPoint::Advise returned " << hr << endl;
- cout << "Press any key to exit" << endl;
- _getch();
- pConnectionPoint->Unadvise(dwCookie);
- // Now free the vtbl, the has probably already deleted itself
- CoTaskMemFree(IStink);
- pConnectionPoint->Release();
- pConnectionPointContainer->Release();
- cout << "Client: Calling Release() for pUnknown" << endl;
- hr = pUnknown->Release();
- cout << "Client: Calling CoUninitialize()" << endl;
- CoUninitialize();
- }