#Region    ;************ Includes ************
#include-once
#include <Clipboard.au3>
#include <DDEMLConstants.au3>
#EndRegion    ;************ Includes ************
; ------------------------------------------------------------------------------
;
; Version:        1.5.4
; AutoIt Version: 3.3.0.0
; Language:       English
; Author:         doudou
; Description:    Common functions for Microsoft DDEML
;                 (Dynamic Data Exchange Management Library).
; Requirements:   ClipboardConstants
;                 DDEMLConstants
; $Revision: 1.3 $
; $Date: 2010/04/22 13:59:07 $
;
; ------------------------------------------------------------------------------
#cs
	Dynamic data exchange (DDE) is a form of interprocess communication that uses
	shared memory to exchange data between applications. Applications can use DDE
	for one-time data transfers and for ongoing exchanges and updating of data.
#ce

If Not IsDeclared("_DDEML_idInst") Then Global $_DDEML_idInst = 0
If Not IsDeclared("_DDEML_hDdeCallback") Then Global $_DDEML_hDdeCallback = 0
If Not IsDeclared("_DDEML_prefCallback") Then Global $_DDEML_prefCallback = ""
; set this to 0 manually when talking to ASCII servers
If Not IsDeclared("_DDEML_UNICODE") Then
	Assign("_DDEML_UNICODE", Execute("@Unicode"), 2)
	If @error Then
		If IsDeclared("_DDEML_UNICODE") Then
			$_DDEML_UNICODE = Execute("@AutoItUnicode")
		Else
			Assign("_DDEML_UNICODE", Execute("@AutoItUnicode"), 2)
		EndIf
	EndIf
	If @error Or Not IsInt($_DDEML_UNICODE) Then
		ConsoleWrite("WARNING: _DDEML_UNICODE is automatically set to 1" & @CRLF)
		$_DDEML_UNICODE = 1
		SetError(0)
	EndIf
EndIf

;****** API entry point ******;
;===============================================================================
; Function Name:   _DdeCallback
; Description:     The DdeCallbackProc function is an application-defined
;                  callback function used with the Dynamic Data Exchange Management
;                  Library (DDEML) functions. It processes dynamic data exchange
;                  (DDE) transactions. Here this callback is executed internally
;                  by DllCallback and advanced by name to transaction functions
;                  accordingly.
;
; Parameter(s):    as defined in ddeml.h
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): The return value depends on the transaction class. For more
;                  information about the return values, see descriptions of the
;                  individual transaction types.
;
; Author(s):       doudou
;===============================================================================
Func _DdeCallback($uType, $uFmt, $hConv, $hsz1, $hsz2, $hData, $dwData1, $dwData2)
;~     ConsoleWrite("_DdeCallback(" & $uType & ")" & @CRLF)
	Local $res = 0
	If 0 < StringLen($_DDEML_prefCallback) Then
		Local $wFmt = 0
		;;; TODO: callback parameters check
		Switch $uType
			;Client
			Case $XTYP_ADVDATA
				$res = Call($_DDEML_prefCallback & "AdvData", _DdeQueryString($hsz1), _DdeQueryString($hsz2), $uFmt, $hData, $hConv)
			Case $XTYP_XACT_COMPLETE
				$res = Call($_DDEML_prefCallback & "XActComplete", $dwData1, $dwData2, _DdeQueryString($hsz1), _DdeQueryString($hsz2), $uFmt, $hData, $hConv)

				;Server
			Case $XTYP_ADVREQ
				$res = Call($_DDEML_prefCallback & "AdvReq", $dwData1, _DdeQueryString($hsz1), $hsz2, $uFmt, $hConv)
			Case $XTYP_ADVSTART
				$res = Call($_DDEML_prefCallback & "AdvStart", _DdeQueryString($hsz1), _DdeQueryString($hsz2), $uFmt, $hConv)
			Case $XTYP_ADVSTOP
				$res = Call($_DDEML_prefCallback & "AdvStop", _DdeQueryString($hsz1), _DdeQueryString($hsz2), $uFmt, $hConv)
			Case $XTYP_CONNECT
				$res = Call($_DDEML_prefCallback & "Connect", _DdeQueryString($hsz1), _DdeQueryString($hsz2))
			Case $XTYP_CONNECT_CONFIRM
				$res = Call($_DDEML_prefCallback & "ConnectConfirm", _DdeQueryString($hsz1), _DdeQueryString($hsz2), $hConv)
			Case $XTYP_EXECUTE
				If $_DDEML_UNICODE Then $wFmt = $CF_UNICODETEXT
				$res = Call($_DDEML_prefCallback & "Execute", _DdeQueryString($hsz1), _DdeGetDataAsString($hData, $wFmt), $hConv)
			Case $XTYP_POKE
				$res = Call($_DDEML_prefCallback & "Poke", _DdeQueryString($hsz1), _DdeQueryString($hsz2), $uFmt, $hData, $hConv)
			Case $XTYP_REQUEST
				$res = Call($_DDEML_prefCallback & "Request", _DdeQueryString($hsz1), $hsz2, $uFmt, $hConv)
			Case $XTYP_WILDCONNECT
				$res = Call($_DDEML_prefCallback & "WildConnect", _DdeQueryString($hsz1), _DdeQueryString($hsz2))

				;Client/Server
			Case $XTYP_DISCONNECT
				$res = Call($_DDEML_prefCallback & "Disconnect", $hConv)
			Case $XTYP_ERROR
				$res = Call($_DDEML_prefCallback & "Error", $dwData1, $hConv)
			Case $XTYP_REGISTER
				$res = Call($_DDEML_prefCallback & "Register", _DdeQueryString($hsz1), _DdeQueryString($hsz2))
			Case $XTYP_UNREGISTER
				$res = Call($_DDEML_prefCallback & "Unregister", _DdeQueryString($hsz1), _DdeQueryString($hsz2))

		EndSwitch
	EndIf
	If 0xDEAD = @error And 0xBEEF = @extended Then
		ConsoleWrite("DDE callback function of type " & $uType & " not found, returning default" & @CRLF)
		Switch BitAND($uType, $XCLASS_MASK)
			Case $XCLASS_BOOL
				$res = 0
			Case $XCLASS_DATA
				$res = 0
			Case $XCLASS_FLAGS
				$res = $DDE_FNOTPROCESSED
			Case $XCLASS_NOTIFICATION
				$res = 0
		EndSwitch
	EndIf
