(svn r2324) Introduce _cmd_text for passing strings with a command instead of abusing _decode_parameters as text buffer. This should prevent several possible buffer overruns and is a bit cleaner to use. As bonus it reduces the size of most command packets by 79 bytes.
authortron
Sun, 15 May 2005 18:50:55 +0000
changeset 1820 9b6458526480
parent 1819 e2e977e1462e
child 1821 6b13b0210b07
(svn r2324) Introduce _cmd_text for passing strings with a command instead of abusing _decode_parameters as text buffer. This should prevent several possible buffer overruns and is a bit cleaner to use. As bonus it reduces the size of most command packets by 79 bytes.
aircraft_gui.c
command.c
command.h
engine.c
main_gui.c
misc_cmd.c
network_client.c
network_data.c
network_data.h
network_server.c
order_cmd.c
player_gui.c
players.c
roadveh_gui.c
ship_gui.c
signs.c
station_cmd.c
station_gui.c
town_cmd.c
town_gui.c
train_gui.c
vehicle.c
waypoint.c
--- a/aircraft_gui.c	Sun May 15 18:43:36 2005 +0000
+++ b/aircraft_gui.c	Sun May 15 18:50:55 2005 +0000
@@ -151,11 +151,11 @@
 		break;
 
 	case WE_ON_EDIT_TEXT: {
-		const char *b = e->edittext.str;
-		if (*b == 0)
-			return;
-		memcpy(_decode_parameters, b, 32);
-		DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE));
+		if (e->edittext.str[0] != '\0') {
+			_cmd_text = e->edittext.str;
+			DoCommandP(0, WP(w, buildtrain_d).rename_engine, 0, NULL,
+				CMD_RENAME_ENGINE | CMD_MSG(STR_A03A_CAN_T_RENAME_AIRCRAFT_TYPE));
+		}
 	} break;
 
 	case WE_RESIZE:
@@ -410,11 +410,11 @@
 		break;
 
 	case WE_ON_EDIT_TEXT: {
-		const char *b = e->edittext.str;
-		if (*b == 0)
-			return;
-		memcpy(_decode_parameters, b, 32);
-		DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(STR_A031_CAN_T_NAME_AIRCRAFT));
+		if (e->edittext.str[0] != '\0') {
+			_cmd_text = e->edittext.str;
+			DoCommandP(0, w->window_number, 0, NULL,
+				CMD_NAME_VEHICLE | CMD_MSG(STR_A031_CAN_T_NAME_AIRCRAFT));
+		}
 	} break;
 
 	}
--- a/command.c	Sun May 15 18:43:36 2005 +0000
+++ b/command.c	Sun May 15 18:50:55 2005 +0000
@@ -7,6 +7,8 @@
 #include "player.h"
 #include "network.h"
 
+const char* _cmd_text = NULL;
+
 #define DEF_COMMAND(yyyy) int32 yyyy(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 
 DEF_COMMAND(CmdBuildRailroadTrack);
@@ -323,7 +325,10 @@
 	CommandProc *proc;
 
 	/* Do not even think about executing out-of-bounds tile-commands */
-	if (TILE_FROM_XY(x,y) > MapSize()) return CMD_ERROR;
+	if (TILE_FROM_XY(x,y) > MapSize()) {
+		_cmd_text = NULL;
+		return CMD_ERROR;
+	}
 
 	proc = _command_proc_table[procc].proc;
 
@@ -352,6 +357,7 @@
 
 		if (!(flags & DC_EXEC)) {
 			_docommand_recursive--;
+			_cmd_text = NULL;
 			return res;
 		}
 	}
@@ -363,6 +369,7 @@
 		if (res & 0xFFFF) _error_message = res & 0xFFFF;
 error:
 		_docommand_recursive--;
+		_cmd_text = NULL;
 		return CMD_ERROR;
 	}
 
@@ -371,6 +378,7 @@
 		SubtractMoneyFromPlayer(res);
 	}
 
+	_cmd_text = NULL;
 	return res;
 }
 
