Announcement

Collapse
No announcement yet.

UDP Wrapper Crash

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • UDP Wrapper Crash

    I have been trying to create a Wrapper for UDP functionality. Basically a DLL which can open, configure, send/recieve UDP packets, and close. I create a hidden window to handle UDP events and create a separate thread for the dialog processing.

    The problem is, I can open and send, but after that, any other call I make crashes the app.

    Here is the code...
    Code:
     
    #COMPILE DLL
    #REGISTER NONE
    #INCLUDE "WIN32API.INC"
    #INCLUDE "WS2_32.INC"
    GLOBAL ghInstance AS DWORD
    GLOBAL pCALLBACK AS DWORD
    GLOBAL hThread AS DWORD
    GLOBAL hDlg AS DWORD
    TYPE UDP_OBJECT
        pCALLBACK  AS DWORD
        IPAdd      AS ASCIIZ * 20
        PORTNum    AS DWORD
        FILENum    AS DWORD
    END TYPE
    %UDPMSG_BASE    = %WM_USER+500
    
    PMSG         = 
    PMSG_BASE + 800
    '--------------------------------------------------------------------------------
    '   ** Declarations **
    '--------------------------------------------------------------------------------
    DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
    DECLARE FUNCTION ShowDIALOG(BYVAL hParent AS DWORD) AS LONG
    DECLARE FUNCTION MyThread(BYVAL y AS DWORD) AS DWORD
    DECLARE SUB CustomCALLBACK(BYVAL Msg AS LONG)
    '-------------------------------------------------------------------------------
    ' Main DLL entry point called by Windows...
    '
    FUNCTION LIBMAIN (BYVAL hInstance   AS LONG, _
                      BYVAL fwdReason   AS LONG, _
                      BYVAL lpvReserved AS LONG) AS LONG
        SELECT CASE fwdReason
        CASE %DLL_PROCESS_ATTACH
            'Indicates that the DLL is being loaded by another process (a DLL
            'or EXE is loading the DLL).  DLLs can use this opportunity to
            'initialize any instance or global data, such as arrays.
            ghInstance = hInstance
            ShowDialog (%Hwnd_Desktop)
            THREAD CREATE MyThread(ghInstance) TO hThread
            FUNCTION = 1   'success!
        CASE %DLL_PROCESS_DETACH
            'Indicates that the DLL is being unloaded or detached from the
            'calling application.  DLLs can take this opportunity to clean
            'up all resources for all threads attached and known to the DLL.
            THREAD CLOSE hThread TO hThread
            DIALOG END hDlg
            FUNCTION = 1   'success!
        CASE %DLL_THREAD_ATTACH
            'Indicates that the DLL is being loaded by a new thread in the
            'calling application.  DLLs can use this opportunity to
            'initialize any thread local storage (TLS).
            FUNCTION = 1   'success!
        CASE %DLL_THREAD_DETACH
            'Indicates that the thread is exiting cleanly.  If the DLL has
            'allocated any thread local storage, it should be released.
            FUNCTION = 1   'success!
        END SELECT
    END FUNCTION
    '--------------------------------------------------------------------------------
    '   ** CallBacks **
    '--------------------------------------------------------------------------------
    CALLBACK FUNCTION ShowDIALOG1Proc()
    DIM lParam AS LONG
    DIM Count AS LONG
        SELECT CASE CBMSG
            CASE 
    PMSG
                IF pCALLBACK > 0 THEN
                    lParam = CBLPARAM
                    CALL DWORD pCALLBACK USING CustomCALLBACK(lParam)
                    FUNCTION = 1
                END IF
    '            Select Case lParam
    '                Case %FD_READ    'Data is available to be read from the socket.
    '                Case %FD_WRITE   'The socket is ready for data to be written.
    '                Case %FD_ACCEPT  'The socket is able to accept a new connection.
    '                Case %FD_CONNECT 'The connection has been established.
    '                Case %FD_CLOSE   'The socket has been closed.
    '            End Select
        END SELECT
    END FUNCTION
    FUNCTION MyThread(BYVAL y AS DWORD) AS DWORD
    LOCAL e AS LONG
    LOCAL x AS LONG
        DO
            DIALOG DOEVENTS TO e
            DIALOG GET SIZE hDlg TO x, x
        LOOP WHILE x   'When x& = 0, dialog has ended
    END FUNCTION
    '--------------------------------------------------------------------------------
    '   ** Dialogs **
    '--------------------------------------------------------------------------------
    FUNCTION ShowDIALOG(BYVAL hParent AS DWORD) AS LONG
    LOCAL lRslt AS LONG
    LOCAL pIP AS LONG
        DIALOG NEW hParent, "UDP", 267, 182, 195, 102, %WS_POPUP _ '%WS_VISIBLE _
            OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_LEFT OR _
            %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
        DIALOG SHOW MODELESS hDlg, CALL ShowDIALOG1Proc TO lRslt
        DIALOG SHOW STATE hDlg, %SW_HIDE
        FUNCTION = lRslt
    END FUNCTION
    '-------------------------------------------------------------------------------
    ' Examples of exported Subs and functions...
    '
    FUNCTION UDP_CREATE CDECL () EXPORT AS LONG
        FUNCTION = globalalloc(%GPTR, SIZEOF(UDP_OBJECT))
    END FUNCTION
    FUNCTION UDP_SETIP CDECL(BYVAL pUDP_OBJECT AS UDP_OBJECT PTR, BYVAL IP AS STRING, BYVAL PortNum AS DWORD) EXPORT AS LONG
        ERRCLEAR
        @pUDP_OBJECT.IPAdd     = IP
        @pUDP_OBJECT.PortNum   = PortNum
        FUNCTION = ERR
    END FUNCTION
    FUNCTION UDP_CALLBACK CDECL(BYVAL pUDP_OBJECT AS UDP_OBJECT PTR, BYVAL pCALLBK AS DWORD) EXPORT AS LONG
        ERRCLEAR
        pCALLBACK      = pCALLBK
        IF (@pUDP_OBJECT.FileNum > 0) AND (@pUDP_OBJECT.pCALLBACK > 0) THEN
            UDP NOTIFY @pUDP_OBJECT.FileNum, SEND RECV CLOSE TO hDlg AS 
    PMSG
        END IF
        FUNCTION = ERR
    END FUNCTION
     
    FUNCTION UDP_OPEN CDECL(BYVAL pUDP_OBJECT AS UDP_OBJECT PTR) EXPORT AS LONG
        ERRCLEAR
        'Auto Close any previous connection
        IF @pUDP_OBJECT.FileNum > 0 THEN
            UDP CLOSE @pUDP_OBJECT.FileNum
            @pUDP_OBJECT.FileNum   = 0
            @pUDP_OBJECT.pCALLBACK = 0
        END IF
        @pUDP_OBJECT.FileNum = FREEFILE
        UDP OPEN PORT @pUDP_OBJECT.PortNum AS @pUDP_OBJECT.FileNum
        FUNCTION = ERR
    END FUNCTION
    FUNCTION UDP_CLOSE CDECL(BYVAL pUDP_OBJECT AS UDP_OBJECT PTR) EXPORT AS LONG
        ERRCLEAR
        'Auto close previous connection
        IF @pUDP_OBJECT.FileNum > 0 THEN
            UDP CLOSE @pUDP_OBJECT.FileNum
            @pUDP_OBJECT.FileNum = 0
        END IF
        GlobalFree (pUDP_OBJECT)
        FUNCTION = ERR
    END FUNCTION
    FUNCTION UDP_SENDDATA CDECL(BYVAL pUDP_OBJECT AS UDP_OBJECT PTR, BYVAL Packet AS STRING ) EXPORT AS LONG
    DIM pIP AS LONG
        ERRCLEAR
        'Send Data
        IF @pUDP_OBJECT.FileNum > 0 THEN
            HOST ADDR @pUDP_OBJECT.IPAdd TO pIP
            UDP SEND @pUDP_OBJECT.FileNum, AT pIP, @pUDP_OBJECT.PortNum, Packet
        END IF
        FUNCTION = ERR
        SLEEP 1
    END FUNCTION
    FUNCTION UDP_GETDATA CDECL(BYVAL pUDP_OBJECT AS UDP_OBJECT PTR, BYREF IPAdd AS LONG, BYREF PortNum AS LONG) EXPORT AS STRING
    LOCAL Buffer AS STRING
    LOCAL pPort AS LONG
        ERRCLEAR
        'Get Data
        IF @pUDP_OBJECT.FileNum > 0 THEN
            UDP RECV @pUDP_OBJECT.FileNum , FROM IPAdd, PortNum, Buffer
            FUNCTION = Buffer
            EXIT FUNCTION
        END IF
        FUNCTION = "###"
        SLEEP 1
    END FUNCTION
    I would appreciate it if someone could help me figure out what's wrong.

    Thanks
    -Vince

  • #2
    Well, no test EXE provided, but I can see one glaring problem...

    Code:
    CASE %DLL_PROCESS_ATTACH
            'Indicates that the DLL is being loaded by another process (a DLL
            'or EXE is loading the DLL).  DLLs can use this opportunity to
            'initialize any instance or global data, such as arrays.
            ghInstance = hInstance
            ShowDialog (%Hwnd_Desktop)
            THREAD CREATE MyThread(ghInstance) TO hThread
    First of all, the dialog is being created on DLL_PROCESS_ATTACH. That's a no-no.

    Second, the dialog is being created in the context of the calling thread. For that dialog to execute in a secondary thread the DIALOG NEW must execute from the thread function.

    The thread function MyThread is executing a message loop for the queue associated with the second thread... except your window is executing in the context of the calling thread.

    That is, if this doesn't crash (whatever "crash" means), it surely won't work anyway.

    MCM
    Michael Mattias
    Tal Systems Inc. (retired)
    Racine WI USA
    [email protected]
    http://www.talsystems.com

    Comment

    Working...
    X