CnC_Remastered_Collection

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

CCDDE.CPP (22996B)


      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 /***********************************************************************************************
     18  ***              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               ***
     19  ***********************************************************************************************
     20  *                                                                                             *
     21  *                 Project Name : Command & Conquer - Red Alert                                *
     22  *                                                                                             *
     23  *                    File Name : CCDDE.CPP                                                    *
     24  *                                                                                             *
     25  *                   Programmer : Steve Tall                                                   *
     26  *                                                                                             *
     27  *                   Start Date : 10/04/95                                                     *
     28  *                                                                                             *
     29  *                  Last Update : August 5th, 1996 [ST]                                        *
     30  *                                                                                             *
     31  *---------------------------------------------------------------------------------------------*
     32  * Overview:                                                                                   *
     33  *   C&C's interface to the DDE class                                                          *
     34  *                                                                                             *
     35  *---------------------------------------------------------------------------------------------*
     36  *                                                                                             *
     37  * Functions:                                                                                  *
     38  * DDE_Callback -- DDE server callback function                                                *
     39  * DDEServerClass::DDEServerClass -- class constructor                                         *
     40  * DDEServerClass::Enable -- Enables the DDE callback                                          *
     41  * DDEServerClass::Disable -- Disables the DDE callback                                        *
     42  * DDEServerClass::~DDEServerClass -- class destructor                                         *
     43  * DDESC::Callback -- callback function. Called from the DDE_Callback wrapper function         *
     44  * DDESC::Get_MPlayer_Game_Info -- returns a pointer to the multiplayer setup info from wchat  *
     45  * DDESC::Delete_MPlayer_Game_Info -- clears out multi player game setup info                  *
     46  * DDESC::Time_Since_Heartbeat -- returns the time in ticks since the last heartbeat from wchat*
     47  *                                                                                             *
     48  * Send_Data_To_DDE_Server -- sends a packet to WChat                                          *
     49  *                                                                                             *
     50  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     51 
     52 #ifdef WIN32
     53 
     54 #include <WINDOWS.H>
     55 #include "ccdde.h"
     56 #include <stdio.h>
     57 #include <timer.h>
     58 
     59 DDEServerClass	DDEServer;				//Instance of the DDE Server class
     60 
     61 Instance_Class	*DDE_Class = NULL;	// pointer for client callback
     62 												// this *must* be called DDE_Class
     63 
     64 BOOL RA95AlreadyRunning = FALSE;		//Was there an instance of Red Alert 95 already running when we started?
     65 
     66 /*
     67 ** Misc externs so we dont have to include FUNCTION.H
     68 */
     69 extern HWND 			MainWindow;
     70 extern TimerClass	GameTimer;
     71 extern bool			GameTimerInUse;
     72 extern void 			WWDebugString (char *string);
     73 
     74 
     75 /***********************************************************************************************
     76  * DDE_Callback -- DDE server callback function                                                *
     77  *                                                                                             *
     78  *   Just acts as a wrapper for the DDEServerClass callback function                           *
     79  *                                                                                             *
     80  * INPUT:    ptr to data from client                                                           *
     81  *           length of data                                                                    *
     82  *                                                                                             *
     83  * OUTPUT:   Nothing                                                                           *
     84  *                                                                                             *
     85  * WARNINGS: None                                                                              *
     86  *                                                                                             *
     87  * HISTORY:                                                                                    *
     88  *    6/8/96 3:19PM ST : Created                                                               *
     89  *=============================================================================================*/
     90 BOOL CALLBACK DDE_Callback (unsigned char *data, long length)
     91 {
     92 	return (DDEServer.Callback(data, length));
     93 }
     94 
     95 
     96 
     97 
     98 /***********************************************************************************************
     99  * DDEServerClass::DDEServerClass -- class constructor                                         *
    100  *                                                                                             *
    101  *                                                                                             *
    102  *                                                                                             *
    103  * INPUT:    Nothing                                                                           *
    104  *                                                                                             *
    105  * OUTPUT:   Nothing                                                                           *
    106  *                                                                                             *
    107  * WARNINGS: None                                                                              *
    108  *                                                                                             *
    109  * HISTORY:                                                                                    *
    110  *    6/8/96 3:20PM ST : Created                                                               *
    111  *=============================================================================================*/
    112 DDEServerClass::DDEServerClass(void)
    113 {
    114 	MPlayerGameInfo = NULL;		//Flag that we havnt received a start game info packet yet
    115 
    116 	//DDE_Class = new Instance_Class ("CONQUER", "WCHAT");
    117 	DDE_Class = new Instance_Class ("REDALERT", "WCHAT");
    118 
    119 	DDE_Class->Enable_Callback( TRUE );
    120 	IsEnabled = TRUE;
    121 
    122 	if (DDE_Class->Test_Server_Running(DDE_Class->local_name)){
    123 		RA95AlreadyRunning = TRUE;
    124 	}else{
    125 		//DDE_Class->Register_Server( DDE_Callback );				// ST - 5/8/2019
    126 	}
    127 }
    128 
    129 
    130 
    131 /***********************************************************************************************
    132  * DDEServerClass::Enable -- Enables the DDE callback                                          *
    133  *                                                                                             *
    134  *                                                                                             *
    135  *                                                                                             *
    136  * INPUT:    Nothing                                                                           *
    137  *                                                                                             *
    138  * OUTPUT:   Nothing                                                                           *
    139  *                                                                                             *
    140  * WARNINGS: None                                                                              *
    141  *                                                                                             *
    142  * HISTORY:                                                                                    *
    143  *    8/5/96 9:44PM ST : Created                                                               *
    144  *=============================================================================================*/
    145 void DDEServerClass::Enable(void)
    146 {
    147 	if (!IsEnabled){
    148 		DDE_Class->Enable_Callback( TRUE );
    149 		IsEnabled = TRUE;
    150 	}
    151 }
    152 
    153 
    154 
    155 /***********************************************************************************************
    156  * DDEServerClass::Disable -- Disables the DDE callback                                        *
    157  *                                                                                             *
    158  *                                                                                             *
    159  *                                                                                             *
    160  * INPUT:    Nothing                                                                           *
    161  *                                                                                             *
    162  * OUTPUT:   Nothing                                                                           *
    163  *                                                                                             *
    164  * WARNINGS: None                                                                              *
    165  *                                                                                             *
    166  * HISTORY:                                                                                    *
    167  *    8/5/96 9:44PM ST : Created                                                               *
    168  *=============================================================================================*/
    169 void DDEServerClass::Disable(void)
    170 {
    171 	if (IsEnabled){
    172 		DDE_Class->Enable_Callback( FALSE );
    173 		IsEnabled = FALSE;
    174 	}
    175 }
    176 
    177 
    178 
    179 
    180 
    181 
    182 /***********************************************************************************************
    183  * DDEServerClass::~DDEServerClass -- class destructor                                         *
    184  *                                                                                             *
    185  *                                                                                             *
    186  *                                                                                             *
    187  * INPUT:    Nothing                                                                           *
    188  *                                                                                             *
    189  * OUTPUT:   Nothing                                                                           *
    190  *                                                                                             *
    191  * WARNINGS: None                                                                              *
    192  *                                                                                             *
    193  * HISTORY:                                                                                    *
    194  *    6/8/96 3:20PM ST : Created                                                               *
    195  *=============================================================================================*/
    196 DDEServerClass::~DDEServerClass(void)
    197 {
    198 	Delete_MPlayer_Game_Info();
    199 	delete( DDE_Class );
    200 }
    201 
    202 
    203 
    204 /***********************************************************************************************
    205  * DDESC::Callback -- callback function. Called from the DDE_Callback wrapper function         *
    206  *                                                                                             *
    207  *                                                                                             *
    208  *                                                                                             *
    209  * INPUT:    data from DDE client                                                              *
    210  *           length of data                                                                    *
    211  *                                                                                             *
    212  * OUTPUT:   Nothing                                                                           *
    213  *                                                                                             *
    214  * WARNINGS: Data has length and type as first 2 ints                                          *
    215  *                                                                                             *
    216  * HISTORY:                                                                                    *
    217  *    6/8/96 3:21PM ST : Created                                                               *
    218  *=============================================================================================*/
    219 BOOL DDEServerClass::Callback(unsigned char *data, long length)
    220 {
    221 
    222 	/*
    223 	** If the packet length < 0 then this is a special advisory packet
    224 	*/
    225 	if ( length<0 ) {
    226 
    227 		switch( length ) {
    228 
    229 			case	DDE_ADVISE_CONNECT:
    230 				WWDebugString("RA95 - DDE advisory: client connect detected.");
    231 				return TRUE;
    232 
    233 			case	DDE_ADVISE_DISCONNECT:
    234 				WWDebugString("RA95 - DDE advisory: client disconnect detected.");
    235 				return TRUE;
    236 
    237 			default:
    238 				WWDebugString("RA95 - DDE advisory: Unknown DDE advise type.");
    239 				return FALSE;
    240 		}
    241 
    242 	}else{
    243 
    244 		/*
    245 		** Packet must be at least the length of the packet type & size fields to be valid
    246 		*/
    247 		if (length < 2*sizeof(int)) {
    248 			WWDebugString ("RA95 - Received invalid packet.");
    249 			return (FALSE);
    250 		}
    251 
    252 		/*
    253 		** Find out what kind of packet this is and its length.
    254 		*/
    255 		int *packet_pointer = (int *)data;
    256 		int  actual_length = ntohl(*packet_pointer++);
    257 		int  packet_type =  ntohl(*packet_pointer++);
    258 
    259 		/*
    260 		** Strip the ID int from the start of the packet
    261 		*/
    262 		data   += 2*sizeof (int);
    263 		length -= 2*sizeof (int);
    264 		actual_length -= 2*sizeof (int);
    265 
    266 		/*
    267 		** Take the appropriate action for the packet type
    268 		*/
    269 		switch ( packet_type ){
    270 
    271 			/*
    272 			** This is a packet with the info required for starting a new internet game. This is really
    273 		 	* just C&CSPAWN.INI sent from WChat instead of read from disk.
    274 			*/
    275 			case DDE_PACKET_START_MPLAYER_GAME:
    276 				WWDebugString("RA95 - Received start game packet.");
    277 				Delete_MPlayer_Game_Info();
    278 				MPlayerGameInfo = new char [actual_length + 1];
    279 				memcpy (MPlayerGameInfo, data, actual_length);
    280 				*(MPlayerGameInfo + actual_length) = 0;		//Terminator in case we treat it as a string
    281 				MPlayerGameInfoLength = actual_length;
    282 				LastHeartbeat = 0;
    283 				break;
    284 
    285 			case DDE_TICKLE:
    286 				WWDebugString("RA95 - Received 'tickle' packet.");
    287 				//SetForegroundWindow ( MainWindow );
    288 				//ShowWindow ( MainWindow, SW_SHOWMAXIMIZED );
    289 				break;
    290 
    291 			case DDE_PACKET_HEART_BEAT:
    292 				WWDebugString("RA95 - Received heart beat packet.");
    293 				if (GameTimerInUse){
    294 					LastHeartbeat = GameTimer.Time();
    295 				}else{
    296 					LastHeartbeat = 0;
    297 				}
    298 				break;
    299 
    300 			default:
    301 				WWDebugString("RA95 - Received unrecognised packet.");
    302 				break;
    303 
    304 		}
    305 	}
    306 
    307 	return (TRUE);
    308 
    309 }
    310 
    311 
    312 
    313 /***********************************************************************************************
    314  * DDESC::Get_MPlayer_Game_Info -- returns a pointer to the multiplayer setup info from wchat  *
    315  *                                                                                             *
    316  *                                                                                             *
    317  *                                                                                             *
    318  * INPUT:    Nothing                                                                           *
    319  *                                                                                             *
    320  * OUTPUT:   ptr to data in .INI file format                                                   *
    321  *                                                                                             *
    322  * WARNINGS: None                                                                              *
    323  *                                                                                             *
    324  * HISTORY:                                                                                    *
    325  *    6/8/96 3:23PM ST : Created                                                               *
    326  *=============================================================================================*/
    327 char *DDEServerClass::Get_MPlayer_Game_Info (void)
    328 {
    329 	return (MPlayerGameInfo);
    330 }
    331 
    332 
    333 
    334 /***********************************************************************************************
    335  * DDESC::Delete_MPlayer_Game_Info -- clears out multi player game setup info                  *
    336  *                                                                                             *
    337  *                                                                                             *
    338  *                                                                                             *
    339  * INPUT:    Nothing                                                                           *
    340  *                                                                                             *
    341  * OUTPUT:   Nothing                                                                           *
    342  *                                                                                             *
    343  * WARNINGS: None                                                                              *
    344  *                                                                                             *
    345  * HISTORY:                                                                                    *
    346  *    6/8/96 3:24PM ST : Created                                                               *
    347  *=============================================================================================*/
    348 void DDEServerClass::Delete_MPlayer_Game_Info(void)
    349 {
    350 	if (MPlayerGameInfo){
    351 		delete [] MPlayerGameInfo;
    352 		MPlayerGameInfo = NULL;
    353 	}
    354 }
    355 
    356 
    357 
    358 /***********************************************************************************************
    359  * DDESC::Time_Since_Heartbeat -- returns the time in ticks since the last heartbeat from wchat*
    360  *                                                                                             *
    361  *                                                                                             *
    362  *                                                                                             *
    363  * INPUT:    Nothing                                                                           *
    364  *                                                                                             *
    365  * OUTPUT:   time since heartbeat                                                              *
    366  *                                                                                             *
    367  * WARNINGS: None                                                                              *
    368  *                                                                                             *
    369  * HISTORY:                                                                                    *
    370  *    6/9/96 11:05PM ST : Created                                                              *
    371  *=============================================================================================*/
    372 int DDEServerClass::Time_Since_Heartbeat(void)
    373 {
    374 	return (GameTimer.Time() - LastHeartbeat);
    375 }
    376 
    377 
    378 
    379 
    380 /***********************************************************************************************
    381  * Send_Data_To_DDE_Server -- sends a packet to WChat                                          *
    382  *                                                                                             *
    383  *                                                                                             *
    384  *                                                                                             *
    385  * INPUT:    ptr to the data to send                                                           *
    386  *           length of data                                                                    *
    387  *           packet type identifier                                                            *
    388  *                                                                                             *
    389  * OUTPUT:   true if packet successfully sent                                                  *
    390  *                                                                                             *
    391  * WARNINGS: None                                                                              *
    392  *                                                                                             *
    393  * HISTORY:                                                                                    *
    394  *    6/9/96 11:07PM ST : Created                                                              *
    395  *=============================================================================================*/
    396 BOOL Send_Data_To_DDE_Server (char *data, int length, int packet_type)
    397 {
    398 	if( DDE_Class->Open_Poke_Connection(DDE_Class->remote_name) == FALSE) {
    399 		WWDebugString("RA95 - Failed to connect for POKE!");
    400 		return (FALSE);
    401 	}
    402 
    403 	char *poke_data = new char [length + 2*sizeof(int)];
    404 
    405 	int *poke_data_int = (int*)poke_data;
    406 
    407 	*poke_data_int 	= htonl (length + 2*sizeof(int));
    408 	*(poke_data_int+1)= htonl (packet_type);
    409 
    410 	memcpy (poke_data + 8, data, length);
    411 
    412 
    413 	if(DDE_Class->Poke_Server( (LPBYTE) poke_data, ntohl(*poke_data_int) ) == FALSE) {
    414 		WWDebugString("RA95 - POKE failed!\n");
    415 		DDE_Class->Close_Poke_Connection();		// close down the link
    416 		delete poke_data;
    417 		return (FALSE);
    418 	}
    419 
    420 	DDE_Class->Close_Poke_Connection();		// close down the link
    421 
    422 	delete poke_data;
    423 
    424 	return (TRUE);
    425 }
    426 
    427 
    428 #endif	//WIN32