mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
840 lines
31 KiB
Java
840 lines
31 KiB
Java
/*
|
|
* This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com>
|
|
* Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/)
|
|
*/
|
|
|
|
/*
|
|
* @(#)Win32ShellFolder.java 1.30 03/01/23
|
|
*
|
|
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
|
|
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*/
|
|
|
|
package sun.awt.shell;
|
|
|
|
import java.awt.Image;
|
|
import java.awt.image.BufferedImage;
|
|
import java.io.File;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.security.AccessController;
|
|
import java.util.*;
|
|
import sun.security.action.GetPropertyAction;
|
|
|
|
/**
|
|
* Win32 Shell Folders
|
|
* <P>
|
|
* <BR>
|
|
* There are two fundamental types of shell folders : file system folders
|
|
* and non-file system folders. File system folders are relatively easy
|
|
* to deal with. Non-file system folders are items such as My Computer,
|
|
* Network Neighborhood, and the desktop. Some of these non-file system
|
|
* folders have special values and properties.
|
|
* <P>
|
|
* <BR>
|
|
* Win32 keeps two basic data structures for shell folders. The first
|
|
* of these is called an ITEMIDLIST. Usually a pointer, called an
|
|
* LPITEMIDLIST, or more frequently just "PIDL". This structure holds
|
|
* a series of identifiers and can be either relative to the desktop
|
|
* (an absolute PIDL), or relative to the shell folder that contains them.
|
|
* Some Win32 functions can take absolute or relative PIDL values, and
|
|
* others can only accept relative values.
|
|
* <BR>
|
|
* The second data structure is an IShellFolder COM interface. Using
|
|
* this interface, one can enumerate the relative PIDLs in a shell
|
|
* folder, get attributes, etc.
|
|
* <BR>
|
|
* Unfortunately, the two concepts run against each other in many instances.
|
|
* Most notably, it is impossible, except in Windows 2000, to get a parent
|
|
* IShellFolder interface from an absolute PIDL (the SHBindToParent function,
|
|
* the important glue, is not available in most versions of the DLL). Even
|
|
* if this glue were present, there is still no means of getting the parent's
|
|
* PIDL from its IShellFolder interface. Therefore, navigation through the
|
|
* shell folder tree is tricky.
|
|
* <P>
|
|
* <BR>
|
|
* We have provided only a few ways to get a ShellFolder:
|
|
* <OL>
|
|
* <LI> One can call ShellFolder.getRoots() </LI>
|
|
* <LI> One can call ShellFolder.getShellFolder(File f) </LI>
|
|
* <LI> From an existing ShellFolder, one can call getParentFile() </LI>
|
|
* <LI> From an existing ShellFolder, one can call getChildren() </LI>
|
|
* </OL>
|
|
* Our navigation strategy is different for file system folders than non-file
|
|
* system folders. File system folders are initialized with their
|
|
* absolute PIDL, and non-file system folders are initialized with their
|
|
* IShellFolder interface and relative PIDL. Non-file system folders also
|
|
* carry a reference to their parent shell folder.
|
|
*
|
|
* @author Michael Martak
|
|
* @author Leif Samuelsson
|
|
* @since 1.4
|
|
*/
|
|
|
|
final class Win32ShellFolder extends ShellFolder {
|
|
|
|
private static native void initIDs();
|
|
|
|
static {
|
|
initIDs();
|
|
}
|
|
|
|
// Win32 Shell Folder Constants
|
|
public static final int DESKTOP = 0x0000;
|
|
public static final int INTERNET = 0x0001;
|
|
public static final int PROGRAMS = 0x0002;
|
|
public static final int CONTROLS = 0x0003;
|
|
public static final int PRINTERS = 0x0004;
|
|
public static final int PERSONAL = 0x0005;
|
|
public static final int FAVORITES = 0x0006;
|
|
public static final int STARTUP = 0x0007;
|
|
public static final int RECENT = 0x0008;
|
|
public static final int SENDTO = 0x0009;
|
|
public static final int BITBUCKET = 0x000a;
|
|
public static final int STARTMENU = 0x000b;
|
|
public static final int DESKTOPDIRECTORY = 0x0010;
|
|
public static final int DRIVES = 0x0011;
|
|
public static final int NETWORK = 0x0012;
|
|
public static final int NETHOOD = 0x0013;
|
|
public static final int FONTS = 0x0014;
|
|
public static final int TEMPLATES = 0x0015;
|
|
public static final int COMMON_STARTMENU = 0x0016;
|
|
public static final int COMMON_PROGRAMS = 0X0017;
|
|
public static final int COMMON_STARTUP = 0x0018;
|
|
public static final int COMMON_DESKTOPDIRECTORY = 0x0019;
|
|
public static final int APPDATA = 0x001a;
|
|
public static final int PRINTHOOD = 0x001b;
|
|
public static final int ALTSTARTUP = 0x001d;
|
|
public static final int COMMON_ALTSTARTUP = 0x001e;
|
|
public static final int COMMON_FAVORITES = 0x001f;
|
|
public static final int INTERNET_CACHE = 0x0020;
|
|
public static final int COOKIES = 0x0021;
|
|
public static final int HISTORY = 0x0022;
|
|
|
|
// Win32 shell folder attributes
|
|
public static final int ATTRIB_CANCOPY = 0x00000001;
|
|
public static final int ATTRIB_CANMOVE = 0x00000002;
|
|
public static final int ATTRIB_CANLINK = 0x00000004;
|
|
public static final int ATTRIB_CANRENAME = 0x00000010;
|
|
public static final int ATTRIB_CANDELETE = 0x00000020;
|
|
public static final int ATTRIB_HASPROPSHEET = 0x00000040;
|
|
public static final int ATTRIB_DROPTARGET = 0x00000100;
|
|
public static final int ATTRIB_LINK = 0x00010000;
|
|
public static final int ATTRIB_SHARE = 0x00020000;
|
|
public static final int ATTRIB_READONLY = 0x00040000;
|
|
public static final int ATTRIB_GHOSTED = 0x00080000;
|
|
public static final int ATTRIB_HIDDEN = 0x00080000;
|
|
public static final int ATTRIB_FILESYSANCESTOR = 0x10000000;
|
|
public static final int ATTRIB_FOLDER = 0x20000000;
|
|
public static final int ATTRIB_FILESYSTEM = 0x40000000;
|
|
public static final int ATTRIB_HASSUBFOLDER = 0x80000000;
|
|
public static final int ATTRIB_VALIDATE = 0x01000000;
|
|
public static final int ATTRIB_REMOVABLE = 0x02000000;
|
|
public static final int ATTRIB_COMPRESSED = 0x04000000;
|
|
public static final int ATTRIB_BROWSABLE = 0x08000000;
|
|
public static final int ATTRIB_NONENUMERATED = 0x00100000;
|
|
public static final int ATTRIB_NEWCONTENT = 0x00200000;
|
|
|
|
/*
|
|
* We keep track of non-file system shell folders through their
|
|
* IShellFolder interface.
|
|
*/
|
|
private long pIShellFolder = 0;
|
|
/*
|
|
* Relative PIDL is useful for a non-file system folder for caching,
|
|
* but is not entirely necessary. A relative PIDL can be derived
|
|
* from a parent IShellFolder's BindToObject method.
|
|
*/
|
|
private long relativePIDL = 0;
|
|
|
|
/*
|
|
* We keep track of file system shell folders through their
|
|
* absolute PIDL.
|
|
*/
|
|
private long pIDL = 0;
|
|
|
|
/*
|
|
* The following are for caching various shell folder properties.
|
|
*/
|
|
private long attributes = -1L;
|
|
private String folderType = null;
|
|
private String displayName = null;
|
|
private Image smallIcon = null;
|
|
private Image largeIcon = null;
|
|
|
|
|
|
/**
|
|
* Create a non-file system special shell folder, such as the
|
|
* desktop or Network Neighborhood.
|
|
*/
|
|
Win32ShellFolder(ShellFolder parent, int shellFolderType) throws IOException {
|
|
// Desktop is parent of DRIVES and NETWORK, not necessarily
|
|
// other special shell folders.
|
|
super(parent,
|
|
(getFileSystemPath(shellFolderType) == null)
|
|
? ("ShellFolder: 0x"+Integer.toHexString(shellFolderType)) : getFileSystemPath(shellFolderType));
|
|
if (shellFolderType == DESKTOP) {
|
|
initDesktop();
|
|
} else {
|
|
initSpecial(getDesktop().getIShellFolder(), shellFolderType);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a file system shell folder from a file path.
|
|
*/
|
|
public Win32ShellFolder(ShellFolder parent, String absolutePath) throws FileNotFoundException {
|
|
super(parent, absolutePath);
|
|
try {
|
|
boolean initAttributes = true;
|
|
if (absolutePath.length() == 3 && absolutePath.endsWith(":\\")) {
|
|
// It is generally better to initialize attributes here for
|
|
// speed, but we also need to avoid touching removable drives
|
|
// unnecessarily.
|
|
initAttributes = false;
|
|
}
|
|
pIDL = initFile(getDesktopIShellFolder(), absolutePath, initAttributes);
|
|
} catch (IOException e) {
|
|
throw new FileNotFoundException(absolutePath + " (" + e.getMessage() + ")");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a file system shell folder from a file.
|
|
*/
|
|
public Win32ShellFolder(ShellFolder parent, File file) throws FileNotFoundException {
|
|
this(parent, file.getAbsolutePath());
|
|
}
|
|
|
|
/**
|
|
* Create a system shell folder
|
|
*/
|
|
Win32ShellFolder(Win32ShellFolder parent, long pIShellFolder, long relativePIDL, String path) {
|
|
super(parent, (path != null) ? path : "ShellFolder: ");
|
|
this.pIShellFolder = pIShellFolder;
|
|
this.relativePIDL = relativePIDL;
|
|
}
|
|
|
|
// Initializes the desktop shell folder
|
|
private native void initDesktop();
|
|
// Initializes a special, non-file system shell folder
|
|
// from one of the above constants
|
|
private native void initSpecial(long desktopIShellFolder,
|
|
int shellFolderType);
|
|
// Initializes a file system shell folder from an absolute
|
|
// path. Returns the absoulte PIDL of the file. This value
|
|
// must be released using releasePIDL().
|
|
private native long initFile(long desktopIShellFolder, String absolutePath,
|
|
boolean initAttributes) throws IOException;
|
|
|
|
|
|
/**
|
|
* This method is implemented to make sure that no instances
|
|
* of <code>ShellFolder</code> are ever serialized. If <code>isFileSystem()</code> returns
|
|
* <code>true</code>, then the object is representable with an instance of
|
|
* <code>java.io.File</code> instead. If not, then the object depends
|
|
* on native PIDL state and should not be serialized.
|
|
*
|
|
* @returns a <code>java.io.File</code> replacement object. If the folder
|
|
* is a not a normal directory, then returns the first non-removable
|
|
* drive (normally "C:\").
|
|
*/
|
|
protected Object writeReplace() throws java.io.ObjectStreamException {
|
|
if (isFileSystem()) {
|
|
return new File(getPath());
|
|
} else {
|
|
Win32ShellFolder drives = Win32ShellFolderManager.getDrives();
|
|
if (drives != null) {
|
|
File[] driveRoots = drives.listFiles();
|
|
if (driveRoots != null) {
|
|
for (int i = 0; i < driveRoots.length; i++) {
|
|
if (driveRoots[i] instanceof Win32ShellFolder) {
|
|
Win32ShellFolder sf = (Win32ShellFolder)driveRoots[i];
|
|
if (sf.isFileSystem() && !sf.hasAttribute(ATTRIB_REMOVABLE)) {
|
|
return new File(sf.getPath());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Ouch, we have no hard drives. Return something "valid" anyway.
|
|
return new File("C:\\");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Finalizer to clean up any COM objects or PIDLs used by this object.
|
|
*/
|
|
protected void finalize() throws Throwable {
|
|
if (pIDL != 0 && pIShellFolder == 0) {
|
|
releasePIDL(pIDL);
|
|
pIDL = 0;
|
|
|
|
if (relativePIDL != 0) {
|
|
releasePIDL(relativePIDL);
|
|
relativePIDL = 0;
|
|
}
|
|
} else {
|
|
// Can't release pIShellFolder and relativePIDL because
|
|
// they are shared between instances, and reference counting
|
|
// would not be cost effective.
|
|
pIShellFolder = 0;
|
|
}
|
|
}
|
|
|
|
// Release a PIDL object
|
|
private native void releasePIDL(long pIDL);
|
|
|
|
/**
|
|
* Accessor for IShellFolder (non-file system shell folders only)
|
|
*/
|
|
public long getIShellFolder() {
|
|
return pIShellFolder;
|
|
}
|
|
|
|
/**
|
|
* Get the parent ShellFolder's IShellFolder interface (non-file system
|
|
* shell folders only)
|
|
*/
|
|
public long getParentIShellFolder() {
|
|
Win32ShellFolder parent = (Win32ShellFolder)getParentFile();
|
|
// Parent should only be null if this is the desktop IShellFolder
|
|
if (parent == null) {
|
|
if (equals(getDesktop())) {
|
|
return getIShellFolder();
|
|
}
|
|
return 0;
|
|
}
|
|
return parent.getIShellFolder();
|
|
}
|
|
|
|
// Derive a relative PIDL from a parent IShellFolder's BindToObject method
|
|
// and comparing interface pointers. Returns the relative PIDL.
|
|
private long getRelativePIDL(long parentIShellFolder,
|
|
long pIShellFolder) {
|
|
if (parentIShellFolder == 0 || pIShellFolder == 0) {
|
|
return 0;
|
|
}
|
|
long enumObjects = getEnumObjects(parentIShellFolder, true);
|
|
if (enumObjects == 0) {
|
|
return 0;
|
|
}
|
|
try {
|
|
long childPIDL = 0;
|
|
do {
|
|
childPIDL = getNextChild(enumObjects);
|
|
if (childPIDL != 0) {
|
|
long childIShellFolder =
|
|
bindToObject(parentIShellFolder, childPIDL);
|
|
if (childIShellFolder == pIShellFolder) {
|
|
return childPIDL;
|
|
}
|
|
releasePIDL(childPIDL);
|
|
}
|
|
} while (childPIDL != 0);
|
|
} finally {
|
|
releaseEnumObjects(enumObjects);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Accessor for relative PIDL (non-file system shell folders only)
|
|
*/
|
|
public long getRelativePIDL() {
|
|
if (relativePIDL == 0) {
|
|
relativePIDL = getRelativePIDL(
|
|
getParentIShellFolder(), getIShellFolder());
|
|
}
|
|
return relativePIDL;
|
|
}
|
|
|
|
/**
|
|
* Accessor for absolute PIDL (file system shell folders only)
|
|
*/
|
|
public long getPIDL() {
|
|
return pIDL;
|
|
}
|
|
|
|
/**
|
|
* Helper function to return the desktop
|
|
*/
|
|
public Win32ShellFolder getDesktop() {
|
|
return Win32ShellFolderManager.getDesktop();
|
|
}
|
|
|
|
/**
|
|
* Helper function to return the desktop IShellFolder interface
|
|
*/
|
|
public long getDesktopIShellFolder() {
|
|
return getDesktop().getIShellFolder();
|
|
}
|
|
|
|
/**
|
|
* Check to see if two ShellFolder objects are the same
|
|
*/
|
|
public boolean equals(Object o) {
|
|
if (o == null || !(o instanceof Win32ShellFolder)) {
|
|
if (getPIDL() != 0) {
|
|
return super.equals(o);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
Win32ShellFolder rhs = (Win32ShellFolder)o;
|
|
ShellFolder parent = (ShellFolder)getParentFile();
|
|
if (parent != null && !parent.equals(rhs.getParentFile())) {
|
|
return false;
|
|
}
|
|
if (isFileSystem()) {
|
|
return getAbsolutePath().equals(rhs.getAbsolutePath());
|
|
}
|
|
return (getIShellFolder() == rhs.getIShellFolder());
|
|
}
|
|
|
|
/**
|
|
* @return Whether this is a file system shell folder
|
|
*/
|
|
public boolean isFileSystem() {
|
|
return (getPIDL() != 0 || !getPath().startsWith("ShellFolder: "));
|
|
}
|
|
|
|
// Initialize and cache attributes for a file system shell folder
|
|
private native void initAttributes(long pIDL);
|
|
|
|
// Return whether a non-file system shell folder has the supplied
|
|
// attribute
|
|
private native boolean hasAttribute(long parentIShellFolder,
|
|
long relativePIDL, int attribute);
|
|
private native boolean hasAttribute(boolean dummy);
|
|
|
|
/**
|
|
* Return whether the given attribute flag is set for this object
|
|
*/
|
|
public boolean hasAttribute(int attribute) {
|
|
boolean result = false;
|
|
if (getPIDL() != 0) {
|
|
if (attributes == -1L) {
|
|
initAttributes(getPIDL());
|
|
}
|
|
result = (attributes & attribute) != 0;
|
|
}
|
|
if (pIShellFolder != 0) {
|
|
result = result || hasAttribute(getParentIShellFolder(), getRelativePIDL(),
|
|
attribute);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// Return whether this non-file system shell folder behaves
|
|
// like a standard file system object. If this returns true,
|
|
// this shell folder represents a valid file system object.
|
|
private boolean behavesLikeFileSystem(long parentIShellFolder, long relativePIDL) {
|
|
return hasAttribute(parentIShellFolder, relativePIDL, ATTRIB_FILESYSTEM);
|
|
}
|
|
|
|
// Return the path to the underlying file system object
|
|
static native String getFileSystemPath(long parentIShellFolder, long relativePIDL);
|
|
static native String getFileSystemPath(int csidl) throws IOException;
|
|
|
|
// Return whether the path is a network root.
|
|
// Path is assumed to be non-null
|
|
private static boolean isNetworkRoot(String path) {
|
|
return (path.equals("\\\\") || path.equals("\\") || path.equals("//") || path.equals("/"));
|
|
}
|
|
|
|
/**
|
|
* @return The parent shell folder of this shell folder, null if
|
|
* there is no parent
|
|
*/
|
|
public File getParentFile() {
|
|
if (parent == null) {
|
|
if (getPIDL() != 0) {
|
|
String parentName = getParent();
|
|
// Check if we are a root
|
|
if (parentName == null) { // We are a root
|
|
String filename = getAbsolutePath();
|
|
// Check if we are a network path
|
|
if (filename.startsWith("\\")) {
|
|
parent = Win32ShellFolderManager.getNetwork();
|
|
} else {
|
|
parent = Win32ShellFolderManager.getDrives();
|
|
}
|
|
} else if (isNetworkRoot(parentName)) {
|
|
parent = Win32ShellFolderManager.getNetwork();
|
|
} else { // We are not a root
|
|
try {
|
|
parent = new Win32ShellFolder(null, super.getParentFile());
|
|
} catch (FileNotFoundException ignore) { }
|
|
}
|
|
}
|
|
}
|
|
return parent;
|
|
}
|
|
|
|
public boolean isDirectory() {
|
|
return (hasAttribute(ATTRIB_HASSUBFOLDER) || (isFileSystem() && super.isDirectory()));
|
|
}
|
|
|
|
/*
|
|
* Functions for enumerating an IShellFolder's children
|
|
*/
|
|
// Returns an IEnumIDList interface for an IShellFolder. The value
|
|
// returned must be released using releaseEnumObjects().
|
|
private long getEnumObjects(long pIShellFolder, boolean includeHiddenFiles) {
|
|
boolean isDesktop = (pIShellFolder == getDesktopIShellFolder());
|
|
return getEnumObjects(pIShellFolder, isDesktop, includeHiddenFiles);
|
|
}
|
|
// Returns an IEnumIDList interface for an IShellFolder. The value
|
|
// returned must be released using releaseEnumObjects().
|
|
private native long getEnumObjects(long pIShellFolder, boolean isDesktop,
|
|
boolean includeHiddenFiles);
|
|
// Returns the next sequential child as a relative PIDL
|
|
// from an IEnumIDList interface. The value returned must
|
|
// be released using releasePIDL().
|
|
private native long getNextChild(long pEnumObjects);
|
|
// Releases the IEnumIDList interface
|
|
private native void releaseEnumObjects(long pEnumObjects);
|
|
|
|
// Returns the IShellFolder of a child from a parent IShellFolder
|
|
// and a relative PIDL. The value returned must be released
|
|
// using releaseIShellFolder().
|
|
private native long bindToObject(long parentIShellFolder, long pIDL);
|
|
|
|
|
|
|
|
/**
|
|
* @return An array of shell folders that are children of this shell folder
|
|
* object, null if this shell folder is empty.
|
|
*/
|
|
public File[] listFiles(boolean includeHiddenFiles) {
|
|
Win32ShellFolder desktop = Win32ShellFolderManager.getDesktop();
|
|
Win32ShellFolder personal = Win32ShellFolderManager.getPersonal();
|
|
File[] children = null;
|
|
|
|
if (getPIDL() != 0) {
|
|
File[] tmpChildren = super.listFiles(includeHiddenFiles);
|
|
if (tmpChildren != null) {
|
|
children = new File[tmpChildren.length];
|
|
int j = 0;
|
|
for (int i = 0; i < tmpChildren.length; i++) {
|
|
if (Thread.currentThread().isInterrupted()) {
|
|
break;
|
|
}
|
|
try {
|
|
File child = new Win32ShellFolder(this, tmpChildren[i]);
|
|
children[j++] = child;
|
|
} catch (FileNotFoundException ignore) { }
|
|
}
|
|
if (j < tmpChildren.length) {
|
|
tmpChildren = new File[j];
|
|
System.arraycopy(children, 0, tmpChildren, 0, j);
|
|
children = tmpChildren;
|
|
}
|
|
}
|
|
} else {
|
|
ArrayList list = new ArrayList();
|
|
long pIShellFolder = getIShellFolder();
|
|
if (pIShellFolder != 0) {
|
|
long pEnumObjects = getEnumObjects(pIShellFolder, includeHiddenFiles);
|
|
if (pEnumObjects != 0) {
|
|
long childPIDL = 0;
|
|
do {
|
|
childPIDL = getNextChild(pEnumObjects);
|
|
if (childPIDL != 0) {
|
|
Win32ShellFolder childFolder = null;
|
|
if (hasAttribute(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM)) {
|
|
String path = getFileSystemPath(pIShellFolder, childPIDL);
|
|
if (path == null || !new File(path).isAbsolute()) {
|
|
// Some folders like "Infrared Recipient" are reported
|
|
// as being in the filesystem but don't have a real path.
|
|
continue;
|
|
}
|
|
if (this == desktop
|
|
&& personal != null
|
|
&& path.equalsIgnoreCase(personal.getAbsolutePath())) {
|
|
|
|
childFolder = personal;
|
|
} else {
|
|
try {
|
|
childFolder = new Win32ShellFolder(this, path);
|
|
} catch (FileNotFoundException e) {
|
|
continue;
|
|
}
|
|
}
|
|
} else if (hasAttribute(pIShellFolder, childPIDL, ATTRIB_FILESYSANCESTOR)) {
|
|
long childIShellFolder = bindToObject(pIShellFolder, childPIDL);
|
|
childFolder = new Win32ShellFolder(this, childIShellFolder, childPIDL, null);
|
|
} else {
|
|
//System.out.println("Losing a non-file");
|
|
}
|
|
if (childFolder != null) {
|
|
list.add(childFolder);
|
|
}
|
|
} else {
|
|
//System.out.println("Losing a NULL childPIDL");
|
|
}
|
|
} while (childPIDL != 0);
|
|
}
|
|
releaseEnumObjects(pEnumObjects);
|
|
children = (ShellFolder[])list.toArray(new ShellFolder[list.size()]);;
|
|
}
|
|
}
|
|
return children;
|
|
}
|
|
|
|
|
|
/**
|
|
* Look for (possibly special) child folder by it's path
|
|
*
|
|
* @return The child shellfolder, or null if not found.
|
|
*/
|
|
Win32ShellFolder getChildByPath(String filePath) {
|
|
long pIShellFolder = getIShellFolder();
|
|
long pEnumObjects = getEnumObjects(pIShellFolder, true);
|
|
Win32ShellFolder child = null;
|
|
long childPIDL = 0;
|
|
|
|
while ((childPIDL = getNextChild(pEnumObjects)) != 0) {
|
|
if (hasAttribute(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM)) {
|
|
String path = getFileSystemPath(pIShellFolder, childPIDL);
|
|
if (path != null && path.equalsIgnoreCase(filePath)) {
|
|
long childIShellFolder = bindToObject(pIShellFolder, childPIDL);
|
|
child = new Win32ShellFolder(this, childIShellFolder, childPIDL, path);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
releaseEnumObjects(pEnumObjects);
|
|
return child;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return Whether this shell folder is a link
|
|
*/
|
|
public boolean isLink() {
|
|
return hasAttribute(ATTRIB_LINK);
|
|
}
|
|
|
|
/**
|
|
* @return Whether this shell folder is marked as hidden
|
|
*/
|
|
public boolean isHidden() {
|
|
return hasAttribute(ATTRIB_HIDDEN);
|
|
}
|
|
|
|
|
|
// Return the link location of a shell folder
|
|
private native String getLinkLocation(long parentIShellFolder,
|
|
long relativePIDL);
|
|
|
|
/**
|
|
* @return The shell folder linked to by this shell folder, or null
|
|
* if this shell folder is not a link
|
|
*/
|
|
public ShellFolder getLinkLocation() throws FileNotFoundException {
|
|
if (!isLink()) {
|
|
return null;
|
|
}
|
|
String linkLocation = null;
|
|
if (getPIDL() != 0) {
|
|
linkLocation = getLinkLocation(getDesktopIShellFolder(), getPIDL());
|
|
} else {
|
|
linkLocation = getLinkLocation(getParentIShellFolder(), getRelativePIDL());
|
|
}
|
|
if (linkLocation == null) {
|
|
return null;
|
|
}
|
|
return new Win32ShellFolder(null, linkLocation);
|
|
}
|
|
|
|
// Return the display name of a non-file system shell folder
|
|
private native String getDisplayName(long parentIShellFolder,
|
|
long relativePIDL);
|
|
private native String getDisplayName(boolean dummy);
|
|
|
|
/**
|
|
* @return The name used to display this shell folder
|
|
*/
|
|
public String getDisplayName() {
|
|
if (displayName == null && getPIDL() == 0) {
|
|
displayName = getDisplayName(getParentIShellFolder(), getRelativePIDL());
|
|
}
|
|
return displayName;
|
|
}
|
|
|
|
// Return the folder type of a shell folder
|
|
private native String getFolderType(long pIDL);
|
|
|
|
/**
|
|
* @return The type of shell folder as a string
|
|
*/
|
|
public String getFolderType() {
|
|
if (folderType == null && getPIDL() == 0) {
|
|
folderType = getFolderType(getRelativePIDL());
|
|
}
|
|
return folderType;
|
|
}
|
|
|
|
// Return the executable type of a file system shell folder
|
|
private native String getExecutableType(byte[] path_bytes);
|
|
|
|
/**
|
|
* @return The executable type as a string
|
|
*/
|
|
public String getExecutableType() {
|
|
if (!isFileSystem()) {
|
|
return null;
|
|
}
|
|
return getExecutableType(getAbsolutePath().getBytes());
|
|
}
|
|
|
|
// Return the icon of a file system shell folder
|
|
private native long getIcon(long pIDL, boolean getLargeIcon);
|
|
// Return the icon of a non-file system shell folder
|
|
private native long getIcon(long parentIShellFolder,
|
|
long relativePIDL, boolean getLargeIcon);
|
|
// Return the bits from an HICON. This has a side effect of setting
|
|
// the imageHash variable for efficient caching / comparing.
|
|
private native int[] getIconBits(long hIcon, int iconSize);
|
|
// Dispose the HICON
|
|
private native void disposeIcon(long hIcon);
|
|
|
|
public static native int[] getFileChooserBitmapBits();
|
|
|
|
|
|
private int[] getIconBits(boolean getLargeIcon) {
|
|
// Get the HICON
|
|
long hIcon = 0;
|
|
if (getPIDL() != 0) {
|
|
hIcon = getIcon(getPIDL(), getLargeIcon);
|
|
} else {
|
|
hIcon = getIcon(getParentIShellFolder(),
|
|
getRelativePIDL(), getLargeIcon);
|
|
}
|
|
// From an HICON, call GetIconInfo to get the underlying HBITMAPs,
|
|
// then call GetDIBits.
|
|
if (hIcon == 0) {
|
|
return null;
|
|
}
|
|
// Get the bits. This has the side effect of setting the imageHash
|
|
// value for this object.
|
|
int[] bits = getIconBits(hIcon, getLargeIcon ? 32 : 16);
|
|
// Dispose the HICON
|
|
disposeIcon(hIcon);
|
|
return bits;
|
|
}
|
|
|
|
static int[] fileChooserBitmapBits = null;
|
|
static Image[] fileChooserIcons = new Image[47];
|
|
|
|
static Image getFileChooserIcon(int i) {
|
|
if (fileChooserIcons[i] != null) {
|
|
return fileChooserIcons[i];
|
|
} else {
|
|
if (fileChooserBitmapBits == null) {
|
|
fileChooserBitmapBits = getFileChooserBitmapBits();
|
|
}
|
|
if (fileChooserBitmapBits != null) {
|
|
int nImages = fileChooserBitmapBits.length / (16*16);
|
|
int[] bitmapBits = new int[16 * 16];
|
|
for (int y = 0; y < 16; y++) {
|
|
for (int x = 0; x < 16; x++) {
|
|
bitmapBits[y * 16 + x] = fileChooserBitmapBits[y * (nImages * 16) + (i * 16) + x];
|
|
}
|
|
}
|
|
BufferedImage img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
|
|
img.setRGB(0, 0, 16, 16, bitmapBits, 0, 16);
|
|
fileChooserIcons[i] = img;
|
|
}
|
|
}
|
|
return fileChooserIcons[i];
|
|
}
|
|
|
|
|
|
/**
|
|
* @return The icon image used to display this shell folder
|
|
*/
|
|
public Image getIcon(boolean getLargeIcon) {
|
|
Image icon = getLargeIcon ? largeIcon : smallIcon;
|
|
|
|
if (icon == null) {
|
|
int size = getLargeIcon ? 32 : 16;
|
|
int[] iconBits = getIconBits(getLargeIcon);
|
|
if (iconBits == null) {
|
|
return super.getIcon(getLargeIcon);
|
|
}
|
|
BufferedImage img = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
|
|
img.setRGB(0, 0, size, size, iconBits, 0, size);
|
|
if (getLargeIcon) {
|
|
icon = largeIcon = img;
|
|
} else {
|
|
icon = smallIcon = img;
|
|
}
|
|
}
|
|
return icon;
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the canonical form of this abstract pathname. Equivalent to
|
|
* <code>new Win32ShellFolder(getParentFile(), this.{@link java.io.File#getCanonicalPath}())</code>.
|
|
*
|
|
* @see java.io.File#getCanonicalFile
|
|
*/
|
|
public File getCanonicalFile() throws IOException {
|
|
if (getPIDL() != 0) {
|
|
return new Win32ShellFolder(parent, super.getCanonicalPath());
|
|
} else {
|
|
return this;
|
|
}
|
|
}
|
|
|
|
private List topFolderList = null;
|
|
|
|
/**
|
|
* Compares this object with the specified object for order.
|
|
*
|
|
* @see sun.awt.shell.ShellFolder#compareTo(File)
|
|
*/
|
|
public int compareTo(File file2) {
|
|
if (file2 == null || !(file2 instanceof Win32ShellFolder)
|
|
|| ((file2 instanceof Win32ShellFolder) && ((Win32ShellFolder)file2).getPIDL() != 0)) {
|
|
|
|
if (getPIDL() != 0) {
|
|
return super.compareTo(file2);
|
|
} else {
|
|
return -1;
|
|
}
|
|
} else {
|
|
if (getPIDL() != 0) {
|
|
return 1;
|
|
} else {
|
|
if (topFolderList == null) {
|
|
topFolderList = new ArrayList();
|
|
topFolderList.add(Win32ShellFolderManager.getPersonal());
|
|
topFolderList.add(Win32ShellFolderManager.getDesktop());
|
|
topFolderList.add(Win32ShellFolderManager.getDrives());
|
|
topFolderList.add(Win32ShellFolderManager.getNetwork());
|
|
}
|
|
int i1 = topFolderList.indexOf(this);
|
|
int i2 = topFolderList.indexOf(file2);
|
|
|
|
if (i1 >= 0 && i2 >= 0) {
|
|
return (i1 - i2);
|
|
} else if (i1 >= 0) {
|
|
return -1;
|
|
} else if (i2 >= 0) {
|
|
return 1;
|
|
} else {
|
|
return getName().compareTo(file2.getName());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|