dynamic vtable sink.cpp
上传用户:bjlvip
上传日期:2010-02-08
资源大小:744k
文件大小:4k
源码类别:

Windows编程

开发平台:

Visual C++

  1. // client.cpp
  2. #define _WIN32_DCOM
  3. #include <olectl.h>
  4. #include <conio.h>
  5. #include <iostream.h>
  6. #include "Componentcomponent.h"
  7. // This sink can implement any interface at runtime
  8. // In C++, struct == public class
  9. struct CStink // class for the generic sink object
  10. {
  11. // The First item must be a pointer to the vtbl of the sink object
  12. // Here we can see the binary standard that defines COM
  13. void (__stdcall **pVtbl)(); // Declared as a pointer to one or more function pointers
  14. // Next comes the object's data
  15. long m_cRef; // reference counting variable
  16. };
  17. // Non-static methods in a class always have an implicit 'this' argument that points to the current object
  18. // Since these methods are not part of a class we make beleive...
  19. // Every method in the interface must pretend to have a 'this' argument as all callers will provide it
  20. ULONG __stdcall CStink_AddRef(CStink* me)
  21. {
  22. // me is a stand-in for 'this', a reserved keyword in C++
  23. // Everything must be explicitly accessed through the pointer to the object
  24. // Now we can appreciate what C++ does automatically
  25. return ++me->m_cRef;
  26. }
  27. ULONG __stdcall CStink_Release(CStink* me)
  28. {
  29. if(--me->m_cRef != 0)
  30. return me->m_cRef;
  31. delete me; // We can even use delete
  32. return 0;
  33. }
  34. HRESULT __stdcall CStink_QueryInterface(CStink* me, REFIID riid, void** ppv)
  35. {
  36. if(riid == IID_IUnknown || riid == IID_IOutGoing)
  37. *ppv = &me->pVtbl; // Here's a pointer to our interface
  38. else 
  39. {
  40. *ppv = NULL;
  41. return E_NOINTERFACE;
  42. }
  43. CStink_AddRef(me);
  44. return S_OK;
  45. }
  46. // This method could be generated dynamically based on type information
  47. HRESULT __stdcall GotMessage(CStink *me, int Message)
  48. {
  49. MessageBeep(MB_OK);
  50. cout << "StinkGotMessage() is " << (char)Message << endl;
  51. return S_OK;
  52. }
  53. void main()
  54. {
  55. cout << "Client: Calling CoInitialize()" << endl;
  56. CoInitializeEx(NULL, COINIT_MULTITHREADED);
  57. IUnknown* pUnknown;
  58. cout << "Client: Calling CoCreateInstance() " << endl;
  59. CoCreateInstance(CLSID_InsideCOM, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&pUnknown);
  60. IConnectionPointContainer* pConnectionPointContainer;
  61. HRESULT hr = pUnknown->QueryInterface(IID_IConnectionPointContainer, (void**)&pConnectionPointContainer);
  62. if(FAILED(hr))
  63. cout << "Not a connectable object, going to crash now" << endl;
  64. IConnectionPoint* pConnectionPoint;
  65. hr = pConnectionPointContainer->FindConnectionPoint(IID_IOutGoing, &pConnectionPoint);
  66. cout << "FindConnectionPoint returns " << hr << " pConnectionPoint = " << pConnectionPoint << endl;
  67. // Instantiate the object, sort of...
  68. CStink* mySink = new CStink;
  69. int num_methods = 4; // 3 for IUnknown + number of methods in outgoing interfaces
  70. // Allocate memory for the vtbl and cast the returned void* to a pointer to a bunch of funcion pointers
  71. void (__stdcall **IStink)() = (void (__stdcall **)())CoTaskMemAlloc(num_methods * sizeof(void*)); // 4 bytes per pointer
  72. // Initialize the vtbl to point to our implementations
  73. // These three always come first! (in this order)
  74. *(IStink + 0) = (void (__stdcall *)())CStink_QueryInterface;
  75. *(IStink + 1) = (void (__stdcall *)())CStink_AddRef;
  76. *(IStink + 2) = (void (__stdcall *)())CStink_Release;
  77. // Now add any additional methods to the vtbl based on the available type 
  78. // information for the outgoing interface
  79. *(IStink + 3) = (void (__stdcall *)())GotMessage; // IOutGoing only has one additional method
  80. // Give the sink a brain
  81. mySink->pVtbl = IStink;
  82. // Initialize the sink's reference counter
  83. mySink->m_cRef = 0;
  84. DWORD dwCookie;
  85. hr = pConnectionPoint->Advise((IUnknown*)mySink, &dwCookie);
  86. cout << "Client: IConnectionPoint::Advise returned " << hr << endl;
  87. cout << "Press any key to exit" << endl;
  88. _getch();
  89. pConnectionPoint->Unadvise(dwCookie);
  90. // Now free the vtbl, the has probably already deleted itself
  91. CoTaskMemFree(IStink);
  92. pConnectionPoint->Release();
  93. pConnectionPointContainer->Release();
  94. cout << "Client: Calling Release() for pUnknown" << endl;
  95. hr = pUnknown->Release();
  96. cout << "Client: Calling CoUninitialize()" << endl;
  97. CoUninitialize();
  98. }