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