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