c++windows-7comlnk

IShellLink GetArguments is only returning executable


I have a wrapper application that needs to identify all the XP Mode applications published; these all reside within a single folder, and I'm using Qt to obtain all the .lnk files.

This bit works - the trouble is, all the Virtual PC applications use rundll32 in order to kick off a virtual machine and/or its app (e.g. %SystemRoot%\system32\rundll32.exe %SystemRoot%\system32\VMCPropertyHandler.dll,LaunchVMSal "Windows XP Mode" "||some_id" "some_name"), and so I need to read the full target.

Reading the MSDN Docs, GetArguments() on an IShellLink should be returning this data - but it only ever retrieves the path to rundll32.exe, and never with any trailing command line data. GetPath() does the same, as expected, but I see no other methods to call that might be able to obtain the data I need.

I created a test shortcut with different argument styles (/param, -param and plain param), but nothing makes a difference. It's not just Virtual PC links with the fault - this applies to all shortcuts.

Here's the function code:

QString GetShortcutTarget(const char* shortcut)
{
    IShellLink* psl = NULL;
    IPersistFile*   ppf = NULL;
    wchar_t     wsz[MAX_PATH];
    wchar_t     target[MAX_PATH * 4]; // w/e
    QString     retval;

    if ( MultiByteToWideChar(CP_ACP, 0, shortcut, -1, wsz, MAX_PATH) == 0 )
        goto cleanup;

    if ( FAILED(CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER,    IID_IShellLink, (void **)&psl)) )
        goto cleanup;

    if ( FAILED(psl->QueryInterface(IID_IPersistFile, (void **)&ppf)) )
        goto cleanup;

    if ( FAILED(ppf->Load(wsz, STGM_READ)) )
        goto cleanup;

    // GetPath() and GetArguments return the same
    //if ( NOERROR != psl->GetPath(target, _countof(target), nullptr, 0) )
    if ( NOERROR != psl->GetArguments(target, _countof(target)) )
        goto cleanup;

    retval = QString::fromWCharArray(target);

cleanup:
    if ( ppf )
        ppf->Release();
    if ( psl )
        psl->Release();

    return retval;
}

EDIT

Not redefining an interface anywhere, including and linking with:

#include <objidl.h> // IPersistFile
#include <shlobj.h> // IShellLink

#pragma comment ( lib, "ole32.lib" )
#pragma comment ( lib, "uuid.lib" )

Only other COM related code is in a constructor and destructor elsewhere (yes, is already called!):

CoInitialize(NULL);
...
CoUninitialize();

Qt hopefully shouldn't have anything to do with it, as COM is definitely opening and reading the .lnk..


Solution

  • I discovered the problem - the input shortcut was the .lnk, but not the absolute file path; as my current directory wasn't set to where the shortcut was located, this was naturally making it fail to load.

    I had Qt iterating over absolute paths, but I was only passing in the filename when searching for the target. I amended my previous call elsewhere from:

    file_info.fileName()
    

    to:

    file_info.absoluteFilePath()
    

    and this has fixed the issue!