< prev index next >

src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolder2.java

Print this page


   1 /*
   2  * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  57  * a series of identifiers and can be either relative to the desktop
  58  * (an absolute PIDL), or relative to the shell folder that contains them.
  59  * Some Win32 functions can take absolute or relative PIDL values, and
  60  * others can only accept relative values.
  61  * <BR>
  62  * The second data structure is an IShellFolder COM interface.  Using
  63  * this interface, one can enumerate the relative PIDLs in a shell
  64  * folder, get attributes, etc.
  65  * <BR>
  66  * All Win32ShellFolder2 objects which are folder types (even non-file
  67  * system folders) contain an IShellFolder object. Files are named in
  68  * directories via relative PIDLs.
  69  *
  70  * @author Michael Martak
  71  * @author Leif Samuelsson
  72  * @author Kenneth Russell
  73  * @since 1.4 */
  74 @SuppressWarnings("serial") // JDK-implementation class
  75 final class Win32ShellFolder2 extends ShellFolder {
  76 






  77     private static native void initIDs();
  78 
  79     static {
  80         initIDs();
  81     }
  82 
  83     // Win32 Shell Folder Constants
  84     public static final int DESKTOP = 0x0000;
  85     public static final int INTERNET = 0x0001;
  86     public static final int PROGRAMS = 0x0002;
  87     public static final int CONTROLS = 0x0003;
  88     public static final int PRINTERS = 0x0004;
  89     public static final int PERSONAL = 0x0005;
  90     public static final int FAVORITES = 0x0006;
  91     public static final int STARTUP = 0x0007;
  92     public static final int RECENT = 0x0008;
  93     public static final int SENDTO = 0x0009;
  94     public static final int BITBUCKET = 0x000a;
  95     public static final int STARTMENU = 0x000b;
  96     public static final int DESKTOPDIRECTORY = 0x0010;


 960 
 961 
 962     // Icons
 963 
 964     private static Map<Integer, Image> smallSystemImages = new HashMap<>();
 965     private static Map<Integer, Image> largeSystemImages = new HashMap<>();
 966     private static Map<Integer, Image> smallLinkedSystemImages = new HashMap<>();
 967     private static Map<Integer, Image> largeLinkedSystemImages = new HashMap<>();
 968 
 969     // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
 970     private static native long getIShellIcon(long pIShellFolder);
 971 
 972     // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
 973     private static native int getIconIndex(long parentIShellIcon, long relativePIDL);
 974 
 975     // Return the icon of a file system shell folder in the form of an HICON
 976     private static native long getIcon(String absolutePath, boolean getLargeIcon);
 977 
 978     // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
 979     private static native long extractIcon(long parentIShellFolder, long relativePIDL,
 980                                            boolean getLargeIcon, boolean getDefaultIcon);
 981 
 982     // Returns an icon from the Windows system icon list in the form of an HICON
 983     private static native long getSystemIcon(int iconID);
 984     private static native long getIconResource(String libName, int iconID,
 985                                                int cxDesired, int cyDesired,
 986                                                boolean useVGAColors);
 987                                                // Note: useVGAColors is ignored on XP and later
 988 
 989     // Return the bits from an HICON.  This has a side effect of setting
 990     // the imageHash variable for efficient caching / comparing.
 991     private static native int[] getIconBits(long hIcon);
 992     // Dispose the HICON
 993     private static native void disposeIcon(long hIcon);
 994 
 995     // Get buttons from native toolbar implementation.
 996     static native int[] getStandardViewButton0(int iconIndex, boolean small);
 997 
 998     // Should be called from the COM thread
 999     private long getIShellIcon() {
1000         if (pIShellIcon == -1L) {
1001             pIShellIcon = getIShellIcon(getIShellFolder());
1002         }
1003 
1004         return pIShellIcon;
1005     }
1006 
1007     private static Image makeIcon(long hIcon, boolean getLargeIcon) {
1008         if (hIcon != 0L && hIcon != -1L) {
1009             // Get the bits.  This has the side effect of setting the imageHash value for this object.
1010             final int[] iconBits = getIconBits(hIcon);
1011             if (iconBits != null) {
1012                 // icons are always square
1013                 final int size = (int) Math.sqrt(iconBits.length);
1014                 final int baseSize = getLargeIcon ? 32 : 16;
1015                 final BufferedImage img =
1016                         new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
1017                 img.setRGB(0, 0, size, size, iconBits, 0, size);
1018                 return size == baseSize
1019                         ? img
1020                         : new MultiResolutionIconImage(baseSize, img);
1021             }
1022         }
1023         return null;
1024     }
1025 
1026 
1027     /**
1028      * @return The icon image used to display this shell folder
1029      */
1030     public Image getIcon(final boolean getLargeIcon) {
1031         Image icon = getLargeIcon ? largeIcon : smallIcon;

1032         if (icon == null) {
1033             icon =
1034                 invoke(new Callable<Image>() {
1035                     public Image call() {
1036                         Image newIcon = null;
1037                         if (isLink()) {
1038                             Win32ShellFolder2 folder = getLinkLocation(false);
1039                             if (folder != null && folder.isLibrary()) {
1040                                 return folder.getIcon(getLargeIcon);
1041                             }
1042                         }
1043                         if (isFileSystem() || isLibrary()) {
1044                             long parentIShellIcon = (parent != null)
1045                                 ? ((Win32ShellFolder2) parent).getIShellIcon()
1046                                 : 0L;
1047                             long relativePIDL = getRelativePIDL();
1048 
1049                             // These are cached per type (using the index in the system image list)
1050                             int index = getIconIndex(parentIShellIcon, relativePIDL);
1051                             if (index > 0) {
1052                                 Map<Integer, Image> imageCache;
1053                                 if (isLink()) {
1054                                     imageCache = getLargeIcon ? largeLinkedSystemImages : smallLinkedSystemImages;
1055                                 } else {
1056                                     imageCache = getLargeIcon ? largeSystemImages : smallSystemImages;
1057                                 }
1058                                 newIcon = imageCache.get(Integer.valueOf(index));
1059                                 if (newIcon == null) {
1060                                     long hIcon = getIcon(getAbsolutePath(), getLargeIcon);
1061                                     newIcon = makeIcon(hIcon, getLargeIcon);
1062                                     disposeIcon(hIcon);
1063                                     if (newIcon != null) {
1064                                         imageCache.put(Integer.valueOf(index), newIcon);
1065                                     }
1066                                 }
1067                             }
1068                         }
1069 
1070                         if (newIcon == null) {
1071                             // These are only cached per object
1072                             long hIcon = extractIcon(getParentIShellFolder(),
1073                                     getRelativePIDL(), getLargeIcon, false);
1074                             // E_PENDING: loading can take time so get the default
1075                             if(hIcon <= 0) {
1076                                 hIcon = extractIcon(getParentIShellFolder(),
1077                                          getRelativePIDL(), getLargeIcon, true);
1078                                 if(hIcon <= 0) {
1079                                     if (isDirectory()) {
1080                                         return getShell32Icon(4, getLargeIcon);
1081                                     } else {
1082                                         return getShell32Icon(1, getLargeIcon);
1083                                     }
1084                                 }
1085                             }
1086                             newIcon = makeIcon(hIcon, getLargeIcon);
1087                             disposeIcon(hIcon);
1088                         }
1089 
1090                         if (newIcon == null) {
1091                             newIcon = Win32ShellFolder2.super.getIcon(getLargeIcon);
1092                         }
1093                         return newIcon;
1094                     }
1095                 });
1096             if (getLargeIcon) {
1097                 largeIcon = icon;





















1098             } else {
1099                 smallIcon = icon;
1100             }
1101         }
1102         return icon;




1103     }
1104 
1105     /**
1106      * Gets an icon from the Windows system icon list as an {@code Image}
1107      */
1108     static Image getSystemIcon(SystemIcon iconType) {
1109         long hIcon = getSystemIcon(iconType.getIconID());
1110         Image icon = makeIcon(hIcon, true);
1111         disposeIcon(hIcon);
1112         return icon;
1113     }
1114 
1115     /**
1116      * Gets an icon from the Windows system icon list as an {@code Image}
1117      */
1118     static Image getShell32Icon(int iconID, boolean getLargeIcon) {
1119         boolean useVGAColors = true; // Will be ignored on XP and later
1120 
1121         int size = getLargeIcon ? 32 : 16;
1122 
1123         Toolkit toolkit = Toolkit.getDefaultToolkit();
1124         String shellIconBPP = (String)toolkit.getDesktopProperty("win.icon.shellIconBPP");
1125         if (shellIconBPP != null) {
1126             useVGAColors = shellIconBPP.equals("4");
1127         }
1128 
1129         long hIcon = getIconResource("shell32.dll", iconID, size, size, useVGAColors);
1130         if (hIcon != 0) {
1131             Image icon = makeIcon(hIcon, getLargeIcon);
1132             disposeIcon(hIcon);
1133             return icon;
1134         }
1135         return null;
1136     }
1137 
1138     /**
1139      * Returns the canonical form of this abstract pathname.  Equivalent to
1140      * <code>new&nbsp;Win32ShellFolder2(getParentFile(), this.{@link java.io.File#getCanonicalPath}())</code>.
1141      *
1142      * @see java.io.File#getCanonicalFile
1143      */
1144     public File getCanonicalFile() throws IOException {
1145         return this;
1146     }
1147 
1148     /*
1149      * Indicates whether this is a special folder (includes My Documents)
1150      */
1151     public boolean isSpecial() {


   1 /*
   2  * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  57  * a series of identifiers and can be either relative to the desktop
  58  * (an absolute PIDL), or relative to the shell folder that contains them.
  59  * Some Win32 functions can take absolute or relative PIDL values, and
  60  * others can only accept relative values.
  61  * <BR>
  62  * The second data structure is an IShellFolder COM interface.  Using
  63  * this interface, one can enumerate the relative PIDLs in a shell
  64  * folder, get attributes, etc.
  65  * <BR>
  66  * All Win32ShellFolder2 objects which are folder types (even non-file
  67  * system folders) contain an IShellFolder object. Files are named in
  68  * directories via relative PIDLs.
  69  *
  70  * @author Michael Martak
  71  * @author Leif Samuelsson
  72  * @author Kenneth Russell
  73  * @since 1.4 */
  74 @SuppressWarnings("serial") // JDK-implementation class
  75 final class Win32ShellFolder2 extends ShellFolder {
  76 
  77     static final int SMALL_ICON_SIZE = 16;
  78     static final int LARGE_ICON_SIZE = 32;
  79 
  80     static final int FILE_ICON_ID = 1;
  81     static final int FOLDER_ICON_ID = 4;
  82 
  83     private static native void initIDs();
  84 
  85     static {
  86         initIDs();
  87     }
  88 
  89     // Win32 Shell Folder Constants
  90     public static final int DESKTOP = 0x0000;
  91     public static final int INTERNET = 0x0001;
  92     public static final int PROGRAMS = 0x0002;
  93     public static final int CONTROLS = 0x0003;
  94     public static final int PRINTERS = 0x0004;
  95     public static final int PERSONAL = 0x0005;
  96     public static final int FAVORITES = 0x0006;
  97     public static final int STARTUP = 0x0007;
  98     public static final int RECENT = 0x0008;
  99     public static final int SENDTO = 0x0009;
 100     public static final int BITBUCKET = 0x000a;
 101     public static final int STARTMENU = 0x000b;
 102     public static final int DESKTOPDIRECTORY = 0x0010;


 966 
 967 
 968     // Icons
 969 
 970     private static Map<Integer, Image> smallSystemImages = new HashMap<>();
 971     private static Map<Integer, Image> largeSystemImages = new HashMap<>();
 972     private static Map<Integer, Image> smallLinkedSystemImages = new HashMap<>();
 973     private static Map<Integer, Image> largeLinkedSystemImages = new HashMap<>();
 974 
 975     // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
 976     private static native long getIShellIcon(long pIShellFolder);
 977 
 978     // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
 979     private static native int getIconIndex(long parentIShellIcon, long relativePIDL);
 980 
 981     // Return the icon of a file system shell folder in the form of an HICON
 982     private static native long getIcon(String absolutePath, boolean getLargeIcon);
 983 
 984     // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
 985     private static native long extractIcon(long parentIShellFolder, long relativePIDL,
 986                                            int size, boolean getDefaultIcon);
 987 
 988     // Returns an icon from the Windows system icon list in the form of an HICON
 989     private static native long getSystemIcon(int iconID);
 990     private static native long getIconResource(String libName, int iconID,
 991                                                int cxDesired, int cyDesired,
 992                                                boolean useVGAColors);
 993                                                // Note: useVGAColors is ignored on XP and later
 994 
 995     // Return the bits from an HICON.  This has a side effect of setting
 996     // the imageHash variable for efficient caching / comparing.
 997     private static native int[] getIconBits(long hIcon);
 998     // Dispose the HICON
 999     private static native void disposeIcon(long hIcon);
1000 
1001     // Get buttons from native toolbar implementation.
1002     static native int[] getStandardViewButton0(int iconIndex, boolean small);
1003 
1004     // Should be called from the COM thread
1005     private long getIShellIcon() {
1006         if (pIShellIcon == -1L) {
1007             pIShellIcon = getIShellIcon(getIShellFolder());
1008         }
1009 
1010         return pIShellIcon;
1011     }
1012 
1013     private static Image makeIcon(long hIcon, int size) {
1014         if (hIcon != 0L && hIcon != -1L) {
1015             // Get the bits.  This has the side effect of setting the imageHash value for this object.
1016             final int[] iconBits = getIconBits(hIcon);
1017             if (iconBits != null) {
1018                 // icons are always square
1019                 final int iconSize = (int) Math.sqrt(iconBits.length);

1020                 final BufferedImage img =
1021                         new BufferedImage(iconSize, iconSize, BufferedImage.TYPE_INT_ARGB);
1022                 img.setRGB(0, 0, iconSize, iconSize, iconBits, 0, iconSize);
1023                 return iconSize == size
1024                         ? img
1025                         : new MultiResolutionIconImage(size, img);
1026             }
1027         }
1028         return null;
1029     }
1030 
1031 
1032     /**
1033      * @return The icon image used to display this shell folder
1034      */
1035     public Image getIcon(final boolean getLargeIcon) {
1036         Image icon = getLargeIcon ? largeIcon : smallIcon;
1037         int size = getLargeIcon ? LARGE_ICON_SIZE : SMALL_ICON_SIZE;
1038         if (icon == null) {
1039             icon =
1040                 invoke(new Callable<Image>() {
1041                     public Image call() {
1042                         Image newIcon = null;
1043                         if (isLink()) {
1044                             Win32ShellFolder2 folder = getLinkLocation(false);
1045                             if (folder != null && folder.isLibrary()) {
1046                                 return folder.getIcon(getLargeIcon);
1047                             }
1048                         }
1049                         if (isFileSystem() || isLibrary()) {
1050                             long parentIShellIcon = (parent != null)
1051                                 ? ((Win32ShellFolder2) parent).getIShellIcon()
1052                                 : 0L;
1053                             long relativePIDL = getRelativePIDL();
1054 
1055                             // These are cached per type (using the index in the system image list)
1056                             int index = getIconIndex(parentIShellIcon, relativePIDL);
1057                             if (index > 0) {
1058                                 Map<Integer, Image> imageCache;
1059                                 if (isLink()) {
1060                                     imageCache = getLargeIcon ? largeLinkedSystemImages : smallLinkedSystemImages;
1061                                 } else {
1062                                     imageCache = getLargeIcon ? largeSystemImages : smallSystemImages;
1063                                 }
1064                                 newIcon = imageCache.get(Integer.valueOf(index));
1065                                 if (newIcon == null) {
1066                                     long hIcon = getIcon(getAbsolutePath(), getLargeIcon);
1067                                     newIcon = makeIcon(hIcon, size);
1068                                     disposeIcon(hIcon);
1069                                     if (newIcon != null) {
1070                                         imageCache.put(Integer.valueOf(index), newIcon);
1071                                     }
1072                                 }
1073                             }
1074                         }
1075 
1076                         if (newIcon == null) {
1077                             // These are only cached per object
1078                             long hIcon = extractIcon(getParentIShellFolder(),
1079                                     getRelativePIDL(), size, false);
1080                             // E_PENDING: loading can take time so get the default
1081                             if(hIcon <= 0) {
1082                                 hIcon = extractIcon(getParentIShellFolder(),
1083                                          getRelativePIDL(), size, true);
1084                                 if(hIcon <= 0) {
1085                                     if (isDirectory()) {
1086                                         return getShell32Icon(FOLDER_ICON_ID, size);
1087                                     } else {
1088                                         return getShell32Icon(FILE_ICON_ID, size);
1089                                     }
1090                                 }
1091                             }
1092                             newIcon = makeIcon(hIcon, size);
1093                             disposeIcon(hIcon);
1094                         }
1095 
1096                         if (newIcon == null) {
1097                             newIcon = Win32ShellFolder2.super.getIcon(getLargeIcon);
1098                         }
1099                         return newIcon;
1100                     }
1101                 });
1102         }
1103         return icon;
1104     }
1105 
1106     public Image getIcon(int size) {
1107         return invoke(() -> {
1108             Image newIcon = null;
1109             if (isLink()) {
1110                 Win32ShellFolder2 folder = getLinkLocation(false);
1111                 if (folder != null && folder.isLibrary()) {
1112                     return folder.getIcon(size);
1113                 }
1114             }
1115             long hIcon = extractIcon(getParentIShellFolder(),
1116                     getRelativePIDL(), size, false);
1117 
1118             // E_PENDING: loading can take time so get the default
1119             if (hIcon <= 0) {
1120                 hIcon = extractIcon(getParentIShellFolder(),
1121                         getRelativePIDL(), size, true);
1122                 if (hIcon <= 0) {
1123                     if (isDirectory()) {
1124                         return getShell32Icon(FOLDER_ICON_ID, size);
1125                     } else {
1126                         return getShell32Icon(FILE_ICON_ID, size);
1127                     }
1128                 }
1129             }
1130             newIcon = makeIcon(hIcon, size);
1131             disposeIcon(hIcon);
1132             return newIcon;
1133         });
1134     }
1135 
1136     /**
1137      * Gets an icon from the Windows system icon list as an {@code Image}
1138      */
1139     static Image getSystemIcon(SystemIcon iconType) {
1140         long hIcon = getSystemIcon(iconType.getIconID());
1141         Image icon = makeIcon(hIcon, LARGE_ICON_SIZE);
1142         disposeIcon(hIcon);
1143         return icon;
1144     }
1145 
1146     /**
1147      * Gets an icon from the Windows system icon list as an {@code Image}
1148      */
1149     static Image getShell32Icon(int iconID, int size) {
1150         boolean useVGAColors = true; // Will be ignored on XP and later



1151         Toolkit toolkit = Toolkit.getDefaultToolkit();
1152         String shellIconBPP = (String)toolkit.getDesktopProperty("win.icon.shellIconBPP");
1153         if (shellIconBPP != null) {
1154             useVGAColors = shellIconBPP.equals("4");
1155         }
1156 
1157         long hIcon = getIconResource("shell32.dll", iconID, size, size, useVGAColors);
1158         if (hIcon != 0) {
1159             Image icon = makeIcon(hIcon, size);
1160             disposeIcon(hIcon);
1161             return icon;
1162         }
1163         return null;
1164     }
1165 
1166     /**
1167      * Returns the canonical form of this abstract pathname.  Equivalent to
1168      * <code>new&nbsp;Win32ShellFolder2(getParentFile(), this.{@link java.io.File#getCanonicalPath}())</code>.
1169      *
1170      * @see java.io.File#getCanonicalFile
1171      */
1172     public File getCanonicalFile() throws IOException {
1173         return this;
1174     }
1175 
1176     /*
1177      * Indicates whether this is a special folder (includes My Documents)
1178      */
1179     public boolean isSpecial() {


< prev index next >