@@ -394,7 +402,10 @@
 	int y = TileY(tile) * 16;
 
 	/* Do not even think about executing out-of-bounds tile-commands */
-	if (tile > MapSize()) return false;
+	if (tile > MapSize()) {
+		_cmd_text = NULL;
+		return false;
+	}
 
 	assert(_docommand_recursive == 0);
 
@@ -405,6 +416,7 @@
 	// spectator has no rights.
 	if (_current_player == OWNER_SPECTATOR) {
 		ShowErrorMessage(_error_message, _error_message_2, x, y);
+		_cmd_text = NULL;
 		return false;
 	}
 
@@ -446,6 +458,7 @@
 		}
 
 		_docommand_recursive = 0;
+		_cmd_text = NULL;
 		return false;
 	}
 
@@ -467,6 +480,7 @@
 	if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
 		NetworkSend_Command(tile, p1, p2, cmd, callback);
 		_docommand_recursive = 0;
+		_cmd_text = NULL;
 		return true;
 	}
 #endif /* ENABLE_NETWORK */
@@ -505,6 +519,7 @@
 	_docommand_recursive = 0;
 
 	if (callback) callback(true, tile, p1, p2);
+	_cmd_text = NULL;
 	return true;
 
 show_error:
@@ -516,5 +531,6 @@
 	_docommand_recursive = 0;
 
 	if (callback) callback(false, tile, p1, p2);
+	_cmd_text = NULL;
 	return false;
 }
--- a/command.h	Sun May 15 18:43:36 2005 +0000
+++ b/command.h	Sun May 15 18:50:55 2005 +0000
@@ -190,6 +190,8 @@
 int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc);
 int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
 
+extern const char* _cmd_text; // Text, which gets sent with a command
+
 bool IsValidCommand(uint cmd);
 byte GetCommandFlags(uint cmd);
 int32 GetAvailableMoneyForCommand(void);
--- a/engine.c	Sun May 15 18:43:36 2005 +0000
+++ b/engine.c	Sun May 15 18:50:55 2005 +0000
@@ -889,7 +889,7 @@
 
 	if (!IsEngineIndex(p1)) return CMD_ERROR;
 
-	str = AllocateNameUnique((const char*)_decode_parameters, 0);
+	str = AllocateNameUnique(_cmd_text, 0);
 	if (str == 0) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
