Skip to content
⌘ NSIS Forum Archive

kernel32::GlobalAlloc not working in v3.8

6 posts

papaimark#

kernel32::GlobalAlloc not working in v3.8

Hi, dudes.
I have this masterpiece I made in 2008 that I use almost every day.
This is shell, "copy the path" and send to clipboard.
But
Compiled with v3.08 it GETS the path in $0 but does NOT send it to clipboard. (to paste elsewhere)
Compiling it with v2.3, it works!!!

What am I missing?
;...dadada..

!include ${NSISDIR}\Include\WinMessages.nsh
!include "${NSISDIR}\Include\FileFunc.nsh"
!insertmacro GetParameters
SilentInstall Silent
LoadLanguageFile "PORTUGUESEBR.NLF"
xpstyle on ##Using w7x64 !!

;...dadada...

Push $0
Exch $0 ;input string
Push $1
Push $2
System::Call 'user32::OpenClipboard(i 0)'
System::Call 'user32::EmptyClipboard()'
StrLen $1 $0
IntOp $1 $1 + 1
System::Call 'kernel32::GlobalAlloc(i 2, i r1) i.r1'
System::Call 'kernel32::GlobalLock(i r1) i.r2'
System::Call 'kernel32::lstrcpyA(i r2, t r0)'
System::Call 'kernel32::GlobalUnlock(i r1)'
System::Call 'user32::SetClipboardData(i 1, i r1)'
System::Call 'user32::CloseClipboard()'
Pop $2
Pop $1
Pop $0

Used in function .oninit.
I am using W7 64 but compiling with v2.8 it works since w98

Thanks for any help!
JasonFriday13#
I don't remember when NSIS 3.xx switched to unicode by default, but with 3.08 you are trying to copy a unicode string with an ansi function, so you need to convert the script to be unicode aware. Also note that the 'p' type is only supported in v2.51 and v3+, change those back to 'i' if you are using an older version.

Push $0
Exch $0 ;input string
Push $1
Push $2
Push $3
System::Call 'user32::OpenClipboard(p 0)'
System::Call 'user32::EmptyClipboard()'
StrLen $1 $0
IntOp $1 $1 + 1
!ifdef NSIS_UNICODE
IntOp $1 $1 * ${NSIS_CHAR_SIZE}
StrCpy $3 13
!else
StrCpy $3 1
!endif
System::Call 'kernel32::GlobalAlloc(i 2, i r1) p.r1'
System::Call 'kernel32::GlobalLock(p r1) p.r2'
System::Call 'kernel32::lstrcpy(p r2, t r0)'
System::Call 'kernel32::GlobalUnlock(p r1)'
System::Call 'user32::SetClipboardData(i r3, p r1)'
System::Call 'user32::CloseClipboard()'
Pop $3
Pop $2
Pop $1
Pop $0 
JasonFriday13#
Sorry, just realized there is a mistake in the script. lstrcpy is an alias, so that has to be separated out in order to work on pre-win2000 machines.

Push $0
Exch $0 ;input string
Push $1
Push $2
Push $3
System::Call 'user32::OpenClipboard(p 0)'
System::Call 'user32::EmptyClipboard()'
StrLen $1 $0
IntOp $1 $1 + 1
!ifdef NSIS_UNICODE
IntOp $1 $1 * ${NSIS_CHAR_SIZE}
StrCpy $3 13
!else
StrCpy $3 1
!endif
System::Call 'kernel32::GlobalAlloc(i 2, i r1) p.r1'
System::Call 'kernel32::GlobalLock(p r1) p.r2'
!ifdef NSIS_UNICODE
System::Call 'kernel32::lstrcpyW(p r2, w r0)'
!else
System::Call 'kernel32::lstrcpyA(p r2, m r0)'
!endif
System::Call 'kernel32::GlobalUnlock(p r1)'
System::Call 'user32::SetClipboardData(i r3, p r1)'
System::Call 'user32::CloseClipboard()'
Pop $3
Pop $2
Pop $1
Pop $0 
papaimark#
Thank you very much, JasonFriday13.
Both codes worked fine.
If this is allowed here, there goes the full code that fits my needs,
just in case someone wants to modify and use it.
Needs an icon, cp.ico, that shows in left click (shell).

