2
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
3
* Copyright (C) 2009 Volker Berlin (i-net software)
4
* Copyright (C) 2010 Karsten Heinrich (i-net software)
5
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
7
* This code is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU General Public License version 2 only, as
9
* published by the Free Software Foundation. Oracle designates this
10
* particular file as subject to the "Classpath" exception as provided
11
* by Oracle in the LICENSE file that accompanied this code.
13
* This code is distributed in the hope that it will be useful, but WITHOUT
14
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16
* version 2 for more details (a copy is included in the LICENSE file that
17
* accompanied this code).
19
* You should have received a copy of the GNU General Public License version
20
* 2 along with this work; if not, write to the Free Software Foundation,
21
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
24
* or visit www.oracle.com if you need additional information or have any
28
package sun.awt.shell;
30
import java.awt.Image;
31
import java.awt.image.BufferedImage;
33
import java.io.FileNotFoundException;
34
import java.io.IOException;
36
import java.util.concurrent.*;
37
import javax.swing.SwingConstants;
39
import cli.System.IntPtr;
40
import cli.System.Drawing.Bitmap;
42
// NOTE: This class basically a conversion of the OpenJDK Wen32ShellFolder2, but uses
43
// .NET pointers and objects instead of representing pointers as long
49
* There are two fundamental types of shell folders : file system folders
50
* and non-file system folders. File system folders are relatively easy
51
* to deal with. Non-file system folders are items such as My Computer,
52
* Network Neighborhood, and the desktop. Some of these non-file system
53
* folders have special values and properties.
56
* Win32 keeps two basic data structures for shell folders. The first
57
* of these is called an ITEMIDLIST. Usually a pointer, called an
58
* LPITEMIDLIST, or more frequently just "PIDL". This structure holds
59
* a series of identifiers and can be either relative to the desktop
60
* (an absolute PIDL), or relative to the shell folder that contains them.
61
* Some Win32 functions can take absolute or relative PIDL values, and
62
* others can only accept relative values.
64
* The second data structure is an IShellFolder COM interface. Using
65
* this interface, one can enumerate the relative PIDLs in a shell
66
* folder, get attributes, etc.
68
* All Win32ShellFolder2 objects which are folder types (even non-file
69
* system folders) contain an IShellFolder object. Files are named in
70
* directories via relative PIDLs.
72
* @author Michael Martak
73
* @author Leif Samuelsson
74
* @author Kenneth Russell
75
* @author Volker Berlin
76
* @author Karsten Heinrich
79
final class Win32ShellFolder2 extends ShellFolder {
81
// Win32 Shell Folder Constants
82
public static final int DESKTOP = 0x0000;
83
public static final int INTERNET = 0x0001;
84
public static final int PROGRAMS = 0x0002;
85
public static final int CONTROLS = 0x0003;
86
public static final int PRINTERS = 0x0004;
87
public static final int PERSONAL = 0x0005;
88
public static final int FAVORITES = 0x0006;
89
public static final int STARTUP = 0x0007;
90
public static final int RECENT = 0x0008;
91
public static final int SENDTO = 0x0009;
92
public static final int BITBUCKET = 0x000a;
93
public static final int STARTMENU = 0x000b;
94
public static final int DESKTOPDIRECTORY = 0x0010;
95
public static final int DRIVES = 0x0011;
96
public static final int NETWORK = 0x0012;
97
public static final int NETHOOD = 0x0013;
98
public static final int FONTS = 0x0014;
99
public static final int TEMPLATES = 0x0015;
100
public static final int COMMON_STARTMENU = 0x0016;
101
public static final int COMMON_PROGRAMS = 0X0017;
102
public static final int COMMON_STARTUP = 0x0018;
103
public static final int COMMON_DESKTOPDIRECTORY = 0x0019;
104
public static final int APPDATA = 0x001a;
105
public static final int PRINTHOOD = 0x001b;
106
public static final int ALTSTARTUP = 0x001d;
107
public static final int COMMON_ALTSTARTUP = 0x001e;
108
public static final int COMMON_FAVORITES = 0x001f;
109
public static final int INTERNET_CACHE = 0x0020;
110
public static final int COOKIES = 0x0021;
111
public static final int HISTORY = 0x0022;
113
// Win32 shell folder attributes
114
public static final int ATTRIB_CANCOPY = 0x00000001;
115
public static final int ATTRIB_CANMOVE = 0x00000002;
116
public static final int ATTRIB_CANLINK = 0x00000004;
117
public static final int ATTRIB_CANRENAME = 0x00000010;
118
public static final int ATTRIB_CANDELETE = 0x00000020;
119
public static final int ATTRIB_HASPROPSHEET = 0x00000040;
120
public static final int ATTRIB_DROPTARGET = 0x00000100;
121
public static final int ATTRIB_LINK = 0x00010000;
122
public static final int ATTRIB_SHARE = 0x00020000;
123
public static final int ATTRIB_READONLY = 0x00040000;
124
public static final int ATTRIB_GHOSTED = 0x00080000;
125
public static final int ATTRIB_HIDDEN = 0x00080000;
126
public static final int ATTRIB_FILESYSANCESTOR = 0x10000000;
127
public static final int ATTRIB_FOLDER = 0x20000000;
128
public static final int ATTRIB_FILESYSTEM = 0x40000000;
129
public static final int ATTRIB_HASSUBFOLDER = 0x80000000;
130
public static final int ATTRIB_VALIDATE = 0x01000000;
131
public static final int ATTRIB_REMOVABLE = 0x02000000;
132
public static final int ATTRIB_COMPRESSED = 0x04000000;
133
public static final int ATTRIB_BROWSABLE = 0x08000000;
134
public static final int ATTRIB_NONENUMERATED = 0x00100000;
135
public static final int ATTRIB_NEWCONTENT = 0x00200000;
137
// IShellFolder::GetDisplayNameOf constants
138
public static final int SHGDN_NORMAL = 0;
139
public static final int SHGDN_INFOLDER = 1;
140
public static final int SHGDN_INCLUDE_NONFILESYS= 0x2000;
141
public static final int SHGDN_FORADDRESSBAR = 0x4000;
142
public static final int SHGDN_FORPARSING = 0x8000;
144
// Values for system call LoadIcon()
145
public enum SystemIcon {
146
IDI_APPLICATION(32512),
150
IDI_EXCLAMATION(32515),
153
IDI_INFORMATION(32516),
156
private final int iconID;
158
SystemIcon(int iconID) {
159
this.iconID = iconID;
162
public int getIconID() {
167
static class FolderDisposer implements sun.java2d.DisposerRecord {
169
* This is cached as a concession to getFolderType(), which needs
172
cli.System.IntPtr absolutePIDL;
174
* We keep track of shell folders through the IShellFolder
175
* interface of their parents plus their relative PIDL.
177
cli.System.Object pIShellFolder;
178
cli.System.IntPtr relativePIDL;
182
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
183
public void dispose() {
186
if ( relativePIDL != null && !cli.System.IntPtr.Zero.Equals( relativePIDL ) ) {
187
releasePIDL(relativePIDL);
189
if ( absolutePIDL != null && !cli.System.IntPtr.Zero.Equals( absolutePIDL ) ) {
190
releasePIDL(absolutePIDL);
192
if ( pIShellFolder != null ) {
193
releaseIShellFolder(pIShellFolder);
199
FolderDisposer disposer = new FolderDisposer();
201
private void setIShellFolder( cli.System.Object iShellFolder ) {
202
disposer.pIShellFolder = iShellFolder;
205
private void setRelativePIDL(cli.System.IntPtr relativePIDL) {
206
disposer.relativePIDL = relativePIDL;
210
* The following are for caching various shell folder properties.
212
private cli.System.Object pIShellIcon = null;
213
private String folderType = null;
214
private String displayName = null;
215
private Image smallIcon = null;
216
private Image largeIcon = null;
217
private Boolean isDir = null;
220
* The following is to identify the My Documents folder as being special
222
private boolean isPersonal;
225
* Create a system special shell folder, such as the
226
* desktop or Network Neighborhood.
228
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
229
Win32ShellFolder2(final int csidl) throws IOException, InterruptedException {
230
// Desktop is parent of DRIVES and NETWORK, not necessarily
231
// other special shell folders.
232
super ( null, (getFileSystemPath(csidl) == null) ? ("ShellFolder: 0x" + Integer.toHexString(csidl)) : getFileSystemPath(csidl));
233
if (csidl == DESKTOP) {
234
// compared to the Java implementation we require two steps here since
235
// we don't have a callback from the native methods in to this instance
236
setIShellFolder( initDesktopFolder() );
237
setRelativePIDL( initDesktopPIDL() );
239
cli.System.Object desktopFolder = getDesktop().getIShellFolder();
240
cli.System.IntPtr pidl = initSpecialPIDL( desktopFolder, csidl );
241
setRelativePIDL( pidl );
242
setIShellFolder( initSpecialFolder(desktopFolder, pidl) );
243
// At this point, the native method initSpecial() has set our relativePIDL
244
// relative to the Desktop, which may not be our immediate parent. We need
245
// to traverse this ID list and break it into a chain of shell folders from
246
// the top, with each one having an immediate parent and a relativePIDL
247
// relative to that parent.
251
sun.java2d.Disposer.addRecord(this , disposer);
254
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
255
protected void bindToDesktop() {
256
cli.System.IntPtr pIDL = disposer.relativePIDL;
257
parent = getDesktop();
258
while ( pIDL != null && !cli.System.IntPtr.Zero.Equals( pIDL ) ) {
259
// Get a child pidl relative to 'parent'
260
cli.System.IntPtr childPIDL = copyFirstPIDLEntry(pIDL);
261
if (childPIDL != null && !cli.System.IntPtr.Zero.Equals( childPIDL ) ) {
262
// Get a handle to the the rest of the ID list
263
// i,e, parent's grandchilren and down
264
pIDL = getNextPIDLEntry(pIDL);
265
if ( pIDL != null && !cli.System.IntPtr.Zero.Equals( pIDL ) ) {
266
// Now we know that parent isn't immediate to 'this' because it
267
// has a continued ID list. Create a shell folder for this child
268
// pidl and make it the new 'parent'.
269
parent = new Win32ShellFolder2( (Win32ShellFolder2) parent, childPIDL );
271
// No grandchildren means we have arrived at the parent of 'this',
272
// and childPIDL is directly relative to parent.
273
disposer.relativePIDL = childPIDL;
282
* Create a system shell folder
284
@cli.System.Security.SecurityCriticalAttribute.Annotation
285
Win32ShellFolder2(Win32ShellFolder2 parent, cli.System.Object pIShellFolder, cli.System.IntPtr relativePIDL, String path) {
286
super(parent, (path != null) ? path : "ShellFolder: ");
287
this.disposer.pIShellFolder = pIShellFolder;
288
this.disposer.relativePIDL = relativePIDL;
289
sun.java2d.Disposer.addRecord(this, disposer);
293
* Creates a shell folder with a parent and relative PIDL
295
@cli.System.Security.SecurityCriticalAttribute.Annotation
296
Win32ShellFolder2(Win32ShellFolder2 parent, cli.System.IntPtr relativePIDL) {
297
super (parent, getFileSystemPath(parent.getIShellFolder(), relativePIDL));
298
this .disposer.relativePIDL = relativePIDL;
300
sun.java2d.Disposer.addRecord(this , disposer);
303
// Initializes the desktop shell folder
305
* Returns the pIDL of the Desktop folder (pIDL root)
306
* @return the pIDL of the Desktop folder (pIDL root)
308
@cli.System.Security.SecurityCriticalAttribute.Annotation
309
private static native cli.System.IntPtr initDesktopPIDL();
311
* Returns the IShellFolder pointer of the Desktop folder (pIDL root)
312
* @return the IShellFolder pointer of the Desktop folder (pIDL root)
314
@cli.System.Security.SecurityCriticalAttribute.Annotation
315
private static native cli.System.Object initDesktopFolder();
317
// Initializes a special, non-file system shell folder
318
// from one of the above constants
320
* initializes a special folder
321
* @param desktopIShellFolder the IShellFolder reference of the desktop folder
322
* @param csidl the CSIDL of the requested special folder
323
* @return the pIDL of the special folder relative to the desktop root
325
@cli.System.Security.SecurityCriticalAttribute.Annotation
326
private static native cli.System.IntPtr initSpecialPIDL(cli.System.Object desktopIShellFolder, int csidl);
328
* initializes a special folder
329
* @param desktopIShellFolder the IShellFolder reference of the desktop folder
330
* @param pidl the pIDL of the requested folder relative to the desktopIShellFolder
331
* @return the IShellFolder reference for the requested folder
333
@cli.System.Security.SecurityCriticalAttribute.Annotation
334
private static native cli.System.Object initSpecialFolder(cli.System.Object desktopIShellFolder, cli.System.IntPtr pidl);
336
/** Marks this folder as being the My Documents (Personal) folder */
337
public void setIsPersonal() {
342
* This method is implemented to make sure that no instances
343
* of <code>ShellFolder</code> are ever serialized. If <code>isFileSystem()</code> returns
344
* <code>true</code>, then the object is representable with an instance of
345
* <code>java.io.File</code> instead. If not, then the object depends
346
* on native PIDL state and should not be serialized.
348
* @returns a <code>java.io.File</code> replacement object. If the folder
349
* is a not a normal directory, then returns the first non-removable
350
* drive (normally "C:\").
352
protected Object writeReplace()
353
throws java.io.ObjectStreamException {
354
if (isFileSystem()) {
355
return new File(getPath());
357
Win32ShellFolder2 drives = Win32ShellFolderManager2.getDrives();
358
if (drives != null) {
359
File[] driveRoots = drives.listFiles();
360
if (driveRoots != null) {
361
for (int i = 0; i < driveRoots.length; i++) {
362
if (driveRoots[i] instanceof Win32ShellFolder2) {
363
Win32ShellFolder2 sf = (Win32ShellFolder2) driveRoots[i];
364
if (sf.isFileSystem() && !sf.hasAttribute(ATTRIB_REMOVABLE)) {
365
return new File(sf.getPath());
371
// Ouch, we have no hard drives. Return something "valid" anyway.
372
return new File("C:\\");
377
* Finalizer to clean up any COM objects or PIDLs used by this object.
379
protected void dispose() {
383
// Given a (possibly multi-level) relative PIDL (with respect to
384
// the desktop, at least in all of the usage cases in this code),
385
// return a pointer to the next entry. Does not mutate the PIDL in
386
// any way. Returns 0 if the null terminator is reached.
387
// Needs to be accessible to Win32ShellFolderManager2
388
@cli.System.Security.SecurityCriticalAttribute.Annotation
389
static native cli.System.IntPtr getNextPIDLEntry(cli.System.IntPtr pIDL);
391
// Given a (possibly multi-level) relative PIDL (with respect to
392
// the desktop, at least in all of the usage cases in this code),
393
// copy the first entry into a newly-allocated PIDL. Returns 0 if
394
// the PIDL is at the end of the list.
395
// Needs to be accessible to Win32ShellFolderManager2
396
@cli.System.Security.SecurityCriticalAttribute.Annotation
397
static native cli.System.IntPtr copyFirstPIDLEntry(cli.System.IntPtr pIDL);
399
// Given a parent's absolute PIDL and our relative PIDL, build an absolute PIDL
401
* Combines a parent pIDL with a descendant pIDL. It doesn't matter whether the parent pIDL
402
* is relative or absolute since this is only a concatenation of the IDLs
403
* @param ppIDL the parent pIDL
404
* @param pIDL the pIDL relative to the ppIDL
405
* @return a pIDL for the item referenced by the original pIDL but relative to the parent of ppIDL
407
@cli.System.Security.SecurityCriticalAttribute.Annotation
408
private static native cli.System.IntPtr combinePIDLs(cli.System.IntPtr ppIDL, cli.System.IntPtr pIDL);
410
// Release a PIDL object
411
// Needs to be accessible to Win32ShellFolderManager2
412
@cli.System.Security.SecurityCriticalAttribute.Annotation
413
static native void releasePIDL(cli.System.IntPtr pIDL);
415
// Release an IShellFolder object
416
@cli.System.Security.SecurityCriticalAttribute.Annotation
417
static native void releaseIShellFolder( cli.System.Object iShellFolder );
420
* Accessor for IShellFolder
422
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
423
public cli.System.Object getIShellFolder() {
424
if (disposer.pIShellFolder == null ) {
425
assert (isDirectory());
426
assert (parent != null);
427
cli.System.Object parentIShellFolder = getParentIShellFolder();
428
if (parentIShellFolder == null) {
429
throw new InternalError( "Parent IShellFolder was null for " + getAbsolutePath() );
431
// We are a directory with a parent and a relative PIDL.
432
// We want to bind to the parent so we get an IShellFolder instance associated with us.
433
disposer.pIShellFolder = bindToObject(parentIShellFolder, disposer.relativePIDL);
434
if (disposer.pIShellFolder == null ) {
435
throw new InternalError("Unable to bind " + getAbsolutePath() + " to parent");
438
return disposer.pIShellFolder;
442
* Get the parent ShellFolder's IShellFolder interface
444
public cli.System.Object getParentIShellFolder() {
445
Win32ShellFolder2 parent = (Win32ShellFolder2) getParentFile();
446
cli.System.Object parentFolder;
447
if (parent == null) {
448
// Parent should only be null if this is the desktop, whose
449
// relativePIDL is relative to its own IShellFolder.
450
parentFolder = getIShellFolder();
452
parentFolder = parent.getIShellFolder();
458
* Accessor for relative PIDL
460
public cli.System.IntPtr getRelativePIDL() {
461
if (disposer.relativePIDL == null) {
462
throw new InternalError( "Should always have a relative PIDL" );
464
return disposer.relativePIDL;
467
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
468
private cli.System.IntPtr getAbsolutePIDL() {
469
if (parent == null) {
470
// This is the desktop
471
return getRelativePIDL();
473
if (disposer.absolutePIDL == null || disposer.absolutePIDL.Equals( IntPtr.Zero )) {
474
disposer.absolutePIDL = combinePIDLs( ((Win32ShellFolder2) parent).getAbsolutePIDL(), getRelativePIDL());
477
return disposer.absolutePIDL;
482
* Helper function to return the desktop
484
public Win32ShellFolder2 getDesktop() {
485
return Win32ShellFolderManager2.getDesktop();
489
* Helper function to return the desktop IShellFolder interface
491
public cli.System.Object getDesktopIShellFolder() {
492
return getDesktop().getIShellFolder();
495
private static boolean pathsEqual(String path1, String path2) {
496
// Same effective implementation as Win32FileSystem
497
return path1.equalsIgnoreCase(path2);
501
* Check to see if two ShellFolder objects are the same
503
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
504
public boolean equals(Object o) {
505
if (o == null || !(o instanceof Win32ShellFolder2)) {
506
// Short-circuit circuitous delegation path
507
if (!(o instanceof File)) {
508
return super.equals(o);
510
return pathsEqual(getPath(), ((File) o).getPath());
512
Win32ShellFolder2 rhs = (Win32ShellFolder2) o;
513
if ((parent == null && rhs.parent != null) ||
514
(parent != null && rhs.parent == null)) {
518
if (isFileSystem() && rhs.isFileSystem()) {
519
// Only folders with identical parents can be equal
520
return (pathsEqual(getPath(), rhs.getPath()) &&
521
(parent == rhs.parent || parent.equals(rhs.parent)));
524
if (parent == rhs.parent || parent.equals(rhs.parent)) {
526
return pidlsEqual(getParentIShellFolder(), disposer.relativePIDL, rhs.disposer.relativePIDL);
527
} catch (InterruptedException e) {
535
@cli.System.Security.SecurityCriticalAttribute.Annotation
536
static boolean pidlsEqual(final cli.System.Object pIShellFolder, final cli.System.IntPtr pidl1, final cli.System.IntPtr pidl2)
537
throws InterruptedException {
538
return invoke(new Callable<Boolean>() {
539
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
540
public Boolean call() {
541
return compareIDs(pIShellFolder, pidl1, pidl2) == 0;
543
}, RuntimeException.class);
546
@cli.System.Security.SecurityCriticalAttribute.Annotation
547
static native int compareIDs(cli.System.Object pParentIShellFolder, cli.System.IntPtr pidl1, cli.System.IntPtr pidl2);
549
private volatile Boolean cachedIsFileSystem;
552
* @return Whether this is a file system shell folder
554
public boolean isFileSystem() {
555
if (cachedIsFileSystem == null) {
556
cachedIsFileSystem = hasAttribute(ATTRIB_FILESYSTEM);
559
return cachedIsFileSystem;
563
* Return whether the given attribute flag is set for this object
565
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
566
public boolean hasAttribute(int attribute) {
567
// Caching at this point doesn't seem to be cost efficient
568
return (getAttributes0(getParentIShellFolder(), getRelativePIDL(), attribute) & attribute) != 0;
572
* Returns the queried attributes specified in attrsMask.
574
* Could plausibly be used for attribute caching but have to be
575
* very careful not to touch network drives and file system roots
576
* with a full attrsMask
578
@cli.System.Security.SecurityCriticalAttribute.Annotation
579
static native int getAttributes0(cli.System.Object pParentIShellFolder, cli.System.IntPtr pIDL, int attrsMask);
581
// Return the path to the underlying file system object
582
@cli.System.Security.SecurityCriticalAttribute.Annotation
583
private static String getFileSystemPath(cli.System.Object parentIShellFolder, cli.System.IntPtr relativePIDL) {
584
int linkedFolder = ATTRIB_LINK | ATTRIB_FOLDER;
585
if (parentIShellFolder == Win32ShellFolderManager2.getNetwork().getIShellFolder() &&
586
getAttributes0(parentIShellFolder, relativePIDL, linkedFolder) == linkedFolder) {
588
cli.System.Object desktopIShellFolder = Win32ShellFolderManager2.getDesktop().getIShellFolder();
589
String path = getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_FORPARSING );
590
String s = getFileSystemPath(desktopIShellFolder, getLinkLocation( path, false));
591
if (s != null && s.startsWith("\\\\")) {
595
return getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_NORMAL | SHGDN_FORPARSING);
598
// Needs to be accessible to Win32ShellFolderManager2
599
@cli.System.Security.SecurityCriticalAttribute.Annotation
600
static native String getFileSystemPath(int csidl) throws IOException, InterruptedException;
602
// Return whether the path is a network root.
603
// Path is assumed to be non-null
604
private static boolean isNetworkRoot(String path) {
605
return (path.equals("\\\\") || path.equals("\\") || path.equals("//") || path.equals("/"));
609
* @return The parent shell folder of this shell folder, null if
612
public File getParentFile() {
616
public boolean isDirectory() {
618
// Folders with SFGAO_BROWSABLE have "shell extension" handlers and are
619
// not traversable in JFileChooser.
620
if (hasAttribute(ATTRIB_FOLDER) && !hasAttribute(ATTRIB_BROWSABLE)) {
621
isDir = Boolean.TRUE;
622
} else if (isLink()) {
623
ShellFolder linkLocation = getLinkLocation(false);
624
isDir = Boolean.valueOf(linkLocation != null && linkLocation.isDirectory());
626
isDir = Boolean.FALSE;
629
return isDir.booleanValue();
633
* Functions for enumerating an IShellFolder's children
635
// Returns an IEnumIDList interface for an IShellFolder. The value
636
// returned must be released using releaseEnumObjects().
638
* Returns an IEnumIDList interface for an IShellFolder. The value
639
* returned must be released using releaseEnumObjects().
640
* @param pIShellFolder the IShellFolder instance of the parent shell folder
641
* @param includeHiddenFiles if true, hidden files will be included in the enumeration
642
* @return an instance of IEnumIDList
644
@cli.System.Security.SecurityCriticalAttribute.Annotation
645
cli.System.Object getEnumObjects(cli.System.Object pIShellFolder, boolean includeHiddenFiles) {
646
boolean isDesktop = (disposer.pIShellFolder == getDesktopIShellFolder());
647
return getEnumObjects(disposer.pIShellFolder, isDesktop, includeHiddenFiles);
651
* Returns an IEnumIDList interface for an IShellFolder. The value
652
* returned must be released using releaseEnumObjects().
653
* @param pIShellFolder the IShellFolder instance of the parent shell folder
654
* @param isDesktop must be set to true, if the pIShellFolder is the desktop shell folder
655
* @param includeHiddenFiles if true, hidden files will be included in the enumeration
656
* @return an instance of IEnumIDList
658
@cli.System.Security.SecurityCriticalAttribute.Annotation
659
private static native cli.System.Object getEnumObjects(cli.System.Object pIShellFolder, boolean isDesktop, boolean includeHiddenFiles);
662
* Returns the next sequential child as a relative PIDL
663
* from an IEnumIDList interface. The value returned must
664
* be released using releasePIDL().
665
* @param pEnumObjects the IEnumIDList instance to get the next child from
666
* @return the next child or {@link IntPtr#Zero} if the end of the enumeration is reached
668
@cli.System.Security.SecurityCriticalAttribute.Annotation
669
static native cli.System.IntPtr getNextChild(cli.System.Object pEnumObjects);
672
* Releases the IEnumIDList interface
673
* @param pEnumObjects an IEnumIDList instance
675
@cli.System.Security.SecurityCriticalAttribute.Annotation
676
static native void releaseEnumObjects(cli.System.Object pEnumObjects);
679
* Returns the IShellFolder of a child from a parent IShellFolder and a relative pIDL. The pIDL
680
* may as well be any other descendant of the shell folder - at least this is, what the windows API
681
* documentation says.
682
* The value returned must be released using releaseIShellFolder().
683
* @param parentIShellFolder an IShellFolder instance as root for the pIDL
684
* @param pIDL a pIDL relative to the parent shell folder
685
* @return a NEW instance of an IShellFolder for the path given by the pIDL, may be null if the path is invalid
687
@cli.System.Security.SecurityCriticalAttribute.Annotation
688
private static native cli.System.Object bindToObject(cli.System.Object parentIShellFolder, cli.System.IntPtr pIDL);
691
* @return An array of shell folders that are children of this shell folder
692
* object. The array will be empty if the folder is empty. Returns
693
* <code>null</code> if this shellfolder does not denote a directory.
695
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
696
public File[] listFiles(final boolean includeHiddenFiles) {
697
SecurityManager security = System.getSecurityManager();
698
if (security != null) {
699
security.checkRead(getPath());
703
return invoke(new Callable<File[]>() {
704
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
705
public File[] call() throws InterruptedException {
706
if (!isDirectory()) {
709
// Links to directories are not directories and cannot be parents.
710
// This does not apply to folders in My Network Places (NetHood)
711
// because they are both links and real directories!
712
if (isLink() && !hasAttribute(ATTRIB_FOLDER)) {
716
Win32ShellFolder2 desktop = Win32ShellFolderManager2.getDesktop();
717
Win32ShellFolder2 personal = Win32ShellFolderManager2.getPersonal();
719
// If we are a directory, we have a parent and (at least) a
720
// relative PIDL. We must first ensure we are bound to the
721
// parent so we have an IShellFolder to query.
722
cli.System.Object pIShellFolder = getIShellFolder();
723
// Now we can enumerate the objects in this folder.
724
ArrayList<Win32ShellFolder2> list = new ArrayList<Win32ShellFolder2>();
725
cli.System.Object pEnumObjects = getEnumObjects(pIShellFolder, includeHiddenFiles);
726
if (pEnumObjects != null) {
727
cli.System.IntPtr childPIDL = null;
728
int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR;
730
if (Thread.currentThread().isInterrupted()) {
733
childPIDL = getNextChild(pEnumObjects);
734
boolean releasePIDL = true;
735
if ( childPIDL != null && !cli.System.IntPtr.Zero.Equals( childPIDL ) && (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) {
736
Win32ShellFolder2 childFolder = null;
737
if (this .equals(desktop) && personal != null
738
&& pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL) ) {
739
childFolder = personal;
741
childFolder = new Win32ShellFolder2(Win32ShellFolder2.this , childPIDL);
744
list.add(childFolder);
747
releasePIDL(childPIDL);
749
} while (childPIDL != null && !childPIDL.Equals( cli.System.IntPtr.Zero ));
750
releaseEnumObjects(pEnumObjects);
752
return Thread.currentThread().isInterrupted()
754
: list.toArray(new ShellFolder[list.size()]);
756
}, InterruptedException.class);
757
} catch (InterruptedException e) {
764
* Look for (possibly special) child folder by it's path. Note: this will not work an an ancestor(not child)
765
* of the current folder.
766
* @return The child shell folder, or null if not found.
768
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
769
Win32ShellFolder2 getChildByPath(String filePath) {
770
cli.System.Object pIShellFolder = getIShellFolder();
771
cli.System.Object pEnumObjects = getEnumObjects(pIShellFolder, true);
772
Win32ShellFolder2 child = null;
773
cli.System.IntPtr childPIDL = null;
775
childPIDL = getNextChild(pEnumObjects);
776
while ( childPIDL != null && !cli.System.IntPtr.Zero.Equals( childPIDL ) ) {
777
if (getAttributes0(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM) != 0) {
778
String path = getFileSystemPath(pIShellFolder, childPIDL);
779
if (path != null && path.equalsIgnoreCase(filePath)) {
780
cli.System.Object childIShellFolder = bindToObject( pIShellFolder, childPIDL);
781
child = new Win32ShellFolder2(this, childIShellFolder, childPIDL, path);
785
releasePIDL(childPIDL);
786
childPIDL = getNextChild(pEnumObjects);
788
releaseEnumObjects(pEnumObjects);
792
private volatile Boolean cachedIsLink;
795
* @return Whether this shell folder is a link
797
public boolean isLink() {
798
if (cachedIsLink == null) {
799
cachedIsLink = hasAttribute(ATTRIB_LINK);
806
* @return Whether this shell folder is marked as hidden
808
public boolean isHidden() {
809
return hasAttribute(ATTRIB_HIDDEN);
812
// Return the link location of a shell folder
814
* Resolves the link location of an item to an ABSOLUTE pIDL
815
* @param parentIShellFolder the pointer to the parent IShellFolder of the item
816
* @param relativePIDL a single-level pIDL to the item
819
@cli.System.Security.SecurityCriticalAttribute.Annotation
820
static native cli.System.IntPtr getLinkLocation( String path, boolean resolve);
823
* @return The shell folder linked to by this shell folder, or null
824
* if this shell folder is not a link or is a broken or invalid link
826
public ShellFolder getLinkLocation() {
827
return getLinkLocation(true);
830
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
831
private ShellFolder getLinkLocation(final boolean resolve) {
832
return invoke(new Callable<ShellFolder>() {
833
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
834
public ShellFolder call() {
839
ShellFolder location = null;
840
cli.System.IntPtr linkLocationPIDL = getLinkLocation( getAbsolutePath(), resolve);
841
if (linkLocationPIDL != null && !cli.System.IntPtr.Zero.Equals( linkLocationPIDL ) ) {
844
Win32ShellFolderManager2.createShellFolderFromRelativePIDL(getDesktop(),
846
} catch (InterruptedException e) {
848
} catch (InternalError e) {
849
// Could be a link to a non-bindable object, such as a network connection
850
// TODO: getIShellFolder() should throw FileNotFoundException instead
859
* Parse a display name into a PIDL relative to the current IShellFolder.
860
* @param name the name or relative path
861
* @return a pIDL for the path, may be {@link IntPtr#Zero} if not found
862
* @throws FileNotFoundException
864
@cli.System.Security.SecurityCriticalAttribute.Annotation
865
cli.System.IntPtr parseDisplayName(String name) throws FileNotFoundException {
867
return parseDisplayName0(getIShellFolder(), name);
868
} catch (IOException e) {
869
throw new FileNotFoundException("Could not find file " + name);
873
@cli.System.Security.SecurityCriticalAttribute.Annotation
874
private static native cli.System.IntPtr parseDisplayName0(cli.System.Object pIShellFolder, String name) throws IOException;
877
* Returns the display name of an item in a folder
878
* @param parentIShellFolder the pointer to the IShellFolder interface of the parent folder
879
* @param relativePIDL single-level pIDL to the requested item within the parent folder
880
* @param attrs formatting attributes for the display name, refer to SHGDN in MSDN
883
@cli.System.Security.SecurityCriticalAttribute.Annotation
884
private static native String getDisplayNameOf( cli.System.Object parentIShellFolder, cli.System.IntPtr relativePIDL, int attrs);
887
* @return The name used to display this shell folder
889
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
890
public String getDisplayName() {
891
if (displayName == null) {
892
displayName = getDisplayNameOf(getParentIShellFolder(), getRelativePIDL(), SHGDN_NORMAL);
897
// Return the folder type of a shell folder
898
@cli.System.Security.SecurityCriticalAttribute.Annotation
899
private static native String getFolderType(cli.System.IntPtr pIDL);
902
* @return The type of shell folder as a string
904
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
905
public String getFolderType() {
906
if (folderType == null) {
907
folderType = getFolderType(getAbsolutePIDL());
912
// Return the executable type of a file system shell folder
913
private static native String getExecutableType(String path);
916
* @return The executable type as a string
918
public String getExecutableType() {
919
if (!isFileSystem()) {
922
return getExecutableType(getAbsolutePath());
927
private static Map smallSystemImages = new HashMap();
928
private static Map largeSystemImages = new HashMap();
929
private static Map smallLinkedSystemImages = new HashMap();
930
private static Map largeLinkedSystemImages = new HashMap();
933
* Returns the icon index in the system image list
934
* @param parentIShellIcon the the pointer to the IShellIcon instance of the parent folder
935
* @param relativePIDL the relative pIDL to the requested item
936
* @return the system image list index for the icon of the item or zero, if there is no entry
938
@cli.System.Security.SecurityCriticalAttribute.Annotation
939
private static native int getIconIndex(cli.System.Object parentIShellFolder, cli.System.IntPtr relativePIDL);
941
// Return the icon of a file system shell folder in the form of an HICON
942
@cli.System.Security.SecurityCriticalAttribute.Annotation
943
private static native cli.System.IntPtr getIcon(String absolutePath, boolean getLargeIcon);
945
@cli.System.Security.SecurityCriticalAttribute.Annotation
946
private static native cli.System.IntPtr extractIcon(cli.System.Object parentIShellFolder, cli.System.IntPtr relativePIDL,
947
boolean getLargeIcon);
950
* Returns the {@link Bitmap} for a HICON.
952
@cli.System.Security.SecurityCriticalAttribute.Annotation
953
private static native Bitmap getIconBits(cli.System.IntPtr hIcon, int size);
956
* Disposes a icon handle
957
* @param hIcon the handle to be disposed
959
@cli.System.Security.SecurityCriticalAttribute.Annotation
960
private static native void disposeIcon(cli.System.IntPtr hIcon);
962
@cli.System.Security.SecurityCriticalAttribute.Annotation
963
static native Bitmap getStandardViewButton0(int iconIndex);
966
* Creates a Java icon for a HICON pointer
967
* @param hIcon the handle for the icon
968
* @param getLargeIcon true for a large icon, false for a small icon
969
* @return the created image or null, if the handle is invalid
971
@cli.System.Security.SecurityCriticalAttribute.Annotation
972
private static Image makeIcon(cli.System.IntPtr hIcon, boolean getLargeIcon) {
973
if (hIcon != null ) {
974
// Get the bits. This has the side effect of setting the imageHash value for this object.
975
Bitmap bitmap = getIconBits(hIcon, getLargeIcon ? 32 : 16 );
976
if (bitmap == null) {
979
return new BufferedImage(bitmap);
986
* @return The icon image used to display this shell folder
988
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
989
public Image getIcon(boolean getLargeIcon) {
990
Image icon = getLargeIcon ? largeIcon : smallIcon;
992
cli.System.IntPtr relativePIDL = getRelativePIDL();
994
if (isFileSystem() && parent != null) {
995
// These are cached per type (using the index in the system image list)
996
int index = getIconIndex( ((Win32ShellFolder2)parent).getIShellFolder(), relativePIDL);
1000
imageCache = getLargeIcon ? largeLinkedSystemImages : smallLinkedSystemImages;
1002
imageCache = getLargeIcon ? largeSystemImages : smallSystemImages;
1004
icon = (Image) imageCache.get(Integer.valueOf(index));
1006
cli.System.IntPtr hIcon = getIcon(getAbsolutePath(), getLargeIcon);
1007
icon = makeIcon(hIcon, getLargeIcon);
1010
imageCache.put(Integer.valueOf(index), icon);
1017
// These are only cached per object
1018
cli.System.IntPtr hIcon = extractIcon(getParentIShellFolder(), getRelativePIDL(), getLargeIcon);
1019
icon = makeIcon(hIcon, getLargeIcon);
1030
icon = super .getIcon(getLargeIcon);
1036
* Gets an icon from the Windows system icon list as an <code>Image</code>
1038
static Image getShell32Icon(int iconID, boolean getLargeIcon) {
1039
Bitmap bitmap = getShell32IconResourceAsBitmap(iconID, getLargeIcon);
1040
if (bitmap == null) {
1043
return new BufferedImage(bitmap);
1046
private static native Bitmap getShell32IconResourceAsBitmap(int iconID, boolean getLargeIcon);
1049
* Returns the canonical form of this abstract pathname. Equivalent to
1050
* <code>new Win32ShellFolder2(getParentFile(), this.{@link java.io.File#getCanonicalPath}())</code>.
1052
* @see java.io.File#getCanonicalFile
1054
public File getCanonicalFile() throws IOException {
1059
* Indicates whether this is a special folder (includes My Documents)
1061
public boolean isSpecial() {
1062
return isPersonal || !isFileSystem() || (this == getDesktop());
1066
* Compares this object with the specified object for order.
1068
* @see sun.awt.shell.ShellFolder#compareTo(File)
1070
public int compareTo(File file2) {
1071
if (!(file2 instanceof Win32ShellFolder2)) {
1072
if (isFileSystem() && !isSpecial()) {
1073
return super.compareTo(file2);
1075
return -1; // Non-file shellfolders sort before files
1078
return Win32ShellFolderManager2.compareShellFolders(this, (Win32ShellFolder2) file2);
1081
// native constants from commctrl.h
1082
private static final int LVCFMT_LEFT = 0;
1083
private static final int LVCFMT_RIGHT = 1;
1084
private static final int LVCFMT_CENTER = 2;
1086
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
1087
public ShellFolderColumnInfo[] getFolderColumns() {
1088
Object o = doGetColumnInfo(getIShellFolder());
1089
ShellFolderColumnInfo[] columns = (ShellFolderColumnInfo[]) o;
1091
if (columns != null) {
1092
List<ShellFolderColumnInfo> notNullColumns = new ArrayList<ShellFolderColumnInfo>();
1093
for (int i = 0; i < columns.length; i++) {
1094
ShellFolderColumnInfo column = columns[i];
1095
if (column != null) {
1096
column.setAlignment(column.getAlignment() == LVCFMT_RIGHT ? SwingConstants.RIGHT
1097
: column.getAlignment() == LVCFMT_CENTER ? SwingConstants.CENTER
1098
: SwingConstants.LEADING);
1100
column.setComparator(new ColumnComparator(i));
1102
notNullColumns.add(column);
1105
columns = new ShellFolderColumnInfo[notNullColumns.size()];
1106
notNullColumns.toArray(columns);
1111
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
1112
public Object getFolderColumnValue(int column) {
1113
return doGetColumnValue(getParentIShellFolder(), getRelativePIDL(), column);
1116
@cli.System.Security.SecurityCriticalAttribute.Annotation
1117
private static native cli.System.Object /*ShellFolderColumnInfo[]*/ doGetColumnInfo( cli.System.Object iShellFolder2 );
1119
@cli.System.Security.SecurityCriticalAttribute.Annotation
1120
private static native Object doGetColumnValue(cli.System.Object parentIShellFolder2, cli.System.IntPtr childPIDL, int columnIdx);
1122
@cli.System.Security.SecurityCriticalAttribute.Annotation
1123
static native int compareIDsByColumn(cli.System.Object pParentIShellFolder, cli.System.IntPtr pidl1, cli.System.IntPtr pidl2, int columnIdx);
1125
private class ColumnComparator implements Comparator {
1126
private final int columnIdx;
1128
public ColumnComparator(int columnIdx) {
1129
this.columnIdx = columnIdx;
1132
// compares 2 objects within this folder by the specified column
1133
@cli.System.Security.SecuritySafeCriticalAttribute.Annotation
1134
public int compare(Object o, Object o1) {
1135
if (o instanceof Win32ShellFolder2 && o1 instanceof Win32ShellFolder2) {
1136
// delegates comparison to native method
1137
return compareIDsByColumn(getIShellFolder(),
1138
((Win32ShellFolder2) o).getRelativePIDL(),
1139
((Win32ShellFolder2) o1).getRelativePIDL(),
b'\\ No newline at end of file'