--- a/main_gui.c	Sun May 15 18:43:36 2005 +0000
+++ b/main_gui.c	Sun May 15 18:50:55 2005 +0000
@@ -63,7 +63,8 @@
 {
 	const char *b = e->edittext.str;
 	int id;
-	memcpy(_decode_parameters, b, 32);
+
+	_cmd_text = b;
 
 	id = _rename_id;
 
--- a/misc_cmd.c	Sun May 15 18:43:36 2005 +0000
+++ b/misc_cmd.c	Sun May 15 18:50:55 2005 +0000
@@ -129,7 +129,7 @@
 	StringID str;
 	Player *p;
 
-	str = AllocateNameUnique((const char*)_decode_parameters, 4);
+	str = AllocateNameUnique(_cmd_text, 4);
 	if (str == 0) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
@@ -153,7 +153,7 @@
 	StringID str;
 	Player *p;
 
-	str = AllocateNameUnique((const char*)_decode_parameters, 4);
+	str = AllocateNameUnique(_cmd_text, 4);
 	if (str == 0) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
@@ -162,7 +162,10 @@
 		p->president_name_1 = str;
 
 		if (p->name_1 == STR_SV_UNNAMED) {
-			ttd_strlcat((char*)_decode_parameters, " Transport", sizeof(_decode_parameters));
+			char buf[80];
+
+			snprintf(buf, lengthof(buf), "%s Transport", _cmd_text);
+			_cmd_text = buf;
 			DoCommandByTile(0, 0, 0, DC_EXEC, CMD_CHANGE_COMPANY_NAME);
 		}
 		MarkWholeScreenDirty();
--- a/network_client.c	Sun May 15 18:43:36 2005 +0000
+++ b/network_client.c	Sun May 15 18:50:55 2005 +0000
@@ -143,13 +143,10 @@
 	//    uint32: P1 (free variables used in DoCommand)
 	//    uint32: P2
 	//    uint32: Tile
-	//    uint32: decode_params
-	//      10 times the last one (lengthof(cp->dp))
+	//    string: text
 	//    uint8:  CallBackID (see callback_table.c)
 	//
 
-	uint i;
-	char *dparam_char;
 	Packet *p = NetworkSend_Init(PACKET_CLIENT_COMMAND);
 
 	NetworkSend_uint8(p, cp->player);
@@ -157,14 +154,7 @@
 	NetworkSend_uint32(p, cp->p1);
 	NetworkSend_uint32(p, cp->p2);
 	NetworkSend_uint32(p, (uint32)cp->tile);
-	/* We are going to send them byte by byte, because dparam is misused
-	    for chars (if it is used), and else we have a BigEndian / LittleEndian
-	    problem.. we should fix the misuse of dparam... -- TrueLight */
-	dparam_char = (char *)&cp->dp[0];
-	for (i = 0; i < lengthof(cp->dp) * 4; i++) {
-		NetworkSend_uint8(p, *dparam_char);
-		dparam_char++;
-	}
+	NetworkSend_string(p, cp->text);
 	NetworkSend_uint8(p, cp->callback);
 
 	NetworkSend_Packet(p, MY_CLIENT);
@@ -587,22 +577,13 @@
 
 DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMMAND)
 {
-	uint i;
-	char *dparam_char;
 	CommandPacket *cp = malloc(sizeof(CommandPacket));
 	cp->player = NetworkRecv_uint8(MY_CLIENT, p);
 	cp->cmd = NetworkRecv_uint32(MY_CLIENT, p);
 	cp->p1 = NetworkRecv_uint32(MY_CLIENT, p);
 	cp->p2 = NetworkRecv_uint32(MY_CLIENT, p);
 	cp->tile = NetworkRecv_uint32(MY_CLIENT, p);
-	/* We are going to send them byte by byte, because dparam is misused
-	    for chars (if it is used), and else we have a BigEndian / LittleEndian
-	    problem.. we should fix the misuse of dparam... -- TrueLight */
-	dparam_char = (char *)&cp->dp[0];
-	for (i = 0; i < lengthof(cp->dp) * 4; i++) {
-		*dparam_char = NetworkRecv_uint8(MY_CLIENT, p);
-		dparam_char++;
-	}
+	NetworkRecv_string(MY_CLIENT, p, cp->text, sizeof(cp->text));
 	cp->callback = NetworkRecv_uint8(MY_CLIENT, p);
 	cp->frame = NetworkRecv_uint32(MY_CLIENT, p);
 	cp->next = NULL;
--- a/network_data.c	Sun May 15 18:43:36 2005 +0000
+++ b/network_data.c	Sun May 15 18:50:55 2005 +0000
@@ -5,6 +5,7 @@
 // Is the network enabled?
 #ifdef ENABLE_NETWORK
 
+#include "string.h"
 #include "table/strings.h"
 #include "network_client.h"
 #include "command.h"
@@ -394,12 +395,6 @@
 	}
 }
 
-// If this fails, make sure you change the following line below:
-//   'memcpy(qp->dp, _decode_parameters, 10 * sizeof(uint32));'
-// Also, in network_data.h, change the size of CommandPacket->dp!
-// (this protection is there to make sure in network.h dp is of the right size!)
-assert_compile(sizeof(_decode_parameters) == 20 * sizeof(uint32));
-
 // Prepare a DoCommand to be send over the network
 void NetworkSend_Command(uint32 tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback)
 {
@@ -430,8 +425,7 @@
 		c->frame = 0; // The client can't tell which frame, so just make it 0
 	}
 
