diff --git a/Telegram/SourceFiles/_other/updater.cpp b/Telegram/SourceFiles/_other/updater.cpp
index 35dd767b4..3725c5e09 100644
--- a/Telegram/SourceFiles/_other/updater.cpp
+++ b/Telegram/SourceFiles/_other/updater.cpp
@@ -22,7 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 
 bool _debug = false;
 
-wstring updaterName, updaterDir, updateTo, exeName;
+wstring updaterName, updaterDir, updateTo, exeName, customWorkingDir, customKeyFile;
 
 bool equal(const wstring &a, const wstring &b) {
 	return !_wcsicmp(a.c_str(), b.c_str());
@@ -356,6 +356,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
 	args = CommandLineToArgvW(GetCommandLine(), &argsCount);
 	if (args) {
 		for (int i = 1; i < argsCount; ++i) {
+			writeLog(std::wstring(L"Argument: ") + args[i]);
 			if (equal(args[i], L"-update")) {
 				needupdate = true;
 			} else if (equal(args[i], L"-autostart")) {
@@ -368,17 +369,25 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
 			} else if (equal(args[i], L"-testmode")) {
 				testmode = true;
 			} else if (equal(args[i], L"-writeprotected") && ++i < argsCount) {
+				writeLog(std::wstring(L"Argument: ") + args[i]);
 				writeprotected = true;
 				updateTo = args[i];
-				for (int i = 0, l = updateTo.size(); i < l; ++i) {
-					if (updateTo[i] == L'/') {
-						updateTo[i] = L'\\';
+				for (int j = 0, l = updateTo.size(); j < l; ++j) {
+					if (updateTo[j] == L'/') {
+						updateTo[j] = L'\\';
 					}
 				}
+			} else if (equal(args[i], L"-workdir") && ++i < argsCount) {
+				writeLog(std::wstring(L"Argument: ") + args[i]);
+				customWorkingDir = args[i];
+			} else if (equal(args[i], L"-key") && ++i < argsCount) {
+				writeLog(std::wstring(L"Argument: ") + args[i]);
+				customKeyFile = args[i];
 			} else if (equal(args[i], L"-exename") && ++i < argsCount) {
+				writeLog(std::wstring(L"Argument: ") + args[i]);
 				exeName = args[i];
-				for (int i = 0, l = exeName.size(); i < l; ++i) {
-					if (exeName[i] == L'/' || exeName[i] == L'\\') {
+				for (int j = 0, l = exeName.size(); j < l; ++j) {
+					if (exeName[j] == L'/' || exeName[j] == L'\\') {
 						exeName = L"Telegram.exe";
 						break;
 					}
@@ -391,6 +400,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
 		if (needupdate) writeLog(L"Need to update!");
 		if (autostart) writeLog(L"From autostart!");
 		if (writeprotected) writeLog(L"Write Protected folder!");
+		if (!customWorkingDir.empty()) writeLog(L"Will pass custom working dir: " + customWorkingDir);
 
 		updaterName = args[0];
 		writeLog(L"Updater name is: " + updaterName);
@@ -428,6 +438,13 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR cmdPara
 	if (debug) targs += L" -debug";
 	if (startintray) targs += L" -startintray";
 	if (testmode) targs += L" -testmode";
+	if (!customWorkingDir.empty()) {
+		targs += L" -workdir \"" + customWorkingDir + L"\"";
+	}
+	if (!customKeyFile.empty()) {
+		targs += L" -key \"" + customKeyFile + L"\"";
+	}
+	writeLog(L"Result arguments: " + targs);
 
 	bool executed = false;
 	if (writeprotected) { // run un-elevated
diff --git a/Telegram/SourceFiles/_other/updater_linux.cpp b/Telegram/SourceFiles/_other/updater_linux.cpp
index 2e09dd70d..d0a7dc1dd 100644
--- a/Telegram/SourceFiles/_other/updater_linux.cpp
+++ b/Telegram/SourceFiles/_other/updater_linux.cpp
@@ -344,9 +344,16 @@ string CurrentExecutablePath(int argc, char *argv[]) {
 }
 
 int main(int argc, char *argv[]) {
-	bool needupdate = true, autostart = false, debug = false, tosettings = false, startintray = false, testmode = false;
+	bool needupdate = true;
+	bool autostart = false;
+	bool debug = false;
+	bool tosettings = false;
+	bool startintray = false;
+	bool testmode = false;
+	bool customWorkingDir = false;
 
-	char *key = 0, *crashreport = 0;
+	char *key = 0;
+	char *workdir = 0;
 	for (int i = 1; i < argc; ++i) {
 		if (equal(argv[i], "-noupdate")) {
 			needupdate = false;
@@ -360,12 +367,12 @@ int main(int argc, char *argv[]) {
 			testmode = true;
 		} else if (equal(argv[i], "-tosettings")) {
 			tosettings = true;
+		} else if (equal(argv[i], "-workdir_custom")) {
+			customWorkingDir = true;
 		} else if (equal(argv[i], "-key") && ++i < argc) {
 			key = argv[i];
 		} else if (equal(argv[i], "-workpath") && ++i < argc) {
-			workDir = argv[i];
-		} else if (equal(argv[i], "-crashreport") && ++i < argc) {
-			crashreport = argv[i];
+			workDir = workdir = argv[i];
 		} else if (equal(argv[i], "-exename") && ++i < argc) {
 			exeName = argv[i];
 		} else if (equal(argv[i], "-exepath") && ++i < argc) {
@@ -401,6 +408,8 @@ int main(int argc, char *argv[]) {
 			}
 			if (needupdate) {
 				if (workDir.empty()) { // old app launched, update prepared in tupdates/ready (not in tupdates/temp)
+					customWorkingDir = false;
+
 					writeLog("No workdir, trying to figure it out");
 					struct passwd *pw = getpwuid(getuid());
 					if (pw && pw->pw_dir && strlen(pw->pw_dir)) {
@@ -446,22 +455,30 @@ int main(int argc, char *argv[]) {
 	string fullBinaryPath = exePath + exeName;
 	strcpy(path, fullBinaryPath.c_str());
 
-	char *args[MaxArgsCount] = {0}, p_noupdate[] = "-noupdate", p_autostart[] = "-autostart", p_debug[] = "-debug", p_tosettings[] = "-tosettings", p_key[] = "-key", p_startintray[] = "-startintray", p_testmode[] = "-testmode";
+	char *args[MaxArgsCount] = { 0 };
+	char p_noupdate[] = "-noupdate";
+	char p_autostart[] = "-autostart";
+	char p_debug[] = "-debug";
+	char p_tosettings[] = "-tosettings";
+	char p_key[] = "-key";
+	char p_startintray[] = "-startintray";
+	char p_testmode[] = "-testmode";
+	char p_workdir[] = "-workdir";
 	int argIndex = 0;
 	args[argIndex++] = path;
-	if (crashreport) {
-		args[argIndex++] = crashreport;
-	} else {
-		args[argIndex++] = p_noupdate;
-		if (autostart) args[argIndex++] = p_autostart;
-		if (debug) args[argIndex++] = p_debug;
-		if (startintray) args[argIndex++] = p_startintray;
-		if (testmode) args[argIndex++] = p_testmode;
-		if (tosettings) args[argIndex++] = p_tosettings;
-		if (key) {
-			args[argIndex++] = p_key;
-			args[argIndex++] = key;
-		}
+	args[argIndex++] = p_noupdate;
+	if (autostart) args[argIndex++] = p_autostart;
+	if (debug) args[argIndex++] = p_debug;
+	if (startintray) args[argIndex++] = p_startintray;
+	if (testmode) args[argIndex++] = p_testmode;
+	if (tosettings) args[argIndex++] = p_tosettings;
+	if (key) {
+		args[argIndex++] = p_key;
+		args[argIndex++] = key;
+	}
+	if (customWorkingDir && workdir) {
+		args[argIndex++] = p_workdir;
+		args[argIndex++] = workdir;
 	}
 	pid_t pid = fork();
 	switch (pid) {
diff --git a/Telegram/SourceFiles/_other/updater_osx.m b/Telegram/SourceFiles/_other/updater_osx.m
index b2b9d0b03..7aaf111a2 100644
--- a/Telegram/SourceFiles/_other/updater_osx.m
+++ b/Telegram/SourceFiles/_other/updater_osx.m
@@ -23,7 +23,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 NSString *appName = @"Telegram.app";
 NSString *appDir = nil;
 NSString *workDir = nil;
-NSString *crashReportArg = nil;
 
 #ifdef _DEBUG
 BOOL _debug = YES;
@@ -90,6 +89,7 @@ int main(int argc, const char * argv[]) {
 	openLog();
 	pid_t procId = 0;
 	BOOL update = YES, toSettings = NO, autoStart = NO, startInTray = NO, testMode = NO;
+	BOOL customWorkingDir = NO;
 	NSString *key = nil;
 	for (int i = 0; i < argc; ++i) {
 		if ([@"-workpath" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
@@ -102,10 +102,6 @@ int main(int argc, const char * argv[]) {
 				[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
 				procId = [[formatter numberFromString:[NSString stringWithUTF8String:argv[i]]] intValue];
 			}
-		} else if ([@"-crashreport" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
-			if (++i < argc) {
-				crashReportArg = [NSString stringWithUTF8String:argv[i]];
-			}
 		} else if ([@"-noupdate" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
 			update = NO;
 		} else if ([@"-tosettings" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
@@ -118,11 +114,16 @@ int main(int argc, const char * argv[]) {
 			startInTray = YES;
 		} else if ([@"-testmode" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
 			testMode = YES;
+		} else if ([@"-workdir_custom" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
+			customWorkingDir = YES;
 		} else if ([@"-key" isEqualToString:[NSString stringWithUTF8String:argv[i]]]) {
 			if (++i < argc) key = [NSString stringWithUTF8String:argv[i]];
 		}
 	}
-	if (!workDir) workDir = appDir;
+	if (!workDir) {
+		workDir = appDir;
+		customWorkingDir = NO;
+	}
 	openLog();
 	NSMutableArray *argsArr = [[NSMutableArray alloc] initWithCapacity:argc];
 	for (int i = 0; i < argc; ++i) {
@@ -242,17 +243,19 @@ int main(int argc, const char * argv[]) {
 	}
 
 	NSString *appPath = [[NSArray arrayWithObjects:appDir, appRealName, nil] componentsJoinedByString:@""];
-	NSMutableArray *args = [[NSMutableArray alloc] initWithObjects: crashReportArg ? crashReportArg : @"-noupdate", nil];
-	if (!crashReportArg) {
-		if (toSettings) [args addObject:@"-tosettings"];
-		if (_debug) [args addObject:@"-debug"];
-		if (startInTray) [args addObject:@"-startintray"];
-		if (testMode) [args addObject:@"-testmode"];
-		if (autoStart) [args addObject:@"-autostart"];
-		if (key) {
-			[args addObject:@"-key"];
-			[args addObject:key];
-		}
+	NSMutableArray *args = [[NSMutableArray alloc] initWithObjects: @"-noupdate", nil];
+	if (toSettings) [args addObject:@"-tosettings"];
+	if (_debug) [args addObject:@"-debug"];
+	if (startInTray) [args addObject:@"-startintray"];
+	if (testMode) [args addObject:@"-testmode"];
+	if (autoStart) [args addObject:@"-autostart"];
+	if (key) {
+		[args addObject:@"-key"];
+		[args addObject:key];
+	}
+	if (customWorkingDir) {
+		[args addObject:@"-workdir"];
+		[args addObject:workDir];
 	}
 	writeLog([[NSArray arrayWithObjects:@"Running application '", appPath, @"' with args '", [args componentsJoinedByString:@"' '"], @"'..", nil] componentsJoinedByString:@""]);
 	NSError *error = nil;
diff --git a/Telegram/SourceFiles/core/launcher.cpp b/Telegram/SourceFiles/core/launcher.cpp
index cca4c4c22..731aa1aee 100644
--- a/Telegram/SourceFiles/core/launcher.cpp
+++ b/Telegram/SourceFiles/core/launcher.cpp
@@ -29,6 +29,8 @@ namespace Core {
 namespace {
 
 QStringList ReadArguments(int argc, char *argv[]) {
+	Expects(argc >= 0);
+
 	auto result = QStringList();
 	result.reserve(argc);
 	for (auto i = 0; i != argc; ++i) {
@@ -47,7 +49,7 @@ Launcher::Launcher(int argc, char *argv[])
 : _argc(argc)
 , _argv(argv)
 , _arguments(ReadArguments(argc, argv)) {
-	InitFromCommandLine(argc, argv);
+	prepareSettings();
 }
 
 void Launcher::init() {
@@ -84,12 +86,14 @@ int Launcher::exec() {
 #ifndef TDESKTOP_DISABLE_AUTOUPDATE
 	if (cRestartingUpdate()) {
 		DEBUG_LOG(("Application Info: executing updater to install update..."));
-		psExecUpdater();
+		if (!launchUpdater(UpdaterLaunch::PerformUpdate)) {
+			psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
+		}
 	} else
 #endif // !TDESKTOP_DISABLE_AUTOUPDATE
 	if (cRestarting()) {
 		DEBUG_LOG(("Application Info: executing Telegram, because of restart..."));
-		psExecTelegram();
+		launchUpdater(UpdaterLaunch::JustRelaunch);
 	}
 
 	CrashReports::Finish();
@@ -103,4 +107,134 @@ QString Launcher::argumentsString() const {
 	return _arguments.join(' ');
 }
 
+void Launcher::prepareSettings() {
+#ifdef Q_OS_MAC
+#ifndef OS_MAC_OLD
+	if (QSysInfo::macVersion() >= QSysInfo::MV_10_11) {
+		gIsElCapitan = true;
+	}
+#else // OS_MAC_OLD
+	if (QSysInfo::macVersion() < QSysInfo::MV_10_7) {
+		gIsSnowLeopard = true;
+	}
+#endif // OS_MAC_OLD
+#endif // Q_OS_MAC
+
+	switch (cPlatform()) {
+	case dbipWindows:
+		gUpdateURL = QUrl(qsl("http://tdesktop.com/win/tupdates/current"));
+#ifndef OS_WIN_STORE
+		gPlatformString = qsl("Windows");
+#else // OS_WIN_STORE
+		gPlatformString = qsl("WinStore");
+#endif // OS_WIN_STORE
+	break;
+	case dbipMac:
+		gUpdateURL = QUrl(qsl("http://tdesktop.com/mac/tupdates/current"));
+#ifndef OS_MAC_STORE
+		gPlatformString = qsl("MacOS");
+#else // OS_MAC_STORE
+		gPlatformString = qsl("MacAppStore");
+#endif // OS_MAC_STORE
+	break;
+	case dbipMacOld:
+		gUpdateURL = QUrl(qsl("http://tdesktop.com/mac32/tupdates/current"));
+		gPlatformString = qsl("MacOSold");
+	break;
+	case dbipLinux64:
+		gUpdateURL = QUrl(qsl("http://tdesktop.com/linux/tupdates/current"));
+		gPlatformString = qsl("Linux64bit");
+	break;
+	case dbipLinux32:
+		gUpdateURL = QUrl(qsl("http://tdesktop.com/linux32/tupdates/current"));
+		gPlatformString = qsl("Linux32bit");
+	break;
+	}
+
+	auto path = Platform::CurrentExecutablePath(_argc, _argv);
+	LOG(("Executable path before check: %1").arg(path));
+	if (!path.isEmpty()) {
+		auto info = QFileInfo(path);
+		if (info.isSymLink()) {
+			info = info.symLinkTarget();
+		}
+		if (info.exists()) {
+			gExeDir = info.absoluteDir().absolutePath() + '/';
+			gExeName = info.fileName();
+		}
+	}
+	if (cExeName().isEmpty()) {
+		LOG(("WARNING: Could not compute executable path, some features will be disabled."));
+	}
+
+	processArguments();
+}
+
+void Launcher::processArguments() {
+		enum class KeyFormat {
+		NoValues,
+		OneValue,
+		AllLeftValues,
+	};
+	auto parseMap = std::map<QByteArray, KeyFormat> {
+		{ "-testmode"   , KeyFormat::NoValues },
+		{ "-debug"      , KeyFormat::NoValues },
+		{ "-many"       , KeyFormat::NoValues },
+		{ "-key"        , KeyFormat::OneValue },
+		{ "-autostart"  , KeyFormat::NoValues },
+		{ "-fixprevious", KeyFormat::NoValues },
+		{ "-cleanup"    , KeyFormat::NoValues },
+		{ "-noupdate"   , KeyFormat::NoValues },
+		{ "-tosettings" , KeyFormat::NoValues },
+		{ "-startintray", KeyFormat::NoValues },
+		{ "-sendpath"   , KeyFormat::AllLeftValues },
+		{ "-workdir"    , KeyFormat::OneValue },
+		{ "--"          , KeyFormat::OneValue },
+	};
+	auto parseResult = QMap<QByteArray, QStringList>();
+	auto parsingKey = QByteArray();
+	auto parsingFormat = KeyFormat::NoValues;
+	for (const auto &argument : _arguments) {
+		switch (parsingFormat) {
+		case KeyFormat::OneValue: {
+			parseResult[parsingKey] = QStringList(argument.mid(0, 8192));
+			parsingFormat = KeyFormat::NoValues;
+		} break;
+		case KeyFormat::AllLeftValues: {
+			parseResult[parsingKey].push_back(argument.mid(0, 8192));
+		} break;
+		case KeyFormat::NoValues: {
+			parsingKey = argument.toLatin1();
+			auto it = parseMap.find(parsingKey);
+			if (it != parseMap.end()) {
+				parsingFormat = it->second;
+				parseResult[parsingKey] = QStringList();
+			}
+		} break;
+		}
+	}
+
+	gTestMode = parseResult.contains("-testmode");
+	gDebug = parseResult.contains("-debug");
+	gManyInstance = parseResult.contains("-many");
+	gKeyFile = parseResult.value("-key", QStringList()).join(QString());
+	gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart
+		: parseResult.contains("-fixprevious") ? LaunchModeFixPrevious
+		: parseResult.contains("-cleanup") ? LaunchModeCleanup
+		: LaunchModeNormal;
+	gNoStartUpdate = parseResult.contains("-noupdate");
+	gStartToSettings = parseResult.contains("-tosettings");
+	gStartInTray = parseResult.contains("-startintray");
+	gSendPaths = parseResult.value("-sendpath", QStringList());
+	gWorkingDir = parseResult.value("-workdir", QStringList()).join(QString());
+	if (!gWorkingDir.isEmpty()) {
+		if (QDir().exists(gWorkingDir)) {
+			_customWorkingDir = true;
+		} else {
+			gWorkingDir = QString();
+		}
+	}
+	gStartUrl = parseResult.value("--", QStringList()).join(QString());
+}
+
 } // namespace Core
diff --git a/Telegram/SourceFiles/core/launcher.h b/Telegram/SourceFiles/core/launcher.h
index a0c03197b..a16a85c64 100644
--- a/Telegram/SourceFiles/core/launcher.h
+++ b/Telegram/SourceFiles/core/launcher.h
@@ -31,15 +31,32 @@ public:
 	int exec();
 
 	QString argumentsString() const;
+	bool customWorkingDir() const {
+		return _customWorkingDir;
+	}
+
+protected:
+	enum class UpdaterLaunch {
+		PerformUpdate,
+		JustRelaunch,
+	};
 
 private:
+	void prepareSettings();
+	void processArguments();
+
 	void init();
-	virtual void initHook() = 0;
+	virtual void initHook() {
+	}
+
+	virtual bool launchUpdater(UpdaterLaunch action) = 0;
 
 	int _argc;
 	char **_argv;
 	QStringList _arguments;
 
+	bool _customWorkingDir = false;
+
 };
 
 } // namespace Core
diff --git a/Telegram/SourceFiles/platform/linux/launcher_linux.cpp b/Telegram/SourceFiles/platform/linux/launcher_linux.cpp
index 3701c90c5..2753549e1 100644
--- a/Telegram/SourceFiles/platform/linux/launcher_linux.cpp
+++ b/Telegram/SourceFiles/platform/linux/launcher_linux.cpp
@@ -20,9 +20,98 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 */
 #include "platform/linux/launcher_linux.h"
 
-namespace Platform {
+#include "core/crash_reports.h"
 
-void Launcher::initHook() {
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <cstdlib>
+#include <unistd.h>
+#include <dirent.h>
+#include <pwd.h>
+
+namespace Platform {
+namespace {
+
+class Arguments {
+public:
+	void push(QByteArray argument) {
+		argument.append(char(0));
+		_argumentValues.push_back(argument);
+		_arguments.push_back(_argumentValues.back().data());
+	}
+
+	char **result() {
+		_arguments.push_back(nullptr);
+		return _arguments.data();
+	}
+
+private:
+	std::vector<QByteArray> _argumentValues;
+	std::vector<char*> _arguments;
+
+};
+
+} // namespace
+
+bool Launcher::launchUpdater(UpdaterLaunch action) {
+	if (cExeName().isEmpty()) {
+		return false;
+	}
+
+	const auto binaryName = (action == UpdaterLaunch::JustRelaunch)
+		? cExeName()
+		: QStringLiteral("Updater");
+
+	auto argumentsList = Arguments();
+	argumentsList.push(QFile::encodeName(cExeDir() + binaryName));
+
+	if (cLaunchMode() == LaunchModeAutoStart) {
+		argumentsList.push("-autostart");
+	}
+	if (cDebug()) {
+		argumentsList.push("-debug");
+	}
+	if (cStartInTray()) {
+		argumentsList.push("-startintray");
+	}
+	if (cTestMode()) {
+		argumentsList.push("-testmode");
+	}
+	if (cDataFile() != qsl("data")) {
+		argumentsList.push("-key");
+		argumentsList.push(QFile::encodeName(cDataFile()));
+	}
+
+	if (action == UpdaterLaunch::JustRelaunch) {
+		argumentsList.push("-noupdate");
+		argumentsList.push("-tosettings");
+		if (customWorkingDir()) {
+			argumentsList.push("-workdir");
+			argumentsList.push(QFile::encodeName(cWorkingDir()));
+		}
+	} else {
+		argumentsList.push("-workpath");
+		argumentsList.push(QFile::encodeName(cWorkingDir()));
+		argumentsList.push("-exename");
+		argumentsList.push(QFile::encodeName(cExeName()));
+		argumentsList.push("-exepath");
+		argumentsList.push(QFile::encodeName(cExeDir()));
+		if (customWorkingDir()) {
+			argumentsList.push("-workdir_custom");
+		}
+	}
+
+	Logs::closeMain();
+	CrashReports::Finish();
+
+	const auto args = argumentsList.result();
+
+	pid_t pid = fork();
+	switch (pid) {
+	case -1: return false;
+	case 0: execv(args[0], args); return false;
+	}
+	return true;
 }
 
 } // namespace
diff --git a/Telegram/SourceFiles/platform/linux/launcher_linux.h b/Telegram/SourceFiles/platform/linux/launcher_linux.h
index 9ff229828..7f6bb2b9a 100644
--- a/Telegram/SourceFiles/platform/linux/launcher_linux.h
+++ b/Telegram/SourceFiles/platform/linux/launcher_linux.h
@@ -29,7 +29,7 @@ public:
 	using Core::Launcher::Launcher;
 
 private:
-	void initHook() override;
+	bool launchUpdater(UpdaterLaunch action) override;
 
 };
 
diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.cpp b/Telegram/SourceFiles/platform/linux/specific_linux.cpp
index c7b24fe7d..30e6aa54d 100644
--- a/Telegram/SourceFiles/platform/linux/specific_linux.cpp
+++ b/Telegram/SourceFiles/platform/linux/specific_linux.cpp
@@ -526,98 +526,6 @@ void psNewVersion() {
 	psRegisterCustomScheme();
 }
 
-bool _execUpdater(bool update = true, const QString &crashreport = QString()) {
-	if (cExeName().isEmpty()) {
-		return false;
-	}
-	static const int MaxLen = 65536, MaxArgsCount = 128;
-
-	char path[MaxLen] = {0};
-	QByteArray data(QFile::encodeName(cExeDir() + (update ? "Updater" : cExeName())));
-	memcpy(path, data.constData(), data.size());
-
-	char *args[MaxArgsCount] = { 0 };
-	char p_noupdate[] = "-noupdate";
-	char p_autostart[] = "-autostart";
-	char p_debug[] = "-debug";
-	char p_tosettings[] = "-tosettings";
-	char p_key[] = "-key";
-	char p_datafile[MaxLen] = { 0 };
-	char p_path[] = "-workpath";
-	char p_pathbuf[MaxLen] = { 0 };
-	char p_startintray[] = "-startintray";
-	char p_testmode[] = "-testmode";
-	char p_crashreport[] = "-crashreport";
-	char p_crashreportbuf[MaxLen] = { 0 };
-	char p_exe[] = "-exename";
-	char p_exebuf[MaxLen] = { 0 };
-	char p_exepath[] = "-exepath";
-	char p_exepathbuf[MaxLen] = { 0 };
-	int argIndex = 0;
-	args[argIndex++] = path;
-	if (!update) {
-		args[argIndex++] = p_noupdate;
-		args[argIndex++] = p_tosettings;
-	}
-	if (cLaunchMode() == LaunchModeAutoStart) args[argIndex++] = p_autostart;
-	if (cDebug()) args[argIndex++] = p_debug;
-	if (cStartInTray()) args[argIndex++] = p_startintray;
-	if (cTestMode()) args[argIndex++] = p_testmode;
-	if (cDataFile() != qsl("data")) {
-		QByteArray dataf = QFile::encodeName(cDataFile());
-		if (dataf.size() < MaxLen) {
-			memcpy(p_datafile, dataf.constData(), dataf.size());
-			args[argIndex++] = p_key;
-			args[argIndex++] = p_datafile;
-		}
-	}
-	QByteArray pathf = QFile::encodeName(cWorkingDir());
-	if (pathf.size() < MaxLen) {
-		memcpy(p_pathbuf, pathf.constData(), pathf.size());
-		args[argIndex++] = p_path;
-		args[argIndex++] = p_pathbuf;
-	}
-	if (!crashreport.isEmpty()) {
-		QByteArray crashreportf = QFile::encodeName(crashreport);
-		if (crashreportf.size() < MaxLen) {
-			memcpy(p_crashreportbuf, crashreportf.constData(), crashreportf.size());
-			args[argIndex++] = p_crashreport;
-			args[argIndex++] = p_crashreportbuf;
-		}
-	}
-	QByteArray exef = QFile::encodeName(cExeName());
-	if (exef.size() > 0 && exef.size() < MaxLen) {
-		memcpy(p_exebuf, exef.constData(), exef.size());
-		args[argIndex++] = p_exe;
-		args[argIndex++] = p_exebuf;
-	}
-	QByteArray exepathf = QFile::encodeName(cExeDir());
-	if (exepathf.size() > 0 && exepathf.size() < MaxLen) {
-		memcpy(p_exepathbuf, exepathf.constData(), exepathf.size());
-		args[argIndex++] = p_exepath;
-		args[argIndex++] = p_exepathbuf;
-	}
-
-	Logs::closeMain();
-	CrashReports::Finish();
-	pid_t pid = fork();
-	switch (pid) {
-	case -1: return false;
-	case 0: execv(path, args); return false;
-	}
-	return true;
-}
-
-void psExecUpdater() {
-	if (!_execUpdater()) {
-		psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
-	}
-}
-
-void psExecTelegram(const QString &crashreport) {
-	_execUpdater(false, crashreport);
-}
-
 bool psShowOpenWithMenu(int x, int y, const QString &file) {
 	return false;
 }
diff --git a/Telegram/SourceFiles/platform/linux/specific_linux.h b/Telegram/SourceFiles/platform/linux/specific_linux.h
index f66519431..1fa9bc988 100644
--- a/Telegram/SourceFiles/platform/linux/specific_linux.h
+++ b/Telegram/SourceFiles/platform/linux/specific_linux.h
@@ -77,9 +77,6 @@ void psBringToBack(QWidget *w);
 int psCleanup();
 int psFixPrevious();
 
-void psExecUpdater();
-void psExecTelegram(const QString &arg = QString());
-
 QAbstractNativeEventFilter *psNativeEventFilter();
 
 void psNewVersion();
diff --git a/Telegram/SourceFiles/platform/mac/launcher_mac.h b/Telegram/SourceFiles/platform/mac/launcher_mac.h
index 9ff229828..aea3b04a2 100644
--- a/Telegram/SourceFiles/platform/mac/launcher_mac.h
+++ b/Telegram/SourceFiles/platform/mac/launcher_mac.h
@@ -31,6 +31,8 @@ public:
 private:
 	void initHook() override;
 
+	bool launchUpdater(UpdaterLaunch action) override;
+
 };
 
 } // namespace Platform
diff --git a/Telegram/SourceFiles/platform/mac/launcher_mac.mm b/Telegram/SourceFiles/platform/mac/launcher_mac.mm
index 419e272e0..0f0362c6d 100644
--- a/Telegram/SourceFiles/platform/mac/launcher_mac.mm
+++ b/Telegram/SourceFiles/platform/mac/launcher_mac.mm
@@ -20,6 +20,12 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 */
 #include "platform/mac/launcher_mac.h"
 
+#include "core/crash_reports.h"
+#include "platform/mac/mac_utilities.h"
+
+#include <Cocoa/Cocoa.h>
+#include <CoreFoundation/CFURL.h>
+
 namespace Platform {
 
 void Launcher::initHook() {
@@ -29,4 +35,64 @@ void Launcher::initHook() {
 #endif // OS_MAC_OLD
 }
 
+bool Launcher::launchUpdater(UpdaterLaunch action) {
+	if (cExeName().isEmpty()) {
+		return false;
+	}
+	@autoreleasepool {
+
+#ifdef OS_MAC_STORE
+	// In AppStore version we don't have Updater.
+	// We just relaunch our app.
+	if (action == UpdaterLaunch::JustRelaunch) {
+		NSDictionary *conf = [NSDictionary dictionaryWithObject:[NSArray array] forKey:NSWorkspaceLaunchConfigurationArguments];
+		[[NSWorkspace sharedWorkspace] launchApplicationAtURL:[NSURL fileURLWithPath:Q2NSString(cExeDir() + cExeName())] options:NSWorkspaceLaunchAsync | NSWorkspaceLaunchNewInstance configuration:conf error:0];
+		return true;
+	}
+#endif // OS_MAC_STORE
+
+	NSString *path = @"", *args = @"";
+	@try {
+		path = [[NSBundle mainBundle] bundlePath];
+		if (!path) {
+			LOG(("Could not get bundle path!!"));
+			return false;
+		}
+		path = [path stringByAppendingString:@"/Contents/Frameworks/Updater"];
+
+		NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:@"-workpath", Q2NSString(cWorkingDir()), @"-procid", nil];
+		[args addObject:[NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]]];
+		if (cRestartingToSettings()) [args addObject:@"-tosettings"];
+		if (action == UpdaterLaunch::JustRelaunch) [args addObject:@"-noupdate"];
+		if (cLaunchMode() == LaunchModeAutoStart) [args addObject:@"-autostart"];
+		if (cDebug()) [args addObject:@"-debug"];
+		if (cStartInTray()) [args addObject:@"-startintray"];
+		if (cTestMode()) [args addObject:@"-testmode"];
+		if (cDataFile() != qsl("data")) {
+			[args addObject:@"-key"];
+			[args addObject:Q2NSString(cDataFile())];
+		}
+		if (customWorkingDir()) {
+			[args addObject:@"-workdir_custom"];
+		}
+
+		DEBUG_LOG(("Application Info: executing %1 %2").arg(NS2QString(path)).arg(NS2QString([args componentsJoinedByString:@" "])));
+		Logs::closeMain();
+		CrashReports::Finish();
+		if (![NSTask launchedTaskWithLaunchPath:path arguments:args]) {
+			DEBUG_LOG(("Task not launched while executing %1 %2").arg(NS2QString(path)).arg(NS2QString([args componentsJoinedByString:@" "])));
+			return false;
+		}
+	}
+	@catch (NSException *exception) {
+		LOG(("Exception caught while executing %1 %2").arg(NS2QString(path)).arg(NS2QString(args)));
+		return false;
+	}
+	@finally {
+	}
+
+	}
+	return true;
+}
+
 } // namespace Platform
diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.h b/Telegram/SourceFiles/platform/mac/specific_mac.h
index 62e985c4d..9363d8fc5 100644
--- a/Telegram/SourceFiles/platform/mac/specific_mac.h
+++ b/Telegram/SourceFiles/platform/mac/specific_mac.h
@@ -78,9 +78,6 @@ void psBringToBack(QWidget *w);
 int psCleanup();
 int psFixPrevious();
 
-void psExecUpdater();
-void psExecTelegram(const QString &crashreport = QString());
-
 bool psShowOpenWithMenu(int x, int y, const QString &file);
 
 QAbstractNativeEventFilter *psNativeEventFilter();
diff --git a/Telegram/SourceFiles/platform/mac/specific_mac.mm b/Telegram/SourceFiles/platform/mac/specific_mac.mm
index 32b805ade..2c56c393c 100644
--- a/Telegram/SourceFiles/platform/mac/specific_mac.mm
+++ b/Telegram/SourceFiles/platform/mac/specific_mac.mm
@@ -412,16 +412,6 @@ void psNewVersion() {
 	objc_registerCustomScheme();
 }
 
-void psExecUpdater() {
-	if (!objc_execUpdater()) {
-		psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
-	}
-}
-
-void psExecTelegram(const QString &crashreport) {
-	objc_execTelegram(crashreport);
-}
-
 void psAutoStart(bool start, bool silent) {
 }
 
diff --git a/Telegram/SourceFiles/platform/mac/specific_mac_p.h b/Telegram/SourceFiles/platform/mac/specific_mac_p.h
index 24b1531b4..fe22d82c3 100644
--- a/Telegram/SourceFiles/platform/mac/specific_mac_p.h
+++ b/Telegram/SourceFiles/platform/mac/specific_mac_p.h
@@ -32,8 +32,6 @@ bool objc_idleTime(TimeMs &idleTime);
 void objc_start();
 void objc_ignoreApplicationActivationRightNow();
 void objc_finish();
-bool objc_execUpdater();
-void objc_execTelegram(const QString &crashreport);
 
 void objc_registerCustomScheme();
 
diff --git a/Telegram/SourceFiles/platform/mac/specific_mac_p.mm b/Telegram/SourceFiles/platform/mac/specific_mac_p.mm
index dd52b88a2..8a54e4260 100644
--- a/Telegram/SourceFiles/platform/mac/specific_mac_p.mm
+++ b/Telegram/SourceFiles/platform/mac/specific_mac_p.mm
@@ -411,74 +411,6 @@ void objc_registerCustomScheme() {
 #endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
 }
 
-BOOL _execUpdater(BOOL update = YES, const QString &crashreport = QString()) {
-	@autoreleasepool {
-
-	NSString *path = @"", *args = @"";
-	@try {
-		path = [[NSBundle mainBundle] bundlePath];
-		if (!path) {
-			LOG(("Could not get bundle path!!"));
-			return NO;
-		}
-		path = [path stringByAppendingString:@"/Contents/Frameworks/Updater"];
-
-		NSMutableArray *args = [[NSMutableArray alloc] initWithObjects:@"-workpath", Q2NSString(cWorkingDir()), @"-procid", nil];
-		[args addObject:[NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]]];
-		if (cRestartingToSettings()) [args addObject:@"-tosettings"];
-		if (!update) [args addObject:@"-noupdate"];
-		if (cLaunchMode() == LaunchModeAutoStart) [args addObject:@"-autostart"];
-		if (cDebug()) [args addObject:@"-debug"];
-		if (cStartInTray()) [args addObject:@"-startintray"];
-		if (cTestMode()) [args addObject:@"-testmode"];
-		if (cDataFile() != qsl("data")) {
-			[args addObject:@"-key"];
-			[args addObject:Q2NSString(cDataFile())];
-		}
-		if (!crashreport.isEmpty()) {
-			[args addObject:@"-crashreport"];
-			[args addObject:Q2NSString(crashreport)];
-		}
-
-		DEBUG_LOG(("Application Info: executing %1 %2").arg(NS2QString(path)).arg(NS2QString([args componentsJoinedByString:@" "])));
-		Logs::closeMain();
-		CrashReports::Finish();
-		if (![NSTask launchedTaskWithLaunchPath:path arguments:args]) {
-			DEBUG_LOG(("Task not launched while executing %1 %2").arg(NS2QString(path)).arg(NS2QString([args componentsJoinedByString:@" "])));
-			return NO;
-		}
-	}
-	@catch (NSException *exception) {
-		LOG(("Exception caught while executing %1 %2").arg(NS2QString(path)).arg(NS2QString(args)));
-		return NO;
-	}
-	@finally {
-	}
-
-	}
-	return YES;
-}
-
-bool objc_execUpdater() {
-	return !!_execUpdater();
-}
-
-void objc_execTelegram(const QString &crashreport) {
-	if (cExeName().isEmpty()) {
-		return;
-	}
-#ifndef OS_MAC_STORE
-	_execUpdater(NO, crashreport);
-#else // OS_MAC_STORE
-	@autoreleasepool {
-
-	NSDictionary *conf = [NSDictionary dictionaryWithObject:[NSArray array] forKey:NSWorkspaceLaunchConfigurationArguments];
-	[[NSWorkspace sharedWorkspace] launchApplicationAtURL:[NSURL fileURLWithPath:Q2NSString(cExeDir() + cExeName())] options:NSWorkspaceLaunchAsync | NSWorkspaceLaunchNewInstance configuration:conf error:0];
-
-	}
-#endif // OS_MAC_STORE
-}
-
 void objc_activateProgram(WId winId) {
 	[NSApp activateIgnoringOtherApps:YES];
 	if (winId) {
diff --git a/Telegram/SourceFiles/platform/win/launcher_win.cpp b/Telegram/SourceFiles/platform/win/launcher_win.cpp
index cc85d0c9f..cf8f81f06 100644
--- a/Telegram/SourceFiles/platform/win/launcher_win.cpp
+++ b/Telegram/SourceFiles/platform/win/launcher_win.cpp
@@ -20,9 +20,107 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 */
 #include "platform/win/launcher_win.h"
 
+#include "core/crash_reports.h"
+#include "platform/platform_specific.h"
+
+#include <shellapi.h>
+
 namespace Platform {
 
-void Launcher::initHook() {
+bool Launcher::launchUpdater(UpdaterLaunch action) {
+	if (cExeName().isEmpty()) {
+		return false;
+	}
+
+	const auto operation = (action == UpdaterLaunch::JustRelaunch)
+		? QString()
+		: (cWriteProtected()
+			? qsl("runas")
+			: QString());
+	const auto binaryPath = (action == UpdaterLaunch::JustRelaunch)
+		? (cExeDir() + cExeName())
+		: (cWriteProtected()
+			? (cWorkingDir() + qsl("tupdates/temp/Updater.exe"))
+			: (cExeDir() + qsl("Updater.exe")));
+
+	auto argumentsList = QStringList();
+	const auto pushArgument = [&](const QString &argument) {
+		argumentsList.push_back(argument.trimmed());
+	};
+	if (cLaunchMode() == LaunchModeAutoStart) {
+		pushArgument(qsl("-autostart"));
+	}
+	if (cDebug()) {
+		pushArgument(qsl("-debug"));
+	}
+	if (cStartInTray()) {
+		pushArgument(qsl("-startintray"));
+	}
+	if (cTestMode()) {
+		pushArgument(qsl("-testmode"));
+	}
+	if (customWorkingDir()) {
+		pushArgument(qsl("-workdir"));
+		pushArgument('"' + cWorkingDir() + '"');
+	}
+	if (cDataFile() != qsl("data")) {
+		pushArgument(qsl("-key"));
+		pushArgument('"' + cDataFile() + '"');
+	}
+
+	if (action == UpdaterLaunch::JustRelaunch) {
+		pushArgument(qsl("-noupdate"));
+		if (cRestartingToSettings()) {
+			pushArgument(qsl("-tosettings"));
+		}
+	} else {
+		pushArgument(qsl("-update"));
+		pushArgument(qsl("-exename"));
+		pushArgument('"' + cExeName() + '"');
+		if (cWriteProtected()) {
+			pushArgument(qsl("-writeprotected"));
+			pushArgument('"' + cExeDir() + '"');
+		}
+	}
+	return launch(operation, binaryPath, argumentsList);
+}
+
+bool Launcher::launch(
+		const QString &operation,
+		const QString &binaryPath,
+		const QStringList &argumentsList) {
+	const auto convertPath = [](const QString &path) {
+		return QDir::toNativeSeparators(path).toStdWString();
+	};
+	const auto nativeBinaryPath = convertPath(binaryPath);
+	const auto nativeWorkingDir = convertPath(cWorkingDir());
+	const auto arguments = argumentsList.join(' ');
+
+	DEBUG_LOG(("Application Info: executing %1 %2"
+		).arg(binaryPath
+		).arg(arguments
+		));
+
+	Logs::closeMain();
+	CrashReports::Finish();
+
+	const auto hwnd = HWND(0);
+	const auto result = ShellExecute(
+		hwnd,
+		operation.isEmpty() ? nullptr : operation.toStdWString().c_str(),
+		nativeBinaryPath.c_str(),
+		arguments.toStdWString().c_str(),
+		nativeWorkingDir.empty() ? nullptr : nativeWorkingDir.c_str(),
+		SW_SHOWNORMAL);
+	if (long(result) < 32) {
+		DEBUG_LOG(("Application Error: failed to execute %1, working directory: '%2', result: %3"
+			).arg(binaryPath
+			).arg(cWorkingDir()
+			).arg(long(result)
+			));
+		return false;
+	}
+	return true;
 }
 
 } // namespace
diff --git a/Telegram/SourceFiles/platform/win/launcher_win.h b/Telegram/SourceFiles/platform/win/launcher_win.h
index 9ff229828..3d5079934 100644
--- a/Telegram/SourceFiles/platform/win/launcher_win.h
+++ b/Telegram/SourceFiles/platform/win/launcher_win.h
@@ -29,7 +29,12 @@ public:
 	using Core::Launcher::Launcher;
 
 private:
-	void initHook() override;
+	bool launchUpdater(UpdaterLaunch action) override;
+
+	bool launch(
+		const QString &operation,
+		const QString &binaryPath,
+		const QStringList &argumentsList);
 
 };
 
diff --git a/Telegram/SourceFiles/platform/win/specific_win.cpp b/Telegram/SourceFiles/platform/win/specific_win.cpp
index edefd2e4d..2bf662ec7 100644
--- a/Telegram/SourceFiles/platform/win/specific_win.cpp
+++ b/Telegram/SourceFiles/platform/win/specific_win.cpp
@@ -648,53 +648,6 @@ void psNewVersion() {
 	}
 }
 
-void psExecUpdater() {
-	if (cExeName().isEmpty()) {
-		return;
-	}
-
-	QString targs = qsl("-update -exename \"") + cExeName() + '"';
-	if (cLaunchMode() == LaunchModeAutoStart) targs += qsl(" -autostart");
-	if (cDebug()) targs += qsl(" -debug");
-	if (cStartInTray()) targs += qsl(" -startintray");
-	if (cWriteProtected()) targs += qsl(" -writeprotected \"") + cExeDir() + '"';
-
-	QString updaterPath = cWriteProtected() ? (cWorkingDir() + qsl("tupdates/temp/Updater.exe")) : (cExeDir() + qsl("Updater.exe"));
-
-	QString updater(QDir::toNativeSeparators(updaterPath)), wdir(QDir::toNativeSeparators(cWorkingDir()));
-
-	DEBUG_LOG(("Application Info: executing %1 %2").arg(cExeDir() + "Updater.exe").arg(targs));
-	HINSTANCE r = ShellExecute(0, cWriteProtected() ? L"runas" : 0, updater.toStdWString().c_str(), targs.toStdWString().c_str(), wdir.isEmpty() ? 0 : wdir.toStdWString().c_str(), SW_SHOWNORMAL);
-	if (long(r) < 32) {
-		DEBUG_LOG(("Application Error: failed to execute %1, working directory: '%2', result: %3").arg(updater).arg(wdir).arg(long(r)));
-		psDeleteDir(cWorkingDir() + qsl("tupdates/temp"));
-	}
-}
-
-void psExecTelegram(const QString &crashreport) {
-	if (cExeName().isEmpty()) {
-		return;
-	}
-	QString targs = crashreport.isEmpty() ? qsl("-noupdate") : ('"' + crashreport + '"');
-	if (crashreport.isEmpty()) {
-		if (cRestartingToSettings()) targs += qsl(" -tosettings");
-		if (cLaunchMode() == LaunchModeAutoStart) targs += qsl(" -autostart");
-		if (cDebug()) targs += qsl(" -debug");
-		if (cStartInTray()) targs += qsl(" -startintray");
-		if (cTestMode()) targs += qsl(" -testmode");
-		if (cDataFile() != qsl("data")) targs += qsl(" -key \"") + cDataFile() + '"';
-	}
-	QString telegram(QDir::toNativeSeparators(cExeDir() + cExeName())), wdir(QDir::toNativeSeparators(cWorkingDir()));
-
-	DEBUG_LOG(("Application Info: executing %1 %2").arg(cExeDir() + cExeName()).arg(targs));
-	Logs::closeMain();
-	CrashReports::Finish();
-	HINSTANCE r = ShellExecute(0, 0, telegram.toStdWString().c_str(), targs.toStdWString().c_str(), wdir.isEmpty() ? 0 : wdir.toStdWString().c_str(), SW_SHOWNORMAL);
-	if (long(r) < 32) {
-		DEBUG_LOG(("Application Error: failed to execute %1, working directory: '%2', result: %3").arg(telegram).arg(wdir).arg(long(r)));
-	}
-}
-
 void _manageAppLnk(bool create, bool silent, int path_csidl, const wchar_t *args, const wchar_t *description) {
 	if (cExeName().isEmpty()) {
 		return;
diff --git a/Telegram/SourceFiles/platform/win/specific_win.h b/Telegram/SourceFiles/platform/win/specific_win.h
index 66de3d74d..b4709a10c 100644
--- a/Telegram/SourceFiles/platform/win/specific_win.h
+++ b/Telegram/SourceFiles/platform/win/specific_win.h
@@ -90,9 +90,6 @@ void psBringToBack(QWidget *w);
 int psCleanup();
 int psFixPrevious();
 
-void psExecUpdater();
-void psExecTelegram(const QString &arg = QString());
-
 QAbstractNativeEventFilter *psNativeEventFilter();
 
 void psNewVersion();
diff --git a/Telegram/SourceFiles/settings.cpp b/Telegram/SourceFiles/settings.cpp
index 15b02e76b..c4a271aa1 100644
--- a/Telegram/SourceFiles/settings.cpp
+++ b/Telegram/SourceFiles/settings.cpp
@@ -61,7 +61,9 @@ uint32 gConnectionsInSession = 1;
 QString gLoggedPhoneNumber;
 
 QByteArray gLocalSalt;
-DBIScale gRealScale = dbisAuto, gScreenScale = dbisOne, gConfigScale = dbisAuto;
+DBIScale gRealScale = dbisAuto;
+DBIScale gScreenScale = dbisOne;
+DBIScale gConfigScale = dbisAuto;
 bool gCompressPastedImage = true;
 
 QString gTimeFormat = qsl("hh:mm");
@@ -87,6 +89,8 @@ int32 gIntRetinaFactor = 1;
 
 #ifdef Q_OS_WIN
 DBIPlatform gPlatform = dbipWindows;
+#elif defined OS_MAC_OLD
+DBIPlatform gPlatform = dbipMacOld;
 #elif defined Q_OS_MAC
 DBIPlatform gPlatform = dbipMac;
 #elif defined Q_OS_LINUX64
@@ -112,137 +116,3 @@ int32 gAutoDownloadPhoto = 0; // all auto download
 int32 gAutoDownloadAudio = 0;
 int32 gAutoDownloadGif = 0;
 bool gAutoPlayGif = true;
-
-void ParseCommandLineArguments(const QStringList &arguments) {
-	enum class KeyFormat {
-		NoValues,
-		OneValue,
-		AllLeftValues,
-	};
-	auto parseMap = std::map<QByteArray, KeyFormat> {
-		{ "-testmode"   , KeyFormat::NoValues },
-		{ "-debug"      , KeyFormat::NoValues },
-		{ "-many"       , KeyFormat::NoValues },
-		{ "-key"        , KeyFormat::OneValue },
-		{ "-autostart"  , KeyFormat::NoValues },
-		{ "-fixprevious", KeyFormat::NoValues },
-		{ "-cleanup"    , KeyFormat::NoValues },
-		{ "-noupdate"   , KeyFormat::NoValues },
-		{ "-tosettings" , KeyFormat::NoValues },
-		{ "-startintray", KeyFormat::NoValues },
-		{ "-sendpath"   , KeyFormat::AllLeftValues },
-		{ "-workdir"    , KeyFormat::OneValue },
-		{ "--"          , KeyFormat::OneValue },
-	};
-	auto parseResult = QMap<QByteArray, QStringList>();
-	auto parsingKey = QByteArray();
-	auto parsingFormat = KeyFormat::NoValues;
-	for (auto &argument : arguments) {
-		switch (parsingFormat) {
-		case KeyFormat::OneValue: {
-			parseResult[parsingKey] = QStringList(argument.mid(0, 8192));
-			parsingFormat = KeyFormat::NoValues;
-		} break;
-		case KeyFormat::AllLeftValues: {
-			parseResult[parsingKey].push_back(argument.mid(0, 8192));
-		} break;
-		case KeyFormat::NoValues: {
-			parsingKey = argument.toLatin1();
-			auto it = parseMap.find(parsingKey);
-			if (it != parseMap.end()) {
-				parsingFormat = it->second;
-				parseResult[parsingKey] = QStringList();
-			}
-		} break;
-		}
-	}
-
-	gTestMode = parseResult.contains("-testmode");
-	gDebug = parseResult.contains("-debug");
-	gManyInstance = parseResult.contains("-many");
-	gKeyFile = parseResult.value("-key", QStringList()).join(QString());
-	gLaunchMode = parseResult.contains("-autostart") ? LaunchModeAutoStart
-		: parseResult.contains("-fixprevious") ? LaunchModeFixPrevious
-		: parseResult.contains("-cleanup") ? LaunchModeCleanup
-		: LaunchModeNormal;
-	gNoStartUpdate = parseResult.contains("-noupdate");
-	gStartToSettings = parseResult.contains("-tosettings");
-	gStartInTray = parseResult.contains("-startintray");
-	gSendPaths = parseResult.value("-sendpath", QStringList());
-	gWorkingDir = parseResult.value("-workdir", QStringList()).join(QString());
-	if (!gWorkingDir.isEmpty() && !QDir().exists(gWorkingDir)) {
-		gWorkingDir = QString();
-	}
-	gStartUrl = parseResult.value("--", QStringList()).join(QString());
-}
-
-void InitFromCommandLine(int argc, char *argv[]) {
-	Expects(argc >= 0);
-	auto arguments = QStringList();
-	arguments.reserve(argc);
-	for (auto i = 0; i != argc; ++i) {
-		arguments.push_back(fromUtf8Safe(argv[i]));
-	}
-
-#ifdef Q_OS_MAC
-#ifndef OS_MAC_OLD
-	if (QSysInfo::macVersion() >= QSysInfo::MV_10_11) {
-		gIsElCapitan = true;
-	}
-#else // OS_MAC_OLD
-	if (QSysInfo::macVersion() < QSysInfo::MV_10_7) {
-		gIsSnowLeopard = true;
-	}
-	gPlatform = dbipMacOld;
-#endif // OS_MAC_OLD
-#endif // Q_OS_MAC
-
-	switch (cPlatform()) {
-	case dbipWindows:
-		gUpdateURL = QUrl(qsl("http://tdesktop.com/win/tupdates/current"));
-#ifndef OS_WIN_STORE
-		gPlatformString = qsl("Windows");
-#else // OS_WIN_STORE
-		gPlatformString = qsl("WinStore");
-#endif // OS_WIN_STORE
-	break;
-	case dbipMac:
-		gUpdateURL = QUrl(qsl("http://tdesktop.com/mac/tupdates/current"));
-#ifndef OS_MAC_STORE
-		gPlatformString = qsl("MacOS");
-#else // OS_MAC_STORE
-		gPlatformString = qsl("MacAppStore");
-#endif // OS_MAC_STORE
-	break;
-	case dbipMacOld:
-		gUpdateURL = QUrl(qsl("http://tdesktop.com/mac32/tupdates/current"));
-		gPlatformString = qsl("MacOSold");
-	break;
-	case dbipLinux64:
-		gUpdateURL = QUrl(qsl("http://tdesktop.com/linux/tupdates/current"));
-		gPlatformString = qsl("Linux64bit");
-	break;
-	case dbipLinux32:
-		gUpdateURL = QUrl(qsl("http://tdesktop.com/linux32/tupdates/current"));
-		gPlatformString = qsl("Linux32bit");
-	break;
-	}
-
-	auto path = Platform::CurrentExecutablePath(argc, argv);
-	LOG(("Executable path before check: %1").arg(path));
-	if (!path.isEmpty()) {
-		auto info = QFileInfo(path);
-		if (info.isSymLink()) {
-			info = info.symLinkTarget();
-		}
-		if (info.exists()) {
-			gExeDir = info.absoluteDir().absolutePath() + '/';
-			gExeName = info.fileName();
-		}
-	}
-	if (cExeName().isEmpty()) {
-		LOG(("WARNING: Could not compute executable path, some features will be disabled."));
-	}
-
-	ParseCommandLineArguments(arguments);
-}
diff --git a/Telegram/gyp/refresh.sh b/Telegram/gyp/refresh.sh
index 4b0073531..f808de5ba 100755
--- a/Telegram/gyp/refresh.sh
+++ b/Telegram/gyp/refresh.sh
@@ -28,7 +28,7 @@ else
   #gyp --depth=. --generator-output=../.. -Goutput_dir=out Telegram.gyp --format=xcode-ninja
   #gyp --depth=. --generator-output=../.. -Goutput_dir=out Telegram.gyp --format=xcode
   # use patched gyp with Xcode project generator
-  ../../../Libraries/gyp/gyp --depth=. --generator-output=.. -Goutput_dir=../out -Gxcode_upgrade_check_project_version=910 -Dofficial_build_target=$BuildTarget Telegram.gyp --format=xcode
+  ../../../Libraries/gyp/gyp --depth=. --generator-output=.. -Goutput_dir=../out -Gxcode_upgrade_check_project_version=920 -Dofficial_build_target=$BuildTarget Telegram.gyp --format=xcode
 fi
 
 cd ../..