Jump to content
francoiste

crash in DllStructGetData

Recommended Posts

francoiste

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.

Edited by francoiste

Share this post


Link to post
Share on other sites
francoiste

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.

minidump.png

Share this post


Link to post
Share on other sites
AndyG

Hi,

where did you get the information, that there is a reservation in memory for the processname of 256 characters?

The only information that i found was that the processname is a null-terminated string. If you create a dllstruct at the position of this string  (with length=256bytes) and behind this string (shorter than 256bytes) is a reserved part of memory, you get the access violation.

  

 

Share this post


Link to post
Share on other sites
francoiste

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

 

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

  • Similar Content

    • YellowLab
      By YellowLab
      I am having a very unique, but repeatable problem with ImageMagick COM interface. Here are the applicable lines of code:
      $oIM=ObjCreate("ImageMagickObject.MagickImage.1")
      and then later on...
      $oIM.Convert(String($arFileList[$nFileIndex])&'[0]',"-alpha", "remove",@TempDir&"\temp.jpg")
      the array points to a pdf file with the "convert" command converting the first page of the pdf to a jpg with any alpha layer removed.
      Every time, without fail, the first time I run the script on a freshly booted machine it crashes on the $oIM.Convert command. It does this if it isn't compiled and says there is an error executing the command on the object. If compiled, i get an error that autoit has stopped responding. Anytime I run the script, compiled or not, after this initial crash everything works perfectly fine.
      I am totally at a loss as to why this is occurring and how to correct it.
    • UEZ
      By UEZ
      One web created Excel sheet is crashing when calling the _Excel_BookOpen function.
      "C:\Program Files (x86)\AutoIt3\Include\Excel.au3" (227) : ==> Variable must be of type "Object".: $oExcel.Windows($oWorkbook.Name).Visible = $bVisible $oExcel.Windows($oWorkbook.Name)^ ERROR Local $oWorkbook = $oExcel.Workbooks.Open($sFilePath, $bUpdateLinks, $bReadOnly, Default, $sPassword, $sWritePassword) in line 225 seems to load the file but no error is set.
      Is there any way to catch those errors to avoid app crash? ObjEvent("AutoIt.Error", "ErrFunc") doesn't catch it!
       
      Tested on 3.3.14.2 and 3.3.15.0 and Office 2013.
    • HelpfulToasty
      By HelpfulToasty
      So, I'm trying to make this autoit script, and there's a function and stuff, but I can't write a function, inside a function! It's just not working.
      Like;
      Func Function_A($para1) Local $thing = 1 Func Function_B() ;Stuff here EndFunc If Function_B($thing) Then ;Stuff Else ;Stuff EndIf EndFunc ; Something like that. I'm either doing it wrong, or I can't do it in autoit.
      Anyway, help me please!
    • matwachich
      By matwachich
      Hi! I have a question:
      - Why the hell would an application crash when I launch it from windows explorer, and works all fine when I launch it from command prompt?????

      More details:
      - It's an app that uses a DLL written in pure C of mine
      - The app also runs well when launched from SciTE (think it's a problem with the stdout...)
      - The module concerned in the crash is msvcrt.dll
      - All parts of the dll (event external libraries) are compiled using the same GCC (no any .NET sh*t)
      - Not only with AutoIt, even if I try to use this DLL with FreeBasic, I have the same crash
      - Befor, the DLL was not crashing this way, but I made many changes (and I didn't tracked them) since the last good version, so I have no idea where it comes from

      Big thanks!
    • shmuelw1
      By shmuelw1
      I have a script for starting all my startup programs. But when I use the script to start skype, skype crashes immediately. When I start up skype using the shortcut on the desktop it works fine.

      (I'm running Windows 7 64-bit with AutoIt3.exe in compatibility mode for Windows XP.)

      Any ideas?


      Dim $answer If Not ProcessExists("wonderfl.exe") Then Run("C:\Program Files (x86)\Wonderful\wonderfl.exe") Sleep(100) EndIf $answer = MsgBox(4, "", "Run remaining startup programs?", 60) If $answer = 7 Then Exit ; if no button is selected, exit script If Not ProcessExists("PureText.exe") Then Run("C:\Program Files (x86)\Puretext\PureText.exe") Sleep(100) EndIf If Not ProcessExists("2xExplorer.exe") Then Run("C:\Program Files (x86)\2xExplorer\2xExplorer.exe") Sleep(100) EndIf If Not ProcessExists("RBTray.exe") Then Run("C:\Program Files\RBTray Minimize to Tray\64bit\RBTray.exe") Sleep(100) EndIf If Not ProcessExists("FileBX.exe") Then Run("C:\Program Files (x86)\FileBX\FileBX.exe") Sleep(100) EndIf If Not ProcessExists("FreeWheel.exe") Then Run("C:\Program Files (x86)\FreeWheel\FreeWheel.exe") Sleep(100) EndIf If Not ProcessExists("firefox.exe") Then Run("C:\Program Files (x86)\Mozilla Firefox\firefox.exe") Sleep(10000) EndIf If Not ProcessExists("thunderbird.exe") Then Run("C:\Program Files (x86)\Mozilla Thunderbird\thunderbird.exe") Sleep(10000) EndIf If Not ProcessExists("HprSnap7.exe") Then Run("C:\Program Files (x86)\HyperSnap 7\HprSnap7.exe") Sleep(10000) EndIf If Not ProcessExists("magicJack.exe") Then Run("C:\Users\shmuelw\AppData\Roaming\mjusbsp\magicJack.exe") Sleep(10000) EndIf If Not ProcessExists("Skype.exe") Then Run("C:\Program Files (x86)\Skype\Phone\Skype.exe") Sleep(100) EndIf WinMinimizeAll()
×