Sign in to follow this  
Followers 0
Ascend4nt

Kernel Objects Information

21 posts in this topic




Excellent! Thanks for sharing mister.

...I did something similar few weeks ago when that thread about hotkeys was actual, to see if there would be any sign of hotkeys on this level. However, nothing as complete as your code. I wonder if your motivation was similar? That would be mighty cool.

Thanks again.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Insteresting. thanks for sharing  Ascend4nt. I've learned a lot from your codes.

Saludos

Share this post


Link to post
Share on other sites

trancexx, Actually I've had parts of the code laying around for years now.  I was intending to release something like this last year when I first showed Decipher a >function on getting Object names using a thread.  I've done a bit of work in C++ with multithreading using Semaphores and Mutexes, which gave me the need to query those objects too. Why MS never 'officially' exposed these non-mutating query API's (NtQueryMutant, NtQuerySemaphore, etc), I'll never know.. they are pretty important tools for debugging.

Additionally, I've also seen a few random people asking about handles, files, and other system objects that made me think it might be worth something to someone to release this.

As an unexpected result of this, I've also been able to see why certain processes are eating thousands of handles, sometimes for no good reason (khalmnpr.exe - you dirty little slut).

Ah, but back to that HotKeys thread.. that actually did get me digging, but instead of finding an answer, I went and released that '>Atom Tables' UDF a month or so ago, as some hotkey strings are occasionally stored there.

Man, I dunno about you.. but with this project, I'm pretty much done with the Undocumented Windows world. haha

With the Processes and Threads, Atom Tables, multi-CPU Usage and other UDF's I've released, I think I've had my fill.

Share this post


Link to post
Share on other sites

Insteresting. thanks for sharing  Ascend4nt. I've learned a lot from your codes.

Glad to hear it!

Btw, I'd like to hear if the Registry keys, File paths, and NamedPipes/Mailslots etc are being detected properly. (excluding those reporting negative values in the 'ExInfo' column)

Also, hmm.. it appears when running from Scite, querying one of the 'AutoIt3Wrapper' processes fails for certain File types, probably NamedPipes.. the thread querying these doesn't even terminate properly.  I may have to force protection for that specific attribute even on Windows 7

Share this post


Link to post
Share on other sites

This is my output running as admin in windows 7 Home Basic x86

Handles Info.txt

Typemapping.txt

Saludos

Share this post


Link to post
Share on other sites

JScript: thanks for the compliment

DanyfireX, much appreciated! Are you running a Spanish (or otherwise) language version of the O/S?

Share this post


Link to post
Share on other sites

Spanish language.

Saludos

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Nice work :)

I recently been trying to work my way through calling process handles and I was trying to get the path name.

here is output of the self inspect (win 7 64 bit, ran with admin rights and has 64 bit)

Once I get a bit more time, I am going to dig through your code and see what I can learn.

 

 

autoit.xlsx

Edited by step887

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Very cool, thank you for sharing Ascend4nt :)

Edited by MikahS

Snips & Scripts


My Snips: graphCPUTemp ~ getENVvars
My Scripts: Short-Order Encrypter - message and file encryption V1.6.1 ~ AuPad - Notepad written entirely in AutoIt V1.9.4

Feel free to use any of my code for your own use.                                                                                                                                                           Forum FAQ

 

Share this post


Link to post
Share on other sites
here is output of the self inspect (win 7 64 bit, ran with admin rights and has 64 bit)

step887, thanks for the output. I'm curious why HKEY_CURENT_USER isn't being detected for you properly.  The line that reads "HKEY_USERSS-1-5-21...Software" should be converted, so I'm assuming the call to _Security__LookupAccountName() isn't returning the proper SID for you.  Just out of curiosity, try running this and see if the SID matches the one used in that line:

#include <Security.au3>
ConsoleWrite("SID = " & _Security__LookupAccountName(@UserName)[0] & @CRLF)

But anyway, I'm releasing a new version of the UDF shortly which uses a different method of getting the SID, so we'll see if that one works for you

Share this post


Link to post
Share on other sites
#include <Security.au3>
ConsoleWrite("SID = " & _Security__LookupAccountName(@UserName)[0] & @CRLF)

SID = S-1-5-21-3849832183-2284427975-4186142399-1001

Share this post


Link to post
Share on other sites

SID = S-1-5-21.xxx

That's very odd.  Well, give the new UDF a try and see what the output is!

 

