/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #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 ) { #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(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, "&" ); 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 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, "\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 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 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(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, "\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 hash_map< string, string >& rLibraries ) { bool success = false; if ( fchksum && rLibraries.size() ) { fprintf( fchksum, "\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, "\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; 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(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, 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(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, "\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 ); //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; }