;~     ConsoleWrite("_DdeCallback()=" & $res & @CRLF)
	Return $res
EndFunc   ;==>_DdeCallback

;===============================================================================
; Function Name:   _DdeGetLastError
; Description:     The _DdeGetLastError function returns the most recent error code
;                  set by the failure of a Dynamic Data Exchange Management Library
;                  (DDEML) function and resets the error code to DMLERR_NO_ERROR.
;
; Parameter(s):    none
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is the last error
;                  code. Following are the possible DDEML error codes:
;
; $DMLERR_ADVACKTIMEOUT         A request for a synchronous advise transaction
;                               has timed out.
; $DMLERR_BUSY                  The response to the transaction caused the
;                               DDE_FBUSY flag to be set.
; $DMLERR_DATAACKTIMEOUT        A request for a synchronous data transaction has
;                               timed out.
; $DMLERR_DLL_NOT_INITIALIZED   A DDEML function was called without first
;                               calling the DdeInitialize function, or an
;                               invalid instance identifier was passed
;                               to a DDEML function.
; $DMLERR_DLL_USAGE             An application initialized as APPCLASS_MONITOR
;                               has attempted to perform a dynamic data exchange
;                               (DDE) transaction, or an
;                               application initialized as APPCMD_CLIENTONLY has
;                               attempted to perform server transactions.
; $DMLERR_EXECACKTIMEOUT        A request for a synchronous execute transaction
;                               has timed out.
; $DMLERR_INVALIDPARAMETER      A parameter failed to be validated by the DDEML.
;                               Some of the possible causes follow:
;                                    The application used a data handle
;                                    initialized with a different item name
;                                    handle than was required by the
;                                    transaction.
;
;                                    The application used a data handle that was
;                                    initialized with a different clipboard data
;                                    format than was required by the transaction.
;
;                                    The application used a client-side
;                                    conversation handle with a server-side
;                                    function or vice versa.
;
;                                    The application used a freed data handle or
;                                    string handle.
;
;                                    More than one instance of the application
;                                    used the same object.
;
; $DMLERR_LOW_MEMORY            A DDEML application has created a prolonged race
;                               condition (in which the server application
;                               outruns the client), causing large amounts of
;                               memory to be consumed.
; $DMLERR_MEMORY_ERROR          A memory allocation has failed.
; $DMLERR_NO_CONV_ESTABLISHED   A client's attempt to establish a conversation
;                               has failed.
; $DMLERR_NOTPROCESSED          A transaction has failed.
; $DMLERR_POKEACKTIMEOUT        A request for a synchronous poke transaction has
;                               timed out.
; $DMLERR_POSTMSG_FAILED        An internal call to thePostMessage function has
;                               failed.
; $DMLERR_REENTRANCY            An application instance with a synchronous
;                               transaction already in progress attempted to
;                               initiate another synchronous transaction, or
;                               the DdeEnableCallback function was called from
;                               within a DDEML callback function.
; $DMLERR_SERVER_DIED           A server-side transaction was attempted on a
;                               conversation terminated by the client, or the
;                               server terminated before completing a transaction.
; $DMLERR_SYS_ERROR             An internal error has occurred in the DDEML.
; $DMLERR_UNADVACKTIMEOUT       A request to end an advise transaction has timed
;                               out.
; $DMLERR_UNFOUND_QUEUE_ID      An invalid transaction identifier was passed to
;                               a DDEML function. Once the application has
;                               returned from an XTYP_XACT_COMPLETE callback,
;                               the transaction identifier for that callback
;                               function is no longer valid.
;
; Author(s):       doudou
;===============================================================================
Func _DdeGetLastError()
	Local $res = DllCall("user32.dll", "uint", "DdeGetLastError", "dword", $_DDEML_idInst)
	Return $res[0]