Update:

2014-09-26:

Added: Multiple processes and/or types allowed in filters, plus exclusion flag

Changed: NTKernelObjectsInspect example now allows multiple filters and/or processes

         Also, Object totals are displayed where possible (elevated rights necessary for some processes)

Added: $NTOBJ_QUERYBY_PROCESSNAME Filter -> Must be used with processes as names

Improved: DLL Handles used for DLLCalls()

       Note that the biggest time-sink is still the API call NtQuerySystemInformation

       which grabs ALL system handles in one fell swoop (used inside _NTObjGetHandlesUD)

Added: Internal functions which rely on DLLHandles for speed improvements

Added: $g_NTKO_bNamedPipeProtect which can be toggled to prevent certain attributes

       from being scanned when "File" types are found. This is toggled ON for XP/2003 and under,

       OFF for Vista+

Added: $g_NTKO_sFileAttribSkipList -> assign additional Skip-Attributes with this if desired

Added: 'BadMasks' check in collection function which flags certain Attributes which have

       previously caused Thread timeouts. Use $g_NTKO_bSkipBadMasks to toggle this OFF (ON by default)

Changed: HKCU detection relies on a different technique than _Security__LookupAccountName() to get SID

Added: Smaller simpler example (NTKernelObjectsCollectExample)

Misc: Other misc. changes, additions, fixes which shouldn't affect UDF usage

Share this post


Link to post
Share on other sites

Here is the output of NTKernelObjectsSelfExamine.au3

Share this post


Link to post
Share on other sites

Here is the output of NTKernelObjectsSelfExamine.au3

I hope that was a mistake? lol

Share this post


Link to post
Share on other sites

Update: I was thankfully wrong about the 64K limit on system object handles.  There's actually a really high limit - 16,777,216 - and its not actually O/S-wide, but Process-specific (which gives quite a lot of legroom).  The unfortunate problem that creates is that 16+million is more than what would fit in a 16-bit variable.  The NtQuerySystemInformation API call which is used to gather information on handles returns an array of SYSTEM_HANDLE_INFORMATION structures, and those structures limit handle values to 16-bits.  This amount is okay when a Process's handles are never in excess of 16-bits, but for values above this (65,536+), the upper bits are lost, and the handle value then indexes other handles, which can create a mess of confusion. Fortunately, this shouldn't be a problem with most processes, as anything more than a few thousand handles for one process is highly unlikely (and probably a sign of a buggy program).

Another important thing to note is that each handle # is process-specific. So even if there are 7,000 handles for 100 processes, the API call will still return the correct results, as each handle # is unique only to the process to which it belongs. This also means that handle # 4 in one process is something completely different in another process.

Also important to note: handle values (or handle-table indexes) are each offset by 4, so approximately 64K/4, or 16K handles can be consumed by a process before it surpasses 16-bits. The example below shows this.  Use NTKernelObjectsInspect to compare handle values to see where the 'wraparound' happens just after 0xFFFC.

For information on system handles, check out Mark Russinovich's excellent blogs, specifically "Pushing the Limits of Windows: Handles"

#include <WinAPI.au3>
#include <Array.au3>

; Handle values (indexes into handle tables) are offset 4 bytes from each other, so aroune 16K handles
; would be the max representable in 16-bits. (There are already handles at this point, so this will
; indeed cause 17+ bits to be used)
Local $aHandles = _HandleGenerate(65536 / 4)
;MsgBox(0, "Handles Generated", "Generated handles = " & UBound($aHandles))
_ArrayDisplay($aHandles, "Handles Generated")

Func _HandleGenerate($iMax)
    ; Limit of 4999999 is much less than the real max (16 million+)
    If $iMax < 0 Or $iMax > 4999999 Then Return SetError(1, 0, 0)

    Local $hEvent, $aHandles[$iMax]

    $hEvent = _WinAPI_CreateEvent(0, True, True, "_EVENTOBJ_")
    If @error Or $hEvent = 0 Then Return SetError(-1, @error, 0)
    ConsoleWrite("Event Handle for '_EVENTOBJ' = " & $hEvent& @CRLF)

    $aHandles[0] = $hEvent

    For $i = 1 To $iMax - 1
        ; DUPLICATE_SAME_ACCESS (2)
        $aHandles[$i] = _WinAPI_DuplicateHandle(Ptr(-1), $hEvent, Ptr(-1), 0, 0, 2)
        If @error Or $aHandles[$i] = 0 Then
            SetError(-1, @error, 0)
            ExitLoop
        EndIf
    Next
    If @error Then
        If $aHandles[$i] = 0 Then
            ReDim $aHandles[$i - 1]
        EndIf
        Return SetError(2, @extended, $aHandles)
    EndIf
    Return $aHandles
