Solved

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

Posted on 2006-07-06
10
307 Views
Last Modified: 2012-06-27
Hello,

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!

Thanks,

Phelippe
0
Comment
Question by:pcigeomatics
[X]
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
10 Comments
 
LVL 5

Expert Comment

by:bastibartel
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,
            &ppf);
        if (SUCCEEDED(hres)) {
            WORD wsz[MAX_PATH];
 
            // Ensure that the string is Unicode.
            MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz,
                MAX_PATH);
 
            // 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))
                        HandleErr(hres);
                    lstrcpy(lpszPath, szGotPath);
                }
            }
        // Release the pointer to the IPersistFile interface.
        ppf->lpVtbl->Release(ppf);
        }
    // Release the pointer to the IShellLink interface.
    psl->lpVtbl->Release(psl);
    }
    return hres;
}

Cheers,
Sebastian
0
 
LVL 15

Accepted Solution

by:
lakshman_ce earned 63 total points
ID: 17052907
You can try to use the CopyFile and CopyFileEx methods of Win32 API
You can read more at
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/Symbolic_Link_Effects_on_File_Systems_Functions.asp
0
On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

 

Author Comment

by:pcigeomatics
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)
{
    FindClose(hFindHandle);

    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

Phelippe
0
 
LVL 5

Expert Comment

by:bastibartel
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
0
 
LVL 49

Assisted Solution

by:DanRollins
DanRollins earned 62 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
       http://www.codeproject.com/shell/create_shortcut.asp

#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()
{
    CoInitialize(0);

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

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

Expert Comment

by:DanRollins
ID: 17208756
I recommend: split to lakshman_ce and DanRollins
0

Featured Post

On Demand Webinar: Networking for the Cloud Era

Did you know SD-WANs can improve network connectivity? Check out this webinar to learn how an SD-WAN simplified, one-click tool can help you migrate and manage data in the cloud.

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…
In this video, viewers will be given step by step instructions on adjusting mouse, pointer and cursor visibility in Microsoft Windows 10. The video seeks to educate those who are struggling with the new Windows 10 Graphical User Interface. Change Cu…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …

688 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