0

I'm making a Java app that scans the Windows Recent Files folder and resolves .lnk shorcuts to their actual file paths. I'm doing so using JNA the JNA API and simulating IShellLinkW and IPersistFile.

Every time I run my code, CoCreateInstance returns S_OK and the COM pointer is non-null, but my ShellLink object fails immediately as well as my IPersistFile.load.

This is my debug log (I generated a lot of debug messages) after clearing the recent files folder and downloading a dummy pdf:

Resolving: pdf-sample_0.pdf.lnk
===== ShellLink.createShellLink() BEGIN =====
CLSID_SHELL_LINK = {00021401-0000-0000-C000-000000000046}
IID_SHELL_LINK_W = {000214F9-0000-0000-C000-000000000046}
[1] Calling CoInitialize...
[1] CoInitialize HRESULT = 1  (S_FALSE)
[2] Calling CoCreateInstance...
[2] CoCreateInstance HRESULT = 0  (S_OK)
[2] HRESULT (hex) = 0x00000000
[2] Returned COM pointer (ppv) = native@0x1eeef60df60
!!! ShellLink create FAILED !!!
!!! HRESULT = 0x00000000
!!! ppv = native@0x1eeef60df60
Error resolving: pdf-sample_0.pdf.lnk

My question: Why would JNA treat this COM pointer as invalid when CoCreateInstance returns S_OK? Am I using the incorrect COM IDs for the classes/interfaces? Wrong virtual table indices? Or something else?

Relevant Code

1. Relevant Config.java constants

public static final String WIN32_CLASS_ID_OBJECT_SHELL_LINK = "{00021401-0000-0000-C000-000000000046}";
public static final String WIN32_INTERFACE_ID_SHELL_LINK_WIDE = "{000214F9-0000-0000-C000-000000000046}";
public static final String WIN32_INTERFACE_ID_PERSIST_FILE = "{0000010B-0000-0000-C000-000000000046}";
public static final int WIN32_MAX_PATH = 260;
public static final int WIN32_VTABLE_GETPATH = 20;
public static final int WIN32_VTABLE_RESOLVE = 21;
public static final int WIN32_VTABLE_LOAD = 5;

2. ShellLink.createLink snippet (seems like the main issue is happening here)

public static IShellLinkW createShellLink() {

    // Initialize COM
    WinNT.HRESULT initRes = Ole32.INSTANCE.CoInitialize(null);

    // Create the ShellLink COM object
    PointerByReference ppv = new PointerByReference();
    WinNT.HRESULT hres = Ole32.INSTANCE.CoCreateInstance(
            CLSID_SHELL_LINK,
            null,
            WTypes.CLSCTX_INPROC_SERVER,
            IID_SHELL_LINK_W,
            ppv
    );

    Pointer rawPtr = ppv.getValue();

    // Failure
    if (hres == null || hres.intValue() != WinNT.S_OK || rawPtr == null) {
        Ole32.INSTANCE.CoUninitialize();
        return null;
    }

    // Success
    return new IShellLinkW(rawPtr);
}

Even though hres == S_OK and rawPtr != null, this if block still runs.

I am running a Windows 10 machine, and the code runs on Java 17 with JNA 5.13.0. The folder I'm scanning is %APPDATA%\Microsoft\Windows\Recent. If it helps, this app is a JavaFX app.

If it helps, here's a link to the GitHub repository. I would very much appreciate some guidance, thank you!

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.