rev 13901 : Fixes for 8151385. Contains additional fix for 8149453 (upFolder, newFolder, etc. icons) rev 13644 : 8080492: [Parfait] Uninitialised variable in jdk/src/java/desktop/windows/native/libawt/ Reviewed-by: prr, vadim rev 12267 : 8022057: JFileChooser blocks EDT in Win32ShellFolder2.getIcon Reviewed-by: serb, ant rev 12120 : 8081231: JDK9 client build broken on Windows Reviewed-by: azvegint rev 12117 : 8003399: JFileChooser gives wrong path to selected file when saving to Libraries folder on Windows 7 Reviewed-by: serb, ant rev 10731 : 8056216: Remove "sun" directory layer from libawt and common Reviewed-by: erikj, ihse, coffeys
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 23 * questions. 24 */ 25 26 #define OEMRESOURCE 27 28 #ifdef DEBUG 29 // Warning : do not depend on anything in <awt.h>. Including this file 30 // is a fix for 4507525 to use the same operator new and delete as AWT. 31 // This file should stand independent of AWT and should ultimately be 32 // put into its own DLL. 33 #include <awt.h> 34 #else 35 // Include jni_util.h first, so JNU_* macros can be redefined 36 #include "jni_util.h" 37 // Borrow some macros from awt.h 38 #define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast<jchar*>(x), static_cast<jsize>(_tcslen(x))) 39 #define JNU_GetStringPlatformChars(env, x, y) reinterpret_cast<LPCWSTR>(env->GetStringChars(x, y)) 40 #define JNU_ReleaseStringPlatformChars(env, x, y) env->ReleaseStringChars(x, reinterpret_cast<const jchar*>(y)) 41 #endif // DEBUG 42 43 #include <windows.h> 44 #include <shlobj.h> 45 #include <shellapi.h> 46 #include "jlong.h" 47 #include "alloc.h" 48 49 #include "stdhdrs.h" 50 51 // Copy from shlguid.h which is no longer in PlatformSDK 52 #ifndef DEFINE_SHLGUID 53 #define DEFINE_SHLGUID(name, l, w1, w2) DEFINE_GUID(name, l, w1, w2, 0xC0, 0, 0, 0, 0, 0, 0, 0x46) 54 #endif 55 56 // {93F2F68C-1D1B-11d3-A30E-00C04F79ABD1} 57 DEFINE_GUID(IID_IShellFolder2, 0x93f2f68c, 0x1d1b, 0x11d3, 0xa3, 0xe, 0x0, 0xc0, 0x4f, 0x79, 0xab, 0xd1); 58 59 #undef IID_IShellLinkW 60 #undef IID_IExtractIconW 61 // copied from shlguid.h 62 DEFINE_SHLGUID(IID_IShellLinkW, 0x000214F9L, 0, 0); 63 DEFINE_SHLGUID(IID_IExtractIconW, 0x000214FAL, 0, 0); 64 65 //#include <sun_awt_shell_Win32ShellFolder2.h> 66 67 #ifndef DASSERT 68 #define DASSERT(x) 69 #endif 70 #define DEFINE_FIELD_ID(var, cls, field, type) \ 71 jfieldID var = env->GetFieldID(cls, field, type); \ 72 DASSERT(var != NULL); \ 73 CHECK_NULL_RETURN(var, NULL); 74 75 #define EXCEPTION_CHECK \ 76 if(env->ExceptionCheck()) { \ 77 throw std::bad_alloc(); \ 78 } 79 80 // Shell Functions 81 typedef BOOL (WINAPI *DestroyIconType)(HICON); 82 typedef HINSTANCE (WINAPI *FindExecutableType)(LPCTSTR,LPCTSTR,LPTSTR); 83 typedef HICON (WINAPI *ImageList_GetIconType)(HIMAGELIST,int,UINT); 84 typedef BOOL (WINAPI *GetIconInfoType)(HICON,PICONINFO); 85 typedef HRESULT (WINAPI *SHGetDesktopFolderType)(IShellFolder**); 86 typedef DWORD* (WINAPI *SHGetFileInfoType)(LPCTSTR,DWORD,SHFILEINFO*,UINT,UINT); 87 typedef HRESULT (WINAPI *SHGetMallocType)(IMalloc**); 88 typedef BOOL (WINAPI *SHGetPathFromIDListType)(LPCITEMIDLIST,LPTSTR); 89 typedef HRESULT (WINAPI *SHGetSpecialFolderLocationType)(HWND,int,LPITEMIDLIST*); 90 91 static DestroyIconType fn_DestroyIcon; 92 static FindExecutableType fn_FindExecutable; 93 static GetIconInfoType fn_GetIconInfo; 94 static ImageList_GetIconType fn_ImageList_GetIcon; 95 static SHGetDesktopFolderType fn_SHGetDesktopFolder; 96 static SHGetFileInfoType fn_SHGetFileInfo; 97 static SHGetMallocType fn_SHGetMalloc; 98 static SHGetPathFromIDListType fn_SHGetPathFromIDList; 99 static SHGetSpecialFolderLocationType fn_SHGetSpecialFolderLocation; 100 101 // Field IDs 102 static jmethodID MID_pIShellFolder; 103 static jfieldID FID_pIShellIcon; 104 static jmethodID MID_relativePIDL; 105 static jfieldID FID_displayName; 106 static jfieldID FID_folderType; 107 108 // Other statics 109 static IMalloc* pMalloc; 110 static IShellFolder* pDesktop; 111 112 // Some macros from awt.h, because it is not included in release 113 #ifndef IS_WIN2000 114 #define IS_WIN2000 (LOBYTE(LOWORD(::GetVersion())) >= 5) 115 #endif 116 #ifndef IS_WINXP 117 #define IS_WINXP ((IS_WIN2000 && HIBYTE(LOWORD(::GetVersion())) >= 1) || LOBYTE(LOWORD(::GetVersion())) > 5) 118 #endif 119 #ifndef IS_WINVISTA 120 #define IS_WINVISTA (!(::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion())) >= 6) 121 #endif 122 123 124 extern "C" { 125 126 static BOOL initShellProcs() 127 { 128 static HMODULE libShell32 = NULL; 129 static HMODULE libUser32 = NULL; 130 static HMODULE libComCtl32 = NULL; 131 // If already initialized, return TRUE 132 if (libShell32 != NULL && libUser32 != NULL) { 133 return TRUE; 134 } 135 // Load libraries 136 libShell32 = JDK_LoadSystemLibrary("shell32.dll"); 137 if (libShell32 == NULL) { 138 return FALSE; 139 } 140 libUser32 = JDK_LoadSystemLibrary("user32.dll"); 141 if (libUser32 == NULL) { 142 return FALSE; 143 } 144 libComCtl32 = JDK_LoadSystemLibrary("comctl32.dll"); 145 if (libComCtl32 == NULL) { 146 return FALSE; 147 } 148 149 // Set up procs - libComCtl32 150 fn_ImageList_GetIcon = (ImageList_GetIconType)GetProcAddress(libComCtl32, "ImageList_GetIcon"); 151 if (fn_ImageList_GetIcon == NULL) { 152 return FALSE; 153 } 154 155 // Set up procs - libShell32 156 fn_FindExecutable = (FindExecutableType)GetProcAddress( 157 libShell32, "FindExecutableW"); 158 if (fn_FindExecutable == NULL) { 159 return FALSE; 160 } 161 fn_SHGetDesktopFolder = (SHGetDesktopFolderType)GetProcAddress(libShell32, 162 "SHGetDesktopFolder"); 163 if (fn_SHGetDesktopFolder == NULL) { 164 return FALSE; 165 } 166 fn_SHGetFileInfo = (SHGetFileInfoType)GetProcAddress( 167 libShell32, "SHGetFileInfoW"); 168 if (fn_SHGetFileInfo == NULL) { 169 return FALSE; 170 } 171 fn_SHGetMalloc = (SHGetMallocType)GetProcAddress(libShell32, 172 "SHGetMalloc"); 173 if (fn_SHGetMalloc == NULL) { 174 return FALSE; 175 } 176 // Set up IMalloc 177 if (fn_SHGetMalloc(&pMalloc) != S_OK) { 178 return FALSE; 179 } 180 fn_SHGetPathFromIDList = (SHGetPathFromIDListType)GetProcAddress( 181 libShell32, "SHGetPathFromIDListW"); 182 if (fn_SHGetPathFromIDList == NULL) { 183 return FALSE; 184 } 185 fn_SHGetSpecialFolderLocation = (SHGetSpecialFolderLocationType) 186 GetProcAddress(libShell32, "SHGetSpecialFolderLocation"); 187 if (fn_SHGetSpecialFolderLocation == NULL) { 188 return FALSE; 189 } 190 191 // Set up procs - libUser32 192 fn_GetIconInfo = (GetIconInfoType)GetProcAddress(libUser32, "GetIconInfo"); 193 if (fn_GetIconInfo == NULL) { 194 return FALSE; 195 } 196 fn_DestroyIcon = (DestroyIconType)GetProcAddress(libUser32, "DestroyIcon"); 197 if (fn_DestroyIcon == NULL) { 198 return FALSE; 199 } 200 return TRUE; 201 } 202 203 // To call real JNU_NewStringPlatform 204 #undef JNU_NewStringPlatform 205 static jstring jstringFromSTRRET(JNIEnv* env, LPITEMIDLIST pidl, STRRET* pStrret) { 206 switch (pStrret->uType) { 207 case STRRET_CSTR : 208 return JNU_NewStringPlatform(env, reinterpret_cast<const char*>(pStrret->cStr)); 209 case STRRET_OFFSET : 210 // Note : this may need to be WCHAR instead 211 return JNU_NewStringPlatform(env, 212 (CHAR*)pidl + pStrret->uOffset); 213 case STRRET_WSTR : 214 return env->NewString(reinterpret_cast<const jchar*>(pStrret->pOleStr), 215 static_cast<jsize>(wcslen(pStrret->pOleStr))); 216 } 217 return NULL; 218 } 219 // restoring the original definition 220 #define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast<jchar*>(x), static_cast<jsize>(_tcslen(x))) 221 222 /* 223 * Class: sun_awt_shell_Win32ShellFolder2 224 * Method: initIDs 225 * Signature: ()V 226 */ 227 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initIDs 228 (JNIEnv* env, jclass cls) 229 { 230 if (!initShellProcs()) { 231 JNU_ThrowInternalError(env, "Could not initialize shell library"); 232 return; 233 } 234 MID_pIShellFolder = env->GetMethodID(cls, "setIShellFolder", "(J)V"); 235 CHECK_NULL(MID_pIShellFolder); 236 FID_pIShellIcon = env->GetFieldID(cls, "pIShellIcon", "J"); 237 CHECK_NULL(FID_pIShellIcon); 238 MID_relativePIDL = env->GetMethodID(cls, "setRelativePIDL", "(J)V"); 239 CHECK_NULL(MID_relativePIDL); 240 FID_displayName = env->GetFieldID(cls, "displayName", "Ljava/lang/String;"); 241 CHECK_NULL(FID_displayName); 242 FID_folderType = env->GetFieldID(cls, "folderType", "Ljava/lang/String;"); 243 CHECK_NULL(FID_folderType); 244 } 245 246 247 /* 248 * Class: sun_awt_shell_Win32ShellFolderManager2 249 * Method: initializeCom 250 * Signature: ()V 251 */ 252 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolderManager2_initializeCom 253 (JNIEnv* env, jclass cls) 254 { 255 HRESULT hr = ::CoInitialize(NULL); 256 if (FAILED(hr)) { 257 char c[64]; 258 sprintf(c, "Could not initialize COM: HRESULT=0x%08X", hr); 259 JNU_ThrowInternalError(env, c); 260 } 261 } 262 263 /* 264 * Class: sun_awt_shell_Win32ShellFolderManager2 265 * Method: uninitializeCom 266 * Signature: ()V 267 */ 268 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolderManager2_uninitializeCom 269 (JNIEnv* env, jclass cls) 270 { 271 ::CoUninitialize(); 272 } 273 274 static IShellIcon* getIShellIcon(IShellFolder* pIShellFolder) { 275 // http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp 276 HRESULT hres; 277 IShellIcon* pIShellIcon; 278 if (pIShellFolder != NULL) { 279 hres = pIShellFolder->QueryInterface(IID_IShellIcon, (void**)&pIShellIcon); 280 if (SUCCEEDED(hres)) { 281 return pIShellIcon; 282 } 283 } 284 return (IShellIcon*)NULL; 285 } 286 287 288 /* 289 * Class: sun_awt_shell_Win32ShellFolder2 290 * Method: getIShellIcon 291 * Signature: (J)J 292 */ 293 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIShellIcon 294 (JNIEnv* env, jclass cls, jlong parentIShellFolder) 295 { 296 return (jlong)getIShellIcon((IShellFolder*)parentIShellFolder); 297 } 298 299 300 /* 301 * Class: sun_awt_shell_Win32ShellFolder2 302 * Method: initDesktop 303 * Signature: ()V 304 */ 305 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initDesktop 306 (JNIEnv* env, jobject desktop) 307 { 308 // Get desktop IShellFolder 309 HRESULT res = fn_SHGetDesktopFolder(&pDesktop); 310 if (res != S_OK) { 311 JNU_ThrowInternalError(env, "Could not get desktop shell folder"); 312 return; 313 } 314 // Set field ID for pIShellFolder 315 env->CallVoidMethod(desktop, MID_pIShellFolder, (jlong)pDesktop); 316 // Get desktop relative PIDL 317 LPITEMIDLIST relPIDL; 318 res = fn_SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &relPIDL); 319 if (res != S_OK) { 320 JNU_ThrowInternalError(env, 321 "Could not get desktop shell folder ID list"); 322 return; 323 } 324 // Set field ID for relative PIDL 325 env->CallVoidMethod(desktop, MID_relativePIDL, (jlong)relPIDL); 326 } 327 328 /* 329 * Class: sun_awt_shell_Win32ShellFolder2 330 * Method: initSpecial 331 * Signature: (JI)V 332 */ 333 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initSpecial 334 (JNIEnv* env, jobject folder, jlong desktopIShellFolder, jint folderType) 335 { 336 // Get desktop IShellFolder interface 337 IShellFolder* pDesktop = (IShellFolder*)desktopIShellFolder; 338 if (pDesktop == NULL) { 339 JNU_ThrowInternalError(env, "Desktop shell folder missing"); 340 return; 341 } 342 // Get special folder relative PIDL 343 LPITEMIDLIST relPIDL; 344 HRESULT res = fn_SHGetSpecialFolderLocation(NULL, folderType, 345 &relPIDL); 346 if (res != S_OK) { 347 JNU_ThrowIOException(env, "Could not get shell folder ID list"); 348 return; 349 } 350 // Set field ID for relative PIDL 351 env->CallVoidMethod(folder, MID_relativePIDL, (jlong)relPIDL); 352 // Get special folder IShellFolder interface 353 IShellFolder* pFolder; 354 res = pDesktop->BindToObject(relPIDL, NULL, IID_IShellFolder, 355 (void**)&pFolder); 356 if (res != S_OK) { 357 JNU_ThrowInternalError(env, 358 "Could not bind shell folder to interface"); 359 return; 360 } 361 // Set field ID for pIShellFolder 362 env->CallVoidMethod(folder, MID_pIShellFolder, (jlong)pFolder); 363 } 364 365 366 /* 367 * Class: sun_awt_shell_Win32ShellFolder2 368 * Method: getNextPIDLEntry 369 * Signature: (J)J 370 */ 371 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getNextPIDLEntry 372 (JNIEnv* env, jclass cls, jlong jpIDL) 373 { 374 LPITEMIDLIST pIDL = (LPITEMIDLIST)jpIDL; 375 376 // Check for valid pIDL. 377 if(pIDL == NULL) 378 return NULL; 379 380 // Get the size of the specified item identifier. 381 int cb = pIDL->mkid.cb; 382 383 // If the size is zero, it is the end of the list. 384 if (cb == 0) 385 return NULL; 386 387 // Add cb to pidl (casting to increment by bytes). 388 pIDL = (LPITEMIDLIST)(((LPBYTE)pIDL) + cb); 389 390 // Return NULL if it is null-terminating, or a pidl otherwise. 391 return (pIDL->mkid.cb == 0) ? 0 : (jlong)pIDL; 392 } 393 394 395 /* 396 * Class: sun_awt_shell_Win32ShellFolder2 397 * Method: copyFirstPIDLEntry 398 * Signature: (J)J 399 */ 400 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_copyFirstPIDLEntry 401 (JNIEnv* env, jclass cls, jlong jpIDL) 402 { 403 LPITEMIDLIST pIDL = (LPITEMIDLIST)jpIDL; 404 if (pIDL == NULL) { 405 return 0; 406 } 407 // Get the size of the specified item identifier. 408 int cb = pIDL->mkid.cb; 409 410 // If the size is zero, it is the end of the list. 411 if (cb == 0) 412 return 0; 413 414 if (!IS_SAFE_SIZE_ADD(cb, sizeof(SHITEMID))) { 415 return 0; 416 } 417 // Allocate space for this as well as null-terminating entry. 418 LPITEMIDLIST newPIDL = (LPITEMIDLIST)pMalloc->Alloc(cb + sizeof(SHITEMID)); 419 420 // Copy data. 421 memcpy(newPIDL, pIDL, cb); 422 423 // Set null terminator for next entry. 424 LPITEMIDLIST nextPIDL = (LPITEMIDLIST)(((LPBYTE)newPIDL) + cb); 425 nextPIDL->mkid.cb = 0; 426 427 return (jlong)newPIDL; 428 } 429 430 static int pidlLength(LPITEMIDLIST pIDL) { 431 int len = 0; 432 while (pIDL->mkid.cb != 0) { 433 int cb = pIDL->mkid.cb; 434 len += cb; 435 pIDL = (LPITEMIDLIST)(((LPBYTE)pIDL) + cb); 436 } 437 return len; 438 } 439 440 /* 441 * Class: sun_awt_shell_Win32ShellFolder2 442 * Method: combinePIDLs 443 * Signature: (J)J 444 */ 445 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_combinePIDLs 446 (JNIEnv* env, jclass cls, jlong jppIDL, jlong jpIDL) 447 { 448 // Combine an absolute (fully qualified) pidl in a parent with the relative 449 // pidl of a child object to create a new absolute pidl for the child. 450 451 LPITEMIDLIST parentPIDL = (LPITEMIDLIST)jppIDL; 452 LPITEMIDLIST relativePIDL = (LPITEMIDLIST)jpIDL; 453 454 int len1 = pidlLength(parentPIDL); 455 int len2 = pidlLength(relativePIDL); 456 457 if (!IS_SAFE_SIZE_ADD(len1, len2) || !IS_SAFE_SIZE_ADD(len1 + len2, sizeof(SHITEMID))) { 458 return 0; 459 } 460 LPITEMIDLIST newPIDL = (LPITEMIDLIST)pMalloc->Alloc(len1 + len2 + sizeof(SHITEMID)); 461 memcpy(newPIDL, parentPIDL, len1); 462 memcpy(((LPBYTE) newPIDL) + len1, relativePIDL, len2); 463 LPITEMIDLIST nullTerminator = (LPITEMIDLIST)(((LPBYTE) newPIDL) + len1 + len2); 464 nullTerminator->mkid.cb = 0; 465 466 return (jlong) newPIDL; 467 } 468 469 470 /* 471 * Class: sun_awt_shell_Win32ShellFolder2 472 * Method: releasePIDL 473 * Signature: (J)V 474 */ 475 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_releasePIDL 476 (JNIEnv* env, jclass cls, jlong pIDL) 477 { 478 if (pIDL != 0L) { 479 pMalloc->Free((LPITEMIDLIST)pIDL); 480 } 481 } 482 483 484 /* 485 * Class: sun_awt_shell_Win32ShellFolder2 486 * Method: releaseIShellFolder 487 * Signature: (J)V 488 */ 489 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_releaseIShellFolder 490 (JNIEnv* env, jclass cls, jlong pIShellFolder) 491 { 492 if (pIShellFolder != 0L) { 493 ((IShellFolder*)pIShellFolder)->Release(); 494 } 495 } 496 497 498 /* 499 * Class: sun_awt_shell_Win32ShellFolder2 500 * Method: compareIDs 501 * Signature: (JJJ)I 502 */ 503 JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_compareIDs 504 (JNIEnv* env, jclass cls, jlong jpParentIShellFolder, jlong pIDL1, jlong pIDL2) 505 { 506 IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder; 507 if (pParentIShellFolder == NULL) { 508 return 0; 509 } 510 return pParentIShellFolder->CompareIDs(0, (LPCITEMIDLIST) pIDL1, (LPCITEMIDLIST) pIDL2); 511 } 512 513 514 /* 515 * Class: sun_awt_shell_Win32ShellFolder2 516 * Method: getAttributes0 517 * Signature: (JJI)J 518 */ 519 JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getAttributes0 520 (JNIEnv* env, jclass cls, jlong jpParentIShellFolder, jlong jpIDL, jint attrsMask) 521 { 522 IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder; 523 if (pParentIShellFolder == NULL) { 524 return 0; 525 } 526 LPCITEMIDLIST pIDL = (LPCITEMIDLIST)jpIDL; 527 if (pIDL == NULL) { 528 return 0; 529 } 530 ULONG attrs = attrsMask; 531 HRESULT res = pParentIShellFolder->GetAttributesOf(1, &pIDL, &attrs); 532 return attrs; 533 } 534 535 536 /* 537 * Class: sun_awt_shell_Win32ShellFolder2 538 * Method: getFileSystemPath0 539 * Signature: (I)Ljava/lang/String; 540 */ 541 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileSystemPath0 542 (JNIEnv* env, jclass cls, jint csidl) 543 { 544 LPITEMIDLIST relPIDL; 545 TCHAR szBuf[MAX_PATH]; 546 HRESULT res = fn_SHGetSpecialFolderLocation(NULL, csidl, &relPIDL); 547 if (res != S_OK) { 548 JNU_ThrowIOException(env, "Could not get shell folder ID list"); 549 return NULL; 550 } 551 if (fn_SHGetPathFromIDList(relPIDL, szBuf)) { 552 return JNU_NewStringPlatform(env, szBuf); 553 } else { 554 return NULL; 555 } 556 } 557 558 /* 559 * Class: sun_awt_shell_Win32ShellFolder2 560 * Method: getEnumObjects 561 * Signature: (JZ)J 562 */ 563 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getEnumObjects 564 (JNIEnv* env, jobject folder, jlong pIShellFolder, 565 jboolean isDesktop, jboolean includeHiddenFiles) 566 { 567 IShellFolder* pFolder = (IShellFolder*)pIShellFolder; 568 if (pFolder == NULL) { 569 return 0; 570 } 571 DWORD dwFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS; 572 if (includeHiddenFiles) { 573 dwFlags |= SHCONTF_INCLUDEHIDDEN; 574 } 575 /* 576 if (!isDesktop) { 577 dwFlags = dwFlags | SHCONTF_NONFOLDERS; 578 } 579 */ 580 IEnumIDList* pEnum; 581 if (pFolder->EnumObjects(NULL, dwFlags, &pEnum) != S_OK) { 582 return 0; 583 } 584 return (jlong)pEnum; 585 } 586 587 /* 588 * Class: sun_awt_shell_Win32ShellFolder2 589 * Method: getNextChild 590 * Signature: (J)J 591 */ 592 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getNextChild 593 (JNIEnv* env, jobject folder, jlong pEnumObjects) 594 { 595 IEnumIDList* pEnum = (IEnumIDList*)pEnumObjects; 596 if (pEnum == NULL) { 597 return 0; 598 } 599 LPITEMIDLIST pidl; 600 if (pEnum->Next(1, &pidl, NULL) != S_OK) { 601 return 0; 602 } 603 return (jlong)pidl; 604 } 605 606 /* 607 * Class: sun_awt_shell_Win32ShellFolder2 608 * Method: releaseEnumObjects 609 * Signature: (J)V 610 */ 611 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_releaseEnumObjects 612 (JNIEnv* env, jobject folder, jlong pEnumObjects) 613 { 614 IEnumIDList* pEnum = (IEnumIDList*)pEnumObjects; 615 if (pEnum == NULL) { 616 return; 617 } 618 pEnum->Release(); 619 } 620 621 /* 622 * Class: sun_awt_shell_Win32ShellFolder2 623 * Method: bindToObject 624 * Signature: (JJ)J 625 */ 626 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_bindToObject 627 (JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL) 628 { 629 IShellFolder* pParent = (IShellFolder*)parentIShellFolder; 630 if (pParent == NULL) { 631 return 0; 632 } 633 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL; 634 if (pidl == NULL) { 635 return 0; 636 } 637 IShellFolder* pFolder; 638 HRESULT hr = pParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&pFolder); 639 if (SUCCEEDED (hr)) { 640 return (jlong)pFolder; 641 } 642 return 0; 643 } 644 645 646 /* 647 * Class: sun_awt_shell_Win32ShellFolder2 648 * Method: getLinkLocation 649 * Signature: (JJZ)J; 650 */ 651 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getLinkLocation 652 (JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL, jboolean resolve) 653 { 654 HRESULT hres; 655 STRRET strret; 656 OLECHAR olePath[MAX_PATH]; // wide-char version of path name 657 LPWSTR wstr; 658 659 IShellFolder* pParent = (IShellFolder*)parentIShellFolder; 660 if (pParent == NULL) { 661 return NULL; 662 } 663 664 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL; 665 if (pidl == NULL) { 666 return NULL; 667 } 668 669 hres = pParent->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_FORPARSING, &strret); 670 if (FAILED(hres)) { 671 return NULL; 672 } 673 674 switch (strret.uType) { 675 case STRRET_CSTR : 676 // IShellFolder::ParseDisplayName requires the path name in Unicode. 677 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, strret.cStr, -1, olePath, MAX_PATH); 678 wstr = olePath; 679 break; 680 681 case STRRET_OFFSET : 682 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (CHAR *)pidl + strret.uOffset, -1, olePath, MAX_PATH); 683 wstr = olePath; 684 break; 685 686 case STRRET_WSTR : 687 wstr = strret.pOleStr; 688 break; 689 690 default: 691 return NULL; 692 } 693 694 IShellLinkW* psl; 695 hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&psl); 696 if (SUCCEEDED(hres)) { 697 IPersistFile* ppf; 698 hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); 699 if (SUCCEEDED(hres)) { 700 hres = ppf->Load(wstr, STGM_READ); 701 if (SUCCEEDED(hres)) { 702 if (resolve) { 703 hres = psl->Resolve(NULL, 0); 704 // Ignore failure 705 } 706 pidl = (LPITEMIDLIST)NULL; 707 hres = psl->GetIDList(&pidl); 708 } 709 ppf->Release(); 710 } 711 psl->Release(); 712 } 713 714 if (strret.uType == STRRET_WSTR) { 715 CoTaskMemFree(strret.pOleStr); 716 } 717 if (SUCCEEDED(hres)) { 718 return (jlong)pidl; 719 } else { 720 return 0; 721 } 722 } 723 724 725 /* 726 * Class: sun_awt_shell_Win32ShellFolder2 727 * Method: parseDisplayName0 728 * Signature: (JLjava/lang/String;)J 729 */ 730 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_parseDisplayName0 731 (JNIEnv* env, jclass cls, jlong jpIShellFolder, jstring jname) 732 { 733 734 // Get desktop IShellFolder interface 735 IShellFolder* pIShellFolder = (IShellFolder*)jpIShellFolder; 736 if (pIShellFolder == NULL) { 737 JNU_ThrowInternalError(env, "Desktop shell folder missing"); 738 return 0; 739 } 740 // Get relative PIDL for name 741 LPITEMIDLIST pIDL; 742 int nLength = env->GetStringLength(jname); 743 const jchar* strPath = env->GetStringChars(jname, NULL); 744 JNU_CHECK_EXCEPTION_RETURN(env, 0); 745 jchar* wszPath = new jchar[nLength + 1]; 746 wcsncpy(reinterpret_cast<LPWSTR>(wszPath), reinterpret_cast<LPCWSTR>(strPath), nLength); 747 wszPath[nLength] = 0; 748 HRESULT res = pIShellFolder->ParseDisplayName(NULL, NULL, 749 reinterpret_cast<LPWSTR>(wszPath), NULL, &pIDL, NULL); 750 if (res != S_OK) { 751 JNU_ThrowIOException(env, "Could not parse name"); 752 pIDL = 0; 753 } 754 delete[] wszPath; 755 env->ReleaseStringChars(jname, strPath); 756 return (jlong)pIDL; 757 } 758 759 760 /* 761 * Class: sun_awt_shell_Win32ShellFolder2 762 * Method: getDisplayNameOf 763 * Signature: (JJI)Ljava/lang/String; 764 */ 765 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getDisplayNameOf 766 (JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL, jint attrs) 767 { 768 IShellFolder* pParent = (IShellFolder*)parentIShellFolder; 769 if (pParent == NULL) { 770 return NULL; 771 } 772 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL; 773 if (pidl == NULL) { 774 return NULL; 775 } 776 STRRET strret; 777 if (pParent->GetDisplayNameOf(pidl, attrs, &strret) != S_OK) { 778 return NULL; 779 } 780 jstring result = jstringFromSTRRET(env, pidl, &strret); 781 if (strret.uType == STRRET_WSTR) { 782 CoTaskMemFree(strret.pOleStr); 783 } 784 return result; 785 } 786 787 /* 788 * Class: sun_awt_shell_Win32ShellFolder2 789 * Method: getFolderType 790 * Signature: (J)Ljava/lang/String; 791 */ 792 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFolderType 793 (JNIEnv* env, jclass cls, jlong pIDL) 794 { 795 SHFILEINFO fileInfo; 796 if (fn_SHGetFileInfo((LPCTSTR)pIDL, 0L, &fileInfo, sizeof(fileInfo), 797 SHGFI_TYPENAME | SHGFI_PIDL) == 0) { 798 return NULL; 799 } 800 return JNU_NewStringPlatform(env, fileInfo.szTypeName); 801 } 802 803 /* 804 * Class: sun_awt_shell_Win32ShellFolder2 805 * Method: getExecutableType 806 * Signature: (Ljava/lang/String;)Ljava/lang/String; 807 */ 808 JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getExecutableType 809 (JNIEnv* env, jobject folder, jstring path) 810 { 811 TCHAR szBuf[MAX_PATH]; 812 LPCTSTR szPath = JNU_GetStringPlatformChars(env, path, NULL); 813 if (szPath == NULL) { 814 return NULL; 815 } 816 HINSTANCE res = fn_FindExecutable(szPath, szPath, szBuf); 817 JNU_ReleaseStringPlatformChars(env, path, szPath); 818 if ((UINT_PTR)res < 32) { 819 return NULL; 820 } 821 return JNU_NewStringPlatform(env, szBuf); 822 } 823 824 825 /* 826 * Class: sun_awt_shell_Win32ShellFolder2 827 * Method: getIcon 828 * Signature: (Ljava/lang/String;Z)J 829 */ 830 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIcon 831 (JNIEnv* env, jclass cls, jstring absolutePath, jboolean getLargeIcon) 832 { 833 HICON hIcon = NULL; 834 SHFILEINFO fileInfo; 835 LPCTSTR pathStr = JNU_GetStringPlatformChars(env, absolutePath, NULL); 836 JNU_CHECK_EXCEPTION_RETURN(env, 0); 837 if (fn_SHGetFileInfo(pathStr, 0L, &fileInfo, sizeof(fileInfo), 838 SHGFI_ICON | (getLargeIcon ? 0 : SHGFI_SMALLICON)) != 0) { 839 hIcon = fileInfo.hIcon; 840 } 841 JNU_ReleaseStringPlatformChars(env, absolutePath, pathStr); 842 return (jlong)hIcon; 843 } 844 845 /* 846 * Class: sun_awt_shell_Win32ShellFolder2 847 * Method: getIconIndex 848 * Signature: (JJ)I 849 */ 850 JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconIndex 851 (JNIEnv* env, jclass cls, jlong pIShellIconL, jlong relativePIDL) 852 { 853 IShellIcon* pIShellIcon = (IShellIcon*)pIShellIconL; 854 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL; 855 if (pIShellIcon == NULL && pidl == NULL) { 856 return 0; 857 } 858 859 INT index = -1; 860 861 HRESULT hres; 862 // http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp 863 if (pIShellIcon != NULL) { 864 hres = pIShellIcon->GetIconOf(pidl, GIL_FORSHELL, &index); 865 } 866 867 return (jint)index; 868 } 869 870 871 /* 872 * Class: sun_awt_shell_Win32ShellFolder2 873 * Method: extractIcon 874 * Signature: (JJZZ)J 875 */ 876 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_extractIcon 877 (JNIEnv* env, jclass cls, jlong pIShellFolderL, jlong relativePIDL, 878 jboolean getLargeIcon, jboolean getDefaultIcon) 879 { 880 IShellFolder* pIShellFolder = (IShellFolder*)pIShellFolderL; 881 LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL; 882 if (pIShellFolder == NULL || pidl == NULL) { 883 return 0; 884 } 885 886 HICON hIcon = NULL; 887 888 HRESULT hres; 889 IExtractIconW* pIcon; 890 hres = pIShellFolder->GetUIObjectOf(NULL, 1, const_cast<LPCITEMIDLIST*>(&pidl), 891 IID_IExtractIconW, NULL, (void**)&pIcon); 892 if (SUCCEEDED(hres)) { 893 WCHAR szBuf[MAX_PATH]; 894 INT index; 895 UINT flags; 896 UINT uFlags = getDefaultIcon ? GIL_DEFAULTICON : GIL_FORSHELL | GIL_ASYNC; 897 hres = pIcon->GetIconLocation(uFlags, szBuf, MAX_PATH, &index, &flags); 898 if (SUCCEEDED(hres)) { 899 HICON hIconLarge; 900 hres = pIcon->Extract(szBuf, index, &hIconLarge, &hIcon, (16 << 16) + 32); 901 if (SUCCEEDED(hres)) { 902 if (getLargeIcon) { 903 fn_DestroyIcon((HICON)hIcon); 904 hIcon = hIconLarge; 905 } else { 906 fn_DestroyIcon((HICON)hIconLarge); 907 } 908 } 909 } else if (hres == E_PENDING) { 910 pIcon->Release(); 911 return E_PENDING; 912 } 913 pIcon->Release(); 914 } 915 return (jlong)hIcon; 916 } 917 918 919 /* 920 * Class: sun_awt_shell_Win32ShellFolder2 921 * Method: disposeIcon 922 * Signature: (J)V 923 */ 924 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_disposeIcon 925 (JNIEnv* env, jclass cls, jlong hicon) 926 { 927 fn_DestroyIcon((HICON)hicon); 928 } 929 930 /* 931 * Class: sun_awt_shell_Win32ShellFolder2 932 * Method: getIconBits 933 * Signature: (JI)[I 934 */ 935 JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconBits 936 (JNIEnv* env, jclass cls, jlong hicon, jint iconSize) 937 { 938 jintArray iconBits = NULL; 939 940 // Get the icon info 941 ICONINFO iconInfo; 942 if (fn_GetIconInfo((HICON)hicon, &iconInfo)) { 943 // Get the screen DC 944 HDC dc = GetDC(NULL); 945 if (dc != NULL) { 946 // Set up BITMAPINFO 947 BITMAPINFO bmi; 948 memset(&bmi, 0, sizeof(BITMAPINFO)); 949 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 950 bmi.bmiHeader.biWidth = iconSize; 951 bmi.bmiHeader.biHeight = -iconSize; 952 bmi.bmiHeader.biPlanes = 1; 953 bmi.bmiHeader.biBitCount = 32; 954 bmi.bmiHeader.biCompression = BI_RGB; 955 // Extract the color bitmap 956 int nBits = iconSize * iconSize; 957 long colorBits[1024]; 958 GetDIBits(dc, iconInfo.hbmColor, 0, iconSize, colorBits, &bmi, DIB_RGB_COLORS); 959 // XP supports alpha in some icons, and depending on device. 960 // This should take precedence over the icon mask bits. 961 BOOL hasAlpha = FALSE; 962 if (IS_WINXP) { 963 for (int i = 0; i < nBits; i++) { 964 if ((colorBits[i] & 0xff000000) != 0) { 965 hasAlpha = TRUE; 966 break; 967 } 968 } 969 } 970 if (!hasAlpha) { 971 // Extract the mask bitmap 972 long maskBits[1024]; 973 GetDIBits(dc, iconInfo.hbmMask, 0, iconSize, maskBits, &bmi, DIB_RGB_COLORS); 974 // Copy the mask alphas into the color bits 975 for (int i = 0; i < nBits; i++) { 976 if (maskBits[i] == 0) { 977 colorBits[i] |= 0xff000000; 978 } 979 } 980 } 981 // Release DC 982 ReleaseDC(NULL, dc); 983 // Create java array 984 iconBits = env->NewIntArray(nBits); 985 if (!(env->ExceptionCheck())) { 986 // Copy values to java array 987 env->SetIntArrayRegion(iconBits, 0, nBits, colorBits); 988 } 989 } 990 // Fix 4745575 GDI Resource Leak 991 // MSDN 992 // GetIconInfo creates bitmaps for the hbmMask and hbmColor members of ICONINFO. 993 // The calling application must manage these bitmaps and delete them when they 994 // are no longer necessary. 995 ::DeleteObject(iconInfo.hbmColor); 996 ::DeleteObject(iconInfo.hbmMask); 997 } 998 return iconBits; 999 } 1000 1001 /* 1002 * Class: sun_awt_shell_Win32ShellFolder2 1003 * Method: getStandardViewButton0 1004 * Signature: (I)[I 1005 */ 1006 JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getStandardViewButton0 1007 (JNIEnv* env, jclass cls, jint iconIndex) 1008 { 1009 jintArray result = NULL; 1010 1011 // Create a toolbar 1012 HWND hWndToolbar = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, 1013 0, 0, 0, 0, 0, 1014 NULL, NULL, NULL, NULL); 1015 1016 if (hWndToolbar != NULL) { 1017 SendMessage(hWndToolbar, TB_LOADIMAGES, (WPARAM)IDB_VIEW_SMALL_COLOR, (LPARAM)HINST_COMMCTRL); 1018 1019 HIMAGELIST hImageList = (HIMAGELIST) SendMessage(hWndToolbar, TB_GETIMAGELIST, 0, 0); 1020 1021 if (hImageList != NULL) { 1022 HICON hIcon = ImageList_GetIcon(hImageList, iconIndex, ILD_TRANSPARENT); 1023 1024 if (hIcon != NULL) { 1025 result = Java_sun_awt_shell_Win32ShellFolder2_getIconBits(env, cls, ptr_to_jlong(hIcon), 16); 1026 1027 DestroyIcon(hIcon); 1028 } 1029 1030 ImageList_Destroy(hImageList); 1031 } 1032 1033 DestroyWindow(hWndToolbar); 1034 } 1035 1036 return result; 1037 } 1038 1039 /* 1040 * Class: sun_awt_shell_Win32ShellFolder2 1041 * Method: getSystemIcon 1042 * Signature: (I)J 1043 */ 1044 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getSystemIcon 1045 (JNIEnv* env, jclass cls, jint iconID) 1046 { 1047 return (jlong)LoadIcon(NULL, MAKEINTRESOURCE(iconID)); 1048 } 1049 1050 1051 /* 1052 * Class: sun_awt_shell_Win32ShellFolder2 1053 * Method: getIconResource 1054 * Signature: (Ljava/lang/String;IIIZ)J 1055 */ 1056 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconResource 1057 (JNIEnv* env, jclass cls, jstring libName, jint iconID, 1058 jint cxDesired, jint cyDesired, jboolean useVGAColors) 1059 { 1060 const char *pLibName = env->GetStringUTFChars(libName, NULL); 1061 JNU_CHECK_EXCEPTION_RETURN(env, 0); 1062 HINSTANCE libHandle = (HINSTANCE)JDK_LoadSystemLibrary(pLibName); 1063 if (libHandle != NULL) { 1064 UINT fuLoad = (useVGAColors && !IS_WINXP) ? LR_VGACOLOR : 0; 1065 return ptr_to_jlong(LoadImage(libHandle, MAKEINTRESOURCE(iconID), 1066 IMAGE_ICON, cxDesired, cyDesired, 1067 fuLoad)); 1068 } 1069 return 0; 1070 } 1071 1072 1073 /* 1074 * Helper function for creating Java column info object 1075 */ 1076 static jobject CreateColumnInfo(JNIEnv *pEnv, 1077 jclass *pClass, jmethodID *pConstructor, 1078 SHELLDETAILS *psd, ULONG visible) 1079 { 1080 jstring str = jstringFromSTRRET(pEnv, NULL, &(psd->str)); 1081 JNU_CHECK_EXCEPTION_RETURN(pEnv, NULL); 1082 1083 return pEnv->NewObject(*pClass, *pConstructor, 1084 str, 1085 (jint)(psd->cxChar * 6), // TODO: is 6 OK for converting chars to pixels? 1086 (jint)psd->fmt, (jboolean) visible); 1087 } 1088 1089 1090 /* 1091 * Class: sun_awt_shell_Win32ShellFolder2 1092 * Method: doGetColumnInfo 1093 * Signature: (J)[Lsun/awt/shell/ShellFolderColumnInfo; 1094 */ 1095 JNIEXPORT jobjectArray JNICALL 1096 Java_sun_awt_shell_Win32ShellFolder2_doGetColumnInfo 1097 (JNIEnv *env, jobject obj, jlong iShellFolder) 1098 { 1099 1100 HRESULT hr; 1101 IShellFolder *pIShellFolder = (IShellFolder*) iShellFolder; 1102 IUnknown *pIUnknown = NULL; 1103 1104 jclass columnClass = env->FindClass("sun/awt/shell/ShellFolderColumnInfo"); 1105 if(NULL == columnClass) { 1106 return NULL; 1107 } 1108 1109 jmethodID columnConstructor = 1110 env->GetMethodID(columnClass, "<init>", "(Ljava/lang/String;IIZ)V"); 1111 if(NULL == columnConstructor) { 1112 return NULL; 1113 } 1114 1115 // We'are asking the object the list of available columns 1116 SHELLDETAILS sd; 1117 1118 hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown); 1119 if(SUCCEEDED (hr)) { 1120 1121 // The folder exposes IShellFolder2 interface 1122 IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown; 1123 1124 // Count columns 1125 int colNum = -1; 1126 hr = S_OK; 1127 do{ 1128 hr = pIShellFolder2->GetDetailsOf(NULL, ++colNum, &sd); 1129 } while (SUCCEEDED (hr)); 1130 1131 jobjectArray columns = 1132 env->NewObjectArray((jsize) colNum, columnClass, NULL); 1133 if(NULL == columns) { 1134 pIShellFolder2->Release(); 1135 return NULL; 1136 } 1137 1138 // Fill column details list 1139 SHCOLSTATEF csFlags; 1140 colNum = 0; 1141 hr = S_OK; 1142 while (SUCCEEDED (hr)) { 1143 hr = pIShellFolder2->GetDetailsOf(NULL, colNum, &sd); 1144 1145 if (SUCCEEDED (hr)) { 1146 hr = pIShellFolder2->GetDefaultColumnState(colNum, &csFlags); 1147 if (SUCCEEDED (hr)) { 1148 if(!(csFlags & SHCOLSTATE_HIDDEN)) { 1149 jobject column = CreateColumnInfo(env, 1150 &columnClass, &columnConstructor, 1151 &sd, csFlags & SHCOLSTATE_ONBYDEFAULT); 1152 if(!column){ 1153 pIShellFolder2->Release(); 1154 return NULL; 1155 } 1156 env->SetObjectArrayElement(columns, (jsize) colNum, column); 1157 } 1158 } 1159 colNum++; 1160 } 1161 } 1162 1163 pIShellFolder2->Release(); 1164 1165 return columns; 1166 } 1167 1168 hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown); 1169 if(SUCCEEDED (hr)) { 1170 // The folder exposes IShellDetails interface 1171 IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown; 1172 1173 // Count columns 1174 int colNum = -1; 1175 hr = S_OK; 1176 do{ 1177 hr = pIShellDetails->GetDetailsOf(NULL, ++colNum, &sd); 1178 } while (SUCCEEDED (hr)); 1179 1180 jobjectArray columns = 1181 env->NewObjectArray((jsize) colNum, columnClass, NULL); 1182 if(NULL == columns) { 1183 pIShellDetails->Release(); 1184 return NULL; 1185 } 1186 1187 // Fill column details list 1188 colNum = 0; 1189 hr = S_OK; 1190 while (SUCCEEDED (hr)) { 1191 hr = pIShellDetails->GetDetailsOf(NULL, colNum, &sd); 1192 if (SUCCEEDED (hr)) { 1193 jobject column = CreateColumnInfo(env, 1194 &columnClass, &columnConstructor, 1195 &sd, 1); 1196 if(!column){ 1197 pIShellDetails->Release(); 1198 return NULL; 1199 } 1200 env->SetObjectArrayElement(columns, (jsize) colNum++, column); 1201 } 1202 } 1203 1204 pIShellDetails->Release(); 1205 1206 return columns; 1207 } 1208 1209 // The folder exposes neither IShellFolder2 nor IShelDetails 1210 return NULL; 1211 1212 } 1213 1214 /* 1215 * Class: sun_awt_shell_Win32ShellFolder2 1216 * Method: doGetColumnValue 1217 * Signature: (JJI)Ljava/lang/Object; 1218 */ 1219 JNIEXPORT jobject JNICALL 1220 Java_sun_awt_shell_Win32ShellFolder2_doGetColumnValue 1221 (JNIEnv *env, jobject obj, jlong iShellFolder, 1222 jlong jpidl, jint columnIdx) 1223 { 1224 1225 HRESULT hr; 1226 IShellFolder *pIShellFolder = (IShellFolder*) iShellFolder; 1227 IUnknown *pIUnknown = NULL; 1228 1229 1230 LPITEMIDLIST pidl = (LPITEMIDLIST) jpidl; 1231 SHELLDETAILS sd; 1232 1233 hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown); 1234 if(SUCCEEDED (hr)) { 1235 // The folder exposes IShellFolder2 interface 1236 IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown; 1237 hr = pIShellFolder2->GetDetailsOf(pidl, (UINT)columnIdx, &sd); 1238 pIShellFolder2->Release(); 1239 if (SUCCEEDED (hr)) { 1240 STRRET strRet = sd.str; 1241 return jstringFromSTRRET(env, pidl, &strRet); 1242 } 1243 } 1244 1245 hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown); 1246 if(SUCCEEDED (hr)) { 1247 // The folder exposes IShellDetails interface 1248 IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown; 1249 hr = pIShellDetails->GetDetailsOf(pidl, (UINT)columnIdx, &sd); 1250 pIShellDetails->Release(); 1251 if (SUCCEEDED (hr)) { 1252 STRRET strRet = sd.str; 1253 return jstringFromSTRRET(env, pidl, &strRet); 1254 } 1255 } 1256 1257 // The folder exposes neither IShellFolder2 nor IShelDetails 1258 return NULL; 1259 } 1260 1261 /* 1262 * Class: sun_awt_shell_Win32ShellFolder2 1263 * Method: compareIDsByColumn 1264 * Signature: (JJJI)I 1265 */ 1266 JNIEXPORT jint JNICALL 1267 Java_sun_awt_shell_Win32ShellFolder2_compareIDsByColumn 1268 (JNIEnv* env, jclass cls, jlong jpParentIShellFolder, 1269 jlong pIDL1, jlong pIDL2, jint columnIdx) 1270 { 1271 IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder; 1272 if (pParentIShellFolder == NULL) { 1273 return 0; 1274 } 1275 1276 HRESULT hr = pParentIShellFolder->CompareIDs( 1277 (UINT) columnIdx, 1278 (LPCITEMIDLIST) pIDL1, 1279 (LPCITEMIDLIST) pIDL2); 1280 if (SUCCEEDED (hr)) { 1281 return (jint) (short) HRESULT_CODE(hr); 1282 } 1283 1284 return 0; 1285 } 1286 1287 /* 1288 * Class: sun_awt_shell_Win32ShellFolder2 1289 * Method: loadKnownFolders 1290 * Signature: (V)[BLsun/awt/shell/Win32ShellFolder2$KnownfolderDefenition; 1291 */ 1292 JNIEXPORT jobjectArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_loadKnownFolders 1293 (JNIEnv* env, jclass cls ) 1294 { 1295 IKnownFolderManager* pkfm = NULL; 1296 HRESULT hr = CoCreateInstance(CLSID_KnownFolderManager, NULL, 1297 CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pkfm)); 1298 if (!SUCCEEDED(hr)) return NULL; 1299 1300 TRY; 1301 1302 jclass cl = env->FindClass("sun/awt/shell/Win32ShellFolder2$KnownFolderDefinition"); 1303 CHECK_NULL_RETURN(cl, NULL); 1304 DEFINE_FIELD_ID(field_guid, cl, "guid", "Ljava/lang/String;") 1305 DEFINE_FIELD_ID(field_name, cl, "name", "Ljava/lang/String;"); 1306 DEFINE_FIELD_ID(field_description, cl, "description", "Ljava/lang/String;"); 1307 DEFINE_FIELD_ID(field_parent, cl, "parent", "Ljava/lang/String;"); 1308 DEFINE_FIELD_ID(field_relativePath, cl, "relativePath", "Ljava/lang/String;"); 1309 DEFINE_FIELD_ID(field_parsingName, cl, "parsingName", "Ljava/lang/String;"); 1310 DEFINE_FIELD_ID(field_tooltip, cl, "tooltip", "Ljava/lang/String;"); 1311 DEFINE_FIELD_ID(field_localizedName, cl, "localizedName", "Ljava/lang/String;"); 1312 DEFINE_FIELD_ID(field_icon, cl, "icon", "Ljava/lang/String;"); 1313 DEFINE_FIELD_ID(field_security, cl, "security", "Ljava/lang/String;"); 1314 DEFINE_FIELD_ID(field_path, cl, "path", "Ljava/lang/String;"); 1315 DEFINE_FIELD_ID(field_saveLocation, cl, "saveLocation", "Ljava/lang/String;"); 1316 DEFINE_FIELD_ID(field_category, cl, "category", "I"); 1317 DEFINE_FIELD_ID(field_attributes, cl, "attributes", "J"); 1318 DEFINE_FIELD_ID(field_defenitionFlags, cl, "defenitionFlags", "I"); 1319 DEFINE_FIELD_ID(field_ftidType, cl, "ftidType", "Ljava/lang/String;"); 1320 1321 jobjectArray result; 1322 KNOWNFOLDERID* pFoldersIds = NULL; 1323 UINT count = 0; 1324 if (SUCCEEDED(pkfm->GetFolderIds(&pFoldersIds, &count))) { 1325 jmethodID initMethod; 1326 try { 1327 result = env->NewObjectArray(count, cl, NULL); 1328 initMethod = env->GetMethodID(cl, "<init>", "()V"); 1329 EXCEPTION_CHECK 1330 } catch (std::bad_alloc&) { 1331 CoTaskMemFree(pFoldersIds); 1332 pkfm->Release(); 1333 throw; 1334 } 1335 for(UINT i = 0; i < count; ++i) 1336 { 1337 jobject fld; 1338 const KNOWNFOLDERID& folderId = pFoldersIds[i]; 1339 LPOLESTR guid = NULL; 1340 try { 1341 fld = env->NewObject(cl, initMethod); 1342 if (fld) { 1343 env->SetObjectArrayElement(result, i, fld); 1344 } 1345 EXCEPTION_CHECK 1346 1347 if (SUCCEEDED(StringFromCLSID(folderId, &guid))) { 1348 jstring jstr = JNU_NewStringPlatform(env, guid); 1349 if (jstr) { 1350 env->SetObjectField(fld, field_guid, jstr); 1351 } 1352 CoTaskMemFree(guid); 1353 EXCEPTION_CHECK 1354 } 1355 } catch (std::bad_alloc&) { 1356 CoTaskMemFree(pFoldersIds); 1357 pkfm->Release(); 1358 throw; 1359 } 1360 1361 IKnownFolder* pFolder = NULL; 1362 if (SUCCEEDED(pkfm->GetFolder(folderId, &pFolder))) { 1363 KNOWNFOLDER_DEFINITION kfDef; 1364 if (SUCCEEDED(pFolder->GetFolderDefinition(&kfDef))) 1365 { 1366 try { 1367 jstring jstr = JNU_NewStringPlatform(env, kfDef.pszName); 1368 if(jstr) { 1369 env->SetObjectField(fld, field_name, jstr); 1370 } 1371 EXCEPTION_CHECK 1372 if (kfDef.pszDescription) { 1373 jstr = JNU_NewStringPlatform(env, kfDef.pszDescription); 1374 if (jstr) { 1375 env->SetObjectField(fld, field_description, jstr); 1376 } 1377 EXCEPTION_CHECK 1378 } 1379 EXCEPTION_CHECK 1380 if (SUCCEEDED(StringFromCLSID(kfDef.fidParent, &guid))) { 1381 jstr = JNU_NewStringPlatform(env, guid); 1382 if (jstr) { 1383 env->SetObjectField(fld, field_parent, jstr); 1384 } 1385 CoTaskMemFree(guid); 1386 EXCEPTION_CHECK 1387 } 1388 if (kfDef.pszRelativePath) { 1389 jstr = JNU_NewStringPlatform(env, kfDef.pszRelativePath); 1390 if (jstr) { 1391 env->SetObjectField(fld, field_relativePath, jstr); 1392 } 1393 EXCEPTION_CHECK 1394 } 1395 if (kfDef.pszParsingName) { 1396 jstr = JNU_NewStringPlatform(env, kfDef.pszParsingName); 1397 if (jstr) { 1398 env->SetObjectField(fld, field_parsingName, jstr); 1399 } 1400 EXCEPTION_CHECK 1401 } 1402 if (kfDef.pszTooltip) { 1403 jstr = JNU_NewStringPlatform(env, kfDef.pszTooltip); 1404 if (jstr) { 1405 env->SetObjectField(fld, field_tooltip, jstr); 1406 } 1407 EXCEPTION_CHECK 1408 } 1409 if (kfDef.pszLocalizedName) { 1410 jstr = JNU_NewStringPlatform(env, kfDef.pszLocalizedName); 1411 if (jstr) { 1412 env->SetObjectField(fld, field_localizedName, jstr); 1413 } 1414 EXCEPTION_CHECK 1415 } 1416 if (kfDef.pszIcon) { 1417 jstr = JNU_NewStringPlatform(env, kfDef.pszIcon); 1418 if (jstr) { 1419 env->SetObjectField(fld, field_icon, jstr); 1420 } 1421 EXCEPTION_CHECK 1422 } 1423 if (kfDef.pszSecurity) { 1424 jstr = JNU_NewStringPlatform(env, kfDef.pszSecurity); 1425 if (jstr) { 1426 env->SetObjectField(fld, field_security, jstr); 1427 } 1428 EXCEPTION_CHECK 1429 } 1430 if (SUCCEEDED(StringFromCLSID(kfDef.ftidType, &guid))) { 1431 jstr = JNU_NewStringPlatform(env, guid); 1432 if (jstr) { 1433 env->SetObjectField(fld, field_ftidType, jstr); 1434 } 1435 CoTaskMemFree(guid); 1436 EXCEPTION_CHECK 1437 } 1438 env->SetIntField(fld, field_category, kfDef.category); 1439 env->SetIntField(fld, field_defenitionFlags, kfDef.kfdFlags); 1440 env->SetLongField(fld, field_attributes, kfDef.dwAttributes); 1441 1442 LPWSTR folderPath = NULL; 1443 if (SUCCEEDED(pFolder->GetPath(KF_FLAG_NO_ALIAS, &folderPath)) 1444 && folderPath) { 1445 jstr = JNU_NewStringPlatform(env, folderPath); 1446 if (jstr) { 1447 env->SetObjectField(fld, field_path, jstr); 1448 } 1449 CoTaskMemFree(folderPath); 1450 EXCEPTION_CHECK 1451 } 1452 1453 IShellLibrary *plib = NULL; 1454 hr = CoCreateInstance(CLSID_ShellLibrary, NULL, 1455 CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&plib)); 1456 if (SUCCEEDED(hr)) { 1457 hr = plib->LoadLibraryFromKnownFolder(folderId, STGM_READWRITE); 1458 if (SUCCEEDED(hr)) { 1459 IShellItem *item = NULL; 1460 hr = plib->GetDefaultSaveFolder(DSFT_DETECT, 1461 IID_PPV_ARGS(&item)); 1462 if (SUCCEEDED(hr) && item) { 1463 LPWSTR loc = NULL; 1464 hr = item->GetDisplayName(SIGDN_FILESYSPATH, &loc); 1465 if (SUCCEEDED(hr) && loc) 1466 { 1467 jstr = JNU_NewStringPlatform(env, loc); 1468 if (jstr) { 1469 env->SetObjectField(fld, field_saveLocation, jstr); 1470 } 1471 CoTaskMemFree(loc); 1472 } 1473 item->Release(); 1474 } 1475 } 1476 plib->Release(); 1477 EXCEPTION_CHECK 1478 } 1479 FreeKnownFolderDefinitionFields(&kfDef); 1480 } catch (std::bad_alloc&) { 1481 FreeKnownFolderDefinitionFields(&kfDef); 1482 pFolder->Release(); 1483 CoTaskMemFree(pFoldersIds); 1484 pkfm->Release(); 1485 throw; 1486 } 1487 } 1488 } 1489 pFolder->Release(); 1490 } 1491 CoTaskMemFree(pFoldersIds); 1492 } 1493 pkfm->Release(); 1494 return result; 1495 CATCH_BAD_ALLOC_RET(NULL); 1496 } 1497 1498 } // extern "C" --- EOF ---