Resolving shortcut paths in Code Blocks?

I'm creating a file browsing program using SFML, and have made a good amount of progress. However, so far it is unable to work properly with shortcuts, and examples I've seen of how to do this have always come straight from MSDN for Visual C++, and Code::Blocks doesn't play nice with some of the libraries involved. Is there a practical way to retrieve the path from a lnk file in Code Blocks, or to determine if the shortcut goes to a file or folder?
Last edited on
Seems this is what you are referring to? http://www.cplusplus.com/forum/windows/64088/
Yes, but that code won't compile in Code::Blocks. I've tried modifying it, importing libraries, etc. to no avail.
I just compiled this (had to make a few changes) with Code::Blocks using MinGW:

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
102
103
104
105
106
#define WIN32_LEAN_AND_MEAN
#define WINVER       0x0602
#define _WIN32_WINNT 0x0602
#define _WIN32_IE    0x0602

#include <windows.h>
#include <objbase.h>
#include <shlobj.h>
#include <cstdio>
#include <cstdlib>
#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("D:\\dev\\projects.lnk");

	HRESULT hres = CoInitialize(NULL);

	if(SUCCEEDED(hres))
	{
		TCHAR achPath[MAX_PATH] = {0};
		hres = ResolveIt(NULL, cachLinkFile, achPath, MAX_PATH);
		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, MAX_PATH, NULL, SLGP_SHORTPATH);

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

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

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


link with libole32.a and libuuid.a
It works! Thank you!

One quick question I had; does the first command on line 26 take a constant char? I know it doesn't work as a string. I need to figure out how to make the path of the link being resolved variable. Attempting to use constant chars or strings hasn't worked for me so far. For example, I made this slight change to test it out.

1
2
std::string X = "C:\\Desktop.lnk";
	const TCHAR cachLinkFile[] = TEXT(X);

error: initializer fails to determine size of cachLinkFile

When the "C:\\Desktop.lnk" is where the X is, it works great though.
I tried a couple other modifications in an attempt to apply X to the cachLinkFile, but no luck so far.

If I can get past this hurdle I should be able to integrate it into my file browser project, where it will be able to resolve link paths and browse the appropriate directory. Within the project, the browsing occurs by reading a vector of strings containing the directory listings, so the links to be resolved would be retrieved from there.

I think I have it figured out if I can determine the string length beforehand using
memcpy(cachLinkFile,X.c_str(),stringsize);
and initialize the cachLinkFile with a suitably large size of characters, though, as long as it occurs directly after cachLinkFile's initialization. For instance, this works:
1
2
3
    std::string X="C:\\Desktop.lnk";
	char cachLinkFile[64] = "";
    memcpy(cachLinkFile,X.c_str(),X.size());

I think I can take it from here. Thanks for the help!!
Last edited on
I'm pretty sure you can just do this:
1
2
std::string X = "C:\Desktop.lnk";
const TCHAR *cachLinkFile = X.c_str();
That also works. Thanks a lot, Texan40!
Topic archived. No new replies allowed.