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 jint size, 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 hres = pIcon->Extract(szBuf, index, &hIcon, 0, size); 945 } else if (hres == E_PENDING) { 946 pIcon->Release(); 947 return E_PENDING; 948 } 949 pIcon->Release(); 950 } 951 return (jlong)hIcon; 952 } 953 954 955 /* 956 * Class: sun_awt_shell_Win32ShellFolder2 957 * Method: disposeIcon 958 * Signature: (J)V 959 */ 960 JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_disposeIcon 961 (JNIEnv* env, jclass cls, jlong hicon) 962 { 963 fn_DestroyIcon((HICON)hicon); 964 } 965 966 /* 967 * Class: sun_awt_shell_Win32ShellFolder2 968 * Method: getIconBits 969 * Signature: (J)[I 970 */ 971 JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconBits 972 (JNIEnv* env, jclass cls, jlong hicon) 973 { 974 const int MAX_ICON_SIZE = 128; 975 int iconSize = 0; 976 jintArray iconBits = NULL; 977 978 BITMAP bmp; 979 memset(&bmp, 0, sizeof(BITMAP)); 980 981 // Get the icon info 982 ICONINFO iconInfo; 983 if (fn_GetIconInfo((HICON)hicon, &iconInfo)) { 984 // Get the screen DC 985 HDC dc = GetDC(NULL); 986 if (dc != NULL) { 987 // find out the icon size in order to deal with different sizes 988 // delivered depending on HiDPI mode or SD DPI mode. 989 if (iconInfo.hbmColor) { 990 const int nWrittenBytes = GetObject(iconInfo.hbmColor, sizeof(bmp), &bmp); 991 if(nWrittenBytes > 0) { 992 iconSize = bmp.bmWidth; 993 } 994 } else if (iconInfo.hbmMask) { 995 // Icon has no color plane, image data stored in mask 996 const int nWrittenBytes = GetObject(iconInfo.hbmMask, sizeof(bmp), &bmp); 997 if (nWrittenBytes > 0) { 998 iconSize = bmp.bmWidth; 999 } 1000 } 1001 // limit iconSize to MAX_ICON_SIZE, so that the colorBits and maskBits 1002 // arrays are big enough. 1003 // (logic: rather show bad icons than overrun the array size) 1004 iconSize = iconSize > MAX_ICON_SIZE ? MAX_ICON_SIZE : iconSize; 1005 1006 // Set up BITMAPINFO 1007 BITMAPINFO bmi; 1008 memset(&bmi, 0, sizeof(BITMAPINFO)); 1009 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 1010 bmi.bmiHeader.biWidth = iconSize; 1011 bmi.bmiHeader.biHeight = -iconSize; 1012 bmi.bmiHeader.biPlanes = 1; 1013 bmi.bmiHeader.biBitCount = 32; 1014 bmi.bmiHeader.biCompression = BI_RGB; 1015 // Extract the color bitmap 1016 int nBits = iconSize * iconSize; 1017 long colorBits[MAX_ICON_SIZE * MAX_ICON_SIZE]; 1018 GetDIBits(dc, iconInfo.hbmColor, 0, iconSize, colorBits, &bmi, DIB_RGB_COLORS); 1019 // XP supports alpha in some icons, and depending on device. 1020 // This should take precedence over the icon mask bits. 1021 BOOL hasAlpha = FALSE; 1022 if (IS_WINXP) { 1023 for (int i = 0; i < nBits; i++) { 1024 if ((colorBits[i] & 0xff000000) != 0) { 1025 hasAlpha = TRUE; 1026 break; 1027 } 1028 } 1029 } 1030 if (!hasAlpha) { 1031 // Extract the mask bitmap 1032 long maskBits[MAX_ICON_SIZE * MAX_ICON_SIZE]; 1033 GetDIBits(dc, iconInfo.hbmMask, 0, iconSize, maskBits, &bmi, DIB_RGB_COLORS); 1034 // Copy the mask alphas into the color bits 1035 for (int i = 0; i < nBits; i++) { 1036 if (maskBits[i] == 0) { 1037 colorBits[i] |= 0xff000000; 1038 } 1039 } 1040 } 1041 // Release DC 1042 ReleaseDC(NULL, dc); 1043 // Create java array 1044 iconBits = env->NewIntArray(nBits); 1045 if (!(env->ExceptionCheck())) { 1046 // Copy values to java array 1047 env->SetIntArrayRegion(iconBits, 0, nBits, colorBits); 1048 } 1049 } 1050 // Fix 4745575 GDI Resource Leak 1051 // MSDN 1052 // GetIconInfo creates bitmaps for the hbmMask and hbmColor members of ICONINFO. 1053 // The calling application must manage these bitmaps and delete them when they 1054 // are no longer necessary. 1055 ::DeleteObject(iconInfo.hbmColor); 1056 ::DeleteObject(iconInfo.hbmMask); 1057 } 1058 return iconBits; 1059 } 1060 1061 /* 1062 * Class: sun_awt_shell_Win32ShellFolder2 1063 * Method: getStandardViewButton0 1064 * Signature: (IZ)[I 1065 */ 1066 JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getStandardViewButton0 1067 (JNIEnv* env, jclass cls, jint iconIndex, jboolean smallIcon) 1068 { 1069 jintArray result = NULL; 1070 1071 // Create a toolbar 1072 HWND hWndToolbar = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, 1073 0, 0, 0, 0, 0, 1074 NULL, NULL, NULL, NULL); 1075 1076 if (hWndToolbar != NULL) { 1077 WPARAM size = smallIcon ? (WPARAM)IDB_VIEW_SMALL_COLOR : (WPARAM)IDB_VIEW_LARGE_COLOR; 1078 SendMessage(hWndToolbar, TB_LOADIMAGES, size, (LPARAM)HINST_COMMCTRL); 1079 1080 HIMAGELIST hImageList = (HIMAGELIST) SendMessage(hWndToolbar, TB_GETIMAGELIST, 0, 0); 1081 1082 if (hImageList != NULL) { 1083 HICON hIcon = ImageList_GetIcon(hImageList, iconIndex, ILD_TRANSPARENT); 1084 1085 if (hIcon != NULL) { 1086 result = Java_sun_awt_shell_Win32ShellFolder2_getIconBits(env, cls, ptr_to_jlong(hIcon)); 1087 1088 DestroyIcon(hIcon); 1089 } 1090 1091 ImageList_Destroy(hImageList); 1092 } 1093 1094 DestroyWindow(hWndToolbar); 1095 } 1096 1097 return result; 1098 } 1099 1100 /* 1101 * Class: sun_awt_shell_Win32ShellFolder2 1102 * Method: getSystemIcon 1103 * Signature: (I)J 1104 */ 1105 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getSystemIcon 1106 (JNIEnv* env, jclass cls, jint iconID) 1107 { 1108 return (jlong)LoadIcon(NULL, MAKEINTRESOURCE(iconID)); 1109 } 1110 1111 1112 /* 1113 * Class: sun_awt_shell_Win32ShellFolder2 1114 * Method: getIconResource 1115 * Signature: (Ljava/lang/String;IIIZ)J 1116 */ 1117 JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconResource 1118 (JNIEnv* env, jclass cls, jstring libName, jint iconID, 1119 jint cxDesired, jint cyDesired, jboolean useVGAColors) 1120 { 1121 const char *pLibName = env->GetStringUTFChars(libName, NULL); 1122 JNU_CHECK_EXCEPTION_RETURN(env, 0); 1123 HINSTANCE libHandle = (HINSTANCE)JDK_LoadSystemLibrary(pLibName); 1124 if (libHandle != NULL) { 1125 UINT fuLoad = (useVGAColors && !IS_WINXP) ? LR_VGACOLOR : 0; 1126 return ptr_to_jlong(LoadImage(libHandle, MAKEINTRESOURCE(iconID), 1127 IMAGE_ICON, cxDesired, cyDesired, 1128 fuLoad)); 1129 } 1130 return 0; 1131 } 1132 1133 1134 /* 1135 * Helper function for creating Java column info object 1136 */ 1137 static jobject CreateColumnInfo(JNIEnv *pEnv, 1138 jclass *pClass, jmethodID *pConstructor, 1139 int colNum, SHELLDETAILS *psd, ULONG visible) 1140 { 1141 jstring str = jstringFromSTRRET(pEnv, NULL, &(psd->str)); 1142 JNU_CHECK_EXCEPTION_RETURN(pEnv, NULL); 1143 1144 // Convert ShellFolder column names to locale-sensitive names 1145 if (colNum == 0) { 1146 str = lsName; 1147 } else if (colNum == 1) { 1148 str = lsSize; 1149 } else if (colNum == 2) { 1150 str = lsType; 1151 } else if (colNum == 3) { 1152 str = lsDate; 1153 } 1154 return pEnv->NewObject(*pClass, *pConstructor, 1155 str, 1156 (jint)(psd->cxChar * 6), // TODO: is 6 OK for converting chars to pixels? 1157 (jint)psd->fmt, (jboolean) visible); 1158 } 1159 1160 1161 /* 1162 * Class: sun_awt_shell_Win32ShellFolder2 1163 * Method: doGetColumnInfo 1164 * Signature: (J)[Lsun/awt/shell/ShellFolderColumnInfo; 1165 */ 1166 JNIEXPORT jobjectArray JNICALL 1167 Java_sun_awt_shell_Win32ShellFolder2_doGetColumnInfo 1168 (JNIEnv *env, jobject obj, jlong iShellFolder) 1169 { 1170 1171 HRESULT hr; 1172 IShellFolder *pIShellFolder = (IShellFolder*) iShellFolder; 1173 IUnknown *pIUnknown = NULL; 1174 1175 jclass columnClass = env->FindClass("sun/awt/shell/ShellFolderColumnInfo"); 1176 if(NULL == columnClass) { 1177 return NULL; 1178 } 1179 1180 jmethodID columnConstructor = 1181 env->GetMethodID(columnClass, "<init>", "(Ljava/lang/String;IIZ)V"); 1182 if(NULL == columnConstructor) { 1183 return NULL; 1184 } 1185 1186 // We'are asking the object the list of available columns 1187 SHELLDETAILS sd; 1188 1189 hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown); 1190 if(SUCCEEDED (hr)) { 1191 1192 // The folder exposes IShellFolder2 interface 1193 IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown; 1194 1195 // Count columns 1196 int colNum = -1; 1197 hr = S_OK; 1198 do{ 1199 hr = pIShellFolder2->GetDetailsOf(NULL, ++colNum, &sd); 1200 } while (SUCCEEDED (hr)); 1201 1202 jobjectArray columns = 1203 env->NewObjectArray((jsize) colNum, columnClass, NULL); 1204 if(NULL == columns) { 1205 pIShellFolder2->Release(); 1206 return NULL; 1207 } 1208 1209 // Fill column details list 1210 SHCOLSTATEF csFlags; 1211 colNum = 0; 1212 hr = S_OK; 1213 while (SUCCEEDED (hr)) { 1214 hr = pIShellFolder2->GetDetailsOf(NULL, colNum, &sd); 1215 1216 if (SUCCEEDED (hr)) { 1217 hr = pIShellFolder2->GetDefaultColumnState(colNum, &csFlags); 1218 if (SUCCEEDED (hr)) { 1219 if(!(csFlags & SHCOLSTATE_HIDDEN)) { 1220 jobject column = CreateColumnInfo(env, 1221 &columnClass, &columnConstructor, 1222 colNum, &sd, csFlags & SHCOLSTATE_ONBYDEFAULT); 1223 if(!column){ 1224 pIShellFolder2->Release(); 1225 return NULL; 1226 } 1227 env->SetObjectArrayElement(columns, (jsize) colNum, column); 1228 } 1229 } 1230 colNum++; 1231 } 1232 } 1233 1234 pIShellFolder2->Release(); 1235 1236 return columns; 1237 } 1238 1239 hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown); 1240 if(SUCCEEDED (hr)) { 1241 // The folder exposes IShellDetails interface 1242 IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown; 1243 1244 // Count columns 1245 int colNum = -1; 1246 hr = S_OK; 1247 do{ 1248 hr = pIShellDetails->GetDetailsOf(NULL, ++colNum, &sd); 1249 } while (SUCCEEDED (hr)); 1250 1251 jobjectArray columns = 1252 env->NewObjectArray((jsize) colNum, columnClass, NULL); 1253 if(NULL == columns) { 1254 pIShellDetails->Release(); 1255 return NULL; 1256 } 1257 1258 // Fill column details list 1259 colNum = 0; 1260 hr = S_OK; 1261 while (SUCCEEDED (hr)) { 1262 hr = pIShellDetails->GetDetailsOf(NULL, colNum, &sd); 1263 if (SUCCEEDED (hr)) { 1264 jobject column = CreateColumnInfo(env, 1265 &columnClass, &columnConstructor, 1266 colNum, &sd, 1); 1267 if(!column){ 1268 pIShellDetails->Release(); 1269 return NULL; 1270 } 1271 env->SetObjectArrayElement(columns, (jsize) colNum++, column); 1272 } 1273 } 1274 1275 pIShellDetails->Release(); 1276 1277 return columns; 1278 } 1279 1280 // The folder exposes neither IShellFolder2 nor IShelDetails 1281 return NULL; 1282 1283 } 1284 1285 /* 1286 * Class: sun_awt_shell_Win32ShellFolder2 1287 * Method: doGetColumnValue 1288 * Signature: (JJI)Ljava/lang/Object; 1289 */ 1290 JNIEXPORT jobject JNICALL 1291 Java_sun_awt_shell_Win32ShellFolder2_doGetColumnValue 1292 (JNIEnv *env, jobject obj, jlong iShellFolder, 1293 jlong jpidl, jint columnIdx) 1294 { 1295 1296 HRESULT hr; 1297 IShellFolder *pIShellFolder = (IShellFolder*) iShellFolder; 1298 IUnknown *pIUnknown = NULL; 1299 1300 1301 LPITEMIDLIST pidl = (LPITEMIDLIST) jpidl; 1302 SHELLDETAILS sd; 1303 1304 hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown); 1305 if(SUCCEEDED (hr)) { 1306 // The folder exposes IShellFolder2 interface 1307 IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown; 1308 hr = pIShellFolder2->GetDetailsOf(pidl, (UINT)columnIdx, &sd); 1309 pIShellFolder2->Release(); 1310 if (SUCCEEDED (hr)) { 1311 STRRET strRet = sd.str; 1312 return jstringFromSTRRET(env, pidl, &strRet); 1313 } 1314 } 1315 1316 hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown); 1317 if(SUCCEEDED (hr)) { 1318 // The folder exposes IShellDetails interface 1319 IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown; 1320 hr = pIShellDetails->GetDetailsOf(pidl, (UINT)columnIdx, &sd); 1321 pIShellDetails->Release(); 1322 if (SUCCEEDED (hr)) { 1323 STRRET strRet = sd.str; 1324 return jstringFromSTRRET(env, pidl, &strRet); 1325 } 1326 } 1327 1328 // The folder exposes neither IShellFolder2 nor IShelDetails 1329 return NULL; 1330 } 1331 1332 /* 1333 * Class: sun_awt_shell_Win32ShellFolder2 1334 * Method: compareIDsByColumn 1335 * Signature: (JJJI)I 1336 */ 1337 JNIEXPORT jint JNICALL 1338 Java_sun_awt_shell_Win32ShellFolder2_compareIDsByColumn 1339 (JNIEnv* env, jclass cls, jlong jpParentIShellFolder, 1340 jlong pIDL1, jlong pIDL2, jint columnIdx) 1341 { 1342 IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder; 1343 if (pParentIShellFolder == NULL) { 1344 return 0; 1345 } 1346 1347 HRESULT hr = pParentIShellFolder->CompareIDs( 1348 (UINT) columnIdx, 1349 (LPCITEMIDLIST) pIDL1, 1350 (LPCITEMIDLIST) pIDL2); 1351 if (SUCCEEDED (hr)) { 1352 return (jint) (short) HRESULT_CODE(hr); 1353 } 1354 1355 return 0; 1356 } 1357 1358 /* 1359 * Class: sun_awt_shell_Win32ShellFolder2 1360 * Method: loadKnownFolders 1361 * Signature: (V)[BLsun/awt/shell/Win32ShellFolder2$KnownfolderDefenition; 1362 */ 1363 JNIEXPORT jobjectArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_loadKnownFolders 1364 (JNIEnv* env, jclass cls ) 1365 { 1366 IKnownFolderManager* pkfm = NULL; 1367 HRESULT hr = CoCreateInstance(CLSID_KnownFolderManager, NULL, 1368 CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pkfm)); 1369 if (!SUCCEEDED(hr)) return NULL; 1370 1371 TRY; 1372 1373 jclass cl = env->FindClass("sun/awt/shell/Win32ShellFolder2$KnownFolderDefinition"); 1374 CHECK_NULL_RETURN(cl, NULL); 1375 DEFINE_FIELD_ID(field_guid, cl, "guid", "Ljava/lang/String;") 1376 DEFINE_FIELD_ID(field_name, cl, "name", "Ljava/lang/String;"); 1377 DEFINE_FIELD_ID(field_description, cl, "description", "Ljava/lang/String;"); 1378 DEFINE_FIELD_ID(field_parent, cl, "parent", "Ljava/lang/String;"); 1379 DEFINE_FIELD_ID(field_relativePath, cl, "relativePath", "Ljava/lang/String;"); 1380 DEFINE_FIELD_ID(field_parsingName, cl, "parsingName", "Ljava/lang/String;"); 1381 DEFINE_FIELD_ID(field_tooltip, cl, "tooltip", "Ljava/lang/String;"); 1382 DEFINE_FIELD_ID(field_localizedName, cl, "localizedName", "Ljava/lang/String;"); 1383 DEFINE_FIELD_ID(field_icon, cl, "icon", "Ljava/lang/String;"); 1384 DEFINE_FIELD_ID(field_security, cl, "security", "Ljava/lang/String;"); 1385 DEFINE_FIELD_ID(field_path, cl, "path", "Ljava/lang/String;"); 1386 DEFINE_FIELD_ID(field_saveLocation, cl, "saveLocation", "Ljava/lang/String;"); 1387 DEFINE_FIELD_ID(field_category, cl, "category", "I"); 1388 DEFINE_FIELD_ID(field_attributes, cl, "attributes", "J"); 1389 DEFINE_FIELD_ID(field_defenitionFlags, cl, "defenitionFlags", "I"); 1390 DEFINE_FIELD_ID(field_ftidType, cl, "ftidType", "Ljava/lang/String;"); 1391 1392 jobjectArray result; 1393 KNOWNFOLDERID* pFoldersIds = NULL; 1394 UINT count = 0; 1395 if (SUCCEEDED(pkfm->GetFolderIds(&pFoldersIds, &count))) { 1396 jmethodID initMethod; 1397 try { 1398 result = env->NewObjectArray(count, cl, NULL); 1399 initMethod = env->GetMethodID(cl, "<init>", "()V"); 1400 EXCEPTION_CHECK 1401 } catch (std::bad_alloc&) { 1402 CoTaskMemFree(pFoldersIds); 1403 pkfm->Release(); 1404 throw; 1405 } 1406 for(UINT i = 0; i < count; ++i) 1407 { 1408 jobject fld; 1409 const KNOWNFOLDERID& folderId = pFoldersIds[i]; 1410 LPOLESTR guid = NULL; 1411 try { 1412 fld = env->NewObject(cl, initMethod); 1413 if (fld) { 1414 env->SetObjectArrayElement(result, i, fld); 1415 } 1416 EXCEPTION_CHECK 1417 1418 if (SUCCEEDED(StringFromCLSID(folderId, &guid))) { 1419 jstring jstr = JNU_NewStringPlatform(env, guid); 1420 if (jstr) { 1421 env->SetObjectField(fld, field_guid, jstr); 1422 } 1423 CoTaskMemFree(guid); 1424 EXCEPTION_CHECK 1425 } 1426 } catch (std::bad_alloc&) { 1427 CoTaskMemFree(pFoldersIds); 1428 pkfm->Release(); 1429 throw; 1430 } 1431 1432 IKnownFolder* pFolder = NULL; 1433 if (SUCCEEDED(pkfm->GetFolder(folderId, &pFolder))) { 1434 KNOWNFOLDER_DEFINITION kfDef; 1435 if (SUCCEEDED(pFolder->GetFolderDefinition(&kfDef))) 1436 { 1437 try { 1438 jstring jstr = JNU_NewStringPlatform(env, kfDef.pszName); 1439 if(jstr) { 1440 env->SetObjectField(fld, field_name, jstr); 1441 } 1442 EXCEPTION_CHECK 1443 if (kfDef.pszDescription) { 1444 jstr = JNU_NewStringPlatform(env, kfDef.pszDescription); 1445 if (jstr) { 1446 env->SetObjectField(fld, field_description, jstr); 1447 } 1448 EXCEPTION_CHECK 1449 } 1450 EXCEPTION_CHECK 1451 if (SUCCEEDED(StringFromCLSID(kfDef.fidParent, &guid))) { 1452 jstr = JNU_NewStringPlatform(env, guid); 1453 if (jstr) { 1454 env->SetObjectField(fld, field_parent, jstr); 1455 } 1456 CoTaskMemFree(guid); 1457 EXCEPTION_CHECK 1458 } 1459 if (kfDef.pszRelativePath) { 1460 jstr = JNU_NewStringPlatform(env, kfDef.pszRelativePath); 1461 if (jstr) { 1462 env->SetObjectField(fld, field_relativePath, jstr); 1463 } 1464 EXCEPTION_CHECK 1465 } 1466 if (kfDef.pszParsingName) { 1467 jstr = JNU_NewStringPlatform(env, kfDef.pszParsingName); 1468 if (jstr) { 1469 env->SetObjectField(fld, field_parsingName, jstr); 1470 } 1471 EXCEPTION_CHECK 1472 } 1473 if (kfDef.pszTooltip) { 1474 jstr = JNU_NewStringPlatform(env, kfDef.pszTooltip); 1475 if (jstr) { 1476 env->SetObjectField(fld, field_tooltip, jstr); 1477 } 1478 EXCEPTION_CHECK 1479 } 1480 if (kfDef.pszLocalizedName) { 1481 jstr = JNU_NewStringPlatform(env, kfDef.pszLocalizedName); 1482 if (jstr) { 1483 env->SetObjectField(fld, field_localizedName, jstr); 1484 } 1485 EXCEPTION_CHECK 1486 } 1487 if (kfDef.pszIcon) { 1488 jstr = JNU_NewStringPlatform(env, kfDef.pszIcon); 1489 if (jstr) { 1490 env->SetObjectField(fld, field_icon, jstr); 1491 } 1492 EXCEPTION_CHECK 1493 } 1494 if (kfDef.pszSecurity) { 1495 jstr = JNU_NewStringPlatform(env, kfDef.pszSecurity); 1496 if (jstr) { 1497 env->SetObjectField(fld, field_security, jstr); 1498 } 1499 EXCEPTION_CHECK 1500 } 1501 if (SUCCEEDED(StringFromCLSID(kfDef.ftidType, &guid))) { 1502 jstr = JNU_NewStringPlatform(env, guid); 1503 if (jstr) { 1504 env->SetObjectField(fld, field_ftidType, jstr); 1505 } 1506 CoTaskMemFree(guid); 1507 EXCEPTION_CHECK 1508 } 1509 env->SetIntField(fld, field_category, kfDef.category); 1510 env->SetIntField(fld, field_defenitionFlags, kfDef.kfdFlags); 1511 env->SetLongField(fld, field_attributes, kfDef.dwAttributes); 1512 1513 LPWSTR folderPath = NULL; 1514 if (SUCCEEDED(pFolder->GetPath(KF_FLAG_NO_ALIAS, &folderPath)) 1515 && folderPath) { 1516 jstr = JNU_NewStringPlatform(env, folderPath); 1517 if (jstr) { 1518 env->SetObjectField(fld, field_path, jstr); 1519 } 1520 CoTaskMemFree(folderPath); 1521 EXCEPTION_CHECK 1522 } 1523 1524 IShellLibrary *plib = NULL; 1525 hr = CoCreateInstance(CLSID_ShellLibrary, NULL, 1526 CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&plib)); 1527 if (SUCCEEDED(hr)) { 1528 hr = plib->LoadLibraryFromKnownFolder(folderId, STGM_READWRITE); 1529 if (SUCCEEDED(hr)) { 1530 IShellItem *item = NULL; 1531 hr = plib->GetDefaultSaveFolder(DSFT_DETECT, 1532 IID_PPV_ARGS(&item)); 1533 if (SUCCEEDED(hr) && item) { 1534 LPWSTR loc = NULL; 1535 hr = item->GetDisplayName(SIGDN_FILESYSPATH, &loc); 1536 if (SUCCEEDED(hr) && loc) 1537 { 1538 jstr = JNU_NewStringPlatform(env, loc); 1539 if (jstr) { 1540 env->SetObjectField(fld, field_saveLocation, jstr); 1541 } 1542 CoTaskMemFree(loc); 1543 } 1544 item->Release(); 1545 } 1546 } 1547 plib->Release(); 1548 EXCEPTION_CHECK 1549 } 1550 FreeKnownFolderDefinitionFields(&kfDef); 1551 } catch (std::bad_alloc&) { 1552 FreeKnownFolderDefinitionFields(&kfDef); 1553 pFolder->Release(); 1554 CoTaskMemFree(pFoldersIds); 1555 pkfm->Release(); 1556 throw; 1557 } 1558 } 1559 } 1560 pFolder->Release(); 1561 } 1562 CoTaskMemFree(pFoldersIds); 1563 } 1564 pkfm->Release(); 1565 return result; 1566 CATCH_BAD_ALLOC_RET(NULL); 1567 } 1568 1569 } // extern "C"