C++ problem to resolve .lnk files with IShellLink:GetPath()


I use the IShellLink:GetPath() method to resolve .lnk files.

It works fine with the most of my .lnk files (like TuneUp, NotePad, and all Windows programs)

But, with programs like Safari or Adobe Reader, the method just returns this :

C:/Windows/Installer/{xxxxxxxx}/SafariIco.exe for Safari


C:/Windows/Installer/{yyyyyyyy}/SC_Reader.exe for Adobe Reader

How can I get the real path of theses .lnk files WITH DEV-CPP ?

My actual code is attached.

Thanks you in advance !
#include <windows.h>
#include <objidl.h>   /* For IPersistFile */
#include <shlobj.h>   /* For IShellLink */
#if defined(_MSC_VER)
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "uuid.lib")
#include <stdio.h>
#include <tchar.h>
BOOL GetShortcutTarget(LPCTSTR szShortcutFile, LPTSTR szTarget, SIZE_T cchTarget)
    IShellLink*    psl     = NULL;
    IPersistFile*  ppf     = NULL;
    BOOL           bResult = FALSE;
    if (FAILED( CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **) &psl) ))
        goto cleanup;
    if (FAILED( psl->QueryInterface(IID_IPersistFile, (void **) &ppf) ))
        goto cleanup;
#   if !defined(UNICODE)
        WCHAR wsz[MAX_PATH];
        if (0 == MultiByteToWideChar(CP_ACP, 0, szShortcutFile, -1, wsz, MAX_PATH) )
            goto cleanup;
#   else
        LPCWSTR wsz = szShortcutFile;
#   endif
    if (FAILED( ppf->Load(wsz, STGM_READ) ))
        goto cleanup;
    if (NOERROR != psl->GetPath(szTarget, cchTarget, NULL, 0) )
        goto cleanup;
    bResult = TRUE;
    if (ppf) ppf->Release();
    if (psl) psl->Release();
    if (!bResult && cchTarget != 0) szTarget[0] = TEXT('\0');
    return bResult;
int main(void)
    TCHAR szTarget[MAX_PATH];
         szTarget, MAX_PATH);
    _tprintf(TEXT("The shortcut target is '%s'.\n"), szTarget);
    return 0;

Open in new window

Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Um, I assume the "{xxxxxxxx}" part is actually a GUID - then these *are* the real file names, check them out. E.g. a short excerpt from my Windows\Installer directory:
04.02.2008  05:11    <DIR>          {AC76BA86-7AD7-5464-3428-800000000003}
05.05.2008  05:40    <DIR>          {C04E32E0-0416-434D-AFB9-6969D703A9EF}
04.08.2007  10:37    <DIR>          {CE386A4E-D0DA-4208-8235-BCE43275C694}
07.08.2007  11:53    <DIR>          {D7E04009-B191-4E9D-9D2D-1BBE57BD8A42}

Open in new window

ValtyAuthor Commented:
Yes of course, I have GUID, not the "xxxxxxx" : it was just for the example. But how to retreive the real names via the GUID ?
Well, these are the real names. The GUIDs are the names of subdirectories in "Installer" - take a look at that directory.
Learn SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

ValtyAuthor Commented:
But, the programs into these directories are not valids.

Eg :

I have a Safari.lnk who give me this path => C:/Windows/Installer/{xxxxxxxx}/SafariIco.exe

But this path is not the program path ! SafariIco.exe is not a valid Win32 exe.

Safari is really located at C:/Program Files/Safari/Safari.exe

Do you understand ?
ValtyAuthor Commented:
Hm... nobody have the solution ?
You could/should pass flag  SLGP_RAWPATH  and/or SLGP_UNCPRIORITY as 4th argument to GetPath.

You also could/should pass an address of a WIN32_FIND_DATA struct as 3rd argument. The WIN32_FIND_DATA has a cFileName member which should contain the absolute path of the file.

   WIN32_FIND_DATA wfd = { 0 };
   if (NOERROR != psl->GetPath(szTarget, cchTarget, &wfd, SLGP_UNCPRIORITY ) )
        goto cleanup;

  // now check for wfd.cFileName

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ValtyAuthor Commented:
Hello, thanks for your answer

I have tested with SLGP_RAWPATH  and/or SLGP_UNCPRIORITY => no changes

I have also tested with WIN32_FIND_DATA wfd = { 0 }; and a printf with wfd.cFileName, it just returns "taller" or "taller\{XXXX-XXXX-XXX" (the GUID is not complete)
ValtyAuthor Commented:
Nobody have another solution ?
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.