EndFunc   ;==>_DdeGetLastError

; DLL registration functions ;

;===============================================================================
; Function Name:   _DdeInitialize
; Description:     The _DdeInitialize function registers an application with the
;                  Dynamic Data Exchange Management Library (DDEML). An
;                  application must call this function before calling any other
;                  DDEML function.
;
; Parameter(s):    $sCallbackPref - string prefix for transaction callbacks, f.i.
;                                   "OnDDE_"
;                  $dwCmd - Specifies a set of APPCMD_, CBF_, and MF_ flags. The
;                           APPCMD_ flags provide special instructions to
;                           DdeInitialize. The CBF_ flags specify filters that
;                           prevent specific types of transactions from reaching
;                           the callback function. The MF_ flags specify the
;                           types of DDE activity that a DDE monitoring
;                           application monitors. Using these flags enhances the
;                           performance of a DDE application by eliminating
;                           unnecessary calls to the callback function.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is DMLERR_NO_ERROR.
;
;                  If the function fails, the return value is one of the
;                  following values:
;
;                  $DMLERR_DLL_USAGE
;                  $DMLERR_INVALIDPARAMETER
;                  $DMLERR_SYS_ERROR
;
;
; Author(s):       doudou
;===============================================================================
Func _DdeInitialize($sCallbackPref, $dwCmd)
	If $_DDEML_idInst Then
;~         ConsoleWrite("DDEML already initialized" & @CRLF)
		Return $DMLERR_NO_ERROR
	EndIf
	If $_DDEML_hDdeCallback Then DllCallbackFree($_DDEML_hDdeCallback)
	$_DDEML_hDdeCallback = DllCallbackRegister("_DdeCallback", "ptr", $_DDEML_typdef_DdeCallback)
	If 0 = $_DDEML_hDdeCallback Then
		ConsoleWrite("Failed to register DDE callback" & @CRLF)
		Return $DMLERR_SYS_ERROR
	EndIf
	$_DDEML_prefCallback = $sCallbackPref

	Local $pid = DllStructCreate("dword idInst")
	DllStructSetData($pid, "idInst", 0)
	Local $sFunc = "DdeInitializeA"
	If $_DDEML_UNICODE Then $sFunc = "DdeInitializeW"
	Local $res = DllCall("user32.dll", "uint", $sFunc, "ptr", DllStructGetPtr($pid, 1), "ptr", DllCallbackGetPtr($_DDEML_hDdeCallback), "uint", $dwCmd, "uint", 0)
