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 ![]() |