VIProductVersion 2.1.0.0
VIAddVersionKey /LANG=1046 "LegalCopyright" "Your name here"
VIAddVersionKey /LANG=1046 "FileDescription" "INFARTE - Arte em Informática do Papai Mark"
VIAddVersionKey /LANG=1046 "FileVersion" "Versão unicode para nsis 3.8"
VIAddVersionKey /LANG=1046 "ProductName" "Copy the path"
VIAddVersionKey /LANG=1046 "ProductVersion" "2.1, ${__TIMESTAMP__}"
#_________________________________________________________________________
Name "Copiar o Passo"
OutFile "..\Copiar_Passo.exe"
!include ${NSISDIR}\Include\WinMessages.nsh
!include "${NSISDIR}\Include\FileFunc.nsh"
!insertmacro GetParameters
SilentInstall Silent
AutoCloseWindow True
Caption "Papai Mark copia o passo"
Icon cp.ico

Function .OnInit
System::Call "kernel32::CreateMutexA(i 0, i 0, t 'CopiarPassoNoExplorer_PapaiMark') i .r0 ?e"
Pop $R0
StrCmp $R0 0 certo
Banner::show /NoUnload "O Copiador do passo já está aberto !" # only one instance.
Sleep 2000
Banner:😁estroy
Quit

Certo: #Just run Copiar_Passo.exe once and it will register itself.
WriteRegStr HKCR "*\shell\Copiar_Passo" "" "Copiar o Passo"
WriteRegStr HKCR "*\shell\Copiar_Passo\command" "" '$exedir\Copiar_Passo.exe %1'
WriteRegStr HKCR "*\shell\Copiar_Passo" "Icon" "$exedir\Copiar_Passo.exe,0"
WriteRegStr HKCR "Folder\shell\Copiar_Passo" "" "Copiar o Passo"
WriteRegStr HKCR "Folder\shell\Copiar_Passo\command" "" '$exedir\Copiar_Passo.exe %1'
WriteRegStr HKCR "Folder\shell\Copiar_Passo" "Icon" "$exedir\Copiar_Passo.exe,0"
WriteRegStr HKCU "Software\VB and VBA Program Settings\Copiar_Passo" "" "Copiar o Passo" # dont ask me why this is here
WriteRegStr HKCU "Software\VB and VBA Program Settings\Copiar_Passo" "Icon" "$exedir\Copiar_Passo.exe,0"
WriteRegStr HKCU "Software\VB and VBA Program Settings\Copiar_Passo\command" "" '$exedir\Copiar_Passo.exe %1'

${GetParameters} $R0
StrCmp $R0 "" Info
StrCpy $0 $R0

Push $0
Exch $0 ;input string
Push $1
Push $2
Push $3
System::Call 'user32::OpenClipboard(p 0)'
System::Call 'user32::EmptyClipboard()'
StrLen $1 $0
IntOp $1 $1 + 1
!ifdef NSIS_UNICODE
IntOp $1 $1 * ${NSIS_CHAR_SIZE}
StrCpy $3 13
!else
StrCpy $3 1
!endif
System::Call 'kernel32::GlobalAlloc(i 2, i r1) p.r1'
System::Call 'kernel32::GlobalLock(p r1) p.r2'
!ifdef NSIS_UNICODE
System::Call 'kernel32::lstrcpyW(p r2, w r0)'
!else
System::Call 'kernel32::lstrcpyA(p r2, m r0)'
!endif
System::Call 'kernel32::GlobalUnlock(p r1)'
System::Call 'user32::SetClipboardData(i r3, p r1)'
System::Call 'user32::CloseClipboard()'
Pop $3
Pop $2
Pop $1
Pop $0
GoTo fim

Info: # this only pops when executing the executable itself. Just once and it will register itself. keep, fill as you wish.
MessageBox MB_OK|MB_topmost|MB_IconInformation "Copiar o Passo é um utilitário \
do Papai Mark para que o passo$\rcompleto de um arquivo ou programa seja copia\
do para a área$\rde transferência através do clique direito do mouse ( shell ) \
no$\rExplorer do Windows.$\rVeja o log em $exedir\usos.ini$\rCriado originalmente em 2008."

fim: # Just kinda log memories. It may help.
ReadIniStr $9 "$exedir\Usos.ini" "Quantas vezes foi usado desde 07JUN20:" "Count"
IntOp $9 $9 + 1
${GetTime} "L" "L" $1 $2 $3 $5 $6 $7 $8 ;dia mes ano ddsemana hora minuto segundo
WriteIniStr "$exedir\Usos.ini" "Quantas vezes este programa foi usado desde 07JUN20" "Count" "$9" # used since...
WriteIniStr "$exedir\Usos.ini" "Usado em:" "$1/$2/$3-$6h$7m$8s" "$0"
FunctionEnd

Section
Sectionend