Index: src/settings.cpp
===================================================================
--- src/settings.cpp	(revision 20009)
+++ src/settings.cpp	(working copy)
@@ -69,6 +69,7 @@
 
 #include "void_map.h"
 #include "station_base.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/settings.h"
@@ -1083,6 +1084,28 @@
 	return true;
 }
 
+static bool CheckSharingRail(int32 p1)
+{
+	if (!CheckSharingChangePossible(VEH_TRAIN)) return false;
+	UpdateAllBlockSignals();
+	return true;
+}
+
+static bool CheckSharingRoad(int32 p1)
+{
+	return CheckSharingChangePossible(VEH_ROAD);
+}
+
+static bool CheckSharingWater(int32 p1)
+{
+	return CheckSharingChangePossible(VEH_SHIP);
+}
+
+static bool CheckSharingAir(int32 p1)
+{
+	return CheckSharingChangePossible(VEH_AIRCRAFT);
+}
+
 #ifdef ENABLE_NETWORK
 
 static bool UpdateClientName(int32 p1)
Index: src/train.h
===================================================================
--- src/train.h	(revision 20009)
+++ src/train.h	(working copy)
@@ -58,6 +58,8 @@
 void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
 bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);
 
+void DeleteVisibleTrain(Train *v);
+
 int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
 
 /** Variables that are cached to improve performance and such */
Index: src/lang/english.txt
===================================================================
--- src/lang/english.txt	(revision 20009)
+++ src/lang/english.txt	(working copy)
@@ -1237,6 +1237,18 @@
 STR_CONFIG_SETTING_AI_IN_MULTIPLAYER                            :{LTBLUE}Allow AIs in multiplayer: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_AI_MAX_OPCODES                               :{LTBLUE}#opcodes before AI is suspended: {ORANGE}{STRING1}
 
+STR_CONFIG_SETTING_SHARING_RAIL                                 :{LTBLUE}Enable sharing of railways: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_ROAD                                 :{LTBLUE}Enable sharing of road stops and depots: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_WATER                                :{LTBLUE}Enable sharing of docks and ship depots: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_AIR                                  :{LTBLUE}Enable sharing of airports: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_FEE_RAIL                             :{LTBLUE}Daily track toll for trains: {ORANGE}{STRING1} per 1000 tonnes
+STR_CONFIG_SETTING_SHARING_FEE_ROAD                             :{LTBLUE}Stopping fee for road vehicles: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_FEE_WATER                            :{LTBLUE}Docking fee for ships: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_FEE_AIR                              :{LTBLUE}Terminal fee for aircraft: {ORANGE}{STRING1} per day
+STR_CONFIG_SETTING_SHARING_PAYMENT_IN_DEBT                      :{LTBLUE}Allow companies in debt to pay sharing fees: {ORANGE}{STRING1}
+STR_CONFIG_SETTING_SHARING_USED_BY_VEHICLES                     :{WHITE}Can't change this setting, vehicles are using shared infrastructure.
+STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS                     :{WHITE}Can't change this setting, vehicles have orders to destinations of others.
+
 STR_CONFIG_SETTING_SERVINT_ISPERCENT                            :{LTBLUE}Service intervals are in percents: {ORANGE}{STRING1}
 STR_CONFIG_SETTING_SERVINT_TRAINS                               :{LTBLUE}Default service interval for trains: {ORANGE}{STRING1} days/%
 STR_CONFIG_SETTING_SERVINT_TRAINS_DISABLED                      :{LTBLUE}Default service interval for trains: {ORANGE}disabled
@@ -1315,6 +1327,7 @@
 STR_CONFIG_SETTING_CONSTRUCTION_SIGNALS                         :{ORANGE}Signals
 STR_CONFIG_SETTING_STATIONS_CARGOHANDLING                       :{ORANGE}Cargo handling
 STR_CONFIG_SETTING_AI_NPC                                       :{ORANGE}Computer players
+STR_CONFIG_SETTING_SHARING                                      :{ORANGE}Infrastructure sharing
 STR_CONFIG_SETTING_VEHICLES_AUTORENEW                           :{ORANGE}Autorenew
 STR_CONFIG_SETTING_VEHICLES_SERVICING                           :{ORANGE}Servicing
 STR_CONFIG_SETTING_VEHICLES_ROUTING                             :{ORANGE}Routing
@@ -2601,6 +2614,8 @@
 STR_FINANCES_SECTION_SHIP_INCOME                                :{GOLD}Ship Income
 STR_FINANCES_SECTION_LOAN_INTEREST                              :{GOLD}Loan Interest
 STR_FINANCES_SECTION_OTHER                                      :{GOLD}Other
+STR_FINANCES_SECTION_INFRASTRUCTURE_COSTS                       :{GOLD}Infrastructure Sharing Costs
+STR_FINANCES_SECTION_INFRASTRUCTURE_INCOME                      :{GOLD}Infrastructure Sharing Income
 STR_FINANCES_NEGATIVE_INCOME                                    :{BLACK}-{CURRENCY}
 STR_FINANCES_POSITIVE_INCOME                                    :{BLACK}+{CURRENCY}
 STR_FINANCES_TOTAL_CAPTION                                      :{WHITE}Total:
Index: src/settings_gui.cpp
===================================================================
--- src/settings_gui.cpp	(revision 20009)
+++ src/settings_gui.cpp	(working copy)
@@ -1395,8 +1395,23 @@
 /** Computer players sub-page */
 static SettingsPage _settings_ai_npc_page = {_settings_ai_npc, lengthof(_settings_ai_npc)};
 
+static SettingEntry _settings_sharing[] = {
+	SettingEntry("economy.infrastructure_sharing[0]"),
+	SettingEntry("economy.infrastructure_sharing[1]"),
+	SettingEntry("economy.infrastructure_sharing[2]"),
+	SettingEntry("economy.infrastructure_sharing[3]"),
+	SettingEntry("economy.sharing_fee[0]"),
+	SettingEntry("economy.sharing_fee[1]"),
+	SettingEntry("economy.sharing_fee[2]"),
+	SettingEntry("economy.sharing_fee[3]"),
+	SettingEntry("economy.sharing_payment_in_debt"),
+};
+/** Infrastructure sharing sub-page */
+static SettingsPage _settings_sharing_page = {_settings_sharing, lengthof(_settings_sharing)};
+
 static SettingEntry _settings_ai[] = {
 	SettingEntry(&_settings_ai_npc_page, STR_CONFIG_SETTING_AI_NPC),
+	SettingEntry(&_settings_sharing_page, STR_CONFIG_SETTING_SHARING),
 	SettingEntry("economy.give_money"),
 	SettingEntry("economy.allow_shares"),
 };
