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