Jump to content

Calling User32 EnumPropsEx Properly


Recommended Posts

So first things first the example in the help file for _WinApi_Enum_Windows has an error

;_ArrayDisplay($aResult, "_WinAPI_EnumWindows", Default, Default, Default, Default, "#|Handle|Class|Title|Text|Process")
  Should Be
  _ArrayDisplay($aResult, "_WinAPI_EnumWindows", Default, Default, Default, "Handle|Class|Title|Text|Process")

Next is a bit of helpful info on LPCSTR in a callback function it needs  to be passed as a PTR

DllCallbackRegister($sFUNCT, $sRETURN, "ptr")

Finally on to my question

I'd want to call EnumPropsEX and pass a string through lparam + append to it rather than declaring anything globally

I can Come up with two ways to do this The second it a lot more code but possibly safer but the first way I think Should do

1. From a bit of testing It seems AutoIt won't overflow a DllStruct?

2. Are strings passed through DLL call guaranteed to be 'an ANSI string (a minimum of 65536 chars is allocated)' as the Helpfile clearly states?

#include <Array.au3>
#include <WinAPI.au3>
Example()

Func Example()
    Local $aWindows = _WinAPI_EnumWindows()
    Local $aResult[$aWindows[0][0]][6]
    For $i = 1 To $aWindows[0][0]
        $aResult[$i - 1][0] = "0x" & Hex($aWindows[$i][0], 8)
        $aResult[$i - 1][1] = $aWindows[$i][1]
        $aResult[$i - 1][2] = WinGetTitle($aWindows[$i][0])
        $aResult[$i - 1][3] = WinGetText($aWindows[$i][0])
        $aResult[$i - 1][4] = WinGetProcess($aWindows[$i][0])
        $aResult[$i - 1][5] = _ArrayToString(EnumProps($aWindows[$i][0]), ", ", 1)
    Next
    _ArrayDisplay($aResult, "_WinAPI_EnumWindows", Default, Default, Default, "Handle|Class|Title|Text|Process|Properties")
EndFunc   ;==>Example

Func EnumProps($hWnd, $vDLL = 'user32.dll')
    ; Create callback function.
    Local $iErr = 0
    Local $aProps[1] = [0]
    Local $hCb = DllCallbackRegister('_PropEnumProcEx', 'int', 'hwnd;ptr;handle;ptr')
    ; Call EnumPropsEx
    Local $aRet = DllCall($vDLL, 'int', 'EnumPropsEx', 'HWND', $hWnd, 'ptr', DllCallbackGetPtr($hCb), 'str', "")
    If @error Or Not $aRet[0] Then
        $iErr = @error
        ConsoleWrite("EnumProps Error:" & $iErr & @CRLF)
    ElseIf $aRet[3] <> "" Then
        $aProps = StringSplit($aRet[3], ";")
    EndIf
    DllCallbackFree($hCb)

    Return SetError($iErr, 0, $aProps)
EndFunc   ;==>EnumProps

Func _PropEnumProcEx($hWnd, $sProp, $hData, $pStr)
    Local $iSzStr = _WinAPI_StringLenA($sProp) + 1 ; + Null Char
    If $iSzStr > 1 Then
        Local $tProp = DllStructCreate('char[' & $iSzStr & ']', $sProp)
        Local $tRetn = DllStructCreate('char[65535]', $pStr)
        DllStructSetData($tRetn, 1, DllStructGetData($tRetn, 1) & DllStructGetData($tProp, 1) & ";")
    EndIf
    Return 1
EndFunc   ;==>_PropEnumProcEx
;--------------------------------------------------------------------------------------------------------------
Func EnumProps2($hWnd, $iSzBuffer = 4096, $vDLL = 'user32.dll')
    ; Create callback function.
    Local $iErr = 0
    Local $sProps
    Local $aProps[1] = [0]
    Local $hCb = DllCallbackRegister('_PropEnumProcEx', 'int', 'hwnd;ptr;handle;ptr')
    Local $tProps = DllStructCreate('int;int;char[' & $iSzBuffer & ']')
    DllStructSetData($tProps, 1, $iSzBuffer) ;BufferSz
    DllStructSetData($tProps, 2, $iSzBuffer) ;BufferRemaining
    ; Call EnumPropsEx
    Local $aRet = DllCall($vDLL, 'int', 'EnumPropsEx', 'HWND', $hWnd, 'ptr', DllCallbackGetPtr($hCb), 'ptr', DllStructGetPtr($tProps))
    If @error Or Not $aRet[0] Then
        $iErr = @error
        DllStructSetData($tProps, 2, 0)
    EndIf
    DllCallbackFree($hCb)

    $sProps = DllStructGetData($tProps, 3)

    If DllStructGetData($tProps, 2) > 0 Then
        If $sProps <> "" Then
            $aProps = StringSplit(StringTrimRight($sProps, 1), ";")
        EndIf
    Else
        If Not $iErr Then $iErr = 6 ;buffer overflow
        Return SetError($iErr, -DllStructGetData($tProps, 2), $aProps)
    EndIf
    Return $aProps
EndFunc   ;==>EnumProps2

Func _PropEnumProcEx2($hWnd, $sProp, $hData, $ptProp)
    Local $iSzStr = _WinAPI_StringLenA($sProp) + 1
    Local $tProp = DllStructCreate('char[' & $iSzStr & ']', $sProp)

    If $iSzStr > 1 Then
        Local $sRet = DllStructGetData($tProp, 1)
        Local $iSzBuffer = DllStructGetData(DllStructCreate('int', $ptProp), 1)
        Local $tRetn = DllStructCreate('int;int;char[' & $iSzBuffer & ']', $ptProp)
        DllStructSetData($tRetn, 2, DllStructGetData($tRetn, 2) - $iSzStr)
        If DllStructGetData($tRetn, 2) > 0 Then
            DllStructSetData($tRetn, 3, DllStructGetData($tRetn, 3) & $sRet & ";")
        EndIf
    EndIf
    Return 1
EndFunc   ;==>_PropEnumProcEx2

 

Link to comment
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
 Share

×
×
  • Create New...