CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

DDE.CPP (19766B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /***************************************************************************
     17  **   C O N F I D E N T I A L --- W E S T W O O D    S T U D I O S        **
     18  ***************************************************************************
     19  *                                                                         *
     20  *                 Project Name : Dynamic Data Encapsulation               *
     21  *                                                                         *
     22  *                    File Name : DDE.CPP		                             *
     23  *                                                                         *
     24  *                   Programmer : Steve Wetherill                          *
     25  *                                                                         *
     26  *                   Start Date : June 1, 1996                             *
     27  *                                                                         *
     28  *                  Last Update : June 8, 1996 [SW]                        *
     29  *                                                                         *
     30  *-------------------------------------------------------------------------*
     31  * Functions:                                                              *
     32  *   Instance_Class::InstanceClass -- class constructor                    *
     33  *   Instance_Class::InstanceClass -- class destructor                     *
     34  *   Instance_Class::Enable_Callback -- enables local processing of pokes  *
     35  *   Instance_Class::Register_Servers -- registers a local DDE DNS service *
     36  *   Instance_Class::Cleanup_App -- currently does nothing                 *
     37  *   Instance_Class::Test_Server_Running -- does a trial connect to remote *
     38  *	  Instance_Class::Open_Poke_Connection -- pokes some data to server	  *
     39  *   Instance_Class::Close_Poke_Connectionp -- closes connection to remote *
     40  *   Instance_Class::Poke_Server -- sends a chunk of data to remote        *
     41  *   Instance_Class::dde_callback -- processes DDE transactions            *
     42  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     43 
     44 #ifdef WIN32
     45 #include	<windows.h>
     46 #include	"dde.h"
     47 
     48 /***************************************************************************
     49  * These are static members of Instance_Class
     50  *=========================================================================*/
     51 
     52 DWORD	Instance_Class::id_inst;			// instance identifier set by DdeInitialize
     53 BOOL		Instance_Class::process_pokes;	// controls response to pokes
     54 char 	Instance_Class::ascii_name[32];	// name of server
     55 
     56 #if (0)	//ST - 5/8/2019
     57 static BOOL CALLBACK	(*Instance_Class::callback) (
     58 			LPBYTE pointer,		// pointer to received data
     59 			long	length			// length of received data or advisory flag
     60 			) = NULL;
     61 #endif
     62 
     63 /***************************************************************************
     64  * Instance_Class::InstanceClass -- class constructor              			*
     65  *                                                                         *
     66  * INPUT:                                                                  *
     67  *		name1		null terminated ASCII client name									*
     68  *		name1		null terminated ASCII server name									*
     69  *                                                                         *
     70  * OUTPUT:                                                                 *
     71  *		dde_error = TRUE if error occurs when initializing DDE					*
     72  *                                                                         *
     73  * WARNINGS:                                                               *
     74  *		none.																						*
     75  *                                                                         *
     76  * HISTORY:                                                                *
     77  *   6/1/1996 SW : Created.                                                *
     78  *=========================================================================*/
     79 
     80 Instance_Class::Instance_Class( LPSTR name1, LPSTR name2 )
     81 {
     82 	name1; name2;
     83 	return;
     84 
     85 #if (0)	//ST - 5/8/2019
     86 	dde_error = FALSE;		// no errors
     87 	process_pokes = FALSE;	// disable pokes in callback
     88 
     89 	id_inst = 0;				// set to 0 for first time through
     90 	conv_handle = 0;   		// conversation handle reset
     91 
     92 	lstrcpy( ascii_name, name1 );	// keep a record of ASCII name
     93 
     94 	if	( DdeInitialize(
     95 		(LPDWORD) &id_inst,			// instance identifier
     96 		dde_callback,
     97 		APPCLASS_STANDARD | 			// filter server messages
     98 		CBF_FAIL_SELFCONNECTIONS,	// prevent from connecting with self
     99 		0) != DMLERR_NO_ERROR) {   // reserved
    100 			dde_error = TRUE;			// flag an error
    101 	}
    102 
    103 	local_name = DdeCreateStringHandle(
    104 		id_inst,         		// instance identifier
    105     	name1,     				// string to register
    106     	CP_WINANSI);    		// Windows ANSI code page
    107 
    108 	remote_name = DdeCreateStringHandle(
    109 		id_inst,         		// instance identifier
    110     	name2,     				// string to register
    111     	CP_WINANSI);    		// Windows ANSI code page
    112 
    113 	poke_topic = DdeCreateStringHandle(
    114 		id_inst,         		// instance identifier
    115 		"POKE TOPIC", 			// System topic
    116 		CP_WINANSI);    		// Windows ANSI code page
    117 
    118 	poke_item = DdeCreateStringHandle(
    119 		id_inst,         		// instance identifier
    120 		"POKE ITEM", 			// System topic
    121 		CP_WINANSI);    		// Windows ANSI code page
    122 
    123 	system_topic = DdeCreateStringHandle(
    124 		id_inst,         		// instance identifier
    125 		SZDDESYS_TOPIC, 		// System topic
    126 		CP_WINANSI);    		// Windows ANSI code page
    127 #endif
    128 }
    129 
    130 /***************************************************************************
    131  * Instance_Class::~Instance_Class -- class destructor	              		*
    132  *                                                                         *
    133  * INPUT:                                                                  *
    134  *    none.                                                                *
    135  *                                                                         *
    136  * OUTPUT:                                                                 *
    137  *		none.																						*
    138  *                                                                         *
    139  * WARNINGS:                                                               *
    140  *		none.																						*
    141  *                                                                         *
    142  * HISTORY:                                                                *
    143  *   6/1/1996 SW : Created.                                                *
    144  *=========================================================================*/
    145 
    146 Instance_Class::~Instance_Class()
    147 {
    148 	DdeUninitialize( id_inst );
    149 }
    150 
    151 /***************************************************************************
    152  * Instance_Class::Enable_Callback -- enables user callback						*
    153  *                                                                         *
    154  * INPUT:                                                                  *
    155  *    TRUE = enable poke processing														*
    156  *    FALSE = disable poke processing													*
    157  *                                                                         *
    158  * OUTPUT:                                                                 *
    159  *		echos the input																		*
    160  *                                                                         *
    161  * WARNINGS:                                                               *
    162  *		user callback must be explicitly enabled. Disbabled by default.		*
    163  *                                                                         *
    164  * HISTORY:                                                                *
    165  *   6/1/1996 SW : Created.                                                *
    166  *=========================================================================*/
    167 
    168 BOOL	Instance_Class::Enable_Callback( BOOL flag )		// enable or disable callback
    169 {
    170 	return (process_pokes = flag);
    171 
    172 }
    173 
    174 /***************************************************************************
    175  * Instance_Class::Register_Server -- registers a local DDE DNS service    *
    176  *                                                                         *
    177  * INPUT:                                                                  *
    178  *    BOOL CALLBACK ( *callback_fnc) ( LPBYTE, DWORD) = user poke callbacl *
    179  *                                                                         *
    180  * OUTPUT:                                                                 *
    181  *		TRUE == success																		*
    182  *		FALSE == failed																		*
    183  *                                                                         *
    184  * WARNINGS:                                                               *
    185  *		none.																						*
    186  *                                                                         *
    187  * HISTORY:                                                                *
    188  *   6/1/1996 SW : Created.                                                *
    189  *=========================================================================*/
    190 #if (0)	//ST - 5/8/2019
    191 BOOL	Instance_Class::Register_Server( BOOL CALLBACK ( *callback_fnc) (LPBYTE, long) )
    192 {
    193 
    194 	if (DdeNameService( id_inst, local_name,	0L, DNS_REGISTER ) != 0L) {
    195 		callback = callback_fnc;
    196 		return ( TRUE );
    197 	} else {
    198 		return ( FALSE );
    199 	}
    200 }
    201 #endif
    202 
    203 /***************************************************************************
    204  * Instance_Class::Test_Server_Running -- does a trial connect to remote   *
    205  *                                                                         *
    206  * INPUT:                                                                  *
    207  *    name = HSZ string handle of server name.										*
    208  *                                                                         *
    209  * OUTPUT:                                                                 *
    210  *		TRUE == successfully connected to remote										*
    211  *		FALSE == failed to connect															*
    212  *                                                                         *
    213  * WARNINGS:                                                               *
    214  *		- Can be called for local or remote server but of course will 			*
    215  *      fail if a called for local and local server is not "up".				*
    216  *		- Disconects before exiting.														*
    217  *                                                                         *
    218  * HISTORY:                                                                *
    219  *   6/1/1996 SW : Created.                                                *
    220  *=========================================================================*/
    221 
    222 BOOL	Instance_Class::Test_Server_Running( HSZ name )
    223 {
    224 
    225 	if( Open_Poke_Connection( name ) == TRUE) {
    226 		Close_Poke_Connection();
    227 		return( TRUE );
    228 	} else {
    229 		return( FALSE );
    230 	}
    231 }
    232 
    233 /***************************************************************************
    234  *	Instance_Class::Open_Poke_Connection -- open a connection to server		*
    235  *                                                                         *
    236  * INPUT:                                                                  *
    237  *    name = HSZ server name.																*
    238  *                                                                         *
    239  * OUTPUT:                                                                 *
    240  *		TRUE == successfully opened connection											*
    241  *		FALSE == failed to connect															*
    242  *                                                                         *
    243  * WARNINGS:                                                               *
    244  *		Can be called for local or remote server but of course will 			*
    245  *    fail if a called for local and local server is not "up".					*
    246  *                                                                         *
    247  * HISTORY:                                                                *
    248  *   6/1/1996 SW : Created.                                                *
    249  *=========================================================================*/
    250 
    251 BOOL	Instance_Class::Open_Poke_Connection( HSZ name )
    252 {
    253 	conv_handle = DdeConnect(
    254 		id_inst,           	// instance identifier
    255 		name,         			// service name string handle
    256 		poke_topic,        	// topic string handle
    257 		(PCONVCONTEXT) NULL);// use default context
    258 
    259 	if (conv_handle == NULL) {
    260 		return FALSE;
    261 	} else {
    262 		return TRUE;
    263 	}
    264 }
    265 
    266 /***************************************************************************
    267  *	Instance_Class::Close_Poke_Connection -- closes poke connection			*
    268  *                                                                         *
    269  * INPUT:                                                                  *
    270  *    none.																						*
    271  *                                                                         *
    272  * OUTPUT:                                                                 *
    273  *		TRUE == successfully closed connection											*
    274  *		FALSE == failed to close connection for some reason						*
    275  *                                                                         *
    276  * WARNINGS:                                                               *
    277  *		none.																						*
    278  *                                                                         *
    279  * HISTORY:                                                                *
    280  *   6/1/1996 SW : Created.                                                *
    281  *=========================================================================*/
    282 
    283 BOOL	Instance_Class::Close_Poke_Connection( void )
    284 {
    285 	if( conv_handle ) {
    286 		HCONV	temp_handle = conv_handle;
    287 		conv_handle = NULL;
    288 		return( DdeDisconnect( temp_handle ));
    289 	} else {
    290 		return( TRUE );
    291 	}
    292 }
    293 
    294 /***************************************************************************
    295  *	Instance_Class::Poke_Server -- pokes some data to server						*
    296  *                                                                         *
    297  * INPUT:                                                                  *
    298  *    poke_data	points to data to send to remote									*
    299  *    poke_length	length of buffer to send											*
    300  *                                                                         *
    301  * OUTPUT:                                                                 *
    302  *		TRUE == successfully poked the data												*
    303  *		FALSE == failed to connect															*
    304  *                                                                         *
    305  * WARNINGS:                                                               *
    306  *		has a 3 second timeout (change POKE_TIMEOUT, in milliseconds)			*
    307  *                                                                         *
    308  * HISTORY:                                                                *
    309  *   6/1/1996 SW : Created.                                                *
    310  *=========================================================================*/
    311 
    312 #define	POKE_TIMEOUT	60*1000	      // 60 sec timeout
    313 
    314 BOOL	Instance_Class::Poke_Server( LPBYTE poke_data, DWORD poke_length )
    315 {
    316 
    317 	if( DdeClientTransaction(
    318 
    319 		poke_data,					// address of data to pass to server
    320 	  	poke_length,				// length of data
    321 		conv_handle,				// handle of conversation
    322 		poke_topic,					// handle of item name string
    323 		CF_TEXT,						// no special clipboard data format
    324 		XTYP_POKE,					// transaction type
    325 		POKE_TIMEOUT,							// time-out duration (millisecs)
    326 		(LPDWORD) NULL		 		// address of transaction result (don't check)
    327 	   ) == 0) {
    328 
    329 		return( FALSE);
    330 	} else {
    331 		return( TRUE );
    332 	}
    333 }
    334 
    335 /***************************************************************************
    336  *	Instance_Class::dde_callback -- callback dde event handler					*
    337  *                                                                         *
    338  * INPUT:                                                                  *
    339  *		dde_event	transaction type														*
    340  *		uFmt			clipboard data format												*
    341  *		hconv			handle of the conversation											*
    342  *		hsz1			handle of a string													*
    343  *		hsz2			handle of a string													*
    344  *		hdata			handle of a global memory object									*
    345  *		dwData1		transaction-specific data											*
    346  *		dwData2 		transaction-specific data											*
    347  *                                                                         *
    348  * OUTPUT:                                                                 *
    349  *		context specific HDDEDATA object													*
    350  *                                                                         *
    351  * WARNINGS:                                                               *
    352  *	  	NOTE: declared as HDDEDATA CALLBACK which means PASCAL parameters		*
    353  *                                                                         *
    354  * HISTORY:                                                                *
    355  *   6/1/1996 SW : Created.                                                *
    356  *=========================================================================*/
    357 
    358 HDDEDATA CALLBACK Instance_Class::dde_callback(
    359 
    360 	UINT  dde_event,	// transaction type
    361 	UINT  uFmt,			// clipboard data format
    362 	HCONV  ,				// handle of the conversation
    363 	HSZ  hsz1,			// handle of a string
    364 	HSZ  hsz2,			// handle of a string
    365 	HDDEDATA  hdata,	// handle of a global memory object
    366 	DWORD  			,	// transaction-specific data
    367 	DWORD  			 	// transaction-specific data
    368 	)
    369 {
    370 	dde_event;
    371 	uFmt;
    372 	hsz1;
    373 	hsz2;
    374 	hdata;
    375 	return (HDDEDATA)NULL;
    376 
    377 #if (0) // ST 5/8/2019
    378 	if (!Instance_Class::callback){
    379 		return (HDDEDATA) NULL;
    380 	}
    381 
    382 	switch ( dde_event ) {
    383 
    384 		case XTYP_REGISTER:
    385       case XTYP_UNREGISTER:
    386 
    387 			return (HDDEDATA) NULL;
    388 
    389 		case XTYP_ADVDATA:
    390 			return (HDDEDATA) DDE_FACK;
    391 
    392 		case XTYP_XACT_COMPLETE:
    393 
    394 			return (HDDEDATA) NULL;
    395 
    396 		case XTYP_DISCONNECT:
    397 
    398 			Instance_Class::callback( NULL, DDE_ADVISE_DISCONNECT);
    399 			return (HDDEDATA) NULL;
    400 
    401 		case	XTYP_CONNECT: {
    402 
    403 			char	buffer[32];
    404 
    405 			DdeQueryString (Instance_Class::id_inst, hsz2, buffer, sizeof (buffer), 0) ;
    406 
    407 			if (0 != strcmp (buffer, Instance_Class::ascii_name)) {
    408 				return (HDDEDATA) NULL;
    409 			}
    410 
    411 			DdeQueryString (Instance_Class::id_inst, hsz1, buffer, sizeof (buffer), 0) ;
    412 
    413 			if (0 != strcmp (buffer, "POKE TOPIC")) {
    414 				return (HDDEDATA) NULL;
    415 			}
    416 
    417 			Instance_Class::callback( NULL, DDE_ADVISE_CONNECT);
    418 			return (HDDEDATA) TRUE;
    419 		}
    420 
    421 		case	XTYP_POKE:
    422 
    423 			if	(Instance_Class::process_pokes == FALSE ) {
    424 				return (HDDEDATA) DDE_FNOTPROCESSED;	// processing disabled
    425 			} else {
    426 
    427 				char	buffer[32];
    428 
    429 				DdeQueryString (Instance_Class::id_inst, hsz1, buffer, sizeof (buffer), 0) ;
    430 
    431 				if (0 != strcmp (buffer, "POKE TOPIC")) {
    432 					return (HDDEDATA) DDE_FNOTPROCESSED;
    433 				} else if (uFmt == CF_TEXT) {					// make sure it's CF_TEXT
    434 
    435 					BOOL processed;
    436 					BYTE FAR *pdata;
    437 					DWORD dw_length;
    438 
    439 					if ( (pdata = DdeAccessData( hdata, &dw_length)) == NULL ) {
    440 						return (HDDEDATA) DDE_FNOTPROCESSED;
    441 					}
    442 
    443 					processed = Instance_Class::callback((LPBYTE) pdata, dw_length);
    444 
    445 					DdeUnaccessData( hdata );
    446 
    447 					if (processed == TRUE) {
    448 						return (HDDEDATA) DDE_FACK;
    449 					} else {
    450 						return (HDDEDATA) NULL;
    451 					}
    452 
    453 				}
    454 			}
    455 
    456 		default:
    457       	return (HDDEDATA) NULL;
    458     }
    459 #endif
    460 }
    461 
    462 #endif	//WIN32