Index: src/table/settings.h
===================================================================
--- src/table/settings.h	(revision 20009)
+++ src/table/settings.h	(working copy)
@@ -39,6 +39,10 @@
 static bool ChangeDynamicEngines(int32 p1);
 static bool StationCatchmentChanged(int32 p1);
 static bool InvalidateVehTimetableWindow(int32 p1);
+static bool CheckSharingRail(int32 p1);
+static bool CheckSharingRoad(int32 p1);
+static bool CheckSharingWater(int32 p1);
+static bool CheckSharingAir(int32 p1);
 
 #ifdef ENABLE_NETWORK
 static bool UpdateClientName(int32 p1);
@@ -446,6 +450,16 @@
 	 SDT_CONDVAR(GameSettings, economy.initial_city_size,            SLE_UINT8, 56, SL_MAX_VERSION, 0, 0,     2,     1,      10, 1, STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER,   NULL),
 	SDT_CONDBOOL(GameSettings, economy.mod_road_rebuild,                        77, SL_MAX_VERSION, 0, 0,  true,                    STR_CONFIG_SETTING_MODIFIED_ROAD_REBUILD,  NULL),
 
+	SDT_CONDBOOL(GameSettings, economy.infrastructure_sharing[0],              143, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_RAIL,           CheckSharingRail),
+	SDT_CONDBOOL(GameSettings, economy.infrastructure_sharing[1],              143, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_ROAD,           CheckSharingRoad),
+	SDT_CONDBOOL(GameSettings, economy.infrastructure_sharing[2],              143, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_WATER,          CheckSharingWater),
+	SDT_CONDBOOL(GameSettings, economy.infrastructure_sharing[3],              143, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_AIR,            CheckSharingAir),
+	 SDT_CONDVAR(GameSettings, economy.sharing_fee[0],                SLE_UINT,143, SL_MAX_VERSION, 0,CR,   100,     0, 1000000, 10,STR_CONFIG_SETTING_SHARING_FEE_RAIL,       NULL),
+	 SDT_CONDVAR(GameSettings, economy.sharing_fee[1],                SLE_UINT,143, SL_MAX_VERSION, 0,CR,   100,     0, 1000000, 10,STR_CONFIG_SETTING_SHARING_FEE_ROAD,       NULL),
+	 SDT_CONDVAR(GameSettings, economy.sharing_fee[2],                SLE_UINT,143, SL_MAX_VERSION, 0,CR,   100,     0, 1000000, 10,STR_CONFIG_SETTING_SHARING_FEE_WATER,      NULL),
+	 SDT_CONDVAR(GameSettings, economy.sharing_fee[3],                SLE_UINT,143, SL_MAX_VERSION, 0,CR,   100,     0, 1000000, 10,STR_CONFIG_SETTING_SHARING_FEE_AIR,        NULL),
+	SDT_CONDBOOL(GameSettings, economy.sharing_payment_in_debt,                143, SL_MAX_VERSION, 0, 0, false,                    STR_CONFIG_SETTING_SHARING_PAYMENT_IN_DEBT,NULL),
+ 
 	SDT_CONDNULL(1, 0, 106), // previously ai-new setting.
 	    SDT_BOOL(GameSettings, ai.ai_in_multiplayer,                                                0, 0, true,                     STR_CONFIG_SETTING_AI_IN_MULTIPLAYER,      NULL),
 	    SDT_BOOL(GameSettings, ai.ai_disable_veh_train,                                             0, 0, false,                    STR_CONFIG_SETTING_AI_BUILDS_TRAINS,       NULL),
