1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #define UNICODE
25 #define WIN32_LEAN_AND_MEAN
26 #if defined _MSC_VER
27 #pragma warning(push, 1)
28 #pragma warning(disable:4917)
29 #endif
30 #include <windows.h>
31 #include <windowsx.h>
32
33 #include <mapi.h>
34 #include <commctrl.h>
35 #include <commdlg.h>
36 #include <psapi.h>
37
38 #include <shellapi.h>
39 #include <shlobj.h>
40
41 #define _UNICODE
42 #include <tchar.h>
43
44 #define _RICHEDIT_VER 0x0200
45 #include <richedit.h>
46
47 #if defined _MSC_VER
48 #pragma warning(pop)
49 #endif
50
51 #if _RICHEDIT_VER >= 0x0200
52 #define RICHEDIT TEXT("riched20.dll")
53 #else
54 #define RICHEDIT TEXT("riched32.dll")
55 #endif
56
57 #include <systools/win32/uwinapi.h>
58 #include <rtl/digest.h>
59 #include <rtl/bootstrap.hxx>
60 #include <osl/file.hxx>
61 #include <osl/process.h>
62
63 #include <stdlib.h>
64 #include <stdio.h>
65 #include <io.h>
66 #include <fcntl.h>
67 #include <string>
68 #include <hash_map>
69 #include <winsock.h>
70 #include <malloc.h>
71 #include <process.h>
72
73 #include <_version.h>
74
75 #include "resource.h"
76 #include "base64.h"
77
78 #define FORMATBUFSIZE (8*1024)
79 #define MAX_TEXT_BUFFER (32*1024-1)
80 #define MAX_HOSTNAME (1024)
81
82 #ifdef __MINGW32__
83 #include <imagehlp.h>
84 #else
85 #include <dbghelp.h>
86 #endif
87
88 #ifdef _UNICODE
89 #define tstring wstring
90 #else
91 #define tstring string
92 #endif
93
94 using namespace ::std;
95
96
97 wstring g_wstrProductKey;
98 string g_strDefaultLanguage;
99 FILE *g_fpStackFile = NULL;
100 FILE *g_fpChecksumFile = NULL;
101 DWORD g_dwExceptionCode = 0;
102
103 CHAR g_szReportServerA[MAX_HOSTNAME] = "";
104 USHORT g_uReportPort = 80;
105
106 TCHAR g_szBuildId[256] = TEXT("");
107
108 TCHAR g_szDumpFileName[MAX_PATH] = TEXT("");
109
110 CHAR g_szDumpFileNameA[MAX_PATH] = "";
111 CHAR g_szCommentFileNameA[MAX_PATH] = "";
112 CHAR g_szReportFileNameA[MAX_PATH] = "";
113
114
115 bool g_bNoUserInterface = false;
116 bool g_bSendReport = false;
117 bool g_bLoadReport = false;
118
119 #define REPORT_SERVER g_szReportServerA
120 #define REPORT_PORT g_uReportPort
121
122
123 //***************************************************************************
124 // tmpfile from msvcrt creates the temporary file in the root of the current
125 // volume and can fail.
126
_xfopen(const _TCHAR * file,const _TCHAR * mode)127 static FILE *_xfopen( const _TCHAR *file, const _TCHAR *mode )
128 {
129 #ifdef UNICODE
130 if ( (LONG)GetVersion() < 0 )
131 {
132 char afile[MAX_PATH];
133 char amode[16];
134
135 WideCharToMultiByte( CP_ACP, 0, file, -1, afile, MAX_PATH, NULL, NULL );
136 WideCharToMultiByte( CP_ACP, 0, mode, -1, amode, 16, NULL, NULL );
137
138
139 return fopen( afile, amode );
140 }
141 else
142 #endif
143 return _tfopen( file, mode );
144 }
145
146
_tmpfile(void)147 static FILE *_tmpfile(void)
148 {
149 FILE *fp = NULL;
150
151 TCHAR szTempPath[MAX_PATH];
152
153 if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
154 {
155 TCHAR szFileName[MAX_PATH];
156
157 if ( GetTempFileName( szTempPath, TEXT("CRT"), 0, szFileName ) )
158 {
159 HANDLE hFile = CreateFile(
160 szFileName,
161 GENERIC_READ | GENERIC_WRITE,
162 0, NULL,
163 OPEN_EXISTING,
164 FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_NORMAL,
165 NULL );
166
167 if ( IsValidHandle( hFile ) )
168 {
169 int fd = _open_osfhandle( (int)hFile, 0 );
170
171 fp = _fdopen( fd, "w+b" );
172 }
173 }
174 }
175
176 return fp;
177 }
178 //***************************************************************************
179
GetCrashDataPath(LPTSTR szBuffer)180 static BOOL GetCrashDataPath( LPTSTR szBuffer )
181 {
182 ::rtl::OUString ustrValue = ::rtl::OUString::createFromAscii("${$OOO_BASE_DIR/program/bootstrap.ini:UserInstallation}");
183 ::rtl::Bootstrap::expandMacros( ustrValue );
184
185 if ( ustrValue.getLength() )
186 {
187 ustrValue += ::rtl::OUString::createFromAscii("/user/crashdata");
188
189 ::osl::FileBase::RC result = ::osl::Directory::createPath( ustrValue );
190
191 if ( ::osl::FileBase::E_None == result || ::osl::FileBase::E_EXIST == result )
192 {
193 ::rtl::OUString ustrPath;
194
195 result = ::osl::FileBase::getSystemPathFromFileURL( ustrValue, ustrPath );
196 if ( ::osl::FileBase::E_None == result )
197 {
198 _tcsncpy( szBuffer, reinterpret_cast<LPCWSTR>(ustrPath.getStr()), MAX_PATH );
199 return TRUE;
200 }
201 }
202 }
203
204 return FALSE;
205 }
206
207
_open_reportfile(LPCTSTR lpExt,LPCTSTR lpMode)208 static FILE *_open_reportfile( LPCTSTR lpExt, LPCTSTR lpMode )
209 {
210 FILE *fp = NULL;
211 TCHAR szAppDataPath[MAX_PATH] = _T("");
212
213 if ( GetCrashDataPath( szAppDataPath ) )
214 {
215 _tcscat( szAppDataPath, _T("\\crashdat") );
216 _tcscat( szAppDataPath, lpExt );
217
218 fp = _xfopen( szAppDataPath, lpMode );
219 }
220
221 return fp;
222 }
223
224 //***************************************************************************
225
226 struct CrashReportParams
227 {
228 BOOL fAllowContact;
229 tstring sEmail;
230 tstring sTitle;
231 tstring sComment;
232 ULONG uInternetConnection;
233 tstring sProxyServer;
234 tstring sProxyPort;
235
236 CrashReportParams();
237
238 void WriteToRegistry();
239 void ReadFromRegistry();
240 void ReadFromEnvironment();
241 };
242
243 bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams );
244 BOOL WriteCommentFile( LPCTSTR lpComment );
245
246 //***************************************************************************
247
RegReadValue(HKEY hBaseKey,LPCTSTR lpSubKey,LPCTSTR lpValueName,LPVOID lpData,DWORD cbData)248 LONG RegReadValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPVOID lpData, DWORD cbData )
249 {
250 HKEY hKey = NULL;
251 LONG lResult;
252
253 lResult = RegOpenKeyEx( hBaseKey, lpSubKey, 0, KEY_QUERY_VALUE, &hKey );
254
255 if ( ERROR_SUCCESS == lResult )
256 {
257 lResult = RegQueryValueEx( hKey, lpValueName, NULL, NULL, (LPBYTE)lpData, &cbData );
258 RegCloseKey( hKey );
259 }
260
261 return lResult;
262 }
263
264 //***************************************************************************
265
RegWriteValue(HKEY hBaseKey,LPCTSTR lpSubKey,LPCTSTR lpValueName,DWORD dwType,LPCVOID lpData,DWORD cbData)266 LONG RegWriteValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData )
267 {
268 HKEY hKey = NULL;
269 LONG lResult;
270
271 lResult = RegCreateKeyEx( hBaseKey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL );
272
273 if ( ERROR_SUCCESS == lResult )
274 {
275 lResult = RegSetValueEx( hKey, lpValueName, NULL, dwType, (CONST BYTE *)lpData, cbData );
276 RegCloseKey( hKey );
277 }
278
279 return lResult;
280 }
281
282 //***************************************************************************
283
CrashReportParams()284 CrashReportParams::CrashReportParams()
285 {
286 fAllowContact = FALSE;
287 sTitle = TEXT("");
288 sComment = TEXT("");
289 sEmail = TEXT("");
290 uInternetConnection = 0;
291 sProxyServer = TEXT("");
292 sProxyPort = TEXT("");
293 }
294
295 //***************************************************************************
296
ReadFromRegistry()297 void CrashReportParams::ReadFromRegistry()
298 {
299 TCHAR szBuffer[2048];
300
301 if ( ERROR_SUCCESS == RegReadValue(
302 HKEY_CURRENT_USER,
303 TEXT("SOFTWARE\\OpenOffice\\CrashReport"),
304 TEXT("HTTPProxyServer"),
305 szBuffer,
306 sizeof(szBuffer) ) )
307 sProxyServer = szBuffer;
308
309 DWORD dwProxyPort;
310
311 if ( ERROR_SUCCESS == RegReadValue(
312 HKEY_CURRENT_USER,
313 TEXT("SOFTWARE\\OpenOffice\\CrashReport"),
314 TEXT("HTTPProxyPort"),
315 &dwProxyPort,
316 sizeof(dwProxyPort) ) )
317 {
318 _stprintf( szBuffer, TEXT("%d"), dwProxyPort );
319 sProxyPort = szBuffer;
320 }
321
322 if ( ERROR_SUCCESS == RegReadValue(
323 HKEY_CURRENT_USER,
324 TEXT("SOFTWARE\\OpenOffice\\CrashReport"),
325 TEXT("ReturnAddress"),
326 szBuffer,
327 sizeof(szBuffer) ) )
328 sEmail = szBuffer;
329
330 RegReadValue(
331 HKEY_CURRENT_USER,
332 TEXT("SOFTWARE\\OpenOffice\\CrashReport"),
333 TEXT("AllowContact"),
334 &fAllowContact,
335 sizeof(fAllowContact) );
336
337 RegReadValue(
338 HKEY_CURRENT_USER,
339 TEXT("SOFTWARE\\OpenOffice\\CrashReport"),
340 TEXT("HTTPConnection"),
341 &uInternetConnection,
342 sizeof(uInternetConnection) );
343 }
344
345 //***************************************************************************
346
WriteToRegistry()347 void CrashReportParams::WriteToRegistry()
348 {
349 RegWriteValue(
350 HKEY_CURRENT_USER,
351 TEXT("SOFTWARE\\OpenOffice\\CrashReport"),
352 TEXT("HTTPProxyServer"), REG_SZ,
353 sProxyServer.c_str(),
354 sizeof(TCHAR) * (sProxyServer.length() + 1) );
355
356 LPTSTR endptr = NULL;
357 DWORD dwProxyPort = _tcstoul( sProxyPort.c_str(), &endptr, 10 );
358
359 RegWriteValue(
360 HKEY_CURRENT_USER,
361 TEXT("SOFTWARE\\OpenOffice\\CrashReport"),
362 TEXT("HTTPProxyPort"), REG_DWORD,
363 &dwProxyPort,
364 sizeof(DWORD) );
365
366 RegWriteValue(
367 HKEY_CURRENT_USER,
368 TEXT("SOFTWARE\\OpenOffice\\CrashReport"),
369 TEXT("AllowContact"), REG_DWORD,
370 &fAllowContact,
371 sizeof(DWORD) );
372
373
374 RegWriteValue(
375 HKEY_CURRENT_USER,
376 TEXT("SOFTWARE\\OpenOffice\\CrashReport"),
377 TEXT("HTTPConnection"), REG_DWORD,
378 &uInternetConnection,
379 sizeof(DWORD) );
380
381 RegWriteValue(
382 HKEY_CURRENT_USER,
383 TEXT("SOFTWARE\\OpenOffice\\CrashReport"),
384 TEXT("ReturnAddress"), REG_SZ,
385 sEmail.c_str(),
386 sizeof(TCHAR) * (sEmail.length() + 1) );
387 }
388
389 //***************************************************************************
390
ReadFromEnvironment()391 void CrashReportParams::ReadFromEnvironment()
392 {
393 TCHAR szBuffer[2048];
394
395 DWORD dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYSERVER"), szBuffer, elementsof(szBuffer) );
396
397 if ( dwResult && dwResult < elementsof(szBuffer) )
398 sProxyServer = szBuffer;
399
400 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPPROXYPORT"), szBuffer, elementsof(szBuffer) );
401
402 if ( dwResult && dwResult < elementsof(szBuffer) )
403 sProxyPort = szBuffer;
404
405 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_RETURNADDRESS"), szBuffer, elementsof(szBuffer) );
406
407 if ( dwResult && dwResult < elementsof(szBuffer) )
408 {
409 sEmail = szBuffer;
410 // fAllowContact = TRUE;
411 }
412
413 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_HTTPCONNECTIONTYPE"), szBuffer, elementsof(szBuffer) );
414
415 if ( dwResult && dwResult < elementsof(szBuffer) )
416 {
417 if ( 0 == _tcsicmp( szBuffer, _T("DIRECT") ) )
418 uInternetConnection = 1;
419 else if ( 0 == _tcsicmp( szBuffer, _T("MANUALPROXY") ) )
420 uInternetConnection = 2;
421 else if ( 0 == _tcsicmp( szBuffer, _T("SYSTEMDEFAULT") ) )
422 uInternetConnection = 0;
423 }
424
425 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_SUBJECT"), szBuffer, elementsof(szBuffer) );
426
427 if ( dwResult && dwResult < elementsof(szBuffer) )
428 sTitle = szBuffer;
429
430
431 dwResult = GetEnvironmentVariable( TEXT("ERRORREPORT_BODYFILE"), szBuffer, elementsof(szBuffer) );
432
433 if ( dwResult && dwResult < elementsof(szBuffer) )
434 {
435 FILE *fp = _xfopen( szBuffer, _T("rb") );
436
437 if ( fp )
438 {
439 CHAR aUTF8Buffer[256];
440 size_t nBytesRead;
441
442 sComment = TEXT("");
443
444 while ( 0 != (nBytesRead = fread( aUTF8Buffer, sizeof(aUTF8Buffer[0]), elementsof(aUTF8Buffer), fp )) )
445 {
446 TCHAR aBuffer[256+1];
447
448 DWORD dwCharacters = MultiByteToWideChar( CP_UTF8, 0, aUTF8Buffer, nBytesRead, aBuffer, elementsof(aBuffer) - 1 );
449 aBuffer[dwCharacters] = 0;
450 sComment += aBuffer;
451 }
452
453 fclose( fp );
454 }
455 }
456 }
457
458 //***************************************************************************
459
460 typedef BOOL (WINAPI *MiniDumpWriteDump_PROC)(
461 IN HANDLE hProcess,
462 IN DWORD ProcessId,
463 IN HANDLE hFile,
464 IN MINIDUMP_TYPE DumpType,
465 IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
466 IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
467 IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
468 );
469
470 //***************************************************************************
471
InitRichEdit()472 static BOOL WINAPI InitRichEdit()
473 {
474 return (NULL != LoadLibrary( RICHEDIT ));
475 }
476
477 //***************************************************************************
478
DeinitRichEdit()479 static BOOL WINAPI DeinitRichEdit()
480 {
481 return FreeLibrary( GetModuleHandle( RICHEDIT ) );
482 }
483
484 //***************************************************************************
485
trim_string(const string & rString)486 static string trim_string( const string& rString )
487 {
488 string temp = rString;
489
490 while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' )
491 temp.erase( 0, 1 );
492
493 string::size_type len = temp.length();
494
495 while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' )
496 {
497 temp.erase( len - 1, 1 );
498 len = temp.length();
499 }
500
501 return temp;
502 }
503
504 //***************************************************************************
505
LoadAndFormatString(HINSTANCE hInstance,UINT uID,LPTSTR lpBuffer,int nBufferMax)506 static int LoadAndFormatString( HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax )
507 {
508 TCHAR szBuffer[FORMATBUFSIZE];
509 TCHAR szBuffer2[FORMATBUFSIZE];
510
511 LoadString( hInstance, uID, szBuffer, elementsof(szBuffer) );
512
513 LPCTSTR src;
514 LPTSTR dest;
515 for ( dest = szBuffer2, src = szBuffer; *src; src++, dest++ )
516 {
517 switch ( *src )
518 {
519 case '~':
520 *dest = '&';
521 break;
522 case '\\':
523 switch ( *(++src) )
524 {
525 case 'n':
526 *dest = '\n';
527 break;
528 case 'r':
529 *dest = '\r';
530 break;
531 default:
532 *dest = *src;
533 break;
534 }
535 break;
536 default:
537 *dest = *src;
538 break;
539 }
540 }
541
542 *dest = *src;
543
544 return ExpandEnvironmentStrings( szBuffer2, lpBuffer, nBufferMax );
545 }
546
547
548 //***************************************************************************
549
wstring2utf8(const wstring & rString)550 static string wstring2utf8( const wstring &rString )
551 {
552 int nBufSize = WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, NULL, 0, NULL, FALSE );
553
554 LPSTR pBuffer = (LPSTR)alloca( nBufSize );
555
556 WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, pBuffer, nBufSize, NULL, FALSE );
557
558 return string( pBuffer );
559 }
560
561 //***************************************************************************
562
xml_encode(const string & rString)563 static string xml_encode( const string &rString )
564 {
565 string temp = rString;
566 string::size_type pos = 0;
567
568 // First replace all occurrences of '&' because it may occur in further
569 // encoded characters too
570
571 for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 )
572 temp.replace( pos, 1, "&" );
573
574 for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 )
575 temp.replace( pos, 1, "<" );
576
577 for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 )
578 temp.replace( pos, 1, ">" );
579
580 return temp;
581 }
582
583 //***************************************************************************
584
fcopy(FILE * fpin,FILE * fpout)585 static size_t fcopy( FILE *fpin, FILE *fpout )
586 {
587 char buffer[1024];
588 size_t nBytes;
589 size_t nBytesWritten = 0;
590
591 if ( fpin && fpout )
592 {
593 while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) )
594 {
595 nBytesWritten += fwrite( buffer, 1, nBytes, fpout );
596 }
597 }
598
599 return nBytesWritten;
600 }
601
602 //***************************************************************************
603
GetModuleDirectory(HMODULE hModule)604 static string GetModuleDirectory( HMODULE hModule )
605 {
606 TCHAR szModuleName[MAX_PATH] = TEXT("");
607 TCHAR szDrive[_MAX_DRIVE];
608 TCHAR szDir[_MAX_DIR];
609 TCHAR szFName[_MAX_FNAME];
610 TCHAR szExt[_MAX_EXT];
611
612 if ( GetModuleFileName( hModule, szModuleName, MAX_PATH ) )
613 {
614 _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
615 _tmakepath( szModuleName, szDrive, szDir, _T(""), _T("") );
616 }
617
618 CHAR szModuleNameUTF8[MAX_PATH] = "";
619
620 WideCharToMultiByte( CP_UTF8, 0, szModuleName, -1, szModuleNameUTF8, elementsof(szModuleNameUTF8), NULL, NULL );
621 return string( szModuleNameUTF8 );
622 }
623
624 //***************************************************************************
625
GetFileDirectory(const string & rFilePath)626 string GetFileDirectory( const string& rFilePath )
627 {
628 string aDir = rFilePath;
629 size_t pos = aDir.rfind( '\\' );
630
631 if ( string::npos != pos )
632 aDir.erase( pos + 1 );
633 else
634 aDir = "";
635
636 return aDir;
637 }
638
639 //***************************************************************************
640
GetFileName(const string & rFilePath)641 string GetFileName( const string& rFilePath )
642 {
643 string aName = rFilePath;
644 size_t pos = aName.rfind( '\\' );
645
646 if ( string::npos != pos )
647 return aName.substr( pos + 1 );
648 else
649 return aName;
650 }
651
652 //***************************************************************************
653
WriteReportFile(CrashReportParams * pParams)654 BOOL WriteReportFile( CrashReportParams *pParams )
655 {
656 BOOL fSuccess = FALSE;
657 TCHAR szTempPath[MAX_PATH];
658
659 if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
660 {
661 TCHAR szFileName[MAX_PATH];
662
663 if ( GetTempFileName( szTempPath, TEXT("RPM"), 0, szFileName ) )
664 {
665 HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
666
667 if ( hFile )
668 {
669 int fd = _open_osfhandle( (LONG)hFile, _O_TEXT );
670 FILE *fp = _fdopen( fd, "w+t" );
671 CHAR szTitle[1024] = "";
672 CHAR szBuildId[1024] = "";
673 CHAR szEmail[1024] = "";
674 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
675
676 WideCharToMultiByte( CP_UTF8, 0, pParams->sTitle.c_str(), -1, szTitle, sizeof(szTitle), NULL, NULL );
677 WideCharToMultiByte( CP_UTF8, 0, g_szBuildId, -1, szBuildId, sizeof(szBuildId), NULL, NULL );
678 WideCharToMultiByte( CP_UTF8, 0, pParams->sEmail.c_str(), -1, szEmail, sizeof(szEmail), NULL, NULL );
679
680 fprintf( fp,
681 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
682 "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
683 "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
684 "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n",
685 pszUserType ? pszUserType : "",
686 pParams->fAllowContact ? "true" : "false",
687 pParams->fAllowContact ? xml_encode(szEmail).c_str() : ""
688 );
689
690 fprintf( fp,
691 "<reportmail:title>%s</reportmail:title>\n",
692 xml_encode(szTitle).c_str() );
693
694 fprintf( fp,
695 "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain;charset=UTF-8\" class=\"UserComment\"/>\n"
696 "<reportmail:attachment name=\"user.dmp\" media-type=\"application/octet-stream\" class=\"UserDump\"/>\n"
697 "</reportmail:mail>\n"
698
699 "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" procpath=\"%s\" exceptiontype=\"0x%08X\" product=\"%s\"/>\n",
700 szBuildId,
701 _INPATH,
702 xml_encode(g_strDefaultLanguage).c_str(),
703 xml_encode(GetModuleDirectory( NULL )).c_str(),
704 g_dwExceptionCode,
705 xml_encode(wstring2utf8(g_wstrProductKey)).c_str()
706 );
707
708 OSVERSIONINFO VersionInfo;
709
710 ZeroMemory( &VersionInfo, sizeof(VersionInfo) );
711 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo );
712
713 GetVersionEx( &VersionInfo );
714
715 fprintf( fp,
716 "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
717 "<systeminfo:System name=\"%s\" version=\"%d.%d\" build=\"%d\" locale=\"0x%08x\"/>\n"
718 ,
719 VER_PLATFORM_WIN32_NT == VersionInfo.dwPlatformId ? "Windows NT" : "Windows",
720 VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion,
721 VersionInfo.dwBuildNumber,
722 GetUserDefaultLangID()
723
724 );
725 fprintf( fp, "<systeminfo:CPU type=\"x86\"/>\n" );
726 fprintf( fp, "</systeminfo:systeminfo>\n" );
727
728 fseek( g_fpStackFile, 0, SEEK_SET );
729 fcopy( g_fpStackFile, fp );
730
731 fseek( g_fpChecksumFile, 0, SEEK_SET );
732 fcopy( g_fpChecksumFile, fp );
733
734 fprintf( fp, "</errormail:errormail>\n" );
735
736 fclose( fp );
737
738 fSuccess = TRUE;
739
740 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szReportFileNameA, MAX_PATH, NULL, NULL );
741 }
742
743 if ( !fSuccess )
744 DeleteFile( szFileName );
745 }
746 }
747
748 return fSuccess;
749 }
750
751 //***************************************************************************
752
SaveDumpFile(HWND hwndOwner)753 static BOOL SaveDumpFile( HWND hwndOwner )
754 {
755 OPENFILENAME ofn;
756 TCHAR szFileName[MAX_PATH] = TEXT("");
757
758 ZeroMemory( &ofn, sizeof(ofn) );
759 ofn.lStructSize = sizeof(ofn);
760
761 ofn.hwndOwner = hwndOwner;
762 ofn.lpstrFilter = TEXT("*.dmp\0*.dmp\0*.*\0*.*\0");
763 ofn.lpstrFile = szFileName;
764 ofn.nMaxFile = MAX_PATH;
765 ofn.Flags = OFN_ENABLESIZING | OFN_LONGNAMES | OFN_OVERWRITEPROMPT;
766 ofn.lpstrDefExt = TEXT("dmp");
767
768 if ( GetSaveFileName( &ofn ) )
769 {
770 return CopyFile( g_szDumpFileName, szFileName, FALSE );
771 }
772
773
774 return FALSE;
775 }
776
777 //***************************************************************************
778
ScreenToClientRect(HWND hwnd,LPRECT lprc)779 static BOOL ScreenToClientRect( HWND hwnd, LPRECT lprc )
780 {
781 return ScreenToClient( hwnd, (LPPOINT)&lprc->left ) && ScreenToClient( hwnd, (LPPOINT)&lprc->right );
782 }
783
SetWindowRect(HWND hwnd,const RECT * lprc,BOOL fRepaint)784 static BOOL SetWindowRect( HWND hwnd, const RECT *lprc, BOOL fRepaint )
785 {
786 return MoveWindow( hwnd, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, fRepaint );
787 }
788
789 #define GM_LOX 0x01
790 #define GM_HIX 0x02
791 #define GM_LOY 0x04
792 #define GM_HIY 0x08
793
SetGrowMode(HWND hwnd,DWORD dwGrowMode)794 static BOOL SetGrowMode( HWND hwnd, DWORD dwGrowMode )
795 {
796 return SetProp( hwnd, TEXT("GrowMode"), (HANDLE)dwGrowMode );
797 }
798
GetGrowMode(HWND hwnd)799 static DWORD GetGrowMode( HWND hwnd )
800 {
801 return (DWORD)GetProp( hwnd, TEXT("GrowMode") );
802 }
803
GrowWindow(HWND hwnd,LONG dxClient,LONG dyClient,BOOL fRepaint)804 static BOOL GrowWindow( HWND hwnd, LONG dxClient, LONG dyClient, BOOL fRepaint )
805 {
806 DWORD dwGrowMode = GetGrowMode( hwnd );
807 RECT rc;
808
809 GetWindowRect( hwnd, &rc );
810
811 if ( dwGrowMode & GM_LOX )
812 rc.left += dxClient;
813 if ( dwGrowMode & GM_HIX )
814 rc.right += dxClient;
815 if ( dwGrowMode & GM_LOY )
816 rc.top += dyClient;
817 if ( dwGrowMode & GM_HIY )
818 rc.bottom += dyClient;
819
820 ScreenToClientRect( GetParent( hwnd ), &rc );
821 SetWindowRect( hwnd, &rc, fRepaint );
822
823 return TRUE;
824 }
825
GrowChildWindows(HWND hwnd,LPARAM lParam)826 BOOL CALLBACK GrowChildWindows(
827 HWND hwnd, // handle to child window
828 LPARAM lParam // application-defined value
829 )
830 {
831 LONG cx = (SHORT)LOWORD( lParam );
832 LONG cy = (SHORT)HIWORD( lParam );
833
834 GrowWindow( hwnd, cx, cy, TRUE );
835
836 return TRUE;
837 }
838
839 /*
840 BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
841 {
842 HFONT aFont = *((HFONT*) lParam);
843 HDC hDC = GetDC( hwndChild );
844 SelectObject( hDC, aFont );
845 ReleaseDC( hwndChild, hDC );
846 return TRUE;
847 }
848
849 void ApplySystemFont( HWND hwndDlg )
850 {
851 NONCLIENTMETRICSA aNonClientMetrics;
852 aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
853 if ( SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
854 {
855 HFONT aSysFont = CreateFontIndirectA( &aNonClientMetrics.lfMessageFont );
856 EnumChildWindows(hwndDlg, EnumChildProc, (LPARAM) &aSysFont);
857 }
858 }
859 */
860
PreviewDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)861 BOOL CALLBACK PreviewDialogProc(
862 HWND hwndDlg,
863 UINT uMsg,
864 WPARAM wParam,
865 LPARAM lParam
866 )
867 {
868 static RECT rcClient;
869
870 switch ( uMsg )
871 {
872 case WM_SIZE:
873 {
874 LONG cx = LOWORD( lParam );
875 LONG cy = HIWORD( lParam );
876 LONG dxClient, dyClient;
877
878 dxClient = cx - rcClient.right;
879 dyClient = cy - rcClient.bottom;
880
881 EnumChildWindows( hwndDlg, GrowChildWindows, MAKELONG( (SHORT)dxClient, (SHORT)dyClient) );
882
883 GetClientRect( hwndDlg, &rcClient );
884 }
885 break;
886 case WM_INITDIALOG:
887 {
888 GetClientRect( hwndDlg, &rcClient );
889 SetGrowMode( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GM_HIX | GM_HIY );
890 SetGrowMode( GetDlgItem(hwndDlg, IDOK), GM_LOX | GM_HIX | GM_LOY | GM_HIY );
891
892 CrashReportParams *pParams = (CrashReportParams *)lParam;
893
894 TCHAR szBuffer[256] = TEXT("");
895 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
896 HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
897
898 GetWindowText( hwndParent, szBuffer, elementsof(szBuffer) );
899 SetWindowText( hwndDlg, szBuffer );
900
901 LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) );
902 Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
903
904 basic_string<TCHAR> aString;
905
906 aString.append( pParams->sTitle );
907 aString.append( _T("\r\n\r\n") );
908 aString.append( pParams->sComment );
909 aString.append( _T("\r\n---------- report ----------\r\n") );
910
911 FILE *fp = fopen( g_szReportFileNameA, "r" );
912
913 if ( fp )
914 {
915 char buf[1024];
916
917 while ( fgets( buf, elementsof(buf), fp ) != NULL )
918 {
919 WCHAR bufW[1024];
920
921 MultiByteToWideChar( CP_UTF8, 0, buf, -1, bufW, elementsof(bufW) );
922
923 aString.append( bufW );
924 }
925
926 fclose( fp );
927 }
928
929 aString.append( _T("\r\n---------- stack ----------\r\n") );
930
931 fp = fopen( g_szDumpFileNameA, "rb" );
932
933 if ( fp )
934 {
935 unsigned char buf[16];
936 int count;
937
938 do
939 {
940 int i;
941
942 count = fread( buf, sizeof(buf[0]), sizeof(buf)/sizeof(buf[0]), fp );
943
944 for ( i = 0; i < count; i++ )
945 {
946 TCHAR output[16];
947
948 _sntprintf( output, elementsof(output), _T("%02X\x20"), buf[i] );
949 aString.append( output );
950 }
951 for ( ; i < elementsof(buf); i++ )
952 {
953 aString.append( _T("\x20\x20\x20") );
954 }
955
956 for ( i = 0; i < count; i++ )
957 {
958 TCHAR output[2];
959
960 if ( (int)buf[i] >= 0x20 && (int)buf[i] <= 0x7F )
961 output[0] = (TCHAR)buf[i];
962 else
963 output[0] = '.';
964 output[1] = 0;
965 aString.append( output );
966 }
967
968 aString.append( _T("\r\n") );
969
970 } while ( count );
971
972 fclose( fp );
973 }
974
975 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), aString.c_str() );
976
977
978 SetWindowFont( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GetStockObject( SYSTEM_FIXED_FONT ), TRUE );
979 }
980 return TRUE;
981 case WM_COMMAND:
982 switch ( LOWORD(wParam) )
983 {
984 case IDOK:
985 case IDCANCEL:
986 EndDialog( hwndDlg, wParam );
987 return TRUE;
988 }
989 break;
990 default:
991 break;
992 }
993
994 return FALSE;
995 }
996 //***************************************************************************
997
PreviewReport(HWND hwndParent,CrashReportParams * pParams)998 static void PreviewReport( HWND hwndParent, CrashReportParams *pParams )
999 {
1000 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE );
1001
1002 WriteReportFile( pParams );
1003
1004 DialogBoxParam(
1005 hInstance,
1006 MAKEINTRESOURCE(IDD_PREVIEW_FRAME),
1007 hwndParent,
1008 PreviewDialogProc,
1009 (LPARAM)pParams
1010 );
1011
1012 DeleteFileA( g_szReportFileNameA );
1013 }
1014 //***************************************************************************
UpdateOptionsDialogControls(HWND hwndDlg)1015 void UpdateOptionsDialogControls( HWND hwndDlg )
1016 {
1017 if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED )
1018 {
1019 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), TRUE );
1020 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), TRUE );
1021 }
1022 else
1023 {
1024 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), FALSE );
1025 EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), FALSE );
1026 }
1027 }
1028
1029 //***************************************************************************
1030
OptionsDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)1031 BOOL CALLBACK OptionsDialogProc(
1032 HWND hwndDlg,
1033 UINT uMsg,
1034 WPARAM wParam,
1035 LPARAM lParam
1036 )
1037 {
1038 static CrashReportParams *pParams;
1039
1040 switch ( uMsg )
1041 {
1042 case WM_INITDIALOG:
1043 {
1044 TCHAR szBuffer[1024] = TEXT("");
1045 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
1046 //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
1047
1048 pParams = (CrashReportParams *)lParam;
1049
1050 LoadAndFormatString( hInstance, IDS_OPTIONS_CAPTION, szBuffer, elementsof(szBuffer) );
1051 SetWindowText( hwndDlg, szBuffer );
1052
1053 LoadAndFormatString( hInstance, IDS_PROXY_SETTINGS_HEADER, szBuffer, elementsof(szBuffer) );
1054 Static_SetText( GetDlgItem(hwndDlg, IDC_PROXY_SETTINGS), szBuffer );
1055
1056 LoadAndFormatString( hInstance, IDS_PROXY_SYSTEM, szBuffer, elementsof(szBuffer) );
1057 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM), szBuffer );
1058
1059 LoadAndFormatString( hInstance, IDS_PROXY_DIRECT, szBuffer, elementsof(szBuffer) );
1060 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT), szBuffer );
1061
1062 LoadAndFormatString( hInstance, IDS_PROXY_MANUAL, szBuffer, elementsof(szBuffer) );
1063 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL), szBuffer );
1064
1065 LoadAndFormatString( hInstance, IDS_LABEL_PROXYSERVER, szBuffer, elementsof(szBuffer) );
1066 Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYSERVER), szBuffer );
1067
1068 LoadAndFormatString( hInstance, IDS_LABEL_PROXYPORT, szBuffer, elementsof(szBuffer) );
1069 Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYPORT), szBuffer );
1070
1071 LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) );
1072 Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
1073
1074 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
1075 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
1076
1077 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), pParams->sProxyServer.c_str() );
1078 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), pParams->sProxyPort.c_str() );
1079
1080 Button_SetCheck( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM + pParams->uInternetConnection), BST_CHECKED );
1081
1082 SendMessage(
1083 GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION),
1084 EM_SETBKGNDCOLOR,
1085 (WPARAM)FALSE,
1086 GetSysColor( COLOR_3DFACE ) );
1087 LoadAndFormatString( hInstance, IDS_PROXY_DESCRIPTION, szBuffer, elementsof(szBuffer) );
1088 Edit_SetText( GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), szBuffer );
1089
1090 UpdateOptionsDialogControls( hwndDlg );
1091 }
1092 return TRUE;
1093 case WM_COMMAND:
1094 switch ( LOWORD(wParam) )
1095 {
1096 case IDC_RADIO_SYSTEM:
1097 case IDC_RADIO_DIRECT:
1098 case IDC_RADIO_MANUAL:
1099 if ( BN_CLICKED == HIWORD(wParam) )
1100 UpdateOptionsDialogControls( hwndDlg );
1101 break;
1102 case IDOK:
1103 {
1104 TCHAR szBuffer[1024];
1105
1106 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), szBuffer, elementsof(szBuffer) );
1107 pParams->sProxyServer = szBuffer;
1108
1109 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), szBuffer, elementsof(szBuffer) );
1110 pParams->sProxyPort = szBuffer;
1111
1112 if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT) ) & BST_CHECKED )
1113 pParams->uInternetConnection = 1;
1114 else if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED )
1115 pParams->uInternetConnection = 2;
1116 else
1117 pParams->uInternetConnection = 0;
1118 }
1119 case IDCANCEL:
1120 EndDialog( hwndDlg, wParam );
1121 return TRUE;
1122 }
1123 break;
1124 default:
1125 break;
1126 }
1127
1128 return FALSE;
1129 }
1130
1131 //***************************************************************************
1132
OptionsDialog(HWND hwndParent,CrashReportParams * pParams)1133 static void OptionsDialog( HWND hwndParent, CrashReportParams *pParams )
1134 {
1135 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE );
1136
1137 if ( IDOK == DialogBoxParam(
1138 hInstance,
1139 MAKEINTRESOURCE(IDD_OPTIONS_FRAME),
1140 hwndParent,
1141 OptionsDialogProc,
1142 (LPARAM)pParams
1143 ) )
1144 pParams->WriteToRegistry();
1145
1146 }
1147 //***************************************************************************
1148
UpdateReportDialogControls(HWND hwndDlg)1149 void UpdateReportDialogControls( HWND hwndDlg )
1150 {
1151 EnableWindow(
1152 GetDlgItem(hwndDlg, IDC_EDIT_EMAIL),
1153 Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE );
1154 EnableWindow(
1155 GetDlgItem(hwndDlg, IDC_LABEL_EMAIL),
1156 Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE );
1157 }
1158
1159 //***************************************************************************
1160
ReportDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM)1161 BOOL CALLBACK ReportDialogProc(
1162 HWND hwndDlg,
1163 UINT uMsg,
1164 WPARAM wParam,
1165 LPARAM
1166 )
1167 {
1168 switch ( uMsg )
1169 {
1170 case WM_INITDIALOG:
1171 {
1172 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1173 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1174 TCHAR szBuffer[FORMATBUFSIZE];
1175
1176 LoadAndFormatString( hInstance, IDS_REPORT_INTRO, szBuffer, elementsof(szBuffer) );
1177 Static_SetText( GetDlgItem(hwndDlg, IDC_REPORT_INTRO), szBuffer );
1178
1179 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT3), szBuffer );
1180
1181 LoadAndFormatString( hInstance, IDS_ENTER_TITLE, szBuffer, elementsof(szBuffer) );
1182 Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_TITLE), szBuffer );
1183
1184 LoadAndFormatString( hInstance, IDS_ENTER_DESCRIPTION, szBuffer, elementsof(szBuffer) );
1185 Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_DESCRIPTION), szBuffer );
1186
1187 LoadAndFormatString( hInstance, IDS_SHOW_REPORT_BUTTON, szBuffer, elementsof(szBuffer) );
1188 Button_SetText( GetDlgItem(hwndDlg, IDC_SHOW_REPORT), szBuffer );
1189
1190 LoadAndFormatString( hInstance, IDS_SAVE_REPORT_BUTTON, szBuffer, elementsof(szBuffer) );
1191 Button_SetText( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), szBuffer );
1192
1193 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
1194 if ( pszUserType )
1195 ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_SHOW );
1196 else
1197 ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_HIDE );
1198
1199 LoadAndFormatString( hInstance, IDS_OPTIONS_BUTTON, szBuffer, elementsof(szBuffer) );
1200 Button_SetText( GetDlgItem(hwndDlg, IDC_OPTIONS), szBuffer );
1201
1202 LoadAndFormatString( hInstance, IDS_ALLOW_CONTACT, szBuffer, elementsof(szBuffer) );
1203 Button_SetText( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), szBuffer );
1204 Button_SetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), pParams->fAllowContact ? BST_CHECKED : BST_UNCHECKED );
1205
1206 LoadAndFormatString( hInstance, IDS_LABEL_EMAIL, szBuffer, elementsof(szBuffer) );
1207 Button_SetText( GetDlgItem(hwndDlg, IDC_LABEL_EMAIL), szBuffer );
1208
1209 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), pParams->sEmail.c_str() );
1210
1211 UpdateReportDialogControls( hwndDlg );
1212 }
1213 return TRUE;
1214 case WM_SHOWWINDOW:
1215 if ( (BOOL)wParam )
1216 {
1217 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1218 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1219 TCHAR szBuffer[FORMATBUFSIZE];
1220
1221 LoadAndFormatString( hInstance, IDS_REPORT_CAPTION, szBuffer, elementsof(szBuffer) );
1222 SetWindowText( GetParent(hwndDlg), szBuffer );
1223
1224 LoadAndFormatString( hInstance, IDS_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
1225 SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
1226
1227 LoadAndFormatString( hInstance, IDS_DONOT_SEND_BUTTON, szBuffer, elementsof(szBuffer) );
1228 Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer );
1229
1230
1231 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), TRUE );
1232 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), TRUE );
1233 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), FALSE );
1234
1235 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), pParams->sTitle.c_str() );
1236 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), pParams->sComment.c_str() );
1237
1238 /*
1239 SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE,
1240 GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE) | BS_DEFPUSHBUTTON );
1241 SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE,
1242 GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE) &~ BS_DEFPUSHBUTTON );
1243 */
1244 SetFocus( GetDlgItem(hwndDlg,IDC_EDIT_TITLE) );
1245 }
1246 break;
1247 case WM_COMMAND:
1248 switch ( LOWORD(wParam) )
1249 {
1250 case IDC_SHOW_REPORT:
1251 {
1252 TCHAR szBuffer[32767];
1253
1254 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1255
1256 pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT) ) ? TRUE : FALSE;
1257
1258 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), szBuffer, elementsof(szBuffer) );
1259 pParams->sTitle = szBuffer;
1260
1261 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), szBuffer, elementsof(szBuffer) );
1262 pParams->sComment = szBuffer;
1263
1264 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), szBuffer, elementsof(szBuffer) );
1265 pParams->sEmail = szBuffer;
1266
1267 PreviewReport( GetParent(hwndDlg), pParams );
1268 }
1269 return TRUE;
1270 case IDC_SAVE_REPORT:
1271 SaveDumpFile( GetParent(hwndDlg) );
1272 return TRUE;
1273 case IDC_OPTIONS:
1274 {
1275 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
1276 OptionsDialog( GetParent(hwndDlg), pParams );
1277 }
1278 return TRUE;
1279 case IDC_ALLOW_CONTACT:
1280 if ( BN_CLICKED == HIWORD(wParam) )
1281 UpdateReportDialogControls( hwndDlg );
1282 return TRUE;
1283 }
1284 break;
1285 default:
1286 break;
1287 }
1288
1289 return FALSE;
1290 }
1291 //***************************************************************************
1292
WelcomeDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)1293 BOOL CALLBACK WelcomeDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
1294 {
1295 switch ( uMsg )
1296 {
1297 case WM_INITDIALOG:
1298 {
1299 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1300 HWND hwndRichEdit = GetDlgItem(hwndDlg, IDC_RICHEDIT21);
1301 TCHAR szBuffer[FORMATBUFSIZE];
1302 TCHAR szBuffer2[FORMATBUFSIZE];
1303 TCHAR szURL[256];
1304 TCHAR szCaption[256];
1305
1306 SendMessage(
1307 hwndRichEdit,
1308 EM_SETBKGNDCOLOR,
1309 (WPARAM)FALSE,
1310 GetSysColor( COLOR_3DFACE ) );
1311
1312 SendMessage( hwndRichEdit, EM_SETEVENTMASK, 0, ENM_LINK );
1313 SendMessage( hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0 );
1314
1315 LoadAndFormatString( hInstance, IDS_WELCOME_BODY1, szBuffer, elementsof(szBuffer) );
1316 LoadAndFormatString( hInstance, IDS_WELCOME_BODY2, szBuffer2, elementsof(szBuffer2) );
1317 _tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) );
1318 LoadAndFormatString( hInstance, IDS_WELCOME_BODY3, szBuffer2, elementsof(szBuffer2) );
1319 _tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) );
1320 LoadString( hInstance, IDS_PRIVACY_URL, szURL, elementsof(szURL) );
1321 _tcsncat( szBuffer, szURL, elementsof(szBuffer) );
1322 SetWindowText( hwndRichEdit, szBuffer );
1323
1324 LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szCaption, elementsof(szCaption) );
1325 SetWindowText( GetParent(hwndDlg), szCaption );
1326
1327 }
1328 return TRUE;
1329 case WM_SHOWWINDOW:
1330 if ( (BOOL)wParam )
1331 {
1332 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1333 TCHAR szBuffer[FORMATBUFSIZE];
1334
1335 LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szBuffer, elementsof(szBuffer) );
1336 SetWindowText( GetParent(hwndDlg), szBuffer );
1337
1338 LoadAndFormatString( hInstance, IDS_WELCOME_HEADER, szBuffer, elementsof(szBuffer) );
1339 SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
1340
1341 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
1342 Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer );
1343
1344 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), FALSE );
1345 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), FALSE );
1346 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), TRUE );
1347
1348 SetFocus( GetDlgItem(GetParent(hwndDlg),IDNEXT) );
1349 }
1350 break;
1351 case WM_NOTIFY:
1352 {
1353 LPNMHDR pnmh = (LPNMHDR)lParam;
1354
1355 if ( pnmh->idFrom == IDC_RICHEDIT21 && pnmh->code == EN_LINK )
1356 {
1357 ENLINK *plink = (ENLINK*)lParam;
1358
1359 if ( plink->msg == WM_LBUTTONUP )
1360 {
1361 TCHAR szBuffer[256];
1362 TEXTRANGE range;
1363
1364 range.chrg = plink->chrg;
1365 range.lpstrText = szBuffer;
1366
1367 SendMessage( pnmh->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&range );
1368
1369 ShellExecute( hwndDlg, NULL, szBuffer, NULL, NULL, SW_SHOWDEFAULT );
1370 }
1371
1372 }
1373 }
1374 break;
1375 default:
1376 break;
1377 }
1378
1379 return FALSE;
1380 }
1381 //***************************************************************************
1382
DialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)1383 BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
1384 {
1385 static HWND hwndPages[2] = { NULL };
1386 static int iActualPage = 0;
1387
1388 switch ( uMsg )
1389 {
1390 case WM_INITDIALOG:
1391 {
1392 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
1393 TCHAR szBuffer[FORMATBUFSIZE];
1394
1395 SetWindowLong( hwndDlg, GWL_USERDATA, (LONG)lParam );
1396 hwndPages[0] = CreateDialog(
1397 hInstance,
1398 MAKEINTRESOURCE(IDD_WELCOME_PAGE),
1399 hwndDlg,
1400 WelcomeDialogProc );
1401
1402 hwndPages[1] = CreateDialog(
1403 hInstance,
1404 MAKEINTRESOURCE(IDD_REPORT_PAGE),
1405 hwndDlg,
1406 ReportDialogProc );
1407
1408 CHARFORMAT chfmt;
1409
1410 chfmt.cbSize = sizeof(chfmt);
1411 chfmt.dwMask = CFM_BOLD;
1412 chfmt.dwEffects = CFE_BOLD;
1413
1414 SendMessage(
1415 GetDlgItem(hwndDlg, IDC_HEADER),
1416 EM_SETCHARFORMAT,
1417 SCF_ALL,
1418 (LPARAM)&chfmt );
1419
1420 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
1421 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
1422
1423 LoadAndFormatString( hInstance, IDS_NEXT_BUTTON, szBuffer, elementsof(szBuffer) );
1424 Button_SetText( GetDlgItem(hwndDlg, IDNEXT), szBuffer );
1425
1426 LoadAndFormatString( hInstance, IDS_SEND_BUTTON, szBuffer, elementsof(szBuffer) );
1427 Button_SetText( GetDlgItem(hwndDlg, IDFINISH), szBuffer );
1428
1429 LoadAndFormatString( hInstance, IDS_BACK_BUTTON, szBuffer, elementsof(szBuffer) );
1430 Button_SetText( GetDlgItem(hwndDlg, IDBACK), szBuffer );
1431
1432 ShowWindow( hwndPages[1], SW_HIDE );
1433 ShowWindow( hwndPages[0], SW_SHOW );
1434
1435 // Let Crash Reporter window stay on top of all other windows
1436 SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
1437 }
1438 return FALSE;
1439 case WM_CTLCOLORSTATIC:
1440 return (BOOL)CreateSolidBrush(GetSysColor(COLOR_WINDOW));
1441 case WM_COMMAND:
1442 switch ( LOWORD(wParam) )
1443 {
1444 case IDBACK:
1445 if ( iActualPage > 0 )
1446 {
1447 ShowWindow( hwndPages[iActualPage], SW_HIDE );
1448 ShowWindow( hwndPages[--iActualPage], SW_SHOW );
1449 }
1450 return TRUE;
1451 case IDNEXT:
1452 if ( iActualPage < elementsof(hwndPages) - 1 )
1453 {
1454 ShowWindow( hwndPages[iActualPage], SW_HIDE );
1455 ShowWindow( hwndPages[++iActualPage], SW_SHOW );
1456 }
1457 return TRUE;
1458 case IDFINISH:
1459 {
1460 TCHAR szBuffer[32767];
1461 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( hwndDlg, GWL_USERDATA );
1462
1463 pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndPages[1], IDC_ALLOW_CONTACT) ) ? TRUE : FALSE;
1464
1465 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_TITLE), szBuffer, elementsof(szBuffer) );
1466 pParams->sTitle = szBuffer;
1467
1468 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_DESCRIPTION), szBuffer, elementsof(szBuffer) );
1469 pParams->sComment = szBuffer;
1470
1471 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_EMAIL), szBuffer, elementsof(szBuffer) );
1472 pParams->sEmail = szBuffer;
1473
1474 if ( pParams->fAllowContact && !pParams->sEmail.length() )
1475 {
1476 TCHAR szMessage[MAX_TEXT_BUFFER];
1477
1478 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_NOEMAILADDRESS, szMessage, elementsof(szMessage) );
1479
1480 MessageBox( hwndDlg, szMessage, NULL, MB_ICONERROR | MB_OK );
1481 break; // Don't end the dialog
1482 }
1483 else
1484 {
1485 pParams->WriteToRegistry();
1486
1487 WriteCommentFile( pParams->sComment.c_str() );
1488 WriteReportFile( pParams );
1489
1490 if ( !SendCrashReport( hwndDlg, *pParams ) )
1491 break; // Don't end the dialog
1492 }
1493 }
1494 // Fallthrough !!!
1495 case IDCANCEL:
1496 EndDialog( hwndDlg, wParam );
1497 return TRUE;
1498 }
1499 break;
1500 default:
1501 break;
1502 }
1503
1504 return FALSE;
1505 }
1506
1507
1508
1509 //*****************************************************************************
1510 //* Generate MD5 checksum
1511 //*****************************************************************************
1512
1513 #define MAGIC_DESCRIPTION_FILLER 'x'
1514 #define MAGIC_DESCRIPTION_COUNT 80
1515
repatch_soffice_exe(void * pBuffer,size_t nBufSize)1516 static void repatch_soffice_exe( void *pBuffer, size_t nBufSize )
1517 {
1518 wchar_t DescriptionBuffer[MAGIC_DESCRIPTION_COUNT];
1519
1520 memset( DescriptionBuffer, 0, sizeof(DescriptionBuffer) );
1521 wcsncpy( DescriptionBuffer, g_wstrProductKey.c_str(), elementsof(DescriptionBuffer) - 1 );
1522
1523 bool bPatched = false;
1524
1525 do
1526 {
1527 void *pFound = memchr( pBuffer, ((char *)DescriptionBuffer)[0], nBufSize );
1528
1529 if ( pFound )
1530 {
1531 size_t distance = (char *)pFound - (char *)pBuffer;
1532
1533 if ( nBufSize >= distance )
1534 {
1535 nBufSize -= distance;
1536
1537 if ( nBufSize >= sizeof(DescriptionBuffer) &&
1538 0 == memcmp( pFound, DescriptionBuffer, sizeof(DescriptionBuffer) ) )
1539 {
1540 for ( int i = 0; i < 80; i++ )
1541 {
1542 ((wchar_t *)pFound)[i] = MAGIC_DESCRIPTION_FILLER;
1543 }
1544 bPatched = true;
1545 }
1546 else
1547 {
1548 pBuffer = (void *)(((char *)pFound) + 1);
1549 nBufSize--;
1550 }
1551 }
1552 else
1553 nBufSize = 0;
1554 }
1555 else
1556 nBufSize = 0;
1557 } while ( !bPatched && nBufSize );
1558 }
1559
1560 // Normalize executable/library images to prevent different MD5 checksums due
1561 // to a different PE header date/checksum (this doesn't affect the code/data
1562 // sections of a executable/library. Please see tools/source/bootstrp/md5.cxx
1563 // where the same method is also used. The tool so_checksum creates the MD5
1564 // checksums during build time. You have to make sure that both methods use the
1565 // same algorithm otherwise there could be problems with stack reports.
normalize_pe_image(sal_uInt8 * buffer,size_t nBufferSize)1566 static void normalize_pe_image(sal_uInt8* buffer, size_t nBufferSize)
1567 {
1568 const int OFFSET_PE_OFFSET = 0x3c;
1569 const int OFFSET_COFF_TIMEDATESTAMP = 4;
1570 const int PE_SIGNATURE_SIZE = 4;
1571 const int COFFHEADER_SIZE = 20;
1572 const int OFFSET_PE_OPTIONALHEADER_CHECKSUM = 64;
1573
1574 // Check the header part of the file buffer
1575 if (buffer[0] == 'M' && buffer[1] == 'Z')
1576 {
1577 unsigned long PEHeaderOffset = (long)buffer[OFFSET_PE_OFFSET];
1578 if (PEHeaderOffset < nBufferSize-4)
1579 {
1580 if ( buffer[PEHeaderOffset] == 'P' &&
1581 buffer[PEHeaderOffset+1] == 'E' &&
1582 buffer[PEHeaderOffset+2] == 0 &&
1583 buffer[PEHeaderOffset+3] == 0 )
1584 {
1585 PEHeaderOffset += PE_SIGNATURE_SIZE;
1586 if (PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP < nBufferSize-4)
1587 {
1588 // Set timedatestamp and checksum fields to a normalized
1589 // value to enforce the same MD5 checksum for identical
1590 // Windows executables/libraries.
1591 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP] = 0;
1592 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+1] = 0;
1593 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+2] = 0;
1594 buffer[PEHeaderOffset+OFFSET_COFF_TIMEDATESTAMP+3] = 0;
1595 }
1596
1597 if (PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM < nBufferSize-4)
1598 {
1599 // Set checksum to a normalized value
1600 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM] = 0;
1601 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+1] = 0;
1602 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+2] = 0;
1603 buffer[PEHeaderOffset+COFFHEADER_SIZE+OFFSET_PE_OPTIONALHEADER_CHECKSUM+3] = 0;
1604 }
1605 }
1606 }
1607 }
1608 }
1609
calc_md5_checksum(const char * filename,sal_uInt8 * pChecksum,sal_uInt32 nChecksumLen)1610 static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
1611 {
1612 const int MINIMAL_FILESIZE = 512;
1613
1614 sal_uInt32 nBytesProcessed = 0;
1615
1616 FILE *fp = fopen( filename, "rb" );
1617
1618 if ( fp )
1619 {
1620 long nFileSize;
1621
1622 if ( 0 == fseek( fp, 0, SEEK_END ) && -1 != (nFileSize = ftell(fp)) )
1623 {
1624 rewind( fp );
1625
1626 sal_uInt8 *pBuffer = new sal_uInt8[nFileSize];
1627 size_t nBytesRead = fread( pBuffer, 1, nFileSize, fp );
1628
1629 if ( sal::static_int_cast<long>(nBytesRead) == nFileSize )
1630 {
1631 if ( 0 == stricmp( GetFileName(filename).c_str(), "soffice.bin" ) )
1632 repatch_soffice_exe( pBuffer, nBytesRead );
1633 else if ( nFileSize > MINIMAL_FILESIZE )
1634 normalize_pe_image( pBuffer, nBytesRead );
1635
1636 rtlDigestError error = rtl_digest_MD5 (
1637 pBuffer, nBytesRead,
1638 pChecksum, nChecksumLen );
1639
1640 if ( rtl_Digest_E_None == error )
1641 nBytesProcessed = nBytesRead;
1642 }
1643
1644 delete[] pBuffer;
1645 }
1646
1647 fclose( fp );
1648
1649 }
1650
1651 return nBytesProcessed;
1652 }
1653
1654 #if 0
1655 static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
1656 {
1657 sal_uInt32 nBytesProcessed = 0;
1658
1659 FILE *fp = fopen( filename, "rb" );
1660
1661 if ( fp )
1662 {
1663 rtlDigest digest = rtl_digest_createMD5();
1664
1665 if ( digest )
1666 {
1667 size_t nBytesRead;
1668 sal_uInt8 buffer[4096];
1669 rtlDigestError error = rtl_Digest_E_None;
1670
1671 while ( rtl_Digest_E_None == error &&
1672 0 != (nBytesRead = fread( buffer, 1, sizeof(buffer), fp )) )
1673 {
1674 error = rtl_digest_updateMD5( digest, buffer, nBytesRead );
1675 nBytesProcessed += nBytesRead;
1676 }
1677
1678 if ( rtl_Digest_E_None == error )
1679 {
1680 error = rtl_digest_getMD5( digest, pChecksum, nChecksumLen );
1681 }
1682
1683 if ( rtl_Digest_E_None != error )
1684 nBytesProcessed = 0;
1685
1686 rtl_digest_destroyMD5( digest );
1687 }
1688
1689 fclose( fp );
1690 }
1691
1692 return nBytesProcessed;
1693 }
1694
1695 #endif
1696 //***************************************************************************
1697
WriteStackFile(FILE * fout,hash_map<string,string> & rLibraries,DWORD dwProcessId,PEXCEPTION_POINTERS pExceptionPointers)1698 static bool WriteStackFile( FILE *fout, hash_map< string, string >& rLibraries, DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers )
1699 {
1700 bool fSuccess = false;
1701
1702 if ( fout && dwProcessId && pExceptionPointers )
1703 {
1704 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
1705
1706 if ( IsValidHandle(hProcess) )
1707 {
1708 EXCEPTION_POINTERS aExceptionPointers;
1709 CONTEXT aContextRecord;
1710
1711 ReadProcessMemory(
1712 hProcess,
1713 pExceptionPointers,
1714 &aExceptionPointers,
1715 sizeof(aExceptionPointers),
1716 NULL );
1717
1718 ReadProcessMemory(
1719 hProcess,
1720 aExceptionPointers.ContextRecord,
1721 &aContextRecord,
1722 sizeof(aContextRecord),
1723 NULL );
1724
1725 STACKFRAME frame;
1726
1727 ZeroMemory( &frame, sizeof(frame) );
1728 frame.AddrPC.Offset = aContextRecord.Eip;
1729 frame.AddrPC.Mode = AddrModeFlat;
1730 frame.AddrFrame.Offset = aContextRecord.Ebp;
1731 frame.AddrFrame.Mode = AddrModeFlat;
1732
1733 BOOL bSuccess;
1734 int frameNum = 0;
1735
1736 SymInitialize( hProcess, NULL, TRUE );
1737
1738 fprintf( fout, "<errormail:Stack type=\"Win32\">\n" );
1739
1740 do
1741 {
1742 fSuccess = true;
1743
1744 bSuccess = StackWalk( IMAGE_FILE_MACHINE_I386,
1745 hProcess,
1746 NULL,
1747 &frame,
1748 &aContextRecord,
1749 (PREAD_PROCESS_MEMORY_ROUTINE)ReadProcessMemory,
1750 SymFunctionTableAccess,
1751 SymGetModuleBase,
1752 NULL );
1753
1754 if ( bSuccess )
1755 {
1756 // Note: ImageHelp ANSI functions do not have an A postfix while
1757 // Unicode versions have a W postfix. There's no macro
1758 // that depends on define UNICODE
1759
1760 IMAGEHLP_MODULE moduleInfo;
1761
1762 ZeroMemory( &moduleInfo, sizeof(moduleInfo) );
1763 moduleInfo.SizeOfStruct = sizeof(moduleInfo);
1764
1765 if ( SymGetModuleInfo( hProcess, frame.AddrPC.Offset, &moduleInfo ) )
1766 {
1767 rLibraries[ GetFileName( moduleInfo.LoadedImageName ).c_str() ] = moduleInfo.LoadedImageName;
1768
1769 DWORD dwRelOffset = 0;
1770 BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 256 ];
1771 PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
1772
1773 ZeroMemory( symbolBuffer, sizeof(symbolBuffer) );
1774 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
1775 pSymbol->MaxNameLength = 256;
1776
1777 if ( SymGetSymFromAddr( hProcess, frame.AddrPC.Offset, &dwRelOffset, pSymbol ) )
1778 fprintf( fout, "<errormail:StackInfo " \
1779 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" ordinal=\"%s+0x%p\" name=\"%s\" path=\"%s\"/>\n",
1780 frameNum,
1781 frame.AddrPC.Offset,
1782 frame.AddrPC.Offset - moduleInfo.BaseOfImage,
1783 xml_encode(pSymbol->Name).c_str(),
1784 frame.AddrPC.Offset - pSymbol->Address,
1785 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
1786 xml_encode( GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
1787 );
1788 else
1789 fprintf( fout, "<errormail:StackInfo " \
1790 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" name=\"%s\" path=\"%s\"/>\n",
1791 frameNum,
1792 frame.AddrPC.Offset,
1793 frame.AddrPC.Offset - moduleInfo.BaseOfImage,
1794 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
1795 xml_encode(GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
1796 );
1797 }
1798 else
1799 fprintf( fout, "<errormail:StackInfo pos=\"%d\" ip=\"0x%p\"/>\n",
1800 frameNum,
1801 frame.AddrPC.Offset
1802 );
1803
1804 frameNum++;
1805 }
1806
1807 } while ( bSuccess );
1808
1809 fprintf( fout, "</errormail:Stack>\n" );
1810
1811 SymCleanup( hProcess );
1812
1813 CloseHandle( hProcess );
1814 }
1815
1816 }
1817
1818 return fSuccess;
1819 }
1820
WriteChecksumFile(FILE * fchksum,const hash_map<string,string> & rLibraries)1821 bool WriteChecksumFile( FILE *fchksum, const hash_map< string, string >& rLibraries )
1822 {
1823 bool success = false;
1824
1825 if ( fchksum && rLibraries.size() )
1826 {
1827 fprintf( fchksum, "<errormail:Checksums type=\"MD5\">\n" );
1828
1829 hash_map< string, string >::const_iterator iter;
1830
1831 for ( iter = rLibraries.begin();
1832 iter != rLibraries.end();
1833 iter++ )
1834 {
1835 sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5];
1836 sal_uInt32 nBytesProcessed = calc_md5_checksum(
1837 iter->second.c_str(),
1838 checksum, sizeof(checksum) );
1839
1840 if ( nBytesProcessed )
1841 {
1842 fprintf( fchksum, "<errormail:Checksum sum=\"0x" );
1843 for ( int i = 0; i < sizeof(checksum); fprintf( fchksum, "%02X", checksum[i++] ) );
1844 fprintf( fchksum, "\" bytes=\"%d\" file=\"%s\"/>\n",
1845 nBytesProcessed,
1846 GetFileName( iter->first ).c_str() );
1847 }
1848 }
1849
1850 fprintf( fchksum, "</errormail:Checksums>\n" );
1851
1852 success = true;
1853 }
1854
1855 return success;
1856 }
1857
1858 //***************************************************************************
1859
FindDumpFile()1860 BOOL FindDumpFile()
1861 {
1862 TCHAR szFileName[MAX_PATH];
1863
1864 if ( GetCrashDataPath( szFileName ) )
1865 {
1866 _tcscat( szFileName, _T("\\crashdat.dmp") );
1867
1868 HANDLE hFile = CreateFile(
1869 szFileName,
1870 GENERIC_READ,
1871 0, NULL,
1872 OPEN_EXISTING,
1873 FILE_ATTRIBUTE_NORMAL, NULL );
1874
1875 if ( hFile )
1876 {
1877 CloseHandle( hFile );
1878
1879 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
1880 _tcscpy( g_szDumpFileName, szFileName );
1881
1882 return TRUE;
1883 }
1884 }
1885
1886 return FALSE;
1887 }
1888
WriteDumpFile(DWORD dwProcessId,PEXCEPTION_POINTERS pExceptionPointers,DWORD dwThreadId)1889 BOOL WriteDumpFile( DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers, DWORD dwThreadId )
1890 {
1891 BOOL fSuccess = FALSE;
1892 PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam = NULL;
1893 MINIDUMP_EXCEPTION_INFORMATION ExceptionParam;
1894
1895 HMODULE hDbgHelp = LoadLibrary( _T("DBGHELP.DLL" ) );
1896 MiniDumpWriteDump_PROC pMiniDumpWriteDump = NULL;
1897
1898 if ( hDbgHelp )
1899 {
1900 pMiniDumpWriteDump = (MiniDumpWriteDump_PROC)GetProcAddress( hDbgHelp, "MiniDumpWriteDump" );
1901
1902 if ( !pMiniDumpWriteDump )
1903 {
1904 FreeLibrary( hDbgHelp );
1905 return false;
1906 }
1907 }
1908
1909 if ( !pMiniDumpWriteDump )
1910 return false;
1911
1912 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
1913
1914 if ( IsValidHandle(hProcess) )
1915 {
1916 TCHAR szTempPath[MAX_PATH];
1917
1918 // if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
1919 if ( GetCrashDataPath( szTempPath ) )
1920 {
1921 TCHAR szFileName[MAX_PATH];
1922
1923 // if ( GetTempFileName( szTempPath, TEXT("DMP"), 0, szFileName ) )
1924 _tcscpy( szFileName, szTempPath );
1925 _tcscat( szFileName, _T("\\crashdat.dmp") );
1926 {
1927 HANDLE hFile = CreateFile(
1928 szFileName,
1929 GENERIC_READ | GENERIC_WRITE,
1930 0, NULL,
1931 // OPEN_EXISTING,
1932 CREATE_ALWAYS,
1933 FILE_ATTRIBUTE_NORMAL, NULL );
1934
1935 if ( hFile )
1936 {
1937 if ( pExceptionPointers && dwThreadId )
1938 {
1939 ExceptionParam.ThreadId = dwThreadId;
1940 ExceptionParam.ExceptionPointers = pExceptionPointers;
1941 ExceptionParam.ClientPointers = TRUE;
1942
1943 EXCEPTION_POINTERS aExceptionPointers;
1944 EXCEPTION_RECORD aExceptionRecord;
1945
1946 ReadProcessMemory(
1947 hProcess,
1948 pExceptionPointers,
1949 &aExceptionPointers,
1950 sizeof(aExceptionPointers),
1951 NULL );
1952
1953
1954 ReadProcessMemory(
1955 hProcess,
1956 aExceptionPointers.ExceptionRecord,
1957 &aExceptionRecord,
1958 sizeof(aExceptionRecord),
1959 NULL );
1960
1961 g_dwExceptionCode = aExceptionRecord.ExceptionCode;
1962
1963 lpExceptionParam = &ExceptionParam;
1964 }
1965
1966 fSuccess = pMiniDumpWriteDump( hProcess, dwProcessId, hFile, MiniDumpNormal, lpExceptionParam, NULL, NULL );
1967
1968 CloseHandle( hFile );
1969
1970 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
1971 _tcscpy( g_szDumpFileName, szFileName );
1972 }
1973
1974 if ( !fSuccess )
1975 DeleteFile( szFileName );
1976 }
1977 }
1978
1979 CloseHandle( hProcess );
1980 }
1981
1982 FreeLibrary( hDbgHelp );
1983
1984 return fSuccess;
1985 }
1986
1987 //***************************************************************************
1988
FindProcessForImage(LPCTSTR lpImagePath)1989 static DWORD FindProcessForImage( LPCTSTR lpImagePath )
1990 {
1991 DWORD dwProcessId = 0;
1992 DWORD aProcesses[1024];
1993 DWORD dwSize = 0;
1994 TCHAR szShortImagePath[MAX_PATH];
1995
1996 if ( GetShortPathName( lpImagePath, szShortImagePath, elementsof(szShortImagePath) ) &&
1997 EnumProcesses( aProcesses, sizeof(aProcesses), &dwSize ) )
1998 {
1999 unsigned nProcesses = dwSize / sizeof(aProcesses[0]);
2000
2001 for ( unsigned i = 0; !dwProcessId && i < nProcesses; i++ )
2002 {
2003 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] );
2004
2005 if ( IsValidHandle(hProcess) )
2006 {
2007 TCHAR szModulePath[MAX_PATH+1];
2008
2009 if ( GetModuleFileNameEx( hProcess, NULL, szModulePath, MAX_PATH ) )
2010 {
2011 TCHAR szShortModulePath[MAX_PATH];
2012
2013 if ( GetShortPathName( szModulePath, szShortModulePath, elementsof(szShortModulePath) ) )
2014 {
2015 if ( 0 == _tcsicmp( szShortModulePath, szShortImagePath ) )
2016 dwProcessId = aProcesses[i];
2017 }
2018 }
2019
2020 CloseHandle( hProcess );
2021 }
2022 }
2023 }
2024
2025 return dwProcessId;
2026 }
2027 //***************************************************************************
2028
ParseCommandArgs(LPDWORD pdwProcessId,PEXCEPTION_POINTERS * ppException,LPDWORD pdwThreadId)2029 static bool ParseCommandArgs( LPDWORD pdwProcessId, PEXCEPTION_POINTERS* ppException, LPDWORD pdwThreadId )
2030 {
2031 int argc = __argc;
2032 #ifdef __MINGW32__
2033 #ifdef _UNICODE
2034 TCHAR **argv = reinterpret_cast<TCHAR **>(alloca((argc+1)*sizeof(WCHAR*)));
2035 int *sizes = reinterpret_cast<int *>(alloca(argc*sizeof(int)));
2036 int argsize=0;
2037 char **ptr;
2038 int i;
2039 ptr=__argv;
2040 for (i = 0; i < argc; ++i)
2041 {
2042 sizes[i]=MultiByteToWideChar(CP_ACP, 0, *ptr, -1, NULL, 0);
2043 argsize+=sizes[i]+1;
2044 ++ptr;
2045 }
2046 ++argsize;
2047 TCHAR *args = reinterpret_cast<TCHAR *>(alloca(argsize*sizeof(WCHAR)));
2048 ptr=__argv;
2049 TCHAR *cptr=args;
2050 for (i = 0; i < argc; ++i)
2051 {
2052 argv[i]=cptr;
2053 MultiByteToWideChar( CP_ACP, 0, *ptr, -1, cptr, sizes[i] );
2054 ++ptr;
2055 cptr+=sizes[i];
2056 *cptr=0;
2057 ++cptr;
2058 }
2059 argv[i]=cptr;
2060 *cptr=0;
2061 #else
2062 TCHAR **argv = __argv;
2063 #endif
2064 #else
2065 TCHAR **argv = __targv;
2066 #endif
2067 bool bSuccess = true;
2068
2069 for ( int argn = 1; bSuccess && argn < argc; argn++ )
2070 {
2071 if ( 0 == _tcsicmp( argv[argn], _T("-h") ) ||
2072 0 == _tcsicmp( argv[argn], _T("/h") ) ||
2073 0 == _tcsicmp( argv[argn], _T("-?") ) ||
2074 0 == _tcsicmp( argv[argn], _T("/?") ) ||
2075 0 == _tcsicmp( argv[argn], _T("/help") ) ||
2076 0 == _tcsicmp( argv[argn], _T("-help") ) ||
2077 0 == _tcsicmp( argv[argn], _T("--help") )
2078 )
2079 {
2080 HINSTANCE hInstance = GetModuleHandle(NULL);
2081 TCHAR szUsage[FORMATBUFSIZE];
2082 TCHAR szProcess[FORMATBUFSIZE];
2083 TCHAR szProcessDescription[FORMATBUFSIZE];
2084 TCHAR szHelpDescription[FORMATBUFSIZE];
2085
2086 LoadAndFormatString( hInstance, IDS_MSG_CMDLINE_USAGE, szUsage, elementsof(szUsage) );
2087 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID, szProcess, elementsof(szProcess) );
2088 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID_DESCRIPTION, szProcessDescription, elementsof(szProcessDescription) );
2089 LoadAndFormatString( hInstance, IDS_MSG_PARAM_HELP_DESCRIPTION, szHelpDescription, elementsof(szHelpDescription) );
2090
2091 _tprintf(
2092 TEXT("\n%s: crashrep %s\n\n")
2093 TEXT("/?, -h[elp] %s\n\n")
2094 TEXT("%-20s %s\n\n"),
2095 szUsage, szProcess, szHelpDescription, szProcess, szProcessDescription
2096 );
2097
2098 return true;
2099 }
2100 else if ( 0 == _tcsicmp( argv[argn], _T("-p") ) ||
2101 0 == _tcsicmp( argv[argn], _T("/p") ) )
2102 {
2103 if ( ++argn < argc )
2104 *pdwProcessId = _tcstoul( argv[argn], NULL, 0 );
2105 else
2106 bSuccess = false;
2107 }
2108 else if ( 0 == _tcsicmp( argv[argn], _T("-excp") ) ||
2109 0 == _tcsicmp( argv[argn], _T("/excp") ) )
2110 {
2111 if ( ++argn < argc )
2112 *ppException = (PEXCEPTION_POINTERS)_tcstoul( argv[argn], NULL, 0 );
2113 else
2114 bSuccess = false;
2115 }
2116 else if ( 0 == _tcsicmp( argv[argn], _T("-t") ) ||
2117 0 == _tcsicmp( argv[argn], _T("/t") ) )
2118 {
2119 if ( ++argn < argc )
2120 *pdwThreadId = _tcstoul( argv[argn], NULL, 0 );
2121 else
2122 bSuccess = false;
2123 }
2124 else if ( 0 == _tcsicmp( argv[argn], _T("-noui") ) ||
2125 0 == _tcsicmp( argv[argn], _T("/noui") ) )
2126 {
2127 g_bNoUserInterface = true;
2128 }
2129 else if ( 0 == _tcsicmp( argv[argn], _T("-send") ) ||
2130 0 == _tcsicmp( argv[argn], _T("/send") ) )
2131 {
2132 g_bSendReport = true;
2133 }
2134 else if ( 0 == _tcsicmp( argv[argn], _T("-load") ) ||
2135 0 == _tcsicmp( argv[argn], _T("/load") ) )
2136 {
2137 g_bLoadReport = true;
2138 }
2139 else // treat parameter as image path
2140 {
2141 TCHAR szImagePath[MAX_PATH];
2142 LPTSTR lpImageName;
2143
2144 if ( GetFullPathName( argv[argn], MAX_PATH, szImagePath, &lpImageName ) )
2145 {
2146 DWORD dwProcessId = FindProcessForImage( szImagePath );
2147
2148 if ( dwProcessId )
2149 *pdwProcessId = dwProcessId;
2150 else
2151 bSuccess = false;
2152 }
2153 }
2154 }
2155
2156 if ( !*pdwProcessId && !g_bLoadReport )
2157 {
2158 TCHAR szImagePath[MAX_PATH];
2159 LPTSTR lpImageName;
2160
2161 if ( GetFullPathName( TEXT("soffice.exe"), MAX_PATH, szImagePath, &lpImageName ) )
2162 {
2163 DWORD dwProcessId = FindProcessForImage( szImagePath );
2164
2165 if ( dwProcessId )
2166 *pdwProcessId = dwProcessId;
2167 else
2168 bSuccess = false;
2169 }
2170 }
2171
2172 return bSuccess;
2173 }
2174
2175 //***************************************************************************
2176
WriteCommentFile(LPCTSTR lpComment)2177 BOOL WriteCommentFile( LPCTSTR lpComment )
2178 {
2179 BOOL fSuccess = FALSE;
2180 TCHAR szTempPath[MAX_PATH];
2181
2182 if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
2183 {
2184 TCHAR szFileName[MAX_PATH];
2185
2186 if ( GetTempFileName( szTempPath, TEXT("CMT"), 0, szFileName ) )
2187 {
2188 HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
2189
2190 if ( hFile )
2191 {
2192 DWORD dwBytesWritten;
2193
2194 int needed = WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, NULL, 0, NULL, NULL );
2195 if ( needed )
2196 {
2197 char *lpCommentUTF8 = (char *)alloca( needed );
2198 WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, lpCommentUTF8, needed, NULL, NULL );
2199 fSuccess = WriteFile( hFile, lpCommentUTF8, strlen(lpCommentUTF8), &dwBytesWritten, NULL );
2200 }
2201 else
2202 fSuccess = TRUE;
2203
2204
2205 CloseHandle( hFile );
2206
2207 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szCommentFileNameA, MAX_PATH, NULL, NULL );
2208 }
2209
2210 if ( !fSuccess )
2211 DeleteFile( szFileName );
2212 }
2213 }
2214
2215 return fSuccess;
2216 }
2217
2218 //***************************************************************************
2219
_tsetenv(const _TCHAR * lpVar,const _TCHAR * lpValue)2220 static int _tsetenv( const _TCHAR *lpVar, const _TCHAR *lpValue )
2221 {
2222 if ( !lpValue )
2223 lpValue = _T("");
2224
2225 _TCHAR *envstr = (TCHAR *)alloca( (_tcslen( lpVar ) + _tcslen( lpValue ) + 2) * sizeof(_TCHAR) );
2226
2227 _tcscpy( envstr, lpVar );
2228 _tcscat( envstr, _T("=") );
2229 _tcscat( envstr, lpValue );
2230
2231 return _tputenv( envstr );
2232 }
2233
read_line(FILE * fp,string & rLine)2234 static bool read_line( FILE *fp, string& rLine )
2235 {
2236 char szBuffer[1024];
2237 bool bSuccess = false;
2238 bool bEOL = false;
2239 string line;
2240
2241
2242 while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) )
2243 {
2244 int len = strlen(szBuffer);
2245
2246 bSuccess = true;
2247
2248 while ( len && szBuffer[len - 1] == '\n' )
2249 {
2250 szBuffer[--len] = 0;
2251 bEOL = true;
2252 }
2253
2254 line.append( szBuffer );
2255 }
2256
2257 rLine = line;
2258 return bSuccess;
2259 }
2260
get_script_string(const char * pFileName,const char * pKeyName)2261 static string get_script_string( const char *pFileName, const char *pKeyName )
2262 {
2263 FILE *fp = fopen( pFileName, "rt" );
2264 string retValue;
2265
2266 if ( fp )
2267 {
2268 string line;
2269 string section;
2270
2271 while ( read_line( fp, line ) )
2272 {
2273 line = trim_string( line );
2274
2275
2276 string::size_type iEqualSign = line.find( '=', 0 );
2277
2278 if ( iEqualSign != string::npos )
2279 {
2280 string keyname = line.substr( 0, iEqualSign );
2281 keyname = trim_string( keyname );
2282
2283 string value = line.substr( sal::static_int_cast<string::size_type>(iEqualSign + 1) );
2284 value = trim_string( value );
2285
2286 if ( value.length() && '\"' == value[0] )
2287 {
2288 value.erase( 0, 1 );
2289
2290 string::size_type iQuotes = value.find( '"', 0 );
2291
2292 if ( iQuotes != string::npos )
2293 value.erase( iQuotes );
2294 }
2295
2296 if ( 0 == stricmp( keyname.c_str(), pKeyName ) )
2297 {
2298 retValue = value;
2299 break;
2300 }
2301 }
2302 }
2303
2304 fclose( fp );
2305 }
2306
2307 return retValue;
2308 }
2309
ReadBootstrapParams(CrashReportParams & rParams)2310 static bool ReadBootstrapParams( CrashReportParams &rParams )
2311 {
2312 TCHAR szBuffer[256] = TEXT("");
2313 TCHAR szModuleName[MAX_PATH];
2314 TCHAR szModuleVersionName[MAX_PATH];
2315 TCHAR szDrive[_MAX_DRIVE];
2316 TCHAR szDir[_MAX_DIR];
2317 TCHAR szFName[_MAX_FNAME];
2318 TCHAR szExt[_MAX_EXT];
2319 TCHAR szReportServer[MAX_HOSTNAME];
2320 TCHAR szReportPort[256];
2321 bool bSuccess = false;
2322
2323 GetModuleFileName( NULL, szModuleName, MAX_PATH );
2324 _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
2325 _tmakepath( szModuleName, szDrive, szDir, _T("bootstrap"), _T(".ini") );
2326 _tmakepath( szModuleVersionName, szDrive, szDir, _T("version"), _T(".ini") );
2327
2328 if (
2329 GetPrivateProfileString(
2330 TEXT("Bootstrap"),
2331 TEXT("ProductKey"),
2332 TEXT("OpenOffice"),
2333 szBuffer,
2334 elementsof(szBuffer),
2335 szModuleName )
2336 )
2337 {
2338 TCHAR *pVersion = _tcschr( szBuffer, ' ' );
2339
2340 g_wstrProductKey = szBuffer;
2341
2342 if ( pVersion )
2343 {
2344 *pVersion = 0;
2345 pVersion++;
2346 }
2347 else
2348 pVersion = TEXT("");
2349
2350 if ( !_tgetenv( _T("PRODUCTNAME") ) )
2351 {
2352 _tsetenv( TEXT("PRODUCTNAME"), szBuffer );
2353 }
2354 if ( !_tgetenv( _T("PRODUCTVERSION") ) )
2355 _tsetenv( TEXT("PRODUCTVERSION"), pVersion );
2356 }
2357
2358 GetPrivateProfileString(
2359 TEXT("Version"),
2360 TEXT("buildid"),
2361 TEXT("unknown"),
2362 g_szBuildId, elementsof(g_szBuildId),
2363 szModuleVersionName );
2364
2365 g_strDefaultLanguage = get_script_string( "instdb.inf", "DefaultLanguage" );
2366
2367 if ( GetPrivateProfileString(
2368 TEXT("ErrorReport"),
2369 TEXT("ErrorReportPort"),
2370 TEXT("80"),
2371 szReportPort, elementsof(szReportPort),
2372 szModuleName
2373 ) )
2374 {
2375 TCHAR *endptr = NULL;
2376
2377 unsigned short uReportPort = (unsigned short)_tcstoul( szReportPort, &endptr, 10 );
2378 if ( uReportPort )
2379 g_uReportPort = uReportPort;
2380 }
2381
2382 if ( GetPrivateProfileString(
2383 TEXT("ErrorReport"),
2384 TEXT("ErrorReportServer"),
2385 TEXT(""),
2386 szReportServer, elementsof(szReportServer),
2387 szModuleName
2388 ) )
2389 {
2390 bSuccess = 0 != WideCharToMultiByte( CP_ACP, 0, szReportServer, -1, g_szReportServerA, elementsof(g_szReportServerA), NULL, NULL );
2391 }
2392
2393 LPCTSTR lpEnvString;
2394
2395 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYSERVER") )) )
2396 rParams.sProxyServer = lpEnvString;
2397
2398 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYPORT") )) )
2399 rParams.sProxyPort = lpEnvString;
2400
2401 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_SENDERADDRESS") )) )
2402 rParams.sEmail = lpEnvString;
2403
2404 return bSuccess;
2405 }
2406
2407 //***************************************************************************
2408
SendHTTPRequest(FILE * fp,const char * pszServer,unsigned short uPort=80,const char * pszProxyServer=NULL,unsigned short uProxyPort=8080)2409 bool SendHTTPRequest(
2410 FILE *fp,
2411 const char *pszServer,
2412 unsigned short uPort = 80,
2413 const char *pszProxyServer = NULL,
2414 unsigned short uProxyPort = 8080 )
2415 {
2416 bool success = false;
2417
2418 struct hostent *hp;
2419
2420 if ( pszProxyServer )
2421 hp = gethostbyname( pszProxyServer );
2422 else
2423 hp = gethostbyname( pszServer );
2424
2425 if ( hp )
2426 {
2427 SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
2428
2429 if ( s )
2430 {
2431 struct sockaddr_in address;
2432
2433 memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr));
2434 address.sin_family = AF_INET;
2435
2436 if ( pszProxyServer )
2437 address.sin_port = ntohs( uProxyPort );
2438 else
2439 address.sin_port = ntohs( uPort );
2440
2441 if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) )
2442 {
2443 fseek( fp, 0, SEEK_END );
2444 size_t length = ftell( fp );
2445 fseek( fp, 0, SEEK_SET );
2446
2447 char buffer[2048];
2448
2449 if ( pszProxyServer )
2450 sprintf( buffer,
2451 "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
2452 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2453 "Content-Length: %d\r\n"
2454 "SOAPAction: \"\"\r\n\r\n",
2455 pszServer,
2456 uPort,
2457 length
2458 );
2459 else
2460 sprintf( buffer,
2461 "POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
2462 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2463 "Content-Length: %d\r\n"
2464 "SOAPAction: \"\"\r\n\r\n",
2465 length
2466 );
2467
2468 if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
2469 {
2470 size_t nBytes;
2471
2472 do
2473 {
2474 nBytes = fread( buffer, 1, sizeof(buffer), fp );
2475
2476 if ( nBytes )
2477 success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
2478 } while( nBytes && success );
2479
2480 if ( success )
2481 {
2482 memset( buffer, 0, sizeof(buffer) );
2483 success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 );
2484 if ( success )
2485 {
2486 char szHTTPSignature[sizeof(buffer)] = "";
2487 unsigned uHTTPReturnCode = 0;
2488
2489 sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode );
2490 success = uHTTPReturnCode == 200;
2491 }
2492 }
2493 }
2494
2495 }
2496
2497 closesocket( s );
2498 }
2499 }
2500
2501 return success;
2502 }
2503
2504 //***************************************************************************
2505
WriteSOAPRequest(FILE * fp)2506 static void WriteSOAPRequest( FILE *fp )
2507 {
2508 fprintf( fp,
2509 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
2510 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
2511 "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
2512 "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
2513 "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
2514 "xmlns:rds=\"urn:ReportDataService\"\n"
2515 "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
2516 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
2517 "<SOAP-ENV:Body>\n"
2518 );
2519
2520 fprintf( fp, "<rds:submitReport>\n" );
2521 fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
2522 fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
2523
2524 FILE *fpin = fopen( g_szReportFileNameA, "r" );
2525 if ( fpin )
2526 {
2527 fprintf( fp,
2528 "<item>\n"
2529 "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
2530 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2531 fcopy( fpin, fp );
2532 fprintf( fp, "]]></value></item>\n" );
2533 fclose( fpin );
2534 }
2535
2536 fpin = fopen( g_szCommentFileNameA, "r" );
2537 if ( fpin )
2538 {
2539 fprintf( fp,
2540 "<item>\n"
2541 "<key xsi:type=\"xsd:string\">description.txt</key>\n"
2542 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2543 fcopy( fpin, fp );
2544 fprintf( fp, "]]></value></item>\n" );
2545 fclose( fpin );
2546 };
2547
2548
2549 fpin = fopen( g_szDumpFileNameA, "rb" );
2550 if ( fpin )
2551 {
2552 FILE *fptemp = _tmpfile();
2553
2554 if ( fptemp )
2555 {
2556 if ( base64_encode( fpin, fptemp ) )
2557 {
2558 fseek( fptemp, 0, SEEK_SET );
2559 fprintf( fp,
2560 "<item>\n"
2561 "<key xsi:type=\"xsd:string\">user.dmp</key>\n"
2562 "<value xsi:type=\"xsd:string\">" );
2563 fcopy( fptemp, fp );
2564 fprintf( fp, "</value></item>\n" );
2565 }
2566 fclose( fptemp );
2567 }
2568 fclose( fpin );
2569 }
2570
2571 fprintf( fp,
2572 "</hash>\n"
2573 "</rds:submitReport>\n"
2574 "</SOAP-ENV:Body>\n"
2575 "</SOAP-ENV:Envelope>\n"
2576 );
2577 }
2578
2579 //***************************************************************************
2580
2581 struct RequestParams
2582 {
2583 bool success;
2584 FILE *fpin;
2585 const char *lpServer;
2586 unsigned short uPort;
2587 const char *lpProxyServer;
2588 unsigned short uProxyPort;
2589 HWND hwndStatus;
2590 };
2591
SendingThread(void * lpArgs)2592 void _cdecl SendingThread( void *lpArgs )
2593 {
2594 RequestParams *pParams = (RequestParams *)lpArgs;
2595
2596 pParams->success = SendHTTPRequest( pParams->fpin, pParams->lpServer, pParams->uPort, pParams->lpProxyServer, pParams->uProxyPort );
2597
2598 PostMessage( pParams->hwndStatus, WM_COMMAND, IDOK, 0 );
2599 }
2600
2601 //***************************************************************************
2602
SendingStatusDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)2603 BOOL CALLBACK SendingStatusDialogProc(
2604 HWND hwndDlg,
2605 UINT uMsg,
2606 WPARAM wParam,
2607 LPARAM lParam
2608 )
2609 {
2610 static RequestParams *pRequest = NULL;
2611 static HANDLE hSendingThread = NULL;
2612
2613 switch ( uMsg )
2614 {
2615 case WM_INITDIALOG:
2616 {
2617 TCHAR szBuffer[1024] = TEXT("");
2618 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
2619 //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
2620
2621 pRequest = (RequestParams *)lParam;
2622
2623 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
2624 SetWindowText( hwndDlg, szBuffer );
2625
2626 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_STATUS, szBuffer, elementsof(szBuffer) );
2627 Static_SetText( GetDlgItem(hwndDlg, IDC_SENDING_REPORT_STATUS), szBuffer );
2628
2629 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
2630 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
2631
2632 pRequest->hwndStatus = hwndDlg;
2633
2634 hSendingThread = (HANDLE)_beginthread( SendingThread, 0, pRequest );
2635 }
2636 return TRUE;
2637 case WM_COMMAND:
2638 switch ( LOWORD(wParam) )
2639 {
2640 case IDCANCEL:
2641 TerminateThread( hSendingThread, 0 );
2642 case IDOK:
2643 WaitForSingleObject( hSendingThread, INFINITE );
2644 CloseHandle( hSendingThread );
2645 EndDialog( hwndDlg, wParam );
2646 return TRUE;
2647 }
2648 break;
2649 default:
2650 break;
2651 }
2652
2653 return FALSE;
2654 }
2655
2656 //***************************************************************************
2657
SendCrashReport(HWND hwndParent,const CrashReportParams & rParams)2658 bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams )
2659 {
2660 bool success = false;
2661 char szProxyServer[1024] = "";
2662 unsigned short uProxyPort = 8080;
2663 TCHAR *endptr = NULL;
2664
2665 switch ( rParams.uInternetConnection )
2666 {
2667 case 2:
2668 {
2669 WideCharToMultiByte(
2670 CP_ACP, 0, rParams.sProxyServer.c_str(), -1,
2671 szProxyServer, sizeof(szProxyServer), NULL, NULL );
2672 uProxyPort = (unsigned short)_tcstoul( rParams.sProxyPort.c_str(), &endptr, 10 );
2673 }
2674 break;
2675 case 0:
2676 {
2677 DWORD dwProxyEnable = 0;
2678
2679 RegReadValue( HKEY_CURRENT_USER,
2680 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
2681 TEXT("ProxyEnable"),
2682 &dwProxyEnable,
2683 sizeof(dwProxyEnable) );
2684
2685 if ( dwProxyEnable )
2686 {
2687 TCHAR tszProxyServers[1024] = TEXT("");
2688
2689 if ( ERROR_SUCCESS == RegReadValue( HKEY_CURRENT_USER,
2690 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
2691 TEXT("ProxyServer"),
2692 tszProxyServers,
2693 sizeof(tszProxyServers) ) )
2694 {
2695 TCHAR *lpHttpStart = _tcsstr( tszProxyServers, TEXT("http=") );
2696
2697 if ( lpHttpStart )
2698 lpHttpStart += 5;
2699 else
2700 lpHttpStart = tszProxyServers;
2701
2702 TCHAR *lpHttpEnd = _tcschr( lpHttpStart, ';' );
2703
2704 if ( lpHttpEnd )
2705 *lpHttpEnd = 0;
2706
2707 char szHTTPProxyServer[1024] = "";
2708 WideCharToMultiByte( CP_ACP, 0, lpHttpStart, -1, szHTTPProxyServer, sizeof(szHTTPProxyServer), NULL, NULL );
2709
2710 char *lpColon = strchr( szHTTPProxyServer, ':' );
2711
2712 if ( lpColon )
2713 {
2714 char *endptr = NULL;
2715
2716 *lpColon = 0;
2717 uProxyPort = (unsigned short)strtoul( lpColon + 1, &endptr, 10 );
2718 }
2719 else
2720 uProxyPort = 8080;
2721
2722 strcpy( szProxyServer, szHTTPProxyServer );
2723
2724 }
2725 }
2726 }
2727 break;
2728 default:
2729 case 1:
2730 break;
2731 }
2732
2733 FILE *fptemp = _tmpfile();
2734 if ( fptemp )
2735 {
2736 RequestParams request;
2737
2738 request.success = false;
2739 request.fpin = fptemp;
2740 request.lpServer = REPORT_SERVER;
2741 request.uPort = REPORT_PORT;
2742 request.lpProxyServer = szProxyServer[0] ? szProxyServer : NULL;
2743 request.uProxyPort = uProxyPort;
2744 request.hwndStatus = NULL;
2745
2746 WriteSOAPRequest( fptemp );
2747 fseek( fptemp, 0, SEEK_SET );
2748
2749 if ( hwndParent )
2750 {
2751 int retid = DialogBoxParam(
2752 GetModuleHandle(NULL),
2753 MAKEINTRESOURCE(IDD_SENDING_STATUS),
2754 hwndParent,
2755 SendingStatusDialogProc,
2756 (LPARAM)&request
2757 );
2758
2759 success = request.success;
2760
2761 if ( IDOK == retid )
2762 {
2763 if ( !success )
2764 {
2765 TCHAR szMessage[1024];
2766
2767 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) );
2768
2769 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
2770 }
2771 else
2772 {
2773 TCHAR szMessage[1024];
2774 TCHAR szTitle[1024];
2775
2776 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) );
2777 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_HEADER, szTitle, elementsof(szTitle) );
2778
2779 MessageBox( hwndParent, szMessage, szTitle, MB_ICONINFORMATION | MB_OK );
2780 }
2781 }
2782
2783 }
2784 else
2785 {
2786 HANDLE hSendingThread = (HANDLE)_beginthread( SendingThread, 0, (void *)&request );
2787
2788 WaitForSingleObject( hSendingThread, INFINITE );
2789
2790 success = request.success;
2791 if ( !success )
2792 {
2793 TCHAR szMessage[1024];
2794
2795 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) );
2796 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
2797 }
2798 else
2799 {
2800 TCHAR szMessage[1024];
2801
2802 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) );
2803
2804 _ftprintf( stderr, _T("SUCCESS: %s\n"), szMessage );
2805 }
2806 }
2807 fclose( fptemp );
2808 }
2809 else
2810 {
2811 TCHAR szMessage[1024];
2812
2813 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_DISK_FULL, szMessage, elementsof(szMessage) );
2814
2815 if ( hwndParent )
2816 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
2817 else
2818 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
2819 }
2820
2821 return success;
2822 }
2823
2824 //***************************************************************************
2825
2826 #ifdef __MINGW32__
WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR,int)2827 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR /*lpCmdLine*/, int )
2828 #else
2829 int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR /*lpCmdLine*/, int )
2830 #endif
2831 {
2832 int exitcode = -1;
2833 int argc = __argc;
2834
2835 #ifdef __MINGW32__
2836 char **argv = __argv;
2837 #else
2838 #ifdef _UNICODE
2839 char **argv = new char *[argc + 1];
2840
2841 for ( int argn = 0; argn < argc; argn++ )
2842 {
2843 int nBytes = WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, NULL, 0, NULL, NULL );
2844 argv[argn] = new char[nBytes];
2845 WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, argv[argn], nBytes, NULL, NULL );
2846 }
2847 argv[argc] = NULL;
2848 #else
2849 char **argv = __targv;
2850 #endif
2851 #endif
2852
2853 osl_setCommandArgs( argc, argv );
2854
2855 PEXCEPTION_POINTERS pExceptionPointers = NULL;
2856 DWORD dwProcessId = 0;
2857 DWORD dwThreadId = 0;
2858
2859 WSADATA wsaData;
2860 WORD wVersionRequested;
2861
2862 wVersionRequested = MAKEWORD(1, 1);
2863 WSAStartup(wVersionRequested, &wsaData);
2864
2865 CrashReportParams Params;
2866
2867 Params.ReadFromRegistry();
2868 Params.ReadFromEnvironment();
2869
2870 if ( ReadBootstrapParams( Params ) &&
2871 ParseCommandArgs( &dwProcessId, &pExceptionPointers, &dwThreadId ) )
2872 {
2873 bool bGotDumpFile;
2874
2875 if ( g_bLoadReport )
2876 bGotDumpFile = FindDumpFile();
2877 else
2878 bGotDumpFile = WriteDumpFile( dwProcessId, pExceptionPointers, dwThreadId );
2879
2880 if( bGotDumpFile )
2881 {
2882 hash_map< string, string > aLibraries;
2883
2884 if ( g_bLoadReport )
2885 {
2886 g_fpStackFile = _open_reportfile( _T(".stk"), _T("rb") );
2887 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("rb") );
2888 }
2889 else
2890 {
2891 if ( g_bSendReport )
2892 {
2893 g_fpStackFile = _tmpfile();
2894 g_fpChecksumFile = _tmpfile();
2895 }
2896 else
2897 {
2898 g_fpStackFile = _open_reportfile( _T(".stk"), _T("w+b") );
2899 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("w+b") );
2900
2901 FILE *fpUnsent = _open_reportfile( _T(".lck"), _T("w+b") );
2902 if ( fpUnsent )
2903 {
2904 fprintf( fpUnsent, "Unsent\r\n" );
2905 fclose( fpUnsent );
2906 }
2907 }
2908
2909 WriteStackFile( g_fpStackFile, aLibraries, dwProcessId, pExceptionPointers );
2910 WriteChecksumFile( g_fpChecksumFile, aLibraries );
2911 WriteReportFile( &Params );
2912
2913 FILE *fpPreview = _open_reportfile( _T(".prv"), _T("w+b") );
2914
2915 if ( fpPreview )
2916 {
2917 FILE *fp = fopen( g_szReportFileNameA, "rb" );
2918 if ( fp )
2919 {
2920 fcopy( fp, fpPreview );
2921 fclose( fp );
2922 }
2923 fclose( fpPreview );
2924 }
2925 }
2926
2927 if ( g_bSendReport )
2928 {
2929 InitCommonControls();
2930
2931 // Actually this should never be true anymore
2932 if ( !g_bNoUserInterface && InitRichEdit() )
2933 {
2934
2935 INT_PTR result = DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_DIALOG_FRAME), NULL, DialogProc, (LPARAM)&Params );
2936
2937 if ( result > 0 )
2938 {
2939 exitcode = 0;
2940 }
2941 DeinitRichEdit();
2942 }
2943 else
2944 {
2945 WriteCommentFile( Params.sComment.c_str() );
2946 WriteReportFile( &Params );
2947 if ( SendCrashReport( NULL, Params ) )
2948 exitcode = 0;
2949 }
2950
2951
2952 if ( g_szReportFileNameA[0] )
2953 DeleteFileA( g_szReportFileNameA );
2954
2955 if ( g_szCommentFileNameA[0] )
2956 DeleteFileA( g_szCommentFileNameA );
2957 }
2958 else
2959 {
2960 if ( g_szReportFileNameA[0] )
2961 DeleteFileA( g_szReportFileNameA );
2962 exitcode = 0;
2963 }
2964
2965 if ( g_szDumpFileNameA[0] && g_bSendReport )
2966 DeleteFileA( g_szDumpFileNameA );
2967
2968 if ( g_fpStackFile )
2969 fclose( g_fpStackFile );
2970
2971 if ( g_fpChecksumFile )
2972 fclose( g_fpChecksumFile );
2973 }
2974 }
2975
2976
2977 return exitcode;
2978 }
2979