Resolving a Shorcuts Target Path?

So I've been working on this for awhile now with no success. I have used my own code with this general method with no success. Now that I am compiling for release code with multithreaded /MT and release. So the general look of the code is below from MSDN. It's insanely hard to follow. I've tried using my own code and function etc. This is extremely insanely confusing compared to even normal Win32 functions etc. for just resolving a tiny shortcut link. In any case one of the weird thing is that I have to use a bunch of typecastings now when I set my project to release in this code and I'm just wondering where do I begin to figure this out since this is using a bunch of crap COM and a bunch of stuff all for a little link?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
HRESULT ResolveIt(HWND hwnd, LPCSTR lpszLinkFile, LPWSTR lpszPath, int iPathBufferSize) 
{ 
    HRESULT hres; 
    IShellLink* psl; 
    WCHAR szGotPath[MAX_PATH]; 
    WCHAR szDescription[MAX_PATH]; 
    WIN32_FIND_DATA wfd; 
 
    *lpszPath = 0; // Assume failure 

    // Get a pointer to the IShellLink interface. It is assumed that CoInitialize
    // has already been called. 
    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); 
    if (SUCCEEDED(hres)) 
    { 
        IPersistFile* ppf; 
 
        // Get a pointer to the IPersistFile interface. 
        hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); 
        
        if (SUCCEEDED(hres)) 
        { 
            WCHAR wsz[MAX_PATH]; 
 
            // Ensure that the string is Unicode. 
            MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz, MAX_PATH); 
 
            // Add code here to check return value from MultiByteWideChar 
            // for success.
 
            // Load the shortcut. 
            hres = ppf->Load(wsz, STGM_READ); 
            
            if (SUCCEEDED(hres)) 
            { 
                // Resolve the link. 
                hres = psl->Resolve(hwnd, 0); 

                if (SUCCEEDED(hres)) 
                { 
                    // Get the path to the link target. 
                    hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATA*)&wfd, SLGP_SHORTPATH); 

                    if (SUCCEEDED(hres)) 
                    { 
                        // Get the description of the target. 
                        hres = psl->GetDescription(szDescription, MAX_PATH); 

                        if (SUCCEEDED(hres)) 
                        {
                            hres = StringCbCopy(lpszPath, iPathBufferSize, szGotPath);
                            if (SUCCEEDED(hres))
                            {
                                // Handle success
                            }
                            else
                            {
                                // Handle the error
                            }
                        }
                    }
                } 
            } 

            // Release the pointer to the IPersistFile interface. 
            ppf->Release(); 
        } 

        // Release the pointer to the IShellLink interface. 
        psl->Release(); 
    } 
    return hres; 
}


Is not that hard to write your own .lnk file format parser, but if the app is windows only why bother ?

http://www.codeproject.com/Articles/24001/Workaround-for-IShellLink-GetPath
Last edited on
You have more code than needed to resolve a shortcut, if you mean extracting the path it refers to: a NULL can be passed for the find data, and the description is being thrown away (do you plan to extend the function to return that, too?)

Ignoring the description, the following code works fine for me (tweaked to build ANSI and UNICODE, etc).

Succeeded: path = C:\WINDOWS\system32\mspaint.exe


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <objbase.h>
#include <shlobj.h>
#include <strsafe.h>
#include <iostream>
#include <iomanip>

#ifdef _UNICODE
#define TCOUT std::wcout
#define TCERR std::wcerr
#else
#define TCOUT std::cout
#define TCERR std::cerr
#endif

HRESULT ResolveIt(HWND hwnd, LPCTSTR lpszLinkFile, LPTSTR lpszPath, int iPathBufferSize);

int main()
{
	const TCHAR cachLinkFile[] = TEXT("C:\\Development\\Test\\Paint.lnk");

	HRESULT hres = CoInitialize(NULL);

	if(SUCCEEDED(hres))
	{
		TCHAR achPath[MAX_PATH] = {0};
		hres = ResolveIt(NULL, cachLinkFile, achPath, _countof(achPath));
		if (SUCCEEDED(hres))
		{
			TCOUT << TEXT("Succeeded: path = ") << achPath << std::endl;
		}
		else
		{
			TCERR << TEXT("Failed: error = 0x") << std::hex << hres << std::dec << std::endl;
		}

		CoUninitialize();
	}

	return 0;
}

HRESULT ResolveIt(HWND hwnd, LPCTSTR lpszLinkFile, LPTSTR lpszPath, int iPathBufferSize)
{
	if (lpszPath == NULL)
		return E_INVALIDARG;

	*lpszPath = 0;

	// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
	// has already been called.
	IShellLink* psl = NULL;
	HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
	if (SUCCEEDED(hres))
	{
		// Get a pointer to the IPersistFile interface.
		IPersistFile* ppf = NULL;
		hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
		if (SUCCEEDED(hres))
		{
			// Add code here to check return value from MultiByteWideChar
			// for success.

			// Load the shortcut.
#ifdef _UNICODE
			hres = ppf->Load(lpszLinkFile, STGM_READ);
#else
			WCHAR wsz[MAX_PATH] = {0};
			// Ensure that the string is Unicode.
			MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz, MAX_PATH);
			hres = ppf->Load(wsz, STGM_READ);
#endif

			if (SUCCEEDED(hres))
			{
				// Resolve the link.
				hres = psl->Resolve(hwnd, 0);

				if (SUCCEEDED(hres))
				{
					// Get the path to the link target.
					TCHAR szGotPath[MAX_PATH] = {0};
					hres = psl->GetPath(szGotPath, _countof(szGotPath), NULL, SLGP_SHORTPATH);

					if (SUCCEEDED(hres))
					{
						hres = StringCbCopy(lpszPath, iPathBufferSize, szGotPath);
					}
				}
			}

			// Release the pointer to the IPersistFile interface.
			ppf->Release();
		}

		// Release the pointer to the IShellLink interface.
		psl->Release();
	}
	return hres;
}
Last edited on
Acutally I got it this works phew. Wow that's still a crazy amount of code for something like this lol
Last edited on
I figured it out thanks man.
Last edited on
Topic archived. No new replies allowed.