Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.0 KiB

  1. #ifndef _UNK_H_
  2. #define _UNK_H_
  3. #include <objbase.h>
  4. typedef void (*COMFACTORYCB)(BOOL fIncrement);
  5. class CCOMBase
  6. {
  7. public:
  8. virtual HRESULT UnkInit() { return S_OK; }
  9. };
  10. struct INTFMAPENTRY
  11. {
  12. const IID* piid;
  13. DWORD dwOffset;
  14. };
  15. template <class CCOMBASE>
  16. class CUnkTmpl : public CCOMBASE
  17. {
  18. public:
  19. CUnkTmpl(IUnknown*) : _cRef(1) {}
  20. ~CUnkTmpl() { if (_cfcb) { _cfcb(FALSE); } }
  21. STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
  22. {
  23. HRESULT hres;
  24. if (IID_IUnknown == riid)
  25. {
  26. IUnknown* punk;
  27. *ppv = (IUnknown*)(((PBYTE)this) + _pintfmap[0].dwOffset);
  28. punk = (IUnknown*)(*ppv);
  29. punk->AddRef();
  30. hres = S_OK;
  31. }
  32. else
  33. {
  34. hres = _GetInterfaceFromMap(riid, ppv);
  35. }
  36. return hres;
  37. }
  38. STDMETHODIMP_(ULONG) AddRef() { return ::InterlockedIncrement((LONG*)&_cRef); }
  39. STDMETHODIMP_(ULONG) Release()
  40. {
  41. ULONG cRef = ::InterlockedDecrement((LONG*)&_cRef);
  42. if (!cRef)
  43. {
  44. delete this;
  45. }
  46. return cRef;
  47. }
  48. protected:
  49. HRESULT _GetInterfaceFromMap(REFIID riid, void** ppv)
  50. {
  51. HRESULT hres = E_NOINTERFACE;
  52. for (DWORD dw = 0; dw < _cintfmap; ++dw)
  53. {
  54. if (riid == *(_pintfmap[dw].piid))
  55. {
  56. IUnknown* punk = (IUnknown*)(((PBYTE)this) +
  57. _pintfmap[dw].dwOffset);
  58. punk->AddRef();
  59. *ppv = punk;
  60. hres = S_OK;
  61. break;
  62. }
  63. }
  64. return hres;
  65. }
  66. public:
  67. static HRESULT UnkCreateInstance(COMFACTORYCB cfcb,
  68. IUnknown* pUnknownOuter, IUnknown** ppunkNew)
  69. {
  70. HRESULT hres = E_OUTOFMEMORY;
  71. if (!_cfcb)
  72. {
  73. _cfcb = cfcb;
  74. }
  75. CUnkTmpl<CCOMBASE>* pNew = new CUnkTmpl<CCOMBASE>(pUnknownOuter);
  76. if (pNew)
  77. {
  78. hres = pNew->UnkInit();
  79. if (FAILED(hres))
  80. {
  81. delete pNew;
  82. }
  83. else
  84. {
  85. *ppunkNew = (IUnknown*)(((PBYTE)pNew) +
  86. pNew->_pintfmap[0].dwOffset);
  87. }
  88. }
  89. return hres;
  90. }
  91. private:
  92. ULONG _cRef;
  93. static COMFACTORYCB _cfcb;
  94. static const INTFMAPENTRY* _pintfmap;
  95. static const DWORD _cintfmap;
  96. };
  97. // for now: begin
  98. #ifndef OFFSETOFCLASS
  99. //*** OFFSETOFCLASS -- (stolen from ATL)
  100. // we use STATIC_CAST not SAFE_CAST because the compiler gets confused
  101. // (it doesn't constant-fold the ,-op in SAFE_CAST so we end up generating
  102. // code for the table!)
  103. #define OFFSETOFCLASS(base, derived) \
  104. ((DWORD)(DWORD_PTR)(static_cast<base*>((derived*)8))-8)
  105. #endif
  106. // for now: end
  107. #define _INTFMAPENTRY(Cthis, Ifoo) \
  108. { (IID*) &IID_##Ifoo, OFFSETOFCLASS(Ifoo, Cthis) }
  109. #define _INTFMAPENTRY2(Cthis, Ifoo, Iimpl) \
  110. { (IID*) &IID_##Ifoo, OFFSETOFCLASS(Iimpl, Cthis) }
  111. #endif // _UNK_H_