1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #define WIN32_LEAN_AND_MEAN
23 #pragma warning(push, 1)
24 #pragma warning(disable:4917)
40 #define _RICHEDIT_VER 0x0200
47 #if _RICHEDIT_VER >= 0x0200
48 #define RICHEDIT TEXT("riched20.dll")
50 #define RICHEDIT TEXT("riched32.dll")
53 #include <systools/win32/uwinapi.h>
54 #include <rtl/digest.h>
55 #include <rtl/bootstrap.hxx>
56 #include <osl/file.hxx>
57 #include <osl/process.h>
64 #include <boost/unordered_map.hpp>
72 #define FORMATBUFSIZE (8*1024)
73 #define MAX_TEXT_BUFFER (32*1024-1)
74 #define MAX_HOSTNAME (1024)
83 #define tstring wstring
85 #define tstring string
88 using namespace ::std
;
91 wstring g_wstrProductKey
;
92 string g_strDefaultLanguage
;
93 FILE *g_fpStackFile
= NULL
;
94 FILE *g_fpChecksumFile
= NULL
;
95 DWORD g_dwExceptionCode
= 0;
97 CHAR g_szReportServerA
[MAX_HOSTNAME
] = "";
98 USHORT g_uReportPort
= 80;
100 TCHAR g_szBuildId
[256] = TEXT("");
102 TCHAR g_szDumpFileName
[MAX_PATH
] = TEXT("");
104 CHAR g_szDumpFileNameA
[MAX_PATH
] = "";
105 CHAR g_szCommentFileNameA
[MAX_PATH
] = "";
106 CHAR g_szReportFileNameA
[MAX_PATH
] = "";
109 bool g_bNoUserInterface
= false;
110 bool g_bSendReport
= false;
111 bool g_bLoadReport
= false;
113 #define REPORT_SERVER g_szReportServerA
114 #define REPORT_PORT g_uReportPort
117 //***************************************************************************
118 // tmpfile from msvcrt creates the temporary file in the root of the current
119 // volume and can fail.
121 static FILE *_xfopen( const _TCHAR
*file
, const _TCHAR
*mode
)
123 return _tfopen( file
, mode
);
127 static FILE *_tmpfile(void)
131 TCHAR szTempPath
[MAX_PATH
];
133 if ( GetTempPath( SAL_N_ELEMENTS(szTempPath
), szTempPath
) )
135 TCHAR szFileName
[MAX_PATH
];
137 if ( GetTempFileName( szTempPath
, TEXT("CRT"), 0, szFileName
) )
139 HANDLE hFile
= CreateFile(
141 GENERIC_READ
| GENERIC_WRITE
,
144 FILE_FLAG_DELETE_ON_CLOSE
| FILE_ATTRIBUTE_NORMAL
,
147 if ( IsValidHandle( hFile
) )
149 int fd
= _open_osfhandle( (int)hFile
, 0 );
151 fp
= _fdopen( fd
, "w+b" );
158 //***************************************************************************
160 static BOOL
GetCrashDataPath( LPTSTR szBuffer
)
162 OUString
ustrValue("${$BRAND_BASE_DIR/program/bootstrap.ini:UserInstallation}");
163 ::rtl::Bootstrap::expandMacros( ustrValue
);
165 if ( !ustrValue
.isEmpty() )
167 ustrValue
+= OUString("/user/crashdata");
169 ::osl::FileBase::RC result
= ::osl::Directory::createPath( ustrValue
);
171 if ( ::osl::FileBase::E_None
== result
|| ::osl::FileBase::E_EXIST
== result
)
175 result
= ::osl::FileBase::getSystemPathFromFileURL( ustrValue
, ustrPath
);
176 if ( ::osl::FileBase::E_None
== result
)
178 _tcsncpy( szBuffer
, reinterpret_cast<LPCWSTR
>(ustrPath
.getStr()), MAX_PATH
);
188 static FILE *_open_reportfile( LPCTSTR lpExt
, LPCTSTR lpMode
)
191 TCHAR szAppDataPath
[MAX_PATH
] = _T("");
193 if ( GetCrashDataPath( szAppDataPath
) )
195 _tcscat( szAppDataPath
, _T("\\crashdat") );
196 _tcscat( szAppDataPath
, lpExt
);
198 fp
= _xfopen( szAppDataPath
, lpMode
);
204 //***************************************************************************
206 struct CrashReportParams
212 ULONG uInternetConnection
;
213 tstring sProxyServer
;
218 void WriteToRegistry();
219 void ReadFromRegistry();
220 void ReadFromEnvironment();
223 bool SendCrashReport( HWND hwndParent
, const CrashReportParams
&rParams
);
224 BOOL
WriteCommentFile( LPCTSTR lpComment
);
226 //***************************************************************************
228 LONG
RegReadValue( HKEY hBaseKey
, LPCTSTR lpSubKey
, LPCTSTR lpValueName
, LPVOID lpData
, DWORD cbData
)
233 lResult
= RegOpenKeyEx( hBaseKey
, lpSubKey
, 0, KEY_QUERY_VALUE
, &hKey
);
235 if ( ERROR_SUCCESS
== lResult
)
237 lResult
= RegQueryValueEx( hKey
, lpValueName
, NULL
, NULL
, (LPBYTE
)lpData
, &cbData
);
244 //***************************************************************************
246 LONG
RegWriteValue( HKEY hBaseKey
, LPCTSTR lpSubKey
, LPCTSTR lpValueName
, DWORD dwType
, LPCVOID lpData
, DWORD cbData
)
251 lResult
= RegCreateKeyEx( hBaseKey
, lpSubKey
, 0, NULL
, REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
, NULL
, &hKey
, NULL
);
253 if ( ERROR_SUCCESS
== lResult
)
255 lResult
= RegSetValueEx( hKey
, lpValueName
, NULL
, dwType
, (CONST BYTE
*)lpData
, cbData
);
262 //***************************************************************************
264 CrashReportParams::CrashReportParams()
266 fAllowContact
= FALSE
;
270 uInternetConnection
= 0;
271 sProxyServer
= TEXT("");
272 sProxyPort
= TEXT("");
275 //***************************************************************************
277 void CrashReportParams::ReadFromRegistry()
279 TCHAR szBuffer
[2048];
281 if ( ERROR_SUCCESS
== RegReadValue(
283 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
284 TEXT("HTTPProxyServer"),
287 sProxyServer
= szBuffer
;
291 if ( ERROR_SUCCESS
== RegReadValue(
293 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
294 TEXT("HTTPProxyPort"),
296 sizeof(dwProxyPort
) ) )
298 _stprintf( szBuffer
, TEXT("%d"), dwProxyPort
);
299 sProxyPort
= szBuffer
;
302 if ( ERROR_SUCCESS
== RegReadValue(
304 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
305 TEXT("ReturnAddress"),
312 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
313 TEXT("AllowContact"),
315 sizeof(fAllowContact
) );
319 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
320 TEXT("HTTPConnection"),
321 &uInternetConnection
,
322 sizeof(uInternetConnection
) );
325 //***************************************************************************
327 void CrashReportParams::WriteToRegistry()
331 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
332 TEXT("HTTPProxyServer"), REG_SZ
,
333 sProxyServer
.c_str(),
334 sizeof(TCHAR
) * (sProxyServer
.length() + 1) );
336 LPTSTR endptr
= NULL
;
337 DWORD dwProxyPort
= _tcstoul( sProxyPort
.c_str(), &endptr
, 10 );
341 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
342 TEXT("HTTPProxyPort"), REG_DWORD
,
348 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
349 TEXT("AllowContact"), REG_DWORD
,
356 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
357 TEXT("HTTPConnection"), REG_DWORD
,
358 &uInternetConnection
,
363 TEXT("SOFTWARE\\LibreOffice\\CrashReport"),
364 TEXT("ReturnAddress"), REG_SZ
,
366 sizeof(TCHAR
) * (sEmail
.length() + 1) );
369 //***************************************************************************
371 void CrashReportParams::ReadFromEnvironment()
373 TCHAR szBuffer
[2048];
375 DWORD dwResult
= GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYSERVER"), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
377 if ( dwResult
&& dwResult
< SAL_N_ELEMENTS(szBuffer
) )
378 sProxyServer
= szBuffer
;
380 dwResult
= GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYPORT"), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
382 if ( dwResult
&& dwResult
< SAL_N_ELEMENTS(szBuffer
) )
383 sProxyPort
= szBuffer
;
385 dwResult
= GetEnvironmentVariable( TEXT("ERRORREPORT_RETURNADDRESS"), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
387 if ( dwResult
&& dwResult
< SAL_N_ELEMENTS(szBuffer
) )
390 // fAllowContact = TRUE;
393 dwResult
= GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPCONNECTIONTYPE"), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
395 if ( dwResult
&& dwResult
< SAL_N_ELEMENTS(szBuffer
) )
397 if ( 0 == _tcsicmp( szBuffer
, _T("DIRECT") ) )
398 uInternetConnection
= 1;
399 else if ( 0 == _tcsicmp( szBuffer
, _T("MANUALPROXY") ) )
400 uInternetConnection
= 2;
401 else if ( 0 == _tcsicmp( szBuffer
, _T("SYSTEMDEFAULT") ) )
402 uInternetConnection
= 0;
405 dwResult
= GetEnvironmentVariable( TEXT("ERRORREPORT_SUBJECT"), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
407 if ( dwResult
&& dwResult
< SAL_N_ELEMENTS(szBuffer
) )
411 dwResult
= GetEnvironmentVariable( TEXT("ERRORREPORT_BODYFILE"), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
413 if ( dwResult
&& dwResult
< SAL_N_ELEMENTS(szBuffer
) )
415 FILE *fp
= _xfopen( szBuffer
, _T("rb") );
419 CHAR aUTF8Buffer
[256];
424 while ( 0 != (nBytesRead
= fread( aUTF8Buffer
, sizeof(aUTF8Buffer
[0]), SAL_N_ELEMENTS(aUTF8Buffer
), fp
)) )
426 TCHAR aBuffer
[256+1];
428 DWORD dwCharacters
= MultiByteToWideChar( CP_UTF8
, 0, aUTF8Buffer
, nBytesRead
, aBuffer
, SAL_N_ELEMENTS(aBuffer
) - 1 );
429 aBuffer
[dwCharacters
] = 0;
438 //***************************************************************************
440 typedef BOOL (WINAPI
*MiniDumpWriteDump_PROC
)(
444 IN MINIDUMP_TYPE DumpType
,
445 IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam
, OPTIONAL
446 IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam
, OPTIONAL
447 IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
450 //***************************************************************************
452 static BOOL WINAPI
InitRichEdit()
454 return (NULL
!= LoadLibrary( RICHEDIT
));
457 //***************************************************************************
459 static BOOL WINAPI
DeinitRichEdit()
461 return FreeLibrary( GetModuleHandle( RICHEDIT
) );
464 //***************************************************************************
466 static string
trim_string( const string
& rString
)
468 string temp
= rString
;
470 while ( temp
.length() && temp
[0] == ' ' || temp
[0] == '\t' )
473 string::size_type len
= temp
.length();
475 while ( len
&& temp
[len
-1] == ' ' || temp
[len
-1] == '\t' )
477 temp
.erase( len
- 1, 1 );
484 //***************************************************************************
486 static int LoadAndFormatString( HINSTANCE hInstance
, UINT uID
, LPTSTR lpBuffer
, int nBufferMax
)
488 TCHAR szBuffer
[FORMATBUFSIZE
];
489 TCHAR szBuffer2
[FORMATBUFSIZE
];
491 LoadString( hInstance
, uID
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
495 for ( dest
= szBuffer2
, src
= szBuffer
; *src
; src
++, dest
++ )
522 return ExpandEnvironmentStrings( szBuffer2
, lpBuffer
, nBufferMax
);
526 //***************************************************************************
528 static string
wstring2utf8( const wstring
&rString
)
530 int nBufSize
= WideCharToMultiByte( CP_UTF8
, 0, rString
.c_str(), -1, NULL
, 0, NULL
, FALSE
);
532 LPSTR pBuffer
= (LPSTR
)alloca( nBufSize
);
534 WideCharToMultiByte( CP_UTF8
, 0, rString
.c_str(), -1, pBuffer
, nBufSize
, NULL
, FALSE
);
536 return string( pBuffer
);
539 //***************************************************************************
541 static string
xml_encode( const string
&rString
)
543 string temp
= rString
;
544 string::size_type pos
= 0;
546 // First replace all occurrences of '&' because it may occur in further
547 // encoded chardters too
549 for( pos
= 0; (pos
= temp
.find( '&', pos
)) != string::npos
; pos
+= 4 )
550 temp
.replace( pos
, 1, "&" );
552 for( pos
= 0; (pos
= temp
.find( '<', pos
)) != string::npos
; pos
+= 4 )
553 temp
.replace( pos
, 1, "<" );
555 for( pos
= 0; (pos
= temp
.find( '>', pos
)) != string::npos
; pos
+= 4 )
556 temp
.replace( pos
, 1, ">" );
561 //***************************************************************************
563 static size_t fcopy( FILE *fpin
, FILE *fpout
)
566 size_t nBytesWritten
= 0;
571 while ( 0 != (nBytes
= fread( buffer
, 1, sizeof(buffer
), fpin
)) )
573 nBytesWritten
+= fwrite( buffer
, 1, nBytes
, fpout
);
577 return nBytesWritten
;
580 //***************************************************************************
582 static string
GetModuleDirectory( HMODULE hModule
)
584 TCHAR szModuleName
[MAX_PATH
] = TEXT("");
585 TCHAR szDrive
[_MAX_DRIVE
];
586 TCHAR szDir
[_MAX_DIR
];
587 TCHAR szFName
[_MAX_FNAME
];
588 TCHAR szExt
[_MAX_EXT
];
590 if ( GetModuleFileName( hModule
, szModuleName
, MAX_PATH
) )
592 _tsplitpath( szModuleName
, szDrive
, szDir
, szFName
, szExt
);
593 _tmakepath( szModuleName
, szDrive
, szDir
, _T(""), _T("") );
596 CHAR szModuleNameUTF8
[MAX_PATH
] = "";
598 WideCharToMultiByte( CP_UTF8
, 0, szModuleName
, -1, szModuleNameUTF8
, SAL_N_ELEMENTS(szModuleNameUTF8
), NULL
, NULL
);
599 return string( szModuleNameUTF8
);
602 //***************************************************************************
604 string
GetFileDirectory( const string
& rFilePath
)
606 string aDir
= rFilePath
;
607 size_t pos
= aDir
.rfind( '\\' );
609 if ( string::npos
!= pos
)
610 aDir
.erase( pos
+ 1 );
617 //***************************************************************************
619 string
GetFileName( const string
& rFilePath
)
621 string aName
= rFilePath
;
622 size_t pos
= aName
.rfind( '\\' );
624 if ( string::npos
!= pos
)
625 return aName
.substr( pos
+ 1 );
630 //***************************************************************************
632 BOOL
WriteReportFile( CrashReportParams
*pParams
)
634 BOOL fSuccess
= FALSE
;
635 TCHAR szTempPath
[MAX_PATH
];
637 if ( GetTempPath( SAL_N_ELEMENTS(szTempPath
), szTempPath
) )
639 TCHAR szFileName
[MAX_PATH
];
641 if ( GetTempFileName( szTempPath
, TEXT("RPM"), 0, szFileName
) )
643 HANDLE hFile
= CreateFile( szFileName
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
647 int fd
= _open_osfhandle( (LONG
)hFile
, _O_TEXT
);
648 FILE *fp
= _fdopen( fd
, "w+t" );
649 CHAR szTitle
[1024] = "";
650 CHAR szBuildId
[1024] = "";
651 CHAR szEmail
[1024] = "";
652 const char *pszUserType
= getenv( "STAROFFICE_USERTYPE" );
654 WideCharToMultiByte( CP_UTF8
, 0, pParams
->sTitle
.c_str(), -1, szTitle
, sizeof(szTitle
), NULL
, NULL
);
655 WideCharToMultiByte( CP_UTF8
, 0, g_szBuildId
, -1, szBuildId
, sizeof(szBuildId
), NULL
, NULL
);
656 WideCharToMultiByte( CP_UTF8
, 0, pParams
->sEmail
.c_str(), -1, szEmail
, sizeof(szEmail
), NULL
, NULL
);
659 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
660 "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
661 "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
662 "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n",
663 pszUserType
? pszUserType
: "",
664 pParams
->fAllowContact
? "true" : "false",
665 pParams
->fAllowContact
? xml_encode(szEmail
).c_str() : ""
669 "<reportmail:title>%s</reportmail:title>\n",
670 xml_encode(szTitle
).c_str() );
673 "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain;charset=UTF-8\" class=\"UserComment\"/>\n"
674 "<reportmail:attachment name=\"user.dmp\" media-type=\"application/octet-stream\" class=\"UserDump\"/>\n"
675 "</reportmail:mail>\n"
677 "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" procpath=\"%s\" exceptiontype=\"0x%08X\" product=\"%s\"/>\n",
680 xml_encode(g_strDefaultLanguage
).c_str(),
681 xml_encode(GetModuleDirectory( NULL
)).c_str(),
683 xml_encode(wstring2utf8(g_wstrProductKey
)).c_str()
686 OSVERSIONINFO VersionInfo
;
688 ZeroMemory( &VersionInfo
, sizeof(VersionInfo
) );
689 VersionInfo
.dwOSVersionInfoSize
= sizeof(VersionInfo
);
691 GetVersionEx( &VersionInfo
);
694 "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
695 "<systeminfo:System name=\"%s\" version=\"%d.%d\" build=\"%d\" locale=\"0x%08x\"/>\n"
697 VER_PLATFORM_WIN32_NT
== VersionInfo
.dwPlatformId
? "Windows NT" : "Windows",
698 VersionInfo
.dwMajorVersion
, VersionInfo
.dwMinorVersion
,
699 VersionInfo
.dwBuildNumber
,
700 GetUserDefaultLangID()
703 fprintf( fp
, "<systeminfo:CPU type=\"x86\"/>\n" );
704 fprintf( fp
, "</systeminfo:systeminfo>\n" );
706 fseek( g_fpStackFile
, 0, SEEK_SET
);
707 fcopy( g_fpStackFile
, fp
);
709 fseek( g_fpChecksumFile
, 0, SEEK_SET
);
710 fcopy( g_fpChecksumFile
, fp
);
712 fprintf( fp
, "</errormail:errormail>\n" );
718 WideCharToMultiByte( CP_ACP
, 0, szFileName
, -1, g_szReportFileNameA
, MAX_PATH
, NULL
, NULL
);
722 DeleteFile( szFileName
);
729 //***************************************************************************
731 static BOOL
SaveDumpFile( HWND hwndOwner
)
734 TCHAR szFileName
[MAX_PATH
] = TEXT("");
736 ZeroMemory( &ofn
, sizeof(ofn
) );
737 ofn
.lStructSize
= sizeof(ofn
);
739 ofn
.hwndOwner
= hwndOwner
;
740 ofn
.lpstrFilter
= TEXT("*.dmp\0*.dmp\0*.*\0*.*\0");
741 ofn
.lpstrFile
= szFileName
;
742 ofn
.nMaxFile
= MAX_PATH
;
743 ofn
.Flags
= OFN_ENABLESIZING
| OFN_LONGNAMES
| OFN_OVERWRITEPROMPT
;
744 ofn
.lpstrDefExt
= TEXT("dmp");
746 if ( GetSaveFileName( &ofn
) )
748 return CopyFile( g_szDumpFileName
, szFileName
, FALSE
);
753 //***************************************************************************
755 static BOOL
ScreenToClientRect( HWND hwnd
, LPRECT lprc
)
757 return ScreenToClient( hwnd
, (LPPOINT
)&lprc
->left
) && ScreenToClient( hwnd
, (LPPOINT
)&lprc
->right
);
760 static BOOL
SetWindowRect( HWND hwnd
, const RECT
*lprc
, BOOL fRepaint
)
762 return MoveWindow( hwnd
, lprc
->left
, lprc
->top
, lprc
->right
- lprc
->left
, lprc
->bottom
- lprc
->top
, fRepaint
);
770 static BOOL
SetGrowMode( HWND hwnd
, DWORD dwGrowMode
)
772 return SetProp( hwnd
, TEXT("GrowMode"), (HANDLE
)dwGrowMode
);
775 static DWORD
GetGrowMode( HWND hwnd
)
777 return (DWORD
)GetProp( hwnd
, TEXT("GrowMode") );
780 static BOOL
GrowWindow( HWND hwnd
, LONG dxClient
, LONG dyClient
, BOOL fRepaint
)
782 DWORD dwGrowMode
= GetGrowMode( hwnd
);
785 GetWindowRect( hwnd
, &rc
);
787 if ( dwGrowMode
& GM_LOX
)
789 if ( dwGrowMode
& GM_HIX
)
790 rc
.right
+= dxClient
;
791 if ( dwGrowMode
& GM_LOY
)
793 if ( dwGrowMode
& GM_HIY
)
794 rc
.bottom
+= dyClient
;
796 ScreenToClientRect( GetParent( hwnd
), &rc
);
797 SetWindowRect( hwnd
, &rc
, fRepaint
);
802 BOOL CALLBACK
GrowChildWindows(
803 HWND hwnd
, // handle to child window
804 LPARAM lParam
// application-defined value
807 LONG cx
= (SHORT
)LOWORD( lParam
);
808 LONG cy
= (SHORT
)HIWORD( lParam
);
810 GrowWindow( hwnd
, cx
, cy
, TRUE
);
815 BOOL CALLBACK
PreviewDialogProc(
822 static RECT rcClient
;
828 LONG cx
= LOWORD( lParam
);
829 LONG cy
= HIWORD( lParam
);
830 LONG dxClient
, dyClient
;
832 dxClient
= cx
- rcClient
.right
;
833 dyClient
= cy
- rcClient
.bottom
;
835 EnumChildWindows( hwndDlg
, GrowChildWindows
, MAKELONG( (SHORT
)dxClient
, (SHORT
)dyClient
) );
837 GetClientRect( hwndDlg
, &rcClient
);
842 GetClientRect( hwndDlg
, &rcClient
);
843 SetGrowMode( GetDlgItem(hwndDlg
, IDC_EDIT_PREVIEW
), GM_HIX
| GM_HIY
);
844 SetGrowMode( GetDlgItem(hwndDlg
, IDOK
), GM_LOX
| GM_HIX
| GM_LOY
| GM_HIY
);
846 CrashReportParams
*pParams
= (CrashReportParams
*)lParam
;
848 TCHAR szBuffer
[256] = TEXT("");
849 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLong( hwndDlg
, GWL_HINSTANCE
);
850 HWND hwndParent
= (HWND
)GetWindowLong( hwndDlg
, GWL_HWNDPARENT
);
852 GetWindowText( hwndParent
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
853 SetWindowText( hwndDlg
, szBuffer
);
855 LoadAndFormatString( hInstance
, IDS_OK_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
856 Button_SetText( GetDlgItem(hwndDlg
, IDOK
), szBuffer
);
858 basic_string
<TCHAR
> aString
;
860 aString
.append( pParams
->sTitle
);
861 aString
.append( _T("\r\n\r\n") );
862 aString
.append( pParams
->sComment
);
863 aString
.append( _T("\r\n---------- report ----------\r\n") );
865 FILE *fp
= fopen( g_szReportFileNameA
, "r" );
871 while ( fgets( buf
, SAL_N_ELEMENTS(buf
), fp
) != NULL
)
875 MultiByteToWideChar( CP_UTF8
, 0, buf
, -1, bufW
, SAL_N_ELEMENTS(bufW
) );
877 aString
.append( bufW
);
883 aString
.append( _T("\r\n---------- stack ----------\r\n") );
885 fp
= fopen( g_szDumpFileNameA
, "rb" );
889 unsigned char buf
[16];
896 count
= fread( buf
, sizeof(buf
[0]), SAL_N_ELEMENTS(buf
), fp
);
898 for ( i
= 0; i
< count
; i
++ )
902 _sntprintf( output
, SAL_N_ELEMENTS(output
), _T("%02X\x20"), buf
[i
] );
903 aString
.append( output
);
905 for ( ; i
< SAL_N_ELEMENTS(buf
); i
++ )
907 aString
.append( _T("\x20\x20\x20") );
910 for ( i
= 0; i
< count
; i
++ )
914 if ( (int)buf
[i
] >= 0x20 && (int)buf
[i
] <= 0x7F )
915 output
[0] = (TCHAR
)buf
[i
];
919 aString
.append( output
);
922 aString
.append( _T("\r\n") );
928 Edit_SetText( GetDlgItem(hwndDlg
, IDC_EDIT_PREVIEW
), aString
.c_str() );
929 SetWindowFont( GetDlgItem(hwndDlg
, IDC_EDIT_PREVIEW
), GetStockObject( SYSTEM_FIXED_FONT
), TRUE
);
933 switch ( LOWORD(wParam
) )
937 EndDialog( hwndDlg
, wParam
);
947 //***************************************************************************
949 static void PreviewReport( HWND hwndParent
, CrashReportParams
*pParams
)
951 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLong(hwndParent
, GWL_HINSTANCE
);
953 WriteReportFile( pParams
);
957 MAKEINTRESOURCE(IDD_PREVIEW_FRAME
),
963 DeleteFileA( g_szReportFileNameA
);
965 //***************************************************************************
966 void UpdateOptionsDialogControls( HWND hwndDlg
)
968 if ( Button_GetCheck( GetDlgItem(hwndDlg
, IDC_RADIO_MANUAL
) ) & BST_CHECKED
)
970 EnableWindow( GetDlgItem(hwndDlg
, IDC_EDIT_PROXYSERVER
), TRUE
);
971 EnableWindow( GetDlgItem(hwndDlg
, IDC_EDIT_PROXYPORT
), TRUE
);
975 EnableWindow( GetDlgItem(hwndDlg
, IDC_EDIT_PROXYSERVER
), FALSE
);
976 EnableWindow( GetDlgItem(hwndDlg
, IDC_EDIT_PROXYPORT
), FALSE
);
980 //***************************************************************************
982 BOOL CALLBACK
OptionsDialogProc(
989 static CrashReportParams
*pParams
;
995 TCHAR szBuffer
[1024] = TEXT("");
996 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLong( hwndDlg
, GWL_HINSTANCE
);
997 //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
999 pParams
= (CrashReportParams
*)lParam
;
1001 LoadAndFormatString( hInstance
, IDS_OPTIONS_CAPTION
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1002 SetWindowText( hwndDlg
, szBuffer
);
1004 LoadAndFormatString( hInstance
, IDS_PROXY_SETTINGS_HEADER
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1005 Static_SetText( GetDlgItem(hwndDlg
, IDC_PROXY_SETTINGS
), szBuffer
);
1007 LoadAndFormatString( hInstance
, IDS_PROXY_SYSTEM
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1008 Button_SetText( GetDlgItem(hwndDlg
, IDC_RADIO_SYSTEM
), szBuffer
);
1010 LoadAndFormatString( hInstance
, IDS_PROXY_DIRECT
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1011 Button_SetText( GetDlgItem(hwndDlg
, IDC_RADIO_DIRECT
), szBuffer
);
1013 LoadAndFormatString( hInstance
, IDS_PROXY_MANUAL
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1014 Button_SetText( GetDlgItem(hwndDlg
, IDC_RADIO_MANUAL
), szBuffer
);
1016 LoadAndFormatString( hInstance
, IDS_LABEL_PROXYSERVER
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1017 Static_SetText( GetDlgItem(hwndDlg
, IDC_LABEL_PROXYSERVER
), szBuffer
);
1019 LoadAndFormatString( hInstance
, IDS_LABEL_PROXYPORT
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1020 Static_SetText( GetDlgItem(hwndDlg
, IDC_LABEL_PROXYPORT
), szBuffer
);
1022 LoadAndFormatString( hInstance
, IDS_OK_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1023 Button_SetText( GetDlgItem(hwndDlg
, IDOK
), szBuffer
);
1025 LoadAndFormatString( hInstance
, IDS_CANCEL_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1026 Button_SetText( GetDlgItem(hwndDlg
, IDCANCEL
), szBuffer
);
1028 Edit_SetText( GetDlgItem(hwndDlg
, IDC_EDIT_PROXYSERVER
), pParams
->sProxyServer
.c_str() );
1029 Edit_SetText( GetDlgItem(hwndDlg
, IDC_EDIT_PROXYPORT
), pParams
->sProxyPort
.c_str() );
1031 Button_SetCheck( GetDlgItem(hwndDlg
, IDC_RADIO_SYSTEM
+ pParams
->uInternetConnection
), BST_CHECKED
);
1034 GetDlgItem(hwndDlg
, IDC_PROXY_DESCRIPTION
),
1037 GetSysColor( COLOR_3DFACE
) );
1038 LoadAndFormatString( hInstance
, IDS_PROXY_DESCRIPTION
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1039 Edit_SetText( GetDlgItem(hwndDlg
, IDC_PROXY_DESCRIPTION
), szBuffer
);
1041 UpdateOptionsDialogControls( hwndDlg
);
1045 switch ( LOWORD(wParam
) )
1047 case IDC_RADIO_SYSTEM
:
1048 case IDC_RADIO_DIRECT
:
1049 case IDC_RADIO_MANUAL
:
1050 if ( BN_CLICKED
== HIWORD(wParam
) )
1051 UpdateOptionsDialogControls( hwndDlg
);
1055 TCHAR szBuffer
[1024];
1057 Edit_GetText( GetDlgItem(hwndDlg
, IDC_EDIT_PROXYSERVER
), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1058 pParams
->sProxyServer
= szBuffer
;
1060 Edit_GetText( GetDlgItem(hwndDlg
, IDC_EDIT_PROXYPORT
), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1061 pParams
->sProxyPort
= szBuffer
;
1063 if ( Button_GetCheck( GetDlgItem(hwndDlg
, IDC_RADIO_DIRECT
) ) & BST_CHECKED
)
1064 pParams
->uInternetConnection
= 1;
1065 else if ( Button_GetCheck( GetDlgItem(hwndDlg
, IDC_RADIO_MANUAL
) ) & BST_CHECKED
)
1066 pParams
->uInternetConnection
= 2;
1068 pParams
->uInternetConnection
= 0;
1071 EndDialog( hwndDlg
, wParam
);
1082 //***************************************************************************
1084 static void OptionsDialog( HWND hwndParent
, CrashReportParams
*pParams
)
1086 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLong(hwndParent
, GWL_HINSTANCE
);
1088 if ( IDOK
== DialogBoxParam(
1090 MAKEINTRESOURCE(IDD_OPTIONS_FRAME
),
1095 pParams
->WriteToRegistry();
1098 //***************************************************************************
1100 void UpdateReportDialogControls( HWND hwndDlg
)
1103 GetDlgItem(hwndDlg
, IDC_EDIT_EMAIL
),
1104 Button_GetCheck(GetDlgItem(hwndDlg
, IDC_ALLOW_CONTACT
)) & BST_CHECKED
? TRUE
: FALSE
);
1106 GetDlgItem(hwndDlg
, IDC_LABEL_EMAIL
),
1107 Button_GetCheck(GetDlgItem(hwndDlg
, IDC_ALLOW_CONTACT
)) & BST_CHECKED
? TRUE
: FALSE
);
1110 //***************************************************************************
1112 BOOL CALLBACK
ReportDialogProc(
1123 CrashReportParams
*pParams
= (CrashReportParams
*)GetWindowLong( GetParent(hwndDlg
), GWL_USERDATA
);
1124 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLong(hwndDlg
, GWL_HINSTANCE
);
1125 TCHAR szBuffer
[FORMATBUFSIZE
];
1127 LoadAndFormatString( hInstance
, IDS_REPORT_INTRO
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1128 Static_SetText( GetDlgItem(hwndDlg
, IDC_REPORT_INTRO
), szBuffer
);
1130 Edit_SetText( GetDlgItem(hwndDlg
, IDC_EDIT3
), szBuffer
);
1132 LoadAndFormatString( hInstance
, IDS_ENTER_TITLE
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1133 Static_SetText( GetDlgItem(hwndDlg
, IDC_ENTER_TITLE
), szBuffer
);
1135 LoadAndFormatString( hInstance
, IDS_ENTER_DESCRIPTION
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1136 Static_SetText( GetDlgItem(hwndDlg
, IDC_ENTER_DESCRIPTION
), szBuffer
);
1138 LoadAndFormatString( hInstance
, IDS_SHOW_REPORT_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1139 Button_SetText( GetDlgItem(hwndDlg
, IDC_SHOW_REPORT
), szBuffer
);
1141 LoadAndFormatString( hInstance
, IDS_SAVE_REPORT_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1142 Button_SetText( GetDlgItem(hwndDlg
, IDC_SAVE_REPORT
), szBuffer
);
1144 const char *pszUserType
= getenv( "STAROFFICE_USERTYPE" );
1146 ShowWindow( GetDlgItem(hwndDlg
, IDC_SAVE_REPORT
), SW_SHOW
);
1148 ShowWindow( GetDlgItem(hwndDlg
, IDC_SAVE_REPORT
), SW_HIDE
);
1150 LoadAndFormatString( hInstance
, IDS_OPTIONS_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1151 Button_SetText( GetDlgItem(hwndDlg
, IDC_OPTIONS
), szBuffer
);
1153 LoadAndFormatString( hInstance
, IDS_ALLOW_CONTACT
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1154 Button_SetText( GetDlgItem(hwndDlg
, IDC_ALLOW_CONTACT
), szBuffer
);
1155 Button_SetCheck( GetDlgItem(hwndDlg
, IDC_ALLOW_CONTACT
), pParams
->fAllowContact
? BST_CHECKED
: BST_UNCHECKED
);
1157 LoadAndFormatString( hInstance
, IDS_LABEL_EMAIL
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1158 Button_SetText( GetDlgItem(hwndDlg
, IDC_LABEL_EMAIL
), szBuffer
);
1160 Edit_SetText( GetDlgItem(hwndDlg
, IDC_EDIT_EMAIL
), pParams
->sEmail
.c_str() );
1162 UpdateReportDialogControls( hwndDlg
);
1168 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLong(hwndDlg
, GWL_HINSTANCE
);
1169 CrashReportParams
*pParams
= (CrashReportParams
*)GetWindowLong( GetParent(hwndDlg
), GWL_USERDATA
);
1170 TCHAR szBuffer
[FORMATBUFSIZE
];
1172 LoadAndFormatString( hInstance
, IDS_REPORT_CAPTION
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1173 SetWindowText( GetParent(hwndDlg
), szBuffer
);
1175 LoadAndFormatString( hInstance
, IDS_REPORT_HEADER
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1176 SetWindowText( GetDlgItem(GetParent(hwndDlg
), IDC_HEADER
), szBuffer
);
1178 LoadAndFormatString( hInstance
, IDS_DONOT_SEND_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1179 Button_SetText( GetDlgItem(GetParent(hwndDlg
), IDCANCEL
), szBuffer
);
1182 ShowWindow( GetDlgItem(GetParent(hwndDlg
),IDBACK
), TRUE
);
1183 ShowWindow( GetDlgItem(GetParent(hwndDlg
),IDFINISH
), TRUE
);
1184 ShowWindow( GetDlgItem(GetParent(hwndDlg
),IDNEXT
), FALSE
);
1186 Edit_SetText( GetDlgItem(hwndDlg
, IDC_EDIT_TITLE
), pParams
->sTitle
.c_str() );
1187 Edit_SetText( GetDlgItem(hwndDlg
, IDC_EDIT_DESCRIPTION
), pParams
->sComment
.c_str() );
1189 SetFocus( GetDlgItem(hwndDlg
,IDC_EDIT_TITLE
) );
1193 switch ( LOWORD(wParam
) )
1195 case IDC_SHOW_REPORT
:
1197 TCHAR szBuffer
[32767];
1199 CrashReportParams
*pParams
= (CrashReportParams
*)GetWindowLong( GetParent(hwndDlg
), GWL_USERDATA
);
1201 pParams
->fAllowContact
= Button_GetCheck( GetDlgItem(hwndDlg
, IDC_ALLOW_CONTACT
) ) ? TRUE
: FALSE
;
1203 Edit_GetText( GetDlgItem(hwndDlg
, IDC_EDIT_TITLE
), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1204 pParams
->sTitle
= szBuffer
;
1206 Edit_GetText( GetDlgItem(hwndDlg
, IDC_EDIT_DESCRIPTION
), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1207 pParams
->sComment
= szBuffer
;
1209 Edit_GetText( GetDlgItem(hwndDlg
, IDC_EDIT_EMAIL
), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1210 pParams
->sEmail
= szBuffer
;
1212 PreviewReport( GetParent(hwndDlg
), pParams
);
1215 case IDC_SAVE_REPORT
:
1216 SaveDumpFile( GetParent(hwndDlg
) );
1220 CrashReportParams
*pParams
= (CrashReportParams
*)GetWindowLong( GetParent(hwndDlg
), GWL_USERDATA
);
1221 OptionsDialog( GetParent(hwndDlg
), pParams
);
1224 case IDC_ALLOW_CONTACT
:
1225 if ( BN_CLICKED
== HIWORD(wParam
) )
1226 UpdateReportDialogControls( hwndDlg
);
1236 //***************************************************************************
1238 BOOL CALLBACK
WelcomeDialogProc( HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1244 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLong(hwndDlg
, GWL_HINSTANCE
);
1245 HWND hwndRichEdit
= GetDlgItem(hwndDlg
, IDC_RICHEDIT21
);
1246 TCHAR szBuffer
[FORMATBUFSIZE
];
1247 TCHAR szBuffer2
[FORMATBUFSIZE
];
1249 TCHAR szCaption
[256];
1255 GetSysColor( COLOR_3DFACE
) );
1257 SendMessage( hwndRichEdit
, EM_SETEVENTMASK
, 0, ENM_LINK
);
1258 SendMessage( hwndRichEdit
, EM_AUTOURLDETECT
, TRUE
, 0 );
1260 LoadAndFormatString( hInstance
, IDS_WELCOME_BODY1
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1261 LoadAndFormatString( hInstance
, IDS_WELCOME_BODY2
, szBuffer2
, SAL_N_ELEMENTS(szBuffer2
) );
1262 _tcsncat( szBuffer
, szBuffer2
, SAL_N_ELEMENTS(szBuffer
) );
1263 LoadAndFormatString( hInstance
, IDS_WELCOME_BODY3
, szBuffer2
, SAL_N_ELEMENTS(szBuffer2
) );
1264 _tcsncat( szBuffer
, szBuffer2
, SAL_N_ELEMENTS(szBuffer
) );
1265 LoadString( hInstance
, IDS_PRIVACY_URL
, szURL
, SAL_N_ELEMENTS(szURL
) );
1266 _tcsncat( szBuffer
, szURL
, SAL_N_ELEMENTS(szBuffer
) );
1267 SetWindowText( hwndRichEdit
, szBuffer
);
1269 LoadAndFormatString( hInstance
, IDS_WELCOME_CAPTION
, szCaption
, SAL_N_ELEMENTS(szCaption
) );
1270 SetWindowText( GetParent(hwndDlg
), szCaption
);
1277 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLong(hwndDlg
, GWL_HINSTANCE
);
1278 TCHAR szBuffer
[FORMATBUFSIZE
];
1280 LoadAndFormatString( hInstance
, IDS_WELCOME_CAPTION
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1281 SetWindowText( GetParent(hwndDlg
), szBuffer
);
1283 LoadAndFormatString( hInstance
, IDS_WELCOME_HEADER
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1284 SetWindowText( GetDlgItem(GetParent(hwndDlg
), IDC_HEADER
), szBuffer
);
1286 LoadAndFormatString( hInstance
, IDS_CANCEL_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1287 Button_SetText( GetDlgItem(GetParent(hwndDlg
), IDCANCEL
), szBuffer
);
1289 ShowWindow( GetDlgItem(GetParent(hwndDlg
),IDBACK
), FALSE
);
1290 ShowWindow( GetDlgItem(GetParent(hwndDlg
),IDFINISH
), FALSE
);
1291 ShowWindow( GetDlgItem(GetParent(hwndDlg
),IDNEXT
), TRUE
);
1293 SetFocus( GetDlgItem(GetParent(hwndDlg
),IDNEXT
) );
1298 LPNMHDR pnmh
= (LPNMHDR
)lParam
;
1300 if ( pnmh
->idFrom
== IDC_RICHEDIT21
&& pnmh
->code
== EN_LINK
)
1302 ENLINK
*plink
= (ENLINK
*)lParam
;
1304 if ( plink
->msg
== WM_LBUTTONUP
)
1306 TCHAR szBuffer
[256];
1309 range
.chrg
= plink
->chrg
;
1310 range
.lpstrText
= szBuffer
;
1312 SendMessage( pnmh
->hwndFrom
, EM_GETTEXTRANGE
, 0, (LPARAM
)&range
);
1314 ShellExecute( hwndDlg
, NULL
, szBuffer
, NULL
, NULL
, SW_SHOWDEFAULT
);
1326 //***************************************************************************
1328 BOOL CALLBACK
DialogProc( HWND hwndDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1330 static HWND hwndPages
[2] = { NULL
};
1331 static int iActualPage
= 0;
1337 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLong(hwndDlg
, GWL_HINSTANCE
);
1338 TCHAR szBuffer
[FORMATBUFSIZE
];
1340 SetWindowLong( hwndDlg
, GWL_USERDATA
, (LONG
)lParam
);
1341 hwndPages
[0] = CreateDialog(
1343 MAKEINTRESOURCE(IDD_WELCOME_PAGE
),
1345 WelcomeDialogProc
);
1347 hwndPages
[1] = CreateDialog(
1349 MAKEINTRESOURCE(IDD_REPORT_PAGE
),
1355 chfmt
.cbSize
= sizeof(chfmt
);
1356 chfmt
.dwMask
= CFM_BOLD
;
1357 chfmt
.dwEffects
= CFE_BOLD
;
1360 GetDlgItem(hwndDlg
, IDC_HEADER
),
1365 LoadAndFormatString( hInstance
, IDS_CANCEL_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1366 Button_SetText( GetDlgItem(hwndDlg
, IDCANCEL
), szBuffer
);
1368 LoadAndFormatString( hInstance
, IDS_NEXT_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1369 Button_SetText( GetDlgItem(hwndDlg
, IDNEXT
), szBuffer
);
1371 LoadAndFormatString( hInstance
, IDS_SEND_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1372 Button_SetText( GetDlgItem(hwndDlg
, IDFINISH
), szBuffer
);
1374 LoadAndFormatString( hInstance
, IDS_BACK_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1375 Button_SetText( GetDlgItem(hwndDlg
, IDBACK
), szBuffer
);
1377 ShowWindow( hwndPages
[1], SW_HIDE
);
1378 ShowWindow( hwndPages
[0], SW_SHOW
);
1380 // Let Crash Reporter window stay on top of all other windows
1381 SetWindowPos( hwndDlg
, HWND_TOPMOST
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
1384 case WM_CTLCOLORSTATIC
:
1385 return (BOOL
)CreateSolidBrush(GetSysColor(COLOR_WINDOW
));
1387 switch ( LOWORD(wParam
) )
1390 if ( iActualPage
> 0 )
1392 ShowWindow( hwndPages
[iActualPage
], SW_HIDE
);
1393 ShowWindow( hwndPages
[--iActualPage
], SW_SHOW
);
1397 if ( iActualPage
< SAL_N_ELEMENTS(hwndPages
) - 1 )
1399 ShowWindow( hwndPages
[iActualPage
], SW_HIDE
);
1400 ShowWindow( hwndPages
[++iActualPage
], SW_SHOW
);
1405 TCHAR szBuffer
[32767];
1406 CrashReportParams
*pParams
= (CrashReportParams
*)GetWindowLong( hwndDlg
, GWL_USERDATA
);
1408 pParams
->fAllowContact
= Button_GetCheck( GetDlgItem(hwndPages
[1], IDC_ALLOW_CONTACT
) ) ? TRUE
: FALSE
;
1410 Edit_GetText( GetDlgItem(hwndPages
[1], IDC_EDIT_TITLE
), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1411 pParams
->sTitle
= szBuffer
;
1413 Edit_GetText( GetDlgItem(hwndPages
[1], IDC_EDIT_DESCRIPTION
), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1414 pParams
->sComment
= szBuffer
;
1416 Edit_GetText( GetDlgItem(hwndPages
[1], IDC_EDIT_EMAIL
), szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
1417 pParams
->sEmail
= szBuffer
;
1419 if ( pParams
->fAllowContact
&& !pParams
->sEmail
.length() )
1421 TCHAR szMessage
[MAX_TEXT_BUFFER
];
1423 LoadAndFormatString( GetModuleHandle(NULL
), IDS_ERROR_MSG_NOEMAILADDRESS
, szMessage
, SAL_N_ELEMENTS(szMessage
) );
1425 MessageBox( hwndDlg
, szMessage
, NULL
, MB_ICONERROR
| MB_OK
);
1426 break; // Don't end the dialog
1430 pParams
->WriteToRegistry();
1432 WriteCommentFile( pParams
->sComment
.c_str() );
1433 WriteReportFile( pParams
);
1435 if ( !SendCrashReport( hwndDlg
, *pParams
) )
1436 break; // Don't end the dialog
1441 EndDialog( hwndDlg
, wParam
);
1454 //*****************************************************************************
1455 //* Generate MD5 checksum
1456 //*****************************************************************************
1458 #define MAGIC_DESCRIPTION_FILLER 'x'
1459 #define MAGIC_DESCRIPTION_COUNT 80
1461 static void repatch_soffice_exe( void *pBuffer
, size_t nBufSize
)
1463 wchar_t DescriptionBuffer
[MAGIC_DESCRIPTION_COUNT
];
1465 memset( DescriptionBuffer
, 0, sizeof(DescriptionBuffer
) );
1466 wcsncpy( DescriptionBuffer
, g_wstrProductKey
.c_str(), SAL_N_ELEMENTS(DescriptionBuffer
) - 1 );
1468 bool bPatched
= false;
1472 void *pFound
= memchr( pBuffer
, ((char *)DescriptionBuffer
)[0], nBufSize
);
1476 size_t distance
= (char *)pFound
- (char *)pBuffer
;
1478 if ( nBufSize
>= distance
)
1480 nBufSize
-= distance
;
1482 if ( nBufSize
>= sizeof(DescriptionBuffer
) &&
1483 0 == memcmp( pFound
, DescriptionBuffer
, sizeof(DescriptionBuffer
) ) )
1485 for ( int i
= 0; i
< 80; i
++ )
1487 ((wchar_t *)pFound
)[i
] = MAGIC_DESCRIPTION_FILLER
;
1493 pBuffer
= (void *)(((char *)pFound
) + 1);
1502 } while ( !bPatched
&& nBufSize
);
1505 // Normalize executable/library images to prevent different MD5 checksums due
1506 // to a different PE header date/checksum (this doesn't affect the code/data
1507 // sections of a executable/library. Please see tools/source/bootstrp/md5.cxx
1508 // where the same method is also used. The tool so_checksum creates the MD5
1509 // checksums during build time. You have to make sure that both methods use the
1510 // same algorithm otherwise there could be problems with stack reports.
1511 static void normalize_pe_image(sal_uInt8
* buffer
, size_t nBufferSize
)
1513 const int OFFSET_PE_OFFSET
= 0x3c;
1514 const int OFFSET_COFF_TIMEDATESTAMP
= 4;
1515 const int PE_SIGNATURE_SIZE
= 4;
1516 const int COFFHEADER_SIZE
= 20;
1517 const int OFFSET_PE_OPTIONALHEADER_CHECKSUM
= 64;
1519 // Check the header part of the file buffer
1520 if (buffer
[0] == 'M' && buffer
[1] == 'Z')
1522 unsigned long PEHeaderOffset
= (long)buffer
[OFFSET_PE_OFFSET
];
1523 if (PEHeaderOffset
< nBufferSize
-4)
1525 if ( buffer
[PEHeaderOffset
] == 'P' &&
1526 buffer
[PEHeaderOffset
+1] == 'E' &&
1527 buffer
[PEHeaderOffset
+2] == 0 &&
1528 buffer
[PEHeaderOffset
+3] == 0 )
1530 PEHeaderOffset
+= PE_SIGNATURE_SIZE
;
1531 if (PEHeaderOffset
+OFFSET_COFF_TIMEDATESTAMP
< nBufferSize
-4)
1533 // Set timedatestamp and checksum fields to a normalized
1534 // value to enforce the same MD5 checksum for identical
1535 // Windows executables/libraries.
1536 buffer
[PEHeaderOffset
+OFFSET_COFF_TIMEDATESTAMP
] = 0;
1537 buffer
[PEHeaderOffset
+OFFSET_COFF_TIMEDATESTAMP
+1] = 0;
1538 buffer
[PEHeaderOffset
+OFFSET_COFF_TIMEDATESTAMP
+2] = 0;
1539 buffer
[PEHeaderOffset
+OFFSET_COFF_TIMEDATESTAMP
+3] = 0;
1542 if (PEHeaderOffset
+COFFHEADER_SIZE
+OFFSET_PE_OPTIONALHEADER_CHECKSUM
< nBufferSize
-4)
1544 // Set checksum to a normalized value
1545 buffer
[PEHeaderOffset
+COFFHEADER_SIZE
+OFFSET_PE_OPTIONALHEADER_CHECKSUM
] = 0;
1546 buffer
[PEHeaderOffset
+COFFHEADER_SIZE
+OFFSET_PE_OPTIONALHEADER_CHECKSUM
+1] = 0;
1547 buffer
[PEHeaderOffset
+COFFHEADER_SIZE
+OFFSET_PE_OPTIONALHEADER_CHECKSUM
+2] = 0;
1548 buffer
[PEHeaderOffset
+COFFHEADER_SIZE
+OFFSET_PE_OPTIONALHEADER_CHECKSUM
+3] = 0;
1555 static sal_uInt32
calc_md5_checksum( const char *filename
, sal_uInt8
*pChecksum
, sal_uInt32 nChecksumLen
)
1557 const int MINIMAL_FILESIZE
= 512;
1559 sal_uInt32 nBytesProcessed
= 0;
1561 FILE *fp
= fopen( filename
, "rb" );
1567 if ( 0 == fseek( fp
, 0, SEEK_END
) && -1 != (nFileSize
= ftell(fp
)) )
1571 sal_uInt8
*pBuffer
= new sal_uInt8
[nFileSize
];
1572 size_t nBytesRead
= fread( pBuffer
, 1, nFileSize
, fp
);
1574 if ( sal::static_int_cast
<long>(nBytesRead
) == nFileSize
)
1576 if ( 0 == stricmp( GetFileName(filename
).c_str(), "soffice.bin" ) )
1577 repatch_soffice_exe( pBuffer
, nBytesRead
);
1578 else if ( nFileSize
> MINIMAL_FILESIZE
)
1579 normalize_pe_image( pBuffer
, nBytesRead
);
1581 rtlDigestError error
= rtl_digest_MD5 (
1582 pBuffer
, nBytesRead
,
1583 pChecksum
, nChecksumLen
);
1585 if ( rtl_Digest_E_None
== error
)
1586 nBytesProcessed
= nBytesRead
;
1593 return nBytesProcessed
;
1596 //***************************************************************************
1598 static bool WriteStackFile( FILE *fout
, boost::unordered_map
< string
, string
>& rLibraries
, DWORD dwProcessId
, PEXCEPTION_POINTERS pExceptionPointers
)
1600 bool fSuccess
= false;
1602 if ( fout
&& dwProcessId
&& pExceptionPointers
)
1604 HANDLE hProcess
= OpenProcess( PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
, FALSE
, dwProcessId
);
1606 if ( IsValidHandle(hProcess
) )
1608 EXCEPTION_POINTERS aExceptionPointers
;
1609 CONTEXT aContextRecord
;
1614 &aExceptionPointers
,
1615 sizeof(aExceptionPointers
),
1620 aExceptionPointers
.ContextRecord
,
1622 sizeof(aContextRecord
),
1627 ZeroMemory( &frame
, sizeof(frame
) );
1628 frame
.AddrPC
.Offset
= aContextRecord
.Eip
;
1629 frame
.AddrPC
.Mode
= AddrModeFlat
;
1630 frame
.AddrFrame
.Offset
= aContextRecord
.Ebp
;
1631 frame
.AddrFrame
.Mode
= AddrModeFlat
;
1636 SymInitialize( hProcess
, NULL
, TRUE
);
1638 fprintf( fout
, "<errormail:Stack type=\"Win32\">\n" );
1644 bSuccess
= StackWalk( IMAGE_FILE_MACHINE_I386
,
1649 (PREAD_PROCESS_MEMORY_ROUTINE
)ReadProcessMemory
,
1650 SymFunctionTableAccess
,
1656 // Note: ImageHelp ANSI functions do not have an A postfix while
1657 // Unicode versions have a W postfix. There's no macro
1658 // that depends on define UNICODE
1660 IMAGEHLP_MODULE moduleInfo
;
1662 ZeroMemory( &moduleInfo
, sizeof(moduleInfo
) );
1663 moduleInfo
.SizeOfStruct
= sizeof(moduleInfo
);
1665 if ( SymGetModuleInfo( hProcess
, frame
.AddrPC
.Offset
, &moduleInfo
) )
1667 rLibraries
[ GetFileName( moduleInfo
.LoadedImageName
).c_str() ] = moduleInfo
.LoadedImageName
;
1669 DWORD dwRelOffset
= 0;
1670 BYTE symbolBuffer
[sizeof(IMAGEHLP_SYMBOL
) + 256 ];
1671 PIMAGEHLP_SYMBOL pSymbol
= (PIMAGEHLP_SYMBOL
)symbolBuffer
;
1673 ZeroMemory( symbolBuffer
, sizeof(symbolBuffer
) );
1674 pSymbol
->SizeOfStruct
= sizeof(IMAGEHLP_SYMBOL
);
1675 pSymbol
->MaxNameLength
= 256;
1677 if ( SymGetSymFromAddr( hProcess
, frame
.AddrPC
.Offset
, &dwRelOffset
, pSymbol
) )
1678 fprintf( fout
, "<errormail:StackInfo " \
1679 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" ordinal=\"%s+0x%p\" name=\"%s\" path=\"%s\"/>\n",
1681 frame
.AddrPC
.Offset
,
1682 frame
.AddrPC
.Offset
- moduleInfo
.BaseOfImage
,
1683 xml_encode(pSymbol
->Name
).c_str(),
1684 frame
.AddrPC
.Offset
- pSymbol
->Address
,
1685 xml_encode(GetFileName( moduleInfo
.LoadedImageName
)).c_str(),
1686 xml_encode( GetFileDirectory( moduleInfo
.LoadedImageName
)).c_str()
1689 fprintf( fout
, "<errormail:StackInfo " \
1690 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" name=\"%s\" path=\"%s\"/>\n",
1692 frame
.AddrPC
.Offset
,
1693 frame
.AddrPC
.Offset
- moduleInfo
.BaseOfImage
,
1694 xml_encode(GetFileName( moduleInfo
.LoadedImageName
)).c_str(),
1695 xml_encode(GetFileDirectory( moduleInfo
.LoadedImageName
)).c_str()
1699 fprintf( fout
, "<errormail:StackInfo pos=\"%d\" ip=\"0x%p\"/>\n",
1707 } while ( bSuccess
);
1709 fprintf( fout
, "</errormail:Stack>\n" );
1711 SymCleanup( hProcess
);
1713 CloseHandle( hProcess
);
1721 bool WriteChecksumFile( FILE *fchksum
, const boost::unordered_map
< string
, string
>& rLibraries
)
1723 bool success
= false;
1725 if ( fchksum
&& rLibraries
.size() )
1727 fprintf( fchksum
, "<errormail:Checksums type=\"MD5\">\n" );
1729 boost::unordered_map
< string
, string
>::const_iterator iter
;
1731 for ( iter
= rLibraries
.begin(); iter
!= rLibraries
.end(); ++iter
)
1733 sal_uInt8 checksum
[RTL_DIGEST_LENGTH_MD5
];
1734 sal_uInt32 nBytesProcessed
= calc_md5_checksum(
1735 iter
->second
.c_str(),
1736 checksum
, sizeof(checksum
) );
1738 if ( nBytesProcessed
)
1740 fprintf( fchksum
, "<errormail:Checksum sum=\"0x" );
1741 for ( int i
= 0; i
< sizeof(checksum
); fprintf( fchksum
, "%02X", checksum
[i
++] ) );
1742 fprintf( fchksum
, "\" bytes=\"%d\" file=\"%s\"/>\n",
1744 GetFileName( iter
->first
).c_str() );
1748 fprintf( fchksum
, "</errormail:Checksums>\n" );
1756 //***************************************************************************
1760 TCHAR szFileName
[MAX_PATH
];
1762 if ( GetCrashDataPath( szFileName
) )
1764 _tcscat( szFileName
, _T("\\crashdat.dmp") );
1766 HANDLE hFile
= CreateFile(
1771 FILE_ATTRIBUTE_NORMAL
, NULL
);
1775 CloseHandle( hFile
);
1777 WideCharToMultiByte( CP_ACP
, 0, szFileName
, -1, g_szDumpFileNameA
, MAX_PATH
, NULL
, NULL
);
1778 _tcscpy( g_szDumpFileName
, szFileName
);
1787 BOOL
WriteDumpFile( DWORD dwProcessId
, PEXCEPTION_POINTERS pExceptionPointers
, DWORD dwThreadId
)
1789 BOOL fSuccess
= FALSE
;
1790 MINIDUMP_EXCEPTION_INFORMATION ExceptionParam
;
1792 HMODULE hDbgHelp
= LoadLibrary( _T("DBGHELP.DLL" ) );
1793 MiniDumpWriteDump_PROC pMiniDumpWriteDump
= NULL
;
1797 pMiniDumpWriteDump
= (MiniDumpWriteDump_PROC
)GetProcAddress( hDbgHelp
, "MiniDumpWriteDump" );
1799 if ( !pMiniDumpWriteDump
)
1801 FreeLibrary( hDbgHelp
);
1806 if ( !pMiniDumpWriteDump
)
1809 HANDLE hProcess
= OpenProcess( PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
, FALSE
, dwProcessId
);
1811 if ( IsValidHandle(hProcess
) )
1813 TCHAR szTempPath
[MAX_PATH
];
1815 if ( GetCrashDataPath( szTempPath
) )
1817 TCHAR szFileName
[MAX_PATH
];
1819 _tcscpy( szFileName
, szTempPath
);
1820 _tcscat( szFileName
, _T("\\crashdat.dmp") );
1822 HANDLE hFile
= CreateFile(
1824 GENERIC_READ
| GENERIC_WRITE
,
1827 FILE_ATTRIBUTE_NORMAL
, NULL
);
1831 PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam
= NULL
;
1832 if ( pExceptionPointers
&& dwThreadId
)
1834 ExceptionParam
.ThreadId
= dwThreadId
;
1835 ExceptionParam
.ExceptionPointers
= pExceptionPointers
;
1836 ExceptionParam
.ClientPointers
= TRUE
;
1838 EXCEPTION_POINTERS aExceptionPointers
;
1839 EXCEPTION_RECORD aExceptionRecord
;
1844 &aExceptionPointers
,
1845 sizeof(aExceptionPointers
),
1851 aExceptionPointers
.ExceptionRecord
,
1853 sizeof(aExceptionRecord
),
1856 g_dwExceptionCode
= aExceptionRecord
.ExceptionCode
;
1858 lpExceptionParam
= &ExceptionParam
;
1861 fSuccess
= pMiniDumpWriteDump( hProcess
, dwProcessId
, hFile
, MiniDumpNormal
, lpExceptionParam
, NULL
, NULL
);
1863 CloseHandle( hFile
);
1865 WideCharToMultiByte( CP_ACP
, 0, szFileName
, -1, g_szDumpFileNameA
, MAX_PATH
, NULL
, NULL
);
1866 _tcscpy( g_szDumpFileName
, szFileName
);
1870 DeleteFile( szFileName
);
1874 CloseHandle( hProcess
);
1877 FreeLibrary( hDbgHelp
);
1882 //***************************************************************************
1884 static DWORD
FindProcessForImage( LPCTSTR lpImagePath
)
1886 DWORD dwProcessId
= 0;
1887 DWORD aProcesses
[1024];
1889 TCHAR szShortImagePath
[MAX_PATH
];
1891 if ( GetShortPathName( lpImagePath
, szShortImagePath
, SAL_N_ELEMENTS(szShortImagePath
) ) &&
1892 EnumProcesses( aProcesses
, sizeof(aProcesses
), &dwSize
) )
1894 unsigned nProcesses
= dwSize
/ sizeof(aProcesses
[0]);
1896 for ( unsigned i
= 0; !dwProcessId
&& i
< nProcesses
; i
++ )
1898 HANDLE hProcess
= OpenProcess( PROCESS_QUERY_INFORMATION
| PROCESS_VM_READ
, FALSE
, aProcesses
[i
] );
1900 if ( IsValidHandle(hProcess
) )
1902 TCHAR szModulePath
[MAX_PATH
+1];
1904 if ( GetModuleFileNameEx( hProcess
, NULL
, szModulePath
, MAX_PATH
) )
1906 TCHAR szShortModulePath
[MAX_PATH
];
1908 if ( GetShortPathName( szModulePath
, szShortModulePath
, SAL_N_ELEMENTS(szShortModulePath
) ) )
1910 if ( 0 == _tcsicmp( szShortModulePath
, szShortImagePath
) )
1911 dwProcessId
= aProcesses
[i
];
1915 CloseHandle( hProcess
);
1922 //***************************************************************************
1924 static bool ParseCommandArgs( LPDWORD pdwProcessId
, PEXCEPTION_POINTERS
* ppException
, LPDWORD pdwThreadId
)
1929 TCHAR
**argv
= reinterpret_cast<TCHAR
**>(alloca((argc
+1)*sizeof(WCHAR
*)));
1930 int *sizes
= reinterpret_cast<int *>(alloca(argc
*sizeof(int)));
1935 for (i
= 0; i
< argc
; ++i
)
1937 sizes
[i
]=MultiByteToWideChar(CP_ACP
, 0, *ptr
, -1, NULL
, 0);
1938 argsize
+=sizes
[i
]+1;
1942 TCHAR
*args
= reinterpret_cast<TCHAR
*>(alloca(argsize
*sizeof(WCHAR
)));
1945 for (i
= 0; i
< argc
; ++i
)
1948 MultiByteToWideChar( CP_ACP
, 0, *ptr
, -1, cptr
, sizes
[i
] );
1957 TCHAR
**argv
= __argv
;
1960 TCHAR
**argv
= __targv
;
1962 bool bSuccess
= true;
1964 for ( int argn
= 1; bSuccess
&& argn
< argc
; argn
++ )
1966 if ( 0 == _tcsicmp( argv
[argn
], _T("-h") ) ||
1967 0 == _tcsicmp( argv
[argn
], _T("/h") ) ||
1968 0 == _tcsicmp( argv
[argn
], _T("-?") ) ||
1969 0 == _tcsicmp( argv
[argn
], _T("/?") ) ||
1970 0 == _tcsicmp( argv
[argn
], _T("/help") ) ||
1971 0 == _tcsicmp( argv
[argn
], _T("-help") ) ||
1972 0 == _tcsicmp( argv
[argn
], _T("--help") )
1975 HINSTANCE hInstance
= GetModuleHandle(NULL
);
1976 TCHAR szUsage
[FORMATBUFSIZE
];
1977 TCHAR szProcess
[FORMATBUFSIZE
];
1978 TCHAR szProcessDescription
[FORMATBUFSIZE
];
1979 TCHAR szHelpDescription
[FORMATBUFSIZE
];
1981 LoadAndFormatString( hInstance
, IDS_MSG_CMDLINE_USAGE
, szUsage
, SAL_N_ELEMENTS(szUsage
) );
1982 LoadAndFormatString( hInstance
, IDS_MSG_PARAM_PROCESSID
, szProcess
, SAL_N_ELEMENTS(szProcess
) );
1983 LoadAndFormatString( hInstance
, IDS_MSG_PARAM_PROCESSID_DESCRIPTION
, szProcessDescription
, SAL_N_ELEMENTS(szProcessDescription
) );
1984 LoadAndFormatString( hInstance
, IDS_MSG_PARAM_HELP_DESCRIPTION
, szHelpDescription
, SAL_N_ELEMENTS(szHelpDescription
) );
1987 TEXT("\n%s: crashrep %s\n\n")
1988 TEXT("/?, -h[elp] %s\n\n")
1989 TEXT("%-20s %s\n\n"),
1990 szUsage
, szProcess
, szHelpDescription
, szProcess
, szProcessDescription
1995 else if ( 0 == _tcsicmp( argv
[argn
], _T("-p") ) ||
1996 0 == _tcsicmp( argv
[argn
], _T("/p") ) )
1998 if ( ++argn
< argc
)
1999 *pdwProcessId
= _tcstoul( argv
[argn
], NULL
, 0 );
2003 else if ( 0 == _tcsicmp( argv
[argn
], _T("-excp") ) ||
2004 0 == _tcsicmp( argv
[argn
], _T("/excp") ) )
2006 if ( ++argn
< argc
)
2007 *ppException
= (PEXCEPTION_POINTERS
)_tcstoul( argv
[argn
], NULL
, 0 );
2011 else if ( 0 == _tcsicmp( argv
[argn
], _T("-t") ) ||
2012 0 == _tcsicmp( argv
[argn
], _T("/t") ) )
2014 if ( ++argn
< argc
)
2015 *pdwThreadId
= _tcstoul( argv
[argn
], NULL
, 0 );
2019 else if ( 0 == _tcsicmp( argv
[argn
], _T("-noui") ) ||
2020 0 == _tcsicmp( argv
[argn
], _T("/noui") ) )
2022 g_bNoUserInterface
= true;
2024 else if ( 0 == _tcsicmp( argv
[argn
], _T("-send") ) ||
2025 0 == _tcsicmp( argv
[argn
], _T("/send") ) )
2027 g_bSendReport
= true;
2029 else if ( 0 == _tcsicmp( argv
[argn
], _T("-load") ) ||
2030 0 == _tcsicmp( argv
[argn
], _T("/load") ) )
2032 g_bLoadReport
= true;
2034 else // treat parameter as image path
2036 TCHAR szImagePath
[MAX_PATH
];
2039 if ( GetFullPathName( argv
[argn
], MAX_PATH
, szImagePath
, &lpImageName
) )
2041 DWORD dwProcessId
= FindProcessForImage( szImagePath
);
2044 *pdwProcessId
= dwProcessId
;
2051 if ( !*pdwProcessId
&& !g_bLoadReport
)
2053 TCHAR szImagePath
[MAX_PATH
];
2056 if ( GetFullPathName( TEXT("soffice.exe"), MAX_PATH
, szImagePath
, &lpImageName
) )
2058 DWORD dwProcessId
= FindProcessForImage( szImagePath
);
2061 *pdwProcessId
= dwProcessId
;
2070 //***************************************************************************
2072 BOOL
WriteCommentFile( LPCTSTR lpComment
)
2074 BOOL fSuccess
= FALSE
;
2075 TCHAR szTempPath
[MAX_PATH
];
2077 if ( GetTempPath( SAL_N_ELEMENTS(szTempPath
), szTempPath
) )
2079 TCHAR szFileName
[MAX_PATH
];
2081 if ( GetTempFileName( szTempPath
, TEXT("CMT"), 0, szFileName
) )
2083 HANDLE hFile
= CreateFile( szFileName
, GENERIC_READ
| GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
2087 DWORD dwBytesWritten
;
2089 int needed
= WideCharToMultiByte( CP_UTF8
, 0, lpComment
, -1, NULL
, 0, NULL
, NULL
);
2092 char *lpCommentUTF8
= (char *)alloca( needed
);
2093 WideCharToMultiByte( CP_UTF8
, 0, lpComment
, -1, lpCommentUTF8
, needed
, NULL
, NULL
);
2094 fSuccess
= WriteFile( hFile
, lpCommentUTF8
, strlen(lpCommentUTF8
), &dwBytesWritten
, NULL
);
2100 CloseHandle( hFile
);
2102 WideCharToMultiByte( CP_ACP
, 0, szFileName
, -1, g_szCommentFileNameA
, MAX_PATH
, NULL
, NULL
);
2106 DeleteFile( szFileName
);
2113 //***************************************************************************
2115 static int _tsetenv( const _TCHAR
*lpVar
, const _TCHAR
*lpValue
)
2120 _TCHAR
*envstr
= (TCHAR
*)alloca( (_tcslen( lpVar
) + _tcslen( lpValue
) + 2) * sizeof(_TCHAR
) );
2122 _tcscpy( envstr
, lpVar
);
2123 _tcscat( envstr
, _T("=") );
2124 _tcscat( envstr
, lpValue
);
2126 return _tputenv( envstr
);
2129 static bool read_line( FILE *fp
, string
& rLine
)
2131 char szBuffer
[1024];
2132 bool bSuccess
= false;
2137 while ( !bEOL
&& fgets( szBuffer
, sizeof(szBuffer
), fp
) )
2139 int len
= strlen(szBuffer
);
2143 while ( len
&& szBuffer
[len
- 1] == '\n' )
2145 szBuffer
[--len
] = 0;
2149 line
.append( szBuffer
);
2156 static string
get_script_string( const char *pFileName
, const char *pKeyName
)
2158 FILE *fp
= fopen( pFileName
, "rt" );
2166 while ( read_line( fp
, line
) )
2168 line
= trim_string( line
);
2171 string::size_type iEqualSign
= line
.find( '=', 0 );
2173 if ( iEqualSign
!= string::npos
)
2175 string keyname
= line
.substr( 0, iEqualSign
);
2176 keyname
= trim_string( keyname
);
2178 string value
= line
.substr( sal::static_int_cast
<string::size_type
>(iEqualSign
+ 1) );
2179 value
= trim_string( value
);
2181 if ( value
.length() && '\"' == value
[0] )
2183 value
.erase( 0, 1 );
2185 string::size_type iQuotes
= value
.find( '"', 0 );
2187 if ( iQuotes
!= string::npos
)
2188 value
.erase( iQuotes
);
2191 if ( 0 == stricmp( keyname
.c_str(), pKeyName
) )
2205 static bool ReadBootstrapParams( CrashReportParams
&rParams
)
2207 TCHAR szBuffer
[256] = TEXT("");
2208 TCHAR szModuleName
[MAX_PATH
];
2209 TCHAR szModuleVersionName
[MAX_PATH
];
2210 TCHAR szDrive
[_MAX_DRIVE
];
2211 TCHAR szDir
[_MAX_DIR
];
2212 TCHAR szFName
[_MAX_FNAME
];
2213 TCHAR szExt
[_MAX_EXT
];
2214 TCHAR szReportServer
[MAX_HOSTNAME
];
2215 TCHAR szReportPort
[256];
2216 bool bSuccess
= false;
2218 GetModuleFileName( NULL
, szModuleName
, MAX_PATH
);
2219 _tsplitpath( szModuleName
, szDrive
, szDir
, szFName
, szExt
);
2220 _tmakepath( szModuleName
, szDrive
, szDir
, _T("bootstrap"), _T(".ini") );
2221 _tmakepath( szModuleVersionName
, szDrive
, szDir
, _T("version"), _T(".ini") );
2224 GetPrivateProfileString(
2227 TEXT("LibreOffice"),
2229 SAL_N_ELEMENTS(szBuffer
),
2233 TCHAR
*pVersion
= _tcschr( szBuffer
, ' ' );
2235 g_wstrProductKey
= szBuffer
;
2243 pVersion
= TEXT("");
2245 if ( !_tgetenv( _T("PRODUCTNAME") ) )
2247 _tsetenv( TEXT("PRODUCTNAME"), szBuffer
);
2249 if ( !_tgetenv( _T("PRODUCTVERSION") ) )
2250 _tsetenv( TEXT("PRODUCTVERSION"), pVersion
);
2253 GetPrivateProfileString(
2257 g_szBuildId
, SAL_N_ELEMENTS(g_szBuildId
),
2258 szModuleVersionName
);
2260 g_strDefaultLanguage
= get_script_string( "instdb.inf", "DefaultLanguage" );
2262 if ( GetPrivateProfileString(
2263 TEXT("ErrorReport"),
2264 TEXT("ErrorReportPort"),
2266 szReportPort
, SAL_N_ELEMENTS(szReportPort
),
2270 TCHAR
*endptr
= NULL
;
2272 unsigned short uReportPort
= (unsigned short)_tcstoul( szReportPort
, &endptr
, 10 );
2274 g_uReportPort
= uReportPort
;
2277 if ( GetPrivateProfileString(
2278 TEXT("ErrorReport"),
2279 TEXT("ErrorReportServer"),
2281 szReportServer
, SAL_N_ELEMENTS(szReportServer
),
2285 bSuccess
= 0 != WideCharToMultiByte( CP_ACP
, 0, szReportServer
, -1, g_szReportServerA
, SAL_N_ELEMENTS(g_szReportServerA
), NULL
, NULL
);
2288 LPCTSTR lpEnvString
;
2290 if ( 0 != (lpEnvString
= _tgetenv( _T("ERRORREPORT_PROXYSERVER") )) )
2291 rParams
.sProxyServer
= lpEnvString
;
2293 if ( 0 != (lpEnvString
= _tgetenv( _T("ERRORREPORT_PROXYPORT") )) )
2294 rParams
.sProxyPort
= lpEnvString
;
2296 if ( 0 != (lpEnvString
= _tgetenv( _T("ERRORREPORT_SENDERADDRESS") )) )
2297 rParams
.sEmail
= lpEnvString
;
2302 //***************************************************************************
2304 bool SendHTTPRequest(
2306 const char *pszServer
,
2307 unsigned short uPort
= 80,
2308 const char *pszProxyServer
= NULL
,
2309 unsigned short uProxyPort
= 8080 )
2311 bool success
= false;
2315 if ( pszProxyServer
)
2316 hp
= gethostbyname( pszProxyServer
);
2318 hp
= gethostbyname( pszServer
);
2322 SOCKET s
= socket( AF_INET
, SOCK_STREAM
, 0 );
2326 struct sockaddr_in address
;
2328 memcpy(&(address
.sin_addr
.s_addr
), *(hp
->h_addr_list
),sizeof(struct in_addr
));
2329 address
.sin_family
= AF_INET
;
2331 if ( pszProxyServer
)
2332 address
.sin_port
= ntohs( uProxyPort
);
2334 address
.sin_port
= ntohs( uPort
);
2336 if ( 0 == connect( s
, (struct sockaddr
*)&address
, sizeof(struct sockaddr_in
)) )
2338 fseek( fp
, 0, SEEK_END
);
2339 size_t length
= ftell( fp
);
2340 fseek( fp
, 0, SEEK_SET
);
2344 if ( pszProxyServer
)
2346 "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
2347 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2348 "Content-Length: %d\r\n"
2349 "SOAPAction: \"\"\r\n\r\n",
2356 "POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
2357 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2358 "Content-Length: %d\r\n"
2359 "SOAPAction: \"\"\r\n\r\n",
2363 if ( SOCKET_ERROR
!= send( s
, buffer
, strlen(buffer
), 0 ) )
2369 nBytes
= fread( buffer
, 1, sizeof(buffer
), fp
);
2372 success
= SOCKET_ERROR
!= send( s
, buffer
, nBytes
, 0 );
2373 } while( nBytes
&& success
);
2377 memset( buffer
, 0, sizeof(buffer
) );
2378 success
= SOCKET_ERROR
!= recv( s
, buffer
, sizeof(buffer
), 0 );
2381 char szHTTPSignature
[sizeof(buffer
)] = "";
2382 unsigned uHTTPReturnCode
= 0;
2384 sscanf( buffer
, "%s %d ", szHTTPSignature
, &uHTTPReturnCode
);
2385 success
= uHTTPReturnCode
== 200;
2399 //***************************************************************************
2401 static void WriteSOAPRequest( FILE *fp
)
2404 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
2405 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
2406 "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
2407 "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
2408 "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
2409 "xmlns:rds=\"urn:ReportDataService\"\n"
2410 "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
2411 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
2415 fprintf( fp
, "<rds:submitReport>\n" );
2416 fprintf( fp
, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
2417 fprintf( fp
, "<hash xsi:type=\"apache:Map\">\n" );
2419 FILE *fpin
= fopen( g_szReportFileNameA
, "r" );
2424 "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
2425 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2427 fprintf( fp
, "]]></value></item>\n" );
2431 fpin
= fopen( g_szCommentFileNameA
, "r" );
2436 "<key xsi:type=\"xsd:string\">description.txt</key>\n"
2437 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2439 fprintf( fp
, "]]></value></item>\n" );
2444 fpin
= fopen( g_szDumpFileNameA
, "rb" );
2447 FILE *fptemp
= _tmpfile();
2451 if ( base64_encode( fpin
, fptemp
) )
2453 fseek( fptemp
, 0, SEEK_SET
);
2456 "<key xsi:type=\"xsd:string\">user.dmp</key>\n"
2457 "<value xsi:type=\"xsd:string\">" );
2458 fcopy( fptemp
, fp
);
2459 fprintf( fp
, "</value></item>\n" );
2468 "</rds:submitReport>\n"
2469 "</SOAP-ENV:Body>\n"
2470 "</SOAP-ENV:Envelope>\n"
2474 //***************************************************************************
2476 struct RequestParams
2480 const char *lpServer
;
2481 unsigned short uPort
;
2482 const char *lpProxyServer
;
2483 unsigned short uProxyPort
;
2487 void _cdecl
SendingThread( void *lpArgs
)
2489 RequestParams
*pParams
= (RequestParams
*)lpArgs
;
2491 pParams
->success
= SendHTTPRequest( pParams
->fpin
, pParams
->lpServer
, pParams
->uPort
, pParams
->lpProxyServer
, pParams
->uProxyPort
);
2493 PostMessage( pParams
->hwndStatus
, WM_COMMAND
, IDOK
, 0 );
2496 //***************************************************************************
2498 BOOL CALLBACK
SendingStatusDialogProc(
2505 static RequestParams
*pRequest
= NULL
;
2506 static HANDLE hSendingThread
= NULL
;
2512 TCHAR szBuffer
[1024] = TEXT("");
2513 HINSTANCE hInstance
= (HINSTANCE
)GetWindowLong( hwndDlg
, GWL_HINSTANCE
);
2515 pRequest
= (RequestParams
*)lParam
;
2517 LoadAndFormatString( hInstance
, IDS_SENDING_REPORT_HEADER
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
2518 SetWindowText( hwndDlg
, szBuffer
);
2520 LoadAndFormatString( hInstance
, IDS_SENDING_REPORT_STATUS
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
2521 Static_SetText( GetDlgItem(hwndDlg
, IDC_SENDING_REPORT_STATUS
), szBuffer
);
2523 LoadAndFormatString( hInstance
, IDS_CANCEL_BUTTON
, szBuffer
, SAL_N_ELEMENTS(szBuffer
) );
2524 Button_SetText( GetDlgItem(hwndDlg
, IDCANCEL
), szBuffer
);
2526 pRequest
->hwndStatus
= hwndDlg
;
2528 hSendingThread
= (HANDLE
)_beginthread( SendingThread
, 0, pRequest
);
2532 switch ( LOWORD(wParam
) )
2535 TerminateThread( hSendingThread
, 0 );
2537 WaitForSingleObject( hSendingThread
, INFINITE
);
2538 CloseHandle( hSendingThread
);
2539 EndDialog( hwndDlg
, wParam
);
2550 //***************************************************************************
2552 bool SendCrashReport( HWND hwndParent
, const CrashReportParams
&rParams
)
2554 bool success
= false;
2555 char szProxyServer
[1024] = "";
2556 unsigned short uProxyPort
= 8080;
2557 TCHAR
*endptr
= NULL
;
2559 switch ( rParams
.uInternetConnection
)
2563 WideCharToMultiByte(
2564 CP_ACP
, 0, rParams
.sProxyServer
.c_str(), -1,
2565 szProxyServer
, sizeof(szProxyServer
), NULL
, NULL
);
2566 uProxyPort
= (unsigned short)_tcstoul( rParams
.sProxyPort
.c_str(), &endptr
, 10 );
2571 DWORD dwProxyEnable
= 0;
2573 RegReadValue( HKEY_CURRENT_USER
,
2574 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
2575 TEXT("ProxyEnable"),
2577 sizeof(dwProxyEnable
) );
2579 if ( dwProxyEnable
)
2581 TCHAR tszProxyServers
[1024] = TEXT("");
2583 if ( ERROR_SUCCESS
== RegReadValue( HKEY_CURRENT_USER
,
2584 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), TEXT("ProxyServer"),
2586 sizeof(tszProxyServers
) ) )
2588 TCHAR
*lpHttpStart
= _tcsstr( tszProxyServers
, TEXT("http=") );
2593 lpHttpStart
= tszProxyServers
;
2595 TCHAR
*lpHttpEnd
= _tcschr( lpHttpStart
, ';' );
2600 char szHTTPProxyServer
[1024] = "";
2601 WideCharToMultiByte( CP_ACP
, 0, lpHttpStart
, -1, szHTTPProxyServer
, sizeof(szHTTPProxyServer
), NULL
, NULL
);
2603 char *lpColon
= strchr( szHTTPProxyServer
, ':' );
2607 char *endptr
= NULL
;
2610 uProxyPort
= (unsigned short)strtoul( lpColon
+ 1, &endptr
, 10 );
2615 strcpy( szProxyServer
, szHTTPProxyServer
);
2626 FILE *fptemp
= _tmpfile();
2629 RequestParams request
;
2631 request
.success
= false;
2632 request
.fpin
= fptemp
;
2633 request
.lpServer
= REPORT_SERVER
;
2634 request
.uPort
= REPORT_PORT
;
2635 request
.lpProxyServer
= szProxyServer
[0] ? szProxyServer
: NULL
;
2636 request
.uProxyPort
= uProxyPort
;
2637 request
.hwndStatus
= NULL
;
2639 WriteSOAPRequest( fptemp
);
2640 fseek( fptemp
, 0, SEEK_SET
);
2644 int retid
= DialogBoxParam(
2645 GetModuleHandle(NULL
),
2646 MAKEINTRESOURCE(IDD_SENDING_STATUS
),
2648 SendingStatusDialogProc
,
2652 success
= request
.success
;
2654 if ( IDOK
== retid
)
2658 TCHAR szMessage
[1024];
2660 LoadAndFormatString( GetModuleHandle(NULL
), IDS_ERROR_MSG_PROXY
, szMessage
, SAL_N_ELEMENTS(szMessage
) );
2662 MessageBox( hwndParent
, szMessage
, NULL
, MB_ICONERROR
| MB_OK
);
2666 TCHAR szMessage
[1024];
2667 TCHAR szTitle
[1024];
2669 LoadAndFormatString( GetModuleHandle(NULL
), IDS_SENDING_REPORT_STATUS_FINISHED
, szMessage
, SAL_N_ELEMENTS(szMessage
) );
2670 LoadAndFormatString( GetModuleHandle(NULL
), IDS_SENDING_REPORT_HEADER
, szTitle
, SAL_N_ELEMENTS(szTitle
) );
2672 MessageBox( hwndParent
, szMessage
, szTitle
, MB_ICONINFORMATION
| MB_OK
);
2679 HANDLE hSendingThread
= (HANDLE
)_beginthread( SendingThread
, 0, (void *)&request
);
2681 WaitForSingleObject( hSendingThread
, INFINITE
);
2683 success
= request
.success
;
2686 TCHAR szMessage
[1024];
2688 LoadAndFormatString( GetModuleHandle(NULL
), IDS_ERROR_MSG_PROXY
, szMessage
, SAL_N_ELEMENTS(szMessage
) );
2689 _ftprintf( stderr
, _T("ERROR: %s\n"), szMessage
);
2693 TCHAR szMessage
[1024];
2695 LoadAndFormatString( GetModuleHandle(NULL
), IDS_SENDING_REPORT_STATUS_FINISHED
, szMessage
, SAL_N_ELEMENTS(szMessage
) );
2697 _ftprintf( stderr
, _T("SUCCESS: %s\n"), szMessage
);
2704 TCHAR szMessage
[1024];
2706 LoadAndFormatString( GetModuleHandle(NULL
), IDS_ERROR_MSG_DISK_FULL
, szMessage
, SAL_N_ELEMENTS(szMessage
) );
2709 MessageBox( hwndParent
, szMessage
, NULL
, MB_ICONERROR
| MB_OK
);
2711 _ftprintf( stderr
, _T("ERROR: %s\n"), szMessage
);
2717 //***************************************************************************
2720 int WINAPI
WinMain( HINSTANCE hInstance
, HINSTANCE
, LPSTR
/*lpCmdLine*/, int )
2722 int WINAPI
_tWinMain( HINSTANCE hInstance
, HINSTANCE
, LPTSTR
/*lpCmdLine*/, int )
2729 char **argv
= __argv
;
2732 char **argv
= new char *[argc
+ 1];
2734 for ( int argn
= 0; argn
< argc
; argn
++ )
2736 int nBytes
= WideCharToMultiByte( CP_ACP
, 0, __targv
[argn
], -1, NULL
, 0, NULL
, NULL
);
2737 argv
[argn
] = new char[nBytes
];
2738 WideCharToMultiByte( CP_ACP
, 0, __targv
[argn
], -1, argv
[argn
], nBytes
, NULL
, NULL
);
2742 char **argv
= __targv
;
2746 osl_setCommandArgs( argc
, argv
);
2748 PEXCEPTION_POINTERS pExceptionPointers
= NULL
;
2749 DWORD dwProcessId
= 0;
2750 DWORD dwThreadId
= 0;
2753 WORD wVersionRequested
;
2755 wVersionRequested
= MAKEWORD(1, 1);
2756 WSAStartup(wVersionRequested
, &wsaData
);
2758 CrashReportParams Params
;
2760 Params
.ReadFromRegistry();
2761 Params
.ReadFromEnvironment();
2763 if ( ReadBootstrapParams( Params
) &&
2764 ParseCommandArgs( &dwProcessId
, &pExceptionPointers
, &dwThreadId
) )
2768 if ( g_bLoadReport
)
2769 bGotDumpFile
= FindDumpFile();
2771 bGotDumpFile
= WriteDumpFile( dwProcessId
, pExceptionPointers
, dwThreadId
);
2775 boost::unordered_map
< string
, string
> aLibraries
;
2777 if ( g_bLoadReport
)
2779 g_fpStackFile
= _open_reportfile( _T(".stk"), _T("rb") );
2780 g_fpChecksumFile
= _open_reportfile( _T(".chk"), _T("rb") );
2784 if ( g_bSendReport
)
2786 g_fpStackFile
= _tmpfile();
2787 g_fpChecksumFile
= _tmpfile();
2791 g_fpStackFile
= _open_reportfile( _T(".stk"), _T("w+b") );
2792 g_fpChecksumFile
= _open_reportfile( _T(".chk"), _T("w+b") );
2794 FILE *fpUnsent
= _open_reportfile( _T(".lck"), _T("w+b") );
2797 fprintf( fpUnsent
, "Unsent\r\n" );
2802 WriteStackFile( g_fpStackFile
, aLibraries
, dwProcessId
, pExceptionPointers
);
2803 WriteChecksumFile( g_fpChecksumFile
, aLibraries
);
2804 WriteReportFile( &Params
);
2806 FILE *fpPreview
= _open_reportfile( _T(".prv"), _T("w+b") );
2810 FILE *fp
= fopen( g_szReportFileNameA
, "rb" );
2813 fcopy( fp
, fpPreview
);
2816 fclose( fpPreview
);
2820 if ( g_bSendReport
)
2822 InitCommonControls();
2824 // Actually this should never be true anymore
2825 if ( !g_bNoUserInterface
&& InitRichEdit() )
2828 INT_PTR result
= DialogBoxParam( hInstance
, MAKEINTRESOURCE(IDD_DIALOG_FRAME
), NULL
, DialogProc
, (LPARAM
)&Params
);
2838 WriteCommentFile( Params
.sComment
.c_str() );
2839 WriteReportFile( &Params
);
2840 if ( SendCrashReport( NULL
, Params
) )
2845 if ( g_szReportFileNameA
[0] )
2846 DeleteFileA( g_szReportFileNameA
);
2848 if ( g_szCommentFileNameA
[0] )
2849 DeleteFileA( g_szCommentFileNameA
);
2853 if ( g_szReportFileNameA
[0] )
2854 DeleteFileA( g_szReportFileNameA
);
2858 if ( g_szDumpFileNameA
[0] && g_bSendReport
)
2859 DeleteFileA( g_szDumpFileNameA
);
2861 if ( g_fpStackFile
)
2862 fclose( g_fpStackFile
);
2864 if ( g_fpChecksumFile
)
2865 fclose( g_fpChecksumFile
);
2873 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */