[SHELL32]
[reactos.git] / reactos / include / reactos / shellutils.h
1 /*
2 * Copyright 1999, 2000 Juergen Schmied
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #ifndef __ROS_SHELL_UTILS_H
20 #define __ROS_SHELL_UTILS_H
21
22 #ifdef __cplusplus
23 extern "C" {
24 #endif /* defined(__cplusplus) */
25
26 #ifdef __cplusplus
27 # define IID_PPV_ARG(Itype, ppType) IID_##Itype, reinterpret_cast<void**>((static_cast<Itype**>(ppType)))
28 # define IID_NULL_PPV_ARG(Itype, ppType) IID_##Itype, NULL, reinterpret_cast<void**>((static_cast<Itype**>(ppType)))
29 #else
30 # define IID_PPV_ARG(Itype, ppType) IID_##Itype, (void**)(ppType)
31 # define IID_NULL_PPV_ARG(Itype, ppType) IID_##Itype, NULL, (void**)(ppType)
32 #endif
33
34 #if 1
35 #define FAILED_UNEXPECTEDLY(hr) (FAILED(hr) && (Win32DbgPrint(__FILE__, __LINE__, "Unexpected failure %08x.\n", hr), TRUE))
36 #else
37 #define FAILED_UNEXPECTEDLY(hr) FAILED(hr)
38 #endif
39
40 #ifdef __cplusplus
41 } /* extern "C" */
42 #endif /* defined(__cplusplus) */
43
44 #ifdef __cplusplus
45 template <typename T>
46 class CComCreatorCentralInstance
47 {
48 private:
49 static IUnknown *s_pInstance;
50 static bool s_IsTerminated;
51
52 public:
53 static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
54 {
55 *ppv = NULL;
56 if (pv != NULL)
57 return CLASS_E_NOAGGREGATION;
58 if (!s_pInstance)
59 {
60 PVOID pObj;
61 HRESULT hr;
62 s_IsTerminated = true;
63 hr = ATL::CComCreator< T >::CreateInstance(NULL, IID_IUnknown, &pObj);
64 if (FAILED(hr))
65 {
66 s_IsTerminated = false;
67 return hr;
68 }
69 if (InterlockedCompareExchangePointer((PVOID *)&s_pInstance, pObj, NULL))
70 static_cast<IUnknown *>(pObj)->Release();
71 s_IsTerminated = false;
72 }
73 return s_pInstance->QueryInterface(riid, ppv);
74 }
75 static void Term()
76 {
77 ULONG ref;
78 #ifdef ASSERT
79 ASSERT(!s_IsTerminated);
80 #endif
81 s_IsTerminated = true;
82 if (s_pInstance)
83 {
84 ref = s_pInstance->Release();
85 #ifdef ASSERT
86 ASSERT(ref == 0);
87 #endif
88 s_pInstance = NULL;
89 }
90 }
91 static bool IsTerminated() { return s_IsTerminated; }
92 };
93
94 template <typename T>
95 IUnknown *CComCreatorCentralInstance<T>::s_pInstance = NULL;
96
97 template <typename T>
98 bool CComCreatorCentralInstance<T>::s_IsTerminated = false;
99
100 #define DECLARE_CENTRAL_INSTANCE_NOT_AGGREGATABLE(x) \
101 public: \
102 typedef CComCreatorCentralInstance< ATL::CComObject<x> > _CreatorClass;
103 #endif
104
105 #ifdef __cplusplus
106 template <class Base>
107 class CComDebugObject : public Base
108 {
109 public:
110 CComDebugObject(void * = NULL)
111 {
112 #if DEBUG_CCOMOBJECT_CREATION
113 DbgPrint("%S, this=%08p\n", __FUNCTION__, static_cast<Base*>(this));
114 #endif
115 _pAtlModule->Lock();
116 }
117
118 virtual ~CComDebugObject()
119 {
120 this->FinalRelease();
121 _pAtlModule->Unlock();
122 }
123
124 STDMETHOD_(ULONG, AddRef)()
125 {
126 int rc = this->InternalAddRef();
127 #if DEBUG_CCOMOBJECT_REFCOUNTING
128 DbgPrint("%s, RefCount is now %d(--)! \n", __FUNCTION__, rc);
129 #endif
130 return rc;
131 }
132
133 STDMETHOD_(ULONG, Release)()
134 {
135 int rc = this->InternalRelease();
136
137 #if DEBUG_CCOMOBJECT_REFCOUNTING
138 DbgPrint("%s, RefCount is now %d(--)! \n", __FUNCTION__, rc);
139 #endif
140
141 if (rc == 0)
142 {
143 #if DEBUG_CCOMOBJECT_DESTRUCTION
144 DbgPrint("%s, RefCount reached 0 Deleting!\n", __FUNCTION__);
145 #endif
146 delete this;
147 }
148 return rc;
149 }
150
151 STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
152 {
153 return this->_InternalQueryInterface(iid, ppvObject);
154 }
155
156 static HRESULT WINAPI CreateInstance(CComDebugObject<Base> **pp)
157 {
158 CComDebugObject<Base> *newInstance;
159 HRESULT hResult;
160
161 ATLASSERT(pp != NULL);
162 if (pp == NULL)
163 return E_POINTER;
164
165 hResult = E_OUTOFMEMORY;
166 newInstance = NULL;
167 ATLTRY(newInstance = new CComDebugObject<Base>());
168 if (newInstance != NULL)
169 {
170 newInstance->SetVoid(NULL);
171 newInstance->InternalFinalConstructAddRef();
172 hResult = newInstance->_AtlInitialConstruct();
173 if (SUCCEEDED(hResult))
174 hResult = newInstance->FinalConstruct();
175 if (SUCCEEDED(hResult))
176 hResult = newInstance->_AtlFinalConstruct();
177 newInstance->InternalFinalConstructRelease();
178 if (hResult != S_OK)
179 {
180 delete newInstance;
181 newInstance = NULL;
182 }
183 }
184 *pp = newInstance;
185 return hResult;
186 }
187 };
188
189 #ifdef DEBUG_CCOMOBJECT
190 # define _CComObject CComDebugObject
191 #else
192 # define _CComObject CComObject
193 #endif
194
195 template<class T>
196 void ReleaseCComPtrExpectZero(CComPtr<T>& cptr, BOOL forceRelease = FALSE)
197 {
198 if (cptr.p != NULL)
199 {
200 int nrc = cptr->Release();
201 if (nrc > 0)
202 {
203 DbgPrint("WARNING: Unexpected RefCount > 0 (%d)!\n", nrc);
204 if (forceRelease)
205 {
206 while (nrc > 0)
207 {
208 nrc = cptr->Release();
209 }
210 }
211 }
212 cptr.Detach();
213 }
214 }
215
216 template<class T, class R>
217 HRESULT inline ShellDebugObjectCreator(REFIID riid, R ** ppv)
218 {
219 CComPtr<T> obj;
220 HRESULT hResult;
221
222 if (ppv == NULL)
223 return E_POINTER;
224 *ppv = NULL;
225 ATLTRY(obj = new CComDebugObject<T>);
226 if (obj.p == NULL)
227 return E_OUTOFMEMORY;
228 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
229 if (FAILED(hResult))
230 return hResult;
231 return S_OK;
232 }
233
234 template<class T, class R>
235 HRESULT inline ShellObjectCreator(REFIID riid, R ** ppv)
236 {
237 CComPtr<T> obj;
238 HRESULT hResult;
239
240 if (ppv == NULL)
241 return E_POINTER;
242 *ppv = NULL;
243 ATLTRY(obj = new _CComObject<T>);
244 if (obj.p == NULL)
245 return E_OUTOFMEMORY;
246 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
247 if (FAILED(hResult))
248 return hResult;
249 return S_OK;
250 }
251
252 template<class T, class R>
253 HRESULT inline ShellObjectCreatorInit(REFIID riid, R ** ppv)
254 {
255 CComPtr<T> obj;
256 CComPtr<R> result;
257 HRESULT hResult;
258
259 if (ppv == NULL)
260 return E_POINTER;
261 *ppv = NULL;
262 ATLTRY(obj = new _CComObject<T>);
263 if (obj.p == NULL)
264 return E_OUTOFMEMORY;
265 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
266 if (FAILED(hResult))
267 return hResult;
268
269 hResult = obj->Initialize();
270 if (FAILED(hResult))
271 return hResult;
272
273 *ppv = result.Detach();
274
275 return S_OK;
276 }
277
278 template<class T>
279 HRESULT inline ShellObjectCreatorInit(REFIID riid, void ** ppv)
280 {
281 CComPtr<T> obj;
282 CComPtr<IUnknown> result;
283 HRESULT hResult;
284
285 if (ppv == NULL)
286 return E_POINTER;
287 *ppv = NULL;
288 ATLTRY(obj = new _CComObject<T>);
289 if (obj.p == NULL)
290 return E_OUTOFMEMORY;
291 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
292 if (FAILED(hResult))
293 return hResult;
294
295 hResult = obj->Initialize();
296 if (FAILED(hResult))
297 return hResult;
298
299 *ppv = result.Detach();
300
301 return S_OK;
302 }
303
304 template<class T, class T1>
305 HRESULT inline ShellObjectCreatorInit(T1 initArg1, REFIID riid, void ** ppv)
306 {
307 CComPtr<T> obj;
308 HRESULT hResult;
309
310 if (ppv == NULL)
311 return E_POINTER;
312 *ppv = NULL;
313 ATLTRY(obj = new _CComObject<T>);
314 if (obj.p == NULL)
315 return E_OUTOFMEMORY;
316 hResult = obj->QueryInterface(riid, ppv);
317 if (FAILED(hResult))
318 return hResult;
319
320 hResult = obj->Initialize(initArg1);
321 if (FAILED(hResult))
322 return hResult;
323
324 return S_OK;
325 }
326
327 template<class T, class T1, class T2>
328 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, REFIID riid, void ** ppv)
329 {
330 CComPtr<T> obj;
331 HRESULT hResult;
332
333 if (ppv == NULL)
334 return E_POINTER;
335 *ppv = NULL;
336 ATLTRY(obj = new _CComObject<T>);
337 if (obj.p == NULL)
338 return E_OUTOFMEMORY;
339 hResult = obj->QueryInterface(riid, ppv);
340 if (FAILED(hResult))
341 return hResult;
342
343 hResult = obj->Initialize(initArg1, initArg2);
344 if (FAILED(hResult))
345 return hResult;
346
347 return S_OK;
348 }
349
350 template<class T, class T1, class T2, class T3>
351 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, REFIID riid, void ** ppv)
352 {
353 CComPtr<T> obj;
354 HRESULT hResult;
355
356 if (ppv == NULL)
357 return E_POINTER;
358 *ppv = NULL;
359 ATLTRY(obj = new _CComObject<T>);
360 if (obj.p == NULL)
361 return E_OUTOFMEMORY;
362 hResult = obj->QueryInterface(riid, ppv);
363 if (FAILED(hResult))
364 return hResult;
365
366 hResult = obj->Initialize(initArg1, initArg2, initArg3);
367 if (FAILED(hResult))
368 return hResult;
369
370 return S_OK;
371 }
372
373 template<class T, class T1, class R>
374 HRESULT inline ShellObjectCreatorInit(T1 initArg1, REFIID riid, R ** ppv)
375 {
376 CComPtr<T> obj;
377 CComPtr<R> result;
378 HRESULT hResult;
379
380 if (ppv == NULL)
381 return E_POINTER;
382 *ppv = NULL;
383 ATLTRY(obj = new _CComObject<T>);
384 if (obj.p == NULL)
385 return E_OUTOFMEMORY;
386 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
387 if (FAILED(hResult))
388 return hResult;
389
390 hResult = obj->Initialize(initArg1);
391 if (FAILED(hResult))
392 return hResult;
393
394 *ppv = result.Detach();
395
396 return S_OK;
397 }
398
399 template<class T, class T1, class T2, class R>
400 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, REFIID riid, R ** ppv)
401 {
402 CComPtr<T> obj;
403 CComPtr<R> result;
404 HRESULT hResult;
405
406 if (ppv == NULL)
407 return E_POINTER;
408 *ppv = NULL;
409 ATLTRY(obj = new _CComObject<T>);
410 if (obj.p == NULL)
411 return E_OUTOFMEMORY;
412 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
413 if (FAILED(hResult))
414 return hResult;
415
416 hResult = obj->Initialize(initArg1, initArg2);
417 if (FAILED(hResult))
418 return hResult;
419
420 *ppv = result.Detach();
421
422 return S_OK;
423 }
424
425 template<class T, class T1, class T2, class T3, class R>
426 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, REFIID riid, R ** ppv)
427 {
428 CComPtr<T> obj;
429 CComPtr<R> result;
430 HRESULT hResult;
431
432 if (ppv == NULL)
433 return E_POINTER;
434 *ppv = NULL;
435 ATLTRY(obj = new _CComObject<T>);
436 if (obj.p == NULL)
437 return E_OUTOFMEMORY;
438 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
439 if (FAILED(hResult))
440 return hResult;
441
442 hResult = obj->Initialize(initArg1, initArg2, initArg3);
443 if (FAILED(hResult))
444 return hResult;
445
446 *ppv = result.Detach();
447
448 return S_OK;
449 }
450
451 template<class T, class T1, class T2, class T3, class T4, class R>
452 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, T4 initArg4, REFIID riid, R ** ppv)
453 {
454 CComPtr<T> obj;
455 CComPtr<R> result;
456 HRESULT hResult;
457
458 if (ppv == NULL)
459 return E_POINTER;
460 *ppv = NULL;
461 ATLTRY(obj = new _CComObject<T>);
462 if (obj.p == NULL)
463 return E_OUTOFMEMORY;
464 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
465 if (FAILED(hResult))
466 return hResult;
467
468 hResult = obj->Initialize(initArg1, initArg2, initArg3, initArg4);
469 if (FAILED(hResult))
470 return hResult;
471
472 *ppv = result.Detach();
473
474 return S_OK;
475 }
476
477 template<class T, class T1, class T2, class T3, class T4, class T5, class R>
478 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, T4 initArg4, T5 initArg5, REFIID riid, R ** ppv)
479 {
480 CComPtr<T> obj;
481 CComPtr<R> result;
482 HRESULT hResult;
483
484 if (ppv == NULL)
485 return E_POINTER;
486 *ppv = NULL;
487 ATLTRY(obj = new _CComObject<T>);
488 if (obj.p == NULL)
489 return E_OUTOFMEMORY;
490 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
491 if (FAILED(hResult))
492 return hResult;
493
494 hResult = obj->Initialize(initArg1, initArg2, initArg3, initArg4, initArg5);
495 if (FAILED(hResult))
496 return hResult;
497
498 *ppv = result.Detach();
499
500 return S_OK;
501 }
502 #endif /* __cplusplus */
503
504 #endif /* __ROS_SHELL_UTILS_H */