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