
COM QueryInterface
Btw: to ensure your IShellLinkW code works with ANSI builds, pass strings with the "wstr" type.



Win7 HP SP1 64bit | AHK_L U 64bit
Reading only the excerpt which you quoted, it seems to me that maul.esel was showing code which produces a similar result, not telling you to use that code. Note the following:I just followed the maul.esel's tutorial.
You were passing an IID and therefore do not need to "unwrap" an object.If an IID is specified, an interface pointer is returned. (...)
Otherwise, a wrapper object usable by script is returned.

Changing Str to WStr in the all DllCall lines just gives n in the result with the ANSI build.Btw: to ensure your IShellLinkW code works with ANSI builds, pass strings with the "wstr" type.
By the way, although I appreciate your effort, there should be an example in here and there. They wouldn't be called a tutorial unless there is at least one working example. In fact, it caused lots of confusion when I was following it.
There isn't a working example so it is hard to tell what he meant.Reading only the excerpt which you quoted, it seems to me that maul.esel was showing code which produces a similar result, not telling you to use that code
By the way, any thoughts why the code produces only a file name? I expected it returns a full path. I tried the other flags for the GetPath method, LGP_SHORTPATH and SLGP_UNCPRIORITY but the same. Also should I add ObjRelease(pIPersistFile) before returning from the function?

In addition to it, in order to support the ANSI build, I found that the last line of the function had to be changed to:Changing Str to WStr in the all DllCall lines just gives n in the result with the ANSI build.
Return StrGet(&WIN32_FIND_DATA + 44, A_IsUnicode ? "utf-16" : "cp1200")By the way, If I put UTF-8 instead of UTF-16 in the Unicode builds, is started not returning the correct string. Does that mean IShellLinkW internally encodes strings as UTF-16?

Return StrGet(&WIN32_FIND_DATA + 44, A_IsUnicode ? "[color=green]utf-16[/color]" : "[color=darkred]cp1200[/color]")
FileEncoding
[*:x7c4pj88]UTF-16: Unicode UTF-16, little endian byte order. This is equivalent to CP1200.

Return StrGet(&WIN32_FIND_DATA + 44, "utf-16")
Any idea why the function only returns a file name, not the full path?

HRESULT GetPath( [[color=red]out[/color]] LPTSTR pszFile, [in] int cchMaxPath, [in, out] WIN32_FIND_DATA *pfd, [in] DWORD fFlags );