-	// Copy the _decode_parameters to dp
-	memcpy(c->dp, _decode_parameters, 20 * sizeof(uint32));
+	ttd_strlcpy(c->text, (_cmd_text != NULL) ? _cmd_text : "", lengthof(c->text));
 
 	if (_network_server) {
 		// If we are the server, we queue the command in our 'special' queue.
@@ -471,7 +465,7 @@
 void NetworkExecuteCommand(CommandPacket *cp)
 {
 	_current_player = cp->player;
-	memcpy(_decode_parameters, cp->dp, sizeof(cp->dp));
+	_cmd_text = cp->text;
 	/* cp->callback is unsigned. so we don't need to do lower bounds checking. */
 	if (cp->callback > _callback_table_count) {
 		DEBUG(net,0) ("[NET] Received out-of-bounds callback! (%d)", cp->callback);
--- a/network_data.h	Sun May 15 18:43:36 2005 +0000
+++ b/network_data.h	Sun May 15 18:50:55 2005 +0000
@@ -38,7 +38,7 @@
 	uint32 p1;     /// parameter p1
 	uint32 p2;     /// parameter p2
 	uint32 tile;   /// tile command being executed on ; always make it uint32, so it is bigmap compatible (TileIndex)
-	uint32 dp[20]; /// _decode_parameters (for sending strings, etc.)
+	char text[80];
 	uint32 frame;  /// the frame in which this packet is executed
 	byte callback; /// any callback function executed upon successful completion of the command
 } CommandPacket;
--- a/network_server.c	Sun May 15 18:43:36 2005 +0000
+++ b/network_server.c	Sun May 15 18:50:55 2005 +0000
@@ -458,14 +458,11 @@
 	//    uint32: P1 (free variables used in DoCommand)
 	//    uint32: P2
 	//    uint32: Tile
-	//    uint32: decode_params
-	//      10 times the last one (lengthof(cp->dp))
+	//    string: text
 	//    uint8:  CallBackID (see callback_table.c)
 	//    uint32: Frame of execution
 	//
 
-	uint i;
-	char *dparam_char;
 	Packet *p = NetworkSend_Init(PACKET_SERVER_COMMAND);
 
 	NetworkSend_uint8(p, cp->player);
@@ -473,14 +470,7 @@
 	NetworkSend_uint32(p, cp->p1);
 	NetworkSend_uint32(p, cp->p2);
 	NetworkSend_uint32(p, cp->tile);
-	/* We are going to send them byte by byte, because dparam is misused
-	    for chars (if it is used), and else we have a BigEndian / LittleEndian
-	    problem.. we should fix the misuse of dparam... -- TrueLight */
-	dparam_char = (char *)&cp->dp[0];
-	for (i = 0; i < lengthof(cp->dp) * 4; i++) {
-		NetworkSend_uint8(p, *dparam_char);
-		dparam_char++;
-	}
+	NetworkSend_string(p, cp->text);
 	NetworkSend_uint8(p, cp->callback);
 	NetworkSend_uint32(p, cp->frame);
 
@@ -806,8 +796,6 @@
 {
 	NetworkClientState *new_cs;
 	const NetworkClientInfo *ci;
-	char *dparam_char;
-	uint i;
 	byte callback;
 
 	CommandPacket *cp = malloc(sizeof(CommandPacket));
@@ -824,15 +812,7 @@
 	cp->p1     = NetworkRecv_uint32(cs, p);
 	cp->p2     = NetworkRecv_uint32(cs, p);
 	cp->tile   = NetworkRecv_uint32(cs, p);
-	/** @todo We are going to send dparams byte by byte, because dparam is misused
-	 * for charstrings (if it is used), and else we have a Big/Little Endian
-	 * problem.. we should fix the misuse of dparam... -- TrueLight
-	 */
-	dparam_char = (char *)&cp->dp[0];
-	for (i = 0; i < lengthof(cp->dp) * 4; i++) {
-		*dparam_char = NetworkRecv_uint8(cs, p);
-		dparam_char++;
-	}
+	NetworkRecv_string(cs, p, cp->text, lengthof(cp->text));
 
 	callback = NetworkRecv_uint8(cs, p);
 
--- a/order_cmd.c	Sun May 15 18:43:36 2005 +0000
+++ b/order_cmd.c	Sun May 15 18:50:55 2005 +0000
@@ -758,7 +758,7 @@
 
 	/* If we have a custom name, process that */
 	if (bak->name[0] != 0) {
-		strcpy((char*)_decode_parameters, bak->name);
+		_cmd_text = bak->name;
 		DoCommandP(0, v->index, 0, NULL, CMD_NAME_VEHICLE);
 	}
 
--- a/player_gui.c	Sun May 15 18:43:36 2005 +0000
+++ b/player_gui.c	Sun May 15 18:50:55 2005 +0000
@@ -650,7 +650,7 @@
 		if (*b == 0 && WP(w,def_d).byte_1 != 2) // empty string is allowed for password
 			return;
 
-		memcpy(_decode_parameters, b, 32);
+		_cmd_text = b;
 		switch (WP(w,def_d).byte_1) {
 		case 0: /* Change president name */
 			DoCommandP(0, w->window_number, 0, NULL, CMD_CHANGE_PRESIDENT_NAME | CMD_MSG(STR_700D_CAN_T_CHANGE_PRESIDENT));
--- a/players.c	Sun May 15 18:43:36 2005 +0000
+++ b/players.c	Sun May 15 18:50:55 2005 +0000
@@ -691,16 +691,18 @@
 					PlayerID player_backup = _local_player;
 					_network_player_info[p->index].months_empty = 0;
 
-					/* XXX - When a client joins, we automatically set it's name to the player's
-      		 * name (for some reason). As it stands now only the server knows the client's
-					 * name, so it needs to send out a "broadcast" to do this. To achieve this we send
-					 * a network command. However, it uses _local_player to execute the command as.
-					 * To prevent abuse (eg. only yourself can change your name/company), we 'cheat'
-					 * by impersonation _local_player as the server. Not the best solution; but it
-					 * works.
-					 * TODO: Perhaps this could be improved by when the client is ready with joining
-					 * to let it send itself the command, and not the server? For example in network_client.c:534? */
-					memcpy(_decode_parameters, ci->client_name, 32);
+					/* XXX - When a client joins, we automatically set its name to the
+					 * player's name (for some reason). As it stands now only the server
+					 * knows the client's name, so it needs to send out a "broadcast" to
+					 * do this. To achieve this we send a network command. However, it
+					 * uses _local_player to execute the command as.  To prevent abuse
+					 * (eg. only yourself can change your name/company), we 'cheat' by
+					 * impersonation _local_player as the server. Not the best solution;
+					 * but it works.
+					 * TODO: Perhaps this could be improved by when the client is ready
+					 * with joining to let it send itself the command, and not the server?
+					 * For example in network_client.c:534? */
+					_cmd_text = ci->client_name;
 					_local_player = ci->client_playas - 1;
 					NetworkSend_Command(0, 0, 0, CMD_CHANGE_PRESIDENT_NAME, NULL);
 					_local_player = player_backup;
--- a/roadveh_gui.c	Sun May 15 18:43:36 2005 +0000
+++ b/roadveh_gui.c	Sun May 15 18:50:55 2005 +0000
@@ -159,11 +159,11 @@
 		break;
 
 	case WE_ON_EDIT_TEXT: {
-		const char *b = e->edittext.str;
-		if (*b == 0)
-			return;
-		memcpy(_decode_parameters, b, 32);
-		DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(STR_902D_CAN_T_NAME_ROAD_VEHICLE));
+		if (e->edittext.str[0] != '\0') {
+			_cmd_text = e->edittext.str;
+			DoCommandP(0, w->window_number, 0, NULL,
+				CMD_NAME_VEHICLE | CMD_MSG(STR_902D_CAN_T_NAME_ROAD_VEHICLE));
+		}
 	} break;
 
 	}
@@ -441,11 +441,11 @@
 		break;
 
 	case WE_ON_EDIT_TEXT: {
-		const char *b = e->edittext.str;
-		if (*b == 0)
-			return;
-		memcpy(_decode_parameters, b, 32);
-		DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_9037_CAN_T_RENAME_ROAD_VEHICLE));
+		if (e->edittext.str[0] != '\0') {
+			_cmd_text = e->edittext.str;
+			DoCommandP(0, WP(w, buildtrain_d).rename_engine, 0, NULL,
+				CMD_RENAME_ENGINE | CMD_MSG(STR_9037_CAN_T_RENAME_ROAD_VEHICLE));
+		}
 	} break;
 
 	case WE_RESIZE: {
--- a/ship_gui.c	Sun May 15 18:43:36 2005 +0000
+++ b/ship_gui.c	Sun May 15 18:50:55 2005 +0000
@@ -236,11 +236,11 @@
 		break;
 
 	case WE_ON_EDIT_TEXT: {
-		const char *b = e->edittext.str;
-		if (*b == 0)
-			return;
-		memcpy(_decode_parameters, b, 32);
-		DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(STR_9832_CAN_T_NAME_SHIP));
+		if (e->edittext.str[0] != '\0') {
+			_cmd_text = e->edittext.str;
+			DoCommandP(0, w->window_number, 0, NULL,
+				CMD_NAME_VEHICLE | CMD_MSG(STR_9832_CAN_T_NAME_SHIP));
+		}
 	} break;
 
 	}
