ReactOS 0.4.16-dev-1170-ge326b06
shellutils.h
Go to the documentation of this file.
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
23extern "C" {
24#endif /* defined(__cplusplus) */
25
26static inline ULONG
27Win32DbgPrint(const char *filename, int line, const char *lpFormat, ...)
28{
29 char szMsg[512];
30 char *szMsgStart;
31 const char *fname;
32 va_list vl;
33
34 fname = strrchr(filename, '\\');
35 if (fname == NULL)
36 {
37 fname = strrchr(filename, '/');
38 if (fname != NULL)
39 fname++;
40 }
41 else
42 fname++;
43
44 if (fname == NULL)
45 fname = filename;
46
47 szMsgStart = szMsg + sprintf(szMsg, "%s:%d: ", fname, line);
48
49 va_start(vl, lpFormat);
50 vsprintf(szMsgStart, lpFormat, vl);
51 va_end(vl);
52
53 OutputDebugStringA(szMsg);
54
55 /* Return STATUS_SUCCESS, since we are supposed to mimic DbgPrint */
56 return 0;
57}
58
59#define DbgPrint(fmt, ...) \
60 Win32DbgPrint(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
61
62#ifdef __cplusplus
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)))
65#else
66# define IID_PPV_ARG(Itype, ppType) &IID_##Itype, (void**)(ppType)
67# define IID_NULL_PPV_ARG(Itype, ppType) &IID_##Itype, NULL, (void**)(ppType)
68#endif
69
71{
72 // HRESULT_FROM_WIN32 will evaluate its parameter twice, this function will not.
73 return HRESULT_FROM_WIN32(hr);
74}
75
76#if 1
77
78static inline BOOL _ROS_FAILED_HELPER(HRESULT hr, const char* expr, const char* filename, int line)
79{
80 if (FAILED(hr))
81 {
82 Win32DbgPrint(filename, line, "Unexpected failure (%s)=%08x.\n", expr, hr);
83 return TRUE;
84 }
85 return FALSE;
86}
87
88#define FAILED_UNEXPECTEDLY(hr) _ROS_FAILED_HELPER((hr), #hr, __FILE__, __LINE__)
89#else
90#define FAILED_UNEXPECTEDLY(hr) FAILED(hr)
91#endif
92
93#ifdef __cplusplus
94} /* extern "C" */
95#endif /* defined(__cplusplus) */
96
97static inline UINT
99{
100 WCHAR buf[400];
101 UINT cch;
102
103 if (!IsWindowVisible(hwndOwner))
104 hwndOwner = NULL;
105 if (Error == ERROR_SUCCESS)
107
109 NULL, Error, 0, buf, _countof(buf), NULL);
110 if (!cch)
111 {
112 enum { user32_IDS_ERROR = 2 }; // IDS_ERROR from user32 resource.h ("Error" string)
113 cch = LoadStringW(LoadLibraryW(L"USER32"), user32_IDS_ERROR, buf, _countof(buf));
114 wsprintfW(buf + cch, L"\n\n%#x (%d)", Error, Error);
115 }
116 MessageBoxW(hwndOwner, buf, NULL, MB_OK | MB_ICONSTOP);
117 return Error;
118}
119#ifdef __cplusplus
120template<class H> static UINT
121SHELL_ErrorBox(H hwndOwner, UINT Error = GetLastError())
122{
123 return SHELL_ErrorBoxHelper(const_cast<HWND>(hwndOwner), Error);
124}
125#else
126#define SHELL_ErrorBox SHELL_ErrorBoxHelper
127#endif
128
129#ifdef __cplusplus
130#ifdef DECLARE_CLASSFACTORY // ATL
131template <typename T>
132class CComCreatorCentralInstance
133{
134private:
135 static IUnknown *s_pInstance;
136
137public:
138 static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
139 {
140 *ppv = NULL;
141 if (pv != NULL)
143 if (!s_pInstance)
144 {
145 PVOID pObj;
146 HRESULT hr;
148 if (FAILED(hr))
149 return hr;
150 if (InterlockedCompareExchangePointer((PVOID *)&s_pInstance, pObj, NULL))
151 static_cast<IUnknown *>(pObj)->Release();
152 }
153 return s_pInstance->QueryInterface(riid, ppv);
154 }
155 static void Term()
156 {
157 if (s_pInstance)
158 {
159 s_pInstance->Release();
160 s_pInstance = NULL;
161 }
162 }
163};
164
165template <typename T>
166IUnknown *CComCreatorCentralInstance<T>::s_pInstance = NULL;
167
168#define DECLARE_CENTRAL_INSTANCE_NOT_AGGREGATABLE(x) \
169public: \
170 typedef CComCreatorCentralInstance< ATL::CComObject<x> > _CreatorClass;
171
172
173template <class Base>
174class CComDebugObject : public Base
175{
176public:
177 CComDebugObject(void * = NULL)
178 {
179#if DEBUG_CCOMOBJECT_CREATION
180 DbgPrint("%S, this=%08p\n", __FUNCTION__, static_cast<Base*>(this));
181#endif
182 _pAtlModule->Lock();
183 }
184
185 virtual ~CComDebugObject()
186 {
187 this->FinalRelease();
188 _pAtlModule->Unlock();
189 }
190
192 {
193 int rc = this->InternalAddRef();
194#if DEBUG_CCOMOBJECT_REFCOUNTING
195 DbgPrint("%s, RefCount is now %d(--)!\n", __FUNCTION__, rc);
196#endif
197 return rc;
198 }
199
201 {
202 int rc = this->InternalRelease();
203
204#if DEBUG_CCOMOBJECT_REFCOUNTING
205 DbgPrint("%s, RefCount is now %d(--)!\n", __FUNCTION__, rc);
206#endif
207
208 if (rc == 0)
209 {
210#if DEBUG_CCOMOBJECT_DESTRUCTION
211 DbgPrint("%s, RefCount reached 0 Deleting!\n", __FUNCTION__);
212#endif
213 delete this;
214 }
215 return rc;
216 }
217
219 {
220 return this->_InternalQueryInterface(iid, ppvObject);
221 }
222
223 static HRESULT WINAPI CreateInstance(CComDebugObject<Base> **pp)
224 {
225 CComDebugObject<Base> *newInstance;
226 HRESULT hResult;
227
228 ATLASSERT(pp != NULL);
229 if (pp == NULL)
230 return E_POINTER;
231
232 hResult = E_OUTOFMEMORY;
233 newInstance = NULL;
234 ATLTRY(newInstance = new CComDebugObject<Base>());
235 if (newInstance != NULL)
236 {
237 newInstance->SetVoid(NULL);
238 newInstance->InternalFinalConstructAddRef();
239 hResult = newInstance->_AtlInitialConstruct();
240 if (SUCCEEDED(hResult))
241 hResult = newInstance->FinalConstruct();
242 if (SUCCEEDED(hResult))
243 hResult = newInstance->_AtlFinalConstruct();
244 newInstance->InternalFinalConstructRelease();
245 if (hResult != S_OK)
246 {
247 delete newInstance;
248 newInstance = NULL;
249 }
250 }
251 *pp = newInstance;
252 return hResult;
253 }
254};
255
256#ifdef DEBUG_CCOMOBJECT
257# define _CComObject CComDebugObject
258#else
259# define _CComObject CComObject
260#endif
261
262template<class T>
263ULONG ReleaseCComPtrExpectZeroHelper(const char *file, UINT line, CComPtr<T>& cptr, BOOL forceRelease = FALSE)
264{
265 ULONG r = 0;
266 if (cptr.p != NULL)
267 {
268 T *raw = cptr.Detach();
269 int nrc = r = raw->Release();
270 if (nrc > 0)
271 Win32DbgPrint(file, line, "WARNING: Unexpected RefCount > 0 (%d)\n", nrc);
272 while (nrc > 0 && forceRelease)
273 {
274 nrc = raw->Release();
275 }
276 }
277 return r;
278}
279#define ReleaseCComPtrExpectZero(...) ReleaseCComPtrExpectZeroHelper(__FILE__, __LINE__, __VA_ARGS__)
280
281template<class T, class R>
282HRESULT inline ShellDebugObjectCreator(REFIID riid, R ** ppv)
283{
284 CComPtr<T> obj;
285 HRESULT hResult;
286
287 if (ppv == NULL)
288 return E_POINTER;
289 *ppv = NULL;
290 ATLTRY(obj = new CComDebugObject<T>);
291 if (obj.p == NULL)
292 return E_OUTOFMEMORY;
293 hResult = obj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
294 if (FAILED(hResult))
295 return hResult;
296 return S_OK;
297}
298
299template<class T>
300HRESULT inline ShellObjectCreator(CComPtr<T> &objref)
301{
302 _CComObject<T> *pobj;
303 HRESULT hResult = _CComObject<T>::CreateInstance(&pobj);
304 objref = pobj; // AddRef() gets called here
305 if (FAILED(hResult))
306 return hResult;
307 return S_OK;
308}
309
310template<class T>
311HRESULT inline ShellObjectCreator(REFIID riid, void ** ppv)
312{
313 _CComObject<T> *pobj;
314 HRESULT hResult;
315
316 hResult = _CComObject<T>::CreateInstance(&pobj);
317 if (FAILED(hResult))
318 return hResult;
319
320 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
321
322 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
323
324 pobj->Release(); /* In case of failure the object will be released */
325
326 return hResult;
327}
328
329template<class T>
330HRESULT inline ShellObjectCreatorInit(REFIID riid, void ** ppv)
331{
332 _CComObject<T> *pobj;
333 HRESULT hResult;
334
335 hResult = _CComObject<T>::CreateInstance(&pobj);
336 if (FAILED(hResult))
337 return hResult;
338
339 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
340
341 hResult = pobj->Initialize();
342
343 if (SUCCEEDED(hResult))
344 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
345
346 pobj->Release(); /* In case of failure the object will be released */
347
348 return hResult;
349}
350
351template<class T, class T1>
352HRESULT inline ShellObjectCreatorInit(T1 initArg1, REFIID riid, void ** ppv)
353{
354 _CComObject<T> *pobj;
355 HRESULT hResult;
356
357 hResult = _CComObject<T>::CreateInstance(&pobj);
358 if (FAILED(hResult))
359 return hResult;
360
361 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
362
363 hResult = pobj->Initialize(initArg1);
364
365 if (SUCCEEDED(hResult))
366 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
367
368 pobj->Release(); /* In case of failure the object will be released */
369
370 return hResult;
371}
372
373template<class T, class T1, class T2>
374HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, REFIID riid, void ** ppv)
375{
376 _CComObject<T> *pobj;
377 HRESULT hResult;
378
379 hResult = _CComObject<T>::CreateInstance(&pobj);
380 if (FAILED(hResult))
381 return hResult;
382
383 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
384
385 hResult = pobj->Initialize(initArg1, initArg2);
386
387 if (SUCCEEDED(hResult))
388 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
389
390 pobj->Release(); /* In case of failure the object will be released */
391
392 return hResult;
393}
394
395template<class T, class T1, class T2, class T3>
396HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, REFIID riid, void ** ppv)
397{
398 _CComObject<T> *pobj;
399 HRESULT hResult;
400
401 hResult = _CComObject<T>::CreateInstance(&pobj);
402 if (FAILED(hResult))
403 return hResult;
404
405 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
406
407 hResult = pobj->Initialize(initArg1, initArg2, initArg3);
408
409 if (SUCCEEDED(hResult))
410 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
411
412 pobj->Release(); /* In case of failure the object will be released */
413
414 return hResult;
415}
416
417template<class T, class T1, class T2, class T3, class T4>
418HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, T4 initArg4, REFIID riid, void ** ppv)
419{
420 _CComObject<T> *pobj;
421 HRESULT hResult;
422
423 hResult = _CComObject<T>::CreateInstance(&pobj);
424 if (FAILED(hResult))
425 return hResult;
426
427 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
428
429 hResult = pobj->Initialize(initArg1, initArg2, initArg3, initArg4);
430
431 if (SUCCEEDED(hResult))
432 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
433
434 pobj->Release(); /* In case of failure the object will be released */
435
436 return hResult;
437}
438
439template<class T, class T1, class T2, class T3, class T4, class T5>
440HRESULT inline ShellObjectCreatorInit(T1 initArg1, T2 initArg2, T3 initArg3, T4 initArg4, T5 initArg5, REFIID riid, void ** ppv)
441{
442 _CComObject<T> *pobj;
443 HRESULT hResult;
444
445 hResult = _CComObject<T>::CreateInstance(&pobj);
446 if (FAILED(hResult))
447 return hResult;
448
449 pobj->AddRef(); /* CreateInstance returns object with 0 ref count */
450
451 hResult = pobj->Initialize(initArg1, initArg2, initArg3, initArg4, initArg5);
452
453 if (SUCCEEDED(hResult))
454 hResult = pobj->QueryInterface(riid, reinterpret_cast<void **>(ppv));
455
456 pobj->Release(); /* In case of failure the object will be released */
457
458 return hResult;
459}
460#endif // DECLARE_CLASSFACTORY (ATL)
461
462template<class P, class R> static HRESULT SHILClone(P pidl, R *ppOut)
463{
464 R r = *ppOut = (R)ILClone((PIDLIST_RELATIVE)pidl);
465 return r ? S_OK : E_OUTOFMEMORY;
466}
467
468template<class B, class R> static HRESULT SHILCombine(B base, PCUIDLIST_RELATIVE sub, R *ppOut)
469{
470 R r = *ppOut = (R)ILCombine((PCIDLIST_ABSOLUTE)base, sub);
471 return r ? S_OK : E_OUTOFMEMORY;
472}
473
474static inline bool StrIsNullOrEmpty(LPCSTR str) { return !str || !*str; }
475static inline bool StrIsNullOrEmpty(LPCWSTR str) { return !str || !*str; }
476
477HRESULT inline SHSetStrRetEmpty(LPSTRRET pStrRet)
478{
479 pStrRet->uType = STRRET_CSTR;
480 pStrRet->cStr[0] = '\0';
481 return S_OK;
482}
483
484HRESULT inline SHSetStrRet(LPSTRRET pStrRet, LPCSTR pstrValue)
485{
486 pStrRet->uType = STRRET_CSTR;
487 strcpy(pStrRet->cStr, pstrValue);
488 return S_OK;
489}
490
491HRESULT inline SHSetStrRet(LPSTRRET pStrRet, LPCWSTR pwstrValue)
492{
493 SIZE_T cchr = wcslen(pwstrValue);
494 LPWSTR buffer = static_cast<LPWSTR>(CoTaskMemAlloc((cchr + 1) * sizeof(WCHAR)));
495 if (buffer == NULL)
496 return E_OUTOFMEMORY;
497
498 pStrRet->uType = STRRET_WSTR;
499 pStrRet->pOleStr = buffer;
500 wcscpy(buffer, pwstrValue);
501 return S_OK;
502}
503
504HRESULT inline SHSetStrRet(LPSTRRET pStrRet, HINSTANCE hInstance, DWORD resId)
505{
507
508 if (!LoadStringW(hInstance, resId, Buffer, MAX_PATH))
509 return E_FAIL;
510
511 return SHSetStrRet(pStrRet, Buffer);
512}
513
514static inline void DbgDumpMenuInternal(HMENU hmenu, char* padding, int padlevel)
515{
516 WCHAR label[128];
517 int i;
519
520 padding[padlevel] = '.';
521 padding[padlevel + 1] = '.';
522 padding[padlevel + 2] = 0;
523
524 for (i = 0; i < count; i++)
525 {
526 MENUITEMINFOW mii = { 0 };
527
528 mii.cbSize = sizeof(mii);
530 mii.dwTypeData = label;
531 mii.cch = _countof(label);
532
533 GetMenuItemInfoW(hmenu, i, TRUE, &mii);
534
535 if (mii.fType & MFT_BITMAP)
536 DbgPrint("%s%2d - %08x: BITMAP %08p (state=%d, has submenu=%s)\n", padding, i, mii.wID, mii.hbmpItem, mii.fState, mii.hSubMenu ? "TRUE" : "FALSE");
537 else if (mii.fType & MFT_SEPARATOR)
538 DbgPrint("%s%2d - %08x ---SEPARATOR---\n", padding, i, mii.wID);
539 else
540 DbgPrint("%s%2d - %08x: %S (state=%d, has submenu=%s)\n", padding, i, mii.wID, mii.dwTypeData, mii.fState, mii.hSubMenu ? "TRUE" : "FALSE");
541
542 if (mii.hSubMenu)
543 DbgDumpMenuInternal(mii.hSubMenu, padding, padlevel + 2);
544
545 }
546
547 padding[padlevel] = 0;
548}
549
550static __inline void DbgDumpMenu(HMENU hmenu)
551{
552 char padding[128];
553 DbgDumpMenuInternal(hmenu, padding, 0);
554}
555
556
557static inline
558void DumpIdList(LPCITEMIDLIST pcidl)
559{
560 DbgPrint("Begin IDList Dump\n");
561
562 for (; pcidl != NULL; pcidl = ILGetNext(pcidl))
563 {
564 int i;
565 int cb = pcidl->mkid.cb;
566 BYTE * sh = (BYTE*) &(pcidl->mkid);
567 if (cb == 0) // ITEMIDLISTs are terminatedwith a null SHITEMID.
568 break;
569 DbgPrint("Begin SHITEMID (cb=%d)\n", cb);
570 if ((cb & 3) != 0)
571 DbgPrint(" - WARNING: cb is not a multiple of 4\n");
572 for (i = 0; (i + 4) <= cb; i += 4)
573 {
574 DbgPrint(" - abID[%08x]: %02x %02x %02x %02x\n",
575 i,
576 sh[i + 0],
577 sh[i + 1],
578 sh[i + 2],
579 sh[i + 3]);
580 }
581 if (i < cb)
582 {
583 cb -= i;
584 if (cb == 3)
585 {
586 DbgPrint(" - abID[%08x]: %02x %02x %02x --\n",
587 i,
588 sh[i + 0],
589 sh[i + 1],
590 sh[i + 2]);
591 }
592 else if (cb == 2)
593 {
594 DbgPrint(" - abID[%08x]: %02x %02x -- --\n",
595 i,
596 sh[i + 0],
597 sh[i + 1]);
598 }
599 else if (cb == 1)
600 {
601 DbgPrint(" - abID[%08x]: %02x -- -- --\n",
602 i,
603 sh[i + 0]);
604 }
605 }
606 DbgPrint("End SHITEMID\n");
607 }
608 DbgPrint("End IDList Dump.\n");
609}
610
611template <HRESULT (WINAPI *InitFunc)(void*), void (WINAPI *UninitFunc)()>
612struct CCoInitBase
613{
614 HRESULT hr;
615 CCoInitBase() : hr(InitFunc(NULL)) { }
616 ~CCoInitBase()
617 {
618 if (SUCCEEDED(hr))
619 UninitFunc();
620 }
621};
622typedef CCoInitBase<CoInitialize, CoUninitialize> CCoInit;
623typedef CCoInitBase<OleInitialize, OleUninitialize> COleInit;
624
625class CObjectWithSiteBase :
626 public IObjectWithSite
627{
628public:
629 IUnknown* m_pUnkSite;
630
631 CObjectWithSiteBase() : m_pUnkSite(NULL) {}
632 virtual ~CObjectWithSiteBase() { SetSite(NULL); }
633
634 // IObjectWithSite
635 STDMETHODIMP SetSite(IUnknown *pUnkSite) override
636 {
637#if defined(__WINE_SHLWAPI_H) && !defined(NO_SHLWAPI)
638 IUnknown_Set(&m_pUnkSite, pUnkSite);
639#else
640 IUnknown *punkOrg = m_pUnkSite;
641 if (punkOrg)
642 punkOrg->Release();
643 m_pUnkSite = pUnkSite;
644 if (pUnkSite)
645 pUnkSite->AddRef();
646#endif
647 return S_OK;
648 }
649 STDMETHODIMP GetSite(REFIID riid, void **ppvSite) override
650 {
651 *ppvSite = NULL;
652 return m_pUnkSite ? m_pUnkSite->QueryInterface(riid, ppvSite) : E_FAIL;
653 }
654};
655
656
657
658#endif /* __cplusplus */
659
660#define S_LESSTHAN 0xffff
661#define S_EQUAL S_OK
662#define S_GREATERTHAN S_FALSE
663#define MAKE_COMPARE_HRESULT(x) ((x)>0 ? S_GREATERTHAN : ((x)<0 ? S_LESSTHAN : S_EQUAL))
664
665#define SEE_CMIC_COMMON_BASICFLAGS (SEE_MASK_NOASYNC | SEE_MASK_ASYNCOK | SEE_MASK_UNICODE | \
666 SEE_MASK_NO_CONSOLE | SEE_MASK_FLAG_NO_UI | SEE_MASK_FLAG_SEPVDM | \
667 SEE_MASK_FLAG_LOG_USAGE | SEE_MASK_NOZONECHECKS)
668#define SEE_CMIC_COMMON_FLAGS (SEE_CMIC_COMMON_BASICFLAGS | SEE_MASK_HOTKEY | SEE_MASK_ICON | \
669 SEE_MASK_HASLINKNAME | SEE_MASK_HASTITLE)
670
672{
673 return uMsg == WM_MEASUREITEM || uMsg == WM_DRAWITEM ||
674 uMsg == WM_INITMENUPOPUP || uMsg == WM_MENUSELECT || uMsg == WM_MENUCHAR;
675}
676
677static inline BOOL ILIsSingle(LPCITEMIDLIST pidl)
678{
679 return pidl == ILFindLastID(pidl);
680}
681
683{
684 return (PCUIDLIST_ABSOLUTE)(((LPBYTE)pida) + (pida)->aoffset[0]);
685}
686
688{
689 return (PCUIDLIST_RELATIVE)(((LPBYTE)pida) + (pida)->aoffset[i + 1]);
690}
691
692
693#ifdef __cplusplus
694
695#if defined(CMIC_MASK_UNICODE) && defined(SEE_MASK_UNICODE)
696static inline bool IsUnicode(const CMINVOKECOMMANDINFOEX &ici)
697{
698 const UINT minsize = FIELD_OFFSET(CMINVOKECOMMANDINFOEX, ptInvoke);
699 return (ici.fMask & CMIC_MASK_UNICODE) && ici.cbSize >= minsize;
700}
701
702static inline bool IsUnicode(const CMINVOKECOMMANDINFO &ici)
703{
704 return IsUnicode(*(CMINVOKECOMMANDINFOEX*)&ici);
705}
706#endif // CMIC_MASK_UNICODE
707
708DECLSPEC_SELECTANY CLIPFORMAT g_cfHIDA = NULL;
709DECLSPEC_SELECTANY CLIPFORMAT g_cfShellIdListOffsets = NULL;
710
711// Allow to use the HIDA from an IDataObject without copying it
712struct CDataObjectHIDA
713{
714private:
715 STGMEDIUM m_medium;
716 CIDA* m_cida;
717 HRESULT m_hr;
718
719public:
720 explicit CDataObjectHIDA(IDataObject* pDataObject)
721 : m_cida(nullptr)
722 {
723 m_hr = CreateCIDA(pDataObject, &m_cida, m_medium);
724 }
725
726 ~CDataObjectHIDA()
727 {
728 DestroyCIDA(m_cida, m_medium);
729 }
730
731 static void DestroyCIDA(CIDA *pcida, STGMEDIUM &medium)
732 {
733 if (pcida)
734 ::GlobalUnlock(medium.hGlobal);
735 ReleaseStgMedium(&medium);
736 }
737
738 static HRESULT CreateCIDA(IDataObject* pDataObject, CIDA **ppcida, STGMEDIUM &medium)
739 {
740 *ppcida = NULL;
741 medium.pUnkForRelease = NULL;
742 if (g_cfHIDA == NULL)
743 g_cfHIDA = (CLIPFORMAT)RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
744
745 FORMATETC fmt = { g_cfHIDA, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
746 HRESULT hr = pDataObject->GetData(&fmt, &medium);
747 if (SUCCEEDED(hr))
748 {
749 *ppcida = (CIDA*)::GlobalLock(medium.hGlobal);
750 if (*ppcida)
751 return S_OK;
752 ReleaseStgMedium(&medium);
754 }
755 medium.tymed = TYMED_NULL;
756 return hr;
757 }
758
759 HRESULT hr() const
760 {
761 return m_hr;
762 }
763
764 operator bool() const
765 {
766 return m_cida != nullptr;
767 }
768
769 operator const CIDA* () const
770 {
771 return m_cida;
772 }
773
774 const CIDA* operator->() const
775 {
776 return m_cida;
777 }
778};
779
780inline
781HRESULT DataObject_GetData(IDataObject* pDataObject, CLIPFORMAT clipformat, PVOID pBuffer, SIZE_T dwBufferSize)
782{
783 FORMATETC fmt = { clipformat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
784 STGMEDIUM medium = { TYMED_NULL };
785
786 HRESULT hr = pDataObject->GetData(&fmt, &medium);
787 if (SUCCEEDED(hr))
788 {
789 LPVOID blob = GlobalLock(medium.hGlobal);
790 if (blob)
791 {
792 SIZE_T size = GlobalSize(medium.hGlobal);
793 if (size <= dwBufferSize)
794 {
796 hr = S_OK;
797 }
798 else
799 {
801 }
802 GlobalUnlock(medium.hGlobal);
803 }
804 else
805 {
807 }
808
809 ReleaseStgMedium(&medium);
810 }
811 return hr;
812}
813
814inline
815HRESULT DataObject_SetData(IDataObject* pDataObject, CLIPFORMAT clipformat, PVOID pBuffer, SIZE_T dwBufferSize)
816{
817 STGMEDIUM medium = { TYMED_HGLOBAL };
818
819 medium.hGlobal = GlobalAlloc(GHND, dwBufferSize);
820 if (!medium.hGlobal)
821 return E_OUTOFMEMORY;
822
824 LPVOID blob = GlobalLock(medium.hGlobal);
825 if (blob)
826 {
827 CopyMemory(blob, pBuffer, dwBufferSize);
828 GlobalUnlock(medium.hGlobal);
829
830 FORMATETC etc = { clipformat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
831 hr = pDataObject->SetData(&etc, &medium, TRUE);
832 }
833
834 if (FAILED(hr))
835 GlobalFree(medium.hGlobal);
836
837 return hr;
838}
839
840
841inline HRESULT
842DataObject_GetOffset(IDataObject *pDataObject, POINT *point)
843{
844 if (g_cfShellIdListOffsets == NULL)
845 {
846 g_cfShellIdListOffsets = (CLIPFORMAT)RegisterClipboardFormatW(CFSTR_SHELLIDLISTOFFSETW);
847 }
848
849 point->x = point->y = 0;
850
851 return DataObject_GetData(pDataObject, g_cfShellIdListOffsets, point, sizeof(point[0]));
852}
853
854inline HRESULT
855DataObject_SetOffset(IDataObject* pDataObject, POINT* point)
856{
857 if (g_cfShellIdListOffsets == NULL)
858 {
859 g_cfShellIdListOffsets = (CLIPFORMAT)RegisterClipboardFormatW(CFSTR_SHELLIDLISTOFFSETW);
860 }
861
862 return DataObject_SetData(pDataObject, g_cfShellIdListOffsets, point, sizeof(point[0]));
863}
864
865#endif // __cplusplus
866
867#ifdef __cplusplus
868struct SHELL_GetSettingImpl
869{
871 SHELL_GetSettingImpl(DWORD ssf) { SHGetSetSettings(&ss, ssf, FALSE); }
872 const SHELLSTATE* operator ->() { return &ss; }
873};
874#define SHELL_GetSetting(ssf, field) ( SHELL_GetSettingImpl(ssf)->field )
875#else
876#define SHELL_GetSetting(pss, ssf, field) ( SHGetSetSettings((pss), (ssf), FALSE), (pss)->field )
877#endif
878
879static inline void DumpIdListOneLine(LPCITEMIDLIST pidl)
880{
881 char buf[1024], *data, drive = 0;
882 for (UINT depth = 0, type; ; pidl = ILGetNext(pidl), ++depth)
883 {
884 if (!pidl || !pidl->mkid.cb)
885 {
886 if (!depth)
887 {
888 wsprintfA(buf, "%p [] (%s)\n", pidl, pidl ? "Empty/Desktop" : "NULL");
890 }
891 break;
892 }
893 else if (!depth)
894 {
895 wsprintfA(buf, "%p", pidl);
897 }
898 type = pidl->mkid.abID[0] & 0x7f;
899 data = (char*)&pidl->mkid.abID[0];
900 if (depth == 0 && type == 0x1f && pidl->mkid.cb == 20 && *(UINT*)(&data[2]) == 0x20D04FE0)
901 {
902 wsprintfA(buf, " [%.2x ThisPC?]", type); /* "?" because we did not check the full GUID */
903 }
904 else if (depth == 1 && type >= 0x20 && type < 0x30 && type != 0x2E && pidl->mkid.cb > 4)
905 {
906 drive = data[1];
907 wsprintfA(buf, " [%.2x %c: %ub]", type, drive, pidl->mkid.cb);
908 }
909 else if (depth >= 2 && drive && (type & 0x70) == 0x30) /* PT_FS */
910 {
911 if (type & 4)
912 wsprintfA(buf, " [%.2x FS %.256ls %ub]", type, data + 12, pidl->mkid.cb);
913 else
914 wsprintfA(buf, " [%.2x FS %.256hs %ub]", type, data + 12, pidl->mkid.cb);
915 }
916 else
917 {
918 wsprintfA(buf, " [%.2x ? %ub]", type, pidl->mkid.cb);
919 }
921 }
922 OutputDebugStringA("\n");
923}
924
925#endif /* __ROS_SHELL_UTILS_H */
#define ATLASSERT(x)
Definition: CComVariant.cpp:10
#define __inline
Definition: _wctype.cpp:15
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define ATLTRY(x)
Definition: atlcomcli.h:44
BOOL Error
Definition: chkdsk.c:66
#define STDMETHODIMP
Definition: basetyps.h:43
#define STDMETHOD_(t, m)
Definition: basetyps.h:63
#define STDMETHOD(m)
Definition: basetyps.h:62
const GUID IID_IUnknown
_In_ BOOLEAN Release
Definition: cdrom.h:920
HINSTANCE hInstance
Definition: charmap.c:19
static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv)
Definition: atlcom.h:424
Definition: ehthrow.cxx:54
Definition: bufpool.h:45
wcscpy
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_FAIL
Definition: ddrawi.h:102
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define P(row, col)
#define MAX_PATH
Definition: compat.h:34
#define LoadLibraryW(x)
Definition: compat.h:747
static HRESULT WINAPI DataObject_GetData(LPDATAOBJECT iface, LPFORMATETC pformatetcIn, STGMEDIUM *pmedium)
Definition: view.c:175
static HRESULT WINAPI DataObject_SetData(LPDATAOBJECT iface, LPFORMATETC pformatetc, STGMEDIUM *pmedium, BOOL fRelease)
Definition: view.c:203
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
HRESULT SHILClone(_In_opt_ LPCITEMIDLIST pidl, _Outptr_ LPITEMIDLIST *ppidl)
Definition: utils.cpp:133
VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
Definition: ordinal.c:2190
#define __FUNCTION__
Definition: types.h:116
POINTL point
Definition: edittest.c:50
return nullptr
Definition: expand.cpp:78
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
HGLOBAL NTAPI GlobalFree(HGLOBAL hMem)
Definition: heapmem.c:611
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
HGLOBAL NTAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:368
SIZE_T NTAPI GlobalSize(HGLOBAL hMem)
Definition: heapmem.c:1090
#define ss
Definition: i386-dis.c:441
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
void WINAPI SHIM_OBJ_NAME() OutputDebugStringA(LPCSTR lpOutputString)
Definition: ignoredbgout.c:18
int __cdecl vsprintf(char *_Dest, const char *_Format, va_list _Args)
Definition: sprintf.c:733
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
static CInternetFolder * CreateInstance(void)
Definition: inetfolder.c:330
HRESULT SetData([in, unique] FORMATETC *pformatetc, [in, unique] STGMEDIUM *pmedium, [in] BOOL fRelease)
HRESULT GetData([in, unique] FORMATETC *pformatetcIn, [out] STGMEDIUM *pmedium)
HRESULT GetSite([in] REFIID riid, [out, iid_is(riid)] PVOID *ppvSite)
HRESULT SetSite([in] IUnknown *pUnkSite)
ULONG AddRef()
HRESULT QueryInterface([in] REFIID riid, [out, iid_is(riid)] void **ppvObject)
ULONG Release()
#define InterlockedCompareExchangePointer
Definition: interlocked.h:144
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
const char * filename
Definition: ioapi.h:137
#define T
Definition: mbstring.h:31
if(dx< 0)
Definition: linetemp.h:194
#define HResultFromWin32
Definition: loader.cpp:14
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static const WCHAR label[]
Definition: itemdlg.c:1546
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:202
#define H
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
static HRESULT QueryInterface(REFIID, void **)
Definition: events.c:2587
static const DWORD padding[]
Definition: mciwnd.c:89
static ULONG WINAPI AddRef(IStream *iface)
Definition: clist.c:90
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
static HMENU hmenu
Definition: win.c:66
unsigned int UINT
Definition: ndis.h:50
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2478
#define bool
Definition: nsiface.idl:72
#define L(x)
Definition: ntvdm.h:50
LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl)
Definition: pidl.c:237
LPITEMIDLIST WINAPI ILFindLastID(LPCITEMIDLIST pidl)
Definition: pidl.c:198
LPITEMIDLIST WINAPI ILCombine(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
Definition: pidl.c:816
LPITEMIDLIST WINAPI ILGetNext(LPCITEMIDLIST pidl)
Definition: pidl.c:970
#define DECLSPEC_SELECTANY
Definition: guiddef.h:40
#define REFIID
Definition: guiddef.h:118
PVOID pBuffer
const WCHAR * str
_CRT_RESTORE_GCC_WARNINGS _CRT_DISABLE_GCC_WARNINGS _Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
strcpy
Definition: string.h:131
short sh
Definition: format.c:272
#define R(b, x)
Definition: sha2.c:134
VOID WINAPI SHGetSetSettings(LPSHELLSTATE lpss, DWORD dwMask, BOOL bSet)
Definition: shellord.c:225
#define DbgPrint(fmt,...)
Definition: shellutils.h:59
static PCUIDLIST_RELATIVE HIDA_GetPIDLItem(CIDA const *pida, SIZE_T i)
Definition: shellutils.h:687
static BOOL SHELL_IsContextMenuMsg(UINT uMsg)
Definition: shellutils.h:671
static BOOL _ROS_FAILED_HELPER(HRESULT hr, const char *expr, const char *filename, int line)
Definition: shellutils.h:78
static PCUIDLIST_ABSOLUTE HIDA_GetPIDLFolder(CIDA const *pida)
Definition: shellutils.h:682
static ULONG Win32DbgPrint(const char *filename, int line, const char *lpFormat,...)
Definition: shellutils.h:27
static UINT SHELL_ErrorBoxHelper(HWND hwndOwner, UINT Error)
Definition: shellutils.h:98
static BOOL ILIsSingle(LPCITEMIDLIST pidl)
Definition: shellutils.h:677
static void DumpIdListOneLine(LPCITEMIDLIST pidl)
Definition: shellutils.h:879
#define SHELL_ErrorBox
Definition: shellutils.h:126
HRESULT hr
Definition: shlfolder.c:183
static const WCHAR CFSTR_SHELLIDLISTOFFSETW[]
Definition: shlobj.h:516
static const WCHAR CFSTR_SHELLIDLISTW[]
Definition: shlobj.h:514
@ STRRET_CSTR
Definition: shtypes.idl:87
@ STRRET_WSTR
Definition: shtypes.idl:85
const ITEMIDLIST_ABSOLUTE UNALIGNED * PCUIDLIST_ABSOLUTE
Definition: shtypes.idl:63
const ITEMIDLIST_RELATIVE UNALIGNED * PCUIDLIST_RELATIVE
Definition: shtypes.idl:57
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define _countof(array)
Definition: sndvol32.h:70
Definition: shlobj.h:580
LONG y
Definition: windef.h:330
LONG x
Definition: windef.h:329
char cStr[MAX_PATH]
Definition: shtypes.idl:98
UINT uType
Definition: shtypes.idl:93
LPWSTR pOleStr
Definition: shtypes.idl:96
Definition: image.c:134
Definition: query.h:86
Definition: fci.c:127
Definition: dsound.c:943
Definition: parser.c:49
LPWSTR dwTypeData
Definition: winuser.h:3280
LPCWSTR lpFormat
Definition: trayclock.cpp:32
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * LPBYTE
Definition: typedefs.h:53
ULONG_PTR SIZE_T
Definition: typedefs.h:80
uint32_t ULONG
Definition: typedefs.h:59
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define FORMAT_MESSAGE_IGNORE_INSERTS
Definition: winbase.h:447
#define CopyMemory
Definition: winbase.h:1742
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:450
#define GHND
Definition: winbase.h:324
_In_ void _In_ PCCERT_CONTEXT _In_opt_ LPFILETIME _In_ DWORD _In_ DWORD _Outptr_opt_ void ** ppvObject
Definition: wincrypt.h:6082
#define WINAPI
Definition: msvc.h:6
#define STG_E_INVALIDHANDLE
Definition: winerror.h:2569
#define CLASS_E_NOAGGREGATION
Definition: winerror.h:2662
#define E_UNEXPECTED
Definition: winerror.h:2456
#define HRESULT_FROM_WIN32(x)
Definition: winerror.h:92
#define E_POINTER
Definition: winerror.h:2365
#define ERROR_INTERNAL_ERROR
Definition: winerror.h:840
#define MIIM_STRING
Definition: winuser.h:738
#define MIIM_ID
Definition: winuser.h:733
int WINAPI GetMenuItemCount(_In_opt_ HMENU)
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
#define MIIM_FTYPE
Definition: winuser.h:740
UINT WINAPI RegisterClipboardFormatW(_In_ LPCWSTR)
#define MFT_SEPARATOR
Definition: winuser.h:755
int WINAPI MessageBoxW(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType)
int WINAPIV wsprintfA(_Out_ LPSTR, _In_ _Printf_format_string_ LPCSTR,...)
#define WM_DRAWITEM
Definition: winuser.h:1656
#define MIIM_STATE
Definition: winuser.h:732
#define MIIM_SUBMENU
Definition: winuser.h:734
#define WM_MENUCHAR
Definition: winuser.h:1759
#define WM_INITMENUPOPUP
Definition: winuser.h:1757
#define MFT_BITMAP
Definition: winuser.h:749
#define MB_OK
Definition: winuser.h:801
#define WM_MEASUREITEM
Definition: winuser.h:1657
BOOL WINAPI GetMenuItemInfoW(_In_ HMENU, _In_ UINT, _In_ BOOL, _Inout_ LPMENUITEMINFOW)
#define MB_ICONSTOP
Definition: winuser.h:814
#define WM_MENUSELECT
Definition: winuser.h:1758
BOOL WINAPI IsWindowVisible(_In_ HWND)
const char * LPCSTR
Definition: xmlstorage.h:183
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193