Here is the update. It works well.
lnkpath := A_ScriptDIr "\notepad.lnk" FileCreateShortcut, %A_WIndir%\notepad.exe, % lnkpath if target := IShellLinkResolve(lnkpath) msgbox % target else msgbox not found FileDelete, % lnkpath Return IShellLinkResolve(FilePath) { static IID_IShellLinkW := "{000214F9-0000-0000-C000-000000000046}" static CLSID_ShellLink := "{00021401-0000-0000-C000-000000000046}" static IID_IPersistFile := "{0000010b-0000-0000-C000-000000000046}" if !(pCOM_IShellLink := ComObjCreate(CLSID_ShellLink, IID_IShellLinkW)) return False if !(pIPersistFile := ComObjQuery(pCOM_IShellLink, IID_IPersistFile)) Return False vtIShellLink := NumGet(pCOM_IShellLink + 0) ;pointer to the vTable pIShellLink_GetPath := NumGet(vtIShellLink + 03 * A_PtrSize) pIShellLink_Resolve := NumGet(vtIShellLink + 19 * A_PtrSize) vtPersistFile := NumGet(pIPersistFile+0) pIPersistFile_Load := NumGet(vtPersistFile + 05 * A_PtrSize) ;defined in ObjIdl.h ;IPersistFile::Load http://msdn.microsoft.com/en-us/library/windows/desktop/ms687284%28v=vs.85%29.aspx ;Flags http://msdn.microsoft.com/en-us/library/windows/desktop/aa380337%28v=vs.85%29.aspx if hresult := DllCall(pIPersistFile_Load , "Ptr", pIPersistFile , "wStr", FilePath , "Uint", 0x00000000) ;STGM_Read return false ;http://msdn.microsoft.com/en-us/library/windows/desktop/bb774952%28v=vs.85%29.aspx if hresult := DllCall(pIShellLink_Resolve , "ptr", pCOM_IShellLink , "Ptr", A_ScriptHwnd , "Uint", 0x0001) ;SLR_NO_UI return false ; IShellLink::GetPath http://msdn.microsoft.com/en-us/library/windows/desktop/bb774944%28v=VS.85%29.aspx VarSetCapacity(WIN32_FIND_DATA, 592) VarSetCapacity(target, 260) if hresult := DllCall(pIShellLink_GetPath , "ptr", pCOM_IShellLink , "wStr", target , "Int", 260 , "Ptr", &WIN32_FIND_DATA , "Uint", 0x4) ; SLGP_SHORTPATH = 0x1 SLGP_UNCPRIORITY = 0x2 SLGP_RAWPATH = 0x4 return false ObjRelease(pIPersistFile) ObjRelease(pCOM_IShellLink) Return target }

VarSetCapacity(target, 260 [color=red]* 2[/color])It's unicode!

By the way, I noticed that it didn't run in the ANSI build regardless the suggested change.
Here is the updated function which also runs with the ANSI build.
IShellLinkResolve(FilePath) { static IID_IShellLinkW := "{000214F9-0000-0000-C000-000000000046}" static CLSID_ShellLink := "{00021401-0000-0000-C000-000000000046}" static IID_IPersistFile := "{0000010b-0000-0000-C000-000000000046}" if !(pCOM_IShellLink := ComObjCreate(CLSID_ShellLink, IID_IShellLinkW)) return False if !(pIPersistFile := ComObjQuery(pCOM_IShellLink, IID_IPersistFile)) Return False ;IPersistFile::Load http://msdn.microsoft.com/en-us/library/windows/desktop/ms687284%28v=vs.85%29.aspx ;Flags http://msdn.microsoft.com/en-us/library/windows/desktop/aa380337%28v=vs.85%29.aspx if hresult := DllCall(NumGet(NumGet(pIPersistFile+0) + 05 * A_PtrSize) ;IPersistFile::Load , "Ptr", pIPersistFile , "wStr", FilePath , "Uint", 0x00000000) ;STGM_Read return false ;http://msdn.microsoft.com/en-us/library/windows/desktop/bb774952%28v=vs.85%29.aspx if hresult := DllCall(NumGet(NumGet(pCOM_IShellLink + 0) + 19 * A_PtrSize) ;IShellLink:Resolve , "ptr", pCOM_IShellLink , "Ptr", A_ScriptHwnd , "Uint", 0x0001) ;SLR_NO_UI return false ; IShellLink::GetPath http://msdn.microsoft.com/en-us/library/windows/desktop/bb774944%28v=VS.85%29.aspx VarSetCapacity(WIN32_FIND_DATA, 592) VarSetCapacity(target, 260 * 2) if hresult := DllCall(NumGet(NumGet(pCOM_IShellLink + 0) + 03 * A_PtrSize) ;IShellLink:GetPath , "ptr", pCOM_IShellLink , "ptr", &target , "Int", 260 ;[color=red]<-- not sure if it should be 260*2[/color] , "Ptr", &WIN32_FIND_DATA , "Uint", 0x4) ; SLGP_SHORTPATH = 0x1 SLGP_UNCPRIORITY = 0x2 SLGP_RAWPATH = 0x4 return false ObjRelease(pIPersistFile) ObjRelease(pCOM_IShellLink) Return StrGet(&target, "utf-16") }

VarSetCapacity()
Parameters
RequestedCapacity
Specify for RequestedCapacity the number of bytes that the variable should be able to hold after the adjustment. For Unicode strings, this should be the length times two.

IShellLink::GetPath method
cchMaxPath [in]
Type: int
The size, in characters, of the buffer pointed to by the pszFile parameter, including the terminating null character. The maximum path size that can be returned is MAX_PATH. This parameter is commonly set by calling ARRAYSIZE(pszFile). The ARRAYSIZE macro is defined in Winnt.h.

