annotate src/windows/native/sun/windows/ShellFolder2.cpp @ 903:75755e92430c

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