summaryrefslogtreecommitdiff
path: root/crashrep/source/win32/soreport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'crashrep/source/win32/soreport.cpp')
-rwxr-xr-xcrashrep/source/win32/soreport.cpp2982
1 files changed, 2982 insertions, 0 deletions
diff --git a/crashrep/source/win32/soreport.cpp b/crashrep/source/win32/soreport.cpp
new file mode 100755
index 000000000000..f3d19ca98790
--- /dev/null
+++ b/crashrep/source/win32/soreport.cpp
@@ -0,0 +1,2982 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#define UNICODE
+#define WIN32_LEAN_AND_MEAN
+#if defined _MSC_VER
+#pragma warning(push, 1)
+#pragma warning(disable:4917)
+#endif
+#include <windows.h>
+#include <windowsx.h>
+
+#include <mapi.h>
+#include <commctrl.h>
+#include <commdlg.h>
+#include <psapi.h>
+
+#include <shellapi.h>
+#include <shlobj.h>
+
+#define _UNICODE
+#include <tchar.h>
+
+#define _RICHEDIT_VER 0x0200
+#include <richedit.h>
+
+#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 <systools/win32/uwinapi.h>
+#include <rtl/digest.h>
+#include <rtl/bootstrap.hxx>
+#include <osl/file.hxx>
+#include <osl/process.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <string>
+#include <hash_map>
+#include <winsock.h>
+#include <malloc.h>
+#include <process.h>
+
+#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 <imagehlp.h>
+#else
+#include <dbghelp.h>
+#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 )
+{
+#ifdef UNICODE
+ if ( (LONG)GetVersion() < 0 )
+ {
+ char afile[MAX_PATH];
+ char amode[16];
+
+ WideCharToMultiByte( CP_ACP, 0, file, -1, afile, MAX_PATH, NULL, NULL );
+ WideCharToMultiByte( CP_ACP, 0, mode, -1, amode, 16, NULL, NULL );
+
+
+ return fopen( afile, amode );
+ }
+ else
+#endif
+ return _tfopen( file, mode );
+}
+
+
+static FILE *_tmpfile(void)
+{
+ FILE *fp = NULL;
+
+ TCHAR szTempPath[MAX_PATH];
+
+ if ( GetTempPath( elementsof(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::OUString::createFromAscii("${$BRAND_BASE_DIR/program/bootstrap.ini:UserInstallation}");
+ ::rtl::Bootstrap::expandMacros( ustrValue );
+
+ if ( ustrValue.getLength() )
+ {
+ ustrValue += ::rtl::OUString::createFromAscii("/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<LPCWSTR>(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\\OpenOffice.org\\CrashReport"),
+ TEXT("HTTPProxyServer"),
+ szBuffer,
+ sizeof(szBuffer) ) )
+ sProxyServer = szBuffer;
+
+ DWORD dwProxyPort;
+
+ if ( ERROR_SUCCESS == RegReadValue(
+ HKEY_CURRENT_USER,
+ TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
+ TEXT("HTTPProxyPort"),
+ &dwProxyPort,
+ sizeof(dwProxyPort) ) )
+ {
+ _stprintf( szBuffer, TEXT("%d"), dwProxyPort );
+ sProxyPort = szBuffer;
+ }
+
+ if ( ERROR_SUCCESS == RegReadValue(
+ HKEY_CURRENT_USER,
+ TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
+ TEXT("ReturnAddress"),
+ szBuffer,
+ sizeof(szBuffer) ) )
+ sEmail = szBuffer;
+
+ RegReadValue(
+ HKEY_CURRENT_USER,
+ TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
+ TEXT("AllowContact"),
+ &fAllowContact,
+ sizeof(fAllowContact) );
+
+ RegReadValue(
+ HKEY_CURRENT_USER,
+ TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
+ TEXT("HTTPConnection"),
+ &uInternetConnection,
+ sizeof(uInternetConnection) );
+}
+
+//***************************************************************************
+
+void CrashReportParams::WriteToRegistry()
+{
+ RegWriteValue(
+ HKEY_CURRENT_USER,
+ TEXT("SOFTWARE\\OpenOffice.org\\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\\OpenOffice.org\\CrashReport"),
+ TEXT("HTTPProxyPort"), REG_DWORD,
+ &dwProxyPort,
+ sizeof(DWORD) );
+
+ RegWriteValue(
+ HKEY_CURRENT_USER,
+ TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
+ TEXT("AllowContact"), REG_DWORD,
+ &fAllowContact,
+ sizeof(DWORD) );
+
+
+ RegWriteValue(
+ HKEY_CURRENT_USER,
+ TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
+ TEXT("HTTPConnection"), REG_DWORD,
+ &uInternetConnection,
+ sizeof(DWORD) );
+
+ RegWriteValue(
+ HKEY_CURRENT_USER,
+ TEXT("SOFTWARE\\OpenOffice.org\\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, elementsof(szBuffer) );
+
+ if ( dwResult && dwResult < elementsof(szBuffer) )
+ sProxyServer = szBuffer;
+
+ dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYPORT"), szBuffer, elementsof(szBuffer) );
+
+ if ( dwResult && dwResult < elementsof(szBuffer) )
+ sProxyPort = szBuffer;
+
+ dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_RETURNADDRESS"), szBuffer, elementsof(szBuffer) );
+
+ if ( dwResult && dwResult < elementsof(szBuffer) )
+ {
+ sEmail = szBuffer;
+ // fAllowContact = TRUE;
+ }
+
+ dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPCONNECTIONTYPE"), szBuffer, elementsof(szBuffer) );
+
+ if ( dwResult && dwResult < elementsof(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, elementsof(szBuffer) );
+
+ if ( dwResult && dwResult < elementsof(szBuffer) )
+ sTitle = szBuffer;
+
+
+ dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_BODYFILE"), szBuffer, elementsof(szBuffer) );
+
+ if ( dwResult && dwResult < elementsof(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]), elementsof(aUTF8Buffer), fp )) )
+ {
+ TCHAR aBuffer[256+1];
+
+ DWORD dwCharacters = MultiByteToWideChar( CP_UTF8, 0, aUTF8Buffer, nBytesRead, aBuffer, elementsof(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, elementsof(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 occurences 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, "&amp;" );
+
+ for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 )
+ temp.replace( pos, 1, "&lt;" );
+
+ for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 )
+ temp.replace( pos, 1, "&gt;" );
+
+ return temp;
+}
+
+//***************************************************************************
+
+static size_t fcopy( FILE *fpin, FILE *fpout )
+{
+ char buffer[1024];
+ size_t nBytes;
+ size_t nBytesWritten = 0;
+
+ if ( fpin && fpout )
+ {
+ 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, elementsof(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( elementsof(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,
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
+ "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
+ "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n",
+ pszUserType ? pszUserType : "",
+ pParams->fAllowContact ? "true" : "false",
+ pParams->fAllowContact ? xml_encode(szEmail).c_str() : ""
+ );
+
+ fprintf( fp,
+ "<reportmail:title>%s</reportmail:title>\n",
+ xml_encode(szTitle).c_str() );
+
+ fprintf( fp,
+ "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain;charset=UTF-8\" class=\"UserComment\"/>\n"
+ "<reportmail:attachment name=\"user.dmp\" media-type=\"application/octet-stream\" class=\"UserDump\"/>\n"
+ "</reportmail:mail>\n"
+
+ "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" procpath=\"%s\" exceptiontype=\"0x%08X\" product=\"%s\"/>\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,
+ "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
+ "<systeminfo:System name=\"%s\" version=\"%d.%d\" build=\"%d\" locale=\"0x%08x\"/>\n"
+ ,
+ VER_PLATFORM_WIN32_NT == VersionInfo.dwPlatformId ? "Windows NT" : "Windows",
+ VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion,
+ VersionInfo.dwBuildNumber,
+ GetUserDefaultLangID()
+
+ );
+ fprintf( fp, "<systeminfo:CPU type=\"x86\"/>\n" );
+ fprintf( fp, "</systeminfo:systeminfo>\n" );
+
+ fseek( g_fpStackFile, 0, SEEK_SET );
+ fcopy( g_fpStackFile, fp );
+
+ fseek( g_fpChecksumFile, 0, SEEK_SET );
+ fcopy( g_fpChecksumFile, fp );
+
+ fprintf( fp, "</errormail:errormail>\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 EnumChildProc(HWND hwndChild, LPARAM lParam)
+{
+ HFONT aFont = *((HFONT*) lParam);
+ HDC hDC = GetDC( hwndChild );
+ SelectObject( hDC, aFont );
+ ReleaseDC( hwndChild, hDC );
+ return TRUE;
+}
+
+void ApplySystemFont( HWND hwndDlg )
+{
+ NONCLIENTMETRICSA aNonClientMetrics;
+ aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
+ if ( SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
+ {
+ HFONT aSysFont = CreateFontIndirectA( &aNonClientMetrics.lfMessageFont );
+ EnumChildWindows(hwndDlg, EnumChildProc, (LPARAM) &aSysFont);
+ }
+}
+*/
+
+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, elementsof(szBuffer) );
+ SetWindowText( hwndDlg, szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) );
+ Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
+
+ basic_string<TCHAR> 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, elementsof(buf), fp ) != NULL )
+ {
+ WCHAR bufW[1024];
+
+ MultiByteToWideChar( CP_UTF8, 0, buf, -1, bufW, elementsof(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]), sizeof(buf)/sizeof(buf[0]), fp );
+
+ for ( i = 0; i < count; i++ )
+ {
+ TCHAR output[16];
+
+ _sntprintf( output, elementsof(output), _T("%02X\x20"), buf[i] );
+ aString.append( output );
+ }
+ for ( ; i < elementsof(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, elementsof(szBuffer) );
+ SetWindowText( hwndDlg, szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_PROXY_SETTINGS_HEADER, szBuffer, elementsof(szBuffer) );
+ Static_SetText( GetDlgItem(hwndDlg, IDC_PROXY_SETTINGS), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_PROXY_SYSTEM, szBuffer, elementsof(szBuffer) );
+ Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_PROXY_DIRECT, szBuffer, elementsof(szBuffer) );
+ Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_PROXY_MANUAL, szBuffer, elementsof(szBuffer) );
+ Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_LABEL_PROXYSERVER, szBuffer, elementsof(szBuffer) );
+ Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYSERVER), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_LABEL_PROXYPORT, szBuffer, elementsof(szBuffer) );
+ Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYPORT), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) );
+ Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(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, elementsof(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, elementsof(szBuffer) );
+ pParams->sProxyServer = szBuffer;
+
+ Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), szBuffer, elementsof(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, elementsof(szBuffer) );
+ Static_SetText( GetDlgItem(hwndDlg, IDC_REPORT_INTRO), szBuffer );
+
+ Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT3), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_ENTER_TITLE, szBuffer, elementsof(szBuffer) );
+ Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_TITLE), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_ENTER_DESCRIPTION, szBuffer, elementsof(szBuffer) );
+ Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_DESCRIPTION), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_SHOW_REPORT_BUTTON, szBuffer, elementsof(szBuffer) );
+ Button_SetText( GetDlgItem(hwndDlg, IDC_SHOW_REPORT), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_SAVE_REPORT_BUTTON, szBuffer, elementsof(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, elementsof(szBuffer) );
+ Button_SetText( GetDlgItem(hwndDlg, IDC_OPTIONS), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_ALLOW_CONTACT, szBuffer, elementsof(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, elementsof(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, elementsof(szBuffer) );
+ SetWindowText( GetParent(hwndDlg), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
+ SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_DONOT_SEND_BUTTON, szBuffer, elementsof(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() );
+
+ /*
+ SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE,
+ GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE) | BS_DEFPUSHBUTTON );
+ SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE,
+ GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE) &~ BS_DEFPUSHBUTTON );
+ */
+ 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, elementsof(szBuffer) );
+ pParams->sTitle = szBuffer;
+
+ Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), szBuffer, elementsof(szBuffer) );
+ pParams->sComment = szBuffer;
+
+ Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), szBuffer, elementsof(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, elementsof(szBuffer) );
+ LoadAndFormatString( hInstance, IDS_WELCOME_BODY2, szBuffer2, elementsof(szBuffer2) );
+ _tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) );
+ LoadAndFormatString( hInstance, IDS_WELCOME_BODY3, szBuffer2, elementsof(szBuffer2) );
+ _tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) );
+ LoadString( hInstance, IDS_PRIVACY_URL, szURL, elementsof(szURL) );
+ _tcsncat( szBuffer, szURL, elementsof(szBuffer) );
+ SetWindowText( hwndRichEdit, szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szCaption, elementsof(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, elementsof(szBuffer) );
+ SetWindowText( GetParent(hwndDlg), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_WELCOME_HEADER, szBuffer, elementsof(szBuffer) );
+ SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(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, elementsof(szBuffer) );
+ Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_NEXT_BUTTON, szBuffer, elementsof(szBuffer) );
+ Button_SetText( GetDlgItem(hwndDlg, IDNEXT), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_SEND_BUTTON, szBuffer, elementsof(szBuffer) );
+ Button_SetText( GetDlgItem(hwndDlg, IDFINISH), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_BACK_BUTTON, szBuffer, elementsof(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 < elementsof(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, elementsof(szBuffer) );
+ pParams->sTitle = szBuffer;
+
+ Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_DESCRIPTION), szBuffer, elementsof(szBuffer) );
+ pParams->sComment = szBuffer;
+
+ Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_EMAIL), szBuffer, elementsof(szBuffer) );
+ pParams->sEmail = szBuffer;
+
+ if ( pParams->fAllowContact && !pParams->sEmail.length() )
+ {
+ TCHAR szMessage[MAX_TEXT_BUFFER];
+
+ LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_NOEMAILADDRESS, szMessage, elementsof(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(), elementsof(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<long>(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;
+}
+
+#if 0
+static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
+{
+ sal_uInt32 nBytesProcessed = 0;
+
+ FILE *fp = fopen( filename, "rb" );
+
+ if ( fp )
+ {
+ rtlDigest digest = rtl_digest_createMD5();
+
+ if ( digest )
+ {
+ size_t nBytesRead;
+ sal_uInt8 buffer[4096];
+ rtlDigestError error = rtl_Digest_E_None;
+
+ while ( rtl_Digest_E_None == error &&
+ 0 != (nBytesRead = fread( buffer, 1, sizeof(buffer), fp )) )
+ {
+ error = rtl_digest_updateMD5( digest, buffer, nBytesRead );
+ nBytesProcessed += nBytesRead;
+ }
+
+ if ( rtl_Digest_E_None == error )
+ {
+ error = rtl_digest_getMD5( digest, pChecksum, nChecksumLen );
+ }
+
+ if ( rtl_Digest_E_None != error )
+ nBytesProcessed = 0;
+
+ rtl_digest_destroyMD5( digest );
+ }
+
+ fclose( fp );
+ }
+
+ return nBytesProcessed;
+}
+
+#endif
+//***************************************************************************
+
+static bool WriteStackFile( FILE *fout, hash_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, "<errormail:Stack type=\"Win32\">\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, "<errormail:StackInfo " \
+ "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" ordinal=\"%s+0x%p\" name=\"%s\" path=\"%s\"/>\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, "<errormail:StackInfo " \
+ "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" name=\"%s\" path=\"%s\"/>\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, "<errormail:StackInfo pos=\"%d\" ip=\"0x%p\"/>\n",
+ frameNum,
+ frame.AddrPC.Offset
+ );
+
+ frameNum++;
+ }
+
+ } while ( bSuccess );
+
+ fprintf( fout, "</errormail:Stack>\n" );
+
+ SymCleanup( hProcess );
+
+ CloseHandle( hProcess );
+ }
+
+ }
+
+ return fSuccess;
+}
+
+bool WriteChecksumFile( FILE *fchksum, const hash_map< string, string >& rLibraries )
+{
+ bool success = false;
+
+ if ( fchksum && rLibraries.size() )
+ {
+ fprintf( fchksum, "<errormail:Checksums type=\"MD5\">\n" );
+
+ hash_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, "<errormail:Checksum sum=\"0x" );
+ for ( int i = 0; i < sizeof(checksum); fprintf( fchksum, "%02X", checksum[i++] ) );
+ fprintf( fchksum, "\" bytes=\"%d\" file=\"%s\"/>\n",
+ nBytesProcessed,
+ GetFileName( iter->first ) );
+ }
+ }
+
+ fprintf( fchksum, "</errormail:Checksums>\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;
+ PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam = NULL;
+ 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 ( GetTempPath( elementsof(szTempPath), szTempPath ) )
+ if ( GetCrashDataPath( szTempPath ) )
+ {
+ TCHAR szFileName[MAX_PATH];
+
+// if ( GetTempFileName( szTempPath, TEXT("DMP"), 0, szFileName ) )
+ _tcscpy( szFileName, szTempPath );
+ _tcscat( szFileName, _T("\\crashdat.dmp") );
+ {
+ HANDLE hFile = CreateFile(
+ szFileName,
+ GENERIC_READ | GENERIC_WRITE,
+ 0, NULL,
+// OPEN_EXISTING,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL );
+
+ if ( hFile )
+ {
+ 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, elementsof(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, elementsof(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<TCHAR **>(alloca((argc+1)*sizeof(WCHAR*)));
+ int *sizes = reinterpret_cast<int *>(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<TCHAR *>(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, elementsof(szUsage) );
+ LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID, szProcess, elementsof(szProcess) );
+ LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID_DESCRIPTION, szProcessDescription, elementsof(szProcessDescription) );
+ LoadAndFormatString( hInstance, IDS_MSG_PARAM_HELP_DESCRIPTION, szHelpDescription, elementsof(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( elementsof(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<string::size_type>(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("OpenOffice.org"),
+ szBuffer,
+ elementsof(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, elementsof(g_szBuildId),
+ szModuleVersionName );
+
+ g_strDefaultLanguage = get_script_string( "instdb.inf", "DefaultLanguage" );
+
+ if ( GetPrivateProfileString(
+ TEXT("ErrorReport"),
+ TEXT("ErrorReportPort"),
+ TEXT("80"),
+ szReportPort, elementsof(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, elementsof(szReportServer),
+ szModuleName
+ ) )
+ {
+ bSuccess = 0 != WideCharToMultiByte( CP_ACP, 0, szReportServer, -1, g_szReportServerA, elementsof(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,
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
+ "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
+ "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
+ "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
+ "xmlns:rds=\"urn:ReportDataService\"\n"
+ "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
+ "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
+ "<SOAP-ENV:Body>\n"
+ );
+
+ fprintf( fp, "<rds:submitReport>\n" );
+ fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
+ fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
+
+ FILE *fpin = fopen( g_szReportFileNameA, "r" );
+ if ( fpin )
+ {
+ fprintf( fp,
+ "<item>\n"
+ "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
+ "<value xsi:type=\"xsd:string\"><![CDATA[" );
+ fcopy( fpin, fp );
+ fprintf( fp, "]]></value></item>\n" );
+ fclose( fpin );
+ }
+
+ fpin = fopen( g_szCommentFileNameA, "r" );
+ if ( fpin )
+ {
+ fprintf( fp,
+ "<item>\n"
+ "<key xsi:type=\"xsd:string\">description.txt</key>\n"
+ "<value xsi:type=\"xsd:string\"><![CDATA[" );
+ fcopy( fpin, fp );
+ fprintf( fp, "]]></value></item>\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,
+ "<item>\n"
+ "<key xsi:type=\"xsd:string\">user.dmp</key>\n"
+ "<value xsi:type=\"xsd:string\">" );
+ fcopy( fptemp, fp );
+ fprintf( fp, "</value></item>\n" );
+ }
+ fclose( fptemp );
+ }
+ fclose( fpin );
+ }
+
+ fprintf( fp,
+ "</hash>\n"
+ "</rds:submitReport>\n"
+ "</SOAP-ENV:Body>\n"
+ "</SOAP-ENV:Envelope>\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 );
+ //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
+
+ pRequest = (RequestParams *)lParam;
+
+ LoadAndFormatString( hInstance, IDS_SENDING_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
+ SetWindowText( hwndDlg, szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_SENDING_REPORT_STATUS, szBuffer, elementsof(szBuffer) );
+ Static_SetText( GetDlgItem(hwndDlg, IDC_SENDING_REPORT_STATUS), szBuffer );
+
+ LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(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, elementsof(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, elementsof(szMessage) );
+ LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_HEADER, szTitle, elementsof(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, elementsof(szMessage) );
+ _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
+ }
+ else
+ {
+ TCHAR szMessage[1024];
+
+ LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) );
+
+ _ftprintf( stderr, _T("SUCCESS: %s\n"), szMessage );
+ }
+ }
+ fclose( fptemp );
+ }
+ else
+ {
+ TCHAR szMessage[1024];
+
+ LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_DISK_FULL, szMessage, elementsof(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 )
+ {
+ hash_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;
+}
+