A customer wanted to be able to get the target of a shortcut with environment variables unexpanded. The IShellLink::GetPath method will expand environment variables.
The way to get the unexpanded target path is to go for the EXP_SZ_LINK data in the shell link data list. We briefly encountered the shell link data list a while back. Now we’ll dig in a little more.
#include <windows.h>
#include <shlobj.h>
#include <stdio.h> // Horrors! Mixing stdio and C++!
#include <atlbase.h>
#include <atlalloc.h>
int __cdecl wmain(int argc, wchar_t**argv)
{
CCoInitialize init;
CComPtr<IShellLink> lnk;
CoCreateInstance(CLSID_ShellLink, 0,
CLSCTX_ALL, IID_PPV_ARGS(&lnk));
CComQIPtr<IPersistFile> pf(lnk);
pf->Load(argv[1], STGM_READ);
CComQIPtr<IShellLinkDataList> list(lnk);
DWORD flags;
list->GetFlags(&flags);
if (flags & SLDF_HAS_EXP_SZ) {
CHeapPtr<void, CLocalAllocator> rawData;
list->CopyDataBlock(EXP_SZ_LINK_SIG, &rawData);
auto linkData = reinterpret_cast<EXP_SZ_LINK *>(static_cast<void *>(rawData));
printf("Unexpanded target = %ls\n", linkData->swzTarget);
}
return 0;
}
After loading the shortcut file, we ask the IShellLinkDataList to inspect the shortcut flags. If the SLDF_HAS_EXP_SZ flag is set, then the path to the target contains an environment variable reference. To get the original unexpanded path, ask for the EXP_SZ_LINK_SIG data block. That returns a data block in the form of a EXP_SZ_LINK structure, from which you can extract the unexpanded paths.
0 comments