6491795: COM should be initialized for Shell API calls in ShellFolder2.cpp
Reviewed-by: peterz, loneid
This commit is contained in:
parent
95a3c4a81f
commit
93c4a7033c
@ -27,6 +27,7 @@ package javax.swing.plaf.basic;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import javax.swing.*;
|
||||
import javax.swing.filechooser.*;
|
||||
import javax.swing.event.*;
|
||||
@ -223,113 +224,115 @@ public class BasicDirectoryModel extends AbstractListModel implements PropertyCh
|
||||
this.fid = fid;
|
||||
}
|
||||
|
||||
private void invokeLater(DoChangeContents runnable) {
|
||||
runnables.addElement(runnable);
|
||||
SwingUtilities.invokeLater(runnable);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
run0();
|
||||
setBusy(false, fid);
|
||||
}
|
||||
|
||||
public void run0() {
|
||||
FileSystemView fileSystem = filechooser.getFileSystemView();
|
||||
DoChangeContents doChangeContents = ShellFolder.getInvoker().invoke(new Callable<DoChangeContents>() {
|
||||
public DoChangeContents call() throws Exception {
|
||||
FileSystemView fileSystem = filechooser.getFileSystemView();
|
||||
|
||||
File[] list = fileSystem.getFiles(currentDirectory, filechooser.isFileHidingEnabled());
|
||||
File[] list = fileSystem.getFiles(currentDirectory, filechooser.isFileHidingEnabled());
|
||||
|
||||
Vector<File> acceptsList = new Vector<File>();
|
||||
Vector<File> acceptsList = new Vector<File>();
|
||||
|
||||
if (isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
if (isInterrupted()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// run through the file list, add directories and selectable files to fileCache
|
||||
for (File file : list) {
|
||||
if (filechooser.accept(file)) {
|
||||
acceptsList.addElement(file);
|
||||
}
|
||||
}
|
||||
// run through the file list, add directories and selectable files to fileCache
|
||||
for (File file : list) {
|
||||
if (filechooser.accept(file)) {
|
||||
acceptsList.addElement(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
if (isInterrupted()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// First sort alphabetically by filename
|
||||
sort(acceptsList);
|
||||
// First sort alphabetically by filename
|
||||
sort(acceptsList);
|
||||
|
||||
Vector<File> newDirectories = new Vector<File>(50);
|
||||
Vector<File> newFiles = new Vector<File>();
|
||||
// run through list grabbing directories in chunks of ten
|
||||
for(int i = 0; i < acceptsList.size(); i++) {
|
||||
File f = acceptsList.elementAt(i);
|
||||
boolean isTraversable = filechooser.isTraversable(f);
|
||||
if (isTraversable) {
|
||||
newDirectories.addElement(f);
|
||||
} else if (!isTraversable && filechooser.isFileSelectionEnabled()) {
|
||||
newFiles.addElement(f);
|
||||
}
|
||||
if(isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Vector<File> newDirectories = new Vector<File>(50);
|
||||
Vector<File> newFiles = new Vector<File>();
|
||||
// run through list grabbing directories in chunks of ten
|
||||
for (int i = 0; i < acceptsList.size(); i++) {
|
||||
File f = acceptsList.elementAt(i);
|
||||
boolean isTraversable = filechooser.isTraversable(f);
|
||||
if (isTraversable) {
|
||||
newDirectories.addElement(f);
|
||||
} else if (!isTraversable && filechooser.isFileSelectionEnabled()) {
|
||||
newFiles.addElement(f);
|
||||
}
|
||||
if (isInterrupted()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Vector<File> newFileCache = new Vector<File>(newDirectories);
|
||||
newFileCache.addAll(newFiles);
|
||||
Vector<File> newFileCache = new Vector<File>(newDirectories);
|
||||
newFileCache.addAll(newFiles);
|
||||
|
||||
int newSize = newFileCache.size();
|
||||
int oldSize = fileCache.size();
|
||||
int newSize = newFileCache.size();
|
||||
int oldSize = fileCache.size();
|
||||
|
||||
if (newSize > oldSize) {
|
||||
//see if interval is added
|
||||
int start = oldSize;
|
||||
int end = newSize;
|
||||
for (int i = 0; i < oldSize; i++) {
|
||||
if (!newFileCache.get(i).equals(fileCache.get(i))) {
|
||||
start = i;
|
||||
for (int j = i; j < newSize; j++) {
|
||||
if (newFileCache.get(j).equals(fileCache.get(i))) {
|
||||
end = j;
|
||||
if (newSize > oldSize) {
|
||||
//see if interval is added
|
||||
int start = oldSize;
|
||||
int end = newSize;
|
||||
for (int i = 0; i < oldSize; i++) {
|
||||
if (!newFileCache.get(i).equals(fileCache.get(i))) {
|
||||
start = i;
|
||||
for (int j = i; j < newSize; j++) {
|
||||
if (newFileCache.get(j).equals(fileCache.get(i))) {
|
||||
end = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (start >= 0 && end > start
|
||||
&& newFileCache.subList(end, newSize).equals(fileCache.subList(start, oldSize))) {
|
||||
if (isInterrupted()) {
|
||||
return null;
|
||||
}
|
||||
return new DoChangeContents(newFileCache.subList(start, end), start, null, 0, fid);
|
||||
}
|
||||
} else if (newSize < oldSize) {
|
||||
//see if interval is removed
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
for (int i = 0; i < newSize; i++) {
|
||||
if (!newFileCache.get(i).equals(fileCache.get(i))) {
|
||||
start = i;
|
||||
end = i + oldSize - newSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (start >= 0 && end > start
|
||||
&& fileCache.subList(end, oldSize).equals(newFileCache.subList(start, newSize))) {
|
||||
if (isInterrupted()) {
|
||||
return null;
|
||||
}
|
||||
return new DoChangeContents(null, 0, new Vector(fileCache.subList(start, end)), start, fid);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (start >= 0 && end > start
|
||||
&& newFileCache.subList(end, newSize).equals(fileCache.subList(start, oldSize))) {
|
||||
if(isInterrupted()) {
|
||||
return;
|
||||
if (!fileCache.equals(newFileCache)) {
|
||||
if (isInterrupted()) {
|
||||
cancelRunnables(runnables);
|
||||
}
|
||||
return new DoChangeContents(newFileCache, 0, fileCache, 0, fid);
|
||||
}
|
||||
invokeLater(new DoChangeContents(newFileCache.subList(start, end), start, null, 0, fid));
|
||||
newFileCache = null;
|
||||
return null;
|
||||
}
|
||||
} else if (newSize < oldSize) {
|
||||
//see if interval is removed
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
for (int i = 0; i < newSize; i++) {
|
||||
if (!newFileCache.get(i).equals(fileCache.get(i))) {
|
||||
start = i;
|
||||
end = i + oldSize - newSize;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (start >= 0 && end > start
|
||||
&& fileCache.subList(end, oldSize).equals(newFileCache.subList(start, newSize))) {
|
||||
if(isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
invokeLater(new DoChangeContents(null, 0, new Vector<File>(fileCache.subList(start, end)),
|
||||
start, fid));
|
||||
newFileCache = null;
|
||||
}
|
||||
}
|
||||
if (newFileCache != null && !fileCache.equals(newFileCache)) {
|
||||
if (isInterrupted()) {
|
||||
cancelRunnables(runnables);
|
||||
}
|
||||
invokeLater(new DoChangeContents(newFileCache, 0, fileCache, 0, fid));
|
||||
});
|
||||
|
||||
if (doChangeContents != null) {
|
||||
runnables.addElement(doChangeContents);
|
||||
SwingUtilities.invokeLater(doChangeContents);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ import java.awt.Toolkit;
|
||||
import java.io.*;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* @author Michael Martak
|
||||
@ -461,6 +462,35 @@ public abstract class ShellFolder extends File {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Invoker invoker;
|
||||
|
||||
/**
|
||||
* Provides the single access point to the {@link Invoker}. It is guaranteed that the value
|
||||
* returned by this method will be always the same.
|
||||
*
|
||||
* @return the singleton instance of {@link Invoker}
|
||||
*/
|
||||
public static Invoker getInvoker() {
|
||||
if (invoker == null) {
|
||||
invoker = shellFolderManager.createInvoker();
|
||||
}
|
||||
return invoker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface allowing to invoke tasks in different environments on different platforms.
|
||||
*/
|
||||
public static interface Invoker {
|
||||
/**
|
||||
* Invokes a callable task. If the {@code task} throws a checked exception,
|
||||
* it will be wrapped into a {@link RuntimeException}
|
||||
*
|
||||
* @param task a task to invoke
|
||||
* @return the result of {@code task}'s invokation
|
||||
*/
|
||||
<T> T invoke(Callable<T> task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a default comparator for the default column set
|
||||
*/
|
||||
|
@ -27,6 +27,7 @@ package sun.awt.shell;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* @author Michael Martak
|
||||
@ -96,9 +97,23 @@ class ShellFolderManager {
|
||||
}
|
||||
|
||||
public boolean isFileSystemRoot(File dir) {
|
||||
if (dir instanceof ShellFolder && !((ShellFolder)dir).isFileSystem()) {
|
||||
if (dir instanceof ShellFolder && !((ShellFolder) dir).isFileSystem()) {
|
||||
return false;
|
||||
}
|
||||
return (dir.getParentFile() == null);
|
||||
}
|
||||
|
||||
protected ShellFolder.Invoker createInvoker() {
|
||||
return new DirectInvoker();
|
||||
}
|
||||
|
||||
private static class DirectInvoker implements ShellFolder.Invoker {
|
||||
public <T> T invoke(Callable<T> task) {
|
||||
try {
|
||||
return task.call();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import java.text.DateFormat;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
@ -900,6 +901,16 @@ public class FilePane extends JPanel implements PropertyChangeListener {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort() {
|
||||
ShellFolder.getInvoker().invoke(new Callable<Void>() {
|
||||
public Void call() throws Exception {
|
||||
DetailsTableRowSorter.super.sort();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void modelStructureChanged() {
|
||||
super.modelStructureChanged();
|
||||
updateComparators(detailsTableModel.getColumns());
|
||||
|
@ -32,6 +32,7 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
// NOTE: This class supersedes Win32ShellFolder, which was removed from
|
||||
@ -184,15 +185,20 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
boolean disposed;
|
||||
public void dispose() {
|
||||
if (disposed) return;
|
||||
if (relativePIDL != 0) {
|
||||
releasePIDL(relativePIDL);
|
||||
}
|
||||
if (absolutePIDL != 0) {
|
||||
releasePIDL(absolutePIDL);
|
||||
}
|
||||
if (pIShellFolder != 0) {
|
||||
releaseIShellFolder(pIShellFolder);
|
||||
}
|
||||
ShellFolder.getInvoker().invoke(new Callable<Void>() {
|
||||
public Void call() throws Exception {
|
||||
if (relativePIDL != 0) {
|
||||
releasePIDL(relativePIDL);
|
||||
}
|
||||
if (absolutePIDL != 0) {
|
||||
releasePIDL(absolutePIDL);
|
||||
}
|
||||
if (pIShellFolder != 0) {
|
||||
releaseIShellFolder(pIShellFolder);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
@ -218,50 +224,59 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
*/
|
||||
private boolean isPersonal;
|
||||
|
||||
private static String composePathForCsidl(int csidl) throws IOException {
|
||||
String path = getFileSystemPath(csidl);
|
||||
return path == null
|
||||
? ("ShellFolder: 0x" + Integer.toHexString(csidl))
|
||||
: path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a system special shell folder, such as the
|
||||
* desktop or Network Neighborhood.
|
||||
*/
|
||||
Win32ShellFolder2(int csidl) throws IOException {
|
||||
Win32ShellFolder2(final int csidl) throws IOException {
|
||||
// Desktop is parent of DRIVES and NETWORK, not necessarily
|
||||
// other special shell folders.
|
||||
super(null,
|
||||
(getFileSystemPath(csidl) == null)
|
||||
? ("ShellFolder: 0x"+Integer.toHexString(csidl)) : getFileSystemPath(csidl));
|
||||
if (csidl == DESKTOP) {
|
||||
initDesktop();
|
||||
} else {
|
||||
initSpecial(getDesktop().getIShellFolder(), csidl);
|
||||
// At this point, the native method initSpecial() has set our relativePIDL
|
||||
// relative to the Desktop, which may not be our immediate parent. We need
|
||||
// to traverse this ID list and break it into a chain of shell folders from
|
||||
// the top, with each one having an immediate parent and a relativePIDL
|
||||
// relative to that parent.
|
||||
long pIDL = disposer.relativePIDL;
|
||||
parent = getDesktop();
|
||||
while (pIDL != 0) {
|
||||
// Get a child pidl relative to 'parent'
|
||||
long childPIDL = copyFirstPIDLEntry(pIDL);
|
||||
if (childPIDL != 0) {
|
||||
// Get a handle to the the rest of the ID list
|
||||
// i,e, parent's grandchilren and down
|
||||
pIDL = getNextPIDLEntry(pIDL);
|
||||
if (pIDL != 0) {
|
||||
// Now we know that parent isn't immediate to 'this' because it
|
||||
// has a continued ID list. Create a shell folder for this child
|
||||
// pidl and make it the new 'parent'.
|
||||
parent = new Win32ShellFolder2((Win32ShellFolder2)parent, childPIDL);
|
||||
} else {
|
||||
// No grandchildren means we have arrived at the parent of 'this',
|
||||
// and childPIDL is directly relative to parent.
|
||||
disposer.relativePIDL = childPIDL;
|
||||
}
|
||||
super(null, composePathForCsidl(csidl));
|
||||
ShellFolder.getInvoker().invoke(new Callable<Void>() {
|
||||
public Void call() throws Exception {
|
||||
if (csidl == DESKTOP) {
|
||||
initDesktop();
|
||||
} else {
|
||||
break;
|
||||
initSpecial(getDesktop().getIShellFolder(), csidl);
|
||||
// At this point, the native method initSpecial() has set our relativePIDL
|
||||
// relative to the Desktop, which may not be our immediate parent. We need
|
||||
// to traverse this ID list and break it into a chain of shell folders from
|
||||
// the top, with each one having an immediate parent and a relativePIDL
|
||||
// relative to that parent.
|
||||
long pIDL = disposer.relativePIDL;
|
||||
parent = getDesktop();
|
||||
while (pIDL != 0) {
|
||||
// Get a child pidl relative to 'parent'
|
||||
long childPIDL = copyFirstPIDLEntry(pIDL);
|
||||
if (childPIDL != 0) {
|
||||
// Get a handle to the the rest of the ID list
|
||||
// i,e, parent's grandchilren and down
|
||||
pIDL = getNextPIDLEntry(pIDL);
|
||||
if (pIDL != 0) {
|
||||
// Now we know that parent isn't immediate to 'this' because it
|
||||
// has a continued ID list. Create a shell folder for this child
|
||||
// pidl and make it the new 'parent'.
|
||||
parent = new Win32ShellFolder2((Win32ShellFolder2) parent, childPIDL);
|
||||
} else {
|
||||
// No grandchildren means we have arrived at the parent of 'this',
|
||||
// and childPIDL is directly relative to parent.
|
||||
disposer.relativePIDL = childPIDL;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
sun.java2d.Disposer.addRecord(this, disposer);
|
||||
}
|
||||
@ -281,17 +296,26 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
/**
|
||||
* Creates a shell folder with a parent and relative PIDL
|
||||
*/
|
||||
Win32ShellFolder2(Win32ShellFolder2 parent, long relativePIDL) {
|
||||
super(parent, getFileSystemPath(parent.getIShellFolder(), relativePIDL));
|
||||
Win32ShellFolder2(final Win32ShellFolder2 parent, final long relativePIDL) {
|
||||
super(parent,
|
||||
ShellFolder.getInvoker().invoke(new Callable<String>() {
|
||||
public String call() throws Exception {
|
||||
return getFileSystemPath(parent.getIShellFolder(), relativePIDL);
|
||||
}
|
||||
})
|
||||
);
|
||||
this.disposer.relativePIDL = relativePIDL;
|
||||
getAbsolutePath();
|
||||
sun.java2d.Disposer.addRecord(this, disposer);
|
||||
}
|
||||
|
||||
// Initializes the desktop shell folder
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private native void initDesktop();
|
||||
|
||||
// Initializes a special, non-file system shell folder
|
||||
// from one of the above constants
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private native void initSpecial(long desktopIShellFolder, int csidl);
|
||||
|
||||
/** Marks this folder as being the My Documents (Personal) folder */
|
||||
@ -311,26 +335,30 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
* drive (normally "C:\").
|
||||
*/
|
||||
protected Object writeReplace() throws java.io.ObjectStreamException {
|
||||
if (isFileSystem()) {
|
||||
return new File(getPath());
|
||||
} else {
|
||||
Win32ShellFolder2 drives = Win32ShellFolderManager2.getDrives();
|
||||
if (drives != null) {
|
||||
File[] driveRoots = drives.listFiles();
|
||||
if (driveRoots != null) {
|
||||
for (int i = 0; i < driveRoots.length; i++) {
|
||||
if (driveRoots[i] instanceof Win32ShellFolder2) {
|
||||
Win32ShellFolder2 sf = (Win32ShellFolder2)driveRoots[i];
|
||||
if (sf.isFileSystem() && !sf.hasAttribute(ATTRIB_REMOVABLE)) {
|
||||
return new File(sf.getPath());
|
||||
return ShellFolder.getInvoker().invoke(new Callable<File>() {
|
||||
public File call() throws Exception {
|
||||
if (isFileSystem()) {
|
||||
return new File(getPath());
|
||||
} else {
|
||||
Win32ShellFolder2 drives = Win32ShellFolderManager2.getDrives();
|
||||
if (drives != null) {
|
||||
File[] driveRoots = drives.listFiles();
|
||||
if (driveRoots != null) {
|
||||
for (int i = 0; i < driveRoots.length; i++) {
|
||||
if (driveRoots[i] instanceof Win32ShellFolder2) {
|
||||
Win32ShellFolder2 sf = (Win32ShellFolder2) 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:\\");
|
||||
}
|
||||
}
|
||||
// Ouch, we have no hard drives. Return something "valid" anyway.
|
||||
return new File("C:\\");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -364,6 +392,7 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
static native void releasePIDL(long pIDL);
|
||||
|
||||
// Release an IShellFolder object
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native void releaseIShellFolder(long pIShellFolder);
|
||||
|
||||
/**
|
||||
@ -371,18 +400,28 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
*/
|
||||
public long getIShellFolder() {
|
||||
if (disposer.pIShellFolder == 0) {
|
||||
assert(isDirectory());
|
||||
assert(parent != null);
|
||||
long parentIShellFolder = getParentIShellFolder();
|
||||
if (parentIShellFolder == 0) {
|
||||
throw new InternalError("Parent IShellFolder was null for " + getAbsolutePath());
|
||||
}
|
||||
// We are a directory with a parent and a relative PIDL.
|
||||
// We want to bind to the parent so we get an IShellFolder instance associated with us.
|
||||
disposer.pIShellFolder = bindToObject(parentIShellFolder, disposer.relativePIDL);
|
||||
if (disposer.pIShellFolder == 0) {
|
||||
throw new InternalError("Unable to bind " + getAbsolutePath() + " to parent");
|
||||
}
|
||||
disposer.pIShellFolder =
|
||||
ShellFolder.getInvoker().invoke(new Callable<Long>() {
|
||||
public Long call() throws Exception {
|
||||
assert(isDirectory());
|
||||
assert(parent != null);
|
||||
long parentIShellFolder = getParentIShellFolder();
|
||||
if (parentIShellFolder == 0) {
|
||||
throw new InternalError("Parent IShellFolder was null for "
|
||||
+ getAbsolutePath());
|
||||
}
|
||||
// We are a directory with a parent and a relative PIDL.
|
||||
// We want to bind to the parent so we get an
|
||||
// IShellFolder instance associated with us.
|
||||
long pIShellFolder = bindToObject(parentIShellFolder,
|
||||
disposer.relativePIDL);
|
||||
if (pIShellFolder == 0) {
|
||||
throw new InternalError("Unable to bind "
|
||||
+ getAbsolutePath() + " to parent");
|
||||
}
|
||||
return pIShellFolder;
|
||||
}
|
||||
});
|
||||
}
|
||||
return disposer.pIShellFolder;
|
||||
}
|
||||
@ -472,24 +511,42 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean pidlsEqual(long pIShellFolder, long pidl1, long pidl2) {
|
||||
return (compareIDs(pIShellFolder, pidl1, pidl2) == 0);
|
||||
private static boolean pidlsEqual(final long pIShellFolder, final long pidl1, final long pidl2) {
|
||||
return ShellFolder.getInvoker().invoke(new Callable<Boolean>() {
|
||||
public Boolean call() throws Exception {
|
||||
return (compareIDs(pIShellFolder, pidl1, pidl2) == 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native int compareIDs(long pParentIShellFolder, long pidl1, long pidl2);
|
||||
|
||||
private Boolean cachedIsFileSystem;
|
||||
|
||||
/**
|
||||
* @return Whether this is a file system shell folder
|
||||
*/
|
||||
public boolean isFileSystem() {
|
||||
return hasAttribute(ATTRIB_FILESYSTEM);
|
||||
public synchronized boolean isFileSystem() {
|
||||
if (cachedIsFileSystem == null) {
|
||||
cachedIsFileSystem = hasAttribute(ATTRIB_FILESYSTEM);
|
||||
}
|
||||
|
||||
return cachedIsFileSystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given attribute flag is set for this object
|
||||
*/
|
||||
public boolean hasAttribute(int attribute) {
|
||||
// Caching at this point doesn't seem to be cost efficient
|
||||
return (getAttributes0(getParentIShellFolder(), getRelativePIDL(), attribute) & attribute) != 0;
|
||||
public boolean hasAttribute(final int attribute) {
|
||||
return ShellFolder.getInvoker().invoke(new Callable<Boolean>() {
|
||||
public Boolean call() throws Exception {
|
||||
// Caching at this point doesn't seem to be cost efficient
|
||||
return (getAttributes0(getParentIShellFolder(),
|
||||
getRelativePIDL(), attribute)
|
||||
& attribute) != 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -498,26 +555,42 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
* Could plausibly be used for attribute caching but have to be
|
||||
* very careful not to touch network drives and file system roots
|
||||
* with a full attrsMask
|
||||
* NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
*/
|
||||
|
||||
private static native int getAttributes0(long pParentIShellFolder, long pIDL, int attrsMask);
|
||||
|
||||
// Return the path to the underlying file system object
|
||||
private static String getFileSystemPath(long parentIShellFolder, long relativePIDL) {
|
||||
int linkedFolder = ATTRIB_LINK | ATTRIB_FOLDER;
|
||||
if (parentIShellFolder == Win32ShellFolderManager2.getNetwork().getIShellFolder() &&
|
||||
getAttributes0(parentIShellFolder, relativePIDL, linkedFolder) == linkedFolder) {
|
||||
private static String getFileSystemPath(final long parentIShellFolder, final long relativePIDL) {
|
||||
return ShellFolder.getInvoker().invoke(new Callable<String>() {
|
||||
public String call() throws Exception {
|
||||
int linkedFolder = ATTRIB_LINK | ATTRIB_FOLDER;
|
||||
if (parentIShellFolder == Win32ShellFolderManager2.getNetwork().getIShellFolder() &&
|
||||
getAttributes0(parentIShellFolder, relativePIDL, linkedFolder) == linkedFolder) {
|
||||
|
||||
String s =
|
||||
getFileSystemPath(Win32ShellFolderManager2.getDesktop().getIShellFolder(),
|
||||
getLinkLocation(parentIShellFolder, relativePIDL, false));
|
||||
if (s != null && s.startsWith("\\\\")) {
|
||||
return s;
|
||||
String s =
|
||||
getFileSystemPath(Win32ShellFolderManager2.getDesktop().getIShellFolder(),
|
||||
getLinkLocation(parentIShellFolder, relativePIDL, false));
|
||||
if (s != null && s.startsWith("\\\\")) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_FORPARSING);
|
||||
}
|
||||
}
|
||||
return getDisplayNameOf(parentIShellFolder, relativePIDL, SHGDN_NORMAL | SHGDN_FORPARSING);
|
||||
});
|
||||
}
|
||||
|
||||
// Needs to be accessible to Win32ShellFolderManager2
|
||||
static native String getFileSystemPath(int csidl) throws IOException;
|
||||
static String getFileSystemPath(final int csidl) throws IOException {
|
||||
return ShellFolder.getInvoker().invoke(new Callable<String>() {
|
||||
public String call() throws Exception {
|
||||
return getFileSystemPath0(csidl);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native String getFileSystemPath0(int csidl) throws IOException;
|
||||
|
||||
// Return whether the path is a network root.
|
||||
// Path is assumed to be non-null
|
||||
@ -557,24 +630,33 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
*/
|
||||
// Returns an IEnumIDList interface for an IShellFolder. The value
|
||||
// returned must be released using releaseEnumObjects().
|
||||
private long getEnumObjects(long pIShellFolder, boolean includeHiddenFiles) {
|
||||
boolean isDesktop = (disposer.pIShellFolder == getDesktopIShellFolder());
|
||||
return getEnumObjects(disposer.pIShellFolder, isDesktop, includeHiddenFiles);
|
||||
private long getEnumObjects(long pIShellFolder, final boolean includeHiddenFiles) {
|
||||
final boolean isDesktop = (disposer.pIShellFolder == getDesktopIShellFolder());
|
||||
return ShellFolder.getInvoker().invoke(new Callable<Long>() {
|
||||
public Long call() throws Exception {
|
||||
return getEnumObjects(disposer.pIShellFolder, isDesktop, includeHiddenFiles);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Returns an IEnumIDList interface for an IShellFolder. The value
|
||||
// returned must be released using releaseEnumObjects().
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
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().
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private native long getNextChild(long pEnumObjects);
|
||||
// Releases the IEnumIDList interface
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
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().
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native long bindToObject(long parentIShellFolder, long pIDL);
|
||||
|
||||
/**
|
||||
@ -582,60 +664,64 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
* object. The array will be empty if the folder is empty. Returns
|
||||
* <code>null</code> if this shellfolder does not denote a directory.
|
||||
*/
|
||||
public File[] listFiles(boolean includeHiddenFiles) {
|
||||
public File[] listFiles(final boolean includeHiddenFiles) {
|
||||
SecurityManager security = System.getSecurityManager();
|
||||
if (security != null) {
|
||||
security.checkRead(getPath());
|
||||
}
|
||||
if (!isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
// Links to directories are not directories and cannot be parents.
|
||||
// This does not apply to folders in My Network Places (NetHood)
|
||||
// because they are both links and real directories!
|
||||
if (isLink() && !hasAttribute(ATTRIB_FOLDER)) {
|
||||
return new File[0];
|
||||
}
|
||||
|
||||
Win32ShellFolder2 desktop = Win32ShellFolderManager2.getDesktop();
|
||||
Win32ShellFolder2 personal = Win32ShellFolderManager2.getPersonal();
|
||||
|
||||
// If we are a directory, we have a parent and (at least) a
|
||||
// relative PIDL. We must first ensure we are bound to the
|
||||
// parent so we have an IShellFolder to query.
|
||||
long pIShellFolder = getIShellFolder();
|
||||
// Now we can enumerate the objects in this folder.
|
||||
ArrayList<Win32ShellFolder2> list = new ArrayList<Win32ShellFolder2>();
|
||||
long pEnumObjects = getEnumObjects(pIShellFolder, includeHiddenFiles);
|
||||
if (pEnumObjects != 0) {
|
||||
long childPIDL;
|
||||
int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR;
|
||||
do {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
return ShellFolder.getInvoker().invoke(new Callable<File[]>() {
|
||||
public File[] call() throws Exception {
|
||||
if (!isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
// Links to directories are not directories and cannot be parents.
|
||||
// This does not apply to folders in My Network Places (NetHood)
|
||||
// because they are both links and real directories!
|
||||
if (isLink() && !hasAttribute(ATTRIB_FOLDER)) {
|
||||
return new File[0];
|
||||
}
|
||||
childPIDL = getNextChild(pEnumObjects);
|
||||
boolean releasePIDL = true;
|
||||
if (childPIDL != 0 &&
|
||||
(getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) {
|
||||
Win32ShellFolder2 childFolder = null;
|
||||
if (this.equals(desktop)
|
||||
&& personal != null
|
||||
&& pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) {
|
||||
childFolder = personal;
|
||||
} else {
|
||||
childFolder = new Win32ShellFolder2(this, childPIDL);
|
||||
releasePIDL = false;
|
||||
}
|
||||
list.add(childFolder);
|
||||
|
||||
Win32ShellFolder2 desktop = Win32ShellFolderManager2.getDesktop();
|
||||
Win32ShellFolder2 personal = Win32ShellFolderManager2.getPersonal();
|
||||
|
||||
// If we are a directory, we have a parent and (at least) a
|
||||
// relative PIDL. We must first ensure we are bound to the
|
||||
// parent so we have an IShellFolder to query.
|
||||
long pIShellFolder = getIShellFolder();
|
||||
// Now we can enumerate the objects in this folder.
|
||||
ArrayList<Win32ShellFolder2> list = new ArrayList<Win32ShellFolder2>();
|
||||
long pEnumObjects = getEnumObjects(pIShellFolder, includeHiddenFiles);
|
||||
if (pEnumObjects != 0) {
|
||||
long childPIDL;
|
||||
int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR;
|
||||
do {
|
||||
childPIDL = getNextChild(pEnumObjects);
|
||||
boolean releasePIDL = true;
|
||||
if (childPIDL != 0 &&
|
||||
(getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) {
|
||||
Win32ShellFolder2 childFolder;
|
||||
if (Win32ShellFolder2.this.equals(desktop)
|
||||
&& personal != null
|
||||
&& pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) {
|
||||
childFolder = personal;
|
||||
} else {
|
||||
childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL);
|
||||
releasePIDL = false;
|
||||
}
|
||||
list.add(childFolder);
|
||||
}
|
||||
if (releasePIDL) {
|
||||
releasePIDL(childPIDL);
|
||||
}
|
||||
} while (childPIDL != 0 && !Thread.currentThread().isInterrupted());
|
||||
releaseEnumObjects(pEnumObjects);
|
||||
}
|
||||
if (releasePIDL) {
|
||||
releasePIDL(childPIDL);
|
||||
}
|
||||
} while (childPIDL != 0);
|
||||
releaseEnumObjects(pEnumObjects);
|
||||
}
|
||||
return list.toArray(new ShellFolder[list.size()]);
|
||||
return Thread.currentThread().isInterrupted()
|
||||
? new File[0]
|
||||
: list.toArray(new ShellFolder[list.size()]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -644,33 +730,43 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
*
|
||||
* @return The child shellfolder, or null if not found.
|
||||
*/
|
||||
Win32ShellFolder2 getChildByPath(String filePath) {
|
||||
long pIShellFolder = getIShellFolder();
|
||||
long pEnumObjects = getEnumObjects(pIShellFolder, true);
|
||||
Win32ShellFolder2 child = null;
|
||||
long childPIDL;
|
||||
Win32ShellFolder2 getChildByPath(final String filePath) {
|
||||
return ShellFolder.getInvoker().invoke(new Callable<Win32ShellFolder2>() {
|
||||
public Win32ShellFolder2 call() throws Exception {
|
||||
long pIShellFolder = getIShellFolder();
|
||||
long pEnumObjects = getEnumObjects(pIShellFolder, true);
|
||||
Win32ShellFolder2 child = null;
|
||||
long childPIDL = 0;
|
||||
|
||||
while ((childPIDL = getNextChild(pEnumObjects)) != 0) {
|
||||
if (getAttributes0(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM) != 0) {
|
||||
String path = getFileSystemPath(pIShellFolder, childPIDL);
|
||||
if (path != null && path.equalsIgnoreCase(filePath)) {
|
||||
long childIShellFolder = bindToObject(pIShellFolder, childPIDL);
|
||||
child = new Win32ShellFolder2(this, childIShellFolder, childPIDL, path);
|
||||
break;
|
||||
while ((childPIDL = getNextChild(pEnumObjects)) != 0) {
|
||||
if (getAttributes0(pIShellFolder, childPIDL, ATTRIB_FILESYSTEM) != 0) {
|
||||
String path = getFileSystemPath(pIShellFolder, childPIDL);
|
||||
if (path != null && path.equalsIgnoreCase(filePath)) {
|
||||
long childIShellFolder = bindToObject(pIShellFolder, childPIDL);
|
||||
child = new Win32ShellFolder2(Win32ShellFolder2.this,
|
||||
childIShellFolder, childPIDL, path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
releasePIDL(childPIDL);
|
||||
}
|
||||
releaseEnumObjects(pEnumObjects);
|
||||
return child;
|
||||
}
|
||||
releasePIDL(childPIDL);
|
||||
}
|
||||
releaseEnumObjects(pEnumObjects);
|
||||
return child;
|
||||
});
|
||||
}
|
||||
|
||||
private Boolean cachedIsLink;
|
||||
|
||||
/**
|
||||
* @return Whether this shell folder is a link
|
||||
*/
|
||||
public boolean isLink() {
|
||||
return hasAttribute(ATTRIB_LINK);
|
||||
public synchronized boolean isLink() {
|
||||
if (cachedIsLink == null) {
|
||||
cachedIsLink = hasAttribute(ATTRIB_LINK);
|
||||
}
|
||||
|
||||
return cachedIsLink;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -682,6 +778,7 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
|
||||
|
||||
// Return the link location of a shell folder
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native long getLinkLocation(long parentIShellFolder,
|
||||
long relativePIDL, boolean resolve);
|
||||
|
||||
@ -693,38 +790,52 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
return getLinkLocation(true);
|
||||
}
|
||||
|
||||
private ShellFolder getLinkLocation(boolean resolve) {
|
||||
if (!isLink()) {
|
||||
return null;
|
||||
}
|
||||
private ShellFolder getLinkLocation(final boolean resolve) {
|
||||
return ShellFolder.getInvoker().invoke(new Callable<ShellFolder>() {
|
||||
public ShellFolder call() throws Exception {
|
||||
if (!isLink()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ShellFolder location = null;
|
||||
long linkLocationPIDL = getLinkLocation(getParentIShellFolder(),
|
||||
getRelativePIDL(), resolve);
|
||||
if (linkLocationPIDL != 0) {
|
||||
try {
|
||||
location =
|
||||
Win32ShellFolderManager2.createShellFolderFromRelativePIDL(getDesktop(),
|
||||
linkLocationPIDL);
|
||||
} catch (InternalError e) {
|
||||
// Could be a link to a non-bindable object, such as a network connection
|
||||
// TODO: getIShellFolder() should throw FileNotFoundException instead
|
||||
ShellFolder location = null;
|
||||
long linkLocationPIDL = getLinkLocation(getParentIShellFolder(),
|
||||
getRelativePIDL(), resolve);
|
||||
if (linkLocationPIDL != 0) {
|
||||
try {
|
||||
location =
|
||||
Win32ShellFolderManager2.createShellFolderFromRelativePIDL(getDesktop(),
|
||||
linkLocationPIDL);
|
||||
} catch (InternalError e) {
|
||||
// Could be a link to a non-bindable object, such as a network connection
|
||||
// TODO: getIShellFolder() should throw FileNotFoundException instead
|
||||
}
|
||||
}
|
||||
return location;
|
||||
}
|
||||
}
|
||||
return location;
|
||||
});
|
||||
}
|
||||
|
||||
// Parse a display name into a PIDL relative to the current IShellFolder.
|
||||
long parseDisplayName(String name) throws FileNotFoundException {
|
||||
long parseDisplayName(final String name) throws FileNotFoundException {
|
||||
try {
|
||||
return parseDisplayName0(getIShellFolder(), name);
|
||||
} catch (IOException e) {
|
||||
throw new FileNotFoundException("Could not find file " + name);
|
||||
return ShellFolder.getInvoker().invoke(new Callable<Long>() {
|
||||
public Long call() throws Exception {
|
||||
return parseDisplayName0(getIShellFolder(), name);
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException e) {
|
||||
if (e.getCause() instanceof IOException) {
|
||||
throw new FileNotFoundException("Could not find file " + name);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native long parseDisplayName0(long pIShellFolder, String name) throws IOException;
|
||||
|
||||
// Return the display name of a shell folder
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native String getDisplayNameOf(long parentIShellFolder,
|
||||
long relativePIDL,
|
||||
int attrs);
|
||||
@ -734,12 +845,19 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
if (displayName == null) {
|
||||
displayName = getDisplayNameOf(getParentIShellFolder(), getRelativePIDL(), SHGDN_NORMAL);
|
||||
displayName =
|
||||
ShellFolder.getInvoker().invoke(new Callable<String>() {
|
||||
public String call() throws Exception {
|
||||
return getDisplayNameOf(getParentIShellFolder(),
|
||||
getRelativePIDL(), SHGDN_NORMAL);
|
||||
}
|
||||
});
|
||||
}
|
||||
return displayName;
|
||||
}
|
||||
|
||||
// Return the folder type of a shell folder
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native String getFolderType(long pIDL);
|
||||
|
||||
/**
|
||||
@ -747,7 +865,13 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
*/
|
||||
public String getFolderType() {
|
||||
if (folderType == null) {
|
||||
folderType = getFolderType(getAbsolutePIDL());
|
||||
final long absolutePIDL = getAbsolutePIDL();
|
||||
folderType =
|
||||
ShellFolder.getInvoker().invoke(new Callable<String>() {
|
||||
public String call() throws Exception {
|
||||
return getFolderType(absolutePIDL);
|
||||
}
|
||||
});
|
||||
}
|
||||
return folderType;
|
||||
}
|
||||
@ -774,11 +898,16 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
private static Map smallLinkedSystemImages = new HashMap();
|
||||
private static Map largeLinkedSystemImages = new HashMap();
|
||||
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native long getIShellIcon(long pIShellFolder);
|
||||
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native int getIconIndex(long parentIShellIcon, long relativePIDL);
|
||||
|
||||
// Return the icon of a file system shell folder in the form of an HICON
|
||||
private static native long getIcon(String absolutePath, boolean getLargeIcon);
|
||||
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native long extractIcon(long parentIShellFolder, long relativePIDL,
|
||||
boolean getLargeIcon);
|
||||
|
||||
@ -799,7 +928,12 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
|
||||
private long getIShellIcon() {
|
||||
if (pIShellIcon == -1L) {
|
||||
pIShellIcon = getIShellIcon(getIShellFolder());
|
||||
pIShellIcon =
|
||||
ShellFolder.getInvoker().invoke(new Callable<Long>() {
|
||||
public Long call() throws Exception {
|
||||
return getIShellIcon(getIShellFolder());
|
||||
}
|
||||
});
|
||||
}
|
||||
return pIShellIcon;
|
||||
}
|
||||
@ -850,50 +984,60 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
/**
|
||||
* @return The icon image used to display this shell folder
|
||||
*/
|
||||
public Image getIcon(boolean getLargeIcon) {
|
||||
public Image getIcon(final boolean getLargeIcon) {
|
||||
Image icon = getLargeIcon ? largeIcon : smallIcon;
|
||||
if (icon == null) {
|
||||
long parentIShellIcon = (parent != null) ? ((Win32ShellFolder2)parent).getIShellIcon() : 0L;
|
||||
long relativePIDL = getRelativePIDL();
|
||||
icon =
|
||||
ShellFolder.getInvoker().invoke(new Callable<Image>() {
|
||||
public Image call() throws Exception {
|
||||
Image newIcon = null;
|
||||
if (isFileSystem()) {
|
||||
long parentIShellIcon = (parent != null)
|
||||
? ((Win32ShellFolder2) parent).getIShellIcon()
|
||||
: 0L;
|
||||
long relativePIDL = getRelativePIDL();
|
||||
|
||||
if (isFileSystem()) {
|
||||
// These are cached per type (using the index in the system image list)
|
||||
int index = getIconIndex(parentIShellIcon, relativePIDL);
|
||||
if (index > 0) {
|
||||
Map imageCache;
|
||||
if (isLink()) {
|
||||
imageCache = getLargeIcon ? largeLinkedSystemImages : smallLinkedSystemImages;
|
||||
} else {
|
||||
imageCache = getLargeIcon ? largeSystemImages : smallSystemImages;
|
||||
}
|
||||
icon = (Image)imageCache.get(Integer.valueOf(index));
|
||||
if (icon == null) {
|
||||
long hIcon = getIcon(getAbsolutePath(), getLargeIcon);
|
||||
icon = makeIcon(hIcon, getLargeIcon);
|
||||
disposeIcon(hIcon);
|
||||
if (icon != null) {
|
||||
imageCache.put(Integer.valueOf(index), icon);
|
||||
// These are cached per type (using the index in the system image list)
|
||||
int index = getIconIndex(parentIShellIcon, relativePIDL);
|
||||
if (index > 0) {
|
||||
Map imageCache;
|
||||
if (isLink()) {
|
||||
imageCache = getLargeIcon ? largeLinkedSystemImages : smallLinkedSystemImages;
|
||||
} else {
|
||||
imageCache = getLargeIcon ? largeSystemImages : smallSystemImages;
|
||||
}
|
||||
newIcon = (Image) imageCache.get(Integer.valueOf(index));
|
||||
if (newIcon == null) {
|
||||
long hIcon = getIcon(getAbsolutePath(), getLargeIcon);
|
||||
newIcon = makeIcon(hIcon, getLargeIcon);
|
||||
disposeIcon(hIcon);
|
||||
if (newIcon != null) {
|
||||
imageCache.put(Integer.valueOf(index), newIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newIcon == null) {
|
||||
// These are only cached per object
|
||||
long hIcon = extractIcon(getParentIShellFolder(),
|
||||
getRelativePIDL(), getLargeIcon);
|
||||
newIcon = makeIcon(hIcon, getLargeIcon);
|
||||
disposeIcon(hIcon);
|
||||
}
|
||||
|
||||
if (newIcon == null) {
|
||||
newIcon = Win32ShellFolder2.super.getIcon(getLargeIcon);
|
||||
}
|
||||
return newIcon;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (icon == null) {
|
||||
// These are only cached per object
|
||||
long hIcon = extractIcon(getParentIShellFolder(), getRelativePIDL(), getLargeIcon);
|
||||
icon = makeIcon(hIcon, getLargeIcon);
|
||||
disposeIcon(hIcon);
|
||||
}
|
||||
|
||||
});
|
||||
if (getLargeIcon) {
|
||||
largeIcon = icon;
|
||||
} else {
|
||||
smallIcon = icon;
|
||||
}
|
||||
}
|
||||
if (icon == null) {
|
||||
icon = super.getIcon(getLargeIcon);
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
@ -969,39 +1113,50 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
private static final int LVCFMT_CENTER = 2;
|
||||
|
||||
public ShellFolderColumnInfo[] getFolderColumns() {
|
||||
ShellFolderColumnInfo[] columns = doGetColumnInfo(getIShellFolder());
|
||||
return ShellFolder.getInvoker().invoke(new Callable<ShellFolderColumnInfo[]>() {
|
||||
public ShellFolderColumnInfo[] call() throws Exception {
|
||||
ShellFolderColumnInfo[] columns = doGetColumnInfo(getIShellFolder());
|
||||
|
||||
if (columns != null) {
|
||||
List<ShellFolderColumnInfo> notNullColumns =
|
||||
new ArrayList<ShellFolderColumnInfo>();
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
ShellFolderColumnInfo column = columns[i];
|
||||
if (column != null) {
|
||||
column.setAlignment(column.getAlignment() == LVCFMT_RIGHT
|
||||
? SwingConstants.RIGHT
|
||||
: column.getAlignment() == LVCFMT_CENTER
|
||||
? SwingConstants.CENTER
|
||||
: SwingConstants.LEADING);
|
||||
if (columns != null) {
|
||||
List<ShellFolderColumnInfo> notNullColumns =
|
||||
new ArrayList<ShellFolderColumnInfo>();
|
||||
for (int i = 0; i < columns.length; i++) {
|
||||
ShellFolderColumnInfo column = columns[i];
|
||||
if (column != null) {
|
||||
column.setAlignment(column.getAlignment() == LVCFMT_RIGHT
|
||||
? SwingConstants.RIGHT
|
||||
: column.getAlignment() == LVCFMT_CENTER
|
||||
? SwingConstants.CENTER
|
||||
: SwingConstants.LEADING);
|
||||
|
||||
column.setComparator(new ColumnComparator(getIShellFolder(), i));
|
||||
column.setComparator(new ColumnComparator(getIShellFolder(), i));
|
||||
|
||||
notNullColumns.add(column);
|
||||
notNullColumns.add(column);
|
||||
}
|
||||
}
|
||||
columns = new ShellFolderColumnInfo[notNullColumns.size()];
|
||||
notNullColumns.toArray(columns);
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
columns = new ShellFolderColumnInfo[notNullColumns.size()];
|
||||
notNullColumns.toArray(columns);
|
||||
}
|
||||
return columns;
|
||||
});
|
||||
}
|
||||
|
||||
public Object getFolderColumnValue(int column) {
|
||||
return doGetColumnValue(getParentIShellFolder(), getRelativePIDL(), column);
|
||||
public Object getFolderColumnValue(final int column) {
|
||||
return ShellFolder.getInvoker().invoke(new Callable<Object>() {
|
||||
public Object call() throws Exception {
|
||||
return doGetColumnValue(getParentIShellFolder(), getRelativePIDL(), column);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private native ShellFolderColumnInfo[] doGetColumnInfo(long iShellFolder2);
|
||||
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private native Object doGetColumnValue(long parentIShellFolder2, long childPIDL, int columnIdx);
|
||||
|
||||
// NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
|
||||
private static native int compareIDsByColumn(long pParentIShellFolder, long pidl1, long pidl2, int columnIdx);
|
||||
|
||||
|
||||
@ -1020,17 +1175,20 @@ final class Win32ShellFolder2 extends ShellFolder {
|
||||
}
|
||||
|
||||
// compares 2 objects within this folder by the specified column
|
||||
public int compare(File o, File o1) {
|
||||
if (o instanceof Win32ShellFolder2
|
||||
&& o1 instanceof Win32ShellFolder2) {
|
||||
// delegates comparison to native method
|
||||
return compareIDsByColumn(parentIShellFolder,
|
||||
((Win32ShellFolder2) o).getRelativePIDL(),
|
||||
((Win32ShellFolder2) o1).getRelativePIDL(),
|
||||
columnIdx);
|
||||
}
|
||||
return 0;
|
||||
public int compare(final File o, final File o1) {
|
||||
return ShellFolder.getInvoker().invoke(new Callable<Integer>() {
|
||||
public Integer call() throws Exception {
|
||||
if (o instanceof Win32ShellFolder2
|
||||
&& o1 instanceof Win32ShellFolder2) {
|
||||
// delegates comparison to native method
|
||||
return compareIDsByColumn(parentIShellFolder,
|
||||
((Win32ShellFolder2) o).getRelativePIDL(),
|
||||
((Win32ShellFolder2) o1).getRelativePIDL(),
|
||||
columnIdx);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,7 +31,10 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import sun.security.action.LoadLibraryAction;
|
||||
|
||||
import static sun.awt.shell.Win32ShellFolder2.*;
|
||||
@ -408,4 +411,102 @@ public class Win32ShellFolderManager2 extends ShellFolderManager {
|
||||
return name1.compareTo(name2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Invoker createInvoker() {
|
||||
return new ComInvoker();
|
||||
}
|
||||
|
||||
private static class ComInvoker extends ThreadPoolExecutor implements ThreadFactory, ShellFolder.Invoker {
|
||||
private static Thread comThread;
|
||||
|
||||
private ComInvoker() {
|
||||
super(1, 1, 0, TimeUnit.DAYS, new LinkedBlockingQueue<Runnable>());
|
||||
allowCoreThreadTimeOut(false);
|
||||
setThreadFactory(this);
|
||||
final Runnable shutdownHook = new Runnable() {
|
||||
public void run() {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
shutdownNow();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
Runtime.getRuntime().addShutdownHook(
|
||||
new Thread(shutdownHook)
|
||||
);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized Thread newThread(final Runnable task) {
|
||||
final Runnable comRun = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
initializeCom();
|
||||
task.run();
|
||||
} finally {
|
||||
uninitializeCom();
|
||||
}
|
||||
}
|
||||
};
|
||||
comThread =
|
||||
AccessController.doPrivileged(
|
||||
new PrivilegedAction<Thread>() {
|
||||
public Thread run() {
|
||||
/* The thread must be a member of a thread group
|
||||
* which will not get GCed before VM exit.
|
||||
* Make its parent the top-level thread group.
|
||||
*/
|
||||
ThreadGroup tg = Thread.currentThread().getThreadGroup();
|
||||
for (ThreadGroup tgn = tg;
|
||||
tgn != null;
|
||||
tg = tgn, tgn = tg.getParent());
|
||||
Thread thread = new Thread(tg, comRun, "Swing-Shell");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}
|
||||
}
|
||||
);
|
||||
return comThread;
|
||||
}
|
||||
|
||||
public <T> T invoke(Callable<T> task) {
|
||||
try {
|
||||
T result;
|
||||
if (Thread.currentThread() == comThread) {
|
||||
// if it's already called from the COM
|
||||
// thread, we don't need to delegate the task
|
||||
result = task.call();
|
||||
} else {
|
||||
Future<T> future = submit(task);
|
||||
try {
|
||||
result = future.get();
|
||||
} catch (InterruptedException e) {
|
||||
result = null;
|
||||
future.cancel(true);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
Throwable cause = (e instanceof ExecutionException) ? e.getCause() : e;
|
||||
if (cause instanceof RuntimeException) {
|
||||
throw (RuntimeException) cause;
|
||||
}
|
||||
if (cause instanceof Error) {
|
||||
throw (Error) cause;
|
||||
}
|
||||
throw new RuntimeException(cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static native void initializeCom();
|
||||
|
||||
static native void uninitializeCom();
|
||||
}
|
||||
|
@ -225,6 +225,34 @@ JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initIDs
|
||||
FID_folderType = env->GetFieldID(cls, "folderType", "Ljava/lang/String;");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: sun_awt_shell_Win32ShellFolderManager2
|
||||
* Method: initializeCom
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolderManager2_initializeCom
|
||||
(JNIEnv* env, jclass cls)
|
||||
{
|
||||
HRESULT hr = ::CoInitialize(NULL);
|
||||
if (FAILED(hr)) {
|
||||
char c[64];
|
||||
sprintf(c, "Could not initialize COM: HRESULT=0x%08X", hr);
|
||||
JNU_ThrowInternalError(env, c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_awt_shell_Win32ShellFolderManager2
|
||||
* Method: uninitializeCom
|
||||
* Signature: ()V
|
||||
*/
|
||||
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolderManager2_uninitializeCom
|
||||
(JNIEnv* env, jclass cls)
|
||||
{
|
||||
::CoUninitialize();
|
||||
}
|
||||
|
||||
static IShellIcon* getIShellIcon(IShellFolder* pIShellFolder) {
|
||||
// http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp
|
||||
HRESULT hres;
|
||||
@ -239,29 +267,6 @@ static IShellIcon* getIShellIcon(IShellFolder* pIShellFolder) {
|
||||
return (IShellIcon*)NULL;
|
||||
}
|
||||
|
||||
// Fixed 6263669
|
||||
//
|
||||
// CoInitialize wrapper
|
||||
// call CoInitialize to initialize COM in STA mode and check result
|
||||
// RPC_E_CHANGED_MODE means COM has already been initialized in MTA mode,
|
||||
// so don't set the flag to call CoUninitialize later
|
||||
|
||||
BOOL CoInit(BOOL& doCoUninit) { // returns TRUE if initialized successfully
|
||||
switch(::CoInitialize(NULL)) {
|
||||
case S_OK:
|
||||
case S_FALSE:
|
||||
doCoUninit = TRUE;
|
||||
return TRUE;
|
||||
break;
|
||||
case RPC_E_CHANGED_MODE:
|
||||
doCoUninit = FALSE;
|
||||
return TRUE;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Class: sun_awt_shell_Win32ShellFolder2
|
||||
@ -507,10 +512,10 @@ JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getAttributes0
|
||||
|
||||
/*
|
||||
* Class: sun_awt_shell_Win32ShellFolder2
|
||||
* Method: getFileSystemPath
|
||||
* Method: getFileSystemPath0
|
||||
* Signature: (I)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileSystemPath__I
|
||||
JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileSystemPath0
|
||||
(JNIEnv* env, jclass cls, jint csidl)
|
||||
{
|
||||
LPITEMIDLIST relPIDL;
|
||||
@ -611,18 +616,6 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_bindToObject
|
||||
if (SUCCEEDED (hr)) {
|
||||
return (jlong)pFolder;
|
||||
}
|
||||
if (IS_WINVISTA) {
|
||||
BOOL doCoUninit;
|
||||
if (CoInit(doCoUninit)) {
|
||||
hr = pParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&pFolder);
|
||||
if (doCoUninit) {
|
||||
::CoUninitialize();
|
||||
}
|
||||
if (SUCCEEDED (hr)) {
|
||||
return (jlong)pFolder;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -650,7 +643,10 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getLinkLocation
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pParent->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_FORPARSING, &strret);
|
||||
hres = pParent->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_FORPARSING, &strret);
|
||||
if (FAILED(hres)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (strret.uType) {
|
||||
case STRRET_CSTR :
|
||||
@ -669,10 +665,6 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getLinkLocation
|
||||
break;
|
||||
}
|
||||
|
||||
BOOL doCoUninit;
|
||||
if (!CoInit(doCoUninit)) {
|
||||
return 0;
|
||||
}
|
||||
IShellLinkW* psl;
|
||||
hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&psl);
|
||||
if (SUCCEEDED(hres)) {
|
||||
@ -692,9 +684,6 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getLinkLocation
|
||||
}
|
||||
psl->Release();
|
||||
}
|
||||
if (doCoUninit) {
|
||||
::CoUninitialize();
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hres)) {
|
||||
return (jlong)pidl;
|
||||
@ -741,7 +730,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_parseDisplayName0
|
||||
/*
|
||||
* Class: sun_awt_shell_Win32ShellFolder2
|
||||
* Method: getDisplayNameOf
|
||||
* Signature: (JJ)Ljava/lang/String;
|
||||
* Signature: (JJI)Ljava/lang/String;
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getDisplayNameOf
|
||||
(JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL, jint attrs)
|
||||
@ -833,10 +822,6 @@ JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconIndex
|
||||
}
|
||||
|
||||
INT index = -1;
|
||||
BOOL doCoUninit;
|
||||
if (!CoInit(doCoUninit)) {
|
||||
return (jint)index;
|
||||
}
|
||||
|
||||
HRESULT hres;
|
||||
// http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp
|
||||
@ -844,9 +829,6 @@ JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconIndex
|
||||
hres = pIShellIcon->GetIconOf(pidl, GIL_FORSHELL, &index);
|
||||
}
|
||||
|
||||
if (doCoUninit) {
|
||||
::CoUninitialize();
|
||||
}
|
||||
return (jint)index;
|
||||
}
|
||||
|
||||
@ -866,10 +848,6 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_extractIcon
|
||||
}
|
||||
|
||||
HICON hIcon = NULL;
|
||||
BOOL doCoUninit;
|
||||
if (!CoInit(doCoUninit)) {
|
||||
return (jlong)hIcon;
|
||||
}
|
||||
|
||||
HRESULT hres;
|
||||
IExtractIconW* pIcon;
|
||||
@ -894,9 +872,6 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_extractIcon
|
||||
}
|
||||
pIcon->Release();
|
||||
}
|
||||
if (doCoUninit) {
|
||||
::CoUninitialize();
|
||||
}
|
||||
return (jlong)hIcon;
|
||||
}
|
||||
|
||||
@ -994,14 +969,10 @@ JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileChooserB
|
||||
HINSTANCE libComCtl32;
|
||||
HINSTANCE libShell32;
|
||||
|
||||
|
||||
libShell32 = LoadLibrary(TEXT("shell32.dll"));
|
||||
if (libShell32 != NULL) {
|
||||
long osVersion = GetVersion();
|
||||
BOOL isVista = (!(osVersion & 0x80000000) && (LOBYTE(LOWORD(osVersion)) >= 6));
|
||||
|
||||
hBitmap = (HBITMAP)LoadImage(libShell32,
|
||||
isVista ? TEXT("IDB_TB_SH_DEF_16") : MAKEINTRESOURCE(216),
|
||||
IS_WINVISTA ? TEXT("IDB_TB_SH_DEF_16") : MAKEINTRESOURCE(216),
|
||||
IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
|
||||
}
|
||||
if (hBitmap == NULL) {
|
||||
@ -1095,46 +1066,6 @@ JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconResource
|
||||
}
|
||||
|
||||
|
||||
// Helper functions for workaround COM initialization:
|
||||
|
||||
static HRESULT GetDetailsOfFolder(
|
||||
IShellFolder2 *folder,
|
||||
LPCITEMIDLIST pidl,
|
||||
UINT column,
|
||||
SHELLDETAILS *psd)
|
||||
{
|
||||
HRESULT hr = folder->GetDetailsOf(pidl, column, psd);
|
||||
if (IS_WINVISTA && FAILED (hr)) {
|
||||
BOOL doCoUninit;
|
||||
if (CoInit(doCoUninit)) {
|
||||
hr = folder->GetDetailsOf(pidl, column, psd);
|
||||
if (doCoUninit) {
|
||||
::CoUninitialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT GetDetailsOf(
|
||||
IShellDetails *details,
|
||||
LPCITEMIDLIST pidl,
|
||||
UINT column,
|
||||
SHELLDETAILS *psd)
|
||||
{
|
||||
HRESULT hr = details->GetDetailsOf(pidl, column, psd);
|
||||
if (IS_WINVISTA && FAILED (hr)) {
|
||||
BOOL doCoUninit;
|
||||
if (CoInit(doCoUninit)) {
|
||||
hr = details->GetDetailsOf(pidl, column, psd);
|
||||
if (doCoUninit) {
|
||||
::CoUninitialize();
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function for creating Java column info object
|
||||
*/
|
||||
@ -1187,7 +1118,7 @@ JNIEXPORT jobjectArray JNICALL
|
||||
int colNum = -1;
|
||||
hr = S_OK;
|
||||
do{
|
||||
hr = GetDetailsOfFolder(pIShellFolder2, NULL, ++colNum, &sd);
|
||||
hr = pIShellFolder2->GetDetailsOf(NULL, ++colNum, &sd);
|
||||
} while (SUCCEEDED (hr));
|
||||
|
||||
jobjectArray columns =
|
||||
@ -1202,7 +1133,7 @@ JNIEXPORT jobjectArray JNICALL
|
||||
colNum = 0;
|
||||
hr = S_OK;
|
||||
while (SUCCEEDED (hr)) {
|
||||
hr = GetDetailsOfFolder(pIShellFolder2, NULL, colNum, &sd);
|
||||
hr = pIShellFolder2->GetDetailsOf(NULL, colNum, &sd);
|
||||
|
||||
if (SUCCEEDED (hr)) {
|
||||
hr = pIShellFolder2->GetDefaultColumnState(colNum, &csFlags);
|
||||
@ -1232,7 +1163,7 @@ JNIEXPORT jobjectArray JNICALL
|
||||
int colNum = -1;
|
||||
hr = S_OK;
|
||||
do{
|
||||
hr = GetDetailsOf(pIShellDetails, NULL, ++colNum, &sd);
|
||||
hr = pIShellDetails->GetDetailsOf(NULL, ++colNum, &sd);
|
||||
} while (SUCCEEDED (hr));
|
||||
|
||||
jobjectArray columns =
|
||||
@ -1246,7 +1177,7 @@ JNIEXPORT jobjectArray JNICALL
|
||||
colNum = 0;
|
||||
hr = S_OK;
|
||||
while (SUCCEEDED (hr)) {
|
||||
hr = GetDetailsOf(pIShellDetails, NULL, colNum, &sd);
|
||||
hr = pIShellDetails->GetDetailsOf(NULL, colNum, &sd);
|
||||
if (SUCCEEDED (hr)) {
|
||||
jobject column = CreateColumnInfo(env,
|
||||
&columnClass, &columnConstructor,
|
||||
@ -1288,7 +1219,7 @@ JNIEXPORT jobject JNICALL
|
||||
if(SUCCEEDED (hr)) {
|
||||
// The folder exposes IShellFolder2 interface
|
||||
IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown;
|
||||
hr = GetDetailsOfFolder(pIShellFolder2, pidl, (UINT)columnIdx, &sd);
|
||||
hr = pIShellFolder2->GetDetailsOf(pidl, (UINT)columnIdx, &sd);
|
||||
pIShellFolder2->Release();
|
||||
if (SUCCEEDED (hr)) {
|
||||
STRRET strRet = sd.str;
|
||||
@ -1300,7 +1231,7 @@ JNIEXPORT jobject JNICALL
|
||||
if(SUCCEEDED (hr)) {
|
||||
// The folder exposes IShellDetails interface
|
||||
IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown;
|
||||
hr = GetDetailsOf(pIShellDetails, pidl, (UINT)columnIdx, &sd);
|
||||
hr = pIShellDetails->GetDetailsOf(pidl, (UINT)columnIdx, &sd);
|
||||
pIShellDetails->Release();
|
||||
if (SUCCEEDED (hr)) {
|
||||
STRRET strRet = sd.str;
|
||||
|
20
jdk/test/javax/swing/JFileChooser/6570445/bug6570445.java
Normal file
20
jdk/test/javax/swing/JFileChooser/6570445/bug6570445.java
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* @test
|
||||
* @bug 6570445
|
||||
* @summary Checks if Win32ShellFolder2's COM-using methods work under a security manager
|
||||
* @author Leonid Popov
|
||||
*/
|
||||
|
||||
import javax.swing.filechooser.FileSystemView;
|
||||
|
||||
public class bug6570445 {
|
||||
public static void main(String[] args) {
|
||||
System.setSecurityManager(new SecurityManager());
|
||||
|
||||
// The next line of code forces FileSystemView to request data from Win32ShellFolder2,
|
||||
// what causes an exception if a security manager installed (see the bug 6570445 description)
|
||||
FileSystemView.getFileSystemView().getRoots();
|
||||
|
||||
System.out.println("Passed.");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user