|
Java example source code file (ShellFolder2.cpp)
This example Java source code file (ShellFolder2.cpp) is included in the alvinalexander.com
"Java Source Code
Warehouse" project. The intent of this project is to help you "Learn
Java by Example" TM.
Learn more about this Java project at its project page.
The ShellFolder2.cpp Java example source code
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#define OEMRESOURCE
#ifdef DEBUG
// Warning : do not depend on anything in <awt.h>. Including this file
// is a fix for 4507525 to use the same operator new and delete as AWT.
// This file should stand independent of AWT and should ultimately be
// put into its own DLL.
#include <awt.h>
#else
// Include jni_util.h first, so JNU_* macros can be redefined
#include "jni_util.h"
// Borrow some macros from awt.h
#define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast<jchar*>(x), static_cast(_tcslen(x)))
#define JNU_GetStringPlatformChars(env, x, y) reinterpret_cast<LPCWSTR>(env->GetStringChars(x, y))
#define JNU_ReleaseStringPlatformChars(env, x, y) env->ReleaseStringChars(x, reinterpret_cast<const jchar*>(y))
#endif // DEBUG
#include <windows.h>
#include <shlobj.h>
#include <shellapi.h>
#include "jlong.h"
#include "alloc.h"
#include "stdhdrs.h"
// Copy from shlguid.h which is no longer in PlatformSDK
#ifndef DEFINE_SHLGUID
#define DEFINE_SHLGUID(name, l, w1, w2) DEFINE_GUID(name, l, w1, w2, 0xC0, 0, 0, 0, 0, 0, 0, 0x46)
#endif
// {93F2F68C-1D1B-11d3-A30E-00C04F79ABD1}
DEFINE_GUID(IID_IShellFolder2, 0x93f2f68c, 0x1d1b, 0x11d3, 0xa3, 0xe, 0x0, 0xc0, 0x4f, 0x79, 0xab, 0xd1);
#undef IID_IShellLinkW
#undef IID_IExtractIconW
// copied from shlguid.h
DEFINE_SHLGUID(IID_IShellLinkW, 0x000214F9L, 0, 0);
DEFINE_SHLGUID(IID_IExtractIconW, 0x000214FAL, 0, 0);
//#include <sun_awt_shell_Win32ShellFolder2.h>
// Shell Functions
typedef BOOL (WINAPI *DestroyIconType)(HICON);
typedef HINSTANCE (WINAPI *FindExecutableType)(LPCTSTR,LPCTSTR,LPTSTR);
typedef HICON (WINAPI *ImageList_GetIconType)(HIMAGELIST,int,UINT);
typedef BOOL (WINAPI *GetIconInfoType)(HICON,PICONINFO);
typedef HRESULT (WINAPI *SHGetDesktopFolderType)(IShellFolder**);
typedef DWORD* (WINAPI *SHGetFileInfoType)(LPCTSTR,DWORD,SHFILEINFO*,UINT,UINT);
typedef HRESULT (WINAPI *SHGetMallocType)(IMalloc**);
typedef BOOL (WINAPI *SHGetPathFromIDListType)(LPCITEMIDLIST,LPTSTR);
typedef HRESULT (WINAPI *SHGetSpecialFolderLocationType)(HWND,int,LPITEMIDLIST*);
static DestroyIconType fn_DestroyIcon;
static FindExecutableType fn_FindExecutable;
static GetIconInfoType fn_GetIconInfo;
static ImageList_GetIconType fn_ImageList_GetIcon;
static SHGetDesktopFolderType fn_SHGetDesktopFolder;
static SHGetFileInfoType fn_SHGetFileInfo;
static SHGetMallocType fn_SHGetMalloc;
static SHGetPathFromIDListType fn_SHGetPathFromIDList;
static SHGetSpecialFolderLocationType fn_SHGetSpecialFolderLocation;
// Field IDs
static jmethodID MID_pIShellFolder;
static jfieldID FID_pIShellIcon;
static jmethodID MID_relativePIDL;
static jfieldID FID_displayName;
static jfieldID FID_folderType;
// Other statics
static IMalloc* pMalloc;
static IShellFolder* pDesktop;
// Some macros from awt.h, because it is not included in release
#ifndef IS_WIN2000
#define IS_WIN2000 (LOBYTE(LOWORD(::GetVersion())) >= 5)
#endif
#ifndef IS_WINXP
#define IS_WINXP ((IS_WIN2000 && HIBYTE(LOWORD(::GetVersion())) >= 1) || LOBYTE(LOWORD(::GetVersion())) > 5)
#endif
#ifndef IS_WINVISTA
#define IS_WINVISTA (!(::GetVersion() & 0x80000000) && LOBYTE(LOWORD(::GetVersion())) >= 6)
#endif
extern "C" {
static BOOL initShellProcs()
{
static HMODULE libShell32 = NULL;
static HMODULE libUser32 = NULL;
static HMODULE libComCtl32 = NULL;
// If already initialized, return TRUE
if (libShell32 != NULL && libUser32 != NULL) {
return TRUE;
}
// Load libraries
libShell32 = JDK_LoadSystemLibrary("shell32.dll");
if (libShell32 == NULL) {
return FALSE;
}
libUser32 = JDK_LoadSystemLibrary("user32.dll");
if (libUser32 == NULL) {
return FALSE;
}
libComCtl32 = JDK_LoadSystemLibrary("comctl32.dll");
if (libComCtl32 == NULL) {
return FALSE;
}
// Set up procs - libComCtl32
fn_ImageList_GetIcon = (ImageList_GetIconType)GetProcAddress(libComCtl32, "ImageList_GetIcon");
if (fn_ImageList_GetIcon == NULL) {
return FALSE;
}
// Set up procs - libShell32
fn_FindExecutable = (FindExecutableType)GetProcAddress(
libShell32, "FindExecutableW");
if (fn_FindExecutable == NULL) {
return FALSE;
}
fn_SHGetDesktopFolder = (SHGetDesktopFolderType)GetProcAddress(libShell32,
"SHGetDesktopFolder");
if (fn_SHGetDesktopFolder == NULL) {
return FALSE;
}
fn_SHGetFileInfo = (SHGetFileInfoType)GetProcAddress(
libShell32, "SHGetFileInfoW");
if (fn_SHGetFileInfo == NULL) {
return FALSE;
}
fn_SHGetMalloc = (SHGetMallocType)GetProcAddress(libShell32,
"SHGetMalloc");
if (fn_SHGetMalloc == NULL) {
return FALSE;
}
// Set up IMalloc
if (fn_SHGetMalloc(&pMalloc) != S_OK) {
return FALSE;
}
fn_SHGetPathFromIDList = (SHGetPathFromIDListType)GetProcAddress(
libShell32, "SHGetPathFromIDListW");
if (fn_SHGetPathFromIDList == NULL) {
return FALSE;
}
fn_SHGetSpecialFolderLocation = (SHGetSpecialFolderLocationType)
GetProcAddress(libShell32, "SHGetSpecialFolderLocation");
if (fn_SHGetSpecialFolderLocation == NULL) {
return FALSE;
}
// Set up procs - libUser32
fn_GetIconInfo = (GetIconInfoType)GetProcAddress(libUser32, "GetIconInfo");
if (fn_GetIconInfo == NULL) {
return FALSE;
}
fn_DestroyIcon = (DestroyIconType)GetProcAddress(libUser32, "DestroyIcon");
if (fn_DestroyIcon == NULL) {
return FALSE;
}
return TRUE;
}
// To call real JNU_NewStringPlatform
#undef JNU_NewStringPlatform
static jstring jstringFromSTRRET(JNIEnv* env, LPITEMIDLIST pidl, STRRET* pStrret) {
switch (pStrret->uType) {
case STRRET_CSTR :
return JNU_NewStringPlatform(env, reinterpret_cast<const char*>(pStrret->cStr));
case STRRET_OFFSET :
// Note : this may need to be WCHAR instead
return JNU_NewStringPlatform(env,
(CHAR*)pidl + pStrret->uOffset);
case STRRET_WSTR :
return env->NewString(reinterpret_cast<const jchar*>(pStrret->pOleStr),
static_cast<jsize>(wcslen(pStrret->pOleStr)));
}
return NULL;
}
// restoring the original definition
#define JNU_NewStringPlatform(env, x) env->NewString(reinterpret_cast<jchar*>(x), static_cast(_tcslen(x)))
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: initIDs
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initIDs
(JNIEnv* env, jclass cls)
{
if (!initShellProcs()) {
JNU_ThrowInternalError(env, "Could not initialize shell library");
return;
}
MID_pIShellFolder = env->GetMethodID(cls, "setIShellFolder", "(J)V");
FID_pIShellIcon = env->GetFieldID(cls, "pIShellIcon", "J");
MID_relativePIDL = env->GetMethodID(cls, "setRelativePIDL", "(J)V");
FID_displayName = env->GetFieldID(cls, "displayName", "Ljava/lang/String;");
FID_folderType = env->GetFieldID(cls, "folderType", "Ljava/lang/String;");
}
/*
* Class: sun_awt_shell_Win32ShellFolderManager2
* Method: initializeCom
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolderManager2_initializeCom
(JNIEnv* env, jclass cls)
{
HRESULT hr = ::CoInitialize(NULL);
if (FAILED(hr)) {
char c[64];
sprintf(c, "Could not initialize COM: HRESULT=0x%08X", hr);
JNU_ThrowInternalError(env, c);
}
}
/*
* Class: sun_awt_shell_Win32ShellFolderManager2
* Method: uninitializeCom
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolderManager2_uninitializeCom
(JNIEnv* env, jclass cls)
{
::CoUninitialize();
}
static IShellIcon* getIShellIcon(IShellFolder* pIShellFolder) {
// http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp
HRESULT hres;
IShellIcon* pIShellIcon;
if (pIShellFolder != NULL) {
hres = pIShellFolder->QueryInterface(IID_IShellIcon, (void**)&pIShellIcon);
if (SUCCEEDED(hres)) {
return pIShellIcon;
}
}
return (IShellIcon*)NULL;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getIShellIcon
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIShellIcon
(JNIEnv* env, jclass cls, jlong parentIShellFolder)
{
return (jlong)getIShellIcon((IShellFolder*)parentIShellFolder);
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: initDesktop
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initDesktop
(JNIEnv* env, jobject desktop)
{
// Get desktop IShellFolder
HRESULT res = fn_SHGetDesktopFolder(&pDesktop);
if (res != S_OK) {
JNU_ThrowInternalError(env, "Could not get desktop shell folder");
return;
}
// Set field ID for pIShellFolder
env->CallVoidMethod(desktop, MID_pIShellFolder, (jlong)pDesktop);
// Get desktop relative PIDL
LPITEMIDLIST relPIDL;
res = fn_SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &relPIDL);
if (res != S_OK) {
JNU_ThrowInternalError(env,
"Could not get desktop shell folder ID list");
return;
}
// Set field ID for relative PIDL
env->CallVoidMethod(desktop, MID_relativePIDL, (jlong)relPIDL);
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: initSpecial
* Signature: (JI)V
*/
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_initSpecial
(JNIEnv* env, jobject folder, jlong desktopIShellFolder, jint folderType)
{
// Get desktop IShellFolder interface
IShellFolder* pDesktop = (IShellFolder*)desktopIShellFolder;
if (pDesktop == NULL) {
JNU_ThrowInternalError(env, "Desktop shell folder missing");
return;
}
// Get special folder relative PIDL
LPITEMIDLIST relPIDL;
HRESULT res = fn_SHGetSpecialFolderLocation(NULL, folderType,
&relPIDL);
if (res != S_OK) {
JNU_ThrowIOException(env, "Could not get shell folder ID list");
return;
}
// Set field ID for relative PIDL
env->CallVoidMethod(folder, MID_relativePIDL, (jlong)relPIDL);
// Get special folder IShellFolder interface
IShellFolder* pFolder;
res = pDesktop->BindToObject(relPIDL, NULL, IID_IShellFolder,
(void**)&pFolder);
if (res != S_OK) {
JNU_ThrowInternalError(env,
"Could not bind shell folder to interface");
return;
}
// Set field ID for pIShellFolder
env->CallVoidMethod(folder, MID_pIShellFolder, (jlong)pFolder);
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getNextPIDLEntry
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getNextPIDLEntry
(JNIEnv* env, jclass cls, jlong jpIDL)
{
LPITEMIDLIST pIDL = (LPITEMIDLIST)jpIDL;
// Check for valid pIDL.
if(pIDL == NULL)
return NULL;
// Get the size of the specified item identifier.
int cb = pIDL->mkid.cb;
// If the size is zero, it is the end of the list.
if (cb == 0)
return NULL;
// Add cb to pidl (casting to increment by bytes).
pIDL = (LPITEMIDLIST)(((LPBYTE)pIDL) + cb);
// Return NULL if it is null-terminating, or a pidl otherwise.
return (pIDL->mkid.cb == 0) ? 0 : (jlong)pIDL;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: copyFirstPIDLEntry
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_copyFirstPIDLEntry
(JNIEnv* env, jclass cls, jlong jpIDL)
{
LPITEMIDLIST pIDL = (LPITEMIDLIST)jpIDL;
if (pIDL == NULL) {
return 0;
}
// Get the size of the specified item identifier.
int cb = pIDL->mkid.cb;
// If the size is zero, it is the end of the list.
if (cb == 0)
return 0;
if (!IS_SAFE_SIZE_ADD(cb, sizeof(SHITEMID))) {
return 0;
}
// Allocate space for this as well as null-terminating entry.
LPITEMIDLIST newPIDL = (LPITEMIDLIST)pMalloc->Alloc(cb + sizeof(SHITEMID));
// Copy data.
memcpy(newPIDL, pIDL, cb);
// Set null terminator for next entry.
LPITEMIDLIST nextPIDL = (LPITEMIDLIST)(((LPBYTE)newPIDL) + cb);
nextPIDL->mkid.cb = 0;
return (jlong)newPIDL;
}
static int pidlLength(LPITEMIDLIST pIDL) {
int len = 0;
while (pIDL->mkid.cb != 0) {
int cb = pIDL->mkid.cb;
len += cb;
pIDL = (LPITEMIDLIST)(((LPBYTE)pIDL) + cb);
}
return len;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: combinePIDLs
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_combinePIDLs
(JNIEnv* env, jclass cls, jlong jppIDL, jlong jpIDL)
{
// Combine an absolute (fully qualified) pidl in a parent with the relative
// pidl of a child object to create a new absolute pidl for the child.
LPITEMIDLIST parentPIDL = (LPITEMIDLIST)jppIDL;
LPITEMIDLIST relativePIDL = (LPITEMIDLIST)jpIDL;
int len1 = pidlLength(parentPIDL);
int len2 = pidlLength(relativePIDL);
if (!IS_SAFE_SIZE_ADD(len1, len2) || !IS_SAFE_SIZE_ADD(len1 + len2, sizeof(SHITEMID))) {
return 0;
}
LPITEMIDLIST newPIDL = (LPITEMIDLIST)pMalloc->Alloc(len1 + len2 + sizeof(SHITEMID));
memcpy(newPIDL, parentPIDL, len1);
memcpy(((LPBYTE) newPIDL) + len1, relativePIDL, len2);
LPITEMIDLIST nullTerminator = (LPITEMIDLIST)(((LPBYTE) newPIDL) + len1 + len2);
nullTerminator->mkid.cb = 0;
return (jlong) newPIDL;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: releasePIDL
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_releasePIDL
(JNIEnv* env, jclass cls, jlong pIDL)
{
if (pIDL != 0L) {
pMalloc->Free((LPITEMIDLIST)pIDL);
}
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: releaseIShellFolder
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_releaseIShellFolder
(JNIEnv* env, jclass cls, jlong pIShellFolder)
{
if (pIShellFolder != 0L) {
((IShellFolder*)pIShellFolder)->Release();
}
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: compareIDs
* Signature: (JJJ)I
*/
JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_compareIDs
(JNIEnv* env, jclass cls, jlong jpParentIShellFolder, jlong pIDL1, jlong pIDL2)
{
IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder;
if (pParentIShellFolder == NULL) {
return 0;
}
return pParentIShellFolder->CompareIDs(0, (LPCITEMIDLIST) pIDL1, (LPCITEMIDLIST) pIDL2);
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getAttributes0
* Signature: (JJI)J
*/
JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getAttributes0
(JNIEnv* env, jclass cls, jlong jpParentIShellFolder, jlong jpIDL, jint attrsMask)
{
IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder;
if (pParentIShellFolder == NULL) {
return 0;
}
LPCITEMIDLIST pIDL = (LPCITEMIDLIST)jpIDL;
if (pIDL == NULL) {
return 0;
}
ULONG attrs = attrsMask;
HRESULT res = pParentIShellFolder->GetAttributesOf(1, &pIDL, &attrs);
return attrs;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getFileSystemPath0
* Signature: (I)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFileSystemPath0
(JNIEnv* env, jclass cls, jint csidl)
{
LPITEMIDLIST relPIDL;
TCHAR szBuf[MAX_PATH];
HRESULT res = fn_SHGetSpecialFolderLocation(NULL, csidl, &relPIDL);
if (res != S_OK) {
JNU_ThrowIOException(env, "Could not get shell folder ID list");
return NULL;
}
if (fn_SHGetPathFromIDList(relPIDL, szBuf)) {
return JNU_NewStringPlatform(env, szBuf);
} else {
return NULL;
}
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getEnumObjects
* Signature: (JZ)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getEnumObjects
(JNIEnv* env, jobject folder, jlong pIShellFolder,
jboolean isDesktop, jboolean includeHiddenFiles)
{
IShellFolder* pFolder = (IShellFolder*)pIShellFolder;
if (pFolder == NULL) {
return 0;
}
DWORD dwFlags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
if (includeHiddenFiles) {
dwFlags |= SHCONTF_INCLUDEHIDDEN;
}
/*
if (!isDesktop) {
dwFlags = dwFlags | SHCONTF_NONFOLDERS;
}
*/
IEnumIDList* pEnum;
if (pFolder->EnumObjects(NULL, dwFlags, &pEnum) != S_OK) {
return 0;
}
return (jlong)pEnum;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getNextChild
* Signature: (J)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getNextChild
(JNIEnv* env, jobject folder, jlong pEnumObjects)
{
IEnumIDList* pEnum = (IEnumIDList*)pEnumObjects;
if (pEnum == NULL) {
return 0;
}
LPITEMIDLIST pidl;
if (pEnum->Next(1, &pidl, NULL) != S_OK) {
return 0;
}
return (jlong)pidl;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: releaseEnumObjects
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_releaseEnumObjects
(JNIEnv* env, jobject folder, jlong pEnumObjects)
{
IEnumIDList* pEnum = (IEnumIDList*)pEnumObjects;
if (pEnum == NULL) {
return;
}
pEnum->Release();
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: bindToObject
* Signature: (JJ)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_bindToObject
(JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL)
{
IShellFolder* pParent = (IShellFolder*)parentIShellFolder;
if (pParent == NULL) {
return 0;
}
LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
if (pidl == NULL) {
return 0;
}
IShellFolder* pFolder;
HRESULT hr = pParent->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&pFolder);
if (SUCCEEDED (hr)) {
return (jlong)pFolder;
}
return 0;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getLinkLocation
* Signature: (JJZ)J;
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getLinkLocation
(JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL, jboolean resolve)
{
HRESULT hres;
STRRET strret;
OLECHAR olePath[MAX_PATH]; // wide-char version of path name
LPWSTR wstr;
IShellFolder* pParent = (IShellFolder*)parentIShellFolder;
if (pParent == NULL) {
return NULL;
}
LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
if (pidl == NULL) {
return NULL;
}
hres = pParent->GetDisplayNameOf(pidl, SHGDN_NORMAL | SHGDN_FORPARSING, &strret);
if (FAILED(hres)) {
return NULL;
}
switch (strret.uType) {
case STRRET_CSTR :
// IShellFolder::ParseDisplayName requires the path name in Unicode.
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, strret.cStr, -1, olePath, MAX_PATH);
wstr = olePath;
break;
case STRRET_OFFSET :
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (CHAR *)pidl + strret.uOffset, -1, olePath, MAX_PATH);
wstr = olePath;
break;
case STRRET_WSTR :
wstr = strret.pOleStr;
break;
}
IShellLinkW* psl;
hres = ::CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&psl);
if (SUCCEEDED(hres)) {
IPersistFile* ppf;
hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
if (SUCCEEDED(hres)) {
hres = ppf->Load(wstr, STGM_READ);
if (SUCCEEDED(hres)) {
if (resolve) {
hres = psl->Resolve(NULL, 0);
// Ignore failure
}
pidl = (LPITEMIDLIST)NULL;
hres = psl->GetIDList(&pidl);
}
ppf->Release();
}
psl->Release();
}
if (strret.uType == STRRET_WSTR) {
CoTaskMemFree(strret.pOleStr);
}
if (SUCCEEDED(hres)) {
return (jlong)pidl;
} else {
return 0;
}
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: parseDisplayName0
* Signature: (JLjava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_parseDisplayName0
(JNIEnv* env, jclass cls, jlong jpIShellFolder, jstring jname)
{
// Get desktop IShellFolder interface
IShellFolder* pIShellFolder = (IShellFolder*)jpIShellFolder;
if (pIShellFolder == NULL) {
JNU_ThrowInternalError(env, "Desktop shell folder missing");
return 0;
}
// Get relative PIDL for name
LPITEMIDLIST pIDL;
int nLength = env->GetStringLength(jname);
jchar* wszPath = new jchar[nLength + 1];
const jchar* strPath = env->GetStringChars(jname, NULL);
wcsncpy(reinterpret_cast<LPWSTR>(wszPath), reinterpret_cast(strPath), nLength);
wszPath[nLength] = 0;
HRESULT res = pIShellFolder->ParseDisplayName(NULL, NULL,
reinterpret_cast<LPWSTR>(wszPath), NULL, &pIDL, NULL);
if (res != S_OK) {
JNU_ThrowIOException(env, "Could not parse name");
pIDL = 0;
}
delete[] wszPath;
env->ReleaseStringChars(jname, strPath);
return (jlong)pIDL;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getDisplayNameOf
* Signature: (JJI)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getDisplayNameOf
(JNIEnv* env, jclass cls, jlong parentIShellFolder, jlong relativePIDL, jint attrs)
{
IShellFolder* pParent = (IShellFolder*)parentIShellFolder;
if (pParent == NULL) {
return NULL;
}
LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
if (pidl == NULL) {
return NULL;
}
STRRET strret;
if (pParent->GetDisplayNameOf(pidl, attrs, &strret) != S_OK) {
return NULL;
}
jstring result = jstringFromSTRRET(env, pidl, &strret);
if (strret.uType == STRRET_WSTR) {
CoTaskMemFree(strret.pOleStr);
}
return result;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getFolderType
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getFolderType
(JNIEnv* env, jclass cls, jlong pIDL)
{
SHFILEINFO fileInfo;
if (fn_SHGetFileInfo((LPCTSTR)pIDL, 0L, &fileInfo, sizeof(fileInfo),
SHGFI_TYPENAME | SHGFI_PIDL) == 0) {
return NULL;
}
return JNU_NewStringPlatform(env, fileInfo.szTypeName);
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getExecutableType
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_sun_awt_shell_Win32ShellFolder2_getExecutableType
(JNIEnv* env, jobject folder, jstring path)
{
TCHAR szBuf[MAX_PATH];
LPCTSTR szPath = JNU_GetStringPlatformChars(env, path, NULL);
if (szPath == NULL) {
return NULL;
}
HINSTANCE res = fn_FindExecutable(szPath, szPath, szBuf);
JNU_ReleaseStringPlatformChars(env, path, szPath);
if ((UINT_PTR)res < 32) {
return NULL;
}
return JNU_NewStringPlatform(env, szBuf);
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getIcon
* Signature: (Ljava/lang/String;Z)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIcon
(JNIEnv* env, jclass cls, jstring absolutePath, jboolean getLargeIcon)
{
HICON hIcon = NULL;
SHFILEINFO fileInfo;
LPCTSTR pathStr = JNU_GetStringPlatformChars(env, absolutePath, NULL);
if (fn_SHGetFileInfo(pathStr, 0L, &fileInfo, sizeof(fileInfo),
SHGFI_ICON | (getLargeIcon ? 0 : SHGFI_SMALLICON)) != 0) {
hIcon = fileInfo.hIcon;
}
JNU_ReleaseStringPlatformChars(env, absolutePath, pathStr);
return (jlong)hIcon;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getIconIndex
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconIndex
(JNIEnv* env, jclass cls, jlong pIShellIconL, jlong relativePIDL)
{
IShellIcon* pIShellIcon = (IShellIcon*)pIShellIconL;
LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
if (pIShellIcon == NULL && pidl == NULL) {
return 0;
}
INT index = -1;
HRESULT hres;
// http://msdn.microsoft.com/library/en-us/shellcc/platform/Shell/programmersguide/shell_int/shell_int_programming/std_ifaces.asp
if (pIShellIcon != NULL) {
hres = pIShellIcon->GetIconOf(pidl, GIL_FORSHELL, &index);
}
return (jint)index;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: extractIcon
* Signature: (JJZ)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_extractIcon
(JNIEnv* env, jclass cls, jlong pIShellFolderL, jlong relativePIDL, jboolean getLargeIcon)
{
IShellFolder* pIShellFolder = (IShellFolder*)pIShellFolderL;
LPITEMIDLIST pidl = (LPITEMIDLIST)relativePIDL;
if (pIShellFolder == NULL || pidl == NULL) {
return 0;
}
HICON hIcon = NULL;
HRESULT hres;
IExtractIconW* pIcon;
hres = pIShellFolder->GetUIObjectOf(NULL, 1, const_cast<LPCITEMIDLIST*>(&pidl),
IID_IExtractIconW, NULL, (void**)&pIcon);
if (SUCCEEDED(hres)) {
WCHAR szBuf[MAX_PATH];
INT index;
UINT flags;
hres = pIcon->GetIconLocation(GIL_FORSHELL, szBuf, MAX_PATH, &index, &flags);
if (SUCCEEDED(hres)) {
HICON hIconLarge;
hres = pIcon->Extract(szBuf, index, &hIconLarge, &hIcon, (16 << 16) + 32);
if (SUCCEEDED(hres)) {
if (getLargeIcon) {
fn_DestroyIcon((HICON)hIcon);
hIcon = hIconLarge;
} else {
fn_DestroyIcon((HICON)hIconLarge);
}
}
}
pIcon->Release();
}
return (jlong)hIcon;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: disposeIcon
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_sun_awt_shell_Win32ShellFolder2_disposeIcon
(JNIEnv* env, jclass cls, jlong hicon)
{
fn_DestroyIcon((HICON)hicon);
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getIconBits
* Signature: (JI)[I
*/
JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconBits
(JNIEnv* env, jclass cls, jlong hicon, jint iconSize)
{
jintArray iconBits = NULL;
// Get the icon info
ICONINFO iconInfo;
if (fn_GetIconInfo((HICON)hicon, &iconInfo)) {
// Get the screen DC
HDC dc = GetDC(NULL);
if (dc != NULL) {
// Set up BITMAPINFO
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = iconSize;
bmi.bmiHeader.biHeight = -iconSize;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
// Extract the color bitmap
int nBits = iconSize * iconSize;
long colorBits[1024];
GetDIBits(dc, iconInfo.hbmColor, 0, iconSize, colorBits, &bmi, DIB_RGB_COLORS);
// XP supports alpha in some icons, and depending on device.
// This should take precedence over the icon mask bits.
BOOL hasAlpha = FALSE;
if (IS_WINXP) {
for (int i = 0; i < nBits; i++) {
if ((colorBits[i] & 0xff000000) != 0) {
hasAlpha = TRUE;
break;
}
}
}
if (!hasAlpha) {
// Extract the mask bitmap
long maskBits[1024];
GetDIBits(dc, iconInfo.hbmMask, 0, iconSize, maskBits, &bmi, DIB_RGB_COLORS);
// Copy the mask alphas into the color bits
for (int i = 0; i < nBits; i++) {
if (maskBits[i] == 0) {
colorBits[i] |= 0xff000000;
}
}
}
// Release DC
ReleaseDC(NULL, dc);
// Create java array
iconBits = env->NewIntArray(nBits);
// Copy values to java array
env->SetIntArrayRegion(iconBits, 0, nBits, colorBits);
}
// Fix 4745575 GDI Resource Leak
// MSDN
// GetIconInfo creates bitmaps for the hbmMask and hbmColor members of ICONINFO.
// The calling application must manage these bitmaps and delete them when they
// are no longer necessary.
::DeleteObject(iconInfo.hbmColor);
::DeleteObject(iconInfo.hbmMask);
}
return iconBits;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getStandardViewButton0
* Signature: (I)[I
*/
JNIEXPORT jintArray JNICALL Java_sun_awt_shell_Win32ShellFolder2_getStandardViewButton0
(JNIEnv* env, jclass cls, jint iconIndex)
{
jintArray result = NULL;
// Create a toolbar
HWND hWndToolbar = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL);
if (hWndToolbar != NULL) {
SendMessage(hWndToolbar, TB_LOADIMAGES, (WPARAM)IDB_VIEW_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
HIMAGELIST hImageList = (HIMAGELIST) SendMessage(hWndToolbar, TB_GETIMAGELIST, 0, 0);
if (hImageList != NULL) {
HICON hIcon = ImageList_GetIcon(hImageList, iconIndex, ILD_TRANSPARENT);
if (hIcon != NULL) {
result = Java_sun_awt_shell_Win32ShellFolder2_getIconBits(env, cls, ptr_to_jlong(hIcon), 16);
DestroyIcon(hIcon);
}
ImageList_Destroy(hImageList);
}
DestroyWindow(hWndToolbar);
}
return result;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getSystemIcon
* Signature: (I)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getSystemIcon
(JNIEnv* env, jclass cls, jint iconID)
{
return (jlong)LoadIcon(NULL, MAKEINTRESOURCE(iconID));
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: getIconResource
* Signature: (Ljava/lang/String;IIIZ)J
*/
JNIEXPORT jlong JNICALL Java_sun_awt_shell_Win32ShellFolder2_getIconResource
(JNIEnv* env, jclass cls, jstring libName, jint iconID,
jint cxDesired, jint cyDesired, jboolean useVGAColors)
{
const char *pLibName = env->GetStringUTFChars(libName, NULL);
HINSTANCE libHandle = (HINSTANCE)JDK_LoadSystemLibrary(pLibName);
if (libHandle != NULL) {
UINT fuLoad = (useVGAColors && !IS_WINXP) ? LR_VGACOLOR : 0;
return ptr_to_jlong(LoadImage(libHandle, MAKEINTRESOURCE(iconID),
IMAGE_ICON, cxDesired, cyDesired,
fuLoad));
}
return 0;
}
/*
* Helper function for creating Java column info object
*/
static jobject CreateColumnInfo(JNIEnv *pEnv,
jclass *pClass, jmethodID *pConstructor,
SHELLDETAILS *psd, ULONG visible)
{
return pEnv->NewObject(*pClass, *pConstructor,
jstringFromSTRRET(pEnv, NULL, &(psd->str)),
(jint)(psd->cxChar * 6), // TODO: is 6 OK for converting chars to pixels?
(jint)psd->fmt, (jboolean) visible);
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: doGetColumnInfo
* Signature: (J)[Lsun/awt/shell/ShellFolderColumnInfo;
*/
JNIEXPORT jobjectArray JNICALL
Java_sun_awt_shell_Win32ShellFolder2_doGetColumnInfo
(JNIEnv *env, jobject obj, jlong iShellFolder)
{
HRESULT hr;
IShellFolder *pIShellFolder = (IShellFolder*) iShellFolder;
IUnknown *pIUnknown = NULL;
jclass columnClass = env->FindClass("sun/awt/shell/ShellFolderColumnInfo");
if(NULL == columnClass) {
return NULL;
}
jmethodID columnConstructor =
env->GetMethodID(columnClass, "<init>", "(Ljava/lang/String;IIZ)V");
if(NULL == columnConstructor) {
return NULL;
}
// We'are asking the object the list of available columns
SHELLDETAILS sd;
hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown);
if(SUCCEEDED (hr)) {
// The folder exposes IShellFolder2 interface
IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown;
// Count columns
int colNum = -1;
hr = S_OK;
do{
hr = pIShellFolder2->GetDetailsOf(NULL, ++colNum, &sd);
} while (SUCCEEDED (hr));
jobjectArray columns =
env->NewObjectArray((jsize) colNum, columnClass, NULL);
if(NULL == columns) {
pIShellFolder2->Release();
return NULL;
}
// Fill column details list
SHCOLSTATEF csFlags;
colNum = 0;
hr = S_OK;
while (SUCCEEDED (hr)) {
hr = pIShellFolder2->GetDetailsOf(NULL, colNum, &sd);
if (SUCCEEDED (hr)) {
hr = pIShellFolder2->GetDefaultColumnState(colNum, &csFlags);
if (SUCCEEDED (hr)) {
if(!(csFlags & SHCOLSTATE_HIDDEN)) {
jobject column = CreateColumnInfo(env,
&columnClass, &columnConstructor,
&sd, csFlags & SHCOLSTATE_ONBYDEFAULT);
env->SetObjectArrayElement(columns, (jsize) colNum, column);
}
}
colNum++;
}
}
pIShellFolder2->Release();
return columns;
}
hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown);
if(SUCCEEDED (hr)) {
// The folder exposes IShellDetails interface
IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown;
// Count columns
int colNum = -1;
hr = S_OK;
do{
hr = pIShellDetails->GetDetailsOf(NULL, ++colNum, &sd);
} while (SUCCEEDED (hr));
jobjectArray columns =
env->NewObjectArray((jsize) colNum, columnClass, NULL);
if(NULL == columns) {
pIShellDetails->Release();
return NULL;
}
// Fill column details list
colNum = 0;
hr = S_OK;
while (SUCCEEDED (hr)) {
hr = pIShellDetails->GetDetailsOf(NULL, colNum, &sd);
if (SUCCEEDED (hr)) {
jobject column = CreateColumnInfo(env,
&columnClass, &columnConstructor,
&sd, 1);
env->SetObjectArrayElement(columns, (jsize) colNum++, column);
}
}
pIShellDetails->Release();
return columns;
}
// The folder exposes neither IShellFolder2 nor IShelDetails
return NULL;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: doGetColumnValue
* Signature: (JJI)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL
Java_sun_awt_shell_Win32ShellFolder2_doGetColumnValue
(JNIEnv *env, jobject obj, jlong iShellFolder,
jlong jpidl, jint columnIdx)
{
HRESULT hr;
IShellFolder *pIShellFolder = (IShellFolder*) iShellFolder;
IUnknown *pIUnknown = NULL;
LPITEMIDLIST pidl = (LPITEMIDLIST) jpidl;
SHELLDETAILS sd;
hr = pIShellFolder->QueryInterface(IID_IShellFolder2, (void**)&pIUnknown);
if(SUCCEEDED (hr)) {
// The folder exposes IShellFolder2 interface
IShellFolder2 *pIShellFolder2 = (IShellFolder2*) pIUnknown;
hr = pIShellFolder2->GetDetailsOf(pidl, (UINT)columnIdx, &sd);
pIShellFolder2->Release();
if (SUCCEEDED (hr)) {
STRRET strRet = sd.str;
return jstringFromSTRRET(env, pidl, &strRet);
}
}
hr = pIShellFolder->CreateViewObject(NULL, IID_IShellDetails, (void**)&pIUnknown);
if(SUCCEEDED (hr)) {
// The folder exposes IShellDetails interface
IShellDetails *pIShellDetails = (IShellDetails*) pIUnknown;
hr = pIShellDetails->GetDetailsOf(pidl, (UINT)columnIdx, &sd);
pIShellDetails->Release();
if (SUCCEEDED (hr)) {
STRRET strRet = sd.str;
return jstringFromSTRRET(env, pidl, &strRet);
}
}
// The folder exposes neither IShellFolder2 nor IShelDetails
return NULL;
}
/*
* Class: sun_awt_shell_Win32ShellFolder2
* Method: compareIDsByColumn
* Signature: (JJJI)I
*/
JNIEXPORT jint JNICALL
Java_sun_awt_shell_Win32ShellFolder2_compareIDsByColumn
(JNIEnv* env, jclass cls, jlong jpParentIShellFolder,
jlong pIDL1, jlong pIDL2, jint columnIdx)
{
IShellFolder* pParentIShellFolder = (IShellFolder*)jpParentIShellFolder;
if (pParentIShellFolder == NULL) {
return 0;
}
HRESULT hr = pParentIShellFolder->CompareIDs(
(UINT) columnIdx,
(LPCITEMIDLIST) pIDL1,
(LPCITEMIDLIST) pIDL2);
if (SUCCEEDED (hr)) {
return (jint) (short) HRESULT_CODE(hr);
}
return 0;
}
} // extern "C"
Other Java examples (source code examples)
Here is a short list of links related to this Java ShellFolder2.cpp source code file:
|