diff --git a/parity/main.rs b/parity/main.rs
index 7d5426eb9..a435e6230 100644
--- a/parity/main.rs
+++ b/parity/main.rs
@@ -117,7 +117,7 @@ mod stratum;
 
 use std::{process, env};
 use std::collections::HashMap;
-use std::io::{self as stdio, BufReader, Write};
+use std::io::{self as stdio, BufReader, Read, Write};
 use std::fs::File;
 use std::path::PathBuf;
 use util::sha3::sha3;
@@ -190,21 +190,26 @@ fn sync_main(alt_mains: &mut HashMap<String, fn()>) {
 }
 
 // TODO: merge with version in Updater.
-fn updates_latest() -> PathBuf {
+fn updates_path(name: &str) -> PathBuf {
 	let mut dest = PathBuf::from(env::home_dir().unwrap().to_str().expect("env filesystem paths really should be valid; qed"));
 	dest.push(".parity-updates");
-	dest.push("parity");
+	dest.push(name);
 	dest
 }
 
+fn latest_exe_path() -> Option<PathBuf> {
+	File::open(updates_path("latest")).ok()
+		.and_then(|mut f| { let mut exe = String::new(); f.read_to_string(&mut exe).ok().map(|_| updates_path(&exe)) })
+} 
+
 // Starts ~/.parity-updates/parity and returns the code it exits with.
 fn run_parity() -> Option<i32> {
-	let exe = updates_latest();
-	process::Command::new(exe)
-		.args(&env::args_os().collect::<Vec<_>>())
-		.status()
-		.map(|es| es.code().unwrap_or(128))
-		.ok()
+	latest_exe_path().and_then(|exe| process::Command::new(exe)
+			.args(&env::args_os().collect::<Vec<_>>())
+			.status()
+			.map(|es| es.code().unwrap_or(128))
+			.ok()
+		)
 }
 
 const PLEASE_RESTART_EXIT_CODE: i32 = 69;
@@ -254,16 +259,17 @@ fn main() {
 	let force_direct = std::env::args().any(|arg| arg == "--force-direct");
 	let exe = std::env::current_exe().ok();
 	let development = exe.as_ref().and_then(|p| p.parent().and_then(|p| p.parent()).and_then(|p| p.file_name()).map(|n| n == "target")).unwrap_or(false);
-	let same_name = exe.as_ref().and_then(|p| p.file_stem().map(|s| s == "parity")).unwrap_or(false);
-	let have_update = updates_latest().exists();
-	let is_non_updated_current = exe.map_or(false, |p| p.canonicalize().ok() != updates_latest().canonicalize().ok());
+	let same_name = exe.as_ref().map(|p| p.file_stem().map_or(false, |s| s == "parity") && p.extension().map_or(true, |x| x == "exe")).unwrap_or(false);
+	let latest_exe = latest_exe_path();
+	let have_update = latest_exe.as_ref().map_or(false, |p| p.exists());
+	let is_non_updated_current = exe.map_or(false, |exe| latest_exe.as_ref().map_or(false, |lexe| exe.canonicalize().ok() != lexe.canonicalize().ok()));
 	trace_main!("Starting up {} (force-direct: {}, development: {}, same-name: {}, have-update: {}, non-updated-current: {})", std::env::current_exe().map(|x| format!("{}", x.display())).unwrap_or("<unknown>".to_owned()), force_direct, development, same_name, have_update, is_non_updated_current);
 	if !force_direct && !development && same_name && have_update && is_non_updated_current {
 		// looks like we're not running ~/.parity-updates/parity when the user is expecting otherwise.
 		// Everything run inside a loop, so we'll be able to restart from the child into a new version seamlessly. 
 		loop {
 			// If we fail to run the updated parity then fallback to local version. 
-			trace_main!("Attempting to run latest update...");
+			trace_main!("Attempting to run latest update ({})...", latest_exe.as_ref().expect("guarded by have_update; latest_exe must exist for have_update; qed").display());
 			let exit_code = run_parity().unwrap_or_else(|| { trace_main!("Falling back to local..."); main_direct() });
 			trace_main!("Latest exited with {}", exit_code);
 			if exit_code != PLEASE_RESTART_EXIT_CODE {
diff --git a/parity/updater.rs b/parity/updater.rs
index 7da7a6dc8..79abdbe1a 100644
--- a/parity/updater.rs
+++ b/parity/updater.rs
@@ -15,8 +15,9 @@
 // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 
 use std::sync::{Arc, Weak};
-use std::{io, os, fs, env};
-use std::path::{Path, PathBuf};
+use std::{fs, env};
+use std::io::Write;
+use std::path::{PathBuf};
 use util::misc::{VersionInfo, ReleaseTrack/*, platform*/};
 use util::{Address, H160, H256, FixedHash, Mutex, Bytes};
 use super::operations::Operations;
@@ -113,16 +114,6 @@ fn platform() -> String {
 	"test".to_owned()
 }
 
-#[cfg(windows)]
-fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-	os::windows::fs::symlink_file(src, dst)
-}
-
-#[cfg(not(windows))]
-fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-	os::unix::fs::symlink(src, dst)
-}
-
 impl Updater {
 	pub fn new(client: Weak<BlockChainClient>, update_policy: UpdatePolicy) -> Arc<Self> {
 		let mut u = Updater {
@@ -170,10 +161,10 @@ impl Updater {
 		(|| -> Result<bool, String> {
 			let mut s = self.state.lock();
 			if let Some(r) = s.ready.take() {
-				let p = Self::update_file_path(&r.version);
-				let n = Self::updates_latest();
-				let _ = fs::remove_file(&n);
-				match symlink(p, n) {
+				let p = Self::update_file_name(&r.version);
+				let n = Self::updates_path("latest");
+				// TODO: creating then writing is a bit fragile. would be nice to make it atomic.
+				match fs::File::create(&n).and_then(|mut f| f.write_all(p.as_bytes())) {
 					Ok(_) => {
 						info!("Completed upgrade to {}", &r.version);
 						s.installed = Some(r);
@@ -249,17 +240,14 @@ impl Updater {
 		}
 	}
 
-	fn update_file_path(v: &VersionInfo) -> PathBuf {
-		let mut dest = PathBuf::from(env::home_dir().unwrap().to_str().expect("env filesystem paths really should be valid; qed"));
-		dest.push(".parity-updates");
-		dest.push(format!("parity-{}.{}.{}-{:?}", v.version.major, v.version.minor, v.version.patch, v.hash));
-		dest
+	fn update_file_name(v: &VersionInfo) -> String {
+		format!("parity-{}.{}.{}-{:?}", v.version.major, v.version.minor, v.version.patch, v.hash)
 	}
 
-	fn updates_latest() -> PathBuf {
+	fn updates_path(name: &str) -> PathBuf {
 		let mut dest = PathBuf::from(env::home_dir().unwrap().to_str().expect("env filesystem paths really should be valid; qed"));
 		dest.push(".parity-updates");
-		dest.push("parity");
+		dest.push(name);
 		dest
 	}
 
@@ -270,7 +258,7 @@ impl Updater {
 				let fetched = s.fetching.take().unwrap();
 				let b = result.map_err(|e| format!("Unable to fetch update ({}): {:?}", fetched.version, e))?;
 				info!("Fetched latest version ({}) OK to {}", fetched.version, b.display());
-				let dest = Self::update_file_path(&fetched.version);
+				let dest = Self::updates_path(&Self::update_file_name(&fetched.version));
 				fs::create_dir_all(dest.parent().expect("at least one thing pushed; qed")).map_err(|e| format!("Unable to create updates path: {:?}", e))?;
 				fs::copy(&b, &dest).map_err(|e| format!("Unable to copy update: {:?}", e))?;
 				info!("Copied file to {}", dest.display());