+++ /dev/null
-/*
- * Copyright 2003, 2004, 2005 Martin Fuchs
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-
- //
- // Explorer clone
- //
- // shellclasses.h
- //
- // C++ wrapper classes for COM interfaces and shell objects
- //
- // Martin Fuchs, 20.07.2003
- //
-
-
- // windows shell headers
-#include <shellapi.h>
-#include <shlobj.h>
-
-/*@@
-#if _MSC_VER>=1300 // VS.Net
-#include <comdefsp.h>
-using namespace _com_util;
-#endif
-*/
-
-#ifndef _INC_COMUTIL // is comutil.h of MS headers not available?
-#ifndef _NO_COMUTIL
-#define _NO_COMUTIL
-#endif
-#endif
-
- // work around GCC's wide string constant bug when compiling inline functions
-#ifdef __GNUC__
-extern const LPCTSTR sCFSTR_SHELLIDLIST;
-#undef CFSTR_SHELLIDLIST
-#define CFSTR_SHELLIDLIST sCFSTR_SHELLIDLIST
-#endif
-
-#ifdef _MSC_VER
-#define NOVTABLE __declspec(novtable)
-#else
-#define NOVTABLE
-#endif
-#define ANSUNC
-
-
- // Exception Handling
-
-#ifndef _NO_COMUTIL
-
-#define COMExceptionBase _com_error
-
-#else
-
- /// COM ExceptionBase class as replacement for _com_error
-struct COMExceptionBase
-{
- COMExceptionBase(HRESULT hr)
- : _hr(hr)
- {
- }
-
- HRESULT Error() const
- {
- return _hr;
- }
-
- LPCTSTR ErrorMessage() const
- {
- if (_msg.empty()) {
- LPTSTR pBuf;
-
- if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
- 0, _hr, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPTSTR)&pBuf, 0, NULL)) {
- _msg = pBuf;
- LocalFree(pBuf);
- } else {
- TCHAR buffer[128];
- _sntprintf(buffer, COUNTOF(buffer), TEXT("unknown Exception: 0x%08lX"), _hr);
- _msg = buffer;
- }
- }
-
- return _msg;
- }
-
-protected:
- HRESULT _hr;
- mutable String _msg;
-};
-
-#endif
-
-
- /// Exception with context information
-
-struct COMException : public COMExceptionBase
-{
- typedef COMExceptionBase super;
-
- COMException(HRESULT hr)
- : super(hr),
- _context(CURRENT_CONTEXT),
- _file(NULL), _line(0)
- {
- LOG(toString());
- LOG(CURRENT_CONTEXT.getStackTrace());
- }
-
- COMException(HRESULT hr, const char* file, int line)
- : super(hr),
- _context(CURRENT_CONTEXT),
- _file(file), _line(line)
- {
- LOG(toString());
- LOG(CURRENT_CONTEXT.getStackTrace());
- }
-
- COMException(HRESULT hr, const String& obj)
- : super(hr),
- _context(CURRENT_CONTEXT),
- _file(NULL), _line(0)
- {
- LOG(toString());
- LOG(CURRENT_CONTEXT.getStackTrace());
- }
-
- COMException(HRESULT hr, const String& obj, const char* file, int line)
- : super(hr),
- _context(CURRENT_CONTEXT),
- _file(file), _line(line)
- {
- LOG(toString());
- LOG(CURRENT_CONTEXT.getStackTrace());
- }
-
- String toString() const;
-
- Context _context;
-
- const char* _file;
- int _line;
-};
-
-#define THROW_EXCEPTION(hr) throw COMException(hr, __FILE__, __LINE__)
-#define CHECKERROR(hr) ((void)(FAILED(hr)? THROW_EXCEPTION(hr): 0))
-
-
-#ifdef _NO_COMUTIL
-
-inline void CheckError(HRESULT hr)
-{
- if (FAILED(hr))
- throw COMException(hr);
-}
-
-#endif
-
-
- /// COM Initialisation
-
-struct ComInit
-{
- ComInit()
- {
- CHECKERROR(CoInitialize(0));
- }
-
-#if (_WIN32_WINNT>=0x0400) || defined(_WIN32_DCOM)
- ComInit(DWORD flag)
- {
- CHECKERROR(CoInitializeEx(0, flag));
- }
-#endif
-
- ~ComInit()
- {
- CoUninitialize();
- }
-};
-
-
- /// OLE initialisation for drag drop support
-
-struct OleInit
-{
- OleInit()
- {
- CHECKERROR(OleInitialize(0));
- }
-
- ~OleInit()
- {
- OleUninitialize();
- }
-};
-
-
- /// Exception Handler for COM exceptions
-
-extern void HandleException(COMException& e, HWND hwnd);
-
-
- /// We use a common IMalloc object for all shell memory allocations.
-
-struct CommonShellMalloc
-{
- CommonShellMalloc()
- {
- _p = NULL;
- }
-
- void init()
- {
- if (!_p)
- CHECKERROR(SHGetMalloc(&_p));
- }
-
- ~CommonShellMalloc()
- {
- if (_p)
- _p->Release();
- }
-
- operator IMalloc*()
- {
- return _p;
- }
-
- IMalloc* _p;
-};
-
-
- /// wrapper class for IMalloc with usage of common allocator
-
-struct ShellMalloc
-{
- ShellMalloc()
- {
- // initialize s_cmn_shell_malloc
- s_cmn_shell_malloc.init();
- }
-
- IMalloc* operator->()
- {
- return s_cmn_shell_malloc;
- }
-
- static CommonShellMalloc s_cmn_shell_malloc;
-};
-
-
- /// wrapper template class for pointers to shell objects managed by IMalloc
-
-template<typename T> struct SShellPtr
-{
- ~SShellPtr()
- {
- _malloc->Free(_p);
- }
-
- T* operator->()
- {
- return _p;
- }
-
- T const* operator->() const
- {
- return _p;
- }
-
- operator T const *() const
- {
- return _p;
- }
-
- const T& operator*() const
- {
- return *_p;
- }
-
- T& operator*()
- {
- return *_p;
- }
-
-protected:
- SShellPtr()
- : _p(0)
- {
- }
-
- SShellPtr(T* p)
- : _p(p)
- {
- }
-
- void Free()
- {
- _malloc->Free(_p);
- _p = NULL;
- }
-
- T* _p;
- mutable ShellMalloc _malloc; // IMalloc memory management object
-
-private:
- // disallow copying of SShellPtr objects
- SShellPtr(const SShellPtr&) {}
- void operator=(SShellPtr const&) {}
-};
-
-
- /// wrapper class for COM interface pointers
-
-template<typename T> struct SIfacePtr
-{
- SIfacePtr()
- : _p(0)
- {
- }
-
- SIfacePtr(T* p)
- : _p(p)
- {
- if (p)
- p->AddRef();
- }
-
- SIfacePtr(IUnknown* unknown, REFIID riid)
- {
- CHECKERROR(unknown->QueryInterface(riid, (LPVOID*)&_p));
- }
-
- ~SIfacePtr()
- {
- Free();
- }
-
- T* operator->()
- {
- return _p;
- }
-
- const T* operator->() const
- {
- return _p;
- }
-
-/* not GCC compatible
- operator const T*() const
- {
- return _p;
- } */
-
- operator T*()
- {
- return _p;
- }
-
- T** operator&()
- {
- return &_p;
- }
-
- bool empty() const //NOTE: GCC seems not to work correctly when defining operator bool() AND operator T*() at one time
- {
- return !_p;
- }
-
- SIfacePtr& operator=(T* p)
- {
- Free();
-
- if (p) {
- p->AddRef();
- _p = p;
- }
-
- return *this;
- }
-
- void operator=(SIfacePtr const& o)
- {
- T* h = _p;
-
- if (o._p)
- o._p->AddRef();
-
- _p = o._p;
-
- if (h)
- h->Release();
- }
-
- HRESULT CreateInstance(REFIID clsid, REFIID riid)
- {
- return CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, riid, (LPVOID*)&_p);
- }
-
- template<typename I> HRESULT QueryInterface(REFIID riid, I* p)
- {
- return _p->QueryInterface(riid, (LPVOID*)p);
- }
-
- T* get()
- {
- return _p;
- }
-
- void Free()
- {
- T* h = _p;
- _p = NULL;
-
- if (h)
- h->Release();
- }
-
-protected:
- SIfacePtr(const SIfacePtr& o)
- : _p(o._p)
- {
- if (_p)
- _p->AddRef();
- }
-
- T* _p;
-};
-
-
-struct NOVTABLE ComSrvObject // NOVTABLE erlaubt, da protected Destruktor
-{
-protected:
- ComSrvObject() : _ref(1) {}
- virtual ~ComSrvObject() {}
-
- ULONG _ref;
-};
-
-struct SimpleComObject : public ComSrvObject
-{
- ULONG IncRef() {return ++_ref;}
- ULONG DecRef() {ULONG ref=--_ref; if (!ref) {_ref++; delete this;} return ref;}
-};
-
-
- // server object interfaces
-
-template<typename BASE> struct IComSrvQI : public BASE
-{
- IComSrvQI(REFIID uuid_base)
- : _uuid_base(uuid_base)
- {
- }
-
- STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppv)
- {
- *ppv = NULL;
-
- if (IsEqualIID(riid, _uuid_base) || IsEqualIID(riid, IID_IUnknown))
- {*ppv=static_cast<BASE*>(this); this->AddRef(); return S_OK;}
-
- return E_NOINTERFACE;
- }
-
-protected:
- IComSrvQI() {}
- virtual ~IComSrvQI() {}
-
- REFIID _uuid_base;
-};
-
-template<> struct IComSrvQI<IUnknown> : public IUnknown
-{
- STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppv)
- {
- *ppv = NULL;
-
- if (IsEqualIID(riid, IID_IUnknown))
- {*ppv=this; AddRef(); return S_OK;}
-
- return E_NOINTERFACE;
- }
-
-protected:
- IComSrvQI<IUnknown>() {}
- virtual ~IComSrvQI<IUnknown>() {}
-};
-
-
-template<typename BASE, typename OBJ>
- class IComSrvBase : public IComSrvQI<BASE>
-{
- typedef IComSrvQI<BASE> super;
-
-protected:
- IComSrvBase(REFIID uuid_base)
- : super(uuid_base)
- {
- }
-
-public:
- STDMETHODIMP_(ULONG) AddRef() {return static_cast<OBJ*>(this)->IncRef();}
- STDMETHODIMP_(ULONG) Release() {return static_cast<OBJ*>(this)->DecRef();}
-};
-
-
-
-struct ShellFolder;
-
-
- /// caching of desktop ShellFolder object
-
-struct CommonDesktop
-{
- CommonDesktop()
- {
- _desktop = 0;
- }
-
- ~CommonDesktop();
-
- void init();
-
- operator ShellFolder&()
- {
- return *_desktop;
- }
-
-protected:
- ShellFolder* _desktop;
-};
-
-
-#ifndef _NO_COMUTIL // _com_ptr available?
-
- /// IShellFolder smart pointer
-struct ShellFolder : public IShellFolderPtr // IShellFolderPtr uses intrinsic extensions of the VC++ compiler.
-{
- typedef IShellFolderPtr super;
-
- ShellFolder(); // desktop folder
- ShellFolder(IShellFolder* p);
- ShellFolder(IShellFolder* parent, LPCITEMIDLIST pidl);
- ShellFolder(LPCITEMIDLIST pidl);
-
- void attach(IShellFolder* parent, LPCITEMIDLIST pidl);
- String get_name(LPCITEMIDLIST pidl=NULL, SHGDNF flags=SHGDN_NORMAL) const;
-
- bool empty() const {return !operator bool();} //NOTE: see SIfacePtr::empty()
-};
-
-#ifdef UNICODE
-#define IShellLinkPtr IShellLinkWPtr
-#else
-#define IShellLinkPtr IShellLinkAPtr
-#endif
-
- /// IShellLink smart pointer
-struct ShellLinkPtr : public IShellLinkPtr
-{
- typedef IShellLinkPtr super;
-
- ShellLinkPtr(IShellLink* p)
- : super(p)
- {
- p->AddRef();
- }
-
- bool empty() const {return !operator bool();} //NOTE: see SIfacePtr::empty()
-};
-
-#else // _com_ptr not available -> use SIfacePtr
-
- /// IShellFolder smart pointer
-struct ShellFolder : public SIfacePtr<IShellFolder>
-{
- typedef SIfacePtr<IShellFolder> super;
-
- ShellFolder();
- ShellFolder(IShellFolder* p);
- ShellFolder(IShellFolder* parent, LPCITEMIDLIST pidl);
- ShellFolder(LPCITEMIDLIST pidl);
-
- void attach(IShellFolder* parent, LPCITEMIDLIST pidl);
- String get_name(LPCITEMIDLIST pidl, SHGDNF flags=SHGDN_NORMAL) const;
-};
-
- /// IShellLink smart pointer
-struct ShellLinkPtr : public SIfacePtr<IShellLink>
-{
- typedef SIfacePtr<IShellLink> super;
-
- ShellLinkPtr(IShellLink* p)
- : super(p)
- {
- _p->AddRef();
- }
-
-};
-
-#endif
-
-
-extern ShellFolder& GetDesktopFolder();
-
-
-#ifdef UNICODE
-#define path_from_pidl path_from_pidlW
-#else
-#define path_from_pidl path_from_pidlA
-#endif
-
-extern HRESULT path_from_pidlA(IShellFolder* folder, LPCITEMIDLIST pidl, LPSTR buffer, int len);
-extern HRESULT path_from_pidlW(IShellFolder* folder, LPCITEMIDLIST pidl, LPWSTR buffer, int len);
-extern HRESULT name_from_pidl(IShellFolder* folder, LPCITEMIDLIST pidl, LPTSTR buffer, int len, SHGDNF flags);
-
-
- // ILGetSize() was missing in previous versions of MinGW and is not exported from shell32.dll on Windows 2000.
-extern "C" UINT ILGetSize_local(LPCITEMIDLIST pidl);
-#define ILGetSize ILGetSize_local
-
-#if 0
-#ifdef UNICODE // CFSTR_FILENAME was defined wrong in previous versions of MinGW.
-#define CFSTR_FILENAMEW TEXT("FileNameW")
-#undef CFSTR_FILENAME
-#define CFSTR_FILENAME CFSTR_FILENAMEW
-#endif
-#endif
-
-
- /// wrapper class for item ID lists
-
-struct ShellPath : public SShellPtr<ITEMIDLIST>
-{
- typedef SShellPtr<ITEMIDLIST> super;
-
- ShellPath()
- {
- }
-
- ShellPath(IShellFolder* folder, LPCWSTR path)
- {
- CONTEXT("ShellPath::ShellPath(IShellFolder*, LPCWSTR)");
-
- if (path)
- CHECKERROR(folder->ParseDisplayName(0, NULL, (LPOLESTR)path, NULL, &_p, NULL));
- else
- _p = NULL;
- }
-
- ShellPath(LPCWSTR path)
- {
- OBJ_CONTEXT("ShellPath::ShellPath(LPCWSTR)", path);
-
- if (path)
- CHECKERROR(GetDesktopFolder()->ParseDisplayName(0, NULL, (LPOLESTR)path, NULL, &_p, NULL));
- else
- _p = NULL;
- }
-
- ShellPath(IShellFolder* folder, LPCSTR path)
- {
- CONTEXT("ShellPath::ShellPath(IShellFolder*, LPCSTR)");
-
- WCHAR b[MAX_PATH];
-
- if (path) {
- MultiByteToWideChar(CP_ACP, 0, path, -1, b, COUNTOF(b));
- CHECKERROR(folder->ParseDisplayName(0, NULL, b, NULL, &_p, NULL));
- } else
- _p = NULL;
- }
-
- ShellPath(LPCSTR path)
- {
- CONTEXT("ShellPath::ShellPath(LPCSTR)");
-
- WCHAR b[MAX_PATH];
-
- if (path) {
- MultiByteToWideChar(CP_ACP, 0, path, -1, b, COUNTOF(b));
- CHECKERROR(GetDesktopFolder()->ParseDisplayName(0, NULL, b, NULL, &_p, NULL));
- } else
- _p = NULL;
- }
-
- ShellPath(const ShellPath& o)
- : super(NULL)
- {
- //CONTEXT("ShellPath::ShellPath(const ShellPath&)");
-
- if (o._p) {
- int l = ILGetSize(o._p);
- _p = (ITEMIDLIST*) _malloc->Alloc(l);
- if (_p) memcpy(_p, o._p, l);
- }
- }
-
- explicit ShellPath(LPITEMIDLIST p)
- : super(p)
- {
- }
-
- ShellPath(LPCITEMIDLIST p)
- {
- //CONTEXT("ShellPath::ShellPath(LPCITEMIDLIST)");
-
- if (p) {
- int l = ILGetSize(p);
- _p = (ITEMIDLIST*) _malloc->Alloc(l);
- if (_p) memcpy(_p, p, l);
- }
- }
-
- void operator=(const ShellPath& o)
- {
- //CONTEXT("ShellPath::operator=(const ShellPath&)");
-
- ITEMIDLIST* h = _p;
-
- if (o._p) {
- int l = ILGetSize(o._p);
-
- _p = (ITEMIDLIST*) _malloc->Alloc(l);
- if (_p) memcpy(_p, o._p, l);
- }
- else
- _p = NULL;
-
- _malloc->Free(h);
- }
-
- void operator=(ITEMIDLIST* p)
- {
- //CONTEXT("ShellPath::operator=(ITEMIDLIST*)");
-
- ITEMIDLIST* h = _p;
-
- if (p) {
- int l = ILGetSize(p);
- _p = (ITEMIDLIST*) _malloc->Alloc(l);
- if (_p) memcpy(_p, p, l);
- }
- else
- _p = NULL;
-
- _malloc->Free(h);
- }
-
- void operator=(const SHITEMID& o)
- {
- ITEMIDLIST* h = _p;
-
- LPBYTE p = (LPBYTE)_malloc->Alloc(o.cb+2);
- if (p) *(PWORD)((LPBYTE)memcpy(p, &o, o.cb)+o.cb) = 0;
- _p = (ITEMIDLIST*)p;
-
- _malloc->Free(h);
- }
-
- void operator+=(const SHITEMID& o)
- {
- int l0 = ILGetSize(_p);
- LPBYTE p = (LPBYTE)_malloc->Alloc(l0+o.cb);
- int l = l0 - 2;
-
- if (p) {
- memcpy(p, _p, l);
- *(PWORD)((LPBYTE)memcpy(p+l, &o, o.cb)+o.cb) = 0;
- }
-
- _malloc->Free(_p);
- _p = (ITEMIDLIST*)p;
- }
-
- friend bool operator<(const ShellPath& a, const ShellPath& b)
- {
- int la = ILGetSize(a._p);
- int lb = ILGetSize(b._p);
-
- int r = memcmp(a._p, b._p, min(la, lb));
- if (r)
- return r < 0;
- else
- return la < lb;
- }
-
- void assign(LPCITEMIDLIST pidl, size_t size)
- {
- //CONTEXT("ShellPath::assign(LPCITEMIDLIST, size_t)");
-
- ITEMIDLIST* h = _p;
-
- _p = (ITEMIDLIST*) _malloc->Alloc(size+sizeof(USHORT/*SHITEMID::cb*/));
-
- if (_p) {
- memcpy(_p, pidl, size);
- ((ITEMIDLIST*)((LPBYTE)_p+size))->mkid.cb = 0; // terminator
- }
-
- _malloc->Free(h);
- }
-
- void assign(LPCITEMIDLIST pidl)
- {
- //CONTEXT("ShellPath::assign(LPCITEMIDLIST)");
-
- ITEMIDLIST* h = _p;
-
- if (pidl) {
- int l = ILGetSize(pidl);
- _p = (ITEMIDLIST*) _malloc->Alloc(l);
- if (_p) memcpy(_p, pidl, l);
- } else
- _p = NULL;
-
- _malloc->Free(h);
- }
-
- void split(ShellPath& parent, ShellPath& obj) const;
-
- void GetUIObjectOf(REFIID riid, LPVOID* ppvOut, HWND hWnd=0, ShellFolder& sf=GetDesktopFolder());
-
- ShellFolder get_folder()
- {
- return ShellFolder(_p);
- }
-
- ShellFolder get_folder(IShellFolder* parent)
- {
- CONTEXT("ShellPath::get_folder()");
- return ShellFolder(parent, _p);
- }
-
- // convert an item id list from relative to absolute (=relative to the desktop) format
- ShellPath create_absolute_pidl(LPCITEMIDLIST parent_pidl) const;
-};
-
-
-#if defined(__WINE__) && defined(NONAMELESSUNION) // Wine doesn't know of unnamed union members and uses some macros instead.
-#define UNION_MEMBER(x) DUMMYUNIONNAME.##x
-#else
-#define UNION_MEMBER(x) x
-#endif
-
-
- // encapsulation of STRRET structure for easy string retrieval with conversion
-
-#ifdef UNICODE
-#define StrRet StrRetW
-//#define tcscpyn wcscpyn
-#else
-#define StrRet StrRetA
-//#define tcscpyn strcpyn
-#endif
-
-//extern LPSTR strcpyn(LPSTR dest, LPCSTR source, size_t count);
-//extern LPWSTR wcscpyn(LPWSTR dest, LPCWSTR source, size_t count);
-
- /// easy retrieval of multi byte strings out of STRRET structures
-struct StrRetA : public STRRET
-{
- ~StrRetA()
- {
- if (uType == STRRET_WSTR)
- ShellMalloc()->Free(pOleStr);
- }
-
- void GetString(const SHITEMID& shiid, LPSTR b, int l)
- {
- switch(uType) {
- case STRRET_WSTR:
- WideCharToMultiByte(CP_ACP, 0, UNION_MEMBER(pOleStr), -1, b, l, NULL, NULL);
- break;
-
- case STRRET_OFFSET:
- lstrcpynA(b, (LPCSTR)&shiid+UNION_MEMBER(uOffset), l);
- break;
-
- case STRRET_CSTR:
- lstrcpynA(b, UNION_MEMBER(cStr), l);
- }
- }
-};
-
- /// easy retrieval of wide char strings out of STRRET structures
-struct StrRetW : public STRRET
-{
- ~StrRetW()
- {
- if (uType == STRRET_WSTR)
- ShellMalloc()->Free(pOleStr);
- }
-
- void GetString(const SHITEMID& shiid, LPWSTR b, int l)
- {
- switch(uType) {
- case STRRET_WSTR:
- lstrcpynW(b, UNION_MEMBER(pOleStr), l);
- break;
-
- case STRRET_OFFSET:
- MultiByteToWideChar(CP_ACP, 0, (LPCSTR)&shiid+UNION_MEMBER(uOffset), -1, b, l);
- break;
-
- case STRRET_CSTR:
- MultiByteToWideChar(CP_ACP, 0, UNION_MEMBER(cStr), -1, b, l);
- }
- }
-};
-
-
- /// Retrieval of file system paths of ShellPath objects
-class FileSysShellPath : public ShellPath
-{
- TCHAR _fullpath[MAX_PATH];
-
-protected:
- FileSysShellPath() {_fullpath[0] = '\0';}
-
-public:
- FileSysShellPath(const ShellPath& o) : ShellPath(o) {_fullpath[0] = '\0';}
-
- operator LPCTSTR() {if (!SHGetPathFromIDList(_p, _fullpath)) return NULL; return _fullpath;}
-};
-
-
- /// Browse dialog operating on shell namespace
-struct FolderBrowser : public FileSysShellPath
-{
- FolderBrowser(HWND owner, UINT flags, LPCTSTR title, LPCITEMIDLIST root=0)
- {
- _displayname[0] = '\0';
- _browseinfo.hwndOwner = owner;
- _browseinfo.pidlRoot = root;
- _browseinfo.pszDisplayName = _displayname;
- _browseinfo.lpszTitle = title;
- _browseinfo.ulFlags = flags;
- _browseinfo.lpfn = 0;
- _browseinfo.lParam = 0;
- _browseinfo.iImage = 0;
-
- _p = SHBrowseForFolder(&_browseinfo);
- }
-
- LPCTSTR GetDisplayName()
- {
- return _displayname;
- }
-
- bool IsOK()
- {
- return _p != 0;
- }
-
-private:
- BROWSEINFO _browseinfo;
- TCHAR _displayname[MAX_PATH];
-};
-
-
- /// Retrieval of special shell folder paths
-struct SpecialFolderPath : public ShellPath
-{
- SpecialFolderPath(int folder, HWND hwnd)
- {
- HRESULT hr = SHGetSpecialFolderLocation(hwnd, folder, &_p);
- CHECKERROR(hr);
- }
-};
-
- /// Shell folder path of the desktop
-struct DesktopFolderPath : public SpecialFolderPath
-{
- DesktopFolderPath()
- : SpecialFolderPath(CSIDL_DESKTOP, 0)
- {
- }
-};
-
- /// Retrieval of special shell folder
-struct SpecialFolder : public ShellFolder
-{
- SpecialFolder(int folder, HWND hwnd)
- : ShellFolder(GetDesktopFolder(), SpecialFolderPath(folder, hwnd))
- {
- }
-};
-
- /// Shell folder of the desktop
-struct DesktopFolder : public ShellFolder
-{
-};
-
-
- /// file system path of special folder
-struct SpecialFolderFSPath
-{
- SpecialFolderFSPath(int folder/*e.g. CSIDL_DESKTOP*/, HWND hwnd);
-
- operator LPCTSTR()
- {
- return _fullpath;
- }
-
-protected:
- TCHAR _fullpath[MAX_PATH];
-};
-
-/*
- /// file system path of special folder
-struct SpecialFolderFSPath : public FileSysShellPath
-{
- SpecialFolderFSPath(int folder, HWND hwnd)
- {
- CONTEXT("SpecialFolderFSPath::SpecialFolderFSPath()");
-
- HRESULT hr = SHGetSpecialFolderLocation(hwnd, folder, &_p);
- CHECKERROR(hr);
- }
-};
-*/
-
-
- /// wrapper class for enumerating shell namespace objects
-
-struct ShellItemEnumerator : public SIfacePtr<IEnumIDList>
-{
- ShellItemEnumerator(IShellFolder* folder, DWORD flags=SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN)
- {
- CONTEXT("ShellItemEnumerator::ShellItemEnumerator()");
-
- CHECKERROR(folder->EnumObjects(0, flags, &_p));
- }
-};
-
-
- /// list of PIDLs
-struct PIDList
-{
- PIDList()
- {
- memset(&_stgm, 0, sizeof(STGMEDIUM));
- }
-
- ~PIDList()
- {
- if (_stgm.hGlobal) {
- GlobalUnlock(_stgm.hGlobal);
- ReleaseStgMedium(&_stgm);
- }
- }
-
- HRESULT GetData(IDataObject* selection)
- {
- static UINT CF_IDLIST = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
-
- FORMATETC fetc;
- fetc.cfFormat = CF_IDLIST;
- fetc.ptd = NULL;
- fetc.dwAspect = DVASPECT_CONTENT;
- fetc.lindex = -1;
- fetc.tymed = TYMED_HGLOBAL;
-
- HRESULT hr = selection->QueryGetData(&fetc);
- if (FAILED(hr))
- return hr;
-
- hr = selection->GetData(&fetc, &_stgm);
- if (FAILED(hr))
- return hr;
-
- _pIDList = (LPIDA)GlobalLock(_stgm.hGlobal);
-
- return hr;
- }
-
- operator LPIDA() {return _pIDList;}
-
-protected:
- STGMEDIUM _stgm;
- LPIDA _pIDList;
-};
-
-
-struct CtxMenuInterfaces
-{
- CtxMenuInterfaces()
- {
- reset();
- }
-
- void reset();
- bool HandleMenuMsg(UINT nmsg, WPARAM wparam, LPARAM lparam);
- IContextMenu* query_interfaces(IContextMenu* pcm1);
-
- IContextMenu2* _pctxmenu2;
-
- IContextMenu3* _pctxmenu3;
-};
-
-template<typename BASE> struct ExtContextMenuHandlerT
- : public BASE
-{
- typedef BASE super;
-
- ExtContextMenuHandlerT(HWND hwnd)
- : super(hwnd)
- {
- }
-
- template<typename PARA> ExtContextMenuHandlerT(HWND hwnd, const PARA& info)
- : super(hwnd, info)
- {
- }
-
- LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
- {
- switch(nmsg) {
- case WM_DRAWITEM:
- case WM_MEASUREITEM:
- if (!wparam) // Is the message menu-related?
- if (_cm_ifs.HandleMenuMsg(nmsg, wparam, lparam))
- return TRUE;
-
- break;
-
- case WM_INITMENUPOPUP:
- if (_cm_ifs.HandleMenuMsg(nmsg, wparam, lparam))
- return 0;
-
- break;
-
- case WM_MENUCHAR: // only supported by IContextMenu3
- if (_cm_ifs._pctxmenu3) {
- LRESULT lResult = 0;
-
- _cm_ifs._pctxmenu3->HandleMenuMsg2(nmsg, wparam, lparam, &lResult);
-
- return lResult;
- }
-
- return 0;
- }
-
- return super::WndProc(nmsg, wparam, lparam);
- }
-
-protected:
- CtxMenuInterfaces _cm_ifs;
-};
-
-
-extern HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl,
- LPCITEMIDLIST* ppidl, int x, int y, CtxMenuInterfaces& cm_ifs);