[SHELLUTILS.H]
[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>
217 HRESULT inline ShellObjectCreator(REFIID riid, void ** ppv)
218 {
219 _CComObject<T> *pobj;
220 HRESULT hResult;
221
222 hResult = _CComObject<T>::CreateInstance(&pobj);
223 if (FAILED(hResult))
224 return hResult;
225
226 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
227
228 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
229
230 pobj->Release(); /* In case of failure the object will be released */
231
232 return hResult;
233 }
234
235 template<class T>
236 HRESULT inline ShellObjectCreatorInit(REFIID riid, void ** ppv)
237 {
238 _CComObject<T> *pobj;
239 HRESULT hResult;
240
241 hResult = _CComObject<T>::CreateInstance(&pobj);
242 if (FAILED(hResult))
243 return hResult;
244
245 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
246
247 hResult = pobj->Initialize();
248
249 if (SUCCEEDED(hResult))
250 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
251
252 pobj->Release(); /* In case of failure the object will be released */
253
254 return hResult;
255 }
256
257 template<class T, class T1>
258 HRESULT inline ShellObjectCreatorInit(T1 initArg1, REFIID riid, void ** ppv)
259 {
260 _CComObject<T> *pobj;
261 HRESULT hResult;
262
263 hResult = _CComObject<T>::CreateInstance(&pobj);
264 if (FAILED(hResult))
265 return hResult;
266
267 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
268
269 hResult = pobj->Initialize(initArg1);
270
271 if (SUCCEEDED(hResult))
272 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
273
274 pobj->Release(); /* In case of failure the object will be released */
275
276 return hResult;
277 }
278
279 template<class T, class T1, class T2>
280 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, REFIID riid, void ** ppv)
281 {
282 _CComObject<T> *pobj;
283 HRESULT hResult;
284
285 hResult = _CComObject<T>::CreateInstance(&pobj);
286 if (FAILED(hResult))
287 return hResult;
288
289 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
290
291 hResult = pobj->Initialize(initArg1, initArg2);
292
293 if (SUCCEEDED(hResult))
294 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
295
296 pobj->Release(); /* In case of failure the object will be released */
297
298 return hResult;
299 }
300
301 template<class T, class T1, class T2, class T3>
302 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, REFIID riid, void ** ppv)
303 {
304 _CComObject<T> *pobj;
305 HRESULT hResult;
306
307 hResult = _CComObject<T>::CreateInstance(&pobj);
308 if (FAILED(hResult))
309 return hResult;
310
311 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
312
313 hResult = pobj->Initialize(initArg1, initArg2, initArg3);
314
315 if (SUCCEEDED(hResult))
316 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
317
318 pobj->Release(); /* In case of failure the object will be released */
319
320 return hResult;
321 }
322
323 template<class T, class T1, class T2, class T3, class T4>
324 HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, T4 initArg4, REFIID riid, void ** ppv)
325 {
326 _CComObject<T> *pobj;
327 HRESULT hResult;
328
329 hResult = _CComObject<T>::CreateInstance(&pobj);
330 if (FAILED(hResult))
331 return hResult;
332
333 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
334
335 hResult = pobj->Initialize(initArg1, initArg2, initArg3, initArg4);
336
337 if (SUCCEEDED(hResult))
338 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
339
340 pobj->Release(); /* In case of failure the object will be released */
341
342 return hResult;
343 }
344
345 HRESULT inline SHSetStrRet(LPSTRRET pStrRet, LPCSTR pstrValue)
346 {
347 pStrRet->uType = STRRET_CSTR;
348 strcpy(pStrRet->cStr, pstrValue);
349 return S_OK;
350 }
351
352 HRESULT inline SHSetStrRet(LPSTRRET pStrRet, LPCWSTR pwstrValue)
353 {
354 ULONG cchr = wcslen(pwstrValue);
355 LPWSTR buffer = static_cast<LPWSTR>(CoTaskMemAlloc((cchr + 1) * sizeof(WCHAR)));
356 if (buffer == NULL)
357 return E_OUTOFMEMORY;
358
359 pStrRet->uType = STRRET_WSTR;
360 pStrRet->pOleStr = buffer;
361 wcscpy(buffer, pwstrValue);
362 return S_OK;
363 }
364
365 HRESULT inline SHSetStrRet(LPSTRRET pStrRet, HINSTANCE hInstance, DWORD resId)
366 {
367 WCHAR Buffer[MAX_PATH];
368
369 if (!LoadStringW(hInstance, resId, Buffer, MAX_PATH))
370 return E_FAIL;
371
372 return SHSetStrRet(pStrRet, Buffer);
373 }
374
375 #endif /* __cplusplus */
376
377 #define S_LESSTHAN 0xffff
378 #define S_EQUAL S_OK
379 #define S_GREATERTHAN S_FALSE
380 #define MAKE_COMPARE_HRESULT(x) ((x)>0 ? S_GREATERTHAN : ((x)<0 ? S_LESSTHAN : S_EQUAL))
381
382 #endif /* __ROS_SHELL_UTILS_H */