Rnd

From NSIS Wiki
Jump to navigationJump to search
Author: Lloigor (talk, contrib)


Description

Generates a random number within a range using the RtlGenRandom api.

It can be used as is, or as a random seed generator for other functions, like http://nsis.sourceforge.net/Random. The Microsoft C Runtime Library makes use of this function (RtlGenRandom) in its implementation of "rand_s".

Example

!define tempfile "$EXEDIR\test_output.txt"
 
FileOpen $R0 "${tempfile}" "w"
StrCpy $3 0
loop:
   IntOp $3 $3 + 1
;--------------------------
   ${Rnd} $0 -50000 50000
;--------------------------
   FileWrite $R0 "$0$\r$\n"
   IntCmp $3 1000 0 loop
FileClose $R0
ExecWait 'notepad "${tempfile}"'
Delete "${tempfile}"

Function

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Generate a random number using the RtlGenRandom api
;; P1 :out: Random number
;; P2 :in:  Minimum value
;; P3 :in:  Maximum value
;; min/max P2 and P3 values = -2 147 483 647 / 2 147 483 647
;; max range = 2 147 483 647 (31-bit)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
!define Rnd "!insertmacro _Rnd"
!macro _Rnd _RetVal_ _Min_ _Max_
   Push "${_Max_}"
   Push "${_Min_}"
   Call Rnd
   Pop ${_RetVal_}
!macroend
Function Rnd
   Exch $0  ;; Min / return value
   Exch
   Exch $1  ;; Max / random value
   Push "$3"  ;; Max - Min range
   Push "$4"  ;; random value buffer
 
   IntOp $3 $1 - $0 ;; calculate range
   IntOp $3 $3 + 1
   System::Call '*(l) i .r4'
   System::Call 'advapi32::SystemFunction036(i r4, i 4)'  ;; RtlGenRandom
   System::Call '*$4(l .r1)'
   System::Free $4
   ;; fit value within range
   System::Int64Op $1 * $3
   Pop $3
   System::Int64Op $3 / 0xFFFFFFFF
   Pop $3
   IntOp $0 $3 + $0  ;; index with minimum value
 
   Pop $4
   Pop $3
   Pop $1
   Exch $0
FunctionEnd