OWLNext    7.0
Borland's Object Windows Library for the modern age
Loading...
Searching...
No Matches
shellitm.cpp
Go to the documentation of this file.
1//----------------------------------------------------------------------------
2// ObjectWindows
3// Copyright (c) 1995, 1996 by Borland International, All Rights Reserved
4//
5/// \file
6/// Implementations of the following Win95 Shell Classes:
7/// TPidl, TShellItem, and TShellItemIterator
8///
9/// The following clases are completely implemented in the header file:
10/// TShellMalloc, TExtractIcon, TContextMenu, TDataObject, TDropTarget
11//----------------------------------------------------------------------------
12#include <owl/pch.h>
13#include <owl/shellitm.h>
14
15#if defined(__BORLANDC__)
16# pragma option -w-ccc // Disable "Condition is always true/false"
17#endif
18
19using namespace std;
20
21namespace owl {
22
24DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlShell, 1, 0); // Shell Diagostic Group
25
26////////////////////////////////////////////////////////////////////
27//
28// class TShell
29// ~~~~~ ~~~~~~
30// delay loading SHELL32.DLL/SHELL.DLL
31 static const tchar shellStr[] = _T("SHELL32.DLL");
32 static const char DragAcceptFilesStr[] = "DragAcceptFiles";
33 static const char DragFinishStr[] = "DragFinish";
34 static const char DragQueryPointStr[] = "DragQueryPoint";
35 static const char SHAddToRecentDocsStr[]= "SHAddToRecentDocs";
36 static const char SHChangeNotifyStr[] = "SHChangeNotify";
37 static const char SHGetMallocStr[] = "SHGetMalloc";
38 static const char SHGetSpecialFolderLocationStr[] = "SHGetSpecialFolderLocation";
39 static const char SHGetDesktopFolderStr[] = "SHGetDesktopFolder";
40#if defined(UNICODE)
41 static const char DragQueryFileStr[] = "DragQueryFileW";
42 static const char ExtractIconStr[] = "ExtractIconW";
43 static const char ShellExecuteStr[] = "ShellExecuteW";
44 static const char Shell_NotifyIconStr[] = "Shell_NotifyIconW";
45 static const char SHBrowseForFolderStr[]= "SHBrowseForFolderW";
46 static const char SHFileOperationStr[] = "SHFileOperationW";
47 static const char SHGetFileInfoStr[] = "SHGetFileInfoW";
48 static const char SHGetPathFromIDListStr[] = "SHGetPathFromIDListW";
49#else
50 static const char DragQueryFileStr[] = "DragQueryFileA";
51 static const char ExtractIconStr[] = "ExtractIconA";
52 static const char ShellExecuteStr[] = "ShellExecuteA";
53 static const char Shell_NotifyIconStr[] = "Shell_NotifyIconA";
54 static const char SHBrowseForFolderStr[]= "SHBrowseForFolderA";
55 static const char SHFileOperationStr[] = "SHFileOperationA";
56 static const char SHGetFileInfoStr[] = "SHGetFileInfoA";
57 static const char SHGetPathFromIDListStr[] = "SHGetPathFromIDListA";
58#endif
59
60
61//
62/// Returns TModule object wrapping the handle of the SHELL[32].DLL module
63//
66{
67 static TModule shellModule(shellStr, true, true, false);
68 return shellModule;
69}
70//
71/// Invokes 'DragAcceptFiles' indirectly
72//
73void
74TShell::DragAcceptFiles(HWND p1, BOOL p2)
75{
76 static TModuleProcV2<HWND,BOOL>
77 dragAcceptFiles(GetModule(), DragAcceptFilesStr);
78 dragAcceptFiles(p1,p2);
79}
80//
81/// Invokes 'DragFinish' indirectly
82//
83void
85{
86 static TModuleProcV1<HDROP>
87 dragFinish(GetModule(), DragFinishStr);
88 dragFinish(p1);
89}
90//
91/// Invokes 'DragQueryFile' indirectly
92//
93UINT
94TShell::DragQueryFile(HDROP p1, UINT p2, LPTSTR p3, UINT p4)
95{
96 static TModuleProc4<UINT,HDROP,UINT,LPTSTR,UINT>
97 dragQueryFile(GetModule(), DragQueryFileStr);
98 return dragQueryFile(p1, p2, p3, p4);
99}
100//
101/// Invokes 'DragQueryPoint' indirectly
102//
103BOOL
104TShell::DragQueryPoint(HDROP p1, LPPOINT p2)
105{
106 static TModuleProc2<BOOL,HDROP,LPPOINT>
107 dragQueryPoint(GetModule(), DragQueryPointStr);
108 return dragQueryPoint(p1, p2);
109}
110//
111/// Invokes 'ExtractIcon' indirectly
112//
113HICON
114TShell::ExtractIcon(HINSTANCE p1, LPCTSTR p2, UINT p3)
115{
116 static TModuleProc3<HICON,HINSTANCE,LPCTSTR,UINT>
117 extractIcon(GetModule(), ExtractIconStr);
118 return extractIcon(p1, p2, p3);
119}
120//
121/// Invokes 'SHAddToRecentDocs' indirectly
122//
123void
124TShell::SHAddToRecentDocs(UINT p1, LPCVOID p2)
125{
126 static TModuleProcV2<UINT,LPCVOID>
127 sHAddToRecentDocs(GetModule(), SHAddToRecentDocsStr);
128 sHAddToRecentDocs(p1, p2);
129}
130//
131/// Invokes 'SHBrowseForFolder' indirectly
132//
133LPITEMIDLIST
135{
136 static TModuleProc1<LPITEMIDLIST,LPBROWSEINFO>
137 sHBrowseForFolder(GetModule(), SHBrowseForFolderStr);
138 return sHBrowseForFolder(p1);
139}
140//
141/// Invokes 'SHChangeNotify' indirectly
142//
143void
144TShell::SHChangeNotify(LONG p1, UINT p2, LPCVOID p3, LPCVOID p4)
145{
146 static TModuleProcV4<LONG,UINT,LPCVOID,LPCVOID>
147 sHChangeNotify(GetModule(), SHChangeNotifyStr);
148 sHChangeNotify(p1, p2, p3, p4);
149}
150//
151/// Invokes 'SHFileOperation' indirectly
152//
153int
154TShell::SHFileOperation(LPSHFILEOPSTRUCT p1)
155{
156 static TModuleProc1<int,LPSHFILEOPSTRUCT>
157 sHFileOperation(GetModule(), SHFileOperationStr);
158 return sHFileOperation(p1);
159}
160//
161/// Invokes 'SHGetDesktopFolder' indirectly
162//
163HRESULT
165{
166 static TModuleProc1<HRESULT,LPSHELLFOLDER*>
167 sHGetDesktopFolder(GetModule(), SHGetDesktopFolderStr);
168 return sHGetDesktopFolder(p1);
169}
170//
171/// Invokes 'SHGetFileInfo' indirectly
172//
173DWORD
174TShell::SHGetFileInfo(LPCTSTR p1, DWORD p2, SHFILEINFO * p3,
175 UINT p4, UINT p5)
176{
177 static TModuleProc5<UINT,LPCTSTR,DWORD,SHFILEINFO *,UINT,UINT>
178 sHGetFileInfo(GetModule(), SHGetFileInfoStr);
179 return sHGetFileInfo(p1, p2, p3, p4, p5);
180}
181
182//
183/// Invokes 'SHGetMalloc' indirectly
184//
185HRESULT
187{
188 static TModuleProc1<HRESULT,LPMALLOC*>
189 sHGetMalloc(GetModule(), SHGetMallocStr);
190 return sHGetMalloc(p1);
191}
192//
193/// Invokes 'SHGetPathFromIDList' indirectly
194//
195BOOL
196TShell::SHGetPathFromIDList(LPCITEMIDLIST p1, LPTSTR p2)
197{
198 static TModuleProc2<BOOL,LPCITEMIDLIST,LPTSTR>
199 sHGetPathFromIDList(GetModule(), SHGetPathFromIDListStr);
200 return sHGetPathFromIDList(p1, p2);
201}
202//
203/// Invokes 'SHGetSpecialFolderLocation' indirectly
204//
205HRESULT
206TShell::SHGetSpecialFolderLocation(HWND p1, int p2, LPITEMIDLIST* p3)
207{
208 static TModuleProc3<HRESULT,HWND,int,LPITEMIDLIST*>
209 sHGetSpecialFolderLocation(GetModule(), SHGetSpecialFolderLocationStr);
210 return sHGetSpecialFolderLocation(p1, p2, p3);
211}
212//
213/// Invokes 'ShellExecute' indirectly
214//
215HINSTANCE
216TShell::ShellExecute(HWND p1, LPCTSTR p2, LPCTSTR p3, LPCTSTR p4,
217 LPCTSTR p5, INT p6)
218{
219 static TModuleProc6<HINSTANCE,HWND,LPCTSTR,LPCTSTR,LPCTSTR,LPCTSTR,INT>
220 shellExecute(GetModule(), ShellExecuteStr);
221 return shellExecute(p1, p2, p3, p4, p5, p6);
222}
223//
224/// Invokes 'Shell_NotifyIcon' indirectly
225//
226BOOL
227TShell::Shell_NotifyIcon(DWORD p1, PNOTIFYICONDATA p2)
228{
229 static TModuleProc2<BOOL,DWORD,PNOTIFYICONDATA>
230 shell_NotifyIcon(GetModule(), Shell_NotifyIconStr);
231 return shell_NotifyIcon(p1, p2);
232}
233
234//////////////////////////////////////////////////////////////////////////
235//
236/// protected function used internally to free PIDL memory with the shell's allocator
237//
238void
240{
241 if (Pidl) {
242 TShellMalloc malloc;
243 malloc->Free(Pidl);
244 Pidl = nullptr;
245 }
246}
247
248//
249/// GetItemCount returns the number of identifiers in the
250/// identifier list (pidl)
251//
252long
254{
255 long cnt = 0;
256
257 if (Pidl) {
258 LPITEMIDLIST pidl = Pidl;
259 while (pidl->mkid.cb) {
260 cnt++;
261 pidl = Next(pidl);
262 }
263 }
264 return cnt;
265}
266
267//
268/// GetSize returns the size (in bytes) of the PIDL
269//
270ulong
272{
273 long size = sizeof(Pidl->mkid.cb);
274 LPITEMIDLIST pidl = Pidl;
275 while (pidl->mkid.cb) {
276 size += pidl->mkid.cb;
277 pidl = Next(pidl);
278 }
279 return size;
280}
281
282//
283/// CopyPidl copies a pidl (allocates memory with the shell's allocator)
284//
285LPITEMIDLIST
287{
288 if (!Pidl)
289 return nullptr;
290 else {
291 LPITEMIDLIST newPidl;
292 TShellMalloc malloc;
293
294// Expanded by Val Ovechkin 11:57 AM 6/3/98
295 void *p = malloc->Alloc(GetSize());
296 newPidl = reinterpret_cast<LPITEMIDLIST>(p);
297
298 WARNX(OwlShell, !newPidl, 0, \
299 _T("IShellMalloc::Alloc failed. IShellMalloc* = ")\
300 << hex << STATIC_CAST(IMalloc*, malloc));
301 if (!newPidl)
302 TXShell::Raise(IDS_SHELLALLOCFAIL);
303 LPITEMIDLIST pidlSrc = Pidl;
304 LPITEMIDLIST pidlDest = newPidl;
305 while (pidlSrc->mkid.cb) {
306 CopyMemory(pidlDest, pidlSrc, pidlSrc->mkid.cb);
307 pidlDest = Next(pidlDest);
308 pidlSrc = Next(pidlSrc);
309 }
310 ushort zero = 0;
311 CopyMemory(pidlDest, &zero, sizeof(ushort));
312 return newPidl;
313 }
314}
315
316//
317/// GetLastItem returns the last item in an identifier list
318/// for file system items, this is the rightmost part of a path
319/// e.g., GetLastItem() on a pidl representing
320/// \code
321/// "c:\\dir1\\dir2\\dir3\\file1"
322/// \endcode
323/// returns "file1"
324TPidl
326{
327 if (!Pidl)
328 return TPidl();
329 else {
330 long cnt = GetItemCount();
331 LPITEMIDLIST pidl = Pidl;
332 for (int i = 0; i < cnt - 1; i++)
333 pidl = Next(pidl);
334 LPITEMIDLIST newPidl;
335 TShellMalloc malloc;
336
337// Expanded by Val Ovechkin 11:57 AM 6/3/98
338 void *p = malloc->Alloc(pidl->mkid.cb + sizeof (pidl->mkid.cb));
339 newPidl = reinterpret_cast<LPITEMIDLIST>(p);
340
341 WARNX(OwlShell, !newPidl, 0, _T("IShellMalloc::Alloc failed. IShellMalloc* = ")
342 << hex << STATIC_CAST(IMalloc*, malloc));
343 if (!newPidl)
344 TXShell::Raise(IDS_SHELLALLOCFAIL);
345
346 CopyMemory(newPidl, pidl, pidl->mkid.cb);
347 LPITEMIDLIST pidlDest = Next(newPidl);
348 USHORT zero = 0;
349 CopyMemory(pidlDest, &zero, sizeof (USHORT));
350 return newPidl;
351 }
352}
353
354//
355/// StripLastItem returns a pidl stipped of its last (rightmost) item
356//
357TPidl
359{
360 int i;
361 if (!Pidl)
362 return TPidl();
363 else {
364 // calculate the size less the last item id
365 long cnt = GetItemCount();
366 if (cnt < 2)
367 return TPidl();
368 long size = sizeof(Pidl->mkid.cb);
369 LPITEMIDLIST pidl = Pidl;
370 for (i = 0; i < cnt - 1; i++) {
371 size += pidl->mkid.cb;
372 pidl = Next(pidl);
373 }
374 LPITEMIDLIST newPidl;
375 TShellMalloc malloc;
376// Expanded by Val Ovechkin 11:57 AM 6/3/98
377 void *p = malloc->Alloc(size);
378 newPidl = reinterpret_cast<LPITEMIDLIST>(p);
379
380 WARNX(OwlShell, !newPidl, 0, _T("IShellMalloc::Alloc failed. IShellMalloc* = ")
381 << hex << STATIC_CAST(IMalloc*, malloc));
382 if (!newPidl)
383 TXShell::Raise(IDS_SHELLALLOCFAIL);
384 LPITEMIDLIST pidlSrc = Pidl;
385 LPITEMIDLIST pidlDest = newPidl;
386 for (i = 0; i < cnt - 1; i++) {
387 CopyMemory(pidlDest, pidlSrc, pidlSrc->mkid.cb);
388 pidlDest = Next(pidlDest);
389 pidlSrc = Next(pidlSrc);
390 }
391 USHORT zero = 0;
392 CopyMemory(pidlDest, &zero, sizeof (USHORT));
393
394 return newPidl;
395 }
396}
397
398/// TShellItem constructor to make a TShellItem for a file or directory in the file system.
399/// If the throwOnInvalidPath argument is true, an exception will be raised if the path is
400/// not valid or if the file or directory does not exist. If this argument is false, no
401/// exception will be raised and the Valid() function should be called to make sure it
402/// returns true. If Valid() returns false, the TShellItem does not represent a object
403/// in the shell namespace.
404//
405TShellItem::TShellItem(const tchar* path, bool throwOnInvalidPath, HWND windowOwner)
406 :TComRef<IShellFolder>(nullptr), Pidl(nullptr), ParentFolder(nullptr)
407{
408 TShellItem desktop(TShellItem::Desktop, windowOwner);
409
410 TCreateStruct cs;
411 ulong eaten;
412 HRESULT hr = desktop.ParseDisplayName(cs, path, &eaten, windowOwner);
413 WARNX(OwlShell, FAILED(hr), 0, _T("Invalid path. Path = ") << path);
414 if (FAILED(hr))
415 {
416 if (throwOnInvalidPath)
417 TXShell::Raise(IDS_INVALIDPATH);
418 else
419 return;
420 }
421
422 Pidl = cs.Pidl.GetLastItem();
423
424// Expanded by Val Ovechkin 11:57 AM 6/3/98
425 void *p = STATIC_CAST(IShellFolder**, ParentFolder);
426 hr = desktop->BindToObject(cs.Pidl.StripLastItem(), nullptr, IID_IShellFolder,
427 REINTERPRET_CAST(void **, p));
428
429// hr = desktop->BindToObject(cs.Pidl.StripLastItem(), 0, IID_IShellFolder,
430// REINTERPRET_CAST(void **,
431// STATIC_CAST(IShellFolder**, ParentFolder)));
432
433 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::BindToObject failed. TShellItem* = ")
434 << hex << (LPVOID)this << _T(" IShellFolder* = ")
435 << STATIC_CAST(IShellFolder*, ParentFolder));
436 TXShell::Check(hr, IDS_BINDTOOBJECTFAIL);
437}
438
439//
440/// TShellItem constructor to make a TShellItem for a special folder. Special
441/// folders can be any specified in the TSpecialFolderKind enum.
442///
443/// (see MS doc for SHGetSpecialFolderLocation for more information,
444/// Programmer's Guide to MS Windows 95, MS Press, p. 209)
445//
446TShellItem::TShellItem(const TSpecialFolderKind kind, HWND windowOwner)
447 :TComRef<IShellFolder>(nullptr), Pidl(nullptr), ParentFolder(nullptr)
448{
449 IShellFolder* desktop;
450 HRESULT hr = TShell::SHGetDesktopFolder(&desktop);
451 WARNX(OwlShell, FAILED(hr), 0, _T("::SHGetDesktopFolder failed."));
452 TXShell::Check(hr, IDS_SHGETDESKTOPFAIL);
453
454 TPidl pidl;
455 hr = TShell::SHGetSpecialFolderLocation(windowOwner, kind, pidl);
456 WARNX(OwlShell, FAILED(hr), 0, \
457 _T("::SHGetSpecialFolderLocation failed. kind = ") << kind);
458 TXShell::Check(hr, IDS_SHGETSPECIALFAIL);
459 if (kind == Desktop) {
460 I = desktop; // Gets itself for the ParentFolder below
461 I->AddRef();
462 }
463 else {
464 hr = desktop->BindToObject(pidl, nullptr, IID_IShellFolder,
465 REINTERPRET_CAST(void **, STATIC_CAST(IShellFolder**, *this)));
466 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::BindToObject failed. Desktop IShellFolder* = ")
467 << hex << STATIC_CAST(IShellFolder*, desktop));
468 TXShell::Check(hr, IDS_BINDTOOBJECTFAIL);
469 }
470
471 ParentFolder = desktop; // It's not clearly documented but we're assuming
472 Pidl = pidl; // that all special folders are children of the
473} // desktop/root.
474
475//
476/// TShellItem constructor to make a TShellItem from a TCreateStruct
477///
478/// TCreateStruct contains a TPidl and a
479/// TComRef<IShellFolder>ParentFolder which represents the parent folder
480///
481/// TCreateStructs are returned by TShellItem::GetParentFolder() and by the
482/// following TShellItemIterator functions:
483/// operator ++(pre- &post-fix), operator -- (pre- & post-fix), operator [](),
484/// and Current()
485///
486/// TCreateStructs are also returned as out parameters of the following TShellItem
487/// functions:
488/// BrowseForFolder(), ParseDisplayName()
489//
491 :TComRef<IShellFolder>(nullptr), Pidl(cs.Pidl),
492 ParentFolder(cs.ParentFolder)
493{
494}
495
496//
497/// TShellIterm constructor to make a TShellItem from a ITEMIDLIST(pidl) and a
498/// TComRef<IShellFolder> (parent folder)
499//
500//
501TShellItem::TShellItem(LPITEMIDLIST pidl, const TComRef<IShellFolder>& parentFolder)
502 :TComRef<IShellFolder>(nullptr), Pidl(pidl), ParentFolder(parentFolder)
503{
504}
505
506//
507/// TShellItem constructor to make a TShellItem from a TPidl and a
508/// TComRef<IShellFolder> (parent folder)
509//
510TShellItem::TShellItem(const TPidl& pidl, const TComRef<IShellFolder>& parentFolder)
511 :TComRef<IShellFolder>(nullptr), Pidl(pidl), ParentFolder(parentFolder)
512{
513}
514
515//
516/// TShellItem copy constructor
517//
519 :TComRef<IShellFolder>(source), Pidl(source.Pidl),
520 ParentFolder(source.ParentFolder)
521{
522}
523
524//
525/// TShellItem assignment (from another TShellItem)
526//
528{
529 if (&source != this) {
531 Pidl = source.Pidl;
532 ParentFolder = source.ParentFolder;
533 }
534 return *this;
535}
536
537//
538/// TShellItem assignment (from a TCreateStruct)
539//
541{
542 Clear();
543 Pidl = cs.Pidl;
544 ParentFolder = cs.ParentFolder;
545 return *this;
546}
547
548//
549/// GetAttributes gets Capabilities, Display, Contents, & Misc. Attributes
550/// with a single call
551///
552/// 'validateCachedInfo' defaults to false. If true, the shell will not
553/// rely on cached information.
554///
555/// See MS doc for IShellFolder::GetAttributesOf for more information, Programmer's
556/// Guide to MS Windows 95, MS Press, pp. 194-195.
557//
558ulong
559TShellItem::GetAttributes(const ulong reqAttrib, const bool validateCachedInfo) const
560{
562 ulong req = reqAttrib | ((validateCachedInfo)? SFGAO_VALIDATE: 0);
563 HRESULT hr = ParentFolder->GetAttributesOf(1, Pidl, &req);
564 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::GetAttributesOf failed. TShellItem* = ")
565 << hex << (LPVOID)this << _T(" Parent IShellFolder* = ")
566 << STATIC_CAST(IShellFolder*, *CONST_CAST(TComRef<IShellFolder>*, &ParentFolder)));
567 TXShell::Check(hr, IDS_GETATTRIBUTESOFFAIL);
568 return req;
569}
570
571//
572/// GetAttribute is a protected function used by all the attribute functions except
573/// IsDesktop.
574///
575/// \note GetAttribute gets attributes one at a time. GetAttributes (with the 's')
576/// is used to get any number of attributes with one call.
577//
578bool
579TShellItem::GetAttribute(const TAttribute at, const bool validateCachedInfo) const
580{
582 ulong req = at;
583 req = GetAttributes(req, validateCachedInfo);
584 return (req & at);
585}
586
587// Attributes - Additional (Not part of GetAttributes)
588
589//
590/// IsDesktop returns true if the TShellItem respresents the shell's desktop, i.e. if its
591/// fully qualified PIDL is empty.
592//
593bool
595{
598 return ILIsEmpty(static_cast<LPCITEMIDLIST>(pidl));
599}
600
601//
602/// GetParentFolder returns a TCreateStruct representing the folder which contains
603/// the TShellItem.
604//
607{
609 TCreateStruct cs;
610
611 if (IsDesktop()) {
612 cs.Pidl = Pidl; // return self
613 cs.ParentFolder = ParentFolder; // ParentFolder is itself too
614 }
615 else {
616 TShellItem desktop(Desktop);
617 TPidl newFullPidl = GetFullyQualifiedPidl().StripLastItem();
618 cs.Pidl = newFullPidl.GetLastItem();
619
620// Expanded by Val Ovechkin 11:57 AM 6/3/98
621 void *p = STATIC_CAST(IShellFolder**, cs.ParentFolder);
622 HRESULT hr = desktop->BindToObject(newFullPidl.StripLastItem(), nullptr, IID_IShellFolder,
623 REINTERPRET_CAST(void **, p));
624
625// HRESULT hr = desktop->BindToObject(newFullPidl.StripLastItem(), 0, IID_IShellFolder,
626// REINTERPRET_CAST(void **, STATIC_CAST(IShellFolder**, cs.ParentFolder)));
627
628
629 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::BindToObject failed. TShellItem* = ")
630 << hex << (LPVOID)this << _T(" Parent LPITEMIDLIST = ")
631 << static_cast<LPITEMIDLIST>(newFullPidl.StripLastItem()));
632 TXShell::Check(hr, IDS_BINDTOOBJECTFAIL);
633 }
634
635 return cs;
636}
637
638//
639/// GetFullyQualifiedPidl returns a TPidl that is fully qualified (from the desktop).
640///
641/// The result is the absolute PIDL of the parent folder combined with the item's relative
642/// PIDL. For the desktop, the result is an empty PIDL. If the parent folder does not expose
643/// its PIDL, the parsing name of the item is parsed by the desktop instead.
644///
645/// \sa <a href="https://learn.microsoft.com/windows/win32/api/shobjidl_core/nf-shobjidl_core-shgetidlistfromobject" target="_blank">
646/// ::%SHGetIDListFromObject</a>
647//
648TPidl
650{
652 IShellFolder* parentFolder = STATIC_CAST(IShellFolder*, *CONST_CAST(TComRef<IShellFolder>*, &ParentFolder));
653 PIDLIST_ABSOLUTE parentPidl = nullptr;
654 if (SUCCEEDED(::SHGetIDListFromObject(parentFolder, &parentPidl)))
655 {
656 LPITEMIDLIST pidl = ::ILCombine(parentPidl, Pidl);
657 ::ILFree(parentPidl);
658 WARNX(OwlShell, !pidl, 0, _T("::ILCombine failed. TShellItem* = ") << hex << (LPVOID)this);
659 if (!pidl)
660 TXShell::Raise(IDS_SHELLALLOCFAIL);
661 return TPidl(pidl);
662 }
664 TShellItem desktop(Desktop);
665 TCreateStruct cs;
666 desktop.ParseDisplayName(cs, name);
667 return cs.Pidl;
668}
669
670//
671/// GetExeType returns the type of executable that is contained in the TShellItem
672/// Also, the optional major and minor args return version numbers
673/// e.g., return = WindowsPE, major = 4, minor = 0
674///
675/// See MS doc for SHGetFileInfo for more information, Programmer's Guide to MS
676/// Windows 95, MS Press, pp. 205-207.
677//
679TShellItem::GetExeType(uint* major, uint* minor) const
680{
682
684 return NonExecutable;
685
686 DWORD rc = TShell::SHGetFileInfo(GetPath(), 0, nullptr, 0, SHGFI_EXETYPE);
687
688 short exeType = LOWORD(rc);
689
690// Expanded by Val Ovechkin 11:57 AM 6/3/98
691 void *p = &exeType;
692 const char* charType = REINTERPRET_CAST(const char*, p);
693
694// const char* charType = REINTERPRET_CAST(const char*, &exeType);
695
696 if (major)
697 *major = HIBYTE(HIWORD(rc));
698 if (minor)
699 *minor = LOBYTE(HIWORD(rc));
700
701 WARNX(OwlShell,
702 rc && ::strncmp("PE", charType, 2) && ::strncmp("NE", charType, 2) && ::strncmp("MZ", charType, 2),
703 0, "::GetFileInfo returned an invalid exeType. exeType = " << exeType);
704
705 if (!rc)
706 return NonExecutable;
707 else if (!::strncmp("PE", charType, 2))
708 return (HIWORD(rc))? WindowsPE: Win32Console;
709 else if (!::strncmp("NE", charType, 2))
710 return WindowsNE;
711 else if (!::strncmp("MZ", charType, 2))
712 return MSDOS;
713 else
714 TXShell::Raise(IDS_GETFILEINFOFAIL);
715
716 return NonExecutable; // To satisfy compiler
717}
718
719//
720/// GetTypeName returns the type of item that is represented by this TShellItem
721/// examples: application, notepad file, ...
722///
723/// See MS doc for SHGetFileInfo for more information, Programmer's Guide to MS
724/// Windows 95, MS Press, pp. 205-207.
725//
728{
730 TString typeName;
731 SHFILEINFO fi;
732 TPidl pidl = GetFullyQualifiedPidl(); // SHGetFileInfo requires a fully qualified PIDL.
733 DWORD_PTR rc = ::SHGetFileInfo(
734 reinterpret_cast<const tchar*>(static_cast<LPCITEMIDLIST>(pidl)),
735 0, &fi, sizeof (fi), SHGFI_TYPENAME | SHGFI_PIDL);
736
737 WARNX(OwlShell, !rc, 0, _T("::GetFileInfo failed. TShellItem = ") << (LPCSTR)GetDisplayName());
738 if (!rc)
739 TXShell::Raise(IDS_GETFILEINFOFAIL);
740 typeName = fi.szTypeName;
741 return typeName;
742}
743
744//
745/// GetDisplayName returns a name for this TShellItem that is suitable to display
746/// to the user.
747///
748/// The three options are:
749///
750/// - \c \b Normal - Suitable for displaying by itself
751/// - \c \b InFolder - Suitable for displaying within its parent folder
752/// - \c \b ForParsing - Suitable to pass to the ParseDiplayName member function
753///
754/// See MS doc for IShellFolder::GetDisplayNameOf for more information,
755/// Programmer's Guide to MS Windows 95, MS Press, pp. 197-198.
756//
759{
761 TString s;
762 STRRET strRet;
763
764 strRet.uType = STRRET_WSTR;
765 HRESULT hr = ParentFolder->GetDisplayNameOf(Pidl, kind, &strRet);
766 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::GetDisplayNameOf failed. TShellItem* = ")
767 << hex << (LPVOID)this);
768 TXShell::Check(hr, IDS_GETDISPLAYNAMEFAIL);
769
770 switch (strRet.uType) {
771 case STRRET_WSTR:{ // Case requested
772 s = strRet.pOleStr;
773 TShellMalloc malloc;
774 malloc->Free(strRet.pOleStr);
775 }
776 break;
777 case STRRET_CSTR: // C-string
778 s = strRet.cStr;
779 break;
780 case STRRET_OFFSET: // Offset into the piddle
781 s = reinterpret_cast<const char*>(static_cast<LPCITEMIDLIST>(Pidl)) + strRet.uOffset;
782 break;
783 }
784
785 return s;
786}
787
788//
789/// GetPath returns the fully qualified path representing this TShellItem
790//
793{
794 tchar path[_MAX_PATH];
795
797 WARNX(OwlShell, !success, 0, "::SHGetPathFromIDList failed. TShellItem* = "
798 << hex << (LPVOID)this);
799 if (!success)
800 TXShell::Raise(IDS_GETPATHFROMPIDLFAIL);
801
802 TString s;
803 s = path;
804 return s;
805}
806
807//
808/// Rename renames this TShellItem to newName.
809///
810/// kind indicates the kind of name being passed (Normal, InFolder, or ForParsing)
811/// (see GetDisplayName for description of these)
812///
813/// See MS doc for IShellFolder::SetNameOf for more information, Programmer's
814/// Guide to MS Windows 95, MS Press, pp. 198-199.
815//
816void
817TShellItem::Rename(const tchar *newName, HWND windowOwner, const TDisplayNameKind kind)
818{
819 LPITEMIDLIST pidl;
820
821 if (!CanBeRenamed())
822 TXShell::Raise(IDS_SHELLRENAMEFAIL);
823
824 // This stuff needed for ::SHChangeNotify
825 bool isFolder = IsFolder();
826 tchar oldPath[_MAX_PATH];
827 memset(oldPath, 0, sizeof(oldPath));
829 TShellItem parentFolder = GetParentFolder();
830 tchar newPath[_MAX_PATH];
831 memset(newPath, 0, sizeof (newPath));
832 ::_tcscpy(newPath, parentFolder.GetDisplayName(ForParsing));
833 _tcscat(newPath, newName);
834
835 HRESULT hr = ParentFolder->SetNameOf(windowOwner, Pidl, TString(newName), kind, &pidl);
836 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::SetNameOf failed. TShellItem* = ")
837 << hex << (LPVOID)this << _T(" Parent IShellFolder* = ")
838 << STATIC_CAST(IShellFolder*, ParentFolder));
839 TXShell::Check(hr, IDS_SETNAMEOFFAIL);
840 Pidl = pidl;
841
842 TShell::SHChangeNotify(isFolder? SHCNE_RENAMEFOLDER: SHCNE_RENAMEITEM,
843 SHCNF_PATH /*| SHCNF_FLUSH*/, STATIC_CAST(const tchar*, oldPath),
844 newPath);
845}
846
847//
848/// Copy copies this TShellItem to destination path
849///
850/// destIsFolder must tell whether or not dest is a folder
851///
852/// flags are any combination of TFileOpFlags
853/// (see MS doc for SHFILEOPSTRUCT for meanings of these flags,
854/// Programmer's Guide to MS Windows 95, MS Press, p. 215)
855///
856/// Title is the title displayed in the progress dialog box
857///
858/// windowOwner should be set to the owner of the progress dialog box
859///
860/// See MS doc for SHFileOperation for more information, Programmer's Guide to
861/// MS Windows 95, MS Press, p. 204.
862//
863bool
864TShellItem::Copy(const tchar* dest, const bool destIsFolder,
865 const USHORT flags, const tchar* title,
866 HWND windowOwner) const
867{
869 SHFILEOPSTRUCT fo;
870
871 if (!CanBeCopied())
872 TXShell::Raise(IDS_SHELLCOPYFAIL);
873
874 fo.hwnd = windowOwner;
875 fo.wFunc = FO_COPY;
876 tchar srcPath[_MAX_PATH];
877 ::memset(srcPath, 0, sizeof (srcPath));
879 fo.pFrom = srcPath;
880 tchar destPath[_MAX_PATH];
881 ::memset(destPath, 0, sizeof (destPath));
882 ::_tcscpy(destPath, dest);
883 fo.pTo = destPath;
884 fo.fFlags = flags;
885 fo.fAnyOperationsAborted = FALSE;
886 fo.hNameMappings = nullptr;
887 fo.lpszProgressTitle = title;
888
889 if (!destIsFolder)
890 fo.fFlags |= FOF_MULTIDESTFILES; // Destination is a filename, not a folder
891
892 bool isFolder = IsFolder();
893
894 int rc = TShell::SHFileOperation(&fo);
895
896 if (rc || fo.fAnyOperationsAborted)
897 return false;
898
899 TShell::SHChangeNotify(isFolder? SHCNE_MKDIR: SHCNE_CREATE, SHCNF_PATH /*| SHCNF_FLUSH*/,
900 STATIC_CAST(const tchar*, GetDisplayName(ForParsing)), nullptr);
901 return true;
902}
903
904//
905/// Copy copies this TShellItem to destination TShellItem
906///
907/// flags are any combination of TFileOpFlags
908/// (see MS doc for SHFILEOPSTRUCT for meanings of these flags,
909/// Programmer's Guide to MS Windows 95, MS Press, p. 215)
910///
911/// Title is the title displayed in the progress dialog box
912///
913/// windowOwner should be set to the owner of the progress dialog box
914///
915/// See MS doc for SHFileOperation for more information, Programmer's Guide to
916/// MS Windows 95, MS Press, p. 204.
917//
918bool
919TShellItem::Copy(const TShellItem& dest, const USHORT flags, const tchar* title,
920 HWND windowOwner) const
921{
922 return Copy(dest.GetDisplayName(ForParsing), dest.IsFolder(), flags, title, windowOwner);
923}
924
925//
926/// Move moves this TShellItem to destination path (which must be a folder)
927///
928/// flags are any combination of TFileOpFlags
929/// (see MS doc for SHFILEOPSTRUCT for meanings of these flags,
930/// Programmer's Guide to MS Windows 95, MS Press, p. 215)
931///
932/// Title is the title displayed in the progress dialog box
933///
934/// windowOwner should be set to the owner of the progress dialog box
935///
936/// See MS doc for SHFileOperation for more information, Programmer's Guide to
937/// MS Windows 95, MS Press, p. 204.
938//
939bool
940TShellItem::Move(const tchar* destFolder, const USHORT flags, const tchar* title,
941 HWND windowOwner)
942{
944 SHFILEOPSTRUCT fo;
945
946 if (!CanBeMoved())
947 TXShell::Raise(IDS_SHELLMOVEFAIL);
948
949 fo.hwnd = windowOwner;
950 fo.wFunc = FO_MOVE;
951
952 tchar oldPath[_MAX_PATH];
953 ::memset(oldPath, 0, sizeof (oldPath));
955 fo.pFrom = oldPath;
956 tchar destPath[_MAX_PATH];
957 ::memset(destPath, 0, sizeof (destPath));
958 ::_tcscpy(destPath, destFolder);
959 fo.pTo = destPath;
960 fo.fFlags = flags;
961 fo.fAnyOperationsAborted = FALSE;
962 fo.hNameMappings = nullptr;
963 fo.lpszProgressTitle = title;
964
965 bool isFolder = IsFolder();
966
967 int rc = TShell::SHFileOperation(&fo);
968
969 if (rc || fo.fAnyOperationsAborted)
970 return false;
971
972 tchar newPath[_MAX_PATH];
973 ::_tcscpy(newPath, destFolder);
974#if defined(BI_DBCS_SUPPORT)
975 if (*AnsiPrev(newPath, newPath + ::strlen(newPath)) != '\\')
976#else
977 if (newPath[::_tcslen(newPath)-1] != _T('\\'))
978#endif
979 _tcscat(newPath, _T("\\"));
980 _tcscat(newPath, GetDisplayName());
981 *this = TShellItem(newPath); // change myself to the new location
982
983 // Notify deletion of old path
984 TShell::SHChangeNotify(isFolder? SHCNE_RMDIR: SHCNE_DELETE, SHCNF_PATH /*| SHCNF_FLUSH*/,
985 STATIC_CAST(const tchar*, oldPath), nullptr);
986 // Notify creation of new path
987 TShell::SHChangeNotify(isFolder? SHCNE_MKDIR: SHCNE_CREATE, SHCNF_PATH /*| SHCNF_FLUSH*/,
988 STATIC_CAST(const tchar*, GetDisplayName(ForParsing)), nullptr);
989
990 return true;
991}
992
993//
994/// Move moves this TShellItem to destination TShellItem (which must be a folder)
995///
996/// flags are any combination of TFileOpFlags
997/// (see MS doc for SHFILEOPSTRUCT for meanings of these flags,
998/// Programmer's Guide to MS Windows 95, MS Press, p. 215)
999///
1000/// Title is the title displayed in the progress dialog box
1001///
1002/// windowOwner should be set to the owner of the progress dialog box
1003///
1004/// See MS doc for SHFileOperation for more information, Programmer's Guide to
1005/// MS Windows 95, MS Press, p. 204.
1006//
1007bool
1008TShellItem::Move(const TShellItem& destFolder, const USHORT flags,
1009 const tchar* title, HWND windowOwner)
1010{
1011 return Move(destFolder.GetDisplayName(ForParsing), flags, title, windowOwner);
1012}
1013
1014//
1015/// Delete deletes this TShellItem
1016///
1017/// flags are any combination of TFileOpFlags
1018/// (see MS doc for SHFILEOPSTRUCT for meanings of these flags,
1019/// Programmer's Guide to MS Windows 95, MS Press, p. 215)
1020///
1021/// Title is the title displayed in the progress dialog box
1022///
1023/// windowOwner should be set to the owner of the progress dialog box
1024///
1025/// See MS doc for SHFileOperation for more information, Programmer's Guide to
1026/// MS Windows 95, MS Press, p. 204.
1027//
1028bool
1029TShellItem::Delete(const USHORT flags, const tchar* title, HWND windowOwner)
1030{
1032 if (!Pidl) // Nothing to delete!
1033 return true;
1034
1035 if (!CanBeDeleted())
1036 TXShell::Raise(IDS_SHELLDELETEFAIL);
1037
1038 SHFILEOPSTRUCT fo;
1039 fo.hwnd = windowOwner;
1040 fo.wFunc = FO_DELETE;
1041 tchar path[_MAX_PATH];
1042 memset(path, 0, sizeof (path));
1043 ::_tcscpy(path, GetDisplayName(ForParsing)); // Also used to reconstruct if delete fails/user aborts
1044 fo.pFrom = path;
1045 fo.pTo = nullptr;
1046 fo.fFlags = flags;
1047 fo.fAnyOperationsAborted = FALSE;
1048 fo.hNameMappings = nullptr;
1049 fo.lpszProgressTitle = title;
1050
1051 bool isFolder = IsFolder(); // Needed for ::SHChangeNotify
1052
1053 // About to delete: save and release everything
1054 //
1056 Pidl = nullptr;
1057 ParentFolder = nullptr;
1058
1059 int rc = TShell::SHFileOperation(&fo);
1060 if (rc || fo.fAnyOperationsAborted) {
1061 *this = TShellItem(path); // restore everything
1062 return false;
1063 }
1064
1065 TShell::SHChangeNotify(isFolder? SHCNE_RMDIR: SHCNE_DELETE, SHCNF_PATH /*| SHCNF_FLUSH*/,
1066 path, nullptr);
1067
1068 return true;
1069}
1070
1071//
1072/// GetExtractIcon returns an interface pointer to this TShellItem's IExtractIcon
1073/// OLE interface
1074///
1075/// (see MS doc for information on IExtractIcon,
1076/// Programmer's Guide to MS Windows 95, MS Press, pp. 242-244)
1077//
1080{
1082 IExtractIcon* iface;
1083
1084// Expanded by Val Ovechkin 12:29 PM 6/3/98
1085 void *p = &iface;
1086 HRESULT hr = ParentFolder->GetUIObjectOf(windowOwner, 1, Pidl, IID_IExtractIcon,
1087 nullptr, REINTERPRET_CAST(void**, p));
1088
1089// HRESULT hr = ParentFolder->GetUIObjectOf(windowOwner, 1, Pidl, IID_IExtractIcon,
1090// 0, REINTERPRET_CAST(void**, &iface));
1091 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::GetUIObjectOf(IExtractIcon) ")
1092 << _T("failed. TShellItem* = ")
1093 << hex << (LPVOID)this << _T(" Parent IShellFolder* = ")
1094 << STATIC_CAST(IShellFolder*, ParentFolder));
1095 TXShell::Check(hr, IDS_GETUIOBJECTOFFAIL);
1096 return TExtractIcon(iface);
1097}
1098
1099//
1100/// GetContextMenu returns an interface pointer to this TShellItem's IContextMenu
1101/// OLE interface
1102///
1103/// (see MS doc for information on IContextMenu,
1104/// Programmer's Guide to MS Windows 95, MS Press, pp. 237-240)
1105//
1108{
1110 IContextMenu* iface;
1111
1112// Expanded by Val Ovechkin 12:29 PM 6/3/98
1113 void *p = &iface;
1114 HRESULT hr = ParentFolder->GetUIObjectOf(windowOwner, 1, Pidl, IID_IContextMenu,
1115 nullptr, REINTERPRET_CAST(void**, p));
1116
1117// HRESULT hr = ParentFolder->GetUIObjectOf(windowOwner, 1, Pidl, IID_IContextMenu,
1118// 0, REINTERPRET_CAST(void**, &iface));
1119 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::GetUIObjectOf(IContextMenu) ")
1120 << _T("failed. TShellItem* = ")
1121 << hex << (LPVOID)this << _T(" Parent IShellFolder* = ")
1122 << STATIC_CAST(IShellFolder*, ParentFolder));
1123 TXShell::Check(hr, IDS_GETUIOBJECTOFFAIL);
1124 return TContextMenu(iface);
1125}
1126
1127//
1128/// GetDataObject returns an interface pointer to this TShellItem's IDataObject
1129/// OLE interface
1130///
1131/// (see MS doc for a very brief description of IDataObject,
1132/// Programmer's Guide to MS Windows 95, MS Press, p. 113)
1133//
1136{
1138 IDataObject* iface;
1139
1140// Expanded by Val Ovechkin 12:29 PM 6/3/98
1141 void *p = &iface;
1142 HRESULT hr = ParentFolder->GetUIObjectOf(windowOwner, 1, Pidl, IID_IDataObject
1143,
1144 nullptr, REINTERPRET_CAST(void**, p));
1145
1146// HRESULT hr = ParentFolder->GetUIObjectOf(windowOwner, 1, Pidl, IID_IDataObject,
1147// 0, REINTERPRET_CAST(void**, &iface));
1148 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::GetUIObjectOf(IDataObject) ")
1149 << _T("failed. TShellItem* = ")
1150 << hex << (LPVOID)this << _T(" Parent IShellFolder* = ")
1151 << STATIC_CAST(IShellFolder*, ParentFolder));
1152 TXShell::Check(hr, IDS_GETUIOBJECTOFFAIL);
1153 return TDataObject(iface);
1154}
1155
1156//
1157/// GetDropTarget returns an interface pointer to this TShellItem's IDropTarget
1158/// OLE interface
1159//
1162{
1164 IDropTarget* iface;
1165
1166 void *p = &iface;
1167 HRESULT hr = ParentFolder->GetUIObjectOf(windowOwner, 1, Pidl, IID_IDropTarget
1168,
1169 nullptr, REINTERPRET_CAST(void**, p));
1170
1171// HRESULT hr = ParentFolder->GetUIObjectOf(windowOwner, 1, Pidl, IID_IDropTarget,
1172// 0, REINTERPRET_CAST(void**, &iface));
1173 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::GetUIObjectOf(IDropTarget) ")
1174 << _T("failed. TShellItem* = ")
1175 << hex << (LPVOID)this << _T(" Parent IShellFolder* = ")
1176 << STATIC_CAST(IShellFolder*, ParentFolder));
1177 TXShell::Check(hr, IDS_GETUIOBJECTOFFAIL);
1178 return TDropTarget(iface);
1179}
1180
1181//
1182/// GetIcon returns a handle to an icon representing this TShellItem
1183///
1184/// size can be Large, Small, or Shell
1185/// kind can be Link, Open, or Selected
1186/// (see MS doc on SHGetFileInfo for meanings,
1187/// Programmer's Guide to MS Windows 95, MS Press, pp. 206-207)
1188//
1189HICON
1191{
1193
1194 if (!IsPartOfFileSystem()) {
1195 uint inFlags = (size & Shell)? GIL_FORSHELL: 0 | (kind & Open)? GIL_OPENICON: 0;
1196 tchar fileName[_MAX_PATH];
1197 int index;
1198 uint outFlags;
1199 HICON largeIcon;
1200 HICON smallIcon;
1201
1202 TExtractIcon extractIcon = GetExtractIcon();
1203 HRESULT hr = extractIcon->GetIconLocation(inFlags, fileName, COUNTOF(fileName),
1204 &index, &outFlags);
1205 TXShell::Check(hr, IDS_GETICONLOCFAIL);
1206 if (hr != S_FALSE)
1207 if (outFlags & GIL_NOTFILENAME || outFlags & GIL_DONTCACHE) {
1208 hr = extractIcon->Extract(fileName, index, &largeIcon, &smallIcon, GetSystemMetrics(SM_CXICON));
1209 TXShell::Check(hr, IDS_EXTRICONEXTRACTFAIL);
1210 if (hr != S_FALSE)
1211 return (size == Small)? smallIcon: largeIcon;
1212 }
1213 }
1214
1215 // TShellItem is part of file system or couldn't get the icon with
1216 // IExtractIcon::Extract
1217 //
1218 // SHGetFileInfo requires a fully qualified PIDL.
1219 //
1220 SHFILEINFO fi = {};
1221 uint flags = SHGFI_ICON | kind | size;
1223 TShell::SHGetFileInfo(reinterpret_cast<const tchar*>(static_cast<LPCITEMIDLIST>(pidl)),
1224 0, &fi, sizeof (fi), flags | SHGFI_PIDL);
1225 WARNX(OwlShell, !fi.hIcon, 0, _T("::SHGetFileInfo failed. TShellItem* = ")
1226 << hex << (LPVOID)this);
1227 if (!fi.hIcon)
1228 TXShell::Raise(IDS_GETFILEINFOFAIL);
1229 return fi.hIcon;
1230}
1231
1232//
1233/// ResolveShortcut resolves this TShellItem (if it's a shortcut) and returns the
1234/// underlying TShellItem. If this TShellItem is not a shortcut, it just returns itself.
1235///
1236/// \note IMPORTANT: This function calls CoCreateInstance. Therefore an application that
1237/// uses this function MUST have previously called CoInitialize (or OLEInitialize).
1238///
1239/// \note IMPORTANT: If the shortcut cannot be resolved, this function will return an
1240/// empty (invalid) item. One MUST check for this by calling IsValid()
1241/// upon return from this function.
1242//
1245{
1247
1248 if (!IsShortcut())
1249 return *this;
1250
1251 HRESULT hr;
1252 TComRef<IShellLink> shellLink;
1253 hr = TOle::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink,
1254 REINTERPRET_CAST(void **, STATIC_CAST(IShellLink**, shellLink)));
1255 TXShell::Check(hr, IDS_CREATESHELLLINKFAIL);
1256
1257 TComRef<IPersistFile> persistFile;
1258 hr = shellLink->QueryInterface(IID_IPersistFile,
1259 REINTERPRET_CAST(void **, STATIC_CAST(IPersistFile**, persistFile)));
1260 TXShell::Check(hr, IDS_LINKQUERYINTRFCFAIL);
1261 TString shortcutFile = GetPath();
1262 hr = persistFile->Load(shortcutFile, STGM_READ);
1263 TXShell::Check(hr, IDS_PERSISTFILELOADFAIL);
1264
1265 hr = shellLink->Resolve(windowOwner, SLR_ANY_MATCH | SLR_UPDATE);
1266 if (FAILED(hr)) {
1267 // Failure to Resolve: return empty/invalid shell item object
1268 //
1269 return TShellItem();
1270 }
1271
1272 TPidl resolvedPidl;
1273 hr = shellLink->GetIDList(resolvedPidl);
1274 TXShell::Check(hr, IDS_LINKGETIDLISTFAIL);
1275
1276 // Construct the resolved TShellItem
1277 //
1278 TCreateStruct cs;
1279 cs.Pidl = resolvedPidl.GetLastItem();
1280 if (resolvedPidl.GetItemCount() == 1)
1282 else {
1283
1284// Expanded by Val Ovechkin 12:29 PM 6/3/98
1285 void *p = STATIC_CAST(IShellFolder**, cs.ParentFolder);
1286 hr = TShellItem(Desktop)->BindToObject(resolvedPidl.StripLastItem(), nullptr, IID_IShellFolder,
1287 REINTERPRET_CAST(void **, p));
1288
1289// hr = TShellItem(Desktop)->BindToObject(resolvedPidl.StripLastItem(), 0, IID_IShellFolder,
1290// REINTERPRET_CAST(void **, STATIC_CAST(IShellFolder**, cs.ParentFolder)));
1291
1292 TXShell::Check(hr, IDS_BINDTOOBJECTFAIL);
1293 }
1294 return TShellItem(cs);
1295}
1296
1297//
1298/// Create a shortcut to a file object
1299///
1300/// \note IMPORTANT: This function calls CoCreateInstance. Therefore an
1301/// application that uses this function MUST have previously
1302/// called CoInitialize (or OLEInitialize).
1303//
1304HRESULT
1305TShellItem::CreateShortCut(LPCTSTR objPath, LPTSTR pathLink, LPTSTR description)
1306{
1307 HRESULT hr;
1308 TComRef<IShellLink> shellLink;
1309 hr = TOle::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink,
1310 REINTERPRET_CAST(void **, STATIC_CAST(IShellLink**, shellLink)));
1311 TXShell::Check(hr, IDS_CREATESHELLLINKFAIL);
1312
1313 // Set path to shortcut target and add description
1314 //
1315 hr = shellLink->SetPath(TString(objPath));
1316 TXShell::Check(hr, IDS_SHLLINKSETPATHFAIL);
1317 hr = shellLink->SetDescription(TString(description));
1318 TXShell::Check(hr, IDS_SHLLINKSETDESCFAIL);
1319
1320 // Query IShellLink for the IPersistFile Interface for saving the
1321 // shortcut in persistent storage
1322 //
1323 TComRef<IPersistFile> persistFile;
1324 hr = shellLink->QueryInterface(IID_IPersistFile,
1325 REINTERPRET_CAST(void **, STATIC_CAST(IPersistFile**, persistFile)));
1326 TXShell::Check(hr, IDS_LINKQUERYINTRFCFAIL);
1327
1328 // Save link by calling IPersistFile::Save
1329 //
1330 hr = persistFile->Save(TString(pathLink), TRUE);
1331 return hr;
1332}
1333
1334//
1335/// Create a shortcut to a non-file object
1336///
1337/// \note IMPORTANT: This function calls CoCreateInstance. Therefore an
1338/// application that uses this function MUST have previously
1339/// called CoInitialize (or OLEInitialize).
1340//
1341HRESULT
1342TShellItem::CreateShortCut(LPCITEMIDLIST pidl, LPTSTR pathLink, LPTSTR description)
1343{
1344 HRESULT hr;
1345 TComRef<IShellLink> shellLink;
1346 hr = TOle::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink,
1347 REINTERPRET_CAST(void **, STATIC_CAST(IShellLink**, shellLink)));
1348 TXShell::Check(hr, IDS_CREATESHELLLINKFAIL);
1349
1350 // Set path to shortcut target and add description
1351 //
1352 shellLink->SetIDList(pidl);
1353 shellLink->SetDescription(description);
1354
1355 // Query IShellLink for the IPersistFile Interface for saving the
1356 // shortcut in persistent storage
1357 //
1358 TComRef<IPersistFile> persistFile;
1359 hr = shellLink->QueryInterface(IID_IPersistFile,
1360 REINTERPRET_CAST(void **, STATIC_CAST(IPersistFile**, persistFile)));
1361 TXShell::Check(hr, IDS_LINKQUERYINTRFCFAIL);
1362
1363 // Save link by calling IPersistFile::Save
1364 //
1365 hr = persistFile->Save(TString(pathLink), TRUE);
1366 return hr;
1367}
1368
1369//
1370/// Creates a shortcut to this object
1371///
1372/// \note IMPORTANT: This function calls CoCreateInstance. Therefore an
1373/// application that uses this function MUST have previously
1374/// called CoInitialize (or OLEInitialize).
1375//
1377TShellItem::CreateShortCut(LPTSTR linkPath, LPTSTR description)
1378{
1380
1381 if (IsPartOfFileSystem()) {
1382 if (SUCCEEDED(CreateShortCut(GetPath(), linkPath, description)))
1383 return TShellItem(linkPath);
1384 } else {
1385 if (SUCCEEDED(CreateShortCut(GetFullyQualifiedPidl(), linkPath,
1386 description)))
1387 return TShellItem(linkPath);
1388 }
1389
1390 // Failure: return empty/invalid Shell Item object
1391 //
1392 return TShellItem();
1393}
1394
1395//
1396/// Adds the TShellItem to the taskbar's recent document list
1397/// (see MS doc for more info on SHAddToRecentDocs,
1398/// Programmer's Guide to MS Windows 95, MS Press, p. 202)
1399//
1400void
1402{
1404 TShell::SHAddToRecentDocs(SHARD_PIDL, STATIC_CAST(const ITEMIDLIST *, GetFullyQualifiedPidl()));
1405}
1406
1407//
1408// Returns a fully qualified PIDL for the item, normalized by parsing its parsing name from the
1409// desktop. The same item may be reached through different routes in the namespace (e.g. a PIDL
1410// stored in a shortcut may differ from the PIDL obtained by parsing the path), and such PIDLs do
1411// not compare equal with IShellFolder::CompareIDs. If parsing fails, the fully qualified PIDL is
1412// returned as is.
1413//
1414static TPidl GetNormalizedPidl(const TShellItem& item)
1415{
1419 HRESULT hr = desktop.ParseDisplayName(cs, name);
1420 return SUCCEEDED(hr) ? cs.Pidl : item.GetFullyQualifiedPidl();
1421}
1422
1423//
1424/// CompareIDs is a protected function that compares a TShellItem's pidl with
1425/// another TShellItem's pidl
1426///
1427/// (see MS doc for more info CompareIDs,
1428/// Programmer's Guide to MS Windows 95, MS Press, p. 194)
1429//
1430short
1432{
1434 rhs.EnforceValidity();
1435 HRESULT hr;
1436
1437 if (!HaveSameParent(rhs)) { // use the desktop
1438 TShellItem desktop(Desktop);
1439 hr = desktop->CompareIDs(0, GetNormalizedPidl(*this), GetNormalizedPidl(rhs));
1440 WARNX(OwlShell, FAILED(hr), 0, _T("Desktop->CompareIDs failed.")
1441 << _T(" this TShellItem* = ") << hex << (LPVOID)this
1442 << _T(" other TShellItem* = ") << (LPVOID)&rhs);
1443 TXShell::Check(hr, IDS_COMPAREIDSFAIL);
1444 }
1445 else {
1446 hr = ParentFolder->CompareIDs(0, Pidl, rhs.Pidl);
1447 WARNX(OwlShell, FAILED(hr), 0, _T("SameParent->CompareIDs failed.")
1448 << _T(" this TShellItem* = ") << hex << (LPVOID)this
1449 << _T(" other TShellItem* = ") << (LPVOID)&rhs);
1450 TXShell::Check(hr, IDS_COMPAREIDSFAIL);
1451 }
1452
1453 return STATIC_CAST(short, HRESULT_CODE(hr));
1454}
1455
1456//
1457/// EnforceValidity is a protected function that checks that a TShellItem is valid
1458/// before proceeding with an operation that requires the TShellItem to be valid
1459//
1460void
1462{
1463 WARNX(OwlShell, !Valid(), 0, _T("TShellItem is not valid.")
1464 << _T(" TShellItem* = ") << hex << (LPVOID)this);
1465 if (!Valid())
1466 TXShell::Raise(IDS_TSHELLITEMINVALID);
1467}
1468
1469// Folder Functions
1470
1471//
1472/// RetrieveIShellFolder is a protected function that checks to see if a TShellItem's
1473/// IShellFolder interface is already assigned a value. If not, it will BindToObject
1474/// in order to assign the interface a value. Note: Only TShellItem's that are
1475/// folders have an IShellFolder interface; consequently, if this function is
1476/// called on a TShellItem that is not a folder, an exception will be thrown.
1477//
1478void
1480{
1482 if (!I) { // Need to call BindToObject
1483 IShellFolder* iface;
1484 HRESULT hr = ParentFolder->BindToObject(Pidl, nullptr, IID_IShellFolder,
1485 REINTERPRET_CAST(void **, &iface));
1486 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::BindToObject failed.")
1487 << _T(" TShellItem* = ") << hex << (LPVOID)this << _T(" Parent IShellFolder* = ")
1488 << STATIC_CAST(IShellFolder*, *CONST_CAST(TComRef<IShellFolder>*, &ParentFolder)));
1489 TXShell::Check(hr, IDS_BINDTOOBJECTFAIL);
1490 // CONST_CAST(IShellFolder*, I) = iface;
1491 CONST_CAST(TShellItem*,this)->I = iface;
1492 }
1493}
1494
1495//
1496/// EnumObjects is a protected function that returns an IEnumIDList enumerator on
1497/// a folder. Note: This function is only meaningful for folders; consequently,
1498/// if this function is called on a TShellItem that is not a folder, an
1499/// exception will be thrown.
1500//
1501void
1502TShellItem::EnumObjects(IEnumIDList** iface, HWND windowOwner,
1503 const int kind) const
1504{
1507 HRESULT hr = I->EnumObjects(windowOwner, (kind == -1)? TShellItemIterator::Folders |
1508 TShellItemIterator::NonFolders: kind, iface);
1509 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::EnumObjects failed.")
1510 << _T(" TShellItem* = ") << hex << (LPVOID)this);
1511 TXShell::Check(hr, IDS_ENUMOBJECTSFAIL);
1512}
1513
1514//
1515/// BrowseForFolder presents a dialog box to the user in which he can select a
1516/// subfolder. The root of the dialog box is this TShellItem folder.
1517///
1518/// \note It is only meaningful to call this function if the TShellItem is a
1519/// folder; consequently, if this function is called on a TShellItem that is
1520/// not a folder, an exception will be thrown.
1521///
1522/// Additional Documentation: See MS doc on SHBrowseForFolder for more info,
1523/// more info, Programmer's Guide to MS Windows 95, MS Press, pp. 202-203.
1524//
1525bool
1527 const tchar* title, const UINT flags, int* image,
1528 const bool includeStatus, BFFCALLBACK func,
1529 const LPARAM param) const
1530{
1533 tchar displayName[_MAX_PATH];
1534
1535 BROWSEINFO bi;
1536 bi.hwndOwner = windowOwner;
1537 TPidl fullPidl = GetFullyQualifiedPidl();
1538 bi.pidlRoot = fullPidl;
1539 bi.pszDisplayName = displayName;
1540 bi.lpszTitle = title;
1541 bi.ulFlags = flags;
1542 if (includeStatus)
1543 bi.ulFlags |= BIF_STATUSTEXT;
1544 bi.lpfn = func;
1545 bi.lParam = param;
1546
1547 TPidl pidl = TShell::SHBrowseForFolder(&bi);
1548 if (!pidl)
1549 return false;
1550 else {
1551 if (image)
1552 *image = bi.iImage;
1553 TShellItem desktop(Desktop);
1554 cs.Pidl = pidl.GetLastItem();
1555
1556// Expanded by Val Ovechkin 12:29 PM 6/3/98
1557 void *p = STATIC_CAST(IShellFolder**, cs.ParentFolder);
1558 HRESULT hr = desktop->BindToObject(pidl.StripLastItem(), nullptr, IID_IShellFolder
1559,
1560 REINTERPRET_CAST(void **, p));
1561
1562// HRESULT hr = desktop->BindToObject(pidl.StripLastItem(), 0, IID_IShellFolder,
1563// REINTERPRET_CAST(void **, STATIC_CAST(IShellFolder**, cs.ParentFolder)));
1564 WARNX(OwlShell, FAILED(hr), 0, _T("IShellFolder::BindToObject failed.")
1565 << _T(" TShellItem* = ") << hex << (LPVOID)this
1566 << _T(" Desktop IShellFolder* = ") << STATIC_CAST(IShellFolder*, desktop));
1567 TXShell::Check(hr, IDS_BINDTOOBJECTFAIL);
1568
1569 return true;
1570 }
1571}
1572
1573//
1574/// ParseDisplayName parses a "for parsing" display name into a TCreateStruct
1575/// (which can be used to create a TShellItem). In general, it is not necessary
1576/// to call this function when using OWL's shell classes.
1577///
1578/// \note It is only meaningful to call this function if the TShellItem is a
1579/// folder; consequently, if this function is called on a TShellItem that is
1580/// not a folder, an exception will be thrown.
1581///
1582/// Additional Documentation: See MS doc on IShellFolder::ParseDisplayName for
1583/// more info, Programmer's Guide to MS Windows 95, MS Press, pp. 191-192.
1584//
1585HRESULT
1587 ulong* eaten, HWND windowOwner,
1588 ulong* attrib) const
1589{
1591 TPidl pidl;
1592 ulong charsEaten;
1593 ulong attributes;
1595
1596 HRESULT hr = I->ParseDisplayName(windowOwner, nullptr, TString(displayName),
1597 &charsEaten, pidl, &attributes);
1598
1599 if (hr == NOERROR) {
1600 if (eaten)
1601 *eaten = charsEaten;
1602 if (attrib)
1603 *attrib = attributes;
1604 cs.Pidl = pidl;
1605 cs.ParentFolder = *this;
1606 }
1607
1608 return hr;
1609}
1610
1611//
1612/// TShellItemIterator constructor.
1613///
1614/// \note It is only meaningful to construct iterators on folders; therefore,
1615/// if this constructor is passed a TShellItem that is not a folder, an exception
1616/// will be thrown.
1617///
1618/// Additional Documentation: See MS doc on IEnumIDList for more info,
1619/// Programmer's Guide to MS Windows 95, MS Press, pp. 199-201.
1620//
1622 const int kind)
1623:
1624 Index(0),
1625 Pidl(nullptr),
1626 Folder(folder)
1627{
1628 folder.EnumObjects(*this, windowOwner, kind);
1629 Folder = folder; // even though filled in above, the IShellFolder* may not have
1630 // yet have been filled in. (See RetrieveIShellFolder)
1631 Next();
1632}
1633
1634//
1635/// TShellItemIterator copy constructor.
1636///
1637/// \note This function does not work with the intial release of Win95 because
1638/// Win95's IEnumIDList::Clone is broken (it returns E_FAIL (unspecified error))
1639//
1641:
1642 Index(source.Index),
1643 Pidl(source.Pidl),
1644 Folder(source.Folder)
1645{
1646 if (!source.I)
1647 I = nullptr;
1648 else {
1649 HRESULT hr = source.I->Clone(*this);
1650 WARNX(OwlShell, FAILED(hr), 0, _T("IEnumIDList::Clone failed.")
1651 << _T(" TShellItemIterator* = ") << hex << (LPVOID)this
1652 << _T(" source IEnumIDList* = ")
1653 << STATIC_CAST(IEnumIDList*, CONST_CAST(TShellItemIterator&, source)));
1654 TXShell::Check(hr, IDS_CLONEFAIL);
1655 }
1656}
1657
1658//
1659/// TShellItemIterator assignment operator
1660///
1661/// \note This function does not work with the intial release of Win95 because
1662/// Win95's IEnumIDList::Clone is broken (it returns E_FAIL (unspecified error))
1663//
1665{
1666 if (&source != this) {
1667 if (!source.I)
1668 I = nullptr;
1669 else {
1670 HRESULT hr = source.I->Clone(*this);
1671 WARNX(OwlShell, FAILED(hr), 0, _T("IEnumIDList::Clone failed.")
1672 << _T(" TShellItemIterator* = ") << hex << (LPVOID)this << _T(" source IEnumIDList* = ")
1673 << STATIC_CAST(IEnumIDList*, CONST_CAST(TShellItemIterator&, source)));
1674 TXShell::Check(hr, IDS_CLONEFAIL);
1675 Index = source.Index;
1676 Pidl = source.Pidl;
1677 Folder = source.Folder;
1678 }
1679 }
1680 return *this;
1681}
1682
1683//
1684/// operator IEnumIDList** resets the interface pointer and returns a pointer
1685/// to this interface pointer.
1686//
1687TShellItemIterator::operator IEnumIDList**()
1688{
1689 return TComRef<IEnumIDList>::operator IEnumIDList**();
1690}
1691
1692//
1693/// operator ++ increments the "cursor" in the iterator, then returns
1694/// the item pointed to by the cursor
1695///
1696/// The item is returned as a TShellItem::TCreateStruct structure. For more
1697/// information about TCreateStruct, see the comments in the
1698/// TShellItem::TShellItem(const TCreateStruct& cs) constructor.
1699//
1705
1706//
1707/// operator ++(int) returns the item pointed to by the "cursor," then increments
1708/// the cursor.
1709///
1710/// The item is returned as a TShellItem::TCreateStruct structure. For more
1711/// information about TCreateStruct, see the comments in the
1712/// TShellItem::TShellItem(const TCreateStruct& cs) constructor.
1713//
1716{
1718 WARNX(OwlShell, Index == -1, 0, _T("Attempt to read past end of TShellItemIterator")
1719 << _T(" TShellItemIterator* = ") << hex << (LPVOID)this << _T(" IEnumIDList* = ")
1720 << STATIC_CAST(IEnumIDList*, *CONST_CAST(TShellItemIterator*, this)));
1721 if (Index == -1)
1722 TXShell::Raise(IDS_SHELLITERATORATEND);
1723 TShellItem::TCreateStruct cs(Pidl, Folder);
1724 Next();
1725 if (Index != -1)
1726 Index++;
1727 return cs;
1728}
1729
1730//
1731/// operator -- decrements the "cursor" in the iterator, then returns
1732/// the item pointed to by the cursor
1733///
1734/// The item is returned as a TShellItem::TCreateStruct structure. For more
1735/// information about TCreateStruct, see the comments in the
1736/// TShellItem::TShellItem(const TCreateStruct& cs) constructor.
1737///
1738/// \note This function does not work with the intial release of Win95 because
1739/// it requires IEnumIDList::Reset to be called and IEnumIDList::Reset returns
1740/// E_NOTIMPL (not implemented) in the intitial Win95 release.
1741//
1744{
1746 return operator[] (Index - 1);
1747}
1748
1749//
1750/// operator --(int) returns the item pointed to by the "cursor," then decrements
1751/// the cursor.
1752///
1753/// The item is returned as a TShellItem::TCreateStruct structure. For more
1754/// information about TCreateStruct, see the comments in the
1755/// TShellItem::TShellItem(const TCreateStruct& cs) constructor.
1756///
1757/// \note This function does not work with the intial release of Win95 because
1758/// it requires IEnumIDList::Reset to be called and IEnumIDList::Reset returns
1759/// E_NOTIMPL (not implemented) in the intitial Win95 release.
1760//
1763{
1765 WARNX(OwlShell, Index == -1, 0, _T("Attempt to read past end of TShellItemIterator")
1766 << _T(" TShellItemIterator* = ") << hex << (LPVOID)this << _T(" IEnumIDList* = ")
1767 << STATIC_CAST(IEnumIDList*, *CONST_CAST(TShellItemIterator*, this)));
1768 if (Index == -1)
1769 TXShell::Raise(IDS_SHELLITERATORATEND);
1770 TShellItem::TCreateStruct cs(Pidl, Folder);
1771 Reset();
1772 Skip(--Index);
1773 Next();
1774 return cs;
1775}
1776
1777//
1778/// operator Current returns the item pointed to by the "cursor"
1779///
1780/// The item is returned as a TShellItem::TCreateStruct structure. For more
1781/// information about TCreateStruct, see the comments in the
1782/// TShellItem::TShellItem(const TCreateStruct& cs) constructor.
1783//
1786{
1788 WARNX(OwlShell, Index == -1, 0, _T("Attempt to read past end of TShellItemIterator")
1789 << _T(" TShellItemIterator* = ") << hex << (LPVOID)this << _T(" IEnumIDList* = ")
1790 << STATIC_CAST(IEnumIDList*, *CONST_CAST(TShellItemIterator*, this)));
1791 if (Index == -1)
1792 TXShell::Raise(IDS_SHELLITERATORATEND);
1793 return TShellItem::TCreateStruct(Pidl, Folder);
1794}
1795
1796//
1797/// Next is a protected function that increments the cursor. Equivalent to Skip(1).
1798//
1800{
1802
1803 WARNX(OwlShell, Index == -1, 0, _T("Attempt to read past end of TShellItemIterator")
1804 << _T(" TShellItemIterator* = ") << hex << (LPVOID)this << _T(" IEnumIDList* = ")
1805 << STATIC_CAST(IEnumIDList*, *CONST_CAST(TShellItemIterator*, this)));
1806 if (Index == -1)
1807 TXShell::Raise(IDS_SHELLITERATORATEND);
1808
1809 HRESULT hr = I->Next(1, Pidl, nullptr);
1810 WARNX(OwlShell, FAILED(hr), 0, _T("IShellItemIterator::Next failed.")
1811 << _T(" TShellItemIterator* = ") << hex << (LPVOID)this << _T(" IEnumIDList* = ")
1812 << STATIC_CAST(IEnumIDList*, *CONST_CAST(TShellItemIterator*, this)));
1813 TXShell::Check(hr, IDS_IDLISTNEXTFAIL);
1814 if (hr == S_FALSE)
1815 Index = -1;
1816}
1817
1818//
1819/// Skip advances the cursor <count> times. Equivalent to calling Next <count>
1820/// times.
1821///
1822/// \note This function does not work with the intial release of Win95 because
1823/// IEnumIDList::Skip returns E_NOTIMPL (not implemented) in the intitial Win95
1824/// release.
1825//
1826void
1828{
1830 if (count) {
1831 HRESULT hr = I->Skip(count);
1832 WARNX(OwlShell, FAILED(hr), 0, _T("IShellItemIterator::Skip failed.")
1833 << _T(" TShellItemIterator* = ") << hex << (LPVOID)this << _T(" IEnumIDList* = ")
1834 << STATIC_CAST(IEnumIDList*, *CONST_CAST(TShellItemIterator*, this))
1835 << _T(" count = ") << count);
1836 TXShell::Check(hr, IDS_IDLISTSKIPFAIL);
1837 if (hr == S_FALSE)
1838 Index = -1;
1839 else
1840 Index += count;
1841 }
1842}
1843
1844//
1845/// Reset resets the cursor to the beginning.
1846///
1847/// \note This function does not work with the intial release of Win95 because
1848/// IEnumIDList::Reset returns E_NOTIMPL (not implemented) in the intitial Win95
1849/// release.
1850//
1851void
1853{
1855 HRESULT hr = I->Reset();
1856 WARNX(OwlShell, FAILED(hr), 0, _T("IShellItemIterator::Reset failed.")
1857 << _T(" TShellItemIterator* = ") << hex << this << _T(" IEnumIDList* = ")
1858 << STATIC_CAST(IEnumIDList*, *CONST_CAST(TShellItemIterator*, this)));
1859 TXShell::Check(hr, IDS_IDLISTRESETFAIL);
1860 Index = 0;
1861}
1862
1863//
1864/// operator [] returns the item at the <index> location. index is zero based.
1865///
1866/// The item is returned as a TShellItem::TCreateStruct structure. For more
1867/// information about TCreateStruct, see the comments in the
1868/// TShellItem::TShellItem(const TCreateStruct& cs) constructor.
1869///
1870/// \note operator[] doesn't work with the intial release of Win95 because it
1871/// calls Skip and Reset wich are broken in the intial Win95 release. Both of
1872/// these functions return E_NOTIMPL (not implemented). The only way operator[]
1873/// will work is to call it sequentially, beginning at index 0 (i.e., to use it
1874/// like operator ++().
1875//
1878{
1880 if (Index == index)
1881 return TShellItem::TCreateStruct(Pidl, Folder);
1882 if (Index < index)
1883 Skip(index - Index - 1);
1884 else if (Index > index) {
1885 Reset();
1886 Skip(index);
1887 }
1888 Next();
1889 WARNX(OwlShell, Index == -1, 0, _T("Attempt to read past end of TShellItemIterator")
1890 << _T(" TShellItemIterator* = ") << hex << this << _T(" IEnumIDList* = ")
1891 << STATIC_CAST(IEnumIDList*, *CONST_CAST(TShellItemIterator*, this)));
1892 if (Index == -1) {
1893 TXShell::Raise(IDS_SHELLITERATORATEND);
1894 return TShellItem::TCreateStruct(); // To satisfy compiler
1895 }
1896 else
1897 return TShellItem::TCreateStruct(Pidl, Folder);
1898}
1899
1900//
1901/// GetCount returns the number of items in the iterator's list
1902///
1903/// \note This function does not work with the intial release of Win95 because
1904/// Clone and Reset are borken in the intitial Win95 release.
1905//
1906long
1908{
1910 TShellItemIterator list(*this); // clone so we don't affect position
1911 list.Reset();
1912 if (list.Index == -1)
1913 return 0;
1914 long cnt = 1;
1915 while (list.Skip(1), Index != -1)
1916 cnt++;
1917 return cnt;
1918}
1919
1920//
1921/// EnforceValidInterface is a protected function that checks to see that this
1922/// TShellItemIterator contains a valid IEnumIDList interface pointer. If it
1923/// doesn't, it throws an exception.
1924//
1925void
1927{
1928 WARNX(OwlShell, !I, 0, _T("TShellItemIterator is not valid (IEnumIDList* == 0).")
1929 << _T(" TShellItemIterator* = ") << hex
1930 << STATIC_CAST(IEnumIDList*, *CONST_CAST(TShellItemIterator*, this)));
1931 if (!I) {
1932 TXShell::Raise(IDS_IDLISTZEROPOINTER);
1933 }
1934}
1935
1936//
1937/// Constructs a TXShell object with a default IDS_SHELLFAILURE message.
1938//
1939TXShell::TXShell(uint resId, HANDLE handle)
1940:
1941 TXOwl(MakeMessage(resId, static_cast<uint>(reinterpret_cast<UINT_PTR>(handle))), resId)
1942{
1943}
1944
1946{
1947 return new TXShell(*this);
1948}
1949
1950
1951//
1952/// Throws the exception object.
1953//
1955{
1956 throw *this;
1957}
1958
1959//
1960/// Constructs a TXShell exception from scratch, and throws it.
1961//
1962void TXShell::Raise(uint resId, HANDLE handle)
1963{
1964 TXShell(resId, handle).Throw();
1965}
1966
1967//
1968/// Checks an HResult and throws a TXShell if not SUCCEEDED(hr).
1969//
1970void TXShell::Check(HRESULT hr, uint resID, HANDLE handle)
1971{
1972 if FAILED(hr)
1973 Raise(resID, handle);
1974}
1975
1976} // OWL namespace
1977
1978/* ========================================================================== */
1979
#define WARNX(group, condition, level, message)
Definition checks.h:277
TComRef< T > & operator=(T *iface)
Definition pointer.h:230
Wraps the IContextMenu interface (currently lightweight).
Definition shellitm.h:116
TContextMenu(IContextMenu *iface=0)
Default constructor for TContextMenu.
Definition shellitm.h:751
Wraps the IDataObject interface (currently lightweight).
Definition shellitm.h:133
TDataObject(IDataObject *iface=0)
Default constructor for TDataObject.
Definition shellitm.h:792
Wraps the IDropTarget interface (currently lightweight).
Definition shellitm.h:150
TDropTarget(IDropTarget *iface=0)
Default constructor for TDropTarget.
Definition shellitm.h:834
Wraps the IExtractIcon interface (currently lightweight).
Definition shellitm.h:99
TExtractIcon(IExtractIcon *iface=0)
Default constructor for TExtractIcon.
Definition shellitm.h:710
ObjectWindows dynamic-link libraries (DLLs) construct an instance of TModule, which acts as an object...
Definition module.h:78
static HRESULT CoCreateInstance(REFCLSID, LPUNKNOWN, DWORD, REFIID, LPVOID *)
Definition module.cpp:1212
TPidl is an item identifier list class (ITEMIDLIST).
Definition shellitm.h:169
long GetItemCount() const
Get number of item ids in the TPidl (the TPidl can be a list of ids).
Definition shellitm.cpp:253
TPidl(LPITEMIDLIST pidl=0)
Construct a TPidl from an LPITEMIDLIST (pidl).
Definition shellitm.h:897
void FreePidl()
Free a pidl with the shell's allocator.
Definition shellitm.cpp:239
static LPITEMIDLIST Next(LPITEMIDLIST pidl)
Return next item id (in the list).
Definition shellitm.h:883
ulong GetSize() const
Get size (in bytes) of a pidl.
Definition shellitm.cpp:271
TPidl GetLastItem() const
Get the last item id in the TPidl.
Definition shellitm.cpp:325
LPITEMIDLIST CopyPidl() const
Copy a pidl.
Definition shellitm.cpp:286
TPidl StripLastItem() const
Return a TPidl with the last item id stripped off of it.
Definition shellitm.cpp:358
static void DragFinish(HDROP)
Invokes 'DragFinish' indirectly.
Definition shellitm.cpp:84
static HRESULT SHGetMalloc(LPMALLOC *)
Invokes 'SHGetMalloc' indirectly.
Definition shellitm.cpp:186
static void SHChangeNotify(LONG, UINT, LPCVOID, LPCVOID)
Invokes 'SHChangeNotify' indirectly.
Definition shellitm.cpp:144
static HRESULT SHGetDesktopFolder(LPSHELLFOLDER *)
Invokes 'SHGetDesktopFolder' indirectly.
Definition shellitm.cpp:164
static void SHAddToRecentDocs(UINT, LPCVOID)
Invokes 'SHAddToRecentDocs' indirectly.
Definition shellitm.cpp:124
static BOOL SHGetPathFromIDList(LPCITEMIDLIST, TCHAR *)
Invokes 'SHGetPathFromIDList' indirectly.
Definition shellitm.cpp:196
static int SHFileOperation(LPSHFILEOPSTRUCT)
Invokes 'SHFileOperation' indirectly.
Definition shellitm.cpp:154
static void DragAcceptFiles(HWND, BOOL)
Invokes 'DragAcceptFiles' indirectly.
Definition shellitm.cpp:74
static HRESULT SHGetSpecialFolderLocation(HWND, int, LPITEMIDLIST *)
Invokes 'SHGetSpecialFolderLocation' indirectly.
Definition shellitm.cpp:206
static LPITEMIDLIST SHBrowseForFolder(LPBROWSEINFO)
Invokes 'SHBrowseForFolder' indirectly.
Definition shellitm.cpp:134
static HINSTANCE ShellExecute(HWND, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR, INT)
Invokes 'ShellExecute' indirectly.
Definition shellitm.cpp:216
static BOOL DragQueryPoint(HDROP, LPPOINT)
Invokes 'DragQueryPoint' indirectly.
Definition shellitm.cpp:104
static TModule & GetModule()
Returns TModule object wrapping the handle of the SHELL[32].DLL module.
Definition shellitm.cpp:65
static UINT DragQueryFile(HDROP, UINT, TCHAR *, UINT)
Invokes 'DragQueryFile' indirectly.
Definition shellitm.cpp:94
static BOOL Shell_NotifyIcon(DWORD, PNOTIFYICONDATA)
Invokes 'Shell_NotifyIcon' indirectly.
Definition shellitm.cpp:227
static HICON ExtractIcon(HINSTANCE, LPCTSTR, UINT)
Invokes 'ExtractIcon' indirectly.
Definition shellitm.cpp:114
static DWORD SHGetFileInfo(LPCTSTR, DWORD, SHFILEINFO *, UINT, UINT)
Invokes 'SHGetFileInfo' indirectly.
Definition shellitm.cpp:174
An item in the shell's name space.
Definition shellitm.h:238
HRESULT ParseDisplayName(TCreateStruct &cs, const tchar *displayName, ulong *eaten=nullptr, HWND windowOwner=nullptr, ulong *attrib=nullptr) const
Parse a display name into a TShellItem (actually, into a TCreateStruct).
bool IsShortcut(const bool validateCachedInfo=false) const
Return true if the TShellItem represents an item that is a shortcut.
Definition shellitm.h:1028
TShellItem(const tchar *path, bool throwOnInvalidPath=true, HWND windowOwner=0)
TShellItem constructor to make a TShellItem for a file or directory in the file system.
Definition shellitm.cpp:405
HICON GetIcon(TIconSize size=Shell, uint kind=0)
GetIcon returns a handle to an icon representing this TShellItem.
bool BrowseForFolder(TCreateStruct &cs, HWND windowOwner=0, const tchar *title=0, const UINT flags=0, int *image=0, const bool includeStatus=false, BFFCALLBACK func=0, const LPARAM param=0) const
Select a Foler under this TShellItem.
TShellItem ResolveShortcut(HWND windowOwner=0)
Get the TShellItem that a shortcut points to.
static HRESULT CreateShortCut(LPCTSTR objPath, TCHAR *pathLink, TCHAR *description)
Create a shortcut to a file object.
bool CanBeRenamed(const bool validateCachedInfo=false) const
Return true if the TShellItem represents an item that can be renamed.
Definition shellitm.h:997
bool ContainsSubFolder(const bool validateCachedInfo=false) const
Return true if the TShellItem represents an item that contains a subfolder.
Definition shellitm.h:1051
TShellItem & operator=(const TShellItem &source)
TShellItem assignment (from another TShellItem).
Definition shellitm.cpp:527
@ Open
Retrieves the shell item's open icon.
Definition shellitm.h:264
bool CanBeCopied(const bool validateCachedInfo=false) const
Return true if the TShellItem represents an item that can be copied.
Definition shellitm.h:968
TExeKind
Returned by TShellItem::GetExeType See MS doc for SHGetFileInfo for more information,...
Definition shellitm.h:364
@ WindowsPE
Windows level (3.0, 3.5, or 4.0).
Definition shellitm.h:367
@ WindowsNE
Windows-based application.
Definition shellitm.h:366
@ MSDOS
MS-DOS .EXE, .COM, or .BAT file.
Definition shellitm.h:368
@ Win32Console
Win32-based console application.
Definition shellitm.h:369
@ NonExecutable
Nonexecutable file or an error condition.
Definition shellitm.h:365
TString GetDisplayName(const TDisplayNameKind kind=Normal) const
Get Displayname (for a TShellItem that's part of the filesystem, this is the filename).
Definition shellitm.cpp:758
void AddToRecentDocs() const
Add to recent docs (Win95 taskbar:Start:Documents).
bool HaveSameParent(const TShellItem &other) const
HaveSameParent returns true if this TShellItem and other TShellItem have the same immediate parent fo...
Definition shellitm.h:1170
TIconSize
Used by TShellItem::GetIcon See MS doc for SHGetFileInfo for more information, Programmer's Guide to ...
Definition shellitm.h:252
@ Small
Retrieves the shell item's small icon.
Definition shellitm.h:253
@ Shell
Retrieves the shell-sized icon (if unavailable, the normal icon is sized according to the system metr...
Definition shellitm.h:254
TDisplayNameKind
Used by TShelItem::GetDisplayName() and TShellItem::Rename() See MS doc for SHGNO for more informatio...
Definition shellitm.h:244
@ ForParsing
File object suitable for parsing.
Definition shellitm.h:247
TCreateStruct GetParentFolder() const
Get Parent Folder.
Definition shellitm.cpp:606
bool GetAttribute(const TAttribute at, const bool validateCachedInfo) const
GetAttribute is a protected function used by all the attribute functions except IsDesktop.
Definition shellitm.cpp:579
TSpecialFolderKind
Used by TShellItem::TShellItem(const TSpecialFolderKind kind, HWND windowOwner = 0) See MS doc for SH...
Definition shellitm.h:273
@ Desktop
Virtual folder at the root of the namespace.
Definition shellitm.h:276
TDropTarget GetDropTarget(HWND windowOwner=0)
GetDropTarget returns an interface pointer to this TShellItem's IDropTarget OLE interface.
TExeKind GetExeType(uint *major=0, uint *minor=0) const
Get type of executable file (may return NonExecutable).
Definition shellitm.cpp:679
void RetrieveIShellFolder() const
RetrieveIShellFolder is a protected function that checks to see if a TShellItem's IShellFolder interf...
TDataObject GetDataObject(HWND windowOwner=0)
GetDataObject returns an interface pointer to this TShellItem's IDataObject OLE interface.
bool CanBeDeleted(const bool validateCachedInfo=false) const
Return true if the TShellItem represents an item that can be deleted.
Definition shellitm.h:975
bool Move(const tchar *destFolder, const USHORT flags=0, const tchar *title=0, HWND windowOwner=0)
Move moves this TShellItem to destination path (which must be a folder).
Definition shellitm.cpp:940
TPidl GetFullyQualifiedPidl() const
Get fully qualified TPidl.
Definition shellitm.cpp:649
TString GetPath() const
Get path (only call if the TShellItem is part of the file system (IsPartOfFileSystem == true).
Definition shellitm.cpp:792
bool IsPartOfFileSystem(const bool validateCachedInfo=false) const
Return true if the TShellItem represents an item that is part of the file system.
Definition shellitm.h:1067
bool IsFolder(const bool validateCachedInfo=false) const
Return true if the TShellItem represents an item that is a folder.
Definition shellitm.h:1074
bool Copy(const tchar *dest, const bool destIsFolder=true, const USHORT flags=0, const tchar *title=0, HWND windowOwner=0) const
Copy copies this TShellItem to destination path.
Definition shellitm.cpp:864
void EnforceValidity() const
EnforceValidity is a protected function that checks that a TShellItem is valid before proceeding with...
bool Delete(const USHORT flags=0, const tchar *title=0, HWND windowOwner=0)
Delete deletes this TShellItem.
TAttribute
Used by TShellItem::GetAttributes See MS doc for IShellFolder::GetAttributesOf for more information,...
Definition shellitm.h:297
void EnumObjects(IEnumIDList **iface, HWND windowOwner=0, const int kind=-1) const
EnumObjects is a protected function that returns an IEnumIDList enumerator on a folder.
bool Valid() const
Determine if TShellItem reprsents a valid item.
Definition shellitm.h:959
bool CanBeMoved(const bool validateCachedInfo=false) const
Return true if the TShellItem represents an item that can be moved.
Definition shellitm.h:990
ulong GetAttributes(const ulong reqAttrib, const bool validateCachedInfo=false) const
Get Attributes of a TShellItem GetAttributes - Get Capabilities, Display, Contents,...
Definition shellitm.cpp:559
TExtractIcon GetExtractIcon(HWND windowOwner=0)
GetExtractIcon returns an interface pointer to this TShellItem's IExtractIcon OLE interface.
void Rename(const tchar *newName, HWND windowOwner=0, const TDisplayNameKind kind=Normal)
Rename renames this TShellItem to newName.
Definition shellitm.cpp:817
TString GetTypeName() const
Get type of file (e.g., "Borland C++ Header File", "Notepad File").
Definition shellitm.cpp:727
bool IsDesktop() const
IsDesktop returns true if the TShellItem respresents the shell's desktop, i.e.
Definition shellitm.cpp:594
short CompareIDs(const TShellItem &rhs) const
CompareIDs is a protected function that compares a TShellItem's pidl with another TShellItem's pidl.
TContextMenu GetContextMenu(HWND windowOwner=0)
GetContextMenu returns an interface pointer to this TShellItem's IContextMenu OLE interface.
void EnforceValidInterface() const
EnforceValidInterface is a protected function that checks to see that this TShellItemIterator contain...
@ Folders
For shell browser.
Definition shellitm.h:577
@ NonFolders
For default view.
Definition shellitm.h:578
TShellItemIterator(const TShellItem &folder, HWND windowOwner=0, const int kind=Folders|NonFolders)
TShellItemIterator constructor.
TShellItemIterator & operator=(const TShellItemIterator &source)
Assignment operator.
void Reset()
Reset list.
TShellItem::TCreateStruct Current()
operator Current returns the item pointed to by the "cursor"
void Skip(const ulong count)
Skip count items.
long GetCount() const
Get number of TShellItems in the list.
TShellItem::TCreateStruct operator++()
operator ++ increments the "cursor" in the iterator, then returns the item pointed to by the cursor
TShellItem::TCreateStruct operator--()
operator – decrements the "cursor" in the iterator, then returns the item pointed to by the cursor
void Next()
Next is a protected function that increments the cursor. Equivalent to Skip(1).
TShellItem::TCreateStruct operator[](const long index)
operator [] returns the item at the <index> location.
Wraps the shell's IMalloc interface.
Definition shellitm.h:82
Reference to reference counted string object TUString Lightweight reference object consisting of a po...
Definition string.h:67
TString(const char *s=0)
Construct a TString from any type of string.
Definition string.h:255
void Throw()
Throws the exception object.
static void Check(HRESULT hr, uint resId=IDS_SHELLFAILURE, HANDLE handle=0)
Checks an HResult and throws a TXShell if not SUCCEEDED(hr).
TXShell * Clone()
TXShell(uint resId=IDS_SHELLFAILURE, HANDLE handle=0)
Constructs a TXShell object with a default IDS_SHELLFAILURE message.
static void Raise(uint resId=IDS_SHELLFAILURE, HANDLE handle=0)
Constructs a TXShell exception from scratch, and throws it.
#define _tcscat
Definition cygwin.h:83
#define _tcscpy
Definition cygwin.h:79
#define AnsiPrev
Definition cygwin.h:62
#define _MAX_PATH
Definition cygwin.h:97
#define _tcslen
Definition cygwin.h:74
#define _T(x)
Definition cygwin.h:51
static tstring MakeMessage(uint resId, const tstring &infoStr, TModule *module=&GetGlobalModule())
Definition except.cpp:233
TXOwl(const tstring &msg, uint resId=0)
An OWL exception with a given message for displaying and an unsigned Id that can be used for identifi...
Definition except.cpp:123
Object Windows Library (OWLNext Core).
Definition animctrl.h:22
unsigned short ushort
Definition number.h:24
unsigned long ulong
Definition number.h:26
char tchar
Definition defs.h:77
OWL_DIAGINFO
Definition animctrl.cpp:14
unsigned int uint
Definition number.h:25
DIAG_DEFINE_GROUP_INIT(OWL_INI, OwlApp, 1, 0)
#define OWL_INI
Definition defs.h:170
#define CONST_CAST(targetType, object)
Definition defs.h:273
#define REINTERPRET_CAST(targetType, object)
Definition defs.h:275
#define STATIC_CAST(targetType, object)
Definition defs.h:271
#define COUNTOF(s)
Array element count Important: Only use this with an argument of array type.
Definition defs.h:376
Definitions of Win95 Shell Clases: TShellItem, TShellItemIterator, TPidl, TShellMalloc.
TCreateStruct contains information to construct a TShellItem Typically a TCreateStruct is returned (f...
Definition shellitm.h:390
TComRef< IShellFolder > ParentFolder
Definition shellitm.h:396