d89094f18b7eddd9700cabe3f68ad043660deb65
[reactos.git] / reactos / sdk / 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
51 public:
52 static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
53 {
54 *ppv = NULL;
55 if (pv != NULL)
56 return CLASS_E_NOAGGREGATION;
57 if (!s_pInstance)
58 {
59 PVOID pObj;
60 HRESULT hr;
61 hr = ATL::CComCreator< T >::CreateInstance(NULL, IID_IUnknown, &pObj);
62 if (FAILED(hr))
63 return hr;
64 if (InterlockedCompareExchangePointer((PVOID *)&s_pInstance, pObj, NULL))
65 static_cast<IUnknown *>(pObj)->Release();
66 }
67 return s_pInstance->QueryInterface(riid, ppv);
68 }
69 static void Term()
70 {
71 if (s_pInstance)
72 {
73 s_pInstance->Release();
74 s_pInstance = NULL;
75 }
76 }
77 };
78
79 template <typename T>
80 IUnknown *CComCreatorCentralInstance<T>::s_pInstance = NULL;
81
82 #define DECLARE_CENTRAL_INSTANCE_NOT_AGGREGATABLE(x) \
83 public: \
84 typedef CComCreatorCentralInstance< ATL::CComObject<x> > _CreatorClass;
85 #endif
86
87 #ifdef __cplusplus
88 template <class Base>
89 class CComDebugObject : public Base
90 {
91 public:
92 CComDebugObject(void * = NULL)
93 {
94 #if DEBUG_CCOMOBJECT_CREATION
95 DbgPrint("%S, this=%08p\n", __FUNCTION__, static_cast<Base*>(this));
96 #endif
97 _pAtlModule->Lock();
98 }
99
100 virtual ~CComDebugObject()
101 {
102 this->FinalRelease();
103 _pAtlModule->Unlock();
104 }
105
106 STDMETHOD_(ULONG, AddRef)()
107 {
108 int rc = this->InternalAddRef();
109 #if DEBUG_CCOMOBJECT_REFCOUNTING
110 DbgPrint("%s, RefCount is now %d(--)! \n", __FUNCTION__, rc);
111 #endif
112 return rc;
113 }
114
115 STDMETHOD_(ULONG, Release)()
116 {
117 int rc = this->InternalRelease();
118
119 #if DEBUG_CCOMOBJECT_REFCOUNTING
120 DbgPrint("%s, RefCount is now %d(--)! \n", __FUNCTION__, rc);
121 #endif
122
123 if (rc == 0)
124 {
125 #if DEBUG_CCOMOBJECT_DESTRUCTION
126 DbgPrint("%s, RefCount reached 0 Deleting!\n", __FUNCTION__);
127 #endif
128 delete this;
129 }
130 return rc;
131 }
132
133 STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject)
134 {
135 return this->_InternalQueryInterface(iid, ppvObject);
136 }
137
138 static HRESULT WINAPI CreateInstance(CComDebugObject<Base> **pp)
139 {
140 CComDebugObject<Base> *newInstance;
141 HRESULT hResult;
142
143 ATLASSERT(pp != NULL);
144 if (pp == NULL)
145 return E_POINTER;
146
147 hResult = E_OUTOFMEMORY;
148 newInstance = NULL;
149 ATLTRY(newInstance = new CComDebugObject<Base>());
150 if (newInstance != NULL)
151 {
152 newInstance->SetVoid(NULL);
153 newInstance->InternalFinalConstructAddRef();
154 hResult = newInstance->_AtlInitialConstruct();
155 if (SUCCEEDED(hResult))
156 hResult = newInstance->FinalConstruct();
157 if (SUCCEEDED(hResult))
158 hResult = newInstance->_AtlFinalConstruct();
159 newInstance->InternalFinalConstructRelease();
160 if (hResult != S_OK)
161 {
162 delete newInstance;
163 newInstance = NULL;
164 }
165 }
166 *pp = newInstance;
167 return hResult;
168 }
169 };
170
171 #ifdef DEBUG_CCOMOBJECT
172 # define _CComObject CComDebugObject
173 #else
174 # define _CComObject CComObject
175 #endif
176
177 template<class T>
178 void ReleaseCComPtrExpectZero(CComPtr<T>& cptr, BOOL forceRelease = FALSE)
179 {
180 if (cptr.p != NULL)
181 {
182 int nrc = cptr->Release();
183 if (nrc > 0)
184 {
185 DbgPrint("WARNING: Unexpected RefCount > 0 (%d)!\n", nrc);
186 if (forceRelease)
187 {
188 while (nrc > 0)
189 {
190 nrc = cptr->Release();
191 }
192 }
193 }
194 cptr.Detach();
195 }
196 }
197
198 template<class T, class R>
199 HRESULT inline ShellDebugObjectCreator(REFIID riid, R ** ppv)
200 {
201 CComPtr<T> obj;
202 HRESULT hResult;
203
204 if (ppv == NULL)
205 return E_POINTER;
206 *ppv = NULL;
207 ATLTRY(obj = new CComDebugObject<T>);
208 if (obj.p == NULL)
209 return E_OUTOFMEMORY;
210 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
211 if (FAILED(hResult))
212 return hResult;
213 return S_OK;
214 }
215
216 template<class T, class R>
217 HRESULT inline ShellObjectCreator(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 _CComObject<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 ShellObjectCreatorInit(REFIID riid, R ** ppv)
236 {
237 CComPtr<T> obj;
238 CComPtr<R> result;
239 HRESULT hResult;
240
241 if (ppv == NULL)
242 return E_POINTER;
243 *ppv = NULL;
244 ATLTRY(obj = new _CComObject<T>);
245 if (obj.p == NULL)
246 return E_OUTOFMEMORY;
247 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
248 if (FAILED(hResult))
249 return hResult;
250
251 hResult = obj->Initialize();
252 if (FAILED(hResult))
253 return hResult;
254
255 *ppv = result.Detach();
256
257 return S_OK;
258 }
259
260 template<class T>
261 HRESULT inline ShellObjectCreatorInit(REFIID riid, void ** ppv)
262 {
263 CComPtr<T> obj;
264 CComPtr<IUnknown> result;
265 HRESULT hResult;
266
267 if (ppv == NULL)
268 return E_POINTER;
269 *ppv = NULL;
270 ATLTRY(obj = new _CComObject<T>);
271 if (obj.p == NULL)
272 return E_OUTOFMEMORY;
273 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
274 if (FAILED(hResult))
275 return hResult;
276
277 hResult = obj->Initialize();
278 if (FAILED(hResult))
279 return hResult;
280
281 *ppv = result.Detach();
282
283 return S_OK;
284 }
285
286 template<class T, class T1>
287 HRESULT inline ShellObjectCreatorInit(T1 initArg1, REFIID riid, void ** ppv)
288 {
289 CComPtr<T> obj;
290 HRESULT hResult;
291
292 if (ppv == NULL)
293 return E_POINTER;
294 *ppv = NULL;
295 ATLTRY(obj = new _CComObject<T>);
296 if (obj.p == NULL)
297 return E_OUTOFMEMORY;
298 hResult = obj->QueryInterface(riid, ppv);
299 if (FAILED(hResult))
300 return hResult;
301
302 hResult = obj->Initialize(initArg1);
303 if (FAILED(hResult))
304 return hResult;
305
306 return S_OK;
307 }
308
309 template<class T, class T1, class T2>
310 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, REFIID riid, void ** ppv)
311 {
312 CComPtr<T> obj;
313 HRESULT hResult;
314
315 if (ppv == NULL)
316 return E_POINTER;
317 *ppv = NULL;
318 ATLTRY(obj = new _CComObject<T>);
319 if (obj.p == NULL)
320 return E_OUTOFMEMORY;
321 hResult = obj->QueryInterface(riid, ppv);
322 if (FAILED(hResult))
323 return hResult;
324
325 hResult = obj->Initialize(initArg1, initArg2);
326 if (FAILED(hResult))
327 return hResult;
328
329 return S_OK;
330 }
331
332 template<class T, class T1, class T2, class T3>
333 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, REFIID riid, void ** ppv)
334 {
335 CComPtr<T> obj;
336 HRESULT hResult;
337
338 if (ppv == NULL)
339 return E_POINTER;
340 *ppv = NULL;
341 ATLTRY(obj = new _CComObject<T>);
342 if (obj.p == NULL)
343 return E_OUTOFMEMORY;
344 hResult = obj->QueryInterface(riid, ppv);
345 if (FAILED(hResult))
346 return hResult;
347
348 hResult = obj->Initialize(initArg1, initArg2, initArg3);
349 if (FAILED(hResult))
350 return hResult;
351
352 return S_OK;
353 }
354
355 template<class T, class T1, class R>
356 HRESULT inline ShellObjectCreatorInit(T1 initArg1, REFIID riid, R ** ppv)
357 {
358 CComPtr<T> obj;
359 CComPtr<R> result;
360 HRESULT hResult;
361
362 if (ppv == NULL)
363 return E_POINTER;
364 *ppv = NULL;
365 ATLTRY(obj = new _CComObject<T>);
366 if (obj.p == NULL)
367 return E_OUTOFMEMORY;
368 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
369 if (FAILED(hResult))
370 return hResult;
371
372 hResult = obj->Initialize(initArg1);
373 if (FAILED(hResult))
374 return hResult;
375
376 *ppv = result.Detach();
377
378 return S_OK;
379 }
380
381 template<class T, class T1, class T2, class R>
382 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, REFIID riid, R ** ppv)
383 {
384 CComPtr<T> obj;
385 CComPtr<R> result;
386 HRESULT hResult;
387
388 if (ppv == NULL)
389 return E_POINTER;
390 *ppv = NULL;
391 ATLTRY(obj = new _CComObject<T>);
392 if (obj.p == NULL)
393 return E_OUTOFMEMORY;
394 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
395 if (FAILED(hResult))
396 return hResult;
397
398 hResult = obj->Initialize(initArg1, initArg2);
399 if (FAILED(hResult))
400 return hResult;
401
402 *ppv = result.Detach();
403
404 return S_OK;
405 }
406
407 template<class T, class T1, class T2, class T3, class R>
408 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, REFIID riid, R ** ppv)
409 {
410 CComPtr<T> obj;
411 CComPtr<R> result;
412 HRESULT hResult;
413
414 if (ppv == NULL)
415 return E_POINTER;
416 *ppv = NULL;
417 ATLTRY(obj = new _CComObject<T>);
418 if (obj.p == NULL)
419 return E_OUTOFMEMORY;
420 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
421 if (FAILED(hResult))
422 return hResult;
423
424 hResult = obj->Initialize(initArg1, initArg2, initArg3);
425 if (FAILED(hResult))
426 return hResult;
427
428 *ppv = result.Detach();
429
430 return S_OK;
431 }
432
433 template<class T, class T1, class T2, class T3, class T4, class R>
434 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, T4 initArg4, REFIID riid, R ** ppv)
435 {
436 CComPtr<T> obj;
437 CComPtr<R> result;
438 HRESULT hResult;
439
440 if (ppv == NULL)
441 return E_POINTER;
442 *ppv = NULL;
443 ATLTRY(obj = new _CComObject<T>);
444 if (obj.p == NULL)
445 return E_OUTOFMEMORY;
446 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
447 if (FAILED(hResult))
448 return hResult;
449
450 hResult = obj->Initialize(initArg1, initArg2, initArg3, initArg4);
451 if (FAILED(hResult))
452 return hResult;
453
454 *ppv = result.Detach();
455
456 return S_OK;
457 }
458
459 template<class T, class T1, class T2, class T3, class T4, class T5, class R>
460 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, T4 initArg4, T5 initArg5, REFIID riid, R ** ppv)
461 {
462 CComPtr<T> obj;
463 CComPtr<R> result;
464 HRESULT hResult;
465
466 if (ppv == NULL)
467 return E_POINTER;
468 *ppv = NULL;
469 ATLTRY(obj = new _CComObject<T>);
470 if (obj.p == NULL)
471 return E_OUTOFMEMORY;
472 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(&result));
473 if (FAILED(hResult))
474 return hResult;
475
476 hResult = obj->Initialize(initArg1, initArg2, initArg3, initArg4, initArg5);
477 if (FAILED(hResult))
478 return hResult;
479
480 *ppv = result.Detach();
481
482 return S_OK;
483 }
484
485 HRESULT inline SHSetStrRet(LPSTRRET pStrRet, LPCSTR pstrValue)
486 {
487 pStrRet->uType = STRRET_CSTR;
488 strcpy(pStrRet->cStr, pstrValue);
489 return S_OK;
490 }
491
492 HRESULT inline SHSetStrRet(LPSTRRET pStrRet, LPCWSTR pwstrValue)
493 {
494 ULONG cchr = wcslen(pwstrValue);
495 LPWSTR buffer = static_cast<LPWSTR>(CoTaskMemAlloc((cchr + 1) * sizeof(WCHAR)));
496 if (buffer == NULL)
497 return E_OUTOFMEMORY;
498
499 pStrRet->uType = STRRET_WSTR;
500 pStrRet->pOleStr = buffer;
501 wcscpy(buffer, pwstrValue);
502 return S_OK;
503 }
504
505 HRESULT inline SHSetStrRet(LPSTRRET pStrRet, HINSTANCE hInstance, DWORD resId)
506 {
507 WCHAR Buffer[MAX_PATH];
508
509 if (!LoadStringW(hInstance, resId, Buffer, MAX_PATH))
510 return E_FAIL;
511
512 return SHSetStrRet(pStrRet, Buffer);
513 }
514
515 #endif /* __cplusplus */
516
517 #define S_LESSTHAN 0xffff
518 #define S_EQUAL S_OK
519 #define S_GREATERTHAN S_FALSE
520 #define MAKE_COMPARE_HRESULT(x) ((x)>0 ? S_GREATERTHAN : ((x)<0 ? S_LESSTHAN : S_EQUAL))
521
522 #endif /* __ROS_SHELL_UTILS_H */