update dev300-m58
[ooovba.git] / crashrep / source / win32 / soreport.cpp
blob9cd7e180bf4a479ad563a9c7ad944c89418e7922
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: soreport.cpp,v $
10 * $Revision: 1.24 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #define UNICODE
32 #define WIN32_LEAN_AND_MEAN
33 #if defined _MSC_VER
34 #pragma warning(push, 1)
35 #pragma warning(disable:4917)
36 #endif
37 #include <windows.h>
38 #include <windowsx.h>
40 #include <mapi.h>
41 #include <commctrl.h>
42 #include <commdlg.h>
43 #include <psapi.h>
45 #include <shellapi.h>
46 #include <shlobj.h>
48 #define _UNICODE
49 #include <tchar.h>
51 #define _RICHEDIT_VER 0x0200
52 #include <richedit.h>
54 #if defined _MSC_VER
55 #pragma warning(pop)
56 #endif
58 #if _RICHEDIT_VER >= 0x0200
59 #define RICHEDIT TEXT("riched20.dll")
60 #else
61 #define RICHEDIT TEXT("riched32.dll")
62 #endif
64 #include <systools/win32/uwinapi.h>
65 #include <rtl/digest.h>
66 #include <rtl/bootstrap.hxx>
67 #include <osl/file.hxx>
68 #include <osl/process.h>
70 #include <stdlib.h>
71 #include <stdio.h>
72 #include <io.h>
73 #include <fcntl.h>
74 #include <string>
75 #include <hash_map>
76 #include <winsock.h>
77 #include <malloc.h>
78 #include <process.h>
80 #include <_version.h>
82 #include "resource.h"
83 #include "base64.h"
85 #define FORMATBUFSIZE (8*1024)
86 #define MAX_TEXT_BUFFER (32*1024-1)
87 #define MAX_HOSTNAME (1024)
89 #ifdef __MINGW32__
90 #include <imagehlp.h>
91 #else
92 #include <dbghelp.h>
93 #endif
95 #ifdef _UNICODE
96 #define tstring wstring
97 #else
98 #define tstring string
99 #endif
101 using namespace ::std;
104 wstring g_wstrProductKey;
105 string g_strDefaultLanguage;
106 FILE *g_fpStackFile = NULL;
107 FILE *g_fpChecksumFile = NULL;
108 DWORD g_dwExceptionCode = 0;
110 CHAR g_szReportServerA[MAX_HOSTNAME] = "";
111 USHORT g_uReportPort = 80;
113 TCHAR g_szBuildId[256] = TEXT("");
115 TCHAR g_szDumpFileName[MAX_PATH] = TEXT("");
117 CHAR g_szDumpFileNameA[MAX_PATH] = "";
118 CHAR g_szCommentFileNameA[MAX_PATH] = "";
119 CHAR g_szReportFileNameA[MAX_PATH] = "";
122 bool g_bNoUserInterface = false;
123 bool g_bSendReport = false;
124 bool g_bLoadReport = false;
126 #define REPORT_SERVER g_szReportServerA
127 #define REPORT_PORT g_uReportPort
130 //***************************************************************************
131 // tmpfile from msvcrt creates the temporary file in the root of the current
132 // volume and can fail.
134 static FILE *_xfopen( const _TCHAR *file, const _TCHAR *mode )
136 #ifdef UNICODE
137 if ( (LONG)GetVersion() < 0 )
139 char afile[MAX_PATH];
140 char amode[16];
142 WideCharToMultiByte( CP_ACP, 0, file, -1, afile, MAX_PATH, NULL, NULL );
143 WideCharToMultiByte( CP_ACP, 0, mode, -1, amode, 16, NULL, NULL );
146 return fopen( afile, amode );
148 else
149 #endif
150 return _tfopen( file, mode );
154 static FILE *_tmpfile(void)
156 FILE *fp = NULL;
158 TCHAR szTempPath[MAX_PATH];
160 if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
162 TCHAR szFileName[MAX_PATH];
164 if ( GetTempFileName( szTempPath, TEXT("CRT"), 0, szFileName ) )
166 HANDLE hFile = CreateFile(
167 szFileName,
168 GENERIC_READ | GENERIC_WRITE,
169 0, NULL,
170 OPEN_EXISTING,
171 FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_NORMAL,
172 NULL );
174 if ( IsValidHandle( hFile ) )
176 int fd = _open_osfhandle( (int)hFile, 0 );
178 fp = _fdopen( fd, "w+b" );
183 return fp;
185 //***************************************************************************
187 static BOOL GetCrashDataPath( LPTSTR szBuffer )
189 ::rtl::OUString ustrValue = ::rtl::OUString::createFromAscii("${$BRAND_BASE_DIR/program/bootstrap.ini:UserInstallation}");
190 ::rtl::Bootstrap::expandMacros( ustrValue );
192 if ( ustrValue.getLength() )
194 ustrValue += ::rtl::OUString::createFromAscii("/user/crashdata");
196 ::osl::FileBase::RC result = ::osl::Directory::createPath( ustrValue );
198 if ( ::osl::FileBase::E_None == result || ::osl::FileBase::E_EXIST == result )
200 ::rtl::OUString ustrPath;
202 result = ::osl::FileBase::getSystemPathFromFileURL( ustrValue, ustrPath );
203 if ( ::osl::FileBase::E_None == result )
205 _tcsncpy( szBuffer, reinterpret_cast<LPCWSTR>(ustrPath.getStr()), MAX_PATH );
206 return TRUE;
211 return FALSE;
215 static FILE *_open_reportfile( LPCTSTR lpExt, LPCTSTR lpMode )
217 FILE *fp = NULL;
218 TCHAR szAppDataPath[MAX_PATH] = _T("");
220 if ( GetCrashDataPath( szAppDataPath ) )
222 _tcscat( szAppDataPath, _T("\\crashdat") );
223 _tcscat( szAppDataPath, lpExt );
225 fp = _xfopen( szAppDataPath, lpMode );
228 return fp;
231 //***************************************************************************
233 struct CrashReportParams
235 BOOL fAllowContact;
236 tstring sEmail;
237 tstring sTitle;
238 tstring sComment;
239 ULONG uInternetConnection;
240 tstring sProxyServer;
241 tstring sProxyPort;
243 CrashReportParams();
245 void WriteToRegistry();
246 void ReadFromRegistry();
247 void ReadFromEnvironment();
250 bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams );
251 BOOL WriteCommentFile( LPCTSTR lpComment );
253 //***************************************************************************
255 LONG RegReadValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPVOID lpData, DWORD cbData )
257 HKEY hKey = NULL;
258 LONG lResult;
260 lResult = RegOpenKeyEx( hBaseKey, lpSubKey, 0, KEY_QUERY_VALUE, &hKey );
262 if ( ERROR_SUCCESS == lResult )
264 lResult = RegQueryValueEx( hKey, lpValueName, NULL, NULL, (LPBYTE)lpData, &cbData );
265 RegCloseKey( hKey );
268 return lResult;
271 //***************************************************************************
273 LONG RegWriteValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData )
275 HKEY hKey = NULL;
276 LONG lResult;
278 lResult = RegCreateKeyEx( hBaseKey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL );
280 if ( ERROR_SUCCESS == lResult )
282 lResult = RegSetValueEx( hKey, lpValueName, NULL, dwType, (CONST BYTE *)lpData, cbData );
283 RegCloseKey( hKey );
286 return lResult;
289 //***************************************************************************
291 CrashReportParams::CrashReportParams()
293 fAllowContact = FALSE;
294 sTitle = TEXT("");
295 sComment = TEXT("");
296 sEmail = TEXT("");
297 uInternetConnection = 0;
298 sProxyServer = TEXT("");
299 sProxyPort = TEXT("");
302 //***************************************************************************
304 void CrashReportParams::ReadFromRegistry()
306 TCHAR szBuffer[2048];
308 if ( ERROR_SUCCESS == RegReadValue(
309 HKEY_CURRENT_USER,
310 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
311 TEXT("HTTPProxyServer"),
312 szBuffer,
313 sizeof(szBuffer) ) )
314 sProxyServer = szBuffer;
316 DWORD dwProxyPort;
318 if ( ERROR_SUCCESS == RegReadValue(
319 HKEY_CURRENT_USER,
320 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
321 TEXT("HTTPProxyPort"),
322 &dwProxyPort,
323 sizeof(dwProxyPort) ) )
325 _stprintf( szBuffer, TEXT("%d"), dwProxyPort );
326 sProxyPort = szBuffer;
329 if ( ERROR_SUCCESS == RegReadValue(
330 HKEY_CURRENT_USER,
331 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
332 TEXT("ReturnAddress"),
333 szBuffer,
334 sizeof(szBuffer) ) )
335 sEmail = szBuffer;
337 RegReadValue(
338 HKEY_CURRENT_USER,
339 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
340 TEXT("AllowContact"),
341 &fAllowContact,
342 sizeof(fAllowContact) );
344 RegReadValue(
345 HKEY_CURRENT_USER,
346 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
347 TEXT("HTTPConnection"),
348 &uInternetConnection,
349 sizeof(uInternetConnection) );
352 //***************************************************************************
354 void CrashReportParams::WriteToRegistry()
356 RegWriteValue(
357 HKEY_CURRENT_USER,
358 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
359 TEXT("HTTPProxyServer"), REG_SZ,
360 sProxyServer.c_str(),
361 sizeof(TCHAR) * (sProxyServer.length() + 1) );
363 LPTSTR endptr = NULL;
364 DWORD dwProxyPort = _tcstoul( sProxyPort.c_str(), &endptr, 10 );
366 RegWriteValue(
367 HKEY_CURRENT_USER,
368 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
369 TEXT("HTTPProxyPort"), REG_DWORD,
370 &dwProxyPort,
371 sizeof(DWORD) );
373 RegWriteValue(
374 HKEY_CURRENT_USER,
375 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
376 TEXT("AllowContact"), REG_DWORD,
377 &fAllowContact,
378 sizeof(DWORD) );
381 RegWriteValue(
382 HKEY_CURRENT_USER,
383 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
384 TEXT("HTTPConnection"), REG_DWORD,
385 &uInternetConnection,
386 sizeof(DWORD) );
388 RegWriteValue(
389 HKEY_CURRENT_USER,
390 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
391 TEXT("ReturnAddress"), REG_SZ,
392 sEmail.c_str(),
393 sizeof(TCHAR) * (sEmail.length() + 1) );
396 //***************************************************************************
398 void CrashReportParams::ReadFromEnvironment()
400 TCHAR szBuffer[2048];
402 DWORD dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYSERVER"), szBuffer, elementsof(szBuffer) );
404 if ( dwResult && dwResult < elementsof(szBuffer) )
405 sProxyServer = szBuffer;
407 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYPORT"), szBuffer, elementsof(szBuffer) );
409 if ( dwResult && dwResult < elementsof(szBuffer) )
410 sProxyPort = szBuffer;
412 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_RETURNADDRESS"), szBuffer, elementsof(szBuffer) );
414 if ( dwResult && dwResult < elementsof(szBuffer) )
416 sEmail = szBuffer;
417 // fAllowContact = TRUE;
420 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPCONNECTIONTYPE"), szBuffer, elementsof(szBuffer) );
422 if ( dwResult && dwResult < elementsof(szBuffer) )
424 if ( 0 == _tcsicmp( szBuffer, _T("DIRECT") ) )
425 uInternetConnection = 1;
426 else if ( 0 == _tcsicmp( szBuffer, _T("MANUALPROXY") ) )
427 uInternetConnection = 2;
428 else if ( 0 == _tcsicmp( szBuffer, _T("SYSTEMDEFAULT") ) )
429 uInternetConnection = 0;
432 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_SUBJECT"), szBuffer, elementsof(szBuffer) );
434 if ( dwResult && dwResult < elementsof(szBuffer) )
435 sTitle = szBuffer;
438 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_BODYFILE"), szBuffer, elementsof(szBuffer) );
440 if ( dwResult && dwResult < elementsof(szBuffer) )
442 FILE *fp = _xfopen( szBuffer, _T("rb") );
444 if ( fp )
446 CHAR aUTF8Buffer[256];
447 size_t nBytesRead;
449 sComment = TEXT("");
451 while ( 0 != (nBytesRead = fread( aUTF8Buffer, sizeof(aUTF8Buffer[0]), elementsof(aUTF8Buffer), fp )) )
453 TCHAR aBuffer[256+1];
455 DWORD dwCharacters = MultiByteToWideChar( CP_UTF8, 0, aUTF8Buffer, nBytesRead, aBuffer, elementsof(aBuffer) - 1 );
456 aBuffer[dwCharacters] = 0;
457 sComment += aBuffer;
460 fclose( fp );
465 //***************************************************************************
467 typedef BOOL (WINAPI *MiniDumpWriteDump_PROC)(
468 IN HANDLE hProcess,
469 IN DWORD ProcessId,
470 IN HANDLE hFile,
471 IN MINIDUMP_TYPE DumpType,
472 IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
473 IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
474 IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
477 //***************************************************************************
479 static BOOL WINAPI InitRichEdit()
481 return (NULL != LoadLibrary( RICHEDIT ));
484 //***************************************************************************
486 static BOOL WINAPI DeinitRichEdit()
488 return FreeLibrary( GetModuleHandle( RICHEDIT ) );
491 //***************************************************************************
493 static string trim_string( const string& rString )
495 string temp = rString;
497 while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' )
498 temp.erase( 0, 1 );
500 string::size_type len = temp.length();
502 while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' )
504 temp.erase( len - 1, 1 );
505 len = temp.length();
508 return temp;
511 //***************************************************************************
513 static int LoadAndFormatString( HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax )
515 TCHAR szBuffer[FORMATBUFSIZE];
516 TCHAR szBuffer2[FORMATBUFSIZE];
518 LoadString( hInstance, uID, szBuffer, elementsof(szBuffer) );
520 LPCTSTR src;
521 LPTSTR dest;
522 for ( dest = szBuffer2, src = szBuffer; *src; src++, dest++ )
524 switch ( *src )
526 case '~':
527 *dest = '&';
528 break;
529 case '\\':
530 switch ( *(++src) )
532 case 'n':
533 *dest = '\n';
534 break;
535 case 'r':
536 *dest = '\r';
537 break;
538 default:
539 *dest = *src;
540 break;
542 break;
543 default:
544 *dest = *src;
545 break;
549 *dest = *src;
551 return ExpandEnvironmentStrings( szBuffer2, lpBuffer, nBufferMax );
555 //***************************************************************************
557 static string wstring2utf8( const wstring &rString )
559 int nBufSize = WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, NULL, 0, NULL, FALSE );
561 LPSTR pBuffer = (LPSTR)alloca( nBufSize );
563 WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, pBuffer, nBufSize, NULL, FALSE );
565 return string( pBuffer );
568 //***************************************************************************
570 static string xml_encode( const string &rString )
572 string temp = rString;
573 string::size_type pos = 0;
575 // First replace all occurences of '&' because it may occur in further
576 // encoded chardters too
578 for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 )
579 temp.replace( pos, 1, "&amp;" );
581 for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 )
582 temp.replace( pos, 1, "&lt;" );
584 for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 )
585 temp.replace( pos, 1, "&gt;" );
587 return temp;
590 //***************************************************************************
592 static size_t fcopy( FILE *fpin, FILE *fpout )
594 char buffer[1024];
595 size_t nBytes;
596 size_t nBytesWritten = 0;
598 if ( fpin && fpout )
600 while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) )
602 nBytesWritten += fwrite( buffer, 1, nBytes, fpout );
606 return nBytesWritten;
609 //***************************************************************************
611 static string GetModuleDirectory( HMODULE hModule )
613 TCHAR szModuleName[MAX_PATH] = TEXT("");
614 TCHAR szDrive[_MAX_DRIVE];
615 TCHAR szDir[_MAX_DIR];
616 TCHAR szFName[_MAX_FNAME];
617 TCHAR szExt[_MAX_EXT];
619 if ( GetModuleFileName( hModule, szModuleName, MAX_PATH ) )
621 _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
622 _tmakepath( szModuleName, szDrive, szDir, _T(""), _T("") );
625 CHAR szModuleNameUTF8[MAX_PATH] = "";
627 WideCharToMultiByte( CP_UTF8, 0, szModuleName, -1, szModuleNameUTF8, elementsof(szModuleNameUTF8), NULL, NULL );
628 return string( szModuleNameUTF8 );
631 //***************************************************************************
633 string GetFileDirectory( const string& rFilePath )
635 string aDir = rFilePath;
636 size_t pos = aDir.rfind( '\\' );
638 if ( string::npos != pos )
639 aDir.erase( pos + 1 );
640 else
641 aDir = "";
643 return aDir;
646 //***************************************************************************
648 string GetFileName( const string& rFilePath )
650 string aName = rFilePath;
651 size_t pos = aName.rfind( '\\' );
653 if ( string::npos != pos )
654 return aName.substr( pos + 1 );
655 else
656 return aName;
659 //***************************************************************************
661 BOOL WriteReportFile( CrashReportParams *pParams )
663 BOOL fSuccess = FALSE;
664 TCHAR szTempPath[MAX_PATH];
666 if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
668 TCHAR szFileName[MAX_PATH];
670 if ( GetTempFileName( szTempPath, TEXT("RPM"), 0, szFileName ) )
672 HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
674 if ( hFile )
676 int fd = _open_osfhandle( (LONG)hFile, _O_TEXT );
677 FILE *fp = _fdopen( fd, "w+t" );
678 CHAR szTitle[1024] = "";
679 CHAR szBuildId[1024] = "";
680 CHAR szEmail[1024] = "";
681 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
683 WideCharToMultiByte( CP_UTF8, 0, pParams->sTitle.c_str(), -1, szTitle, sizeof(szTitle), NULL, NULL );
684 WideCharToMultiByte( CP_UTF8, 0, g_szBuildId, -1, szBuildId, sizeof(szBuildId), NULL, NULL );
685 WideCharToMultiByte( CP_UTF8, 0, pParams->sEmail.c_str(), -1, szEmail, sizeof(szEmail), NULL, NULL );
687 fprintf( fp,
688 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
689 "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
690 "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
691 "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n",
692 pszUserType ? pszUserType : "",
693 pParams->fAllowContact ? "true" : "false",
694 pParams->fAllowContact ? xml_encode(szEmail).c_str() : ""
697 fprintf( fp,
698 "<reportmail:title>%s</reportmail:title>\n",
699 xml_encode(szTitle).c_str() );
701 fprintf( fp,
702 "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain;charset=UTF-8\" class=\"UserComment\"/>\n"
703 "<reportmail:attachment name=\"user.dmp\" media-type=\"application/octet-stream\" class=\"UserDump\"/>\n"
704 "</reportmail:mail>\n"
706 "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" procpath=\"%s\" exceptiontype=\"0x%08X\" product=\"%s\"/>\n",
707 szBuildId,
708 _INPATH,
709 xml_encode(g_strDefaultLanguage).c_str(),
710 xml_encode(GetModuleDirectory( NULL )).c_str(),
711 g_dwExceptionCode,
712 xml_encode(wstring2utf8(g_wstrProductKey)).c_str()
715 OSVERSIONINFO VersionInfo;
717 ZeroMemory( &VersionInfo, sizeof(VersionInfo) );
718 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo );
720 GetVersionEx( &VersionInfo );
722 fprintf( fp,
723 "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
724 "<systeminfo:System name=\"%s\" version=\"%d.%d\" build=\"%d\" locale=\"0x%08x\"/>\n"
726 VER_PLATFORM_WIN32_NT == VersionInfo.dwPlatformId ? "Windows NT" : "Windows",
727 VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion,
728 VersionInfo.dwBuildNumber,
729 GetUserDefaultLangID()
732 fprintf( fp, "<systeminfo:CPU type=\"x86\"/>\n" );
733 fprintf( fp, "</systeminfo:systeminfo>\n" );
735 fseek( g_fpStackFile, 0, SEEK_SET );
736 fcopy( g_fpStackFile, fp );
738 fseek( g_fpChecksumFile, 0, SEEK_SET );
739 fcopy( g_fpChecksumFile, fp );
741 fprintf( fp, "</errormail:errormail>\n" );
743 fclose( fp );
745 fSuccess = TRUE;
747 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szReportFileNameA, MAX_PATH, NULL, NULL );
750 if ( !fSuccess )
751 DeleteFile( szFileName );
755 return fSuccess;
758 //***************************************************************************
760 static BOOL SaveDumpFile( HWND hwndOwner )
762 OPENFILENAME ofn;
763 TCHAR szFileName[MAX_PATH] = TEXT("");
765 ZeroMemory( &ofn, sizeof(ofn) );
766 ofn.lStructSize = sizeof(ofn);
768 ofn.hwndOwner = hwndOwner;
769 ofn.lpstrFilter = TEXT("*.dmp\0*.dmp\0*.*\0*.*\0");
770 ofn.lpstrFile = szFileName;
771 ofn.nMaxFile = MAX_PATH;
772 ofn.Flags = OFN_ENABLESIZING | OFN_LONGNAMES | OFN_OVERWRITEPROMPT;
773 ofn.lpstrDefExt = TEXT("dmp");
775 if ( GetSaveFileName( &ofn ) )
777 return CopyFile( g_szDumpFileName, szFileName, FALSE );
781 return FALSE;
784 //***************************************************************************
786 static BOOL ScreenToClientRect( HWND hwnd, LPRECT lprc )
788 return ScreenToClient( hwnd, (LPPOINT)&lprc->left ) && ScreenToClient( hwnd, (LPPOINT)&lprc->right );
791 static BOOL SetWindowRect( HWND hwnd, const RECT *lprc, BOOL fRepaint )
793 return MoveWindow( hwnd, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, fRepaint );
796 #define GM_LOX 0x01
797 #define GM_HIX 0x02
798 #define GM_LOY 0x04
799 #define GM_HIY 0x08
801 static BOOL SetGrowMode( HWND hwnd, DWORD dwGrowMode )
803 return SetProp( hwnd, TEXT("GrowMode"), (HANDLE)dwGrowMode );
806 static DWORD GetGrowMode( HWND hwnd )
808 return (DWORD)GetProp( hwnd, TEXT("GrowMode") );
811 static BOOL GrowWindow( HWND hwnd, LONG dxClient, LONG dyClient, BOOL fRepaint )
813 DWORD dwGrowMode = GetGrowMode( hwnd );
814 RECT rc;
816 GetWindowRect( hwnd, &rc );
818 if ( dwGrowMode & GM_LOX )
819 rc.left += dxClient;
820 if ( dwGrowMode & GM_HIX )
821 rc.right += dxClient;
822 if ( dwGrowMode & GM_LOY )
823 rc.top += dyClient;
824 if ( dwGrowMode & GM_HIY )
825 rc.bottom += dyClient;
827 ScreenToClientRect( GetParent( hwnd ), &rc );
828 SetWindowRect( hwnd, &rc, fRepaint );
830 return TRUE;
833 BOOL CALLBACK GrowChildWindows(
834 HWND hwnd, // handle to child window
835 LPARAM lParam // application-defined value
838 LONG cx = (SHORT)LOWORD( lParam );
839 LONG cy = (SHORT)HIWORD( lParam );
841 GrowWindow( hwnd, cx, cy, TRUE );
843 return TRUE;
847 BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
849 HFONT aFont = *((HFONT*) lParam);
850 HDC hDC = GetDC( hwndChild );
851 SelectObject( hDC, aFont );
852 ReleaseDC( hwndChild, hDC );
853 return TRUE;
856 void ApplySystemFont( HWND hwndDlg )
858 NONCLIENTMETRICSA aNonClientMetrics;
859 aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
860 if ( SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
862 HFONT aSysFont = CreateFontIndirectA( &aNonClientMetrics.lfMessageFont );
863 EnumChildWindows(hwndDlg, EnumChildProc, (LPARAM) &aSysFont);
868 BOOL CALLBACK PreviewDialogProc(
869 HWND hwndDlg,
870 UINT uMsg,
871 WPARAM wParam,
872 LPARAM lParam
875 static RECT rcClient;
877 switch ( uMsg )
879 case WM_SIZE:
881 LONG cx = LOWORD( lParam );
882 LONG cy = HIWORD( lParam );
883 LONG dxClient, dyClient;
885 dxClient = cx - rcClient.right;
886 dyClient = cy - rcClient.bottom;
888 EnumChildWindows( hwndDlg, GrowChildWindows, MAKELONG( (SHORT)dxClient, (SHORT)dyClient) );
890 GetClientRect( hwndDlg, &rcClient );
892 break;
893 case WM_INITDIALOG:
895 GetClientRect( hwndDlg, &rcClient );
896 SetGrowMode( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GM_HIX | GM_HIY );
897 SetGrowMode( GetDlgItem(hwndDlg, IDOK), GM_LOX | GM_HIX | GM_LOY | GM_HIY );
899 CrashReportParams *pParams = (CrashReportParams *)lParam;
901 TCHAR szBuffer[256] = TEXT("");
902 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
903 HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
905 GetWindowText( hwndParent, szBuffer, elementsof(szBuffer) );
906 SetWindowText( hwndDlg, szBuffer );
908 LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) );
909 Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
911 basic_string<TCHAR> aString;
913 aString.append( pParams->sTitle );
914 aString.append( _T("\r\n\r\n") );
915 aString.append( pParams->sComment );
916 aString.append( _T("\r\n---------- report ----------\r\n") );
918 FILE *fp = fopen( g_szReportFileNameA, "r" );
920 if ( fp )
922 char buf[1024];
924 while ( fgets( buf, elementsof(buf), fp ) != NULL )
926 WCHAR bufW[1024];
928 MultiByteToWideChar( CP_UTF8, 0, buf, -1, bufW, elementsof(bufW) );
930 aString.append( bufW );
933 fclose( fp );
936 aString.append( _T("\r\n---------- stack ----------\r\n") );
938 fp = fopen( g_szDumpFileNameA, "rb" );
940 if ( fp )
942 unsigned char buf[16];
943 int count;
947 int i;
949 count = fread( buf, sizeof(buf[0]), sizeof(buf)/sizeof(buf[0]), fp );
951 for ( i = 0; i < count; i++ )
953 TCHAR output[16];
955 _sntprintf( output, elementsof(output), _T("%02X\x20"), buf[i] );
956 aString.append( output );
958 for ( ; i < elementsof(buf); i++ )
960 aString.append( _T("\x20\x20\x20") );
963 for ( i = 0; i < count; i++ )
965 TCHAR output[2];
967 if ( (int)buf[i] >= 0x20 && (int)buf[i] <= 0x7F )
968 output[0] = (TCHAR)buf[i];
969 else
970 output[0] = '.';
971 output[1] = 0;
972 aString.append( output );
975 aString.append( _T("\r\n") );
977 } while ( count );
979 fclose( fp );
982 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), aString.c_str() );
985 SetWindowFont( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GetStockObject( SYSTEM_FIXED_FONT ), TRUE );
987 return TRUE;
988 case WM_COMMAND:
989 switch ( LOWORD(wParam) )
991 case IDOK:
992 case IDCANCEL:
993 EndDialog( hwndDlg, wParam );
994 return TRUE;
996 break;
997 default:
998 break;
1001 return FALSE;
1003 //***************************************************************************
1005 static void PreviewReport( HWND hwndParent, CrashReportParams *pParams )
1007 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE );
1009 WriteReportFile( pParams );
1011 DialogBoxParam(
1012 hInstance,
1013 MAKEINTRESOURCE(IDD_PREVIEW_FRAME),
1014 hwndParent,
1015 PreviewDialogProc,
1016 (LPARAM)pParams
1019 DeleteFileA( g_szReportFileNameA );
1021 //***************************************************************************
1022 void UpdateOptionsDialogControls( HWND hwndDlg )
1024 if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED )
1026 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), TRUE );
1027 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), TRUE );
1029 else
1031 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), FALSE );
1032 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), FALSE );
1036 //***************************************************************************
1038 BOOL CALLBACK OptionsDialogProc(
1039 HWND hwndDlg,
1040 UINT uMsg,
1041 WPARAM wParam,
1042 LPARAM lParam
1045 static CrashReportParams *pParams;
1047 switch ( uMsg )
1049 case WM_INITDIALOG:
1051 TCHAR szBuffer[1024] = TEXT("");
1052 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
1053 //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
1055 pParams = (CrashReportParams *)lParam;
1057 LoadAndFormatString( hInstance, IDS_OPTIONS_CAPTION, szBuffer, elementsof(szBuffer) );
1058 SetWindowText( hwndDlg, szBuffer );
1060 LoadAndFormatString( hInstance, IDS_PROXY_SETTINGS_HEADER, szBuffer, elementsof(szBuffer) );
1061 Static_SetText( GetDlgItem(hwndDlg, IDC_PROXY_SETTINGS), szBuffer );
1063 LoadAndFormatString( hInstance, IDS_PROXY_SYSTEM, szBuffer, elementsof(szBuffer) );
1064 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM), szBuffer );
1066 LoadAndFormatString( hInstance, IDS_PROXY_DIRECT, szBuffer, elementsof(szBuffer) );
1067 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT), szBuffer );
1069 LoadAndFormatString( hInstance, IDS_PROXY_MANUAL, szBuffer, elementsof(szBuffer) );
1070 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL), szBuffer );
1072 LoadAndFormatString( hInstance, IDS_LABEL_PROXYSERVER, szBuffer, elementsof(szBuffer) );
1073 Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYSERVER), szBuffer );
1075 LoadAndFormatString( hInstance, IDS_LABEL_PROXYPORT, szBuffer, elementsof(szBuffer) );
1076 Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYPORT), szBuffer );
1078 LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) );
1079 Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
1081 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
1082 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
1084 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), pParams->sProxyServer.c_str() );
1085 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), pParams->sProxyPort.c_str() );
1087 Button_SetCheck( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM + pParams->uInternetConnection), BST_CHECKED );
1089 SendMessage(
1090 GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION),
1091 EM_SETBKGNDCOLOR,
1092 (WPARAM)FALSE,
1093 GetSysColor( COLOR_3DFACE ) );
1094 LoadAndFormatString( hInstance, IDS_PROXY_DESCRIPTION, szBuffer, elementsof(szBuffer) );
1095 Edit_SetText( GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), szBuffer );
1097 UpdateOptionsDialogControls( hwndDlg );
1099 return TRUE;
1100 case WM_COMMAND:
1101 switch ( LOWORD(wParam) )
1103 case IDC_RADIO_SYSTEM:
1104 case IDC_RADIO_DIRECT:
1105 case IDC_RADIO_MANUAL:
1106 if ( BN_CLICKED == HIWORD(wParam) )
1107 UpdateOptionsDialogControls( hwndDlg );
1108 break;
1109 case IDOK:
1111 TCHAR szBuffer[1024];
1113 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), szBuffer, elementsof(szBuffer) );
1114 pParams->sProxyServer = szBuffer;
1116 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), szBuffer, elementsof(szBuffer) );
1117 pParams->sProxyPort = szBuffer;
1119 if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT) ) & BST_CHECKED )
1120 pParams->uInternetConnection = 1;
1121 else if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED )
1122 pParams->uInternetConnection = 2;
1123 else
1124 pParams->uInternetConnection = 0;
1126 case IDCANCEL:
1127 EndDialog( hwndDlg, wParam );
1128 return TRUE;
1130 break;
1131 default:
1132 break;
1135 return FALSE;
1138 //***************************************************************************
1140 static void OptionsDialog( HWND hwndParent, CrashReportParams *pParams )
1142 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE );
1144 if ( IDOK == DialogBoxParam(
1145 hInstance,
1146 MAKEINTRESOURCE(IDD_OPTIONS_FRAME),
1147 hwndParent,
1148 OptionsDialogProc,
1149 (LPARAM)pParams
1151 pParams->WriteToRegistry();
1154 //***************************************************************************
1156 void UpdateReportDialogControls( HWND hwndDlg )
1158 EnableWindow(
1159 GetDlgItem(hwndDlg, IDC_EDIT_EMAIL),
1160 Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE );
1161 EnableWindow(
1162 GetDlgItem(hwndDlg, IDC_LABEL_EMAIL),
1163 Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE );
1166 //***************************************************************************
1168 BOOL CALLBACK ReportDialogProc(
1169 HWND hwndDlg,
1170 UINT uMsg,
1171 WPARAM wParam,
1172 LPARAM
1175 switch ( uMsg )
1177 case WM_INITDIALOG:
1179 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1180 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1181 TCHAR szBuffer[FORMATBUFSIZE];
1183 LoadAndFormatString( hInstance, IDS_REPORT_INTRO, szBuffer, elementsof(szBuffer) );
1184 Static_SetText( GetDlgItem(hwndDlg, IDC_REPORT_INTRO), szBuffer );
1186 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT3), szBuffer );
1188 LoadAndFormatString( hInstance, IDS_ENTER_TITLE, szBuffer, elementsof(szBuffer) );
1189 Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_TITLE), szBuffer );
1191 LoadAndFormatString( hInstance, IDS_ENTER_DESCRIPTION, szBuffer, elementsof(szBuffer) );
1192 Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_DESCRIPTION), szBuffer );
1194 LoadAndFormatString( hInstance, IDS_SHOW_REPORT_BUTTON, szBuffer, elementsof(szBuffer) );
1195 Button_SetText( GetDlgItem(hwndDlg, IDC_SHOW_REPORT), szBuffer );
1197 LoadAndFormatString( hInstance, IDS_SAVE_REPORT_BUTTON, szBuffer, elementsof(szBuffer) );
1198 Button_SetText( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), szBuffer );
1200 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
1201 if ( pszUserType )
1202 ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_SHOW );
1203 else
1204 ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_HIDE );
1206 LoadAndFormatString( hInstance, IDS_OPTIONS_BUTTON, szBuffer, elementsof(szBuffer) );
1207 Button_SetText( GetDlgItem(hwndDlg, IDC_OPTIONS), szBuffer );
1209 LoadAndFormatString( hInstance, IDS_ALLOW_CONTACT, szBuffer, elementsof(szBuffer) );
1210 Button_SetText( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), szBuffer );
1211 Button_SetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), pParams->fAllowContact ? BST_CHECKED : BST_UNCHECKED );
1213 LoadAndFormatString( hInstance, IDS_LABEL_EMAIL, szBuffer, elementsof(szBuffer) );
1214 Button_SetText( GetDlgItem(hwndDlg, IDC_LABEL_EMAIL), szBuffer );
1216 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), pParams->sEmail.c_str() );
1218 UpdateReportDialogControls( hwndDlg );
1220 return TRUE;
1221 case WM_SHOWWINDOW:
1222 if ( (BOOL)wParam )
1224 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1225 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1226 TCHAR szBuffer[FORMATBUFSIZE];
1228 LoadAndFormatString( hInstance, IDS_REPORT_CAPTION, szBuffer, elementsof(szBuffer) );
1229 SetWindowText( GetParent(hwndDlg), szBuffer );
1231 LoadAndFormatString( hInstance, IDS_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
1232 SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
1234 LoadAndFormatString( hInstance, IDS_DONOT_SEND_BUTTON, szBuffer, elementsof(szBuffer) );
1235 Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer );
1238 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), TRUE );
1239 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), TRUE );
1240 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), FALSE );
1242 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), pParams->sTitle.c_str() );
1243 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), pParams->sComment.c_str() );
1246 SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE,
1247 GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE) | BS_DEFPUSHBUTTON );
1248 SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE,
1249 GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE) &~ BS_DEFPUSHBUTTON );
1251 SetFocus( GetDlgItem(hwndDlg,IDC_EDIT_TITLE) );
1253 break;
1254 case WM_COMMAND:
1255 switch ( LOWORD(wParam) )
1257 case IDC_SHOW_REPORT:
1259 TCHAR szBuffer[32767];
1261 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1263 pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT) ) ? TRUE : FALSE;
1265 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), szBuffer, elementsof(szBuffer) );
1266 pParams->sTitle = szBuffer;
1268 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), szBuffer, elementsof(szBuffer) );
1269 pParams->sComment = szBuffer;
1271 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), szBuffer, elementsof(szBuffer) );
1272 pParams->sEmail = szBuffer;
1274 PreviewReport( GetParent(hwndDlg), pParams );
1276 return TRUE;
1277 case IDC_SAVE_REPORT:
1278 SaveDumpFile( GetParent(hwndDlg) );
1279 return TRUE;
1280 case IDC_OPTIONS:
1282 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1283 OptionsDialog( GetParent(hwndDlg), pParams );
1285 return TRUE;
1286 case IDC_ALLOW_CONTACT:
1287 if ( BN_CLICKED == HIWORD(wParam) )
1288 UpdateReportDialogControls( hwndDlg );
1289 return TRUE;
1291 break;
1292 default:
1293 break;
1296 return FALSE;
1298 //***************************************************************************
1300 BOOL CALLBACK WelcomeDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
1302 switch ( uMsg )
1304 case WM_INITDIALOG:
1306 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1307 HWND hwndRichEdit = GetDlgItem(hwndDlg, IDC_RICHEDIT21);
1308 TCHAR szBuffer[FORMATBUFSIZE];
1309 TCHAR szBuffer2[FORMATBUFSIZE];
1310 TCHAR szURL[256];
1311 TCHAR szCaption[256];
1313 SendMessage(
1314 hwndRichEdit,
1315 EM_SETBKGNDCOLOR,
1316 (WPARAM)FALSE,
1317 GetSysColor( COLOR_3DFACE ) );
1319 SendMessage( hwndRichEdit, EM_SETEVENTMASK, 0, ENM_LINK );
1320 SendMessage( hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0 );
1322 LoadAndFormatString( hInstance, IDS_WELCOME_BODY1, szBuffer, elementsof(szBuffer) );
1323 LoadAndFormatString( hInstance, IDS_WELCOME_BODY2, szBuffer2, elementsof(szBuffer2) );
1324 _tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) );
1325 LoadAndFormatString( hInstance, IDS_WELCOME_BODY3, szBuffer2, elementsof(szBuffer2) );
1326 _tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) );
1327 LoadString( hInstance, IDS_PRIVACY_URL, szURL, elementsof(szURL) );
1328 _tcsncat( szBuffer, szURL, elementsof(szBuffer) );
1329 SetWindowText( hwndRichEdit, szBuffer );
1331 LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szCaption, elementsof(szCaption) );
1332 SetWindowText( GetParent(hwndDlg), szCaption );
1335 return TRUE;
1336 case WM_SHOWWINDOW:
1337 if ( (BOOL)wParam )
1339 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1340 TCHAR szBuffer[FORMATBUFSIZE];
1342 LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szBuffer, elementsof(szBuffer) );
1343 SetWindowText( GetParent(hwndDlg), szBuffer );
1345 LoadAndFormatString( hInstance, IDS_WELCOME_HEADER, szBuffer, elementsof(szBuffer) );
1346 SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
1348 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
1349 Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer );
1351 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), FALSE );
1352 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), FALSE );
1353 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), TRUE );
1355 SetFocus( GetDlgItem(GetParent(hwndDlg),IDNEXT) );
1357 break;
1358 case WM_NOTIFY:
1360 LPNMHDR pnmh = (LPNMHDR)lParam;
1362 if ( pnmh->idFrom == IDC_RICHEDIT21 && pnmh->code == EN_LINK )
1364 ENLINK *plink = (ENLINK*)lParam;
1366 if ( plink->msg == WM_LBUTTONUP )
1368 TCHAR szBuffer[256];
1369 TEXTRANGE range;
1371 range.chrg = plink->chrg;
1372 range.lpstrText = szBuffer;
1374 SendMessage( pnmh->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&range );
1376 ShellExecute( hwndDlg, NULL, szBuffer, NULL, NULL, SW_SHOWDEFAULT );
1381 break;
1382 default:
1383 break;
1386 return FALSE;
1388 //***************************************************************************
1390 BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
1392 static HWND hwndPages[2] = { NULL };
1393 static int iActualPage = 0;
1395 switch ( uMsg )
1397 case WM_INITDIALOG:
1399 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1400 TCHAR szBuffer[FORMATBUFSIZE];
1402 SetWindowLong( hwndDlg, GWL_USERDATA, (LONG)lParam );
1403 hwndPages[0] = CreateDialog(
1404 hInstance,
1405 MAKEINTRESOURCE(IDD_WELCOME_PAGE),
1406 hwndDlg,
1407 WelcomeDialogProc );
1409 hwndPages[1] = CreateDialog(
1410 hInstance,
1411 MAKEINTRESOURCE(IDD_REPORT_PAGE),
1412 hwndDlg,
1413 ReportDialogProc );
1415 CHARFORMAT chfmt;
1417 chfmt.cbSize = sizeof(chfmt);
1418 chfmt.dwMask = CFM_BOLD;
1419 chfmt.dwEffects = CFE_BOLD;
1421 SendMessage(
1422 GetDlgItem(hwndDlg, IDC_HEADER),
1423 EM_SETCHARFORMAT,
1424 SCF_ALL,
1425 (LPARAM)&chfmt );
1427 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
1428 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
1430 LoadAndFormatString( hInstance, IDS_NEXT_BUTTON, szBuffer, elementsof(szBuffer) );
1431 Button_SetText( GetDlgItem(hwndDlg, IDNEXT), szBuffer );
1433 LoadAndFormatString( hInstance, IDS_SEND_BUTTON, szBuffer, elementsof(szBuffer) );
1434 Button_SetText( GetDlgItem(hwndDlg, IDFINISH), szBuffer );
1436 LoadAndFormatString( hInstance, IDS_BACK_BUTTON, szBuffer, elementsof(szBuffer) );
1437 Button_SetText( GetDlgItem(hwndDlg, IDBACK), szBuffer );
1439 ShowWindow( hwndPages[1], SW_HIDE );
1440 ShowWindow( hwndPages[0], SW_SHOW );
1442 // Let Crash Reporter window stay on top of all other windows
1443 SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
1445 return FALSE;
1446 case WM_CTLCOLORSTATIC:
1447 return (BOOL)CreateSolidBrush(GetSysColor(COLOR_WINDOW));
1448 case WM_COMMAND:
1449 switch ( LOWORD(wParam) )
1451 case IDBACK:
1452 if ( iActualPage > 0 )
1454 ShowWindow( hwndPages[iActualPage], SW_HIDE );
1455 ShowWindow( hwndPages[--iActualPage], SW_SHOW );
1457 return TRUE;
1458 case IDNEXT:
1459 if ( iActualPage < elementsof(hwndPages) - 1 )
1461 ShowWindow( hwndPages[iActualPage], SW_HIDE );
1462 ShowWindow( hwndPages[++iActualPage], SW_SHOW );
1464 return TRUE;
1465 case IDFINISH:
1467 TCHAR szBuffer[32767];
1468 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( hwndDlg, GWL_USERDATA );
1470 pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndPages[1], IDC_ALLOW_CONTACT) ) ? TRUE : FALSE;
1472 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_TITLE), szBuffer, elementsof(szBuffer) );
1473 pParams->sTitle = szBuffer;
1475 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_DESCRIPTION), szBuffer, elementsof(szBuffer) );
1476 pParams->sComment = szBuffer;
1478 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_EMAIL), szBuffer, elementsof(szBuffer) );
1479 pParams->sEmail = szBuffer;
1481 if ( pParams->fAllowContact && !pParams->sEmail.length() )
1483 TCHAR szMessage[MAX_TEXT_BUFFER];
1485 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_NOEMAILADDRESS, szMessage, elementsof(szMessage) );
1487 MessageBox( hwndDlg, szMessage, NULL, MB_ICONERROR | MB_OK );
1488 break; // Don't end the dialog
1490 else
1492 pParams->WriteToRegistry();
1494 WriteCommentFile( pParams->sComment.c_str() );
1495 WriteReportFile( pParams );
1497 if ( !SendCrashReport( hwndDlg, *pParams ) )
1498 break; // Don't end the dialog
1501 // Fallthrough !!!
1502 case IDCANCEL:
1503 EndDialog( hwndDlg, wParam );
1504 return TRUE;
1506 break;
1507 default:
1508 break;
1511 return FALSE;
1516 //*****************************************************************************
1517 //* Generate MD5 checksum
1518 //*****************************************************************************
1520 #define MAGIC_DESCRIPTION_FILLER 'x'
1521 #define MAGIC_DESCRIPTION_COUNT 80
1523 static void repatch_soffice_exe( void *pBuffer, size_t nBufSize )
1525 wchar_t DescriptionBuffer[MAGIC_DESCRIPTION_COUNT];
1527 memset( DescriptionBuffer, 0, sizeof(DescriptionBuffer) );
1528 wcsncpy( DescriptionBuffer, g_wstrProductKey.c_str(), elementsof(DescriptionBuffer) - 1 );
1530 bool bPatched = false;
1534 void *pFound = memchr( pBuffer, ((char *)DescriptionBuffer)[0], nBufSize );
1536 if ( pFound )
1538 size_t distance = (char *)pFound - (char *)pBuffer;
1540 if ( nBufSize >= distance )
1542 nBufSize -= distance;
1544 if ( nBufSize >= sizeof(DescriptionBuffer) &&
1545 0 == memcmp( pFound, DescriptionBuffer, sizeof(DescriptionBuffer) ) )
1547 for ( int i = 0; i < 80; i++ )
1549 ((wchar_t *)pFound)[i] = MAGIC_DESCRIPTION_FILLER;
1551 bPatched = true;
1553 else
1555 pBuffer = (void *)(((char *)pFound) + 1);
1556 nBufSize--;
1559 else
1560 nBufSize = 0;
1562 else
1563 nBufSize = 0;
1564 } while ( !bPatched && nBufSize );
1567 // Normalize executable/library images to prevent different MD5 checksums due
1568 // to a different PE header date/checksum (this doesn't affect the code/data
1569 // sections of a executable/library. Please see tools/source/bootstrp/md5.cxx
1570 // where the same method is also used. The tool so_checksum creates the MD5
1571 // checksums during build time. You have to make sure that both methods use the
1572 // same algorithm otherwise there could be problems with stack reports.
1573 static void normalize_pe_image(sal_uInt8* buffer, size_t nBufferSize)
1575 const int OFFSET_PE_OFFSET = 0x3c;
1576 const int OFFSET_COFF_TIMEDATESTAMP = 4;
1577 const int PE_SIGNATURE_SIZE = 4;
1578 const int COFFHEADER_SIZE = 20;
1579 const int OFFSET_PE_OPTIONALHEADER_CHECKSUM = 64;
1581 // Check the header part of the file buffer
1582 if (buffer[0] == 'M' && buffer[1] == 'Z')
1584 unsigned long PEHeaderOffset = (long)buffer[OFFSET_PE_OFFSET];
1585 if (PEHeaderOffset < nBufferSize-4)
1587 if ( buffer[PEHeaderOffset] == 'P' &&
1588 buffer[PEHeaderOffset+1] == 'E' &&
1589 buffer[PEHeaderOffset+2] == 0 &&
1590 buffer[PEHeaderOffset+3] == 0 )
1592 PEHeaderOffset += PE_SIGNATURE_SIZE;
1593 if (PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP < nBufferSize-4)
1595 // Set timedatestamp and checksum fields to a normalized
1596 // value to enforce the same MD5 checksum for identical
1597 // Windows executables/libraries.
1598 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP] = 0;
1599 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+1] = 0;
1600 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+2] = 0;
1601 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+3] = 0;
1604 if (PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM < nBufferSize-4)
1606 // Set checksum to a normalized value
1607 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM] = 0;
1608 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+1] = 0;
1609 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+2] = 0;
1610 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+3] = 0;
1617 static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
1619 const int MINIMAL_FILESIZE = 512;
1621 sal_uInt32 nBytesProcessed = 0;
1623 FILE *fp = fopen( filename, "rb" );
1625 if ( fp )
1627 long nFileSize;
1629 if ( 0 == fseek( fp, 0, SEEK_END ) && -1 != (nFileSize = ftell(fp)) )
1631 rewind( fp );
1633 sal_uInt8 *pBuffer = new sal_uInt8[nFileSize];
1634 size_t nBytesRead = fread( pBuffer, 1, nFileSize, fp );
1636 if ( sal::static_int_cast<long>(nBytesRead) == nFileSize )
1638 if ( 0 == stricmp( GetFileName(filename).c_str(), "soffice.bin" ) )
1639 repatch_soffice_exe( pBuffer, nBytesRead );
1640 else if ( nFileSize > MINIMAL_FILESIZE )
1641 normalize_pe_image( pBuffer, nBytesRead );
1643 rtlDigestError error = rtl_digest_MD5 (
1644 pBuffer, nBytesRead,
1645 pChecksum, nChecksumLen );
1647 if ( rtl_Digest_E_None == error )
1648 nBytesProcessed = nBytesRead;
1651 delete[] pBuffer;
1654 fclose( fp );
1658 return nBytesProcessed;
1661 #if 0
1662 static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
1664 sal_uInt32 nBytesProcessed = 0;
1666 FILE *fp = fopen( filename, "rb" );
1668 if ( fp )
1670 rtlDigest digest = rtl_digest_createMD5();
1672 if ( digest )
1674 size_t nBytesRead;
1675 sal_uInt8 buffer[4096];
1676 rtlDigestError error = rtl_Digest_E_None;
1678 while ( rtl_Digest_E_None == error &&
1679 0 != (nBytesRead = fread( buffer, 1, sizeof(buffer), fp )) )
1681 error = rtl_digest_updateMD5( digest, buffer, nBytesRead );
1682 nBytesProcessed += nBytesRead;
1685 if ( rtl_Digest_E_None == error )
1687 error = rtl_digest_getMD5( digest, pChecksum, nChecksumLen );
1690 if ( rtl_Digest_E_None != error )
1691 nBytesProcessed = 0;
1693 rtl_digest_destroyMD5( digest );
1696 fclose( fp );
1699 return nBytesProcessed;
1702 #endif
1703 //***************************************************************************
1705 static bool WriteStackFile( FILE *fout, hash_map< string, string >& rLibraries, DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers )
1707 bool fSuccess = false;
1709 if ( fout && dwProcessId && pExceptionPointers )
1711 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
1713 if ( IsValidHandle(hProcess) )
1715 EXCEPTION_POINTERS aExceptionPointers;
1716 CONTEXT aContextRecord;
1718 ReadProcessMemory(
1719 hProcess,
1720 pExceptionPointers,
1721 &aExceptionPointers,
1722 sizeof(aExceptionPointers),
1723 NULL );
1725 ReadProcessMemory(
1726 hProcess,
1727 aExceptionPointers.ContextRecord,
1728 &aContextRecord,
1729 sizeof(aContextRecord),
1730 NULL );
1732 STACKFRAME frame;
1734 ZeroMemory( &frame, sizeof(frame) );
1735 frame.AddrPC.Offset = aContextRecord.Eip;
1736 frame.AddrPC.Mode = AddrModeFlat;
1737 frame.AddrFrame.Offset = aContextRecord.Ebp;
1738 frame.AddrFrame.Mode = AddrModeFlat;
1740 BOOL bSuccess;
1741 int frameNum = 0;
1743 SymInitialize( hProcess, NULL, TRUE );
1745 fprintf( fout, "<errormail:Stack type=\"Win32\">\n" );
1749 fSuccess = true;
1751 bSuccess = StackWalk( IMAGE_FILE_MACHINE_I386,
1752 hProcess,
1753 NULL,
1754 &frame,
1755 &aContextRecord,
1756 (PREAD_PROCESS_MEMORY_ROUTINE)ReadProcessMemory,
1757 SymFunctionTableAccess,
1758 SymGetModuleBase,
1759 NULL );
1761 if ( bSuccess )
1763 // Note: ImageHelp ANSI functions do not have an A postfix while
1764 // Unicode versions have a W postfix. There's no macro
1765 // that depends on define UNICODE
1767 IMAGEHLP_MODULE moduleInfo;
1769 ZeroMemory( &moduleInfo, sizeof(moduleInfo) );
1770 moduleInfo.SizeOfStruct = sizeof(moduleInfo);
1772 if ( SymGetModuleInfo( hProcess, frame.AddrPC.Offset, &moduleInfo ) )
1774 rLibraries[ GetFileName( moduleInfo.LoadedImageName ).c_str() ] = moduleInfo.LoadedImageName;
1776 DWORD dwRelOffset = 0;
1777 BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 256 ];
1778 PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
1780 ZeroMemory( symbolBuffer, sizeof(symbolBuffer) );
1781 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
1782 pSymbol->MaxNameLength = 256;
1784 if ( SymGetSymFromAddr( hProcess, frame.AddrPC.Offset, &dwRelOffset, pSymbol ) )
1785 fprintf( fout, "<errormail:StackInfo " \
1786 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" ordinal=\"%s+0x%p\" name=\"%s\" path=\"%s\"/>\n",
1787 frameNum,
1788 frame.AddrPC.Offset,
1789 frame.AddrPC.Offset - moduleInfo.BaseOfImage,
1790 xml_encode(pSymbol->Name).c_str(),
1791 frame.AddrPC.Offset - pSymbol->Address,
1792 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
1793 xml_encode( GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
1795 else
1796 fprintf( fout, "<errormail:StackInfo " \
1797 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" name=\"%s\" path=\"%s\"/>\n",
1798 frameNum,
1799 frame.AddrPC.Offset,
1800 frame.AddrPC.Offset - moduleInfo.BaseOfImage,
1801 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
1802 xml_encode(GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
1805 else
1806 fprintf( fout, "<errormail:StackInfo pos=\"%d\" ip=\"0x%p\"/>\n",
1807 frameNum,
1808 frame.AddrPC.Offset
1811 frameNum++;
1814 } while ( bSuccess );
1816 fprintf( fout, "</errormail:Stack>\n" );
1818 SymCleanup( hProcess );
1820 CloseHandle( hProcess );
1825 return fSuccess;
1828 bool WriteChecksumFile( FILE *fchksum, const hash_map< string, string >& rLibraries )
1830 bool success = false;
1832 if ( fchksum && rLibraries.size() )
1834 fprintf( fchksum, "<errormail:Checksums type=\"MD5\">\n" );
1836 hash_map< string, string >::const_iterator iter;
1838 for ( iter = rLibraries.begin();
1839 iter != rLibraries.end();
1840 iter++ )
1842 sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5];
1843 sal_uInt32 nBytesProcessed = calc_md5_checksum(
1844 iter->second.c_str(),
1845 checksum, sizeof(checksum) );
1847 if ( nBytesProcessed )
1849 fprintf( fchksum, "<errormail:Checksum sum=\"0x" );
1850 for ( int i = 0; i < sizeof(checksum); fprintf( fchksum, "%02X", checksum[i++] ) );
1851 fprintf( fchksum, "\" bytes=\"%d\" file=\"%s\"/>\n",
1852 nBytesProcessed,
1853 GetFileName( iter->first ) );
1857 fprintf( fchksum, "</errormail:Checksums>\n" );
1859 success = true;
1862 return success;
1865 //***************************************************************************
1867 BOOL FindDumpFile()
1869 TCHAR szFileName[MAX_PATH];
1871 if ( GetCrashDataPath( szFileName ) )
1873 _tcscat( szFileName, _T("\\crashdat.dmp") );
1875 HANDLE hFile = CreateFile(
1876 szFileName,
1877 GENERIC_READ,
1878 0, NULL,
1879 OPEN_EXISTING,
1880 FILE_ATTRIBUTE_NORMAL, NULL );
1882 if ( hFile )
1884 CloseHandle( hFile );
1886 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
1887 _tcscpy( g_szDumpFileName, szFileName );
1889 return TRUE;
1893 return FALSE;
1896 BOOL WriteDumpFile( DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers, DWORD dwThreadId )
1898 BOOL fSuccess = FALSE;
1899 PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam = NULL;
1900 MINIDUMP_EXCEPTION_INFORMATION ExceptionParam;
1902 HMODULE hDbgHelp = LoadLibrary( _T("DBGHELP.DLL" ) );
1903 MiniDumpWriteDump_PROC pMiniDumpWriteDump = NULL;
1905 if ( hDbgHelp )
1907 pMiniDumpWriteDump = (MiniDumpWriteDump_PROC)GetProcAddress( hDbgHelp, "MiniDumpWriteDump" );
1909 if ( !pMiniDumpWriteDump )
1911 FreeLibrary( hDbgHelp );
1912 return false;
1916 if ( !pMiniDumpWriteDump )
1917 return false;
1919 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
1921 if ( IsValidHandle(hProcess) )
1923 TCHAR szTempPath[MAX_PATH];
1925 // if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
1926 if ( GetCrashDataPath( szTempPath ) )
1928 TCHAR szFileName[MAX_PATH];
1930 // if ( GetTempFileName( szTempPath, TEXT("DMP"), 0, szFileName ) )
1931 _tcscpy( szFileName, szTempPath );
1932 _tcscat( szFileName, _T("\\crashdat.dmp") );
1934 HANDLE hFile = CreateFile(
1935 szFileName,
1936 GENERIC_READ | GENERIC_WRITE,
1937 0, NULL,
1938 // OPEN_EXISTING,
1939 CREATE_ALWAYS,
1940 FILE_ATTRIBUTE_NORMAL, NULL );
1942 if ( hFile )
1944 if ( pExceptionPointers && dwThreadId )
1946 ExceptionParam.ThreadId = dwThreadId;
1947 ExceptionParam.ExceptionPointers = pExceptionPointers;
1948 ExceptionParam.ClientPointers = TRUE;
1950 EXCEPTION_POINTERS aExceptionPointers;
1951 EXCEPTION_RECORD aExceptionRecord;
1953 ReadProcessMemory(
1954 hProcess,
1955 pExceptionPointers,
1956 &aExceptionPointers,
1957 sizeof(aExceptionPointers),
1958 NULL );
1961 ReadProcessMemory(
1962 hProcess,
1963 aExceptionPointers.ExceptionRecord,
1964 &aExceptionRecord,
1965 sizeof(aExceptionRecord),
1966 NULL );
1968 g_dwExceptionCode = aExceptionRecord.ExceptionCode;
1970 lpExceptionParam = &ExceptionParam;
1973 fSuccess = pMiniDumpWriteDump( hProcess, dwProcessId, hFile, MiniDumpNormal, lpExceptionParam, NULL, NULL );
1975 CloseHandle( hFile );
1977 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
1978 _tcscpy( g_szDumpFileName, szFileName );
1981 if ( !fSuccess )
1982 DeleteFile( szFileName );
1986 CloseHandle( hProcess );
1989 FreeLibrary( hDbgHelp );
1991 return fSuccess;
1994 //***************************************************************************
1996 static DWORD FindProcessForImage( LPCTSTR lpImagePath )
1998 DWORD dwProcessId = 0;
1999 DWORD aProcesses[1024];
2000 DWORD dwSize = 0;
2001 TCHAR szShortImagePath[MAX_PATH];
2003 if ( GetShortPathName( lpImagePath, szShortImagePath, elementsof(szShortImagePath) ) &&
2004 EnumProcesses( aProcesses, sizeof(aProcesses), &dwSize ) )
2006 unsigned nProcesses = dwSize / sizeof(aProcesses[0]);
2008 for ( unsigned i = 0; !dwProcessId && i < nProcesses; i++ )
2010 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] );
2012 if ( IsValidHandle(hProcess) )
2014 TCHAR szModulePath[MAX_PATH+1];
2016 if ( GetModuleFileNameEx( hProcess, NULL, szModulePath, MAX_PATH ) )
2018 TCHAR szShortModulePath[MAX_PATH];
2020 if ( GetShortPathName( szModulePath, szShortModulePath, elementsof(szShortModulePath) ) )
2022 if ( 0 == _tcsicmp( szShortModulePath, szShortImagePath ) )
2023 dwProcessId = aProcesses[i];
2027 CloseHandle( hProcess );
2032 return dwProcessId;
2034 //***************************************************************************
2036 static bool ParseCommandArgs( LPDWORD pdwProcessId, PEXCEPTION_POINTERS* ppException, LPDWORD pdwThreadId )
2038 int argc = __argc;
2039 #ifdef __MINGW32__
2040 #ifdef _UNICODE
2041 TCHAR **argv = reinterpret_cast<TCHAR **>(alloca((argc+1)*sizeof(WCHAR*)));
2042 int *sizes = reinterpret_cast<int *>(alloca(argc*sizeof(int)));
2043 int argsize=0;
2044 char **ptr;
2045 int i;
2046 ptr=__argv;
2047 for (i = 0; i < argc; ++i)
2049 sizes[i]=MultiByteToWideChar(CP_ACP, 0, *ptr, -1, NULL, 0);
2050 argsize+=sizes[i]+1;
2051 ++ptr;
2053 ++argsize;
2054 TCHAR *args = reinterpret_cast<TCHAR *>(alloca(argsize*sizeof(WCHAR)));
2055 ptr=__argv;
2056 TCHAR *cptr=args;
2057 for (i = 0; i < argc; ++i)
2059 argv[i]=cptr;
2060 MultiByteToWideChar( CP_ACP, 0, *ptr, -1, cptr, sizes[i] );
2061 ++ptr;
2062 cptr+=sizes[i];
2063 *cptr=0;
2064 ++cptr;
2066 argv[i]=cptr;
2067 *cptr=0;
2068 #else
2069 TCHAR **argv = __argv;
2070 #endif
2071 #else
2072 TCHAR **argv = __targv;
2073 #endif
2074 bool bSuccess = true;
2076 for ( int argn = 1; bSuccess && argn < argc; argn++ )
2078 if ( 0 == _tcsicmp( argv[argn], _T("-h") ) ||
2079 0 == _tcsicmp( argv[argn], _T("/h") ) ||
2080 0 == _tcsicmp( argv[argn], _T("-?") ) ||
2081 0 == _tcsicmp( argv[argn], _T("/?") ) ||
2082 0 == _tcsicmp( argv[argn], _T("/help") ) ||
2083 0 == _tcsicmp( argv[argn], _T("-help") ) ||
2084 0 == _tcsicmp( argv[argn], _T("--help") )
2087 HINSTANCE hInstance = GetModuleHandle(NULL);
2088 TCHAR szUsage[FORMATBUFSIZE];
2089 TCHAR szProcess[FORMATBUFSIZE];
2090 TCHAR szProcessDescription[FORMATBUFSIZE];
2091 TCHAR szHelpDescription[FORMATBUFSIZE];
2093 LoadAndFormatString( hInstance, IDS_MSG_CMDLINE_USAGE, szUsage, elementsof(szUsage) );
2094 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID, szProcess, elementsof(szProcess) );
2095 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID_DESCRIPTION, szProcessDescription, elementsof(szProcessDescription) );
2096 LoadAndFormatString( hInstance, IDS_MSG_PARAM_HELP_DESCRIPTION, szHelpDescription, elementsof(szHelpDescription) );
2098 _tprintf(
2099 TEXT("\n%s: crashrep %s\n\n")
2100 TEXT("/?, -h[elp] %s\n\n")
2101 TEXT("%-20s %s\n\n"),
2102 szUsage, szProcess, szHelpDescription, szProcess, szProcessDescription
2105 return true;
2107 else if ( 0 == _tcsicmp( argv[argn], _T("-p") ) ||
2108 0 == _tcsicmp( argv[argn], _T("/p") ) )
2110 if ( ++argn < argc )
2111 *pdwProcessId = _tcstoul( argv[argn], NULL, 0 );
2112 else
2113 bSuccess = false;
2115 else if ( 0 == _tcsicmp( argv[argn], _T("-excp") ) ||
2116 0 == _tcsicmp( argv[argn], _T("/excp") ) )
2118 if ( ++argn < argc )
2119 *ppException = (PEXCEPTION_POINTERS)_tcstoul( argv[argn], NULL, 0 );
2120 else
2121 bSuccess = false;
2123 else if ( 0 == _tcsicmp( argv[argn], _T("-t") ) ||
2124 0 == _tcsicmp( argv[argn], _T("/t") ) )
2126 if ( ++argn < argc )
2127 *pdwThreadId = _tcstoul( argv[argn], NULL, 0 );
2128 else
2129 bSuccess = false;
2131 else if ( 0 == _tcsicmp( argv[argn], _T("-noui") ) ||
2132 0 == _tcsicmp( argv[argn], _T("/noui") ) )
2134 g_bNoUserInterface = true;
2136 else if ( 0 == _tcsicmp( argv[argn], _T("-send") ) ||
2137 0 == _tcsicmp( argv[argn], _T("/send") ) )
2139 g_bSendReport = true;
2141 else if ( 0 == _tcsicmp( argv[argn], _T("-load") ) ||
2142 0 == _tcsicmp( argv[argn], _T("/load") ) )
2144 g_bLoadReport = true;
2146 else // treat parameter as image path
2148 TCHAR szImagePath[MAX_PATH];
2149 LPTSTR lpImageName;
2151 if ( GetFullPathName( argv[argn], MAX_PATH, szImagePath, &lpImageName ) )
2153 DWORD dwProcessId = FindProcessForImage( szImagePath );
2155 if ( dwProcessId )
2156 *pdwProcessId = dwProcessId;
2157 else
2158 bSuccess = false;
2163 if ( !*pdwProcessId && !g_bLoadReport )
2165 TCHAR szImagePath[MAX_PATH];
2166 LPTSTR lpImageName;
2168 if ( GetFullPathName( TEXT("soffice.exe"), MAX_PATH, szImagePath, &lpImageName ) )
2170 DWORD dwProcessId = FindProcessForImage( szImagePath );
2172 if ( dwProcessId )
2173 *pdwProcessId = dwProcessId;
2174 else
2175 bSuccess = false;
2179 return bSuccess;
2182 //***************************************************************************
2184 BOOL WriteCommentFile( LPCTSTR lpComment )
2186 BOOL fSuccess = FALSE;
2187 TCHAR szTempPath[MAX_PATH];
2189 if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
2191 TCHAR szFileName[MAX_PATH];
2193 if ( GetTempFileName( szTempPath, TEXT("CMT"), 0, szFileName ) )
2195 HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
2197 if ( hFile )
2199 DWORD dwBytesWritten;
2201 int needed = WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, NULL, 0, NULL, NULL );
2202 if ( needed )
2204 char *lpCommentUTF8 = (char *)alloca( needed );
2205 WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, lpCommentUTF8, needed, NULL, NULL );
2206 fSuccess = WriteFile( hFile, lpCommentUTF8, strlen(lpCommentUTF8), &dwBytesWritten, NULL );
2208 else
2209 fSuccess = TRUE;
2212 CloseHandle( hFile );
2214 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szCommentFileNameA, MAX_PATH, NULL, NULL );
2217 if ( !fSuccess )
2218 DeleteFile( szFileName );
2222 return fSuccess;
2225 //***************************************************************************
2227 static int _tsetenv( const _TCHAR *lpVar, const _TCHAR *lpValue )
2229 if ( !lpValue )
2230 lpValue = _T("");
2232 _TCHAR *envstr = (TCHAR *)alloca( (_tcslen( lpVar ) + _tcslen( lpValue ) + 2) * sizeof(_TCHAR) );
2234 _tcscpy( envstr, lpVar );
2235 _tcscat( envstr, _T("=") );
2236 _tcscat( envstr, lpValue );
2238 return _tputenv( envstr );
2241 static bool read_line( FILE *fp, string& rLine )
2243 char szBuffer[1024];
2244 bool bSuccess = false;
2245 bool bEOL = false;
2246 string line;
2249 while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) )
2251 int len = strlen(szBuffer);
2253 bSuccess = true;
2255 while ( len && szBuffer[len - 1] == '\n' )
2257 szBuffer[--len] = 0;
2258 bEOL = true;
2261 line.append( szBuffer );
2264 rLine = line;
2265 return bSuccess;
2268 static string get_script_string( const char *pFileName, const char *pKeyName )
2270 FILE *fp = fopen( pFileName, "rt" );
2271 string retValue;
2273 if ( fp )
2275 string line;
2276 string section;
2278 while ( read_line( fp, line ) )
2280 line = trim_string( line );
2283 string::size_type iEqualSign = line.find( '=', 0 );
2285 if ( iEqualSign != string::npos )
2287 string keyname = line.substr( 0, iEqualSign );
2288 keyname = trim_string( keyname );
2290 string value = line.substr( sal::static_int_cast<string::size_type>(iEqualSign + 1) );
2291 value = trim_string( value );
2293 if ( value.length() && '\"' == value[0] )
2295 value.erase( 0, 1 );
2297 string::size_type iQuotes = value.find( '"', 0 );
2299 if ( iQuotes != string::npos )
2300 value.erase( iQuotes );
2303 if ( 0 == stricmp( keyname.c_str(), pKeyName ) )
2305 retValue = value;
2306 break;
2311 fclose( fp );
2314 return retValue;
2317 static bool ReadBootstrapParams( CrashReportParams &rParams )
2319 TCHAR szBuffer[256] = TEXT("");
2320 TCHAR szModuleName[MAX_PATH];
2321 TCHAR szModuleVersionName[MAX_PATH];
2322 TCHAR szDrive[_MAX_DRIVE];
2323 TCHAR szDir[_MAX_DIR];
2324 TCHAR szFName[_MAX_FNAME];
2325 TCHAR szExt[_MAX_EXT];
2326 TCHAR szReportServer[MAX_HOSTNAME];
2327 TCHAR szReportPort[256];
2328 bool bSuccess = false;
2330 GetModuleFileName( NULL, szModuleName, MAX_PATH );
2331 _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
2332 _tmakepath( szModuleName, szDrive, szDir, _T("bootstrap"), _T(".ini") );
2333 _tmakepath( szModuleVersionName, szDrive, szDir, _T("version"), _T(".ini") );
2335 if (
2336 GetPrivateProfileString(
2337 TEXT("Bootstrap"),
2338 TEXT("ProductKey"),
2339 TEXT("OpenOffice.org"),
2340 szBuffer,
2341 elementsof(szBuffer),
2342 szModuleName )
2345 TCHAR *pVersion = _tcschr( szBuffer, ' ' );
2347 g_wstrProductKey = szBuffer;
2349 if ( pVersion )
2351 *pVersion = 0;
2352 pVersion++;
2354 else
2355 pVersion = TEXT("");
2357 if ( !_tgetenv( _T("PRODUCTNAME") ) )
2359 _tsetenv( TEXT("PRODUCTNAME"), szBuffer );
2361 if ( !_tgetenv( _T("PRODUCTVERSION") ) )
2362 _tsetenv( TEXT("PRODUCTVERSION"), pVersion );
2365 GetPrivateProfileString(
2366 TEXT("Version"),
2367 TEXT("buildid"),
2368 TEXT("unknown"),
2369 g_szBuildId, elementsof(g_szBuildId),
2370 szModuleVersionName );
2372 g_strDefaultLanguage = get_script_string( "instdb.inf", "DefaultLanguage" );
2374 if ( GetPrivateProfileString(
2375 TEXT("ErrorReport"),
2376 TEXT("ErrorReportPort"),
2377 TEXT("80"),
2378 szReportPort, elementsof(szReportPort),
2379 szModuleName
2382 TCHAR *endptr = NULL;
2384 unsigned short uReportPort = (unsigned short)_tcstoul( szReportPort, &endptr, 10 );
2385 if ( uReportPort )
2386 g_uReportPort = uReportPort;
2389 if ( GetPrivateProfileString(
2390 TEXT("ErrorReport"),
2391 TEXT("ErrorReportServer"),
2392 TEXT(""),
2393 szReportServer, elementsof(szReportServer),
2394 szModuleName
2397 bSuccess = 0 != WideCharToMultiByte( CP_ACP, 0, szReportServer, -1, g_szReportServerA, elementsof(g_szReportServerA), NULL, NULL );
2400 LPCTSTR lpEnvString;
2402 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYSERVER") )) )
2403 rParams.sProxyServer = lpEnvString;
2405 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYPORT") )) )
2406 rParams.sProxyPort = lpEnvString;
2408 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_SENDERADDRESS") )) )
2409 rParams.sEmail = lpEnvString;
2411 return bSuccess;
2414 //***************************************************************************
2416 bool SendHTTPRequest(
2417 FILE *fp,
2418 const char *pszServer,
2419 unsigned short uPort = 80,
2420 const char *pszProxyServer = NULL,
2421 unsigned short uProxyPort = 8080 )
2423 bool success = false;
2425 struct hostent *hp;
2427 if ( pszProxyServer )
2428 hp = gethostbyname( pszProxyServer );
2429 else
2430 hp = gethostbyname( pszServer );
2432 if ( hp )
2434 SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
2436 if ( s )
2438 struct sockaddr_in address;
2440 memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr));
2441 address.sin_family = AF_INET;
2443 if ( pszProxyServer )
2444 address.sin_port = ntohs( uProxyPort );
2445 else
2446 address.sin_port = ntohs( uPort );
2448 if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) )
2450 fseek( fp, 0, SEEK_END );
2451 size_t length = ftell( fp );
2452 fseek( fp, 0, SEEK_SET );
2454 char buffer[2048];
2456 if ( pszProxyServer )
2457 sprintf( buffer,
2458 "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
2459 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2460 "Content-Length: %d\r\n"
2461 "SOAPAction: \"\"\r\n\r\n",
2462 pszServer,
2463 uPort,
2464 length
2466 else
2467 sprintf( buffer,
2468 "POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
2469 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2470 "Content-Length: %d\r\n"
2471 "SOAPAction: \"\"\r\n\r\n",
2472 length
2475 if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
2477 size_t nBytes;
2481 nBytes = fread( buffer, 1, sizeof(buffer), fp );
2483 if ( nBytes )
2484 success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
2485 } while( nBytes && success );
2487 if ( success )
2489 memset( buffer, 0, sizeof(buffer) );
2490 success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 );
2491 if ( success )
2493 char szHTTPSignature[sizeof(buffer)] = "";
2494 unsigned uHTTPReturnCode = 0;
2496 sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode );
2497 success = uHTTPReturnCode == 200;
2504 closesocket( s );
2508 return success;
2511 //***************************************************************************
2513 static void WriteSOAPRequest( FILE *fp )
2515 fprintf( fp,
2516 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
2517 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
2518 "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
2519 "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
2520 "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
2521 "xmlns:rds=\"urn:ReportDataService\"\n"
2522 "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
2523 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
2524 "<SOAP-ENV:Body>\n"
2527 fprintf( fp, "<rds:submitReport>\n" );
2528 fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
2529 fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
2531 FILE *fpin = fopen( g_szReportFileNameA, "r" );
2532 if ( fpin )
2534 fprintf( fp,
2535 "<item>\n"
2536 "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
2537 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2538 fcopy( fpin, fp );
2539 fprintf( fp, "]]></value></item>\n" );
2540 fclose( fpin );
2543 fpin = fopen( g_szCommentFileNameA, "r" );
2544 if ( fpin )
2546 fprintf( fp,
2547 "<item>\n"
2548 "<key xsi:type=\"xsd:string\">description.txt</key>\n"
2549 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2550 fcopy( fpin, fp );
2551 fprintf( fp, "]]></value></item>\n" );
2552 fclose( fpin );
2556 fpin = fopen( g_szDumpFileNameA, "rb" );
2557 if ( fpin )
2559 FILE *fptemp = _tmpfile();
2561 if ( fptemp )
2563 if ( base64_encode( fpin, fptemp ) )
2565 fseek( fptemp, 0, SEEK_SET );
2566 fprintf( fp,
2567 "<item>\n"
2568 "<key xsi:type=\"xsd:string\">user.dmp</key>\n"
2569 "<value xsi:type=\"xsd:string\">" );
2570 fcopy( fptemp, fp );
2571 fprintf( fp, "</value></item>\n" );
2573 fclose( fptemp );
2575 fclose( fpin );
2578 fprintf( fp,
2579 "</hash>\n"
2580 "</rds:submitReport>\n"
2581 "</SOAP-ENV:Body>\n"
2582 "</SOAP-ENV:Envelope>\n"
2586 //***************************************************************************
2588 struct RequestParams
2590 bool success;
2591 FILE *fpin;
2592 const char *lpServer;
2593 unsigned short uPort;
2594 const char *lpProxyServer;
2595 unsigned short uProxyPort;
2596 HWND hwndStatus;
2599 void _cdecl SendingThread( void *lpArgs )
2601 RequestParams *pParams = (RequestParams *)lpArgs;
2603 pParams->success = SendHTTPRequest( pParams->fpin, pParams->lpServer, pParams->uPort, pParams->lpProxyServer, pParams->uProxyPort );
2605 PostMessage( pParams->hwndStatus, WM_COMMAND, IDOK, 0 );
2608 //***************************************************************************
2610 BOOL CALLBACK SendingStatusDialogProc(
2611 HWND hwndDlg,
2612 UINT uMsg,
2613 WPARAM wParam,
2614 LPARAM lParam
2617 static RequestParams *pRequest = NULL;
2618 static HANDLE hSendingThread = NULL;
2620 switch ( uMsg )
2622 case WM_INITDIALOG:
2624 TCHAR szBuffer[1024] = TEXT("");
2625 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
2626 //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
2628 pRequest = (RequestParams *)lParam;
2630 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
2631 SetWindowText( hwndDlg, szBuffer );
2633 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_STATUS, szBuffer, elementsof(szBuffer) );
2634 Static_SetText( GetDlgItem(hwndDlg, IDC_SENDING_REPORT_STATUS), szBuffer );
2636 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
2637 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
2639 pRequest->hwndStatus = hwndDlg;
2641 hSendingThread = (HANDLE)_beginthread( SendingThread, 0, pRequest );
2643 return TRUE;
2644 case WM_COMMAND:
2645 switch ( LOWORD(wParam) )
2647 case IDCANCEL:
2648 TerminateThread( hSendingThread, 0 );
2649 case IDOK:
2650 WaitForSingleObject( hSendingThread, INFINITE );
2651 CloseHandle( hSendingThread );
2652 EndDialog( hwndDlg, wParam );
2653 return TRUE;
2655 break;
2656 default:
2657 break;
2660 return FALSE;
2663 //***************************************************************************
2665 bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams )
2667 bool success = false;
2668 char szProxyServer[1024] = "";
2669 unsigned short uProxyPort = 8080;
2670 TCHAR *endptr = NULL;
2672 switch ( rParams.uInternetConnection )
2674 case 2:
2676 WideCharToMultiByte(
2677 CP_ACP, 0, rParams.sProxyServer.c_str(), -1,
2678 szProxyServer, sizeof(szProxyServer), NULL, NULL );
2679 uProxyPort = (unsigned short)_tcstoul( rParams.sProxyPort.c_str(), &endptr, 10 );
2681 break;
2682 case 0:
2684 DWORD dwProxyEnable = 0;
2686 RegReadValue( HKEY_CURRENT_USER,
2687 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
2688 TEXT("ProxyEnable"),
2689 &dwProxyEnable,
2690 sizeof(dwProxyEnable) );
2692 if ( dwProxyEnable )
2694 TCHAR tszProxyServers[1024] = TEXT("");
2696 if ( ERROR_SUCCESS == RegReadValue( HKEY_CURRENT_USER,
2697 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), TEXT("ProxyServer"),
2698 tszProxyServers,
2699 sizeof(tszProxyServers) ) )
2701 TCHAR *lpHttpStart = _tcsstr( tszProxyServers, TEXT("http=") );
2703 if ( lpHttpStart )
2704 lpHttpStart += 5;
2705 else
2706 lpHttpStart = tszProxyServers;
2708 TCHAR *lpHttpEnd = _tcschr( lpHttpStart, ';' );
2710 if ( lpHttpEnd )
2711 *lpHttpEnd = 0;
2713 char szHTTPProxyServer[1024] = "";
2714 WideCharToMultiByte( CP_ACP, 0, lpHttpStart, -1, szHTTPProxyServer, sizeof(szHTTPProxyServer), NULL, NULL );
2716 char *lpColon = strchr( szHTTPProxyServer, ':' );
2718 if ( lpColon )
2720 char *endptr = NULL;
2722 *lpColon = 0;
2723 uProxyPort = (unsigned short)strtoul( lpColon + 1, &endptr, 10 );
2725 else
2726 uProxyPort = 8080;
2728 strcpy( szProxyServer, szHTTPProxyServer );
2733 break;
2734 default:
2735 case 1:
2736 break;
2739 FILE *fptemp = _tmpfile();
2740 if ( fptemp )
2742 RequestParams request;
2744 request.success = false;
2745 request.fpin = fptemp;
2746 request.lpServer = REPORT_SERVER;
2747 request.uPort = REPORT_PORT;
2748 request.lpProxyServer = szProxyServer[0] ? szProxyServer : NULL;
2749 request.uProxyPort = uProxyPort;
2750 request.hwndStatus = NULL;
2752 WriteSOAPRequest( fptemp );
2753 fseek( fptemp, 0, SEEK_SET );
2755 if ( hwndParent )
2757 int retid = DialogBoxParam(
2758 GetModuleHandle(NULL),
2759 MAKEINTRESOURCE(IDD_SENDING_STATUS),
2760 hwndParent,
2761 SendingStatusDialogProc,
2762 (LPARAM)&request
2765 success = request.success;
2767 if ( IDOK == retid )
2769 if ( !success )
2771 TCHAR szMessage[1024];
2773 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) );
2775 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
2777 else
2779 TCHAR szMessage[1024];
2780 TCHAR szTitle[1024];
2782 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) );
2783 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_HEADER, szTitle, elementsof(szTitle) );
2785 MessageBox( hwndParent, szMessage, szTitle, MB_ICONINFORMATION | MB_OK );
2790 else
2792 HANDLE hSendingThread = (HANDLE)_beginthread( SendingThread, 0, (void *)&request );
2794 WaitForSingleObject( hSendingThread, INFINITE );
2796 success = request.success;
2797 if ( !success )
2799 TCHAR szMessage[1024];
2801 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) );
2802 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
2804 else
2806 TCHAR szMessage[1024];
2808 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) );
2810 _ftprintf( stderr, _T("SUCCESS: %s\n"), szMessage );
2813 fclose( fptemp );
2815 else
2817 TCHAR szMessage[1024];
2819 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_DISK_FULL, szMessage, elementsof(szMessage) );
2821 if ( hwndParent )
2822 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
2823 else
2824 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
2827 return success;
2830 //***************************************************************************
2832 #ifdef __MINGW32__
2833 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR /*lpCmdLine*/, int )
2834 #else
2835 int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR /*lpCmdLine*/, int )
2836 #endif
2838 int exitcode = -1;
2839 int argc = __argc;
2841 #ifdef __MINGW32__
2842 char **argv = __argv;
2843 #else
2844 #ifdef _UNICODE
2845 char **argv = new char *[argc + 1];
2847 for ( int argn = 0; argn < argc; argn++ )
2849 int nBytes = WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, NULL, 0, NULL, NULL );
2850 argv[argn] = new char[nBytes];
2851 WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, argv[argn], nBytes, NULL, NULL );
2853 argv[argc] = NULL;
2854 #else
2855 char **argv = __targv;
2856 #endif
2857 #endif
2859 osl_setCommandArgs( argc, argv );
2861 PEXCEPTION_POINTERS pExceptionPointers = NULL;
2862 DWORD dwProcessId = 0;
2863 DWORD dwThreadId = 0;
2865 WSADATA wsaData;
2866 WORD wVersionRequested;
2868 wVersionRequested = MAKEWORD(1, 1);
2869 WSAStartup(wVersionRequested, &wsaData);
2871 CrashReportParams Params;
2873 Params.ReadFromRegistry();
2874 Params.ReadFromEnvironment();
2876 if ( ReadBootstrapParams( Params ) &&
2877 ParseCommandArgs( &dwProcessId, &pExceptionPointers, &dwThreadId ) )
2879 bool bGotDumpFile;
2881 if ( g_bLoadReport )
2882 bGotDumpFile = FindDumpFile();
2883 else
2884 bGotDumpFile = WriteDumpFile( dwProcessId, pExceptionPointers, dwThreadId );
2886 if( bGotDumpFile )
2888 hash_map< string, string > aLibraries;
2890 if ( g_bLoadReport )
2892 g_fpStackFile = _open_reportfile( _T(".stk"), _T("rb") );
2893 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("rb") );
2895 else
2897 if ( g_bSendReport )
2899 g_fpStackFile = _tmpfile();
2900 g_fpChecksumFile = _tmpfile();
2902 else
2904 g_fpStackFile = _open_reportfile( _T(".stk"), _T("w+b") );
2905 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("w+b") );
2907 FILE *fpUnsent = _open_reportfile( _T(".lck"), _T("w+b") );
2908 if ( fpUnsent )
2910 fprintf( fpUnsent, "Unsent\r\n" );
2911 fclose( fpUnsent );
2915 WriteStackFile( g_fpStackFile, aLibraries, dwProcessId, pExceptionPointers );
2916 WriteChecksumFile( g_fpChecksumFile, aLibraries );
2917 WriteReportFile( &Params );
2919 FILE *fpPreview = _open_reportfile( _T(".prv"), _T("w+b") );
2921 if ( fpPreview )
2923 FILE *fp = fopen( g_szReportFileNameA, "rb" );
2924 if ( fp )
2926 fcopy( fp, fpPreview );
2927 fclose( fp );
2929 fclose( fpPreview );
2933 if ( g_bSendReport )
2935 InitCommonControls();
2937 // Actually this should never be true anymore
2938 if ( !g_bNoUserInterface && InitRichEdit() )
2941 INT_PTR result = DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_DIALOG_FRAME), NULL, DialogProc, (LPARAM)&Params );
2943 if ( result > 0 )
2945 exitcode = 0;
2947 DeinitRichEdit();
2949 else
2951 WriteCommentFile( Params.sComment.c_str() );
2952 WriteReportFile( &Params );
2953 if ( SendCrashReport( NULL, Params ) )
2954 exitcode = 0;
2958 if ( g_szReportFileNameA[0] )
2959 DeleteFileA( g_szReportFileNameA );
2961 if ( g_szCommentFileNameA[0] )
2962 DeleteFileA( g_szCommentFileNameA );
2964 else
2966 if ( g_szReportFileNameA[0] )
2967 DeleteFileA( g_szReportFileNameA );
2968 exitcode = 0;
2971 if ( g_szDumpFileNameA[0] && g_bSendReport )
2972 DeleteFileA( g_szDumpFileNameA );
2974 if ( g_fpStackFile )
2975 fclose( g_fpStackFile );
2977 if ( g_fpChecksumFile )
2978 fclose( g_fpChecksumFile );
2983 return exitcode;