Index: src/ship_cmd.cpp
===================================================================
--- src/ship_cmd.cpp	(revision 20009)
+++ src/ship_cmd.cpp	(working copy)
@@ -39,6 +39,7 @@
 #include "engine_base.h"
 #include "engine_func.h"
 #include "company_base.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -114,7 +115,7 @@
 
 	FOR_ALL_DEPOTS(depot) {
 		TileIndex tile = depot->xy;
-		if (IsShipDepotTile(tile) && IsTileOwner(tile, v->owner)) {
+		if (IsShipDepotTile(tile) && IsInfraTileUsageAllowed(VEH_SHIP, v->owner, tile)) {
 			uint dist = DistanceManhattan(tile, v->tile);
 			if (dist < best_dist) {
 				best_dist = dist;
@@ -627,7 +628,7 @@
 	/* The ai_new queries the vehicle cost before building the route,
 	 * so we must check against cheaters no sooner than now. --pasky */
 	if (!IsShipDepotTile(tile)) return CMD_ERROR;
-	if (!IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!IsInfraUsageAllowed(VEH_SHIP, _current_company, GetTileOwner(tile))) return CMD_ERROR;
 
 	unit_num = (flags & DC_AUTOREPLACE) ? 0 : GetFreeUnitNumber(VEH_SHIP);
 
Index: src/order_cmd.cpp
===================================================================
--- src/order_cmd.cpp	(revision 20009)
+++ src/order_cmd.cpp	(working copy)
@@ -28,6 +28,7 @@
 #include "station_base.h"
 #include "waypoint_base.h"
 #include "company_base.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 
@@ -482,7 +483,7 @@
 			if (st == NULL) return CMD_ERROR;
 
 			if (st->owner != OWNER_NONE) {
-				CommandCost ret = CheckOwnership(st->owner);
+				CommandCost ret = CheckInfraUsageAllowed(v->type, st->owner);
 				if (ret.Failed()) return ret;
 			}
 
@@ -530,7 +531,7 @@
 
 					if (st == NULL) return CMD_ERROR;
 
-					CommandCost ret = CheckOwnership(st->owner);
+					CommandCost ret = CheckInfraUsageAllowed(v->type, st->owner);
 					if (ret.Failed()) return ret;
 
 					if (!CanVehicleUseStation(v, st) || !st->airport.HasHangar()) {
@@ -541,7 +542,7 @@
 
 					if (dp == NULL) return CMD_ERROR;
 
-					CommandCost ret = CheckOwnership(GetTileOwner(dp->xy));
+					CommandCost ret = CheckInfraUsageAllowed(v->type, GetTileOwner(dp->xy), dp->xy);
 					if (ret.Failed()) return ret;
 
 					switch (v->type) {
@@ -579,7 +580,7 @@
 				case VEH_TRAIN: {
 					if (!(wp->facilities & FACIL_TRAIN)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
 
-					CommandCost ret = CheckOwnership(wp->owner);
+					CommandCost ret = CheckInfraUsageAllowed(v->type, wp->owner);
 					if (ret.Failed()) return ret;
 					break;
 				}
@@ -587,7 +588,7 @@
 				case VEH_SHIP:
 					if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
 					if (wp->owner != OWNER_NONE) {
-						CommandCost ret = CheckOwnership(wp->owner);
+						CommandCost ret = CheckInfraUsageAllowed(v->type, wp->owner);
 						if (ret.Failed()) return ret;
 					}
 					break;
Index: src/company_cmd.cpp
===================================================================
--- src/company_cmd.cpp	(revision 20009)
+++ src/company_cmd.cpp	(working copy)
@@ -189,14 +189,16 @@
 	if (HasBit(1 << EXPENSES_TRAIN_INC    |
 	           1 << EXPENSES_ROADVEH_INC  |
 	           1 << EXPENSES_AIRCRAFT_INC |
-	           1 << EXPENSES_SHIP_INC, cost.GetExpensesType())) {
+	           1 << EXPENSES_SHIP_INC     |
+			   1 << EXPENSES_SHARING_INC, cost.GetExpensesType())) {
 		c->cur_economy.income -= cost.GetCost();
 	} else if (HasBit(1 << EXPENSES_TRAIN_RUN    |
 	                  1 << EXPENSES_ROADVEH_RUN  |
 	                  1 << EXPENSES_AIRCRAFT_RUN |
 	                  1 << EXPENSES_SHIP_RUN     |
 	                  1 << EXPENSES_PROPERTY     |
-	                  1 << EXPENSES_LOAN_INT, cost.GetExpensesType())) {
+	                  1 << EXPENSES_LOAN_INT     |
+					  1 << EXPENSES_SHARING_COST, cost.GetExpensesType())) {
 		c->cur_economy.expenses -= cost.GetCost();
 	}
 
Index: src/vehicle_cmd.cpp
===================================================================
--- src/vehicle_cmd.cpp	(revision 20009)
+++ src/vehicle_cmd.cpp	(working copy)
@@ -28,6 +28,7 @@
 #include "depot_map.h"
 #include "vehiclelist.h"
 #include "engine_base.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 
@@ -77,7 +78,7 @@
 	Vehicle *v = Vehicle::GetIfValid(p1);
 	if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
 
-	CommandCost ret = CheckOwnership(v->owner);
+	CommandCost ret = CheckVehicleControlAllowed(v);
 	if (ret.Failed()) return ret;
 
 	if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_VEHICLE_IS_DESTROYED);
@@ -224,7 +225,7 @@
 	VehicleType vehicle_type = Extract<VehicleType, 0, 3>(p1);
 
 	if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR;
-	if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!IsDepotTile(tile) || !IsInfraUsageAllowed(vehicle_type, _current_company, GetTileOwner(tile))) return CMD_ERROR;
 
 	/* Get the list of vehicles in the depot */
 	BuildDepotVehicleList(vehicle_type, tile, &list, &list, true);
Index: src/train_cmd.cpp
===================================================================
--- src/train_cmd.cpp	(revision 20009)
+++ src/train_cmd.cpp	(working copy)
@@ -41,6 +41,7 @@
 #include "engine_base.h"
 #include "engine_func.h"
 #include "newgrf.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/train_cmd.h"
@@ -705,7 +706,7 @@
 	/* Check if the train is actually being built in a depot belonging
 	 * to the company. Doesn't matter if only the cost is queried */
 	if (!IsRailDepotTile(tile)) return CMD_ERROR;
-	if (!IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!IsInfraUsageAllowed(VEH_TRAIN, _current_company, GetTileOwner(tile))) return CMD_ERROR;
 
 	if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(eid, tile, flags);
 
@@ -1898,7 +1899,7 @@
 	Train *t = Train::GetIfValid(p1);
 	if (t == NULL) return CMD_ERROR;
 
-	CommandCost ret = CheckOwnership(t->owner);
+	CommandCost ret = CheckVehicleControlAllowed(t);
 	if (ret.Failed()) return ret;
 
 
@@ -1935,7 +1936,7 @@
 	Train *v = Train::GetIfValid(p1);
 	if (v == NULL) return CMD_ERROR;
 
-	CommandCost ret = CheckOwnership(v->owner);
+	CommandCost ret = CheckVehicleControlAllowed(v);
 	if (ret.Failed()) return ret;
 
 	if (!v->IsStoppedInDepot()) return_cmd_error(STR_TRAIN_MUST_BE_STOPPED);
@@ -2917,7 +2918,7 @@
 static inline bool CheckCompatibleRail(const Train *v, TileIndex tile)
 {
 	return
-		IsTileOwner(tile, v->owner) && (
+		IsInfraTileUsageAllowed(VEH_TRAIN, v->owner, tile) && (
 			!v->IsFrontEngine() ||
 			HasBit(v->compatible_railtypes, GetRailType(tile))
 		);
@@ -4036,6 +4037,9 @@
 			/* running costs */
 			CommandCost cost(EXPENSES_TRAIN_RUN, this->GetRunningCost() * this->running_ticks / (DAYS_IN_YEAR  * DAY_TICKS));
 
+			/* sharing fee */
+			PayDailyTrackSharingFee(this);
+
 			this->profit_this_year -= cost.GetCost();
 			this->running_ticks = 0;
 
@@ -4066,3 +4070,49 @@
 
 	return TrackDirectionToTrackdir(FindFirstTrack(this->track), this->direction);
 }
+
+/**
+ * Delete a train while it is visible.
+ * This happens when a company bankrupts when infrastructure sharing is enabled.
+ * @param v The train to delete.
+ */
+void DeleteVisibleTrain(Train *v)
+{
+	FreeTrainTrackReservation(v);
+	TileIndex crossing = TrainApproachingCrossingTile(v);
+
+	/* delete train from back to front */
+	Train *u;
+	Train *prev = v->Last();
+	do {
+		u = prev;
+		prev = u->Previous();
+		if (prev != NULL) prev->SetNext(NULL);
+
+		/* 'u' shouldn't be accessed after it has been deleted */
+		TileIndex tile = u->tile;
+		TrackBits trackbits = u->track;
+
+		delete u;
+
+		if (trackbits == TRACK_BIT_WORMHOLE) {
+			/* Vehicle is inside a wormhole, u->track contains no useful value then. */
+			trackbits = DiagDirToDiagTrackBits(GetTunnelBridgeDirection(tile));
+		}
+
+		Track track = TrackBitsToTrack(trackbits);
+		if (HasReservedTracks(tile, trackbits)) UnreserveRailTrack(tile, track);
+		if (IsLevelCrossingTile(tile)) UpdateLevelCrossing(tile);
+
+		/* Update signals */
+		if (IsTileType(tile, MP_TUNNELBRIDGE) || IsRailDepotTile(tile)) {
+			AddSideToSignalBuffer(tile, INVALID_DIAGDIR, GetTileOwner(tile));
+		} else {
+			AddTrackToSignalBuffer(tile, track, GetTileOwner(tile));
+		}
+	} while (prev != NULL);
+
+	if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
+
+	UpdateSignalsInBuffer();
+}
Index: src/settings_type.h
===================================================================
--- src/settings_type.h	(revision 20009)
+++ src/settings_type.h	(working copy)
@@ -350,6 +350,9 @@
 	TownFoundingByte found_town;             ///< town founding, @see TownFounding
 	bool   station_noise_level;              ///< build new airports when the town noise level is still within accepted limits
 	uint16 town_noise_population[3];         ///< population to base decision on noise evaluation (@see town_council_tolerance)
+	bool   infrastructure_sharing[4];        ///< enable infrastructure sharing for rail/road/water/air
+	uint   sharing_fee[4];                   ///< fees for infrastructure sharing for rail/road/water/air
+	bool   sharing_payment_in_debt;          ///< allow fee payment for companies with more loan than money (switch off to prevent MP exploits)
 };
 
 /** Settings related to stations. */
Index: src/depot_gui.cpp
===================================================================
--- src/depot_gui.cpp	(revision 20009)
+++ src/depot_gui.cpp	(working copy)
@@ -30,6 +30,8 @@
 #include "tilehighlight_func.h"
 #include "window_gui.h"
 #include "vehiclelist.h"
+#include "company_base.h"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -691,7 +693,7 @@
 
 		/* Setup disabled buttons. */
 		TileIndex tile = this->window_number;
-		this->SetWidgetsDisabledState(!IsTileOwner(tile, _local_company),
+		this->SetWidgetsDisabledState(!Company::IsValidID(_local_company) || !IsInfraTileUsageAllowed(this->type, _local_company, tile),
 			DEPOT_WIDGET_STOP_ALL,
 			DEPOT_WIDGET_START_ALL,
 			DEPOT_WIDGET_SELL,
Index: src/order_gui.cpp
===================================================================
--- src/order_gui.cpp	(revision 20009)
+++ src/order_gui.cpp	(working copy)
@@ -29,6 +29,7 @@
 #include "station_base.h"
 #include "waypoint_base.h"
 #include "core/geometry_func.hpp"
+#include "infrastructure_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -308,7 +309,7 @@
 	if (_settings_game.order.gotodepot) {
 		switch (GetTileType(tile)) {
 			case MP_RAILWAY:
-				if (v->type == VEH_TRAIN && IsTileOwner(tile, _local_company)) {
+				if (v->type == VEH_TRAIN && IsInfraTileUsageAllowed(VEH_TRAIN, v->owner, tile)) {
 					if (IsRailDepot(tile)) {
 						order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS,
 								_settings_client.gui.new_nonstop ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
@@ -319,7 +320,7 @@
 				break;
 
 			case MP_ROAD:
-				if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsTileOwner(tile, _local_company)) {
+				if (IsRoadDepot(tile) && v->type == VEH_ROAD && IsInfraTileUsageAllowed(VEH_ROAD, v->owner, tile)) {
 					order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS,
 							_settings_client.gui.new_nonstop ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
 					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
@@ -329,7 +330,7 @@
 
 			case MP_STATION:
 				if (v->type != VEH_AIRCRAFT) break;
-				if (IsHangar(tile) && IsTileOwner(tile, _local_company)) {
+				if (IsHangar(tile) && IsInfraTileUsageAllowed(VEH_AIRCRAFT, v->owner, tile)) {
 					order.MakeGoToDepot(GetStationIndex(tile), ODTFB_PART_OF_ORDERS, ONSF_STOP_EVERYWHERE);
 					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
 					return order;
@@ -338,7 +339,7 @@
 
 			case MP_WATER:
 				if (v->type != VEH_SHIP) break;
-				if (IsShipDepot(tile) && IsTileOwner(tile, _local_company)) {
+				if (IsShipDepot(tile) && IsInfraTileUsageAllowed(VEH_SHIP, v->owner, tile)) {
 					order.MakeGoToDepot(GetDepotIndex(tile), ODTFB_PART_OF_ORDERS, ONSF_STOP_EVERYWHERE);
 					if (_ctrl_pressed) order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() ^ ODTFB_SERVICE));
 					return order;
@@ -352,7 +353,7 @@
 	/* check waypoint */
 	if (IsRailWaypointTile(tile) &&
 			v->type == VEH_TRAIN &&
-			IsTileOwner(tile, _local_company)) {
+			IsInfraTileUsageAllowed(VEH_TRAIN, v->owner, tile)) {
 		order.MakeGoToWaypoint(Waypoint::GetByTile(tile)->index);
 		if (_settings_client.gui.new_nonstop != _ctrl_pressed) order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
 		return order;
@@ -367,7 +368,7 @@
 		StationID st_index = GetStationIndex(tile);
 		const Station *st = Station::Get(st_index);
 
-		if (st->owner == _local_company || st->owner == OWNER_NONE) {
+		if (IsInfraUsageAllowed(v->type, v->owner, st->owner)) {
 			byte facil;
 			(facil = FACIL_DOCK, v->type == VEH_SHIP) ||
 			(facil = FACIL_TRAIN, v->type == VEH_TRAIN) ||
Index: src/economy.cpp
===================================================================
--- src/economy.cpp	(revision 20009)
+++ src/economy.cpp	(working copy)
@@ -48,6 +48,7 @@
 #include "newgrf.h"
 #include "engine_base.h"
 #include "core/backup_type.hpp"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -381,7 +382,8 @@
 		ClrBit(t->have_ratings, old_owner);
 	}
 
-	{
+	/* Change ownership of vehicles */
+	if (new_owner != INVALID_OWNER) {
 		FreeUnitIDGenerator unitidgen[] = {
 			FreeUnitIDGenerator(VEH_TRAIN, new_owner), FreeUnitIDGenerator(VEH_ROAD,     new_owner),
 			FreeUnitIDGenerator(VEH_SHIP,  new_owner), FreeUnitIDGenerator(VEH_AIRCRAFT, new_owner)
@@ -390,16 +392,16 @@
 		Vehicle *v;
 		FOR_ALL_VEHICLES(v) {
 			if (v->owner == old_owner && IsCompanyBuildableVehicleType(v->type)) {
-				if (new_owner == INVALID_OWNER) {
-					if (v->Previous() == NULL) delete v;
-				} else {
-					v->owner = new_owner;
-					v->colourmap = PAL_NONE;
-					if (v->IsEngineCountable()) Company::Get(new_owner)->num_engines[v->engine_type]++;
-					if (v->IsPrimaryVehicle()) v->unitnumber = unitidgen[v->type].NextID();
-				}
+				v->owner = new_owner;
+				v->colourmap = PAL_NONE;
+				if (v->IsEngineCountable()) Company::Get(new_owner)->num_engines[v->engine_type]++;
+				if (v->IsPrimaryVehicle()) v->unitnumber = unitidgen[v->type].NextID();
 			}
 		}
+	} else {
+		/* Depending on sharing settings, other companies could be affected too.
+		 * Let the infrastructure sharing code handle this. */
+		HandleSharingCompanyDeletion(old_owner);
 	}
 
 	/*  Change ownership of tiles */
@@ -414,22 +416,13 @@
 			 * and signals were not propagated
 			 * Similiar with crossings - it is needed to bar crossings that weren't before
 			 * because of different owner of crossing and approaching train */
-			tile = 0;
-
-			do {
-				if (IsTileType(tile, MP_RAILWAY) && IsTileOwner(tile, new_owner) && HasSignals(tile)) {
-					TrackBits tracks = GetTrackBits(tile);
-					do { // there may be two tracks with signals for TRACK_BIT_HORZ and TRACK_BIT_VERT
-						Track track = RemoveFirstTrack(&tracks);
-						if (HasSignalOnTrack(tile, track)) AddTrackToSignalBuffer(tile, track, new_owner);
-					} while (tracks != TRACK_BIT_NONE);
-				} else if (IsLevelCrossingTile(tile) && IsTileOwner(tile, new_owner)) {
-					UpdateLevelCrossing(tile);
-				}
-			} while (++tile != MapSize());
+			UpdateAllBlockSignals(new_owner);
+		} else if (_settings_game.economy.infrastructure_sharing[VEH_TRAIN]) {
+			/* tracks are being removed while sharing is enabled.
+			 * Thus, update all signals and crossings. */
+			UpdateAllBlockSignals();
 		}
-
-		/* update signals in buffer */
+		/* Update any signals in the buffer */
 		UpdateSignalsInBuffer();
 	}
 
Index: src/company_gui.cpp
===================================================================
--- src/company_gui.cpp	(revision 20009)
+++ src/company_gui.cpp	(working copy)
@@ -55,6 +55,8 @@
 	EXPENSES_AIRCRAFT_INC,
 	EXPENSES_SHIP_INC,
 	EXPENSES_LOAN_INT,
+	EXPENSES_SHARING_INC,
+	EXPENSES_SHARING_COST,
 	EXPENSES_OTHER,
 };
 
@@ -64,6 +66,7 @@
 	EXPENSES_ROADVEH_INC,
 	EXPENSES_AIRCRAFT_INC,
 	EXPENSES_SHIP_INC,
+	EXPENSES_SHARING_INC,
 	INVALID_EXPENSES,
 	EXPENSES_TRAIN_RUN,
 	EXPENSES_ROADVEH_RUN,
@@ -71,6 +74,7 @@
 	EXPENSES_SHIP_RUN,
 	EXPENSES_PROPERTY,
 	EXPENSES_LOAN_INT,
+	EXPENSES_SHARING_COST,
 	INVALID_EXPENSES,
 	EXPENSES_CONSTRUCTION,
 	EXPENSES_NEW_VEHICLES,
Index: src/vehicle_gui.cpp
===================================================================
--- src/vehicle_gui.cpp	(revision 20009)
+++ src/vehicle_gui.cpp	(working copy)
@@ -44,6 +44,7 @@
 #include "engine_func.h"
 #include "newgrf.h"
 #include "station_base.h"
+#include "infrastructure_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -2018,6 +2019,7 @@
 	{
 		const Vehicle *v = Vehicle::Get(this->window_number);
 		bool is_localcompany = v->owner == _local_company;
+		bool can_control = IsVehicleControlAllowed(v, _local_company);
 		bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
 
 		this->SetWidgetDisabledState(VVW_WIDGET_GOTO_DEPOT, !is_localcompany);
@@ -2026,8 +2028,8 @@
 
 		if (v->type == VEH_TRAIN) {
 			this->SetWidgetLoweredState(VVW_WIDGET_FORCE_PROCEED, Train::From(v)->force_proceed == TFP_SIGNAL);
-			this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localcompany);
-			this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localcompany);
+			this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !can_control);
+			this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !can_control);
 		}
 
 		this->DrawWidgets();
Index: src/saveload/saveload.cpp
===================================================================
--- src/saveload/saveload.cpp	(revision 20009)
+++ src/saveload/saveload.cpp	(working copy)
@@ -47,7 +47,7 @@
 
 #include "saveload_internal.h"
 
-extern const uint16 SAVEGAME_VERSION = 142;
+extern const uint16 SAVEGAME_VERSION = 143;
 
 SavegameType _savegame_type; ///< type of savegame we are loading
 
Index: src/saveload/company_sl.cpp
===================================================================
--- src/saveload/company_sl.cpp	(revision 20009)
+++ src/saveload/company_sl.cpp	(working copy)
@@ -135,7 +135,8 @@
 
 	/* yearly expenses was changed to 64-bit in savegame version 2. */
 	SLE_CONDARR(CompanyProperties, yearly_expenses,       SLE_FILE_I32 | SLE_VAR_I64, 3 * 13, 0, 1),
-	SLE_CONDARR(CompanyProperties, yearly_expenses,       SLE_INT64, 3 * 13,                  2, SL_MAX_VERSION),
+	SLE_CONDARR(CompanyProperties, yearly_expenses,       SLE_INT64, 3 * 13,                  2, 142),
+	SLE_CONDARR(CompanyProperties, yearly_expenses,       SLE_INT64, 3 * 15,                143, SL_MAX_VERSION),
 
 	SLE_CONDVAR(CompanyProperties, is_ai,                 SLE_BOOL,                    2, SL_MAX_VERSION),
 	SLE_CONDNULL(1, 107, 111), ///< is_noai
Index: src/saveload/afterload.cpp
===================================================================
--- src/saveload/afterload.cpp	(revision 20009)
+++ src/saveload/afterload.cpp	(working copy)
@@ -53,6 +53,7 @@
 #include "../engine_func.h"
 #include "../rail_gui.h"
 #include "../core/backup_type.hpp"
+#include "../core/mem_func.hpp"
 
 #include "table/strings.h"
 
@@ -2133,6 +2134,20 @@
 		FOR_ALL_DEPOTS(d) d->build_date = _date;
 	}
 
+	if (CheckSavegameVersion(143)) {
+		Company *c;
+		FOR_ALL_COMPANIES(c) {
+			/* yearly_expenses has 3*15 entries now, saveload code gave us 3*13.
+			 * Move the old data to the right place in the new array and clear the new data.
+			 * The move has to be done in reverse order (first 2, then 1). */
+			MemMoveT(&c->yearly_expenses[2][0], &c->yearly_expenses[1][11], 13);
+			MemMoveT(&c->yearly_expenses[1][0], &c->yearly_expenses[0][13], 13);
+			/* Clear the old location of just-moved data, so sharing income/expenses is set to 0 */
+			MemSetT(&c->yearly_expenses[0][13], 0, 2);
+			MemSetT(&c->yearly_expenses[1][13], 0, 2);
+		}
+	}
+
 	/* Road stops is 'only' updating some caches */
 	AfterLoadRoadStops();
 	AfterLoadLabelMaps();
Index: src/roadveh_cmd.cpp
===================================================================
--- src/roadveh_cmd.cpp	(revision 20009)
+++ src/roadveh_cmd.cpp	(working copy)
@@ -42,6 +42,7 @@
 #include "company_base.h"
 #include "engine_func.h"
 #include "core/backup_type.hpp"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -214,7 +215,7 @@
 	/* The ai_new queries the vehicle cost before building the route,
 	 * so we must check against cheaters no sooner than now. --pasky */
 	if (!IsRoadDepotTile(tile)) return CMD_ERROR;
-	if (!IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!IsInfraUsageAllowed(VEH_ROAD, _current_company, GetTileOwner(tile))) return CMD_ERROR;
 
 	if (HasTileRoadType(tile, ROADTYPE_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE);
 
@@ -413,7 +414,7 @@
 	RoadVehicle *v = RoadVehicle::GetIfValid(p1);
 	if (v == NULL) return CMD_ERROR;
 
-	CommandCost ret = CheckOwnership(v->owner);
+	CommandCost ret = CheckVehicleControlAllowed(v);
 	if (ret.Failed()) return ret;
 
 	if ((v->vehstatus & VS_STOPPED) ||
@@ -949,14 +950,14 @@
 	TrackdirBits trackdirs = TrackStatusToTrackdirBits(ts);
 
 	if (IsTileType(tile, MP_ROAD)) {
-		if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->compatible_roadtypes) == 0)) {
+		if (IsRoadDepot(tile) && (!IsInfraTileUsageAllowed(VEH_ROAD, v->owner, tile) || GetRoadDepotDirection(tile) == enterdir || (GetRoadTypes(tile) & v->compatible_roadtypes) == 0)) {
 			/* Road depot owned by another company or with the wrong orientation */
 			trackdirs = TRACKDIR_BIT_NONE;
 		}
 	} else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) {
 		/* Standard road stop (drive-through stops are treated as normal road) */
 
-		if (!IsTileOwner(tile, v->owner) || GetRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
+		if (!IsInfraTileUsageAllowed(VEH_ROAD, v->owner, tile) || GetRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
 			/* different station owner or wrong orientation or the vehicle has articulated parts */
 			trackdirs = TRACKDIR_BIT_NONE;
 		} else {
@@ -1456,7 +1457,7 @@
 			/* In case an RV is stopped in a road stop, why not try to load? */
 			if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
 					v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
-					v->owner == GetTileOwner(v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
+					IsInfraTileUsageAllowed(VEH_ROAD, v->owner, v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
 					GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK)) {
 				Station *st = Station::GetByTile(v->tile);
 				v->last_station_visited = st->index;
@@ -1490,7 +1491,7 @@
 			_road_veh_data_1[v->state - RVSB_IN_ROAD_STOP + (_settings_game.vehicle.road_side << RVS_DRIVE_SIDE)] == v->frame) ||
 			(IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
 			v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
-			v->owner == GetTileOwner(v->tile) &&
+			IsInfraTileUsageAllowed(VEH_ROAD, v->owner, v->tile) &&
 			GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
 			v->frame == RVC_DRIVE_THROUGH_STOP_FRAME))) {
 
Index: src/economy_type.h
===================================================================
--- src/economy_type.h	(revision 20009)
+++ src/economy_type.h	(working copy)
@@ -155,6 +155,8 @@
 	EXPENSES_SHIP_INC,            ///< Income from ships.
 	EXPENSES_LOAN_INT,            ///< Interest payments over the loan.
 	EXPENSES_OTHER,               ///< Other expenses.
+	EXPENSES_SHARING_COST,        ///< Infrastructure sharing costs
+	EXPENSES_SHARING_INC,         ///< Infrastructure sharing income
 	EXPENSES_END,                 ///< Number of expense types.
 	INVALID_EXPENSES      = 0xFF, ///< Invalid expense type.
 };
Index: src/signal.cpp
===================================================================
--- src/signal.cpp	(revision 20009)
+++ src/signal.cpp	(working copy)
@@ -17,6 +17,7 @@
 #include "functions.h"
 #include "train.h"
 #include "company_base.h"
+#include "infrastructure_func.h"
 
 
 /** these are the maximums used for updating signal blocks */
@@ -277,7 +278,7 @@
 
 		switch (GetTileType(tile)) {
 			case MP_RAILWAY: {
-				if (GetTileOwner(tile) != owner) continue; // do not propagate signals on others' tiles (remove for tracksharing)
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 
 				if (IsRailDepot(tile)) {
 					if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot
@@ -351,7 +352,7 @@
 
 			case MP_STATION:
 				if (!HasStationRail(tile)) continue;
-				if (GetTileOwner(tile) != owner) continue;
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 				if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
 				if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile
 
@@ -361,7 +362,7 @@
 
 			case MP_ROAD:
 				if (!IsLevelCrossing(tile)) continue;
-				if (GetTileOwner(tile) != owner) continue;
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 				if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis
 
 				if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
@@ -369,7 +370,7 @@
 				break;
 
 			case MP_TUNNELBRIDGE: {
-				if (GetTileOwner(tile) != owner) continue;
+				if (!IsOneSignalBlock(owner, GetTileOwner(tile))) continue;
 				if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
 				DiagDirection dir = GetTunnelBridgeDirection(tile);
 
@@ -583,8 +584,9 @@
 		DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NW, DIAGDIR_NE
 	};
 
-	/* do not allow signal updates for two companies in one run */
-	assert(_globset.IsEmpty() || owner == _last_owner);
+	/* do not allow signal updates for two companies in one run,
+	 * if these companies are not part of the same signal block */
+	assert(_globset.IsEmpty() || IsOneSignalBlock(owner, _last_owner));
 
 	_last_owner = owner;
 
@@ -608,8 +610,9 @@
  */
 void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner)
 {
-	/* do not allow signal updates for two companies in one run */
-	assert(_globset.IsEmpty() || owner == _last_owner);
+	/* do not allow signal updates for two companies in one run,
+	 * if these companies are not part of the same signal block */
+	assert(_globset.IsEmpty() || IsOneSignalBlock(owner, _last_owner));
 
 	_last_owner = owner;
 
Index: src/vehicle.cpp
===================================================================
--- src/vehicle.cpp	(revision 20009)
+++ src/vehicle.cpp	(working copy)
@@ -51,6 +51,7 @@
 #include "engine_base.h"
 #include "newgrf.h"
 #include "core/backup_type.hpp"
+#include "infrastructure_func.h"
 
 #include "table/sprites.h"
 #include "table/strings.h"
@@ -1650,6 +1651,9 @@
 		case OT_LOADING: {
 			uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
 
+			/* Pay the loading fee for using someone else's station, if appropriate */
+			if (!mode && this->type != VEH_TRAIN) PayStationSharingFee(this, Station::Get(this->last_station_visited));
+
 			/* Not the first call for this tick, or still loading */
 			if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) ||
 					(_settings_game.order.timetabling && this->current_order_time < wait_time)) return;
Index: src/pathfinder/npf/npf.cpp
===================================================================
--- src/pathfinder/npf/npf.cpp	(revision 20009)
+++ src/pathfinder/npf/npf.cpp	(working copy)
@@ -16,6 +16,7 @@
 #include "../../functions.h"
 #include "../../ship.h"
 #include "../../roadstop_base.h"
+#include "../../infrastructure_func.h"
 #include "../pathfinder_func.h"
 #include "../pathfinder_type.h"
 #include "../follow_track.hpp"
@@ -666,25 +667,31 @@
  */
 static bool CanEnterTileOwnerCheck(Owner owner, TileIndex tile, DiagDirection enterdir)
 {
-	if (IsTileType(tile, MP_RAILWAY) || // Rail tile (also rail depot)
-			HasStationTileRail(tile) ||     // Rail station tile/waypoint
-			IsRoadDepotTile(tile) ||        // Road depot tile
-			IsStandardRoadStopTile(tile)) { // Road station tile (but not drive-through stops)
-		return IsTileOwner(tile, owner);  // You need to own these tiles entirely to use them
-	}
+	switch (GetTileType(tile)) {
+		case MP_RAILWAY:
+			return IsInfraTileUsageAllowed(VEH_TRAIN, owner, tile); // Rail tile (also rail depot)
 
-	switch (GetTileType(tile)) {
 		case MP_ROAD:
 			/* rail-road crossing : are we looking at the railway part? */
 			if (IsLevelCrossing(tile) &&
 					DiagDirToAxis(enterdir) != GetCrossingRoadAxis(tile)) {
-				return IsTileOwner(tile, owner); // Railway needs owner check, while the street is public
+				return IsInfraTileUsageAllowed(VEH_TRAIN, owner, tile); // Railway needs owner check, while the street is public
+			} else if (IsRoadDepot(tile)) { // Road depot tile
+				return IsInfraTileUsageAllowed(VEH_ROAD, owner, tile);
 			}
 			break;
 
+		case MP_STATION:
+			if (HasStationRail(tile)) { // Rail station tile/waypoint
+				return IsInfraTileUsageAllowed(VEH_TRAIN, owner, tile);
+			} else if (IsStandardRoadStopTile(tile)) { // Road station tile (but not drive-through stops)
+				return IsInfraTileUsageAllowed(VEH_ROAD, owner, tile);
+			}
+			break;
+
 		case MP_TUNNELBRIDGE:
 			if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
-				return IsTileOwner(tile, owner);
+				return IsInfraTileUsageAllowed(VEH_TRAIN, owner, tile);
 			}
 			break;
 
Index: src/pathfinder/follow_track.hpp
===================================================================
--- src/pathfinder/follow_track.hpp	(revision 20009)
+++ src/pathfinder/follow_track.hpp	(working copy)
@@ -19,6 +19,7 @@
 #include "../tunnelbridge.h"
 #include "../tunnelbridge_map.h"
 #include "../depot_map.h"
+#include "../infrastructure_func.h"
 #include "pf_performance_timer.hpp"
 
 /** Track follower helper template class (can serve pathfinders and vehicle
@@ -282,6 +283,11 @@
 				m_err = EC_NO_WAY;
 				return false;
 			}
+			/* road stops shouldn't be entered unless allowed to */
+			if (!IsInfraTileUsageAllowed(VEH_ROAD, m_veh_owner, m_new_tile)) {
+				m_err = EC_OWNER;
+				return false;
+			}
 		}
 
 		/* single tram bits can only be entered from one direction */
@@ -300,8 +306,8 @@
 				m_err = EC_NO_WAY;
 				return false;
 			}
-			/* don't try to enter other company's depots */
-			if (GetTileOwner(m_new_tile) != m_veh_owner) {
+			/* don't try to enter other company's depots if not allowed */
+			if (!IsInfraTileUsageAllowed(VEH_ROAD, m_veh_owner, m_new_tile)) {
 				m_err = EC_OWNER;
 				return false;
 			}
@@ -314,8 +320,8 @@
 			}
 		}
 
-		/* rail transport is possible only on tiles with the same owner as vehicle */
-		if (IsRailTT() && GetTileOwner(m_new_tile) != m_veh_owner) {
+		/* rail transport is possible only on allowed tiles */
+		if (IsRailTT() && !IsInfraTileUsageAllowed(VEH_TRAIN, m_veh_owner, m_new_tile)) {
 			/* different owner */
 			m_err = EC_NO_WAY;
 			return false;
Index: src/aircraft_cmd.cpp
===================================================================
--- src/aircraft_cmd.cpp	(revision 20009)
+++ src/aircraft_cmd.cpp	(working copy)
@@ -37,6 +37,7 @@
 #include "engine_func.h"
 #include "core/random_func.hpp"
 #include "core/backup_type.hpp"
+#include "infrastructure_func.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -115,7 +116,7 @@
 	const AircraftVehicleInfo *avi = AircraftVehInfo(v->engine_type);
 
 	FOR_ALL_STATIONS(st) {
-		if (st->owner != v->owner || !(st->facilities & FACIL_AIRPORT)) continue;
+		if (!IsInfraUsageAllowed(VEH_AIRCRAFT, v->owner, st->owner) || !(st->facilities & FACIL_AIRPORT)) continue;
 
 		const AirportFTAClass *afc = st->airport.GetFTA();
 		if (!st->airport.HasHangar() || (
@@ -146,7 +147,7 @@
 
 	FOR_VEHICLE_ORDERS(v, order) {
 		const Station *st = Station::Get(order->station);
-		if (st->owner == v->owner && (st->facilities & FACIL_AIRPORT)) {
+		if (IsInfraUsageAllowed(VEH_AIRCRAFT, v->owner, st->owner) && (st->facilities & FACIL_AIRPORT)) {
 			/* If an airport doesn't have a hangar, skip it */
 			if (st->Airport()->nof_depots != 0)
 				return true;
@@ -250,7 +251,7 @@
 	/* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */
 	if (flags & DC_QUERY_COST) return value;
 
-	if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
+	if (!IsHangarTile(tile) || !IsInfraUsageAllowed(VEH_AIRCRAFT, _current_company, GetTileOwner(tile))) return CMD_ERROR;
 
 	/* Prevent building aircraft types at places which can't handle them */
 	if (!CanVehicleUseStation(eid, Station::GetByTile(tile))) return CMD_ERROR;
@@ -1523,7 +1524,7 @@
 	/* runway busy or not allowed to use this airstation, circle */
 	if ((apc->flags & (v->subtype == AIR_HELICOPTER ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES)) &&
 			st->airport.tile != INVALID_TILE &&
-			(st->owner == OWNER_NONE || st->owner == v->owner)) {
+			IsInfraUsageAllowed(VEH_AIRCRAFT, v->owner, st->owner)) {
 		/* {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41},
 		 * if it is an airplane, look for LANDING, for helicopter HELILANDING
 		 * it is possible to choose from multiple landing runways, so loop until a free one is found */
Index: projects/openttd_vs80.vcproj
===================================================================
--- projects/openttd_vs80.vcproj	(revision 20009)
+++ projects/openttd_vs80.vcproj	(working copy)
@@ -584,6 +584,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini.cpp"
 				>
 			</File>
@@ -1080,6 +1084,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure_func.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini_type.h"
 				>
 			</File>
Index: projects/openttd_vs90.vcproj
===================================================================
--- projects/openttd_vs90.vcproj	(revision 20009)
+++ projects/openttd_vs90.vcproj	(working copy)
@@ -581,6 +581,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini.cpp"
 				>
 			</File>
@@ -1077,6 +1081,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\infrastructure_func.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\ini_type.h"
 				>
 			</File>
Index: source.list
===================================================================
--- source.list	(revision 20009)
+++ source.list	(working copy)
@@ -31,6 +31,7 @@
 ground_vehicle.cpp
 heightmap.cpp
 highscore.cpp
+infrastructure.cpp
 ini.cpp
 landscape.cpp
 map.cpp
@@ -179,6 +180,7 @@
 industry.h
 industry_type.h
 industrytype.h
+infrastructure_func.h
 ini_type.h
 landscape.h
 landscape_type.h
