2 * Copyright 1999, 2000 Juergen Schmied
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.
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.
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
19 #ifndef __ROS_SHELL_UTILS_H
20 #define __ROS_SHELL_UTILS_H
24 #endif /* defined(__cplusplus) */
27 Win32DbgPrint(const char *filename
, int line
, const char *lpFormat
, ...)
35 fname
= strrchr(filename
, '\\');
38 fname
= strrchr(filename
, '/');
48 szMsgStart
= szMsg
+ sprintf(szMsg
, "%s:%d: ", fname
, line
);
50 va_start(vl
, lpFormat
);
51 uRet
= (ULONG
) vsprintf(szMsgStart
, lpFormat
, vl
);
54 OutputDebugStringA(szMsg
);
59 #define DbgPrint(fmt, ...) \
60 Win32DbgPrint(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
63 # define IID_PPV_ARG(Itype, ppType) IID_##Itype, reinterpret_cast<void**>((static_cast<Itype**>(ppType)))
64 # define IID_NULL_PPV_ARG(Itype, ppType) IID_##Itype, NULL, reinterpret_cast<void**>((static_cast<Itype**>(ppType)))
66 # define IID_PPV_ARG(Itype, ppType) IID_##Itype, (void**)(ppType)
67 # define IID_NULL_PPV_ARG(Itype, ppType) IID_##Itype, NULL, (void**)(ppType)
71 #define FAILED_UNEXPECTEDLY(hr) (FAILED(hr) && (Win32DbgPrint(__FILE__, __LINE__, "Unexpected failure %08x.\n", hr), TRUE))
73 #define FAILED_UNEXPECTEDLY(hr) FAILED(hr)
78 #endif /* defined(__cplusplus) */
82 class CComCreatorCentralInstance
85 static IUnknown
*s_pInstance
;
88 static HRESULT WINAPI
CreateInstance(void *pv
, REFIID riid
, LPVOID
*ppv
)
92 return CLASS_E_NOAGGREGATION
;
97 hr
= ATL::CComCreator
< T
>::CreateInstance(NULL
, IID_IUnknown
, &pObj
);
100 if (InterlockedCompareExchangePointer((PVOID
*)&s_pInstance
, pObj
, NULL
))
101 static_cast<IUnknown
*>(pObj
)->Release();
103 return s_pInstance
->QueryInterface(riid
, ppv
);
109 s_pInstance
->Release();
115 template <typename T
>
116 IUnknown
*CComCreatorCentralInstance
<T
>::s_pInstance
= NULL
;
118 #define DECLARE_CENTRAL_INSTANCE_NOT_AGGREGATABLE(x) \
120 typedef CComCreatorCentralInstance< ATL::CComObject<x> > _CreatorClass;
124 template <class Base
>
125 class CComDebugObject
: public Base
128 CComDebugObject(void * = NULL
)
130 #if DEBUG_CCOMOBJECT_CREATION
131 DbgPrint("%S, this=%08p\n", __FUNCTION__
, static_cast<Base
*>(this));
136 virtual ~CComDebugObject()
138 this->FinalRelease();
139 _pAtlModule
->Unlock();
142 STDMETHOD_(ULONG
, AddRef
)()
144 int rc
= this->InternalAddRef();
145 #if DEBUG_CCOMOBJECT_REFCOUNTING
146 DbgPrint("%s, RefCount is now %d(--)! \n", __FUNCTION__
, rc
);
151 STDMETHOD_(ULONG
, Release
)()
153 int rc
= this->InternalRelease();
155 #if DEBUG_CCOMOBJECT_REFCOUNTING
156 DbgPrint("%s, RefCount is now %d(--)! \n", __FUNCTION__
, rc
);
161 #if DEBUG_CCOMOBJECT_DESTRUCTION
162 DbgPrint("%s, RefCount reached 0 Deleting!\n", __FUNCTION__
);
169 STDMETHOD(QueryInterface
)(REFIID iid
, void **ppvObject
)
171 return this->_InternalQueryInterface(iid
, ppvObject
);
174 static HRESULT WINAPI
CreateInstance(CComDebugObject
<Base
> **pp
)
176 CComDebugObject
<Base
> *newInstance
;
179 ATLASSERT(pp
!= NULL
);
183 hResult
= E_OUTOFMEMORY
;
185 ATLTRY(newInstance
= new CComDebugObject
<Base
>());
186 if (newInstance
!= NULL
)
188 newInstance
->SetVoid(NULL
);
189 newInstance
->InternalFinalConstructAddRef();
190 hResult
= newInstance
->_AtlInitialConstruct();
191 if (SUCCEEDED(hResult
))
192 hResult
= newInstance
->FinalConstruct();
193 if (SUCCEEDED(hResult
))
194 hResult
= newInstance
->_AtlFinalConstruct();
195 newInstance
->InternalFinalConstructRelease();
207 #ifdef DEBUG_CCOMOBJECT
208 # define _CComObject CComDebugObject
210 # define _CComObject CComObject
214 void ReleaseCComPtrExpectZero(CComPtr
<T
>& cptr
, BOOL forceRelease
= FALSE
)
218 int nrc
= cptr
->Release();
221 DbgPrint("WARNING: Unexpected RefCount > 0 (%d)!\n", nrc
);
226 nrc
= cptr
->Release();
234 template<class T
, class R
>
235 HRESULT
inline ShellDebugObjectCreator(REFIID riid
, R
** ppv
)
243 ATLTRY(obj
= new CComDebugObject
<T
>);
245 return E_OUTOFMEMORY
;
246 hResult
= obj
->QueryInterface(riid
, reinterpret_cast<void **>(ppv
));
253 HRESULT
inline ShellObjectCreator(REFIID riid
, void ** ppv
)
255 _CComObject
<T
> *pobj
;
258 hResult
= _CComObject
<T
>::CreateInstance(&pobj
);
262 pobj
->AddRef(); /* CreateInstance returns object with 0 ref count */
264 hResult
= pobj
->QueryInterface(riid
, reinterpret_cast<void **>(ppv
));
266 pobj
->Release(); /* In case of failure the object will be released */
272 HRESULT
inline ShellObjectCreatorInit(REFIID riid
, void ** ppv
)
274 _CComObject
<T
> *pobj
;
277 hResult
= _CComObject
<T
>::CreateInstance(&pobj
);
281 pobj
->AddRef(); /* CreateInstance returns object with 0 ref count */
283 hResult
= pobj
->Initialize();
285 if (SUCCEEDED(hResult
))
286 hResult
= pobj
->QueryInterface(riid
, reinterpret_cast<void **>(ppv
));
288 pobj
->Release(); /* In case of failure the object will be released */
293 template<class T
, class T1
>
294 HRESULT
inline ShellObjectCreatorInit(T1 initArg1
, REFIID riid
, void ** ppv
)
296 _CComObject
<T
> *pobj
;
299 hResult
= _CComObject
<T
>::CreateInstance(&pobj
);
303 pobj
->AddRef(); /* CreateInstance returns object with 0 ref count */
305 hResult
= pobj
->Initialize(initArg1
);
307 if (SUCCEEDED(hResult
))
308 hResult
= pobj
->QueryInterface(riid
, reinterpret_cast<void **>(ppv
));
310 pobj
->Release(); /* In case of failure the object will be released */
315 template<class T
, class T1
, class T2
>
316 HRESULT
inline ShellObjectCreatorInit(T1 initArg1
, T2 initArg2
, REFIID riid
, void ** ppv
)
318 _CComObject
<T
> *pobj
;
321 hResult
= _CComObject
<T
>::CreateInstance(&pobj
);
325 pobj
->AddRef(); /* CreateInstance returns object with 0 ref count */
327 hResult
= pobj
->Initialize(initArg1
, initArg2
);
329 if (SUCCEEDED(hResult
))
330 hResult
= pobj
->QueryInterface(riid
, reinterpret_cast<void **>(ppv
));
332 pobj
->Release(); /* In case of failure the object will be released */
337 template<class T
, class T1
, class T2
, class T3
>
338 HRESULT
inline ShellObjectCreatorInit(T1 initArg1
, T2 initArg2
, T3 initArg3
, REFIID riid
, void ** ppv
)
340 _CComObject
<T
> *pobj
;
343 hResult
= _CComObject
<T
>::CreateInstance(&pobj
);
347 pobj
->AddRef(); /* CreateInstance returns object with 0 ref count */
349 hResult
= pobj
->Initialize(initArg1
, initArg2
, initArg3
);
351 if (SUCCEEDED(hResult
))
352 hResult
= pobj
->QueryInterface(riid
, reinterpret_cast<void **>(ppv
));
354 pobj
->Release(); /* In case of failure the object will be released */
359 template<class T
, class T1
, class T2
, class T3
, class T4
>
360 HRESULT
inline ShellObjectCreatorInit(T1 initArg1
, T2 initArg2
, T3 initArg3
, T4 initArg4
, REFIID riid
, void ** ppv
)
362 _CComObject
<T
> *pobj
;
365 hResult
= _CComObject
<T
>::CreateInstance(&pobj
);
369 pobj
->AddRef(); /* CreateInstance returns object with 0 ref count */
371 hResult
= pobj
->Initialize(initArg1
, initArg2
, initArg3
, initArg4
);
373 if (SUCCEEDED(hResult
))
374 hResult
= pobj
->QueryInterface(riid
, reinterpret_cast<void **>(ppv
));
376 pobj
->Release(); /* In case of failure the object will be released */
381 HRESULT
inline SHSetStrRet(LPSTRRET pStrRet
, LPCSTR pstrValue
)
383 pStrRet
->uType
= STRRET_CSTR
;
384 strcpy(pStrRet
->cStr
, pstrValue
);
388 HRESULT
inline SHSetStrRet(LPSTRRET pStrRet
, LPCWSTR pwstrValue
)
390 SIZE_T cchr
= wcslen(pwstrValue
);
391 LPWSTR buffer
= static_cast<LPWSTR
>(CoTaskMemAlloc((cchr
+ 1) * sizeof(WCHAR
)));
393 return E_OUTOFMEMORY
;
395 pStrRet
->uType
= STRRET_WSTR
;
396 pStrRet
->pOleStr
= buffer
;
397 wcscpy(buffer
, pwstrValue
);
401 HRESULT
inline SHSetStrRet(LPSTRRET pStrRet
, HINSTANCE hInstance
, DWORD resId
)
403 WCHAR Buffer
[MAX_PATH
];
405 if (!LoadStringW(hInstance
, resId
, Buffer
, MAX_PATH
))
408 return SHSetStrRet(pStrRet
, Buffer
);
411 static inline void DbgDumpMenuInternal(HMENU hmenu
, char* padding
, int padlevel
)
415 int count
= GetMenuItemCount(hmenu
);
417 padding
[padlevel
] = '.';
418 padding
[padlevel
+ 1] = '.';
419 padding
[padlevel
+ 2] = 0;
421 for (i
= 0; i
< count
; i
++)
423 MENUITEMINFOW mii
= { 0 };
425 mii
.cbSize
= sizeof(mii
);
426 mii
.fMask
= MIIM_STRING
| MIIM_FTYPE
| MIIM_SUBMENU
| MIIM_STATE
| MIIM_ID
;
427 mii
.dwTypeData
= label
;
428 mii
.cch
= _countof(label
);
430 GetMenuItemInfoW(hmenu
, i
, TRUE
, &mii
);
432 if (mii
.fType
& MFT_BITMAP
)
433 DbgPrint("%s%2d - %08x: BITMAP %08p (state=%d, has submenu=%s)\n", padding
, i
, mii
.wID
, mii
.hbmpItem
, mii
.fState
, mii
.hSubMenu
? "TRUE" : "FALSE");
434 else if (mii
.fType
& MFT_SEPARATOR
)
435 DbgPrint("%s%2d - %08x ---SEPARATOR---\n", padding
, i
, mii
.wID
);
437 DbgPrint("%s%2d - %08x: %S (state=%d, has submenu=%s)\n", padding
, i
, mii
.wID
, mii
.dwTypeData
, mii
.fState
, mii
.hSubMenu
? "TRUE" : "FALSE");
440 DbgDumpMenuInternal(mii
.hSubMenu
, padding
, padlevel
+ 2);
444 padding
[padlevel
] = 0;
447 static __inline
void DbgDumpMenu(HMENU hmenu
)
450 DbgDumpMenuInternal(hmenu
, padding
, 0);
455 void DumpIdList(LPCITEMIDLIST pcidl
)
457 DbgPrint("Begin IDList Dump\n");
459 for (; pcidl
!= NULL
; pcidl
= ILGetNext(pcidl
))
462 int cb
= pcidl
->mkid
.cb
;
463 BYTE
* sh
= (BYTE
*) &(pcidl
->mkid
);
464 if (cb
== 0) // ITEMIDLISTs are terminatedwith a null SHITEMID.
466 DbgPrint("Begin SHITEMID (cb=%d)\n", cb
);
468 DbgPrint(" - WARNING: cb is not a multiple of 4\n");
469 for (i
= 0; (i
+ 4) <= cb
; i
+= 4)
471 DbgPrint(" - abID[%08x]: %02x %02x %02x %02x\n",
483 DbgPrint(" - abID[%08x]: %02x %02x %02x --\n",
491 DbgPrint(" - abID[%08x]: %02x %02x -- --\n",
498 DbgPrint(" - abID[%08x]: %02x -- -- --\n",
503 DbgPrint("End SHITEMID\n");
505 DbgPrint("End IDList Dump.\n");
508 #endif /* __cplusplus */
510 #define S_LESSTHAN 0xffff
512 #define S_GREATERTHAN S_FALSE
513 #define MAKE_COMPARE_HRESULT(x) ((x)>0 ? S_GREATERTHAN : ((x)<0 ? S_LESSTHAN : S_EQUAL))
515 #endif /* __ROS_SHELL_UTILS_H */