EndFunc

Share this post


Link to post
Share on other sites

I hope that was a mistake? lol

it was uploaded the file but forgot to attach

autoit.xlsx

1 person likes this

Share this post


Link to post
Share on other sites

step887, much appreciated. It looks to be working as it should.  I'd recommend deleting or obfuscating the S-1-5-21-xxx SIDs, as I'm not sure if that info can be used for malicious purposes

Share this post


Link to post
Share on other sites

Never one to be satisfied with edge cases, I took the initative to properly fool-proof this beast against processes with 16K+ handles. Yup, now the truncated bits of handles are properly restored using simple wraparound detection. Enjoy!

Update 2014-10-01:

Fixed: _NTObjGetHandlesUD() was failing to return an error code if $FilterBy was 0, resulting in empty arras
Improved: _NTObjGetHandlesUD() now tracks & calculates internally what handle values are beyond 65,536
Added: NTKernelObjectSpam (simple test of creating tons of Kernel Objects)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • kingjacob90
      By kingjacob90
      HI
      I am wanting to know what my CPU temp is but don't know what object to use. I don't relay know how objget works so would not know where to start. I have seen people integrate things like windows speech to text into their scripts but don't know how they know what object to use! How do I find the right object? And how dose it work?
       
      Thanks Jacob
    • RaiNote
      By RaiNote
      Hi,
      How to work easily and fast with the oleview.exe which Displays the Object COM from Windows and other programs~
    • Keithw
      By Keithw
      I'm trying to create a remote object using the example script on the ObjCreate function reference page:
      #include <MsgBoxConstants.au3> ;Open the MediaPlayer ona REMOTE computer Local $oRemoteMedia = ObjCreate("WMPlayer.OCX", "W2RATD5NGK32", "W2RATD5NGK32\administrator", "Win7Pilot") If Not @error Then MsgBox($MB_SYSTEMMODAL, "Remote ObjCreate Test", "ObjCreate() of a remote Mediaplayer Object successful !") $oRemoteMedia.openPlayer(@WindowsDir & "\media\tada.wav") ; Play sound if file is present Else MsgBox($MB_SYSTEMMODAL, "Remote ObjCreate Test", "Failed to open remote Object. Error code: " & Hex(@error, 8)) EndIf The message returns:  Failed to open remote Object.  Error Code:  80004002 
       
      I've tried researching this error but haven't found any useful info.  All I know are these requirements below and I know for sure that the services are running, and the script is being executed as x64 with admin rights.
      I'm now at a dead end and not sure how to further troubleshoot this error.  Also, the script runs fine when I use my own hostname.  Any ideas? 
    • Rickname
      By Rickname
      Hi,
      First , I don't know nothing about COM and I saw this script :
      #include <MsgBoxConstants.au3> Example() Func Example() ; Error monitoring. This will trap all COM errors while alive. ; This particular object is declared as local, meaning after the function returns it will not exist. Local $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc") ; Create Internet Explorer object Local $oIE = ObjCreate("InternetExplorer.Application") ; Check for errors If @error Then Return $oIE.Visible = True ; set visibility ; Custom sink object Local $oIEEvents = ObjEvent($oIE, "_IEEvent_", "DWebBrowserEvents2") ; Navigate somewhere $oIE.navigate("http://www.google.com/") ; Check for errors while loading If @error Then $oIE.Quit() Return EndIf ; Wait for page to load While 1 If $oIE.readyState = "complete" Or $oIE.readyState = 4 Then ExitLoop Sleep(10) WEnd EndFunc ... Now I want to know how can I find & list ALL those possible "functions" of a specific COM object ( those .Visible, .navigate, .readyState ... ), since I can't find those things nowhere listed 
    • MarkRobbins
      By MarkRobbins
      I've been thinking about this for the last couple of weeks, and I've finally got around to putting together a proof of concept.
      As far as OOP goes, Javascript is a pretty damn good language -- very flexible, but lets look at some code. Here is a two button form for AutoIt written in Javascript.
      var $=this; var hgui; this.MsgHandler_=function (m){ if (m==$.AutoIt.GUI_EVENT_CLOSE) { $.AutoIt.GUIDelete(hgui); return true; }else if (m==button1) { $.AutoIt.Run("notepad.exe"); }else if (m==button2) { alert('Thanks from a javascript alert box!'); } return false; } var button1,button2; function Example1(){ var msg; hgui=$.AutoIt.GUICreate("My Gui",400,500); button1=$.AutoIt.GUICreateButton("Run Notepad",10,10,200,30); button2=$.AutoIt.GUICreateButton("Press Me",10,40,200,30); $.AutoIt.GUISetState($.AutoIt.SW_SHOW,hgui); } Example1(); This code would reside in an external file and be called by AutoIt.
      I've created a framework in AutoIt using AutoItObject that is just big enough to make this code work.
      Basically I am creating an AutoItObject, tacking on some core AutoIt functions and constants, and sending it off to play in Javascript land. There is much more to be tacked on.
      Other than this AutoItObject being a proxy for AutoIt functionality, there is a Javascript COM object into which the javascript file is loaded, and a message loop that calls back into the javascript.
      The framework is 300 lines of code.
      Before I extend this, I want to know if AutoIt ALREADY has a COM object I that I can use like this. But I am thinking that even if it does, this hand-coded way would be better because you can make the calls pass objects instead of parameters.
      Here is the framework:
      #include <AutoItObject.au3> #include <GUIConstants.au3> Global $thisfile=@ScriptFullPath; Global $logg=$thisfile&".log.txt"; Global $jsfile=$thisfile&".js"; ;e C:\batch\borg\TestJsaio.au3.js ;fret not, you do not need, will be a no-op if not exist Global Const $snarl="C:\batch\Snarl_CMD.exe"; ; need script exit for AIO shutdown OnAutoItExitRegister("EvtScriptExit") _AutoItObject_StartUp() ; error handler Global $oError $oError = ObjEvent("AutoIt.Error", "_ErrFunc") ; JScript Com globals Global $_ComObj_proxy Global $_com Global $_Js JScriptInit() ;;;;;;;;;;;;;;;;;;;;;;;;;;done inits ;;;;;;;;;;; begin framework ; set up a mini framework of AutoIt Functions/constants and stick them on an object Global $AutoItForCom=_AutoItObject_Create(); ;_AutoItObject_AddMethod(ByRef $oObject, $sName, $sAutoItFunc, $fPrivate = False) _AutoItObject_AddMethod($AutoItForCom,"GUICreate","GUICreate_AI") _AutoItObject_AddMethod($AutoItForCom,"GUISetState","GUISetState_AI") _AutoItObject_AddMethod($AutoItForCom,"GUIGetMsg","GUIGetMsg_AI") _AutoItObject_AddMethod($AutoItForCom,"GUIDelete","GUIDelete_AI") _AutoItObject_AddMethod($AutoItForCom,"MsgBox","MsgBox_AI") _AutoItObject_AddMethod($AutoItForCom,"GuiCreateButton","GuiCreateButton_AI") _AutoItObject_AddMethod($AutoItForCom,"Run","Run_AI") ;_AutoItObject_AddProperty(ByRef $oObject, $sName, $iFlags = $ELSCOPE_PUBLIC, $vData = "") _AutoItObject_AddProperty($AutoItForCom, "SW_SHOW", $ELSCOPE_PUBLIC+$ELSCOPE_READONLY, @SW_SHOW) _AutoItObject_AddProperty($AutoItForCom, "GUI_EVENT_CLOSE", $ELSCOPE_PUBLIC+$ELSCOPE_READONLY, $GUI_EVENT_CLOSE) ;;; here are the tie-ins that the object will call Func GUICreate_AI($me,$title,$width,$height) #forceref $me ;GUICreate ( "title" [, width [, height [, left [, top [, style [, exStyle [, parent]]]]]]] ) Local $rv=GUICreate($title,$width,$height) Return $rv EndFunc Func GUISetState_AI($me,$flag,$hwnd) #forceref $me ;GUISetState ( [flag [, winhandle]] ) Local $rv=GUISetState($flag,HWnd($hwnd));need to covert Int32 Return $rv EndFunc Func GUIGetMsg_AI($me,$advanced) #forceref $me Local $rv= GUIGetMsg ($advanced) Return $rv EndFunc Func GUIDelete_AI($me,$winhandle) #forceref $me Local $rv=GUIDelete($winhandle) Return $rv EndFunc Func MsgBox_AI($me,$flag,$title,$text) #forceref $me ;MsgBox ( flag, "title", "text" [, timeout [, hwnd]] ) Local $rv=MsgBox($flag,$title,$text) Return $rv EndFunc Func GUICreateButton_AI($me,$text,$left,$top,$width=Default,$height=Default,$style=Default,$exstyle=Default) #forceref $me ;GUICtrlCreateButton ( "text", left, top [, width [, height [, style [, exStyle]]]] ) Local $rv=GUICtrlCreateButton ( $text, $left, $top, $width, $height, $style, $exstyle) Return $rv EndFunc Func Run_AI($me,$program,$wkdir=Default,$show_flag=Default,$opt_flag=Default) #forceref $me ;Msg2("run",$program) Local $rv; If False Then ElseIf @NumParams==2 Then $rv=Run($program) ElseIf @NumParams==3 Then $rv=Run($program,$wkdir) ElseIf @NumParams==4 Then $rv=Run($program,$wkdir,$show_flag) ElseIf @NumParams==5 Then $rv=Run($program,$wkdir,$show_flag,$opt_flag) EndIf ;Run ( "program" [, "workingdir" [, show_flag [, opt_flag]]] ) ;Local $rv=Run($program,$wkdir,$show_flag,$opt_flag) Return $rv EndFunc ;;;;;;;;;;;;;;;; end of tie-ins ;;;;;;;;;; setup JScript COM obj Global $jso=NewComObj() ; import our AutoIt Proxy into the jso $jso.set("AutoIt", $AutoItForCom) ; read our javascript file Global $ftext=FileRead($jsfile) ; set the file text up as a Main function $jso.set_function("Main", "", $ftext) ; need to run our message loop in autoit code, but pass it back to JS land here $jso.set_function("MsgHandler", "m", "return eval('this.MsgHandler_(m)');") ; hold on to your britches... ; this call will run through the js file and the file must do a setup and have a callback MsgHandler_ $jso.Main() ;; Message Loop Local $end_if_true Local $m While True $m=GUIGetMsg(0) $end_if_true=$jso.MsgHandler($m) ;Msg($end_if_true); If $end_if_true Then ExitLoop EndIf WEnd Exit ;; the only thing worth looking at below this point is the _ComObj_init and friends ;;;;;;;;;;;;;;;functions Func EvtScriptExit() ;Msg("EvtScriptExit") _AutoItObject_Shutdown() ;_logline('EvtScriptExit') ;If IsObj($MidiMgr) Then ; $MidiMgr.Terminate() ;EndIf EndFunc Func Msg($s) MsgBox(0,$thisfile,$s) EndFunc Func Msg2($t,$s) MsgBox(0,$t,$s) EndFunc Func logclear() FileDelete($logg) EndFunc Func _logline($line) logline($line) EndFunc Func logline($line) Local $fh1=FileOpen($logg,1); If $fh1<>-1 Then FileWriteLine($fh1,$line) FileClose($fh1) EndIf EndFunc Func logsnarl($line) logerr($line) snarl(10,'Fatal Error',$line) EndFunc Func snarl($i,$t,$s) If Not FileExists($snarl) Then Return EndIf $s1=StringReplace($s,'"',"'") $t1=StringReplace($t,'"',"'") $cmd=$snarl&' snShowMessage '&$i&' "'&$t1&'" "'&$s1&'"'; Run($cmd) EndFunc ;;;;js utils ; #FUNCTION# ================================================================== ; Name : _ComObj_init ; Description : Creates MS Windows Script control and deploy it as proxy for ; AutoIt COM object binding. ; Syntax : _ComObj_init([$VBScriptSupport = false]) ; Parameter : $VBScriptSupport ; By default JScript doesn't have alert() function, it is provided ; by browser's window object. ; We can emulate this using VBScript's MsgBox function, which is ; performance hog because we need another ScriptControl instance. ; Other advantage is to be able to execute other VBScript's methods ; within function via vb.Eval() method. ; This feature is disabled by default. ; ============================================================================= Func _ComObj_init ($VBScriptSupport = false) Local $_Script $_Script = ObjCreate("ScriptControl") $_Script.Language = "JScript" $_Script.Timeout = 60000 ;$_Script.AddCode("var $=this,arrays=[],vb;function set_vbscript($) {vb=$;vb.Language='VBScript';vb.AllowUI=true;}function alert(s){if(vb)vb.Eval('MsgBox(Unescape(""'+s+'""), 0, ""Autoit"")')}function get_proxy(){return $}function new_object($){$=new Function('return{'+$+'}')();$.set=function(k, v){$[k]=v};$.unset=function(k){delete $[k]};$.set_object=function(k,$){this.set(k,new_object($))};$.set_array=function(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];$.set(v.shift(),new_array.apply(this,v))};$.set_function=function(k,p,$){this.set(k,new_function(p,$))};return $}function new_array(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];return v}function array_get($,k){return $[k]}function array_set($,k,v){return $[k]=v}var new_function=(function(){function F(r) {return Function.apply(this,r)}F.prototype = Function.prototype;return function(p,$){p=p.split(/\s*,\s*/);p.push($);return new F(p)}})()") ;a[a.length]=i; ;function new_array(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];return v} Local $more= _ "$.get=function(k){return $[k]};" & _ "$.has=function(n){" & _ " for (var i in this){" & _ " if (i!=n){" & _ " continue;" & _ " }" & _ " if (!this.hasOwnProperty(i)){" & _ " continue;" & _ " }" & _ " if (typeof(this[i])=='function'){" & _ " continue;" & _ " }" & _ " return true;" & _ " };" & _ " return false;" & _ "};" & _ "$.keys=function(){" & _ " var a=[];" & _ " for (var i in this){" & _ " if (this.hasOwnProperty(i)){" & _ " if (typeof(this[i])!='function'){" & _ " a[a.length]=i;" & _ " }" & _ " }" & _ " };" & _ " return a;" & _ "};" & _ "$.set2=function(){" & _ " for(var x=0;x<arguments.length-1;x+=2){" & _ " this[arguments[x]]=arguments[x+1]" & _ " }" & _ "};" & _ "Array.prototype.item=function(n){" & _ " return this[n];" & _ "};" & _ "Array.prototype.has=function(v){" & _ " for(x=0;x<this.length;x++){" & _ " if(this[x]==v){return true;}" & _ " }" & _ " return false;" & _ "};" & _ "Array.prototype.asString=function(d){" & _ " var s='';" & _ " for(x=0;x<this.length;x++){" & _ " if(s==''){s=this[x];}else{s+=d+this[x];}" & _ " }" & _ " return s;" & _ "};" $_Script.AddCode("var $=this,arrays=[],vb;function set_vbscript($) {vb=$;vb.Language='VBScript';vb.AllowUI=true;}function alert(s){if(vb)vb.Eval('MsgBox(Unescape(""'+s+'""), 0, ""Autoit"")')}function get_proxy(){return $}function new_object($){$=new Function('return{'+$+'}')();$.set=function(k, v){$[k]=v};"&$more&"$.unset=function(k){delete $[k]};$.set_object=function(k,$){this.set(k,new_object($))};$.set_array=function(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];$.set(v.shift(),new_array.apply(this,v))};$.set_function=function(k,p,$){this.set(k,new_function(p,$))};return $}function new_array(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];return v}function array_get($,k){return $[k]}function array_set($,k,v){return $[k]=v}var new_function=(function(){function F(r) {return Function.apply(this,r)}F.prototype = Function.prototype;return function(p,$){p=p.split(/\s*,\s*/);p.push($);return new F(p)}})()") If $VBScriptSupport = true Then $_Script.Run("set_vbscript", ObjCreate("ScriptControl")) Return $_Script EndFunc ; ============================================================================= Func NewComObj() Local $com While True $com=$_com.new_object("") Sleep(30) If IsObj($com) Then ExitLoop EndIf WEnd Sleep(30) Return $com EndFunc Func JScriptInit() $_ComObj_proxy = _ComObj_init(true) $_com = $_ComObj_proxy.Run("get_proxy") $_Js = $_com.new_object("") $_Js.set_function("AIOSetProperty","o,n,v","o[n]=v;") EndFunc Func JS_SetProp() $_Js = $_com.new_object("") $_Js.set_function("AIOSetProperty","o,n,v","o[n]=v;") Return $_Js; EndFunc My main questions are...
      Why doesn't this already exist, and where is it? and... Why doesn't this already exist -- what wall am I headed for?