;~     ConsoleWrite("_DdeInitialize()=" & $res[0] & ", pid=" & DllStructGetData($pid, 1) & @CRLF)
	If $DMLERR_NO_ERROR = $res[0] Then
		$_DDEML_idInst = DllStructGetData($pid, 1)
	ElseIf $_DDEML_hDdeCallback Then
		DllCallbackFree($_DDEML_hDdeCallback)
		$_DDEML_hDdeCallback = 0
	EndIf
	$pid = 0
	Return $res[0]
EndFunc   ;==>_DdeInitialize

;===============================================================================
; Function Name:   _DdeUninitialize
; Description:     The _DdeUninitialize function frees all Dynamic Data Exchange
;                  Management Library (DDEML) resources associated with the
;                  calling application.
;
; Parameter(s):    none
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is True.
;                  If the function fails, the return value is False.
;
; Author(s):       doudou
;===============================================================================
Func _DdeUninitialize()
	Local $res = DllCall("user32.dll", "int", "DdeUninitialize", "dword", $_DDEML_idInst)
	$_DDEML_idInst = 0
	If $_DDEML_hDdeCallback Then DllCallbackFree($_DDEML_hDdeCallback)
	$_DDEML_hDdeCallback = 0

;~     ConsoleWrite("_DdeUninitialize()=" & $res[0] & @CRLF)
	If $res[0] Then Return True
	Return False
EndFunc   ;==>_DdeUninitialize

;===============================================================================
; Function Name:   _DdeIsInitialized
; Description:     The _DdeIsInitialized function returns the status of DDEML.
;
; Parameter(s):    none
;
; Return Value(s): True if _DdeInitialize() was previously executed successfully,
;                  otherwise the return value is False.
;
; Author(s):       doudou
;===============================================================================
Func _DdeIsInitialized()
	Return (0 <> $_DDEML_idInst) And (0 <> $_DDEML_hDdeCallback)
EndFunc   ;==>_DdeIsInitialized

; conversation control functions ;

;===============================================================================
; Function Name:   _DdeDisconnect
; Description:     The _DdeDisconnect function terminates a conversation started
;                  by either the DdeConnect or DdeConnectList function and
;                  invalidates the specified conversation handle.
;
; Parameter(s):    $hConv - Handle to the active conversation to be terminated.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is True.
;                  If the function fails, the return value is False.
;
; Author(s):       doudou
;===============================================================================
Func _DdeDisconnect($hConv)
	Local $res = DllCall("user32.dll", "int", "DdeDisconnect", $_DDEML_HANDLETYPE, $hConv)
;~     ConsoleWrite("_DdeDisconnect(" & $hConv & ")=" & $res[0] & @CRLF)
	If $res[0] Then Return True

	SetError(_DdeGetLastError())
	Return False
EndFunc   ;==>_DdeDisconnect

;===============================================================================
; Function Name:   _DdeQueryConvInfo
; Description:     The _DdeQueryConvInfo function obtains information about a
;                  dynamic data exchange (DDE) transaction and about the
;                  conversation in which the transaction takes place.
;
; Parameter(s):    $hConv - Handle to the conversation.
;                  $dwTransAct - Specifies the transaction. For asynchronous
;                                transactions, this parameter should be a transaction
;                                identifier returned by the _DdeClientTransaction
;                                function. For synchronous transactions, this
;                                parameter should be $QID_SYNC.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is CONVINFO DLL structure.
;                  If the function fails, the return value is 0.
;
; Author(s):       doudou
;===============================================================================
Func _DdeQueryConvInfo($hConv, $dwTransAct)
	Local $pConv = DllStructCreate($_DDEML_typdef_CONVINFO)
	Local $res = DllCall("user32.dll", "uint", "DdeQueryConvInfo", $_DDEML_HANDLETYPE, $hConv, "dword", $dwTransAct, "ptr", DllStructGetPtr($pConv))
	If $res[0] Then Return $pConv

	SetError(_DdeGetLastError())
	Return 0
EndFunc   ;==>_DdeQueryConvInfo

; data transfer functions ;

