annotate src/windows/native/sun/windows/ShellFolder2.cpp @ 0:37a05a11f281

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children 75755e92430c
rev   line source
duke@0 1 /*
duke@0 2 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
duke@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@0 4 *
duke@0 5 * This code is free software; you can redistribute it and/or modify it
duke@0 6 * under the terms of the GNU General Public License version 2 only, as
duke@0 7 * published by the Free Software Foundation. Sun designates this
duke@0 8 * particular file as subject to the "Classpath" exception as provided
duke@0 9 * by Sun in the LICENSE file that accompanied this code.
duke@0 10 *
duke@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@0 14 * version 2 for more details (a copy is included in the LICENSE file that
duke@0 15 * accompanied this code).
duke@0 16 *
duke@0 17 * You should have received a copy of the GNU General Public License version
duke@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
duke@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@0 20 *
duke@0 21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
duke@0 22 * CA 95054 USA or visit www.sun.com if you need additional information or
duke@0 23 * have any questions.
duke@0 24 */
duke@0 25
duke@0 26 #define OEMRESOURCE
duke@0 27
duke@0 28 #ifdef DEBUG
duke@0 29 // Warning : do not depend on anything in <awt.h>. Including this file
duke@0 30 // is a fix for 4507525 to use the same operator new and delete as AWT.
duke@0 31 // This file should stand independent of AWT and should ultimately be
duke@0 32 // put into its own DLL.
duke@0 33 #include <awt.h>
duke@0 34 #endif
duke@0 35
duke@0 36 #include <windows.h>
duke@0 37 #include <shlobj.h>
duke@0 38 #include <shellapi.h>
duke@0 39 #include "jni_util.h"
duke@0 40 #include "jlong.h"
duke@0 41 #include "alloc.h"
duke@0 42
duke@0 43 #include "stdhdrs.h"
duke@0 44 #include "UnicowsLoader.h"
duke@0 45
duke@0 46 // {93F2F68C-1D1B-11d3-A30E-00C04F79ABD1}
duke@0 47 DEFINE_GUID(IID_IShellFolder2, 0x93f2f68c, 0x1d1b, 0x11d3, 0xa3, 0xe, 0x0, 0xc0, 0x4f, 0x79, 0xab, 0xd1);
duke@0 48
duke@0 49 #undef IID_IShellLinkW
duke@0 50 #undef IID_IExtractIconW
duke@0 51 // copied from shlguid.h
duke@0 52 DEFINE_SHLGUID(IID_IShellLinkW, 0x000214F9L, 0, 0);
duke@0 53 DEFINE_SHLGUID(IID_IExtractIconW, 0x000214FAL, 0, 0);
duke@0 54
duke@0 55 //#include <sun_awt_shell_Win32ShellFolder2.h>
duke@0 56
duke@0 57 // Shell Functions
duke@0 58 typedef BOOL (WINAPI *DestroyIconType)(HICON);
duke@0 59 typedef HINSTANCE (WINAPI *FindExecutableType)(LPCTSTR,LPCTSTR,LPTSTR);
duke@0 60 typedef HICON (WINAPI *ImageList_GetIconType)(HIMAGELIST,int,UINT);
duke@0 61 typedef BOOL (WINAPI *GetIconInfoType)(HICON,PICONINFO);
duke@0 62 typedef HRESULT (WINAPI *SHGetDesktopFolderType)(IShellFolder**);
duke@0 63 typedef DWORD* (WINAPI *SHGetFileInfoType)(LPCTSTR,DWORD,SHFILEINFO*,UINT,UINT);
duke@0 64 typedef HRESULT (WINAPI *SHGetMallocType)(IMalloc**);
duke@0 65 typedef BOOL (WINAPI *SHGetPathFromIDListType)(LPCITEMIDLIST,LPTSTR);
duke@0 66 typedef HRESULT (WINAPI *SHGetSpecialFolderLocationType)(HWND,int,LPITEMIDLIST*);
duke@0 67
duke@0 68 static DestroyIconType fn_DestroyIcon;
duke@0 69 static FindExecutableType fn_FindExecutable;
duke@0 70 static GetIconInfoType fn_GetIconInfo;
duke@0 71 static ImageList_GetIconType fn_ImageList_GetIcon;
duke@0 72 static SHGetDesktopFolderType fn_SHGetDesktopFolder;
duke@0 73 static SHGetFileInfoType fn_SHGetFileInfo;
duke@0 74 static SHGetMallocType fn_SHGetMalloc;
duke@0 75 static SHGetPathFromIDListType fn_SHGetPathFromIDList;
duke@0 76 static SHGetSpecialFolderLocationType fn_SHGetSpecialFolderLocation;
duke@0 77
duke@0 78 // Field IDs
duke@0 79 static jmethodID MID_pIShellFolder;
duke@0 80 static jfieldID FID_pIShellIcon;
duke@0 81 static jmethodID MID_relativePIDL;
duke@0 82 static jfieldID FID_displayName;
duke@0 83 static jfieldID FID_folderType;
duke@0 84
duke@0 85 // Other statics
duke@0 86 static IMalloc* pMalloc;
duke@0 87 static IShellFolder* pDesktop;
duke@0 88
duke@0 89 static BOOL isXP;
duke@0 90
duke@0 91 // copied from awt.h, because it is not included in release
duke@0 92 #if defined (WIN32)
duke@0 93 #define IS_WINVISTA (!(::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion())) >= 6)
duke@0 94 #else
duke@0 95 #define IS_WINVISTA FALSE
duke@0 96 #endif
duke@0 97
duke@0 98
duke@0 99 extern "C" {
duke@0 100
duke@0 101 static BOOL initShellProcs()
duke@0 102 {
duke@0 103 static HMODULE libShell32 = NULL;
duke@0 104 static HMODULE libUser32 = NULL;
duke@0 105 static HMODULE libComCtl32 = NULL;
duke@0 106 static HMODULE libUnicows = UnicowsLoader::GetModuleHandle();
duke@0 107 // If already initialized, return TRUE
duke@0 108 if (libShell32 != NULL && libUser32 != NULL) {
duke@0 109 return TRUE;
duke@0 110 }
duke@0 111 // Load libraries
duke@0 112 libShell32 = LoadLibrary(TEXT("shell32.dll"));
duke@0 113 if (libShell32 == NULL) {
duke@0 114 return FALSE;
duke@0 115 }
duke@0 116 libUser32 = LoadLibrary(TEXT("user32.dll"));
duke@0 117 if (libUser32 == NULL) {
duke@0 118 return FALSE;
duke@0 119 }
duke@0 120 libComCtl32 = LoadLibrary(TEXT("comctl32.dll"));
duke@0 121 if (libComCtl32 == NULL) {
duke@0 122 return FALSE;
duke@0 123 }
duke@0 124
duke@0 125 // Set up procs - libComCtl32
duke@0 126 fn_ImageList_GetIcon = (ImageList_GetIconType)GetProcAddress(libComCtl32, "ImageList_GetIcon");
duke@0 127 if (fn_ImageList_GetIcon == NULL) {
duke@0 128 return FALSE;
duke@0 129 }
duke@0 130
duke@0 131 // Set up procs - libShell32
duke@0 132 fn_FindExecutable = (FindExecutableType)GetProcAddress(
duke@0 133 (libUnicows ? libUnicows : libShell32), "FindExecutableW");
duke@0 134 if (fn_FindExecutable == NULL) {
duke@0 135 return FALSE;
duke@0 136 }
duke@0 137 fn_SHGetDesktopFolder = (SHGetDesktopFolderType)GetProcAddress(libShell32,
duke@0 138 "SHGetDesktopFolder");
duke@0 139 if (fn_SHGetDesktopFolder == NULL) {
duke@0 140 return FALSE;
duke@0 141 }
duke@0 142 fn_SHGetFileInfo = (SHGetFileInfoType)GetProcAddress(
duke@0 143 (libUnicows ? libUnicows : libShell32), "SHGetFileInfoW");
duke@0 144 if (fn_SHGetFileInfo == NULL) {
duke@0 145 return FALSE;
duke@0 146 }
duke@0 147 fn_SHGetMalloc = (SHGetMallocType)GetProcAddress(libShell32,
duke@0 148 "SHGetMalloc");
duke@0 149 if (fn_SHGetMalloc == NULL) {
duke@0 150 return FALSE;
duke@0 151 }
duke@0 152 // Set up IMalloc
duke@0 153 if (fn_SHGetMalloc(&pMalloc) != S_OK) {
duke@0 154 return FALSE;
duke@0 155 }
duke@0 156 fn_SHGetPathFromIDList = (SHGetPathFromIDListType)GetProcAddress(
duke@0 157 (libUnicows ? libUnicows : libShell32), "SHGetPathFromIDListW");
duke@0 158 if (fn_SHGetPathFromIDList == NULL) {
duke@0 159 return FALSE;
duke@0 160 }
duke@0 161 fn_SHGetSpecialFolderLocation = (SHGetSpecialFolderLocationType)
duke@0 162 GetProcAddress(libShell32, "SHGetSpecialFolderLocation");
duke@0 163 if (fn_SHGetSpecialFolderLocation == NULL) {
duke@0 164 return FALSE;
duke@0 165 }
duke@0 166
duke@0 167 // Set up procs - libUser32
duke@0 168 fn_GetIconInfo = (GetIconInfoType)GetProcAddress(libUser32, "GetIconInfo");
duke@0 169 if (fn_GetIconInfo == NULL) {
duke@0 170 return FALSE;
duke@0 171 }
duke@0 172 fn_DestroyIcon = (DestroyIconType)GetProcAddress(libUser32, "DestroyIcon");
duke@0 173 if (fn_DestroyIcon == NULL) {
duke@0 174 return FALSE;
duke@0 175 }
duke@0 176 return TRUE;
duke@0 177 }
duke@0 178
duke@0 179 // To call real JNU_NewStringPlatform
duke@0 180 #undef JNU_NewStringPlatform
duke@0 181 static jstring jstringFromSTRRET(JNIEnv* env, LPITEMIDLIST pidl, STRRET* pStrret) {
duke@0 182 switch (pStrret->uType) {
duke@0 183 case STRRET_CSTR :
duke@0 184 return JNU_NewStringPlatform(env, pStrret->cStr);
duke@0 185 case STRRET_OFFSET :
duke@0 186 // Note : this may need to be WCHAR instead
duke@0 187 return JNU_NewStringPlatform(env,
duke@0 188 (CHAR*)pidl + pStrret->uOffset);
duke@0 189 case STRRET_WSTR :
duke@0 190 return env->NewString(pStrret->pOleStr,
duke@0 191 static_cast<jsize>(wcslen(pStrret->pOleStr)));
duke@0 192 }
duke@0 193 return NULL;
duke@0 194 }
duke@0 195 // restoring the original definition
duke@0 196 #define JNU_NewStringPlatform(env, x) env->NewString(x, static_cast<jsize>(_tcslen(x)))
duke@0 197
duke@0 198 /*
duke@0 199 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 200 * Method: initIDs
duke@0 201 * Signature: ()V
duke@0 202 */
duke@0 203 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initIDs
duke@0 204 (JNIEnv* env, jclass cls)
duke@0 205 {
duke@0 206 if (!initShellProcs()) {
duke@0 207 JNU_ThrowInternalError(env, "Could not initialize shell library");
duke@0 208 return;
duke@0 209 }
duke@0 210 MID_pIShellFolder = env->GetMethodID(cls, "setIShellFolder", "(J)V");
duke@0 211 FID_pIShellIcon = env->GetFieldID(cls, "pIShellIcon", "J");
duke@0 212 MID_relativePIDL = env->GetMethodID(cls, "setRelativePIDL", "(J)V");
duke@0 213 FID_displayName = env->GetFieldID(cls, "displayName", "Ljava/lang/String;");
duke@0 214 FID_folderType = env->GetFieldID(cls, "folderType", "Ljava/lang/String;");
duke@0 215
duke@0 216 // Find out if we are on XP or later
duke@0 217 long version = GetVersion();
duke@0 218 isXP = (!(version & 0x80000000) &&
duke@0 219 (LOBYTE(LOWORD(version)) == 5 &&
duke@0 220 HIBYTE(LOWORD(version)) >= 1) ||
duke@0 221 LOBYTE(LOWORD(version)) > 5);
duke@0 222 }
duke@0 223
duke@0 224 static IShellIcon* getIShellIcon(IShellFolder* pIShellFolder) {
duke@0 225 // http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp
duke@0 226 HRESULT hres;
duke@0 227 HICON hIcon = NULL;
duke@0 228 IShellIcon* pIShellIcon;
duke@0 229 if (pIShellFolder != NULL) {
duke@0 230 hres = pIShellFolder->QueryInterface(IID_IShellIcon, (void**)&pIShellIcon);
duke@0 231 if (SUCCEEDED(hres)) {
duke@0 232 return pIShellIcon;
duke@0 233 }
duke@0 234 }
duke@0 235 return (IShellIcon*)NULL;
duke@0 236 }
duke@0 237
duke@0 238 // Fixed 6263669
duke@0 239 //
duke@0 240 // CoInitialize wrapper
duke@0 241 // call CoInitialize to initialize COM in STA mode and check result
duke@0 242 // RPC_E_CHANGED_MODE means COM has already been initialized in MTA mode,
duke@0 243 // so don't set the flag to call CoUninitialize later
duke@0 244
duke@0 245 BOOL CoInit(BOOL& doCoUninit) { // returns TRUE if initialized successfully
duke@0 246 switch(::CoInitialize(NULL)) {
duke@0 247 case S_OK:
duke@0 248 case S_FALSE:
duke@0 249 doCoUninit = TRUE;
duke@0 250 return TRUE;
duke@0 251 break;
duke@0 252 case RPC_E_CHANGED_MODE:
duke@0 253 doCoUninit = FALSE;
duke@0 254 return TRUE;
duke@0 255 break;
duke@0 256 default:
duke@0 257 return FALSE;
duke@0 258 }
duke@0 259 }
duke@0 260
duke@0 261
duke@0 262 /*
duke@0 263 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 264 * Method: getIShellIcon
duke@0 265 * Signature: (J)J
duke@0 266 */
duke@0 267 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIShellIcon
duke@0 268 (JNIEnv* env, jclass cls, jlong parentIShellFolder)
duke@0 269 {
duke@0 270 return (jlong)getIShellIcon((IShellFolder*)parentIShellFolder);
duke@0 271 }
duke@0 272
duke@0 273
duke@0 274 /*
duke@0 275 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 276 * Method: initDesktop
duke@0 277 * Signature: ()V
duke@0 278 */
duke@0 279 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initDesktop
duke@0 280 (JNIEnv* env, jobject desktop)
duke@0 281 {
duke@0 282 // Get desktop IShellFolder
duke@0 283 HRESULT res = fn_SHGetDesktopFolder(&pDesktop);
duke@0 284 if (res != S_OK) {
duke@0 285 JNU_ThrowInternalError(env, "Could not get desktop shell folder");
duke@0 286 return;
duke@0 287 }
duke@0 288 // Set field ID for pIShellFolder
duke@0 289 env->CallVoidMethod(desktop, MID_pIShellFolder, (jlong)pDesktop);
duke@0 290 // Get desktop relative PIDL
duke@0 291 LPITEMIDLIST relPIDL;
duke@0 292 res = fn_SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &relPIDL);
duke@0 293 if (res != S_OK) {
duke@0 294 JNU_ThrowInternalError(env,
duke@0 295 "Could not get desktop shell folder ID list");
duke@0 296 return;
duke@0 297 }
duke@0 298 // Set field ID for relative PIDL
duke@0 299 env->CallVoidMethod(desktop, MID_relativePIDL, (jlong)relPIDL);
duke@0 300 }
duke@0 301
duke@0 302 /*
duke@0 303 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 304 * Method: initSpecial
duke@0 305 * Signature: (JI)V
duke@0 306 */
duke@0 307 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initSpecial
duke@0 308 (JNIEnv* env, jobject folder, jlong desktopIShellFolder, jint folderType)
duke@0 309 {
duke@0 310 // Get desktop IShellFolder interface
duke@0 311 IShellFolder* pDesktop = (IShellFolder*)desktopIShellFolder;
duke@0 312 if (pDesktop == NULL) {
duke@0 313 JNU_ThrowInternalError(env, "Desktop shell folder missing");
duke@0 314 return;
duke@0 315 }
duke@0 316 // Get special folder relative PIDL
duke@0 317 LPITEMIDLIST relPIDL;
duke@0 318 HRESULT res = fn_SHGetSpecialFolderLocation(NULL, folderType,
duke@0 319 &relPIDL);
duke@0 320 if (res != S_OK) {
duke@0 321 JNU_ThrowIOException(env, "Could not get shell folder ID list");
duke@0 322 return;
duke@0 323 }
duke@0 324 // Set field ID for relative PIDL
duke@0 325 env->CallVoidMethod(folder, MID_relativePIDL, (jlong)relPIDL);
duke@0 326 // Get special folder IShellFolder interface
duke@0 327 IShellFolder* pFolder;
duke@0 328 res = pDesktop->BindToObject(relPIDL, NULL, IID_IShellFolder,
duke@0 329 (void**)&pFolder);
duke@0 330 if (res != S_OK) {
duke@0 331 JNU_ThrowInternalError(env,
duke@0 332 "Could not bind shell folder to interface");
duke@0 333 return;
duke@0 334 }
duke@0 335 // Set field ID for pIShellFolder
duke@0 336 env->CallVoidMethod(folder, MID_pIShellFolder, (jlong)pFolder);
duke@0 337 }
duke@0 338
duke@0 339
duke@0 340 /*
duke@0 341 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 342 * Method: getNextPIDLEntry
duke@0 343 * Signature: (J)J
duke@0 344 */
duke@0 345 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getNextPIDLEntry
duke@0 346 (JNIEnv* env, jclass cls, jlong jpIDL)
duke@0 347 {
duke@0 348 LPITEMIDLIST pIDL = (LPITEMIDLIST)jpIDL;
duke@0 349
duke@0 350 // Check for valid pIDL.
duke@0 351 if(pIDL == NULL)
duke@0 352 return NULL;
duke@0 353
duke@0 354 // Get the size of the specified item identifier.
duke@0 355 int cb = pIDL->mkid.cb;
duke@0 356
duke@0 357 // If the size is zero, it is the end of the list.
duke@0 358 if (cb == 0)
duke@0 359 return NULL;
duke@0 360
duke@0 361 // Add cb to pidl (casting to increment by bytes).
duke@0 362 pIDL = (LPITEMIDLIST)(((LPBYTE)pIDL) + cb);
duke@0 363
duke@0 364 // Return NULL if it is null-terminating, or a pidl otherwise.
duke@0 365 return (pIDL->mkid.cb == 0) ? 0 : (jlong)pIDL;
duke@0 366 }
duke@0 367
duke@0 368
duke@0 369 /*
duke@0 370 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 371 * Method: copyFirstPIDLEntry
duke@0 372 * Signature: (J)J
duke@0 373 */
duke@0 374 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_copyFirstPIDLEntry
duke@0 375 (JNIEnv* env, jclass cls, jlong jpIDL)
duke@0 376 {
duke@0 377 LPITEMIDLIST pIDL = (LPITEMIDLIST)jpIDL;
duke@0 378 if (pIDL == NULL) {
duke@0 379 return 0;
duke@0 380 }
duke@0 381 // Get the size of the specified item identifier.
duke@0 382 int cb = pIDL->mkid.cb;
duke@0 383
duke@0 384 // If the size is zero, it is the end of the list.
duke@0 385 if (cb == 0)
duke@0 386 return 0;
duke@0 387
duke@0 388 // Allocate space for this as well as null-terminating entry.
duke@0 389 LPITEMIDLIST newPIDL = (LPITEMIDLIST)pMalloc->Alloc(cb + sizeof(SHITEMID));
duke@0 390
duke@0 391 // Copy data.
duke@0 392 memcpy(newPIDL, pIDL, cb);
duke@0 393
duke@0 394 // Set null terminator for next entry.
duke@0 395 LPITEMIDLIST nextPIDL = (LPITEMIDLIST)(((LPBYTE)newPIDL) + cb);
duke@0 396 nextPIDL->mkid.cb = 0;
duke@0 397
duke@0 398 return (jlong)newPIDL;
duke@0 399 }
duke@0 400
duke@0 401 static int pidlLength(LPITEMIDLIST pIDL) {
duke@0 402 int len = 0;
duke@0 403 while (pIDL->mkid.cb != 0) {
duke@0 404 int cb = pIDL->mkid.cb;
duke@0 405 len += cb;
duke@0 406 pIDL = (LPITEMIDLIST)(((LPBYTE)pIDL) + cb);
duke@0 407 }
duke@0 408 return len;
duke@0 409 }
duke@0 410
duke@0 411 /*
duke@0 412 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 413 * Method: combinePIDLs
duke@0 414 * Signature: (J)J
duke@0 415 */
duke@0 416 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_combinePIDLs
duke@0 417 (JNIEnv* env, jclass cls, jlong jppIDL, jlong jpIDL)
duke@0 418 {
duke@0 419 // Combine an absolute (fully qualified) pidl in a parent with the relative
duke@0 420 // pidl of a child object to create a new absolute pidl for the child.
duke@0 421
duke@0 422 LPITEMIDLIST parentPIDL = (LPITEMIDLIST)jppIDL;
duke@0 423 LPITEMIDLIST relativePIDL = (LPITEMIDLIST)jpIDL;
duke@0 424
duke@0 425 int len1 = pidlLength(parentPIDL);
duke@0 426 int len2 = pidlLength(relativePIDL);
duke@0 427
duke@0 428 LPITEMIDLIST newPIDL = (LPITEMIDLIST)pMalloc->Alloc(len1 + len2 + sizeof(SHITEMID));
duke@0 429 memcpy(newPIDL, parentPIDL, len1);
duke@0 430 memcpy(((LPBYTE) newPIDL) + len1, relativePIDL, len2);
duke@0 431 LPITEMIDLIST nullTerminator = (LPITEMIDLIST)(((LPBYTE) newPIDL) + len1 + len2);
duke@0 432 nullTerminator->mkid.cb = 0;
duke@0 433
duke@0 434 return (jlong) newPIDL;
duke@0 435 }
duke@0 436
duke@0 437
duke@0 438 /*
duke@0 439 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 440 * Method: releasePIDL
duke@0 441 * Signature: (J)V
duke@0 442 */
duke@0 443 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_releasePIDL
duke@0 444 (JNIEnv* env, jclass cls, jlong pIDL)
duke@0 445 {
duke@0 446 if (pIDL != 0L) {
duke@0 447 pMalloc->Free((LPITEMIDLIST)pIDL);
duke@0 448 }
duke@0 449 }
duke@0 450
duke@0 451
duke@0 452 /*
duke@0 453 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 454 * Method: releaseIShellFolder
duke@0 455 * Signature: (J)V
duke@0 456 */
duke@0 457 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_releaseIShellFolder
duke@0 458 (JNIEnv* env, jclass cls, jlong pIShellFolder)
duke@0 459 {
duke@0 460 if (pIShellFolder != 0L) {
duke@0 461 ((IShellFolder*)pIShellFolder)->Release();
duke@0 462 }
duke@0 463 }
duke@0 464
duke@0 465
duke@0 466 /*
duke@0 467 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 468 * Method: compareIDs
duke@0 469 * Signature: (JJJ)I
duke@0 470 */
duke@0 471 JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_compareIDs
duke@0 472 (JNIEnv* env, jclass cls, jlong jpParentIShellFolder, jlong pIDL1, jlong pIDL2)
duke@0 473 {
duke@0 474 IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder;
duke@0 475 if (pParentIShellFolder == NULL) {
duke@0 476 return 0;
duke@0 477 }
duke@0 478 return pParentIShellFolder->CompareIDs(0, (LPCITEMIDLIST) pIDL1, (LPCITEMIDLIST) pIDL2);
duke@0 479 }
duke@0 480
duke@0 481
duke@0 482 /*
duke@0 483 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 484 * Method: getAttributes0
duke@0 485 * Signature: (JJI)J
duke@0 486 */
duke@0 487 JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getAttributes0
duke@0 488 (JNIEnv* env, jclass cls, jlong jpParentIShellFolder, jlong jpIDL, jint attrsMask)
duke@0 489 {
duke@0 490 IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder;
duke@0 491 if (pParentIShellFolder == NULL) {
duke@0 492 return 0;
duke@0 493 }
duke@0 494 LPCITEMIDLIST pIDL = (LPCITEMIDLIST)jpIDL;
duke@0 495 if (pIDL == NULL) {
duke@0 496 return 0;
duke@0 497 }
duke@0 498 ULONG attrs = attrsMask;
duke@0 499 HRESULT res = pParentIShellFolder->GetAttributesOf(1, &pIDL, &attrs);
duke@0 500 return attrs;
duke@0 501 }
duke@0 502
duke@0 503
duke@0 504 /*
duke@0 505 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 506 * Method: getFileSystemPath
duke@0 507 * Signature: (I)Ljava/lang/String;
duke@0 508 */
duke@0 509 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileSystemPath__I
duke@0 510 (JNIEnv* env, jclass cls, jint csidl)
duke@0 511 {
duke@0 512 LPITEMIDLIST relPIDL;
duke@0 513 TCHAR szBuf[MAX_PATH];
duke@0 514 HRESULT res = fn_SHGetSpecialFolderLocation(NULL, csidl, &relPIDL);
duke@0 515 if (res != S_OK) {
duke@0 516 JNU_ThrowIOException(env, "Could not get shell folder ID list");
duke@0 517 return NULL;
duke@0 518 }
duke@0 519 if (fn_SHGetPathFromIDList(relPIDL, szBuf)) {
duke@0 520 return JNU_NewStringPlatform(env, szBuf);
duke@0 521 } else {
duke@0 522 return NULL;
duke@0 523 }
duke@0 524 }
duke@0 525
duke@0 526 /*
duke@0 527 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 528 * Method: getEnumObjects
duke@0 529 * Signature: (JZ)J
duke@0 530 */
duke@0 531 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getEnumObjects
duke@0 532 (JNIEnv* env, jobject folder, jlong pIShellFolder,
duke@0 533 jboolean isDesktop, jboolean includeHiddenFiles)
duke@0 534 {
duke@0 535 IShellFolder* pFolder = (IShellFolder*)pIShellFolder;
duke@0 536 if (pFolder == NULL) {
duke@0 537 return 0;
duke@0 538 }
duke@0 539 DWORD dwFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
duke@0 540 if (includeHiddenFiles) {
duke@0 541 dwFlags |= SHCONTF_INCLUDEHIDDEN;
duke@0 542 }
duke@0 543 /*
duke@0 544 if (!isDesktop) {
duke@0 545 dwFlags = dwFlags | SHCONTF_NONFOLDERS;
duke@0 546 }
duke@0 547 */
duke@0 548 IEnumIDList* pEnum;
duke@0 549 if (pFolder->EnumObjects(NULL, dwFlags, &pEnum) != S_OK) {
duke@0 550 return 0;
duke@0 551 }
duke@0 552 return (jlong)pEnum;
duke@0 553 }
duke@0 554
duke@0 555 /*
duke@0 556 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 557 * Method: getNextChild
duke@0 558 * Signature: (J)J
duke@0 559 */
duke@0 560 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getNextChild
duke@0 561 (JNIEnv* env, jobject folder, jlong pEnumObjects)
duke@0 562 {
duke@0 563 IEnumIDList* pEnum = (IEnumIDList*)pEnumObjects;
duke@0 564 if (pEnum == NULL) {
duke@0 565 return 0;
duke@0 566 }
duke@0 567 LPITEMIDLIST pidl;
duke@0 568 if (pEnum->Next(1, &pidl, NULL) != S_OK) {
duke@0 569 return 0;
duke@0 570 }
duke@0 571 return (jlong)pidl;
duke@0 572 }
duke@0 573
duke@0 574 /*
duke@0 575 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 576 * Method: releaseEnumObjects
duke@0 577 * Signature: (J)V
duke@0 578 */
duke@0 579 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_releaseEnumObjects
duke@0 580 (JNIEnv* env, jobject folder, jlong pEnumObjects)
duke@0 581 {
duke@0 582 IEnumIDList* pEnum = (IEnumIDList*)pEnumObjects;
duke@0 583 if (pEnum == NULL) {
duke@0 584 return;
duke@0 585 }
duke@0 586 pEnum->Release();
duke@0 587 }
duke@0 588
duke@0 589 /*
duke@0 590 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 591 * Method: bindToObject
duke@0 592 * Signature: (JJ)J
duke@0 593 */
duke@0 594 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_bindToObject
duke@0 595 (JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL)
duke@0 596 {
duke@0 597 IShellFolder* pParent = (IShellFolder*)parentIShellFolder;
duke@0 598 if (pParent == NULL) {
duke@0 599 return 0;
duke@0 600 }
duke@0 601 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
duke@0 602 if (pidl == NULL) {
duke@0 603 return 0;
duke@0 604 }
duke@0 605 IShellFolder* pFolder;
duke@0 606 HRESULT hr = pParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&pFolder);
duke@0 607 if (SUCCEEDED (hr)) {
duke@0 608 return (jlong)pFolder;
duke@0 609 }
duke@0 610 if (IS_WINVISTA) {
duke@0 611 BOOL doCoUninit;
duke@0 612 if (CoInit(doCoUninit)) {
duke@0 613 hr = pParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&pFolder);
duke@0 614 if (doCoUninit) {
duke@0 615 ::CoUninitialize();
duke@0 616 }
duke@0 617 if (SUCCEEDED (hr)) {
duke@0 618 return (jlong)pFolder;
duke@0 619 }
duke@0 620 }
duke@0 621 }
duke@0 622 return 0;
duke@0 623 }
duke@0 624
duke@0 625
duke@0 626 /*
duke@0 627 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 628 * Method: getLinkLocation
duke@0 629 * Signature: (JJZ)J;
duke@0 630 */
duke@0 631 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getLinkLocation
duke@0 632 (JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL, jboolean resolve)
duke@0 633 {
duke@0 634 HRESULT hres;
duke@0 635 STRRET strret;
duke@0 636 OLECHAR olePath[MAX_PATH]; // wide-char version of path name
duke@0 637 LPWSTR wstr;
duke@0 638
duke@0 639 IShellFolder* pParent = (IShellFolder*)parentIShellFolder;
duke@0 640 if (pParent == NULL) {
duke@0 641 return NULL;
duke@0 642 }
duke@0 643
duke@0 644 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
duke@0 645 if (pidl == NULL) {
duke@0 646 return NULL;
duke@0 647 }
duke@0 648
duke@0 649 pParent->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_FORPARSING, &strret);
duke@0 650
duke@0 651 switch (strret.uType) {
duke@0 652 case STRRET_CSTR :
duke@0 653 // IShellFolder::ParseDisplayName requires the path name in Unicode.
duke@0 654 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, strret.cStr, -1, olePath, MAX_PATH);
duke@0 655 wstr = olePath;
duke@0 656 break;
duke@0 657
duke@0 658 case STRRET_OFFSET :
duke@0 659 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (CHAR *)pidl + strret.uOffset, -1, olePath, MAX_PATH);
duke@0 660 wstr = olePath;
duke@0 661 break;
duke@0 662
duke@0 663 case STRRET_WSTR :
duke@0 664 wstr = strret.pOleStr;
duke@0 665 break;
duke@0 666 }
duke@0 667
duke@0 668 BOOL doCoUninit;
duke@0 669 if (!CoInit(doCoUninit)) {
duke@0 670 return 0;
duke@0 671 }
duke@0 672 if (IS_NT) {
duke@0 673 IShellLinkW* psl;
duke@0 674 hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&psl);
duke@0 675 if (SUCCEEDED(hres)) {
duke@0 676 IPersistFile* ppf;
duke@0 677 hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
duke@0 678 if (SUCCEEDED(hres)) {
duke@0 679 hres = ppf->Load(wstr, STGM_READ);
duke@0 680 if (SUCCEEDED(hres)) {
duke@0 681 if (resolve) {
duke@0 682 hres = psl->Resolve(NULL, 0);
duke@0 683 // Ignore failure
duke@0 684 }
duke@0 685 pidl = (LPITEMIDLIST)NULL;
duke@0 686 hres = psl->GetIDList(&pidl);
duke@0 687 }
duke@0 688 ppf->Release();
duke@0 689 }
duke@0 690 psl->Release();
duke@0 691 }
duke@0 692 } else {
duke@0 693 IShellLinkA* psl;
duke@0 694 hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkA, (LPVOID *)&psl);
duke@0 695 if (SUCCEEDED(hres)) {
duke@0 696 IPersistFile* ppf;
duke@0 697 hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
duke@0 698 if (SUCCEEDED(hres)) {
duke@0 699 hres = ppf->Load(wstr, STGM_READ);
duke@0 700 if (SUCCEEDED(hres)) {
duke@0 701 if (resolve) {
duke@0 702 hres = psl->Resolve(NULL, 0);
duke@0 703 // Ignore failure
duke@0 704 }
duke@0 705 pidl = (LPITEMIDLIST)NULL;
duke@0 706 hres = psl->GetIDList(&pidl);
duke@0 707 }
duke@0 708 ppf->Release();
duke@0 709 }
duke@0 710 psl->Release();
duke@0 711 }
duke@0 712 }
duke@0 713 if (doCoUninit) {
duke@0 714 ::CoUninitialize();
duke@0 715 }
duke@0 716
duke@0 717 if (SUCCEEDED(hres)) {
duke@0 718 return (jlong)pidl;
duke@0 719 } else {
duke@0 720 return 0;
duke@0 721 }
duke@0 722 }
duke@0 723
duke@0 724
duke@0 725 /*
duke@0 726 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 727 * Method: parseDisplayName0
duke@0 728 * Signature: (JLjava/lang/String;)J
duke@0 729 */
duke@0 730 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_parseDisplayName0
duke@0 731 (JNIEnv* env, jclass cls, jlong jpIShellFolder, jstring jname)
duke@0 732 {
duke@0 733
duke@0 734 // Get desktop IShellFolder interface
duke@0 735 IShellFolder* pIShellFolder = (IShellFolder*)jpIShellFolder;
duke@0 736 if (pIShellFolder == NULL) {
duke@0 737 JNU_ThrowInternalError(env, "Desktop shell folder missing");
duke@0 738 return 0;
duke@0 739 }
duke@0 740 // Get relative PIDL for name
duke@0 741 LPITEMIDLIST pIDL;
duke@0 742 int nLength = env->GetStringLength(jname);
duke@0 743 jchar* wszPath = new jchar[nLength + 1];
duke@0 744 const jchar* strPath = env->GetStringChars(jname, NULL);
duke@0 745 wcsncpy(wszPath, strPath, nLength);
duke@0 746 wszPath[nLength] = 0;
duke@0 747 HRESULT res = pIShellFolder->ParseDisplayName(NULL, NULL,
duke@0 748 const_cast<jchar*>(wszPath), NULL, &pIDL, NULL);
duke@0 749 if (res != S_OK) {
duke@0 750 JNU_ThrowIOException(env, "Could not parse name");
duke@0 751 pIDL = 0;
duke@0 752 }
duke@0 753 delete[] wszPath;
duke@0 754 env->ReleaseStringChars(jname, strPath);
duke@0 755 return (jlong)pIDL;
duke@0 756 }
duke@0 757
duke@0 758
duke@0 759 /*
duke@0 760 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 761 * Method: getDisplayNameOf
duke@0 762 * Signature: (JJ)Ljava/lang/String;
duke@0 763 */
duke@0 764 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getDisplayNameOf
duke@0 765 (JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL, jint attrs)
duke@0 766 {
duke@0 767 IShellFolder* pParent = (IShellFolder*)parentIShellFolder;
duke@0 768 if (pParent == NULL) {
duke@0 769 return NULL;
duke@0 770 }
duke@0 771 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
duke@0 772 if (pidl == NULL) {
duke@0 773 return NULL;
duke@0 774 }
duke@0 775 STRRET strret;
duke@0 776 if (pParent->GetDisplayNameOf(pidl, attrs, &strret) != S_OK) {
duke@0 777 return NULL;
duke@0 778 }
duke@0 779 return jstringFromSTRRET(env, pidl, &strret);
duke@0 780 }
duke@0 781
duke@0 782 /*
duke@0 783 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 784 * Method: getFolderType
duke@0 785 * Signature: (J)Ljava/lang/String;
duke@0 786 */
duke@0 787 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFolderType
duke@0 788 (JNIEnv* env, jclass cls, jlong pIDL)
duke@0 789 {
duke@0 790 SHFILEINFO fileInfo;
duke@0 791 if (fn_SHGetFileInfo((LPCTSTR)pIDL, 0L, &fileInfo, sizeof(fileInfo),
duke@0 792 SHGFI_TYPENAME | SHGFI_PIDL) == 0) {
duke@0 793 return NULL;
duke@0 794 }
duke@0 795 return JNU_NewStringPlatform(env, fileInfo.szTypeName);
duke@0 796 }
duke@0 797
duke@0 798 /*
duke@0 799 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 800 * Method: getExecutableType
duke@0 801 * Signature: (Ljava/lang/String;)Ljava/lang/String;
duke@0 802 */
duke@0 803 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getExecutableType
duke@0 804 (JNIEnv* env, jobject folder, jstring path)
duke@0 805 {
duke@0 806 TCHAR szBuf[MAX_PATH];
duke@0 807 LPCTSTR szPath = (LPCTSTR)JNU_GetStringPlatformChars(env, path, NULL);
duke@0 808 if (szPath == NULL) {
duke@0 809 return NULL;
duke@0 810 }
duke@0 811 HINSTANCE res = fn_FindExecutable(szPath, szPath, szBuf);
duke@0 812 JNU_ReleaseStringPlatformChars(env, path, szPath);
duke@0 813 if ((UINT_PTR)res < 32) {
duke@0 814 return NULL;
duke@0 815 }
duke@0 816 return JNU_NewStringPlatform(env, szBuf);
duke@0 817 }
duke@0 818
duke@0 819
duke@0 820 /*
duke@0 821 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 822 * Method: getIcon
duke@0 823 * Signature: (Ljava/lang/String;Z)J
duke@0 824 */
duke@0 825 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIcon
duke@0 826 (JNIEnv* env, jclass cls, jstring absolutePath, jboolean getLargeIcon)
duke@0 827 {
duke@0 828 HICON hIcon = NULL;
duke@0 829 SHFILEINFO fileInfo;
duke@0 830 LPCTSTR pathStr = (LPCTSTR)JNU_GetStringPlatformChars(env, absolutePath, NULL);
duke@0 831 if (fn_SHGetFileInfo(pathStr, 0L, &fileInfo, sizeof(fileInfo),
duke@0 832 SHGFI_ICON | (getLargeIcon ? 0 : SHGFI_SMALLICON)) != 0) {
duke@0 833 hIcon = fileInfo.hIcon;
duke@0 834 }
duke@0 835 JNU_ReleaseStringPlatformChars(env, absolutePath, pathStr);
duke@0 836 return (jlong)hIcon;
duke@0 837 }
duke@0 838
duke@0 839 /*
duke@0 840 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 841 * Method: getIconIndex
duke@0 842 * Signature: (JJ)I
duke@0 843 */
duke@0 844 JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconIndex
duke@0 845 (JNIEnv* env, jclass cls, jlong pIShellIconL, jlong relativePIDL)
duke@0 846 {
duke@0 847 IShellIcon* pIShellIcon = (IShellIcon*)pIShellIconL;
duke@0 848 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
duke@0 849 if (pIShellIcon == NULL && pidl == NULL) {
duke@0 850 return 0;
duke@0 851 }
duke@0 852
duke@0 853 INT index = -1;
duke@0 854 BOOL doCoUninit;
duke@0 855 if (!CoInit(doCoUninit)) {
duke@0 856 return (jint)index;
duke@0 857 }
duke@0 858
duke@0 859 HRESULT hres;
duke@0 860 // http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp
duke@0 861 if (pIShellIcon != NULL) {
duke@0 862 hres = pIShellIcon->GetIconOf(pidl, GIL_FORSHELL, &index);
duke@0 863 }
duke@0 864
duke@0 865 if (doCoUninit) {
duke@0 866 ::CoUninitialize();
duke@0 867 }
duke@0 868 return (jint)index;
duke@0 869 }
duke@0 870
duke@0 871
duke@0 872 /*
duke@0 873 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 874 * Method: extractIcon
duke@0 875 * Signature: (JJZ)J
duke@0 876 */
duke@0 877 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_extractIcon
duke@0 878 (JNIEnv* env, jclass cls, jlong pIShellFolderL, jlong relativePIDL, jboolean getLargeIcon)
duke@0 879 {
duke@0 880 IShellFolder* pIShellFolder = (IShellFolder*)pIShellFolderL;
duke@0 881 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
duke@0 882 if (pIShellFolder == NULL || pidl == NULL) {
duke@0 883 return 0;
duke@0 884 }
duke@0 885
duke@0 886 HICON hIcon = NULL;
duke@0 887 BOOL doCoUninit;
duke@0 888 if (!CoInit(doCoUninit)) {
duke@0 889 return (jlong)hIcon;
duke@0 890 }
duke@0 891
duke@0 892 HRESULT hres;
duke@0 893 if (IS_NT) {
duke@0 894 IExtractIconW* pIcon;
duke@0 895 hres = pIShellFolder->GetUIObjectOf(NULL, 1, const_cast<LPCITEMIDLIST*>(&pidl),
duke@0 896 IID_IExtractIconW, NULL, (void**)&pIcon);
duke@0 897 if (SUCCEEDED(hres)) {
duke@0 898 WCHAR szBuf[MAX_PATH];
duke@0 899 INT index;
duke@0 900 UINT flags;
duke@0 901 hres = pIcon->GetIconLocation(GIL_FORSHELL, szBuf, MAX_PATH, &index, &flags);
duke@0 902 if (SUCCEEDED(hres)) {
duke@0 903 HICON hIconLarge;
duke@0 904 hres = pIcon->Extract(szBuf, index, &hIconLarge, &hIcon, (16 << 16) + 32);
duke@0 905 if (SUCCEEDED(hres)) {
duke@0 906 if (getLargeIcon) {
duke@0 907 fn_DestroyIcon((HICON)hIcon);
duke@0 908 hIcon = hIconLarge;
duke@0 909 } else {
duke@0 910 fn_DestroyIcon((HICON)hIconLarge);
duke@0 911 }
duke@0 912 }
duke@0 913 }
duke@0 914 pIcon->Release();
duke@0 915 }
duke@0 916 } else {
duke@0 917 IExtractIconA* pIcon;
duke@0 918 hres = pIShellFolder->GetUIObjectOf(NULL, 1, const_cast<LPCITEMIDLIST*>(&pidl),
duke@0 919 IID_IExtractIconA, NULL, (void**)&pIcon);
duke@0 920 if (SUCCEEDED(hres)) {
duke@0 921 CHAR szBuf[MAX_PATH];
duke@0 922 INT index;
duke@0 923 UINT flags;
duke@0 924 hres = pIcon->GetIconLocation(GIL_FORSHELL, szBuf, MAX_PATH, &index, &flags);
duke@0 925 if (SUCCEEDED(hres)) {
duke@0 926 HICON hIconLarge;
duke@0 927 hres = pIcon->Extract(szBuf, index, &hIconLarge, &hIcon, (16 << 16) + 32);
duke@0 928 if (SUCCEEDED(hres)) {
duke@0 929 if (getLargeIcon) {
duke@0 930 fn_DestroyIcon((HICON)hIcon);
duke@0 931 hIcon = hIconLarge;
duke@0 932 } else {
duke@0 933 fn_DestroyIcon((HICON)hIconLarge);
duke@0 934 }
duke@0 935 }
duke@0 936 }
duke@0 937 pIcon->Release();
duke@0 938 }
duke@0 939 }
duke@0 940 if (doCoUninit) {
duke@0 941 ::CoUninitialize();
duke@0 942 }
duke@0 943 return (jlong)hIcon;
duke@0 944 }
duke@0 945
duke@0 946
duke@0 947 /*
duke@0 948 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 949 * Method: disposeIcon
duke@0 950 * Signature: (J)V
duke@0 951 */
duke@0 952 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_disposeIcon
duke@0 953 (JNIEnv* env, jclass cls, jlong hicon)
duke@0 954 {
duke@0 955 fn_DestroyIcon((HICON)hicon);
duke@0 956 }
duke@0 957
duke@0 958 /*
duke@0 959 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 960 * Method: getIconBits
duke@0 961 * Signature: (JI)[I
duke@0 962 */
duke@0 963 JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconBits
duke@0 964 (JNIEnv* env, jclass cls, jlong hicon, jint iconSize)
duke@0 965 {
duke@0 966 jintArray iconBits = NULL;
duke@0 967
duke@0 968 // Get the icon info
duke@0 969 ICONINFO iconInfo;
duke@0 970 if (fn_GetIconInfo((HICON)hicon, &iconInfo)) {
duke@0 971 // Get the screen DC
duke@0 972 HDC dc = GetDC(NULL);
duke@0 973 if (dc != NULL) {
duke@0 974 // Set up BITMAPINFO
duke@0 975 BITMAPINFO bmi;
duke@0 976 memset(&bmi, 0, sizeof(BITMAPINFO));
duke@0 977 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
duke@0 978 bmi.bmiHeader.biWidth = iconSize;
duke@0 979 bmi.bmiHeader.biHeight = -iconSize;
duke@0 980 bmi.bmiHeader.biPlanes = 1;
duke@0 981 bmi.bmiHeader.biBitCount = 32;
duke@0 982 bmi.bmiHeader.biCompression = BI_RGB;
duke@0 983 // Extract the color bitmap
duke@0 984 int nBits = iconSize * iconSize;
duke@0 985 long colorBits[1024];
duke@0 986 GetDIBits(dc, iconInfo.hbmColor, 0, iconSize, colorBits, &bmi, DIB_RGB_COLORS);
duke@0 987 // XP supports alpha in some icons, and depending on device.
duke@0 988 // This should take precedence over the icon mask bits.
duke@0 989 BOOL hasAlpha = FALSE;
duke@0 990 if (isXP) {
duke@0 991 for (int i = 0; i < nBits; i++) {
duke@0 992 if ((colorBits[i] & 0xff000000) != 0) {
duke@0 993 hasAlpha = TRUE;
duke@0 994 break;
duke@0 995 }
duke@0 996 }
duke@0 997 }
duke@0 998 if (!hasAlpha) {
duke@0 999 // Extract the mask bitmap
duke@0 1000 long maskBits[1024];
duke@0 1001 GetDIBits(dc, iconInfo.hbmMask, 0, iconSize, maskBits, &bmi, DIB_RGB_COLORS);
duke@0 1002 // Copy the mask alphas into the color bits
duke@0 1003 for (int i = 0; i < nBits; i++) {
duke@0 1004 if (maskBits[i] == 0) {
duke@0 1005 colorBits[i] |= 0xff000000;
duke@0 1006 }
duke@0 1007 }
duke@0 1008 }
duke@0 1009 // Release DC
duke@0 1010 ReleaseDC(NULL, dc);
duke@0 1011 // Create java array
duke@0 1012 iconBits = env->NewIntArray(nBits);
duke@0 1013 // Copy values to java array
duke@0 1014 env->SetIntArrayRegion(iconBits, 0, nBits, colorBits);
duke@0 1015 }
duke@0 1016 // Fix 4745575 GDI Resource Leak
duke@0 1017 // MSDN
duke@0 1018 // GetIconInfo creates bitmaps for the hbmMask and hbmColor members of ICONINFO.
duke@0 1019 // The calling application must manage these bitmaps and delete them when they
duke@0 1020 // are no longer necessary.
duke@0 1021 ::DeleteObject(iconInfo.hbmColor);
duke@0 1022 ::DeleteObject(iconInfo.hbmMask);
duke@0 1023 }
duke@0 1024 return iconBits;
duke@0 1025 }
duke@0 1026
duke@0 1027 /*
duke@0 1028 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 1029 * Method: getFileChooserBitmapBits
duke@0 1030 * Signature: ()[I
duke@0 1031 */
duke@0 1032 JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileChooserBitmapBits
duke@0 1033 (JNIEnv* env, jclass cls)
duke@0 1034 {
duke@0 1035 HBITMAP hBitmap = NULL;
duke@0 1036 BITMAP bm;
duke@0 1037 HINSTANCE libComCtl32;
duke@0 1038 HINSTANCE libShell32;
duke@0 1039
duke@0 1040
duke@0 1041 libShell32 = LoadLibrary(TEXT("shell32.dll"));
duke@0 1042 if (libShell32 != NULL) {
duke@0 1043 long osVersion = GetVersion();
duke@0 1044 BOOL isVista = (!(osVersion & 0x80000000) && (LOBYTE(LOWORD(osVersion)) >= 6));
duke@0 1045
duke@0 1046 hBitmap = (HBITMAP)LoadImage(libShell32,
duke@0 1047 isVista ? TEXT("IDB_TB_SH_DEF_16") : MAKEINTRESOURCE(216),
duke@0 1048 IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
duke@0 1049 }
duke@0 1050 if (hBitmap == NULL) {
duke@0 1051 libComCtl32 = LoadLibrary(TEXT("comctl32.dll"));
duke@0 1052 if (libComCtl32 != NULL) {
duke@0 1053 hBitmap = (HBITMAP)LoadImage(libComCtl32, MAKEINTRESOURCE(124),
duke@0 1054 IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
duke@0 1055 }
duke@0 1056 }
duke@0 1057 if (hBitmap == NULL) {
duke@0 1058 return NULL;
duke@0 1059 }
duke@0 1060
duke@0 1061 GetObject(hBitmap, sizeof(bm), (LPSTR)&bm);
duke@0 1062
duke@0 1063 // Get the screen DC
duke@0 1064 HDC dc = GetDC(NULL);
duke@0 1065 if (dc == NULL) {
duke@0 1066 return NULL;
duke@0 1067 }
duke@0 1068
duke@0 1069 // Set up BITMAPINFO
duke@0 1070 BITMAPINFO bmi;
duke@0 1071 memset(&bmi, 0, sizeof(BITMAPINFO));
duke@0 1072 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
duke@0 1073 bmi.bmiHeader.biWidth = bm.bmWidth;
duke@0 1074 bmi.bmiHeader.biHeight = -bm.bmHeight;
duke@0 1075 bmi.bmiHeader.biPlanes = 1;
duke@0 1076 bmi.bmiHeader.biBitCount = 32;
duke@0 1077 bmi.bmiHeader.biCompression = BI_RGB;
duke@0 1078 // Extract the color bitmap
duke@0 1079 int numPixels = bm.bmWidth * bm.bmHeight;
duke@0 1080 //long colorBits[192 * 16];
duke@0 1081 long *colorBits = (long*)safe_Malloc(numPixels * sizeof(long));
duke@0 1082 if (GetDIBits(dc, hBitmap, 0, bm.bmHeight, colorBits, &bmi, DIB_RGB_COLORS) == 0) {
duke@0 1083 return NULL;
duke@0 1084 }
duke@0 1085
duke@0 1086 // Release DC
duke@0 1087 ReleaseDC(NULL, dc);
duke@0 1088
duke@0 1089 // The color of the first pixel defines the transparency, according
duke@0 1090 // to the documentation for LR_LOADTRANSPARENT at
duke@0 1091 // http://msdn.microsoft.com/library/psdk/winui/resource_9fhi.htm
duke@0 1092 long transparent = colorBits[0];
duke@0 1093 for (int i=0; i < numPixels; i++) {
duke@0 1094 if (colorBits[i] != transparent) {
duke@0 1095 colorBits[i] |= 0xff000000;
duke@0 1096 }
duke@0 1097 }
duke@0 1098
duke@0 1099 // Create java array
duke@0 1100 jintArray bits = env->NewIntArray(numPixels);
duke@0 1101 // Copy values to java array
duke@0 1102 env->SetIntArrayRegion(bits, 0, numPixels, colorBits);
duke@0 1103 // Fix 4745575 GDI Resource Leak
duke@0 1104 ::DeleteObject(hBitmap);
duke@0 1105 ::FreeLibrary(libComCtl32);
duke@0 1106 return bits;
duke@0 1107 }
duke@0 1108
duke@0 1109 /*
duke@0 1110 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 1111 * Method: getSystemIcon
duke@0 1112 * Signature: (I)J
duke@0 1113 */
duke@0 1114 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getSystemIcon
duke@0 1115 (JNIEnv* env, jclass cls, jint iconID)
duke@0 1116 {
duke@0 1117 return (jlong)LoadIcon(NULL, MAKEINTRESOURCE(iconID));
duke@0 1118 }
duke@0 1119
duke@0 1120
duke@0 1121 /*
duke@0 1122 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 1123 * Method: getIconResource
duke@0 1124 * Signature: (Ljava/lang/String;IIIZ)J
duke@0 1125 */
duke@0 1126 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconResource
duke@0 1127 (JNIEnv* env, jclass cls, jstring libName, jint iconID,
duke@0 1128 jint cxDesired, jint cyDesired, jboolean useVGAColors)
duke@0 1129 {
duke@0 1130 HINSTANCE libHandle = LoadLibrary(env->GetStringChars(libName, NULL));
duke@0 1131 if (libHandle != NULL) {
duke@0 1132 UINT fuLoad = (useVGAColors && !isXP) ? LR_VGACOLOR : 0;
duke@0 1133 return ptr_to_jlong(LoadImage(libHandle, MAKEINTRESOURCE(iconID),
duke@0 1134 IMAGE_ICON, cxDesired, cyDesired,
duke@0 1135 fuLoad));
duke@0 1136 }
duke@0 1137 return 0;
duke@0 1138 }
duke@0 1139
duke@0 1140
duke@0 1141 // Helper functions for workaround COM initialization:
duke@0 1142
duke@0 1143 static HRESULT GetDetailsOfFolder(
duke@0 1144 IShellFolder2 *folder,
duke@0 1145 LPCITEMIDLIST pidl,
duke@0 1146 UINT column,
duke@0 1147 SHELLDETAILS *psd)
duke@0 1148 {
duke@0 1149 HRESULT hr = folder->GetDetailsOf(pidl, column, psd);
duke@0 1150 if (IS_WINVISTA && FAILED (hr)) {
duke@0 1151 BOOL doCoUninit;
duke@0 1152 if (CoInit(doCoUninit)) {
duke@0 1153 hr = folder->GetDetailsOf(pidl, column, psd);
duke@0 1154 if (doCoUninit) {
duke@0 1155 ::CoUninitialize();
duke@0 1156 }
duke@0 1157 }
duke@0 1158 }
duke@0 1159 return hr;
duke@0 1160 }
duke@0 1161
duke@0 1162 static HRESULT GetDetailsOf(
duke@0 1163 IShellDetails *details,
duke@0 1164 LPCITEMIDLIST pidl,
duke@0 1165 UINT column,
duke@0 1166 SHELLDETAILS *psd)
duke@0 1167 {
duke@0 1168 HRESULT hr = details->GetDetailsOf(pidl, column, psd);
duke@0 1169 if (IS_WINVISTA && FAILED (hr)) {
duke@0 1170 BOOL doCoUninit;
duke@0 1171 if (CoInit(doCoUninit)) {
duke@0 1172 hr = details->GetDetailsOf(pidl, column, psd);
duke@0 1173 if (doCoUninit) {
duke@0 1174 ::CoUninitialize();
duke@0 1175 }
duke@0 1176 }
duke@0 1177 }
duke@0 1178 return hr;
duke@0 1179 }
duke@0 1180
duke@0 1181 /*
duke@0 1182 * Helper function for creating Java column info object
duke@0 1183 */
duke@0 1184 static jobject CreateColumnInfo(JNIEnv *pEnv,
duke@0 1185 jclass *pClass, jmethodID *pConstructor,
duke@0 1186 SHELLDETAILS *psd, ULONG visible)
duke@0 1187 {
duke@0 1188 return pEnv->NewObject(*pClass, *pConstructor,
duke@0 1189 jstringFromSTRRET(pEnv, NULL, &(psd->str)),
duke@0 1190 (jint)(psd->cxChar * 6), // TODO: is 6 OK for converting chars to pixels?
duke@0 1191 (jint)psd->fmt, (jboolean) visible);
duke@0 1192 }
duke@0 1193
duke@0 1194
duke@0 1195 /*
duke@0 1196 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 1197 * Method: doGetColumnInfo
duke@0 1198 * Signature: (J)[Lsun/awt/shell/ShellFolderColumnInfo;
duke@0 1199 */
duke@0 1200 JNIEXPORT jobjectArray JNICALL
duke@0 1201 Java_sun_awt_shell_Win32ShellFolder2_doGetColumnInfo
duke@0 1202 (JNIEnv *env, jobject obj, jlong iShellFolder)
duke@0 1203 {
duke@0 1204
duke@0 1205 HRESULT hr;
duke@0 1206 IShellFolder *pIShellFolder = (IShellFolder*) iShellFolder;
duke@0 1207 IUnknown *pIUnknown = NULL;
duke@0 1208
duke@0 1209 jclass columnClass = env->FindClass("sun/awt/shell/ShellFolderColumnInfo");
duke@0 1210 if(NULL == columnClass) {
duke@0 1211 return NULL;
duke@0 1212 }
duke@0 1213
duke@0 1214 jmethodID columnConstructor =
duke@0 1215 env->GetMethodID(columnClass, "<init>", "(Ljava/lang/String;IIZ)V");
duke@0 1216 if(NULL == columnConstructor) {
duke@0 1217 return NULL;
duke@0 1218 }
duke@0 1219
duke@0 1220 // We'are asking the object the list of available columns
duke@0 1221 SHELLDETAILS sd;
duke@0 1222
duke@0 1223 hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown);
duke@0 1224 if(SUCCEEDED (hr)) {
duke@0 1225
duke@0 1226 // The folder exposes IShellFolder2 interface
duke@0 1227 IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown;
duke@0 1228
duke@0 1229 // Count columns
duke@0 1230 int colNum = -1;
duke@0 1231 hr = S_OK;
duke@0 1232 do{
duke@0 1233 hr = GetDetailsOfFolder(pIShellFolder2, NULL, ++colNum, &sd);
duke@0 1234 } while (SUCCEEDED (hr));
duke@0 1235
duke@0 1236 jobjectArray columns =
duke@0 1237 env->NewObjectArray((jsize) colNum, columnClass, NULL);
duke@0 1238 if(NULL == columns) {
duke@0 1239 pIShellFolder2->Release();
duke@0 1240 return NULL;
duke@0 1241 }
duke@0 1242
duke@0 1243 // Fill column details list
duke@0 1244 SHCOLSTATEF csFlags;
duke@0 1245 colNum = 0;
duke@0 1246 hr = S_OK;
duke@0 1247 while (SUCCEEDED (hr)) {
duke@0 1248 hr = GetDetailsOfFolder(pIShellFolder2, NULL, colNum, &sd);
duke@0 1249
duke@0 1250 if (SUCCEEDED (hr)) {
duke@0 1251 hr = pIShellFolder2->GetDefaultColumnState(colNum, &csFlags);
duke@0 1252 if (SUCCEEDED (hr)) {
duke@0 1253 if(!(csFlags & SHCOLSTATE_HIDDEN)) {
duke@0 1254 jobject column = CreateColumnInfo(env,
duke@0 1255 &columnClass, &columnConstructor,
duke@0 1256 &sd, csFlags & SHCOLSTATE_ONBYDEFAULT);
duke@0 1257 env->SetObjectArrayElement(columns, (jsize) colNum, column);
duke@0 1258 }
duke@0 1259 }
duke@0 1260 colNum++;
duke@0 1261 }
duke@0 1262 }
duke@0 1263
duke@0 1264 pIShellFolder2->Release();
duke@0 1265
duke@0 1266 return columns;
duke@0 1267 }
duke@0 1268
duke@0 1269 hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown);
duke@0 1270 if(SUCCEEDED (hr)) {
duke@0 1271 // The folder exposes IShellDetails interface
duke@0 1272 IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown;
duke@0 1273
duke@0 1274 // Count columns
duke@0 1275 int colNum = -1;
duke@0 1276 hr = S_OK;
duke@0 1277 do{
duke@0 1278 hr = GetDetailsOf(pIShellDetails, NULL, ++colNum, &sd);
duke@0 1279 } while (SUCCEEDED (hr));
duke@0 1280
duke@0 1281 jobjectArray columns =
duke@0 1282 env->NewObjectArray((jsize) colNum, columnClass, NULL);
duke@0 1283 if(NULL == columns) {
duke@0 1284 pIShellDetails->Release();
duke@0 1285 return NULL;
duke@0 1286 }
duke@0 1287
duke@0 1288 // Fill column details list
duke@0 1289 colNum = 0;
duke@0 1290 hr = S_OK;
duke@0 1291 while (SUCCEEDED (hr)) {
duke@0 1292 hr = GetDetailsOf(pIShellDetails, NULL, colNum, &sd);
duke@0 1293 if (SUCCEEDED (hr)) {
duke@0 1294 jobject column = CreateColumnInfo(env,
duke@0 1295 &columnClass, &columnConstructor,
duke@0 1296 &sd, 1);
duke@0 1297 env->SetObjectArrayElement(columns, (jsize) colNum++, column);
duke@0 1298 }
duke@0 1299 }
duke@0 1300
duke@0 1301 pIShellDetails->Release();
duke@0 1302
duke@0 1303 return columns;
duke@0 1304 }
duke@0 1305
duke@0 1306 // The folder exposes neither IShellFolder2 nor IShelDetails
duke@0 1307 return NULL;
duke@0 1308
duke@0 1309 }
duke@0 1310
duke@0 1311 /*
duke@0 1312 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 1313 * Method: doGetColumnValue
duke@0 1314 * Signature: (JJI)Ljava/lang/Object;
duke@0 1315 */
duke@0 1316 JNIEXPORT jobject JNICALL
duke@0 1317 Java_sun_awt_shell_Win32ShellFolder2_doGetColumnValue
duke@0 1318 (JNIEnv *env, jobject obj, jlong iShellFolder,
duke@0 1319 jlong jpidl, jint columnIdx)
duke@0 1320 {
duke@0 1321
duke@0 1322 HRESULT hr;
duke@0 1323 IShellFolder *pIShellFolder = (IShellFolder*) iShellFolder;
duke@0 1324 IUnknown *pIUnknown = NULL;
duke@0 1325
duke@0 1326
duke@0 1327 LPITEMIDLIST pidl = (LPITEMIDLIST) jpidl;
duke@0 1328 SHELLDETAILS sd;
duke@0 1329
duke@0 1330 hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown);
duke@0 1331 if(SUCCEEDED (hr)) {
duke@0 1332 // The folder exposes IShellFolder2 interface
duke@0 1333 IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown;
duke@0 1334 hr = GetDetailsOfFolder(pIShellFolder2, pidl, (UINT)columnIdx, &sd);
duke@0 1335 pIShellFolder2->Release();
duke@0 1336 if (SUCCEEDED (hr)) {
duke@0 1337 STRRET strRet = sd.str;
duke@0 1338 return jstringFromSTRRET(env, pidl, &strRet);
duke@0 1339 }
duke@0 1340 }
duke@0 1341
duke@0 1342 hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown);
duke@0 1343 if(SUCCEEDED (hr)) {
duke@0 1344 // The folder exposes IShellDetails interface
duke@0 1345 IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown;
duke@0 1346 hr = GetDetailsOf(pIShellDetails, pidl, (UINT)columnIdx, &sd);
duke@0 1347 pIShellDetails->Release();
duke@0 1348 if (SUCCEEDED (hr)) {
duke@0 1349 STRRET strRet = sd.str;
duke@0 1350 return jstringFromSTRRET(env, pidl, &strRet);
duke@0 1351 }
duke@0 1352 }
duke@0 1353
duke@0 1354 // The folder exposes neither IShellFolder2 nor IShelDetails
duke@0 1355 return NULL;
duke@0 1356 }
duke@0 1357
duke@0 1358 /*
duke@0 1359 * Class: sun_awt_shell_Win32ShellFolder2
duke@0 1360 * Method: compareIDsByColumn
duke@0 1361 * Signature: (JJJI)I
duke@0 1362 */
duke@0 1363 JNIEXPORT jint JNICALL
duke@0 1364 Java_sun_awt_shell_Win32ShellFolder2_compareIDsByColumn
duke@0 1365 (JNIEnv* env, jclass cls, jlong jpParentIShellFolder,
duke@0 1366 jlong pIDL1, jlong pIDL2, jint columnIdx)
duke@0 1367 {
duke@0 1368 IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder;
duke@0 1369 if (pParentIShellFolder == NULL) {
duke@0 1370 return 0;
duke@0 1371 }
duke@0 1372
duke@0 1373 HRESULT hr = pParentIShellFolder->CompareIDs(
duke@0 1374 (UINT) columnIdx,
duke@0 1375 (LPCITEMIDLIST) pIDL1,
duke@0 1376 (LPCITEMIDLIST) pIDL2);
duke@0 1377 if (SUCCEEDED (hr)) {
duke@0 1378 return (jint) (short) HRESULT_CODE(hr);
duke@0 1379 }
duke@0 1380
duke@0 1381 return 0;
duke@0 1382 }
duke@0 1383
duke@0 1384
duke@0 1385 } // extern "C"