masterfix DEV300: #i10000# build fix
[LibreOffice.git] / crashrep / source / win32 / soreport.cpp
blobabca528dc98755c23bdcfcaaa9c77a48a9b629e4
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 #define UNICODE
29 #define WIN32_LEAN_AND_MEAN
30 #if defined _MSC_VER
31 #pragma warning(push, 1)
32 #pragma warning(disable:4917)
33 #endif
34 #include <windows.h>
35 #include <windowsx.h>
37 #include <mapi.h>
38 #include <commctrl.h>
39 #include <commdlg.h>
40 #include <psapi.h>
42 #include <shellapi.h>
43 #include <shlobj.h>
45 #define _UNICODE
46 #include <tchar.h>
48 #define _RICHEDIT_VER 0x0200
49 #include <richedit.h>
51 #if defined _MSC_VER
52 #pragma warning(pop)
53 #endif
55 #if _RICHEDIT_VER >= 0x0200
56 #define RICHEDIT TEXT("riched20.dll")
57 #else
58 #define RICHEDIT TEXT("riched32.dll")
59 #endif
61 #include <systools/win32/uwinapi.h>
62 #include <rtl/digest.h>
63 #include <rtl/bootstrap.hxx>
64 #include <osl/file.hxx>
65 #include <osl/process.h>
67 #include <stdlib.h>
68 #include <stdio.h>
69 #include <io.h>
70 #include <fcntl.h>
71 #include <string>
72 #include <hash_map>
73 #include <winsock.h>
74 #include <malloc.h>
75 #include <process.h>
77 #include <_version.h>
79 #include "resource.h"
80 #include "base64.h"
82 #define FORMATBUFSIZE (8*1024)
83 #define MAX_TEXT_BUFFER (32*1024-1)
84 #define MAX_HOSTNAME (1024)
86 #ifdef __MINGW32__
87 #include <imagehlp.h>
88 #else
89 #include <dbghelp.h>
90 #endif
92 #ifdef _UNICODE
93 #define tstring wstring
94 #else
95 #define tstring string
96 #endif
98 using namespace ::std;
101 wstring g_wstrProductKey;
102 string g_strDefaultLanguage;
103 FILE *g_fpStackFile = NULL;
104 FILE *g_fpChecksumFile = NULL;
105 DWORD g_dwExceptionCode = 0;
107 CHAR g_szReportServerA[MAX_HOSTNAME] = "";
108 USHORT g_uReportPort = 80;
110 TCHAR g_szBuildId[256] = TEXT("");
112 TCHAR g_szDumpFileName[MAX_PATH] = TEXT("");
114 CHAR g_szDumpFileNameA[MAX_PATH] = "";
115 CHAR g_szCommentFileNameA[MAX_PATH] = "";
116 CHAR g_szReportFileNameA[MAX_PATH] = "";
119 bool g_bNoUserInterface = false;
120 bool g_bSendReport = false;
121 bool g_bLoadReport = false;
123 #define REPORT_SERVER g_szReportServerA
124 #define REPORT_PORT g_uReportPort
127 //***************************************************************************
128 // tmpfile from msvcrt creates the temporary file in the root of the current
129 // volume and can fail.
131 static FILE *_xfopen( const _TCHAR *file, const _TCHAR *mode )
133 #ifdef UNICODE
134 if ( (LONG)GetVersion() < 0 )
136 char afile[MAX_PATH];
137 char amode[16];
139 WideCharToMultiByte( CP_ACP, 0, file, -1, afile, MAX_PATH, NULL, NULL );
140 WideCharToMultiByte( CP_ACP, 0, mode, -1, amode, 16, NULL, NULL );
143 return fopen( afile, amode );
145 else
146 #endif
147 return _tfopen( file, mode );
151 static FILE *_tmpfile(void)
153 FILE *fp = NULL;
155 TCHAR szTempPath[MAX_PATH];
157 if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
159 TCHAR szFileName[MAX_PATH];
161 if ( GetTempFileName( szTempPath, TEXT("CRT"), 0, szFileName ) )
163 HANDLE hFile = CreateFile(
164 szFileName,
165 GENERIC_READ | GENERIC_WRITE,
166 0, NULL,
167 OPEN_EXISTING,
168 FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_NORMAL,
169 NULL );
171 if ( IsValidHandle( hFile ) )
173 int fd = _open_osfhandle( (int)hFile, 0 );
175 fp = _fdopen( fd, "w+b" );
180 return fp;
182 //***************************************************************************
184 static BOOL GetCrashDataPath( LPTSTR szBuffer )
186 ::rtl::OUString ustrValue = ::rtl::OUString::createFromAscii("${$BRAND_BASE_DIR/program/bootstrap.ini:UserInstallation}");
187 ::rtl::Bootstrap::expandMacros( ustrValue );
189 if ( ustrValue.getLength() )
191 ustrValue += ::rtl::OUString::createFromAscii("/user/crashdata");
193 ::osl::FileBase::RC result = ::osl::Directory::createPath( ustrValue );
195 if ( ::osl::FileBase::E_None == result || ::osl::FileBase::E_EXIST == result )
197 ::rtl::OUString ustrPath;
199 result = ::osl::FileBase::getSystemPathFromFileURL( ustrValue, ustrPath );
200 if ( ::osl::FileBase::E_None == result )
202 _tcsncpy( szBuffer, reinterpret_cast<LPCWSTR>(ustrPath.getStr()), MAX_PATH );
203 return TRUE;
208 return FALSE;
212 static FILE *_open_reportfile( LPCTSTR lpExt, LPCTSTR lpMode )
214 FILE *fp = NULL;
215 TCHAR szAppDataPath[MAX_PATH] = _T("");
217 if ( GetCrashDataPath( szAppDataPath ) )
219 _tcscat( szAppDataPath, _T("\\crashdat") );
220 _tcscat( szAppDataPath, lpExt );
222 fp = _xfopen( szAppDataPath, lpMode );
225 return fp;
228 //***************************************************************************
230 struct CrashReportParams
232 BOOL fAllowContact;
233 tstring sEmail;
234 tstring sTitle;
235 tstring sComment;
236 ULONG uInternetConnection;
237 tstring sProxyServer;
238 tstring sProxyPort;
240 CrashReportParams();
242 void WriteToRegistry();
243 void ReadFromRegistry();
244 void ReadFromEnvironment();
247 bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams );
248 BOOL WriteCommentFile( LPCTSTR lpComment );
250 //***************************************************************************
252 LONG RegReadValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPVOID lpData, DWORD cbData )
254 HKEY hKey = NULL;
255 LONG lResult;
257 lResult = RegOpenKeyEx( hBaseKey, lpSubKey, 0, KEY_QUERY_VALUE, &hKey );
259 if ( ERROR_SUCCESS == lResult )
261 lResult = RegQueryValueEx( hKey, lpValueName, NULL, NULL, (LPBYTE)lpData, &cbData );
262 RegCloseKey( hKey );
265 return lResult;
268 //***************************************************************************
270 LONG RegWriteValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData )
272 HKEY hKey = NULL;
273 LONG lResult;
275 lResult = RegCreateKeyEx( hBaseKey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL );
277 if ( ERROR_SUCCESS == lResult )
279 lResult = RegSetValueEx( hKey, lpValueName, NULL, dwType, (CONST BYTE *)lpData, cbData );
280 RegCloseKey( hKey );
283 return lResult;
286 //***************************************************************************
288 CrashReportParams::CrashReportParams()
290 fAllowContact = FALSE;
291 sTitle = TEXT("");
292 sComment = TEXT("");
293 sEmail = TEXT("");
294 uInternetConnection = 0;
295 sProxyServer = TEXT("");
296 sProxyPort = TEXT("");
299 //***************************************************************************
301 void CrashReportParams::ReadFromRegistry()
303 TCHAR szBuffer[2048];
305 if ( ERROR_SUCCESS == RegReadValue(
306 HKEY_CURRENT_USER,
307 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
308 TEXT("HTTPProxyServer"),
309 szBuffer,
310 sizeof(szBuffer) ) )
311 sProxyServer = szBuffer;
313 DWORD dwProxyPort;
315 if ( ERROR_SUCCESS == RegReadValue(
316 HKEY_CURRENT_USER,
317 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
318 TEXT("HTTPProxyPort"),
319 &dwProxyPort,
320 sizeof(dwProxyPort) ) )
322 _stprintf( szBuffer, TEXT("%d"), dwProxyPort );
323 sProxyPort = szBuffer;
326 if ( ERROR_SUCCESS == RegReadValue(
327 HKEY_CURRENT_USER,
328 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
329 TEXT("ReturnAddress"),
330 szBuffer,
331 sizeof(szBuffer) ) )
332 sEmail = szBuffer;
334 RegReadValue(
335 HKEY_CURRENT_USER,
336 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
337 TEXT("AllowContact"),
338 &fAllowContact,
339 sizeof(fAllowContact) );
341 RegReadValue(
342 HKEY_CURRENT_USER,
343 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
344 TEXT("HTTPConnection"),
345 &uInternetConnection,
346 sizeof(uInternetConnection) );
349 //***************************************************************************
351 void CrashReportParams::WriteToRegistry()
353 RegWriteValue(
354 HKEY_CURRENT_USER,
355 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
356 TEXT("HTTPProxyServer"), REG_SZ,
357 sProxyServer.c_str(),
358 sizeof(TCHAR) * (sProxyServer.length() + 1) );
360 LPTSTR endptr = NULL;
361 DWORD dwProxyPort = _tcstoul( sProxyPort.c_str(), &endptr, 10 );
363 RegWriteValue(
364 HKEY_CURRENT_USER,
365 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
366 TEXT("HTTPProxyPort"), REG_DWORD,
367 &dwProxyPort,
368 sizeof(DWORD) );
370 RegWriteValue(
371 HKEY_CURRENT_USER,
372 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
373 TEXT("AllowContact"), REG_DWORD,
374 &fAllowContact,
375 sizeof(DWORD) );
378 RegWriteValue(
379 HKEY_CURRENT_USER,
380 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
381 TEXT("HTTPConnection"), REG_DWORD,
382 &uInternetConnection,
383 sizeof(DWORD) );
385 RegWriteValue(
386 HKEY_CURRENT_USER,
387 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
388 TEXT("ReturnAddress"), REG_SZ,
389 sEmail.c_str(),
390 sizeof(TCHAR) * (sEmail.length() + 1) );
393 //***************************************************************************
395 void CrashReportParams::ReadFromEnvironment()
397 TCHAR szBuffer[2048];
399 DWORD dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYSERVER"), szBuffer, elementsof(szBuffer) );
401 if ( dwResult && dwResult < elementsof(szBuffer) )
402 sProxyServer = szBuffer;
404 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYPORT"), szBuffer, elementsof(szBuffer) );
406 if ( dwResult && dwResult < elementsof(szBuffer) )
407 sProxyPort = szBuffer;
409 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_RETURNADDRESS"), szBuffer, elementsof(szBuffer) );
411 if ( dwResult && dwResult < elementsof(szBuffer) )
413 sEmail = szBuffer;
414 // fAllowContact = TRUE;
417 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPCONNECTIONTYPE"), szBuffer, elementsof(szBuffer) );
419 if ( dwResult && dwResult < elementsof(szBuffer) )
421 if ( 0 == _tcsicmp( szBuffer, _T("DIRECT") ) )
422 uInternetConnection = 1;
423 else if ( 0 == _tcsicmp( szBuffer, _T("MANUALPROXY") ) )
424 uInternetConnection = 2;
425 else if ( 0 == _tcsicmp( szBuffer, _T("SYSTEMDEFAULT") ) )
426 uInternetConnection = 0;
429 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_SUBJECT"), szBuffer, elementsof(szBuffer) );
431 if ( dwResult && dwResult < elementsof(szBuffer) )
432 sTitle = szBuffer;
435 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_BODYFILE"), szBuffer, elementsof(szBuffer) );
437 if ( dwResult && dwResult < elementsof(szBuffer) )
439 FILE *fp = _xfopen( szBuffer, _T("rb") );
441 if ( fp )
443 CHAR aUTF8Buffer[256];
444 size_t nBytesRead;
446 sComment = TEXT("");
448 while ( 0 != (nBytesRead = fread( aUTF8Buffer, sizeof(aUTF8Buffer[0]), elementsof(aUTF8Buffer), fp )) )
450 TCHAR aBuffer[256+1];
452 DWORD dwCharacters = MultiByteToWideChar( CP_UTF8, 0, aUTF8Buffer, nBytesRead, aBuffer, elementsof(aBuffer) - 1 );
453 aBuffer[dwCharacters] = 0;
454 sComment += aBuffer;
457 fclose( fp );
462 //***************************************************************************
464 typedef BOOL (WINAPI *MiniDumpWriteDump_PROC)(
465 IN HANDLE hProcess,
466 IN DWORD ProcessId,
467 IN HANDLE hFile,
468 IN MINIDUMP_TYPE DumpType,
469 IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
470 IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
471 IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
474 //***************************************************************************
476 static BOOL WINAPI InitRichEdit()
478 return (NULL != LoadLibrary( RICHEDIT ));
481 //***************************************************************************
483 static BOOL WINAPI DeinitRichEdit()
485 return FreeLibrary( GetModuleHandle( RICHEDIT ) );
488 //***************************************************************************
490 static string trim_string( const string& rString )
492 string temp = rString;
494 while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' )
495 temp.erase( 0, 1 );
497 string::size_type len = temp.length();
499 while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' )
501 temp.erase( len - 1, 1 );
502 len = temp.length();
505 return temp;
508 //***************************************************************************
510 static int LoadAndFormatString( HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax )
512 TCHAR szBuffer[FORMATBUFSIZE];
513 TCHAR szBuffer2[FORMATBUFSIZE];
515 LoadString( hInstance, uID, szBuffer, elementsof(szBuffer) );
517 LPCTSTR src;
518 LPTSTR dest;
519 for ( dest = szBuffer2, src = szBuffer; *src; src++, dest++ )
521 switch ( *src )
523 case '~':
524 *dest = '&';
525 break;
526 case '\\':
527 switch ( *(++src) )
529 case 'n':
530 *dest = '\n';
531 break;
532 case 'r':
533 *dest = '\r';
534 break;
535 default:
536 *dest = *src;
537 break;
539 break;
540 default:
541 *dest = *src;
542 break;
546 *dest = *src;
548 return ExpandEnvironmentStrings( szBuffer2, lpBuffer, nBufferMax );
552 //***************************************************************************
554 static string wstring2utf8( const wstring &rString )
556 int nBufSize = WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, NULL, 0, NULL, FALSE );
558 LPSTR pBuffer = (LPSTR)alloca( nBufSize );
560 WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, pBuffer, nBufSize, NULL, FALSE );
562 return string( pBuffer );
565 //***************************************************************************
567 static string xml_encode( const string &rString )
569 string temp = rString;
570 string::size_type pos = 0;
572 // First replace all occurences of '&' because it may occur in further
573 // encoded chardters too
575 for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 )
576 temp.replace( pos, 1, "&amp;" );
578 for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 )
579 temp.replace( pos, 1, "&lt;" );
581 for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 )
582 temp.replace( pos, 1, "&gt;" );
584 return temp;
587 //***************************************************************************
589 static size_t fcopy( FILE *fpin, FILE *fpout )
591 char buffer[1024];
592 size_t nBytes;
593 size_t nBytesWritten = 0;
595 if ( fpin && fpout )
597 while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) )
599 nBytesWritten += fwrite( buffer, 1, nBytes, fpout );
603 return nBytesWritten;
606 //***************************************************************************
608 static string GetModuleDirectory( HMODULE hModule )
610 TCHAR szModuleName[MAX_PATH] = TEXT("");
611 TCHAR szDrive[_MAX_DRIVE];
612 TCHAR szDir[_MAX_DIR];
613 TCHAR szFName[_MAX_FNAME];
614 TCHAR szExt[_MAX_EXT];
616 if ( GetModuleFileName( hModule, szModuleName, MAX_PATH ) )
618 _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
619 _tmakepath( szModuleName, szDrive, szDir, _T(""), _T("") );
622 CHAR szModuleNameUTF8[MAX_PATH] = "";
624 WideCharToMultiByte( CP_UTF8, 0, szModuleName, -1, szModuleNameUTF8, elementsof(szModuleNameUTF8), NULL, NULL );
625 return string( szModuleNameUTF8 );
628 //***************************************************************************
630 string GetFileDirectory( const string& rFilePath )
632 string aDir = rFilePath;
633 size_t pos = aDir.rfind( '\\' );
635 if ( string::npos != pos )
636 aDir.erase( pos + 1 );
637 else
638 aDir = "";
640 return aDir;
643 //***************************************************************************
645 string GetFileName( const string& rFilePath )
647 string aName = rFilePath;
648 size_t pos = aName.rfind( '\\' );
650 if ( string::npos != pos )
651 return aName.substr( pos + 1 );
652 else
653 return aName;
656 //***************************************************************************
658 BOOL WriteReportFile( CrashReportParams *pParams )
660 BOOL fSuccess = FALSE;
661 TCHAR szTempPath[MAX_PATH];
663 if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
665 TCHAR szFileName[MAX_PATH];
667 if ( GetTempFileName( szTempPath, TEXT("RPM"), 0, szFileName ) )
669 HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
671 if ( hFile )
673 int fd = _open_osfhandle( (LONG)hFile, _O_TEXT );
674 FILE *fp = _fdopen( fd, "w+t" );
675 CHAR szTitle[1024] = "";
676 CHAR szBuildId[1024] = "";
677 CHAR szEmail[1024] = "";
678 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
680 WideCharToMultiByte( CP_UTF8, 0, pParams->sTitle.c_str(), -1, szTitle, sizeof(szTitle), NULL, NULL );
681 WideCharToMultiByte( CP_UTF8, 0, g_szBuildId, -1, szBuildId, sizeof(szBuildId), NULL, NULL );
682 WideCharToMultiByte( CP_UTF8, 0, pParams->sEmail.c_str(), -1, szEmail, sizeof(szEmail), NULL, NULL );
684 fprintf( fp,
685 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
686 "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
687 "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
688 "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n",
689 pszUserType ? pszUserType : "",
690 pParams->fAllowContact ? "true" : "false",
691 pParams->fAllowContact ? xml_encode(szEmail).c_str() : ""
694 fprintf( fp,
695 "<reportmail:title>%s</reportmail:title>\n",
696 xml_encode(szTitle).c_str() );
698 fprintf( fp,
699 "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain;charset=UTF-8\" class=\"UserComment\"/>\n"
700 "<reportmail:attachment name=\"user.dmp\" media-type=\"application/octet-stream\" class=\"UserDump\"/>\n"
701 "</reportmail:mail>\n"
703 "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" procpath=\"%s\" exceptiontype=\"0x%08X\" product=\"%s\"/>\n",
704 szBuildId,
705 _INPATH,
706 xml_encode(g_strDefaultLanguage).c_str(),
707 xml_encode(GetModuleDirectory( NULL )).c_str(),
708 g_dwExceptionCode,
709 xml_encode(wstring2utf8(g_wstrProductKey)).c_str()
712 OSVERSIONINFO VersionInfo;
714 ZeroMemory( &VersionInfo, sizeof(VersionInfo) );
715 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo );
717 GetVersionEx( &VersionInfo );
719 fprintf( fp,
720 "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
721 "<systeminfo:System name=\"%s\" version=\"%d.%d\" build=\"%d\" locale=\"0x%08x\"/>\n"
723 VER_PLATFORM_WIN32_NT == VersionInfo.dwPlatformId ? "Windows NT" : "Windows",
724 VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion,
725 VersionInfo.dwBuildNumber,
726 GetUserDefaultLangID()
729 fprintf( fp, "<systeminfo:CPU type=\"x86\"/>\n" );
730 fprintf( fp, "</systeminfo:systeminfo>\n" );
732 fseek( g_fpStackFile, 0, SEEK_SET );
733 fcopy( g_fpStackFile, fp );
735 fseek( g_fpChecksumFile, 0, SEEK_SET );
736 fcopy( g_fpChecksumFile, fp );
738 fprintf( fp, "</errormail:errormail>\n" );
740 fclose( fp );
742 fSuccess = TRUE;
744 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szReportFileNameA, MAX_PATH, NULL, NULL );
747 if ( !fSuccess )
748 DeleteFile( szFileName );
752 return fSuccess;
755 //***************************************************************************
757 static BOOL SaveDumpFile( HWND hwndOwner )
759 OPENFILENAME ofn;
760 TCHAR szFileName[MAX_PATH] = TEXT("");
762 ZeroMemory( &ofn, sizeof(ofn) );
763 ofn.lStructSize = sizeof(ofn);
765 ofn.hwndOwner = hwndOwner;
766 ofn.lpstrFilter = TEXT("*.dmp\0*.dmp\0*.*\0*.*\0");
767 ofn.lpstrFile = szFileName;
768 ofn.nMaxFile = MAX_PATH;
769 ofn.Flags = OFN_ENABLESIZING | OFN_LONGNAMES | OFN_OVERWRITEPROMPT;
770 ofn.lpstrDefExt = TEXT("dmp");
772 if ( GetSaveFileName( &ofn ) )
774 return CopyFile( g_szDumpFileName, szFileName, FALSE );
778 return FALSE;
781 //***************************************************************************
783 static BOOL ScreenToClientRect( HWND hwnd, LPRECT lprc )
785 return ScreenToClient( hwnd, (LPPOINT)&lprc->left ) && ScreenToClient( hwnd, (LPPOINT)&lprc->right );
788 static BOOL SetWindowRect( HWND hwnd, const RECT *lprc, BOOL fRepaint )
790 return MoveWindow( hwnd, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, fRepaint );
793 #define GM_LOX 0x01
794 #define GM_HIX 0x02
795 #define GM_LOY 0x04
796 #define GM_HIY 0x08
798 static BOOL SetGrowMode( HWND hwnd, DWORD dwGrowMode )
800 return SetProp( hwnd, TEXT("GrowMode"), (HANDLE)dwGrowMode );
803 static DWORD GetGrowMode( HWND hwnd )
805 return (DWORD)GetProp( hwnd, TEXT("GrowMode") );
808 static BOOL GrowWindow( HWND hwnd, LONG dxClient, LONG dyClient, BOOL fRepaint )
810 DWORD dwGrowMode = GetGrowMode( hwnd );
811 RECT rc;
813 GetWindowRect( hwnd, &rc );
815 if ( dwGrowMode & GM_LOX )
816 rc.left += dxClient;
817 if ( dwGrowMode & GM_HIX )
818 rc.right += dxClient;
819 if ( dwGrowMode & GM_LOY )
820 rc.top += dyClient;
821 if ( dwGrowMode & GM_HIY )
822 rc.bottom += dyClient;
824 ScreenToClientRect( GetParent( hwnd ), &rc );
825 SetWindowRect( hwnd, &rc, fRepaint );
827 return TRUE;
830 BOOL CALLBACK GrowChildWindows(
831 HWND hwnd, // handle to child window
832 LPARAM lParam // application-defined value
835 LONG cx = (SHORT)LOWORD( lParam );
836 LONG cy = (SHORT)HIWORD( lParam );
838 GrowWindow( hwnd, cx, cy, TRUE );
840 return TRUE;
844 BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
846 HFONT aFont = *((HFONT*) lParam);
847 HDC hDC = GetDC( hwndChild );
848 SelectObject( hDC, aFont );
849 ReleaseDC( hwndChild, hDC );
850 return TRUE;
853 void ApplySystemFont( HWND hwndDlg )
855 NONCLIENTMETRICSA aNonClientMetrics;
856 aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
857 if ( SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
859 HFONT aSysFont = CreateFontIndirectA( &aNonClientMetrics.lfMessageFont );
860 EnumChildWindows(hwndDlg, EnumChildProc, (LPARAM) &aSysFont);
865 BOOL CALLBACK PreviewDialogProc(
866 HWND hwndDlg,
867 UINT uMsg,
868 WPARAM wParam,
869 LPARAM lParam
872 static RECT rcClient;
874 switch ( uMsg )
876 case WM_SIZE:
878 LONG cx = LOWORD( lParam );
879 LONG cy = HIWORD( lParam );
880 LONG dxClient, dyClient;
882 dxClient = cx - rcClient.right;
883 dyClient = cy - rcClient.bottom;
885 EnumChildWindows( hwndDlg, GrowChildWindows, MAKELONG( (SHORT)dxClient, (SHORT)dyClient) );
887 GetClientRect( hwndDlg, &rcClient );
889 break;
890 case WM_INITDIALOG:
892 GetClientRect( hwndDlg, &rcClient );
893 SetGrowMode( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GM_HIX | GM_HIY );
894 SetGrowMode( GetDlgItem(hwndDlg, IDOK), GM_LOX | GM_HIX | GM_LOY | GM_HIY );
896 CrashReportParams *pParams = (CrashReportParams *)lParam;
898 TCHAR szBuffer[256] = TEXT("");
899 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
900 HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
902 GetWindowText( hwndParent, szBuffer, elementsof(szBuffer) );
903 SetWindowText( hwndDlg, szBuffer );
905 LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) );
906 Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
908 basic_string<TCHAR> aString;
910 aString.append( pParams->sTitle );
911 aString.append( _T("\r\n\r\n") );
912 aString.append( pParams->sComment );
913 aString.append( _T("\r\n---------- report ----------\r\n") );
915 FILE *fp = fopen( g_szReportFileNameA, "r" );
917 if ( fp )
919 char buf[1024];
921 while ( fgets( buf, elementsof(buf), fp ) != NULL )
923 WCHAR bufW[1024];
925 MultiByteToWideChar( CP_UTF8, 0, buf, -1, bufW, elementsof(bufW) );
927 aString.append( bufW );
930 fclose( fp );
933 aString.append( _T("\r\n---------- stack ----------\r\n") );
935 fp = fopen( g_szDumpFileNameA, "rb" );
937 if ( fp )
939 unsigned char buf[16];
940 int count;
944 int i;
946 count = fread( buf, sizeof(buf[0]), sizeof(buf)/sizeof(buf[0]), fp );
948 for ( i = 0; i < count; i++ )
950 TCHAR output[16];
952 _sntprintf( output, elementsof(output), _T("%02X\x20"), buf[i] );
953 aString.append( output );
955 for ( ; i < elementsof(buf); i++ )
957 aString.append( _T("\x20\x20\x20") );
960 for ( i = 0; i < count; i++ )
962 TCHAR output[2];
964 if ( (int)buf[i] >= 0x20 && (int)buf[i] <= 0x7F )
965 output[0] = (TCHAR)buf[i];
966 else
967 output[0] = '.';
968 output[1] = 0;
969 aString.append( output );
972 aString.append( _T("\r\n") );
974 } while ( count );
976 fclose( fp );
979 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), aString.c_str() );
982 SetWindowFont( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GetStockObject( SYSTEM_FIXED_FONT ), TRUE );
984 return TRUE;
985 case WM_COMMAND:
986 switch ( LOWORD(wParam) )
988 case IDOK:
989 case IDCANCEL:
990 EndDialog( hwndDlg, wParam );
991 return TRUE;
993 break;
994 default:
995 break;
998 return FALSE;
1000 //***************************************************************************
1002 static void PreviewReport( HWND hwndParent, CrashReportParams *pParams )
1004 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE );
1006 WriteReportFile( pParams );
1008 DialogBoxParam(
1009 hInstance,
1010 MAKEINTRESOURCE(IDD_PREVIEW_FRAME),
1011 hwndParent,
1012 PreviewDialogProc,
1013 (LPARAM)pParams
1016 DeleteFileA( g_szReportFileNameA );
1018 //***************************************************************************
1019 void UpdateOptionsDialogControls( HWND hwndDlg )
1021 if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED )
1023 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), TRUE );
1024 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), TRUE );
1026 else
1028 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), FALSE );
1029 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), FALSE );
1033 //***************************************************************************
1035 BOOL CALLBACK OptionsDialogProc(
1036 HWND hwndDlg,
1037 UINT uMsg,
1038 WPARAM wParam,
1039 LPARAM lParam
1042 static CrashReportParams *pParams;
1044 switch ( uMsg )
1046 case WM_INITDIALOG:
1048 TCHAR szBuffer[1024] = TEXT("");
1049 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
1050 //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
1052 pParams = (CrashReportParams *)lParam;
1054 LoadAndFormatString( hInstance, IDS_OPTIONS_CAPTION, szBuffer, elementsof(szBuffer) );
1055 SetWindowText( hwndDlg, szBuffer );
1057 LoadAndFormatString( hInstance, IDS_PROXY_SETTINGS_HEADER, szBuffer, elementsof(szBuffer) );
1058 Static_SetText( GetDlgItem(hwndDlg, IDC_PROXY_SETTINGS), szBuffer );
1060 LoadAndFormatString( hInstance, IDS_PROXY_SYSTEM, szBuffer, elementsof(szBuffer) );
1061 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM), szBuffer );
1063 LoadAndFormatString( hInstance, IDS_PROXY_DIRECT, szBuffer, elementsof(szBuffer) );
1064 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT), szBuffer );
1066 LoadAndFormatString( hInstance, IDS_PROXY_MANUAL, szBuffer, elementsof(szBuffer) );
1067 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL), szBuffer );
1069 LoadAndFormatString( hInstance, IDS_LABEL_PROXYSERVER, szBuffer, elementsof(szBuffer) );
1070 Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYSERVER), szBuffer );
1072 LoadAndFormatString( hInstance, IDS_LABEL_PROXYPORT, szBuffer, elementsof(szBuffer) );
1073 Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYPORT), szBuffer );
1075 LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) );
1076 Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
1078 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
1079 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
1081 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), pParams->sProxyServer.c_str() );
1082 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), pParams->sProxyPort.c_str() );
1084 Button_SetCheck( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM + pParams->uInternetConnection), BST_CHECKED );
1086 SendMessage(
1087 GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION),
1088 EM_SETBKGNDCOLOR,
1089 (WPARAM)FALSE,
1090 GetSysColor( COLOR_3DFACE ) );
1091 LoadAndFormatString( hInstance, IDS_PROXY_DESCRIPTION, szBuffer, elementsof(szBuffer) );
1092 Edit_SetText( GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), szBuffer );
1094 UpdateOptionsDialogControls( hwndDlg );
1096 return TRUE;
1097 case WM_COMMAND:
1098 switch ( LOWORD(wParam) )
1100 case IDC_RADIO_SYSTEM:
1101 case IDC_RADIO_DIRECT:
1102 case IDC_RADIO_MANUAL:
1103 if ( BN_CLICKED == HIWORD(wParam) )
1104 UpdateOptionsDialogControls( hwndDlg );
1105 break;
1106 case IDOK:
1108 TCHAR szBuffer[1024];
1110 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), szBuffer, elementsof(szBuffer) );
1111 pParams->sProxyServer = szBuffer;
1113 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), szBuffer, elementsof(szBuffer) );
1114 pParams->sProxyPort = szBuffer;
1116 if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT) ) & BST_CHECKED )
1117 pParams->uInternetConnection = 1;
1118 else if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED )
1119 pParams->uInternetConnection = 2;
1120 else
1121 pParams->uInternetConnection = 0;
1123 case IDCANCEL:
1124 EndDialog( hwndDlg, wParam );
1125 return TRUE;
1127 break;
1128 default:
1129 break;
1132 return FALSE;
1135 //***************************************************************************
1137 static void OptionsDialog( HWND hwndParent, CrashReportParams *pParams )
1139 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE );
1141 if ( IDOK == DialogBoxParam(
1142 hInstance,
1143 MAKEINTRESOURCE(IDD_OPTIONS_FRAME),
1144 hwndParent,
1145 OptionsDialogProc,
1146 (LPARAM)pParams
1148 pParams->WriteToRegistry();
1151 //***************************************************************************
1153 void UpdateReportDialogControls( HWND hwndDlg )
1155 EnableWindow(
1156 GetDlgItem(hwndDlg, IDC_EDIT_EMAIL),
1157 Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE );
1158 EnableWindow(
1159 GetDlgItem(hwndDlg, IDC_LABEL_EMAIL),
1160 Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE );
1163 //***************************************************************************
1165 BOOL CALLBACK ReportDialogProc(
1166 HWND hwndDlg,
1167 UINT uMsg,
1168 WPARAM wParam,
1169 LPARAM
1172 switch ( uMsg )
1174 case WM_INITDIALOG:
1176 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1177 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1178 TCHAR szBuffer[FORMATBUFSIZE];
1180 LoadAndFormatString( hInstance, IDS_REPORT_INTRO, szBuffer, elementsof(szBuffer) );
1181 Static_SetText( GetDlgItem(hwndDlg, IDC_REPORT_INTRO), szBuffer );
1183 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT3), szBuffer );
1185 LoadAndFormatString( hInstance, IDS_ENTER_TITLE, szBuffer, elementsof(szBuffer) );
1186 Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_TITLE), szBuffer );
1188 LoadAndFormatString( hInstance, IDS_ENTER_DESCRIPTION, szBuffer, elementsof(szBuffer) );
1189 Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_DESCRIPTION), szBuffer );
1191 LoadAndFormatString( hInstance, IDS_SHOW_REPORT_BUTTON, szBuffer, elementsof(szBuffer) );
1192 Button_SetText( GetDlgItem(hwndDlg, IDC_SHOW_REPORT), szBuffer );
1194 LoadAndFormatString( hInstance, IDS_SAVE_REPORT_BUTTON, szBuffer, elementsof(szBuffer) );
1195 Button_SetText( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), szBuffer );
1197 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
1198 if ( pszUserType )
1199 ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_SHOW );
1200 else
1201 ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_HIDE );
1203 LoadAndFormatString( hInstance, IDS_OPTIONS_BUTTON, szBuffer, elementsof(szBuffer) );
1204 Button_SetText( GetDlgItem(hwndDlg, IDC_OPTIONS), szBuffer );
1206 LoadAndFormatString( hInstance, IDS_ALLOW_CONTACT, szBuffer, elementsof(szBuffer) );
1207 Button_SetText( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), szBuffer );
1208 Button_SetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), pParams->fAllowContact ? BST_CHECKED : BST_UNCHECKED );
1210 LoadAndFormatString( hInstance, IDS_LABEL_EMAIL, szBuffer, elementsof(szBuffer) );
1211 Button_SetText( GetDlgItem(hwndDlg, IDC_LABEL_EMAIL), szBuffer );
1213 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), pParams->sEmail.c_str() );
1215 UpdateReportDialogControls( hwndDlg );
1217 return TRUE;
1218 case WM_SHOWWINDOW:
1219 if ( (BOOL)wParam )
1221 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1222 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1223 TCHAR szBuffer[FORMATBUFSIZE];
1225 LoadAndFormatString( hInstance, IDS_REPORT_CAPTION, szBuffer, elementsof(szBuffer) );
1226 SetWindowText( GetParent(hwndDlg), szBuffer );
1228 LoadAndFormatString( hInstance, IDS_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
1229 SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
1231 LoadAndFormatString( hInstance, IDS_DONOT_SEND_BUTTON, szBuffer, elementsof(szBuffer) );
1232 Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer );
1235 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), TRUE );
1236 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), TRUE );
1237 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), FALSE );
1239 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), pParams->sTitle.c_str() );
1240 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), pParams->sComment.c_str() );
1243 SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE,
1244 GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE) | BS_DEFPUSHBUTTON );
1245 SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE,
1246 GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE) &~ BS_DEFPUSHBUTTON );
1248 SetFocus( GetDlgItem(hwndDlg,IDC_EDIT_TITLE) );
1250 break;
1251 case WM_COMMAND:
1252 switch ( LOWORD(wParam) )
1254 case IDC_SHOW_REPORT:
1256 TCHAR szBuffer[32767];
1258 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1260 pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT) ) ? TRUE : FALSE;
1262 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), szBuffer, elementsof(szBuffer) );
1263 pParams->sTitle = szBuffer;
1265 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), szBuffer, elementsof(szBuffer) );
1266 pParams->sComment = szBuffer;
1268 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), szBuffer, elementsof(szBuffer) );
1269 pParams->sEmail = szBuffer;
1271 PreviewReport( GetParent(hwndDlg), pParams );
1273 return TRUE;
1274 case IDC_SAVE_REPORT:
1275 SaveDumpFile( GetParent(hwndDlg) );
1276 return TRUE;
1277 case IDC_OPTIONS:
1279 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1280 OptionsDialog( GetParent(hwndDlg), pParams );
1282 return TRUE;
1283 case IDC_ALLOW_CONTACT:
1284 if ( BN_CLICKED == HIWORD(wParam) )
1285 UpdateReportDialogControls( hwndDlg );
1286 return TRUE;
1288 break;
1289 default:
1290 break;
1293 return FALSE;
1295 //***************************************************************************
1297 BOOL CALLBACK WelcomeDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
1299 switch ( uMsg )
1301 case WM_INITDIALOG:
1303 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1304 HWND hwndRichEdit = GetDlgItem(hwndDlg, IDC_RICHEDIT21);
1305 TCHAR szBuffer[FORMATBUFSIZE];
1306 TCHAR szBuffer2[FORMATBUFSIZE];
1307 TCHAR szURL[256];
1308 TCHAR szCaption[256];
1310 SendMessage(
1311 hwndRichEdit,
1312 EM_SETBKGNDCOLOR,
1313 (WPARAM)FALSE,
1314 GetSysColor( COLOR_3DFACE ) );
1316 SendMessage( hwndRichEdit, EM_SETEVENTMASK, 0, ENM_LINK );
1317 SendMessage( hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0 );
1319 LoadAndFormatString( hInstance, IDS_WELCOME_BODY1, szBuffer, elementsof(szBuffer) );
1320 LoadAndFormatString( hInstance, IDS_WELCOME_BODY2, szBuffer2, elementsof(szBuffer2) );
1321 _tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) );
1322 LoadAndFormatString( hInstance, IDS_WELCOME_BODY3, szBuffer2, elementsof(szBuffer2) );
1323 _tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) );
1324 LoadString( hInstance, IDS_PRIVACY_URL, szURL, elementsof(szURL) );
1325 _tcsncat( szBuffer, szURL, elementsof(szBuffer) );
1326 SetWindowText( hwndRichEdit, szBuffer );
1328 LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szCaption, elementsof(szCaption) );
1329 SetWindowText( GetParent(hwndDlg), szCaption );
1332 return TRUE;
1333 case WM_SHOWWINDOW:
1334 if ( (BOOL)wParam )
1336 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1337 TCHAR szBuffer[FORMATBUFSIZE];
1339 LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szBuffer, elementsof(szBuffer) );
1340 SetWindowText( GetParent(hwndDlg), szBuffer );
1342 LoadAndFormatString( hInstance, IDS_WELCOME_HEADER, szBuffer, elementsof(szBuffer) );
1343 SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
1345 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
1346 Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer );
1348 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), FALSE );
1349 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), FALSE );
1350 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), TRUE );
1352 SetFocus( GetDlgItem(GetParent(hwndDlg),IDNEXT) );
1354 break;
1355 case WM_NOTIFY:
1357 LPNMHDR pnmh = (LPNMHDR)lParam;
1359 if ( pnmh->idFrom == IDC_RICHEDIT21 && pnmh->code == EN_LINK )
1361 ENLINK *plink = (ENLINK*)lParam;
1363 if ( plink->msg == WM_LBUTTONUP )
1365 TCHAR szBuffer[256];
1366 TEXTRANGE range;
1368 range.chrg = plink->chrg;
1369 range.lpstrText = szBuffer;
1371 SendMessage( pnmh->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&range );
1373 ShellExecute( hwndDlg, NULL, szBuffer, NULL, NULL, SW_SHOWDEFAULT );
1378 break;
1379 default:
1380 break;
1383 return FALSE;
1385 //***************************************************************************
1387 BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
1389 static HWND hwndPages[2] = { NULL };
1390 static int iActualPage = 0;
1392 switch ( uMsg )
1394 case WM_INITDIALOG:
1396 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1397 TCHAR szBuffer[FORMATBUFSIZE];
1399 SetWindowLong( hwndDlg, GWL_USERDATA, (LONG)lParam );
1400 hwndPages[0] = CreateDialog(
1401 hInstance,
1402 MAKEINTRESOURCE(IDD_WELCOME_PAGE),
1403 hwndDlg,
1404 WelcomeDialogProc );
1406 hwndPages[1] = CreateDialog(
1407 hInstance,
1408 MAKEINTRESOURCE(IDD_REPORT_PAGE),
1409 hwndDlg,
1410 ReportDialogProc );
1412 CHARFORMAT chfmt;
1414 chfmt.cbSize = sizeof(chfmt);
1415 chfmt.dwMask = CFM_BOLD;
1416 chfmt.dwEffects = CFE_BOLD;
1418 SendMessage(
1419 GetDlgItem(hwndDlg, IDC_HEADER),
1420 EM_SETCHARFORMAT,
1421 SCF_ALL,
1422 (LPARAM)&chfmt );
1424 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
1425 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
1427 LoadAndFormatString( hInstance, IDS_NEXT_BUTTON, szBuffer, elementsof(szBuffer) );
1428 Button_SetText( GetDlgItem(hwndDlg, IDNEXT), szBuffer );
1430 LoadAndFormatString( hInstance, IDS_SEND_BUTTON, szBuffer, elementsof(szBuffer) );
1431 Button_SetText( GetDlgItem(hwndDlg, IDFINISH), szBuffer );
1433 LoadAndFormatString( hInstance, IDS_BACK_BUTTON, szBuffer, elementsof(szBuffer) );
1434 Button_SetText( GetDlgItem(hwndDlg, IDBACK), szBuffer );
1436 ShowWindow( hwndPages[1], SW_HIDE );
1437 ShowWindow( hwndPages[0], SW_SHOW );
1439 // Let Crash Reporter window stay on top of all other windows
1440 SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
1442 return FALSE;
1443 case WM_CTLCOLORSTATIC:
1444 return (BOOL)CreateSolidBrush(GetSysColor(COLOR_WINDOW));
1445 case WM_COMMAND:
1446 switch ( LOWORD(wParam) )
1448 case IDBACK:
1449 if ( iActualPage > 0 )
1451 ShowWindow( hwndPages[iActualPage], SW_HIDE );
1452 ShowWindow( hwndPages[--iActualPage], SW_SHOW );
1454 return TRUE;
1455 case IDNEXT:
1456 if ( iActualPage < elementsof(hwndPages) - 1 )
1458 ShowWindow( hwndPages[iActualPage], SW_HIDE );
1459 ShowWindow( hwndPages[++iActualPage], SW_SHOW );
1461 return TRUE;
1462 case IDFINISH:
1464 TCHAR szBuffer[32767];
1465 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( hwndDlg, GWL_USERDATA );
1467 pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndPages[1], IDC_ALLOW_CONTACT) ) ? TRUE : FALSE;
1469 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_TITLE), szBuffer, elementsof(szBuffer) );
1470 pParams->sTitle = szBuffer;
1472 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_DESCRIPTION), szBuffer, elementsof(szBuffer) );
1473 pParams->sComment = szBuffer;
1475 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_EMAIL), szBuffer, elementsof(szBuffer) );
1476 pParams->sEmail = szBuffer;
1478 if ( pParams->fAllowContact && !pParams->sEmail.length() )
1480 TCHAR szMessage[MAX_TEXT_BUFFER];
1482 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_NOEMAILADDRESS, szMessage, elementsof(szMessage) );
1484 MessageBox( hwndDlg, szMessage, NULL, MB_ICONERROR | MB_OK );
1485 break; // Don't end the dialog
1487 else
1489 pParams->WriteToRegistry();
1491 WriteCommentFile( pParams->sComment.c_str() );
1492 WriteReportFile( pParams );
1494 if ( !SendCrashReport( hwndDlg, *pParams ) )
1495 break; // Don't end the dialog
1498 // Fallthrough !!!
1499 case IDCANCEL:
1500 EndDialog( hwndDlg, wParam );
1501 return TRUE;
1503 break;
1504 default:
1505 break;
1508 return FALSE;
1513 //*****************************************************************************
1514 //* Generate MD5 checksum
1515 //*****************************************************************************
1517 #define MAGIC_DESCRIPTION_FILLER 'x'
1518 #define MAGIC_DESCRIPTION_COUNT 80
1520 static void repatch_soffice_exe( void *pBuffer, size_t nBufSize )
1522 wchar_t DescriptionBuffer[MAGIC_DESCRIPTION_COUNT];
1524 memset( DescriptionBuffer, 0, sizeof(DescriptionBuffer) );
1525 wcsncpy( DescriptionBuffer, g_wstrProductKey.c_str(), elementsof(DescriptionBuffer) - 1 );
1527 bool bPatched = false;
1531 void *pFound = memchr( pBuffer, ((char *)DescriptionBuffer)[0], nBufSize );
1533 if ( pFound )
1535 size_t distance = (char *)pFound - (char *)pBuffer;
1537 if ( nBufSize >= distance )
1539 nBufSize -= distance;
1541 if ( nBufSize >= sizeof(DescriptionBuffer) &&
1542 0 == memcmp( pFound, DescriptionBuffer, sizeof(DescriptionBuffer) ) )
1544 for ( int i = 0; i < 80; i++ )
1546 ((wchar_t *)pFound)[i] = MAGIC_DESCRIPTION_FILLER;
1548 bPatched = true;
1550 else
1552 pBuffer = (void *)(((char *)pFound) + 1);
1553 nBufSize--;
1556 else
1557 nBufSize = 0;
1559 else
1560 nBufSize = 0;
1561 } while ( !bPatched && nBufSize );
1564 // Normalize executable/library images to prevent different MD5 checksums due
1565 // to a different PE header date/checksum (this doesn't affect the code/data
1566 // sections of a executable/library. Please see tools/source/bootstrp/md5.cxx
1567 // where the same method is also used. The tool so_checksum creates the MD5
1568 // checksums during build time. You have to make sure that both methods use the
1569 // same algorithm otherwise there could be problems with stack reports.
1570 static void normalize_pe_image(sal_uInt8* buffer, size_t nBufferSize)
1572 const int OFFSET_PE_OFFSET = 0x3c;
1573 const int OFFSET_COFF_TIMEDATESTAMP = 4;
1574 const int PE_SIGNATURE_SIZE = 4;
1575 const int COFFHEADER_SIZE = 20;
1576 const int OFFSET_PE_OPTIONALHEADER_CHECKSUM = 64;
1578 // Check the header part of the file buffer
1579 if (buffer[0] == 'M' && buffer[1] == 'Z')
1581 unsigned long PEHeaderOffset = (long)buffer[OFFSET_PE_OFFSET];
1582 if (PEHeaderOffset < nBufferSize-4)
1584 if ( buffer[PEHeaderOffset] == 'P' &&
1585 buffer[PEHeaderOffset+1] == 'E' &&
1586 buffer[PEHeaderOffset+2] == 0 &&
1587 buffer[PEHeaderOffset+3] == 0 )
1589 PEHeaderOffset += PE_SIGNATURE_SIZE;
1590 if (PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP < nBufferSize-4)
1592 // Set timedatestamp and checksum fields to a normalized
1593 // value to enforce the same MD5 checksum for identical
1594 // Windows executables/libraries.
1595 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP] = 0;
1596 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+1] = 0;
1597 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+2] = 0;
1598 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+3] = 0;
1601 if (PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM < nBufferSize-4)
1603 // Set checksum to a normalized value
1604 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM] = 0;
1605 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+1] = 0;
1606 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+2] = 0;
1607 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+3] = 0;
1614 static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
1616 const int MINIMAL_FILESIZE = 512;
1618 sal_uInt32 nBytesProcessed = 0;
1620 FILE *fp = fopen( filename, "rb" );
1622 if ( fp )
1624 long nFileSize;
1626 if ( 0 == fseek( fp, 0, SEEK_END ) && -1 != (nFileSize = ftell(fp)) )
1628 rewind( fp );
1630 sal_uInt8 *pBuffer = new sal_uInt8[nFileSize];
1631 size_t nBytesRead = fread( pBuffer, 1, nFileSize, fp );
1633 if ( sal::static_int_cast<long>(nBytesRead) == nFileSize )
1635 if ( 0 == stricmp( GetFileName(filename).c_str(), "soffice.bin" ) )
1636 repatch_soffice_exe( pBuffer, nBytesRead );
1637 else if ( nFileSize > MINIMAL_FILESIZE )
1638 normalize_pe_image( pBuffer, nBytesRead );
1640 rtlDigestError error = rtl_digest_MD5 (
1641 pBuffer, nBytesRead,
1642 pChecksum, nChecksumLen );
1644 if ( rtl_Digest_E_None == error )
1645 nBytesProcessed = nBytesRead;
1648 delete[] pBuffer;
1651 fclose( fp );
1655 return nBytesProcessed;
1658 #if 0
1659 static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
1661 sal_uInt32 nBytesProcessed = 0;
1663 FILE *fp = fopen( filename, "rb" );
1665 if ( fp )
1667 rtlDigest digest = rtl_digest_createMD5();
1669 if ( digest )
1671 size_t nBytesRead;
1672 sal_uInt8 buffer[4096];
1673 rtlDigestError error = rtl_Digest_E_None;
1675 while ( rtl_Digest_E_None == error &&
1676 0 != (nBytesRead = fread( buffer, 1, sizeof(buffer), fp )) )
1678 error = rtl_digest_updateMD5( digest, buffer, nBytesRead );
1679 nBytesProcessed += nBytesRead;
1682 if ( rtl_Digest_E_None == error )
1684 error = rtl_digest_getMD5( digest, pChecksum, nChecksumLen );
1687 if ( rtl_Digest_E_None != error )
1688 nBytesProcessed = 0;
1690 rtl_digest_destroyMD5( digest );
1693 fclose( fp );
1696 return nBytesProcessed;
1699 #endif
1700 //***************************************************************************
1702 static bool WriteStackFile( FILE *fout, hash_map< string, string >& rLibraries, DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers )
1704 bool fSuccess = false;
1706 if ( fout && dwProcessId && pExceptionPointers )
1708 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
1710 if ( IsValidHandle(hProcess) )
1712 EXCEPTION_POINTERS aExceptionPointers;
1713 CONTEXT aContextRecord;
1715 ReadProcessMemory(
1716 hProcess,
1717 pExceptionPointers,
1718 &aExceptionPointers,
1719 sizeof(aExceptionPointers),
1720 NULL );
1722 ReadProcessMemory(
1723 hProcess,
1724 aExceptionPointers.ContextRecord,
1725 &aContextRecord,
1726 sizeof(aContextRecord),
1727 NULL );
1729 STACKFRAME frame;
1731 ZeroMemory( &frame, sizeof(frame) );
1732 frame.AddrPC.Offset = aContextRecord.Eip;
1733 frame.AddrPC.Mode = AddrModeFlat;
1734 frame.AddrFrame.Offset = aContextRecord.Ebp;
1735 frame.AddrFrame.Mode = AddrModeFlat;
1737 BOOL bSuccess;
1738 int frameNum = 0;
1740 SymInitialize( hProcess, NULL, TRUE );
1742 fprintf( fout, "<errormail:Stack type=\"Win32\">\n" );
1746 fSuccess = true;
1748 bSuccess = StackWalk( IMAGE_FILE_MACHINE_I386,
1749 hProcess,
1750 NULL,
1751 &frame,
1752 &aContextRecord,
1753 (PREAD_PROCESS_MEMORY_ROUTINE)ReadProcessMemory,
1754 SymFunctionTableAccess,
1755 SymGetModuleBase,
1756 NULL );
1758 if ( bSuccess )
1760 // Note: ImageHelp ANSI functions do not have an A postfix while
1761 // Unicode versions have a W postfix. There's no macro
1762 // that depends on define UNICODE
1764 IMAGEHLP_MODULE moduleInfo;
1766 ZeroMemory( &moduleInfo, sizeof(moduleInfo) );
1767 moduleInfo.SizeOfStruct = sizeof(moduleInfo);
1769 if ( SymGetModuleInfo( hProcess, frame.AddrPC.Offset, &moduleInfo ) )
1771 rLibraries[ GetFileName( moduleInfo.LoadedImageName ).c_str() ] = moduleInfo.LoadedImageName;
1773 DWORD dwRelOffset = 0;
1774 BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 256 ];
1775 PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
1777 ZeroMemory( symbolBuffer, sizeof(symbolBuffer) );
1778 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
1779 pSymbol->MaxNameLength = 256;
1781 if ( SymGetSymFromAddr( hProcess, frame.AddrPC.Offset, &dwRelOffset, pSymbol ) )
1782 fprintf( fout, "<errormail:StackInfo " \
1783 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" ordinal=\"%s+0x%p\" name=\"%s\" path=\"%s\"/>\n",
1784 frameNum,
1785 frame.AddrPC.Offset,
1786 frame.AddrPC.Offset - moduleInfo.BaseOfImage,
1787 xml_encode(pSymbol->Name).c_str(),
1788 frame.AddrPC.Offset - pSymbol->Address,
1789 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
1790 xml_encode( GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
1792 else
1793 fprintf( fout, "<errormail:StackInfo " \
1794 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" name=\"%s\" path=\"%s\"/>\n",
1795 frameNum,
1796 frame.AddrPC.Offset,
1797 frame.AddrPC.Offset - moduleInfo.BaseOfImage,
1798 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
1799 xml_encode(GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
1802 else
1803 fprintf( fout, "<errormail:StackInfo pos=\"%d\" ip=\"0x%p\"/>\n",
1804 frameNum,
1805 frame.AddrPC.Offset
1808 frameNum++;
1811 } while ( bSuccess );
1813 fprintf( fout, "</errormail:Stack>\n" );
1815 SymCleanup( hProcess );
1817 CloseHandle( hProcess );
1822 return fSuccess;
1825 bool WriteChecksumFile( FILE *fchksum, const hash_map< string, string >& rLibraries )
1827 bool success = false;
1829 if ( fchksum && rLibraries.size() )
1831 fprintf( fchksum, "<errormail:Checksums type=\"MD5\">\n" );
1833 hash_map< string, string >::const_iterator iter;
1835 for ( iter = rLibraries.begin();
1836 iter != rLibraries.end();
1837 iter++ )
1839 sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5];
1840 sal_uInt32 nBytesProcessed = calc_md5_checksum(
1841 iter->second.c_str(),
1842 checksum, sizeof(checksum) );
1844 if ( nBytesProcessed )
1846 fprintf( fchksum, "<errormail:Checksum sum=\"0x" );
1847 for ( int i = 0; i < sizeof(checksum); fprintf( fchksum, "%02X", checksum[i++] ) );
1848 fprintf( fchksum, "\" bytes=\"%d\" file=\"%s\"/>\n",
1849 nBytesProcessed,
1850 GetFileName( iter->first ).c_str() );
1854 fprintf( fchksum, "</errormail:Checksums>\n" );
1856 success = true;
1859 return success;
1862 //***************************************************************************
1864 BOOL FindDumpFile()
1866 TCHAR szFileName[MAX_PATH];
1868 if ( GetCrashDataPath( szFileName ) )
1870 _tcscat( szFileName, _T("\\crashdat.dmp") );
1872 HANDLE hFile = CreateFile(
1873 szFileName,
1874 GENERIC_READ,
1875 0, NULL,
1876 OPEN_EXISTING,
1877 FILE_ATTRIBUTE_NORMAL, NULL );
1879 if ( hFile )
1881 CloseHandle( hFile );
1883 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
1884 _tcscpy( g_szDumpFileName, szFileName );
1886 return TRUE;
1890 return FALSE;
1893 BOOL WriteDumpFile( DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers, DWORD dwThreadId )
1895 BOOL fSuccess = FALSE;
1896 PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam = NULL;
1897 MINIDUMP_EXCEPTION_INFORMATION ExceptionParam;
1899 HMODULE hDbgHelp = LoadLibrary( _T("DBGHELP.DLL" ) );
1900 MiniDumpWriteDump_PROC pMiniDumpWriteDump = NULL;
1902 if ( hDbgHelp )
1904 pMiniDumpWriteDump = (MiniDumpWriteDump_PROC)GetProcAddress( hDbgHelp, "MiniDumpWriteDump" );
1906 if ( !pMiniDumpWriteDump )
1908 FreeLibrary( hDbgHelp );
1909 return false;
1913 if ( !pMiniDumpWriteDump )
1914 return false;
1916 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
1918 if ( IsValidHandle(hProcess) )
1920 TCHAR szTempPath[MAX_PATH];
1922 // if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
1923 if ( GetCrashDataPath( szTempPath ) )
1925 TCHAR szFileName[MAX_PATH];
1927 // if ( GetTempFileName( szTempPath, TEXT("DMP"), 0, szFileName ) )
1928 _tcscpy( szFileName, szTempPath );
1929 _tcscat( szFileName, _T("\\crashdat.dmp") );
1931 HANDLE hFile = CreateFile(
1932 szFileName,
1933 GENERIC_READ | GENERIC_WRITE,
1934 0, NULL,
1935 // OPEN_EXISTING,
1936 CREATE_ALWAYS,
1937 FILE_ATTRIBUTE_NORMAL, NULL );
1939 if ( hFile )
1941 if ( pExceptionPointers && dwThreadId )
1943 ExceptionParam.ThreadId = dwThreadId;
1944 ExceptionParam.ExceptionPointers = pExceptionPointers;
1945 ExceptionParam.ClientPointers = TRUE;
1947 EXCEPTION_POINTERS aExceptionPointers;
1948 EXCEPTION_RECORD aExceptionRecord;
1950 ReadProcessMemory(
1951 hProcess,
1952 pExceptionPointers,
1953 &aExceptionPointers,
1954 sizeof(aExceptionPointers),
1955 NULL );
1958 ReadProcessMemory(
1959 hProcess,
1960 aExceptionPointers.ExceptionRecord,
1961 &aExceptionRecord,
1962 sizeof(aExceptionRecord),
1963 NULL );
1965 g_dwExceptionCode = aExceptionRecord.ExceptionCode;
1967 lpExceptionParam = &ExceptionParam;
1970 fSuccess = pMiniDumpWriteDump( hProcess, dwProcessId, hFile, MiniDumpNormal, lpExceptionParam, NULL, NULL );
1972 CloseHandle( hFile );
1974 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
1975 _tcscpy( g_szDumpFileName, szFileName );
1978 if ( !fSuccess )
1979 DeleteFile( szFileName );
1983 CloseHandle( hProcess );
1986 FreeLibrary( hDbgHelp );
1988 return fSuccess;
1991 //***************************************************************************
1993 static DWORD FindProcessForImage( LPCTSTR lpImagePath )
1995 DWORD dwProcessId = 0;
1996 DWORD aProcesses[1024];
1997 DWORD dwSize = 0;
1998 TCHAR szShortImagePath[MAX_PATH];
2000 if ( GetShortPathName( lpImagePath, szShortImagePath, elementsof(szShortImagePath) ) &&
2001 EnumProcesses( aProcesses, sizeof(aProcesses), &dwSize ) )
2003 unsigned nProcesses = dwSize / sizeof(aProcesses[0]);
2005 for ( unsigned i = 0; !dwProcessId && i < nProcesses; i++ )
2007 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] );
2009 if ( IsValidHandle(hProcess) )
2011 TCHAR szModulePath[MAX_PATH+1];
2013 if ( GetModuleFileNameEx( hProcess, NULL, szModulePath, MAX_PATH ) )
2015 TCHAR szShortModulePath[MAX_PATH];
2017 if ( GetShortPathName( szModulePath, szShortModulePath, elementsof(szShortModulePath) ) )
2019 if ( 0 == _tcsicmp( szShortModulePath, szShortImagePath ) )
2020 dwProcessId = aProcesses[i];
2024 CloseHandle( hProcess );
2029 return dwProcessId;
2031 //***************************************************************************
2033 static bool ParseCommandArgs( LPDWORD pdwProcessId, PEXCEPTION_POINTERS* ppException, LPDWORD pdwThreadId )
2035 int argc = __argc;
2036 #ifdef __MINGW32__
2037 #ifdef _UNICODE
2038 TCHAR **argv = reinterpret_cast<TCHAR **>(alloca((argc+1)*sizeof(WCHAR*)));
2039 int *sizes = reinterpret_cast<int *>(alloca(argc*sizeof(int)));
2040 int argsize=0;
2041 char **ptr;
2042 int i;
2043 ptr=__argv;
2044 for (i = 0; i < argc; ++i)
2046 sizes[i]=MultiByteToWideChar(CP_ACP, 0, *ptr, -1, NULL, 0);
2047 argsize+=sizes[i]+1;
2048 ++ptr;
2050 ++argsize;
2051 TCHAR *args = reinterpret_cast<TCHAR *>(alloca(argsize*sizeof(WCHAR)));
2052 ptr=__argv;
2053 TCHAR *cptr=args;
2054 for (i = 0; i < argc; ++i)
2056 argv[i]=cptr;
2057 MultiByteToWideChar( CP_ACP, 0, *ptr, -1, cptr, sizes[i] );
2058 ++ptr;
2059 cptr+=sizes[i];
2060 *cptr=0;
2061 ++cptr;
2063 argv[i]=cptr;
2064 *cptr=0;
2065 #else
2066 TCHAR **argv = __argv;
2067 #endif
2068 #else
2069 TCHAR **argv = __targv;
2070 #endif
2071 bool bSuccess = true;
2073 for ( int argn = 1; bSuccess && argn < argc; argn++ )
2075 if ( 0 == _tcsicmp( argv[argn], _T("-h") ) ||
2076 0 == _tcsicmp( argv[argn], _T("/h") ) ||
2077 0 == _tcsicmp( argv[argn], _T("-?") ) ||
2078 0 == _tcsicmp( argv[argn], _T("/?") ) ||
2079 0 == _tcsicmp( argv[argn], _T("/help") ) ||
2080 0 == _tcsicmp( argv[argn], _T("-help") ) ||
2081 0 == _tcsicmp( argv[argn], _T("--help") )
2084 HINSTANCE hInstance = GetModuleHandle(NULL);
2085 TCHAR szUsage[FORMATBUFSIZE];
2086 TCHAR szProcess[FORMATBUFSIZE];
2087 TCHAR szProcessDescription[FORMATBUFSIZE];
2088 TCHAR szHelpDescription[FORMATBUFSIZE];
2090 LoadAndFormatString( hInstance, IDS_MSG_CMDLINE_USAGE, szUsage, elementsof(szUsage) );
2091 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID, szProcess, elementsof(szProcess) );
2092 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID_DESCRIPTION, szProcessDescription, elementsof(szProcessDescription) );
2093 LoadAndFormatString( hInstance, IDS_MSG_PARAM_HELP_DESCRIPTION, szHelpDescription, elementsof(szHelpDescription) );
2095 _tprintf(
2096 TEXT("\n%s: crashrep %s\n\n")
2097 TEXT("/?, -h[elp] %s\n\n")
2098 TEXT("%-20s %s\n\n"),
2099 szUsage, szProcess, szHelpDescription, szProcess, szProcessDescription
2102 return true;
2104 else if ( 0 == _tcsicmp( argv[argn], _T("-p") ) ||
2105 0 == _tcsicmp( argv[argn], _T("/p") ) )
2107 if ( ++argn < argc )
2108 *pdwProcessId = _tcstoul( argv[argn], NULL, 0 );
2109 else
2110 bSuccess = false;
2112 else if ( 0 == _tcsicmp( argv[argn], _T("-excp") ) ||
2113 0 == _tcsicmp( argv[argn], _T("/excp") ) )
2115 if ( ++argn < argc )
2116 *ppException = (PEXCEPTION_POINTERS)_tcstoul( argv[argn], NULL, 0 );
2117 else
2118 bSuccess = false;
2120 else if ( 0 == _tcsicmp( argv[argn], _T("-t") ) ||
2121 0 == _tcsicmp( argv[argn], _T("/t") ) )
2123 if ( ++argn < argc )
2124 *pdwThreadId = _tcstoul( argv[argn], NULL, 0 );
2125 else
2126 bSuccess = false;
2128 else if ( 0 == _tcsicmp( argv[argn], _T("-noui") ) ||
2129 0 == _tcsicmp( argv[argn], _T("/noui") ) )
2131 g_bNoUserInterface = true;
2133 else if ( 0 == _tcsicmp( argv[argn], _T("-send") ) ||
2134 0 == _tcsicmp( argv[argn], _T("/send") ) )
2136 g_bSendReport = true;
2138 else if ( 0 == _tcsicmp( argv[argn], _T("-load") ) ||
2139 0 == _tcsicmp( argv[argn], _T("/load") ) )
2141 g_bLoadReport = true;
2143 else // treat parameter as image path
2145 TCHAR szImagePath[MAX_PATH];
2146 LPTSTR lpImageName;
2148 if ( GetFullPathName( argv[argn], MAX_PATH, szImagePath, &lpImageName ) )
2150 DWORD dwProcessId = FindProcessForImage( szImagePath );
2152 if ( dwProcessId )
2153 *pdwProcessId = dwProcessId;
2154 else
2155 bSuccess = false;
2160 if ( !*pdwProcessId && !g_bLoadReport )
2162 TCHAR szImagePath[MAX_PATH];
2163 LPTSTR lpImageName;
2165 if ( GetFullPathName( TEXT("soffice.exe"), MAX_PATH, szImagePath, &lpImageName ) )
2167 DWORD dwProcessId = FindProcessForImage( szImagePath );
2169 if ( dwProcessId )
2170 *pdwProcessId = dwProcessId;
2171 else
2172 bSuccess = false;
2176 return bSuccess;
2179 //***************************************************************************
2181 BOOL WriteCommentFile( LPCTSTR lpComment )
2183 BOOL fSuccess = FALSE;
2184 TCHAR szTempPath[MAX_PATH];
2186 if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
2188 TCHAR szFileName[MAX_PATH];
2190 if ( GetTempFileName( szTempPath, TEXT("CMT"), 0, szFileName ) )
2192 HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
2194 if ( hFile )
2196 DWORD dwBytesWritten;
2198 int needed = WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, NULL, 0, NULL, NULL );
2199 if ( needed )
2201 char *lpCommentUTF8 = (char *)alloca( needed );
2202 WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, lpCommentUTF8, needed, NULL, NULL );
2203 fSuccess = WriteFile( hFile, lpCommentUTF8, strlen(lpCommentUTF8), &dwBytesWritten, NULL );
2205 else
2206 fSuccess = TRUE;
2209 CloseHandle( hFile );
2211 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szCommentFileNameA, MAX_PATH, NULL, NULL );
2214 if ( !fSuccess )
2215 DeleteFile( szFileName );
2219 return fSuccess;
2222 //***************************************************************************
2224 static int _tsetenv( const _TCHAR *lpVar, const _TCHAR *lpValue )
2226 if ( !lpValue )
2227 lpValue = _T("");
2229 _TCHAR *envstr = (TCHAR *)alloca( (_tcslen( lpVar ) + _tcslen( lpValue ) + 2) * sizeof(_TCHAR) );
2231 _tcscpy( envstr, lpVar );
2232 _tcscat( envstr, _T("=") );
2233 _tcscat( envstr, lpValue );
2235 return _tputenv( envstr );
2238 static bool read_line( FILE *fp, string& rLine )
2240 char szBuffer[1024];
2241 bool bSuccess = false;
2242 bool bEOL = false;
2243 string line;
2246 while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) )
2248 int len = strlen(szBuffer);
2250 bSuccess = true;
2252 while ( len && szBuffer[len - 1] == '\n' )
2254 szBuffer[--len] = 0;
2255 bEOL = true;
2258 line.append( szBuffer );
2261 rLine = line;
2262 return bSuccess;
2265 static string get_script_string( const char *pFileName, const char *pKeyName )
2267 FILE *fp = fopen( pFileName, "rt" );
2268 string retValue;
2270 if ( fp )
2272 string line;
2273 string section;
2275 while ( read_line( fp, line ) )
2277 line = trim_string( line );
2280 string::size_type iEqualSign = line.find( '=', 0 );
2282 if ( iEqualSign != string::npos )
2284 string keyname = line.substr( 0, iEqualSign );
2285 keyname = trim_string( keyname );
2287 string value = line.substr( sal::static_int_cast<string::size_type>(iEqualSign + 1) );
2288 value = trim_string( value );
2290 if ( value.length() && '\"' == value[0] )
2292 value.erase( 0, 1 );
2294 string::size_type iQuotes = value.find( '"', 0 );
2296 if ( iQuotes != string::npos )
2297 value.erase( iQuotes );
2300 if ( 0 == stricmp( keyname.c_str(), pKeyName ) )
2302 retValue = value;
2303 break;
2308 fclose( fp );
2311 return retValue;
2314 static bool ReadBootstrapParams( CrashReportParams &rParams )
2316 TCHAR szBuffer[256] = TEXT("");
2317 TCHAR szModuleName[MAX_PATH];
2318 TCHAR szModuleVersionName[MAX_PATH];
2319 TCHAR szDrive[_MAX_DRIVE];
2320 TCHAR szDir[_MAX_DIR];
2321 TCHAR szFName[_MAX_FNAME];
2322 TCHAR szExt[_MAX_EXT];
2323 TCHAR szReportServer[MAX_HOSTNAME];
2324 TCHAR szReportPort[256];
2325 bool bSuccess = false;
2327 GetModuleFileName( NULL, szModuleName, MAX_PATH );
2328 _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
2329 _tmakepath( szModuleName, szDrive, szDir, _T("bootstrap"), _T(".ini") );
2330 _tmakepath( szModuleVersionName, szDrive, szDir, _T("version"), _T(".ini") );
2332 if (
2333 GetPrivateProfileString(
2334 TEXT("Bootstrap"),
2335 TEXT("ProductKey"),
2336 TEXT("OpenOffice.org"),
2337 szBuffer,
2338 elementsof(szBuffer),
2339 szModuleName )
2342 TCHAR *pVersion = _tcschr( szBuffer, ' ' );
2344 g_wstrProductKey = szBuffer;
2346 if ( pVersion )
2348 *pVersion = 0;
2349 pVersion++;
2351 else
2352 pVersion = TEXT("");
2354 if ( !_tgetenv( _T("PRODUCTNAME") ) )
2356 _tsetenv( TEXT("PRODUCTNAME"), szBuffer );
2358 if ( !_tgetenv( _T("PRODUCTVERSION") ) )
2359 _tsetenv( TEXT("PRODUCTVERSION"), pVersion );
2362 GetPrivateProfileString(
2363 TEXT("Version"),
2364 TEXT("buildid"),
2365 TEXT("unknown"),
2366 g_szBuildId, elementsof(g_szBuildId),
2367 szModuleVersionName );
2369 g_strDefaultLanguage = get_script_string( "instdb.inf", "DefaultLanguage" );
2371 if ( GetPrivateProfileString(
2372 TEXT("ErrorReport"),
2373 TEXT("ErrorReportPort"),
2374 TEXT("80"),
2375 szReportPort, elementsof(szReportPort),
2376 szModuleName
2379 TCHAR *endptr = NULL;
2381 unsigned short uReportPort = (unsigned short)_tcstoul( szReportPort, &endptr, 10 );
2382 if ( uReportPort )
2383 g_uReportPort = uReportPort;
2386 if ( GetPrivateProfileString(
2387 TEXT("ErrorReport"),
2388 TEXT("ErrorReportServer"),
2389 TEXT(""),
2390 szReportServer, elementsof(szReportServer),
2391 szModuleName
2394 bSuccess = 0 != WideCharToMultiByte( CP_ACP, 0, szReportServer, -1, g_szReportServerA, elementsof(g_szReportServerA), NULL, NULL );
2397 LPCTSTR lpEnvString;
2399 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYSERVER") )) )
2400 rParams.sProxyServer = lpEnvString;
2402 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYPORT") )) )
2403 rParams.sProxyPort = lpEnvString;
2405 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_SENDERADDRESS") )) )
2406 rParams.sEmail = lpEnvString;
2408 return bSuccess;
2411 //***************************************************************************
2413 bool SendHTTPRequest(
2414 FILE *fp,
2415 const char *pszServer,
2416 unsigned short uPort = 80,
2417 const char *pszProxyServer = NULL,
2418 unsigned short uProxyPort = 8080 )
2420 bool success = false;
2422 struct hostent *hp;
2424 if ( pszProxyServer )
2425 hp = gethostbyname( pszProxyServer );
2426 else
2427 hp = gethostbyname( pszServer );
2429 if ( hp )
2431 SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
2433 if ( s )
2435 struct sockaddr_in address;
2437 memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr));
2438 address.sin_family = AF_INET;
2440 if ( pszProxyServer )
2441 address.sin_port = ntohs( uProxyPort );
2442 else
2443 address.sin_port = ntohs( uPort );
2445 if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) )
2447 fseek( fp, 0, SEEK_END );
2448 size_t length = ftell( fp );
2449 fseek( fp, 0, SEEK_SET );
2451 char buffer[2048];
2453 if ( pszProxyServer )
2454 sprintf( buffer,
2455 "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
2456 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2457 "Content-Length: %d\r\n"
2458 "SOAPAction: \"\"\r\n\r\n",
2459 pszServer,
2460 uPort,
2461 length
2463 else
2464 sprintf( buffer,
2465 "POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
2466 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2467 "Content-Length: %d\r\n"
2468 "SOAPAction: \"\"\r\n\r\n",
2469 length
2472 if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
2474 size_t nBytes;
2478 nBytes = fread( buffer, 1, sizeof(buffer), fp );
2480 if ( nBytes )
2481 success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
2482 } while( nBytes && success );
2484 if ( success )
2486 memset( buffer, 0, sizeof(buffer) );
2487 success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 );
2488 if ( success )
2490 char szHTTPSignature[sizeof(buffer)] = "";
2491 unsigned uHTTPReturnCode = 0;
2493 sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode );
2494 success = uHTTPReturnCode == 200;
2501 closesocket( s );
2505 return success;
2508 //***************************************************************************
2510 static void WriteSOAPRequest( FILE *fp )
2512 fprintf( fp,
2513 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
2514 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
2515 "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
2516 "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
2517 "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
2518 "xmlns:rds=\"urn:ReportDataService\"\n"
2519 "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
2520 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
2521 "<SOAP-ENV:Body>\n"
2524 fprintf( fp, "<rds:submitReport>\n" );
2525 fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
2526 fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
2528 FILE *fpin = fopen( g_szReportFileNameA, "r" );
2529 if ( fpin )
2531 fprintf( fp,
2532 "<item>\n"
2533 "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
2534 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2535 fcopy( fpin, fp );
2536 fprintf( fp, "]]></value></item>\n" );
2537 fclose( fpin );
2540 fpin = fopen( g_szCommentFileNameA, "r" );
2541 if ( fpin )
2543 fprintf( fp,
2544 "<item>\n"
2545 "<key xsi:type=\"xsd:string\">description.txt</key>\n"
2546 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2547 fcopy( fpin, fp );
2548 fprintf( fp, "]]></value></item>\n" );
2549 fclose( fpin );
2553 fpin = fopen( g_szDumpFileNameA, "rb" );
2554 if ( fpin )
2556 FILE *fptemp = _tmpfile();
2558 if ( fptemp )
2560 if ( base64_encode( fpin, fptemp ) )
2562 fseek( fptemp, 0, SEEK_SET );
2563 fprintf( fp,
2564 "<item>\n"
2565 "<key xsi:type=\"xsd:string\">user.dmp</key>\n"
2566 "<value xsi:type=\"xsd:string\">" );
2567 fcopy( fptemp, fp );
2568 fprintf( fp, "</value></item>\n" );
2570 fclose( fptemp );
2572 fclose( fpin );
2575 fprintf( fp,
2576 "</hash>\n"
2577 "</rds:submitReport>\n"
2578 "</SOAP-ENV:Body>\n"
2579 "</SOAP-ENV:Envelope>\n"
2583 //***************************************************************************
2585 struct RequestParams
2587 bool success;
2588 FILE *fpin;
2589 const char *lpServer;
2590 unsigned short uPort;
2591 const char *lpProxyServer;
2592 unsigned short uProxyPort;
2593 HWND hwndStatus;
2596 void _cdecl SendingThread( void *lpArgs )
2598 RequestParams *pParams = (RequestParams *)lpArgs;
2600 pParams->success = SendHTTPRequest( pParams->fpin, pParams->lpServer, pParams->uPort, pParams->lpProxyServer, pParams->uProxyPort );
2602 PostMessage( pParams->hwndStatus, WM_COMMAND, IDOK, 0 );
2605 //***************************************************************************
2607 BOOL CALLBACK SendingStatusDialogProc(
2608 HWND hwndDlg,
2609 UINT uMsg,
2610 WPARAM wParam,
2611 LPARAM lParam
2614 static RequestParams *pRequest = NULL;
2615 static HANDLE hSendingThread = NULL;
2617 switch ( uMsg )
2619 case WM_INITDIALOG:
2621 TCHAR szBuffer[1024] = TEXT("");
2622 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
2623 //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
2625 pRequest = (RequestParams *)lParam;
2627 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
2628 SetWindowText( hwndDlg, szBuffer );
2630 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_STATUS, szBuffer, elementsof(szBuffer) );
2631 Static_SetText( GetDlgItem(hwndDlg, IDC_SENDING_REPORT_STATUS), szBuffer );
2633 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
2634 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
2636 pRequest->hwndStatus = hwndDlg;
2638 hSendingThread = (HANDLE)_beginthread( SendingThread, 0, pRequest );
2640 return TRUE;
2641 case WM_COMMAND:
2642 switch ( LOWORD(wParam) )
2644 case IDCANCEL:
2645 TerminateThread( hSendingThread, 0 );
2646 case IDOK:
2647 WaitForSingleObject( hSendingThread, INFINITE );
2648 CloseHandle( hSendingThread );
2649 EndDialog( hwndDlg, wParam );
2650 return TRUE;
2652 break;
2653 default:
2654 break;
2657 return FALSE;
2660 //***************************************************************************
2662 bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams )
2664 bool success = false;
2665 char szProxyServer[1024] = "";
2666 unsigned short uProxyPort = 8080;
2667 TCHAR *endptr = NULL;
2669 switch ( rParams.uInternetConnection )
2671 case 2:
2673 WideCharToMultiByte(
2674 CP_ACP, 0, rParams.sProxyServer.c_str(), -1,
2675 szProxyServer, sizeof(szProxyServer), NULL, NULL );
2676 uProxyPort = (unsigned short)_tcstoul( rParams.sProxyPort.c_str(), &endptr, 10 );
2678 break;
2679 case 0:
2681 DWORD dwProxyEnable = 0;
2683 RegReadValue( HKEY_CURRENT_USER,
2684 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
2685 TEXT("ProxyEnable"),
2686 &dwProxyEnable,
2687 sizeof(dwProxyEnable) );
2689 if ( dwProxyEnable )
2691 TCHAR tszProxyServers[1024] = TEXT("");
2693 if ( ERROR_SUCCESS == RegReadValue( HKEY_CURRENT_USER,
2694 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), TEXT("ProxyServer"),
2695 tszProxyServers,
2696 sizeof(tszProxyServers) ) )
2698 TCHAR *lpHttpStart = _tcsstr( tszProxyServers, TEXT("http=") );
2700 if ( lpHttpStart )
2701 lpHttpStart += 5;
2702 else
2703 lpHttpStart = tszProxyServers;
2705 TCHAR *lpHttpEnd = _tcschr( lpHttpStart, ';' );
2707 if ( lpHttpEnd )
2708 *lpHttpEnd = 0;
2710 char szHTTPProxyServer[1024] = "";
2711 WideCharToMultiByte( CP_ACP, 0, lpHttpStart, -1, szHTTPProxyServer, sizeof(szHTTPProxyServer), NULL, NULL );
2713 char *lpColon = strchr( szHTTPProxyServer, ':' );
2715 if ( lpColon )
2717 char *endptr = NULL;
2719 *lpColon = 0;
2720 uProxyPort = (unsigned short)strtoul( lpColon + 1, &endptr, 10 );
2722 else
2723 uProxyPort = 8080;
2725 strcpy( szProxyServer, szHTTPProxyServer );
2730 break;
2731 default:
2732 case 1:
2733 break;
2736 FILE *fptemp = _tmpfile();
2737 if ( fptemp )
2739 RequestParams request;
2741 request.success = false;
2742 request.fpin = fptemp;
2743 request.lpServer = REPORT_SERVER;
2744 request.uPort = REPORT_PORT;
2745 request.lpProxyServer = szProxyServer[0] ? szProxyServer : NULL;
2746 request.uProxyPort = uProxyPort;
2747 request.hwndStatus = NULL;
2749 WriteSOAPRequest( fptemp );
2750 fseek( fptemp, 0, SEEK_SET );
2752 if ( hwndParent )
2754 int retid = DialogBoxParam(
2755 GetModuleHandle(NULL),
2756 MAKEINTRESOURCE(IDD_SENDING_STATUS),
2757 hwndParent,
2758 SendingStatusDialogProc,
2759 (LPARAM)&request
2762 success = request.success;
2764 if ( IDOK == retid )
2766 if ( !success )
2768 TCHAR szMessage[1024];
2770 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) );
2772 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
2774 else
2776 TCHAR szMessage[1024];
2777 TCHAR szTitle[1024];
2779 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) );
2780 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_HEADER, szTitle, elementsof(szTitle) );
2782 MessageBox( hwndParent, szMessage, szTitle, MB_ICONINFORMATION | MB_OK );
2787 else
2789 HANDLE hSendingThread = (HANDLE)_beginthread( SendingThread, 0, (void *)&request );
2791 WaitForSingleObject( hSendingThread, INFINITE );
2793 success = request.success;
2794 if ( !success )
2796 TCHAR szMessage[1024];
2798 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) );
2799 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
2801 else
2803 TCHAR szMessage[1024];
2805 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) );
2807 _ftprintf( stderr, _T("SUCCESS: %s\n"), szMessage );
2810 fclose( fptemp );
2812 else
2814 TCHAR szMessage[1024];
2816 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_DISK_FULL, szMessage, elementsof(szMessage) );
2818 if ( hwndParent )
2819 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
2820 else
2821 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
2824 return success;
2827 //***************************************************************************
2829 #ifdef __MINGW32__
2830 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR /*lpCmdLine*/, int )
2831 #else
2832 int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR /*lpCmdLine*/, int )
2833 #endif
2835 int exitcode = -1;
2836 int argc = __argc;
2838 #ifdef __MINGW32__
2839 char **argv = __argv;
2840 #else
2841 #ifdef _UNICODE
2842 char **argv = new char *[argc + 1];
2844 for ( int argn = 0; argn < argc; argn++ )
2846 int nBytes = WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, NULL, 0, NULL, NULL );
2847 argv[argn] = new char[nBytes];
2848 WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, argv[argn], nBytes, NULL, NULL );
2850 argv[argc] = NULL;
2851 #else
2852 char **argv = __targv;
2853 #endif
2854 #endif
2856 osl_setCommandArgs( argc, argv );
2858 PEXCEPTION_POINTERS pExceptionPointers = NULL;
2859 DWORD dwProcessId = 0;
2860 DWORD dwThreadId = 0;
2862 WSADATA wsaData;
2863 WORD wVersionRequested;
2865 wVersionRequested = MAKEWORD(1, 1);
2866 WSAStartup(wVersionRequested, &wsaData);
2868 CrashReportParams Params;
2870 Params.ReadFromRegistry();
2871 Params.ReadFromEnvironment();
2873 if ( ReadBootstrapParams( Params ) &&
2874 ParseCommandArgs( &dwProcessId, &pExceptionPointers, &dwThreadId ) )
2876 bool bGotDumpFile;
2878 if ( g_bLoadReport )
2879 bGotDumpFile = FindDumpFile();
2880 else
2881 bGotDumpFile = WriteDumpFile( dwProcessId, pExceptionPointers, dwThreadId );
2883 if( bGotDumpFile )
2885 hash_map< string, string > aLibraries;
2887 if ( g_bLoadReport )
2889 g_fpStackFile = _open_reportfile( _T(".stk"), _T("rb") );
2890 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("rb") );
2892 else
2894 if ( g_bSendReport )
2896 g_fpStackFile = _tmpfile();
2897 g_fpChecksumFile = _tmpfile();
2899 else
2901 g_fpStackFile = _open_reportfile( _T(".stk"), _T("w+b") );
2902 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("w+b") );
2904 FILE *fpUnsent = _open_reportfile( _T(".lck"), _T("w+b") );
2905 if ( fpUnsent )
2907 fprintf( fpUnsent, "Unsent\r\n" );
2908 fclose( fpUnsent );
2912 WriteStackFile( g_fpStackFile, aLibraries, dwProcessId, pExceptionPointers );
2913 WriteChecksumFile( g_fpChecksumFile, aLibraries );
2914 WriteReportFile( &Params );
2916 FILE *fpPreview = _open_reportfile( _T(".prv"), _T("w+b") );
2918 if ( fpPreview )
2920 FILE *fp = fopen( g_szReportFileNameA, "rb" );
2921 if ( fp )
2923 fcopy( fp, fpPreview );
2924 fclose( fp );
2926 fclose( fpPreview );
2930 if ( g_bSendReport )
2932 InitCommonControls();
2934 // Actually this should never be true anymore
2935 if ( !g_bNoUserInterface && InitRichEdit() )
2938 INT_PTR result = DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_DIALOG_FRAME), NULL, DialogProc, (LPARAM)&Params );
2940 if ( result > 0 )
2942 exitcode = 0;
2944 DeinitRichEdit();
2946 else
2948 WriteCommentFile( Params.sComment.c_str() );
2949 WriteReportFile( &Params );
2950 if ( SendCrashReport( NULL, Params ) )
2951 exitcode = 0;
2955 if ( g_szReportFileNameA[0] )
2956 DeleteFileA( g_szReportFileNameA );
2958 if ( g_szCommentFileNameA[0] )
2959 DeleteFileA( g_szCommentFileNameA );
2961 else
2963 if ( g_szReportFileNameA[0] )
2964 DeleteFileA( g_szReportFileNameA );
2965 exitcode = 0;
2968 if ( g_szDumpFileNameA[0] && g_bSendReport )
2969 DeleteFileA( g_szDumpFileNameA );
2971 if ( g_fpStackFile )
2972 fclose( g_fpStackFile );
2974 if ( g_fpChecksumFile )
2975 fclose( g_fpChecksumFile );
2980 return exitcode;