[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 311
  • Last Modified:

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

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
pcigeomatics
Asked:
pcigeomatics
2 Solutions
 
bastibartelCommented:
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
 
lakshman_ceCommented:
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
Important Lessons on Recovering from Petya

In their most recent webinar, Skyport Systems explores ways to isolate and protect critical databases to keep the core of your company safe from harm.

 
pcigeomaticsAuthor Commented:
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
 
bastibartelCommented:
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
 
DanRollinsCommented:
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
 
DanRollinsCommented:
I recommend: split to lakshman_ce and DanRollins
0

Featured Post

Upgrade your Question Security!

Add Premium security features to your question to ensure its privacy or anonymity. Learn more about your ability to control Question Security today.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now