xref: /reactos/sdk/include/ddk/stdunk.h (revision 58588b76)
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 
20 DECLARE_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 
30 typedef 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 
42 class 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 
94 NTSTATUS
95 STDMETHODCALLTYPE
96 Unknown_QueryInterface(
97     IUnknown* this,
98     IN  REFIID refiid,
99     OUT PVOID* output);
100 
101 ULONG
102 STDMETHODCALLTYPE
103 Unknown_AddRef(
104     IUnknown* unknown_this);
105 
106 ULONG
107 STDMETHODCALLTYPE
108 Unknown_Release(
109     IUnknown* unknown_this);
110 
111 typedef 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 
167 inline PVOID
168 KCOM_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 
183 inline PVOID
184 operator new (
185     size_t  size,
186     POOL_TYPE pool_type)
187 {
188     return KCOM_New(size, pool_type, 'wNcP');
189 }
190 
191 inline PVOID
192 operator new (
193     size_t size,
194     POOL_TYPE pool_type,
195     ULONG tag)
196 {
197     return KCOM_New(size, pool_type, tag);
198 }
199 
200 inline void __cdecl
201 operator delete(
202     PVOID ptr)
203 {
204     ExFreePool(ptr);
205 }
206 
207 inline void __cdecl
208 operator delete(
209     PVOID ptr, UINT_PTR)
210 {
211     ExFreePool(ptr);
212 }
213 
214 #endif  /* _NEW_DELETE_OPERATORS_ */
215 
216 
217 #else   /* Being compiled with C */
218 
219 
220 #endif  /* __cplusplus */
221 
222 #endif  /* include guard */
223