Jump to content
BlackSnoww

Undeclared variable on DLL call

Recommended Posts

I stumbled upon the code of @Yashied here at this thread https://www.autoitscript.com/forum/topic/108145-screenshot-over-tcp/?tab=comments#comment-969161 about sending Secreenshots through TCP without saving a physical file to the drive. I tried editing the code and found an error i cant figure it out. can anyone help ?

Server

#Include <APIConstants.au3>
#Include <GDIPlus.au3>
#Include <Memory.au3>
#Include <WinAPIEx.au3>

;Global Const $STM_SETIMAGE = 0x0172
;Global Const $STM_GETIMAGE = 0x0173

TCPStartup()
$Main = TCPListen(@IPAddress4, 33891)
If @error Then
    Exit
EndIf

GUICreate('MyGUI', 800, 600, @DesktopWidth - 819, @DesktopHeight - 671)
$Pic = GUICtrlCreatePic('', 0, 0, 800, 600)
GUISetState()

Do
    $Socket = TCPAccept($Main)
Until $Socket <> -1

Global $tHeader = DllStructCreate('byte[4]')
Global $pHeader = DllStructGetPtr($tHeader)
Global $bData = 0, $Count = 0

_GDIPlus_Startup()

Do
    If Not IsBinary($bData) Then
        $bData = TCPRecv($Socket, 16384, 1)
        If @error Then
            ExitLoop
        EndIf
    EndIf
    If IsBinary($bData) Then
        If Not $Count Then
            DllStructSetData($tHeader, 1, $bData)
            $tData = DllStructCreate('dword', $pHeader)
            $Size = DllStructGetData($tData, 1)
            $tData = DllStructCreate('byte[' & $Size & ']')
            $pData = DllStructGetPtr($tData)
        EndIf
        $Lenght = BinaryLen($bData)
        $Sum = $Count + $Lenght
        If $Sum > $Size Then
            $dL = $Size - $Count
            $tPart = DllStructCreate('byte[' & $dL & ']', $pData + $Count)
            DllStructSetData($tPart, 1, $bData)
            $tByte = DllStructCreate('byte[' & $Lenght & ']')
            $tRecv = DllStructCreate('byte[' & ($Lenght - $dL) & ']', DllStructGetPtr($tByte) + $dL)
            DllStructSetData($tByte, 1, $bData)
            $bData = DllStructGetData($tRecv, 1)
            $Sum = $Size
        Else
            $tPart = DllStructCreate('byte[' & $Lenght & ']', $pData + $Count)
            DllStructSetData($tPart, 1, $bData)
            $Count = $Sum
            $bData = 0
        EndIf
        If $Sum = $Size Then
            _SetScreenshot($Pic, $tData)
            $Count = 0
        EndIf
    EndIf
Until GUIGetMsg() = -3

_GDIPlus_Shutdown()

TCPCloseSocket($Socket)
TCPShutdown()

Func _SetScreenshot($CtrlID, ByRef $tData, $fUpdate = 0)

    Local $hBitmap, $hPrev, $hScreen, $hMemory, $pMemory, $pStream, $pData, $iSize

    $hWnd = GUICtrlGetHandle($CtrlID)
    If Not $hWnd Then
        Return 0
    EndIf

    $pData = DllStructGetPtr($tData)
    $iSize = DllStructGetData(DllStructCreate('dword', $pData + 4), 1)
    $hMemory = _MemGlobalAlloc($iSize, $GMEM_MOVEABLE)
    $pMemory = _MemGlobalLock($hMemory)
    _MemMoveMemory($pData + 8, $pMemory, $iSize)
    _MemGlobalUnlock($hMemory)
    $pStream = _WinAPI_CreateStreamOnHGlobal($hMemory)
    $hBitmap = _GDIPlus_CreateBitmapFromStream($pStream)
    $hScreen = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_ReleaseStream($pStream)
    _WinAPI_DeleteObject(_SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hScreen))
    $hPrev = _SendMessage($hWnd, $STM_GETIMAGE)
    If $hPrev <> $hScreen Then
        _WinAPI_DeleteObject($hScreen)
    EndIf
    If $fUpdate Then
        _WinAPI_UpdateWindow($hWnd)
    EndIf
    Return 1
