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