NSIS ANTI EMULATOR - nsis

I'm trying to make a anti emulator
allocating a big memory region and force the kernel to commit the pages to physical ram by filling the memory with values because the emulator can't allocate too much memory
But I don't know how to fill the memory with values of that region
this is what I made so far
System::Call "kernel32::LocalAlloc(i 0, i 143978374) p .r0" ; allocate 143 978 374 bytes and write pointer in $0
;I need to fill the memory with values here
System::Call "kernel32::LocalFree(p r0)"

If you call LocalAlloc with the LMEM_ZEROINIT flag Windows might write to the buffer for you. Technically speaking, this might be a implementation detail and in theory a future system could support such a feature in hardware. Your emulation thing, whatever that is, might ignore it as well.
You can write to memory with the system plug-in struct syntax:
!define PAGESIZE 4096
!define BLOBSIZE 143978374
!include Util.nsh
!ifndef IntPtrOp ; NSIS 2 compatibility
!define IntPtrOp IntOp
!endif
!ifndef IntPtrCmpU
!define IntCmpU
!endif
System::Alloc ${BLOBSIZE} ; This calls GlobalAlloc(GPTR, ...)
Pop $0
${IntPtrCmpU} $0 0 done "" "" ; Failure to allocate memory?
StrCpy $1 $0 ; Start
${IntPtrOp} $2 $1 + ${BLOBSIZE} ; End
loop:
System::Call '*$1(&i1 42)' ; Set the first byte in the page to 42
${IntPtrOp} $1 $1 + ${PAGESIZE}
${IntPtrCmpU} $1 $2 "" loop ""
System::Free $0
done:
The System plug-in is not super fast so a large memory block will take a while to fill.

Related

How to check the space in the drive by taking the path from the Destination Folder When installing the software using NSIS

How to check the space in the drive by taking the path from the Destination Folder When installing the software.
I am able to check the space of the specific drive (for eg, "C") using the below code snippet.
But I want to take the drive or path from the Destination folder dynamically and check the space of the drive whether there is enough space or not.
!define sysGetDiskFreeSpaceEx 'kernel32::GetDiskFreeSpaceExA(t, *l, *l, *l) i'
function CheckSpaceFunc
IntCmp $2 0 ignorequota
; obey quota
System::Call '${sysGetDiskFreeSpaceEx}(r1,.r2,,.)'
goto converttokb
; ignore quota
ignorequota:
System::Call '${sysGetDiskFreeSpaceEx}(r1,.,,.r2)'
converttokb:
; convert the large integer byte values into managable kb
System::Int64Op $2 / 1024
Pop $2
; check space
System::Int64Op $2 > $0
Pop $2
functionend
Section "TestApp"
SectionIn RO
StrCpy $0 40000 ; kb u need
StrCpy $1 'c:' ; check drive c: for space
Call CheckSpaceFunc
IntCmp $2 1 okay
MessageBox MB_OK "Error: Not enough disk space"
okay:
SectionEnd
Could anyone please help me
The built-in directory page (Page Directory or !insertmacro MUI_PAGE_DIRECTORY) will perform the free space check for you and takes care of all the details.
It might be tempting to just do StrCpy $1 $InstDir 3 to get the drive letter and perform the check yourself but this can give you the wrong result because NTFS supports mounting other volumes as a folder.
GetDiskFreeSpaceEx does support directory paths but I believe the path has to exist so if you want to use $InstDir before $InstDir has been created then you must chop off subfolders until GetDiskFreeSpaceEx succeeds (or you only have a invalid drive letter left of the path).
Your !define should also be changed from GetDiskFreeSpaceExA to GetDiskFreeSpaceEx because it uses the t string type. This will make it Unicode compatible.

Check/Prevent Windows Shutdown (NSIS)

To summarize, I need to check and/or prevent a user if he/she decides to shutdown the computer while the installer is running. Now I've researched for a while and came up with the following:
${If} ${AtMostWinXP}
System::Call `kernel32::GetModuleHandle(i0)i.r3`
System::Call `user32::CreateWindowEx(i0,t"STATIC",t"MyApp",i0,i0,i0,i0,i0,i$HWNDPARENT,i0,ir3,i0)i.r1`
${ElseIf} ${AtLeastVista}
System::Call `user32::ShutdownBlockReasonCreate(ir1,w"MyApp is running and still needs to clean up before shutting down!")i.r0`
${EndIf}
However the above snippet isn't working. Am I missing something? I've tried using just:
System::Call `kernel32::GetModuleHandle(i0)i.r3`
System::Call `user32::CreateWindowEx(i0,t"STATIC",t"MyApp",i0,i0,i0,i0,i0,i$HWNDPARENT,i0,ir3,i0)i.r1`
System::Call `user32::ShutdownBlockReasonCreate(ir1,w"MyApp is running and still needs to clean up before shutting down!")i.r0`
As the first two calls are meant for Windows XP and earlier and the third call is meant for Windows Vista or later but is ignored by Windows XP and earlier I believe (I have no evidence to support this theory). This too isn't working.
Also, I can use user32::ShutdownBlockReasonCreate(ir1,w"$(PreventShutdown)")i.r0 instead of using the entire string in the above snippet for different language support, right?
Your code for Windows XP makes no sense, the window needs to handle WM_QUERYENDSESSION to block the shutdown. Luckily NSIS already handles WM_QUERYENDSESSION for you.
Use something like this for Vista and later:
LoadLanguageFile "${NSISDIR}\Contrib\Language Files\English.nlf"
LangString BlockReason ${LANG_ENGLISH} "Installer blah blah"
LoadLanguageFile "${NSISDIR}\Contrib\Language Files\Swedish.nlf"
LangString BlockReason ${LANG_SWEDISH} "Installer bork bork"
!include nsDialogs.nsh ; For WS_CHILD
!define /ifndef WS_POPUP 0x80000000
!include LogicLib.nsh
Function CreateShutdownBlockReason
StrCpy $1 $hwndParent
${If} $1 Z= 0 ; $hwndParent is 0, create a new window for silent installers
System::Call 'USER32::CreateWindowEx(i0, t "STATIC", t "$(^Name)", i ${WS_CHILD}|${WS_POPUP}, i0, i0, i0, i0, p r1, i0, i0, i0)p.r1'
${EndIf}
System::Call 'USER32::ShutdownBlockReasonCreate(p r1, w "$(BlockReason)")'
FunctionEnd
Function .onInit
IfSilent 0 +2
Call CreateShutdownBlockReason ; .onGuiInit is not executed in silent installers
FunctionEnd
Function .onGuiInit
Call CreateShutdownBlockReason
FunctionEnd
I'm not sure if a silent installer will be able to block the shutdown but this is the best you can do without a plug-in.