;===============================================================================
; Function Name:   _DdeCreateStringHandle
; Description:     The _DdeCreateStringHandle function creates a handle that
;                  identifies the string pointed to by the psz parameter.
;                  A dynamic data exchange (DDE) client or server application can
;                  pass the string handle as a parameter to other Dynamic Data
;                  Exchange Management Library (DDEML) functions.
;
; Parameter(s):    $sz - String for which a handle is to be created. This string
;                        may be up to 255 characters. The reason for this limit
;                        is that DDEML string management functions are implemented
;                        using global atoms.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is a string handle.
;                  If the function fails, the return value is 0.
;
; Author(s):       doudou
;===============================================================================
Func _DdeCreateStringHandle($sz)
	Local $cp = $CP_WINANSI
	Local $sFunc = "DdeCreateStringHandleA"
	Local $strType = "str"
	If $_DDEML_UNICODE Then
		$sFunc = "DdeCreateStringHandleW"
		$cp = $CP_WINUNICODE
		$strType = "wstr"
	EndIf
	Local $res = DllCall("user32.dll", $_DDEML_HANDLETYPE, $sFunc, "dword", $_DDEML_idInst, $strType, $sz, "int", $cp)
	If 0 = $res[0] Then SetError(_DdeGetLastError())
	Return $res[0]
EndFunc   ;==>_DdeCreateStringHandle

;===============================================================================
; Function Name:   _DdeFreeStringHandle
; Description:     The _DdeFreeStringHandle function frees a string handle in the
;                  calling application.
;
; Parameter(s):    $hsz - Handle to the string handle to be freed. This handle
;                         must have been created by a previous call to the
;                         _DdeCreateStringHandle function.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is True.
;                  If the function fails, the return value is False.
;
; Author(s):       doudou
;===============================================================================
Func _DdeFreeStringHandle($hsz)
	Local $res = DllCall("user32.dll", "int", "DdeFreeStringHandle", "dword", $_DDEML_idInst, $_DDEML_HANDLETYPE, $hsz)
	If $res[0] Then Return True

	SetError(_DdeGetLastError())
	Return False
EndFunc   ;==>_DdeFreeStringHandle

;===============================================================================
; Function Name:   _DdeKeepStringHandle
; Description:     The _DdeKeepStringHandle function increments the usage count
;                  associated with the specified handle. This function enables
;                  an application to save a string handle passed to the application's
;                  dynamic data exchange (DDE) callback function. Otherwise,
;                  a string handle passed to the callback function is deleted
;                  when the callback function returns. This function should also
;                  be used to keep a copy of a string handle referenced by the
;                  CONVINFO structure returned by the _DdeQueryConvInfo function.
;
; Parameter(s):    $hsz - Handle to the string handle to be saved.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is True.
;                  If the function fails, the return value is False.
;
; Author(s):       doudou
;===============================================================================
Func _DdeKeepStringHandle($hsz)
	Local $res = DllCall("user32.dll", "int", "DdeKeepStringHandle", "dword", $_DDEML_idInst, $_DDEML_HANDLETYPE, $hsz)
	If $res[0] Then Return True

	SetError(_DdeGetLastError())
	Return False
EndFunc   ;==>_DdeKeepStringHandle

;===============================================================================
; Function Name:   _DdeQueryString
; Description:     The _DdeQueryString function copies text associated with
;                  a string handle into a buffer.
;
; Parameter(s):    $hsz - Handle to the string to copy. This handle must have
;                         been created by a previous call to the
;                         _DdeCreateStringHandle function.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is the queried string.
;                  If the function fails, the return value is "".
;
; Author(s):       doudou
;===============================================================================
Func _DdeQueryString($hsz)
	Local $cp = $CP_WINANSI
	Local $sFunc = "DdeQueryStringA"
	Local $strType = "str"
	If $_DDEML_UNICODE Then
		$sFunc = "DdeQueryStringW"
		$cp = $CP_WINUNICODE
		$strType = "wstr"
	EndIf
	Local $res = DllCall("user32.dll", "dword", $sFunc, "dword", $_DDEML_idInst, $_DDEML_HANDLETYPE, $hsz, $strType, "", "dword", 32768, "int", $cp)
	If $res[0] Then Return $res[3]

	SetError(_DdeGetLastError(), $res[0])
	Return ""
EndFunc   ;==>_DdeQueryString

