Function Passgen($iLen,Optional $sSalt,$sRequires)
Dim $iSalt,$i,$t,$s
Dim $asTemplate[]
Dim $sAlphaUpper,$sAlphaLower,$sNumeric,$sSpecial,$iRand
$sAlphaUpper="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
$sAlphaLower="abcdefghijklmnopqrstuvwxyz"
$sNumeric="1234567890"
$sSpecial="!£$$%^&*()_+-=[]{};;@@#~,./<>?"
If CInt($iLen)<Len($sRequires) $iLen=Len($sRequires) EndIf
ReDim $asTemplate[$iLen-1]
; If no salt is specified then create on based on the date/time
If $sSalt="" $sSalt=@DATE+@TIME+@MSECS EndIf
; Convert salt string to numeric
$iSalt=54321
While $sSalt<>""
$iSalt=($iSalt*10+Asc($sSalt))
$sSalt=SubStr($sSalt,2)
Loop
; Seed RNG, discard first result
SRND($iSalt) $Passgen=Rnd()
; Create template
For $i = 1 To $iLen
If SubStr($sRequires,$i,1)=""
$asTemplate[$i-1]="?"
Else
$asTemplate[$i-1]= SubStr($sRequires,$i,1)
EndIf
Next
$Passgen=""
For $i = $iLen To 1 Step -1
$iRand=IIf($i=1,0,RND($i-1))
Select
Case $asTemplate[$iRand]=="A"
$s=$sAlphaUpper
Case $asTemplate[$iRand]=="a"
$s=$sAlphaLower
Case $asTemplate[$iRand]="X" or $asTemplate[$iRand]="x"
$s=$sAlphaLower+$sAlphaUpper
Case $asTemplate[$iRand]="9"
$s=$sNumeric
Case $asTemplate[$iRand]="#"
$s=$sSpecial
Case Default
$s=$sAlphaUpper+$sAlphaLower+$sNumeric+$sSpecial
EndSelect
$Passgen=$Passgen+SubStr($s,Rnd(Len($s)-1)+1,1)
; Discard used template character
$asTemplate[$iRand]=""
$asTemplate=Split(Join(Split(Trim(Join($asTemplate))," ")))
Next
EndFunction