win32.c
changeset 5168 10a8dc9788d7
parent 5167 2b9d61386688
child 5218 aae5f36a5256
equal deleted inserted replaced
5167:2b9d61386688 5168:10a8dc9788d7
    16 #include <fcntl.h>
    16 #include <fcntl.h>
    17 #include "variables.h"
    17 #include "variables.h"
    18 #include "win32.h"
    18 #include "win32.h"
    19 #include "fios.h" // opendir/readdir/closedir
    19 #include "fios.h" // opendir/readdir/closedir
    20 #include <ctype.h>
    20 #include <ctype.h>
       
    21 #include <tchar.h>
    21 #include <errno.h>
    22 #include <errno.h>
    22 #include <sys/types.h>
    23 #include <sys/types.h>
    23 #include <sys/stat.h>
    24 #include <sys/stat.h>
    24 
    25 
    25 static bool _has_console;
    26 static bool _has_console;
    38 	ShowCursor(show);
    39 	ShowCursor(show);
    39 
    40 
    40 	return !show;
    41 	return !show;
    41 }
    42 }
    42 
    43 
    43 
    44 /** Helper function needed by dynamically loading libraries
    44 // Helper function needed by dynamically loading SDL
    45  * XXX: Hurray for MS only having an ANSI GetProcAddress function
    45 bool LoadLibraryList(Function proc[], const char* dll)
    46  * on normal windows and no Wide version except for in Windows Mobile/CE */
       
    47 bool LoadLibraryList(Function proc[], const char *dll)
    46 {
    48 {
    47 	while (*dll != '\0') {
    49 	while (*dll != '\0') {
    48 		HMODULE lib = LoadLibrary(dll);
    50 		HMODULE lib;
       
    51 		lib = LoadLibrary(MB_TO_WIDE(dll));
    49 
    52 
    50 		if (lib == NULL) return false;
    53 		if (lib == NULL) return false;
    51 		for (;;) {
    54 		for (;;) {
    52 			FARPROC p;
    55 			FARPROC p;
    53 
    56 
    54 			while (*dll++ != '\0');
    57 			while (*dll++ != '\0');
    55 			if (*dll == '\0') break;
    58 			if (*dll == '\0') break;
       
    59 #if defined(WINCE)
       
    60 			p = GetProcAddress(lib, MB_TO_WIDE(dll);
       
    61 #else
    56 			p = GetProcAddress(lib, dll);
    62 			p = GetProcAddress(lib, dll);
       
    63 #endif
    57 			if (p == NULL) return false;
    64 			if (p == NULL) return false;
    58 			*proc++ = (Function)p;
    65 			*proc++ = (Function)p;
    59 		}
    66 		}
    60 		dll++;
    67 		dll++;
    61 	}
    68 	}
    62 	return true;
    69 	return true;
    63 }
    70 }
    64 
    71 
    65 #ifdef _MSC_VER
    72 #ifdef _MSC_VER
    66 static const char *_exception_string;
    73 static const char *_exception_string = NULL;
    67 #endif
    74 #endif
    68 
    75 
    69 void ShowOSErrorBox(const char *buf)
    76 void ShowOSErrorBox(const char *buf)
    70 {
    77 {
    71 	MyShowCursor(true);
    78 	MyShowCursor(true);
    72 	MessageBoxA(GetActiveWindow(), buf, "Error!", MB_ICONSTOP);
    79 	MessageBox(GetActiveWindow(), MB_TO_WIDE(buf), _T("Error!"), MB_ICONSTOP);
    73 
    80 
    74 // if exception tracker is enabled, we crash here to let the exception handler handle it.
    81 // if exception tracker is enabled, we crash here to let the exception handler handle it.
    75 #if defined(WIN32_EXCEPTION_TRACKER) && !defined(_DEBUG)
    82 #if defined(WIN32_EXCEPTION_TRACKER) && !defined(_DEBUG)
    76 	if (*buf == '!') {
    83 	if (*buf == '!') {
    77 		_exception_string = buf;
    84 		_exception_string = buf;
   117 		crc = ((crc >> 8) & 0x00FFFFFF) ^ _crc_table[(crc ^ *data++) & 0xFF];
   124 		crc = ((crc >> 8) & 0x00FFFFFF) ^ _crc_table[(crc ^ *data++) & 0xFF];
   118 	}
   125 	}
   119 	return crc;
   126 	return crc;
   120 }
   127 }
   121 
   128 
   122 static void GetFileInfo(DebugFileInfo *dfi, const char *filename)
   129 static void GetFileInfo(DebugFileInfo *dfi, const TCHAR *filename)
   123 {
   130 {
   124 	memset(dfi, 0, sizeof(dfi));
   131 	memset(dfi, 0, sizeof(dfi));
   125 
   132 
   126 	{
   133 	{
   127 		HANDLE file;
   134 		HANDLE file;
   153 }
   160 }
   154 
   161 
   155 
   162 
   156 static char *PrintModuleInfo(char *output, HMODULE mod)
   163 static char *PrintModuleInfo(char *output, HMODULE mod)
   157 {
   164 {
   158 	char buffer[MAX_PATH];
   165 	TCHAR buffer[MAX_PATH];
   159 	DebugFileInfo dfi;
   166 	DebugFileInfo dfi;
   160 
   167 
   161 	GetModuleFileName(mod, buffer, MAX_PATH);
   168 	GetModuleFileName(mod, buffer, MAX_PATH);
   162 	GetFileInfo(&dfi, buffer);
   169 	GetFileInfo(&dfi, buffer);
   163 	output += sprintf(output, " %-20s handle: %p size: %d crc: %.8X date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n",
   170 	output += sprintf(output, " %-20s handle: %p size: %d crc: %.8X date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n",
   164 		buffer,
   171 		WIDE_TO_MB(buffer),
   165 		mod,
   172 		mod,
   166 		dfi.size,
   173 		dfi.size,
   167 		dfi.crc32,
   174 		dfi.crc32,
   168 		dfi.file_time.wYear,
   175 		dfi.file_time.wYear,
   169 		dfi.file_time.wMonth,
   176 		dfi.file_time.wMonth,
   182 	HMODULE modules[100];
   189 	HMODULE modules[100];
   183 	DWORD needed;
   190 	DWORD needed;
   184 	BOOL res;
   191 	BOOL res;
   185 	int count,i;
   192 	int count,i;
   186 
   193 
   187 	if (LoadLibraryList((Function*)&EnumProcessModules, "psapi.dll\0EnumProcessModules\0")) {
   194 	if (LoadLibraryList((Function*)&EnumProcessModules, "psapi.dll\0EnumProcessModules\0\0")) {
   188 		proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
   195 		proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
   189 		if (proc) {
   196 		if (proc) {
   190 			res = EnumProcessModules(proc, modules, sizeof(modules), &needed);
   197 			res = EnumProcessModules(proc, modules, sizeof(modules), &needed);
   191 			CloseHandle(proc);
   198 			CloseHandle(proc);
   192 			if (res) {
   199 			if (res) {
   200 	}
   207 	}
   201 	output = PrintModuleInfo(output, NULL);
   208 	output = PrintModuleInfo(output, NULL);
   202 	return output;
   209 	return output;
   203 }
   210 }
   204 
   211 
   205 static const char _crash_desc[] =
   212 static const TCHAR _crash_desc[] =
   206 	"A serious fault condition occured in the game. The game will shut down.\n"
   213 	_T("A serious fault condition occured in the game. The game will shut down.\n")
   207 	"Press \"Submit report\" to send crash information to the developers. "
   214 	_T("Press \"Submit report\" to send crash information to the developers. ")
   208 	"This will greatly help debugging. "
   215 	_T("This will greatly help debugging. ")
   209 	"The information contained in the report is displayed below.\n"
   216 	_T("The information contained in the report is displayed below.\n")
   210 	"Press \"Emergency save\" to attempt saving the game.";
   217 	_T("Press \"Emergency save\" to attempt saving the game.");
   211 
   218 
   212 static const char _save_succeeded[] =
   219 static const TCHAR _save_succeeded[] =
   213 	"Emergency save succeeded.\n"
   220 	_T("Emergency save succeeded.\n")
   214 	"Be aware that critical parts of the internal game state may have become "
   221 	_T("Be aware that critical parts of the internal game state may have become ")
   215 	"corrupted. The saved game is not guaranteed to work.";
   222 	_T("corrupted. The saved game is not guaranteed to work.");
   216 
   223 
   217 static bool EmergencySave(void)
   224 static bool EmergencySave(void)
   218 {
   225 {
   219 	SaveOrLoad("crash.sav", SL_SAVE);
   226 	SaveOrLoad("crash.sav", SL_SAVE);
   220 	return true;
   227 	return true;
   221 }
   228 }
   222 
   229 
   223 typedef struct {
   230 typedef struct {
   224 	HINTERNET (WINAPI *InternetOpenA)(LPCSTR,DWORD, LPCSTR, LPCSTR, DWORD);
   231 	HINTERNET (WINAPI *InternetOpen)(LPCTSTR,DWORD, LPCTSTR, LPCTSTR, DWORD);
   225 	HINTERNET (WINAPI *InternetConnectA)(HINTERNET, LPCSTR, INTERNET_PORT, LPCSTR, LPCSTR, DWORD, DWORD, DWORD);
   232 	HINTERNET (WINAPI *InternetConnect)(HINTERNET, LPCTSTR, INTERNET_PORT, LPCTSTR, LPCTSTR, DWORD, DWORD, DWORD);
   226 	HINTERNET (WINAPI *HttpOpenRequestA)(HINTERNET, LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPCSTR *, DWORD, DWORD);
   233 	HINTERNET (WINAPI *HttpOpenRequest)(HINTERNET, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR, LPCTSTR *, DWORD, DWORD);
   227 	BOOL (WINAPI *HttpSendRequestA)(HINTERNET, LPCSTR, DWORD, LPVOID, DWORD);
   234 	BOOL (WINAPI *HttpSendRequest)(HINTERNET, LPCTSTR, DWORD, LPVOID, DWORD);
   228 	BOOL (WINAPI *InternetCloseHandle)(HINTERNET);
   235 	BOOL (WINAPI *InternetCloseHandle)(HINTERNET);
   229 	BOOL (WINAPI *HttpQueryInfo)(HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD);
   236 	BOOL (WINAPI *HttpQueryInfo)(HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD);
   230 } WinInetProcs;
   237 } WinInetProcs;
   231 
   238 
   232 #define M(x) x "\0"
   239 #define M(x) x "\0"
       
   240 #if defined(UNICODE)
       
   241 # define W(x) x "W"
       
   242 #else
       
   243 # define W(x) x "A"
       
   244 #endif
   233 static const char wininet_files[] =
   245 static const char wininet_files[] =
   234 	M("wininet.dll")
   246 	M("wininet.dll")
   235 	M("InternetOpenA")
   247 	M(W("InternetOpen"))
   236 	M("InternetConnectA")
   248 	M(W("InternetConnect"))
   237 	M("HttpOpenRequestA")
   249 	M(W("HttpOpenRequest"))
   238 	M("HttpSendRequestA")
   250 	M(W("HttpSendRequest"))
   239 	M("InternetCloseHandle")
   251 	M("InternetCloseHandle")
   240 	M("HttpQueryInfoA")
   252 	M(W("HttpQueryInfo"))
   241 	M("");
   253 	M("");
       
   254 #undef W
   242 #undef M
   255 #undef M
   243 
   256 
   244 static WinInetProcs _wininet;
   257 static WinInetProcs _wininet;
   245 
   258 
   246 
   259 
   247 static const char *SubmitCrashReport(HWND wnd, void *msg, size_t msglen, const char *arg)
   260 static const TCHAR *SubmitCrashReport(HWND wnd, void *msg, size_t msglen, const TCHAR *arg)
   248 {
   261 {
   249 	HINTERNET inet, conn, http;
   262 	HINTERNET inet, conn, http;
   250 	const char *err = NULL;
   263 	const TCHAR *err = NULL;
   251 	DWORD code, len;
   264 	DWORD code, len;
   252 	static char buf[100];
   265 	static TCHAR buf[100];
   253 	char buff[100];
   266 	TCHAR buff[100];
   254 
   267 
   255 	if (_wininet.InternetOpen == NULL && !LoadLibraryList((Function*)&_wininet, wininet_files)) return "can't load wininet.dll";
   268 	if (_wininet.InternetOpen == NULL && !LoadLibraryList((Function*)&_wininet, wininet_files)) return _T("can't load wininet.dll");
   256 
   269 
   257 	inet = _wininet.InternetOpen("OTTD", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
   270 	inet = _wininet.InternetOpen(_T("OTTD"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0 );
   258 	if (inet == NULL) { err = "internetopen failed"; goto error1; }
   271 	if (inet == NULL) { err = _T("internetopen failed"); goto error1; }
   259 
   272 
   260 	conn = _wininet.InternetConnect(inet, "openttd.com", INTERNET_DEFAULT_HTTP_PORT, "", "", INTERNET_SERVICE_HTTP, 0, 0);
   273 	conn = _wininet.InternetConnect(inet, _T("www.openttd.org"), INTERNET_DEFAULT_HTTP_PORT, _T(""), _T(""), INTERNET_SERVICE_HTTP, 0, 0);
   261 	if (conn == NULL) { err = "internetconnect failed"; goto error2; }
   274 	if (conn == NULL) { err = _T("internetconnect failed"); goto error2; }
   262 
   275 
   263 	sprintf(buff, "/crash.php?file=%s&ident=%d", arg, _ident);
   276 	_sntprintf(buff, lengthof(buff), _T("/crash.php?file=%s&ident=%d"), arg, _ident);
   264 
   277 
   265 	http = _wininet.HttpOpenRequest(conn, "POST", buff, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE , 0);
   278 	http = _wininet.HttpOpenRequest(conn, _T("POST"), buff, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE , 0);
   266 	if (http == NULL) { err = "httpopenrequest failed"; goto error3; }
   279 	if (http == NULL) { err = _T("httpopenrequest failed"); goto error3; }
   267 
   280 
   268 	if (!_wininet.HttpSendRequest(http, "Content-type: application/binary", -1, msg, (DWORD)msglen)) { err = "httpsendrequest failed"; goto error4; }
   281 	if (!_wininet.HttpSendRequest(http, _T("Content-type: application/binary"), -1, msg, (DWORD)msglen)) { err = _T("httpsendrequest failed"); goto error4; }
   269 
   282 
   270 	len = sizeof(code);
   283 	len = sizeof(code);
   271 	if (!_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &code, &len, 0)) { err = "httpqueryinfo failed"; goto error4; }
   284 	if (!_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &code, &len, 0)) { err = _T("httpqueryinfo failed"); goto error4; }
   272 
   285 
   273 	if (code != 200) {
   286 	if (code != 200) {
   274 		int l = sprintf(buf, "Server said: %d ", code);
   287 		int l = _sntprintf(buf, lengthof(buf), _T("Server said: %d "), code);
   275 		len = sizeof(buf) - l;
   288 		len = sizeof(buf) - l;
   276 		_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_TEXT, buf + l, &len, 0);
   289 		_wininet.HttpQueryInfo(http, HTTP_QUERY_STATUS_TEXT, buf + l, &len, 0);
   277 		err = buf;
   290 		err = buf;
   278 	}
   291 	}
   279 
   292 
   285 	_wininet.InternetCloseHandle(inet);
   298 	_wininet.InternetCloseHandle(inet);
   286 error1:
   299 error1:
   287 	return err;
   300 	return err;
   288 }
   301 }
   289 
   302 
   290 static void SubmitFile(HWND wnd, const char *file)
   303 static void SubmitFile(HWND wnd, const TCHAR *file)
   291 {
   304 {
   292 	HANDLE h;
   305 	HANDLE h;
   293 	unsigned long size;
   306 	unsigned long size;
   294 	unsigned long read;
   307 	unsigned long read;
   295 	void *mem;
   308 	void *mem;
   311 	free(mem);
   324 	free(mem);
   312 error1:
   325 error1:
   313 	CloseHandle(h);
   326 	CloseHandle(h);
   314 }
   327 }
   315 
   328 
   316 static const char * const _expand_texts[] = {"S&how report >>", "&Hide report <<" };
   329 static const TCHAR * const _expand_texts[] = {_T("S&how report >>"), _T("&Hide report <<") };
   317 
   330 
   318 static void SetWndSize(HWND wnd, int mode)
   331 static void SetWndSize(HWND wnd, int mode)
   319 {
   332 {
   320 	RECT r,r2;
   333 	RECT r,r2;
   321 	int offs;
   334 	int offs;
   351 }
   364 }
   352 
   365 
   353 static INT_PTR CALLBACK CrashDialogFunc(HWND wnd,UINT msg,WPARAM wParam,LPARAM lParam)
   366 static INT_PTR CALLBACK CrashDialogFunc(HWND wnd,UINT msg,WPARAM wParam,LPARAM lParam)
   354 {
   367 {
   355 	switch (msg) {
   368 	switch (msg) {
   356 	case WM_INITDIALOG:
   369 	case WM_INITDIALOG: {
       
   370 #if defined(UNICODE)
       
   371 # define crash_msg crash_msgW
       
   372 		TCHAR crash_msgW[8096];
       
   373 		MultiByteToWideChar(CP_ACP, 0, _crash_msg, -1, crash_msgW, lengthof(crash_msgW));
       
   374 #else
       
   375 # define crash_msg _crash_msg
       
   376 #endif
   357 		SetDlgItemText(wnd, 10, _crash_desc);
   377 		SetDlgItemText(wnd, 10, _crash_desc);
   358 		SetDlgItemText(wnd, 11, _crash_msg);
   378 		SetDlgItemText(wnd, 11, crash_msg);
   359 		SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE);
   379 		SendDlgItemMessage(wnd, 11, WM_SETFONT, (WPARAM)GetStockObject(ANSI_FIXED_FONT), FALSE);
   360 		SetWndSize(wnd, -1);
   380 		SetWndSize(wnd, -1);
   361 		return TRUE;
   381 	} return TRUE;
   362 	case WM_COMMAND:
   382 	case WM_COMMAND:
   363 		switch (wParam) {
   383 		switch (wParam) {
   364 		case 12: // Close
   384 		case 12: // Close
   365 			ExitProcess(0);
   385 			ExitProcess(0);
   366 		case 13: { // Emergency save
   386 		case 13: { // Emergency save
   367 			if (DoEmergencySave(wnd)) {
   387 			if (DoEmergencySave(wnd)) {
   368 				MessageBoxA(wnd, _save_succeeded, "Save successful", MB_ICONINFORMATION);
   388 				MessageBox(wnd, _save_succeeded, _T("Save successful"), MB_ICONINFORMATION);
   369 			} else {
   389 			} else {
   370 				MessageBoxA(wnd, "Save failed", "Save failed", MB_ICONINFORMATION);
   390 				MessageBox(wnd, _T("Save failed"), _T("Save failed"), MB_ICONINFORMATION);
   371 			}
   391 			}
   372 			break;
   392 			break;
   373 		}
   393 		}
   374 		case 14: { // Submit crash report
   394 		case 14: { // Submit crash report
   375 			const char *s;
   395 			const TCHAR *s;
   376 
   396 
   377 			SetCursor(LoadCursor(NULL, IDC_WAIT));
   397 			SetCursor(LoadCursor(NULL, IDC_WAIT));
   378 
   398 
   379 			s = SubmitCrashReport(wnd, _crash_msg, strlen(_crash_msg), "");
   399 			s = SubmitCrashReport(wnd, _crash_msg, strlen(_crash_msg), _T(""));
   380 			if (s) {
   400 			if (s != NULL) {
   381 				MessageBoxA(wnd, s, "Error", MB_ICONSTOP);
   401 				MessageBox(wnd, s, _T("Error"), MB_ICONSTOP);
   382 				break;
   402 				break;
   383 			}
   403 			}
   384 
   404 
   385 			// try to submit emergency savegame
   405 			// try to submit emergency savegame
   386 			if (_did_emerg_save || DoEmergencySave(wnd)) {
   406 			if (_did_emerg_save || DoEmergencySave(wnd)) SubmitFile(wnd, _T("crash.sav"));
   387 				SubmitFile(wnd, "crash.sav");
   407 
   388 			}
       
   389 			// try to submit the autosaved game
   408 			// try to submit the autosaved game
   390 			if (_opt.autosave) {
   409 			if (_opt.autosave) {
   391 				char buf[40];
   410 				TCHAR buf[40];
   392 				sprintf(buf, "autosave%d.sav", (_autosave_ctr - 1) & 3);
   411 				_sntprintf(buf, lengthof(buf), _T("autosave%d.sav"), (_autosave_ctr - 1) & 3);
   393 				SubmitFile(wnd, buf);
   412 				SubmitFile(wnd, buf);
   394 			}
   413 			}
   395 			EnableWindow(GetDlgItem(wnd, 14), FALSE);
   414 			EnableWindow(GetDlgItem(wnd, 14), FALSE);
   396 			SetCursor(LoadCursor(NULL, IDC_ARROW));
   415 			SetCursor(LoadCursor(NULL, IDC_ARROW));
   397 			MessageBoxA(wnd, "Crash report submitted. Thank you.", "Crash Report", MB_ICONINFORMATION);
   416 			MessageBox(wnd, _T("Crash report submitted. Thank you."), _T("Crash Report"), MB_ICONINFORMATION);
   398 			break;
   417 			break;
   399 		}
   418 		}
   400 		case 15: // Expand
   419 		case 15: // Expand
   401 			_expanded ^= 1;
   420 			_expanded ^= 1;
   402 			SetWndSize(wnd, _expanded);
   421 			SetWndSize(wnd, _expanded);
   421 
   440 
   422 static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep)
   441 static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep)
   423 {
   442 {
   424 	extern const char _openttd_revision[];
   443 	extern const char _openttd_revision[];
   425 	char *output;
   444 	char *output;
   426 	static bool had_exception;
   445 	static bool had_exception = false;
   427 
   446 
   428 	if (had_exception) ExitProcess(0);
   447 	if (had_exception) ExitProcess(0);
   429 	had_exception = true;
   448 	had_exception = true;
   430 
   449 
   431 	_ident = GetTickCount(); // something pretty unique
   450 	_ident = GetTickCount(); // something pretty unique
   434 	_crash_msg = output = LocalAlloc(LMEM_FIXED, 8192);
   453 	_crash_msg = output = LocalAlloc(LMEM_FIXED, 8192);
   435 
   454 
   436 	{
   455 	{
   437 		SYSTEMTIME time;
   456 		SYSTEMTIME time;
   438 		GetLocalTime(&time);
   457 		GetLocalTime(&time);
   439 		output += snprintf(output, 8192,
   458 		output += sprintf(output,
   440 			"*** OpenTTD Crash Report ***\r\n"
   459 			"*** OpenTTD Crash Report ***\r\n"
   441 			"Date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n"
   460 			"Date: %d-%.2d-%.2d %.2d:%.2d:%.2d\r\n"
   442 			"Build: %s built on " __DATE__ " " __TIME__ "\r\n",
   461 			"Build: %s built on " __DATE__ " " __TIME__ "\r\n",
   443 			time.wYear,
   462 			time.wYear,
   444 			time.wMonth,
   463 			time.wMonth,
   557 			" Windows version %d.%d %d %s\r\n",
   576 			" Windows version %d.%d %d %s\r\n",
   558 			os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber, os.szCSDVersion);
   577 			os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber, os.szCSDVersion);
   559 	}
   578 	}
   560 
   579 
   561 	{
   580 	{
   562 		HANDLE file = CreateFile("crash.log", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
   581 		HANDLE file = CreateFile(_T("crash.log"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
   563 		DWORD num_written;
   582 		DWORD num_written;
   564 		if (file != INVALID_HANDLE_VALUE) {
   583 		if (file != INVALID_HANDLE_VALUE) {
   565 			WriteFile(file, _crash_msg, output - _crash_msg, &num_written, NULL);
   584 			WriteFile(file, _crash_msg, output - _crash_msg, &num_written, NULL);
   566 			CloseHandle(file);
   585 			CloseHandle(file);
   567 		}
   586 		}
   701 	return file[3] == '\0'; // C:\...
   720 	return file[3] == '\0'; // C:\...
   702 }
   721 }
   703 
   722 
   704 void FiosGetDrives(void)
   723 void FiosGetDrives(void)
   705 {
   724 {
   706 	char drives[256];
   725 	TCHAR drives[256];
   707 	const char *s;
   726 	const TCHAR *s;
   708 
   727 
   709 	GetLogicalDriveStrings(sizeof(drives), drives);
   728 	GetLogicalDriveStrings(sizeof(drives), drives);
   710 	for (s = drives; *s != '\0';) {
   729 	for (s = drives; *s != '\0';) {
   711 		FiosItem *fios = FiosAlloc();
   730 		FiosItem *fios = FiosAlloc();
   712 		fios->type = FIOS_TYPE_DRIVE;
   731 		fios->type = FIOS_TYPE_DRIVE;
   713 		fios->mtime = 0;
   732 		fios->mtime = 0;
   714 		snprintf(fios->name,  lengthof(fios->name),  "%c:", s[0]);
   733 		snprintf(fios->name, lengthof(fios->name),  "%c:", s[0] & 0xFF);
   715 		ttd_strlcpy(fios->title, fios->name, lengthof(fios->title));
   734 		ttd_strlcpy(fios->title, fios->name, lengthof(fios->title));
   716 		while (*s++ != '\0');
   735 		while (*s++ != '\0');
   717 	}
   736 	}
   718 }
   737 }
   719 
   738 
   738 
   757 
   739 bool FiosGetDiskFreeSpace(const char *path, uint32 *tot)
   758 bool FiosGetDiskFreeSpace(const char *path, uint32 *tot)
   740 {
   759 {
   741 	UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS);  // disable 'no-disk' message box
   760 	UINT sem = SetErrorMode(SEM_FAILCRITICALERRORS);  // disable 'no-disk' message box
   742 	bool retval = false;
   761 	bool retval = false;
   743 	char root[4];
   762 	TCHAR root[4];
   744 	DWORD spc, bps, nfc, tnc;
   763 	DWORD spc, bps, nfc, tnc;
   745 
   764 
   746 	snprintf(root, lengthof(root), "%c:" PATHSEP, path[0]);
   765 	_sntprintf(root, lengthof(root), _T("%c:") _T(PATHSEP), path[0]);
   747 	if (tot != NULL && GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) {
   766 	if (tot != NULL && GetDiskFreeSpace(root, &spc, &bps, &nfc, &tnc)) {
   748 		*tot = ((spc * bps) * (uint64)nfc) >> 20;
   767 		*tot = ((spc * bps) * (uint64)nfc) >> 20;
   749 		retval = true;
   768 		retval = true;
   750 	}
   769 	}
   751 
   770 
   828 
   847 
   829 		ReleaseCapture();
   848 		ReleaseCapture();
   830 		_left_button_clicked =_left_button_down = false;
   849 		_left_button_clicked =_left_button_down = false;
   831 
   850 
   832 		old = MyShowCursor(true);
   851 		old = MyShowCursor(true);
   833 		if (MessageBoxA(GetActiveWindow(), str, "OpenTTD", MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL) {
   852 		if (MessageBox(GetActiveWindow(), MB_TO_WIDE(str), _T("OpenTTD"), MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL) {
   834 			CreateConsole();
   853 			CreateConsole();
   835 		}
   854 		}
   836 		MyShowCursor(old);
   855 		MyShowCursor(old);
   837 	}
   856 	}
   838 }
   857 }
   844 	#define _OUT_TO_MSGBOX       2
   863 	#define _OUT_TO_MSGBOX       2
   845 	#define _REPORT_ERRMODE      3
   864 	#define _REPORT_ERRMODE      3
   846 	int _set_error_mode(int);
   865 	int _set_error_mode(int);
   847 #endif
   866 #endif
   848 
   867 
   849 int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
   868 int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
   850 	LPTSTR lpCmdLine, int nCmdShow)
   869 	LPTSTR lpCmdLine, int nCmdShow)
   851 {
   870 {
   852 	int argc;
   871 	int argc;
   853 	char *argv[64]; // max 64 command line arguments
   872 	char *argv[64]; // max 64 command line arguments
       
   873 
       
   874 #if defined(UNICODE)
       
   875 	/* We need to backup the command line (arguments) because the pointer
       
   876 	 * of FS2OTTD() is only temporary */
       
   877 	char cmdline[MAX_PATH];
       
   878 	ttd_strlcpy(cmdline, FS2OTTD(GetCommandLine()), sizeof(cmdline));
       
   879 #else
       
   880 	char *cmdline = GetCommandLine();
       
   881 #endif
   854 
   882 
   855 #if defined(_DEBUG)
   883 #if defined(_DEBUG)
   856 	CreateConsole();
   884 	CreateConsole();
   857 #endif
   885 #endif
   858 
   886 
   861 	// setup random seed to something quite random
   889 	// setup random seed to something quite random
   862 	_random_seeds[1][0] = _random_seeds[0][0] = GetTickCount();
   890 	_random_seeds[1][0] = _random_seeds[0][0] = GetTickCount();
   863 	_random_seeds[1][1] = _random_seeds[0][1] = _random_seeds[0][0] * 0x1234567;
   891 	_random_seeds[1][1] = _random_seeds[0][1] = _random_seeds[0][0] * 0x1234567;
   864 	SeedMT(_random_seeds[0][0]);
   892 	SeedMT(_random_seeds[0][0]);
   865 
   893 
   866 	argc = ParseCommandLine(GetCommandLine(), argv, lengthof(argv));
   894 	argc = ParseCommandLine(cmdline, argv, lengthof(argv));
   867 
   895 
   868 #if defined(WIN32_EXCEPTION_TRACKER)
   896 #if defined(WIN32_EXCEPTION_TRACKER)
   869 	{
   897 	Win32InitializeExceptions();
   870 		Win32InitializeExceptions();
       
   871 	}
       
   872 #endif
   898 #endif
   873 
   899 
   874 #if defined(WIN32_EXCEPTION_TRACKER_DEBUG)
   900 #if defined(WIN32_EXCEPTION_TRACKER_DEBUG)
   875 	_try {
   901 	_try {
   876 		uint32 _stdcall ExceptionHandler(void *ep);
   902 		LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep);
   877 #endif
   903 #endif
   878 		ttd_main(argc, argv);
   904 		ttd_main(argc, argv);
   879 
   905 
   880 #if defined(WIN32_EXCEPTION_TRACKER_DEBUG)
   906 #if defined(WIN32_EXCEPTION_TRACKER_DEBUG)
   881 	} _except (ExceptionHandler(_exception_info())) {}
   907 	} _except (ExceptionHandler(_exception_info())) {}