get hard disk drive name in which windows OS installed using NSIS

I need to get hard disk drive letter like C: or D: or any in which the OS is installed on any windows.
Kindly help me get out of this.
Section
StrCpy $0 $sysdir 3
DetailPrint $0
SectionEnd
$SYSDIR is the Windows system directory (usually C:\Windows\System or C:\WinNT\System32, but that's detected at runtime).
StrCpy has the syntax StrCpy user_var(destination) str(source) [maxlen] [start_offset] where maxlen and start_offset are optional.
So the code above, copies the first three letters from $SYSDIR into the $0 variable.

Can i detect 32 or 64 bit OS without plugin somehow?

now i use the x64.nsh for this, but i can detect it without this plugin?
${If} ${RunningX64}
MessageBox MB_OK "running on 64 bit"
File /r ${64BIT_OPENVPN_INSTALL}
Execwait ${64BIT_OPENVPN_INSTALL}
${Else}
MessageBox MB_OK "running on 32 bit"
File /r ${32BIT_OPENVPN_INSTALL}
Execwait ${32BIT_OPENVPN_INSTALL}
${EndIf}
x64.nsh does not implies specific external plugin usage (apart the system plugin): it is just an included file that defines 3 macros based on kernel calls (i.e kernel32::GetCurrentProcess() and kernel32::IsWow64Process()) through the system plugin, that can be conveniently used with LogicLib.nsh
There are probably many ways to detect the native bitness by just looking at files and registry keys but there is always the risk that some 32-bit systems have somehow ended up with a SysWOW64 folder in %WinDir% etc.
The SetRegView test should be pretty safe but there is a small window where some other app could change the registry at just the wrong time giving you the wrong result.
The correct way to detect this is of course to call the IsWow64Process function and the x64.nsh header already does that for you.
!include LogicLib.nsh
Section
!if "${NSIS_PTR_SIZE}" > 4
DetailPrint "64-bit NSIS, this must be a 64-bit system"
!endif
${If} ${FileExists} "$WinDir\SysWOW64\kernel32.dll"
DetailPrint "Probably not a native 32-bit system"
${EndIf}
${If} ${FileExists} "$WinDir\SysNative\kernel32.dll"
DetailPrint "Probably a 32-bit app on a native 64-bit system (Vista+ only)"
${EndIf}
SetRegView 64
ReadRegStr $6 HKLM "Software\Microsoft\Windows\CurrentVersion" "ProgramFilesDir"
SetRegView lastused
SetRegView 32
ReadRegStr $3 HKLM "Software\Microsoft\Windows\CurrentVersion" "ProgramFilesDir"
SetRegView lastused
${If} $3 != $6
DetailPrint "Probably a 32-bit app on a native 64-bit system"
${EndIf}
; ReadEnvStr on ProgramW6432 or PROCESSOR_ARCHITEW6432 etc
SectionEnd

How to get system drive volume serial number

I am building a setup which requires to retrieve the disk volume of the drive on which the Operating system is installed. I have tried the following code:
Function ShowDiskVolumeSerialNumber
!define GetVolumeInformation "Kernel32::GetVolumeInformation(t,t,i,*i,*i,*i,t,i) i"
System::Call '${GetVolumeInformation ("$0",,${NSIS_MAX_STRLEN},.r0,,,,${NSIS_MAX_STRLEN})'
IntFmt $0 "%08X" $0
MessageBox MB_OK $0
FunctionEnd
I call the above function by specifying the desired drive:
StrCpy $0 "C:\"
Call ShowDiskVolumeSerialNumber
The above gives the volume no of c:\ drive. However if my OS is installed on d:\ or e:\ it will not work. I want a function which will automatically detect the drive on which the OS is installed and retrieve its volume no.
Secondly, the volume number retrieved is without a hyphen (e.g. 349620C1). I need the volume serial number retrieved as 3496-20C1.
Could someone please give a complete NSIS function when will do both the things i.e:
Automatically detect the drive on which the OS is installed and retrieve its serial no with a hyphen in between.
To get the OS drive, StrCpy $0 $windir 3 is probably enough (You did not specify if you wanted the boot volume or the system volume, on most systems they are the same so $windir is a good starting point)
To edit the serial number:
StrCpy $0 $serial 4
StrCpy $serial $serial "" 4
StrCpy $serial "$0-$serial"

Resources