Jump to content

francoiste

Active Members
  • Posts

    79
  • Joined

  • Last visited

Everything posted by francoiste

  1. that's "UAC Virtualization" available on windows OS. intended to make old crappy software (that doesn't care about restricted permissions) still work. it may kick in for certain folders in the file system and locations in the registry. this feature can lead to many problems. especially on multi-user environments. i strongly recommend to turn that feature OFF: [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System] "EnableVirtualization"=dword:00000000 the above registry switch does not disable UAC. it disables the "virtualization fake" (the file and registry redirection to some personal VirtualStore), only.
  2. in AutoIt we have: _WinAPI_IsProcessorFeaturePresent($iFeature) this internally just calls what is provided by microsoft: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724482(v=vs.85).aspx unfortunately this is completely outdated as we can only check for features like MMX and up to a maximum of SSE2 or SSE3 - which have been introduced back in 2001 / 2004. but nowadays there is stuff like AVX, AVX2, AVX-512 ... for example see: https://en.wikipedia.org/wiki/Template:Multimedia_extensions well, for CPP we have the FeatureDetector (by Mysticial): https://github.com/Mysticial/FeatureDetector it calls __cpuid / __cpuidex from <intrin.h>. for additional details see: https://msdn.microsoft.com/en-us/library/hskdteyh.aspx has anyone tried to determine such SIMD features and related CPU capabilites with AutoIt?
  3. proposed fix (to check the actual StringLength): #include <array.au3> ; Needed to display array in example. #include <security.au3> ; Get OWNER from SID. $tag_WTS_PROCESS_INFO = _ "DWORD SessionId;" & _ "DWORD ProcessId;" & _ "PTR pProcessName;" & _ "PTR pUserSid" ; ############ Example code ####################### MsgBox(0, "Process by name or number(PID)", "'Owner' of Explorer.exe is " & _ProcessListOWNER_WTS("Explorer.exe")) $temp = _ProcessListOWNER_WTS() $temp[0][0] = "Process" $temp[0][1] = "ProcessId" $temp[0][2] = "SessionId" $temp[0][3] = "ProcessOWNER" _ArrayDisplay($temp, "Process list with OWNER...") ; ############################################### ; ############ Here be func! #################### Func _ProcessListOWNER_WTS($PID = 0) Local $i, $ret, $ret1, $mem $ret = DllCall("WTSApi32.dll", "int", "WTSEnumerateProcessesW", "int", 0, "int", 0, "int", 1, "ptr*", 0, "int*", 0) Local $array[$ret[5]][4] $mem = DllStructCreate($tag_WTS_PROCESS_INFO, $ret[4]) For $i = 0 To $ret[5] - 1 $mem = DllStructCreate($tag_WTS_PROCESS_INFO, $ret[4] + ($i * DllStructGetSize($mem))) ;if DllStructGetData($mem, "pProcessName") Then Local $pData = DllStructGetData($mem, "pProcessName") Local $iStringLen = _PtrStringLenW($pData) Local $pName = DllStructCreate("wchar[" & $iStringLen + 1 & "]", $pData) $array[$i][0] = DllStructGetData($pName, 1) ;EndIf $array[$i][1] = DllStructGetData($mem, "ProcessId") $array[$i][2] = DllStructGetData($mem, "SessionId") ;if DllStructGetData($mem, "pUserSid") Then $ret1 = _Security__LookupAccountSid(DllStructGetData($mem, "pUserSid")) If IsArray($ret1) Then $array[$i][3] = $ret1[0] ;EndIf Next DllCall("WTSApi32.dll", "int", "WTSFreeMemory", "int", $ret[4]) If $PID Then If IsInt($PID) Then For $i = 0 To UBound($array, 1) - 1 If $array[$i][1] = $PID Then Return $array[$i][3] EndIf Next Else For $i = 0 To UBound($array, 1) - 1 If $array[$i][0] = $PID Then Return $array[$i][3] EndIf Next EndIf EndIf Return $array EndFunc ;==>_ProcessListOWNER_WTS ;################################ END FUNC ########################################## Func _PtrStringLenW($pString) Local $aCall = DllCall("kernel32.dll", "dword", "lstrlenW", "ptr", $pString) If @error Then Return SetError(1, 0, 0) Return $aCall[0] EndFunc ;==>_PtrStringLenW
  4. thank you very much! after some more searching i have found a solution in this other thread: i'm now running the following: ;***************************************** ;# returns an array: ProcessName | ProcessID | SessionID | ProcessOwner Func _GetProcessList() ;# ... $aRet = DllCall("WTSApi32.dll", "int", "WTSEnumerateProcessesW", "int", $WTS_CURRENT_SERVER_HANDLE, "int", 0, "int", 1, "ptr*", 0, "int*", 0) ;# <==== changed to WIDE ;# ... Local $array[$aRet[5]][4] Local $mem = DllStructCreate($tagWTS_PROCESS_INFO, $aRet[4]) For $i = 0 To $aRet[5] - 1 ;# ... Local $ret2 = DllStructGetData($mem, "pProcessName") Local $iStringLen = _PtrStringLenW($ret2) ;# <==== NEW Local $ret3 = DllStructCreate("wchar[" & $iStringLen + 1 & "]", $ret2) ;# <==== FIXED (wide and stringlen) Local $string = "" & DllStructGetData($ret3, 1) & "" ;# <==== here it used to crash $array[$i][0] = $string ;# ... Next ;# ... EndFunc ;==>_GetProcessList Func _PtrStringLenW($pString) Local $aCall = DllCall("kernel32.dll", "dword", "lstrlenW", "ptr", $pString) If @error Then Return SetError(1, 0, 0) Return $aCall[0] EndFunc ;==>_PtrStringLenW Func _PtrStringLen($pString) Local $aCall = DllCall("kernel32.dll", "dword", "lstrlen", "ptr", $pString) If @error Then Return SetError(1, 0, 0) Return $aCall[0] EndFunc ;==>_PtrStringLen
  5. i'm still suffering from those sporadic crashes. i took a look at the minidump file created by windows, but could not find anything helpful so far. see the attached screenshot.
  6. i have spawned a follow-up question in: https://www.autoitscript.com/forum/topic/192333-crash-in-dllstructgetdata/
  7. this is a follow-up to i sporadically and very rarely get an access violation exception. here is some simplyfied repro code: #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Change2CUI=y #AutoIt3Wrapper_Run_Tidy=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** #include-once #include <Array.au3> #include <security.au3> ;~ #include "ESC_Globals.au3" Global Const $WTS_CURRENT_SESSION = -1 Global Const $WTS_CURRENT_SERVER_HANDLE = 0 Global Const $WTS_CLIENTPROTOCOLTYPE = 16 Global Const $WTS_CONNECTSTATE = 8 Global Const $WTS_USERNAME = 5 Global Const $tagWTS_SESSION_INFO = _ "dword SessionId;" & _ "ptr WinStationName;" & _ "uint State" Global Const $tagWTS_PROCESS_INFO = _ "DWORD SessionId;" & _ "DWORD ProcessId;" & _ "PTR pProcessName;" & _ "PTR pUserSid" For $i = 0 To 1000 * 20 ConsoleWrite("iteration " & $i & @CRLF) _GetProcessList() Sleep(1000) Next MsgBox(0, "COMPLETED", "everything done") ;***************************************** ;# returns an array: ProcessName | ProcessID | SessionID | ProcessOwner Func _GetProcessList() Local $i, $aRet ConsoleWrite("_GetProcessList() --> " & @AutoItPID & @CRLF) Local $aProcessList = ProcessList() $aRet = DllCall("WTSApi32.dll", "int", "WTSEnumerateProcesses", "int", $WTS_CURRENT_SERVER_HANDLE, "int", 0, "int", 1, "ptr*", 0, "int*", 0) If @error Or ($aRet[0] == 0) Then MsgBox(4096 + 48, "Error", "Failed invoking WTSEnumerateProcesses") Return (SetError(1, 0, -1)) EndIf Local $array[$aRet[5]][4] Local $mem = DllStructCreate($tagWTS_PROCESS_INFO, $aRet[4]) For $i = 0 To $aRet[5] - 1 ConsoleWrite("IT: " & $i) ;# DEBUG $mem = DllStructCreate($tagWTS_PROCESS_INFO, $aRet[4] + ($i * DllStructGetSize($mem))) ConsoleWrite(" - PID: ") ;# DEBUG $array[$i][1] = Int(DllStructGetData($mem, "ProcessId"), 1) ;# convert to Int32 ConsoleWrite($array[$i][1]) ;# DEBUG ConsoleWrite("; SID: ") ;# DEBUG $array[$i][2] = Int(DllStructGetData($mem, "SessionId"), 1) ;# convert to Int32 ConsoleWrite($array[$i][2]) ;# DEBUG Local $name1 = "???" For $j = 1 To $aProcessList[0][0] If $aProcessList[$j][1] == $array[$i][1] Then $name1 = $aProcessList[$j][0] ExitLoop EndIf Next ConsoleWrite("; NAME1: " & $name1) ;# DEBUG ConsoleWrite("; NAM") ;# DEBUG Local $ret2 = DllStructGetData($mem, "pProcessName") ConsoleWrite("E") ;# DEBUG Local $ret3 = DllStructCreate("char[256]", $ret2) Local $myRet = @error ConsoleWrite(": ") ;# DEBUG If $myRet == 0 Then Local $string = "" & DllStructGetData($ret3, 1) & "" ;# <==== here it sometimes CRASHES $array[$i][0] = $string ConsoleWrite($array[$i][0]) ;# DEBUG Else MsgBox(4096 + 48, "Error", "Failed for DllStructCreate: " & $myRet) ;# i never got here $array[$i][0] = "???" ConsoleWrite($array[$i][0]) ;# DEBUG EndIf ConsoleWrite("; OWNER") ;# DEBUG Local $ret3 = _Security__LookupAccountSid(DllStructGetData($mem, "pUserSid")) ConsoleWrite(": ") ;# DEBUG If IsArray($ret3) Then $array[$i][3] = "" & $ret3[1] & "/" & $ret3[0] & "" ConsoleWrite($array[$i][3]) ;# DEBUG EndIf ConsoleWrite(@CRLF) ;# DEBUG Next ConsoleWrite("endLoop." & @CRLF) ;# DEBUG DllCall("WTSApi32.dll", "int", "WTSFreeMemory", "int", $aRet[4]) ConsoleWrite("_GetProcessList() <-- " & @AutoItPID & @CRLF) ;# DEBUG Return $array EndFunc ;==>_GetProcessList first of all i'd like to understand WHY it crashes in DllStructGetData. and then i'd like to AVOID it, of course so far i have found no way to add some try-catch logic in AutoIt. any ideas why it would crash under very rare circumstances? my script is 32bit executed on windows 64bit OS. i have seen it on both, windows 7 and windows 10. i have seen it with both, script execution and compiled exe.
  8. thanks for the advice on what to do and what better not to do. facts are: i do need the decimal value of that pointer (i.e. the address). my examples given above are limited to some simple repro code, only. i have a couple of other scenarios that are more complex. now let's get back to where i think a bug exists in AutoIt. as with many other programming languages you can do various conversions. for example: $test = String(99) $test = Int("99") $test = Hex(99) $test = Ptr(99) $test = Dec("0x63") now, as you can see in the following repro code it gives wrong results for pointers greater than 2^31: ConsoleWrite("1st round: 2^16 -1" & @CRLF) Local $myInt = 2 ^ 16 - 1 Local $myPtr = Ptr($myInt) ConsoleWrite("Int: " & $myInt & @CRLF) ConsoleWrite("Ptr: " & $myPtr & @CRLF) $myInt = Int($myPtr) ConsoleWrite("Int: " & $myInt & @CRLF) ConsoleWrite(@CRLF) ConsoleWrite("2nd round: 2^24 -1" & @CRLF) $myInt = 2 ^ 24 - 1 $myPtr = Ptr($myInt) ConsoleWrite("Int: " & $myInt & @CRLF) ConsoleWrite("Ptr: " & $myPtr & @CRLF) $myInt = Int($myPtr) ConsoleWrite("Int: " & $myInt & @CRLF) ConsoleWrite(@CRLF) ConsoleWrite("3rd round: 2^31 -1" & @CRLF) $myInt = 2 ^ 31 - 1 $myPtr = Ptr($myInt) ConsoleWrite("Int: " & $myInt & @CRLF) ConsoleWrite("Ptr: " & $myPtr & @CRLF) $myInt = Int($myPtr) ConsoleWrite("Int: " & $myInt & @CRLF) ConsoleWrite(@CRLF) ConsoleWrite("4th round: 2^32 -1" & @CRLF) $myInt = 2 ^ 32 - 1 $myPtr = Ptr($myInt) ConsoleWrite("Int: " & $myInt & @CRLF) ConsoleWrite("Ptr: " & $myPtr & @CRLF) $myInt = Int($myPtr) ;# <------ this is where the bug hits! <<<<< ConsoleWrite("Int: " & $myInt & @CRLF) ConsoleWrite(@CRLF) and as you are saying "yes, pointers are of course unsigned by definition" then obviously there is a bug in the current int conversion: for VarType "Ptr" it must return the value by reading it as unsigned int.
  9. thanks for your reply. it seems you are having a complete different understanding of the context, though. i'm doing a lot with VirtualAlloc / VirtualAllocEx / VirtualQuery / VirtualQueryEx. and for those i need a numeric representation of the location in the virtual address space of the process. period. in post #4 i have added a more meaningful example. i (again) classify the current behaviour as "bug": the int conversion is giving wrong results. as stated earlier: i'm currently using a workaround to do custom hex parsing of that address (interpreting it as "unsigned"). but a permanent fix would be desirable.
  10. let me give another example (that more closely matches the actual problem i am facing): #include <Memory.au3> #include <AutoItConstants.au3> #include <StringConstants.au3> Local $iAddress = _MemVirtualAlloc(0, 1024, $MEM_RESERVE + $MEM_TOP_DOWN, $PAGE_READWRITE) ConsoleWrite("allocation address: " & $iAddress & " - VarType: " & VarGetType($iAddress) & @CRLF) Local $iNumericAddress = Int ($iAddress) ConsoleWrite("numeric address: " & $iNumericAddress & @CRLF) If $iNumericAddress < 0 Then ConsoleWrite("ERROR: signed / unsigned mismatch - NEGATIVE memory address!" & @CRLF) EndIf If $iNumericAddress > 2^16 Then ConsoleWrite("do something ..." & @CRLF) EndIf ;# where "_MemVirtualAlloc" is defined in the standard included file "Memory.au3" as follows: ;~ Func _MemVirtualAlloc($pAddress, $iSize, $iAllocation, $iProtect) ;~ Local $aResult = DllCall("kernel32.dll", "ptr", "VirtualAlloc", "ptr", $pAddress, "ulong_ptr", $iSize, "dword", $iAllocation, "dword", $iProtect) ;~ If @error Then Return SetError(@error, @extended, 0) ;~ Return $aResult[0] ;~ EndFunc there seems to bug in the int conversion "Int()": the "VarGetType()" states that we are dealing with a "Ptr". but after the int conversion it carries a negative value. --- there is another side-observation: the standard "_MemVirtualAlloc()" is defined to be returning "ptr". but actually the return type is of "uint_ptr". so i try my custom implementation: Func CustomVirtualAlloc($pAddress, $iSize, $iAllocation, $iProtect) Local $aResult = DllCall("kernel32.dll", "uint_ptr", "VirtualAlloc", "uint_ptr", $pAddress, "ulong_ptr", $iSize, "dword", $iAllocation, "dword", $iProtect) If @error Then Return SetError(@error, @extended, 0) Return $aResult[0] EndFunc but now "VarGetType()" incorrectly states it was of type "Int32". in turn the int conversion will also give wrong results in this case. it seems as if AutoIt wasn't fully aware of the datatype "uint_ptr", at all? the UINT_PTR is being mentioned in the documentation, though: DllCall(...)
  11. i have not found any built-in methods that allow to read values as unsigned integer. all of the following return negative "-393216". but when read as unsigned the value actually is positive "4294574080". #include <AutoItConstants.au3> ConsoleWrite("value: " & 0xFFFA0000 & @CRLF) ConsoleWrite("value: " & Int(0xFFFA0000, $NUMBER_AUTO) & @CRLF) ConsoleWrite("value: " & Int(0xFFFA0000, $NUMBER_32BIT) & @CRLF) ConsoleWrite("value: " & Int(0xFFFA0000, $NUMBER_64BIT) & @CRLF) ConsoleWrite("value: " & Int("0xFFFA0000", $NUMBER_AUTO) & @CRLF) ConsoleWrite("value: " & Int("0xFFFA0000", $NUMBER_32BIT) & @CRLF) ConsoleWrite("value: " & Int("0xFFFA0000", $NUMBER_64BIT) & @CRLF) ConsoleWrite("value: " & Ptr(0xFFFA0000) & @CRLF) ConsoleWrite("value: " & Ptr("0xFFFA0000") & @CRLF) so as workaround i'm currently doing: convert the value to string (e.g. a pointer value i'm interested in) then do some custom parsing of that hex value to calculate the decimal value myself with the decimal value i can then do some arithmetic comparison and pointer logic. is there no smarter support for UINT and UINT_PTR? PS: related trac ticket: https://www.autoitscript.com/trac/autoit/ticket/3245
  12. what's the scope of local variables inside a "For" loop? the following snippet throws an error when doing the 2nd loop: For $i = 1 To 5 Local Const $sIteration = "iteration: " & $i ConsoleWrite($sIteration & @CRLF) Next the error says: "Can not redeclare a constant"
  13. sure i have compiled it. see the code snippet i have provided in my initial question. the help file looks a bit strange. the comments are giving an example to invoke it on a command prompt something like "echo Hello! | ConsoleRead.exe" - so it is piped to STDIN. that seems to be a whole different story. but when writing a console tool we obviously need some simple way to do both, ConsoleWrite() and ConsoleRead(). is such functionality not available out-of-the-box? reading through other discussions it seems this was only possible by using custom UDF, such as "Console.au3" (by Shaggi)? see this one, for exmple:
  14. i'm writing a command line tool (i.e. CUI instead of GUI) and would like to query the user for input, such as: Press any key to continue Do you really want to proceed? [y|n] i'm using the following code (derived from the example in the help file). but it does not wait for user input. it continues immediately. #Region ;**** Directives created by AutoIt3Wrapper_GUI **** #AutoIt3Wrapper_Compression=4 #AutoIt3Wrapper_Change2CUI=y #AutoIt3Wrapper_Run_Tidy=y #EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** AutoItSetOption("MustDeclareVars", 1) Opt("TrayAutoPause", 0) If Not @Compiled Then ConsoleWrite("ERROR - This script must be compiled to EXE in order to read from the console." & @CRLF) ConsoleWrite("exiting ..." & @CRLF) Sleep(5000) Exit (1) EndIf ConsoleWrite("Do you want to continue? [y|n]" & @CRLF) Local $sOutput = "" While True $sOutput &= ConsoleRead() If @error Then ExitLoop Sleep(25) WEnd If $sOutput <> "y" Then ConsoleWrite("skipping - your answer was: " & $sOutput & @CRLF) Else ConsoleWrite("proceeding - your answer was: " & $sOutput & @CRLF) ; do some funny stuff ... Sleep(5000) EndIf ConsoleWrite("done. exiting ..." & @CRLF) Sleep(5000) am i missing something?
  15. technically speaking what's the difference between the following two: 1) #RequireAdmin2) #pragma compile(ExecLevel, requireAdministrator)obviously the second one works for "compiled" scripts, only. but are there any other differences? in the documentation those two are not even cross-linked in the "related" paragraph.
  16. @WoodGrain: 1) the code snippet in post #9 has some additional error checking. so what is the output on your problem machines? which of the messageboxes are showing up? 2) as suggested by JohnOne in post #2: do you see different behaviour when explicitly requesting admin privileges? add the following line at the top of your script: #RequireAdmin to get assistance with your issue you should be more responsive ...
  17. for internal reference: the "bug" report (as mentioned by PTim) would be: https://www.autoitscript.com/trac/autoit/ticket/3162
  18. before raising a bug for autoit you need to be sure this symptom is specific to autoit. however, after doing some searching it rather seems to be specific to windows xp: http://stackoverflow.com/a/27097793http://stackoverflow.com/a/17124533
  19. on your XP machines: is it really successful in invoking the BAT? is @error <> 0 ? #pragma compile(Console, True) #include <Constants.au3> #include <MsgBoxConstants.au3> Local $Result Local $command $Command = @ScriptDir & "\mytest.bat" $Result = RunWait("""" & $Command & """", @ScriptDir) If @error Then MsgBox($MB_SYSTEMMODAL, "Error", "Failed to spawn: " & $Command) Else MsgBox($MB_SYSTEMMODAL, "Test", "Result: " & $Result) EndIf Exit $Result
  20. i would guess that on "some" of your computers the @TempDir have space characters in the path. so for Run(...) make sure to embrace the path with quotes. in addition: just add error handling wherever you can: Local $sTargetPath = @TempDir & "\HCTB\TB_Setup-sif7r8pgcq.exe" If Not FileExists (@TempDir & "\HCTB") Then If Not DirCreate(@TempDir & "\HCTB") Then MsgBox($MB_SYSTEMMODAL, "Error", "Failed to create directory.") EndIf EndIf If FileExists ($sTargetPath) Then If Not FileSetAttrib($sTargetPath, "-R") Then MsgBox($MB_SYSTEMMODAL, "Error", "Failed to remove read-only flag.") EndIf EndIf If Not FileInstall("G:\IT\Downloads\TB\12.0.45471\Host\TB_Setup-sif7r8pgcq.exe", $sTargetPath, 1) Then MsgBox($MB_SYSTEMMODAL, "Error", "Failed to copy file.") EndIf Sleep (500) If Not FileExists ($sTargetPath) Then MsgBox($MB_SYSTEMMODAL, "Error", "Target file does not exist: " & $sTargetPath) EndIf Local $iPID = Run( """" & $sTargetPath & """", "") ;# Paths with spaces need to be enclosed in quotation marks! If $iPID = 0 Then MsgBox($MB_SYSTEMMODAL, "Error", "Failed to spawn: " & $sTargetPath) EndIf
  21. your question: "Is it possible to renovate this program?" my question: "is it possible you use a meaningful subject line?" for example: instead of referring to "the program" - why don't you refer to the "form builder" (from topic 46283)? PS: also see the "GUI designer" summary thread: topic 167013
  22. right. i was sparing you from the full context. in my code i have a two-dimensional array. that's why i can't omit that parameter. _ArrayToString($aTmp, "; ", 1, Default, "; ", 2, 2)
  23. interesting. in the changelog i found for version "3.3.10.0" so it seems this was now rolled-back by version "3.3.14.2"? conclusion: from now on i'll put custom COM error handlers all over the place. because otherwise it breaks my scripts.
  24. to improve my code example: this "$iEnd_Row" parameter is "optional" - and has an "internal default", anyways. so to avoid running into such problems (when the internal defaults change in a future release): simply use the "Default" keyword: ; do NOT pass a default VALUE: _ArrayToString($aResult, "; ", 1, -1)) ; instead, use the "Default" KEYWORD: _ArrayToString($aResult, "; ", 1, Default))
×
×
  • Create New...