CnC_Remastered_Collection

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

DDE.CPP (19838B)


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