Source file: /~heha/messtech/matdde.zip/source/ddeinit/ddeinit.cpp

//+++++++++++++++++++++++++++++++
// +++++ DDEInit for MATLAB 16bit

#include <windows.h>
#include <ddeml.h>

#define	DLLMEX
extern "C"
{
    #include "..\header\mex.h"		    //alle Standard-MATLAB mex/mx-Funktionen
    #include "..\header\testargs.h"
}
#include "..\header\fastdde.h"

#pragma	hdrstop


#define	ARGS_IN_MIN 2		//ARGS_IN_MIN Argumente	muessen	mind. angegeben	sein
#define	ARGS_IN_MAX 2		//ARGS_IN_MAX Argumente	muessen	max. angegeben sein

#define	ARG1_IN	    prhs[0]	//Service
#define	ARG2_IN	    prhs[1]	//Topic

#define	ARG1_OUT    plhs[0]	//DDE Channel


//Prototypes
BOOL RegisterDDECallback( void );   //Instanzierung der	DDE-Callback-Funktion
void ExitFunction();		    //deinstalliert DDEML beim Beenden von MATLAB
void DisconnectMsgBox( HCONV );	    //Anzeige der MessageBox bei DDE-Disconnect


//Globale Variablen
static DWORD	    idInst	= (DWORD)0;		//Instance of app for DDEML
static BOOL	    FirstStart	= TRUE;			//s. RegisterDDECallback()

void (*lpfnExitFcn)() =	ExitFunction;			//Zeiger auf ExitFunction




HDDEDATA CALLBACK _loadds DDECallback (	WORD wType, WORD cbFormat, HCONV hConv,	HSZ, HSZ hszItem, HDDEDATA hData, DWORD, DWORD)
{
    void (FAR PASCAL *lpfnDDEAdvise)( HCONV, HSZ, HDDEDATA, WORD );		//Zeiger auf DDEAdvise() in Modul ddeadv.dll


    switch ( wType )
    {
	case XTYP_DISCONNECT:		
	    DisconnectMsgBox( hConv );
	    return (HDDEDATA) NULL;


	case XTYP_ADVDATA:
	{
	    HMODULE hModule = GetModuleHandle( (LPCSTR)	"ddeadv.dll" );
		if ( hModule )
		{
		    lpfnDDEAdvise = (void (FAR PASCAL*)	(HCONV,	HSZ, HDDEDATA, WORD)) GetProcAddress( (HINSTANCE)hModule,
									    (LPCSTR) "DDEAdvise" );
		    if ( lpfnDDEAdvise )
		    {
			(*lpfnDDEAdvise)( hConv, hszItem, hData, cbFormat );	//Absprung in die Funktion DDEAdvise()
			return (HDDEDATA) DDE_FACK;
		    }		

		}
	    return (HDDEDATA) DDE_FNOTPROCESSED;	    
	}
	
	default:
	    return (HDDEDATA) NULL;
    }

}


void DisconnectMsgBox( HCONV hConv )
{
    CONVINFO ci;
    
    HLOCAL hLocalSvc;
    HLOCAL hLocalTopic;
    HLOCAL hLocalBuffer;
    
    char* szSvcPartner;
    char* szTopic;
    char* szBuffer;
    
    ci.cb = sizeof(CONVINFO);
    DdeQueryConvInfo( hConv, (DWORD)QID_SYNC, &ci);

    int	cbPartner = (int)DdeQueryString( idInst, ci.hszSvcPartner, (LPSTR) NULL, 0, 0);
    hLocalSvc =	LocalAlloc( LPTR, cbPartner + 2	);
    szSvcPartner = (char*) LocalLock( hLocalSvc	);
    DdeQueryString( idInst, ci.hszSvcPartner, (LPSTR)szSvcPartner, cbPartner + 1, CP_WINANSI);

    int	cbTopic	= (int)DdeQueryString( idInst, ci.hszTopic, (LPSTR) NULL, 0, 0);
    hLocalTopic	= LocalAlloc( LPTR, cbTopic + 2	);
    szTopic = (char*) LocalLock( hLocalTopic );
    DdeQueryString( idInst, ci.hszTopic, (LPSTR)szTopic, cbTopic + 1, CP_WINANSI);
							      
    hLocalBuffer = LocalAlloc( LPTR, cbPartner + cbTopic + 65 /* <- restlicher Text*/ );
    szBuffer = (char*) LocalLock( hLocalBuffer );
    
    wsprintf( szBuffer,	"Disconnect request from ...\r\n\r\nServer:  %s\r\nTopic:   %s", szSvcPartner, szTopic );
    MessageBox(	hWndMATLABCmd, szBuffer, "MATLAB  DDE -	Toolbox", (MB_APPLMODAL	| MB_ICONINFORMATION | MB_OK) );
	    
    LocalUnlock( hLocalSvc );
    LocalUnlock( hLocalTopic );
    LocalUnlock( hLocalBuffer );
}




