Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win


How can I retreive the location that a symbolic link points to on Windows?

Posted on 2006-07-06
Medium Priority
Last Modified: 2012-06-27

I need to get the canonical form of a path. To do so, I need to resolve symbolic links if some are found in the input path. On unix, I used lstat() to see if the dirrectory or the file is a symbolic link, if so then I use readlink() to get the location that the link points to.

Now I need to implement the same thing on Windows, but I can't find how I can get this information about a symbolic link.

Please Help!


Question by:pcigeomatics
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions

Expert Comment

ID: 17052894
From MSDN:

HRESULT ResolveIt(HWND hwnd, LPCSTR lpszLinkFile, LPSTR lpszPath)
    HRESULT hres;
    IShellLink* psl;
    char szGotPath[MAX_PATH];
    char szDescription[MAX_PATH];
    WIN32_FIND_DATA wfd;
    *lpszPath = 0; // assume failure
    // Get a pointer to the IShellLink interface.
    hres = CoCreateInstance(&CLSID_ShellLink, NULL,
            CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl);
    if (SUCCEEDED(hres)) {
        IPersistFile* ppf;
        // Get a pointer to the IPersistFile interface.
        hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile,
        if (SUCCEEDED(hres)) {
            WORD wsz[MAX_PATH];
            // Ensure that the string is Unicode.
            MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz,
            // Load the shortcut.
            hres = ppf->lpVtbl->Load(ppf, wsz, STGM_READ);
            if (SUCCEEDED(hres)) {
                // Resolve the link.
                hres = psl->lpVtbl->Resolve(psl, hwnd, SLR_ANY_MATCH);
                if (SUCCEEDED(hres)) {
                    // Get the path to the link target.
                    hres = psl->lpVtbl->GetPath(psl, szGotPath,
                        MAX_PATH, (WIN32_FIND_DATA *)&wfd,
                        SLGP_SHORTPATH );
                    if (!SUCCEEDED(hres)
                        HandleErr(hres); // application-defined function
                    // Get the description of the target.
                    hres = psl->lpVtbl->GetDescription(psl,
                        szDescription, MAX_PATH);
                    if (!SUCCEEDED(hres))
                    lstrcpy(lpszPath, szGotPath);
        // Release the pointer to the IPersistFile interface.
    // Release the pointer to the IShellLink interface.
    return hres;

LVL 15

Accepted Solution

lakshman_ce earned 252 total points
ID: 17052907
You can try to use the CopyFile and CopyFileEx methods of Win32 API
You can
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.


Author Comment

ID: 17053466
The ResolveIt() functions seems to be doing what I want, but I don't have access to a HWND...

The CopyFile() or CopyFileEx() functions are not what I'm looking for.

The IShellLink::GetPath() method looks like could do the work, but hurray for Windows documentation, I have no clue how to create the object or what files to include.

I tried this with no success;

WIN32_FIND_DATA sFindData;

HANDLE hFindHandle = FindFirstFile("C:\\temp\\demo", &sFindData); // C:\temp\demo is a link to C:\home\demo

if (hFindHandle != INVALID_HANDLE_VALUE)

    char szResolvePath[MAX_PATH];

    HRESULT hResult = IShellLink::GetPath(szResolvePath, MAX_PATH, &sFindData, SLGP_UNCPRIORITY);

    if (hResult == NOERROR)
        printf("Resolved Path: %s\n", szResolvePath);

I get these errors;

c:\Temp\Testl\Test.cpp(40) : error C2653: 'IShellLink' : is not a class or namespace name
c:\Temp\Test\Test.cpp(41) : error C2065: 'SLGP_UNCPRIORITY' : undeclared identifier


Expert Comment

ID: 17054590
Hi there,

Try including  "shlobj.h2
For the HWND you may pass any Window Handle you like. It is for any message boxes that the shell may need to popup.

Cheers Sebastian
LVL 49

Assisted Solution

DanRollins earned 248 total points
ID: 17054973
Here's a slightly more concise version of the same sequence, including the various prerequisites, such as the #include and the call to CoInitialize.   It is from here:

       How to create and resolve a shortcut

#include <atlbase.h>

HRESULT ResolveShortcut(/*in*/ LPCTSTR lpszShortcutPath,
                        /*out*/ LPTSTR lpszFilePath)
    HRESULT hRes = E_FAIL;
    CComPtr<IShellLink> ipShellLink;
    TCHAR szPath[MAX_PATH];    
    WIN32_FIND_DATA wfd;    
    WCHAR wszTemp[MAX_PATH];

    lpszFilePath[0] = '\0';

    hRes = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
                            IID_IShellLink, (void**)&ipShellLink
    if (SUCCEEDED(hRes)) {
        CComQIPtr<IPersistFile> ipPersistFile(ipShellLink);
        MultiByteToWideChar(CP_ACP, 0, lpszShortcutPath, -1, wszTemp, MAX_PATH);

        hRes = ipPersistFile->Load(wszTemp, STGM_READ);
        if (SUCCEEDED(hRes)) {
            hRes = ipShellLink->Resolve(NULL, SLR_UPDATE);
            if (SUCCEEDED(hRes)) {
                hRes = ipShellLink->GetPath(szPath, MAX_PATH, &wfd, SLGP_RAWPATH);
                if (FAILED(hRes)) {
                    return hRes;
                lstrcpyn( lpszFilePath, szPath, MAX_PATH );
    return hRes;

void CD35Dlg::OnButton2()

    char lpszShortcutPath[] = "C:\\Documents and Settings\\Dan\\Desktop\\Imaging.lnk";
    char szFilePath[MAX_PATH];

    ResolveShortcut( lpszShortcutPath, szFilePath );
    CoUninitialize( );      
LVL 49

Expert Comment

ID: 17208756
I recommend: split to lakshman_ce and DanRollins

Featured Post

Tech or Treat!

Submit an article about your scariest tech experience—and the solution—and you’ll be automatically entered to win one of 4 fantastic tech gadgets.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The following diagram presents a diamond class hierarchy: As depicted, diamond inheritance denotes when two classes (e.g., CDerived1 and CDerived2), separately extending a common base class (e.g., CBase), are sub classed simultaneously by a fourt…
In Easy String Encryption Using CryptoAPI in C++ (http://www.experts-exchange.com/viewArticle.jsp?aid=1193) I described how to encrypt text and recommended that the encrypted text be stored as a series of hexadecimal digits -- because cyphertext may…
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Suggested Courses

618 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question