@@ -378,11 +378,11 @@
 		break;
 
 	case WE_ON_EDIT_TEXT: {
-		const char *b = e->edittext.str;
-		if (*b == 0)
-			return;
-		memcpy(_decode_parameters, b, 32);
-		DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_9839_CAN_T_RENAME_SHIP_TYPE));
+		if (e->edittext.str[0] != '\0') {
+			_cmd_text = e->edittext.str;
+			DoCommandP(0, WP(w, buildtrain_d).rename_engine, 0, NULL,
+				CMD_RENAME_ENGINE | CMD_MSG(STR_9839_CAN_T_RENAME_SHIP_TYPE));
+		}
 	} break;
 
 	case WE_RESIZE:
--- a/signs.c	Sun May 15 18:43:36 2005 +0000
+++ b/signs.c	Sun May 15 18:50:55 2005 +0000
@@ -142,7 +142,7 @@
 	 * So rename the sign. If it is empty, it has no name, so delete it */
 	if (GetDParam(0) != 0) {
 		/* Create the name */
-		StringID str = AllocateName((const char*)_decode_parameters, 0);
+		StringID str = AllocateName(_cmd_text, 0);
 		if (str == 0) return CMD_ERROR;
 
 		if (flags & DC_EXEC) {
--- a/station_cmd.c	Sun May 15 18:43:36 2005 +0000
+++ b/station_cmd.c	Sun May 15 18:50:55 2005 +0000
@@ -2658,7 +2658,7 @@
 
 	if (!IsValidStation(st) || !CheckOwnership(st->owner)) return CMD_ERROR;
 
-	str = AllocateNameUnique((const char*)_decode_parameters, 6);
+	str = AllocateNameUnique(_cmd_text, 6);
 	if (str == 0) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
--- a/station_gui.c	Sun May 15 18:43:36 2005 +0000
+++ b/station_gui.c	Sun May 15 18:50:55 2005 +0000
@@ -503,14 +503,13 @@
 		break;
 
 	case WE_ON_EDIT_TEXT: {
-		Station *st;
-		const char *b = e->edittext.str;
-		if (*b == 0)
-			return;
-		memcpy(_decode_parameters, b, 32);
+		if (e->edittext.str[0] != '\0') {
+			Station* st = GetStation(w->window_number);
 
-		st = GetStation(w->window_number);
-		DoCommandP(st->xy, w->window_number, 0, NULL, CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION));
+			_cmd_text = e->edittext.str;
+			DoCommandP(st->xy, w->window_number, 0, NULL,
+				CMD_RENAME_STATION | CMD_MSG(STR_3031_CAN_T_RENAME_STATION));
+		}
 	} break;
 
 	case WE_DESTROY: {
--- a/town_cmd.c	Sun May 15 18:43:36 2005 +0000
+++ b/town_cmd.c	Sun May 15 18:50:55 2005 +0000
@@ -1451,7 +1451,7 @@
 
 	t = GetTown(p1);
 
-	str = AllocateNameUnique((const char*)_decode_parameters, 4);
+	str = AllocateNameUnique(_cmd_text, 4);
 	if (str == 0) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
--- a/town_gui.c	Sun May 15 18:43:36 2005 +0000
+++ b/town_gui.c	Sun May 15 18:50:55 2005 +0000
@@ -276,11 +276,11 @@
 		break;
 
 	case WE_ON_EDIT_TEXT: {
-		const char *b = e->edittext.str;
-		if (*b == 0)
-			return;
-		memcpy(_decode_parameters, b, 32);
-		DoCommandP(0, w->window_number, 0, NULL, CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN));
+		if (e->edittext.str[0] != '\0') {
+			_cmd_text = e->edittext.str;
+			DoCommandP(0, w->window_number, 0, NULL,
+				CMD_RENAME_TOWN | CMD_MSG(STR_2008_CAN_T_RENAME_TOWN));
+		}
 	} break;
 	}
 }