extern "C" void	mexFunction(
	  int	  nlhs,			//number of output matrizes
	  Matrix  *plhs[],
	  int	  nrhs,			//number of input matrizes
	  Matrix  *prhs[]
	  )

{
    unsigned long hChannel[] = {0, 0};	//2 mal	32 bit (ChannelHandle, was zurueckgegeben wird)

    if (    TestIOArgs(	nrhs, ARGS_IN_MIN, ARGS_IN_MAX ) && //alle erforderlichen Parameter angegeben?
	    TestServiceArg( ARG1_IN ) &&		    //Service-Argument ok?
	    TestTopicArg( ARG2_IN ) &&			    //Topic-Argument ok?
	    RegisterDDECallback()   )			    //Instanzieren der DDE-Callback-Funktion
							    //nur beim ersten Aufruf von ddeinit
    {									    
	HCONV	hConv =	0;	    //Conversation handle
	HSZ	hszService;
	HSZ	hszTopic;

	char* szService;
	char* szTopic;
	int m,n;

    //szService	und szTopic aus	uebergebenen Parametern	festlegen
	szService = (char*) mxCalloc( m= (int)mxGetN(ARG1_IN) +	1, sizeof(char)	);
	szTopic	= (char*) mxCalloc( n= (int)mxGetN(ARG2_IN) + 1, sizeof(char) );
	
	if ( szService != 0 && szTopic != 0 )
	{
	    mxGetString( ARG1_IN, szService, m );
	    mxGetString( ARG2_IN, szTopic, n );
    
    //StringHandles erzeugen
	    hszService = DdeCreateStringHandle ( idInst, szService, CP_WINANSI );
	    hszTopic = DdeCreateStringHandle ( idInst, szTopic,	CP_WINANSI );
	    
	    if ( hszService != 0 && hszTopic !=	0 )
	    {
    //DDE-Verbindung herstellen
		hConv =	DdeConnect ( idInst, hszService, hszTopic, (PCONVCONTEXT) NULL );

		if ( hConv )
		{
		    hChannel[0]	= hConv;    //bit 0-31
		    hChannel[1]	= idInst;   //bit 32-63
		}
		
	    }
	    else HandleDdeError(DdeGetLastError(idInst));
	    
	    if ( hszService ) DdeFreeStringHandle ( idInst, hszService );
	    if ( hszTopic ) DdeFreeStringHandle	( idInst, hszTopic );
	}
	else
	{
	    mexPrintf( "???  Memory allocation error.\r\n" );
	    ErrorBeep();
	}

	if ( szService ) mxFree( szService );
	if ( szTopic ) mxFree( szTopic );
    }

    ARG1_OUT = mxCreateFull(1, 1, REAL);
    hmemcpy( (char huge*)mxGetPr(ARG1_OUT), (char*)hChannel, sizeof(double) );
}



BOOL RegisterDDECallback() 
{
    if ( FirstStart )	//beim 1. Aufruf von DDEINIT
    {
	//DDE initialisieren (Windows DDEML.DLL)
	UINT DDEInitResult = DdeInitialize ( (LPDWORD)&idInst, (PFNCALLBACK)DDECallback,
					    APPCLASS_STANDARD |	APPCMD_CLIENTONLY, 0L );
	if ( DDEInitResult != DMLERR_NO_ERROR )
	{
	    HandleDdeError(DDEInitResult);
	    return FALSE;				    
	}

	mexAtExit ( (*lpfnExitFcn) );	//fuer DdeUninitialize(..)
	FirstStart = FALSE;
    }

    return TRUE;
}


void ExitFunction()
{
    if ( idInst	!= (DWORD)0 )
	DdeUninitialize	( idInst );
}




Detected encoding: ASCII (7 bit)2