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