master
  1/*
  2    ReactOS Kernel-Mode COM
  3    IUnknown implementations
  4
  5    This file is in the public domain.
  6
  7    AUTHORS
  8        Andrew Greenwood
  9*/
 10
 11#ifndef STDUNK_H
 12#define STDUNK_H
 13
 14#include <punknown.h>
 15
 16/* ===============================================================
 17    INonDelegatingUnknown interface
 18*/
 19
 20DECLARE_INTERFACE(INonDelegatingUnknown)
 21{
 22    STDMETHOD_(NTSTATUS, NonDelegatingQueryInterface)( THIS_
 23        IN  REFIID,
 24        OUT PVOID*) PURE;
 25
 26    STDMETHOD_(ULONG, NonDelegatingAddRef)( THIS ) PURE;
 27    STDMETHOD_(ULONG, NonDelegatingRelease)( THIS ) PURE;
 28};
 29
 30typedef INonDelegatingUnknown *PNONDELEGATINGUNKNOWN;
 31
 32
 33/* ===============================================================
 34    CUnknown declaration / definition
 35
 36    There are 2 variants for this, and I'm not sure if the C
 37    version is correct.
 38*/
 39
 40#ifdef __cplusplus
 41
 42class CUnknown : public INonDelegatingUnknown
 43{
 44    private :
 45        LONG m_ref_count;
 46        PUNKNOWN m_outer_unknown;
 47
 48    public :
 49        /* CUnknown */
 50        CUnknown(PUNKNOWN pUnknownOuter);
 51        virtual ~CUnknown();
 52
 53        PUNKNOWN GetOuterUnknown()
 54        { return m_outer_unknown; }
 55
 56        /* INonDelegatingUnknown */
 57        STDMETHODIMP_(ULONG) NonDelegatingAddRef();
 58        STDMETHODIMP_(ULONG) NonDelegatingRelease();
 59
 60        STDMETHODIMP_(NTSTATUS) NonDelegatingQueryInterface(
 61            REFIID  rIID,
 62            PVOID* ppVoid);
 63};
 64
 65#define DECLARE_STD_UNKNOWN() \
 66    STDMETHODIMP_(NTSTATUS) NonDelegatingQueryInterface( \
 67        REFIID iid, \
 68        PVOID* ppvObject); \
 69\
 70    STDMETHODIMP_(NTSTATUS) QueryInterface( \
 71        REFIID riid, \
 72        void** ppv) \
 73    { \
 74        return GetOuterUnknown()->QueryInterface(riid, ppv); \
 75    } \
 76\
 77    STDMETHODIMP_(ULONG) AddRef() \
 78    { \
 79        return GetOuterUnknown()->AddRef(); \
 80    } \
 81\
 82    STDMETHODIMP_(ULONG) Release() \
 83    { \
 84        return GetOuterUnknown()->Release(); \
 85    }
 86
 87#define DEFINE_STD_CONSTRUCTOR(classname) \
 88    classname(PUNKNOWN outer_unknown) \
 89    : CUnknown(outer_unknown) \
 90    { }
 91
 92#else   /* Not C++ - this is probably very buggy... */
 93
 94NTSTATUS
 95STDMETHODCALLTYPE
 96Unknown_QueryInterface(
 97    IUnknown* this,
 98    IN  REFIID refiid,
 99    OUT PVOID* output);
100
101ULONG
102STDMETHODCALLTYPE
103Unknown_AddRef(
104    IUnknown* unknown_this);
105
106ULONG
107STDMETHODCALLTYPE
108Unknown_Release(
109    IUnknown* unknown_this);
110
111typedef struct CUnknown
112{
113    __GNU_EXTENSION union
114    {
115        IUnknown IUnknown;
116        INonDelegatingUnknown INonDelegatingUnknown;
117    };
118
119    LONG m_ref_count;
120    PUNKNOWN m_outer_unknown;
121} CUnknown;
122
123#endif  /* __cplusplus */
124
125
126
127#ifdef __cplusplus
128
129
130/* ===============================================================
131    Construction helpers
132*/
133
134#define QICAST(typename) \
135    PVOID( (typename) (this) )
136
137#define QICASTUNKNOWN(typename) \
138    PVOID( PUNKNOWN( (typename) (this) ) )
139
140#define STD_CREATE_BODY_WITH_TAG_(classname, unknown, outer_unknown, pool_type, tag, base) \
141    classname *new_ptr = new(pool_type, tag) classname(outer_unknown); \
142\
143    if ( ! new_ptr ) \
144        return STATUS_INSUFFICIENT_RESOURCES; \
145\
146    *unknown = PUNKNOWN((base)(new_ptr)); \
147    (*unknown)->AddRef(); \
148    return STATUS_SUCCESS
149
150#define STD_CREATE_BODY_WITH_TAG(classname, unknown, outer_unknown, pool_type, tag, base) \
151    STD_CREATE_BODY_WITH_TAG_(classname, unknown, outer_unknown, pool_type, tag, PUNKNOWN)
152
153#define STD_CREATE_BODY_(classname, unknown, outer_unknown, pool_type, base) \
154    STD_CREATE_BODY_WITH_TAG_(classname, unknown, outer_unknown, pool_type, 'rCcP', base)
155
156#define STD_CREATE_BODY(classname, unknown, outer_unknown, pool_type) \
157    STD_CREATE_BODY_(classname, unknown, outer_unknown, pool_type, PUNKNOWN)
158
159
160/* ===============================================================
161    Custom "new" and "delete" C++ operators
162*/
163
164#ifndef _NEW_DELETE_OPERATORS_
165#define _NEW_DELETE_OPERATORS_
166
167inline PVOID
168KCOM_New(
169    size_t size,
170    POOL_TYPE pool_type,
171    ULONG tag)
172{
173    PVOID result;
174
175    result = ExAllocatePoolWithTag(pool_type, size, tag);
176
177    if ( result )
178        RtlZeroMemory(result, size);
179
180    return result;
181}
182
183inline PVOID
184operator new (
185    size_t  size,
186    POOL_TYPE pool_type)
187{
188    return KCOM_New(size, pool_type, 'wNcP');
189}
190
191inline PVOID
192operator new (
193    size_t size,
194    POOL_TYPE pool_type,
195    ULONG tag)
196{
197    return KCOM_New(size, pool_type, tag);
198}
199
200inline void __cdecl
201operator delete(
202    PVOID ptr)
203{
204    ExFreePool(ptr);
205}
206
207#endif  /* ALLOCATION_OPERATORS_DEFINED */
208
209
210#else   /* Being compiled with C */
211
212
213#endif  /* __cplusplus */
214
215#endif  /* include guard */