alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

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.

Java - Java tags/keywords

could, false, hresult, ishellfolder, ishellfolder\*, jnicall, jnienv, jniexport, jnu_newstringplatform, lpitemidlist, null, s_ok, succeeded, winapi

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:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.