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