Hi,
This example creates a shortcut to notepad.exe in the same directory. This is a 64-bit VS 2022 project
but it can also be compiled with makeit.bat. :thup:
; MSDN example
; https://learn.microsoft.com/en-us/windows/win32/shell/links#creating-a-shortcut-and-a-folder-shortcut-to-a-file
include \masm32\include64\masm64rt.inc
.data
;********************************************
IID_IShellLinkA dd 214EEh
dw 0,0,0c0h
db 0,0,0,0,0,46h
;********************************************
IID_IShellLinkW dd 214F9h
dw 0,0,0c0h
db 0,0,0,0,0,46h
;********************************************
CLSID_ShellLink dd 21401h
dw 0,0,0c0h
db 0,0,0,0,0,46h
;********************************************
IID_IPersistFile dd 10bh
dw 0,0,0c0h
db 0,0,0,0,0,46h
;********************************************
pIShellLink dq 0
ppf dq 0
lpszPathLink dw "t","o","N","o","t","e","p","a","d",".","l","n","k",0,0,0,0
lpszPathObj db "C:\Windows\System32\notepad.exe",0
lpszDesc db "Shortcut to Notepad",0
;*******************************************************************;
.code
main proc
xor ecx, ecx
mov edx, 2
call CoInitializeEx
call Shortcut
call CoUninitialize
xor ecx, ecx
call ExitProcess
main endp
;*******************************************************************;
Shortcut proc
lea rax, pIShellLink ; Result -> IID_IShellLinkW interface
lea r9, IID_IShellLinkA
mov [rsp+4*8], rax
mov r8d, 1 ; 1 = CLSCTX_INPROC_SERVER
xor edx, edx
lea rcx, CLSID_ShellLink
call CoCreateInstance
test eax, eax ; eax = 0 -> Success
jne Ret_0 ; return FALSE
mov rcx, pIShellLink ; IID_IShellLinkW interface
lea r8, ppf ; Result -> IID_IPersistFile interface
mov rax, [rcx] ; rax -> Vtbl with methods
lea rdx, IID_IPersistFile
call qword ptr [rax+0*8] ; IID_IShellLinkW::QueryInterface method = 0*8
test eax, eax ; eax = 0 -> Success
jne Ret_B ; return FALSE
mov rcx, pIShellLink ; IID_IShellLinkW interface
mov rax, [rcx] ; IID_IShellLink::IShellLinkAVtbl
lea rdx, lpszPathObj ; Pointer to ANSI string
call qword ptr [rax+20*8] ; IID_IShellLinkW::SetPath method in IShellLinkA = 20*8
test eax, eax ; eax = 0 -> Success
jne Ret_A
mov rcx, pIShellLink ; IID_IShellLinkW interface
lea rdx, lpszDesc ; Pointer to ANSI string
mov rax, [rcx] ; IID_IShellLinkW::IShellLinkWVtbl ; Vtbl with methods
call qword ptr [rax+7*8] ; IID_IShellLinkW::SetDescription method in IShellLinkAVtbl = 7*8
test eax, eax ; eax = 0 -> Success
jne Ret_A
mov rcx, ppf ; IID_IPersistFile interface
lea rdx, lpszPathLink ; Pointer to Unicode string
xor r8d, r8d ; fRemember parameter = 0
mov rax, [rcx] ; IID_IPersistFile::Vtbl with methods
call qword ptr [rax+6*8] ; IID_IPersistFile::Save method = 6*8
test eax, eax ; eax = 0 -> Success
jne Ret_A
; ppf->Release()
mov rcx, ppf ; IID_IPersistFile interface
mov rax, [rcx] ; IID_IPersistFile::Vtbl with methods
call qword ptr [rax+2*8] ; IID_IPersistFile::Release method
; pIShellLink->Release()
mov rcx, pIShellLink ; IID_IShellLinkW interface
mov rax, [rcx] ; IID_IShellLinkW::IShellLinkWVtbl ; Vtbl with methods
call qword ptr [rax+2*8] ; IID_IShellLinkW::Release method
mov eax, 1 ; Return 1 -> success
ret
Ret_A:
; ppf->Release()
mov rcx, ppf ; IID_IPersistFile interface
mov rax, [rcx] ; Vtbl with methods
call qword ptr [rax+2*8] ; IID_IPersistFile::Release method
Ret_B:
; pIShellLink->Release()
mov rcx, pIShellLink ; IID_IShellLinkW interface
mov rax, [rcx] ; Vtbl with methods
call qword ptr [rax+2*8] ; IID_IShellLinkW::Release method
Ret_0:
xor eax, eax ; Error -> return FALSE
ret
Shortcut endp
;*******************************************************************;
end
Nice. :thumbsup:
Thank you
zedd151, :thumbsup:
Quoteby zedd151: I will delegate that task to the 64 bit gurus.
The "64 bit gurus" are probably still on long vacation... Just kidding... :biggrin:
Just because I don't write code in 64 bit, doesn't mean I can't test other peoples work. :biggrin:
I had to adjust the paths btw - for my build environment - to make it work. :cool: attached below
for the source file:
"include \masm32\include64\masm64rt.inc"
to
"include \masm64\include64\masm64rt.inc"
for the batch file:
"\masm32\bin64\ml64.exe /c /nologo %appname%.asm"
"\masm32\bin64\polink.exe /SUBSYSTEM:WINDOWS /ENTRY:main %appname%.obj"
to
"\masm64\bin64\ml64.exe /c /nologo %appname%.asm"
"\masm64\bin64\link.exe /SUBSYSTEM:WINDOWS /ENTRY:main %appname%.obj"
and changed "polink" to "link", as I have removed polink from my install of the SDK. :smiley:
The attachment contains only what is needed to build without Visual Studio.