diff --git a/gameheaders/stratagus-game-launcher.h b/gameheaders/stratagus-game-launcher.h
index 328df85a9..9cfd759eb 100644
--- a/gameheaders/stratagus-game-launcher.h
+++ b/gameheaders/stratagus-game-launcher.h
@@ -145,8 +145,13 @@
 
 #if ( defined (_MSC_VER) || defined (_WIN32) || defined (_WIN64) ) && ! defined (WIN32)
 #define WIN32
+#endif
+
+#ifdef WIN32
+#include <Shlwapi.h>
 #pragma comment(lib, "comdlg32.lib")
 #pragma comment(lib, "ole32.lib")
+#pragma comment(lib, "Shlwapi.lib")
 #endif
 
 /**
@@ -169,28 +174,34 @@
 #endif
 
 #ifdef WIN32
+#ifndef WINVER
 #define WINVER 0x0501
+#endif
 #include <windows.h>
 #include <wincon.h>
 #include <process.h>
+#else
+#include <ftw.h>
 #endif
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ftw.h>
 
 #include <sys/stat.h>
 #include <sys/types.h>
 
 #if defined(_MSC_VER) || defined(__MINGW32__)
 #include <direct.h>
-#define inline __inline
+//#define inline __inline
 #define chdir _chdir
 #define getcwd _getcwd
 #define spawnvp _spawnvp
 #define stat _stat
+#define strdup _strdup
+#define mkdir(f, m) _mkdir(f)
+#define dirname(x) PathRemoveFileSpec(x)
 #endif
 
 #ifdef _MSC_VER
@@ -226,32 +237,28 @@ int ConsoleMode = 0;
 #include "tinyfiledialogs.c"
 
 static void SetUserDataPath(char* data_path) {
-#if USE_WIN32
+#if WIN32
 	strcpy(data_path, getenv("APPDATA"));
 #else
 	strcpy(data_path, getenv("HOME"));
 #endif
 	int datalen = strlen(data_path);
-	if (datalen == 0) {
-		return;
-	}
-	data_path[datalen] = '/';
-	data_path[datalen + 1] = '\0';
-
-#if USE_WIN32
-	strcat(data_path, "Stratagus\\");
+#if WIN32
+	strcat(data_path, "\\Stratagus\\");
 #elif defined(USE_MAC)
-	strcat(data_path, "Library/Stratagus/");
+	strcat(data_path, "/Library/Stratagus/");
 #else
-	strcat(data_path, ".stratagus/");
+	strcat(data_path, "/.stratagus/");
 #endif
 	strcat(data_path, "data." GAME_NAME);
 }
 
-#ifdef USE_WIN32
+#ifdef WIN32
 #define QUOTE "\""
+#define SLASH "\\"
 #else
 #define QUOTE "'"
+#define SLASH "/"
 #endif
 
 static void error(char* title, char* text) {
@@ -264,25 +271,27 @@ char src_root[BUFF_SIZE];
 
 void mkdir_p(const char* path)
 {
-	char* cp;
-	char* s;
+	char *cp, *s, *s2;
 
 	if (*path && path[0] == '.') {  // relative don't work
 		return;
 	}
 	cp = strdup(path);
 	s = strrchr(cp, '/');
+	if (!s) s = strrchr(cp, SLASH[0]);
 	if (s) {
 		*s = '\0';  // remove file
 		s = cp;
 		for (;;) {  // make each path element
-			s = strchr(s, '/');
+			s2 = strchr(s, '/');
+			if (!s2) s = strchr(s, SLASH[0]);
+			s = s2;
 			if (s) {
 				*s = '\0';
 			}
 			mkdir(cp, 0777);
 			if (s) {
-				*s++ = '/';
+				*s++ = SLASH[0];
 			} else {
 				break;
 			}
@@ -293,6 +302,31 @@ void mkdir_p(const char* path)
 	free(cp);
 }
 
+#ifdef WIN32
+#include <wchar.h>
+#include <string>
+static void copy_dir(const char* source_folder, const char* target_folder)
+{
+	wchar_t *wsource_folder = new wchar_t[strlen(source_folder) + 1];
+	size_t convertedChars = 0;
+	mbstowcs_s(&convertedChars, wsource_folder, strlen(source_folder) + 1, source_folder, _TRUNCATE);
+	wchar_t *wtarget_folder = new wchar_t[strlen(target_folder) + 1];
+	mbstowcs_s(&convertedChars, wtarget_folder, strlen(target_folder) + 1, target_folder, _TRUNCATE);
+	WCHAR sf[MAX_PATH + 1];
+	WCHAR tf[MAX_PATH + 1];
+	wcscpy_s(sf, MAX_PATH, wsource_folder);
+	mkdir_p(target_folder);
+	wcscpy_s(tf, MAX_PATH, wtarget_folder);
+	sf[lstrlenW(sf) + 1] = 0;
+	tf[lstrlenW(tf) + 1] = 0;
+	SHFILEOPSTRUCTW s = { 0 };
+	s.wFunc = FO_COPY;
+	s.pTo = tf;
+	s.pFrom = sf;
+	s.fFlags = FOF_SILENT | FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NO_UI;
+	SHFileOperationW(&s);
+}
+#else
 static int copy_file(const char* src_path, const struct stat* sb, int typeflag) {
 	char dst_path[BUFF_SIZE];
 	strcpy(dst_path, dst_root);
@@ -323,7 +357,7 @@ static void copy_dir(const char* src_path, const char* dst_path) {
 	strcpy(src_root, src_path);
 	ftw(src_path, copy_file, 20);
 }
-
+#endif
 
 int check_version(char* tool_path, char* data_path) {
     char buf[4096] = {'\0'};
@@ -338,11 +372,37 @@ int check_version(char* tool_path, char* data_path) {
 		return 1; // No file means we don't care
 	}
     sprintf(buf, "%s -V", tool_path);
+#ifndef WIN32
     FILE *pipe = popen(buf, "r");
     if (f) {
 		fgets(toolversion, 20, pipe);
 		pclose(pipe);
     }
+#else
+	HANDLE g_hChildStd_OUT_Rd = NULL;
+	HANDLE g_hChildStd_OUT_Wr = NULL;
+	SECURITY_ATTRIBUTES saAttr;
+	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
+	saAttr.bInheritHandle = TRUE;
+	saAttr.lpSecurityDescriptor = NULL;
+	if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0))
+		return 1;
+	if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
+		return 1;
+	PROCESS_INFORMATION piProcInfo;
+	STARTUPINFO siStartInfo;
+	ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
+	ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
+	siStartInfo.cb = sizeof(STARTUPINFO);
+	siStartInfo.hStdError = g_hChildStd_OUT_Wr;
+	siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
+	siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
+	if (!CreateProcess(NULL, buf, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo))
+		return 1;
+	CloseHandle(piProcInfo.hProcess);
+	CloseHandle(piProcInfo.hThread);
+	ReadFile(g_hChildStd_OUT_Rd, toolversion, 20, NULL, NULL);
+#endif
     // strip whitespace
     for (size_t i=0, j=0; toolversion[j]=toolversion[i]; j+=!isspace(toolversion[i++]));
     for (size_t i=0, j=0; dataversion[j]=dataversion[i]; j+=!isspace(dataversion[i++]));
@@ -355,7 +415,7 @@ int check_version(char* tool_path, char* data_path) {
 static void ExtractData(char* extractor_tool, char* destination, char* scripts_path, int force=0) {
 	if (!force) {
 		tinyfd_messageBox("Missing data",
-						  DATA_NOT_EXTRACTED "Please select the " GAME_CD, "ok", "error", 1);
+						  DATA_NOT_EXTRACTED " Please select the " GAME_CD, "ok", "error", 1);
 	} else {
 		tinyfd_messageBox("", "Please select the " GAME_CD, "ok", "error", 1);
 	}
@@ -370,21 +430,13 @@ static void ExtractData(char* extractor_tool, char* destination, char* scripts_p
 	char srcfolder[1024] = {'\0'};
 	strcpy(srcfolder, datafile);
 
-#ifdef WIN32
-	PathRemoveFileSpec(srcfolder);
-#else
 	dirname(srcfolder);
-#endif
 
 	struct stat st;
 	if (stat(scripts_path, &st) != 0) {
 		// deployment time path not found, try compile time path
 		strcpy(scripts_path, SRC_PATH());
-#ifdef WIN32
-		PathRemoveFileSpec(scripts_path);
-#else
 		dirname(scripts_path);
-#endif
 	}
 
 	char contrib_src_path[BUFF_SIZE];
@@ -393,10 +445,10 @@ static void ExtractData(char* extractor_tool, char* destination, char* scripts_p
 	char* contrib_directories[] = CONTRIB_DIRECTORIES;
 	while (contrib_directories[i] != NULL && contrib_directories[i + 1] != NULL) {
 		strcpy(contrib_src_path, scripts_path);
-		strcat(contrib_src_path, "/");
+		strcat(contrib_src_path, SLASH);
 		strcat(contrib_src_path, contrib_directories[i]);
 		strcpy(contrib_dest_path, destination);
-		strcat(contrib_dest_path, "/");
+		strcat(contrib_dest_path, SLASH);
 		strcat(contrib_dest_path, contrib_directories[i + 1]);
 		copy_dir(contrib_src_path, contrib_dest_path);
 		i += 2;
@@ -409,6 +461,8 @@ static void ExtractData(char* extractor_tool, char* destination, char* scripts_p
 	if (!ConsoleMode) {
 		strcat(cmdbuf, "x-terminal-emulator -e \"");
 	}
+#else
+	strcat(cmdbuf, "/C \"");
 #endif
 	strcat(cmdbuf, extractor_tool);
 	strcat(cmdbuf, " " QUOTE);
@@ -422,9 +476,37 @@ static void ExtractData(char* extractor_tool, char* destination, char* scripts_p
 	if (!ConsoleMode) {
 	strcat(cmdbuf, "\"");
 }
+#else
+	strcat(cmdbuf, "\"");
 #endif
-	printf("Running %s\n", cmdbuf);
-	system(cmdbuf);
+#ifdef WIN32
+	DWORD exitcode = 0;
+	SHELLEXECUTEINFO ShExecInfo = { 0 };
+	char* toolpath = strdup(extractor_tool);
+	PathRemoveFileSpec(toolpath);
+	// remove the leading quote
+	if (toolpath[0] == '"') memmove(toolpath, toolpath + 1, strlen(toolpath) + 1);
+	ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
+	ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
+	ShExecInfo.hwnd = NULL;
+	ShExecInfo.lpVerb = NULL;
+	ShExecInfo.lpFile = "cmd";
+	ShExecInfo.lpParameters = cmdbuf;
+	ShExecInfo.lpDirectory = toolpath;
+	ShExecInfo.nShow = SW_SHOW;
+	ShExecInfo.hInstApp = NULL;
+	ShellExecuteEx(&ShExecInfo);
+	WaitForSingleObject(ShExecInfo.hProcess, INFINITE);
+	GetExitCodeProcess(ShExecInfo.hProcess, &exitcode);
+#else
+	int exitcode = 0;
+    printf("Running %s\n", cmdbuf);
+	exitcode = system(cmdbuf);
+#endif
+	if (exitcode != 0) {
+		tinyfd_messageBox("Missing data", "Data extraction failed", "ok", "error", 1);
+		_unlink(destination);
+	};
 }
 
 int main(int argc, char * argv[]) {
@@ -449,13 +531,8 @@ int main(int argc, char * argv[]) {
 
 	// The extractor is in the same dir as we are
 	strcpy(extractor_path, argv[0]);
-#ifdef WIN32
-	PathRemoveFileSpec(extractor_path);
-	strcat(extractor_path, "\\" EXTRACTOR_TOOL);
-#else
 	dirname(extractor_path);
-	strcat(extractor_path, "/" EXTRACTOR_TOOL);
-#endif
+	strcat(extractor_path, SLASH EXTRACTOR_TOOL);
 	// Once we have the path, we quote it by moving the memory one byte to the
 	// right, and surrounding it with the quote character and finishing null
 	// bytes. Then we add the arguments.
@@ -524,7 +601,7 @@ int main(int argc, char * argv[]) {
 
 	if ( stat(stratagus_bin, &st) != 0 ) {
 #ifdef WIN32
-		stratagus_bin = _fullpath(argv[0], NULL);
+		_fullpath(stratagus_bin, argv[0], BUFF_SIZE);
 		PathRemoveFileSpec(stratagus_bin);
 		strcat(extractor_path, "\\stratagus.exe");
 #else
@@ -612,20 +689,7 @@ int main(int argc, char * argv[]) {
 	}
 	stratagus_argv[argc + 2] = NULL;
 
-#ifdef WIN32
-	AttachConsole(ATTACH_PARENT_PROCESS);
-
-	errno = 0;
-	int ret = spawnvp(_P_WAIT, stratagus_bin, stratagus_argv);
-#ifdef _MSC_VER
-	free (stratagus_argv);
-#endif
-	if ( errno == 0 ) {
-		return ret;
-	}
-#else
-	execvp(stratagus_bin, stratagus_argv);
-#endif
+	_execvp(stratagus_bin, stratagus_argv);
 
 #ifndef WIN32
 	if (strcmp(stratagus_bin, "stratagus") == 0) {