--- a/train_gui.c	Sun May 15 18:43:36 2005 +0000
+++ b/train_gui.c	Sun May 15 18:50:55 2005 +0000
@@ -219,12 +219,11 @@
 		break;
 
 	case WE_ON_EDIT_TEXT: {
-		const char *b = e->edittext.str;
-		if (*b == 0)
-			return;
-
-		memcpy(_decode_parameters, b, 32);
-		DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL, CMD_RENAME_ENGINE | CMD_MSG(STR_886B_CAN_T_RENAME_TRAIN_VEHICLE));
+		if (e->edittext.str[0] != '\0') {
+			_cmd_text = e->edittext.str;
+			DoCommandP(0, WP(w,buildtrain_d).rename_engine, 0, NULL,
+				CMD_RENAME_ENGINE | CMD_MSG(STR_886B_CAN_T_RENAME_TRAIN_VEHICLE));
+		}
 	} break;
 
 	case WE_RESIZE: {
@@ -1144,11 +1143,11 @@
 		break;
 
 	case WE_ON_EDIT_TEXT: {
-		const char *b = e->edittext.str;
-		if (*b == 0)
-			return;
-		memcpy(_decode_parameters, b, 32);
-		DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(STR_8866_CAN_T_NAME_TRAIN));
+		if (e->edittext.str[0] != '\0') {
+			_cmd_text = e->edittext.str;
+			DoCommandP(0, w->window_number, 0, NULL,
+				CMD_NAME_VEHICLE | CMD_MSG(STR_8866_CAN_T_NAME_TRAIN));
+		}
 	} break;
 	}
 }
--- a/vehicle.c	Sun May 15 18:43:36 2005 +0000
+++ b/vehicle.c	Sun May 15 18:50:55 2005 +0000
@@ -1660,7 +1660,7 @@
 
 	if (!CheckOwnership(v->owner)) return CMD_ERROR;
 
-	str = AllocateNameUnique((const char*)_decode_parameters, 2);
+	str = AllocateNameUnique(_cmd_text, 2);
 	if (str == 0) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
--- a/waypoint.c	Sun May 15 18:43:36 2005 +0000
+++ b/waypoint.c	Sun May 15 18:50:55 2005 +0000
@@ -302,8 +302,8 @@
 
 	if (!IsWaypointIndex(p1)) return CMD_ERROR;
 
-	if (_decode_parameters[0] != 0) {
-		str = AllocateNameUnique((const char*)_decode_parameters, 0);
+	if (_cmd_text[0] != '\0') {
+		str = AllocateNameUnique(_cmd_text, 0);
 		if (str == 0)
 			return CMD_ERROR;