/* ReactOS Kernel-Mode COM IUnknown implementations This file is in the public domain. AUTHORS Andrew Greenwood */ #ifndef STDUNK_H #define STDUNK_H #include /* =============================================================== INonDelegatingUnknown interface */ DECLARE_INTERFACE(INonDelegatingUnknown) { STDMETHOD_(NTSTATUS, NonDelegatingQueryInterface)( THIS_ IN REFIID, OUT PVOID*) PURE; STDMETHOD_(ULONG, NonDelegatingAddRef)( THIS ) PURE; STDMETHOD_(ULONG, NonDelegatingRelease)( THIS ) PURE; }; typedef INonDelegatingUnknown *PNONDELEGATINGUNKNOWN; /* =============================================================== CUnknown declaration / definition There are 2 variants for this, and I'm not sure if the C version is correct. */ #ifdef __cplusplus class CUnknown : public INonDelegatingUnknown { private : LONG m_ref_count; PUNKNOWN m_outer_unknown; public : /* CUnknown */ CUnknown(PUNKNOWN pUnknownOuter); virtual ~CUnknown(); PUNKNOWN GetOuterUnknown() { return m_outer_unknown; } /* INonDelegatingUnknown */ STDMETHODIMP_(ULONG) NonDelegatingAddRef(); STDMETHODIMP_(ULONG) NonDelegatingRelease(); STDMETHODIMP_(NTSTATUS) NonDelegatingQueryInterface( REFIID rIID, PVOID* ppVoid); }; #define DECLARE_STD_UNKNOWN() \ STDMETHODIMP_(NTSTATUS) NonDelegatingQueryInterface( \ REFIID iid, \ PVOID* ppvObject); \ \ STDMETHODIMP_(NTSTATUS) QueryInterface( \ REFIID riid, \ void** ppv) \ { \ return GetOuterUnknown()->QueryInterface(riid, ppv); \ } \ \ STDMETHODIMP_(ULONG) AddRef() \ { \ return GetOuterUnknown()->AddRef(); \ } \ \ STDMETHODIMP_(ULONG) Release() \ { \ return GetOuterUnknown()->Release(); \ } #define DEFINE_STD_CONSTRUCTOR(classname) \ classname(PUNKNOWN outer_unknown) \ : CUnknown(outer_unknown) \ { } #else /* Not C++ - this is probably very buggy... */ NTSTATUS STDMETHODCALLTYPE Unknown_QueryInterface( IUnknown* this, IN REFIID refiid, OUT PVOID* output); ULONG STDMETHODCALLTYPE Unknown_AddRef( IUnknown* unknown_this); ULONG STDMETHODCALLTYPE Unknown_Release( IUnknown* unknown_this); typedef struct CUnknown { __GNU_EXTENSION union { IUnknown IUnknown; INonDelegatingUnknown INonDelegatingUnknown; }; LONG m_ref_count; PUNKNOWN m_outer_unknown; } CUnknown; #endif /* __cplusplus */ #ifdef __cplusplus /* =============================================================== Construction helpers */ #define QICAST(typename) \ PVOID( (typename) (this) ) #define QICASTUNKNOWN(typename) \ PVOID( PUNKNOWN( (typename) (this) ) ) #define STD_CREATE_BODY_WITH_TAG_(classname, unknown, outer_unknown, pool_type, tag, base) \ classname *new_ptr = new(pool_type, tag) classname(outer_unknown); \ \ if ( ! new_ptr ) \ return STATUS_INSUFFICIENT_RESOURCES; \ \ *unknown = PUNKNOWN((base)(new_ptr)); \ (*unknown)->AddRef(); \ return STATUS_SUCCESS #define STD_CREATE_BODY_WITH_TAG(classname, unknown, outer_unknown, pool_type, tag, base) \ STD_CREATE_BODY_WITH_TAG_(classname, unknown, outer_unknown, pool_type, tag, PUNKNOWN) #define STD_CREATE_BODY_(classname, unknown, outer_unknown, pool_type, base) \ STD_CREATE_BODY_WITH_TAG_(classname, unknown, outer_unknown, pool_type, 'rCcP', base) #define STD_CREATE_BODY(classname, unknown, outer_unknown, pool_type) \ STD_CREATE_BODY_(classname, unknown, outer_unknown, pool_type, PUNKNOWN) /* =============================================================== Custom "new" and "delete" C++ operators */ #ifndef _NEW_DELETE_OPERATORS_ #define _NEW_DELETE_OPERATORS_ inline PVOID KCOM_New( size_t size, POOL_TYPE pool_type, ULONG tag) { PVOID result; result = ExAllocatePoolWithTag(pool_type, size, tag); if ( result ) RtlZeroMemory(result, size); return result; } inline PVOID operator new ( size_t size, POOL_TYPE pool_type) { return KCOM_New(size, pool_type, 'wNcP'); } inline PVOID operator new ( size_t size, POOL_TYPE pool_type, ULONG tag) { return KCOM_New(size, pool_type, tag); } inline void __cdecl operator delete( PVOID ptr) { ExFreePool(ptr); } inline void __cdecl operator delete( PVOID ptr, UINT_PTR) { ExFreePool(ptr); } #endif /* _NEW_DELETE_OPERATORS_ */ #else /* Being compiled with C */ #endif /* __cplusplus */ #endif /* include guard */