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; |
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 |
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); |