Get link targets (shortcuts) / CallCOM

Just starting out? Need help? Post your questions and find answers here.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Max..

There is a nice snippet of Danilo

viewtopic.php?t=4945">http://forums.pur ... php?t=4945

to create links.

Did anyone figure out how to retrieve the path/target of existing links?

There is a GetPath Method which should do that



and I also found an example in C, but sadly I'm not smart enough to get it converted to PB.

http://www.codeguru.com/shell/gettingshortcuts.shtml


Max.

AMD Athlon, Matrox G550, Win 2K SP3, IE 6.0, PB 3.62
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

This works here:

Code: Select all

; ANSI version (works in Windows 95 and 98 too)

#CLSCTX_INPROC_SERVER = 1
#SLGP_UNCPRIORITY = 2

#QueryInterface = 0
#Release = 8
#GetArguments = 12
#GetPath = 32
#Load = 20

Procedure.s GetShortcutTarget(LinkFileName.s)
  Temp.s = LCase(LinkFileName)
  If FindString(Temp, ".lnk", 0)
    Link.s = LinkFileName
  Else
    Link.s = LinkFileName+".lnk"
  EndIf
  Info.s
  Shared psl ; IShellLink*
  hres = CoCreateInstance_(?CLSID_ShellLink, #NULL, #CLSCTX_INPROC_SERVER, ?IID_IShellLink, @psl)
  If hres=#S_OK
    Shared ppf ; IPersistFile*
    hres = CallCOM(#QueryInterface, psl, ?IID_IPersistFile, @ppf)
    If hres=#S_OK
      Dim wsz.w(#MAX_PATH)
      MultiByteToWideChar_(#CP_ACP, #MB_PRECOMPOSED, Link, -1, wsz(), #MAX_PATH)
      hres = CallCOM(#Load, ppf, wsz(), 0)
      If hres=#S_OK
        TempBuffer = AllocateMemory(0, 1024)
        CallCOM(#GetPath, psl, TempBuffer, 1024, #NULL, #SLGP_UNCPRIORITY)
        TempBuffer = MemoryID() ; TempBuffer variable trashed for some reason (weird!)
        Info.s = PeekS(TempBuffer)
        CallCOM(#GetArguments, psl, TempBuffer, 1024)
        Info+" "+PeekS(TempBuffer)
        FreeMemory(0)
      EndIf
    EndIf
    CallCOM(#Release, psl)
  EndIf
  ProcedureReturn Info
EndProcedure

CoInitialize_(0)
File$ = OpenFileRequester("Select link", "", "Link files (*.lnk)|*.lnk|All files (*.*)|*.*", 0)
If File$
  MessageRequester("Links to", GetShortcutTarget(File$), 0)
EndIf
CoUnInitialize_()

End

!section '.data' Data readable writeable
IID_IShellLink:
!dd $000214EE
!dw 0, 0
!db $0C0, 0, 0, 0, 0, 0, 0, $046
CLSID_ShellLink:
!dd $21401
!dw 0, 0
!db $0C0, 0, 0, 0, 0, 0, 0, $046
IID_IPersistFile:
!dd $0000010B
!dw 0, 0
!db $0C0, 0, 0, 0, 0, 0, 0, $046
El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Max..

Thanks El Choni!

Your variable declarations look "a little bit" different than mines.

But it doesn't work here...

Code: Select all

If hres =#S_OK
This condition is not met and the procedure returns an empty string. If I force it to get into it, the result is still empty.



Max.

AMD Athlon, Matrox G550, Win 2K SP3, IE 6.0, PB 3.62
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

Which one is failing? CoCreateInstance_() or the following CallComs?.

Try doing some error handling:

Code: Select all

If hres=#S_OK
 ...
Else
  Debug Hex(hres)
EndIf
And post the debugged result, to look up the error name. If you want to do it yourself, I'm using WINDOWS.INC file from Masm to see what error has occured.

El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Max..
Originally posted by El_Choni

Which one is failing? CoCreateInstance_() or the following CallComs? I bet this has to do with Win 2k (I've only tesed it in Win XP).
Sorry, forgot one line; this is the entire block now.
Seems that it fails at the Load Method.

Code: Select all

hres = CallCOM(#Load, ppf, wsz(), 0)      If hres=#S_OK
        TempBuffer = AllocateMemory(0, 1024)
        CallCOM(#GetPath, psl, TempBuffer, 1024, #NULL, #SLGP_UNCPRIORITY)
        TempBuffer = MemoryID() ; TempBuffer variable trashed for some reason (weird!)
        Info.s = PeekS(MemoryID())
        CallCOM(#GetArguments, psl, TempBuffer, 1024)
        Info+" "+PeekS(TempBuffer)
        FreeMemory(0)
      EndIf
    EndIf
Sadly I don't have XP avail at the moment. BTW, retested Danilo's CreateShortcut and that works on Win 2K.

Max.

AMD Athlon, Matrox G550, Win 2K SP3, IE 6.0, PB 3.62
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Max..
Originally posted by El_Choni

And post the debugged result, to look up the error name. If you want to do it yourself, I'm using WINDOWS.INC file from Masm to see what error has occured.
Ok, it's strange:

Code: Select all

Debug Hex(hres) -> 80070002
But:

I added now also - should have checked earlier - a

Code: Select all

Debug File$ -> C:\Programme\Ethereal\ethereal.exe
after the OpenFileRequester (yes, I opened a link: D:\Ethereal.lnk):

So it looks as if the OpenFileRequester resolves the link already.



If I hardcode

Code: Select all

File$ = "D:\Ethereal.lnk"
then your example works very well.

Is that behaviour different in Win 2K & XP?

BTW, thanks for your patience. :)


Max.

AMD Athlon, Matrox G550, Win 2K SP3, IE 6.0, PB 3.62
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by El_Choni.

In XP the link is not resolved by OpenFileRequester().

About the error code, I can't find that one in WINDOWS.INC, maybe in the header files from lcc (but I don't have lcc here).

Those are the error codes for IPersistFile::Load

Code: Select all

STG_E_INVALIDFUNCTION                equ 80030001h
STG_E_FILENOTFOUND                   equ 80030002h
STG_E_PATHNOTFOUND                   equ 80030003h
STG_E_TOOMANYOPENFILES               equ 80030004h
STG_E_ACCESSDENIED                   equ 80030005h
STG_E_INVALIDHANDLE                  equ 80030006h
STG_E_INSUFFICIENTMEMORY             equ 80030008h
STG_E_INVALIDPOINTER                 equ 80030009h
STG_E_NOMOREFILES                    equ 80030012h
STG_E_DISKISWRITEPROTECTED           equ 80030013h
STG_E_SEEKERROR                      equ 80030019h
STG_E_WRITEFAULT                     equ 8003001Dh
STG_E_READFAULT                      equ 8003001Eh
STG_E_SHAREVIOLATION                 equ 80030020h
STG_E_LOCKVIOLATION                  equ 80030021h
STG_E_FILEALREADYEXISTS              equ 80030050h
STG_E_INVALIDPARAMETER               equ 80030057h
STG_E_MEDIUMFULL                     equ 80030070h
STG_E_ABNORMALAPIEXIT                equ 800300FAh
STG_E_INVALIDHEADER                  equ 800300FBh
STG_E_INVALIDNAME                    equ 800300FCh
STG_E_UNKNOWN                        equ 800300FDh
STG_E_UNIMPLEMENTEDFUNCTION          equ 800300FEh
STG_E_INVALIDFLAG                    equ 800300FFh
STG_E_INUSE                          equ 80030100h
STG_E_NOTCURRENT                     equ 80030101h
STG_E_REVERTED                       equ 80030102h
STG_E_CANTSAVE                       equ 80030103h
STG_E_OLDFORMAT                      equ 80030104h
STG_E_OLDDLL                         equ 80030105h
STG_E_SHAREREQUIRED                  equ 80030106h
STG_E_NOTFILEBASEDSTORAGE            equ 80030107h
STG_E_EXTANTMARSHALLINGS             equ 80030108h
Maybe a solution would be to check if the returnd string ends in ".lnk". If it does, use the procedure, if it doesn't, use the string as it comes (suppose the link has been resolved).

El_Choni
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Max..

Yep, could do, but as I get the links from the Directory functions and them are not resolved, everything is fine.

BTW, you should post your code in the snippets section and upload it to PB's site.

Max.

AMD Athlon, Matrox G550, Win 2K SP3, IE 6.0, PB 3.62
Post Reply