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