;===============================================================================
; Function Name:   _DdeCreateDataHandle
; Description:     The _DdeCreateDataHandle function creates a dynamic data
;                  exchange (DDE) object and fills the object with data from
;                  the specified buffer. A DDE application uses this function
;                  during transactions that involve passing data to the partner
;                  application.
;
; Parameter(s):    $data - Buffer that contains data to be copied to the DDE object.
;                  $afCmd (optiona) - Specifies the creation flags. This parameter
;                                      can be $HDATA_APPOWNED, which specifies that
;                                      the server application calling the
;                                      _DdeCreateDataHandle function owns the data
;                                      handle this function creates. This flag
;                                      enables the application to share the data
;                                      handle with other Dynamic Data Exchange
;                                      Management Library (DDEML) applications
;                                      rather than creating a separate handle to
;                                      pass to each application. If this flag is
;                                      specified, the application must eventually
;                                      free the shared memory object associated
;                                      with the handle by using the _DdeFreeDataHandle
;                                      function. If this flag is not specified,
;                                      the handle becomes invalid in the application
;                                      that created the handle after the data
;                                      handle is returned by the application's
;                                      DDE callback function or is used as a
;                                      parameter in another DDEML function.
;                  $hszItem (optional) - Handle to the string that specifies the
;                                        data item corresponding to the DDE object.
;                                        This handle must have been created by a
;                                        previous call to the _DdeCreateStringHandle
;                                        function. If the data handle is to be
;                                        used in an $XTYP_EXECUTE transaction,
;                                        this parameter must be 0.
;                  $wFmt (optional) - Specifies the standard clipboard format of the data.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is a data handle.
;                  If the function fails, the return value is 0.
;
; Author(s):       doudou
;===============================================================================
Func _DdeCreateDataHandle($data, $afCmd = 0, $hszItem = 0, $wFmt = $CF_TEXT)
	Local $pData, $cb
	If $CF_TEXT = $wFmt And $_DDEML_UNICODE Then $wFmt = $CF_UNICODETEXT
	$cb = _DDEML_CreateDataStruct($data, $pData, $wFmt)
	Local $res = DllCall("user32.dll", $_DDEML_HANDLETYPE, "DdeCreateDataHandle", "dword", $_DDEML_idInst, "ptr", DllStructGetPtr($pData, 1), "dword", $cb, "dword", 0, $_DDEML_HANDLETYPE, $hszItem, "uint", $wFmt, "uint", $afCmd)
	If 0 = $res[0] Then SetError(_DdeGetLastError())
	Return $res[0]
EndFunc   ;==>_DdeCreateDataHandle

;===============================================================================
; Function Name:   _DdeFreeDataHandle
; Description:     The _DdeFreeDataHandle function frees a dynamic data exchange
;                  (DDE) object and deletes the data handle associated with the
;                  object.
;
; Parameter(s):    $hData - Handle to the DDE object to be freed. This handle
;                            must have been created by a previous call to the
;                            _DdeCreateDataHandle function or returned by the
;                            _DdeClientTransaction function.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is True.
;                  If the function fails, the return value is False.
;
; Author(s):       doudou
;===============================================================================
Func _DdeFreeDataHandle($hData)
	Local $res = DllCall("user32.dll", "int", "DdeFreeDataHandle", $_DDEML_HANDLETYPE, $hData)
	If $res[0] Then Return True

	Return SetError(_DdeGetLastError(), 0, False)
EndFunc   ;==>_DdeFreeDataHandle
;===============================================================================
; Function Name:   _DdeGetData
; Description:     The _DdeGetData copies binary representation of data
;                  from the specified dynamic data exchange (DDE) object to the
;                  local buffer.
;
; Parameter(s):    $hData - Handle to the DDE object that contains the data to copy.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is the structure
;                  with byte array as sinlge member that contains the data.
;                  If the function fails, the return value is 0.
;
; Author(s):       doudou
;===============================================================================
Func _DdeGetData($hData)
	Local $res = DllCall("user32.dll", "dword", "DdeGetData", $_DDEML_HANDLETYPE, $hData, "ptr", 0, "dword", 0, "dword", 0)
	If $res[0] Then
		Local $tp = DllStructCreate("byte data[" & $res[0] & "]")
		$res = DllCall("user32.dll", "dword", "DdeGetData", $_DDEML_HANDLETYPE, $hData, "ptr", DllStructGetPtr($tp), "dword", $res[0], "dword", 0)
		If $res[0] Then Return $tp
	EndIf
	Return SetError(_DdeGetLastError(), $res[0], 0)
