CnC_Remastered_Collection

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

SENDFILE.CPP (26760B)


      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 : SENDFILE.CPP                                       *
     24  *                                                                                   *
     25  *                   Programmer : Steve Tall                                         *
     26  *                                                                                   *
     27  *                   Start Date : Audust 20th, 1996                                  *
     28  *                                                                                   *
     29  *                  Last Update : August 20th, 1996 [ST]                             *
     30  *                                                                                   *
     31  *-----------------------------------------------------------------------------------*
     32  * Overview:                                                                         *
     33  *                                                                                   *
     34  *  Functions for scenario file transfer between machines                            *
     35  *                                                                                   *
     36  *-----------------------------------------------------------------------------------*
     37  * Functions:                                                             	 			*
     38  *                                                                         				*
     39  *                                                                         				*
     40  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     41 
     42 #if (0)//PG
     43 #include "function.h"
     44 
     45 //#include "WolDebug.h"
     46 
     47 #ifdef WINSOCK_IPX
     48 #include "WSProto.h"
     49 #else
     50 
     51 #ifdef WIN32
     52 #include	"tcpip.h"
     53 #else
     54 #include	"fakesock.h"
     55 #endif	//WIN32
     56 
     57 #endif	//WINSOCK_IPX
     58 
     59 bool Receive_Remote_File ( char *file_name, unsigned int file_length, int gametype);
     60 bool Send_Remote_File ( char *file_name, int gametype );
     61 
     62 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
     63 extern bool Is_Mission_Counterstrike (char *file_name);
     64 extern bool Is_Mission_Aftermath (char *file_name);
     65 #endif
     66 
     67 #define RESPONSE_TIMEOUT	60*60
     68 
     69 #ifdef WOLAPI_INTEGRATION
     70 #include "WolapiOb.h"
     71 extern WolapiObject* pWolapi;
     72 #endif
     73 
     74 /***********************************************************************************************
     75  * Get_Scenario_File_From_Host -- Initiates download of scenario file from game host           *
     76  *                                                                                             *
     77  *                                                                                             *
     78  *                                                                                             *
     79  * INPUT:    ptr to buffer to copy file name into                                              *
     80  *           game type - 0 for modem/null modem, 1 otherwise                                   *
     81  *                                                                                             *
     82  * OUTPUT:   true if file sucessfully downloaded                                               *
     83  *                                                                                             *
     84  * WARNINGS: None                                                                              *
     85  *                                                                                             *
     86  * HISTORY:                                                                                    *
     87  *    8/22/96 3:06PM ST : Created                                                              *
     88  *=============================================================================================*/
     89 bool Get_Scenario_File_From_Host(char *return_name, int gametype)
     90 {
     91 	//WWDebugString ("RA95 - In Get_Scenario_From_Host\n");
     92 
     93 	unsigned int file_length;
     94 
     95 	SerialPacketType 	send_packet;
     96 	SerialPacketType 	receive_packet;
     97 	GlobalPacketType	net_send_packet;
     98 	GlobalPacketType	net_receive_packet;
     99 	unsigned int		packet_len;
    100 	unsigned short		product_id;
    101 
    102 	IPXAddressClass	sender_address;
    103 
    104 	CDTimerClass<SystemTimerClass> response_timer;		// timeout timer for waiting for responses
    105 
    106 	/*
    107 	** Send the scenario request using guaranteed delivery.
    108 	*/
    109 	if (!gametype) {
    110 		memset ((void*)&send_packet, 0, sizeof (send_packet));
    111 		send_packet.Command = SERIAL_REQ_SCENARIO;
    112 		NullModem.Send_Message (&send_packet, sizeof(send_packet), 1);
    113 	} else {
    114 		memset ((void*)&net_send_packet, 0, sizeof (net_send_packet));
    115 		net_send_packet.Command = NET_REQ_SCENARIO;
    116 		Ipx.Send_Global_Message (&net_send_packet, sizeof (net_send_packet),
    117 			1, &(Session.HostAddress) );
    118 	}
    119 
    120 
    121 
    122 	//WWDebugString ("RA95 - Waiting for response from host\n");
    123 
    124 	/*
    125 	** Wait for host to respond with a file info packet
    126 	*/
    127 	response_timer = RESPONSE_TIMEOUT;
    128 	if (!gametype){
    129 		do {
    130 			NullModem.Service();
    131 
    132 			if (NullModem.Get_Message ((void*)&receive_packet, (int*)&packet_len) > 0) {
    133 
    134 				if (receive_packet.Command == SERIAL_FILE_INFO){
    135 					strcpy (return_name, receive_packet.ScenarioInfo.ShortFileName);
    136 					file_length = receive_packet.ScenarioInfo.FileLength;
    137 					break;
    138 				}
    139 			}
    140 		} while ( response_timer );
    141 	}else{
    142 		do {
    143 			Ipx.Service();
    144 			int receive_packet_length = sizeof (net_receive_packet);
    145 			if (Ipx.Get_Global_Message (&net_receive_packet, &receive_packet_length,
    146 				&sender_address, &product_id)){
    147 
    148 //WWDebugString ("RA95 - Got packet from host\n");
    149 #ifdef WINSOCK_IPX
    150 				if (net_receive_packet.Command == NET_FILE_INFO && sender_address == Session.HostAddress) {
    151 #else	//WINSOCK_IPX
    152 				if (net_receive_packet.Command == NET_FILE_INFO &&
    153 						(Winsock.Get_Connected() || sender_address == Session.HostAddress)){
    154 #endif	//WINSOCK_IPX
    155 					strcpy (return_name, net_receive_packet.ScenarioInfo.ShortFileName);
    156 					file_length = net_receive_packet.ScenarioInfo.FileLength;
    157 //WWDebugString ("RA95 - Got file info packet from host\n");
    158 					break;
    159 				}
    160 			}
    161 
    162 #ifdef WOLAPI_INTEGRATION
    163 			if( Session.Type == GAME_INTERNET && pWolapi && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )
    164 			{
    165 				pWolapi->pChat->PumpMessages();
    166 				pWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;
    167 			}
    168 #endif
    169 		} while ( response_timer );
    170 	}
    171 
    172 //char rt[80];
    173 //sprintf (rt, "RA95 - response_timer = %d\n", response_timer );
    174 //WWDebugString (rt);
    175 
    176 	/*
    177 	** If we timed out then something horrible has happened to the other player so just
    178 	** return failure.
    179 	*/
    180 	if (!response_timer) return (false);
    181 
    182 //	debugprint( "about to download '%s'\n", return_name );
    183 
    184 	/*
    185 	** Receive the file from the host
    186 	*/
    187 	return (Receive_Remote_File ( return_name, file_length, gametype));
    188 }
    189 
    190 
    191 
    192 
    193 
    194 
    195 
    196 /***********************************************************************************************
    197  * Receive_Remote_File -- Handles incoming file download packets from the game host            *
    198  *                                                                                             *
    199  *                                                                                             *
    200  *                                                                                             *
    201  * INPUT:    file name to save as                                                              *
    202  *           length of file to expect                                                          *
    203  *           game type - 0 for modem/null modem, 1 otherwise                                   *
    204  *                                                                                             *
    205  * OUTPUT:   true if file downloaded was completed                                             *
    206  *                                                                                             *
    207  * WARNINGS: This fuction can modify the file name passed in                                   *
    208  *                                                                                             *
    209  * HISTORY:                                                                                    *
    210  *   8/22/96 3:07PM ST : Created                                                               *
    211  *=============================================================================================*/
    212 bool Receive_Remote_File ( char *file_name, unsigned int file_length, int gametype)
    213 {
    214 
    215 	//WWDebugString ("RA95 - In Receive_Remote_File\n");
    216 	unsigned short		product_id;
    217 	IPXAddressClass	sender_address;
    218 
    219 	/*
    220 	** Dialog & button dimensions
    221 	*/
    222 	int d_dialog_w = 200 *RESFACTOR;											// dialog width
    223 	int d_dialog_h = 90*RESFACTOR;											// dialog height
    224 	int d_dialog_x = ((320*RESFACTOR - d_dialog_w) / 2);				// dialog x-coord
    225 	int d_dialog_y = ((200*RESFACTOR - d_dialog_h) / 2);				// centered y-coord
    226 	int d_dialog_cx = d_dialog_x + (d_dialog_w / 2);		// center x-coord
    227 
    228 	int d_margin1=10;
    229 	int d_txt6_h=15;
    230 
    231 #if (GERMAN | FRENCH)
    232 	int d_cancel_w = 50*RESFACTOR;
    233 #else
    234 	int d_cancel_w = 40*RESFACTOR;
    235 #endif
    236 	int d_cancel_h = 9*RESFACTOR;
    237 	int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
    238 	int d_cancel_y = d_dialog_y + d_dialog_h - 20*RESFACTOR;
    239 
    240 	int d_progress_w = 100*RESFACTOR;
    241 	int d_progress_h = 10*RESFACTOR;
    242 	int d_progress_x = (SeenBuff.Get_Width()/2) - d_progress_w/2;
    243 	int d_progress_y = d_dialog_y + 45*RESFACTOR;
    244 
    245 	int	width;
    246 	int	height;
    247 
    248 	char *info_string = (char*)Text_String (TXT_RECEIVING_SCENARIO);
    249 
    250 	Fancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),
    251 		TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);
    252 
    253 	Format_Window_String(info_string, SeenBuff.Get_Height(), width, height);
    254 
    255 
    256 	/*
    257 	** Button Enumerations
    258 	*/
    259 	enum {
    260 		BUTTON_CANCEL = 100,
    261 		BUTTON_PROGRESS
    262 	};
    263 
    264 	/*
    265 	** Buttons
    266 	*/
    267 	//TextButtonClass *buttons;										// button list
    268 
    269 	TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
    270 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    271 #if (GERMAN | FRENCH)
    272 		d_cancel_x, d_cancel_y);
    273 #else
    274 		d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
    275 #endif
    276 
    277 	GaugeClass progress_meter (BUTTON_PROGRESS,
    278 		d_progress_x, d_progress_y, d_progress_w, d_progress_h);
    279 
    280 	Fancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),
    281 		TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);
    282 
    283 
    284 	typedef enum {
    285 		REDRAW_NONE = 0,
    286 		REDRAW_PROGRESS,
    287 		REDRAW_BUTTONS,
    288 		REDRAW_BACKGROUND,
    289 		REDRAW_ALL = REDRAW_BACKGROUND
    290 	} RedrawType;
    291 
    292 
    293 	bool 			process = true;
    294 	RedrawType 	display = REDRAW_ALL;		// redraw level
    295 	KeyNumType 	input;
    296 	GadgetClass *commands;					// button list
    297 	bool			return_code;
    298 	int			update_time = 0;
    299 
    300 
    301 
    302 	RemoteFileTransferType receive_packet;
    303 
    304 	int 				last_received_block = -1;		//No blocks received yet
    305 	unsigned int 	total_length = 0;
    306 	unsigned int	packet_len;
    307 
    308 	/*
    309 	** If the file name is already in use, use the temp file name
    310 	*/
    311 	CCFileClass test_file (file_name);
    312 	if (test_file.Is_Available()){
    313 		strcpy (file_name, "DOWNLOAD.TMP");
    314 	}
    315 
    316 	RawFileClass save_file (file_name);
    317 
    318 	/*
    319 	** If the file already exists then delete it and re-create it.
    320 	*/
    321 	if (save_file.Is_Available()) save_file.Delete();
    322 
    323 	/*
    324 	** Open the file for write
    325 	*/
    326 	save_file.Open ( WRITE );
    327 
    328 	commands = &cancelbtn;
    329 	commands->Add_Tail (progress_meter);
    330 
    331 	progress_meter.Set_Maximum(100);		// Max is 100%
    332 	progress_meter.Set_Value(0);			// Current is 0%
    333 
    334 	/*
    335 	** Wait for all the blocks to arrive
    336 	*/
    337 
    338 	do	{
    339 #ifdef WIN32
    340 		/*
    341 		** If we have just received input focus again after running in the background then
    342 		** we need to redraw.
    343 		*/
    344 		if (AllSurfaces.SurfacesRestored) {
    345 			AllSurfaces.SurfacesRestored=FALSE;
    346 			display = REDRAW_ALL;
    347 		}
    348 #endif
    349 
    350 #ifdef WOLAPI_INTEGRATION
    351 		if( Session.Type == GAME_INTERNET && pWolapi && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )
    352 		{
    353 			pWolapi->pChat->PumpMessages();
    354 			pWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;
    355 		}
    356 #endif
    357 
    358 		if (display){
    359 
    360 			if (display >= REDRAW_BACKGROUND){
    361 
    362 				Hide_Mouse();
    363 				/*
    364 				** Redraw backgound & dialog box
    365 				*/
    366 				Load_Title_Page(true);
    367 				Set_Palette(CCPalette);
    368 
    369 				Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
    370 
    371 				/*
    372 				** Dialog & Field labels
    373 				*/
    374 				Draw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);
    375 
    376 				Fancy_Text_Print(info_string, d_dialog_cx-width/2, d_dialog_y + 25*RESFACTOR,
    377 									GadgetClass::Get_Color_Scheme(), TBLACK,
    378 									TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
    379 
    380 				Show_Mouse();
    381 
    382 			}
    383 
    384 			if (display >= REDRAW_BUTTONS){
    385 
    386 				commands->Draw_All();
    387 
    388 			}
    389 
    390 			if (display >= REDRAW_PROGRESS){
    391 				progress_meter.Draw_Me(true);
    392 			}
    393 
    394 			display = REDRAW_NONE;
    395 		}
    396 
    397 
    398 		if (!gametype){
    399 			NullModem.Service();
    400 
    401 			if (NullModem.Get_Message ((void*)&receive_packet, (int*)&packet_len) > 0) {
    402 
    403 				if (receive_packet.Command == NET_FILE_CHUNK){
    404 
    405 					if (receive_packet.BlockNumber == last_received_block + 1){
    406 
    407 						save_file.Write ( receive_packet.RawData, receive_packet.BlockLength );
    408 						total_length += receive_packet.BlockLength;
    409 						last_received_block ++;
    410 
    411 						update_time++;
    412 						if (update_time >7){
    413 							progress_meter.Set_Value ( (total_length*100) / file_length );
    414 							display = REDRAW_PROGRESS;
    415 							update_time = 0;;
    416 						}
    417 
    418 						if (total_length >= file_length){
    419 							process = false;
    420 							return_code = true;
    421 							progress_meter.Set_Value ( 100 );
    422 							progress_meter.Draw_Me(true);
    423 						}
    424 					}
    425 				}
    426 			}
    427 		}else{
    428 			Ipx.Service();
    429 
    430 			int receive_packet_len = sizeof (receive_packet);
    431 			if (Ipx.Get_Global_Message (&receive_packet, &receive_packet_len,
    432 				&sender_address, &product_id)){
    433 
    434 #ifdef WINSOCK_IPX
    435 				if (receive_packet.Command == NET_FILE_CHUNK && sender_address == Session.HostAddress){
    436 #else	//WINSOCK_IPX
    437 				if (receive_packet.Command == NET_FILE_CHUNK &&
    438 							(Winsock.Get_Connected() || sender_address == Session.HostAddress)){
    439 #endif	//WINSOCK_IPX
    440 
    441 					if (receive_packet.BlockNumber == last_received_block + 1){
    442 
    443 						save_file.Write ( receive_packet.RawData, receive_packet.BlockLength );
    444 						total_length += receive_packet.BlockLength;
    445 						last_received_block ++;
    446 
    447 						update_time++;
    448 						if (update_time >7){
    449 							progress_meter.Set_Value ( (total_length*100) / file_length );
    450 							display = REDRAW_PROGRESS;
    451 							update_time = 0;;
    452 						}
    453 
    454 						if (total_length >= file_length){
    455 							process = false;
    456 							return_code = true;
    457 							progress_meter.Set_Value ( 100 );
    458 							progress_meter.Draw_Me(true);
    459 						}
    460 					}
    461 				}
    462 			}
    463 		}
    464 
    465 
    466 		if (process){
    467 			input = cancelbtn.Input();
    468 
    469 			/*
    470 			---------------------------- Process input ----------------------------
    471 			*/
    472 			switch (input) {
    473 
    474 				/*
    475 				** Cancel. Just return to the main menu
    476 				*/
    477 				case (KN_ESC):
    478 				case (BUTTON_CANCEL | KN_BUTTON):
    479 					process = false;
    480 					return_code = false;
    481 					break;
    482 			}
    483 		}
    484 
    485 
    486 	} while ( process );
    487 
    488 	save_file.Close();
    489 
    490 	/*
    491 	** Update the internal list of scenarios to include the downloaded one so we know about it
    492 	**  for the next game.
    493 	*/
    494 	Session.Read_Scenario_Descriptions();
    495 
    496 	return (return_code);
    497 }
    498 
    499 
    500 
    501 
    502 
    503 
    504 /***********************************************************************************************
    505  * Send_Remote_File -- Sends a file to game clients                                            *
    506  *                                                                                             *
    507  *                                                                                             *
    508  *                                                                                             *
    509  * INPUT:    File name                                                                         *
    510  *                                                                                             *
    511  * OUTPUT:   true if file transfer was successfully completed                                  *
    512  *           game type - 0 for modem/null modem, 1 otherwise                                   *
    513  *                                                                                             *
    514  * WARNINGS: None                                                                              *
    515  *                                                                                             *
    516  * HISTORY:                                                                                    *
    517  *    8/22/96 3:09PM ST : Created                                                              *
    518  *=============================================================================================*/
    519 bool Send_Remote_File ( char *file_name, int gametype )
    520 {
    521 	//WWDebugString ("RA95 - In Send_Remote_File\n");
    522 
    523 	/*
    524 	** Dialog & button dimensions
    525 	*/
    526 	int factor			= (SeenBuff.Get_Width() == 320) ? 1 : 2;
    527 
    528 	int d_dialog_w = 240 *factor;											// dialog width
    529 	int d_dialog_h = 90*factor;											// dialog height
    530 	int d_dialog_x = ((320*factor - d_dialog_w) / 2);				// dialog x-coord
    531 	int d_dialog_y = ((200*factor - d_dialog_h) / 2);				// centered y-coord
    532 	int d_dialog_cx = d_dialog_x + (d_dialog_w / 2);		// center x-coord
    533 
    534 	int d_margin1=10;
    535 	int d_txt6_h=15;
    536 
    537 #if (GERMAN | FRENCH)
    538 	int d_cancel_w = 50*factor;
    539 #else
    540 	int d_cancel_w = 40*factor;
    541 #endif
    542 	int d_cancel_h = 9*factor;
    543 	int d_cancel_x = d_dialog_cx - d_cancel_w / 2;
    544 	int d_cancel_y = d_dialog_y + d_dialog_h - 20*factor;
    545 
    546 	int d_progress_w = 100*factor;
    547 	int d_progress_h = 10*factor;
    548 	int d_progress_x = (SeenBuff.Get_Width()/2) - d_progress_w/2;
    549 	int d_progress_y = d_dialog_y + 45*factor;
    550 
    551 	int	width;
    552 	int	height;
    553 
    554 	char *info_string = (char*)Text_String (TXT_SENDING_SCENARIO);
    555 
    556 	CDTimerClass<SystemTimerClass> response_timer;		// timeout timer for waiting for responses
    557 
    558 	Fancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),
    559 		TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);
    560 
    561 	Format_Window_String(info_string, SeenBuff.Get_Height(), width, height);
    562 
    563 
    564 	/*
    565 	** Button Enumerations
    566 	*/
    567 	enum {
    568 		BUTTON_CANCEL = 100,
    569 		BUTTON_PROGRESS
    570 	};
    571 
    572 	/*
    573 	** Buttons
    574 	*/
    575 	//TextButtonClass *buttons;										// button list
    576 
    577 	TextButtonClass cancelbtn(BUTTON_CANCEL, TXT_CANCEL,
    578 		TPF_CENTER | TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW,
    579 #if (GERMAN | FRENCH)
    580 		d_cancel_x, d_cancel_y);
    581 #else
    582 		d_cancel_x, d_cancel_y, d_cancel_w, d_cancel_h);
    583 #endif
    584 
    585 	GaugeClass progress_meter (BUTTON_PROGRESS,
    586 		d_progress_x, d_progress_y, d_progress_w, d_progress_h);
    587 
    588 	Fancy_Text_Print(TXT_NONE, 0, 0, GadgetClass::Get_Color_Scheme(),
    589 		TBLACK, TPF_CENTER|TPF_6PT_GRAD|TPF_USE_GRAD_PAL|TPF_NOSHADOW);
    590 
    591 
    592 	typedef enum {
    593 		REDRAW_NONE = 0,
    594 		REDRAW_PROGRESS,
    595 		REDRAW_BUTTONS,
    596 		REDRAW_BACKGROUND,
    597 		REDRAW_ALL = REDRAW_BACKGROUND
    598 	} RedrawType;
    599 
    600 
    601 	bool 			process = true;
    602 	RedrawType 	display = REDRAW_ALL;		// redraw level
    603 	KeyNumType 	input;
    604 	GadgetClass *commands;					// button list
    605 	bool			return_code;
    606 	int			update_time = 0;
    607 
    608 
    609 	int file_length;
    610 	int block_number;
    611 	int max_chunk_size;
    612 	int total_blocks;
    613 	int bytes_left;
    614 
    615 	void *read_ptr;
    616 
    617 	RemoteFileTransferType	send_packet;
    618 	SerialPacketType			file_info;
    619 	GlobalPacketType			net_file_info;
    620 
    621 
    622 	CCFileClass send_file (file_name);
    623 
    624 	if ( !send_file.Is_Available() ){
    625 		//WWDebugString ("RA95 - Error - could not find file to send to client\n");
    626 //		debugprint("RA95 - Error - could not find file to send to client\n");
    627 		return (false);
    628 	}
    629 	file_length = send_file.Size();
    630 
    631 	response_timer = RESPONSE_TIMEOUT;
    632 
    633 	/*
    634 	** Send the file info to the remote machine(s)
    635 	*/
    636 	if (!gametype){
    637 		file_info.Command = SERIAL_FILE_INFO;
    638 		strcpy (&file_info.ScenarioInfo.ShortFileName[0], file_name);
    639 #ifdef FIXIT_VERSION_3
    640 		//	If we're sending an official map, always send it to 'download.tmp'.
    641 		if( Is_Mission_Counterstrike( file_name ) || Is_Mission_Aftermath( file_name ) ) {
    642 			strcpy (&file_info.ScenarioInfo.ShortFileName[0], "DOWNLOAD.TMP");
    643 		}
    644 #else
    645 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
    646 // If we're sending an Aftermath map, always send it to 'download.tmp'.
    647 		if (Is_Mission_Aftermath(file_name)) {
    648 			strcpy (&file_info.ScenarioInfo.ShortFileName[0], "DOWNLOAD.TMP");
    649 		}
    650 #endif
    651 #endif
    652 		file_info.ScenarioInfo.FileLength = file_length;
    653 		NullModem.Send_Message (&file_info, sizeof (file_info), 1);
    654 		while (NullModem.Num_Send() > 0 && response_timer){
    655 			NullModem.Service();
    656 		}
    657 	} else {
    658 		net_file_info.Command = NET_FILE_INFO;
    659 		strcpy (&net_file_info.ScenarioInfo.ShortFileName[0], file_name);
    660 //		debugprint( "Uploading '%s'\n", file_name );
    661 #ifdef FIXIT_VERSION_3
    662 		//	If we're sending an official map, always send it to 'download.tmp'.
    663 		if( Is_Mission_Counterstrike( file_name ) || Is_Mission_Aftermath( file_name ) ) {
    664 			strcpy (&net_file_info.ScenarioInfo.ShortFileName[0], "DOWNLOAD.TMP");
    665 		}
    666 #else
    667 #ifdef FIXIT_CSII	//	checked - ajw 9/28/98
    668 // If we're sending an Aftermath map, always send it to 'download.tmp'.
    669 		if (Is_Mission_Aftermath(file_name)) {
    670 			strcpy (&file_info.ScenarioInfo.ShortFileName[0], "DOWNLOAD.TMP");
    671 			//	There was a bug here: s/b net_file_info. This means that players that don't have Aftermath could have been 
    672 			//	accumulating Aftermath maps all this time!!! (File wasn't getting renamed to "DOWNLOAD.TMP".)
    673 		}
    674 #endif
    675 #endif
    676 //		debugprint( "ShortFileName is '%s'\n", net_file_info.ScenarioInfo.ShortFileName );
    677 		net_file_info.ScenarioInfo.FileLength = file_length;
    678 
    679 		for (int i=0 ; i<Session.RequestCount ; i++){
    680 			Ipx.Send_Global_Message (&net_file_info, sizeof (GlobalPacketType),
    681 				1, &(Session.Players[Session.ScenarioRequests[i]]->Address) );
    682 		}
    683 
    684 		while (Ipx.Global_Num_Send() > 0 && response_timer) {
    685 			Ipx.Service();
    686 		}
    687 	}
    688 
    689 
    690 	max_chunk_size = MAX_SEND_FILE_PACKET_SIZE;
    691 	total_blocks = (file_length + max_chunk_size-1) / max_chunk_size;
    692 	bytes_left = file_length;
    693 
    694 	send_file.Open ( READ );
    695 
    696 
    697 	commands = &cancelbtn;
    698 	commands->Add_Tail (progress_meter);
    699 
    700 	progress_meter.Set_Maximum(100);		// Max is 100%
    701 	progress_meter.Set_Value(0);			// Current is 0%
    702 
    703 
    704 	block_number = 0;
    705 
    706 	while ( process ){
    707 
    708 #ifdef WIN32
    709 		/*
    710 		** If we have just received input focus again after running in the background then
    711 		** we need to redraw.
    712 		*/
    713 		if (AllSurfaces.SurfacesRestored) {
    714 			AllSurfaces.SurfacesRestored=FALSE;
    715 			display = REDRAW_ALL;
    716 		}
    717 #endif
    718 
    719 #ifdef WOLAPI_INTEGRATION
    720 		if( Session.Type == GAME_INTERNET && pWolapi && ( ::timeGetTime() > pWolapi->dwTimeNextWolapiPump ) )
    721 		{
    722 			pWolapi->pChat->PumpMessages();
    723 			pWolapi->dwTimeNextWolapiPump = ::timeGetTime() + WOLAPIPUMPWAIT;
    724 		}
    725 #endif
    726 
    727 		if (display){
    728 
    729 			if (display >= REDRAW_BACKGROUND){
    730 
    731 				Hide_Mouse();
    732 				/*
    733 				** Redraw backgound & dialog box
    734 				*/
    735 				Load_Title_Page(true);
    736 				Set_Palette(CCPalette);
    737 
    738 				Dialog_Box(d_dialog_x, d_dialog_y, d_dialog_w, d_dialog_h);
    739 
    740 				/*
    741 				** Dialog & Field labels
    742 				*/
    743 				Draw_Caption (TXT_NONE, d_dialog_x, d_dialog_y, d_dialog_w);
    744 
    745 				Fancy_Text_Print(info_string, d_dialog_cx-width/2, d_dialog_y + 25*factor,
    746 									GadgetClass::Get_Color_Scheme(), TBLACK,
    747 									TPF_6PT_GRAD | TPF_USE_GRAD_PAL | TPF_NOSHADOW);
    748 
    749 				Show_Mouse();
    750 
    751 			}
    752 
    753 			if (display >= REDRAW_BUTTONS){
    754 
    755 				commands->Draw_All();
    756 
    757 			}
    758 
    759 			if (display >= REDRAW_PROGRESS){
    760 				progress_meter.Draw_Me(true);
    761 			}
    762 
    763 			display = REDRAW_NONE;
    764 		}
    765 
    766 
    767 		if (!gametype){
    768 			NullModem.Service();
    769 
    770 
    771 			if (block_number < total_blocks){
    772 
    773 				if ( NullModem.Num_Send() <2 ){
    774 
    775 					send_packet.Command = SERIAL_FILE_CHUNK;
    776 					send_packet.BlockNumber = block_number;
    777 					send_packet.BlockLength = MIN (file_length, max_chunk_size);
    778 
    779 					file_length -= send_packet.BlockLength;
    780 
    781 					read_ptr = &send_packet.RawData[0];
    782 
    783 					if (send_file.Read (read_ptr , send_packet.BlockLength) == send_packet.BlockLength){
    784 						NullModem.Send_Message ((void*)&send_packet, sizeof(send_packet), 1);
    785 					}
    786 
    787 					block_number++;
    788 
    789 					update_time++;
    790 					if (update_time >7){
    791 						progress_meter.Set_Value ( (block_number*100) / total_blocks );
    792 						display = REDRAW_PROGRESS;
    793 						update_time = 0;;
    794 					}
    795 
    796 				}
    797 			}else{
    798 				if (NullModem.Num_Send() == 0){
    799 					process = false;
    800 					return_code = true;
    801 					progress_meter.Set_Value ( 100 );
    802 					progress_meter.Draw_Me(true);
    803 
    804 				}
    805 			}
    806 
    807 
    808 		}else{
    809 			Ipx.Service();
    810 
    811 			if (block_number < total_blocks){
    812 
    813 				if ( Ipx.Global_Num_Send() == 0 ){
    814 
    815 					send_packet.Command = SERIAL_FILE_CHUNK;
    816 					send_packet.BlockNumber = block_number;
    817 					send_packet.BlockLength = MIN (file_length, max_chunk_size);
    818 
    819 					file_length -= send_packet.BlockLength;
    820 
    821 					read_ptr = &send_packet.RawData[0];
    822 
    823 					if (send_file.Read (read_ptr , send_packet.BlockLength) == send_packet.BlockLength){
    824 						for (int i=0 ; i<Session.RequestCount ; i++){
    825 							Ipx.Send_Global_Message (&send_packet, sizeof (send_packet),
    826 								1, &(Session.Players[Session.ScenarioRequests[i]]->Address) );
    827 						}
    828 					}
    829 
    830 					block_number++;
    831 
    832 					update_time++;
    833 					if (update_time >7){
    834 						progress_meter.Set_Value ( (block_number*100) / total_blocks );
    835 						display = REDRAW_PROGRESS;
    836 						update_time = 0;;
    837 					}
    838 
    839 				}
    840 			}else{
    841 				if (Ipx.Global_Num_Send() == 0){
    842 					process = false;
    843 					return_code = true;
    844 					progress_meter.Set_Value ( 100 );
    845 					progress_meter.Draw_Me(true);
    846 				}
    847 			}
    848 
    849 
    850 
    851 		}
    852 
    853 
    854 		if (process){
    855 			input = cancelbtn.Input();
    856 
    857 			/*
    858 			---------------------------- Process input ----------------------------
    859 			*/
    860 			switch (input) {
    861 
    862 				/*
    863 				** Cancel. Just return to the main menu
    864 				*/
    865 				case (KN_ESC):
    866 				case (BUTTON_CANCEL | KN_BUTTON):
    867 					process = false;
    868 					return_code = false;
    869 					break;
    870 			}
    871 		}
    872 
    873 	}
    874 
    875 	return (return_code);
    876 }
    877 #endif