bump product version to 4.1.6.2
[LibreOffice.git] / crashrep / source / win32 / soreport.cxx
blob08038efe09ea71aef3a249e64cd806965a49980d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #define UNICODE
21 #define WIN32_LEAN_AND_MEAN
22 #if defined _MSC_VER
23 #pragma warning(push, 1)
24 #pragma warning(disable:4917)
25 #endif
26 #include <windows.h>
27 #include <windowsx.h>
29 #include <mapi.h>
30 #include <commctrl.h>
31 #include <commdlg.h>
32 #include <psapi.h>
34 #include <shellapi.h>
35 #include <shlobj.h>
37 #define _UNICODE
38 #include <tchar.h>
40 #define _RICHEDIT_VER 0x0200
41 #include <richedit.h>
43 #if defined _MSC_VER
44 #pragma warning(pop)
45 #endif
47 #if _RICHEDIT_VER >= 0x0200
48 #define RICHEDIT TEXT("riched20.dll")
49 #else
50 #define RICHEDIT TEXT("riched32.dll")
51 #endif
53 #include <systools/win32/uwinapi.h>
54 #include <rtl/digest.h>
55 #include <rtl/bootstrap.hxx>
56 #include <osl/file.hxx>
57 #include <osl/process.h>
59 #include <stdlib.h>
60 #include <stdio.h>
61 #include <io.h>
62 #include <fcntl.h>
63 #include <string>
64 #include <boost/unordered_map.hpp>
65 #include <winsock.h>
66 #include <malloc.h>
67 #include <process.h>
69 #include "resource.h"
70 #include "base64.h"
72 #define FORMATBUFSIZE (8*1024)
73 #define MAX_TEXT_BUFFER (32*1024-1)
74 #define MAX_HOSTNAME (1024)
76 #ifdef __MINGW32__
77 #include <imagehlp.h>
78 #else
79 #include <dbghelp.h>
80 #endif
82 #ifdef _UNICODE
83 #define tstring wstring
84 #else
85 #define tstring string
86 #endif
88 using namespace ::std;
91 wstring g_wstrProductKey;
92 string g_strDefaultLanguage;
93 FILE *g_fpStackFile = NULL;
94 FILE *g_fpChecksumFile = NULL;
95 DWORD g_dwExceptionCode = 0;
97 CHAR g_szReportServerA[MAX_HOSTNAME] = "";
98 USHORT g_uReportPort = 80;
100 TCHAR g_szBuildId[256] = TEXT("");
102 TCHAR g_szDumpFileName[MAX_PATH] = TEXT("");
104 CHAR g_szDumpFileNameA[MAX_PATH] = "";
105 CHAR g_szCommentFileNameA[MAX_PATH] = "";
106 CHAR g_szReportFileNameA[MAX_PATH] = "";
109 bool g_bNoUserInterface = false;
110 bool g_bSendReport = false;
111 bool g_bLoadReport = false;
113 #define REPORT_SERVER g_szReportServerA
114 #define REPORT_PORT g_uReportPort
117 //***************************************************************************
118 // tmpfile from msvcrt creates the temporary file in the root of the current
119 // volume and can fail.
121 static FILE *_xfopen( const _TCHAR *file, const _TCHAR *mode )
123 return _tfopen( file, mode );
127 static FILE *_tmpfile(void)
129 FILE *fp = NULL;
131 TCHAR szTempPath[MAX_PATH];
133 if ( GetTempPath( SAL_N_ELEMENTS(szTempPath), szTempPath ) )
135 TCHAR szFileName[MAX_PATH];
137 if ( GetTempFileName( szTempPath, TEXT("CRT"), 0, szFileName ) )
139 HANDLE hFile = CreateFile(
140 szFileName,
141 GENERIC_READ | GENERIC_WRITE,
142 0, NULL,
143 OPEN_EXISTING,
144 FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_NORMAL,
145 NULL );
147 if ( IsValidHandle( hFile ) )
149 int fd = _open_osfhandle( (int)hFile, 0 );
151 fp = _fdopen( fd, "w+b" );
156 return fp;
158 //***************************************************************************
160 static BOOL GetCrashDataPath( LPTSTR szBuffer )
162 OUString ustrValue("${$BRAND_BASE_DIR/program/bootstrap.ini:UserInstallation}");
163 ::rtl::Bootstrap::expandMacros( ustrValue );
165 if ( !ustrValue.isEmpty() )
167 ustrValue += OUString("/user/crashdata");
169 ::osl::FileBase::RC result = ::osl::Directory::createPath( ustrValue );
171 if ( ::osl::FileBase::E_None == result || ::osl::FileBase::E_EXIST == result )
173 OUString ustrPath;
175 result = ::osl::FileBase::getSystemPathFromFileURL( ustrValue, ustrPath );
176 if ( ::osl::FileBase::E_None == result )
178 _tcsncpy( szBuffer, reinterpret_cast<LPCWSTR>(ustrPath.getStr()), MAX_PATH );
179 return TRUE;
184 return FALSE;
188 static FILE *_open_reportfile( LPCTSTR lpExt, LPCTSTR lpMode )
190 FILE *fp = NULL;
191 TCHAR szAppDataPath[MAX_PATH] = _T("");
193 if ( GetCrashDataPath( szAppDataPath ) )
195 _tcscat( szAppDataPath, _T("\\crashdat") );
196 _tcscat( szAppDataPath, lpExt );
198 fp = _xfopen( szAppDataPath, lpMode );
201 return fp;
204 //***************************************************************************
206 struct CrashReportParams
208 BOOL fAllowContact;
209 tstring sEmail;
210 tstring sTitle;
211 tstring sComment;
212 ULONG uInternetConnection;
213 tstring sProxyServer;
214 tstring sProxyPort;
216 CrashReportParams();
218 void WriteToRegistry();
219 void ReadFromRegistry();
220 void ReadFromEnvironment();
223 bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams );
224 BOOL WriteCommentFile( LPCTSTR lpComment );
226 //***************************************************************************
228 LONG RegReadValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPVOID lpData, DWORD cbData )
230 HKEY hKey = NULL;
231 LONG lResult;
233 lResult = RegOpenKeyEx( hBaseKey, lpSubKey, 0, KEY_QUERY_VALUE, &hKey );
235 if ( ERROR_SUCCESS == lResult )
237 lResult = RegQueryValueEx( hKey, lpValueName, NULL, NULL, (LPBYTE)lpData, &cbData );
238 RegCloseKey( hKey );
241 return lResult;
244 //***************************************************************************
246 LONG RegWriteValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData )
248 HKEY hKey = NULL;
249 LONG lResult;
251 lResult = RegCreateKeyEx( hBaseKey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL );
253 if ( ERROR_SUCCESS == lResult )
255 lResult = RegSetValueEx( hKey, lpValueName, NULL, dwType, (CONST BYTE *)lpData, cbData );
256 RegCloseKey( hKey );
259 return lResult;
262 //***************************************************************************
264 CrashReportParams::CrashReportParams()
266 fAllowContact = FALSE;
267 sTitle = TEXT("");
268 sComment = TEXT("");
269 sEmail = TEXT("");
270 uInternetConnection = 0;
271 sProxyServer = TEXT("");
272 sProxyPort = TEXT("");
275 //***************************************************************************
277 void CrashReportParams::ReadFromRegistry()
279 TCHAR szBuffer[2048];
281 if ( ERROR_SUCCESS == RegReadValue(
282 HKEY_CURRENT_USER,
283 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
284 TEXT("HTTPProxyServer"),
285 szBuffer,
286 sizeof(szBuffer) ) )
287 sProxyServer = szBuffer;
289 DWORD dwProxyPort;
291 if ( ERROR_SUCCESS == RegReadValue(
292 HKEY_CURRENT_USER,
293 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
294 TEXT("HTTPProxyPort"),
295 &dwProxyPort,
296 sizeof(dwProxyPort) ) )
298 _stprintf( szBuffer, TEXT("%d"), dwProxyPort );
299 sProxyPort = szBuffer;
302 if ( ERROR_SUCCESS == RegReadValue(
303 HKEY_CURRENT_USER,
304 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
305 TEXT("ReturnAddress"),
306 szBuffer,
307 sizeof(szBuffer) ) )
308 sEmail = szBuffer;
310 RegReadValue(
311 HKEY_CURRENT_USER,
312 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
313 TEXT("AllowContact"),
314 &fAllowContact,
315 sizeof(fAllowContact) );
317 RegReadValue(
318 HKEY_CURRENT_USER,
319 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
320 TEXT("HTTPConnection"),
321 &uInternetConnection,
322 sizeof(uInternetConnection) );
325 //***************************************************************************
327 void CrashReportParams::WriteToRegistry()
329 RegWriteValue(
330 HKEY_CURRENT_USER,
331 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
332 TEXT("HTTPProxyServer"), REG_SZ,
333 sProxyServer.c_str(),
334 sizeof(TCHAR) * (sProxyServer.length() + 1) );
336 LPTSTR endptr = NULL;
337 DWORD dwProxyPort = _tcstoul( sProxyPort.c_str(), &endptr, 10 );
339 RegWriteValue(
340 HKEY_CURRENT_USER,
341 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
342 TEXT("HTTPProxyPort"), REG_DWORD,
343 &dwProxyPort,
344 sizeof(DWORD) );
346 RegWriteValue(
347 HKEY_CURRENT_USER,
348 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
349 TEXT("AllowContact"), REG_DWORD,
350 &fAllowContact,
351 sizeof(DWORD) );
354 RegWriteValue(
355 HKEY_CURRENT_USER,
356 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
357 TEXT("HTTPConnection"), REG_DWORD,
358 &uInternetConnection,
359 sizeof(DWORD) );
361 RegWriteValue(
362 HKEY_CURRENT_USER,
363 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
364 TEXT("ReturnAddress"), REG_SZ,
365 sEmail.c_str(),
366 sizeof(TCHAR) * (sEmail.length() + 1) );
369 //***************************************************************************
371 void CrashReportParams::ReadFromEnvironment()
373 TCHAR szBuffer[2048];
375 DWORD dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYSERVER"), szBuffer, SAL_N_ELEMENTS(szBuffer) );
377 if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) )
378 sProxyServer = szBuffer;
380 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYPORT"), szBuffer, SAL_N_ELEMENTS(szBuffer) );
382 if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) )
383 sProxyPort = szBuffer;
385 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_RETURNADDRESS"), szBuffer, SAL_N_ELEMENTS(szBuffer) );
387 if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) )
389 sEmail = szBuffer;
390 // fAllowContact = TRUE;
393 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPCONNECTIONTYPE"), szBuffer, SAL_N_ELEMENTS(szBuffer) );
395 if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) )
397 if ( 0 == _tcsicmp( szBuffer, _T("DIRECT") ) )
398 uInternetConnection = 1;
399 else if ( 0 == _tcsicmp( szBuffer, _T("MANUALPROXY") ) )
400 uInternetConnection = 2;
401 else if ( 0 == _tcsicmp( szBuffer, _T("SYSTEMDEFAULT") ) )
402 uInternetConnection = 0;
405 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_SUBJECT"), szBuffer, SAL_N_ELEMENTS(szBuffer) );
407 if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) )
408 sTitle = szBuffer;
411 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_BODYFILE"), szBuffer, SAL_N_ELEMENTS(szBuffer) );
413 if ( dwResult && dwResult < SAL_N_ELEMENTS(szBuffer) )
415 FILE *fp = _xfopen( szBuffer, _T("rb") );
417 if ( fp )
419 CHAR aUTF8Buffer[256];
420 size_t nBytesRead;
422 sComment = TEXT("");
424 while ( 0 != (nBytesRead = fread( aUTF8Buffer, sizeof(aUTF8Buffer[0]), SAL_N_ELEMENTS(aUTF8Buffer), fp )) )
426 TCHAR aBuffer[256+1];
428 DWORD dwCharacters = MultiByteToWideChar( CP_UTF8, 0, aUTF8Buffer, nBytesRead, aBuffer, SAL_N_ELEMENTS(aBuffer) - 1 );
429 aBuffer[dwCharacters] = 0;
430 sComment += aBuffer;
433 fclose( fp );
438 //***************************************************************************
440 typedef BOOL (WINAPI *MiniDumpWriteDump_PROC)(
441 IN HANDLE hProcess,
442 IN DWORD ProcessId,
443 IN HANDLE hFile,
444 IN MINIDUMP_TYPE DumpType,
445 IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
446 IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
447 IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
450 //***************************************************************************
452 static BOOL WINAPI InitRichEdit()
454 return (NULL != LoadLibrary( RICHEDIT ));
457 //***************************************************************************
459 static BOOL WINAPI DeinitRichEdit()
461 return FreeLibrary( GetModuleHandle( RICHEDIT ) );
464 //***************************************************************************
466 static string trim_string( const string& rString )
468 string temp = rString;
470 while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' )
471 temp.erase( 0, 1 );
473 string::size_type len = temp.length();
475 while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' )
477 temp.erase( len - 1, 1 );
478 len = temp.length();
481 return temp;
484 //***************************************************************************
486 static int LoadAndFormatString( HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax )
488 TCHAR szBuffer[FORMATBUFSIZE];
489 TCHAR szBuffer2[FORMATBUFSIZE];
491 LoadString( hInstance, uID, szBuffer, SAL_N_ELEMENTS(szBuffer) );
493 LPCTSTR src;
494 LPTSTR dest;
495 for ( dest = szBuffer2, src = szBuffer; *src; src++, dest++ )
497 switch ( *src )
499 case '~':
500 *dest = '&';
501 break;
502 case '\\':
503 switch ( *(++src) )
505 case 'n':
506 *dest = '\n';
507 break;
508 case 'r':
509 *dest = '\r';
510 break;
511 default:
512 *dest = *src;
513 break;
515 break;
516 default:
517 *dest = *src;
518 break;
521 *dest = *src;
522 return ExpandEnvironmentStrings( szBuffer2, lpBuffer, nBufferMax );
526 //***************************************************************************
528 static string wstring2utf8( const wstring &rString )
530 int nBufSize = WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, NULL, 0, NULL, FALSE );
532 LPSTR pBuffer = (LPSTR)alloca( nBufSize );
534 WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, pBuffer, nBufSize, NULL, FALSE );
536 return string( pBuffer );
539 //***************************************************************************
541 static string xml_encode( const string &rString )
543 string temp = rString;
544 string::size_type pos = 0;
546 // First replace all occurrences of '&' because it may occur in further
547 // encoded chardters too
549 for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 )
550 temp.replace( pos, 1, "&amp;" );
552 for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 )
553 temp.replace( pos, 1, "&lt;" );
555 for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 )
556 temp.replace( pos, 1, "&gt;" );
558 return temp;
561 //***************************************************************************
563 static size_t fcopy( FILE *fpin, FILE *fpout )
565 char buffer[1024];
566 size_t nBytesWritten = 0;
568 if ( fpin && fpout )
570 size_t nBytes;
571 while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) )
573 nBytesWritten += fwrite( buffer, 1, nBytes, fpout );
577 return nBytesWritten;
580 //***************************************************************************
582 static string GetModuleDirectory( HMODULE hModule )
584 TCHAR szModuleName[MAX_PATH] = TEXT("");
585 TCHAR szDrive[_MAX_DRIVE];
586 TCHAR szDir[_MAX_DIR];
587 TCHAR szFName[_MAX_FNAME];
588 TCHAR szExt[_MAX_EXT];
590 if ( GetModuleFileName( hModule, szModuleName, MAX_PATH ) )
592 _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
593 _tmakepath( szModuleName, szDrive, szDir, _T(""), _T("") );
596 CHAR szModuleNameUTF8[MAX_PATH] = "";
598 WideCharToMultiByte( CP_UTF8, 0, szModuleName, -1, szModuleNameUTF8, SAL_N_ELEMENTS(szModuleNameUTF8), NULL, NULL );
599 return string( szModuleNameUTF8 );
602 //***************************************************************************
604 string GetFileDirectory( const string& rFilePath )
606 string aDir = rFilePath;
607 size_t pos = aDir.rfind( '\\' );
609 if ( string::npos != pos )
610 aDir.erase( pos + 1 );
611 else
612 aDir = "";
614 return aDir;
617 //***************************************************************************
619 string GetFileName( const string& rFilePath )
621 string aName = rFilePath;
622 size_t pos = aName.rfind( '\\' );
624 if ( string::npos != pos )
625 return aName.substr( pos + 1 );
626 else
627 return aName;
630 //***************************************************************************
632 BOOL WriteReportFile( CrashReportParams *pParams )
634 BOOL fSuccess = FALSE;
635 TCHAR szTempPath[MAX_PATH];
637 if ( GetTempPath( SAL_N_ELEMENTS(szTempPath), szTempPath ) )
639 TCHAR szFileName[MAX_PATH];
641 if ( GetTempFileName( szTempPath, TEXT("RPM"), 0, szFileName ) )
643 HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
645 if ( hFile )
647 int fd = _open_osfhandle( (LONG)hFile, _O_TEXT );
648 FILE *fp = _fdopen( fd, "w+t" );
649 CHAR szTitle[1024] = "";
650 CHAR szBuildId[1024] = "";
651 CHAR szEmail[1024] = "";
652 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
654 WideCharToMultiByte( CP_UTF8, 0, pParams->sTitle.c_str(), -1, szTitle, sizeof(szTitle), NULL, NULL );
655 WideCharToMultiByte( CP_UTF8, 0, g_szBuildId, -1, szBuildId, sizeof(szBuildId), NULL, NULL );
656 WideCharToMultiByte( CP_UTF8, 0, pParams->sEmail.c_str(), -1, szEmail, sizeof(szEmail), NULL, NULL );
658 fprintf( fp,
659 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
660 "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
661 "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
662 "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n",
663 pszUserType ? pszUserType : "",
664 pParams->fAllowContact ? "true" : "false",
665 pParams->fAllowContact ? xml_encode(szEmail).c_str() : ""
668 fprintf( fp,
669 "<reportmail:title>%s</reportmail:title>\n",
670 xml_encode(szTitle).c_str() );
672 fprintf( fp,
673 "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain;charset=UTF-8\" class=\"UserComment\"/>\n"
674 "<reportmail:attachment name=\"user.dmp\" media-type=\"application/octet-stream\" class=\"UserDump\"/>\n"
675 "</reportmail:mail>\n"
677 "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" procpath=\"%s\" exceptiontype=\"0x%08X\" product=\"%s\"/>\n",
678 szBuildId,
679 _INPATH,
680 xml_encode(g_strDefaultLanguage).c_str(),
681 xml_encode(GetModuleDirectory( NULL )).c_str(),
682 g_dwExceptionCode,
683 xml_encode(wstring2utf8(g_wstrProductKey)).c_str()
686 OSVERSIONINFO VersionInfo;
688 ZeroMemory( &VersionInfo, sizeof(VersionInfo) );
689 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo );
691 GetVersionEx( &VersionInfo );
693 fprintf( fp,
694 "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
695 "<systeminfo:System name=\"%s\" version=\"%d.%d\" build=\"%d\" locale=\"0x%08x\"/>\n"
697 VER_PLATFORM_WIN32_NT == VersionInfo.dwPlatformId ? "Windows NT" : "Windows",
698 VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion,
699 VersionInfo.dwBuildNumber,
700 GetUserDefaultLangID()
703 fprintf( fp, "<systeminfo:CPU type=\"x86\"/>\n" );
704 fprintf( fp, "</systeminfo:systeminfo>\n" );
706 fseek( g_fpStackFile, 0, SEEK_SET );
707 fcopy( g_fpStackFile, fp );
709 fseek( g_fpChecksumFile, 0, SEEK_SET );
710 fcopy( g_fpChecksumFile, fp );
712 fprintf( fp, "</errormail:errormail>\n" );
714 fclose( fp );
716 fSuccess = TRUE;
718 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szReportFileNameA, MAX_PATH, NULL, NULL );
721 if ( !fSuccess )
722 DeleteFile( szFileName );
726 return fSuccess;
729 //***************************************************************************
731 static BOOL SaveDumpFile( HWND hwndOwner )
733 OPENFILENAME ofn;
734 TCHAR szFileName[MAX_PATH] = TEXT("");
736 ZeroMemory( &ofn, sizeof(ofn) );
737 ofn.lStructSize = sizeof(ofn);
739 ofn.hwndOwner = hwndOwner;
740 ofn.lpstrFilter = TEXT("*.dmp\0*.dmp\0*.*\0*.*\0");
741 ofn.lpstrFile = szFileName;
742 ofn.nMaxFile = MAX_PATH;
743 ofn.Flags = OFN_ENABLESIZING | OFN_LONGNAMES | OFN_OVERWRITEPROMPT;
744 ofn.lpstrDefExt = TEXT("dmp");
746 if ( GetSaveFileName( &ofn ) )
748 return CopyFile( g_szDumpFileName, szFileName, FALSE );
750 return FALSE;
753 //***************************************************************************
755 static BOOL ScreenToClientRect( HWND hwnd, LPRECT lprc )
757 return ScreenToClient( hwnd, (LPPOINT)&lprc->left ) && ScreenToClient( hwnd, (LPPOINT)&lprc->right );
760 static BOOL SetWindowRect( HWND hwnd, const RECT *lprc, BOOL fRepaint )
762 return MoveWindow( hwnd, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, fRepaint );
765 #define GM_LOX 0x01
766 #define GM_HIX 0x02
767 #define GM_LOY 0x04
768 #define GM_HIY 0x08
770 static BOOL SetGrowMode( HWND hwnd, DWORD dwGrowMode )
772 return SetProp( hwnd, TEXT("GrowMode"), (HANDLE)dwGrowMode );
775 static DWORD GetGrowMode( HWND hwnd )
777 return (DWORD)GetProp( hwnd, TEXT("GrowMode") );
780 static BOOL GrowWindow( HWND hwnd, LONG dxClient, LONG dyClient, BOOL fRepaint )
782 DWORD dwGrowMode = GetGrowMode( hwnd );
783 RECT rc;
785 GetWindowRect( hwnd, &rc );
787 if ( dwGrowMode & GM_LOX )
788 rc.left += dxClient;
789 if ( dwGrowMode & GM_HIX )
790 rc.right += dxClient;
791 if ( dwGrowMode & GM_LOY )
792 rc.top += dyClient;
793 if ( dwGrowMode & GM_HIY )
794 rc.bottom += dyClient;
796 ScreenToClientRect( GetParent( hwnd ), &rc );
797 SetWindowRect( hwnd, &rc, fRepaint );
799 return TRUE;
802 BOOL CALLBACK GrowChildWindows(
803 HWND hwnd, // handle to child window
804 LPARAM lParam // application-defined value
807 LONG cx = (SHORT)LOWORD( lParam );
808 LONG cy = (SHORT)HIWORD( lParam );
810 GrowWindow( hwnd, cx, cy, TRUE );
812 return TRUE;
815 BOOL CALLBACK PreviewDialogProc(
816 HWND hwndDlg,
817 UINT uMsg,
818 WPARAM wParam,
819 LPARAM lParam
822 static RECT rcClient;
824 switch ( uMsg )
826 case WM_SIZE:
828 LONG cx = LOWORD( lParam );
829 LONG cy = HIWORD( lParam );
830 LONG dxClient, dyClient;
832 dxClient = cx - rcClient.right;
833 dyClient = cy - rcClient.bottom;
835 EnumChildWindows( hwndDlg, GrowChildWindows, MAKELONG( (SHORT)dxClient, (SHORT)dyClient) );
837 GetClientRect( hwndDlg, &rcClient );
839 break;
840 case WM_INITDIALOG:
842 GetClientRect( hwndDlg, &rcClient );
843 SetGrowMode( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GM_HIX | GM_HIY );
844 SetGrowMode( GetDlgItem(hwndDlg, IDOK), GM_LOX | GM_HIX | GM_LOY | GM_HIY );
846 CrashReportParams *pParams = (CrashReportParams *)lParam;
848 TCHAR szBuffer[256] = TEXT("");
849 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
850 HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
852 GetWindowText( hwndParent, szBuffer, SAL_N_ELEMENTS(szBuffer) );
853 SetWindowText( hwndDlg, szBuffer );
855 LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
856 Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
858 basic_string<TCHAR> aString;
860 aString.append( pParams->sTitle );
861 aString.append( _T("\r\n\r\n") );
862 aString.append( pParams->sComment );
863 aString.append( _T("\r\n---------- report ----------\r\n") );
865 FILE *fp = fopen( g_szReportFileNameA, "r" );
867 if ( fp )
869 char buf[1024];
871 while ( fgets( buf, SAL_N_ELEMENTS(buf), fp ) != NULL )
873 WCHAR bufW[1024];
875 MultiByteToWideChar( CP_UTF8, 0, buf, -1, bufW, SAL_N_ELEMENTS(bufW) );
877 aString.append( bufW );
880 fclose( fp );
883 aString.append( _T("\r\n---------- stack ----------\r\n") );
885 fp = fopen( g_szDumpFileNameA, "rb" );
887 if ( fp )
889 unsigned char buf[16];
890 int count;
894 int i;
896 count = fread( buf, sizeof(buf[0]), SAL_N_ELEMENTS(buf), fp );
898 for ( i = 0; i < count; i++ )
900 TCHAR output[16];
902 _sntprintf( output, SAL_N_ELEMENTS(output), _T("%02X\x20"), buf[i] );
903 aString.append( output );
905 for ( ; i < SAL_N_ELEMENTS(buf); i++ )
907 aString.append( _T("\x20\x20\x20") );
910 for ( i = 0; i < count; i++ )
912 TCHAR output[2];
914 if ( (int)buf[i] >= 0x20 && (int)buf[i] <= 0x7F )
915 output[0] = (TCHAR)buf[i];
916 else
917 output[0] = '.';
918 output[1] = 0;
919 aString.append( output );
922 aString.append( _T("\r\n") );
924 } while ( count );
926 fclose( fp );
928 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), aString.c_str() );
929 SetWindowFont( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GetStockObject( SYSTEM_FIXED_FONT ), TRUE );
931 return TRUE;
932 case WM_COMMAND:
933 switch ( LOWORD(wParam) )
935 case IDOK:
936 case IDCANCEL:
937 EndDialog( hwndDlg, wParam );
938 return TRUE;
940 break;
941 default:
942 break;
945 return FALSE;
947 //***************************************************************************
949 static void PreviewReport( HWND hwndParent, CrashReportParams *pParams )
951 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE );
953 WriteReportFile( pParams );
955 DialogBoxParam(
956 hInstance,
957 MAKEINTRESOURCE(IDD_PREVIEW_FRAME),
958 hwndParent,
959 PreviewDialogProc,
960 (LPARAM)pParams
963 DeleteFileA( g_szReportFileNameA );
965 //***************************************************************************
966 void UpdateOptionsDialogControls( HWND hwndDlg )
968 if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED )
970 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), TRUE );
971 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), TRUE );
973 else
975 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), FALSE );
976 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), FALSE );
980 //***************************************************************************
982 BOOL CALLBACK OptionsDialogProc(
983 HWND hwndDlg,
984 UINT uMsg,
985 WPARAM wParam,
986 LPARAM lParam
989 static CrashReportParams *pParams;
991 switch ( uMsg )
993 case WM_INITDIALOG:
995 TCHAR szBuffer[1024] = TEXT("");
996 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
997 //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
999 pParams = (CrashReportParams *)lParam;
1001 LoadAndFormatString( hInstance, IDS_OPTIONS_CAPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1002 SetWindowText( hwndDlg, szBuffer );
1004 LoadAndFormatString( hInstance, IDS_PROXY_SETTINGS_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1005 Static_SetText( GetDlgItem(hwndDlg, IDC_PROXY_SETTINGS), szBuffer );
1007 LoadAndFormatString( hInstance, IDS_PROXY_SYSTEM, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1008 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM), szBuffer );
1010 LoadAndFormatString( hInstance, IDS_PROXY_DIRECT, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1011 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT), szBuffer );
1013 LoadAndFormatString( hInstance, IDS_PROXY_MANUAL, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1014 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL), szBuffer );
1016 LoadAndFormatString( hInstance, IDS_LABEL_PROXYSERVER, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1017 Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYSERVER), szBuffer );
1019 LoadAndFormatString( hInstance, IDS_LABEL_PROXYPORT, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1020 Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYPORT), szBuffer );
1022 LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1023 Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
1025 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1026 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
1028 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), pParams->sProxyServer.c_str() );
1029 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), pParams->sProxyPort.c_str() );
1031 Button_SetCheck( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM + pParams->uInternetConnection), BST_CHECKED );
1033 SendMessage(
1034 GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION),
1035 EM_SETBKGNDCOLOR,
1036 (WPARAM)FALSE,
1037 GetSysColor( COLOR_3DFACE ) );
1038 LoadAndFormatString( hInstance, IDS_PROXY_DESCRIPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1039 Edit_SetText( GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), szBuffer );
1041 UpdateOptionsDialogControls( hwndDlg );
1043 return TRUE;
1044 case WM_COMMAND:
1045 switch ( LOWORD(wParam) )
1047 case IDC_RADIO_SYSTEM:
1048 case IDC_RADIO_DIRECT:
1049 case IDC_RADIO_MANUAL:
1050 if ( BN_CLICKED == HIWORD(wParam) )
1051 UpdateOptionsDialogControls( hwndDlg );
1052 break;
1053 case IDOK:
1055 TCHAR szBuffer[1024];
1057 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), szBuffer, SAL_N_ELEMENTS(szBuffer) );
1058 pParams->sProxyServer = szBuffer;
1060 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), szBuffer, SAL_N_ELEMENTS(szBuffer) );
1061 pParams->sProxyPort = szBuffer;
1063 if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT) ) & BST_CHECKED )
1064 pParams->uInternetConnection = 1;
1065 else if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED )
1066 pParams->uInternetConnection = 2;
1067 else
1068 pParams->uInternetConnection = 0;
1070 case IDCANCEL:
1071 EndDialog( hwndDlg, wParam );
1072 return TRUE;
1074 break;
1075 default:
1076 break;
1079 return FALSE;
1082 //***************************************************************************
1084 static void OptionsDialog( HWND hwndParent, CrashReportParams *pParams )
1086 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE );
1088 if ( IDOK == DialogBoxParam(
1089 hInstance,
1090 MAKEINTRESOURCE(IDD_OPTIONS_FRAME),
1091 hwndParent,
1092 OptionsDialogProc,
1093 (LPARAM)pParams
1095 pParams->WriteToRegistry();
1098 //***************************************************************************
1100 void UpdateReportDialogControls( HWND hwndDlg )
1102 EnableWindow(
1103 GetDlgItem(hwndDlg, IDC_EDIT_EMAIL),
1104 Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE );
1105 EnableWindow(
1106 GetDlgItem(hwndDlg, IDC_LABEL_EMAIL),
1107 Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE );
1110 //***************************************************************************
1112 BOOL CALLBACK ReportDialogProc(
1113 HWND hwndDlg,
1114 UINT uMsg,
1115 WPARAM wParam,
1116 LPARAM
1119 switch ( uMsg )
1121 case WM_INITDIALOG:
1123 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1124 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1125 TCHAR szBuffer[FORMATBUFSIZE];
1127 LoadAndFormatString( hInstance, IDS_REPORT_INTRO, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1128 Static_SetText( GetDlgItem(hwndDlg, IDC_REPORT_INTRO), szBuffer );
1130 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT3), szBuffer );
1132 LoadAndFormatString( hInstance, IDS_ENTER_TITLE, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1133 Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_TITLE), szBuffer );
1135 LoadAndFormatString( hInstance, IDS_ENTER_DESCRIPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1136 Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_DESCRIPTION), szBuffer );
1138 LoadAndFormatString( hInstance, IDS_SHOW_REPORT_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1139 Button_SetText( GetDlgItem(hwndDlg, IDC_SHOW_REPORT), szBuffer );
1141 LoadAndFormatString( hInstance, IDS_SAVE_REPORT_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1142 Button_SetText( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), szBuffer );
1144 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
1145 if ( pszUserType )
1146 ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_SHOW );
1147 else
1148 ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_HIDE );
1150 LoadAndFormatString( hInstance, IDS_OPTIONS_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1151 Button_SetText( GetDlgItem(hwndDlg, IDC_OPTIONS), szBuffer );
1153 LoadAndFormatString( hInstance, IDS_ALLOW_CONTACT, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1154 Button_SetText( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), szBuffer );
1155 Button_SetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), pParams->fAllowContact ? BST_CHECKED : BST_UNCHECKED );
1157 LoadAndFormatString( hInstance, IDS_LABEL_EMAIL, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1158 Button_SetText( GetDlgItem(hwndDlg, IDC_LABEL_EMAIL), szBuffer );
1160 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), pParams->sEmail.c_str() );
1162 UpdateReportDialogControls( hwndDlg );
1164 return TRUE;
1165 case WM_SHOWWINDOW:
1166 if ( (BOOL)wParam )
1168 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1169 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1170 TCHAR szBuffer[FORMATBUFSIZE];
1172 LoadAndFormatString( hInstance, IDS_REPORT_CAPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1173 SetWindowText( GetParent(hwndDlg), szBuffer );
1175 LoadAndFormatString( hInstance, IDS_REPORT_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1176 SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
1178 LoadAndFormatString( hInstance, IDS_DONOT_SEND_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1179 Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer );
1182 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), TRUE );
1183 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), TRUE );
1184 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), FALSE );
1186 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), pParams->sTitle.c_str() );
1187 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), pParams->sComment.c_str() );
1189 SetFocus( GetDlgItem(hwndDlg,IDC_EDIT_TITLE) );
1191 break;
1192 case WM_COMMAND:
1193 switch ( LOWORD(wParam) )
1195 case IDC_SHOW_REPORT:
1197 TCHAR szBuffer[32767];
1199 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1201 pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT) ) ? TRUE : FALSE;
1203 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), szBuffer, SAL_N_ELEMENTS(szBuffer) );
1204 pParams->sTitle = szBuffer;
1206 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), szBuffer, SAL_N_ELEMENTS(szBuffer) );
1207 pParams->sComment = szBuffer;
1209 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), szBuffer, SAL_N_ELEMENTS(szBuffer) );
1210 pParams->sEmail = szBuffer;
1212 PreviewReport( GetParent(hwndDlg), pParams );
1214 return TRUE;
1215 case IDC_SAVE_REPORT:
1216 SaveDumpFile( GetParent(hwndDlg) );
1217 return TRUE;
1218 case IDC_OPTIONS:
1220 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1221 OptionsDialog( GetParent(hwndDlg), pParams );
1223 return TRUE;
1224 case IDC_ALLOW_CONTACT:
1225 if ( BN_CLICKED == HIWORD(wParam) )
1226 UpdateReportDialogControls( hwndDlg );
1227 return TRUE;
1229 break;
1230 default:
1231 break;
1234 return FALSE;
1236 //***************************************************************************
1238 BOOL CALLBACK WelcomeDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
1240 switch ( uMsg )
1242 case WM_INITDIALOG:
1244 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1245 HWND hwndRichEdit = GetDlgItem(hwndDlg, IDC_RICHEDIT21);
1246 TCHAR szBuffer[FORMATBUFSIZE];
1247 TCHAR szBuffer2[FORMATBUFSIZE];
1248 TCHAR szURL[256];
1249 TCHAR szCaption[256];
1251 SendMessage(
1252 hwndRichEdit,
1253 EM_SETBKGNDCOLOR,
1254 (WPARAM)FALSE,
1255 GetSysColor( COLOR_3DFACE ) );
1257 SendMessage( hwndRichEdit, EM_SETEVENTMASK, 0, ENM_LINK );
1258 SendMessage( hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0 );
1260 LoadAndFormatString( hInstance, IDS_WELCOME_BODY1, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1261 LoadAndFormatString( hInstance, IDS_WELCOME_BODY2, szBuffer2, SAL_N_ELEMENTS(szBuffer2) );
1262 _tcsncat( szBuffer, szBuffer2, SAL_N_ELEMENTS(szBuffer) );
1263 LoadAndFormatString( hInstance, IDS_WELCOME_BODY3, szBuffer2, SAL_N_ELEMENTS(szBuffer2) );
1264 _tcsncat( szBuffer, szBuffer2, SAL_N_ELEMENTS(szBuffer) );
1265 LoadString( hInstance, IDS_PRIVACY_URL, szURL, SAL_N_ELEMENTS(szURL) );
1266 _tcsncat( szBuffer, szURL, SAL_N_ELEMENTS(szBuffer) );
1267 SetWindowText( hwndRichEdit, szBuffer );
1269 LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szCaption, SAL_N_ELEMENTS(szCaption) );
1270 SetWindowText( GetParent(hwndDlg), szCaption );
1273 return TRUE;
1274 case WM_SHOWWINDOW:
1275 if ( (BOOL)wParam )
1277 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1278 TCHAR szBuffer[FORMATBUFSIZE];
1280 LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1281 SetWindowText( GetParent(hwndDlg), szBuffer );
1283 LoadAndFormatString( hInstance, IDS_WELCOME_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1284 SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
1286 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1287 Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer );
1289 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), FALSE );
1290 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), FALSE );
1291 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), TRUE );
1293 SetFocus( GetDlgItem(GetParent(hwndDlg),IDNEXT) );
1295 break;
1296 case WM_NOTIFY:
1298 LPNMHDR pnmh = (LPNMHDR)lParam;
1300 if ( pnmh->idFrom == IDC_RICHEDIT21 && pnmh->code == EN_LINK )
1302 ENLINK *plink = (ENLINK*)lParam;
1304 if ( plink->msg == WM_LBUTTONUP )
1306 TCHAR szBuffer[256];
1307 TEXTRANGE range;
1309 range.chrg = plink->chrg;
1310 range.lpstrText = szBuffer;
1312 SendMessage( pnmh->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&range );
1314 ShellExecute( hwndDlg, NULL, szBuffer, NULL, NULL, SW_SHOWDEFAULT );
1319 break;
1320 default:
1321 break;
1324 return FALSE;
1326 //***************************************************************************
1328 BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
1330 static HWND hwndPages[2] = { NULL };
1331 static int iActualPage = 0;
1333 switch ( uMsg )
1335 case WM_INITDIALOG:
1337 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1338 TCHAR szBuffer[FORMATBUFSIZE];
1340 SetWindowLong( hwndDlg, GWL_USERDATA, (LONG)lParam );
1341 hwndPages[0] = CreateDialog(
1342 hInstance,
1343 MAKEINTRESOURCE(IDD_WELCOME_PAGE),
1344 hwndDlg,
1345 WelcomeDialogProc );
1347 hwndPages[1] = CreateDialog(
1348 hInstance,
1349 MAKEINTRESOURCE(IDD_REPORT_PAGE),
1350 hwndDlg,
1351 ReportDialogProc );
1353 CHARFORMAT chfmt;
1355 chfmt.cbSize = sizeof(chfmt);
1356 chfmt.dwMask = CFM_BOLD;
1357 chfmt.dwEffects = CFE_BOLD;
1359 SendMessage(
1360 GetDlgItem(hwndDlg, IDC_HEADER),
1361 EM_SETCHARFORMAT,
1362 SCF_ALL,
1363 (LPARAM)&chfmt );
1365 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1366 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
1368 LoadAndFormatString( hInstance, IDS_NEXT_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1369 Button_SetText( GetDlgItem(hwndDlg, IDNEXT), szBuffer );
1371 LoadAndFormatString( hInstance, IDS_SEND_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1372 Button_SetText( GetDlgItem(hwndDlg, IDFINISH), szBuffer );
1374 LoadAndFormatString( hInstance, IDS_BACK_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
1375 Button_SetText( GetDlgItem(hwndDlg, IDBACK), szBuffer );
1377 ShowWindow( hwndPages[1], SW_HIDE );
1378 ShowWindow( hwndPages[0], SW_SHOW );
1380 // Let Crash Reporter window stay on top of all other windows
1381 SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
1383 return FALSE;
1384 case WM_CTLCOLORSTATIC:
1385 return (BOOL)CreateSolidBrush(GetSysColor(COLOR_WINDOW));
1386 case WM_COMMAND:
1387 switch ( LOWORD(wParam) )
1389 case IDBACK:
1390 if ( iActualPage > 0 )
1392 ShowWindow( hwndPages[iActualPage], SW_HIDE );
1393 ShowWindow( hwndPages[--iActualPage], SW_SHOW );
1395 return TRUE;
1396 case IDNEXT:
1397 if ( iActualPage < SAL_N_ELEMENTS(hwndPages) - 1 )
1399 ShowWindow( hwndPages[iActualPage], SW_HIDE );
1400 ShowWindow( hwndPages[++iActualPage], SW_SHOW );
1402 return TRUE;
1403 case IDFINISH:
1405 TCHAR szBuffer[32767];
1406 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( hwndDlg, GWL_USERDATA );
1408 pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndPages[1], IDC_ALLOW_CONTACT) ) ? TRUE : FALSE;
1410 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_TITLE), szBuffer, SAL_N_ELEMENTS(szBuffer) );
1411 pParams->sTitle = szBuffer;
1413 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_DESCRIPTION), szBuffer, SAL_N_ELEMENTS(szBuffer) );
1414 pParams->sComment = szBuffer;
1416 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_EMAIL), szBuffer, SAL_N_ELEMENTS(szBuffer) );
1417 pParams->sEmail = szBuffer;
1419 if ( pParams->fAllowContact && !pParams->sEmail.length() )
1421 TCHAR szMessage[MAX_TEXT_BUFFER];
1423 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_NOEMAILADDRESS, szMessage, SAL_N_ELEMENTS(szMessage) );
1425 MessageBox( hwndDlg, szMessage, NULL, MB_ICONERROR | MB_OK );
1426 break; // Don't end the dialog
1428 else
1430 pParams->WriteToRegistry();
1432 WriteCommentFile( pParams->sComment.c_str() );
1433 WriteReportFile( pParams );
1435 if ( !SendCrashReport( hwndDlg, *pParams ) )
1436 break; // Don't end the dialog
1439 // Fallthrough !!!
1440 case IDCANCEL:
1441 EndDialog( hwndDlg, wParam );
1442 return TRUE;
1444 break;
1445 default:
1446 break;
1449 return FALSE;
1454 //*****************************************************************************
1455 //* Generate MD5 checksum
1456 //*****************************************************************************
1458 #define MAGIC_DESCRIPTION_FILLER 'x'
1459 #define MAGIC_DESCRIPTION_COUNT 80
1461 static void repatch_soffice_exe( void *pBuffer, size_t nBufSize )
1463 wchar_t DescriptionBuffer[MAGIC_DESCRIPTION_COUNT];
1465 memset( DescriptionBuffer, 0, sizeof(DescriptionBuffer) );
1466 wcsncpy( DescriptionBuffer, g_wstrProductKey.c_str(), SAL_N_ELEMENTS(DescriptionBuffer) - 1 );
1468 bool bPatched = false;
1472 void *pFound = memchr( pBuffer, ((char *)DescriptionBuffer)[0], nBufSize );
1474 if ( pFound )
1476 size_t distance = (char *)pFound - (char *)pBuffer;
1478 if ( nBufSize >= distance )
1480 nBufSize -= distance;
1482 if ( nBufSize >= sizeof(DescriptionBuffer) &&
1483 0 == memcmp( pFound, DescriptionBuffer, sizeof(DescriptionBuffer) ) )
1485 for ( int i = 0; i < 80; i++ )
1487 ((wchar_t *)pFound)[i] = MAGIC_DESCRIPTION_FILLER;
1489 bPatched = true;
1491 else
1493 pBuffer = (void *)(((char *)pFound) + 1);
1494 nBufSize--;
1497 else
1498 nBufSize = 0;
1500 else
1501 nBufSize = 0;
1502 } while ( !bPatched && nBufSize );
1505 // Normalize executable/library images to prevent different MD5 checksums due
1506 // to a different PE header date/checksum (this doesn't affect the code/data
1507 // sections of a executable/library. Please see tools/source/bootstrp/md5.cxx
1508 // where the same method is also used. The tool so_checksum creates the MD5
1509 // checksums during build time. You have to make sure that both methods use the
1510 // same algorithm otherwise there could be problems with stack reports.
1511 static void normalize_pe_image(sal_uInt8* buffer, size_t nBufferSize)
1513 const int OFFSET_PE_OFFSET = 0x3c;
1514 const int OFFSET_COFF_TIMEDATESTAMP = 4;
1515 const int PE_SIGNATURE_SIZE = 4;
1516 const int COFFHEADER_SIZE = 20;
1517 const int OFFSET_PE_OPTIONALHEADER_CHECKSUM = 64;
1519 // Check the header part of the file buffer
1520 if (buffer[0] == 'M' && buffer[1] == 'Z')
1522 unsigned long PEHeaderOffset = (long)buffer[OFFSET_PE_OFFSET];
1523 if (PEHeaderOffset < nBufferSize-4)
1525 if ( buffer[PEHeaderOffset] == 'P' &&
1526 buffer[PEHeaderOffset+1] == 'E' &&
1527 buffer[PEHeaderOffset+2] == 0 &&
1528 buffer[PEHeaderOffset+3] == 0 )
1530 PEHeaderOffset += PE_SIGNATURE_SIZE;
1531 if (PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP < nBufferSize-4)
1533 // Set timedatestamp and checksum fields to a normalized
1534 // value to enforce the same MD5 checksum for identical
1535 // Windows executables/libraries.
1536 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP] = 0;
1537 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+1] = 0;
1538 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+2] = 0;
1539 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+3] = 0;
1542 if (PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM < nBufferSize-4)
1544 // Set checksum to a normalized value
1545 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM] = 0;
1546 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+1] = 0;
1547 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+2] = 0;
1548 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+3] = 0;
1555 static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
1557 const int MINIMAL_FILESIZE = 512;
1559 sal_uInt32 nBytesProcessed = 0;
1561 FILE *fp = fopen( filename, "rb" );
1563 if ( fp )
1565 long nFileSize;
1567 if ( 0 == fseek( fp, 0, SEEK_END ) && -1 != (nFileSize = ftell(fp)) )
1569 rewind( fp );
1571 sal_uInt8 *pBuffer = new sal_uInt8[nFileSize];
1572 size_t nBytesRead = fread( pBuffer, 1, nFileSize, fp );
1574 if ( sal::static_int_cast<long>(nBytesRead) == nFileSize )
1576 if ( 0 == stricmp( GetFileName(filename).c_str(), "soffice.bin" ) )
1577 repatch_soffice_exe( pBuffer, nBytesRead );
1578 else if ( nFileSize > MINIMAL_FILESIZE )
1579 normalize_pe_image( pBuffer, nBytesRead );
1581 rtlDigestError error = rtl_digest_MD5 (
1582 pBuffer, nBytesRead,
1583 pChecksum, nChecksumLen );
1585 if ( rtl_Digest_E_None == error )
1586 nBytesProcessed = nBytesRead;
1589 delete[] pBuffer;
1591 fclose( fp );
1593 return nBytesProcessed;
1596 //***************************************************************************
1598 static bool WriteStackFile( FILE *fout, boost::unordered_map< string, string >& rLibraries, DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers )
1600 bool fSuccess = false;
1602 if ( fout && dwProcessId && pExceptionPointers )
1604 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
1606 if ( IsValidHandle(hProcess) )
1608 EXCEPTION_POINTERS aExceptionPointers;
1609 CONTEXT aContextRecord;
1611 ReadProcessMemory(
1612 hProcess,
1613 pExceptionPointers,
1614 &aExceptionPointers,
1615 sizeof(aExceptionPointers),
1616 NULL );
1618 ReadProcessMemory(
1619 hProcess,
1620 aExceptionPointers.ContextRecord,
1621 &aContextRecord,
1622 sizeof(aContextRecord),
1623 NULL );
1625 STACKFRAME frame;
1627 ZeroMemory( &frame, sizeof(frame) );
1628 frame.AddrPC.Offset = aContextRecord.Eip;
1629 frame.AddrPC.Mode = AddrModeFlat;
1630 frame.AddrFrame.Offset = aContextRecord.Ebp;
1631 frame.AddrFrame.Mode = AddrModeFlat;
1633 BOOL bSuccess;
1634 int frameNum = 0;
1636 SymInitialize( hProcess, NULL, TRUE );
1638 fprintf( fout, "<errormail:Stack type=\"Win32\">\n" );
1642 fSuccess = true;
1644 bSuccess = StackWalk( IMAGE_FILE_MACHINE_I386,
1645 hProcess,
1646 NULL,
1647 &frame,
1648 &aContextRecord,
1649 (PREAD_PROCESS_MEMORY_ROUTINE)ReadProcessMemory,
1650 SymFunctionTableAccess,
1651 SymGetModuleBase,
1652 NULL );
1654 if ( bSuccess )
1656 // Note: ImageHelp ANSI functions do not have an A postfix while
1657 // Unicode versions have a W postfix. There's no macro
1658 // that depends on define UNICODE
1660 IMAGEHLP_MODULE moduleInfo;
1662 ZeroMemory( &moduleInfo, sizeof(moduleInfo) );
1663 moduleInfo.SizeOfStruct = sizeof(moduleInfo);
1665 if ( SymGetModuleInfo( hProcess, frame.AddrPC.Offset, &moduleInfo ) )
1667 rLibraries[ GetFileName( moduleInfo.LoadedImageName ).c_str() ] = moduleInfo.LoadedImageName;
1669 DWORD dwRelOffset = 0;
1670 BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 256 ];
1671 PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
1673 ZeroMemory( symbolBuffer, sizeof(symbolBuffer) );
1674 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
1675 pSymbol->MaxNameLength = 256;
1677 if ( SymGetSymFromAddr( hProcess, frame.AddrPC.Offset, &dwRelOffset, pSymbol ) )
1678 fprintf( fout, "<errormail:StackInfo " \
1679 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" ordinal=\"%s+0x%p\" name=\"%s\" path=\"%s\"/>\n",
1680 frameNum,
1681 frame.AddrPC.Offset,
1682 frame.AddrPC.Offset - moduleInfo.BaseOfImage,
1683 xml_encode(pSymbol->Name).c_str(),
1684 frame.AddrPC.Offset - pSymbol->Address,
1685 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
1686 xml_encode( GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
1688 else
1689 fprintf( fout, "<errormail:StackInfo " \
1690 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" name=\"%s\" path=\"%s\"/>\n",
1691 frameNum,
1692 frame.AddrPC.Offset,
1693 frame.AddrPC.Offset - moduleInfo.BaseOfImage,
1694 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
1695 xml_encode(GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
1698 else
1699 fprintf( fout, "<errormail:StackInfo pos=\"%d\" ip=\"0x%p\"/>\n",
1700 frameNum,
1701 frame.AddrPC.Offset
1704 frameNum++;
1707 } while ( bSuccess );
1709 fprintf( fout, "</errormail:Stack>\n" );
1711 SymCleanup( hProcess );
1713 CloseHandle( hProcess );
1718 return fSuccess;
1721 bool WriteChecksumFile( FILE *fchksum, const boost::unordered_map< string, string >& rLibraries )
1723 bool success = false;
1725 if ( fchksum && rLibraries.size() )
1727 fprintf( fchksum, "<errormail:Checksums type=\"MD5\">\n" );
1729 boost::unordered_map< string, string >::const_iterator iter;
1731 for ( iter = rLibraries.begin(); iter != rLibraries.end(); ++iter )
1733 sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5];
1734 sal_uInt32 nBytesProcessed = calc_md5_checksum(
1735 iter->second.c_str(),
1736 checksum, sizeof(checksum) );
1738 if ( nBytesProcessed )
1740 fprintf( fchksum, "<errormail:Checksum sum=\"0x" );
1741 for ( int i = 0; i < sizeof(checksum); fprintf( fchksum, "%02X", checksum[i++] ) );
1742 fprintf( fchksum, "\" bytes=\"%d\" file=\"%s\"/>\n",
1743 nBytesProcessed,
1744 GetFileName( iter->first ).c_str() );
1748 fprintf( fchksum, "</errormail:Checksums>\n" );
1750 success = true;
1753 return success;
1756 //***************************************************************************
1758 BOOL FindDumpFile()
1760 TCHAR szFileName[MAX_PATH];
1762 if ( GetCrashDataPath( szFileName ) )
1764 _tcscat( szFileName, _T("\\crashdat.dmp") );
1766 HANDLE hFile = CreateFile(
1767 szFileName,
1768 GENERIC_READ,
1769 0, NULL,
1770 OPEN_EXISTING,
1771 FILE_ATTRIBUTE_NORMAL, NULL );
1773 if ( hFile )
1775 CloseHandle( hFile );
1777 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
1778 _tcscpy( g_szDumpFileName, szFileName );
1780 return TRUE;
1784 return FALSE;
1787 BOOL WriteDumpFile( DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers, DWORD dwThreadId )
1789 BOOL fSuccess = FALSE;
1790 MINIDUMP_EXCEPTION_INFORMATION ExceptionParam;
1792 HMODULE hDbgHelp = LoadLibrary( _T("DBGHELP.DLL" ) );
1793 MiniDumpWriteDump_PROC pMiniDumpWriteDump = NULL;
1795 if ( hDbgHelp )
1797 pMiniDumpWriteDump = (MiniDumpWriteDump_PROC)GetProcAddress( hDbgHelp, "MiniDumpWriteDump" );
1799 if ( !pMiniDumpWriteDump )
1801 FreeLibrary( hDbgHelp );
1802 return false;
1806 if ( !pMiniDumpWriteDump )
1807 return false;
1809 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
1811 if ( IsValidHandle(hProcess) )
1813 TCHAR szTempPath[MAX_PATH];
1815 if ( GetCrashDataPath( szTempPath ) )
1817 TCHAR szFileName[MAX_PATH];
1819 _tcscpy( szFileName, szTempPath );
1820 _tcscat( szFileName, _T("\\crashdat.dmp") );
1822 HANDLE hFile = CreateFile(
1823 szFileName,
1824 GENERIC_READ | GENERIC_WRITE,
1825 0, NULL,
1826 CREATE_ALWAYS,
1827 FILE_ATTRIBUTE_NORMAL, NULL );
1829 if ( hFile )
1831 PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam = NULL;
1832 if ( pExceptionPointers && dwThreadId )
1834 ExceptionParam.ThreadId = dwThreadId;
1835 ExceptionParam.ExceptionPointers = pExceptionPointers;
1836 ExceptionParam.ClientPointers = TRUE;
1838 EXCEPTION_POINTERS aExceptionPointers;
1839 EXCEPTION_RECORD aExceptionRecord;
1841 ReadProcessMemory(
1842 hProcess,
1843 pExceptionPointers,
1844 &aExceptionPointers,
1845 sizeof(aExceptionPointers),
1846 NULL );
1849 ReadProcessMemory(
1850 hProcess,
1851 aExceptionPointers.ExceptionRecord,
1852 &aExceptionRecord,
1853 sizeof(aExceptionRecord),
1854 NULL );
1856 g_dwExceptionCode = aExceptionRecord.ExceptionCode;
1858 lpExceptionParam = &ExceptionParam;
1861 fSuccess = pMiniDumpWriteDump( hProcess, dwProcessId, hFile, MiniDumpNormal, lpExceptionParam, NULL, NULL );
1863 CloseHandle( hFile );
1865 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
1866 _tcscpy( g_szDumpFileName, szFileName );
1869 if ( !fSuccess )
1870 DeleteFile( szFileName );
1874 CloseHandle( hProcess );
1877 FreeLibrary( hDbgHelp );
1879 return fSuccess;
1882 //***************************************************************************
1884 static DWORD FindProcessForImage( LPCTSTR lpImagePath )
1886 DWORD dwProcessId = 0;
1887 DWORD aProcesses[1024];
1888 DWORD dwSize = 0;
1889 TCHAR szShortImagePath[MAX_PATH];
1891 if ( GetShortPathName( lpImagePath, szShortImagePath, SAL_N_ELEMENTS(szShortImagePath) ) &&
1892 EnumProcesses( aProcesses, sizeof(aProcesses), &dwSize ) )
1894 unsigned nProcesses = dwSize / sizeof(aProcesses[0]);
1896 for ( unsigned i = 0; !dwProcessId && i < nProcesses; i++ )
1898 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] );
1900 if ( IsValidHandle(hProcess) )
1902 TCHAR szModulePath[MAX_PATH+1];
1904 if ( GetModuleFileNameEx( hProcess, NULL, szModulePath, MAX_PATH ) )
1906 TCHAR szShortModulePath[MAX_PATH];
1908 if ( GetShortPathName( szModulePath, szShortModulePath, SAL_N_ELEMENTS(szShortModulePath) ) )
1910 if ( 0 == _tcsicmp( szShortModulePath, szShortImagePath ) )
1911 dwProcessId = aProcesses[i];
1915 CloseHandle( hProcess );
1920 return dwProcessId;
1922 //***************************************************************************
1924 static bool ParseCommandArgs( LPDWORD pdwProcessId, PEXCEPTION_POINTERS* ppException, LPDWORD pdwThreadId )
1926 int argc = __argc;
1927 #ifdef __MINGW32__
1928 #ifdef _UNICODE
1929 TCHAR **argv = reinterpret_cast<TCHAR **>(alloca((argc+1)*sizeof(WCHAR*)));
1930 int *sizes = reinterpret_cast<int *>(alloca(argc*sizeof(int)));
1931 int argsize=0;
1932 char **ptr;
1933 int i;
1934 ptr=__argv;
1935 for (i = 0; i < argc; ++i)
1937 sizes[i]=MultiByteToWideChar(CP_ACP, 0, *ptr, -1, NULL, 0);
1938 argsize+=sizes[i]+1;
1939 ++ptr;
1941 ++argsize;
1942 TCHAR *args = reinterpret_cast<TCHAR *>(alloca(argsize*sizeof(WCHAR)));
1943 ptr=__argv;
1944 TCHAR *cptr=args;
1945 for (i = 0; i < argc; ++i)
1947 argv[i]=cptr;
1948 MultiByteToWideChar( CP_ACP, 0, *ptr, -1, cptr, sizes[i] );
1949 ++ptr;
1950 cptr+=sizes[i];
1951 *cptr=0;
1952 ++cptr;
1954 argv[i]=cptr;
1955 *cptr=0;
1956 #else
1957 TCHAR **argv = __argv;
1958 #endif
1959 #else
1960 TCHAR **argv = __targv;
1961 #endif
1962 bool bSuccess = true;
1964 for ( int argn = 1; bSuccess && argn < argc; argn++ )
1966 if ( 0 == _tcsicmp( argv[argn], _T("-h") ) ||
1967 0 == _tcsicmp( argv[argn], _T("/h") ) ||
1968 0 == _tcsicmp( argv[argn], _T("-?") ) ||
1969 0 == _tcsicmp( argv[argn], _T("/?") ) ||
1970 0 == _tcsicmp( argv[argn], _T("/help") ) ||
1971 0 == _tcsicmp( argv[argn], _T("-help") ) ||
1972 0 == _tcsicmp( argv[argn], _T("--help") )
1975 HINSTANCE hInstance = GetModuleHandle(NULL);
1976 TCHAR szUsage[FORMATBUFSIZE];
1977 TCHAR szProcess[FORMATBUFSIZE];
1978 TCHAR szProcessDescription[FORMATBUFSIZE];
1979 TCHAR szHelpDescription[FORMATBUFSIZE];
1981 LoadAndFormatString( hInstance, IDS_MSG_CMDLINE_USAGE, szUsage, SAL_N_ELEMENTS(szUsage) );
1982 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID, szProcess, SAL_N_ELEMENTS(szProcess) );
1983 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID_DESCRIPTION, szProcessDescription, SAL_N_ELEMENTS(szProcessDescription) );
1984 LoadAndFormatString( hInstance, IDS_MSG_PARAM_HELP_DESCRIPTION, szHelpDescription, SAL_N_ELEMENTS(szHelpDescription) );
1986 _tprintf(
1987 TEXT("\n%s: crashrep %s\n\n")
1988 TEXT("/?, -h[elp] %s\n\n")
1989 TEXT("%-20s %s\n\n"),
1990 szUsage, szProcess, szHelpDescription, szProcess, szProcessDescription
1993 return true;
1995 else if ( 0 == _tcsicmp( argv[argn], _T("-p") ) ||
1996 0 == _tcsicmp( argv[argn], _T("/p") ) )
1998 if ( ++argn < argc )
1999 *pdwProcessId = _tcstoul( argv[argn], NULL, 0 );
2000 else
2001 bSuccess = false;
2003 else if ( 0 == _tcsicmp( argv[argn], _T("-excp") ) ||
2004 0 == _tcsicmp( argv[argn], _T("/excp") ) )
2006 if ( ++argn < argc )
2007 *ppException = (PEXCEPTION_POINTERS)_tcstoul( argv[argn], NULL, 0 );
2008 else
2009 bSuccess = false;
2011 else if ( 0 == _tcsicmp( argv[argn], _T("-t") ) ||
2012 0 == _tcsicmp( argv[argn], _T("/t") ) )
2014 if ( ++argn < argc )
2015 *pdwThreadId = _tcstoul( argv[argn], NULL, 0 );
2016 else
2017 bSuccess = false;
2019 else if ( 0 == _tcsicmp( argv[argn], _T("-noui") ) ||
2020 0 == _tcsicmp( argv[argn], _T("/noui") ) )
2022 g_bNoUserInterface = true;
2024 else if ( 0 == _tcsicmp( argv[argn], _T("-send") ) ||
2025 0 == _tcsicmp( argv[argn], _T("/send") ) )
2027 g_bSendReport = true;
2029 else if ( 0 == _tcsicmp( argv[argn], _T("-load") ) ||
2030 0 == _tcsicmp( argv[argn], _T("/load") ) )
2032 g_bLoadReport = true;
2034 else // treat parameter as image path
2036 TCHAR szImagePath[MAX_PATH];
2037 LPTSTR lpImageName;
2039 if ( GetFullPathName( argv[argn], MAX_PATH, szImagePath, &lpImageName ) )
2041 DWORD dwProcessId = FindProcessForImage( szImagePath );
2043 if ( dwProcessId )
2044 *pdwProcessId = dwProcessId;
2045 else
2046 bSuccess = false;
2051 if ( !*pdwProcessId && !g_bLoadReport )
2053 TCHAR szImagePath[MAX_PATH];
2054 LPTSTR lpImageName;
2056 if ( GetFullPathName( TEXT("soffice.exe"), MAX_PATH, szImagePath, &lpImageName ) )
2058 DWORD dwProcessId = FindProcessForImage( szImagePath );
2060 if ( dwProcessId )
2061 *pdwProcessId = dwProcessId;
2062 else
2063 bSuccess = false;
2067 return bSuccess;
2070 //***************************************************************************
2072 BOOL WriteCommentFile( LPCTSTR lpComment )
2074 BOOL fSuccess = FALSE;
2075 TCHAR szTempPath[MAX_PATH];
2077 if ( GetTempPath( SAL_N_ELEMENTS(szTempPath), szTempPath ) )
2079 TCHAR szFileName[MAX_PATH];
2081 if ( GetTempFileName( szTempPath, TEXT("CMT"), 0, szFileName ) )
2083 HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
2085 if ( hFile )
2087 DWORD dwBytesWritten;
2089 int needed = WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, NULL, 0, NULL, NULL );
2090 if ( needed )
2092 char *lpCommentUTF8 = (char *)alloca( needed );
2093 WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, lpCommentUTF8, needed, NULL, NULL );
2094 fSuccess = WriteFile( hFile, lpCommentUTF8, strlen(lpCommentUTF8), &dwBytesWritten, NULL );
2096 else
2097 fSuccess = TRUE;
2100 CloseHandle( hFile );
2102 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szCommentFileNameA, MAX_PATH, NULL, NULL );
2105 if ( !fSuccess )
2106 DeleteFile( szFileName );
2110 return fSuccess;
2113 //***************************************************************************
2115 static int _tsetenv( const _TCHAR *lpVar, const _TCHAR *lpValue )
2117 if ( !lpValue )
2118 lpValue = _T("");
2120 _TCHAR *envstr = (TCHAR *)alloca( (_tcslen( lpVar ) + _tcslen( lpValue ) + 2) * sizeof(_TCHAR) );
2122 _tcscpy( envstr, lpVar );
2123 _tcscat( envstr, _T("=") );
2124 _tcscat( envstr, lpValue );
2126 return _tputenv( envstr );
2129 static bool read_line( FILE *fp, string& rLine )
2131 char szBuffer[1024];
2132 bool bSuccess = false;
2133 bool bEOL = false;
2134 string line;
2137 while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) )
2139 int len = strlen(szBuffer);
2141 bSuccess = true;
2143 while ( len && szBuffer[len - 1] == '\n' )
2145 szBuffer[--len] = 0;
2146 bEOL = true;
2149 line.append( szBuffer );
2152 rLine = line;
2153 return bSuccess;
2156 static string get_script_string( const char *pFileName, const char *pKeyName )
2158 FILE *fp = fopen( pFileName, "rt" );
2159 string retValue;
2161 if ( fp )
2163 string line;
2164 string section;
2166 while ( read_line( fp, line ) )
2168 line = trim_string( line );
2171 string::size_type iEqualSign = line.find( '=', 0 );
2173 if ( iEqualSign != string::npos )
2175 string keyname = line.substr( 0, iEqualSign );
2176 keyname = trim_string( keyname );
2178 string value = line.substr( sal::static_int_cast<string::size_type>(iEqualSign + 1) );
2179 value = trim_string( value );
2181 if ( value.length() && '\"' == value[0] )
2183 value.erase( 0, 1 );
2185 string::size_type iQuotes = value.find( '"', 0 );
2187 if ( iQuotes != string::npos )
2188 value.erase( iQuotes );
2191 if ( 0 == stricmp( keyname.c_str(), pKeyName ) )
2193 retValue = value;
2194 break;
2199 fclose( fp );
2202 return retValue;
2205 static bool ReadBootstrapParams( CrashReportParams &rParams )
2207 TCHAR szBuffer[256] = TEXT("");
2208 TCHAR szModuleName[MAX_PATH];
2209 TCHAR szModuleVersionName[MAX_PATH];
2210 TCHAR szDrive[_MAX_DRIVE];
2211 TCHAR szDir[_MAX_DIR];
2212 TCHAR szFName[_MAX_FNAME];
2213 TCHAR szExt[_MAX_EXT];
2214 TCHAR szReportServer[MAX_HOSTNAME];
2215 TCHAR szReportPort[256];
2216 bool bSuccess = false;
2218 GetModuleFileName( NULL, szModuleName, MAX_PATH );
2219 _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
2220 _tmakepath( szModuleName, szDrive, szDir, _T("bootstrap"), _T(".ini") );
2221 _tmakepath( szModuleVersionName, szDrive, szDir, _T("version"), _T(".ini") );
2223 if (
2224 GetPrivateProfileString(
2225 TEXT("Bootstrap"),
2226 TEXT("ProductKey"),
2227 TEXT("LibreOffice"),
2228 szBuffer,
2229 SAL_N_ELEMENTS(szBuffer),
2230 szModuleName )
2233 TCHAR *pVersion = _tcschr( szBuffer, ' ' );
2235 g_wstrProductKey = szBuffer;
2237 if ( pVersion )
2239 *pVersion = 0;
2240 pVersion++;
2242 else
2243 pVersion = TEXT("");
2245 if ( !_tgetenv( _T("PRODUCTNAME") ) )
2247 _tsetenv( TEXT("PRODUCTNAME"), szBuffer );
2249 if ( !_tgetenv( _T("PRODUCTVERSION") ) )
2250 _tsetenv( TEXT("PRODUCTVERSION"), pVersion );
2253 GetPrivateProfileString(
2254 TEXT("Version"),
2255 TEXT("buildid"),
2256 TEXT("unknown"),
2257 g_szBuildId, SAL_N_ELEMENTS(g_szBuildId),
2258 szModuleVersionName );
2260 g_strDefaultLanguage = get_script_string( "instdb.inf", "DefaultLanguage" );
2262 if ( GetPrivateProfileString(
2263 TEXT("ErrorReport"),
2264 TEXT("ErrorReportPort"),
2265 TEXT("80"),
2266 szReportPort, SAL_N_ELEMENTS(szReportPort),
2267 szModuleName
2270 TCHAR *endptr = NULL;
2272 unsigned short uReportPort = (unsigned short)_tcstoul( szReportPort, &endptr, 10 );
2273 if ( uReportPort )
2274 g_uReportPort = uReportPort;
2277 if ( GetPrivateProfileString(
2278 TEXT("ErrorReport"),
2279 TEXT("ErrorReportServer"),
2280 TEXT(""),
2281 szReportServer, SAL_N_ELEMENTS(szReportServer),
2282 szModuleName
2285 bSuccess = 0 != WideCharToMultiByte( CP_ACP, 0, szReportServer, -1, g_szReportServerA, SAL_N_ELEMENTS(g_szReportServerA), NULL, NULL );
2288 LPCTSTR lpEnvString;
2290 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYSERVER") )) )
2291 rParams.sProxyServer = lpEnvString;
2293 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYPORT") )) )
2294 rParams.sProxyPort = lpEnvString;
2296 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_SENDERADDRESS") )) )
2297 rParams.sEmail = lpEnvString;
2299 return bSuccess;
2302 //***************************************************************************
2304 bool SendHTTPRequest(
2305 FILE *fp,
2306 const char *pszServer,
2307 unsigned short uPort = 80,
2308 const char *pszProxyServer = NULL,
2309 unsigned short uProxyPort = 8080 )
2311 bool success = false;
2313 struct hostent *hp;
2315 if ( pszProxyServer )
2316 hp = gethostbyname( pszProxyServer );
2317 else
2318 hp = gethostbyname( pszServer );
2320 if ( hp )
2322 SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
2324 if ( s )
2326 struct sockaddr_in address;
2328 memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr));
2329 address.sin_family = AF_INET;
2331 if ( pszProxyServer )
2332 address.sin_port = ntohs( uProxyPort );
2333 else
2334 address.sin_port = ntohs( uPort );
2336 if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) )
2338 fseek( fp, 0, SEEK_END );
2339 size_t length = ftell( fp );
2340 fseek( fp, 0, SEEK_SET );
2342 char buffer[2048];
2344 if ( pszProxyServer )
2345 sprintf( buffer,
2346 "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
2347 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2348 "Content-Length: %d\r\n"
2349 "SOAPAction: \"\"\r\n\r\n",
2350 pszServer,
2351 uPort,
2352 length
2354 else
2355 sprintf( buffer,
2356 "POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
2357 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2358 "Content-Length: %d\r\n"
2359 "SOAPAction: \"\"\r\n\r\n",
2360 length
2363 if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
2365 size_t nBytes;
2369 nBytes = fread( buffer, 1, sizeof(buffer), fp );
2371 if ( nBytes )
2372 success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
2373 } while( nBytes && success );
2375 if ( success )
2377 memset( buffer, 0, sizeof(buffer) );
2378 success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 );
2379 if ( success )
2381 char szHTTPSignature[sizeof(buffer)] = "";
2382 unsigned uHTTPReturnCode = 0;
2384 sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode );
2385 success = uHTTPReturnCode == 200;
2392 closesocket( s );
2396 return success;
2399 //***************************************************************************
2401 static void WriteSOAPRequest( FILE *fp )
2403 fprintf( fp,
2404 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
2405 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
2406 "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
2407 "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
2408 "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
2409 "xmlns:rds=\"urn:ReportDataService\"\n"
2410 "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
2411 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
2412 "<SOAP-ENV:Body>\n"
2415 fprintf( fp, "<rds:submitReport>\n" );
2416 fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
2417 fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
2419 FILE *fpin = fopen( g_szReportFileNameA, "r" );
2420 if ( fpin )
2422 fprintf( fp,
2423 "<item>\n"
2424 "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
2425 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2426 fcopy( fpin, fp );
2427 fprintf( fp, "]]></value></item>\n" );
2428 fclose( fpin );
2431 fpin = fopen( g_szCommentFileNameA, "r" );
2432 if ( fpin )
2434 fprintf( fp,
2435 "<item>\n"
2436 "<key xsi:type=\"xsd:string\">description.txt</key>\n"
2437 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2438 fcopy( fpin, fp );
2439 fprintf( fp, "]]></value></item>\n" );
2440 fclose( fpin );
2444 fpin = fopen( g_szDumpFileNameA, "rb" );
2445 if ( fpin )
2447 FILE *fptemp = _tmpfile();
2449 if ( fptemp )
2451 if ( base64_encode( fpin, fptemp ) )
2453 fseek( fptemp, 0, SEEK_SET );
2454 fprintf( fp,
2455 "<item>\n"
2456 "<key xsi:type=\"xsd:string\">user.dmp</key>\n"
2457 "<value xsi:type=\"xsd:string\">" );
2458 fcopy( fptemp, fp );
2459 fprintf( fp, "</value></item>\n" );
2461 fclose( fptemp );
2463 fclose( fpin );
2466 fprintf( fp,
2467 "</hash>\n"
2468 "</rds:submitReport>\n"
2469 "</SOAP-ENV:Body>\n"
2470 "</SOAP-ENV:Envelope>\n"
2474 //***************************************************************************
2476 struct RequestParams
2478 bool success;
2479 FILE *fpin;
2480 const char *lpServer;
2481 unsigned short uPort;
2482 const char *lpProxyServer;
2483 unsigned short uProxyPort;
2484 HWND hwndStatus;
2487 void _cdecl SendingThread( void *lpArgs )
2489 RequestParams *pParams = (RequestParams *)lpArgs;
2491 pParams->success = SendHTTPRequest( pParams->fpin, pParams->lpServer, pParams->uPort, pParams->lpProxyServer, pParams->uProxyPort );
2493 PostMessage( pParams->hwndStatus, WM_COMMAND, IDOK, 0 );
2496 //***************************************************************************
2498 BOOL CALLBACK SendingStatusDialogProc(
2499 HWND hwndDlg,
2500 UINT uMsg,
2501 WPARAM wParam,
2502 LPARAM lParam
2505 static RequestParams *pRequest = NULL;
2506 static HANDLE hSendingThread = NULL;
2508 switch ( uMsg )
2510 case WM_INITDIALOG:
2512 TCHAR szBuffer[1024] = TEXT("");
2513 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
2515 pRequest = (RequestParams *)lParam;
2517 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_HEADER, szBuffer, SAL_N_ELEMENTS(szBuffer) );
2518 SetWindowText( hwndDlg, szBuffer );
2520 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_STATUS, szBuffer, SAL_N_ELEMENTS(szBuffer) );
2521 Static_SetText( GetDlgItem(hwndDlg, IDC_SENDING_REPORT_STATUS), szBuffer );
2523 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, SAL_N_ELEMENTS(szBuffer) );
2524 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
2526 pRequest->hwndStatus = hwndDlg;
2528 hSendingThread = (HANDLE)_beginthread( SendingThread, 0, pRequest );
2530 return TRUE;
2531 case WM_COMMAND:
2532 switch ( LOWORD(wParam) )
2534 case IDCANCEL:
2535 TerminateThread( hSendingThread, 0 );
2536 case IDOK:
2537 WaitForSingleObject( hSendingThread, INFINITE );
2538 CloseHandle( hSendingThread );
2539 EndDialog( hwndDlg, wParam );
2540 return TRUE;
2542 break;
2543 default:
2544 break;
2547 return FALSE;
2550 //***************************************************************************
2552 bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams )
2554 bool success = false;
2555 char szProxyServer[1024] = "";
2556 unsigned short uProxyPort = 8080;
2557 TCHAR *endptr = NULL;
2559 switch ( rParams.uInternetConnection )
2561 case 2:
2563 WideCharToMultiByte(
2564 CP_ACP, 0, rParams.sProxyServer.c_str(), -1,
2565 szProxyServer, sizeof(szProxyServer), NULL, NULL );
2566 uProxyPort = (unsigned short)_tcstoul( rParams.sProxyPort.c_str(), &endptr, 10 );
2568 break;
2569 case 0:
2571 DWORD dwProxyEnable = 0;
2573 RegReadValue( HKEY_CURRENT_USER,
2574 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
2575 TEXT("ProxyEnable"),
2576 &dwProxyEnable,
2577 sizeof(dwProxyEnable) );
2579 if ( dwProxyEnable )
2581 TCHAR tszProxyServers[1024] = TEXT("");
2583 if ( ERROR_SUCCESS == RegReadValue( HKEY_CURRENT_USER,
2584 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), TEXT("ProxyServer"),
2585 tszProxyServers,
2586 sizeof(tszProxyServers) ) )
2588 TCHAR *lpHttpStart = _tcsstr( tszProxyServers, TEXT("http=") );
2590 if ( lpHttpStart )
2591 lpHttpStart += 5;
2592 else
2593 lpHttpStart = tszProxyServers;
2595 TCHAR *lpHttpEnd = _tcschr( lpHttpStart, ';' );
2597 if ( lpHttpEnd )
2598 *lpHttpEnd = 0;
2600 char szHTTPProxyServer[1024] = "";
2601 WideCharToMultiByte( CP_ACP, 0, lpHttpStart, -1, szHTTPProxyServer, sizeof(szHTTPProxyServer), NULL, NULL );
2603 char *lpColon = strchr( szHTTPProxyServer, ':' );
2605 if ( lpColon )
2607 char *endptr = NULL;
2609 *lpColon = 0;
2610 uProxyPort = (unsigned short)strtoul( lpColon + 1, &endptr, 10 );
2612 else
2613 uProxyPort = 8080;
2615 strcpy( szProxyServer, szHTTPProxyServer );
2620 break;
2621 default:
2622 case 1:
2623 break;
2626 FILE *fptemp = _tmpfile();
2627 if ( fptemp )
2629 RequestParams request;
2631 request.success = false;
2632 request.fpin = fptemp;
2633 request.lpServer = REPORT_SERVER;
2634 request.uPort = REPORT_PORT;
2635 request.lpProxyServer = szProxyServer[0] ? szProxyServer : NULL;
2636 request.uProxyPort = uProxyPort;
2637 request.hwndStatus = NULL;
2639 WriteSOAPRequest( fptemp );
2640 fseek( fptemp, 0, SEEK_SET );
2642 if ( hwndParent )
2644 int retid = DialogBoxParam(
2645 GetModuleHandle(NULL),
2646 MAKEINTRESOURCE(IDD_SENDING_STATUS),
2647 hwndParent,
2648 SendingStatusDialogProc,
2649 (LPARAM)&request
2652 success = request.success;
2654 if ( IDOK == retid )
2656 if ( !success )
2658 TCHAR szMessage[1024];
2660 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, SAL_N_ELEMENTS(szMessage) );
2662 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
2664 else
2666 TCHAR szMessage[1024];
2667 TCHAR szTitle[1024];
2669 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, SAL_N_ELEMENTS(szMessage) );
2670 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_HEADER, szTitle, SAL_N_ELEMENTS(szTitle) );
2672 MessageBox( hwndParent, szMessage, szTitle, MB_ICONINFORMATION | MB_OK );
2677 else
2679 HANDLE hSendingThread = (HANDLE)_beginthread( SendingThread, 0, (void *)&request );
2681 WaitForSingleObject( hSendingThread, INFINITE );
2683 success = request.success;
2684 if ( !success )
2686 TCHAR szMessage[1024];
2688 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, SAL_N_ELEMENTS(szMessage) );
2689 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
2691 else
2693 TCHAR szMessage[1024];
2695 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, SAL_N_ELEMENTS(szMessage) );
2697 _ftprintf( stderr, _T("SUCCESS: %s\n"), szMessage );
2700 fclose( fptemp );
2702 else
2704 TCHAR szMessage[1024];
2706 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_DISK_FULL, szMessage, SAL_N_ELEMENTS(szMessage) );
2708 if ( hwndParent )
2709 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
2710 else
2711 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
2714 return success;
2717 //***************************************************************************
2719 #ifdef __MINGW32__
2720 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR /*lpCmdLine*/, int )
2721 #else
2722 int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR /*lpCmdLine*/, int )
2723 #endif
2725 int exitcode = -1;
2726 int argc = __argc;
2728 #ifdef __MINGW32__
2729 char **argv = __argv;
2730 #else
2731 #ifdef _UNICODE
2732 char **argv = new char *[argc + 1];
2734 for ( int argn = 0; argn < argc; argn++ )
2736 int nBytes = WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, NULL, 0, NULL, NULL );
2737 argv[argn] = new char[nBytes];
2738 WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, argv[argn], nBytes, NULL, NULL );
2740 argv[argc] = NULL;
2741 #else
2742 char **argv = __targv;
2743 #endif
2744 #endif
2746 osl_setCommandArgs( argc, argv );
2748 PEXCEPTION_POINTERS pExceptionPointers = NULL;
2749 DWORD dwProcessId = 0;
2750 DWORD dwThreadId = 0;
2752 WSADATA wsaData;
2753 WORD wVersionRequested;
2755 wVersionRequested = MAKEWORD(1, 1);
2756 WSAStartup(wVersionRequested, &wsaData);
2758 CrashReportParams Params;
2760 Params.ReadFromRegistry();
2761 Params.ReadFromEnvironment();
2763 if ( ReadBootstrapParams( Params ) &&
2764 ParseCommandArgs( &dwProcessId, &pExceptionPointers, &dwThreadId ) )
2766 bool bGotDumpFile;
2768 if ( g_bLoadReport )
2769 bGotDumpFile = FindDumpFile();
2770 else
2771 bGotDumpFile = WriteDumpFile( dwProcessId, pExceptionPointers, dwThreadId );
2773 if( bGotDumpFile )
2775 boost::unordered_map< string, string > aLibraries;
2777 if ( g_bLoadReport )
2779 g_fpStackFile = _open_reportfile( _T(".stk"), _T("rb") );
2780 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("rb") );
2782 else
2784 if ( g_bSendReport )
2786 g_fpStackFile = _tmpfile();
2787 g_fpChecksumFile = _tmpfile();
2789 else
2791 g_fpStackFile = _open_reportfile( _T(".stk"), _T("w+b") );
2792 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("w+b") );
2794 FILE *fpUnsent = _open_reportfile( _T(".lck"), _T("w+b") );
2795 if ( fpUnsent )
2797 fprintf( fpUnsent, "Unsent\r\n" );
2798 fclose( fpUnsent );
2802 WriteStackFile( g_fpStackFile, aLibraries, dwProcessId, pExceptionPointers );
2803 WriteChecksumFile( g_fpChecksumFile, aLibraries );
2804 WriteReportFile( &Params );
2806 FILE *fpPreview = _open_reportfile( _T(".prv"), _T("w+b") );
2808 if ( fpPreview )
2810 FILE *fp = fopen( g_szReportFileNameA, "rb" );
2811 if ( fp )
2813 fcopy( fp, fpPreview );
2814 fclose( fp );
2816 fclose( fpPreview );
2820 if ( g_bSendReport )
2822 InitCommonControls();
2824 // Actually this should never be true anymore
2825 if ( !g_bNoUserInterface && InitRichEdit() )
2828 INT_PTR result = DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_DIALOG_FRAME), NULL, DialogProc, (LPARAM)&Params );
2830 if ( result > 0 )
2832 exitcode = 0;
2834 DeinitRichEdit();
2836 else
2838 WriteCommentFile( Params.sComment.c_str() );
2839 WriteReportFile( &Params );
2840 if ( SendCrashReport( NULL, Params ) )
2841 exitcode = 0;
2845 if ( g_szReportFileNameA[0] )
2846 DeleteFileA( g_szReportFileNameA );
2848 if ( g_szCommentFileNameA[0] )
2849 DeleteFileA( g_szCommentFileNameA );
2851 else
2853 if ( g_szReportFileNameA[0] )
2854 DeleteFileA( g_szReportFileNameA );
2855 exitcode = 0;
2858 if ( g_szDumpFileNameA[0] && g_bSendReport )
2859 DeleteFileA( g_szDumpFileNameA );
2861 if ( g_fpStackFile )
2862 fclose( g_fpStackFile );
2864 if ( g_fpChecksumFile )
2865 fclose( g_fpChecksumFile );
2870 return exitcode;
2873 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */