--- /dev/null
+#include <windows.h>
+#include <windowsx.h>
+#include <wingdi.h>
+#include <commctrl.h>
+#include <wininet.h>
+#include <time.h>
+#include <processthreadsapi.h>
+
+#include "vg_opt.h"
+#include "vg_platform.h"
+#include "vg_string.h"
+#include "vg_io.h"
+
+#include "vg_tool.c"
+
+char *report_text = NULL;
+u32 report_length = 0;
+
+HWND window = NULL,
+ send_button = NULL,
+ select_button = NULL,
+ close_button = NULL,
+ textbox = NULL;
+
+int sent_report = 0;
+
+WNDPROC defWndProc = NULL;
+
+LRESULT OnWindowClose( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ PostQuitMessage(0);
+ return CallWindowProc(defWndProc, hwnd, message, wParam, lParam);
+}
+
+#define HTTPBOUND "99667vg.mtzero.boundary88337"
+
+void send_report(void)
+{
+ HINTERNET hSession = InternetOpen(
+ "Mozilla/5.0", // User-Agent
+ INTERNET_OPEN_TYPE_PRECONFIG,
+ NULL,
+ NULL,
+ 0);
+
+ if( hSession == NULL )
+ {
+ MessageBox( window, "Call failed.",
+ "InternetOpen (wininet)", MB_OK|MB_ICONERROR);
+ goto e4;
+ }
+
+ HINTERNET hConnect = InternetConnect(
+ hSession,
+ "skaterift.com", // HOST
+ INTERNET_DEFAULT_HTTPS_PORT,
+ "",
+ "",
+ INTERNET_SERVICE_HTTP,
+ 0,
+ 0);
+
+ if( hConnect == NULL )
+ {
+ MessageBox( window, "Call failed.",
+ "InternetConnect (wininet)", MB_OK|MB_ICONERROR);
+ goto e3;
+ }
+
+ HINTERNET hHttpFile = HttpOpenRequest(
+ hConnect,
+ "POST", // METHOD
+ "/vgreport/index.php", // URI
+ NULL,
+ NULL,
+ NULL,
+ INTERNET_FLAG_SECURE|INTERNET_FLAG_RELOAD,
+ 0);
+ if( hHttpFile == NULL )
+ {
+ MessageBox( window, "Call failed.",
+ "HttpOpenRequest (wininet)", MB_OK|MB_ICONERROR);
+ goto e2;
+ }
+
+ HttpAddRequestHeaders( hHttpFile, "Content-Type: multipart/form-data; boundary=" HTTPBOUND "\r\nConnection: close\r\n",
+ -1, HTTP_ADDREQ_FLAG_ADD );
+ vg_str content;
+ vg_strnull( &content, NULL, 0 );
+ vg_strcat( &content, "--" HTTPBOUND "\r\nContent-Disposition: form-data; name=\"uploaded_file\"\r\n" );
+ vg_strcat( &content, "Content-Type: text/plain\r\n\r\n" );
+ vg_strcat( &content, report_text );
+ vg_strcat( &content, "\r\n\r\n--" HTTPBOUND "--\r\n" );
+
+ while( !HttpSendRequest(hHttpFile, NULL, 0, content.buffer, content.i) )
+ {
+ DWORD option = InternetErrorDlg(
+ window,
+ hHttpFile,
+ ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED,
+ FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
+ FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
+ FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
+ NULL);
+
+ if( option == ERROR_CANCELLED )
+ goto e1;
+ }
+
+ {
+ DWORD dwFileSize = 4096;
+ char* buffer[dwFileSize + 1];
+
+ while(1)
+ {
+ DWORD dwBytesRead;
+ BOOL bRead;
+
+ bRead = InternetReadFile(
+ hHttpFile,
+ buffer,
+ dwFileSize + 1,
+ &dwBytesRead);
+
+ if( dwBytesRead == 0 )
+ break;
+
+ if( !bRead )
+ {
+ MessageBox( window, "Report may or may not have been sent",
+ "Error reading response", MB_OK|MB_ICONERROR);
+ goto e1;
+ }
+ else
+ buffer[dwBytesRead] = 0;
+ }
+
+ sent_report = 1;
+ MessageBox( window, "Thank you, a developer will take a look and try to fix this bug.", "Report Sent!", MB_OK );
+ }
+
+e1:InternetCloseHandle(hHttpFile);
+e2:InternetCloseHandle(hConnect);
+e3:InternetCloseHandle(hSession);
+e4:return;
+}
+
+LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
+{
+ if (message == WM_CLOSE && hwnd == window) return OnWindowClose(hwnd, message, wParam, lParam);
+ if( message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && (HWND)lParam == close_button )
+ {
+ exit(0);
+ }
+ if( message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && (HWND)lParam == send_button )
+ {
+ if( sent_report )
+ {
+ if( MessageBox( window,
+ "The more times you send it the faster the bug gets fixed!",
+ "Mail this report?", MB_YESNO|MB_APPLMODAL ) == IDYES )
+ {
+ MessageBox( window, "Thank you, a developer will take a look and try to fix this bug.", "Report Sent!", MB_OK );
+ }
+ }
+ else
+ {
+ if( MessageBox( window,
+ "Clicking yes confirms sending this error log straight to the developers (which we would much appreciate)",
+ "Mail this report?", MB_YESNO|MB_APPLMODAL ) == IDYES )
+ {
+ send_report();
+ }
+ }
+ }
+ if( message == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && (HWND)lParam == select_button )
+ {
+ SetFocus( textbox );
+ Edit_SetSel( textbox, 0, 100000 );
+ }
+ return CallWindowProc(defWndProc, hwnd, message, wParam, lParam);
+}
+
+
+int main( int argc, const char *argv[] )
+{
+ if( argc < 3 )
+ {
+ MessageBox( NULL, "Required parameters: PID and Crash path.",
+ "Usage error", MB_OK|MB_ICONERROR );
+ return -1;
+
+ }
+ vg_log_init();
+
+ DWORD pid = (DWORD)strtoul( argv[1], NULL, 16 );
+ HANDLE hGameProcess = OpenProcess( PROCESS_QUERY_INFORMATION, 0, pid );
+ if( hGameProcess == NULL )
+ goto we_crashed;
+
+ while(1)
+ {
+ sleep(2);
+ DWORD exit_code;
+ if( GetExitCodeProcess( hGameProcess, &exit_code ) )
+ {
+ if( exit_code == STATUS_PENDING )
+ continue;
+ else if( exit_code == 0 )
+ return 0;
+ else
+ goto we_crashed;
+ }
+ }
+
+we_crashed:
+ report_text = vg_file_read( NULL, argv[2], &report_length, 1 );
+ if( !report_text )
+ {
+ MessageBox( NULL, "Can't even open the crash text file. Something has gone seriously wrong! Contact a developer.",
+ "Total epic failure!", MB_OK|MB_ICONERROR );
+ return -1;
+ }
+
+ int x = 10;
+ int y = 10;
+ int w = 800;
+ int h = 600;
+ int sh = 32;
+ int p = 8;
+
+ RECT rect;
+ rect.left = x;
+ rect.top = y;
+ rect.right = x + w;
+ rect.bottom = y + h;
+
+ UINT style = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
+ AdjustWindowRectEx( &rect, style, 0, 0 );
+
+ window = CreateWindowEx( 0, WC_DIALOG, "VG Error report", style,
+ rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top,
+ NULL, NULL, NULL, NULL );
+
+ CreateWindowEx( 0, WC_STATIC, "Very sorry, VG Game engine has crashed. This is probably the fault of a developer!\n"
+ "\n"
+ "Here is some information about the crash. Optionally you can submit "
+ "this log anonymously, straight to Mt.Zero Software."
+ " This will help get the bug fixed for future players!",
+ WS_CHILD | WS_VISIBLE, p, p, w-p*2, 80, window, NULL, NULL, NULL );
+
+ textbox = CreateWindowEx( WS_EX_CLIENTEDGE, WC_EDIT, "textBox",
+ WS_CHILD | WS_VSCROLL | WS_VISIBLE | ES_MULTILINE | ES_WANTRETURN | ES_READONLY,
+ p, p+80+p, 800-p*2, 600-(p*2+sh+80+p), window, NULL, NULL, NULL );
+
+ send_button = CreateWindowEx( 0, WC_BUTTON, "Send to Mt.Zero developers",
+ WS_CHILD | WS_VISIBLE,
+ 800-(200+p), 600-(p*2+sh)+p, 200, sh, window, NULL, NULL, NULL );
+ close_button = CreateWindowEx( 0, WC_BUTTON, "Close",
+ WS_CHILD | WS_VISIBLE,
+ 800-(200+p)-(100+p), 600-(p*2+sh)+p, 100, sh, window, NULL, NULL, NULL );
+ select_button = CreateWindowEx( 0, WC_BUTTON, "Select all",
+ WS_CHILD | WS_VISIBLE,
+ p, 600-(p*2+sh)+p, 100, sh, window, NULL, NULL, NULL );
+
+ Edit_SetText( textbox, report_text );
+ Edit_SetSel( textbox, 0, 0 );
+
+ HFONT font = CreateFont( 16, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, "Consolas");
+ SendMessage( textbox, WM_SETFONT, (WPARAM)font, 1 );
+
+ defWndProc = (WNDPROC)SetWindowLongPtr(window, GWLP_WNDPROC, (LONG_PTR)WndProc);
+
+ ShowWindow(window, SW_SHOW);
+
+ MSG message = { 0 };
+ while( GetMessage(&message, NULL, 0, 0) )
+ DispatchMessage(&message);
+ return (int)message.wParam;
+}
vg_magi_restore();
}
+#ifdef _WIN32
+#include <windows.h>
+#include <processthreadsapi.h>
+#endif
static int cmd_vg_settings_toggle( int argc, const char *argv[] );
void vg_init( int argc, const char *argv[], const char *window_name )
{
+ vg.window_name = window_name;
vg.thread_purpose = SDL_TLSCreate();
VG_ASSERT( vg.thread_purpose );
SDL_TLSSet( vg.thread_purpose, &_thread_purpose_main, NULL );
-
vg_log_init();
- vg.sig_engine = _vg_tower_create_signal( "Engine" );
- vg.sig_client = _vg_tower_create_signal( "Client" );
- _vg_tower_register_trigger( _vg_tower_mask( vg.sig_client ), vg_on_client_ready );
-
- if( !vg_init_async_queue( &vg.main_tasks ) )
- return;
- if( !vg_init_async_queue( &vg.loader_tasks ) )
- return;
-
- vg_rand_seed( &vg.rand, 461 );
-
/* launch options */
_vg_opt_init( argc, argv );
const char *arg;
vg_error( "Could not open '%s' for logging.\n", arg );
}
- vg.window_name = window_name;
+#ifdef _WIN32
+ DWORD pid = GetCurrentProcessId();
+
+ char report_args_buf[ 512 ];
+ vg_str report_args;
+ vg_strnull( &report_args, report_args_buf, sizeof(report_args_buf) );
+ vg_strcat( &report_args, "vgcrashreport.exe " );
+ vg_strcatu64( &report_args, pid, 16 );
+ vg_strcat( &report_args, " " );
+ vg_strcat( &report_args, vg_log.crash_path );
+
+ STARTUPINFO si={0};
+ PROCESS_INFORMATION pi={0};
+ si.cb = sizeof(si);
+
+ if( CreateProcess( NULL, report_args_buf, NULL, NULL, 0, BELOW_NORMAL_PRIORITY_CLASS,
+ NULL, NULL, &si, &pi ) == 0 )
+ {
+ vg_error( "Could not start crash reporter. Reason: %d\n", GetLastError() );
+ }
+ else
+ vg_success( "Crash watcher started!\n" );
+
+#endif
+ vg.sig_engine = _vg_tower_create_signal( "Engine" );
+ vg.sig_client = _vg_tower_create_signal( "Client" );
+ _vg_tower_register_trigger( _vg_tower_mask( vg.sig_client ), vg_on_client_ready );
+
+ if( !vg_init_async_queue( &vg.main_tasks ) )
+ return;
+ if( !vg_init_async_queue( &vg.loader_tasks ) )
+ return;
+
+ vg_rand_seed( &vg.rand, 461 );
}
static int cmd_die( int argc, const char *argv[] )