annotate src/windows/native/sun/windows/ShellFolder2.cpp @ 1133:51148b9aed43

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