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