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