EndFunc   ;==>_DdeGetData
;===============================================================================
; Function Name:   _DdeGetDataAsStruct
; Description:     The _DdeGetDataAsStruct copies the data from the specified
;                  dynamic data exchange (DDE) object to the specified structure.
;
; Parameter(s):    $hData - Handle to the DDE object that contains the data to copy.
; Parameter(s):    $structOrString - Either reference to the structure or string with
;                                 structure definition.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is the structure
;                  whose members are filled with the DDE data.
;                  If the function fails, the return value is 0.
;
; Author(s):       doudou
;===============================================================================
Func _DdeGetDataAsStruct($hData, ByRef $structOrString)
	Local $tp = $structOrString
	If Not IsDllStruct($tp) Then $tp = DllStructCreate("" & $structOrString)
	If IsDllStruct($tp) Then
		$res = DllCall("user32.dll", "dword", "DdeGetData", $_DDEML_HANDLETYPE, $hData, "ptr", DllStructGetPtr($tp), "dword", DllStructGetSize($tp), "dword", 0)
		Return SetError(_DdeGetLastError(), $res[0], $tp)
	EndIf
	Return SetError(1, 0, 0)
EndFunc   ;==>_DdeGetDataAsStruct
;===============================================================================
; Function Name:   _DdeGetDataAsString
; Description:     The _DdeGetDataAsString copies string representation of data
;                  from the specified dynamic data exchange (DDE) object to the
;                  local buffer.
;
; Parameter(s):    $hData - Handle to the DDE object that contains the data to copy.
; Parameter(s):    $wFmt - (optional) string format, can be $CF_TEXT or $CF_UNICODETEXT.
;
; Requirement(s):  External:   user32.dll (it's already in system32).
;
; Return Value(s): If the function succeeds, the return value is the data string.
;                  If the function fails, the return value is "".
;
; Author(s):       doudou
;===============================================================================
Func _DdeGetDataAsString($hData, $wFmt = 0)
	Local $strType = "str"
	If $CF_UNICODETEXT = $wFmt Then $strType = "wstr"
	Local $res = DllCall("user32.dll", "dword", "DdeGetData", $_DDEML_HANDLETYPE, $hData, $strType, "", "dword", 32768, "dword", 0)
	If $res[0] Then Return $res[2]
	Return SetError(_DdeGetLastError(), $res[0], "")
EndFunc   ;==>_DdeGetDataAsString

; helper functions ;

Func _DDEML_CreateDataStruct($data, ByRef $pStruct, $wFmt = $CF_TEXT)
	Local $res = 0
	Select
		Case IsInt($data) And $CF_TEXT <> $wFmt And $CF_OEMTEXT <> $wFmt And $CF_UNICODETEXT <> $wFmt
			$res = 32
			If @OSArch = "IA64" Or @OSArch = "X64" Then $res = 64
			If 32 < $res Then
				$pStruct = DllStructCreate("int64")
			Else
				$pStruct = DllStructCreate("int")
			EndIf
			DllStructSetData($pStruct, 1, $data)

		Case IsFloat($data) And $CF_TEXT <> $wFmt And $CF_OEMTEXT <> $wFmt And $CF_UNICODETEXT <> $wFmt
			$res = 64
			$pStruct = DllStructCreate("double")
			DllStructSetData($pStruct, 1, $data)

		Case IsBinary($data)
			$res = BinaryLen($data)
			$pStruct = DllStructCreate("byte[" & $res & "]")
			DllStructSetData($pStruct, 1, $data)

		Case IsDllStruct($data)
			$res = DllStructGetSize($data)
			$pStruct = $data

		Case IsArray($data) Or IsObj($data)
			; TODO
			SetError($DMLERR_INVALIDPARAMETER)
;~             ConsoleWrite("_DDEML_CreateDataStruct: data type not yet supported" & @CRLF)
			Return 0

		Case Else
			Local $s = String($data)
			$res = StringLen($s) + 1
			If $CF_UNICODETEXT = $wFmt Then
				$pStruct = DllStructCreate("wchar[" & $res & "]")
			Else
				$pStruct = DllStructCreate("char[" & $res & "]")
			EndIf
			$res = DllStructGetSize($pStruct)
			DllStructSetData($pStruct, 1, $s)
	EndSelect

	Return $res
EndFunc   ;==>_DDEML_CreateDataStruct
