The following works with Unicode enabled or disabled, and also work with EnableExplicit enabled or disabled.
Hopefully more tips and tricks code will be tested and made to work with those two compile options. (points a finger at the others)

Hopefully the code speaks for itself, it was based on Danilo's http://www.purebasic.fr/english/viewtopic.php?t=8668 code.
But made unicode "compatible" and EnableExplicit "compatible" and enhanced to make almost all arguments optional or have sensible defaults.
The link filename can be specified with or without ".lnk" at the end, the procedure will add it if missing.
Code: Select all
Procedure.l CreateShellFileLink(path$,link$,args$="",desc$="",workpath$="",showcommand.l=#SW_SHOWNORMAL,hotkey.l=#Null,icon$="",iconindex.l=0)
Protected ppf.IPersistFile,hres.l,result.l
CompilerIf #PB_Compiler_Unicode
Protected psl.IShellLinkW
CompilerElse
Protected psl.IShellLinkA,mem.s
CompilerEndIf
If workpath$=""
workpath$=GetPathPart(path$)
EndIf
If icon$=""
icon$=path$
EndIf
If (LCase(Right(link$,4))<>".lnk")
link$+".lnk"
EndIf
If CoInitialize_(#Null)=#S_OK
If CoCreateInstance_(?CLSID_ShellLink,0,1,?IID_IShellLink,@psl)=#S_OK
Set_ShellLink_preferences:
psl\SetPath(@path$)
psl\SetArguments(@args$)
psl\SetWorkingDirectory(@workpath$)
psl\SetDescription(@desc$)
psl\SetShowCmd(showcommand)
psl\SetHotkey(hotkey)
psl\SetIconLocation(@icon$,iconindex)
If psl\QueryInterface(?IID_IPersistFile,@ppf)=#S_OK
CompilerIf #PB_Compiler_Unicode
hres=ppf\Save(@link$,#True)
CompilerElse
mem.s=Space(#MAX_PATH)
MultiByteToWideChar_(#CP_ACP,#Null,link$,-1,mem,Len(mem))
hres=ppf\Save(@mem,#True)
CompilerEndIf
result=1
ppf\Release()
EndIf
psl\Release()
EndIf
CoUninitialize_()
EndIf
ProcedureReturn result
DataSection
IID_IShellLink:
CompilerIf #PB_Compiler_Unicode
Data.l $000214F9
CompilerElse
Data.l $000214EE
CompilerEndIf
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46
CLSID_ShellLink:
Data.l $00021401
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46
IID_IPersistFile:
Data.l $0000010b
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46
EndDataSection
EndProcedure
CreateShellFileLink("c:\windows\system32\calc.exe","c:\test")