EndFunc   ;==>_SetScreenshot

Func _GDIPlus_CreateBitmapFromStream($pStream)

    Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipCreateBitmapFromStream', 'ptr', $pStream, 'ptr*', 0)

    If (@error) Or ($Ret[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return $Ret[2]
EndFunc   ;==>_GDIPlus_CreateBitmapFromStream

Client

#Include <APIConstants.au3>
#Include <GDIPlus.au3>
#Include <Memory.au3>
#Include <WinAPIEx.au3>

TCPStartup()
$Socket = TCPConnect(@IPAddress4, 33891)
If @error Then
    Exit
EndIf

_GDIPlus_Startup()

Global $tEncoder = _WinAPI_GUIDFromString(_GDIPlus_EncodersGetCLSID('png'))
Global $pEncoder = DllStructGetPtr($tEncoder)
Local $iWidth = @DesktopWidth
 Local $iHeight = @DesktopHeight
 Local $iX = 0
 Local $iY = 0

While 1
    TCPSend($Socket, _GetScreenshot($iX, $iY, $iWidth, $iHeight))
    If @error Then
       ExitLoop
   EndIf
    Sleep(1000)
WEnd

_GDIPlus_Shutdown()

TCPShutdown()

Func _GetScreenshot($iX,$iY, $iWidth, $iHeight)

    Local $hSrcDC, $hDstDC, $hDstSv, $hBitmap, $hDesktop, $hScreen, $hMemory, $pMemory, $pStream, $tOut, $pOut, $iSize, $pParams=0

    $hDesktop = _WinAPI_GetDesktopWindow()
    $hSrcDC = _WinAPI_GetDC($hDesktop)
    $hScreen = _WinAPI_CreateCompatibleBitmap($hSrcDC, $iWidth, $iHeight)
    $hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
    $hDstSv = _WinAPI_SelectObject($hDstDC, $hScreen)
    _WinAPI_BitBlt($hDstDC, $iX, $iY, $iWidth, $iHeight, $hSrcDC, $iX, $iY, $SRCCOPY)
    _WinAPI_SelectObject($hDstDC, $hDstSv)
    _WinAPI_ReleaseDC($hDesktop, $hSrcDC)
    _WinAPI_DeleteDC($hDstDC)
    $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hScreen)
    _WinAPI_DeleteObject($hScreen)
    $pStream = _WinAPI_CreateStreamOnHGlobal(0)
    _GDIPlus_SaveImageToStream($hBitmap, $pStream, $pEncoder,$pParams)
    _GDIPlus_BitmapDispose($hBitmap)
   $hMemory = _WinAPI_GetHGlobalFromStream($pStream)
    $pMemory = _MemGlobalLock($hMemory)
    $iSize = _MemGlobalSize($hMemory)
    $tOut = DllStructCreate('dword;dword;byte[' & ($iSize - Mod($iSize, 4) + 4) & ']')
    $pOut = DllStructGetPtr($tOut)
    DllStructSetData($tOut, 1, DllStructGetSize($tOut))
    DllStructSetData($tOut, 2, $iSize)
    _MemMoveMemory($pMemory, $pOut + 8, $iSize)
    _WinAPI_ReleaseStream($pStream)
    Return DllStructGetData(DllStructCreate('byte[' & DllStructGetSize($tOut) & ']', DllStructGetPtr($tOut)), 1)
EndFunc


Func _GDIPlus_SaveImageToStream($hImage, $pStream, $pEncoder, $pParams)

    Local $Ret = DllCall($ghGDIPDll, 'uint', 'GdipSaveImageToStream', 'ptr', $hImage, 'ptr', $pStream, 'ptr', $pEncoder, 'ptr', $pParams)

    If (@error) Or ($Ret[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return 1
EndFunc   ;==>_GDIPlus_SaveImageToStream

the error on the attached file

er.png

Share this post


Link to post
Share on other sites

BlackSnoww,

The $ghGDIPDll DLL name within the various GDI #include files was renamed a long time ago to $__g_hGDIPDll - try changing that in the calling line and see if it works.

M23


Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

@Melba23

Thanks for your help i have this fully working on TCP.

on the side note i have implemented this using Mailslots UDF as the TCP version made a bottleneck in sending the screenshots lol.

I was hoping this would make is faster.

 

So my problem is

Running the mailslots on the same PC runs without a problem. Problem arise when its run on the different PC.

the mailslot name used on the same PC  "Both server and client is using the same name"

Global Const $sMailSlotName = "\\.\mailslot\RandomNameForThisTest"

 

 

On the different PC

Name for host

Global Const $sMailSlotName = "\\.\mailslot\RandomNameForThisTest"

Name for Client where localuser-PC is the computer name of the host

Global Const $sMailSlotName = "\\localuser-PC\mailslot\RandomNameForThisTest"

Mailslot naming was made to this due to the reading made from this site https://www.codeproject.com/Articles/8527/Using-Mailslots-for-Interprocess-Communication "after the introduction part"

my the Client returns a error code of 2 which the UDF documentation states "WriteFile function or call to it failed." and i dont know why.

can you help me ? maybe u know whats my problem because in my digging u have been using mailslots alot xD

 

Server

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#include "MailSlot.au3"
#Include <APIConstants.au3>
#Include <GDIPlus.au3>
#Include <Memory.au3>
#Include <WinAPIEx.au3>


Global Const $sMailSlotName = "\\.\mailslot\RandomNameForThisTest"
Global $hMailSlot = _MailSlotCreate($sMailSlotName)
If @error Then
    MsgBox(48 + 262144, "MailSlot", "Failed to create new account!" & @CRLF & "Probably one using that 'address' already exists.")
    Exit
EndIf


GUICreate('MyGUI', 800, 600, @DesktopWidth - 819, @DesktopHeight - 671)
$Pic = GUICtrlCreatePic('', 0, 0, 800, 600)
GUISetState()


Global $tHeader = DllStructCreate('byte[4]')
Global $pHeader = DllStructGetPtr($tHeader)
Global $bData = 0, $Count = 0
Global $sData

_GDIPlus_Startup()

Do
      _ReadMessage($hMailSlot)
      $bData = $sData


    If IsBinary($bData) Then
        If Not $Count Then
            DllStructSetData($tHeader, 1, $bData)
            $tData = DllStructCreate('dword', $pHeader)
            $Size = DllStructGetData($tData, 1)
            $tData = DllStructCreate('byte[' & $Size & ']')
            $pData = DllStructGetPtr($tData)
        EndIf
        $Lenght = BinaryLen($bData)
        $Sum = $Count + $Lenght
        If $Sum > $Size Then
            $dL = $Size - $Count
            $tPart = DllStructCreate('byte[' & $dL & ']', $pData + $Count)
            DllStructSetData($tPart, 1, $bData)
            $tByte = DllStructCreate('byte[' & $Lenght & ']')
            $tRecv = DllStructCreate('byte[' & ($Lenght - $dL) & ']', DllStructGetPtr($tByte) + $dL)
            DllStructSetData($tByte, 1, $bData)
            $bData = DllStructGetData($tRecv, 1)
            $Sum = $Size
        Else
            $tPart = DllStructCreate('byte[' & $Lenght & ']', $pData + $Count)
            DllStructSetData($tPart, 1, $bData)
            $Count = $Sum
            $bData = 0
        EndIf
        If $Sum = $Size Then
            _SetScreenshot($Pic, $tData)
            $Count = 0
        EndIf
    EndIf
Until GUIGetMsg() = -3

_GDIPlus_Shutdown()

Func _SetScreenshot($CtrlID, ByRef $tData, $fUpdate = 0)

    Local $hBitmap, $hPrev, $hScreen, $hMemory, $pMemory, $pStream, $pData, $iSize

    $hWnd = GUICtrlGetHandle($CtrlID)
    If Not $hWnd Then
        Return 0
    EndIf

    $pData = DllStructGetPtr($tData)
    $iSize = DllStructGetData(DllStructCreate('dword', $pData + 4), 1)
    $hMemory = _MemGlobalAlloc($iSize, $GMEM_MOVEABLE)
    $pMemory = _MemGlobalLock($hMemory)
    _MemMoveMemory($pData + 8, $pMemory, $iSize)
    _MemGlobalUnlock($hMemory)
    $pStream = _WinAPI_CreateStreamOnHGlobal($hMemory)
    $hBitmap = _GDIPlus_CreateBitmapFromStream($pStream)
    $hScreen = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_ReleaseStream($pStream)
    _WinAPI_DeleteObject(_SendMessage($hWnd, $STM_SETIMAGE, $IMAGE_BITMAP, $hScreen))
    $hPrev = _SendMessage($hWnd, $STM_GETIMAGE)
    If $hPrev <> $hScreen Then
        _WinAPI_DeleteObject($hScreen)
    EndIf
    If $fUpdate Then
        _WinAPI_UpdateWindow($hWnd)
    EndIf
    Return 1
EndFunc   ;==>_SetScreenshot

Func _GDIPlus_CreateBitmapFromStream($pStream)

    Local $Ret = DllCall($__g_hGDIPDll, 'uint', 'GdipCreateBitmapFromStream', 'ptr', $pStream, 'ptr*', 0)

    If (@error) Or ($Ret[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return $Ret[2]
 EndFunc   ;==>_GDIPlus_CreateBitmapFromStream


Func _ReadMessage($hHandle)

    Local $iSize = _MailSlotCheckForNextMessage($hHandle)

    If $iSize Then
         $sData = _MailSlotRead($hMailSlot, $iSize, 0)
    ;   $iNumberOfMessagesOverall += 1
    ;   GUICtrlSetData($hEdit, "Message No" & $iNumberOfMessagesOverall & " , Size = " & $iSize & " :" & @CRLF & @CRLF & $sData)
    Else
    ;   MsgBox(64, "Nothing read", "MailSlot is empty", 0, $hGUI)
    EndIf
EndFunc   ;==>_ReadMessage

Client

#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6
#Include <APIConstants.au3>
#Include <GDIPlus.au3>
#Include <Memory.au3>
#Include <WinAPIEx.au3>
#include <File.au3>
#include <MsgBoxConstants.au3>
#include "MailSlot.au3"


_GDIPlus_Startup()

Global Const $sMailSlotName = "\\localuser-PC\mailslot\RandomNameForThisTest"

Global $tEncoder = _WinAPI_GUIDFromString(_GDIPlus_EncodersGetCLSID('png'))
Global $pEncoder = DllStructGetPtr($tEncoder)
Local $iWidth = @DesktopWidth
 Local $iHeight = @DesktopHeight
 Local $iX = 0
 Local $iY = 0
 Global $time = 0

Global $Loops = 10
Global $begin = TimerInit()


While 1
      $ret =  _GetScreenshot($iX, $iY, $iWidth, $iHeight)
      _MailSlotWrite($sMailSlotName, $ret,0)
      Switch @error
            Case 1
                MsgBox(48, "MailSlot demo error", "Account that you try to send to likely doesn't exist!")
                Exit
            Case 2
                MsgBox(48, "MailSlot demo error", "Message is blocked!")
            Case 3
                MsgBox(48, "MailSlot demo error", "Message is send but there is an open handle left." & @CRLF & "That could lead to possible errors in future")
            Case 4
                MsgBox(48, "MailSlot demo error", "All is fucked up!" & @CRLF & "Try debugging MailSlot.au3 functions. Thanks.")
            Case Else
    ;           MsgBox(64, "MailSlot demo", "Sucessfully sent!")
        EndSwitch

WEnd

_GDIPlus_Shutdown()


Func _GetScreenshot($iX,$iY, $iWidth, $iHeight)

    Local $hSrcDC, $hDstDC, $hDstSv, $hBitmap, $hDesktop, $hScreen, $hMemory, $pMemory, $pStream, $tOut, $pOut, $iSize, $pParams=0

    $hDesktop = _WinAPI_GetDesktopWindow()
    $hSrcDC = _WinAPI_GetDC($hDesktop)
    $hScreen = _WinAPI_CreateCompatibleBitmap($hSrcDC, $iWidth, $iHeight)
    $hDstDC = _WinAPI_CreateCompatibleDC($hSrcDC)
    $hDstSv = _WinAPI_SelectObject($hDstDC, $hScreen)
    _WinAPI_BitBlt($hDstDC, $iX, $iY, $iWidth, $iHeight, $hSrcDC, $iX, $iY, $SRCCOPY)
    _WinAPI_SelectObject($hDstDC, $hDstSv)
    _WinAPI_ReleaseDC($hDesktop, $hSrcDC)
    _WinAPI_DeleteDC($hDstDC)
    $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hScreen)
    _WinAPI_DeleteObject($hScreen)
    $pStream = _WinAPI_CreateStreamOnHGlobal(0)
    _GDIPlus_SaveImageToStream($hBitmap, $pStream, $pEncoder,$pParams)
    _GDIPlus_BitmapDispose($hBitmap)
   $hMemory = _WinAPI_GetHGlobalFromStream($pStream)
    $pMemory = _MemGlobalLock($hMemory)
    $iSize = _MemGlobalSize($hMemory)
    $tOut = DllStructCreate('dword;dword;byte[' & ($iSize - Mod($iSize, 4) + 4) & ']')
    $pOut = DllStructGetPtr($tOut)
    DllStructSetData($tOut, 1, DllStructGetSize($tOut))
    DllStructSetData($tOut, 2, $iSize)
    _MemMoveMemory($pMemory, $pOut + 8, $iSize)
    _WinAPI_ReleaseStream($pStream)
    Return DllStructGetData(DllStructCreate('byte[' & DllStructGetSize($tOut) & ']', DllStructGetPtr($tOut)), 1)

EndFunc


Func _GDIPlus_SaveImageToStream($hImage, $pStream, $pEncoder, $pParams)

    Local $Ret = DllCall($__g_hGDIPDll, 'uint', 'GdipSaveImageToStream', 'ptr', $hImage, 'ptr', $pStream, 'ptr', $pEncoder, 'ptr', $pParams)

    If (@error) Or ($Ret[0]) Then
        Return SetError(@error, @extended, 0)
    EndIf
    Return 1
 EndFunc   ;==>_GDIPlus_SaveImageToStream


 Func _FileSend($sBuff)

    While BinaryLen($sBuff)
        $iSendReturn = TCPSend($Socket, $sBuff)
        If @error Then Return SetError(4, 0, -1)

        $sBuff = BinaryMid ($sBuff, $iSendReturn + 1, BinaryLen ($sBuff) - $iSendReturn)
     WEnd

    Return 1
EndFunc

 

Share this post


Link to post
Share on other sites

MailSlot MTU is limited to 65,507 bytes on localhost, and 412 bytes (datagram - 12 bytes header) on LAN. See my Pool environment (link in sig) for more info and some examples how to transfer larger data chunks on LANs.

Share this post


Link to post
Share on other sites

oh i figured that one out by making use of a buffer but the sending of data is much slower compared to Mailslots :(

i tried comparing the FPS and the mailslots gave much more smoother results.

Share this post


Link to post
Share on other sites

You could test UDP; should be faster than TCP because there's no triple handshake, but there's no resend upon packet-loss, so you'd have to check the file integrity at the other end yourself.

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

×
×
  • Create New...