CnC_Remastered_Collection

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

CCDDE.CPP (21712B)


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