====== Winst32 Preprocessor ======
In short, this preprocessor is run instead of the original opsi WINST action processor as main action processor command to //add// additional control and logging features. During its own run it will decide if WINST is allowed to run or not and therefor control the overall action processing.
At the moment it is capable of:
* Checking registry values before starting WINST as a action precondition
* Checking list of running processes before starting WINST as a action precondition
* Setting registry values before and/or after starting WINST
* Logging current product configuration of the client and the action request(s) being processed
**But beware:**
__**It is ABSOLUTELY NOT meant as a complete replacement for the allmighty winst32.exe that everybody knows or as a new installing mechanism!**__
__**THIS IS NOT FOR THE FAINT-HEARTED AND YOU SHOULD BE ABSOLUTELY SURE OF WHAT YOU ARE DOING! I WILL NOT GIVE ANY IN-DEPTH EXPLANATION FOR THE NEWBY USERS!**__
__**USE WITH CAUTION!USE WITH CAUTION!USE WITH CAUTION!NO RISK NO FUN!USE WITH CAUTION!USE WITH CAUTION!USE WITH CAUTION!**__
Links to the files:
* [[winst32_preproc.exe#winst32_preproc.au3|winst32_preproc.au3 - main program AutoIt source code]]
* [[winst32_preproc.exe#winst32_preproc.ini (example)|winst32_preproc.ini - example ini file]]
* [[winst32_preproc.exe#AssoArrays.au3|AssoArrays.au3 - (necessary for compilation)]]
* [[winst32_preproc.exe#BinaryCall.au3|BinaryCall.au3 - (necessary for compilation)]]
* [[winst32_preproc.exe#GetOpt.au3|GetOpt.au3 - (necessary for compilation)]]
* [[winst32_preproc.exe#Json.au3|Json.au3 - (necessary for compilation)]]
v1.0, Tested with Windows 10 x64 1809 Enterprise
--- //[[holger.pandel@googlemail.com|pandel]] 2019/10/25 13:52//
v1.1, Tested with Windows 10 x64 1809 Enterprise
--- //[[holger.pandel@googlemail.com|pandel]] 2019/10/28 15:00//
==== Motivation ====
Let's imagine the following situation:
We have the problem that our company uses two different software deployment systems and the only one that we can control ourselfs is opsi. So it is rather important to know if we can safely process our opsi tasks. Additionally, we have some clients which run more or less important scheduled tasks which should not be disturbed, so we would have to check for that, too.
All these checks can be done via Windows registry queries, but not via opsi client agent directly. So I had the idea to write this preprocessor...
==== How it works ====
The preprocssor is run instead of the original winst32.exe via opsiclientd and takes control over the execution of winst32.exe based on registry checks itself. It acts as a wrapper to winst32.exe.
Everything is controlled via a single configuration file.
You can create an example configuration file in the same directory by running winst32_preproc.exe without any command line parameter.
=== Where to install ===
That depends on your liking. You can put it into your standard opsi-client-agent installation folder, but then you have to take care of re-deployment after updating the client. This can be done by re-packaging the original opsi-client-agent-*.opsi with the included files, ie.
=== Modifications to opsiclientd.conf ===
In opsiclientd.conf you will find a configuration entry (or multiple ones if you configured your own/different events) looking like this:
[action_processor]
...
# Action processor command
command = "%action_processor.local_dir%\\%action_processor.filename%" /opsiservice "%service_url%" /clientid %global.host_id% /username %global.host_id% /password %global.opsi_host_key%
To get the preprocessor up and running, you have to replace the above mentioned command like so (notice the "-r" at the very end of the line!):
command = "%global.base_dir%\\winst32_preproc.exe" -f="%action_processor.local_dir%\\%action_processor.filename%" -s=%service_url% -c=%global.host_id% -u=%global.host_id% -p=%global.opsi_host_key% -l="%global.log_dir%\\winst32_preproc.log" -r
This example expects winst32_preproc.exe and its ini file in %global.base_dir% (see opsiclientd.conf). If you put it somewhere else, modify the line accordingly.
=== Command line parameters ===
The program contains a short help regarding the command line parameters. Simply issue "winst32_preproc.exe -h" to see
------------------------------------------------------------------------------------------------------------------
winst32_preproc (MIT licensed) v1.1.0.0 Command Line
Available command line options:
-f --acp-command Action processor filename, ie. winst32.exe
-s --service_url service URL
-c --clientid client id
-u --username service username
-p --password password
-d --debug Debug output
-r --run Production mode (REALLY activate the program!)
-l --log Different logfile name
-h --help Show this help
Default logfile: C:\Users\\AppData\Local\Temp\winst32_preproc\winst32_preproc.log
=== Standard mode = Test mode ===
For security reasons, the default mode of winst32_preproc ist test mode. That means, if you not explicitely specify production mode via command line, the program will only show you what would happen, but don't actually do anything. So, if you have configured the ini file according to your needs you can simple put both files in a directory on your test client and start the program from an administrator console to test it.
Let's assume the following (see opsiclientd.conf for your current values):
* your opsi host_id: testclient.opsinet.local
* your opsi_host_key: 5f5efffffa26fe90473a734f1da68fed
* opsi config service url: https://192.168.10.10:4447/rpc
winst32_preproc.exe -d -t -f="C:\Program Files (x86)\opsi.org\opsi-client-agent\\opsi-winst\\winst32.exe" -s=https://192.168.10.10:4447/rpc -c=testclient.opsinet.local -u=testclient.opsinet.local -p=5f5efffffa26fe90473a734f1da68fed
**NOTE: the path to winst32.exe must be the right one, otherwise he programm will not do anything.**
==== The configuration: winst32_preproc.ini ====
The structure of the configuration file is rather simple. It consists of five blocks:
* general - logging configuration and version information
* registry_check - registry value(s) that should be checked to decide if winst32.exe is being executed
* registry_pre - registry value(s) that should be set BEFORE winst32.exe is being executed
* registry_post - registry value(s) that should be set AFTER winst32.exe is being executed
* process_check - list of processes that should be checked to decide if winst32.exe is being executed
=== How the blocks work ===
== registry_check ==
The keys and values you specify here will be checked for their existance AND values. They a treated as ONE single result, that means, if you specify multiple values to check for and one (ore more) values cannot be read or found, this check is considered "failed" and winst32.exe execution will be prevented.
== process_check ==
The process names you specify here will be checked if they are running. They a treated as ONE single result, that means, if you specify multiple process names to check for and one (ore more) will found, this check is considered "failed" and winst32.exe execution will be prevented.
== registry_pre / registry_post ==
The registry_pre and registry_post block work the same. They simply set the values you specify IF (AND ONLY IF) the registry_check block was passed successfully.
== Configuration values ==
__Registry checks__
A configuration entry like
reg1=HKLM|64|SOFTWARE\RZ\FSV|FSVActive|0
means, that (on a 64 bit machine!) the preprocessor looks into
HKEY_LOCAL_MACHINE\SOFTWARE\RZ\FSV
for a value
FSVActive = 0
On a 64 bit machine, a line like
reg1=HKLM|32|SOFTWARE\RZ\FSV|FSVActive|0
would result in a actual registry key of
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\RZ\FSV
In general, a single line can be seen as:
reg=|||||
== Possible registry leaf values: ==
* HKLM (stands for: HKEY_LOCAL_MACHINE)
* HKU (stands for: HKEY_USERS)
* HKCR (stands for: HKEY_CLASSES_ROOT)
* HKCU (stands for: HKEY_CURRENT_USER)
* HKCC (stands for: HKEY_CURRENT_CONFIG)
== Possible bitnesses: ==
* 32
* 64
== Possible value types: ==
* REG_BINARY ("0x..." value notation)
* REG_SZ
* REG_EXPAND_SZ
* REG_QWORD ("0x..." value notation)
* REG_DWORD
* (REG_MULTI_SZ can be specified, but you are only able to read or set the first element, so it is not very useful here.)
__Process checks__
Process checks are much simpler:
A line like
proc1=winword.exe
will check, if winword.exe is found in the list of active processes.
=== Example ===
[general]
version=1.1.0.0
logInstalled=1
logActions=1
[registry_check]
count=1
reg1=HKLM|64|SOFTWARE\RZ\FSV|FSVActive|0
[registry_pre]
count=2
reg1=HKLM|64|SOFTWARE\RZ\FSV|FSVActive|1|REG_SZ
reg2=HKLM|64|SOFTWARE\opsi.org\Winst|Active|1|REG_SZ
[registry_post]
count=3
reg1=HKLM|64|SOFTWARE\RZ\FSV|FSVActive|0|REG_SZ
reg2=HKLM|64|SOFTWARE\opsi.org\Winst|Active|0|REG_SZ
reg3=HKLM|32|SOFTWARE\Somewhere\Else|SomeOtherValue|50|REG_DWORD
[process_check]
count=1
proc1=svchost.exe
The syntax should be obvious. "count" is simply the number of lines in the single block, every single entry starts with "reg" and a consecutive number.
To deactivate a certain block completely, simply set its "count" value to 0. The single "reg" line entries will then be ignored, you don't have to delete them.
//DON'T delete a block to disable it!//
What this example will do (in pseudo-lingo):
if ("FSVActive" under "HKEY_LOCAL_MACHINE\SOFTWARE\RZ\FSV" is "0") AND ("svchost.exe" is NOT in the list of active processes) then
log currently installed products on client
log current action requests
set "FSVActive" under "HKEY_LOCAL_MACHINE\SOFTWARE\RZ\FSV" to "1"
set "Active" under "HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\Winst" to "1"
execute winst32.exe (with its parameters)
set "FSVActive" under "HKEY_LOCAL_MACHINE\SOFTWARE\RZ\FSV" to "0"
set "Active" under "HKEY_LOCAL_MACHINE\SOFTWARE\opsi.org\Winst" to "0"
set "SomeOtherValue" under "HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Somewhere\Else" to "50"
else
exit and do nothing
If you don't want the preprocessor to log your installed products and/or action requests everytime it is started, simply set the configuration values to 0.
==== Files ====
* [[winst32_preproc.exe#winst32_preproc.au3|winst32_preproc.au3 - main program AutoIt source code]]
* [[winst32_preproc.exe#winst32_preproc.ini (example)|winst32_preproc.ini - example ini file]]
* [[winst32_preproc.exe#AssoArrays.au3|AssoArrays.au3 - (necessary for compilation)]]
* [[winst32_preproc.exe#BinaryCall.au3|BinaryCall.au3 - (necessary for compilation)]]
* [[winst32_preproc.exe#GetOpt.au3|GetOpt.au3 - (necessary for compilation)]]
* [[winst32_preproc.exe#Json.au3|Json.au3 - (necessary for compilation)]]
=== winst32_preproc.ini (example) ===
[general]
version=1.1.0.0
logInstalled=1
logActions=1
[registry_check]
count=1
reg1=HKLM|64|SOFTWARE\RZ\FSV|FSVActive|0
[registry_pre]
count=2
reg1=HKLM|64|SOFTWARE\RZ\FSV|FSVActive|1|REG_SZ
reg2=HKLM|64|SOFTWARE\opsi.org\Winst|Active|1|REG_SZ
[registry_post]
count=3
reg1=HKLM|64|SOFTWARE\RZ\FSV|FSVActive|0|REG_SZ
reg2=HKLM|64|SOFTWARE\opsi.org\Winst|Active|0|REG_SZ
reg3=HKLM|32|SOFTWARE\Somewhere\Else|SomeOtherValue|50|REG_DWORD
[process_check]
count=1
proc1=svchost.exe
=== winst32_preproc.au3 ===
;*****************************************
;winst32_preproc.au3 by Holger Pandel
;Erstellt mit ISN AutoIt Studio v. 1.09
;*****************************************
;OPSI standard call to winst32
;command = "%action_processor.local_dir%\\%action_processor.filename%" /opsiservice "%service_url%" /clientid %global.host_id% /username %global.host_id% /password %global.opsi_host_key%
; modified preprocessor command
;_getopts()
;command = "%global.base_dir%\\winst32_preproc.exe" -f="%action_processor.local_dir%\\%action_processor.filename%" -s=%service_url% -c=%global.host_id% -u=%global.host_id% -p=%global.opsi_host_key% -l="%global.log_dir%\\winst32_preproc.log" -r
; includes
#include
#include
#include
#include
#include "UDFs\AssoArrays.au3"
#include "UDFs\GetOpt.au3"
#include "UDFs\json.au3"
Global Const $HTTP_STATUS_OK = 200
;Opt('MustDeclareVars', 1)
; appplication title and version
Global $header = "winst32_preproc (MIT licensed)"
Global $version = "1.1.0.0"
Global $logdir = @TempDir & "\winst32_preproc"
Global $log_mode = True ; write log file = true
Global $log_file = $logdir & "\winst32_preproc.log" ; set default logfile name
Global $opsi_command = "C:\Program Files (x86)\opsi.org\opsi-client-agent\opsi-winst\winst32.exe"
Global $opsi_url = "https://server.id:4447/rpc"
Global $opsi_client = "localhost.localdom.net"
Global $opsi_user = "localhost.localdom.net"
Global $opsi_pass = "1234567890"
Global $Pid, $Handle, $ExitCode, $Cmd, $Cmdout
Global $iniName = "winst32_preproc.ini"
Global $isRegOk = False
; if true, it outputs messages on console, if false onbly to log file
Global $debug = False
; if true, do not actually run any command
Global $test = True
Local $msg = '------------------------------------------------------------------------------------------------------------------' & @CRLF ; start line
$msg &= $header & ' v' & $version & ' Command Line' & @CRLF & @CRLF ; Message.
; Load ini data
Global $iniName = "winst32_preproc"
_getIniValues($iniName)
; let's have a look at the CmdLine
If $CmdLine[0] = 0 Then
$msg &= "No arguments passed. See -h for help or use -d for a test run. Exiting." & @CRLF & @CRLF
ConsoleWrite($msg)
Exit 0
Else
_debug($msg)
EndIf
; get cmdline options
_getopts()
If not FileExists($opsi_command) Then
_debug("OPSI action processor not found. Exit.")
_exit(1)
EndIf
_debug("Running as user: " & @UserName)
_debug("Profile dir : " & @UserProfileDir)
_debug("Log file : " & $log_file)
; for debugging purpose
;If $test Then
; x_display()
;EndIf
; ---------------------------------------------------------------------------------------------------------------------
; ---- MAIN ---------
If x($iniName & ".registry_check.count") > 0 Then
Local $isRegOk = _runRegistryCheck()
If $isRegOk Then
_debug("All registry checks passed successfully.")
Else
_debug("One or more registry checks where unsuccsessful.")
_exit(0)
EndIf
EndIf
If x($iniName & ".process_check.count") > 0 Then
Local $isProcOk = _runProcessCheck()
If $isProcOk Then
_debug("All process checks passed successfully.")
Else
_debug("One or more process checks where unsuccsessful.")
_exit(0)
EndIf
EndIf
if $test Then
; test run
$Cmdout = '"' & $opsi_command & '" /opsiservice "' & $opsi_url & '" /clientid ' & $opsi_client & ' /username ' & $opsi_user & ' /password ***(confidential)***'
_debug("")
_debug("TESTMODE processing")
_debug("-------------------")
_debug("action processor: " & $opsi_command)
_debug("url: " & $opsi_url)
_debug("client: " & $opsi_client)
_debug("user: " & $opsi_user)
_debug("pass: (CONFIDENTIAL)")
_debug("")
If x($iniName & ".general.logInstalled") = 1 Then _opsi_showInstalledProducts($opsi_url, $opsi_client, $opsi_user, $opsi_pass)
If x($iniName & ".general.logActions") = 1 Then _opsi_showActionRequests($opsi_url, $opsi_client, $opsi_user, $opsi_pass)
_debug("")
_debug("I) Registry PRE-phase:")
_updateRegistry("pre")
_debug("")
_debug("II) Command to be launched: " & $Cmdout)
_debug("")
_debug("III) Registry POST-phase:")
_updateRegistry("post")
_debug("")
_debug("Testing only, no opsi processing for now.")
_debug("For production mode, use the -r switch (USE WITH CAUTION).")
_exit(0)
Else
; production run
If x($iniName & ".general.logInstalled") = 1 Then _opsi_showInstalledProducts($opsi_url, $opsi_client, $opsi_user, $opsi_pass)
If x($iniName & ".general.logActions") = 1 Then _opsi_showActionRequests($opsi_url, $opsi_client, $opsi_user, $opsi_pass)
_updateRegistry("pre")
$retval = _startActionProcessor($opsi_command, $opsi_url, $opsi_user, $opsi_client, $opsi_pass)
_updateRegistry("post")
_exit($retval)
EndIf
; ---------------------------------------------------------------------------------------------------------------------
; ---- SUPPORT FUNCTIONS ---------
; check if registry values are as necessary
Func _runRegistryCheck()
Local $rc = False
_debug("Running registry checkss...")
If x($iniName & ".registry_check.count") = 0 Then
_debug("--> nothing to check")
return True
EndIf
; Example entry: reg1=HKLM|64|SOFTWARE\FIDUCIA\Bitlocker|FSVActive|0
For $i = 1 To x($iniName & ".registry_check.count")
Local $a = x($iniName & ".registry_check.reg" & $i)
_debug("Test " & $i & ": " & $a[0] & "\" & $a[2] & "(" & $a[1] & "bit):" & $a[3] & "=" & $a[4])
If $a[2] = "32" Then
If RegRead($a[0] & "\" & $a[2], $a[3]) = $a[4] then
$rc = True
_debug("--> rc=" & $rc)
Else
$rc = False
_debug("--> rc=" & $rc)
return $rc
EndIf
Else
If RegRead($a[0] & $a[1] & "\" & $a[2], $a[3]) = $a[4] then
$rc = True
_debug("--> rc=" & $rc)
Else
$rc = False
_debug("--> rc=" & $rc)
return $rc
EndIf
EndIf
Next
return $rc
EndFunc
; check if specified process exist
Func _runProcessCheck()
Local $rc = False
_debug("Running process checks...")
If x($iniName & ".process_check.count") = 0 Then
_debug("--> nothing to check")
return True
EndIf
; Example entry: proc1=winword.exe
For $i = 1 To x($iniName & ".process_check.count")
Local $a = x($iniName & ".process_check.proc" & $i)
_debug("Test if not running " & $i & ": " & $a)
Local $pid = ProcessExists($a)
If $pid > 0 Then
$rc = False
_debug("--> rc=" & $rc)
_debug("--> PID=" & $pid)
return $rc
Else
$rc = True
_debug("--> rc=" & $rc)
return $rc
EndIf
Next
EndFunc
; set registry entries
; $phase can be "pre" or "post"
; RegWrite ( "keyname" [, "valuename", "type", value] )
Func _updateRegistry($phase)
Local $rc = False
_debug("Running registry phase: " & $phase)
; Example entry: reg1=HKLM|32|SOFTWARE\FIDUCIA\Bitlocker|FSVActive|0|REG_SZ
If x($iniName & ".registry_" & $phase & ".count") = 0 Then
_debug("--> nothing to do in this phase")
return
EndIf
For $i = 1 To x($iniName & ".registry_" & $phase & ".count")
Local $a = x($iniName & ".registry_" & $phase & ".reg" & $i)
If not $test Then
_debug("Setting " & $i & ": " & $a[0] & "\" & $a[2] & "(" & $a[1] & "bit):" & $a[3] & "=" & $a[4])
If $a[2] = "32" Then
If RegWrite($a[0] & "\" & $a[2], $a[3], $a[5], $a[4]) then
$rc = True
_debug("--> rc=" & $rc)
EndIf
Else
If RegWrite($a[0] & $a[1] & "\" & $a[2], $a[3], $a[5], $a[4]) then
$rc = True
_debug("--> rc=" & $rc)
EndIf
EndIf
Else
_debug("(TESTMODE) Setting " & $i & ": " & $a[0] & "\" & $a[2] & "(" & $a[1] & "bit):" & $a[3] & " = " & $a[5] & ":" & $a[4])
EndIf
Next
EndFunc
; run action processor command
Func _startActionProcessor($command, $URL, $clientid, $user, $pass)
_debug("Starting action...")
$Cmd = '"' & $command & '" /opsiservice "' & $URL & '" /clientid ' & $clientid & ' /username ' & $user & ' /password ' & $pass
$Cmdout = '"' & $command & '" /opsiservice "' & $URL & '" /clientid ' & $clientid & ' /username ' & $user & ' /password ***(confidential)***'
_debug("action processor: " & $command)
_debug("url: " & $URL)
_debug("client: " & $clientid)
_debug("user: " & $user)
_debug("pass: (CONFIDENTIAL)")
_debug("cmd: " & $Cmdout)
$Pid = Run($Cmd, '', @SW_SHOW, $STDOUT_CHILD + $STDERR_CHILD)
$Handle = _ProcessExitCode($Pid)
ProcessWaitClose($pid)
$ExitCode = _ProcessExitCode($Pid, $Handle)
_ProcessCloseHandle($Handle)
return $ExitCode
EndFunc
; handle command line options
Func _getopts()
Local $sMsg = '------------------------------------------------------------------------------------------------------------------' & @CRLF ; start line
$sMsg &= $header & ' v' & $version & ' Command Line' & @CRLF & @CRLF ; Message.
Local $sOpt, $sSubOpt, $sOper
Local $h_specified = False
Local $failure = False
; Options array, entries have the format [short, long, default value]
Local $aOpts[9][3] = [ _
['-f', '--acp_command', $GETOPT_REQUIRED_ARGUMENT], _
['-s', '--service_url', $GETOPT_REQUIRED_ARGUMENT], _
['-c', '--clientid', $GETOPT_REQUIRED_ARGUMENT], _
['-u', '--username', $GETOPT_REQUIRED_ARGUMENT], _
['-p', '--password', $GETOPT_REQUIRED_ARGUMENT], _
['-d', '--debug', True], _
['-r', '--r', True], _
['-l', '--log', $log_file], _
['-h', '--help', True]]
_GetOpt_Set($aOpts) ; Set options.
If 0 < $GetOpt_Opts[0] Then ; If there are any options...
; first loop: analyse parameters and create message texts, exit program if needed
While 1 ; ...loop through them one by one.
; Get the next option passing a string with valid options.
$sOpt = _GetOpt('f:s:c:u:p:rdtlh') ; p: means -p option requires an argument.
If Not $sOpt Then ExitLoop ; No options or end of loop.
; Check @extended above if you want better error handling.
; The current option is stored in $GetOpt_Opt, it's index (in $GetOpt_Opts)
; in $GetOpt_Ind and it's value in $GetOpt_Arg.
Switch $sOpt ; What is the current option?
Case '?' ; Unknown options come here. @extended is set to $E_GETOPT_UNKNOWN_OPTION
$sMsg &= 'Unknown option: ' & $GetOpt_Ind & ': ' & $GetOpt_Opt
$sMsg &= ' with value "' & $GetOpt_Arg & '" (' & VarGetType($GetOpt_Arg) & ').' & @CRLF
$sMsg &= 'UNKNOWN OPTION passed.' & @CRLF
$failure = True
Case ':' ; Options with missing required arguments come here. @extended is set to $E_GETOPT_MISSING_ARGUMENT
$sMsg &= 'MISSING REQUIRED ARGUMENT for option: ' & $GetOpt_Ind & ': ' & $GetOpt_Opt & @CRLF
$failure = True
Case 'l'
$sMsg &= 'Option ' & $GetOpt_Ind & ': ' & $GetOpt_Opt
$sMsg &= ' with value "' & $GetOpt_Arg & '" (' & VarGetType($GetOpt_Arg) & ')'
$sMsg &= '.' & @CRLF
$log_file = $GetOpt_Arg
Case 'd'
$sMsg &= 'Option ' & $GetOpt_Ind & ': ' & $GetOpt_Opt
$sMsg &= ' with value "' & $GetOpt_Arg & '" (' & VarGetType($GetOpt_Arg) & ')'
$sMsg &= '.' & @CRLF
$debug = True
Case 'r'
$sMsg &= 'Option ' & $GetOpt_Ind & ': ' & $GetOpt_Opt
$sMsg &= ' with value "' & $GetOpt_Arg & '" (' & VarGetType($GetOpt_Arg) & ')'
$sMsg &= '.' & @CRLF
$test = False
Case 'f'
$sMsg &= 'Option ' & $GetOpt_Ind & ': ' & $GetOpt_Opt
$sMsg &= ' with required value "' & $GetOpt_Arg & '" (' & VarGetType($GetOpt_Arg) & ')'
$sMsg &= '.' & @CRLF
$opsi_command = $GetOpt_Arg
Case 's'
$sMsg &= 'Option ' & $GetOpt_Ind & ': ' & $GetOpt_Opt
$sMsg &= ' with required value "' & $GetOpt_Arg & '" (' & VarGetType($GetOpt_Arg) & ')'
$sMsg &= '.' & @CRLF
$opsi_url = $GetOpt_Arg
Case 'c'
$sMsg &= 'Option ' & $GetOpt_Ind & ': ' & $GetOpt_Opt
$sMsg &= ' with required value "' & $GetOpt_Arg & '" (' & VarGetType($GetOpt_Arg) & ')'
$sMsg &= '.' & @CRLF
$opsi_client = $GetOpt_Arg
Case 'u'
$sMsg &= 'Option ' & $GetOpt_Ind & ': ' & $GetOpt_Opt
$sMsg &= ' with required value "' & $GetOpt_Arg & '" (' & VarGetType($GetOpt_Arg) & ')'
$sMsg &= '.' & @CRLF
$opsi_user = $GetOpt_Arg
Case 'p'
$sMsg &= 'Option ' & $GetOpt_Ind & ': ' & $GetOpt_Opt
$sMsg &= ' with ***(confidential)*** value supplied. '
$sMsg &= '.' & @CRLF
$opsi_pass = $GetOpt_Arg
Case 'h'
$sMsg &= 'Available command line options:' & @CRLF & @CRLF & _
'-f' & @TAB & '--acp-command ' & @TAB & 'Action processor filename, ie. winst32.exe' & @CRLF & _
'-s' & @TAB & '--service_url ' & @TAB & 'service URL' & @CRLF & _
'-c' & @TAB & '--clientid ' & @TAB & 'client id' & @CRLF & _
'-u' & @TAB & '--username ' & @TAB & 'service username' & @CRLF & _
'-p' & @TAB & '--password ' & @TAB & 'password' & @CRLF & _
'-d' & @TAB & '--debug ' & @TAB & 'Debug output' & @CRLF & _
'-r' & @TAB & '--run ' & @TAB & 'Production mode (REALLY activate the program!)' & @CRLF & _
'-l' & @TAB & '--log ' & @TAB & 'Different logfile name' & @CRLF & _
'-h' & @TAB & '--help ' & @TAB & 'Show this help' & @CRLF & @CRLF & _
'Default logfile: ' & $log_file & @CRLF & @CRLF
$h_specified = True
EndSwitch
Wend
If 0 < $GetOpt_Opers[0] Then ; If there are any operands...
$sMsg &= 'INVALID OPERANDS PASSED. This is not allowed. Check for missing ''='' in --path or --log option!' & @CRLF
While 1 ; ...loop through them one by one.
$sOper = _GetOpt_Oper() ; Get the next operand.
If Not $sOper Then ExitLoop ; no operands or end of loop.
; Check @extended above if you want better error handling.
$sMsg &= 'Operand ' & $GetOpt_OperInd & ': ' & $sOper & @CRLF
WEnd
$failure = True
EndIf
If $failure Then $sMsg &= @CRLF & 'Please check the command line parameters!' & @CRLF
If $h_specified Or $failure Then ; show help screen or wrong options ?
ConsoleWrite(@crlf & $sMsg)
If $failure Then _exit(1)
_exit(0)
EndIf
EndIf
; write header to log
_writeLog(_formatIOText($sMsg))
EndFunc
; part of _getIniValues
Func _getLeaf($leaf, $tab)
Local $str
If not IsObj($leaf) Then Return
$colKeys = $leaf.Keys
For $strKey in $colKeys
$str = ""
If IsArray($leaf.Item($strKey)) Then
$str = $leaf.Item($strKey)[0]
For $i = 1 to Ubound($leaf.Item($strKey)) - 1
$str &= "|" & $leaf.Item($strKey)[$i]
Next
_debug($tab & $strKey & ' -> ' & $str)
Else
_debug($tab & $strKey & ' -> ' & $leaf.Item($strKey))
EndIf
_getLeaf($leaf.Item($strKey), $tab & " ")
Next
EndFunc
; read ini values
Func _getIniValues($iniName)
Dim $szDrive, $szDir, $szFName, $szExt, $pathTemp, $kdSel, $op
$pathTemp = _PathSplit(@ScriptFullPath, $szDrive, $szDir, $szFName, $szExt)
Dim $appPath = $szDrive & $szDir
Dim $iniFile = $appPath & $iniName & ".ini"
Dim $rc, $cpm[3], $msg, $str, $colKeys
_debug("Ini file : " & $iniFile)
If FileExists($iniFile) Then ;--- global INI file found
$rc = _ReadAssocFromIni2($iniFile)
If @error Then
_debug("Error while reading ini file. Errno: " & @error)
Else
_debug("Entries read: " & $rc)
_debug("Logging configuration:")
_debug("--------------- snip ------------------")
_getLeaf($_xHashCollection, " ")
_debug("--------------- snip -----------------")
_debug("INI reading complete.")
EndIf
Else ;--- INI not existing, creating new one in script directory
$msg = "INI file not found: " & $iniFile & @CRLF & _
"A new INI file with example values will be created in the script directory." & @CRLF & _
"Please customize the INI file before using it." & @CRLF & @CRLF
ConsoleWrite($msg)
_createIni($appPath & $iniName)
EndIf
EndFunc ;==>_getIniValues
; get current product status
Func _REST_request($req, $clientid, $user, $pass)
Local $REST = ObjCreate("WinHttp.WinHttpRequest.5.1")
Local $agent ='Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.112 Safari/537.36'
; https://$serverid:$serverport/rpc?{ "id": 1, "method": "getProductInstallationStatus_listOfHashes", "params": ["$clientid"] }
;ConsoleWrite(@CRLF & "Request: " & $req)
$REST.Open("GET", $req, False)
If (@error) Then Return SetError(1, 0, "Error on open")
$REST.SetRequestHeader('Authorization','Basic ' & base64($user & ":" & $pass, True, True))
$REST.setRequestHeader ("User-Agent", $agent)
$REST.Option(4) = 13056
$REST.Send()
If (@error) Then Return SetError(2, 0, "Error on send")
If ($REST.Status <> $HTTP_STATUS_OK) Then Return SetError(3, 0, "Error on request - HTTP status " & $REST.Status)
return $REST.ResponseText
EndFunc
; convert lastStateChange into more readable format
Func _opsiDate($raw)
Local $year = StringMid($raw,1, 4)
Local $mon = StringMid($raw,5, 2)
Local $day = StringMid($raw,7, 2)
Local $hour = StringMid($raw,9, 2)
Local $min = StringMid($raw,11, 2)
return $day & "." & $mon & "." & $year & " " & $hour & ":" & $min
EndFunc
; request all installed products on client
Func _opsi_showInstalledProducts($URL, $clientid, $user, $pass)
Local $_getProductInstallationStatus_listOfHashes = $URL & '?{ "id": 1, "method": "getProductInstallationStatus_listOfHashes", "params": ["' & $clientid & '"] }'
Local $retval = _REST_request($_getProductInstallationStatus_listOfHashes, $clientid, $user, $pass)
If (@error) Then
_debug("Error on REST request: " & $retval)
return
EndIf
Local $data = json_decode($retVal)
;json_dump($retval)
_debug("Currently installed:")
Local $i = 0
While 1
$product_id = json_get($data, '.result[' & $i & '].productId')
$installationStatus = json_get($data, '.result[' & $i & '].installationStatus')
$installed = json_get($data, '.result[' & $i & '].lastStateChange')
If @error Then ExitLoop
If $installationStatus = "installed" Then
_debug("--> " & $product_id & " (lastStateChange: " & _opsiDate($installed) & ")")
EndIf
$i += 1
WEnd
EndFunc
; request current action requests for client
Func _opsi_showActionRequests($URL, $clientid, $user, $pass)
Local $_getProductActionRequests_listOfHashes = $URL & '?{ "id": 1, "method": "getProductActionRequests_listOfHashes", "params": ["' & $clientid & '"] }'
Local $retval = _REST_request($_getProductActionRequests_listOfHashes, $clientid, $user, $pass)
If (@error) Then
_debug("Error on REST request: " & $retval)
return
EndIf
Local $data = json_decode($retVal)
;json_dump($retval)
_debug("Current action requests:")
Local $i = 0
While 1
$product_id = json_get($data, '.result[' & $i & '].productId')
$actionRequest = json_get($data, '.result[' & $i & '].actionRequest')
If @error Then ExitLoop
If $actionRequest <> "none" Then
_debug("--> " & $product_id & ": " & $actionRequest)
EndIf
$i += 1
WEnd
EndFunc
; common exit
Func _exit($rc)
_debug("")
_debug("winst32_preproc exiting.")
_debug("------------------------------------------------------------------------------------------------------------------")
Exit $rc
EndFunc
; create default example ini file
Func _createIni($ini)
x($ini & ".general.version", $version)
x($ini & ".general.logInstalled", 1)
x($ini & ".general.logActions", 1)
x($ini & ".registry_check.count", 1)
Local $a = ["HKLM", "64", "SOFTWARE\RZ\FSV", "FSVActive", "0"]
x($ini & ".registry_check.reg1", $a)
x($ini & ".registry_pre.count", 2)
Local $a = ["HKLM", "64", "SOFTWARE\RZ\FSV", "FSVActive", "1", "REG_SZ"]
x($ini & ".registry_pre.reg1", $a)
Local $a = ["HKLM", "64", "SOFTWARE\opsi.org\Winst", "Active", "1", "REG_SZ"]
x($ini & ".registry_pre.reg2", $a)
x($ini & ".registry_post.count", 3)
Local $a = ["HKLM", "64", "SOFTWARE\RZ\FSV", "FSVActive", "0", "REG_SZ"]
x($ini & ".registry_post.reg1", $a)
Local $a = ["HKLM", "64", "SOFTWARE\opsi.org\Winst", "Active", "0", "REG_SZ"]
x($ini & ".registry_post.reg2", $a)
Local $a = ["HKLM", "32", "SOFTWARE\Somewhere\Else|SomeOtherValue", "50", "REG_DWORD"]
x($ini & ".registry_post.reg3", $a)
x($ini & ".process_check.count", 1)
Local $a = ["svchost.exe"]
x($ini & ".process_check.proc1", $a)
_WriteAssocToIni($ini)
EndFunc
; ---------------------------------------------------------------------------------------------------------------------
; ---- TOOLS ---------
; output debug messages to console
Func _debug($dbg, $line = @ScriptLineNumber)
Local $time = "[" & @MDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & "] ! DEBUG"
If $debug Then
if $line = -1 then
ConsoleWrite(@CRLF & $time & ": " & $dbg)
Else
ConsoleWrite(@CRLF & $time & " (" & $line & "): " & $dbg)
Endif
EndIf
_writeLog(_formatIOText($dbg))
EndFunc ;==>_debug
; format message text line for console and log
; if $mark is "?????", then special question format is used
Func _formatIOText($text, $mark = "")
Local $time = "[" & @MDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & "] "
If $mark = "" Then
$text = $time & StringReplace($text, @CRLF, @CRLF & $time)
ElseIf $mark = "?????" Then
$text = $time & $text & ": "
Else
$text = $time & "! " & $mark & ": " & StringReplace($text, @CRLF, @CRLF & $time & "! " & $mark & ": ")
EndIf
Return $text
EndFunc ;==>_formatIOText
; log messages to disc
Func _writeLog($msg, $nocrlf = False)
; write lines to logfile, even if --quiet is specified
If $log_mode Then
Local $file = FileOpen($log_file, 1 + 8) ; create dir and open/create file
If $nocrlf Then
FileWrite($file, $msg)
Else
FileWrite($file, @CRLF & $msg)
EndIf
FileFlush($file)
FileClose($file)
EndIf
EndFunc ;==>_writeLog
;===============================================================================
;
; Function Name: _ProcessExitCode()
; Description: Returns a handle/exitcode from use of Run().
; Parameter(s): $i_Pid - ProcessID returned from a Run() execution
; $h_Process - Process handle
; Requirement(s): None
; Return Value(s): On Success - Returns Process handle while Run() is executing
; (use above directly after Run() line with only PID parameter)
; - Returns Process Exitcode when Process does not exist
; (use above with PID and Process Handle parameter returned from first UDF call)
; On Failure - 0
; Author(s): MHz (Thanks to DaveF for posting these DllCalls in Support Forum)
;
;===============================================================================
;
Func _ProcessExitCode($i_Pid, $h_Process = 0)
; 0 = Return Process Handle of PID else use Handle to Return Exitcode of a PID
Local $v_Placeholder
If Not IsArray($h_Process) Then
; Return the process handle of a PID
$h_Process = DllCall('kernel32.dll', 'ptr', 'OpenProcess', 'int', 0x400, 'int', 0, 'int', $i_Pid)
If Not @error Then Return $h_Process
Else
; Return Process Exitcode of PID
$h_Process = DllCall('kernel32.dll', 'ptr', 'GetExitCodeProcess', 'ptr', $h_Process[0], 'int*', $v_Placeholder)
If Not @error Then Return $h_Process[2]
EndIf
Return 0
EndFunc ;==>_ProcessExitCode
; close handle to attached process
Func _ProcessCloseHandle($h_Process)
; Close the process handle of a PID
DllCall('kernel32.dll', 'ptr', 'CloseHandle', 'ptr', $h_Process)
If Not @error Then Return 1
Return 0
EndFunc ;==>_ProcessCloseHandle
; Get STDOUT and ERROUT from commandline tool
Func ShowStdOutErr($l_Handle, $ShowConsole = 1, $Replace = "", $ReplaceWith = "")
Local $Line = "x", $Line2 = "x", $tot_out, $err1 = 0, $err2 = 0, $cnt1 = 0, $cnt2 = 0
Do
Sleep(10)
$Line = StdoutRead($l_Handle)
$err1 = @error
If $Replace <> "" Then $Line = StringReplace($Line, $Replace, $ReplaceWith)
$tot_out &= $Line
If $ShowConsole Then
ConsoleWrite($Line)
EndIf
$Line2 = StderrRead($l_Handle)
$err2 = @error
If $Replace <> "" Then $Line2 = StringReplace($Line2, $Replace, $ReplaceWith)
$tot_out &= $Line2
If $ShowConsole Then
ConsoleWrite($Line2)
EndIf
; end the loop also when AutoIt3 has ended but a sub process was shelled with Run() that is still active
; only do this every 50 cycles to avoid cpu hunger
If $cnt1 = 50 Then
$cnt1 = 0
; loop another 50 times just to ensure the buffers emptied.
If Not ProcessExists($l_Handle) Then
If $cnt2 > 2 Then ExitLoop
$cnt2 += 1
EndIf
EndIf
$cnt1 += 1
Until ($err1 And $err2)
Return $tot_out
EndFunc ;==>ShowStdOutErr
; Author: MilesAhead
; http://www.autoitscript.com/forum/topic/110768-itaskbarlist3/page__view__findpost__p__910631
; read AssocArray from IniFile Section
; returns number of items read - sets @error on failure
; modified (original see AssoArray.au3): Holger Pandel, 2015: accept full path name of ini
Func _ReadAssocFromIni2($myIni = 'config.ini', $mySection = '', $sSep = "|")
Local $szDrive, $szDir, $szFName, $szExt, $pathTemp
$pathTemp = _PathSplit(@ScriptFullPath, $szDrive, $szDir, $szFName, $szExt)
$sIni = $szFName
If $mySection == '' Then
$aSection = IniReadSectionNames ($myIni); All sections
If @error Then
_debug("Error while reading section names from: " & $myIni)
Return SetError(@error, 0, 0)
EndIf
Else
Dim $aSection[2] = [1,$mySection]; specific Section
EndIf
For $i = 1 To UBound($aSection)-1
Local $sectionArray = IniReadSection($myIni, $aSection[$i])
If @error Then
_debug("Error while reading section: " & $aSection[$i])
Return SetError(1, 0, 0)
EndIf
For $x = 1 To $sectionArray[0][0]
If StringInStr($sectionArray[$x][1], $sSep) then
$posS = _MakePosArray($sectionArray[$x][1], $sSep)
Else
$posS = $sectionArray[$x][1]
EndIf
x($sIni&"."&$aSection[$i]&"."&$sectionArray[$x][0], $posS)
Next
next
Return $sectionArray[0][0]
EndFunc ;==>_ReadAssocFromIni
;==============================================================================================================================
; Function: base64($vCode [, $bEncode = True [, $bUrl = False]])
;
; Description: Decode or Encode $vData using Microsoft.XMLDOM to Base64Binary or Base64Url.
; IMPORTANT! Encoded base64url is without @LF after 72 lines. Some websites may require this.
;
; Parameter(s): $vData - string or integer | Data to encode or decode.
; $bEncode - boolean | True - encode, False - decode.
; $bUrl - boolean | True - output is will decoded or encoded using base64url shema.
;
; Return Value(s): On Success - Returns output data
; On Failure - Returns 1 - Failed to create object.
;
; Author (s): (Ghads on Wordpress.com), Ascer
;===============================================================================================================================
Func base64($vCode, $bEncode = True, $bUrl = False)
Local $oDM = ObjCreate("Microsoft.XMLDOM")
If Not IsObj($oDM) Then Return SetError(1, 0, 1)
Local $oEL = $oDM.createElement("Tmp")
$oEL.DataType = "bin.base64"
If $bEncode then
$oEL.NodeTypedValue = Binary($vCode)
If Not $bUrl Then Return $oEL.Text
Return StringReplace(StringReplace(StringReplace($oEL.Text, "+", "-"),"/", "_"), @LF, "")
Else
If $bUrl Then $vCode = StringReplace(StringReplace($vCode, "-", "+"), "_", "/")
$oEL.Text = $vCode
Return $oEL.NodeTypedValue
EndIf
EndFunc ;==>base64
=== AssoArrays.au3 ===
#include-once
#include
; #INDEX# =======================================================================================================================
; Title .........: xHashCollection
; AutoIt Version : 3.3.4.0
; Language ......: English
; Description ...: Create and use Multidimentional Associative arrays
; Author ........: OHB
; ===============================================================================================================================
;~ $tt = TimerInit()
Global $_xHashCollection = ObjCreate( "Scripting.Dictionary" ), $_xHashCache
;~ ConsoleWrite("Asso Array Load up time: "&Round(TimerDiff($tt) ) & @CRLF)
; #FUNCTION# ====================================================================================================================
; Name...........: x
; Description ...: Gets or sets a value in an Associative Array
; Syntax.........: SET: x( $sKey , $vValue )
; GET: x( $key )
; Parameters ....: $sKey - the key to set or get. Examples:
; x( 'foo' ) gets value of foo
; x( 'foo.bar' ) gets value of bar which is a key of foo
; $bar = "baz"
; x( 'foo.$bar' ) gets value of baz which is a key of foo (variables are expanded)
; Return values .: Success - When setting, return the value set. When getting, returns the requested value.
; Failure - Returns a 0
; Author ........: OHB
; ===============================================================================================================================
Func x( $sKey = '' , $vValue = '' )
$func = "get"
If @NumParams <> 1 Then $func = "set"
If $sKey == '' Then
If $func == "get" Then
Return $_xHashCollection
Else
$_xHashCollection.removeAll
Return ''
EndIf
EndIf
$parts = StringSplit( $sKey , "." )
$last_key = $parts[$parts[0]]
$cur = $_xHashCollection
For $x = 1 To $parts[0] - 1
If Not $cur.exists( $parts[$x] ) Then
If $func == "get" Then Return
$cur.add( $parts[$x] , ObjCreate( "Scripting.Dictionary" ) )
EndIf
$cur = $cur.item( $parts[$x] )
Next
If IsPtr( $vValue ) Then $vValue = String( $vValue )
If $func == "get" Then
If Not $cur.exists( $last_key ) Then Return
$item = $cur.item( $last_key )
Return $item
ElseIf Not $cur.exists( $last_key ) Then
$cur.add( $last_key , $vValue )
Else
$cur.item( $last_key ) = $vValue
EndIf
Return $vValue
EndFunc
; #FUNCTION# ====================================================================================================================
; Name...........: x_del
; Description ...: Removes a key from an Associative Array
; Syntax.........: x_del( $sKey )
; Parameters ....: $sKey - the key to remove.
; Return values .: Success - True
; Failure - False
; Author ........: OHB
; ===============================================================================================================================
Func x_del( $sKey )
If $sKey == '' Then Return x( '' , '' )
$parts = StringSplit( $sKey , "." )
$cur = $_xHashCollection
For $x = 1 To $parts[0] - 1
If Not $cur.exists( $parts[$x] ) Then Return False
$cur = $cur.item( $parts[$x] )
Next
$cur.remove( $parts[$parts[0]] )
Return True
EndFunc
; #FUNCTION# ====================================================================================================================
; Name...........: x_display
; Description ...: Displays the contents of an Associative Array
; Syntax.........: x_display( $sKey )
; Parameters ....: $sKey - the key to display. Examples:
; x_display() displays everything
; x_display( 'foo' ) displays the contents of foo
; Author ........: OHB
; ===============================================================================================================================
Func x_display( $key = '' )
$text = $key
If $key <> '' Then $text &= " "
$text &= StringTrimRight( _x_display( x( $key ) , '' ) , 2 )
ConsoleWrite($text & @LF)
$wHnd = GUICreate( "Array " & $key , 700 , 500 )
GUISetState( @SW_SHOW , $wHnd )
$block = GUICtrlCreateEdit( $text , 5 , 5 , 690 , 490 )
GUICtrlSetFont( $block , 10 , 400 , -1 , 'Courier' )
While 1
If GUIGetMsg() == -3 Then ExitLoop
WEnd
GUISetState( @SW_HIDE , $wHnd )
GUIDelete( $wHnd )
EndFunc
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: _x_display
; Description ...: Itterates through an array and builds output for x_display
; Author ........: OHB
; ===============================================================================================================================
Func _x_display( $item , $tab )
If IsObj( $item ) Then
$text = 'Array (' & @CRLF
$itemAdded = False
For $i In $item
$text &= $tab & " [" & $i & "] => " & _x_display( $item.item($i) , $tab & " " )
$itemAdded = True
Next
If Not $itemAdded Then $text &= @CRLF
$text &= $tab & ')'
ElseIf IsArray( $item ) Then
$text = "Array"
$totalItems = 1
$dimensions = UBound( $item , 0 )
For $dimension = 1 To $dimensions
$size = UBound( $item , $dimension )
$totalItems *= $size
$text &= "[" & $size & "]"
Next
$text &= " (" & @CRLF
For $itemID = 0 To $totalItems - 1
$idName = ''
$idNum = $itemID
For $dimension = 1 To $dimensions - 1
$mul = ( $totalItems / UBound( $item , $dimension ) )
$a = Floor( $idNum / $mul )
$idName &= '[' & $a & ']'
$idNum -= ( $a * $mul )
Next
$idName &= '[' & $idNum & ']'
$text &= $tab & " " & $idName & " => " & _x_display( Execute( "$item" & $idName ) , $tab & " " )
Next
$text &= $tab & ")"
Else
$text = $item
EndIf
$text &= @CRLF
Return $text
EndFunc
; Name...........: x_count
; Description ...: Returns a count of items
; Syntax.........: x_count( $sKey )
; Parameters ....: $sKey - the key
; Return values .: Success: count of items of a provided key
; x_count() returns count os keys on first level
; Failure: 0, set error to:
; -1 = the key is not an object, but an item with a value
; -2 = the key does not exist
; Author ........: shEiD (original "x" UDF by: OHB)
Func x_count($sKey = '')
If $sKey == '' Then Return $_xHashCollection.Count
Local $cur = $_xHashCollection
Local $parts = StringSplit($sKey, ".")
For $x = 1 To $parts[0]
If Not $cur.exists($parts[$x]) Then Return SetError(-2, 0, 0)
$cur = $cur.item($parts[$x])
Next
If Not IsObj($cur) Then Return SetError(-1, 0, 0)
Return $cur.Count
EndFunc ;==>x_count
; Author: MilesAhead
; http://www.autoitscript.com/forum/topic/110768-itaskbarlist3/page__view__findpost__p__910631
;write AssocArray to IniFile Section
;returns 1 on success - sets @error on failure
Func _WriteAssocToIni($myIni = 'config', $mySection = '', $bEraseAll = false, $sSep = "|")
$myIni = $myIni&".ini"
If $bEraseAll then
$temp = FileOpen($myIni, 2)
FileClose($temp)
EndIf
Local $sIni = StringLeft($myIni,StringInStr($myIni,".")-1)
If Not $_xHashCollection.Exists($sIni) Then Return SetError(1, 0, 0)
If $mySection == '' Then
$aSection = $_xHashCollection($sIni).Keys(); All sections
Else
Dim $aSection[1] = [$mySection]; specific Section
EndIf
Local $retVal = 0
For $i = 0 To UBound($aSection)-1
$cur = x($sIni&"."&$aSection[$i])
$retVal = 0
If $cur.Count() < 1 Then
Return SetError(1, 0, 0)
EndIf
Local $iArray[$cur.Count()][2]
Local $aArray = $cur.Keys()
For $x = 0 To UBound($aArray) - 1
$iArray[$x][0] = $aArray[$x]
$value = x($sIni&"."&$aSection[$i]&"."&$aArray[$x])
If IsArray($value) then
$iArray[$x][1] = _MakePosString($value, $sSep)
Else
$iArray[$x][1] = $value
EndIf
Next
$retVal = IniWriteSection($myIni, $aSection[$i], $iArray, 0)
next
Return SetError(@error, 0, $retVal)
EndFunc ;==>_WriteAssocToIni
;read AssocArray from IniFile Section
;returns number of items read - sets @error on failure
Func _ReadAssocFromIni($myIni = 'config', $mySection = '', $sSep = "|")
$myIni = $myIni&".ini"
Local $sIni = StringLeft($myIni,StringInStr($myIni,".")-1)
If $mySection == '' Then
$aSection = IniReadSectionNames ($myIni); All sections
If @error Then Return SetError(@error, 0, 0)
Else
Dim $aSection[2] = [1,$mySection]; specific Section
EndIf
For $i = 1 To UBound($aSection)-1
Local $sectionArray = IniReadSection($myIni, $aSection[$i])
If @error Then Return SetError(1, 0, 0)
For $x = 1 To $sectionArray[0][0]
If StringInStr($sectionArray[$x][1], $sSep) then
$posS = _MakePosArray($sectionArray[$x][1], $sSep)
Else
$posS = $sectionArray[$x][1]
EndIf
x($sIni&"."&$aSection[$i]&"."&$sectionArray[$x][0], $posS)
Next
next
Return $sectionArray[0][0]
EndFunc ;==>_ReadAssocFromIni
;makes a Position string using '#' number separator
Func _MakePosString($posArray, $sSep = "|")
Local $str = ""
For $x = 0 To UBound($posArray) - 2
$str &= String($posArray[$x]) & $sSep
Next
$str &= String($posArray[UBound($posArray) - 1])
Return $str
EndFunc ;==>_MakePosString
;makes a Position array from a Position string
Func _MakePosArray($posString, $sSep = "|")
Return StringSplit($posString, $sSep, 2)
EndFunc ;==>_MakePosArray
=== GetOpt.au3 ===
; #INDEX# ======================================================================
; Title .........: GetOpt.au3
; Version ......: 1.3
; Language ......: English
; Author(s) .....: dany
; Link ..........: http://www.autoitscript.com/forum/topic/143167-getoptau3-udf-to-parse-the-command-line/
; Description ...: AutoIt3 port of getopt(). Parse a command line c-style like
; using _GetOpt in a loop. GNU style options with - (and -- for
; long options) are supported as well as Windows / style options.
; See Forum link for an example.
; See http://www.gnu.org/software/libc/manual/html_node/Getopt.html
; for more information.
; Remarks .......: TODO:
; + Optionally enforce use of one option style only, no mixing.
; * Rewrite code to use a ByRef array as return value(s) where
; possible and Local-ize the rest. This would be version 2.0
; to mark fundamental difference in implementation.
; * More documentation in the source.
; CHANGELOG:
; Version 1.3:
; + Added support for -- (marks end of options).
; + Added support for + option modifiers e.g. +x.
; + Added support for /- option modifiers e.g. /-X.
; + Added _GetOpt_Sub to iterate through comma-separated
; suboptions like -s=a=foo,b=bar.
; * Changed $GETOPT_REQUIRED_ARGUMENT from keyword Default to
; Chr(127), keyword can now be used as an option argument.
; * Standardized comments and function headers.
; * Tidy-ed up source code.
; Version 1.2:
; + Support for required arguments with options, e.g.
; _GetOpt('ab:c') where -b=foo is valid and -b will return
; an error.
; + Added support for /C:foo (colon) when using DOS style.
; + Added optional auto-casting of command line arguments from
; Strings to AutoIt variants, e.g. -a=yes on the CLI would set
; the $GetOpt_Arg to True and not 'yes'. See __GetOpt_Cast
; * Private __GetOpt_DOSToGNU to simplify code.
; Version 1.1:
; * Initial public release.
; ==============================================================================
; #CURRENT# ====================================================================
;_GetOpt_Set
;_GetOpt
;_GetOpt_Raw
;_GetOpt_Oper
;_GetOpt_Sub
;_GetOpt_Rewind
; ==============================================================================
; #INTERNAL_USE_ONLY# ==========================================================
;__GetOpt_StartUp
;__GetOpt_DOSToGNU
;__GetOpt_ParseOpt
;__GetOpt_SubStart
;__GetOpt_SubStop
;__GetOpt_Cast
; ==============================================================================
#include-once
; #CONSTANTS# ==================================================================
Global Const $GETOPT_VERSION = '1.3' ; String: Version number.
Global Const $GETOPT_REQUIRED_ARGUMENT = Chr(127) ; String: Value to use for required arguments.
Global Enum $GETOPT_MOD_NONE = 0, $GETOPT_MOD_PLUS, $GETOPT_MOD_MINUS ; Int: Option modifiers.
; Int: @extended error return codes.
Global Enum $E_GETOPT_BAD_FUNCTION_ARGUMENT = 1, _
$E_GETOPT_INVALID_OPTIONS, $E_GETOPT_NO_OPTIONS_SET, _
$E_GETOPT_NO_COMMAND_LINE, $E_GETOPT_NO_OPTIONS, $E_GETOPT_NO_OPERANDS, _
$E_GETOPT_UNKNOWN_OPTION, $E_GETOPT_MISSING_ARGUMENT, _
$E_GETOPT_SUBOPTION_MISMATCH, $E_GETOPT_NO_SUBOPTIONS, $E_GETOPT_UNKNOWN_SUBOPTION
; #VARIABLES# ==================================================================
;Global $GetOpt_OptionStyle = 0 ; 0 = Mix (default), 1 = /Windows, 2 = --gnu ; Force style, not yet implemented.
Global $GetOpt_CastArguments = True ; Boolean: Whether or not to attempt to cast arguments to AutoIt variants when quering them. Default True.
Global $GetOpt_SubOptSeparator = ',' ; String: Suboption separator. Default ',' (comma).
Global $GetOpt_Opt = '' ; String: Current option.
Global $GetOpt_Long = '' ; String: Current long option, if any.
Global $GetOpt_Arg = '' ; Mixed: Argument for current option, if any.
Global $GetOpt_Ind = 0 ; Int: Option index in $GetOpt_Opts.
Global $GetOpt_Mod = 0 ; Int: Indicates option modifier. See $GETOPT_MOD_* constants.
Global $GetOpt_IndRaw = 0 ; Int: Raw option index in $GetOpt_Opts.
Global $GetOpt_OperInd = 0 ; Int: Operand index in $GetOpt_Opers.
Global $GetOpt_Opts[1] = [0] ; Array: Options.
Global $GetOpt_Opers[1] = [0] ; Array: Operands (non-options).
Global $GetOpt_SubOpt = '' ; String: Current suboption, if any.
Global $GetOpt_SubArg = '' ; Mixed: Current argument for suboption, if any.
Global $GetOpt_SubInd = 0 ; Int: Suboption index in $GetOpt_SubOpts.
Global $GetOpt_SubOpts[1] = [0] ; Array: Suboptions.
Global $GetOpt_ArgC = 0 ; Int: Number of arguments passed, this includes the running script/program ($CmdLine[0] + 1).
Global $GetOpt_ArgV[1] = [@ScriptName] ; Array: Array of arguments passed, this includes the running script/program at index 0 (modified $CmdLine).
; #INTERNAL_USE_ONLY# ==========================================================
Local $__GetOpt_fStartUp = False
Local $__GetOpt_aOpts[1][3] = [[0, 0, 0]]
Local $__GetOpt_fSubStart = False
Local $__GetOpt_sSubOpt = ''
; #FUNCTION# ===================================================================
; Name...........: _GetOpt_Set
; Description ...: Set an array of options used by the program.
; Syntax.........: _GetOpt_Set($aOpts)
; Parameters ....: $aOpts - Array: 2-dim array with program options.
; Return values .: Success - Int: Returns 1.
; Failure - Int: Returns 0, sets @error to 1 and sets @extended:
; |1 $E_GETOPT_BAD_FUNCTION_ARGUMENT Argument is wrong variant.
; |2 $E_GETOPT_INVALID_OPTIONS The options array has a wrong
; +number of subscripts.
; |4 $E_GETOPT_NO_COMMAND_LINE No command line to parse.
; Author ........: dany
; Modified ......:
; Remarks .......: The options array has three entries:
; |[0][0] Short option.
; |[0][1] Long option version.
; |[0][2] Default value.
; |Set the value to $GETOPT_REQUIRED_ARGUMENT if the option
; +requires an argument to be passed.
; Related .......: _GetOpt, _GetOpt_Raw, _GetOpt_Oper, _GetOpt_Rewind
;===============================================================================
Func _GetOpt_Set($aOpts)
If 0 = $CmdLine[0] Then Return SetError(1, $E_GETOPT_NO_COMMAND_LINE, 0)
If Not IsArray($aOpts) Then Return SetError(1, $E_GETOPT_BAD_FUNCTION_ARGUMENT, 0)
If 3 > UBound($aOpts, 2) Then Return SetError(1, $E_GETOPT_INVALID_OPTIONS, 0)
Local $i, $iMax = UBound($aOpts)
ReDim $__GetOpt_aOpts[$iMax + 1][3]
$__GetOpt_aOpts[0][0] = $iMax
For $i = 0 To $iMax - 1
$aOpts[$i][0] = __GetOpt_DOSToGNU($aOpts[$i][0])
$aOpts[$i][1] = __GetOpt_DOSToGNU($aOpts[$i][1])
$__GetOpt_aOpts[$i + 1][0] = $aOpts[$i][0]
$__GetOpt_aOpts[$i + 1][1] = $aOpts[$i][1]
$__GetOpt_aOpts[$i + 1][2] = $aOpts[$i][2]
Next
__GetOpt_StartUp()
Return 1
EndFunc ;==>_GetOpt_Set
; #FUNCTION# ===================================================================
; Name...........: _GetOpt
; Description ...: Get the next available option from the command line.
; Syntax.........: _GetOpt($sOpts)
; Parameters ....: $sOpts - String: Containing all available options.
; Return values .: Success - String: The current option.
; Failure - String: '?' in case the option is not recognized.
; |- String: ':' in case the option is missing a required argument.
; |- Int: 0 if anything else went wrong or no options are left.
; |Sets @error to 1 and sets @extended:
; |1 $E_GETOPT_BAD_FUNCTION_ARGUMENT Argument is wrong variant.
; |2 $E_GETOPT_NO_OPTIONS_SET No program options set.
; |4 $E_GETOPT_NO_COMMAND_LINE No command line to parse.
; |5 $E_GETOPT_NO_OPTIONS No options passed.
; |7 $E_GETOPT_UNKNOWN_OPTION Current option is unknown.
; |8 $E_GETOPT_MISSING_ARGUMENT The current option is missing a
; +required argument.
; Author ........: dany
; Modified ......:
; Remarks .......: $sOpts Something like 'abc' where each letter represents an
; +option as set with _GetOpt_Set. Options with a colon : require
; +an argument ('ab:c').
; Related .......: _GetOpt_Raw, _GetOpt_Oper
;===============================================================================
Func _GetOpt($sOpts)
If 0 = $CmdLine[0] Then Return SetError(1, $E_GETOPT_NO_COMMAND_LINE, 0)
If Not IsString($sOpts) Then Return SetError(1, $E_GETOPT_BAD_FUNCTION_ARGUMENT, 0)
__GetOpt_StartUp()
If 0 = $GetOpt_Opts[0] Then Return SetError(1, $E_GETOPT_NO_OPTIONS, 0)
If $GetOpt_Ind + 1 > $GetOpt_Opts[0] Then Return 0
Local $i, $aOpt, $iLong = 0, $sLongOpt = ''
$GetOpt_Opt = ''
$GetOpt_Long = ''
$GetOpt_Arg = ''
$GetOpt_Mod = $GETOPT_MOD_NONE
$aOpt = __GetOpt_ParseOpt($GetOpt_Opts[$GetOpt_Ind + 1])
If '--' = $aOpt[0] Then Return 0
If IsArray($__GetOpt_aOpts) Then
If '+' = StringLeft($aOpt[0], 1) Then
$aOpt[0] = StringReplace($aOpt[0], '+', '-', 1)
$GetOpt_Mod = $GETOPT_MOD_PLUS
ElseIf '*' = StringLeft($aOpt[0], 1) Then
$aOpt[0] = StringReplace($aOpt[0], '*', '-', 1)
$GetOpt_Mod = $GETOPT_MOD_MINUS
EndIf
If '--' = StringLeft($aOpt[0], 2) Then $iLong = 1
For $i = 1 To $__GetOpt_aOpts[0][0]
If $aOpt[0] = $__GetOpt_aOpts[$i][$iLong] Then
$aOpt[0] = $__GetOpt_aOpts[$i][0]
$sLongOpt = $__GetOpt_aOpts[$i][1]
If '' = $aOpt[1] Then
$aOpt[1] = $__GetOpt_aOpts[$i][2]
Else
If $GetOpt_CastArguments Then $aOpt[1] = __GetOpt_Cast($aOpt[1])
EndIf
ExitLoop
EndIf
Next
Else
Return SetError(1, $E_GETOPT_NO_OPTIONS_SET, 0)
EndIf
$aOpt[0] = StringReplace($aOpt[0], '-', '')
$GetOpt_Opt = $aOpt[0]
$GetOpt_Long = $sLongOpt
$GetOpt_Arg = $aOpt[1]
$GetOpt_Ind += 1
; recycle
$iLong = StringInStr($sOpts, $aOpt[0])
If Not $iLong Then Return SetError(1, $E_GETOPT_UNKNOWN_OPTION, '?')
If ':' = StringMid($sOpts, $iLong + 1, 1) Then
If $GETOPT_REQUIRED_ARGUMENT = $aOpt[1] Then Return SetError(1, $E_GETOPT_MISSING_ARGUMENT, ':')
EndIf
Return $GetOpt_Opt
EndFunc ;==>_GetOpt
; #FUNCTION# ===================================================================
; Name...........: _GetOpt_Raw
; Description ...: Get the next available option from the command line.
; Syntax.........: _GetOpt_Raw()
; Return values .: Success - String: The current raw option as in $CmdLine.
; Failure - Int: Returns 0, sets @error to 1 and sets @extended:
; |4 $E_GETOPT_NO_COMMAND_LINE No command line to parse.
; |5 $E_GETOPT_NO_OPTIONS No options passed.
; Author ........: dany
; Modified ......:
; Remarks .......:
; Related .......: _GetOpt, _GetOpt_Oper
;===============================================================================
Func _GetOpt_Raw()
If 0 = $CmdLine[0] Then Return SetError(1, $E_GETOPT_NO_COMMAND_LINE, 0)
__GetOpt_StartUp()
If 0 = $GetOpt_Opts[0] Then Return SetError(1, $E_GETOPT_NO_OPTIONS, 0)
If $GetOpt_IndRaw + 1 > $GetOpt_Opts[0] Then Return 0
$GetOpt_IndRaw += 1
Return $GetOpt_Opts[$GetOpt_IndRaw]
EndFunc ;==>_GetOpt_Raw
; #FUNCTION# ===================================================================
; Name...........: _GetOpt_Oper
; Description ...: Get the next available operand from the command line.
; Syntax.........: _GetOpt_Oper()
; Return values .: Success - String: The current operand.
; Failure - Int: Returns 0, sets @error to 1 and sets @extended:
; |4 $E_GETOPT_NO_COMMAND_LINE No command line to parse.
; |6 $E_GETOPT_NO_OPERANDS No operands passed.
; Author ........: dany
; Modified ......:
; Remarks .......:
; Related .......: _GetOpt, _GetOpt_Raw
;===============================================================================
Func _GetOpt_Oper()
If 0 = $CmdLine[0] Then Return SetError(1, $E_GETOPT_NO_COMMAND_LINE, 0)
__GetOpt_StartUp()
If 0 = $GetOpt_Opers[0] Then Return SetError(1, $E_GETOPT_NO_OPERANDS, 0)
If $GetOpt_OperInd + 1 > $GetOpt_Opers[0] Then Return 0
$GetOpt_OperInd += 1
Return $GetOpt_Opers[$GetOpt_OperInd]
EndFunc ;==>_GetOpt_Oper
; #FUNCTION# ===================================================================
; Name...........: _GetOpt_Sub
; Description ...: Get the next available suboption from an option.
; Syntax.........: _GetOpt_Sub($sSubOption, $aSubOpts)
; Parameters ....: $sSubOption - String:
; $aSubOpts - Array:
; Return values .: Success - String: The current suboption.
; Failure - Int: Returns 0, sets @error to 1 and sets @extended:
; |1 $E_GETOPT_BAD_FUNCTION_ARGUMENT Argument is wrong variant.
; |4 $E_GETOPT_NO_COMMAND_LINE No command line to parse.
; |9 $E_GETOPT_SUBOPTION_MISMATCH Passed suboption is different
; +from the one stored internally.
; |10 $E_GETOPT_NO_SUBOPTIONS No suboptions to parse.
; |11 $E_GETOPT_UNKNOWN_SUBOPTION Current suboption is unknown.
; Author ........: dany
; Modified ......:
; Remarks .......:
; Related .......: _GetOpt
;===============================================================================
Func _GetOpt_Sub($sSubOption, $aSubOpts)
If 0 = $CmdLine[0] Then Return SetError(1, $E_GETOPT_NO_COMMAND_LINE, 0)
If Not IsString($sSubOption) Then Return SetError(1, $E_GETOPT_BAD_FUNCTION_ARGUMENT, 0)
If Not IsArray($aSubOpts) Then Return SetError(1, $E_GETOPT_BAD_FUNCTION_ARGUMENT, 0)
If Not $__GetOpt_fSubStart Then __GetOpt_SubStart($sSubOption)
If $__GetOpt_sSubOpt <> $sSubOption Then Return SetError(1, $E_GETOPT_SUBOPTION_MISMATCH, 0)
If 0 = $GetOpt_SubOpts[0] Then
__GetOpt_SubStop()
Return SetError(1, $E_GETOPT_NO_SUBOPTIONS, 0)
EndIf
If $GetOpt_SubInd + 1 > $GetOpt_SubOpts[0] Then
__GetOpt_SubStop()
Return 0
EndIf
Local $i, $iMax = UBound($aSubOpts) - 1
Local $aParsed = __GetOpt_ParseOpt($GetOpt_SubOpts[$GetOpt_SubInd + 1])
$GetOpt_SubInd += 1
$GetOpt_SubOpt = $aParsed[0]
$GetOpt_SubArg = $aParsed[1]
For $i = 0 To $iMax
If $aSubOpts[$i][0] = $aParsed[0] Then
If '' = $GetOpt_SubArg Then
$GetOpt_SubArg = $aSubOpts[$i][1]
Else
If $GetOpt_CastArguments Then $GetOpt_SubArg = __GetOpt_Cast($GetOpt_SubArg)
EndIf
Return $GetOpt_SubOpt
EndIf
Next
Return SetError(1, $E_GETOPT_UNKNOWN_SUBOPTION, '?')
EndFunc ;==>_GetOpt_Sub
; #FUNCTION# ===================================================================
; Name...........: _GetOpt_Rewind
; Description ...: Rewind all iteration functions and variables.
; Syntax.........: _GetOpt_Rewind()
; Return values .: 1, always.
; Author ........: dany
; Modified ......:
; Remarks .......:
; Related .......: _GetOpt, _GetOpt_Raw, _GetOpt_Oper
;===============================================================================
Func _GetOpt_Rewind()
__GetOpt_StartUp()
$GetOpt_Opt = ''
$GetOpt_Long = ''
$GetOpt_Arg = ''
$GetOpt_Ind = 0
$GetOpt_Mod = 0
$GetOpt_IndRaw = 0
$GetOpt_OperInd = 0
__GetOpt_SubStop()
Return 1
EndFunc ;==>_GetOpt_Rewind
; #INTERNAL_USE_ONLY# ==========================================================
; Name...........: __GetOpt_StartUp
; Description ...: Parses raw command line and normalizes arguments to GNU style.
; Syntax.........: __GetOpt_StartUp()
; Return values .: 1, always.
; Author ........: dany
; Modified ......:
; Remarks .......: For Internal Use Only
;===============================================================================
Func __GetOpt_StartUp()
If $__GetOpt_fStartUp Then Return 1
Local $i, $fEndOfOpts = False, $aParsed = $CmdLine
$GetOpt_ArgC = $CmdLine[0] + 1
ReDim $GetOpt_ArgV[$GetOpt_ArgC]
For $i = 1 To $aParsed[0]
$GetOpt_ArgV[$i] = $aParsed[$i]
$aParsed[$i] = __GetOpt_DOSToGNU($aParsed[$i])
If Not $fEndOfOpts And StringRegExp($aParsed[$i], '^[-+*]') Then
$GetOpt_Opts[0] += 1
ReDim $GetOpt_Opts[$GetOpt_Opts[0] + 1]
$GetOpt_Opts[$GetOpt_Opts[0]] = $aParsed[$i]
If '--' = $aParsed[$i] Then $fEndOfOpts = True
EndIf
Next
For $i = 1 To $aParsed[0]
If Not StringInStr('-+*', StringLeft($aParsed[$i], 1)) Then
$GetOpt_Opers[0] += 1
ReDim $GetOpt_Opers[$GetOpt_Opers[0] + 1]
$GetOpt_Opers[$GetOpt_Opers[0]] = $aParsed[$i]
EndIf
Next
$__GetOpt_fStartUp = True
Return _GetOpt_Rewind()
EndFunc ;==>__GetOpt_StartUp
; #INTERNAL_USE_ONLY# ==========================================================
; Name...........: __GetOpt_DOSToGNU
; Description ...: Translates DOS style options to GNU style.
; Syntax.........: __GetOpt_DOSToGNU($sOpt)
; Parameters ....: $sOpt - String: Current raw option.
; Return values .: String: Translated GNU style option.
; Author ........: dany
; Modified ......:
; Remarks .......: For Internal Use Only
;===============================================================================
Func __GetOpt_DOSToGNU($sOpt)
If StringInStr($sOpt, ':') And Not StringInStr($sOpt, '=') Then
If StringRegExp($sOpt, '^[/+-]') Then $sOpt = StringReplace($sOpt, ':', '=', 1)
EndIf
If '/' = StringLeft($sOpt, 1) And '//' <> StringLeft($sOpt, 2) Then
$sOpt = StringReplace($sOpt, '/-', '*', 1)
If 0 = @extended Then $sOpt = StringReplace($sOpt, '/', '-', 1)
If 2 < StringLen($sOpt) And '=' <> StringMid($sOpt, 3, 1) Then
$sOpt = StringReplace($sOpt, '-', '--', 1)
EndIf
EndIf
Return $sOpt
EndFunc ;==>__GetOpt_DOSToGNU
; #INTERNAL_USE_ONLY# ==========================================================
; Name...........: __GetOpt_ParseOpt
; Description ...: Splits raw option into option and passed argument.
; Syntax.........: __GetOpt_ParseOpt($sOpt)
; Parameters ....: $sOpt - String: Current raw option.
; Return values .: Array: With index 0 = option and 1 = argument.
; Author ........: dany
; Modified ......:
; Remarks .......: For Internal Use Only
;===============================================================================
Func __GetOpt_ParseOpt($sOpt)
Local $iPos, $aParsed[2]
$iPos = StringInStr($sOpt, '=')
If 0 = $iPos Then $iPos = StringLen($sOpt) + 1
$aParsed[0] = StringMid($sOpt, 1, $iPos - 1)
$aParsed[1] = StringMid($sOpt, $iPos + 1)
Return $aParsed
EndFunc ;==>__GetOpt_ParseOpt
; #INTERNAL_USE_ONLY# ==========================================================
; Name...........: __GetOpt_SubStart
; Description ...: Sets variables for use with _GetOpt_Sub.
; Syntax.........: __GetOpt_SubStart($sSubOption)
; Return values .: 1, always.
; Author ........: dany
; Modified ......:
; Remarks .......: For Internal Use Only
;===============================================================================
Func __GetOpt_SubStart($sSubOption)
If $__GetOpt_fSubStart Then Return 1
__GetOpt_SubStop()
Local $i, $aSubOpts = StringSplit($sSubOption, $GetOpt_SubOptSeparator)
$__GetOpt_sSubOpt = $sSubOption
ReDim $GetOpt_SubOpts[1]
$GetOpt_SubOpts[0] = 0
For $i = 1 To $aSubOpts[0]
$GetOpt_SubOpts[0] += 1
ReDim $GetOpt_SubOpts[$GetOpt_SubOpts[0] + 1]
$GetOpt_SubOpts[$GetOpt_SubOpts[0]] = $aSubOpts[$i]
Next
$__GetOpt_fSubStart = True
Return 1
EndFunc ;==>__GetOpt_SubStart
; #INTERNAL_USE_ONLY# ==========================================================
; Name...........: __GetOpt_SubStop
; Description ...: Resets all variables dealing with suboptions.
; Syntax.........: __GetOpt_SubStop()
; Return values .: 1, always.
; Author ........: dany
; Modified ......:
; Remarks .......: For Internal Use Only
;===============================================================================
Func __GetOpt_SubStop()
ReDim $GetOpt_SubOpts[1]
$GetOpt_SubOpts[0] = 0
$GetOpt_SubOpt = ''
$GetOpt_SubArg = ''
$GetOpt_SubInd = 0
$__GetOpt_sSubOpt = ''
$__GetOpt_fSubStart = False
Return 1
EndFunc ;==>__GetOpt_SubStop
; #INTERNAL_USE_ONLY# ==========================================================
; Name...........: __GetOpt_Cast
; Description ...: Attempt to cast a String to a different AutoIt variant based
; on it's content.
; Syntax.........: __GetOpt_Cast($sArg)
; Parameters ....: $sArg - String: Current argument.
; Return values .: Mixed: Float, Int, Default, True, False or String variant.
; Author ........: dany
; Modified ......:
; Remarks .......: For Internal Use Only
;===============================================================================
Func __GetOpt_Cast($sArg)
If StringIsFloat($sArg) Then Return Number($sArg)
If StringIsInt($sArg) Then Return Int($sArg)
If 'Default' = $sArg Then Return Default
If StringRegExp($sArg, '^(?i)(true|y(es)?)$') Then Return True
If StringRegExp($sArg, '^(?i)(false|no?)$') Then Return False
Return String($sArg)
EndFunc ;==>__GetOpt_Cast
=== BinaryCall.au3 ===
; =============================================================================
; AutoIt BinaryCall UDF (2014.7.24)
; Purpose: Allocate, Decompress, And Prepare Binary Machine Code
; Author: Ward
; =============================================================================
#Include-once
Global $__BinaryCall_Kernel32dll = DllOpen('kernel32.dll')
Global $__BinaryCall_Msvcrtdll = DllOpen('msvcrt.dll')
Global $__BinaryCall_LastError = ""
Func _BinaryCall_GetProcAddress($Module, $Proc)
Local $Ret = DllCall($__BinaryCall_Kernel32dll, 'ptr', 'GetProcAddress', 'ptr', $Module, 'str', $Proc)
If @Error Or Not $Ret[0] Then Return SetError(1, @Error, 0)
Return $Ret[0]
EndFunc
Func _BinaryCall_LoadLibrary($Filename)
Local $Ret = DllCall($__BinaryCall_Kernel32dll, "handle", "LoadLibraryW", "wstr", $Filename)
If @Error Then Return SetError(1, @Error, 0)
Return $Ret[0]
EndFunc
Func _BinaryCall_lstrlenA($Ptr)
Local $Ret = DllCall($__BinaryCall_Kernel32dll, "int", "lstrlenA", "ptr", $Ptr)
If @Error Then Return SetError(1, @Error, 0)
Return $Ret[0]
EndFunc
Func _BinaryCall_Alloc($Code, $Padding = 0)
Local $Length = BinaryLen($Code) + $Padding
Local $Ret = DllCall($__BinaryCall_Kernel32dll, "ptr", "VirtualAlloc", "ptr", 0, "ulong_ptr", $Length, "dword", 0x1000, "dword", 0x40)
If @Error Or Not $Ret[0] Then Return SetError(1, @Error, 0)
If BinaryLen($Code) Then
Local $Buffer = DllStructCreate("byte[" & $Length & "]", $Ret[0])
DllStructSetData($Buffer, 1, $Code)
EndIf
Return $Ret[0]
EndFunc
Func _BinaryCall_RegionSize($Ptr)
Local $Buffer = DllStructCreate("ptr;ptr;dword;uint_ptr;dword;dword;dword")
Local $Ret = DllCall($__BinaryCall_Kernel32dll, "int", "VirtualQuery", "ptr", $Ptr, "ptr", DllStructGetPtr($Buffer), "uint_ptr", DllStructGetSize($Buffer))
If @Error Or $Ret[0] = 0 Then Return SetError(1, @Error, 0)
Return DllStructGetData($Buffer, 4)
EndFunc
Func _BinaryCall_Free($Ptr)
Local $Ret = DllCall($__BinaryCall_Kernel32dll, "bool", "VirtualFree", "ptr", $Ptr, "ulong_ptr", 0, "dword", 0x8000)
If @Error Or $Ret[0] = 0 Then
$Ret = DllCall($__BinaryCall_Kernel32dll, "bool", "GlobalFree", "ptr", $Ptr)
If @Error Or $Ret[0] <> 0 Then Return SetError(1, @Error, False)
EndIf
Return True
EndFunc
Func _BinaryCall_Release($CodeBase)
Local $Ret = _BinaryCall_Free($CodeBase)
Return SetError(@Error, @Extended, $Ret)
EndFunc
Func _BinaryCall_MemorySearch($Ptr, $Length, $Binary)
Static $CodeBase
If Not $CodeBase Then
If @AutoItX64 Then
$CodeBase = _BinaryCall_Create('0x4883EC084D85C94889C8742C4C39CA72254C29CA488D141131C9EB0848FFC14C39C97414448A1408453A140874EE48FFC04839D076E231C05AC3', '', 0, True, False)
Else
$CodeBase = _BinaryCall_Create('0x5589E58B4D14578B4508568B550C538B7D1085C9742139CA721B29CA8D341031D2EB054239CA740F8A1C17381C1074F34039F076EA31C05B5E5F5DC3', '', 0, True, False)
EndIf
If Not $CodeBase Then Return SetError(1, 0, 0)
EndIf
$Binary = Binary($Binary)
Local $Buffer = DllStructCreate("byte[" & BinaryLen($Binary) & "]")
DllStructSetData($Buffer, 1, $Binary)
Local $Ret = DllCallAddress("ptr:cdecl", $CodeBase, "ptr", $Ptr, "uint", $Length, "ptr", DllStructGetPtr($Buffer), "uint", DllStructGetSize($Buffer))
Return $Ret[0]
EndFunc
Func _BinaryCall_Base64Decode($Src)
Static $CodeBase
If Not $CodeBase Then
If @AutoItX64 Then
$CodeBase = _BinaryCall_Create('0x41544989CAB9FF000000555756E8BE000000534881EC000100004889E7F3A44C89D6E98A0000004439C87E0731C0E98D0000000FB66E01440FB626FFC00FB65E020FB62C2C460FB62424408A3C1C0FB65E034189EB41C1E4024183E3308A1C1C41C1FB044509E34080FF634189CC45881C08744C440FB6DFC1E5044489DF4088E883E73CC1FF0209C7418D44240241887C08014883C10380FB63742488D841C1E3064883C60483E03F4409D841884408FF89F389C84429D339D30F8C67FFFFFF4881C4000100005B5E5F5D415CC35EC3E8F9FFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0000003F3435363738393A3B3C3D00000063000000000102030405060708090A0B0C0D0E0F101112131415161718190000000000001A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233', '', 132, True, False)
Else
$CodeBase = _BinaryCall_Create('0x55B9FF00000089E531C05756E8F10000005381EC0C0100008B55088DBDF5FEFFFFF3A4E9C00000003B45140F8FC20000000FB65C0A028A9C1DF5FEFFFF889DF3FEFFFF0FB65C0A038A9C1DF5FEFFFF889DF2FEFFFF0FB65C0A018985E8FEFFFF0FB69C1DF5FEFFFF899DECFEFFFF0FB63C0A89DE83E630C1FE040FB6BC3DF5FEFFFFC1E70209FE8B7D1089F3881C074080BDF3FEFFFF63745C0FB6B5F3FEFFFF8BBDECFEFFFF8B9DE8FEFFFF89F083E03CC1E704C1F80209F88B7D1088441F0189D883C00280BDF2FEFFFF6374278A85F2FEFFFFC1E60683C10483E03F09F088441F0289D883C0033B4D0C0F8C37FFFFFFEB0231C081C40C0100005B5E5F5DC35EC3E8F9FFFFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000003E0000003F3435363738393A3B3C3D00000063000000000102030405060708090A0B0C0D0E0F101112131415161718190000000000001A1B1C1D1E1F202122232425262728292A2B2C2D2E2F30313233', '', 132, True, False)
EndIf
If Not $CodeBase Then Return SetError(1, 0, Binary(""))
EndIf
$Src = String($Src)
Local $SrcLen = StringLen($Src)
Local $SrcBuf = DllStructCreate("char[" & $SrcLen & "]")
DllStructSetData($SrcBuf, 1, $Src)
Local $DstLen = Int(($SrcLen + 2) / 4) * 3 + 1
Local $DstBuf = DllStructCreate("byte[" & $DstLen & "]")
Local $Ret = DllCallAddress("uint:cdecl", $CodeBase, "ptr", DllStructGetPtr($SrcBuf), "uint", $SrcLen, "ptr", DllStructGetPtr($DstBuf), "uint", $DstLen)
If $Ret[0] = 0 Then Return SetError(2, 0, Binary(""))
Return BinaryMid(DllStructGetData($DstBuf, 1), 1, $Ret[0])
EndFunc
Func _BinaryCall_Base64Encode($Src)
Static $CodeBase
If Not $CodeBase Then
If @AutoItX64 Then
$CodeBase = _BinaryCall_Create('AwAAAARiAQAAAAAAAAArkuFQDAlvIp0qAgbDnjr76UDZs1EPNIP2K18t9s6SNTbd43IB7HfdyPM8VfD/o36z4AmSW2m2AIsC6Af3fKNsHU4BdQKGd0PQXHxPSX0iNqp1YAKovksqQna06NeKMoOYqryTUX4WgpHjokhp6zY2sEFSIjcL7dW3FDoNVz4bGPyZHRvjFwmqvr7YGlNYKwNoh+SYCXmIgVPVZ63Vz1fbT33/QFpWmWOeBRqs4J+c8Qp6zJFsK345Pjw0I8kMSsnho4F4oNzQ2OsAbmIioaQ6Ma2ziw5NH+M+t4SpEeHDnBdUTTL20sxWZ0yKruFAsBIRoHvM7LYcid2eBV2d5roSjnkwMG0g69LNjs1fHjbI/9iU/hJwpSsgl4fltXdZG659/li13UFY89M7UfckiZ9XOeBM0zadgNsy8r8M3rEAAA==')
Else
$CodeBase = _BinaryCall_Create('AwAAAARVAQAAAAAAAAAqr7blBndrIGnmhhfXD7R1fkOTKhicg1W6MCtStbz+CsneBEg0bbHH1sqTLmLfY7A6LqZl6LYWT5ULVj6MXgugPbBn9wKsSU2ZCcBBPNkx09HVPdUaKnbqghDGj/C5SHoF+A/5g+UgE1C5zJZORjJ8ljs5lt2Y9lA4BsY7jVKX2vmDvHK1NnSR6nVwh7Pb+Po/UpNcy5sObVWDKkYSCCtCIjKIYqOe3c6k8Xsp4eritCUprXEVvCFi7K5Z6HFXdm3nZsFcE+eSJ1WkRnVQbWcmpjGMGka61C68+CI7tsQ13UnCFWNSpDrCbzUejMZh8HdPgEc5vCg3pKMKin/NavNpB6+87Y9y7HIxmKsPdjDT30u9hUKWnYiRe3nrwKyVDsiYpKU/Nse368jHag5B5or3UKA+nb2+eY8JwzgA')
EndIf
If Not $CodeBase Then Return SetError(1, 0, Binary(""))
EndIf
$Src = Binary($Src)
Local $SrcLen = BinaryLen($Src)
Local $SrcBuf = DllStructCreate("byte[" & $SrcLen & "]")
DllStructSetData($SrcBuf, 1, $Src)
Local $DstLen = Int(($SrcLen + 2) / 3) * 4 + 1
Local $DstBuf = DllStructCreate("char[" & $DstLen & "]")
Local $Ret = DllCallAddress("uint:cdecl", $CodeBase, "ptr", DllStructGetPtr($SrcBuf), "uint", $SrcLen, "ptr", DllStructGetPtr($DstBuf), "uint", $DstLen)
If $Ret[0] = 0 Then Return Binary("")
Return StringMid(DllStructGetData($DstBuf, 1), 1, $Ret[0])
EndFunc
Func _BinaryCall_LzmaDecompress($Src)
Static $CodeBase
If Not $CodeBase Then
If @AutoItX64 Then
$CodeBase = _BinaryCall_Create(_BinaryCall_Base64Decode('QVcxwEFWQVVBVFVXSInXVkiJzlMx20iB7OgAAABEiiFBgPzgdgnpyQAAAEGD7C1BiMf/wEGA/Cx38THA6wRBg+wJQYjG/8BBgPwId/GLRglEi24FQQ+2zkyJRCQoRQ+2/0HB5xBBiQFBD7bEAcG4AAMAANPgjYQAcA4AAEhjyOjIBAAATInpSInF6L0EAABIicMxwEyJ8kSI4EyLRCQoiNQl//8A/0QJ+EiF24lFAHQoTYXtdCNIjVfzSI1MJDhIg8YNTIkEJE2J6UmJ2EiJ7+g2AAAAicbrBb4BAAAASInp6IQEAACF9nQKSInZMdvodgQAAEiJ2EiBxOgAAABbXl9dQVxBXUFeQV/DVVNBV0FWQVVBVEFQTQHBQVFNicVRVkgB8lJIieX8SYn0iwdMjX8Eik8Cg8r/0+L30olV6Ijhg8r/0+L30olV5ADBiUXsuAEAAACJReCJRdyJRdhIiUXQRSnJKfaDy/8A0bgAAwAA0+BIjYg2BwAAuAAEAARMif/R6fOrvwUAAADoUAMAAP/PdfdEie9EicgrfSDB4ARBifpEI1XoRAHQTY0cR+hAAwAAD4WTAAAAik3sI33k0+eA6Qj22dPuAfe4AQAAAEiNPH++AAEAAMHnCEGD+QdNjbR/bA4AAHI0TInvSCt90A+2P9HnQYnzIf5BAfNPjRxe6O8CAACJwcHuCIPhATnOvgABAAB1DjnGd9jrDE2J8+jQAgAAOfBy9EyJ76pEiclBg/kEcg65AwAAAEGD+QpyA4PBA0EpyelDAgAAT42cT4ABAADomgIAAHUsi0XcQYP5B4lF4BnAi1XY99CLTdCD4AOJVdxBicGJTdhNjbdkBgAA6akAAABPjZxPmAEAAOhfAgAAdUZEicjB4AREAdBNjZxH4AEAAOhHAgAAdWpBg/kHuQkAAAByA4PBAkGJyUyJ70grfdBIO30gD4L9AQAAigdIA33QqumzAQAAT42cT7ABAADoCgIAAIt12HQhT42cT8gBAADo+AEAAIt13HQJi03ci3XgiU3gi03YiU3ci03QiU3YiXXQQYP5B7kIAAAAcgODwQNBiclNjbdoCgAATYnz6LsBAAB1FESJ0CnJweADvggAAABJjXxGBOs2TY1eAuicAQAAdRpEidC5CAAAAMHgA74IAAAASY28RgQBAADrEUmNvgQCAAC5EAAAAL4AAQAAiU3MuAEAAABJifvoYQEAAInCKfJy8gNVzEGD+QSJVcwPg7kAAABBg8EHuQMAAAA50XICidHB4Qa4AQAAAEmNvE9gAwAAvkAAAABJifvoHwEAAEGJwkEp8nLwQYP6BHJ4RInWRIlV0NHug2XQAf/Og03QAkGD+g5zFYnx0mXQi0XQRCnQTY20R14FAADrLIPuBOi6AAAA0evRZdBBOdhyBv9F0EEp2P/OdedNjbdEBgAAwWXQBL4EAAAAvwEAAACJ+E2J8+ioAAAAqAF0Awl90NHn/8516+sERIlV0P9F0EyJ74tNzEiJ+IPBAkgrRSBIOUXQd1RIif5IK3XQSItVGKyqSDnXcwT/yXX1SYn9D7bwTDttGA+C9fz//+gwAAAAKcBIi1UQTCtlCESJIkiLVWBMK20gRIkqSIPEKEFcQV1BXUFfW13DXli4AQAAAOvSgfsAAAABcgHDweMITDtlAHPmQcHgCEWKBCRJg8QBwynATY0cQ4H7AAAAAXMVweMITDtlAHPBQcHgCEWKBCRJg8QBidlBD7cTwekLD6/KQTnIcxOJy7kACAAAKdHB6QVmQQELAcDDKcvB6gVBKchmQSkTAcCDwAHDSLj////////////gbXN2Y3J0LmRsbHxtYWxsb2MASLj////////////gZnJlZQA='))
Else
$CodeBase = _BinaryCall_Create(_BinaryCall_Base64Decode('VYnlVzH/VlOD7EyLXQiKC4D54A+HxQAAADHA6wWD6S2I0ID5LI1QAXfziEXmMcDrBYPpCYjQgPkIjVABd/OIReWLRRSITeSLUwkPtsmLcwWJEA+2ReUBwbgAAwAA0+CNhABwDgAAiQQk6EcEAACJNCSJRdToPAQAAItV1InHi0Xkhf+JArgBAAAAdDaF9nQyi0UQg8MNiRQkiXQkFIl8JBCJRCQYjUXgiUQkDItFDIlcJASD6A2JRCQI6CkAAACLVdSJRdSJFCToAQQAAItF1IXAdAqJPCQx/+jwAwAAg8RMifhbXl9dw1dWU1WJ5YtFJAFFKFD8i3UYAXUcVot1FK2SUopO/oPI/9Pg99BQiPGDyP/T4PfQUADRifeD7AwpwEBQUFBQUFcp9laDy/+4AAMAANPgjYg2BwAAuAAEAATR6fOragVZ6MoCAADi+Yt9/ItF8Ct9JCH4iUXosADoywIAAA+FhQAAAIpN9CN97NPngOkI9tnT7lgB916NPH/B5wg8B1qNjH5sDgAAUVa+AAEAAFCwAXI0i338K33cD7Y/i23M0eeJ8SH+AfGNbE0A6JgCAACJwcHuCIPhATnOvgABAAB1DjnwctfrDIttzOh5AgAAOfBy9FqD+gSJ0XIJg/oKsQNyArEGKcpS60mwwOhJAgAAdRRYX1pZWln/NCRRUrpkBgAAsQDrb7DM6CwCAAB1LLDw6BMCAAB1U1g8B7AJcgKwC1CLdfwrddw7dSQPgs8BAACsi338qumOAQAAsNjo9wEAAIt12HQbsOTo6wEAAIt11HQJi3XQi03UiU3Qi03YiU3Ui03ciU3YiXXcWF9ZumgKAACxCAH6Ulc8B4jIcgIEA1CLbczovAEAAHUUi0Xoi33MweADKclqCF6NfEcE6zWLbcyDxQLomwEAAHUYi0Xoi33MweADaghZaghejbxHBAEAAOsQvwQCAAADfcxqEFm+AAEAAIlN5CnAQIn96GYBAACJwSnxcvMBTeSDfcQED4OwAAAAg0XEB4tN5IP5BHIDagNZi33IweEGKcBAakBejbxPYAMAAIn96CoBAACJwSnxcvOJTeiJTdyD+QRyc4nOg2XcAdHug03cAk6D+Q5zGbivAgAAKciJ8dJl3ANF3NHgA0XIiUXM6y2D7gToowAAANHr0WXcOV3gcgb/RdwpXeBOdei4RAYAAANFyIlFzMFl3ARqBF4p/0eJ+IttzOi0AAAAqAF0Awl93NHnTnXs6wD/RdyLTeSDwQKLffyJ+CtFJDlF3HdIif4rddyLVSisqjnXcwNJdfeJffwPtvA7fSgPgnH9///oKAAAACnAjWwkPItVIIt1+Ct1GIkyi1Usi338K30kiTrJW15fw15YKcBA69qB+wAAAAFyAcPB4whWi3X4O3Ucc+SLReDB4AisiUXgiXX4XsOLTcQPtsDB4QQDRegByOsGD7bAA0XEi23IjWxFACnAjWxFAIH7AAAAAXMci0wkOMFkJCAIO0wkXHOcihH/RCQ4weMIiFQkIInZD7dVAMHpCw+vyjlMJCBzF4nLuQAIAAAp0cHpBWYBTQABwI1sJEDDweoFKUwkICnLZilVAAHAg8ABjWwkQMO4///////gbXN2Y3J0LmRsbHxtYWxsb2MAuP//////4GZyZWUA'))
EndIf
If Not $CodeBase Then Return SetError(1, 0, Binary(""))
EndIf
$Src = Binary($Src)
Local $SrcLen = BinaryLen($Src)
Local $SrcBuf = DllStructCreate("byte[" & $SrcLen & "]")
DllStructSetData($SrcBuf, 1, $Src)
Local $Ret = DllCallAddress("ptr:cdecl", $CodeBase, "ptr", DllStructGetPtr($SrcBuf), "uint_ptr", $SrcLen, "uint_ptr*", 0, "uint*", 0)
If $Ret[0] Then
Local $DstBuf = DllStructCreate("byte[" & $Ret[3] & "]", $Ret[0])
Local $Output = DllStructGetData($DstBuf, 1)
DllCall($__BinaryCall_Msvcrtdll, "none:cdecl", "free", "ptr", $Ret[0])
Return $Output
EndIf
Return SetError(2, 0, Binary(""))
EndFunc
Func _BinaryCall_Relocation($Base, $Reloc)
Local $Size = Int(BinaryMid($Reloc, 1, 2))
For $i = 3 To BinaryLen($Reloc) Step $Size
Local $Offset = Int(BinaryMid($Reloc, $i, $Size))
Local $Ptr = $Base + $Offset
DllStructSetData(DllStructCreate("ptr", $Ptr), 1, DllStructGetData(DllStructCreate("ptr", $Ptr), 1) + $Base)
Next
EndFunc
Func _BinaryCall_ImportLibrary($Base, $Length)
Local $JmpBin, $JmpOff, $JmpLen, $DllName, $ProcName
If @AutoItX64 Then
$JmpBin = Binary("0x48B8FFFFFFFFFFFFFFFFFFE0")
$JmpOff = 2
Else
$JmpBin = Binary("0xB8FFFFFFFFFFE0")
$JmpOff = 1
EndIf
$JmpLen = BinaryLen($JmpBin)
Do
Local $Ptr = _BinaryCall_MemorySearch($Base, $Length, $JmpBin)
If $Ptr = 0 Then ExitLoop
Local $StringPtr = $Ptr + $JmpLen
Local $StringLen = _BinaryCall_lstrlenA($StringPtr)
Local $String = DllStructGetData(DllStructCreate("char[" & $StringLen & "]", $StringPtr), 1)
Local $Split = StringSplit($String, "|")
If $Split[0] = 1 Then
$ProcName = $Split[1]
ElseIf $Split[0] = 2 Then
If $Split[1] Then $DllName = $Split[1]
$ProcName = $Split[2]
EndIf
If $DllName And $ProcName Then
Local $Handle = _BinaryCall_LoadLibrary($DllName)
If Not $Handle Then
$__BinaryCall_LastError = "LoadLibrary fail on " & $DllName
Return SetError(1, 0, False)
EndIf
Local $Proc = _BinaryCall_GetProcAddress($Handle, $ProcName)
If Not $Proc Then
$__BinaryCall_LastError = "GetProcAddress failed on " & $ProcName
Return SetError(2, 0, False)
EndIf
DllStructSetData(DllStructCreate("ptr", $Ptr + $JmpOff), 1, $Proc)
EndIf
Local $Diff = Int($Ptr - $Base + $JmpLen + $StringLen + 1)
$Base += $Diff
$Length -= $Diff
Until $Length <= $JmpLen
Return True
EndFunc
Func _BinaryCall_CodePrepare($Code)
If Not $Code Then Return ""
If IsBinary($Code) Then Return $Code
$Code = String($Code)
If StringLeft($Code, 2) = "0x" Then Return Binary($Code)
If StringIsXDigit($Code) Then Return Binary("0x" & $Code)
Return _BinaryCall_LzmaDecompress(_BinaryCall_Base64Decode($Code))
EndFunc
Func _BinaryCall_SymbolFind($CodeBase, $Identify, $Length = Default)
$Identify = Binary($Identify)
If IsKeyword($Length) Then
$Length = _BinaryCall_RegionSize($CodeBase)
EndIf
Local $Ptr = _BinaryCall_MemorySearch($CodeBase, $Length, $Identify)
If $Ptr = 0 Then Return SetError(1, 0, 0)
Return $Ptr + BinaryLen($Identify)
EndFunc
Func _BinaryCall_SymbolList($CodeBase, $Symbol)
If Not IsArray($Symbol) Or $CodeBase = 0 Then Return SetError(1, 0, 0)
Local $Tag = ""
For $i = 0 To UBound($Symbol) - 1
$Tag &= "ptr " & $Symbol[$i] & ";"
Next
Local $SymbolList = DllStructCreate($Tag)
If @Error Then Return SetError(1, 0, 0)
For $i = 0 To UBound($Symbol) - 1
$CodeBase = _BinaryCall_SymbolFind($CodeBase, $Symbol[$i])
DllStructSetData($SymbolList, $Symbol[$i], $CodeBase)
Next
Return $SymbolList
EndFunc
Func _BinaryCall_Create($Code, $Reloc = '', $Padding = 0, $ReleaseOnExit = True, $LibraryImport = True)
Local $BinaryCode = _BinaryCall_CodePrepare($Code)
If Not $BinaryCode Then Return SetError(1, 0, 0)
Local $BinaryCodeLen = BinaryLen($BinaryCode)
Local $TotalCodeLen = $BinaryCodeLen + $Padding
Local $CodeBase = _BinaryCall_Alloc($BinaryCode, $Padding)
If Not $CodeBase Then Return SetError(2, 0, 0)
If $Reloc Then
$Reloc = _BinaryCall_CodePrepare($Reloc)
If Not $Reloc Then Return SetError(3, 0, 0)
_BinaryCall_Relocation($CodeBase, $Reloc)
EndIf
If $LibraryImport Then
If Not _BinaryCall_ImportLibrary($CodeBase, $BinaryCodeLen) Then
_BinaryCall_Free($CodeBase)
Return SetError(4, 0, 0)
EndIf
EndIf
If $ReleaseOnExit Then
_BinaryCall_ReleaseOnExit($CodeBase)
EndIf
Return SetError(0, $TotalCodeLen, $CodeBase)
EndFunc
Func _BinaryCall_CommandLineToArgv($CommandLine, ByRef $Argc, $IsUnicode = False)
Static $SymbolList
If Not IsDllStruct($SymbolList) Then
Local $Code
If @AutoItX64 Then
$Code = 'AwAAAASuAgAAAAAAAAAkL48ClEB9jTEOeYv4yYTosNjFNgf81Ag4vS2VP4y4wxFa+4yMI7GDB7CG+xn4JE3cdEVvk8cMp4oIuS3DgTxlcKHGVIg94tvzG/256bizZfGtAETQUCPQjW5+JSx2C/Y4C0VNJMKTlSCHiV5AzXRZ5gw3WFghbtkCCFxWOX+RDSI2oH/vROEOnqc0jfKTo17EBjqX+dW3QxrUe45xsbyYTZ9ccIGySgcOAxetbRiSxQnz8BOMbJyfrbZbuVJyGpKrXFLh/5MlBZ09Cim9qgflbGzmkrGStT9QL1f+O2krzyOzgaWWqhWL6S+y0G32RWVi0uMLR/JOGLEW/+Yg/4bzkeC0lKELT+RmWAatNa38BRfaitROMN12moRDHM6LYD1lzPLnaiefSQRVti561sxni/AFkYoCb5Lkuyw4RIn/r/flRiUg5w48YkqBBd9rXkaXrEoKwPg6rmOvOCZadu//B6HN4+Ipq5aYNuZMxSJXmxwXVRSQZVpSfLS2ATZMd9/Y7kLqrKy1H4V76SgI/d9OKApfKSbQ8ZaKIHBCsoluEip3UDOB82Z21zd933UH5l0laGWLIrTz7xVGkecjo0NQzR7LyhhoV3xszlIuw2v8q0Q/S9LxB5G6tYbOXo7lLjNIZc0derZz7DNeeeJ9dQE9hp8unubaTBpulPxTNtRjog=='
Else
$Code = 'AwAAAAR6AgAAAAAAAABcQfD553vjya/3DmalU0BKqABevUb/60GZ55rMwmzpQfPSRUlIl04lEiS8RDrXpS0EoBUe+uzDgZd37nVu9wsJ4fykqYvLoMz3ApxQbTBKleOIRSla6I0V8dNP3P7rHeUfjH0jCho0RvhhVpf0o4ht/iZptauxaoy1zQ19TkPZ/vf5Im8ecY6qEdHNzjo2H60jVwiOJ+1J47TmQRwxJ+yKLakq8QNxtKkRIB9B9ugfo3NAL0QslDxbyU0dSgw2aOPxV+uttLzYNnWbLBZVQbchcKgLRjC/32U3Op576sOYFolB1Nj4/33c7MRgtGLjlZfTB/4yNvd4/E+u3U6/Q4MYApCfWF4R/d9CAdiwgIjCYUkGDExKjFtHbAWXfWh9kQ7Q/GWUjsfF9BtHO6924Cy1Ou+BUKksqsxmIKP4dBjvvmz9OHc1FdtR9I63XKyYtlUnqVRtKwlNrYAZVCSFsyAefMbteq1ihU33sCsLkAnp1LRZ2wofgT1/JtT8+GO2s/n52D18wM70RH2n5uJJv8tlxQc1lwbmo4XQvcbcE91U2j9glvt2wC1pkP0hF23Nr/iiIEZHIPAOAHvhervlHE830LSHyUx8yh5Tjojr0gdLvQ=='
EndIf
Local $CodeBase = _BinaryCall_Create($Code)
If @Error Then Return SetError(1, 0, 0)
Local $Symbol[] = ["ToArgvW","ToArgvA"]
$SymbolList = _BinaryCall_SymbolList($CodeBase, $Symbol)
If @Error Then Return SetError(1, 0, 0)
EndIf
Local $Ret
If $IsUnicode Then
$Ret = DllCallAddress("ptr:cdecl", DllStructGetData($SymbolList, "ToArgvW"), "wstr", $CommandLine, "int*", 0)
Else
$Ret = DllCallAddress("ptr:cdecl", DllStructGetData($SymbolList, "ToArgvA"), "str", $CommandLine, "int*", 0)
EndIf
If Not @Error And $Ret[0] <> 0 Then
_BinaryCall_ReleaseOnExit($Ret[0])
$Argc = $Ret[2]
Return $Ret[0]
Else
Return SetError(2, 0, 0)
EndIf
EndFunc
Func _BinaryCall_StdioRedirect($Filename = "CON", $Flag = 1 + 2 + 4)
Static $SymbolList
If Not IsDllStruct($SymbolList) Then
Local $Code, $Reloc
If @AutoItX64 Then
$Code = 'AwAAAASjAQAAAAAAAAAkL48ClEB9jTEOeYv4yYTosNjFM1rLNdMULriZUDxTj+ZdkQ01F5zKL+WDCScfQKKLn66EDmcA+gXIkPcZV4lyz8VPw8BPZlNB5KymydM15kCA+uqvmBc1V0NJfzgsF0Amhn0JhM/ZIguYCHxywMQ1SgKxUb05dxDg8WlX/2aPfSolcX47+4/72lPDNTeT7d7XRdm0ND+eCauuQcRH2YOahare9ASxuU4IMHCh2rbZYHwmTNRiQUB/8dLGtph93yhmwdHtyMPLX2x5n6sdA1mxua9htLsLTulE05LLmXbRYXylDz0A'
$Reloc = 'AwAAAAQIAAAAAAAAAAABAB7T+CzGn9ScQAC='
Else
$Code = 'AwAAAASVAQAAAAAAAABcQfD553vjya/3DmalU0BKqABaUcndypZ3mTYUkHxlLV/lKZPrXYWXgNATjyiowkUQGDVYUy5THQwK4zYdU7xuGf7qfVDELc1SNbiW3NgD4D6N6ZM7auI1jPaThsPfA/ouBcx2aVQX36fjmViTZ8ZLzafjJeR7d5OG5s9sAoIzFLTZsqrFlkIJedqDAOfhA/0mMrkavTWnsio6yTbic1dER0DcEsXpLn0vBNErKHoagLzAgofHNLeFRw5yHWz5owR5CYL7rgiv2k51neHBWGx97A=='
$Reloc = 'AwAAAAQgAAAAAAAAAAABABfyHS/VRkdjBBzbtGPD6vtmVH/IsGHYvPsTv2lGuqJxGlAA'
EndIf
Local $CodeBase = _BinaryCall_Create($Code, $Reloc)
If @Error Then Return SetError(1, 0, 0)
Local $Symbol[] = ["StdinRedirect","StdoutRedirect","StderrRedirect"]
$SymbolList = _BinaryCall_SymbolList($CodeBase, $Symbol)
If @Error Then Return SetError(1, 0, 0)
EndIf
If BitAND($Flag, 1) Then DllCallAddress("none:cdecl", DllStructGetData($SymbolList, "StdinRedirect"), "str", $Filename)
If BitAND($Flag, 2) Then DllCallAddress("none:cdecl", DllStructGetData($SymbolList, "StdoutRedirect"), "str", $Filename)
If BitAND($Flag, 4) Then DllCallAddress("none:cdecl", DllStructGetData($SymbolList, "StderrRedirect"), "str", $Filename)
EndFunc
Func _BinaryCall_StdinRedirect($Filename = "CON")
Local $Ret = _BinaryCall_StdioRedirect($Filename, 1)
Return SetError(@Error, @Extended, $Ret)
EndFunc
Func _BinaryCall_StdoutRedirect($Filename = "CON")
Local $Ret = _BinaryCall_StdioRedirect($Filename, 2)
Return SetError(@Error, @Extended, $Ret)
EndFunc
Func _BinaryCall_StderrRedirect($Filename = "CON")
Local $Ret = _BinaryCall_StdioRedirect($Filename, 4)
Return SetError(@Error, @Extended, $Ret)
EndFunc
Func _BinaryCall_ReleaseOnExit($Ptr)
OnAutoItExitRegister('__BinaryCall_DoRelease')
__BinaryCall_ReleaseOnExit_Handle($Ptr)
EndFunc
Func __BinaryCall_DoRelease()
__BinaryCall_ReleaseOnExit_Handle()
EndFunc
Func __BinaryCall_ReleaseOnExit_Handle($Ptr = Default)
Static $PtrList
If @NumParams = 0 Then
If IsArray($PtrList) Then
For $i = 1 To $PtrList[0]
_BinaryCall_Free($PtrList[$i])
Next
EndIf
Else
If Not IsArray($PtrList) Then
Local $InitArray[1] = [0]
$PtrList = $InitArray
EndIf
If IsPtr($Ptr) Then
Local $Array = $PtrList
Local $Size = UBound($Array)
ReDim $Array[$Size + 1]
$Array[$Size] = $Ptr
$Array[0] += 1
$PtrList = $Array
EndIf
EndIf
EndFunc
=== Json.au3 ===
; ============================================================================================================================
; File : Json.au3 (2018.12.29)
; Purpose : A Non-Strict JavaScript Object Notation (JSON) Parser UDF
; Author : Ward
; Dependency: BinaryCall.au3
; Website : http://www.json.org/index.html
;
; Source : jsmn.c
; Author : zserge
; Website : http://zserge.com/jsmn.html
;
; Source : json_string_encode.c, json_string_decode.c
; Author : Ward
; Jos - Added Json_Dump()
; TheXMan - Json_ObjGetItems and some Json_Dump Fixes.
; Jos - Changed Json_ObjGet() and Json_ObjExists() to allow for multilevel object in string.
; ============================================================================================================================
; ============================================================================================================================
; Public Functions:
; Json_StringEncode($String, $Option = 0)
; Json_StringDecode($String)
; Json_IsObject(ByRef $Object)
; Json_IsNull(ByRef $Null)
; Json_Encode($Data, $Option = 0, $Indent = Default, $ArraySep = Default, $ObjectSep = Default, $ColonSep = Default)
; Json_Decode($Json, $InitTokenCount = 1000)
; Json_ObjCreate()
; Json_ObjPut(ByRef $Object, $Key, $Value)
; Json_ObjGet(ByRef $Object, $Key)
; Json_ObjDelete(ByRef $Object, $Key)
; Json_ObjExists(ByRef $Object, $Key)
; Json_ObjGetCount(ByRef $Object)
; Json_ObjGetKeys(ByRef $Object)
; Json_ObjGetItems(ByRef $Object)
; Json_ObjClear(ByRef $Object)
; Json_Put(ByRef $Var, $Notation, $Data, $CheckExists = False)
; Json_Get(ByRef $Var, $Notation)
; Json_Dump($String)
; ============================================================================================================================
#include-once
#include "BinaryCall.au3"
; The following constants can be combined to form options for Json_Encode()
Global Const $JSON_UNESCAPED_UNICODE = 1 ; Encode multibyte Unicode characters literally
Global Const $JSON_UNESCAPED_SLASHES = 2 ; Don't escape /
Global Const $JSON_HEX_TAG = 4 ; All < and > are converted to \u003C and \u003E
Global Const $JSON_HEX_AMP = 8 ; All &s are converted to \u0026
Global Const $JSON_HEX_APOS = 16 ; All ' are converted to \u0027
Global Const $JSON_HEX_QUOT = 32 ; All " are converted to \u0022
Global Const $JSON_UNESCAPED_ASCII = 64 ; Don't escape ascii charcters between chr(1) ~ chr(0x1f)
Global Const $JSON_PRETTY_PRINT = 128 ; Use whitespace in returned data to format it
Global Const $JSON_STRICT_PRINT = 256 ; Make sure returned JSON string is RFC4627 compliant
Global Const $JSON_UNQUOTED_STRING = 512 ; Output unquoted string if possible (conflicting with $Json_STRICT_PRINT)
; Error value returnd by Json_Decode()
Global Const $JSMN_ERROR_NOMEM = -1 ; Not enough tokens were provided
Global Const $JSMN_ERROR_INVAL = -2 ; Invalid character inside JSON string
Global Const $JSMN_ERROR_PART = -3 ; The string is not a full JSON packet, more bytes expected
Global $Total_JSON_DUMP_Output = ""
Func __Jsmn_RuntimeLoader($ProcName = "")
Static $SymbolList
If Not IsDllStruct($SymbolList) Then
Local $Code
If @AutoItX64 Then
$Code = 'AwAAAAQfCAAAAAAAAAA1HbEvgTNrvX54gCiWSTVmt5v7RCdoFJ/zhkKmwcm8yVqZPjJBoVhNHHAIzrHWKbZh1J0QAUaHB5zyQTilTmWa9O0OKeLrk/Jg+o7CmMzjEk74uPongdHv37nwYXvg97fiHvjP2bBzI9gxSkKq9Cqh/GxSHIlZPYyW76pXUt//25Aqs2Icfpyay/NFd50rW7eMliH5ynkrp16HM1afithVrO+LpSaz/IojowApmXnBHUncHliDqbkx6/AODUkyDm1hj+AiEZ9Me1Jy+hBQ1/wC/YnuuYSJvNAKp6XDnyc8Nwr54Uqx5SbUW2CezwQQ7aXX/HFiHSKpQcFW/gi8oSx5nsoxUXVjxeNI/L7z6GF2mfu3Tnpt7hliWEdA2r2VB+TIM7Pgwl9X3Ge0T3KJQUaRtLJZcPvVtOuKXr2Q9wy7hl80hVRrt9zYrbjBHXLrRx/HeIMkZwxhmKo/dD/vvaNgE+BdU8eeJqFBJK2alrK2rh2WkRynftyepm1WrdKrz/5KhQPp/4PqH+9IADDjoGBbfvJQXdT+yiO8DtfrVnd+JOEKsKEsdgeM3UXx5r6tEHO9rYWbzbnyEiX7WozZemry+vBZMMtHn1aA63+RcDQED73xOsnj00/9E5Z6hszM5Hi8vi6Hw3iOgf3cHwcXG44aau0JpuA2DlrUvnJOYkNnY+bECeSdAR1UQkFNyqRoH2xm4Y7gYMCPsFtPBlwwleEKI27SsUq1ZHVQvFCoef7DXgf/GwPCAvwDMIQfb3hJtIVubOkASRQZVNIJ/y4KPrn/gcASV7fvMjE34loltTVlyqprUWxpI51tN6vhTOLAp+CHseKxWaf9g1wdbVs0e/5xAiqgJbmKNi9OYbhV/blpp3SL63XKxGiHdxhK1aR+4rUY4eckNbaHfW7ob+q7aBoHSs6LVX9lWakb/xWxwQdwcX/7/C+TcQSOOg6rLoWZ8wur9qp+QwzoCbXkf04OYpvD5kqgEiwQnB90kLtcA+2XSbDRu+aq02eNNCzgkZujeL/HjVISjf2EuQKSsZkBhS15eiXoRgPaUoQ5586VS7t7rhM8ng5LiVzoUQIZ0pNKxWWqD+gXRBvOMIXY2yd0Ei4sE5KFIEhbs3u8vwP7nFLIpZ/RembPTuc0ZlguGJgJ2F5iApfia+C2tRYRNjVCqECCveWw6P2Btfaq9gw7cWWmJflIQbjxtccDqsn52cftLqXSna9zk05mYdJSV8z2W7vM1YJ5Rd82v0j3kau710A/kQrN41bdaxmKjL+gvSRlOLB1bpvkCtf9+h+eVA4XIkIXKFydr1OjMZ8wq2FIxPJXskAe4YMgwQmeWZXMK1KBbLB3yQR1YOYaaHk1fNea9KsXgs5YLbiP/noAusz76oEDo/DJh1aw7cUwdhboVPg1bNq88mRb5RGa13KDK9uEET7OA02KbSL+Q4HOtyasLUoVrZzVyd8iZPoGrV36vHnj+yvG4fq6F/fkug/sBRp186yVZQVmdAgFd+WiRLnUjxHUKJ6xBbpt4FTP42E/PzPw3JlDb0UQtXTDnIL0CWqbns2E7rZ5PBwrwQYwvBn/gaEeLVGDSh84DfW4zknIneGnYDXdVEHC+ITzejAnNxb1duB+w2aVTk64iXsKHETq53GMH6DuFi0oUeEFb/xp0HsRyNC8vBjOq3Kk7NZHxCQLh7UATFttG7sH+VIqGjjNwmraGJ0C92XhpQwSgfAb3KHucCHGTTti0sn6cgS3vb36BkjGKsRhXVuoQCFH96bvTYtl8paQQW9ufRfvxPqmU0sALdR0fIvZwd7Z8z0UoEec6b1Sul4e60REj/H4scb6N2ryHBR9ua5N1YxJu1uwgoLXUL2wT9ZPBjPjySUzeqXikUIKKYgNlWy+VlNIiWWTPtKpCTr508logA=='
Else
$Code = 'AwAAAASFBwAAAAAAAAA1HbEvgTNrvX54gCiqsa1mt5v7RCdoAFjCfVE40DZbE5UfabA9UKuHrjqOMbvjSoB2zBJTEYEQejBREnPrXL3VwpVOW+L9SSfo0rTfA8U2W+Veqo1uy0dOsPhl7vAHbBHrvJNfEUe8TT0q2eaTX2LeWpyrFEm4I3mhDJY/E9cpWf0A78e+y4c7NxewvcVvAakIHE8Xb8fgtqCTVQj3Q1eso7n1fKQj5YsQ20A86Gy9fz8dky78raeZnhYayn0b1riSUKxGVnWja2i02OvAVM3tCCvXwcbSkHTRjuIAbMu2mXF1UpKci3i/GzPmbxo9n/3aX/jpR6UvxMZuaEDEij4yzfZv7EyK9WCNBXxMmtTp3Uv6MZsK+nopXO3C0xFzZA/zQObwP3zhJ4sdatzMhFi9GAM70R4kgMzsxQDNArueXj+UFzbCCFZ89zXs22F7Ixi0FyFTk3jhH56dBaN65S+gtPztNGzEUmtk4M8IanhQSw8xCXr0x0MPDpDFDZs3aN5TtTPYmyk3psk7OrmofCQGG5cRcqEt9902qtxQDOHumfuCPMvU+oMjzLzBVEDnBbj+tY3y1jvgGbmEJguAgfB04tSeAt/2618ksnJJK+dbBkDLxjB4xrFr3uIFFadJQWUckl5vfh4MVXbsFA1hG49lqWDa7uSuPCnOhv8Yql376I4U4gfcF8LcgorkxS+64urv2nMUq6AkBEMQ8bdkI64oKLFfO7fGxh5iMNZuLoutDn2ll3nq4rPi4kOyAtfhW0UPyjvqNtXJ/h0Wik5Mi8z7BVxaURTDk81TP8y9+tzjySB/uGfHFAzjF8DUY1vqJCgn0GQ8ANtiiElX/+Wnc9HWi2bEEXItbm4yv97QrEPvJG9nPRBKWGiAQsIA5J+WryX5NrfEfRPk0QQwyl16lpHlw6l0UMuk7S21xjQgyWo0MywfzoBWW7+t4HH9sqavvP4dYAw81BxXqVHQhefUOS23en4bFUPWE98pAN6bul+kS767vDK34yTC3lA2a8wLrBEilmFhdB74fxbAl+db91PivhwF/CR4Igxr35uLdof7+jAYyACopQzmsbHpvAAwT2lapLix8H03nztAC3fBqFSPBVdIv12lsrrDw4dfhJEzq7AbL/Y7L/nIcBsQ/3UyVnZk4kZP1KzyPCBLLIQNpCVgOLJzQuyaQ6k2QCBy0eJ0ppUyfp54LjwVg0X7bwncYbAomG4ZcFwTQnC2AX3oYG5n6Bz4SLLjxrFsY+v/SVa+GqH8uePBh1TPkHVNmzjXXymEf5jROlnd+EjfQdRyitkjPrg2HiQxxDcVhCh5J2L5+6CY9eIaYgrbd8zJnzAD8KnowHwh2bi4JLgmt7ktJ1XGizox7cWf3/Dod56KAcaIrSVw9XzYybdJCf0YRA6yrwPWXbwnzc/4+UDkmegi+AoCEMoue+cC7vnYVdmlbq/YLE/DWJX383oz2Ryq8anFrZ8jYvdoh8WI+dIugYL2SwRjmBoSwn56XIaot/QpMo3pYJIa4o8aZIZrjvB7BXO5aCDeMuZdUMT6AXGAGF1AeAWxFd2XIo1coR+OplMNDuYia8YAtnSTJ9JwGYWi2dJz3xrxsTQpBONf3yn8LVf8eH+o5eXc7lzCtHlDB+YyI8V9PyMsUPOeyvpB3rr9fDfNy263Zx33zTi5jldgP2OetUqGfbwl+0+zNYnrg64bluyIN/Awt1doDCQkCKpKXxuPaem/SyCHrKjg'
EndIf
Local $Symbol[] = ["jsmn_parse", "jsmn_init", "json_string_decode", "json_string_encode"]
Local $CodeBase = _BinaryCall_Create($Code)
If @error Then Exit MsgBox(16, "Json", "Startup Failure!")
$SymbolList = _BinaryCall_SymbolList($CodeBase, $Symbol)
If @error Then Exit MsgBox(16, "Json", "Startup Failure!")
EndIf
If $ProcName Then Return DllStructGetData($SymbolList, $ProcName)
EndFunc ;==>__Jsmn_RuntimeLoader
Func Json_StringEncode($String, $Option = 0)
Static $Json_StringEncode = __Jsmn_RuntimeLoader("json_string_encode")
Local $Length = StringLen($String) * 6 + 1
Local $Buffer = DllStructCreate("wchar[" & $Length & "]")
Local $Ret = DllCallAddress("int:cdecl", $Json_StringEncode, "wstr", $String, "ptr", DllStructGetPtr($Buffer), "uint", $Length, "int", $Option)
Return SetError($Ret[0], 0, DllStructGetData($Buffer, 1))
EndFunc ;==>Json_StringEncode
Func Json_StringDecode($String)
Static $Json_StringDecode = __Jsmn_RuntimeLoader("json_string_decode")
Local $Length = StringLen($String) + 1
Local $Buffer = DllStructCreate("wchar[" & $Length & "]")
Local $Ret = DllCallAddress("int:cdecl", $Json_StringDecode, "wstr", $String, "ptr", DllStructGetPtr($Buffer), "uint", $Length)
Return SetError($Ret[0], 0, DllStructGetData($Buffer, 1))
EndFunc ;==>Json_StringDecode
Func Json_Decode($Json, $InitTokenCount = 1000)
Static $Jsmn_Init = __Jsmn_RuntimeLoader("jsmn_init"), $Jsmn_Parse = __Jsmn_RuntimeLoader("jsmn_parse")
If $Json = "" Then $Json = '""'
Local $TokenList, $Ret
Local $Parser = DllStructCreate("uint pos;int toknext;int toksuper")
Do
DllCallAddress("none:cdecl", $Jsmn_Init, "ptr", DllStructGetPtr($Parser))
$TokenList = DllStructCreate("byte[" & ($InitTokenCount * 20) & "]")
$Ret = DllCallAddress("int:cdecl", $Jsmn_Parse, "ptr", DllStructGetPtr($Parser), "wstr", $Json, "ptr", DllStructGetPtr($TokenList), "uint", $InitTokenCount)
$InitTokenCount *= 2
Until $Ret[0] <> $JSMN_ERROR_NOMEM
Local $Next = 0
Return SetError($Ret[0], 0, _Json_Token($Json, DllStructGetPtr($TokenList), $Next))
EndFunc ;==>Json_Decode
Func _Json_Token(ByRef $Json, $Ptr, ByRef $Next)
If $Next = -1 Then Return Null
Local $Token = DllStructCreate("int;int;int;int", $Ptr + ($Next * 20))
Local $Type = DllStructGetData($Token, 1)
Local $Start = DllStructGetData($Token, 2)
Local $End = DllStructGetData($Token, 3)
Local $Size = DllStructGetData($Token, 4)
$Next += 1
If $Type = 0 And $Start = 0 And $End = 0 And $Size = 0 Then ; Null Item
$Next = -1
Return Null
EndIf
Switch $Type
Case 0 ; Json_PRIMITIVE
Local $Primitive = StringMid($Json, $Start + 1, $End - $Start)
Switch $Primitive
Case "true"
Return True
Case "false"
Return False
Case "null"
Return Null
Case Else
If StringRegExp($Primitive, "^[+\-0-9]") Then
Return Number($Primitive)
Else
Return Json_StringDecode($Primitive)
EndIf
EndSwitch
Case 1 ; Json_OBJECT
Local $Object = Json_ObjCreate()
For $i = 0 To $Size - 1 Step 2
Local $Key = _Json_Token($Json, $Ptr, $Next)
Local $Value = _Json_Token($Json, $Ptr, $Next)
If Not IsString($Key) Then $Key = Json_Encode($Key)
If $Object.Exists($Key) Then $Object.Remove($Key)
$Object.Add($Key, $Value)
Next
Return $Object
Case 2 ; Json_ARRAY
Local $Array[$Size]
For $i = 0 To $Size - 1
$Array[$i] = _Json_Token($Json, $Ptr, $Next)
Next
Return $Array
Case 3 ; Json_STRING
Return Json_StringDecode(StringMid($Json, $Start + 1, $End - $Start))
EndSwitch
EndFunc ;==>_Json_Token
Func Json_IsObject(ByRef $Object)
Return (IsObj($Object) And ObjName($Object) = "Dictionary")
EndFunc ;==>Json_IsObject
Func Json_IsNull(ByRef $Null)
Return IsKeyword($Null) Or (Not IsObj($Null) And VarGetType($Null) = "Object")
EndFunc ;==>Json_IsNull
Func Json_Encode_Compact($Data, $Option = 0)
Local $Json = ""
Select
Case IsString($Data)
Return '"' & Json_StringEncode($Data, $Option) & '"'
Case IsNumber($Data)
Return $Data
Case IsArray($Data) And UBound($Data, 0) = 1
$Json = "["
For $i = 0 To UBound($Data) - 1
$Json &= Json_Encode_Compact($Data[$i], $Option) & ","
Next
If StringRight($Json, 1) = "," Then $Json = StringTrimRight($Json, 1)
Return $Json & "]"
Case Json_IsObject($Data)
$Json = "{"
Local $Keys = $Data.Keys()
For $i = 0 To UBound($Keys) - 1
$Json &= '"' & Json_StringEncode($Keys[$i], $Option) & '":' & Json_Encode_Compact($Data.Item($Keys[$i]), $Option) & ","
Next
If StringRight($Json, 1) = "," Then $Json = StringTrimRight($Json, 1)
Return $Json & "}"
Case IsBool($Data)
Return StringLower($Data)
Case IsPtr($Data)
Return Number($Data)
Case IsBinary($Data)
Return '"' & Json_StringEncode(BinaryToString($Data, 4), $Option) & '"'
Case Else ; Keyword, DllStruct, Object
Return "null"
EndSelect
EndFunc ;==>Json_Encode_Compact
Func Json_Encode_Pretty($Data, $Option, $Indent, $ArraySep, $ObjectSep, $ColonSep, $ArrayCRLF = Default, $ObjectCRLF = Default, $NextIdent = "")
Local $ThisIdent = $NextIdent, $Json = "", $String = "", $Match = "", $Keys = ""
Local $Length = 0
Select
Case IsString($Data)
$String = Json_StringEncode($Data, $Option)
If BitAND($Option, $JSON_UNQUOTED_STRING) And Not BitAND($Option, $JSON_STRICT_PRINT) And Not StringRegExp($String, "[\s,:]") And Not StringRegExp($String, "^[+\-0-9]") Then
Return $String
Else
Return '"' & $String & '"'
EndIf
Case IsArray($Data) And UBound($Data, 0) = 1
If UBound($Data) = 0 Then Return "[]"
If IsKeyword($ArrayCRLF) Then
$ArrayCRLF = ""
$Match = StringRegExp($ArraySep, "[\r\n]+$", 3)
If IsArray($Match) Then $ArrayCRLF = $Match[0]
EndIf
If $ArrayCRLF Then $NextIdent &= $Indent
$Length = UBound($Data) - 1
For $i = 0 To $Length
If $ArrayCRLF Then $Json &= $NextIdent
$Json &= Json_Encode_Pretty($Data[$i], $Option, $Indent, $ArraySep, $ObjectSep, $ColonSep, $ArrayCRLF, $ObjectCRLF, $NextIdent)
If $i < $Length Then $Json &= $ArraySep
Next
If $ArrayCRLF Then Return "[" & $ArrayCRLF & $Json & $ArrayCRLF & $ThisIdent & "]"
Return "[" & $Json & "]"
Case Json_IsObject($Data)
If $Data.Count = 0 Then Return "{}"
If IsKeyword($ObjectCRLF) Then
$ObjectCRLF = ""
$Match = StringRegExp($ObjectSep, "[\r\n]+$", 3)
If IsArray($Match) Then $ObjectCRLF = $Match[0]
EndIf
If $ObjectCRLF Then $NextIdent &= $Indent
$Keys = $Data.Keys()
$Length = UBound($Keys) - 1
For $i = 0 To $Length
If $ObjectCRLF Then $Json &= $NextIdent
$Json &= Json_Encode_Pretty(String($Keys[$i]), $Option, $Indent, $ArraySep, $ObjectSep, $ColonSep) & $ColonSep _
& Json_Encode_Pretty($Data.Item($Keys[$i]), $Option, $Indent, $ArraySep, $ObjectSep, $ColonSep, $ArrayCRLF, $ObjectCRLF, $NextIdent)
If $i < $Length Then $Json &= $ObjectSep
Next
If $ObjectCRLF Then Return "{" & $ObjectCRLF & $Json & $ObjectCRLF & $ThisIdent & "}"
Return "{" & $Json & "}"
Case Else
Return Json_Encode_Compact($Data, $Option)
EndSelect
EndFunc ;==>Json_Encode_Pretty
Func Json_Encode($Data, $Option = 0, $Indent = Default, $ArraySep = Default, $ObjectSep = Default, $ColonSep = Default)
If BitAND($Option, $JSON_PRETTY_PRINT) Then
Local $Strict = BitAND($Option, $JSON_STRICT_PRINT)
If IsKeyword($Indent) Then
$Indent = @TAB
Else
$Indent = Json_StringDecode($Indent)
If StringRegExp($Indent, "[^\t ]") Then $Indent = @TAB
EndIf
If IsKeyword($ArraySep) Then
$ArraySep = "," & @CRLF
Else
$ArraySep = Json_StringDecode($ArraySep)
If $ArraySep = "" Or StringRegExp($ArraySep, "[^\s,]|,.*,") Or ($Strict And Not StringRegExp($ArraySep, ",")) Then $ArraySep = "," & @CRLF
EndIf
If IsKeyword($ObjectSep) Then
$ObjectSep = "," & @CRLF
Else
$ObjectSep = Json_StringDecode($ObjectSep)
If $ObjectSep = "" Or StringRegExp($ObjectSep, "[^\s,]|,.*,") Or ($Strict And Not StringRegExp($ObjectSep, ",")) Then $ObjectSep = "," & @CRLF
EndIf
If IsKeyword($ColonSep) Then
$ColonSep = ": "
Else
$ColonSep = Json_StringDecode($ColonSep)
If $ColonSep = "" Or StringRegExp($ColonSep, "[^\s,:]|[,:].*[,:]") Or ($Strict And (StringRegExp($ColonSep, ",") Or Not StringRegExp($ColonSep, ":"))) Then $ColonSep = ": "
EndIf
Return Json_Encode_Pretty($Data, $Option, $Indent, $ArraySep, $ObjectSep, $ColonSep)
ElseIf BitAND($Option, $JSON_UNQUOTED_STRING) Then
Return Json_Encode_Pretty($Data, $Option, "", ",", ",", ":")
Else
Return Json_Encode_Compact($Data, $Option)
EndIf
EndFunc ;==>Json_Encode
Func Json_ObjCreate()
Local $Object = ObjCreate('Scripting.Dictionary')
$Object.CompareMode = 0
Return $Object
EndFunc ;==>Json_ObjCreate
Func Json_ObjPut(ByRef $Object, $Key, $Value)
$Key = String($Key)
If $Object.Exists($Key) Then $Object.Remove($Key)
$Object.Add($Key, $Value)
EndFunc ;==>Json_ObjPut
Func Json_ObjGet(ByRef $Object, $Key)
Local $DynObject = $Object
Local $Keys = StringSplit($Key, ".")
For $x = 1 To $Keys[0]
If $DynObject.Exists($Keys[$x]) Then
If $x = $Keys[0] Then
Return $DynObject.Item($Keys[$x])
Else
$DynObject = Json_ObjGet($DynObject, $Keys[$x])
EndIf
EndIf
Next
Return SetError(1, 0, '')
EndFunc ;==>Json_ObjGet
Func Json_ObjDelete(ByRef $Object, $Key)
$Key = String($Key)
If $Object.Exists($Key) Then $Object.Remove($Key)
EndFunc ;==>Json_ObjDelete
Func Json_ObjExists(ByRef $Object, $Key)
Local $DynObject = $Object
Local $Keys = StringSplit($Key, ".")
For $x = 1 To $Keys[0]
If $DynObject.Exists($Keys[$x]) Then
If $x = $Keys[0] Then
Return True
Else
$DynObject = Json_ObjGet($DynObject, $Keys[$x])
EndIf
Else
Return False
EndIf
Next
Return False
EndFunc ;==>Json_ObjExists
Func Json_ObjGetCount(ByRef $Object)
Return $Object.Count
EndFunc ;==>Json_ObjGetCount
Func Json_ObjGetKeys(ByRef $Object)
Return $Object.Keys()
EndFunc ;==>Json_ObjGetKeys
Func Json_ObjGetItems(ByRef $Object)
Return $Object.Items()
EndFunc ;==>Json_ObjGetItems
Func Json_ObjClear(ByRef $Object)
Return $Object.RemoveAll()
EndFunc ;==>Json_ObjClear
; Both dot notation and square bracket notation can be supported
Func Json_Put(ByRef $Var, $Notation, $Data, $CheckExists = False)
Local $Ret = 0, $Item = "", $Error = 0
Local $Match = ""
$Match = StringRegExp($Notation, "(^\[([^\]]+)\])|(^\.([^\.\[]+))", 3)
If IsArray($Match) Then
Local $Index
If UBound($Match) = 4 Then
$Index = String(Json_Decode($Match[3])) ; only string using dot notation
$Notation = StringTrimLeft($Notation, StringLen($Match[2]))
Else
$Index = Json_Decode($Match[1])
$Notation = StringTrimLeft($Notation, StringLen($Match[0]))
EndIf
If IsString($Index) Then
If $CheckExists And (Not Json_IsObject($Var) Or Not Json_ObjExists($Var, $Index)) Then
Return SetError(1, 0, False) ; no specific object
EndIf
If Not Json_IsObject($Var) Then $Var = Json_ObjCreate()
If $Notation Then
$Item = Json_ObjGet($Var, $Index)
$Ret = Json_Put($Item, $Notation, $Data, $CheckExists)
$Error = @error
If Not $Error Then Json_ObjPut($Var, $Index, $Item)
Return SetError($Error, 0, $Ret)
Else
Json_ObjPut($Var, $Index, $Data)
Return True
EndIf
ElseIf IsInt($Index) Then
If $Index < 0 Or ($CheckExists And (Not IsArray($Var) Or UBound($Var, 0) <> 1 Or $Index >= UBound($Var))) Then
Return SetError(1, 0, False) ; no specific object
EndIf
If Not IsArray($Var) Or UBound($Var, 0) <> 1 Then
Dim $Var[$Index + 1]
ElseIf $Index >= UBound($Var) Then
ReDim $Var[$Index + 1]
EndIf
If $Notation Then
$Ret = Json_Put($Var[$Index], $Notation, $Data, $CheckExists)
Return SetError(@error, 0, $Ret)
Else
$Var[$Index] = $Data
Return True
EndIf
EndIf
EndIf
Return SetError(2, 0, False) ; invalid notation
EndFunc ;==>Json_Put
; Both dot notation and square bracket notation can be supported
Func Json_Get(ByRef $Var, $Notation)
Local $Match = StringRegExp($Notation, "(^\[([^\]]+)\])|(^\.([^\.\[]+))", 3)
If IsArray($Match) Then
Local $Index
If UBound($Match) = 4 Then
$Index = String(Json_Decode($Match[3])) ; only string using dot notation
$Notation = StringTrimLeft($Notation, StringLen($Match[2]))
Else
$Index = Json_Decode($Match[1])
$Notation = StringTrimLeft($Notation, StringLen($Match[0]))
EndIf
Local $Item
If IsString($Index) And Json_IsObject($Var) And Json_ObjExists($Var, $Index) Then
$Item = Json_ObjGet($Var, $Index)
ElseIf IsInt($Index) And IsArray($Var) And UBound($Var, 0) = 1 And $Index >= 0 And $Index < UBound($Var) Then
$Item = $Var[$Index]
Else
Return SetError(1, 0, "") ; no specific object
EndIf
If Not $Notation Then Return $Item
Local $Ret = Json_Get($Item, $Notation)
Return SetError(@error, 0, $Ret)
EndIf
Return SetError(2, 0, "") ; invalid notation
EndFunc ;==>Json_Get
; List all JSON keys and their value to the Console
Func Json_Dump($Json, $InitTokenCount = 1000)
Static $Jsmn_Init = __Jsmn_RuntimeLoader("jsmn_init"), $Jsmn_Parse = __Jsmn_RuntimeLoader("jsmn_parse")
If $Json = "" Then $Json = '""'
Local $TokenList, $Ret
$Total_JSON_DUMP_Output = "" ; reset totaldump variable at the start of the dump process (Use for testing)
Local $Parser = DllStructCreate("uint pos;int toknext;int toksuper")
Do
DllCallAddress("none:cdecl", $Jsmn_Init, "ptr", DllStructGetPtr($Parser))
$TokenList = DllStructCreate("byte[" & ($InitTokenCount * 20) & "]")
$Ret = DllCallAddress("int:cdecl", $Jsmn_Parse, "ptr", DllStructGetPtr($Parser), "wstr", $Json, "ptr", DllStructGetPtr($TokenList), "uint", $InitTokenCount)
$InitTokenCount *= 2
Until $Ret[0] <> $JSMN_ERROR_NOMEM
Local $Next = 0
_Json_TokenDump($Json, DllStructGetPtr($TokenList), $Next)
EndFunc ;==>Json_Dump
Func _Json_TokenDump(ByRef $Json, $Ptr, ByRef $Next, $ObjPath = "")
If $Next = -1 Then Return Null
Local $Token = DllStructCreate("int;int;int;int", $Ptr + ($Next * 20))
Local $Type = DllStructGetData($Token, 1)
Local $Start = DllStructGetData($Token, 2)
Local $End = DllStructGetData($Token, 3)
Local $Size = DllStructGetData($Token, 4)
Local $Value
$Next += 1
If $Type = 0 And $Start = 0 And $End = 0 And $Size = 0 Then ; Null Item
$Next = -1
Return Null
EndIf
Switch $Type
Case 0 ; Json_PRIMITIVE
Local $Primitive = StringMid($Json, $Start + 1, $End - $Start)
Switch $Primitive
Case "true"
Return "True"
Case "false"
Return "False"
Case "null"
Return "Null"
Case Else
If StringRegExp($Primitive, "^[+\-0-9]") Then
Return Number($Primitive)
Else
Return Json_StringDecode($Primitive)
EndIf
EndSwitch
Case 1 ; Json_OBJECT
For $i = 0 To $Size - 1 Step 2
Local $Key = _Json_TokenDump($Json, $Ptr, $Next)
Local $cObjPath = $ObjPath & "." & $Key
$Value = _Json_TokenDump($Json, $Ptr, $Next, $ObjPath & "." & $Key)
If Not (IsBool($Value) And $Value = False) Then
If Not IsString($Key) Then
$Key = Json_Encode($Key)
EndIf
; show the key and its value
ConsoleWrite("+-> " & $cObjPath & ' =' & $Value & @CRLF)
$Total_JSON_DUMP_Output &= "+-> " & $cObjPath & ' =' & $Value & @CRLF
EndIf
Next
Return False
Case 2 ; Json_ARRAY
Local $sObjPath = $ObjPath
For $i = 0 To $Size - 1
$sObjPath = $ObjPath & "[" & $i & "]"
$Value = _Json_TokenDump($Json, $Ptr, $Next, $sObjPath)
If Not (IsBool($Value) And $Value = False) Then ;XC - Changed line
; show the key and its value
ConsoleWrite("+=> " & $sObjPath & "=>" & $Value & @CRLF)
$Total_JSON_DUMP_Output &= "+=> " & $sObjPath & "=>" & $Value & @CRLF
EndIf
Next
$ObjPath = $sObjPath
Return False
Case 3 ; Json_STRING
Local $LastKey = Json_StringDecode(StringMid($Json, $Start + 1, $End - $Start))
Return $LastKey
EndSwitch
EndFunc ;==>_Json_TokenDump