Solved

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

Posted on 2006-07-06
10
301 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
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
 
LVL 5

Expert Comment

by:bastibartel
ID: 17052911
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

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

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

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…
This tutorial demonstrates a quick way of adding group price to multiple Magento products.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

708 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now