shellclasses.h

Go to the documentation of this file.
00001 /*
00002  * Copyright 2003, 2004, 2005 Martin Fuchs
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 
00020  //
00021  // Explorer clone
00022  //
00023  // shellclasses.h
00024  //
00025  // C++ wrapper classes for COM interfaces and shell objects
00026  //
00027  // Martin Fuchs, 20.07.2003
00028  //
00029 
00030 
00031  // windows shell headers
00032 #include <shellapi.h>
00033 #include <shlobj.h>
00034 
00035 /*@@
00036 #if _MSC_VER>=1300  // VS.Net
00037 #include <comdefsp.h>
00038 using namespace _com_util;
00039 #endif
00040 */
00041 
00042 #ifndef _INC_COMUTIL    // is comutil.h of MS headers not available?
00043 #ifndef _NO_COMUTIL
00044 #define _NO_COMUTIL
00045 #endif
00046 #endif
00047 
00048  // work around GCC's wide string constant bug when compiling inline functions
00049 #ifdef __GNUC__
00050 extern const LPCTSTR sCFSTR_SHELLIDLIST;
00051 #undef CFSTR_SHELLIDLIST
00052 #define CFSTR_SHELLIDLIST sCFSTR_SHELLIDLIST
00053 #endif
00054 
00055 #ifdef _MSC_VER
00056 #define NOVTABLE __declspec(novtable)
00057 #else
00058 #define NOVTABLE
00059 #endif
00060 #define ANSUNC
00061 
00062 
00063  // Exception Handling
00064 
00065 #ifndef _NO_COMUTIL
00066 
00067 #define COMExceptionBase _com_error
00068 
00069 #else
00070 
00071  /// COM ExceptionBase class as replacement for _com_error
00072 struct COMExceptionBase
00073 {
00074     COMExceptionBase(HRESULT hr)
00075      :  _hr(hr)
00076     {
00077     }
00078 
00079     HRESULT Error() const
00080     {
00081         return _hr;
00082     }
00083 
00084     LPCTSTR ErrorMessage() const
00085     {
00086         if (_msg.empty()) {
00087             LPTSTR pBuf;
00088 
00089             if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
00090                 0, _hr, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPTSTR)&pBuf, 0, NULL)) {
00091                 _msg = pBuf;
00092                 LocalFree(pBuf);
00093              } else {
00094                 TCHAR buffer[128];
00095                 _sntprintf(buffer, COUNTOF(buffer), TEXT("unknown Exception: 0x%08lX"), _hr);
00096                 _msg = buffer;
00097              }
00098         }
00099 
00100         return _msg;
00101     }
00102 
00103 protected:
00104     HRESULT _hr;
00105     mutable String _msg;
00106 };
00107 
00108 #endif
00109 
00110 
00111  /// Exception with context information
00112 
00113 struct COMException : public COMExceptionBase
00114 {
00115     typedef COMExceptionBase super;
00116 
00117     COMException(HRESULT hr)
00118      :  super(hr),
00119         _context(CURRENT_CONTEXT),
00120         _file(NULL), _line(0)
00121     {
00122         LOG(toString());
00123         LOG(CURRENT_CONTEXT.getStackTrace());
00124     }
00125 
00126     COMException(HRESULT hr, const char* file, int line)
00127      :  super(hr),
00128         _context(CURRENT_CONTEXT),
00129         _file(file), _line(line)
00130     {
00131         LOG(toString());
00132         LOG(CURRENT_CONTEXT.getStackTrace());
00133     }
00134 
00135     COMException(HRESULT hr, const String& obj)
00136      :  super(hr),
00137         _context(CURRENT_CONTEXT),
00138         _file(NULL), _line(0)
00139     {
00140         LOG(toString());
00141         LOG(CURRENT_CONTEXT.getStackTrace());
00142     }
00143 
00144     COMException(HRESULT hr, const String& obj, const char* file, int line)
00145      :  super(hr),
00146         _context(CURRENT_CONTEXT),
00147         _file(file), _line(line)
00148     {
00149         LOG(toString());
00150         LOG(CURRENT_CONTEXT.getStackTrace());
00151     }
00152 
00153     String toString() const;
00154 
00155     Context _context;
00156 
00157     const char* _file;
00158     int _line;
00159 };
00160 
00161 #define THROW_EXCEPTION(hr) throw COMException(hr, __FILE__, __LINE__)
00162 #define CHECKERROR(hr) ((void)(FAILED(hr)? THROW_EXCEPTION(hr): 0))
00163 
00164 
00165 #ifdef _NO_COMUTIL
00166 
00167 inline void CheckError(HRESULT hr)
00168 {
00169     if (FAILED(hr))
00170         throw COMException(hr);
00171 }
00172 
00173 #endif
00174 
00175 
00176  /// COM Initialisation
00177 
00178 struct ComInit
00179 {
00180     ComInit()
00181     {
00182         CHECKERROR(CoInitialize(0));
00183     }
00184 
00185 #if (_WIN32_WINNT>=0x0400) || defined(_WIN32_DCOM)
00186     ComInit(DWORD flag)
00187     {
00188         CHECKERROR(CoInitializeEx(0, flag));
00189     }
00190 #endif
00191 
00192     ~ComInit()
00193     {
00194         CoUninitialize();
00195     }
00196 };
00197 
00198 
00199  /// OLE initialisation for drag drop support
00200 
00201 struct OleInit
00202 {
00203     OleInit()
00204     {
00205         CHECKERROR(OleInitialize(0));
00206     }
00207 
00208     ~OleInit()
00209     {
00210         OleUninitialize();
00211     }
00212 };
00213 
00214 
00215  /// Exception Handler for COM exceptions
00216 
00217 extern void HandleException(COMException& e, HWND hwnd);
00218 
00219 
00220  /// We use a common IMalloc object for all shell memory allocations.
00221 
00222 struct CommonShellMalloc
00223 {
00224     CommonShellMalloc()
00225     {
00226         _p = NULL;
00227     }
00228 
00229     void init()
00230     {
00231         if (!_p)
00232             CHECKERROR(SHGetMalloc(&_p));
00233     }
00234 
00235     ~CommonShellMalloc()
00236     {
00237         if (_p)
00238             _p->Release();
00239     }
00240 
00241     operator IMalloc*()
00242     {
00243         return _p;
00244     }
00245 
00246     IMalloc* _p;
00247 };
00248 
00249 
00250  /// wrapper class for IMalloc with usage of common allocator
00251 
00252 struct ShellMalloc
00253 {
00254     ShellMalloc()
00255     {
00256          // initialize s_cmn_shell_malloc
00257         s_cmn_shell_malloc.init();
00258     }
00259 
00260     IMalloc* operator->()
00261     {
00262         return s_cmn_shell_malloc;
00263     }
00264 
00265     static CommonShellMalloc s_cmn_shell_malloc;
00266 };
00267 
00268 
00269  /// wrapper template class for pointers to shell objects managed by IMalloc
00270 
00271 template<typename T> struct SShellPtr
00272 {
00273     ~SShellPtr()
00274     {
00275         _malloc->Free(_p);
00276     }
00277 
00278     T* operator->()
00279     {
00280         return _p;
00281     }
00282 
00283     T const* operator->() const
00284     {
00285         return _p;
00286     }
00287 
00288     operator T const *() const
00289     {
00290         return _p;
00291     }
00292 
00293     const T& operator*() const
00294     {
00295         return *_p;
00296     }
00297 
00298     T& operator*()
00299     {
00300         return *_p;
00301     }
00302 
00303 protected:
00304     SShellPtr()
00305      :  _p(0)
00306     {
00307     }
00308 
00309     SShellPtr(T* p)
00310      :  _p(p)
00311     {
00312     }
00313 
00314     void Free()
00315     {
00316         _malloc->Free(_p);
00317         _p = NULL;
00318     }
00319 
00320     T* _p;
00321     mutable ShellMalloc _malloc;    // IMalloc memory management object
00322 
00323 private:
00324      // disallow copying of SShellPtr objects
00325     SShellPtr(const SShellPtr&) {}
00326     void operator=(SShellPtr const&) {}
00327 };
00328 
00329 
00330  /// wrapper class for COM interface pointers
00331 
00332 template<typename T> struct SIfacePtr
00333 {
00334     SIfacePtr()
00335      :  _p(0)
00336     {
00337     }
00338 
00339     SIfacePtr(T* p)
00340      :  _p(p)
00341     {
00342         if (p)
00343             p->AddRef();
00344     }
00345 
00346     SIfacePtr(IUnknown* unknown, REFIID riid)
00347     {
00348         CHECKERROR(unknown->QueryInterface(riid, (LPVOID*)&_p));
00349     }
00350 
00351     ~SIfacePtr()
00352     {
00353         Free();
00354     }
00355 
00356     T* operator->()
00357     {
00358         return _p;
00359     }
00360 
00361     const T* operator->() const
00362     {
00363         return _p;
00364     }
00365 
00366 /* not GCC compatible
00367     operator const T*() const
00368     {
00369         return _p;
00370     } */
00371 
00372     operator T*()
00373     {
00374         return _p;
00375     }
00376 
00377     T** operator&()
00378     {
00379         return &_p;
00380     }
00381 
00382     bool empty() const  //NOTE: GCC seems not to work correctly when defining operator bool() AND operator T*() at one time
00383     {
00384         return !_p;
00385     }
00386 
00387     SIfacePtr& operator=(T* p)
00388     {
00389         Free();
00390 
00391         if (p) {
00392             p->AddRef();
00393             _p = p;
00394         }
00395 
00396         return *this;
00397     }
00398 
00399     void operator=(SIfacePtr const& o)
00400     {
00401         T* h = _p;
00402 
00403         if (o._p)
00404             o._p->AddRef();
00405 
00406         _p = o._p;
00407 
00408         if (h)
00409             h->Release();
00410     }
00411 
00412     HRESULT CreateInstance(REFIID clsid, REFIID riid)
00413     {
00414         return CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, riid, (LPVOID*)&_p);
00415     }
00416 
00417     template<typename I> HRESULT QueryInterface(REFIID riid, I* p)
00418     {
00419         return _p->QueryInterface(riid, (LPVOID*)p);
00420     }
00421 
00422     T* get()
00423     {
00424         return _p;
00425     }
00426 
00427     void Free()
00428     {
00429         T* h = _p;
00430         _p = NULL;
00431 
00432         if (h)
00433             h->Release();
00434     }
00435 
00436 protected:
00437     SIfacePtr(const SIfacePtr& o)
00438      :  _p(o._p)
00439     {
00440         if (_p)
00441             _p->AddRef();
00442     }
00443 
00444     T* _p;
00445 };
00446 
00447 
00448 struct NOVTABLE ComSrvObject    // NOVTABLE erlaubt, da protected Destruktor
00449 {
00450 protected:
00451     ComSrvObject() : _ref(1) {}
00452     virtual ~ComSrvObject() {}
00453 
00454     ULONG   _ref;
00455 };
00456 
00457 struct SimpleComObject : public ComSrvObject
00458 {
00459     ULONG IncRef() {return ++_ref;}
00460     ULONG DecRef() {ULONG ref=--_ref; if (!ref) {_ref++; delete this;} return ref;}
00461 };
00462 
00463 
00464  // server object interfaces
00465 
00466 template<typename BASE> struct IComSrvQI : public BASE
00467 {
00468     IComSrvQI(REFIID uuid_base)
00469      :  _uuid_base(uuid_base)
00470     {
00471     }
00472 
00473     STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppv)
00474     {
00475         *ppv = NULL;
00476 
00477         if (IsEqualIID(riid, _uuid_base) || IsEqualIID(riid, IID_IUnknown))
00478             {*ppv=static_cast<BASE*>(this); this->AddRef(); return S_OK;}
00479 
00480         return E_NOINTERFACE;
00481     }
00482 
00483 protected:
00484     IComSrvQI() {}
00485     virtual ~IComSrvQI() {}
00486 
00487     REFIID  _uuid_base;
00488 };
00489 
00490 template<> struct IComSrvQI<IUnknown> : public IUnknown
00491 {
00492     STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppv)
00493     {
00494         *ppv = NULL;
00495 
00496         if (IsEqualIID(riid, IID_IUnknown))
00497             {*ppv=this; AddRef(); return S_OK;}
00498 
00499         return E_NOINTERFACE;
00500     }
00501 
00502 protected:
00503     IComSrvQI<IUnknown>() {}
00504     virtual ~IComSrvQI<IUnknown>() {}
00505 };
00506 
00507 
00508 template<typename BASE, typename OBJ>
00509     class IComSrvBase : public IComSrvQI<BASE>
00510 {
00511     typedef IComSrvQI<BASE> super;
00512 
00513 protected:
00514     IComSrvBase(REFIID uuid_base)
00515      :  super(uuid_base)
00516     {
00517     }
00518 
00519 public:
00520     STDMETHODIMP_(ULONG) AddRef() {return static_cast<OBJ*>(this)->IncRef();}
00521     STDMETHODIMP_(ULONG) Release() {return static_cast<OBJ*>(this)->DecRef();}
00522 };
00523 
00524 
00525 
00526 struct ShellFolder;
00527 
00528 
00529  /// caching of desktop ShellFolder object
00530 
00531 struct CommonDesktop
00532 {
00533     CommonDesktop()
00534     {
00535         _desktop = 0;
00536     }
00537 
00538     ~CommonDesktop();
00539 
00540     void init();
00541 
00542     operator ShellFolder&()
00543     {
00544         return *_desktop;
00545     }
00546 
00547 protected:
00548     ShellFolder* _desktop;
00549 };
00550 
00551 
00552 #ifndef _NO_COMUTIL // _com_ptr available?
00553 
00554  /// IShellFolder smart pointer
00555 struct ShellFolder : public IShellFolderPtr // IShellFolderPtr uses intrinsic extensions of the VC++ compiler.
00556 {
00557     typedef IShellFolderPtr super;
00558 
00559     ShellFolder();  // desktop folder
00560     ShellFolder(IShellFolder* p);
00561     ShellFolder(IShellFolder* parent, LPCITEMIDLIST pidl);
00562     ShellFolder(LPCITEMIDLIST pidl);
00563 
00564     void    attach(IShellFolder* parent, LPCITEMIDLIST pidl);
00565     String  get_name(LPCITEMIDLIST pidl=NULL, SHGDNF flags=SHGDN_NORMAL) const;
00566 
00567     bool    empty() const {return !operator bool();}    //NOTE: see SIfacePtr::empty()
00568 };
00569 
00570 #ifdef UNICODE
00571 #define IShellLinkPtr IShellLinkWPtr
00572 #else
00573 #define IShellLinkPtr IShellLinkAPtr
00574 #endif
00575 
00576  /// IShellLink smart pointer
00577 struct ShellLinkPtr : public IShellLinkPtr
00578 {
00579     typedef IShellLinkPtr super;
00580 
00581     ShellLinkPtr(IShellLink* p)
00582      :  super(p)
00583     {
00584         p->AddRef();
00585     }
00586 
00587     bool    empty() const {return !operator bool();}    //NOTE: see SIfacePtr::empty()
00588 };
00589 
00590 #else // _com_ptr not available -> use SIfacePtr
00591 
00592  /// IShellFolder smart pointer
00593 struct ShellFolder : public SIfacePtr<IShellFolder>
00594 {
00595     typedef SIfacePtr<IShellFolder> super;
00596 
00597     ShellFolder();
00598     ShellFolder(IShellFolder* p);
00599     ShellFolder(IShellFolder* parent, LPCITEMIDLIST pidl);
00600     ShellFolder(LPCITEMIDLIST pidl);
00601 
00602     void    attach(IShellFolder* parent, LPCITEMIDLIST pidl);
00603     String  get_name(LPCITEMIDLIST pidl, SHGDNF flags=SHGDN_NORMAL) const;
00604 };
00605 
00606  /// IShellLink smart pointer
00607 struct ShellLinkPtr : public SIfacePtr<IShellLink>
00608 {
00609     typedef SIfacePtr<IShellLink> super;
00610 
00611     ShellLinkPtr(IShellLink* p)
00612      :  super(p)
00613     {
00614         _p->AddRef();
00615     }
00616 
00617 };
00618 
00619 #endif
00620 
00621 
00622 extern ShellFolder& GetDesktopFolder();
00623 
00624 
00625 #ifdef UNICODE
00626 #define path_from_pidl path_from_pidlW
00627 #else
00628 #define path_from_pidl path_from_pidlA
00629 #endif
00630 
00631 extern HRESULT path_from_pidlA(IShellFolder* folder, LPCITEMIDLIST pidl, LPSTR buffer, int len);
00632 extern HRESULT path_from_pidlW(IShellFolder* folder, LPCITEMIDLIST pidl, LPWSTR buffer, int len);
00633 extern HRESULT name_from_pidl(IShellFolder* folder, LPCITEMIDLIST pidl, LPTSTR buffer, int len, SHGDNF flags);
00634 
00635 
00636  // ILGetSize() was missing in previous versions of MinGW and is not exported from shell32.dll on Windows 2000.
00637 extern "C" UINT ILGetSize_local(LPCITEMIDLIST pidl);
00638 #define ILGetSize ILGetSize_local
00639 
00640 #if 0
00641 #ifdef UNICODE      // CFSTR_FILENAME was defined wrong in previous versions of MinGW.
00642 #define CFSTR_FILENAMEW TEXT("FileNameW")
00643 #undef CFSTR_FILENAME
00644 #define CFSTR_FILENAME CFSTR_FILENAMEW
00645 #endif
00646 #endif
00647 
00648 
00649  /// wrapper class for item ID lists
00650 
00651 struct ShellPath : public SShellPtr<ITEMIDLIST>
00652 {
00653     typedef SShellPtr<ITEMIDLIST> super;
00654 
00655     ShellPath()
00656     {
00657     }
00658 
00659     ShellPath(IShellFolder* folder, LPCWSTR path)
00660     {
00661         CONTEXT("ShellPath::ShellPath(IShellFolder*, LPCWSTR)");
00662 
00663         if (path)
00664             CHECKERROR(folder->ParseDisplayName(0, NULL, (LPOLESTR)path, NULL, &_p, NULL));
00665         else
00666             _p = NULL;
00667     }
00668 
00669     ShellPath(LPCWSTR path)
00670     {
00671         OBJ_CONTEXT("ShellPath::ShellPath(LPCWSTR)", path);
00672 
00673         if (path)
00674             CHECKERROR(GetDesktopFolder()->ParseDisplayName(0, NULL, (LPOLESTR)path, NULL, &_p, NULL));
00675         else
00676             _p = NULL;
00677     }
00678 
00679     ShellPath(IShellFolder* folder, LPCSTR path)
00680     {
00681         CONTEXT("ShellPath::ShellPath(IShellFolder*, LPCSTR)");
00682 
00683         WCHAR b[MAX_PATH];
00684 
00685         if (path) {
00686             MultiByteToWideChar(CP_ACP, 0, path, -1, b, COUNTOF(b));
00687             CHECKERROR(folder->ParseDisplayName(0, NULL, b, NULL, &_p, NULL));
00688         } else
00689             _p = NULL;
00690     }
00691 
00692     ShellPath(LPCSTR path)
00693     {
00694         CONTEXT("ShellPath::ShellPath(LPCSTR)");
00695 
00696         WCHAR b[MAX_PATH];
00697 
00698         if (path) {
00699             MultiByteToWideChar(CP_ACP, 0, path, -1, b, COUNTOF(b));
00700             CHECKERROR(GetDesktopFolder()->ParseDisplayName(0, NULL, b, NULL, &_p, NULL));
00701         } else
00702             _p = NULL;
00703     }
00704 
00705     ShellPath(const ShellPath& o)
00706      :  super(NULL)
00707     {
00708         //CONTEXT("ShellPath::ShellPath(const ShellPath&)");
00709 
00710         if (o._p) {
00711             int l = ILGetSize(o._p);
00712             _p = (ITEMIDLIST*) _malloc->Alloc(l);
00713             if (_p) memcpy(_p, o._p, l);
00714         }
00715     }
00716 
00717     explicit ShellPath(LPITEMIDLIST p)
00718      :  super(p)
00719     {
00720     }
00721 
00722     ShellPath(LPCITEMIDLIST p)
00723     {
00724         //CONTEXT("ShellPath::ShellPath(LPCITEMIDLIST)");
00725 
00726         if (p) {
00727             int l = ILGetSize(p);
00728             _p = (ITEMIDLIST*) _malloc->Alloc(l);
00729             if (_p) memcpy(_p, p, l);
00730         }
00731     }
00732 
00733     void operator=(const ShellPath& o)
00734     {
00735         //CONTEXT("ShellPath::operator=(const ShellPath&)");
00736 
00737         ITEMIDLIST* h = _p;
00738 
00739         if (o._p) {
00740             int l = ILGetSize(o._p);
00741 
00742             _p = (ITEMIDLIST*) _malloc->Alloc(l);
00743             if (_p) memcpy(_p, o._p, l);
00744         }
00745         else
00746             _p = NULL;
00747 
00748         _malloc->Free(h);
00749     }
00750 
00751     void operator=(ITEMIDLIST* p)
00752     {
00753         //CONTEXT("ShellPath::operator=(ITEMIDLIST*)");
00754 
00755         ITEMIDLIST* h = _p;
00756 
00757         if (p) {
00758             int l = ILGetSize(p);
00759             _p = (ITEMIDLIST*) _malloc->Alloc(l);
00760             if (_p) memcpy(_p, p, l);
00761         }
00762         else
00763             _p = NULL;
00764 
00765         _malloc->Free(h);
00766     }
00767 
00768     void operator=(const SHITEMID& o)
00769     {
00770         ITEMIDLIST* h = _p;
00771 
00772         LPBYTE p = (LPBYTE)_malloc->Alloc(o.cb+2);
00773         if (p) *(PWORD)((LPBYTE)memcpy(p, &o, o.cb)+o.cb) = 0;
00774         _p = (ITEMIDLIST*)p;
00775 
00776         _malloc->Free(h);
00777     }
00778 
00779     void operator+=(const SHITEMID& o)
00780     {
00781         int l0 = ILGetSize(_p);
00782         LPBYTE p = (LPBYTE)_malloc->Alloc(l0+o.cb);
00783         int l = l0 - 2;
00784 
00785         if (p) {
00786             memcpy(p, _p, l);
00787             *(PWORD)((LPBYTE)memcpy(p+l, &o, o.cb)+o.cb) = 0;
00788         }
00789 
00790         _malloc->Free(_p);
00791         _p = (ITEMIDLIST*)p;
00792     }
00793 
00794     friend bool operator<(const ShellPath& a, const ShellPath& b)
00795     {
00796         int la = ILGetSize(a._p);
00797         int lb = ILGetSize(b._p);
00798 
00799         int r = memcmp(a._p, b._p, min(la, lb));
00800         if (r)
00801             return r < 0;
00802         else
00803             return la < lb;
00804     }
00805 
00806     void assign(LPCITEMIDLIST pidl, size_t size)
00807     {
00808         //CONTEXT("ShellPath::assign(LPCITEMIDLIST, size_t)");
00809 
00810         ITEMIDLIST* h = _p;
00811 
00812         _p = (ITEMIDLIST*) _malloc->Alloc(size+sizeof(USHORT/*SHITEMID::cb*/));
00813 
00814         if (_p) {
00815             memcpy(_p, pidl, size);
00816             ((ITEMIDLIST*)((LPBYTE)_p+size))->mkid.cb = 0; // terminator
00817         }
00818 
00819         _malloc->Free(h);
00820     }
00821 
00822     void assign(LPCITEMIDLIST pidl)
00823     {
00824         //CONTEXT("ShellPath::assign(LPCITEMIDLIST)");
00825 
00826         ITEMIDLIST* h = _p;
00827 
00828         if (pidl) {
00829             int l = ILGetSize(pidl);
00830             _p = (ITEMIDLIST*) _malloc->Alloc(l);
00831             if (_p) memcpy(_p, pidl, l);
00832         } else
00833             _p = NULL;
00834 
00835         _malloc->Free(h);
00836     }
00837 
00838     void split(ShellPath& parent, ShellPath& obj) const;
00839 
00840     void GetUIObjectOf(REFIID riid, LPVOID* ppvOut, HWND hWnd=0, ShellFolder& sf=GetDesktopFolder());
00841 
00842     ShellFolder get_folder()
00843     {
00844         return ShellFolder(_p);
00845     }
00846 
00847     ShellFolder get_folder(IShellFolder* parent)
00848     {
00849         CONTEXT("ShellPath::get_folder()");
00850         return ShellFolder(parent, _p);
00851     }
00852 
00853      // convert an item id list from relative to absolute (=relative to the desktop) format
00854     ShellPath create_absolute_pidl(LPCITEMIDLIST parent_pidl) const;
00855 };
00856 
00857 
00858 #if defined(__WINE__) && defined(NONAMELESSUNION)   // Wine doesn't know of unnamed union members and uses some macros instead.
00859 #define UNION_MEMBER(x) DUMMYUNIONNAME.##x
00860 #else
00861 #define UNION_MEMBER(x) x
00862 #endif
00863 
00864 
00865  // encapsulation of STRRET structure for easy string retrieval with conversion
00866 
00867 #ifdef UNICODE
00868 #define StrRet StrRetW
00869 //#define   tcscpyn wcscpyn
00870 #else
00871 #define StrRet StrRetA
00872 //#define   tcscpyn strcpyn
00873 #endif
00874 
00875 //extern LPSTR strcpyn(LPSTR dest, LPCSTR source, size_t count);
00876 //extern LPWSTR wcscpyn(LPWSTR dest, LPCWSTR source, size_t count);
00877 
00878  /// easy retrieval of multi byte strings out of STRRET structures
00879 struct StrRetA : public STRRET
00880 {
00881     ~StrRetA()
00882     {
00883         if (uType == STRRET_WSTR)
00884             ShellMalloc()->Free(pOleStr);
00885     }
00886 
00887     void GetString(const SHITEMID& shiid, LPSTR b, int l)
00888     {
00889         switch(uType) {
00890           case STRRET_WSTR:
00891             WideCharToMultiByte(CP_ACP, 0, UNION_MEMBER(pOleStr), -1, b, l, NULL, NULL);
00892             break;
00893 
00894           case STRRET_OFFSET:
00895             lstrcpynA(b, (LPCSTR)&shiid+UNION_MEMBER(uOffset), l);
00896             break;
00897 
00898           case STRRET_CSTR:
00899             lstrcpynA(b, UNION_MEMBER(cStr), l);
00900         }
00901     }
00902 };
00903 
00904  /// easy retrieval of wide char strings out of STRRET structures
00905 struct StrRetW : public STRRET
00906 {
00907     ~StrRetW()
00908     {
00909         if (uType == STRRET_WSTR)
00910             ShellMalloc()->Free(pOleStr);
00911     }
00912 
00913     void GetString(const SHITEMID& shiid, LPWSTR b, int l)
00914     {
00915         switch(uType) {
00916           case STRRET_WSTR:
00917             lstrcpynW(b, UNION_MEMBER(pOleStr), l);
00918             break;
00919 
00920           case STRRET_OFFSET:
00921             MultiByteToWideChar(CP_ACP, 0, (LPCSTR)&shiid+UNION_MEMBER(uOffset), -1, b, l);
00922             break;
00923 
00924           case STRRET_CSTR:
00925             MultiByteToWideChar(CP_ACP, 0, UNION_MEMBER(cStr), -1, b, l);
00926         }
00927     }
00928 };
00929 
00930 
00931  /// Retrieval of file system paths of ShellPath objects
00932 class FileSysShellPath : public ShellPath
00933 {
00934     TCHAR   _fullpath[MAX_PATH];
00935 
00936 protected:
00937     FileSysShellPath() {_fullpath[0] = '\0';}
00938 
00939 public:
00940     FileSysShellPath(const ShellPath& o) : ShellPath(o) {_fullpath[0] = '\0';}
00941 
00942     operator LPCTSTR() {if (!SHGetPathFromIDList(_p, _fullpath)) return NULL; return _fullpath;}
00943 };
00944 
00945 
00946  /// Browse dialog operating on shell namespace
00947 struct FolderBrowser : public FileSysShellPath
00948 {
00949     FolderBrowser(HWND owner, UINT flags, LPCTSTR title, LPCITEMIDLIST root=0)
00950     {
00951         _displayname[0] = '\0';
00952         _browseinfo.hwndOwner = owner;
00953         _browseinfo.pidlRoot = root;
00954         _browseinfo.pszDisplayName = _displayname;
00955         _browseinfo.lpszTitle = title;
00956         _browseinfo.ulFlags = flags;
00957         _browseinfo.lpfn = 0;
00958         _browseinfo.lParam = 0;
00959         _browseinfo.iImage = 0;
00960 
00961         _p = SHBrowseForFolder(&_browseinfo);
00962     }
00963 
00964     LPCTSTR GetDisplayName()
00965     {
00966         return _displayname;
00967     }
00968 
00969     bool IsOK()
00970     {
00971         return _p != 0;
00972     }
00973 
00974 private:
00975     BROWSEINFO _browseinfo;
00976     TCHAR   _displayname[MAX_PATH];
00977 };
00978 
00979 
00980  /// Retrieval of special shell folder paths
00981 struct SpecialFolderPath : public ShellPath
00982 {
00983     SpecialFolderPath(int folder, HWND hwnd)
00984     {
00985         HRESULT hr = SHGetSpecialFolderLocation(hwnd, folder, &_p);
00986         CHECKERROR(hr);
00987     }
00988 };
00989 
00990  /// Shell folder path of the desktop
00991 struct DesktopFolderPath : public SpecialFolderPath
00992 {
00993     DesktopFolderPath()
00994      :  SpecialFolderPath(CSIDL_DESKTOP, 0)
00995     {
00996     }
00997 };
00998 
00999  /// Retrieval of special shell folder
01000 struct SpecialFolder : public ShellFolder
01001 {
01002     SpecialFolder(int folder, HWND hwnd)
01003      :  ShellFolder(GetDesktopFolder(), SpecialFolderPath(folder, hwnd))
01004     {
01005     }
01006 };
01007 
01008  /// Shell folder of the desktop
01009 struct DesktopFolder : public ShellFolder
01010 {
01011 };
01012 
01013 
01014  /// file system path of special folder
01015 struct SpecialFolderFSPath
01016 {
01017     SpecialFolderFSPath(int folder/*e.g. CSIDL_DESKTOP*/, HWND hwnd);
01018 
01019     operator LPCTSTR()
01020     {
01021         return _fullpath;
01022     }
01023 
01024 protected:
01025     TCHAR   _fullpath[MAX_PATH];
01026 };
01027 
01028 /*
01029  /// file system path of special folder
01030 struct SpecialFolderFSPath : public FileSysShellPath
01031 {
01032     SpecialFolderFSPath(int folder, HWND hwnd)
01033     {
01034         CONTEXT("SpecialFolderFSPath::SpecialFolderFSPath()");
01035 
01036         HRESULT hr = SHGetSpecialFolderLocation(hwnd, folder, &_p);
01037         CHECKERROR(hr);
01038     }
01039 };
01040 */
01041 
01042 
01043  /// wrapper class for enumerating shell namespace objects
01044 
01045 struct ShellItemEnumerator : public SIfacePtr<IEnumIDList>
01046 {
01047     ShellItemEnumerator(IShellFolder* folder, DWORD flags=SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN)
01048     {
01049         CONTEXT("ShellItemEnumerator::ShellItemEnumerator()");
01050 
01051         CHECKERROR(folder->EnumObjects(0, flags, &_p));
01052     }
01053 };
01054 
01055 
01056  /// list of PIDLs
01057 struct PIDList
01058 {
01059     PIDList()
01060     {
01061         memset(&_stgm, 0, sizeof(STGMEDIUM));
01062     }
01063 
01064     ~PIDList()
01065     {
01066         if (_stgm.hGlobal) {
01067             GlobalUnlock(_stgm.hGlobal);
01068             ReleaseStgMedium(&_stgm);
01069         }
01070     }
01071 
01072     HRESULT GetData(IDataObject* selection)
01073     {
01074         static UINT CF_IDLIST = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
01075 
01076         FORMATETC fetc;
01077         fetc.cfFormat = CF_IDLIST;
01078         fetc.ptd = NULL;
01079         fetc.dwAspect = DVASPECT_CONTENT;
01080         fetc.lindex = -1;
01081         fetc.tymed = TYMED_HGLOBAL;
01082 
01083         HRESULT hr = selection->QueryGetData(&fetc);
01084         if (FAILED(hr))
01085             return hr;
01086 
01087         hr = selection->GetData(&fetc, &_stgm);
01088         if (FAILED(hr))
01089             return hr;
01090 
01091         _pIDList = (LPIDA)GlobalLock(_stgm.hGlobal);
01092 
01093         return hr;
01094     }
01095 
01096     operator LPIDA() {return _pIDList;}
01097 
01098 protected:
01099     STGMEDIUM _stgm;
01100     LPIDA _pIDList;
01101 };
01102 
01103 
01104 struct CtxMenuInterfaces
01105 {
01106     CtxMenuInterfaces()
01107     {
01108         reset();
01109     }
01110 
01111     void    reset();
01112     bool    HandleMenuMsg(UINT nmsg, WPARAM wparam, LPARAM lparam);
01113     IContextMenu* query_interfaces(IContextMenu* pcm1);
01114 
01115     IContextMenu2*  _pctxmenu2;
01116 
01117 #ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005)
01118     IContextMenu3*  _pctxmenu3;
01119 #endif
01120 };
01121 
01122 template<typename BASE> struct ExtContextMenuHandlerT
01123  : public BASE
01124 {
01125     typedef BASE super;
01126 
01127     ExtContextMenuHandlerT(HWND hwnd)
01128      :  super(hwnd)
01129     {
01130     }
01131 
01132     template<typename PARA> ExtContextMenuHandlerT(HWND hwnd, const PARA& info)
01133      :  super(hwnd, info)
01134     {
01135     }
01136 
01137     LRESULT WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
01138     {
01139         switch(nmsg) {
01140           case WM_DRAWITEM:
01141           case WM_MEASUREITEM:
01142             if (!wparam)    // Is the message menu-related?
01143                 if (_cm_ifs.HandleMenuMsg(nmsg, wparam, lparam))
01144                     return TRUE;
01145 
01146             break;
01147 
01148           case WM_INITMENUPOPUP:
01149             if (_cm_ifs.HandleMenuMsg(nmsg, wparam, lparam))
01150                 return 0;
01151 
01152             break;
01153 
01154 #ifndef __MINGW32__ // IContextMenu3 missing in MinGW (as of 6.2.2005)
01155           case WM_MENUCHAR: // only supported by IContextMenu3
01156            if (_cm_ifs._pctxmenu3) {
01157                LRESULT lResult = 0;
01158 
01159                _cm_ifs._pctxmenu3->HandleMenuMsg2(nmsg, wparam, lparam, &lResult);
01160 
01161                return lResult;
01162            }
01163 
01164            return 0;
01165 #endif
01166         }
01167 
01168         return super::WndProc(nmsg, wparam, lparam);
01169     }
01170 
01171 protected:
01172     CtxMenuInterfaces _cm_ifs;
01173 };
01174 
01175 
01176 extern HRESULT ShellFolderContextMenu(IShellFolder* shell_folder, HWND hwndParent, int cidl,
01177                                         LPCITEMIDLIST* ppidl, int x, int y, CtxMenuInterfaces& cm_ifs);

ROS Explorer Source Code Documentation
generated on 02.01.2013 by doxygen

ROS Explorer Homepage