From dbaa34c5dbc9ff615c6a57056cd2663ede8caede Mon Sep 17 00:00:00 2001 From: Peter Foley Date: Tue, 22 Jan 2013 16:07:24 -0500 Subject: convert crashrep to gbuild and add to tail_build Change-Id: I90cf6c2c5fb806855b7e4fec18c890f7bd2ff6b5 --- crashrep/source/win32/base64.cpp | 75 - crashrep/source/win32/base64.cxx | 75 + crashrep/source/win32/crashrep.rc | 12 + crashrep/source/win32/crashrep.ulf | 221 +++ crashrep/source/win32/makefile.mk | 79 - crashrep/source/win32/soreport.cpp | 2875 ------------------------------------ crashrep/source/win32/soreport.cxx | 2873 +++++++++++++++++++++++++++++++++++ 7 files changed, 3181 insertions(+), 3029 deletions(-) delete mode 100644 crashrep/source/win32/base64.cpp create mode 100644 crashrep/source/win32/base64.cxx create mode 100755 crashrep/source/win32/crashrep.rc create mode 100644 crashrep/source/win32/crashrep.ulf delete mode 100644 crashrep/source/win32/makefile.mk delete mode 100644 crashrep/source/win32/soreport.cpp create mode 100644 crashrep/source/win32/soreport.cxx (limited to 'crashrep/source/win32') diff --git a/crashrep/source/win32/base64.cpp b/crashrep/source/win32/base64.cpp deleted file mode 100644 index a0b8769f6bc5..000000000000 --- a/crashrep/source/win32/base64.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include -#include -#include "base64.h" - -static const char base64_tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -extern "C" size_t base64_encode( FILE *fin, FILE *fout ) -{ - size_t nLineLength = 0; - size_t nBytesWritten = 0; - - size_t nBytes = 0; - - do - { - unsigned char in_buffer[3]; - - memset( in_buffer, 0, sizeof(in_buffer) ); - nBytes = fread( in_buffer, 1, sizeof(in_buffer), fin ); - - if ( nBytes ) - { - unsigned long value = - ((unsigned long)in_buffer[0]) << 16 | - ((unsigned long)in_buffer[1]) << 8 | - ((unsigned long)in_buffer[2]) << 0; - - unsigned char out_buffer[4]; - - memset( out_buffer, '=', sizeof(out_buffer) ); - - out_buffer[0] = base64_tab[(value >> 18) & 0x3F]; - out_buffer[1] = base64_tab[(value >> 12) & 0x3F]; - - if ( nBytes > 1 ) - { - out_buffer[2] = base64_tab[(value >> 6) & 0x3F]; - if ( nBytes > 2 ) - out_buffer[3] = base64_tab[(value >> 0) & 0x3F]; - } - - if ( nLineLength >= 76 ) - { - fputs( "\n", fout ); - nLineLength = 0; - } - - nBytesWritten += fwrite( out_buffer, 1, sizeof(out_buffer), fout ); - nLineLength += sizeof(out_buffer); - } - } while ( nBytes ); - - return nBytesWritten; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/crashrep/source/win32/base64.cxx b/crashrep/source/win32/base64.cxx new file mode 100644 index 000000000000..a0b8769f6bc5 --- /dev/null +++ b/crashrep/source/win32/base64.cxx @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include +#include +#include "base64.h" + +static const char base64_tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +extern "C" size_t base64_encode( FILE *fin, FILE *fout ) +{ + size_t nLineLength = 0; + size_t nBytesWritten = 0; + + size_t nBytes = 0; + + do + { + unsigned char in_buffer[3]; + + memset( in_buffer, 0, sizeof(in_buffer) ); + nBytes = fread( in_buffer, 1, sizeof(in_buffer), fin ); + + if ( nBytes ) + { + unsigned long value = + ((unsigned long)in_buffer[0]) << 16 | + ((unsigned long)in_buffer[1]) << 8 | + ((unsigned long)in_buffer[2]) << 0; + + unsigned char out_buffer[4]; + + memset( out_buffer, '=', sizeof(out_buffer) ); + + out_buffer[0] = base64_tab[(value >> 18) & 0x3F]; + out_buffer[1] = base64_tab[(value >> 12) & 0x3F]; + + if ( nBytes > 1 ) + { + out_buffer[2] = base64_tab[(value >> 6) & 0x3F]; + if ( nBytes > 2 ) + out_buffer[3] = base64_tab[(value >> 0) & 0x3F]; + } + + if ( nLineLength >= 76 ) + { + fputs( "\n", fout ); + nLineLength = 0; + } + + nBytesWritten += fwrite( out_buffer, 1, sizeof(out_buffer), fout ); + nLineLength += sizeof(out_buffer); + } + } while ( nBytes ); + + return nBytesWritten; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/crashrep/source/win32/crashrep.rc b/crashrep/source/win32/crashrep.rc new file mode 100755 index 000000000000..250ed92d7e85 --- /dev/null +++ b/crashrep/source/win32/crashrep.rc @@ -0,0 +1,12 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "crashrep_impl.rc" + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/crashrep/source/win32/crashrep.ulf b/crashrep/source/win32/crashrep.ulf new file mode 100644 index 000000000000..12ef7e75c246 --- /dev/null +++ b/crashrep/source/win32/crashrep.ulf @@ -0,0 +1,221 @@ + +[%WELCOME_CAPTION%] +en-US = "%PRODUCTNAME% %PRODUCTVERSION% Error Report" + + +[%WELCOME_HEADER%] +en-US = "Welcome to the %PRODUCTNAME% %PRODUCTVERSION% Error Report" + + +[%WELCOME_BODY1%] +en-US = "This error report tool gathers information about how %PRODUCTNAME% is working and sends it to The Document Foundation to help improve future versions.\n\n" + + +[%WELCOME_BODY2%] +en-US = "It's easy - just send the report without any further effort on your part by clicking 'Send' in the next dialog, or you can briefly describe how the error occurred and then click 'Send'. If you want to see the report, click the 'Show Report' button. No data will be sent if you click 'Do Not Send'.\n\n" + + +[%WELCOME_BODY3%] +en-US = "Customer Privacy\nThe information gathered is limited to data concerning the state of %PRODUCTNAME% %PRODUCTVERSION% when the error occurred. Other information about passwords or document contents is not collected.\n\nThe information will only be used to improve the quality of %PRODUCTNAME% and will not be shared with third parties.\nFor more information on The Document Foundation's privacy policy, visit\n" + + +[%PRIVACY_URL%] +en-US = "http://www.documentfoundation.org/privacy" + + +[%NEXT_BUTTON%] +en-US = "~Next >>" + + +[%CANCEL_BUTTON%] +en-US = "Cancel" + + +[%OK_BUTTON%] +en-US = "OK" + + +[%REPORT_CAPTION%] +en-US = "%PRODUCTNAME% %PRODUCTVERSION% Error Report" + + +[%REPORT_HEADER%] +en-US = "An error occurred while running %PRODUCTNAME% %PRODUCTVERSION%" + + +[%REPORT_BODY%] +en-US = "The %PRODUCTNAME% %PRODUCTVERSION% Error Report has gathered information that could help The Document Foundation improve %PRODUCTNAME%.\nIn the spaces below, you can enter a title for your crash report and describe the action you were trying to carry out when the error occurred. Then click 'Send'.\n" + + +[%ENTER_TITLE%] +en-US = "Which type of document (e.g. presentation) were you using when the error occurred?" + + +[%ALLOW_CONTACT%] +en-US = "~I allow The Document Foundation to contact me regarding this report." + + +[%ENTER_EMAIL%] +en-US = "Please enter your e-mail address." + + +[%ENTER_DESCRIPTION%] +en-US = "~How were you using %PRODUCTNAME% when the error occurred ?" + + +[%BACK_BUTTON%] +en-US = " << ~Back" + + +[%SEND_BUTTON%] +en-US = "S~end" + + +[%DONOT_SEND_BUTTON%] +en-US = "Do ~Not Send" + + +[%SHOW_REPORT_BUTTON%] +en-US = "Show ~Report..." + + +[%SAVE_REPORT_BUTTON%] +en-US = "~Save Report..." + + +[%SAVE_REPORT_TITLE%] +en-US = "Save Report to" + + +[%ERROR_MSG_SIMPLE_MAPI%] +en-US = "The error report could not be sent because the default e-mail program does not support MAPI.\n Please use a MAPI-compatible e-mail program." + + +[%ERROR_MSG_DISK_FULL%] +en-US = "The error report could not be temporarily saved and could therefore not be sent." + + + +[%ERROR_MSG_SENDMAIL%] +en-US = "The error report could not be sent because 'sendmail' could not be started.\nPlease check the 'sendmail' settings." + + +[%ERROR_MSG_PROXY%] +en-US = "The error report could not be sent. Please check the proxy settings under 'Options' in the Error Report Tool." + + +[%ERROR_MSG_NOCONNECT%] +en-US = "The error report could not be sent because there is no Internet connection. Please check your Internet settings." + + +[%OPTIONS_BUTTON%] +en-US = "~Options..." + + +[%OPTIONS_TITLE%] +en-US = "Options" + + +[%PROXY_SETTINGS_HEADER%] +en-US = "Proxy settings" + + +[%PROXY_SETTINGS_SYSTEM%] +en-US = "Use ~system settings" + + +[%PROXY_SETTINGS_DIRECT%] +en-US = "Use ~direct connection to the Internet" + + +[%PROXY_SETTINGS_MANUAL%] +en-US = "Use ~manual settings" + + +[%PROXY_SETTINGS_ADDRESS%] +en-US = "HT~TP Proxy" + + +[%PROXY_SETTINGS_PORT%] +en-US = "~Port" + + +[%PROXY_SETTINGS_DESCRIPTION%] +en-US = "The %PRODUCTNAME% Error Report tool needs to be connected to the Internet to be able to send error reports.\n\nCompanies often use proxy servers in conjunction with a firewall to protect the network.\n\nIf this applies to your situation, you have to specify the address and port for the server." + + +[%SENDING_REPORT_HEADER%] +en-US = "Sending Error Report" + + +[%SENDING_REPORT_STATUS%] +en-US = "Status: Sending error report" + + +[%SENDING_REPORT_STATUS_FINISHED%] +en-US = "Status: The error report has been sent successfully." + + +[%ERROR_MSG_NOEMAILADDRESS%] +en-US = "You have marked the option 'I allow The Document Foundation to contact me regarding this report.'\nPlease enter your e-mail address." + + +[%MSG_CMDLINE_USAGE%] +en-US = "Usage:" + + +[%MSG_PARAM_PROCESSID%] +en-US = "-p " + + +[%MSG_PARAM_PROCESSID_DESCRIPTION%] +en-US = "Assigns the %PRODUCTNAME% process ID (PID) to the Error Report Tool" + + +[%MSG_PARAM_HELP_DESCRIPTION%] +en-US = "Shows this help text.\nDetailed information can be found in the Setup Guide." + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/crashrep/source/win32/makefile.mk b/crashrep/source/win32/makefile.mk deleted file mode 100644 index 79e02b970c3a..000000000000 --- a/crashrep/source/win32/makefile.mk +++ /dev/null @@ -1,79 +0,0 @@ -# -# This file is part of the LibreOffice project. -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -# -# This file incorporates work covered by the following license notice: -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed -# with this work for additional information regarding copyright -# ownership. The ASF licenses this file to you under the Apache -# License, Version 2.0 (the "License"); you may not use this file -# except in compliance with the License. You may obtain a copy of -# the License at http://www.apache.org/licenses/LICENSE-2.0 . -# - -PRJ=..$/.. - -PRJNAME=crashrep -TARGET=soreport -LIBTARGET=NO -ENABLE_EXCEPTIONS=TRUE -TARGETTYPE=GUI - -# --- Settings ----------------------------------------------------- - -.INCLUDE : settings.mk - -# --- Resources ---------------------------------------------------- - -RCFILES=$(RES)$/$(TARGET).rc - -# --- Files -------------------------------------------------------- - -OBJFILES=\ - $(OBJ)$/soreport.obj\ - $(OBJ)$/base64.obj - -.IF "$(WITH_LANG)"!="" -ULFDIR:=$(COMMONMISC)$/crash_res -.ELSE # "$(WITH_LANG)"!="" -ULFDIR:=..$/all -.ENDIF # "$(WITH_LANG)"!="" -LNGFILES=$(ULFDIR)$/crashrep.ulf - -APP1OBJS=$(OBJFILES) - -APP1NOSAL=TRUE - -APP1TARGET=$(TARGET) -APP1RPATH=OOO - -STDLIB1=\ - $(SALLIB)\ - $(GDI32LIB)\ - $(COMCTL32LIB)\ - $(COMDLG32LIB)\ - $(ADVAPI32LIB)\ - $(WS2_32LIB)\ - $(SHELL32LIB)\ - $(DBGHELPLIB)\ - psapi.lib - -APP1NOSVRES=$(RES)$/$(TARGET).res - -# --- Targets ------------------------------------------------------ - -.INCLUDE : target.mk - -$(OBJ)$/soreport.obj: $(INCCOM)$/_version.h - -# Generate the native Windows resource file -# using lngconvex.exe - -$(RCFILES) : $(LNGFILES) makefile.mk rcfooter.txt rcheader.txt rctemplate.txt ctrylnglist.txt - $(LNGCONVEX) -ulf $(ULFDIR)$/crashrep.ulf -rc $(RES)$/$(TARGET).rc -rct rctemplate.txt -rch rcheader.txt -rcf rcfooter.txt - diff --git a/crashrep/source/win32/soreport.cpp b/crashrep/source/win32/soreport.cpp deleted file mode 100644 index 0721950393c4..000000000000 --- a/crashrep/source/win32/soreport.cpp +++ /dev/null @@ -1,2875 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#define UNICODE -#define WIN32_LEAN_AND_MEAN -#if defined _MSC_VER -#pragma warning(push, 1) -#pragma warning(disable:4917) -#endif -#include -#include - -#include -#include -#include -#include - -#include -#include - -#define _UNICODE -#include - -#define _RICHEDIT_VER 0x0200 -#include - -#if defined _MSC_VER -#pragma warning(pop) -#endif - -#if _RICHEDIT_VER >= 0x0200 -#define RICHEDIT TEXT("riched20.dll") -#else -#define RICHEDIT TEXT("riched32.dll") -#endif - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include <_version.h> - -#include "resource.h" -#include "base64.h" - -#define FORMATBUFSIZE (8*1024) -#define MAX_TEXT_BUFFER (32*1024-1) -#define MAX_HOSTNAME (1024) - -#ifdef __MINGW32__ -#include -#else -#include -#endif - -#ifdef _UNICODE -#define tstring wstring -#else -#define tstring string -#endif - -using namespace ::std; - - -wstring g_wstrProductKey; -string g_strDefaultLanguage; -FILE *g_fpStackFile = NULL; -FILE *g_fpChecksumFile = NULL; -DWORD g_dwExceptionCode = 0; - -CHAR g_szReportServerA[MAX_HOSTNAME] = ""; -USHORT g_uReportPort = 80; - -TCHAR g_szBuildId[256] = TEXT(""); - -TCHAR g_szDumpFileName[MAX_PATH] = TEXT(""); - -CHAR g_szDumpFileNameA[MAX_PATH] = ""; -CHAR g_szCommentFileNameA[MAX_PATH] = ""; -CHAR g_szReportFileNameA[MAX_PATH] = ""; - - -bool g_bNoUserInterface = false; -bool g_bSendReport = false; -bool g_bLoadReport = false; - -#define REPORT_SERVER g_szReportServerA -#define REPORT_PORT g_uReportPort - - -//*************************************************************************** -// tmpfile from msvcrt creates the temporary file in the root of the current -// volume and can fail. - -static FILE *_xfopen( const _TCHAR *file, const _TCHAR *mode ) -{ - return _tfopen( file, mode ); -} - - -static FILE *_tmpfile(void) -{ - FILE *fp = NULL; - - TCHAR szTempPath[MAX_PATH]; - - if ( GetTempPath( SAL_N_ELEMENTS(szTempPath), szTempPath ) ) - { - TCHAR szFileName[MAX_PATH]; - - if ( GetTempFileName( szTempPath, TEXT("CRT"), 0, szFileName ) ) - { - HANDLE hFile = CreateFile( - szFileName, - GENERIC_READ | GENERIC_WRITE, - 0, NULL, - OPEN_EXISTING, - FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_NORMAL, - NULL ); - - if ( IsValidHandle( hFile ) ) - { - int fd = _open_osfhandle( (int)hFile, 0 ); - - fp = _fdopen( fd, "w+b" ); - } - } - } - - return fp; -} -//*************************************************************************** - -static BOOL GetCrashDataPath( LPTSTR szBuffer ) -{ - ::rtl::OUString ustrValue(RTL_CONSTASCII_USTRINGPARAM("${$BRAND_BASE_DIR/program/bootstrap.ini:UserInstallation}")); - ::rtl::Bootstrap::expandMacros( ustrValue ); - - if ( ustrValue.getLength() ) - { - ustrValue += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/user/crashdata")); - - ::osl::FileBase::RC result = ::osl::Directory::createPath( ustrValue ); - - if ( ::osl::FileBase::E_None == result || ::osl::FileBase::E_EXIST == result ) - { - ::rtl::OUString ustrPath; - - result = ::osl::FileBase::getSystemPathFromFileURL( ustrValue, ustrPath ); - if ( ::osl::FileBase::E_None == result ) - { - _tcsncpy( szBuffer, reinterpret_cast(ustrPath.getStr()), MAX_PATH ); - return TRUE; - } - } - } - - return FALSE; -} - - -static FILE *_open_reportfile( LPCTSTR lpExt, LPCTSTR lpMode ) -{ - FILE *fp = NULL; - TCHAR szAppDataPath[MAX_PATH] = _T(""); - - if ( GetCrashDataPath( szAppDataPath ) ) - { - _tcscat( szAppDataPath, _T("\\crashdat") ); - _tcscat( szAppDataPath, lpExt ); - - fp = _xfopen( szAppDataPath, lpMode ); - } - - return fp; -} - -//*************************************************************************** - -struct CrashReportParams -{ - BOOL fAllowContact; - tstring sEmail; - tstring sTitle; - tstring sComment; - ULONG uInternetConnection; - tstring sProxyServer; - tstring sProxyPort; - - CrashReportParams(); - - void WriteToRegistry(); - void ReadFromRegistry(); - void ReadFromEnvironment(); -}; - -bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams ); -BOOL WriteCommentFile( LPCTSTR lpComment ); - -//*************************************************************************** - -LONG RegReadValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPVOID lpData, DWORD cbData ) -{ - HKEY hKey = NULL; - LONG lResult; - - lResult = RegOpenKeyEx( hBaseKey, lpSubKey, 0, KEY_QUERY_VALUE, &hKey ); - - if ( ERROR_SUCCESS == lResult ) - { - lResult = RegQueryValueEx( hKey, lpValueName, NULL, NULL, (LPBYTE)lpData, &cbData ); - RegCloseKey( hKey ); - } - - return lResult; -} - -//*************************************************************************** - -LONG RegWriteValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData ) -{ - HKEY hKey = NULL; - LONG lResult; - - lResult = RegCreateKeyEx( hBaseKey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL ); - - if ( ERROR_SUCCESS == lResult ) - { - lResult = RegSetValueEx( hKey, lpValueName, NULL, dwType, (CONST BYTE *)lpData, cbData ); - RegCloseKey( hKey ); - } - - return lResult; -} - -//*************************************************************************** - -CrashReportParams::CrashReportParams() -{ - fAllowContact = FALSE; - sTitle = TEXT(""); - sComment = TEXT(""); - sEmail = TEXT(""); - uInternetConnection = 0; - sProxyServer = TEXT(""); - sProxyPort = TEXT(""); -} - -//*************************************************************************** - -void CrashReportParams::ReadFromRegistry() -{ - TCHAR szBuffer[2048]; - - if ( ERROR_SUCCESS == RegReadValue( - HKEY_CURRENT_USER, - TEXT("SOFTWARE\\LibreOffice\\CrashReport"), - TEXT("HTTPProxyServer"), - szBuffer, - sizeof(szBuffer) ) ) - sProxyServer = szBuffer; - - DWORD dwProxyPort; - - if ( ERROR_SUCCESS == RegReadValue( - HKEY_CURRENT_USER, - TEXT("SOFTWARE\\LibreOffice\\CrashReport"), - TEXT("HTTPProxyPort"), - &dwProxyPort, - sizeof(dwProxyPort) ) ) - { - _stprintf( szBuffer, TEXT("%d"), dwProxyPort ); - sProxyPort = szBuffer; - } - - if ( ERROR_SUCCESS == RegReadValue( - HKEY_CURRENT_USER, - TEXT("SOFTWARE\\LibreOffice\\CrashReport"), - TEXT("ReturnAddress"), - szBuffer, - sizeof(szBuffer) ) ) - sEmail = szBuffer; - - RegReadValue( - HKEY_CURRENT_USER, - TEXT("SOFTWARE\\LibreOffice\\CrashReport"), - TEXT("AllowContact"), - &fAllowContact, - sizeof(fAllowContact) ); - - RegReadValue( - HKEY_CURRENT_USER, - TEXT("SOFTWARE\\LibreOffice\\CrashReport"), - TEXT("HTTPConnection"), - &uInternetConnection, - sizeof(uInternetConnection) ); -} - -//*************************************************************************** - -void CrashReportParams::WriteToRegistry() -{ - RegWriteValue( - HKEY_CURRENT_USER, - TEXT("SOFTWARE\\LibreOffice\\CrashReport"), - TEXT("HTTPProxyServer"), REG_SZ, - sProxyServer.c_str(), - sizeof(TCHAR) * (sProxyServer.length() + 1) ); - - LPTSTR endptr = NULL; - DWORD dwProxyPort = _tcstoul( sProxyPort.c_str(), &endptr, 10 ); - - RegWriteValue( - HKEY_CURRENT_USER, - TEXT("SOFTWARE\\LibreOffice\\CrashReport"), - TEXT("HTTPProxyPort"), REG_DWORD, - &dwProxyPort, - sizeof(DWORD) ); - - RegWriteValue( - HKEY_CURRENT_USER, - TEXT("SOFTWARE\\LibreOffice\\CrashReport"), - TEXT("AllowContact"), REG_DWORD, - &fAllowContact, - sizeof(DWORD) ); - - - RegWriteValue( - HKEY_CURRENT_USER, - TEXT("SOFTWARE\\LibreOffice\\CrashReport"), - TEXT("HTTPConnection"), REG_DWORD, - &uInternetConnection, - sizeof(DWORD) ); - - RegWriteValue( - HKEY_CURRENT_USER, - TEXT("SOFTWARE\\LibreOffice\\CrashReport"), - TEXT("ReturnAddress"), REG_SZ, - sEmail.c_str(), - sizeof(TCHAR) * (sEmail.length() + 1) ); -} - -//*************************************************************************** - -void CrashReportParams::ReadFromEnvironment() -{ - TCHAR szBuffer[2048]; - - DWORD dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYSERVER"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - - if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) - sProxyServer = szBuffer; - - dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYPORT"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - - if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) - sProxyPort = szBuffer; - - dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_RETURNADDRESS"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - - if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) - { - sEmail = szBuffer; - // fAllowContact = TRUE; - } - - dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPCONNECTIONTYPE"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - - if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) - { - if ( 0 == _tcsicmp( szBuffer, _T("DIRECT") ) ) - uInternetConnection = 1; - else if ( 0 == _tcsicmp( szBuffer, _T("MANUALPROXY") ) ) - uInternetConnection = 2; - else if ( 0 == _tcsicmp( szBuffer, _T("SYSTEMDEFAULT") ) ) - uInternetConnection = 0; - } - - dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_SUBJECT"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - - if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) - sTitle = szBuffer; - - - dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_BODYFILE"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - - if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) - { - FILE *fp = _xfopen( szBuffer, _T("rb") ); - - if ( fp ) - { - CHAR aUTF8Buffer[256]; - size_t nBytesRead; - - sComment = TEXT(""); - - while ( 0 != (nBytesRead = fread( aUTF8Buffer, sizeof(aUTF8Buffer[0]), SAL_N_ELEMENTS(aUTF8Buffer), fp )) ) - { - TCHAR aBuffer[256+1]; - - DWORD dwCharacters = MultiByteToWideChar( CP_UTF8, 0, aUTF8Buffer, nBytesRead, aBuffer, SAL_N_ELEMENTS(aBuffer) - 1 ); - aBuffer[dwCharacters] = 0; - sComment += aBuffer; - } - - fclose( fp ); - } - } -} - -//*************************************************************************** - -typedef BOOL (WINAPI *MiniDumpWriteDump_PROC)( - IN HANDLE hProcess, - IN DWORD ProcessId, - IN HANDLE hFile, - IN MINIDUMP_TYPE DumpType, - IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL - IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL - IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL - ); - -//*************************************************************************** - -static BOOL WINAPI InitRichEdit() -{ - return (NULL != LoadLibrary( RICHEDIT )); -} - -//*************************************************************************** - -static BOOL WINAPI DeinitRichEdit() -{ - return FreeLibrary( GetModuleHandle( RICHEDIT ) ); -} - -//*************************************************************************** - -static string trim_string( const string& rString ) -{ - string temp = rString; - - while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' ) - temp.erase( 0, 1 ); - - string::size_type len = temp.length(); - - while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' ) - { - temp.erase( len - 1, 1 ); - len = temp.length(); - } - - return temp; -} - -//*************************************************************************** - -static int LoadAndFormatString( HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax ) -{ - TCHAR szBuffer[FORMATBUFSIZE]; - TCHAR szBuffer2[FORMATBUFSIZE]; - - LoadString( hInstance, uID, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - - LPCTSTR src; - LPTSTR dest; - for ( dest = szBuffer2, src = szBuffer; *src; src++, dest++ ) - { - switch ( *src ) - { - case '~': - *dest = '&'; - break; - case '\\': - switch ( *(++src) ) - { - case 'n': - *dest = '\n'; - break; - case 'r': - *dest = '\r'; - break; - default: - *dest = *src; - break; - } - break; - default: - *dest = *src; - break; - } - } - *dest = *src; - return ExpandEnvironmentStrings( szBuffer2, lpBuffer, nBufferMax ); -} - - -//*************************************************************************** - -static string wstring2utf8( const wstring &rString ) -{ - int nBufSize = WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, NULL, 0, NULL, FALSE ); - - LPSTR pBuffer = (LPSTR)alloca( nBufSize ); - - WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, pBuffer, nBufSize, NULL, FALSE ); - - return string( pBuffer ); -} - -//*************************************************************************** - -static string xml_encode( const string &rString ) -{ - string temp = rString; - string::size_type pos = 0; - - // First replace all occurrences of '&' because it may occur in further - // encoded chardters too - - for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 ) - temp.replace( pos, 1, "&" ); - - for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 ) - temp.replace( pos, 1, "<" ); - - for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 ) - temp.replace( pos, 1, ">" ); - - return temp; -} - -//*************************************************************************** - -static size_t fcopy( FILE *fpin, FILE *fpout ) -{ - char buffer[1024]; - size_t nBytesWritten = 0; - - if ( fpin && fpout ) - { - size_t nBytes; - while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) ) - { - nBytesWritten += fwrite( buffer, 1, nBytes, fpout ); - } - } - - return nBytesWritten; -} - -//*************************************************************************** - -static string GetModuleDirectory( HMODULE hModule ) -{ - TCHAR szModuleName[MAX_PATH] = TEXT(""); - TCHAR szDrive[_MAX_DRIVE]; - TCHAR szDir[_MAX_DIR]; - TCHAR szFName[_MAX_FNAME]; - TCHAR szExt[_MAX_EXT]; - - if ( GetModuleFileName( hModule, szModuleName, MAX_PATH ) ) - { - _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt ); - _tmakepath( szModuleName, szDrive, szDir, _T(""), _T("") ); - } - - CHAR szModuleNameUTF8[MAX_PATH] = ""; - - WideCharToMultiByte( CP_UTF8, 0, szModuleName, -1, szModuleNameUTF8, SAL_N_ELEMENTS(szModuleNameUTF8), NULL, NULL ); - return string( szModuleNameUTF8 ); -} - -//*************************************************************************** - -string GetFileDirectory( const string& rFilePath ) -{ - string aDir = rFilePath; - size_t pos = aDir.rfind( '\\' ); - - if ( string::npos != pos ) - aDir.erase( pos + 1 ); - else - aDir = ""; - - return aDir; -} - -//*************************************************************************** - -string GetFileName( const string& rFilePath ) -{ - string aName = rFilePath; - size_t pos = aName.rfind( '\\' ); - - if ( string::npos != pos ) - return aName.substr( pos + 1 ); - else - return aName; -} - -//*************************************************************************** - -BOOL WriteReportFile( CrashReportParams *pParams ) -{ - BOOL fSuccess = FALSE; - TCHAR szTempPath[MAX_PATH]; - - if ( GetTempPath( SAL_N_ELEMENTS(szTempPath), szTempPath ) ) - { - TCHAR szFileName[MAX_PATH]; - - if ( GetTempFileName( szTempPath, TEXT("RPM"), 0, szFileName ) ) - { - HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); - - if ( hFile ) - { - int fd = _open_osfhandle( (LONG)hFile, _O_TEXT ); - FILE *fp = _fdopen( fd, "w+t" ); - CHAR szTitle[1024] = ""; - CHAR szBuildId[1024] = ""; - CHAR szEmail[1024] = ""; - const char *pszUserType = getenv( "STAROFFICE_USERTYPE" ); - - WideCharToMultiByte( CP_UTF8, 0, pParams->sTitle.c_str(), -1, szTitle, sizeof(szTitle), NULL, NULL ); - WideCharToMultiByte( CP_UTF8, 0, g_szBuildId, -1, szBuildId, sizeof(szBuildId), NULL, NULL ); - WideCharToMultiByte( CP_UTF8, 0, pParams->sEmail.c_str(), -1, szEmail, sizeof(szEmail), NULL, NULL ); - - fprintf( fp, - "\n" - "\n" - "\n" - "\n", - pszUserType ? pszUserType : "", - pParams->fAllowContact ? "true" : "false", - pParams->fAllowContact ? xml_encode(szEmail).c_str() : "" - ); - - fprintf( fp, - "%s\n", - xml_encode(szTitle).c_str() ); - - fprintf( fp, - "\n" - "\n" - "\n" - - "\n", - szBuildId, - _INPATH, - xml_encode(g_strDefaultLanguage).c_str(), - xml_encode(GetModuleDirectory( NULL )).c_str(), - g_dwExceptionCode, - xml_encode(wstring2utf8(g_wstrProductKey)).c_str() - ); - - OSVERSIONINFO VersionInfo; - - ZeroMemory( &VersionInfo, sizeof(VersionInfo) ); - VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo ); - - GetVersionEx( &VersionInfo ); - - fprintf( fp, - "\n" - "\n" - , - VER_PLATFORM_WIN32_NT == VersionInfo.dwPlatformId ? "Windows NT" : "Windows", - VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion, - VersionInfo.dwBuildNumber, - GetUserDefaultLangID() - - ); - fprintf( fp, "\n" ); - fprintf( fp, "\n" ); - - fseek( g_fpStackFile, 0, SEEK_SET ); - fcopy( g_fpStackFile, fp ); - - fseek( g_fpChecksumFile, 0, SEEK_SET ); - fcopy( g_fpChecksumFile, fp ); - - fprintf( fp, "\n" ); - - fclose( fp ); - - fSuccess = TRUE; - - WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szReportFileNameA, MAX_PATH, NULL, NULL ); - } - - if ( !fSuccess ) - DeleteFile( szFileName ); - } - } - - return fSuccess; -} - -//*************************************************************************** - -static BOOL SaveDumpFile( HWND hwndOwner ) -{ - OPENFILENAME ofn; - TCHAR szFileName[MAX_PATH] = TEXT(""); - - ZeroMemory( &ofn, sizeof(ofn) ); - ofn.lStructSize = sizeof(ofn); - - ofn.hwndOwner = hwndOwner; - ofn.lpstrFilter = TEXT("*.dmp\0*.dmp\0*.*\0*.*\0"); - ofn.lpstrFile = szFileName; - ofn.nMaxFile = MAX_PATH; - ofn.Flags = OFN_ENABLESIZING | OFN_LONGNAMES | OFN_OVERWRITEPROMPT; - ofn.lpstrDefExt = TEXT("dmp"); - - if ( GetSaveFileName( &ofn ) ) - { - return CopyFile( g_szDumpFileName, szFileName, FALSE ); - } - return FALSE; -} - -//*************************************************************************** - -static BOOL ScreenToClientRect( HWND hwnd, LPRECT lprc ) -{ - return ScreenToClient( hwnd, (LPPOINT)&lprc->left ) && ScreenToClient( hwnd, (LPPOINT)&lprc->right ); -} - -static BOOL SetWindowRect( HWND hwnd, const RECT *lprc, BOOL fRepaint ) -{ - return MoveWindow( hwnd, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, fRepaint ); -} - -#define GM_LOX 0x01 -#define GM_HIX 0x02 -#define GM_LOY 0x04 -#define GM_HIY 0x08 - -static BOOL SetGrowMode( HWND hwnd, DWORD dwGrowMode ) -{ - return SetProp( hwnd, TEXT("GrowMode"), (HANDLE)dwGrowMode ); -} - -static DWORD GetGrowMode( HWND hwnd ) -{ - return (DWORD)GetProp( hwnd, TEXT("GrowMode") ); -} - -static BOOL GrowWindow( HWND hwnd, LONG dxClient, LONG dyClient, BOOL fRepaint ) -{ - DWORD dwGrowMode = GetGrowMode( hwnd ); - RECT rc; - - GetWindowRect( hwnd, &rc ); - - if ( dwGrowMode & GM_LOX ) - rc.left += dxClient; - if ( dwGrowMode & GM_HIX ) - rc.right += dxClient; - if ( dwGrowMode & GM_LOY ) - rc.top += dyClient; - if ( dwGrowMode & GM_HIY ) - rc.bottom += dyClient; - - ScreenToClientRect( GetParent( hwnd ), &rc ); - SetWindowRect( hwnd, &rc, fRepaint ); - - return TRUE; -} - -BOOL CALLBACK GrowChildWindows( - HWND hwnd, // handle to child window - LPARAM lParam // application-defined value -) -{ - LONG cx = (SHORT)LOWORD( lParam ); - LONG cy = (SHORT)HIWORD( lParam ); - - GrowWindow( hwnd, cx, cy, TRUE ); - - return TRUE; -} - -BOOL CALLBACK PreviewDialogProc( - HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - LPARAM lParam - ) -{ - static RECT rcClient; - - switch ( uMsg ) - { - case WM_SIZE: - { - LONG cx = LOWORD( lParam ); - LONG cy = HIWORD( lParam ); - LONG dxClient, dyClient; - - dxClient = cx - rcClient.right; - dyClient = cy - rcClient.bottom; - - EnumChildWindows( hwndDlg, GrowChildWindows, MAKELONG( (SHORT)dxClient, (SHORT)dyClient) ); - - GetClientRect( hwndDlg, &rcClient ); - } - break; - case WM_INITDIALOG: - { - GetClientRect( hwndDlg, &rcClient ); - SetGrowMode( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GM_HIX | GM_HIY ); - SetGrowMode( GetDlgItem(hwndDlg, IDOK), GM_LOX | GM_HIX | GM_LOY | GM_HIY ); - - CrashReportParams *pParams = (CrashReportParams *)lParam; - - TCHAR szBuffer[256] = TEXT(""); - HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE ); - HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT ); - - GetWindowText( hwndParent, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - SetWindowText( hwndDlg, szBuffer ); - - LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer ); - - basic_string aString; - - aString.append( pParams->sTitle ); - aString.append( _T("\r\n\r\n") ); - aString.append( pParams->sComment ); - aString.append( _T("\r\n---------- report ----------\r\n") ); - - FILE *fp = fopen( g_szReportFileNameA, "r" ); - - if ( fp ) - { - char buf[1024]; - - while ( fgets( buf, SAL_N_ELEMENTS(buf), fp ) != NULL ) - { - WCHAR bufW[1024]; - - MultiByteToWideChar( CP_UTF8, 0, buf, -1, bufW, SAL_N_ELEMENTS(bufW) ); - - aString.append( bufW ); - } - - fclose( fp ); - } - - aString.append( _T("\r\n---------- stack ----------\r\n") ); - - fp = fopen( g_szDumpFileNameA, "rb" ); - - if ( fp ) - { - unsigned char buf[16]; - int count; - - do - { - int i; - - count = fread( buf, sizeof(buf[0]), SAL_N_ELEMENTS(buf), fp ); - - for ( i = 0; i < count; i++ ) - { - TCHAR output[16]; - - _sntprintf( output, SAL_N_ELEMENTS(output), _T("%02X\x20"), buf[i] ); - aString.append( output ); - } - for ( ; i < SAL_N_ELEMENTS(buf); i++ ) - { - aString.append( _T("\x20\x20\x20") ); - } - - for ( i = 0; i < count; i++ ) - { - TCHAR output[2]; - - if ( (int)buf[i] >= 0x20 && (int)buf[i] <= 0x7F ) - output[0] = (TCHAR)buf[i]; - else - output[0] = '.'; - output[1] = 0; - aString.append( output ); - } - - aString.append( _T("\r\n") ); - - } while ( count ); - - fclose( fp ); - } - Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), aString.c_str() ); - SetWindowFont( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GetStockObject( SYSTEM_FIXED_FONT ), TRUE ); - } - return TRUE; - case WM_COMMAND: - switch ( LOWORD(wParam) ) - { - case IDOK: - case IDCANCEL: - EndDialog( hwndDlg, wParam ); - return TRUE; - } - break; - default: - break; - } - - return FALSE; -} -//*************************************************************************** - -static void PreviewReport( HWND hwndParent, CrashReportParams *pParams ) -{ - HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE ); - - WriteReportFile( pParams ); - - DialogBoxParam( - hInstance, - MAKEINTRESOURCE(IDD_PREVIEW_FRAME), - hwndParent, - PreviewDialogProc, - (LPARAM)pParams - ); - - DeleteFileA( g_szReportFileNameA ); -} -//*************************************************************************** -void UpdateOptionsDialogControls( HWND hwndDlg ) -{ - if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED ) - { - EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), TRUE ); - EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), TRUE ); - } - else - { - EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), FALSE ); - EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), FALSE ); - } -} - -//*************************************************************************** - -BOOL CALLBACK OptionsDialogProc( - HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - LPARAM lParam - ) -{ - static CrashReportParams *pParams; - - switch ( uMsg ) - { - case WM_INITDIALOG: - { - TCHAR szBuffer[1024] = TEXT(""); - HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE ); - //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT ); - - pParams = (CrashReportParams *)lParam; - - LoadAndFormatString( hInstance, IDS_OPTIONS_CAPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - SetWindowText( hwndDlg, szBuffer ); - - LoadAndFormatString( hInstance, IDS_PROXY_SETTINGS_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Static_SetText( GetDlgItem(hwndDlg, IDC_PROXY_SETTINGS), szBuffer ); - - LoadAndFormatString( hInstance, IDS_PROXY_SYSTEM, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM), szBuffer ); - - LoadAndFormatString( hInstance, IDS_PROXY_DIRECT, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT), szBuffer ); - - LoadAndFormatString( hInstance, IDS_PROXY_MANUAL, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL), szBuffer ); - - LoadAndFormatString( hInstance, IDS_LABEL_PROXYSERVER, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYSERVER), szBuffer ); - - LoadAndFormatString( hInstance, IDS_LABEL_PROXYPORT, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYPORT), szBuffer ); - - LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer ); - - LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer ); - - Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), pParams->sProxyServer.c_str() ); - Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), pParams->sProxyPort.c_str() ); - - Button_SetCheck( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM + pParams->uInternetConnection), BST_CHECKED ); - - SendMessage( - GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), - EM_SETBKGNDCOLOR, - (WPARAM)FALSE, - GetSysColor( COLOR_3DFACE ) ); - LoadAndFormatString( hInstance, IDS_PROXY_DESCRIPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Edit_SetText( GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), szBuffer ); - - UpdateOptionsDialogControls( hwndDlg ); - } - return TRUE; - case WM_COMMAND: - switch ( LOWORD(wParam) ) - { - case IDC_RADIO_SYSTEM: - case IDC_RADIO_DIRECT: - case IDC_RADIO_MANUAL: - if ( BN_CLICKED == HIWORD(wParam) ) - UpdateOptionsDialogControls( hwndDlg ); - break; - case IDOK: - { - TCHAR szBuffer[1024]; - - Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - pParams->sProxyServer = szBuffer; - - Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - pParams->sProxyPort = szBuffer; - - if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT) ) & BST_CHECKED ) - pParams->uInternetConnection = 1; - else if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED ) - pParams->uInternetConnection = 2; - else - pParams->uInternetConnection = 0; - } - case IDCANCEL: - EndDialog( hwndDlg, wParam ); - return TRUE; - } - break; - default: - break; - } - - return FALSE; -} - -//*************************************************************************** - -static void OptionsDialog( HWND hwndParent, CrashReportParams *pParams ) -{ - HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE ); - - if ( IDOK == DialogBoxParam( - hInstance, - MAKEINTRESOURCE(IDD_OPTIONS_FRAME), - hwndParent, - OptionsDialogProc, - (LPARAM)pParams - ) ) - pParams->WriteToRegistry(); - -} -//*************************************************************************** - -void UpdateReportDialogControls( HWND hwndDlg ) -{ - EnableWindow( - GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), - Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE ); - EnableWindow( - GetDlgItem(hwndDlg, IDC_LABEL_EMAIL), - Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE ); -} - -//*************************************************************************** - -BOOL CALLBACK ReportDialogProc( - HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - LPARAM - ) -{ - switch ( uMsg ) - { - case WM_INITDIALOG: - { - CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); - HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); - TCHAR szBuffer[FORMATBUFSIZE]; - - LoadAndFormatString( hInstance, IDS_REPORT_INTRO, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Static_SetText( GetDlgItem(hwndDlg, IDC_REPORT_INTRO), szBuffer ); - - Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT3), szBuffer ); - - LoadAndFormatString( hInstance, IDS_ENTER_TITLE, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_TITLE), szBuffer ); - - LoadAndFormatString( hInstance, IDS_ENTER_DESCRIPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_DESCRIPTION), szBuffer ); - - LoadAndFormatString( hInstance, IDS_SHOW_REPORT_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDC_SHOW_REPORT), szBuffer ); - - LoadAndFormatString( hInstance, IDS_SAVE_REPORT_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), szBuffer ); - - const char *pszUserType = getenv( "STAROFFICE_USERTYPE" ); - if ( pszUserType ) - ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_SHOW ); - else - ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_HIDE ); - - LoadAndFormatString( hInstance, IDS_OPTIONS_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDC_OPTIONS), szBuffer ); - - LoadAndFormatString( hInstance, IDS_ALLOW_CONTACT, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), szBuffer ); - Button_SetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), pParams->fAllowContact ? BST_CHECKED : BST_UNCHECKED ); - - LoadAndFormatString( hInstance, IDS_LABEL_EMAIL, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDC_LABEL_EMAIL), szBuffer ); - - Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), pParams->sEmail.c_str() ); - - UpdateReportDialogControls( hwndDlg ); - } - return TRUE; - case WM_SHOWWINDOW: - if ( (BOOL)wParam ) - { - HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); - CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); - TCHAR szBuffer[FORMATBUFSIZE]; - - LoadAndFormatString( hInstance, IDS_REPORT_CAPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - SetWindowText( GetParent(hwndDlg), szBuffer ); - - LoadAndFormatString( hInstance, IDS_REPORT_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer ); - - LoadAndFormatString( hInstance, IDS_DONOT_SEND_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer ); - - - ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), TRUE ); - ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), TRUE ); - ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), FALSE ); - - Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), pParams->sTitle.c_str() ); - Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), pParams->sComment.c_str() ); - - SetFocus( GetDlgItem(hwndDlg,IDC_EDIT_TITLE) ); - } - break; - case WM_COMMAND: - switch ( LOWORD(wParam) ) - { - case IDC_SHOW_REPORT: - { - TCHAR szBuffer[32767]; - - CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); - - pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT) ) ? TRUE : FALSE; - - Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - pParams->sTitle = szBuffer; - - Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - pParams->sComment = szBuffer; - - Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - pParams->sEmail = szBuffer; - - PreviewReport( GetParent(hwndDlg), pParams ); - } - return TRUE; - case IDC_SAVE_REPORT: - SaveDumpFile( GetParent(hwndDlg) ); - return TRUE; - case IDC_OPTIONS: - { - CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); - OptionsDialog( GetParent(hwndDlg), pParams ); - } - return TRUE; - case IDC_ALLOW_CONTACT: - if ( BN_CLICKED == HIWORD(wParam) ) - UpdateReportDialogControls( hwndDlg ); - return TRUE; - } - break; - default: - break; - } - - return FALSE; -} -//*************************************************************************** - -BOOL CALLBACK WelcomeDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) -{ - switch ( uMsg ) - { - case WM_INITDIALOG: - { - HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); - HWND hwndRichEdit = GetDlgItem(hwndDlg, IDC_RICHEDIT21); - TCHAR szBuffer[FORMATBUFSIZE]; - TCHAR szBuffer2[FORMATBUFSIZE]; - TCHAR szURL[256]; - TCHAR szCaption[256]; - - SendMessage( - hwndRichEdit, - EM_SETBKGNDCOLOR, - (WPARAM)FALSE, - GetSysColor( COLOR_3DFACE ) ); - - SendMessage( hwndRichEdit, EM_SETEVENTMASK, 0, ENM_LINK ); - SendMessage( hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0 ); - - LoadAndFormatString( hInstance, IDS_WELCOME_BODY1, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - LoadAndFormatString( hInstance, IDS_WELCOME_BODY2, szBuffer2, SAL_N_ELEMENTS(szBuffer2) ); - _tcsncat( szBuffer, szBuffer2, SAL_N_ELEMENTS(szBuffer) ); - LoadAndFormatString( hInstance, IDS_WELCOME_BODY3, szBuffer2, SAL_N_ELEMENTS(szBuffer2) ); - _tcsncat( szBuffer, szBuffer2, SAL_N_ELEMENTS(szBuffer) ); - LoadString( hInstance, IDS_PRIVACY_URL, szURL, SAL_N_ELEMENTS(szURL) ); - _tcsncat( szBuffer, szURL, SAL_N_ELEMENTS(szBuffer) ); - SetWindowText( hwndRichEdit, szBuffer ); - - LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szCaption, SAL_N_ELEMENTS(szCaption) ); - SetWindowText( GetParent(hwndDlg), szCaption ); - - } - return TRUE; - case WM_SHOWWINDOW: - if ( (BOOL)wParam ) - { - HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); - TCHAR szBuffer[FORMATBUFSIZE]; - - LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - SetWindowText( GetParent(hwndDlg), szBuffer ); - - LoadAndFormatString( hInstance, IDS_WELCOME_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer ); - - LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer ); - - ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), FALSE ); - ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), FALSE ); - ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), TRUE ); - - SetFocus( GetDlgItem(GetParent(hwndDlg),IDNEXT) ); - } - break; - case WM_NOTIFY: - { - LPNMHDR pnmh = (LPNMHDR)lParam; - - if ( pnmh->idFrom == IDC_RICHEDIT21 && pnmh->code == EN_LINK ) - { - ENLINK *plink = (ENLINK*)lParam; - - if ( plink->msg == WM_LBUTTONUP ) - { - TCHAR szBuffer[256]; - TEXTRANGE range; - - range.chrg = plink->chrg; - range.lpstrText = szBuffer; - - SendMessage( pnmh->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&range ); - - ShellExecute( hwndDlg, NULL, szBuffer, NULL, NULL, SW_SHOWDEFAULT ); - } - - } - } - break; - default: - break; - } - - return FALSE; -} -//*************************************************************************** - -BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) -{ - static HWND hwndPages[2] = { NULL }; - static int iActualPage = 0; - - switch ( uMsg ) - { - case WM_INITDIALOG: - { - HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); - TCHAR szBuffer[FORMATBUFSIZE]; - - SetWindowLong( hwndDlg, GWL_USERDATA, (LONG)lParam ); - hwndPages[0] = CreateDialog( - hInstance, - MAKEINTRESOURCE(IDD_WELCOME_PAGE), - hwndDlg, - WelcomeDialogProc ); - - hwndPages[1] = CreateDialog( - hInstance, - MAKEINTRESOURCE(IDD_REPORT_PAGE), - hwndDlg, - ReportDialogProc ); - - CHARFORMAT chfmt; - - chfmt.cbSize = sizeof(chfmt); - chfmt.dwMask = CFM_BOLD; - chfmt.dwEffects = CFE_BOLD; - - SendMessage( - GetDlgItem(hwndDlg, IDC_HEADER), - EM_SETCHARFORMAT, - SCF_ALL, - (LPARAM)&chfmt ); - - LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer ); - - LoadAndFormatString( hInstance, IDS_NEXT_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDNEXT), szBuffer ); - - LoadAndFormatString( hInstance, IDS_SEND_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDFINISH), szBuffer ); - - LoadAndFormatString( hInstance, IDS_BACK_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDBACK), szBuffer ); - - ShowWindow( hwndPages[1], SW_HIDE ); - ShowWindow( hwndPages[0], SW_SHOW ); - - // Let Crash Reporter window stay on top of all other windows - SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); - } - return FALSE; - case WM_CTLCOLORSTATIC: - return (BOOL)CreateSolidBrush(GetSysColor(COLOR_WINDOW)); - case WM_COMMAND: - switch ( LOWORD(wParam) ) - { - case IDBACK: - if ( iActualPage > 0 ) - { - ShowWindow( hwndPages[iActualPage], SW_HIDE ); - ShowWindow( hwndPages[--iActualPage], SW_SHOW ); - } - return TRUE; - case IDNEXT: - if ( iActualPage < SAL_N_ELEMENTS(hwndPages) - 1 ) - { - ShowWindow( hwndPages[iActualPage], SW_HIDE ); - ShowWindow( hwndPages[++iActualPage], SW_SHOW ); - } - return TRUE; - case IDFINISH: - { - TCHAR szBuffer[32767]; - CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( hwndDlg, GWL_USERDATA ); - - pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndPages[1], IDC_ALLOW_CONTACT) ) ? TRUE : FALSE; - - Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_TITLE), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - pParams->sTitle = szBuffer; - - Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_DESCRIPTION), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - pParams->sComment = szBuffer; - - Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_EMAIL), szBuffer, SAL_N_ELEMENTS(szBuffer) ); - pParams->sEmail = szBuffer; - - if ( pParams->fAllowContact && !pParams->sEmail.length() ) - { - TCHAR szMessage[MAX_TEXT_BUFFER]; - - LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_NOEMAILADDRESS, szMessage, SAL_N_ELEMENTS(szMessage) ); - - MessageBox( hwndDlg, szMessage, NULL, MB_ICONERROR | MB_OK ); - break; // Don't end the dialog - } - else - { - pParams->WriteToRegistry(); - - WriteCommentFile( pParams->sComment.c_str() ); - WriteReportFile( pParams ); - - if ( !SendCrashReport( hwndDlg, *pParams ) ) - break; // Don't end the dialog - } - } - // Fallthrough !!! - case IDCANCEL: - EndDialog( hwndDlg, wParam ); - return TRUE; - } - break; - default: - break; - } - - return FALSE; -} - - - -//***************************************************************************** -//* Generate MD5 checksum -//***************************************************************************** - -#define MAGIC_DESCRIPTION_FILLER 'x' -#define MAGIC_DESCRIPTION_COUNT 80 - -static void repatch_soffice_exe( void *pBuffer, size_t nBufSize ) -{ - wchar_t DescriptionBuffer[MAGIC_DESCRIPTION_COUNT]; - - memset( DescriptionBuffer, 0, sizeof(DescriptionBuffer) ); - wcsncpy( DescriptionBuffer, g_wstrProductKey.c_str(), SAL_N_ELEMENTS(DescriptionBuffer) - 1 ); - - bool bPatched = false; - - do - { - void *pFound = memchr( pBuffer, ((char *)DescriptionBuffer)[0], nBufSize ); - - if ( pFound ) - { - size_t distance = (char *)pFound - (char *)pBuffer; - - if ( nBufSize >= distance ) - { - nBufSize -= distance; - - if ( nBufSize >= sizeof(DescriptionBuffer) && - 0 == memcmp( pFound, DescriptionBuffer, sizeof(DescriptionBuffer) ) ) - { - for ( int i = 0; i < 80; i++ ) - { - ((wchar_t *)pFound)[i] = MAGIC_DESCRIPTION_FILLER; - } - bPatched = true; - } - else - { - pBuffer = (void *)(((char *)pFound) + 1); - nBufSize--; - } - } - else - nBufSize = 0; - } - else - nBufSize = 0; - } while ( !bPatched && nBufSize ); -} - -// Normalize executable/library images to prevent different MD5 checksums due -// to a different PE header date/checksum (this doesn't affect the code/data -// sections of a executable/library. Please see tools/source/bootstrp/md5.cxx -// where the same method is also used. The tool so_checksum creates the MD5 -// checksums during build time. You have to make sure that both methods use the -// same algorithm otherwise there could be problems with stack reports. -static void normalize_pe_image(sal_uInt8* buffer, size_t nBufferSize) -{ - const int OFFSET_PE_OFFSET = 0x3c; - const int OFFSET_COFF_TIMEDATESTAMP = 4; - const int PE_SIGNATURE_SIZE = 4; - const int COFFHEADER_SIZE = 20; - const int OFFSET_PE_OPTIONALHEADER_CHECKSUM = 64; - - // Check the header part of the file buffer - if (buffer[0] == 'M' && buffer[1] == 'Z') - { - unsigned long PEHeaderOffset = (long)buffer[OFFSET_PE_OFFSET]; - if (PEHeaderOffset < nBufferSize-4) - { - if ( buffer[PEHeaderOffset] == 'P' && - buffer[PEHeaderOffset+1] == 'E' && - buffer[PEHeaderOffset+2] == 0 && - buffer[PEHeaderOffset+3] == 0 ) - { - PEHeaderOffset += PE_SIGNATURE_SIZE; - if (PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP < nBufferSize-4) - { - // Set timedatestamp and checksum fields to a normalized - // value to enforce the same MD5 checksum for identical - // Windows executables/libraries. - buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP] = 0; - buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+1] = 0; - buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+2] = 0; - buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+3] = 0; - } - - if (PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM < nBufferSize-4) - { - // Set checksum to a normalized value - buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM] = 0; - buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+1] = 0; - buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+2] = 0; - buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+3] = 0; - } - } - } - } -} - -static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen ) -{ - const int MINIMAL_FILESIZE = 512; - - sal_uInt32 nBytesProcessed = 0; - - FILE *fp = fopen( filename, "rb" ); - - if ( fp ) - { - long nFileSize; - - if ( 0 == fseek( fp, 0, SEEK_END ) && -1 != (nFileSize = ftell(fp)) ) - { - rewind( fp ); - - sal_uInt8 *pBuffer = new sal_uInt8[nFileSize]; - size_t nBytesRead = fread( pBuffer, 1, nFileSize, fp ); - - if ( sal::static_int_cast(nBytesRead) == nFileSize ) - { - if ( 0 == stricmp( GetFileName(filename).c_str(), "soffice.bin" ) ) - repatch_soffice_exe( pBuffer, nBytesRead ); - else if ( nFileSize > MINIMAL_FILESIZE ) - normalize_pe_image( pBuffer, nBytesRead ); - - rtlDigestError error = rtl_digest_MD5 ( - pBuffer, nBytesRead, - pChecksum, nChecksumLen ); - - if ( rtl_Digest_E_None == error ) - nBytesProcessed = nBytesRead; - } - - delete[] pBuffer; - } - fclose( fp ); - } - return nBytesProcessed; -} - -//*************************************************************************** - -static bool WriteStackFile( FILE *fout, boost::unordered_map< string, string >& rLibraries, DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers ) -{ - bool fSuccess = false; - - if ( fout && dwProcessId && pExceptionPointers ) - { - HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId ); - - if ( IsValidHandle(hProcess) ) - { - EXCEPTION_POINTERS aExceptionPointers; - CONTEXT aContextRecord; - - ReadProcessMemory( - hProcess, - pExceptionPointers, - &aExceptionPointers, - sizeof(aExceptionPointers), - NULL ); - - ReadProcessMemory( - hProcess, - aExceptionPointers.ContextRecord, - &aContextRecord, - sizeof(aContextRecord), - NULL ); - - STACKFRAME frame; - - ZeroMemory( &frame, sizeof(frame) ); - frame.AddrPC.Offset = aContextRecord.Eip; - frame.AddrPC.Mode = AddrModeFlat; - frame.AddrFrame.Offset = aContextRecord.Ebp; - frame.AddrFrame.Mode = AddrModeFlat; - - BOOL bSuccess; - int frameNum = 0; - - SymInitialize( hProcess, NULL, TRUE ); - - fprintf( fout, "\n" ); - - do - { - fSuccess = true; - - bSuccess = StackWalk( IMAGE_FILE_MACHINE_I386, - hProcess, - NULL, - &frame, - &aContextRecord, - (PREAD_PROCESS_MEMORY_ROUTINE)ReadProcessMemory, - SymFunctionTableAccess, - SymGetModuleBase, - NULL ); - - if ( bSuccess ) - { - // Note: ImageHelp ANSI functions do not have an A postfix while - // Unicode versions have a W postfix. There's no macro - // that depends on define UNICODE - - IMAGEHLP_MODULE moduleInfo; - - ZeroMemory( &moduleInfo, sizeof(moduleInfo) ); - moduleInfo.SizeOfStruct = sizeof(moduleInfo); - - if ( SymGetModuleInfo( hProcess, frame.AddrPC.Offset, &moduleInfo ) ) - { - rLibraries[ GetFileName( moduleInfo.LoadedImageName ).c_str() ] = moduleInfo.LoadedImageName; - - DWORD dwRelOffset = 0; - BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 256 ]; - PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer; - - ZeroMemory( symbolBuffer, sizeof(symbolBuffer) ); - pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); - pSymbol->MaxNameLength = 256; - - if ( SymGetSymFromAddr( hProcess, frame.AddrPC.Offset, &dwRelOffset, pSymbol ) ) - fprintf( fout, "\n", - frameNum, - frame.AddrPC.Offset, - frame.AddrPC.Offset - moduleInfo.BaseOfImage, - xml_encode(pSymbol->Name).c_str(), - frame.AddrPC.Offset - pSymbol->Address, - xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(), - xml_encode( GetFileDirectory( moduleInfo.LoadedImageName )).c_str() - ); - else - fprintf( fout, "\n", - frameNum, - frame.AddrPC.Offset, - frame.AddrPC.Offset - moduleInfo.BaseOfImage, - xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(), - xml_encode(GetFileDirectory( moduleInfo.LoadedImageName )).c_str() - ); - } - else - fprintf( fout, "\n", - frameNum, - frame.AddrPC.Offset - ); - - frameNum++; - } - - } while ( bSuccess ); - - fprintf( fout, "\n" ); - - SymCleanup( hProcess ); - - CloseHandle( hProcess ); - } - - } - - return fSuccess; -} - -bool WriteChecksumFile( FILE *fchksum, const boost::unordered_map< string, string >& rLibraries ) -{ - bool success = false; - - if ( fchksum && rLibraries.size() ) - { - fprintf( fchksum, "\n" ); - - boost::unordered_map< string, string >::const_iterator iter; - - for ( iter = rLibraries.begin(); iter != rLibraries.end(); ++iter ) - { - sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5]; - sal_uInt32 nBytesProcessed = calc_md5_checksum( - iter->second.c_str(), - checksum, sizeof(checksum) ); - - if ( nBytesProcessed ) - { - fprintf( fchksum, "\n", - nBytesProcessed, - GetFileName( iter->first ).c_str() ); - } - } - - fprintf( fchksum, "\n" ); - - success = true; - } - - return success; -} - -//*************************************************************************** - -BOOL FindDumpFile() -{ - TCHAR szFileName[MAX_PATH]; - - if ( GetCrashDataPath( szFileName ) ) - { - _tcscat( szFileName, _T("\\crashdat.dmp") ); - - HANDLE hFile = CreateFile( - szFileName, - GENERIC_READ, - 0, NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL ); - - if ( hFile ) - { - CloseHandle( hFile ); - - WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL ); - _tcscpy( g_szDumpFileName, szFileName ); - - return TRUE; - } - } - - return FALSE; -} - -BOOL WriteDumpFile( DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers, DWORD dwThreadId ) -{ - BOOL fSuccess = FALSE; - MINIDUMP_EXCEPTION_INFORMATION ExceptionParam; - - HMODULE hDbgHelp = LoadLibrary( _T("DBGHELP.DLL" ) ); - MiniDumpWriteDump_PROC pMiniDumpWriteDump = NULL; - - if ( hDbgHelp ) - { - pMiniDumpWriteDump = (MiniDumpWriteDump_PROC)GetProcAddress( hDbgHelp, "MiniDumpWriteDump" ); - - if ( !pMiniDumpWriteDump ) - { - FreeLibrary( hDbgHelp ); - return false; - } - } - - if ( !pMiniDumpWriteDump ) - return false; - - HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId ); - - if ( IsValidHandle(hProcess) ) - { - TCHAR szTempPath[MAX_PATH]; - - if ( GetCrashDataPath( szTempPath ) ) - { - TCHAR szFileName[MAX_PATH]; - - _tcscpy( szFileName, szTempPath ); - _tcscat( szFileName, _T("\\crashdat.dmp") ); - { - HANDLE hFile = CreateFile( - szFileName, - GENERIC_READ | GENERIC_WRITE, - 0, NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, NULL ); - - if ( hFile ) - { - PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam = NULL; - if ( pExceptionPointers && dwThreadId ) - { - ExceptionParam.ThreadId = dwThreadId; - ExceptionParam.ExceptionPointers = pExceptionPointers; - ExceptionParam.ClientPointers = TRUE; - - EXCEPTION_POINTERS aExceptionPointers; - EXCEPTION_RECORD aExceptionRecord; - - ReadProcessMemory( - hProcess, - pExceptionPointers, - &aExceptionPointers, - sizeof(aExceptionPointers), - NULL ); - - - ReadProcessMemory( - hProcess, - aExceptionPointers.ExceptionRecord, - &aExceptionRecord, - sizeof(aExceptionRecord), - NULL ); - - g_dwExceptionCode = aExceptionRecord.ExceptionCode; - - lpExceptionParam = &ExceptionParam; - } - - fSuccess = pMiniDumpWriteDump( hProcess, dwProcessId, hFile, MiniDumpNormal, lpExceptionParam, NULL, NULL ); - - CloseHandle( hFile ); - - WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL ); - _tcscpy( g_szDumpFileName, szFileName ); - } - - if ( !fSuccess ) - DeleteFile( szFileName ); - } - } - - CloseHandle( hProcess ); - } - - FreeLibrary( hDbgHelp ); - - return fSuccess; -} - -//*************************************************************************** - -static DWORD FindProcessForImage( LPCTSTR lpImagePath ) -{ - DWORD dwProcessId = 0; - DWORD aProcesses[1024]; - DWORD dwSize = 0; - TCHAR szShortImagePath[MAX_PATH]; - - if ( GetShortPathName( lpImagePath, szShortImagePath, SAL_N_ELEMENTS(szShortImagePath) ) && - EnumProcesses( aProcesses, sizeof(aProcesses), &dwSize ) ) - { - unsigned nProcesses = dwSize / sizeof(aProcesses[0]); - - for ( unsigned i = 0; !dwProcessId && i < nProcesses; i++ ) - { - HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] ); - - if ( IsValidHandle(hProcess) ) - { - TCHAR szModulePath[MAX_PATH+1]; - - if ( GetModuleFileNameEx( hProcess, NULL, szModulePath, MAX_PATH ) ) - { - TCHAR szShortModulePath[MAX_PATH]; - - if ( GetShortPathName( szModulePath, szShortModulePath, SAL_N_ELEMENTS(szShortModulePath) ) ) - { - if ( 0 == _tcsicmp( szShortModulePath, szShortImagePath ) ) - dwProcessId = aProcesses[i]; - } - } - - CloseHandle( hProcess ); - } - } - } - - return dwProcessId; -} -//*************************************************************************** - -static bool ParseCommandArgs( LPDWORD pdwProcessId, PEXCEPTION_POINTERS* ppException, LPDWORD pdwThreadId ) -{ - int argc = __argc; -#ifdef __MINGW32__ -#ifdef _UNICODE - TCHAR **argv = reinterpret_cast(alloca((argc+1)*sizeof(WCHAR*))); - int *sizes = reinterpret_cast(alloca(argc*sizeof(int))); - int argsize=0; - char **ptr; - int i; - ptr=__argv; - for (i = 0; i < argc; ++i) - { - sizes[i]=MultiByteToWideChar(CP_ACP, 0, *ptr, -1, NULL, 0); - argsize+=sizes[i]+1; - ++ptr; - } - ++argsize; - TCHAR *args = reinterpret_cast(alloca(argsize*sizeof(WCHAR))); - ptr=__argv; - TCHAR *cptr=args; - for (i = 0; i < argc; ++i) - { - argv[i]=cptr; - MultiByteToWideChar( CP_ACP, 0, *ptr, -1, cptr, sizes[i] ); - ++ptr; - cptr+=sizes[i]; - *cptr=0; - ++cptr; - } - argv[i]=cptr; - *cptr=0; -#else - TCHAR **argv = __argv; -#endif -#else - TCHAR **argv = __targv; -#endif - bool bSuccess = true; - - for ( int argn = 1; bSuccess && argn < argc; argn++ ) - { - if ( 0 == _tcsicmp( argv[argn], _T("-h") ) || - 0 == _tcsicmp( argv[argn], _T("/h") ) || - 0 == _tcsicmp( argv[argn], _T("-?") ) || - 0 == _tcsicmp( argv[argn], _T("/?") ) || - 0 == _tcsicmp( argv[argn], _T("/help") ) || - 0 == _tcsicmp( argv[argn], _T("-help") ) || - 0 == _tcsicmp( argv[argn], _T("--help") ) - ) - { - HINSTANCE hInstance = GetModuleHandle(NULL); - TCHAR szUsage[FORMATBUFSIZE]; - TCHAR szProcess[FORMATBUFSIZE]; - TCHAR szProcessDescription[FORMATBUFSIZE]; - TCHAR szHelpDescription[FORMATBUFSIZE]; - - LoadAndFormatString( hInstance, IDS_MSG_CMDLINE_USAGE, szUsage, SAL_N_ELEMENTS(szUsage) ); - LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID, szProcess, SAL_N_ELEMENTS(szProcess) ); - LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID_DESCRIPTION, szProcessDescription, SAL_N_ELEMENTS(szProcessDescription) ); - LoadAndFormatString( hInstance, IDS_MSG_PARAM_HELP_DESCRIPTION, szHelpDescription, SAL_N_ELEMENTS(szHelpDescription) ); - - _tprintf( - TEXT("\n%s: crashrep %s\n\n") - TEXT("/?, -h[elp] %s\n\n") - TEXT("%-20s %s\n\n"), - szUsage, szProcess, szHelpDescription, szProcess, szProcessDescription - ); - - return true; - } - else if ( 0 == _tcsicmp( argv[argn], _T("-p") ) || - 0 == _tcsicmp( argv[argn], _T("/p") ) ) - { - if ( ++argn < argc ) - *pdwProcessId = _tcstoul( argv[argn], NULL, 0 ); - else - bSuccess = false; - } - else if ( 0 == _tcsicmp( argv[argn], _T("-excp") ) || - 0 == _tcsicmp( argv[argn], _T("/excp") ) ) - { - if ( ++argn < argc ) - *ppException = (PEXCEPTION_POINTERS)_tcstoul( argv[argn], NULL, 0 ); - else - bSuccess = false; - } - else if ( 0 == _tcsicmp( argv[argn], _T("-t") ) || - 0 == _tcsicmp( argv[argn], _T("/t") ) ) - { - if ( ++argn < argc ) - *pdwThreadId = _tcstoul( argv[argn], NULL, 0 ); - else - bSuccess = false; - } - else if ( 0 == _tcsicmp( argv[argn], _T("-noui") ) || - 0 == _tcsicmp( argv[argn], _T("/noui") ) ) - { - g_bNoUserInterface = true; - } - else if ( 0 == _tcsicmp( argv[argn], _T("-send") ) || - 0 == _tcsicmp( argv[argn], _T("/send") ) ) - { - g_bSendReport = true; - } - else if ( 0 == _tcsicmp( argv[argn], _T("-load") ) || - 0 == _tcsicmp( argv[argn], _T("/load") ) ) - { - g_bLoadReport = true; - } - else // treat parameter as image path - { - TCHAR szImagePath[MAX_PATH]; - LPTSTR lpImageName; - - if ( GetFullPathName( argv[argn], MAX_PATH, szImagePath, &lpImageName ) ) - { - DWORD dwProcessId = FindProcessForImage( szImagePath ); - - if ( dwProcessId ) - *pdwProcessId = dwProcessId; - else - bSuccess = false; - } - } - } - - if ( !*pdwProcessId && !g_bLoadReport ) - { - TCHAR szImagePath[MAX_PATH]; - LPTSTR lpImageName; - - if ( GetFullPathName( TEXT("soffice.exe"), MAX_PATH, szImagePath, &lpImageName ) ) - { - DWORD dwProcessId = FindProcessForImage( szImagePath ); - - if ( dwProcessId ) - *pdwProcessId = dwProcessId; - else - bSuccess = false; - } - } - - return bSuccess; -} - -//*************************************************************************** - -BOOL WriteCommentFile( LPCTSTR lpComment ) -{ - BOOL fSuccess = FALSE; - TCHAR szTempPath[MAX_PATH]; - - if ( GetTempPath( SAL_N_ELEMENTS(szTempPath), szTempPath ) ) - { - TCHAR szFileName[MAX_PATH]; - - if ( GetTempFileName( szTempPath, TEXT("CMT"), 0, szFileName ) ) - { - HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); - - if ( hFile ) - { - DWORD dwBytesWritten; - - int needed = WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, NULL, 0, NULL, NULL ); - if ( needed ) - { - char *lpCommentUTF8 = (char *)alloca( needed ); - WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, lpCommentUTF8, needed, NULL, NULL ); - fSuccess = WriteFile( hFile, lpCommentUTF8, strlen(lpCommentUTF8), &dwBytesWritten, NULL ); - } - else - fSuccess = TRUE; - - - CloseHandle( hFile ); - - WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szCommentFileNameA, MAX_PATH, NULL, NULL ); - } - - if ( !fSuccess ) - DeleteFile( szFileName ); - } - } - - return fSuccess; -} - -//*************************************************************************** - -static int _tsetenv( const _TCHAR *lpVar, const _TCHAR *lpValue ) -{ - if ( !lpValue ) - lpValue = _T(""); - - _TCHAR *envstr = (TCHAR *)alloca( (_tcslen( lpVar ) + _tcslen( lpValue ) + 2) * sizeof(_TCHAR) ); - - _tcscpy( envstr, lpVar ); - _tcscat( envstr, _T("=") ); - _tcscat( envstr, lpValue ); - - return _tputenv( envstr ); -} - -static bool read_line( FILE *fp, string& rLine ) -{ - char szBuffer[1024]; - bool bSuccess = false; - bool bEOL = false; - string line; - - - while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) ) - { - int len = strlen(szBuffer); - - bSuccess = true; - - while ( len && szBuffer[len - 1] == '\n' ) - { - szBuffer[--len] = 0; - bEOL = true; - } - - line.append( szBuffer ); - } - - rLine = line; - return bSuccess; -} - -static string get_script_string( const char *pFileName, const char *pKeyName ) -{ - FILE *fp = fopen( pFileName, "rt" ); - string retValue; - - if ( fp ) - { - string line; - string section; - - while ( read_line( fp, line ) ) - { - line = trim_string( line ); - - - string::size_type iEqualSign = line.find( '=', 0 ); - - if ( iEqualSign != string::npos ) - { - string keyname = line.substr( 0, iEqualSign ); - keyname = trim_string( keyname ); - - string value = line.substr( sal::static_int_cast(iEqualSign + 1) ); - value = trim_string( value ); - - if ( value.length() && '\"' == value[0] ) - { - value.erase( 0, 1 ); - - string::size_type iQuotes = value.find( '"', 0 ); - - if ( iQuotes != string::npos ) - value.erase( iQuotes ); - } - - if ( 0 == stricmp( keyname.c_str(), pKeyName ) ) - { - retValue = value; - break; - } - } - } - - fclose( fp ); - } - - return retValue; -} - -static bool ReadBootstrapParams( CrashReportParams &rParams ) -{ - TCHAR szBuffer[256] = TEXT(""); - TCHAR szModuleName[MAX_PATH]; - TCHAR szModuleVersionName[MAX_PATH]; - TCHAR szDrive[_MAX_DRIVE]; - TCHAR szDir[_MAX_DIR]; - TCHAR szFName[_MAX_FNAME]; - TCHAR szExt[_MAX_EXT]; - TCHAR szReportServer[MAX_HOSTNAME]; - TCHAR szReportPort[256]; - bool bSuccess = false; - - GetModuleFileName( NULL, szModuleName, MAX_PATH ); - _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt ); - _tmakepath( szModuleName, szDrive, szDir, _T("bootstrap"), _T(".ini") ); - _tmakepath( szModuleVersionName, szDrive, szDir, _T("version"), _T(".ini") ); - - if ( - GetPrivateProfileString( - TEXT("Bootstrap"), - TEXT("ProductKey"), - TEXT("LibreOffice"), - szBuffer, - SAL_N_ELEMENTS(szBuffer), - szModuleName ) - ) - { - TCHAR *pVersion = _tcschr( szBuffer, ' ' ); - - g_wstrProductKey = szBuffer; - - if ( pVersion ) - { - *pVersion = 0; - pVersion++; - } - else - pVersion = TEXT(""); - - if ( !_tgetenv( _T("PRODUCTNAME") ) ) - { - _tsetenv( TEXT("PRODUCTNAME"), szBuffer ); - } - if ( !_tgetenv( _T("PRODUCTVERSION") ) ) - _tsetenv( TEXT("PRODUCTVERSION"), pVersion ); - } - - GetPrivateProfileString( - TEXT("Version"), - TEXT("buildid"), - TEXT("unknown"), - g_szBuildId, SAL_N_ELEMENTS(g_szBuildId), - szModuleVersionName ); - - g_strDefaultLanguage = get_script_string( "instdb.inf", "DefaultLanguage" ); - - if ( GetPrivateProfileString( - TEXT("ErrorReport"), - TEXT("ErrorReportPort"), - TEXT("80"), - szReportPort, SAL_N_ELEMENTS(szReportPort), - szModuleName - ) ) - { - TCHAR *endptr = NULL; - - unsigned short uReportPort = (unsigned short)_tcstoul( szReportPort, &endptr, 10 ); - if ( uReportPort ) - g_uReportPort = uReportPort; - } - - if ( GetPrivateProfileString( - TEXT("ErrorReport"), - TEXT("ErrorReportServer"), - TEXT(""), - szReportServer, SAL_N_ELEMENTS(szReportServer), - szModuleName - ) ) - { - bSuccess = 0 != WideCharToMultiByte( CP_ACP, 0, szReportServer, -1, g_szReportServerA, SAL_N_ELEMENTS(g_szReportServerA), NULL, NULL ); - } - - LPCTSTR lpEnvString; - - if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYSERVER") )) ) - rParams.sProxyServer = lpEnvString; - - if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYPORT") )) ) - rParams.sProxyPort = lpEnvString; - - if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_SENDERADDRESS") )) ) - rParams.sEmail = lpEnvString; - - return bSuccess; -} - -//*************************************************************************** - -bool SendHTTPRequest( - FILE *fp, - const char *pszServer, - unsigned short uPort = 80, - const char *pszProxyServer = NULL, - unsigned short uProxyPort = 8080 ) -{ - bool success = false; - - struct hostent *hp; - - if ( pszProxyServer ) - hp = gethostbyname( pszProxyServer ); - else - hp = gethostbyname( pszServer ); - - if ( hp ) - { - SOCKET s = socket( AF_INET, SOCK_STREAM, 0 ); - - if ( s ) - { - struct sockaddr_in address; - - memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr)); - address.sin_family = AF_INET; - - if ( pszProxyServer ) - address.sin_port = ntohs( uProxyPort ); - else - address.sin_port = ntohs( uPort ); - - if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) ) - { - fseek( fp, 0, SEEK_END ); - size_t length = ftell( fp ); - fseek( fp, 0, SEEK_SET ); - - char buffer[2048]; - - if ( pszProxyServer ) - sprintf( buffer, - "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n" - "Content-Type: text/xml; charset=\"utf-8\"\r\n" - "Content-Length: %d\r\n" - "SOAPAction: \"\"\r\n\r\n", - pszServer, - uPort, - length - ); - else - sprintf( buffer, - "POST /soap/servlet/rpcrouter HTTP/1.0\r\n" - "Content-Type: text/xml; charset=\"utf-8\"\r\n" - "Content-Length: %d\r\n" - "SOAPAction: \"\"\r\n\r\n", - length - ); - - if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) ) - { - size_t nBytes; - - do - { - nBytes = fread( buffer, 1, sizeof(buffer), fp ); - - if ( nBytes ) - success = SOCKET_ERROR != send( s, buffer, nBytes, 0 ); - } while( nBytes && success ); - - if ( success ) - { - memset( buffer, 0, sizeof(buffer) ); - success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 ); - if ( success ) - { - char szHTTPSignature[sizeof(buffer)] = ""; - unsigned uHTTPReturnCode = 0; - - sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode ); - success = uHTTPReturnCode == 200; - } - } - } - - } - - closesocket( s ); - } - } - - return success; -} - -//*************************************************************************** - -static void WriteSOAPRequest( FILE *fp ) -{ - fprintf( fp, - "\n" - "\n" - "\n" - ); - - fprintf( fp, "\n" ); - fprintf( fp, "This is an autogenerated crash report mail.\n" ); - fprintf( fp, "\n" ); - - FILE *fpin = fopen( g_szReportFileNameA, "r" ); - if ( fpin ) - { - fprintf( fp, - "\n" - "reportmail.xml\n" - "\n" ); - fclose( fpin ); - } - - fpin = fopen( g_szCommentFileNameA, "r" ); - if ( fpin ) - { - fprintf( fp, - "\n" - "description.txt\n" - "\n" ); - fclose( fpin ); - }; - - - fpin = fopen( g_szDumpFileNameA, "rb" ); - if ( fpin ) - { - FILE *fptemp = _tmpfile(); - - if ( fptemp ) - { - if ( base64_encode( fpin, fptemp ) ) - { - fseek( fptemp, 0, SEEK_SET ); - fprintf( fp, - "\n" - "user.dmp\n" - "" ); - fcopy( fptemp, fp ); - fprintf( fp, "\n" ); - } - fclose( fptemp ); - } - fclose( fpin ); - } - - fprintf( fp, - "\n" - "\n" - "\n" - "\n" - ); -} - -//*************************************************************************** - -struct RequestParams -{ - bool success; - FILE *fpin; - const char *lpServer; - unsigned short uPort; - const char *lpProxyServer; - unsigned short uProxyPort; - HWND hwndStatus; -}; - -void _cdecl SendingThread( void *lpArgs ) -{ - RequestParams *pParams = (RequestParams *)lpArgs; - - pParams->success = SendHTTPRequest( pParams->fpin, pParams->lpServer, pParams->uPort, pParams->lpProxyServer, pParams->uProxyPort ); - - PostMessage( pParams->hwndStatus, WM_COMMAND, IDOK, 0 ); -} - -//*************************************************************************** - -BOOL CALLBACK SendingStatusDialogProc( - HWND hwndDlg, - UINT uMsg, - WPARAM wParam, - LPARAM lParam - ) -{ - static RequestParams *pRequest = NULL; - static HANDLE hSendingThread = NULL; - - switch ( uMsg ) - { - case WM_INITDIALOG: - { - TCHAR szBuffer[1024] = TEXT(""); - HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE ); - - pRequest = (RequestParams *)lParam; - - LoadAndFormatString( hInstance, IDS_SENDING_REPORT_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - SetWindowText( hwndDlg, szBuffer ); - - LoadAndFormatString( hInstance, IDS_SENDING_REPORT_STATUS, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Static_SetText( GetDlgItem(hwndDlg, IDC_SENDING_REPORT_STATUS), szBuffer ); - - LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); - Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer ); - - pRequest->hwndStatus = hwndDlg; - - hSendingThread = (HANDLE)_beginthread( SendingThread, 0, pRequest ); - } - return TRUE; - case WM_COMMAND: - switch ( LOWORD(wParam) ) - { - case IDCANCEL: - TerminateThread( hSendingThread, 0 ); - case IDOK: - WaitForSingleObject( hSendingThread, INFINITE ); - CloseHandle( hSendingThread ); - EndDialog( hwndDlg, wParam ); - return TRUE; - } - break; - default: - break; - } - - return FALSE; -} - -//*************************************************************************** - -bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams ) -{ - bool success = false; - char szProxyServer[1024] = ""; - unsigned short uProxyPort = 8080; - TCHAR *endptr = NULL; - - switch ( rParams.uInternetConnection ) - { - case 2: - { - WideCharToMultiByte( - CP_ACP, 0, rParams.sProxyServer.c_str(), -1, - szProxyServer, sizeof(szProxyServer), NULL, NULL ); - uProxyPort = (unsigned short)_tcstoul( rParams.sProxyPort.c_str(), &endptr, 10 ); - } - break; - case 0: - { - DWORD dwProxyEnable = 0; - - RegReadValue( HKEY_CURRENT_USER, - TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), - TEXT("ProxyEnable"), - &dwProxyEnable, - sizeof(dwProxyEnable) ); - - if ( dwProxyEnable ) - { - TCHAR tszProxyServers[1024] = TEXT(""); - - if ( ERROR_SUCCESS == RegReadValue( HKEY_CURRENT_USER, - TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), TEXT("ProxyServer"), - tszProxyServers, - sizeof(tszProxyServers) ) ) - { - TCHAR *lpHttpStart = _tcsstr( tszProxyServers, TEXT("http=") ); - - if ( lpHttpStart ) - lpHttpStart += 5; - else - lpHttpStart = tszProxyServers; - - TCHAR *lpHttpEnd = _tcschr( lpHttpStart, ';' ); - - if ( lpHttpEnd ) - *lpHttpEnd = 0; - - char szHTTPProxyServer[1024] = ""; - WideCharToMultiByte( CP_ACP, 0, lpHttpStart, -1, szHTTPProxyServer, sizeof(szHTTPProxyServer), NULL, NULL ); - - char *lpColon = strchr( szHTTPProxyServer, ':' ); - - if ( lpColon ) - { - char *endptr = NULL; - - *lpColon = 0; - uProxyPort = (unsigned short)strtoul( lpColon + 1, &endptr, 10 ); - } - else - uProxyPort = 8080; - - strcpy( szProxyServer, szHTTPProxyServer ); - - } - } - } - break; - default: - case 1: - break; - } - - FILE *fptemp = _tmpfile(); - if ( fptemp ) - { - RequestParams request; - - request.success = false; - request.fpin = fptemp; - request.lpServer = REPORT_SERVER; - request.uPort = REPORT_PORT; - request.lpProxyServer = szProxyServer[0] ? szProxyServer : NULL; - request.uProxyPort = uProxyPort; - request.hwndStatus = NULL; - - WriteSOAPRequest( fptemp ); - fseek( fptemp, 0, SEEK_SET ); - - if ( hwndParent ) - { - int retid = DialogBoxParam( - GetModuleHandle(NULL), - MAKEINTRESOURCE(IDD_SENDING_STATUS), - hwndParent, - SendingStatusDialogProc, - (LPARAM)&request - ); - - success = request.success; - - if ( IDOK == retid ) - { - if ( !success ) - { - TCHAR szMessage[1024]; - - LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, SAL_N_ELEMENTS(szMessage) ); - - MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK ); - } - else - { - TCHAR szMessage[1024]; - TCHAR szTitle[1024]; - - LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, SAL_N_ELEMENTS(szMessage) ); - LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_HEADER, szTitle, SAL_N_ELEMENTS(szTitle) ); - - MessageBox( hwndParent, szMessage, szTitle, MB_ICONINFORMATION | MB_OK ); - } - } - - } - else - { - HANDLE hSendingThread = (HANDLE)_beginthread( SendingThread, 0, (void *)&request ); - - WaitForSingleObject( hSendingThread, INFINITE ); - - success = request.success; - if ( !success ) - { - TCHAR szMessage[1024]; - - LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, SAL_N_ELEMENTS(szMessage) ); - _ftprintf( stderr, _T("ERROR: %s\n"), szMessage ); - } - else - { - TCHAR szMessage[1024]; - - LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, SAL_N_ELEMENTS(szMessage) ); - - _ftprintf( stderr, _T("SUCCESS: %s\n"), szMessage ); - } - } - fclose( fptemp ); - } - else - { - TCHAR szMessage[1024]; - - LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_DISK_FULL, szMessage, SAL_N_ELEMENTS(szMessage) ); - - if ( hwndParent ) - MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK ); - else - _ftprintf( stderr, _T("ERROR: %s\n"), szMessage ); - } - - return success; -} - -//*************************************************************************** - -#ifdef __MINGW32__ -int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR /*lpCmdLine*/, int ) -#else -int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR /*lpCmdLine*/, int ) -#endif -{ - int exitcode = -1; - int argc = __argc; - -#ifdef __MINGW32__ - char **argv = __argv; -#else -#ifdef _UNICODE - char **argv = new char *[argc + 1]; - - for ( int argn = 0; argn < argc; argn++ ) - { - int nBytes = WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, NULL, 0, NULL, NULL ); - argv[argn] = new char[nBytes]; - WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, argv[argn], nBytes, NULL, NULL ); - } - argv[argc] = NULL; -#else - char **argv = __targv; -#endif -#endif - - osl_setCommandArgs( argc, argv ); - - PEXCEPTION_POINTERS pExceptionPointers = NULL; - DWORD dwProcessId = 0; - DWORD dwThreadId = 0; - - WSADATA wsaData; - WORD wVersionRequested; - - wVersionRequested = MAKEWORD(1, 1); - WSAStartup(wVersionRequested, &wsaData); - - CrashReportParams Params; - - Params.ReadFromRegistry(); - Params.ReadFromEnvironment(); - - if ( ReadBootstrapParams( Params ) && - ParseCommandArgs( &dwProcessId, &pExceptionPointers, &dwThreadId ) ) - { - bool bGotDumpFile; - - if ( g_bLoadReport ) - bGotDumpFile = FindDumpFile(); - else - bGotDumpFile = WriteDumpFile( dwProcessId, pExceptionPointers, dwThreadId ); - - if( bGotDumpFile ) - { - boost::unordered_map< string, string > aLibraries; - - if ( g_bLoadReport ) - { - g_fpStackFile = _open_reportfile( _T(".stk"), _T("rb") ); - g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("rb") ); - } - else - { - if ( g_bSendReport ) - { - g_fpStackFile = _tmpfile(); - g_fpChecksumFile = _tmpfile(); - } - else - { - g_fpStackFile = _open_reportfile( _T(".stk"), _T("w+b") ); - g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("w+b") ); - - FILE *fpUnsent = _open_reportfile( _T(".lck"), _T("w+b") ); - if ( fpUnsent ) - { - fprintf( fpUnsent, "Unsent\r\n" ); - fclose( fpUnsent ); - } - } - - WriteStackFile( g_fpStackFile, aLibraries, dwProcessId, pExceptionPointers ); - WriteChecksumFile( g_fpChecksumFile, aLibraries ); - WriteReportFile( &Params ); - - FILE *fpPreview = _open_reportfile( _T(".prv"), _T("w+b") ); - - if ( fpPreview ) - { - FILE *fp = fopen( g_szReportFileNameA, "rb" ); - if ( fp ) - { - fcopy( fp, fpPreview ); - fclose( fp ); - } - fclose( fpPreview ); - } - } - - if ( g_bSendReport ) - { - InitCommonControls(); - - // Actually this should never be true anymore - if ( !g_bNoUserInterface && InitRichEdit() ) - { - - INT_PTR result = DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_DIALOG_FRAME), NULL, DialogProc, (LPARAM)&Params ); - - if ( result > 0 ) - { - exitcode = 0; - } - DeinitRichEdit(); - } - else - { - WriteCommentFile( Params.sComment.c_str() ); - WriteReportFile( &Params ); - if ( SendCrashReport( NULL, Params ) ) - exitcode = 0; - } - - - if ( g_szReportFileNameA[0] ) - DeleteFileA( g_szReportFileNameA ); - - if ( g_szCommentFileNameA[0] ) - DeleteFileA( g_szCommentFileNameA ); - } - else - { - if ( g_szReportFileNameA[0] ) - DeleteFileA( g_szReportFileNameA ); - exitcode = 0; - } - - if ( g_szDumpFileNameA[0] && g_bSendReport ) - DeleteFileA( g_szDumpFileNameA ); - - if ( g_fpStackFile ) - fclose( g_fpStackFile ); - - if ( g_fpChecksumFile ) - fclose( g_fpChecksumFile ); - } - } - - - return exitcode; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/crashrep/source/win32/soreport.cxx b/crashrep/source/win32/soreport.cxx new file mode 100644 index 000000000000..fc8886c542eb --- /dev/null +++ b/crashrep/source/win32/soreport.cxx @@ -0,0 +1,2873 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#define UNICODE +#define WIN32_LEAN_AND_MEAN +#if defined _MSC_VER +#pragma warning(push, 1) +#pragma warning(disable:4917) +#endif +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define _UNICODE +#include + +#define _RICHEDIT_VER 0x0200 +#include + +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#if _RICHEDIT_VER >= 0x0200 +#define RICHEDIT TEXT("riched20.dll") +#else +#define RICHEDIT TEXT("riched32.dll") +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "resource.h" +#include "base64.h" + +#define FORMATBUFSIZE (8*1024) +#define MAX_TEXT_BUFFER (32*1024-1) +#define MAX_HOSTNAME (1024) + +#ifdef __MINGW32__ +#include +#else +#include +#endif + +#ifdef _UNICODE +#define tstring wstring +#else +#define tstring string +#endif + +using namespace ::std; + + +wstring g_wstrProductKey; +string g_strDefaultLanguage; +FILE *g_fpStackFile = NULL; +FILE *g_fpChecksumFile = NULL; +DWORD g_dwExceptionCode = 0; + +CHAR g_szReportServerA[MAX_HOSTNAME] = ""; +USHORT g_uReportPort = 80; + +TCHAR g_szBuildId[256] = TEXT(""); + +TCHAR g_szDumpFileName[MAX_PATH] = TEXT(""); + +CHAR g_szDumpFileNameA[MAX_PATH] = ""; +CHAR g_szCommentFileNameA[MAX_PATH] = ""; +CHAR g_szReportFileNameA[MAX_PATH] = ""; + + +bool g_bNoUserInterface = false; +bool g_bSendReport = false; +bool g_bLoadReport = false; + +#define REPORT_SERVER g_szReportServerA +#define REPORT_PORT g_uReportPort + + +//*************************************************************************** +// tmpfile from msvcrt creates the temporary file in the root of the current +// volume and can fail. + +static FILE *_xfopen( const _TCHAR *file, const _TCHAR *mode ) +{ + return _tfopen( file, mode ); +} + + +static FILE *_tmpfile(void) +{ + FILE *fp = NULL; + + TCHAR szTempPath[MAX_PATH]; + + if ( GetTempPath( SAL_N_ELEMENTS(szTempPath), szTempPath ) ) + { + TCHAR szFileName[MAX_PATH]; + + if ( GetTempFileName( szTempPath, TEXT("CRT"), 0, szFileName ) ) + { + HANDLE hFile = CreateFile( + szFileName, + GENERIC_READ | GENERIC_WRITE, + 0, NULL, + OPEN_EXISTING, + FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_NORMAL, + NULL ); + + if ( IsValidHandle( hFile ) ) + { + int fd = _open_osfhandle( (int)hFile, 0 ); + + fp = _fdopen( fd, "w+b" ); + } + } + } + + return fp; +} +//*************************************************************************** + +static BOOL GetCrashDataPath( LPTSTR szBuffer ) +{ + ::rtl::OUString ustrValue(RTL_CONSTASCII_USTRINGPARAM("${$BRAND_BASE_DIR/program/bootstrap.ini:UserInstallation}")); + ::rtl::Bootstrap::expandMacros( ustrValue ); + + if ( ustrValue.getLength() ) + { + ustrValue += ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/user/crashdata")); + + ::osl::FileBase::RC result = ::osl::Directory::createPath( ustrValue ); + + if ( ::osl::FileBase::E_None == result || ::osl::FileBase::E_EXIST == result ) + { + ::rtl::OUString ustrPath; + + result = ::osl::FileBase::getSystemPathFromFileURL( ustrValue, ustrPath ); + if ( ::osl::FileBase::E_None == result ) + { + _tcsncpy( szBuffer, reinterpret_cast(ustrPath.getStr()), MAX_PATH ); + return TRUE; + } + } + } + + return FALSE; +} + + +static FILE *_open_reportfile( LPCTSTR lpExt, LPCTSTR lpMode ) +{ + FILE *fp = NULL; + TCHAR szAppDataPath[MAX_PATH] = _T(""); + + if ( GetCrashDataPath( szAppDataPath ) ) + { + _tcscat( szAppDataPath, _T("\\crashdat") ); + _tcscat( szAppDataPath, lpExt ); + + fp = _xfopen( szAppDataPath, lpMode ); + } + + return fp; +} + +//*************************************************************************** + +struct CrashReportParams +{ + BOOL fAllowContact; + tstring sEmail; + tstring sTitle; + tstring sComment; + ULONG uInternetConnection; + tstring sProxyServer; + tstring sProxyPort; + + CrashReportParams(); + + void WriteToRegistry(); + void ReadFromRegistry(); + void ReadFromEnvironment(); +}; + +bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams ); +BOOL WriteCommentFile( LPCTSTR lpComment ); + +//*************************************************************************** + +LONG RegReadValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPVOID lpData, DWORD cbData ) +{ + HKEY hKey = NULL; + LONG lResult; + + lResult = RegOpenKeyEx( hBaseKey, lpSubKey, 0, KEY_QUERY_VALUE, &hKey ); + + if ( ERROR_SUCCESS == lResult ) + { + lResult = RegQueryValueEx( hKey, lpValueName, NULL, NULL, (LPBYTE)lpData, &cbData ); + RegCloseKey( hKey ); + } + + return lResult; +} + +//*************************************************************************** + +LONG RegWriteValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData ) +{ + HKEY hKey = NULL; + LONG lResult; + + lResult = RegCreateKeyEx( hBaseKey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL ); + + if ( ERROR_SUCCESS == lResult ) + { + lResult = RegSetValueEx( hKey, lpValueName, NULL, dwType, (CONST BYTE *)lpData, cbData ); + RegCloseKey( hKey ); + } + + return lResult; +} + +//*************************************************************************** + +CrashReportParams::CrashReportParams() +{ + fAllowContact = FALSE; + sTitle = TEXT(""); + sComment = TEXT(""); + sEmail = TEXT(""); + uInternetConnection = 0; + sProxyServer = TEXT(""); + sProxyPort = TEXT(""); +} + +//*************************************************************************** + +void CrashReportParams::ReadFromRegistry() +{ + TCHAR szBuffer[2048]; + + if ( ERROR_SUCCESS == RegReadValue( + HKEY_CURRENT_USER, + TEXT("SOFTWARE\\LibreOffice\\CrashReport"), + TEXT("HTTPProxyServer"), + szBuffer, + sizeof(szBuffer) ) ) + sProxyServer = szBuffer; + + DWORD dwProxyPort; + + if ( ERROR_SUCCESS == RegReadValue( + HKEY_CURRENT_USER, + TEXT("SOFTWARE\\LibreOffice\\CrashReport"), + TEXT("HTTPProxyPort"), + &dwProxyPort, + sizeof(dwProxyPort) ) ) + { + _stprintf( szBuffer, TEXT("%d"), dwProxyPort ); + sProxyPort = szBuffer; + } + + if ( ERROR_SUCCESS == RegReadValue( + HKEY_CURRENT_USER, + TEXT("SOFTWARE\\LibreOffice\\CrashReport"), + TEXT("ReturnAddress"), + szBuffer, + sizeof(szBuffer) ) ) + sEmail = szBuffer; + + RegReadValue( + HKEY_CURRENT_USER, + TEXT("SOFTWARE\\LibreOffice\\CrashReport"), + TEXT("AllowContact"), + &fAllowContact, + sizeof(fAllowContact) ); + + RegReadValue( + HKEY_CURRENT_USER, + TEXT("SOFTWARE\\LibreOffice\\CrashReport"), + TEXT("HTTPConnection"), + &uInternetConnection, + sizeof(uInternetConnection) ); +} + +//*************************************************************************** + +void CrashReportParams::WriteToRegistry() +{ + RegWriteValue( + HKEY_CURRENT_USER, + TEXT("SOFTWARE\\LibreOffice\\CrashReport"), + TEXT("HTTPProxyServer"), REG_SZ, + sProxyServer.c_str(), + sizeof(TCHAR) * (sProxyServer.length() + 1) ); + + LPTSTR endptr = NULL; + DWORD dwProxyPort = _tcstoul( sProxyPort.c_str(), &endptr, 10 ); + + RegWriteValue( + HKEY_CURRENT_USER, + TEXT("SOFTWARE\\LibreOffice\\CrashReport"), + TEXT("HTTPProxyPort"), REG_DWORD, + &dwProxyPort, + sizeof(DWORD) ); + + RegWriteValue( + HKEY_CURRENT_USER, + TEXT("SOFTWARE\\LibreOffice\\CrashReport"), + TEXT("AllowContact"), REG_DWORD, + &fAllowContact, + sizeof(DWORD) ); + + + RegWriteValue( + HKEY_CURRENT_USER, + TEXT("SOFTWARE\\LibreOffice\\CrashReport"), + TEXT("HTTPConnection"), REG_DWORD, + &uInternetConnection, + sizeof(DWORD) ); + + RegWriteValue( + HKEY_CURRENT_USER, + TEXT("SOFTWARE\\LibreOffice\\CrashReport"), + TEXT("ReturnAddress"), REG_SZ, + sEmail.c_str(), + sizeof(TCHAR) * (sEmail.length() + 1) ); +} + +//*************************************************************************** + +void CrashReportParams::ReadFromEnvironment() +{ + TCHAR szBuffer[2048]; + + DWORD dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYSERVER"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + + if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) + sProxyServer = szBuffer; + + dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYPORT"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + + if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) + sProxyPort = szBuffer; + + dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_RETURNADDRESS"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + + if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) + { + sEmail = szBuffer; + // fAllowContact = TRUE; + } + + dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPCONNECTIONTYPE"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + + if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) + { + if ( 0 == _tcsicmp( szBuffer, _T("DIRECT") ) ) + uInternetConnection = 1; + else if ( 0 == _tcsicmp( szBuffer, _T("MANUALPROXY") ) ) + uInternetConnection = 2; + else if ( 0 == _tcsicmp( szBuffer, _T("SYSTEMDEFAULT") ) ) + uInternetConnection = 0; + } + + dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_SUBJECT"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + + if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) + sTitle = szBuffer; + + + dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_BODYFILE"), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + + if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) ) + { + FILE *fp = _xfopen( szBuffer, _T("rb") ); + + if ( fp ) + { + CHAR aUTF8Buffer[256]; + size_t nBytesRead; + + sComment = TEXT(""); + + while ( 0 != (nBytesRead = fread( aUTF8Buffer, sizeof(aUTF8Buffer[0]), SAL_N_ELEMENTS(aUTF8Buffer), fp )) ) + { + TCHAR aBuffer[256+1]; + + DWORD dwCharacters = MultiByteToWideChar( CP_UTF8, 0, aUTF8Buffer, nBytesRead, aBuffer, SAL_N_ELEMENTS(aBuffer) - 1 ); + aBuffer[dwCharacters] = 0; + sComment += aBuffer; + } + + fclose( fp ); + } + } +} + +//*************************************************************************** + +typedef BOOL (WINAPI *MiniDumpWriteDump_PROC)( + IN HANDLE hProcess, + IN DWORD ProcessId, + IN HANDLE hFile, + IN MINIDUMP_TYPE DumpType, + IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL + IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL + IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL + ); + +//*************************************************************************** + +static BOOL WINAPI InitRichEdit() +{ + return (NULL != LoadLibrary( RICHEDIT )); +} + +//*************************************************************************** + +static BOOL WINAPI DeinitRichEdit() +{ + return FreeLibrary( GetModuleHandle( RICHEDIT ) ); +} + +//*************************************************************************** + +static string trim_string( const string& rString ) +{ + string temp = rString; + + while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' ) + temp.erase( 0, 1 ); + + string::size_type len = temp.length(); + + while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' ) + { + temp.erase( len - 1, 1 ); + len = temp.length(); + } + + return temp; +} + +//*************************************************************************** + +static int LoadAndFormatString( HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax ) +{ + TCHAR szBuffer[FORMATBUFSIZE]; + TCHAR szBuffer2[FORMATBUFSIZE]; + + LoadString( hInstance, uID, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + + LPCTSTR src; + LPTSTR dest; + for ( dest = szBuffer2, src = szBuffer; *src; src++, dest++ ) + { + switch ( *src ) + { + case '~': + *dest = '&'; + break; + case '\\': + switch ( *(++src) ) + { + case 'n': + *dest = '\n'; + break; + case 'r': + *dest = '\r'; + break; + default: + *dest = *src; + break; + } + break; + default: + *dest = *src; + break; + } + } + *dest = *src; + return ExpandEnvironmentStrings( szBuffer2, lpBuffer, nBufferMax ); +} + + +//*************************************************************************** + +static string wstring2utf8( const wstring &rString ) +{ + int nBufSize = WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, NULL, 0, NULL, FALSE ); + + LPSTR pBuffer = (LPSTR)alloca( nBufSize ); + + WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, pBuffer, nBufSize, NULL, FALSE ); + + return string( pBuffer ); +} + +//*************************************************************************** + +static string xml_encode( const string &rString ) +{ + string temp = rString; + string::size_type pos = 0; + + // First replace all occurrences of '&' because it may occur in further + // encoded chardters too + + for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 ) + temp.replace( pos, 1, "&" ); + + for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 ) + temp.replace( pos, 1, "<" ); + + for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 ) + temp.replace( pos, 1, ">" ); + + return temp; +} + +//*************************************************************************** + +static size_t fcopy( FILE *fpin, FILE *fpout ) +{ + char buffer[1024]; + size_t nBytesWritten = 0; + + if ( fpin && fpout ) + { + size_t nBytes; + while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) ) + { + nBytesWritten += fwrite( buffer, 1, nBytes, fpout ); + } + } + + return nBytesWritten; +} + +//*************************************************************************** + +static string GetModuleDirectory( HMODULE hModule ) +{ + TCHAR szModuleName[MAX_PATH] = TEXT(""); + TCHAR szDrive[_MAX_DRIVE]; + TCHAR szDir[_MAX_DIR]; + TCHAR szFName[_MAX_FNAME]; + TCHAR szExt[_MAX_EXT]; + + if ( GetModuleFileName( hModule, szModuleName, MAX_PATH ) ) + { + _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt ); + _tmakepath( szModuleName, szDrive, szDir, _T(""), _T("") ); + } + + CHAR szModuleNameUTF8[MAX_PATH] = ""; + + WideCharToMultiByte( CP_UTF8, 0, szModuleName, -1, szModuleNameUTF8, SAL_N_ELEMENTS(szModuleNameUTF8), NULL, NULL ); + return string( szModuleNameUTF8 ); +} + +//*************************************************************************** + +string GetFileDirectory( const string& rFilePath ) +{ + string aDir = rFilePath; + size_t pos = aDir.rfind( '\\' ); + + if ( string::npos != pos ) + aDir.erase( pos + 1 ); + else + aDir = ""; + + return aDir; +} + +//*************************************************************************** + +string GetFileName( const string& rFilePath ) +{ + string aName = rFilePath; + size_t pos = aName.rfind( '\\' ); + + if ( string::npos != pos ) + return aName.substr( pos + 1 ); + else + return aName; +} + +//*************************************************************************** + +BOOL WriteReportFile( CrashReportParams *pParams ) +{ + BOOL fSuccess = FALSE; + TCHAR szTempPath[MAX_PATH]; + + if ( GetTempPath( SAL_N_ELEMENTS(szTempPath), szTempPath ) ) + { + TCHAR szFileName[MAX_PATH]; + + if ( GetTempFileName( szTempPath, TEXT("RPM"), 0, szFileName ) ) + { + HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + + if ( hFile ) + { + int fd = _open_osfhandle( (LONG)hFile, _O_TEXT ); + FILE *fp = _fdopen( fd, "w+t" ); + CHAR szTitle[1024] = ""; + CHAR szBuildId[1024] = ""; + CHAR szEmail[1024] = ""; + const char *pszUserType = getenv( "STAROFFICE_USERTYPE" ); + + WideCharToMultiByte( CP_UTF8, 0, pParams->sTitle.c_str(), -1, szTitle, sizeof(szTitle), NULL, NULL ); + WideCharToMultiByte( CP_UTF8, 0, g_szBuildId, -1, szBuildId, sizeof(szBuildId), NULL, NULL ); + WideCharToMultiByte( CP_UTF8, 0, pParams->sEmail.c_str(), -1, szEmail, sizeof(szEmail), NULL, NULL ); + + fprintf( fp, + "\n" + "\n" + "\n" + "\n", + pszUserType ? pszUserType : "", + pParams->fAllowContact ? "true" : "false", + pParams->fAllowContact ? xml_encode(szEmail).c_str() : "" + ); + + fprintf( fp, + "%s\n", + xml_encode(szTitle).c_str() ); + + fprintf( fp, + "\n" + "\n" + "\n" + + "\n", + szBuildId, + _INPATH, + xml_encode(g_strDefaultLanguage).c_str(), + xml_encode(GetModuleDirectory( NULL )).c_str(), + g_dwExceptionCode, + xml_encode(wstring2utf8(g_wstrProductKey)).c_str() + ); + + OSVERSIONINFO VersionInfo; + + ZeroMemory( &VersionInfo, sizeof(VersionInfo) ); + VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo ); + + GetVersionEx( &VersionInfo ); + + fprintf( fp, + "\n" + "\n" + , + VER_PLATFORM_WIN32_NT == VersionInfo.dwPlatformId ? "Windows NT" : "Windows", + VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion, + VersionInfo.dwBuildNumber, + GetUserDefaultLangID() + + ); + fprintf( fp, "\n" ); + fprintf( fp, "\n" ); + + fseek( g_fpStackFile, 0, SEEK_SET ); + fcopy( g_fpStackFile, fp ); + + fseek( g_fpChecksumFile, 0, SEEK_SET ); + fcopy( g_fpChecksumFile, fp ); + + fprintf( fp, "\n" ); + + fclose( fp ); + + fSuccess = TRUE; + + WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szReportFileNameA, MAX_PATH, NULL, NULL ); + } + + if ( !fSuccess ) + DeleteFile( szFileName ); + } + } + + return fSuccess; +} + +//*************************************************************************** + +static BOOL SaveDumpFile( HWND hwndOwner ) +{ + OPENFILENAME ofn; + TCHAR szFileName[MAX_PATH] = TEXT(""); + + ZeroMemory( &ofn, sizeof(ofn) ); + ofn.lStructSize = sizeof(ofn); + + ofn.hwndOwner = hwndOwner; + ofn.lpstrFilter = TEXT("*.dmp\0*.dmp\0*.*\0*.*\0"); + ofn.lpstrFile = szFileName; + ofn.nMaxFile = MAX_PATH; + ofn.Flags = OFN_ENABLESIZING | OFN_LONGNAMES | OFN_OVERWRITEPROMPT; + ofn.lpstrDefExt = TEXT("dmp"); + + if ( GetSaveFileName( &ofn ) ) + { + return CopyFile( g_szDumpFileName, szFileName, FALSE ); + } + return FALSE; +} + +//*************************************************************************** + +static BOOL ScreenToClientRect( HWND hwnd, LPRECT lprc ) +{ + return ScreenToClient( hwnd, (LPPOINT)&lprc->left ) && ScreenToClient( hwnd, (LPPOINT)&lprc->right ); +} + +static BOOL SetWindowRect( HWND hwnd, const RECT *lprc, BOOL fRepaint ) +{ + return MoveWindow( hwnd, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, fRepaint ); +} + +#define GM_LOX 0x01 +#define GM_HIX 0x02 +#define GM_LOY 0x04 +#define GM_HIY 0x08 + +static BOOL SetGrowMode( HWND hwnd, DWORD dwGrowMode ) +{ + return SetProp( hwnd, TEXT("GrowMode"), (HANDLE)dwGrowMode ); +} + +static DWORD GetGrowMode( HWND hwnd ) +{ + return (DWORD)GetProp( hwnd, TEXT("GrowMode") ); +} + +static BOOL GrowWindow( HWND hwnd, LONG dxClient, LONG dyClient, BOOL fRepaint ) +{ + DWORD dwGrowMode = GetGrowMode( hwnd ); + RECT rc; + + GetWindowRect( hwnd, &rc ); + + if ( dwGrowMode & GM_LOX ) + rc.left += dxClient; + if ( dwGrowMode & GM_HIX ) + rc.right += dxClient; + if ( dwGrowMode & GM_LOY ) + rc.top += dyClient; + if ( dwGrowMode & GM_HIY ) + rc.bottom += dyClient; + + ScreenToClientRect( GetParent( hwnd ), &rc ); + SetWindowRect( hwnd, &rc, fRepaint ); + + return TRUE; +} + +BOOL CALLBACK GrowChildWindows( + HWND hwnd, // handle to child window + LPARAM lParam // application-defined value +) +{ + LONG cx = (SHORT)LOWORD( lParam ); + LONG cy = (SHORT)HIWORD( lParam ); + + GrowWindow( hwnd, cx, cy, TRUE ); + + return TRUE; +} + +BOOL CALLBACK PreviewDialogProc( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ) +{ + static RECT rcClient; + + switch ( uMsg ) + { + case WM_SIZE: + { + LONG cx = LOWORD( lParam ); + LONG cy = HIWORD( lParam ); + LONG dxClient, dyClient; + + dxClient = cx - rcClient.right; + dyClient = cy - rcClient.bottom; + + EnumChildWindows( hwndDlg, GrowChildWindows, MAKELONG( (SHORT)dxClient, (SHORT)dyClient) ); + + GetClientRect( hwndDlg, &rcClient ); + } + break; + case WM_INITDIALOG: + { + GetClientRect( hwndDlg, &rcClient ); + SetGrowMode( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GM_HIX | GM_HIY ); + SetGrowMode( GetDlgItem(hwndDlg, IDOK), GM_LOX | GM_HIX | GM_LOY | GM_HIY ); + + CrashReportParams *pParams = (CrashReportParams *)lParam; + + TCHAR szBuffer[256] = TEXT(""); + HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE ); + HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT ); + + GetWindowText( hwndParent, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + SetWindowText( hwndDlg, szBuffer ); + + LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer ); + + basic_string aString; + + aString.append( pParams->sTitle ); + aString.append( _T("\r\n\r\n") ); + aString.append( pParams->sComment ); + aString.append( _T("\r\n---------- report ----------\r\n") ); + + FILE *fp = fopen( g_szReportFileNameA, "r" ); + + if ( fp ) + { + char buf[1024]; + + while ( fgets( buf, SAL_N_ELEMENTS(buf), fp ) != NULL ) + { + WCHAR bufW[1024]; + + MultiByteToWideChar( CP_UTF8, 0, buf, -1, bufW, SAL_N_ELEMENTS(bufW) ); + + aString.append( bufW ); + } + + fclose( fp ); + } + + aString.append( _T("\r\n---------- stack ----------\r\n") ); + + fp = fopen( g_szDumpFileNameA, "rb" ); + + if ( fp ) + { + unsigned char buf[16]; + int count; + + do + { + int i; + + count = fread( buf, sizeof(buf[0]), SAL_N_ELEMENTS(buf), fp ); + + for ( i = 0; i < count; i++ ) + { + TCHAR output[16]; + + _sntprintf( output, SAL_N_ELEMENTS(output), _T("%02X\x20"), buf[i] ); + aString.append( output ); + } + for ( ; i < SAL_N_ELEMENTS(buf); i++ ) + { + aString.append( _T("\x20\x20\x20") ); + } + + for ( i = 0; i < count; i++ ) + { + TCHAR output[2]; + + if ( (int)buf[i] >= 0x20 && (int)buf[i] <= 0x7F ) + output[0] = (TCHAR)buf[i]; + else + output[0] = '.'; + output[1] = 0; + aString.append( output ); + } + + aString.append( _T("\r\n") ); + + } while ( count ); + + fclose( fp ); + } + Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), aString.c_str() ); + SetWindowFont( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GetStockObject( SYSTEM_FIXED_FONT ), TRUE ); + } + return TRUE; + case WM_COMMAND: + switch ( LOWORD(wParam) ) + { + case IDOK: + case IDCANCEL: + EndDialog( hwndDlg, wParam ); + return TRUE; + } + break; + default: + break; + } + + return FALSE; +} +//*************************************************************************** + +static void PreviewReport( HWND hwndParent, CrashReportParams *pParams ) +{ + HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE ); + + WriteReportFile( pParams ); + + DialogBoxParam( + hInstance, + MAKEINTRESOURCE(IDD_PREVIEW_FRAME), + hwndParent, + PreviewDialogProc, + (LPARAM)pParams + ); + + DeleteFileA( g_szReportFileNameA ); +} +//*************************************************************************** +void UpdateOptionsDialogControls( HWND hwndDlg ) +{ + if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED ) + { + EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), TRUE ); + EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), TRUE ); + } + else + { + EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), FALSE ); + EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), FALSE ); + } +} + +//*************************************************************************** + +BOOL CALLBACK OptionsDialogProc( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ) +{ + static CrashReportParams *pParams; + + switch ( uMsg ) + { + case WM_INITDIALOG: + { + TCHAR szBuffer[1024] = TEXT(""); + HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE ); + //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT ); + + pParams = (CrashReportParams *)lParam; + + LoadAndFormatString( hInstance, IDS_OPTIONS_CAPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + SetWindowText( hwndDlg, szBuffer ); + + LoadAndFormatString( hInstance, IDS_PROXY_SETTINGS_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Static_SetText( GetDlgItem(hwndDlg, IDC_PROXY_SETTINGS), szBuffer ); + + LoadAndFormatString( hInstance, IDS_PROXY_SYSTEM, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM), szBuffer ); + + LoadAndFormatString( hInstance, IDS_PROXY_DIRECT, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT), szBuffer ); + + LoadAndFormatString( hInstance, IDS_PROXY_MANUAL, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL), szBuffer ); + + LoadAndFormatString( hInstance, IDS_LABEL_PROXYSERVER, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYSERVER), szBuffer ); + + LoadAndFormatString( hInstance, IDS_LABEL_PROXYPORT, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYPORT), szBuffer ); + + LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer ); + + LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer ); + + Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), pParams->sProxyServer.c_str() ); + Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), pParams->sProxyPort.c_str() ); + + Button_SetCheck( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM + pParams->uInternetConnection), BST_CHECKED ); + + SendMessage( + GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), + EM_SETBKGNDCOLOR, + (WPARAM)FALSE, + GetSysColor( COLOR_3DFACE ) ); + LoadAndFormatString( hInstance, IDS_PROXY_DESCRIPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Edit_SetText( GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), szBuffer ); + + UpdateOptionsDialogControls( hwndDlg ); + } + return TRUE; + case WM_COMMAND: + switch ( LOWORD(wParam) ) + { + case IDC_RADIO_SYSTEM: + case IDC_RADIO_DIRECT: + case IDC_RADIO_MANUAL: + if ( BN_CLICKED == HIWORD(wParam) ) + UpdateOptionsDialogControls( hwndDlg ); + break; + case IDOK: + { + TCHAR szBuffer[1024]; + + Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + pParams->sProxyServer = szBuffer; + + Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + pParams->sProxyPort = szBuffer; + + if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT) ) & BST_CHECKED ) + pParams->uInternetConnection = 1; + else if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED ) + pParams->uInternetConnection = 2; + else + pParams->uInternetConnection = 0; + } + case IDCANCEL: + EndDialog( hwndDlg, wParam ); + return TRUE; + } + break; + default: + break; + } + + return FALSE; +} + +//*************************************************************************** + +static void OptionsDialog( HWND hwndParent, CrashReportParams *pParams ) +{ + HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE ); + + if ( IDOK == DialogBoxParam( + hInstance, + MAKEINTRESOURCE(IDD_OPTIONS_FRAME), + hwndParent, + OptionsDialogProc, + (LPARAM)pParams + ) ) + pParams->WriteToRegistry(); + +} +//*************************************************************************** + +void UpdateReportDialogControls( HWND hwndDlg ) +{ + EnableWindow( + GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), + Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE ); + EnableWindow( + GetDlgItem(hwndDlg, IDC_LABEL_EMAIL), + Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE ); +} + +//*************************************************************************** + +BOOL CALLBACK ReportDialogProc( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM + ) +{ + switch ( uMsg ) + { + case WM_INITDIALOG: + { + CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); + HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); + TCHAR szBuffer[FORMATBUFSIZE]; + + LoadAndFormatString( hInstance, IDS_REPORT_INTRO, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Static_SetText( GetDlgItem(hwndDlg, IDC_REPORT_INTRO), szBuffer ); + + Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT3), szBuffer ); + + LoadAndFormatString( hInstance, IDS_ENTER_TITLE, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_TITLE), szBuffer ); + + LoadAndFormatString( hInstance, IDS_ENTER_DESCRIPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_DESCRIPTION), szBuffer ); + + LoadAndFormatString( hInstance, IDS_SHOW_REPORT_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDC_SHOW_REPORT), szBuffer ); + + LoadAndFormatString( hInstance, IDS_SAVE_REPORT_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), szBuffer ); + + const char *pszUserType = getenv( "STAROFFICE_USERTYPE" ); + if ( pszUserType ) + ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_SHOW ); + else + ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_HIDE ); + + LoadAndFormatString( hInstance, IDS_OPTIONS_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDC_OPTIONS), szBuffer ); + + LoadAndFormatString( hInstance, IDS_ALLOW_CONTACT, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), szBuffer ); + Button_SetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), pParams->fAllowContact ? BST_CHECKED : BST_UNCHECKED ); + + LoadAndFormatString( hInstance, IDS_LABEL_EMAIL, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDC_LABEL_EMAIL), szBuffer ); + + Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), pParams->sEmail.c_str() ); + + UpdateReportDialogControls( hwndDlg ); + } + return TRUE; + case WM_SHOWWINDOW: + if ( (BOOL)wParam ) + { + HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); + CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); + TCHAR szBuffer[FORMATBUFSIZE]; + + LoadAndFormatString( hInstance, IDS_REPORT_CAPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + SetWindowText( GetParent(hwndDlg), szBuffer ); + + LoadAndFormatString( hInstance, IDS_REPORT_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer ); + + LoadAndFormatString( hInstance, IDS_DONOT_SEND_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer ); + + + ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), TRUE ); + ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), TRUE ); + ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), FALSE ); + + Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), pParams->sTitle.c_str() ); + Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), pParams->sComment.c_str() ); + + SetFocus( GetDlgItem(hwndDlg,IDC_EDIT_TITLE) ); + } + break; + case WM_COMMAND: + switch ( LOWORD(wParam) ) + { + case IDC_SHOW_REPORT: + { + TCHAR szBuffer[32767]; + + CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); + + pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT) ) ? TRUE : FALSE; + + Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + pParams->sTitle = szBuffer; + + Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + pParams->sComment = szBuffer; + + Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + pParams->sEmail = szBuffer; + + PreviewReport( GetParent(hwndDlg), pParams ); + } + return TRUE; + case IDC_SAVE_REPORT: + SaveDumpFile( GetParent(hwndDlg) ); + return TRUE; + case IDC_OPTIONS: + { + CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); + OptionsDialog( GetParent(hwndDlg), pParams ); + } + return TRUE; + case IDC_ALLOW_CONTACT: + if ( BN_CLICKED == HIWORD(wParam) ) + UpdateReportDialogControls( hwndDlg ); + return TRUE; + } + break; + default: + break; + } + + return FALSE; +} +//*************************************************************************** + +BOOL CALLBACK WelcomeDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + switch ( uMsg ) + { + case WM_INITDIALOG: + { + HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); + HWND hwndRichEdit = GetDlgItem(hwndDlg, IDC_RICHEDIT21); + TCHAR szBuffer[FORMATBUFSIZE]; + TCHAR szBuffer2[FORMATBUFSIZE]; + TCHAR szURL[256]; + TCHAR szCaption[256]; + + SendMessage( + hwndRichEdit, + EM_SETBKGNDCOLOR, + (WPARAM)FALSE, + GetSysColor( COLOR_3DFACE ) ); + + SendMessage( hwndRichEdit, EM_SETEVENTMASK, 0, ENM_LINK ); + SendMessage( hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0 ); + + LoadAndFormatString( hInstance, IDS_WELCOME_BODY1, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + LoadAndFormatString( hInstance, IDS_WELCOME_BODY2, szBuffer2, SAL_N_ELEMENTS(szBuffer2) ); + _tcsncat( szBuffer, szBuffer2, SAL_N_ELEMENTS(szBuffer) ); + LoadAndFormatString( hInstance, IDS_WELCOME_BODY3, szBuffer2, SAL_N_ELEMENTS(szBuffer2) ); + _tcsncat( szBuffer, szBuffer2, SAL_N_ELEMENTS(szBuffer) ); + LoadString( hInstance, IDS_PRIVACY_URL, szURL, SAL_N_ELEMENTS(szURL) ); + _tcsncat( szBuffer, szURL, SAL_N_ELEMENTS(szBuffer) ); + SetWindowText( hwndRichEdit, szBuffer ); + + LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szCaption, SAL_N_ELEMENTS(szCaption) ); + SetWindowText( GetParent(hwndDlg), szCaption ); + + } + return TRUE; + case WM_SHOWWINDOW: + if ( (BOOL)wParam ) + { + HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); + TCHAR szBuffer[FORMATBUFSIZE]; + + LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + SetWindowText( GetParent(hwndDlg), szBuffer ); + + LoadAndFormatString( hInstance, IDS_WELCOME_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer ); + + LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer ); + + ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), FALSE ); + ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), FALSE ); + ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), TRUE ); + + SetFocus( GetDlgItem(GetParent(hwndDlg),IDNEXT) ); + } + break; + case WM_NOTIFY: + { + LPNMHDR pnmh = (LPNMHDR)lParam; + + if ( pnmh->idFrom == IDC_RICHEDIT21 && pnmh->code == EN_LINK ) + { + ENLINK *plink = (ENLINK*)lParam; + + if ( plink->msg == WM_LBUTTONUP ) + { + TCHAR szBuffer[256]; + TEXTRANGE range; + + range.chrg = plink->chrg; + range.lpstrText = szBuffer; + + SendMessage( pnmh->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&range ); + + ShellExecute( hwndDlg, NULL, szBuffer, NULL, NULL, SW_SHOWDEFAULT ); + } + + } + } + break; + default: + break; + } + + return FALSE; +} +//*************************************************************************** + +BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) +{ + static HWND hwndPages[2] = { NULL }; + static int iActualPage = 0; + + switch ( uMsg ) + { + case WM_INITDIALOG: + { + HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); + TCHAR szBuffer[FORMATBUFSIZE]; + + SetWindowLong( hwndDlg, GWL_USERDATA, (LONG)lParam ); + hwndPages[0] = CreateDialog( + hInstance, + MAKEINTRESOURCE(IDD_WELCOME_PAGE), + hwndDlg, + WelcomeDialogProc ); + + hwndPages[1] = CreateDialog( + hInstance, + MAKEINTRESOURCE(IDD_REPORT_PAGE), + hwndDlg, + ReportDialogProc ); + + CHARFORMAT chfmt; + + chfmt.cbSize = sizeof(chfmt); + chfmt.dwMask = CFM_BOLD; + chfmt.dwEffects = CFE_BOLD; + + SendMessage( + GetDlgItem(hwndDlg, IDC_HEADER), + EM_SETCHARFORMAT, + SCF_ALL, + (LPARAM)&chfmt ); + + LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer ); + + LoadAndFormatString( hInstance, IDS_NEXT_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDNEXT), szBuffer ); + + LoadAndFormatString( hInstance, IDS_SEND_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDFINISH), szBuffer ); + + LoadAndFormatString( hInstance, IDS_BACK_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDBACK), szBuffer ); + + ShowWindow( hwndPages[1], SW_HIDE ); + ShowWindow( hwndPages[0], SW_SHOW ); + + // Let Crash Reporter window stay on top of all other windows + SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); + } + return FALSE; + case WM_CTLCOLORSTATIC: + return (BOOL)CreateSolidBrush(GetSysColor(COLOR_WINDOW)); + case WM_COMMAND: + switch ( LOWORD(wParam) ) + { + case IDBACK: + if ( iActualPage > 0 ) + { + ShowWindow( hwndPages[iActualPage], SW_HIDE ); + ShowWindow( hwndPages[--iActualPage], SW_SHOW ); + } + return TRUE; + case IDNEXT: + if ( iActualPage < SAL_N_ELEMENTS(hwndPages) - 1 ) + { + ShowWindow( hwndPages[iActualPage], SW_HIDE ); + ShowWindow( hwndPages[++iActualPage], SW_SHOW ); + } + return TRUE; + case IDFINISH: + { + TCHAR szBuffer[32767]; + CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( hwndDlg, GWL_USERDATA ); + + pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndPages[1], IDC_ALLOW_CONTACT) ) ? TRUE : FALSE; + + Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_TITLE), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + pParams->sTitle = szBuffer; + + Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_DESCRIPTION), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + pParams->sComment = szBuffer; + + Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_EMAIL), szBuffer, SAL_N_ELEMENTS(szBuffer) ); + pParams->sEmail = szBuffer; + + if ( pParams->fAllowContact && !pParams->sEmail.length() ) + { + TCHAR szMessage[MAX_TEXT_BUFFER]; + + LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_NOEMAILADDRESS, szMessage, SAL_N_ELEMENTS(szMessage) ); + + MessageBox( hwndDlg, szMessage, NULL, MB_ICONERROR | MB_OK ); + break; // Don't end the dialog + } + else + { + pParams->WriteToRegistry(); + + WriteCommentFile( pParams->sComment.c_str() ); + WriteReportFile( pParams ); + + if ( !SendCrashReport( hwndDlg, *pParams ) ) + break; // Don't end the dialog + } + } + // Fallthrough !!! + case IDCANCEL: + EndDialog( hwndDlg, wParam ); + return TRUE; + } + break; + default: + break; + } + + return FALSE; +} + + + +//***************************************************************************** +//* Generate MD5 checksum +//***************************************************************************** + +#define MAGIC_DESCRIPTION_FILLER 'x' +#define MAGIC_DESCRIPTION_COUNT 80 + +static void repatch_soffice_exe( void *pBuffer, size_t nBufSize ) +{ + wchar_t DescriptionBuffer[MAGIC_DESCRIPTION_COUNT]; + + memset( DescriptionBuffer, 0, sizeof(DescriptionBuffer) ); + wcsncpy( DescriptionBuffer, g_wstrProductKey.c_str(), SAL_N_ELEMENTS(DescriptionBuffer) - 1 ); + + bool bPatched = false; + + do + { + void *pFound = memchr( pBuffer, ((char *)DescriptionBuffer)[0], nBufSize ); + + if ( pFound ) + { + size_t distance = (char *)pFound - (char *)pBuffer; + + if ( nBufSize >= distance ) + { + nBufSize -= distance; + + if ( nBufSize >= sizeof(DescriptionBuffer) && + 0 == memcmp( pFound, DescriptionBuffer, sizeof(DescriptionBuffer) ) ) + { + for ( int i = 0; i < 80; i++ ) + { + ((wchar_t *)pFound)[i] = MAGIC_DESCRIPTION_FILLER; + } + bPatched = true; + } + else + { + pBuffer = (void *)(((char *)pFound) + 1); + nBufSize--; + } + } + else + nBufSize = 0; + } + else + nBufSize = 0; + } while ( !bPatched && nBufSize ); +} + +// Normalize executable/library images to prevent different MD5 checksums due +// to a different PE header date/checksum (this doesn't affect the code/data +// sections of a executable/library. Please see tools/source/bootstrp/md5.cxx +// where the same method is also used. The tool so_checksum creates the MD5 +// checksums during build time. You have to make sure that both methods use the +// same algorithm otherwise there could be problems with stack reports. +static void normalize_pe_image(sal_uInt8* buffer, size_t nBufferSize) +{ + const int OFFSET_PE_OFFSET = 0x3c; + const int OFFSET_COFF_TIMEDATESTAMP = 4; + const int PE_SIGNATURE_SIZE = 4; + const int COFFHEADER_SIZE = 20; + const int OFFSET_PE_OPTIONALHEADER_CHECKSUM = 64; + + // Check the header part of the file buffer + if (buffer[0] == 'M' && buffer[1] == 'Z') + { + unsigned long PEHeaderOffset = (long)buffer[OFFSET_PE_OFFSET]; + if (PEHeaderOffset < nBufferSize-4) + { + if ( buffer[PEHeaderOffset] == 'P' && + buffer[PEHeaderOffset+1] == 'E' && + buffer[PEHeaderOffset+2] == 0 && + buffer[PEHeaderOffset+3] == 0 ) + { + PEHeaderOffset += PE_SIGNATURE_SIZE; + if (PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP < nBufferSize-4) + { + // Set timedatestamp and checksum fields to a normalized + // value to enforce the same MD5 checksum for identical + // Windows executables/libraries. + buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP] = 0; + buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+1] = 0; + buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+2] = 0; + buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+3] = 0; + } + + if (PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM < nBufferSize-4) + { + // Set checksum to a normalized value + buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM] = 0; + buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+1] = 0; + buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+2] = 0; + buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+3] = 0; + } + } + } + } +} + +static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen ) +{ + const int MINIMAL_FILESIZE = 512; + + sal_uInt32 nBytesProcessed = 0; + + FILE *fp = fopen( filename, "rb" ); + + if ( fp ) + { + long nFileSize; + + if ( 0 == fseek( fp, 0, SEEK_END ) && -1 != (nFileSize = ftell(fp)) ) + { + rewind( fp ); + + sal_uInt8 *pBuffer = new sal_uInt8[nFileSize]; + size_t nBytesRead = fread( pBuffer, 1, nFileSize, fp ); + + if ( sal::static_int_cast(nBytesRead) == nFileSize ) + { + if ( 0 == stricmp( GetFileName(filename).c_str(), "soffice.bin" ) ) + repatch_soffice_exe( pBuffer, nBytesRead ); + else if ( nFileSize > MINIMAL_FILESIZE ) + normalize_pe_image( pBuffer, nBytesRead ); + + rtlDigestError error = rtl_digest_MD5 ( + pBuffer, nBytesRead, + pChecksum, nChecksumLen ); + + if ( rtl_Digest_E_None == error ) + nBytesProcessed = nBytesRead; + } + + delete[] pBuffer; + } + fclose( fp ); + } + return nBytesProcessed; +} + +//*************************************************************************** + +static bool WriteStackFile( FILE *fout, boost::unordered_map< string, string >& rLibraries, DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers ) +{ + bool fSuccess = false; + + if ( fout && dwProcessId && pExceptionPointers ) + { + HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId ); + + if ( IsValidHandle(hProcess) ) + { + EXCEPTION_POINTERS aExceptionPointers; + CONTEXT aContextRecord; + + ReadProcessMemory( + hProcess, + pExceptionPointers, + &aExceptionPointers, + sizeof(aExceptionPointers), + NULL ); + + ReadProcessMemory( + hProcess, + aExceptionPointers.ContextRecord, + &aContextRecord, + sizeof(aContextRecord), + NULL ); + + STACKFRAME frame; + + ZeroMemory( &frame, sizeof(frame) ); + frame.AddrPC.Offset = aContextRecord.Eip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Offset = aContextRecord.Ebp; + frame.AddrFrame.Mode = AddrModeFlat; + + BOOL bSuccess; + int frameNum = 0; + + SymInitialize( hProcess, NULL, TRUE ); + + fprintf( fout, "\n" ); + + do + { + fSuccess = true; + + bSuccess = StackWalk( IMAGE_FILE_MACHINE_I386, + hProcess, + NULL, + &frame, + &aContextRecord, + (PREAD_PROCESS_MEMORY_ROUTINE)ReadProcessMemory, + SymFunctionTableAccess, + SymGetModuleBase, + NULL ); + + if ( bSuccess ) + { + // Note: ImageHelp ANSI functions do not have an A postfix while + // Unicode versions have a W postfix. There's no macro + // that depends on define UNICODE + + IMAGEHLP_MODULE moduleInfo; + + ZeroMemory( &moduleInfo, sizeof(moduleInfo) ); + moduleInfo.SizeOfStruct = sizeof(moduleInfo); + + if ( SymGetModuleInfo( hProcess, frame.AddrPC.Offset, &moduleInfo ) ) + { + rLibraries[ GetFileName( moduleInfo.LoadedImageName ).c_str() ] = moduleInfo.LoadedImageName; + + DWORD dwRelOffset = 0; + BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 256 ]; + PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer; + + ZeroMemory( symbolBuffer, sizeof(symbolBuffer) ); + pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); + pSymbol->MaxNameLength = 256; + + if ( SymGetSymFromAddr( hProcess, frame.AddrPC.Offset, &dwRelOffset, pSymbol ) ) + fprintf( fout, "\n", + frameNum, + frame.AddrPC.Offset, + frame.AddrPC.Offset - moduleInfo.BaseOfImage, + xml_encode(pSymbol->Name).c_str(), + frame.AddrPC.Offset - pSymbol->Address, + xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(), + xml_encode( GetFileDirectory( moduleInfo.LoadedImageName )).c_str() + ); + else + fprintf( fout, "\n", + frameNum, + frame.AddrPC.Offset, + frame.AddrPC.Offset - moduleInfo.BaseOfImage, + xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(), + xml_encode(GetFileDirectory( moduleInfo.LoadedImageName )).c_str() + ); + } + else + fprintf( fout, "\n", + frameNum, + frame.AddrPC.Offset + ); + + frameNum++; + } + + } while ( bSuccess ); + + fprintf( fout, "\n" ); + + SymCleanup( hProcess ); + + CloseHandle( hProcess ); + } + + } + + return fSuccess; +} + +bool WriteChecksumFile( FILE *fchksum, const boost::unordered_map< string, string >& rLibraries ) +{ + bool success = false; + + if ( fchksum && rLibraries.size() ) + { + fprintf( fchksum, "\n" ); + + boost::unordered_map< string, string >::const_iterator iter; + + for ( iter = rLibraries.begin(); iter != rLibraries.end(); ++iter ) + { + sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5]; + sal_uInt32 nBytesProcessed = calc_md5_checksum( + iter->second.c_str(), + checksum, sizeof(checksum) ); + + if ( nBytesProcessed ) + { + fprintf( fchksum, "\n", + nBytesProcessed, + GetFileName( iter->first ).c_str() ); + } + } + + fprintf( fchksum, "\n" ); + + success = true; + } + + return success; +} + +//*************************************************************************** + +BOOL FindDumpFile() +{ + TCHAR szFileName[MAX_PATH]; + + if ( GetCrashDataPath( szFileName ) ) + { + _tcscat( szFileName, _T("\\crashdat.dmp") ); + + HANDLE hFile = CreateFile( + szFileName, + GENERIC_READ, + 0, NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL ); + + if ( hFile ) + { + CloseHandle( hFile ); + + WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL ); + _tcscpy( g_szDumpFileName, szFileName ); + + return TRUE; + } + } + + return FALSE; +} + +BOOL WriteDumpFile( DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers, DWORD dwThreadId ) +{ + BOOL fSuccess = FALSE; + MINIDUMP_EXCEPTION_INFORMATION ExceptionParam; + + HMODULE hDbgHelp = LoadLibrary( _T("DBGHELP.DLL" ) ); + MiniDumpWriteDump_PROC pMiniDumpWriteDump = NULL; + + if ( hDbgHelp ) + { + pMiniDumpWriteDump = (MiniDumpWriteDump_PROC)GetProcAddress( hDbgHelp, "MiniDumpWriteDump" ); + + if ( !pMiniDumpWriteDump ) + { + FreeLibrary( hDbgHelp ); + return false; + } + } + + if ( !pMiniDumpWriteDump ) + return false; + + HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId ); + + if ( IsValidHandle(hProcess) ) + { + TCHAR szTempPath[MAX_PATH]; + + if ( GetCrashDataPath( szTempPath ) ) + { + TCHAR szFileName[MAX_PATH]; + + _tcscpy( szFileName, szTempPath ); + _tcscat( szFileName, _T("\\crashdat.dmp") ); + { + HANDLE hFile = CreateFile( + szFileName, + GENERIC_READ | GENERIC_WRITE, + 0, NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL ); + + if ( hFile ) + { + PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam = NULL; + if ( pExceptionPointers && dwThreadId ) + { + ExceptionParam.ThreadId = dwThreadId; + ExceptionParam.ExceptionPointers = pExceptionPointers; + ExceptionParam.ClientPointers = TRUE; + + EXCEPTION_POINTERS aExceptionPointers; + EXCEPTION_RECORD aExceptionRecord; + + ReadProcessMemory( + hProcess, + pExceptionPointers, + &aExceptionPointers, + sizeof(aExceptionPointers), + NULL ); + + + ReadProcessMemory( + hProcess, + aExceptionPointers.ExceptionRecord, + &aExceptionRecord, + sizeof(aExceptionRecord), + NULL ); + + g_dwExceptionCode = aExceptionRecord.ExceptionCode; + + lpExceptionParam = &ExceptionParam; + } + + fSuccess = pMiniDumpWriteDump( hProcess, dwProcessId, hFile, MiniDumpNormal, lpExceptionParam, NULL, NULL ); + + CloseHandle( hFile ); + + WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL ); + _tcscpy( g_szDumpFileName, szFileName ); + } + + if ( !fSuccess ) + DeleteFile( szFileName ); + } + } + + CloseHandle( hProcess ); + } + + FreeLibrary( hDbgHelp ); + + return fSuccess; +} + +//*************************************************************************** + +static DWORD FindProcessForImage( LPCTSTR lpImagePath ) +{ + DWORD dwProcessId = 0; + DWORD aProcesses[1024]; + DWORD dwSize = 0; + TCHAR szShortImagePath[MAX_PATH]; + + if ( GetShortPathName( lpImagePath, szShortImagePath, SAL_N_ELEMENTS(szShortImagePath) ) && + EnumProcesses( aProcesses, sizeof(aProcesses), &dwSize ) ) + { + unsigned nProcesses = dwSize / sizeof(aProcesses[0]); + + for ( unsigned i = 0; !dwProcessId && i < nProcesses; i++ ) + { + HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] ); + + if ( IsValidHandle(hProcess) ) + { + TCHAR szModulePath[MAX_PATH+1]; + + if ( GetModuleFileNameEx( hProcess, NULL, szModulePath, MAX_PATH ) ) + { + TCHAR szShortModulePath[MAX_PATH]; + + if ( GetShortPathName( szModulePath, szShortModulePath, SAL_N_ELEMENTS(szShortModulePath) ) ) + { + if ( 0 == _tcsicmp( szShortModulePath, szShortImagePath ) ) + dwProcessId = aProcesses[i]; + } + } + + CloseHandle( hProcess ); + } + } + } + + return dwProcessId; +} +//*************************************************************************** + +static bool ParseCommandArgs( LPDWORD pdwProcessId, PEXCEPTION_POINTERS* ppException, LPDWORD pdwThreadId ) +{ + int argc = __argc; +#ifdef __MINGW32__ +#ifdef _UNICODE + TCHAR **argv = reinterpret_cast(alloca((argc+1)*sizeof(WCHAR*))); + int *sizes = reinterpret_cast(alloca(argc*sizeof(int))); + int argsize=0; + char **ptr; + int i; + ptr=__argv; + for (i = 0; i < argc; ++i) + { + sizes[i]=MultiByteToWideChar(CP_ACP, 0, *ptr, -1, NULL, 0); + argsize+=sizes[i]+1; + ++ptr; + } + ++argsize; + TCHAR *args = reinterpret_cast(alloca(argsize*sizeof(WCHAR))); + ptr=__argv; + TCHAR *cptr=args; + for (i = 0; i < argc; ++i) + { + argv[i]=cptr; + MultiByteToWideChar( CP_ACP, 0, *ptr, -1, cptr, sizes[i] ); + ++ptr; + cptr+=sizes[i]; + *cptr=0; + ++cptr; + } + argv[i]=cptr; + *cptr=0; +#else + TCHAR **argv = __argv; +#endif +#else + TCHAR **argv = __targv; +#endif + bool bSuccess = true; + + for ( int argn = 1; bSuccess && argn < argc; argn++ ) + { + if ( 0 == _tcsicmp( argv[argn], _T("-h") ) || + 0 == _tcsicmp( argv[argn], _T("/h") ) || + 0 == _tcsicmp( argv[argn], _T("-?") ) || + 0 == _tcsicmp( argv[argn], _T("/?") ) || + 0 == _tcsicmp( argv[argn], _T("/help") ) || + 0 == _tcsicmp( argv[argn], _T("-help") ) || + 0 == _tcsicmp( argv[argn], _T("--help") ) + ) + { + HINSTANCE hInstance = GetModuleHandle(NULL); + TCHAR szUsage[FORMATBUFSIZE]; + TCHAR szProcess[FORMATBUFSIZE]; + TCHAR szProcessDescription[FORMATBUFSIZE]; + TCHAR szHelpDescription[FORMATBUFSIZE]; + + LoadAndFormatString( hInstance, IDS_MSG_CMDLINE_USAGE, szUsage, SAL_N_ELEMENTS(szUsage) ); + LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID, szProcess, SAL_N_ELEMENTS(szProcess) ); + LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID_DESCRIPTION, szProcessDescription, SAL_N_ELEMENTS(szProcessDescription) ); + LoadAndFormatString( hInstance, IDS_MSG_PARAM_HELP_DESCRIPTION, szHelpDescription, SAL_N_ELEMENTS(szHelpDescription) ); + + _tprintf( + TEXT("\n%s: crashrep %s\n\n") + TEXT("/?, -h[elp] %s\n\n") + TEXT("%-20s %s\n\n"), + szUsage, szProcess, szHelpDescription, szProcess, szProcessDescription + ); + + return true; + } + else if ( 0 == _tcsicmp( argv[argn], _T("-p") ) || + 0 == _tcsicmp( argv[argn], _T("/p") ) ) + { + if ( ++argn < argc ) + *pdwProcessId = _tcstoul( argv[argn], NULL, 0 ); + else + bSuccess = false; + } + else if ( 0 == _tcsicmp( argv[argn], _T("-excp") ) || + 0 == _tcsicmp( argv[argn], _T("/excp") ) ) + { + if ( ++argn < argc ) + *ppException = (PEXCEPTION_POINTERS)_tcstoul( argv[argn], NULL, 0 ); + else + bSuccess = false; + } + else if ( 0 == _tcsicmp( argv[argn], _T("-t") ) || + 0 == _tcsicmp( argv[argn], _T("/t") ) ) + { + if ( ++argn < argc ) + *pdwThreadId = _tcstoul( argv[argn], NULL, 0 ); + else + bSuccess = false; + } + else if ( 0 == _tcsicmp( argv[argn], _T("-noui") ) || + 0 == _tcsicmp( argv[argn], _T("/noui") ) ) + { + g_bNoUserInterface = true; + } + else if ( 0 == _tcsicmp( argv[argn], _T("-send") ) || + 0 == _tcsicmp( argv[argn], _T("/send") ) ) + { + g_bSendReport = true; + } + else if ( 0 == _tcsicmp( argv[argn], _T("-load") ) || + 0 == _tcsicmp( argv[argn], _T("/load") ) ) + { + g_bLoadReport = true; + } + else // treat parameter as image path + { + TCHAR szImagePath[MAX_PATH]; + LPTSTR lpImageName; + + if ( GetFullPathName( argv[argn], MAX_PATH, szImagePath, &lpImageName ) ) + { + DWORD dwProcessId = FindProcessForImage( szImagePath ); + + if ( dwProcessId ) + *pdwProcessId = dwProcessId; + else + bSuccess = false; + } + } + } + + if ( !*pdwProcessId && !g_bLoadReport ) + { + TCHAR szImagePath[MAX_PATH]; + LPTSTR lpImageName; + + if ( GetFullPathName( TEXT("soffice.exe"), MAX_PATH, szImagePath, &lpImageName ) ) + { + DWORD dwProcessId = FindProcessForImage( szImagePath ); + + if ( dwProcessId ) + *pdwProcessId = dwProcessId; + else + bSuccess = false; + } + } + + return bSuccess; +} + +//*************************************************************************** + +BOOL WriteCommentFile( LPCTSTR lpComment ) +{ + BOOL fSuccess = FALSE; + TCHAR szTempPath[MAX_PATH]; + + if ( GetTempPath( SAL_N_ELEMENTS(szTempPath), szTempPath ) ) + { + TCHAR szFileName[MAX_PATH]; + + if ( GetTempFileName( szTempPath, TEXT("CMT"), 0, szFileName ) ) + { + HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); + + if ( hFile ) + { + DWORD dwBytesWritten; + + int needed = WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, NULL, 0, NULL, NULL ); + if ( needed ) + { + char *lpCommentUTF8 = (char *)alloca( needed ); + WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, lpCommentUTF8, needed, NULL, NULL ); + fSuccess = WriteFile( hFile, lpCommentUTF8, strlen(lpCommentUTF8), &dwBytesWritten, NULL ); + } + else + fSuccess = TRUE; + + + CloseHandle( hFile ); + + WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szCommentFileNameA, MAX_PATH, NULL, NULL ); + } + + if ( !fSuccess ) + DeleteFile( szFileName ); + } + } + + return fSuccess; +} + +//*************************************************************************** + +static int _tsetenv( const _TCHAR *lpVar, const _TCHAR *lpValue ) +{ + if ( !lpValue ) + lpValue = _T(""); + + _TCHAR *envstr = (TCHAR *)alloca( (_tcslen( lpVar ) + _tcslen( lpValue ) + 2) * sizeof(_TCHAR) ); + + _tcscpy( envstr, lpVar ); + _tcscat( envstr, _T("=") ); + _tcscat( envstr, lpValue ); + + return _tputenv( envstr ); +} + +static bool read_line( FILE *fp, string& rLine ) +{ + char szBuffer[1024]; + bool bSuccess = false; + bool bEOL = false; + string line; + + + while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) ) + { + int len = strlen(szBuffer); + + bSuccess = true; + + while ( len && szBuffer[len - 1] == '\n' ) + { + szBuffer[--len] = 0; + bEOL = true; + } + + line.append( szBuffer ); + } + + rLine = line; + return bSuccess; +} + +static string get_script_string( const char *pFileName, const char *pKeyName ) +{ + FILE *fp = fopen( pFileName, "rt" ); + string retValue; + + if ( fp ) + { + string line; + string section; + + while ( read_line( fp, line ) ) + { + line = trim_string( line ); + + + string::size_type iEqualSign = line.find( '=', 0 ); + + if ( iEqualSign != string::npos ) + { + string keyname = line.substr( 0, iEqualSign ); + keyname = trim_string( keyname ); + + string value = line.substr( sal::static_int_cast(iEqualSign + 1) ); + value = trim_string( value ); + + if ( value.length() && '\"' == value[0] ) + { + value.erase( 0, 1 ); + + string::size_type iQuotes = value.find( '"', 0 ); + + if ( iQuotes != string::npos ) + value.erase( iQuotes ); + } + + if ( 0 == stricmp( keyname.c_str(), pKeyName ) ) + { + retValue = value; + break; + } + } + } + + fclose( fp ); + } + + return retValue; +} + +static bool ReadBootstrapParams( CrashReportParams &rParams ) +{ + TCHAR szBuffer[256] = TEXT(""); + TCHAR szModuleName[MAX_PATH]; + TCHAR szModuleVersionName[MAX_PATH]; + TCHAR szDrive[_MAX_DRIVE]; + TCHAR szDir[_MAX_DIR]; + TCHAR szFName[_MAX_FNAME]; + TCHAR szExt[_MAX_EXT]; + TCHAR szReportServer[MAX_HOSTNAME]; + TCHAR szReportPort[256]; + bool bSuccess = false; + + GetModuleFileName( NULL, szModuleName, MAX_PATH ); + _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt ); + _tmakepath( szModuleName, szDrive, szDir, _T("bootstrap"), _T(".ini") ); + _tmakepath( szModuleVersionName, szDrive, szDir, _T("version"), _T(".ini") ); + + if ( + GetPrivateProfileString( + TEXT("Bootstrap"), + TEXT("ProductKey"), + TEXT("LibreOffice"), + szBuffer, + SAL_N_ELEMENTS(szBuffer), + szModuleName ) + ) + { + TCHAR *pVersion = _tcschr( szBuffer, ' ' ); + + g_wstrProductKey = szBuffer; + + if ( pVersion ) + { + *pVersion = 0; + pVersion++; + } + else + pVersion = TEXT(""); + + if ( !_tgetenv( _T("PRODUCTNAME") ) ) + { + _tsetenv( TEXT("PRODUCTNAME"), szBuffer ); + } + if ( !_tgetenv( _T("PRODUCTVERSION") ) ) + _tsetenv( TEXT("PRODUCTVERSION"), pVersion ); + } + + GetPrivateProfileString( + TEXT("Version"), + TEXT("buildid"), + TEXT("unknown"), + g_szBuildId, SAL_N_ELEMENTS(g_szBuildId), + szModuleVersionName ); + + g_strDefaultLanguage = get_script_string( "instdb.inf", "DefaultLanguage" ); + + if ( GetPrivateProfileString( + TEXT("ErrorReport"), + TEXT("ErrorReportPort"), + TEXT("80"), + szReportPort, SAL_N_ELEMENTS(szReportPort), + szModuleName + ) ) + { + TCHAR *endptr = NULL; + + unsigned short uReportPort = (unsigned short)_tcstoul( szReportPort, &endptr, 10 ); + if ( uReportPort ) + g_uReportPort = uReportPort; + } + + if ( GetPrivateProfileString( + TEXT("ErrorReport"), + TEXT("ErrorReportServer"), + TEXT(""), + szReportServer, SAL_N_ELEMENTS(szReportServer), + szModuleName + ) ) + { + bSuccess = 0 != WideCharToMultiByte( CP_ACP, 0, szReportServer, -1, g_szReportServerA, SAL_N_ELEMENTS(g_szReportServerA), NULL, NULL ); + } + + LPCTSTR lpEnvString; + + if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYSERVER") )) ) + rParams.sProxyServer = lpEnvString; + + if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYPORT") )) ) + rParams.sProxyPort = lpEnvString; + + if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_SENDERADDRESS") )) ) + rParams.sEmail = lpEnvString; + + return bSuccess; +} + +//*************************************************************************** + +bool SendHTTPRequest( + FILE *fp, + const char *pszServer, + unsigned short uPort = 80, + const char *pszProxyServer = NULL, + unsigned short uProxyPort = 8080 ) +{ + bool success = false; + + struct hostent *hp; + + if ( pszProxyServer ) + hp = gethostbyname( pszProxyServer ); + else + hp = gethostbyname( pszServer ); + + if ( hp ) + { + SOCKET s = socket( AF_INET, SOCK_STREAM, 0 ); + + if ( s ) + { + struct sockaddr_in address; + + memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr)); + address.sin_family = AF_INET; + + if ( pszProxyServer ) + address.sin_port = ntohs( uProxyPort ); + else + address.sin_port = ntohs( uPort ); + + if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) ) + { + fseek( fp, 0, SEEK_END ); + size_t length = ftell( fp ); + fseek( fp, 0, SEEK_SET ); + + char buffer[2048]; + + if ( pszProxyServer ) + sprintf( buffer, + "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n" + "Content-Type: text/xml; charset=\"utf-8\"\r\n" + "Content-Length: %d\r\n" + "SOAPAction: \"\"\r\n\r\n", + pszServer, + uPort, + length + ); + else + sprintf( buffer, + "POST /soap/servlet/rpcrouter HTTP/1.0\r\n" + "Content-Type: text/xml; charset=\"utf-8\"\r\n" + "Content-Length: %d\r\n" + "SOAPAction: \"\"\r\n\r\n", + length + ); + + if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) ) + { + size_t nBytes; + + do + { + nBytes = fread( buffer, 1, sizeof(buffer), fp ); + + if ( nBytes ) + success = SOCKET_ERROR != send( s, buffer, nBytes, 0 ); + } while( nBytes && success ); + + if ( success ) + { + memset( buffer, 0, sizeof(buffer) ); + success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 ); + if ( success ) + { + char szHTTPSignature[sizeof(buffer)] = ""; + unsigned uHTTPReturnCode = 0; + + sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode ); + success = uHTTPReturnCode == 200; + } + } + } + + } + + closesocket( s ); + } + } + + return success; +} + +//*************************************************************************** + +static void WriteSOAPRequest( FILE *fp ) +{ + fprintf( fp, + "\n" + "\n" + "\n" + ); + + fprintf( fp, "\n" ); + fprintf( fp, "This is an autogenerated crash report mail.\n" ); + fprintf( fp, "\n" ); + + FILE *fpin = fopen( g_szReportFileNameA, "r" ); + if ( fpin ) + { + fprintf( fp, + "\n" + "reportmail.xml\n" + "\n" ); + fclose( fpin ); + } + + fpin = fopen( g_szCommentFileNameA, "r" ); + if ( fpin ) + { + fprintf( fp, + "\n" + "description.txt\n" + "\n" ); + fclose( fpin ); + }; + + + fpin = fopen( g_szDumpFileNameA, "rb" ); + if ( fpin ) + { + FILE *fptemp = _tmpfile(); + + if ( fptemp ) + { + if ( base64_encode( fpin, fptemp ) ) + { + fseek( fptemp, 0, SEEK_SET ); + fprintf( fp, + "\n" + "user.dmp\n" + "" ); + fcopy( fptemp, fp ); + fprintf( fp, "\n" ); + } + fclose( fptemp ); + } + fclose( fpin ); + } + + fprintf( fp, + "\n" + "\n" + "\n" + "\n" + ); +} + +//*************************************************************************** + +struct RequestParams +{ + bool success; + FILE *fpin; + const char *lpServer; + unsigned short uPort; + const char *lpProxyServer; + unsigned short uProxyPort; + HWND hwndStatus; +}; + +void _cdecl SendingThread( void *lpArgs ) +{ + RequestParams *pParams = (RequestParams *)lpArgs; + + pParams->success = SendHTTPRequest( pParams->fpin, pParams->lpServer, pParams->uPort, pParams->lpProxyServer, pParams->uProxyPort ); + + PostMessage( pParams->hwndStatus, WM_COMMAND, IDOK, 0 ); +} + +//*************************************************************************** + +BOOL CALLBACK SendingStatusDialogProc( + HWND hwndDlg, + UINT uMsg, + WPARAM wParam, + LPARAM lParam + ) +{ + static RequestParams *pRequest = NULL; + static HANDLE hSendingThread = NULL; + + switch ( uMsg ) + { + case WM_INITDIALOG: + { + TCHAR szBuffer[1024] = TEXT(""); + HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE ); + + pRequest = (RequestParams *)lParam; + + LoadAndFormatString( hInstance, IDS_SENDING_REPORT_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + SetWindowText( hwndDlg, szBuffer ); + + LoadAndFormatString( hInstance, IDS_SENDING_REPORT_STATUS, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Static_SetText( GetDlgItem(hwndDlg, IDC_SENDING_REPORT_STATUS), szBuffer ); + + LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) ); + Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer ); + + pRequest->hwndStatus = hwndDlg; + + hSendingThread = (HANDLE)_beginthread( SendingThread, 0, pRequest ); + } + return TRUE; + case WM_COMMAND: + switch ( LOWORD(wParam) ) + { + case IDCANCEL: + TerminateThread( hSendingThread, 0 ); + case IDOK: + WaitForSingleObject( hSendingThread, INFINITE ); + CloseHandle( hSendingThread ); + EndDialog( hwndDlg, wParam ); + return TRUE; + } + break; + default: + break; + } + + return FALSE; +} + +//*************************************************************************** + +bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams ) +{ + bool success = false; + char szProxyServer[1024] = ""; + unsigned short uProxyPort = 8080; + TCHAR *endptr = NULL; + + switch ( rParams.uInternetConnection ) + { + case 2: + { + WideCharToMultiByte( + CP_ACP, 0, rParams.sProxyServer.c_str(), -1, + szProxyServer, sizeof(szProxyServer), NULL, NULL ); + uProxyPort = (unsigned short)_tcstoul( rParams.sProxyPort.c_str(), &endptr, 10 ); + } + break; + case 0: + { + DWORD dwProxyEnable = 0; + + RegReadValue( HKEY_CURRENT_USER, + TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), + TEXT("ProxyEnable"), + &dwProxyEnable, + sizeof(dwProxyEnable) ); + + if ( dwProxyEnable ) + { + TCHAR tszProxyServers[1024] = TEXT(""); + + if ( ERROR_SUCCESS == RegReadValue( HKEY_CURRENT_USER, + TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), TEXT("ProxyServer"), + tszProxyServers, + sizeof(tszProxyServers) ) ) + { + TCHAR *lpHttpStart = _tcsstr( tszProxyServers, TEXT("http=") ); + + if ( lpHttpStart ) + lpHttpStart += 5; + else + lpHttpStart = tszProxyServers; + + TCHAR *lpHttpEnd = _tcschr( lpHttpStart, ';' ); + + if ( lpHttpEnd ) + *lpHttpEnd = 0; + + char szHTTPProxyServer[1024] = ""; + WideCharToMultiByte( CP_ACP, 0, lpHttpStart, -1, szHTTPProxyServer, sizeof(szHTTPProxyServer), NULL, NULL ); + + char *lpColon = strchr( szHTTPProxyServer, ':' ); + + if ( lpColon ) + { + char *endptr = NULL; + + *lpColon = 0; + uProxyPort = (unsigned short)strtoul( lpColon + 1, &endptr, 10 ); + } + else + uProxyPort = 8080; + + strcpy( szProxyServer, szHTTPProxyServer ); + + } + } + } + break; + default: + case 1: + break; + } + + FILE *fptemp = _tmpfile(); + if ( fptemp ) + { + RequestParams request; + + request.success = false; + request.fpin = fptemp; + request.lpServer = REPORT_SERVER; + request.uPort = REPORT_PORT; + request.lpProxyServer = szProxyServer[0] ? szProxyServer : NULL; + request.uProxyPort = uProxyPort; + request.hwndStatus = NULL; + + WriteSOAPRequest( fptemp ); + fseek( fptemp, 0, SEEK_SET ); + + if ( hwndParent ) + { + int retid = DialogBoxParam( + GetModuleHandle(NULL), + MAKEINTRESOURCE(IDD_SENDING_STATUS), + hwndParent, + SendingStatusDialogProc, + (LPARAM)&request + ); + + success = request.success; + + if ( IDOK == retid ) + { + if ( !success ) + { + TCHAR szMessage[1024]; + + LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, SAL_N_ELEMENTS(szMessage) ); + + MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK ); + } + else + { + TCHAR szMessage[1024]; + TCHAR szTitle[1024]; + + LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, SAL_N_ELEMENTS(szMessage) ); + LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_HEADER, szTitle, SAL_N_ELEMENTS(szTitle) ); + + MessageBox( hwndParent, szMessage, szTitle, MB_ICONINFORMATION | MB_OK ); + } + } + + } + else + { + HANDLE hSendingThread = (HANDLE)_beginthread( SendingThread, 0, (void *)&request ); + + WaitForSingleObject( hSendingThread, INFINITE ); + + success = request.success; + if ( !success ) + { + TCHAR szMessage[1024]; + + LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, SAL_N_ELEMENTS(szMessage) ); + _ftprintf( stderr, _T("ERROR: %s\n"), szMessage ); + } + else + { + TCHAR szMessage[1024]; + + LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, SAL_N_ELEMENTS(szMessage) ); + + _ftprintf( stderr, _T("SUCCESS: %s\n"), szMessage ); + } + } + fclose( fptemp ); + } + else + { + TCHAR szMessage[1024]; + + LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_DISK_FULL, szMessage, SAL_N_ELEMENTS(szMessage) ); + + if ( hwndParent ) + MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK ); + else + _ftprintf( stderr, _T("ERROR: %s\n"), szMessage ); + } + + return success; +} + +//*************************************************************************** + +#ifdef __MINGW32__ +int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR /*lpCmdLine*/, int ) +#else +int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR /*lpCmdLine*/, int ) +#endif +{ + int exitcode = -1; + int argc = __argc; + +#ifdef __MINGW32__ + char **argv = __argv; +#else +#ifdef _UNICODE + char **argv = new char *[argc + 1]; + + for ( int argn = 0; argn < argc; argn++ ) + { + int nBytes = WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, NULL, 0, NULL, NULL ); + argv[argn] = new char[nBytes]; + WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, argv[argn], nBytes, NULL, NULL ); + } + argv[argc] = NULL; +#else + char **argv = __targv; +#endif +#endif + + osl_setCommandArgs( argc, argv ); + + PEXCEPTION_POINTERS pExceptionPointers = NULL; + DWORD dwProcessId = 0; + DWORD dwThreadId = 0; + + WSADATA wsaData; + WORD wVersionRequested; + + wVersionRequested = MAKEWORD(1, 1); + WSAStartup(wVersionRequested, &wsaData); + + CrashReportParams Params; + + Params.ReadFromRegistry(); + Params.ReadFromEnvironment(); + + if ( ReadBootstrapParams( Params ) && + ParseCommandArgs( &dwProcessId, &pExceptionPointers, &dwThreadId ) ) + { + bool bGotDumpFile; + + if ( g_bLoadReport ) + bGotDumpFile = FindDumpFile(); + else + bGotDumpFile = WriteDumpFile( dwProcessId, pExceptionPointers, dwThreadId ); + + if( bGotDumpFile ) + { + boost::unordered_map< string, string > aLibraries; + + if ( g_bLoadReport ) + { + g_fpStackFile = _open_reportfile( _T(".stk"), _T("rb") ); + g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("rb") ); + } + else + { + if ( g_bSendReport ) + { + g_fpStackFile = _tmpfile(); + g_fpChecksumFile = _tmpfile(); + } + else + { + g_fpStackFile = _open_reportfile( _T(".stk"), _T("w+b") ); + g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("w+b") ); + + FILE *fpUnsent = _open_reportfile( _T(".lck"), _T("w+b") ); + if ( fpUnsent ) + { + fprintf( fpUnsent, "Unsent\r\n" ); + fclose( fpUnsent ); + } + } + + WriteStackFile( g_fpStackFile, aLibraries, dwProcessId, pExceptionPointers ); + WriteChecksumFile( g_fpChecksumFile, aLibraries ); + WriteReportFile( &Params ); + + FILE *fpPreview = _open_reportfile( _T(".prv"), _T("w+b") ); + + if ( fpPreview ) + { + FILE *fp = fopen( g_szReportFileNameA, "rb" ); + if ( fp ) + { + fcopy( fp, fpPreview ); + fclose( fp ); + } + fclose( fpPreview ); + } + } + + if ( g_bSendReport ) + { + InitCommonControls(); + + // Actually this should never be true anymore + if ( !g_bNoUserInterface && InitRichEdit() ) + { + + INT_PTR result = DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_DIALOG_FRAME), NULL, DialogProc, (LPARAM)&Params ); + + if ( result > 0 ) + { + exitcode = 0; + } + DeinitRichEdit(); + } + else + { + WriteCommentFile( Params.sComment.c_str() ); + WriteReportFile( &Params ); + if ( SendCrashReport( NULL, Params ) ) + exitcode = 0; + } + + + if ( g_szReportFileNameA[0] ) + DeleteFileA( g_szReportFileNameA ); + + if ( g_szCommentFileNameA[0] ) + DeleteFileA( g_szCommentFileNameA ); + } + else + { + if ( g_szReportFileNameA[0] ) + DeleteFileA( g_szReportFileNameA ); + exitcode = 0; + } + + if ( g_szDumpFileNameA[0] && g_bSendReport ) + DeleteFileA( g_szDumpFileNameA ); + + if ( g_fpStackFile ) + fclose( g_fpStackFile ); + + if ( g_fpChecksumFile ) + fclose( g_fpChecksumFile ); + } + } + + + return exitcode; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit