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( (intptr_t)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( (intptr_t)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 INT_PTR 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)GetWindowLongPtr( hwndDlg, GWLP_HINSTANCE );
896 HWND hwndParent = (HWND)GetWindowLongPtr( hwndDlg, GWLP_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)GetWindowLongPtr(hwndParent, GWLP_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 INT_PTR 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)GetWindowLongPtr( hwndDlg, GWLP_HINSTANCE );
1046 //HWND hwndParent = (HWND)GetWindowLongPtr( hwndDlg, GWLP_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)GetWindowLongPtr(hwndParent, GWLP_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 INT_PTR 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*)GetWindowLongPtr( GetParent(hwndDlg), GWLP_USERDATA );
1173 HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hwndDlg, GWLP_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)GetWindowLongPtr(hwndDlg, GWLP_HINSTANCE );
1218 CrashReportParams *pParams = (CrashReportParams*)GetWindowLongPtr( GetParent(hwndDlg), GWLP_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 SetWindowLongPtr( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWLP_STYLE,
1240 GetWindowLongPtr( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWLP_STYLE) | BS_DEFPUSHBUTTON );
1241 SetWindowLongPtr( GetDlgItem(GetParent(hwndDlg),IDBACK), GWLP_STYLE,
1242 GetWindowLongPtr( GetDlgItem(GetParent(hwndDlg),IDBACK), GWLP_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*)GetWindowLongPtr( GetParent(hwndDlg), GWLP_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*)GetWindowLongPtr( GetParent(hwndDlg), GWLP_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 INT_PTR CALLBACK WelcomeDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
1294 {
1295 switch ( uMsg )
1296 {
1297 case WM_INITDIALOG:
1298 {
1299 HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr(hwndDlg, GWLP_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)GetWindowLongPtr(hwndDlg, GWLP_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 INT_PTR 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)GetWindowLongPtr(hwndDlg, GWLP_HINSTANCE );
1393 TCHAR szBuffer[FORMATBUFSIZE];
1394
1395 SetWindowLongPtr( hwndDlg, GWLP_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*)GetWindowLongPtr( hwndDlg, GWLP_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 #if defined(INTEL)
1729 frame.AddrPC.Offset = aContextRecord.Eip;
1730 #elif defined(X86_64)
1731 frame.AddrPC.Offset = aContextRecord.Rip;
1732 #else
1733 #error Unsupported architecture
1734 #endif
1735 frame.AddrPC.Mode = AddrModeFlat;
1736 #if defined(INTEL)
1737 frame.AddrFrame.Offset = aContextRecord.Ebp;
1738 #elif defined(X86_64)
1739 frame.AddrFrame.Offset = aContextRecord.Rbp;
1740 #else
1741 #error Unsupported architecture
1742 #endif
1743 frame.AddrFrame.Mode = AddrModeFlat;
1744
1745 BOOL bSuccess;
1746 int frameNum = 0;
1747
1748 SymInitialize( hProcess, NULL, TRUE );
1749
1750 fprintf( fout, "<errormail:Stack type=\"Win32\">\n" );
1751
1752 do
1753 {
1754 fSuccess = true;
1755
1756 bSuccess = StackWalk( IMAGE_FILE_MACHINE_I386,
1757 hProcess,
1758 NULL,
1759 &frame,
1760 &aContextRecord,
1761 (PREAD_PROCESS_MEMORY_ROUTINE)ReadProcessMemory,
1762 SymFunctionTableAccess,
1763 SymGetModuleBase,
1764 NULL );
1765
1766 if ( bSuccess )
1767 {
1768 // Note: ImageHelp ANSI functions do not have an A postfix while
1769 // Unicode versions have a W postfix. There's no macro
1770 // that depends on define UNICODE
1771
1772 IMAGEHLP_MODULE moduleInfo;
1773
1774 ZeroMemory( &moduleInfo, sizeof(moduleInfo) );
1775 moduleInfo.SizeOfStruct = sizeof(moduleInfo);
1776
1777 if ( SymGetModuleInfo( hProcess, frame.AddrPC.Offset, &moduleInfo ) )
1778 {
1779 rLibraries[ GetFileName( moduleInfo.LoadedImageName ).c_str() ] = moduleInfo.LoadedImageName;
1780
1781 // SymGetSymFromAddr's displacement parameter is arch-dependent:
1782 // on x86 it is PDWORD, on x64 the dbghelp macro maps it to
1783 // SymGetSymFromAddr64 wanting PDWORD64. Match the type per arch
1784 // (same INTEL/X86_64 guard used for AddrPC.Offset above); an
1785 // unconditional DWORD64 breaks the x86 build (C2664).
1786 #if defined(INTEL)
1787 DWORD dwRelOffset = 0;
1788 #elif defined(X86_64)
1789 DWORD64 dwRelOffset = 0;
1790 #else
1791 #error Unsupported architecture
1792 #endif
1793 BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 256 ];
1794 PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
1795
1796 ZeroMemory( symbolBuffer, sizeof(symbolBuffer) );
1797 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
1798 pSymbol->MaxNameLength = 256;
1799
1800 if ( SymGetSymFromAddr( hProcess, frame.AddrPC.Offset, &dwRelOffset, pSymbol ) )
1801 fprintf( fout, "<errormail:StackInfo " \
1802 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" ordinal=\"%s+0x%p\" name=\"%s\" path=\"%s\"/>\n",
1803 frameNum,
1804 frame.AddrPC.Offset,
1805 frame.AddrPC.Offset - moduleInfo.BaseOfImage,
1806 xml_encode(pSymbol->Name).c_str(),
1807 frame.AddrPC.Offset - pSymbol->Address,
1808 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
1809 xml_encode( GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
1810 );
1811 else
1812 fprintf( fout, "<errormail:StackInfo " \
1813 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" name=\"%s\" path=\"%s\"/>\n",
1814 frameNum,
1815 frame.AddrPC.Offset,
1816 frame.AddrPC.Offset - moduleInfo.BaseOfImage,
1817 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
1818 xml_encode(GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
1819 );
1820 }
1821 else
1822 fprintf( fout, "<errormail:StackInfo pos=\"%d\" ip=\"0x%p\"/>\n",
1823 frameNum,
1824 frame.AddrPC.Offset
1825 );
1826
1827 frameNum++;
1828 }
1829
1830 } while ( bSuccess );
1831
1832 fprintf( fout, "</errormail:Stack>\n" );
1833
1834 SymCleanup( hProcess );
1835
1836 CloseHandle( hProcess );
1837 }
1838
1839 }
1840
1841 return fSuccess;
1842 }
1843
WriteChecksumFile(FILE * fchksum,const hash_map<string,string> & rLibraries)1844 bool WriteChecksumFile( FILE *fchksum, const hash_map< string, string >& rLibraries )
1845 {
1846 bool success = false;
1847
1848 if ( fchksum && rLibraries.size() )
1849 {
1850 fprintf( fchksum, "<errormail:Checksums type=\"MD5\">\n" );
1851
1852 hash_map< string, string >::const_iterator iter;
1853
1854 for ( iter = rLibraries.begin();
1855 iter != rLibraries.end();
1856 iter++ )
1857 {
1858 sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5];
1859 sal_uInt32 nBytesProcessed = calc_md5_checksum(
1860 iter->second.c_str(),
1861 checksum, sizeof(checksum) );
1862
1863 if ( nBytesProcessed )
1864 {
1865 fprintf( fchksum, "<errormail:Checksum sum=\"0x" );
1866 for ( int i = 0; i < sizeof(checksum); fprintf( fchksum, "%02X", checksum[i++] ) );
1867 fprintf( fchksum, "\" bytes=\"%d\" file=\"%s\"/>\n",
1868 nBytesProcessed,
1869 GetFileName( iter->first ).c_str() );
1870 }
1871 }
1872
1873 fprintf( fchksum, "</errormail:Checksums>\n" );
1874
1875 success = true;
1876 }
1877
1878 return success;
1879 }
1880
1881 //***************************************************************************
1882
FindDumpFile()1883 BOOL FindDumpFile()
1884 {
1885 TCHAR szFileName[MAX_PATH];
1886
1887 if ( GetCrashDataPath( szFileName ) )
1888 {
1889 _tcscat( szFileName, _T("\\crashdat.dmp") );
1890
1891 HANDLE hFile = CreateFile(
1892 szFileName,
1893 GENERIC_READ,
1894 0, NULL,
1895 OPEN_EXISTING,
1896 FILE_ATTRIBUTE_NORMAL, NULL );
1897
1898 if ( hFile )
1899 {
1900 CloseHandle( hFile );
1901
1902 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
1903 _tcscpy( g_szDumpFileName, szFileName );
1904
1905 return TRUE;
1906 }
1907 }
1908
1909 return FALSE;
1910 }
1911
WriteDumpFile(DWORD dwProcessId,PEXCEPTION_POINTERS pExceptionPointers,DWORD dwThreadId)1912 BOOL WriteDumpFile( DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers, DWORD dwThreadId )
1913 {
1914 BOOL fSuccess = FALSE;
1915 PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam = NULL;
1916 MINIDUMP_EXCEPTION_INFORMATION ExceptionParam;
1917
1918 HMODULE hDbgHelp = LoadLibrary( _T("DBGHELP.DLL" ) );
1919 MiniDumpWriteDump_PROC pMiniDumpWriteDump = NULL;
1920
1921 if ( hDbgHelp )
1922 {
1923 pMiniDumpWriteDump = (MiniDumpWriteDump_PROC)GetProcAddress( hDbgHelp, "MiniDumpWriteDump" );
1924
1925 if ( !pMiniDumpWriteDump )
1926 {
1927 FreeLibrary( hDbgHelp );
1928 return false;
1929 }
1930 }
1931
1932 if ( !pMiniDumpWriteDump )
1933 return false;
1934
1935 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
1936
1937 if ( IsValidHandle(hProcess) )
1938 {
1939 TCHAR szTempPath[MAX_PATH];
1940
1941 // if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
1942 if ( GetCrashDataPath( szTempPath ) )
1943 {
1944 TCHAR szFileName[MAX_PATH];
1945
1946 // if ( GetTempFileName( szTempPath, TEXT("DMP"), 0, szFileName ) )
1947 _tcscpy( szFileName, szTempPath );
1948 _tcscat( szFileName, _T("\\crashdat.dmp") );
1949 {
1950 HANDLE hFile = CreateFile(
1951 szFileName,
1952 GENERIC_READ | GENERIC_WRITE,
1953 0, NULL,
1954 // OPEN_EXISTING,
1955 CREATE_ALWAYS,
1956 FILE_ATTRIBUTE_NORMAL, NULL );
1957
1958 if ( hFile )
1959 {
1960 if ( pExceptionPointers && dwThreadId )
1961 {
1962 ExceptionParam.ThreadId = dwThreadId;
1963 ExceptionParam.ExceptionPointers = pExceptionPointers;
1964 ExceptionParam.ClientPointers = TRUE;
1965
1966 EXCEPTION_POINTERS aExceptionPointers;
1967 EXCEPTION_RECORD aExceptionRecord;
1968
1969 ReadProcessMemory(
1970 hProcess,
1971 pExceptionPointers,
1972 &aExceptionPointers,
1973 sizeof(aExceptionPointers),
1974 NULL );
1975
1976
1977 ReadProcessMemory(
1978 hProcess,
1979 aExceptionPointers.ExceptionRecord,
1980 &aExceptionRecord,
1981 sizeof(aExceptionRecord),
1982 NULL );
1983
1984 g_dwExceptionCode = aExceptionRecord.ExceptionCode;
1985
1986 lpExceptionParam = &ExceptionParam;
1987 }
1988
1989 fSuccess = pMiniDumpWriteDump( hProcess, dwProcessId, hFile, MiniDumpNormal, lpExceptionParam, NULL, NULL );
1990
1991 CloseHandle( hFile );
1992
1993 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
1994 _tcscpy( g_szDumpFileName, szFileName );
1995 }
1996
1997 if ( !fSuccess )
1998 DeleteFile( szFileName );
1999 }
2000 }
2001
2002 CloseHandle( hProcess );
2003 }
2004
2005 FreeLibrary( hDbgHelp );
2006
2007 return fSuccess;
2008 }
2009
2010 //***************************************************************************
2011
FindProcessForImage(LPCTSTR lpImagePath)2012 static DWORD FindProcessForImage( LPCTSTR lpImagePath )
2013 {
2014 DWORD dwProcessId = 0;
2015 DWORD aProcesses[1024];
2016 DWORD dwSize = 0;
2017 TCHAR szShortImagePath[MAX_PATH];
2018
2019 if ( GetShortPathName( lpImagePath, szShortImagePath, elementsof(szShortImagePath) ) &&
2020 EnumProcesses( aProcesses, sizeof(aProcesses), &dwSize ) )
2021 {
2022 unsigned nProcesses = dwSize / sizeof(aProcesses[0]);
2023
2024 for ( unsigned i = 0; !dwProcessId && i < nProcesses; i++ )
2025 {
2026 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] );
2027
2028 if ( IsValidHandle(hProcess) )
2029 {
2030 TCHAR szModulePath[MAX_PATH+1];
2031
2032 if ( GetModuleFileNameEx( hProcess, NULL, szModulePath, MAX_PATH ) )
2033 {
2034 TCHAR szShortModulePath[MAX_PATH];
2035
2036 if ( GetShortPathName( szModulePath, szShortModulePath, elementsof(szShortModulePath) ) )
2037 {
2038 if ( 0 == _tcsicmp( szShortModulePath, szShortImagePath ) )
2039 dwProcessId = aProcesses[i];
2040 }
2041 }
2042
2043 CloseHandle( hProcess );
2044 }
2045 }
2046 }
2047
2048 return dwProcessId;
2049 }
2050 //***************************************************************************
2051
ParseCommandArgs(LPDWORD pdwProcessId,PEXCEPTION_POINTERS * ppException,LPDWORD pdwThreadId)2052 static bool ParseCommandArgs( LPDWORD pdwProcessId, PEXCEPTION_POINTERS* ppException, LPDWORD pdwThreadId )
2053 {
2054 int argc = __argc;
2055 #ifdef __MINGW32__
2056 #ifdef _UNICODE
2057 TCHAR **argv = reinterpret_cast<TCHAR **>(alloca((argc+1)*sizeof(WCHAR*)));
2058 int *sizes = reinterpret_cast<int *>(alloca(argc*sizeof(int)));
2059 int argsize=0;
2060 char **ptr;
2061 int i;
2062 ptr=__argv;
2063 for (i = 0; i < argc; ++i)
2064 {
2065 sizes[i]=MultiByteToWideChar(CP_ACP, 0, *ptr, -1, NULL, 0);
2066 argsize+=sizes[i]+1;
2067 ++ptr;
2068 }
2069 ++argsize;
2070 TCHAR *args = reinterpret_cast<TCHAR *>(alloca(argsize*sizeof(WCHAR)));
2071 ptr=__argv;
2072 TCHAR *cptr=args;
2073 for (i = 0; i < argc; ++i)
2074 {
2075 argv[i]=cptr;
2076 MultiByteToWideChar( CP_ACP, 0, *ptr, -1, cptr, sizes[i] );
2077 ++ptr;
2078 cptr+=sizes[i];
2079 *cptr=0;
2080 ++cptr;
2081 }
2082 argv[i]=cptr;
2083 *cptr=0;
2084 #else
2085 TCHAR **argv = __argv;
2086 #endif
2087 #else
2088 TCHAR **argv = __targv;
2089 #endif
2090 bool bSuccess = true;
2091
2092 for ( int argn = 1; bSuccess && argn < argc; argn++ )
2093 {
2094 if ( 0 == _tcsicmp( argv[argn], _T("-h") ) ||
2095 0 == _tcsicmp( argv[argn], _T("/h") ) ||
2096 0 == _tcsicmp( argv[argn], _T("-?") ) ||
2097 0 == _tcsicmp( argv[argn], _T("/?") ) ||
2098 0 == _tcsicmp( argv[argn], _T("/help") ) ||
2099 0 == _tcsicmp( argv[argn], _T("-help") ) ||
2100 0 == _tcsicmp( argv[argn], _T("--help") )
2101 )
2102 {
2103 HINSTANCE hInstance = GetModuleHandle(NULL);
2104 TCHAR szUsage[FORMATBUFSIZE];
2105 TCHAR szProcess[FORMATBUFSIZE];
2106 TCHAR szProcessDescription[FORMATBUFSIZE];
2107 TCHAR szHelpDescription[FORMATBUFSIZE];
2108
2109 LoadAndFormatString( hInstance, IDS_MSG_CMDLINE_USAGE, szUsage, elementsof(szUsage) );
2110 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID, szProcess, elementsof(szProcess) );
2111 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID_DESCRIPTION, szProcessDescription, elementsof(szProcessDescription) );
2112 LoadAndFormatString( hInstance, IDS_MSG_PARAM_HELP_DESCRIPTION, szHelpDescription, elementsof(szHelpDescription) );
2113
2114 _tprintf(
2115 TEXT("\n%s: crashrep %s\n\n")
2116 TEXT("/?, -h[elp] %s\n\n")
2117 TEXT("%-20s %s\n\n"),
2118 szUsage, szProcess, szHelpDescription, szProcess, szProcessDescription
2119 );
2120
2121 return true;
2122 }
2123 else if ( 0 == _tcsicmp( argv[argn], _T("-p") ) ||
2124 0 == _tcsicmp( argv[argn], _T("/p") ) )
2125 {
2126 if ( ++argn < argc )
2127 *pdwProcessId = _tcstoul( argv[argn], NULL, 0 );
2128 else
2129 bSuccess = false;
2130 }
2131 else if ( 0 == _tcsicmp( argv[argn], _T("-excp") ) ||
2132 0 == _tcsicmp( argv[argn], _T("/excp") ) )
2133 {
2134 if ( ++argn < argc )
2135 *ppException = (PEXCEPTION_POINTERS)_tcstoul( argv[argn], NULL, 0 );
2136 else
2137 bSuccess = false;
2138 }
2139 else if ( 0 == _tcsicmp( argv[argn], _T("-t") ) ||
2140 0 == _tcsicmp( argv[argn], _T("/t") ) )
2141 {
2142 if ( ++argn < argc )
2143 *pdwThreadId = _tcstoul( argv[argn], NULL, 0 );
2144 else
2145 bSuccess = false;
2146 }
2147 else if ( 0 == _tcsicmp( argv[argn], _T("-noui") ) ||
2148 0 == _tcsicmp( argv[argn], _T("/noui") ) )
2149 {
2150 g_bNoUserInterface = true;
2151 }
2152 else if ( 0 == _tcsicmp( argv[argn], _T("-send") ) ||
2153 0 == _tcsicmp( argv[argn], _T("/send") ) )
2154 {
2155 g_bSendReport = true;
2156 }
2157 else if ( 0 == _tcsicmp( argv[argn], _T("-load") ) ||
2158 0 == _tcsicmp( argv[argn], _T("/load") ) )
2159 {
2160 g_bLoadReport = true;
2161 }
2162 else // treat parameter as image path
2163 {
2164 TCHAR szImagePath[MAX_PATH];
2165 LPTSTR lpImageName;
2166
2167 if ( GetFullPathName( argv[argn], MAX_PATH, szImagePath, &lpImageName ) )
2168 {
2169 DWORD dwProcessId = FindProcessForImage( szImagePath );
2170
2171 if ( dwProcessId )
2172 *pdwProcessId = dwProcessId;
2173 else
2174 bSuccess = false;
2175 }
2176 }
2177 }
2178
2179 if ( !*pdwProcessId && !g_bLoadReport )
2180 {
2181 TCHAR szImagePath[MAX_PATH];
2182 LPTSTR lpImageName;
2183
2184 if ( GetFullPathName( TEXT("soffice.exe"), MAX_PATH, szImagePath, &lpImageName ) )
2185 {
2186 DWORD dwProcessId = FindProcessForImage( szImagePath );
2187
2188 if ( dwProcessId )
2189 *pdwProcessId = dwProcessId;
2190 else
2191 bSuccess = false;
2192 }
2193 }
2194
2195 return bSuccess;
2196 }
2197
2198 //***************************************************************************
2199
WriteCommentFile(LPCTSTR lpComment)2200 BOOL WriteCommentFile( LPCTSTR lpComment )
2201 {
2202 BOOL fSuccess = FALSE;
2203 TCHAR szTempPath[MAX_PATH];
2204
2205 if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
2206 {
2207 TCHAR szFileName[MAX_PATH];
2208
2209 if ( GetTempFileName( szTempPath, TEXT("CMT"), 0, szFileName ) )
2210 {
2211 HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
2212
2213 if ( hFile )
2214 {
2215 DWORD dwBytesWritten;
2216
2217 int needed = WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, NULL, 0, NULL, NULL );
2218 if ( needed )
2219 {
2220 char *lpCommentUTF8 = (char *)alloca( needed );
2221 WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, lpCommentUTF8, needed, NULL, NULL );
2222 fSuccess = WriteFile( hFile, lpCommentUTF8, strlen(lpCommentUTF8), &dwBytesWritten, NULL );
2223 }
2224 else
2225 fSuccess = TRUE;
2226
2227
2228 CloseHandle( hFile );
2229
2230 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szCommentFileNameA, MAX_PATH, NULL, NULL );
2231 }
2232
2233 if ( !fSuccess )
2234 DeleteFile( szFileName );
2235 }
2236 }
2237
2238 return fSuccess;
2239 }
2240
2241 //***************************************************************************
2242
_tsetenv(const _TCHAR * lpVar,const _TCHAR * lpValue)2243 static int _tsetenv( const _TCHAR *lpVar, const _TCHAR *lpValue )
2244 {
2245 if ( !lpValue )
2246 lpValue = _T("");
2247
2248 _TCHAR *envstr = (TCHAR *)alloca( (_tcslen( lpVar ) + _tcslen( lpValue ) + 2) * sizeof(_TCHAR) );
2249
2250 _tcscpy( envstr, lpVar );
2251 _tcscat( envstr, _T("=") );
2252 _tcscat( envstr, lpValue );
2253
2254 return _tputenv( envstr );
2255 }
2256
read_line(FILE * fp,string & rLine)2257 static bool read_line( FILE *fp, string& rLine )
2258 {
2259 char szBuffer[1024];
2260 bool bSuccess = false;
2261 bool bEOL = false;
2262 string line;
2263
2264
2265 while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) )
2266 {
2267 int len = strlen(szBuffer);
2268
2269 bSuccess = true;
2270
2271 while ( len && szBuffer[len - 1] == '\n' )
2272 {
2273 szBuffer[--len] = 0;
2274 bEOL = true;
2275 }
2276
2277 line.append( szBuffer );
2278 }
2279
2280 rLine = line;
2281 return bSuccess;
2282 }
2283
get_script_string(const char * pFileName,const char * pKeyName)2284 static string get_script_string( const char *pFileName, const char *pKeyName )
2285 {
2286 FILE *fp = fopen( pFileName, "rt" );
2287 string retValue;
2288
2289 if ( fp )
2290 {
2291 string line;
2292 string section;
2293
2294 while ( read_line( fp, line ) )
2295 {
2296 line = trim_string( line );
2297
2298
2299 string::size_type iEqualSign = line.find( '=', 0 );
2300
2301 if ( iEqualSign != string::npos )
2302 {
2303 string keyname = line.substr( 0, iEqualSign );
2304 keyname = trim_string( keyname );
2305
2306 string value = line.substr( sal::static_int_cast<string::size_type>(iEqualSign + 1) );
2307 value = trim_string( value );
2308
2309 if ( value.length() && '\"' == value[0] )
2310 {
2311 value.erase( 0, 1 );
2312
2313 string::size_type iQuotes = value.find( '"', 0 );
2314
2315 if ( iQuotes != string::npos )
2316 value.erase( iQuotes );
2317 }
2318
2319 if ( 0 == stricmp( keyname.c_str(), pKeyName ) )
2320 {
2321 retValue = value;
2322 break;
2323 }
2324 }
2325 }
2326
2327 fclose( fp );
2328 }
2329
2330 return retValue;
2331 }
2332
ReadBootstrapParams(CrashReportParams & rParams)2333 static bool ReadBootstrapParams( CrashReportParams &rParams )
2334 {
2335 TCHAR szBuffer[256] = TEXT("");
2336 TCHAR szModuleName[MAX_PATH];
2337 TCHAR szModuleVersionName[MAX_PATH];
2338 TCHAR szDrive[_MAX_DRIVE];
2339 TCHAR szDir[_MAX_DIR];
2340 TCHAR szFName[_MAX_FNAME];
2341 TCHAR szExt[_MAX_EXT];
2342 TCHAR szReportServer[MAX_HOSTNAME];
2343 TCHAR szReportPort[256];
2344 bool bSuccess = false;
2345
2346 GetModuleFileName( NULL, szModuleName, MAX_PATH );
2347 _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
2348 _tmakepath( szModuleName, szDrive, szDir, _T("bootstrap"), _T(".ini") );
2349 _tmakepath( szModuleVersionName, szDrive, szDir, _T("version"), _T(".ini") );
2350
2351 if (
2352 GetPrivateProfileString(
2353 TEXT("Bootstrap"),
2354 TEXT("ProductKey"),
2355 TEXT("OpenOffice"),
2356 szBuffer,
2357 elementsof(szBuffer),
2358 szModuleName )
2359 )
2360 {
2361 TCHAR *pVersion = _tcschr( szBuffer, ' ' );
2362
2363 g_wstrProductKey = szBuffer;
2364
2365 if ( pVersion )
2366 {
2367 *pVersion = 0;
2368 pVersion++;
2369 }
2370 else
2371 pVersion = TEXT("");
2372
2373 if ( !_tgetenv( _T("PRODUCTNAME") ) )
2374 {
2375 _tsetenv( TEXT("PRODUCTNAME"), szBuffer );
2376 }
2377 if ( !_tgetenv( _T("PRODUCTVERSION") ) )
2378 _tsetenv( TEXT("PRODUCTVERSION"), pVersion );
2379 }
2380
2381 GetPrivateProfileString(
2382 TEXT("Version"),
2383 TEXT("buildid"),
2384 TEXT("unknown"),
2385 g_szBuildId, elementsof(g_szBuildId),
2386 szModuleVersionName );
2387
2388 g_strDefaultLanguage = get_script_string( "instdb.inf", "DefaultLanguage" );
2389
2390 if ( GetPrivateProfileString(
2391 TEXT("ErrorReport"),
2392 TEXT("ErrorReportPort"),
2393 TEXT("80"),
2394 szReportPort, elementsof(szReportPort),
2395 szModuleName
2396 ) )
2397 {
2398 TCHAR *endptr = NULL;
2399
2400 unsigned short uReportPort = (unsigned short)_tcstoul( szReportPort, &endptr, 10 );
2401 if ( uReportPort )
2402 g_uReportPort = uReportPort;
2403 }
2404
2405 if ( GetPrivateProfileString(
2406 TEXT("ErrorReport"),
2407 TEXT("ErrorReportServer"),
2408 TEXT(""),
2409 szReportServer, elementsof(szReportServer),
2410 szModuleName
2411 ) )
2412 {
2413 bSuccess = 0 != WideCharToMultiByte( CP_ACP, 0, szReportServer, -1, g_szReportServerA, elementsof(g_szReportServerA), NULL, NULL );
2414 }
2415
2416 LPCTSTR lpEnvString;
2417
2418 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYSERVER") )) )
2419 rParams.sProxyServer = lpEnvString;
2420
2421 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYPORT") )) )
2422 rParams.sProxyPort = lpEnvString;
2423
2424 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_SENDERADDRESS") )) )
2425 rParams.sEmail = lpEnvString;
2426
2427 return bSuccess;
2428 }
2429
2430 //***************************************************************************
2431
SendHTTPRequest(FILE * fp,const char * pszServer,unsigned short uPort=80,const char * pszProxyServer=NULL,unsigned short uProxyPort=8080)2432 bool SendHTTPRequest(
2433 FILE *fp,
2434 const char *pszServer,
2435 unsigned short uPort = 80,
2436 const char *pszProxyServer = NULL,
2437 unsigned short uProxyPort = 8080 )
2438 {
2439 bool success = false;
2440
2441 struct hostent *hp;
2442
2443 if ( pszProxyServer )
2444 hp = gethostbyname( pszProxyServer );
2445 else
2446 hp = gethostbyname( pszServer );
2447
2448 if ( hp )
2449 {
2450 SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
2451
2452 if ( s )
2453 {
2454 struct sockaddr_in address;
2455
2456 memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr));
2457 address.sin_family = AF_INET;
2458
2459 if ( pszProxyServer )
2460 address.sin_port = ntohs( uProxyPort );
2461 else
2462 address.sin_port = ntohs( uPort );
2463
2464 if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) )
2465 {
2466 fseek( fp, 0, SEEK_END );
2467 size_t length = ftell( fp );
2468 fseek( fp, 0, SEEK_SET );
2469
2470 char buffer[2048];
2471
2472 if ( pszProxyServer )
2473 sprintf( buffer,
2474 "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
2475 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2476 "Content-Length: %d\r\n"
2477 "SOAPAction: \"\"\r\n\r\n",
2478 pszServer,
2479 uPort,
2480 length
2481 );
2482 else
2483 sprintf( buffer,
2484 "POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
2485 "Content-Type: text/xml; charset=\"utf-8\"\r\n"
2486 "Content-Length: %d\r\n"
2487 "SOAPAction: \"\"\r\n\r\n",
2488 length
2489 );
2490
2491 if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
2492 {
2493 size_t nBytes;
2494
2495 do
2496 {
2497 nBytes = fread( buffer, 1, sizeof(buffer), fp );
2498
2499 if ( nBytes )
2500 success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
2501 } while( nBytes && success );
2502
2503 if ( success )
2504 {
2505 memset( buffer, 0, sizeof(buffer) );
2506 success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 );
2507 if ( success )
2508 {
2509 char szHTTPSignature[sizeof(buffer)] = "";
2510 unsigned uHTTPReturnCode = 0;
2511
2512 sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode );
2513 success = uHTTPReturnCode == 200;
2514 }
2515 }
2516 }
2517
2518 }
2519
2520 closesocket( s );
2521 }
2522 }
2523
2524 return success;
2525 }
2526
2527 //***************************************************************************
2528
WriteSOAPRequest(FILE * fp)2529 static void WriteSOAPRequest( FILE *fp )
2530 {
2531 fprintf( fp,
2532 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
2533 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
2534 "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
2535 "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
2536 "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
2537 "xmlns:rds=\"urn:ReportDataService\"\n"
2538 "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
2539 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
2540 "<SOAP-ENV:Body>\n"
2541 );
2542
2543 fprintf( fp, "<rds:submitReport>\n" );
2544 fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
2545 fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
2546
2547 FILE *fpin = fopen( g_szReportFileNameA, "r" );
2548 if ( fpin )
2549 {
2550 fprintf( fp,
2551 "<item>\n"
2552 "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
2553 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2554 fcopy( fpin, fp );
2555 fprintf( fp, "]]></value></item>\n" );
2556 fclose( fpin );
2557 }
2558
2559 fpin = fopen( g_szCommentFileNameA, "r" );
2560 if ( fpin )
2561 {
2562 fprintf( fp,
2563 "<item>\n"
2564 "<key xsi:type=\"xsd:string\">description.txt</key>\n"
2565 "<value xsi:type=\"xsd:string\"><![CDATA[" );
2566 fcopy( fpin, fp );
2567 fprintf( fp, "]]></value></item>\n" );
2568 fclose( fpin );
2569 };
2570
2571
2572 fpin = fopen( g_szDumpFileNameA, "rb" );
2573 if ( fpin )
2574 {
2575 FILE *fptemp = _tmpfile();
2576
2577 if ( fptemp )
2578 {
2579 if ( base64_encode( fpin, fptemp ) )
2580 {
2581 fseek( fptemp, 0, SEEK_SET );
2582 fprintf( fp,
2583 "<item>\n"
2584 "<key xsi:type=\"xsd:string\">user.dmp</key>\n"
2585 "<value xsi:type=\"xsd:string\">" );
2586 fcopy( fptemp, fp );
2587 fprintf( fp, "</value></item>\n" );
2588 }
2589 fclose( fptemp );
2590 }
2591 fclose( fpin );
2592 }
2593
2594 fprintf( fp,
2595 "</hash>\n"
2596 "</rds:submitReport>\n"
2597 "</SOAP-ENV:Body>\n"
2598 "</SOAP-ENV:Envelope>\n"
2599 );
2600 }
2601
2602 //***************************************************************************
2603
2604 struct RequestParams
2605 {
2606 bool success;
2607 FILE *fpin;
2608 const char *lpServer;
2609 unsigned short uPort;
2610 const char *lpProxyServer;
2611 unsigned short uProxyPort;
2612 HWND hwndStatus;
2613 };
2614
SendingThread(void * lpArgs)2615 void _cdecl SendingThread( void *lpArgs )
2616 {
2617 RequestParams *pParams = (RequestParams *)lpArgs;
2618
2619 pParams->success = SendHTTPRequest( pParams->fpin, pParams->lpServer, pParams->uPort, pParams->lpProxyServer, pParams->uProxyPort );
2620
2621 PostMessage( pParams->hwndStatus, WM_COMMAND, IDOK, 0 );
2622 }
2623
2624 //***************************************************************************
2625
SendingStatusDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)2626 INT_PTR CALLBACK SendingStatusDialogProc(
2627 HWND hwndDlg,
2628 UINT uMsg,
2629 WPARAM wParam,
2630 LPARAM lParam
2631 )
2632 {
2633 static RequestParams *pRequest = NULL;
2634 static HANDLE hSendingThread = NULL;
2635
2636 switch ( uMsg )
2637 {
2638 case WM_INITDIALOG:
2639 {
2640 TCHAR szBuffer[1024] = TEXT("");
2641 HINSTANCE hInstance = (HINSTANCE)GetWindowLongPtr( hwndDlg, GWLP_HINSTANCE );
2642 //HWND hwndParent = (HWND)GetWindowLongPtr( hwndDlg, GWLP_HWNDPARENT );
2643
2644 pRequest = (RequestParams *)lParam;
2645
2646 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
2647 SetWindowText( hwndDlg, szBuffer );
2648
2649 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_STATUS, szBuffer, elementsof(szBuffer) );
2650 Static_SetText( GetDlgItem(hwndDlg, IDC_SENDING_REPORT_STATUS), szBuffer );
2651
2652 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
2653 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
2654
2655 pRequest->hwndStatus = hwndDlg;
2656
2657 hSendingThread = (HANDLE)_beginthread( SendingThread, 0, pRequest );
2658 }
2659 return TRUE;
2660 case WM_COMMAND:
2661 switch ( LOWORD(wParam) )
2662 {
2663 case IDCANCEL:
2664 TerminateThread( hSendingThread, 0 );
2665 case IDOK:
2666 WaitForSingleObject( hSendingThread, INFINITE );
2667 CloseHandle( hSendingThread );
2668 EndDialog( hwndDlg, wParam );
2669 return TRUE;
2670 }
2671 break;
2672 default:
2673 break;
2674 }
2675
2676 return FALSE;
2677 }
2678
2679 //***************************************************************************
2680
SendCrashReport(HWND hwndParent,const CrashReportParams & rParams)2681 bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams )
2682 {
2683 bool success = false;
2684 char szProxyServer[1024] = "";
2685 unsigned short uProxyPort = 8080;
2686 TCHAR *endptr = NULL;
2687
2688 switch ( rParams.uInternetConnection )
2689 {
2690 case 2:
2691 {
2692 WideCharToMultiByte(
2693 CP_ACP, 0, rParams.sProxyServer.c_str(), -1,
2694 szProxyServer, sizeof(szProxyServer), NULL, NULL );
2695 uProxyPort = (unsigned short)_tcstoul( rParams.sProxyPort.c_str(), &endptr, 10 );
2696 }
2697 break;
2698 case 0:
2699 {
2700 DWORD dwProxyEnable = 0;
2701
2702 RegReadValue( HKEY_CURRENT_USER,
2703 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
2704 TEXT("ProxyEnable"),
2705 &dwProxyEnable,
2706 sizeof(dwProxyEnable) );
2707
2708 if ( dwProxyEnable )
2709 {
2710 TCHAR tszProxyServers[1024] = TEXT("");
2711
2712 if ( ERROR_SUCCESS == RegReadValue( HKEY_CURRENT_USER,
2713 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
2714 TEXT("ProxyServer"),
2715 tszProxyServers,
2716 sizeof(tszProxyServers) ) )
2717 {
2718 TCHAR *lpHttpStart = _tcsstr( tszProxyServers, TEXT("http=") );
2719
2720 if ( lpHttpStart )
2721 lpHttpStart += 5;
2722 else
2723 lpHttpStart = tszProxyServers;
2724
2725 TCHAR *lpHttpEnd = _tcschr( lpHttpStart, ';' );
2726
2727 if ( lpHttpEnd )
2728 *lpHttpEnd = 0;
2729
2730 char szHTTPProxyServer[1024] = "";
2731 WideCharToMultiByte( CP_ACP, 0, lpHttpStart, -1, szHTTPProxyServer, sizeof(szHTTPProxyServer), NULL, NULL );
2732
2733 char *lpColon = strchr( szHTTPProxyServer, ':' );
2734
2735 if ( lpColon )
2736 {
2737 char *endptr = NULL;
2738
2739 *lpColon = 0;
2740 uProxyPort = (unsigned short)strtoul( lpColon + 1, &endptr, 10 );
2741 }
2742 else
2743 uProxyPort = 8080;
2744
2745 strcpy( szProxyServer, szHTTPProxyServer );
2746
2747 }
2748 }
2749 }
2750 break;
2751 default:
2752 case 1:
2753 break;
2754 }
2755
2756 FILE *fptemp = _tmpfile();
2757 if ( fptemp )
2758 {
2759 RequestParams request;
2760
2761 request.success = false;
2762 request.fpin = fptemp;
2763 request.lpServer = REPORT_SERVER;
2764 request.uPort = REPORT_PORT;
2765 request.lpProxyServer = szProxyServer[0] ? szProxyServer : NULL;
2766 request.uProxyPort = uProxyPort;
2767 request.hwndStatus = NULL;
2768
2769 WriteSOAPRequest( fptemp );
2770 fseek( fptemp, 0, SEEK_SET );
2771
2772 if ( hwndParent )
2773 {
2774 int retid = DialogBoxParam(
2775 GetModuleHandle(NULL),
2776 MAKEINTRESOURCE(IDD_SENDING_STATUS),
2777 hwndParent,
2778 SendingStatusDialogProc,
2779 (LPARAM)&request
2780 );
2781
2782 success = request.success;
2783
2784 if ( IDOK == retid )
2785 {
2786 if ( !success )
2787 {
2788 TCHAR szMessage[1024];
2789
2790 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) );
2791
2792 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
2793 }
2794 else
2795 {
2796 TCHAR szMessage[1024];
2797 TCHAR szTitle[1024];
2798
2799 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) );
2800 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_HEADER, szTitle, elementsof(szTitle) );
2801
2802 MessageBox( hwndParent, szMessage, szTitle, MB_ICONINFORMATION | MB_OK );
2803 }
2804 }
2805
2806 }
2807 else
2808 {
2809 HANDLE hSendingThread = (HANDLE)_beginthread( SendingThread, 0, (void *)&request );
2810
2811 WaitForSingleObject( hSendingThread, INFINITE );
2812
2813 success = request.success;
2814 if ( !success )
2815 {
2816 TCHAR szMessage[1024];
2817
2818 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) );
2819 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
2820 }
2821 else
2822 {
2823 TCHAR szMessage[1024];
2824
2825 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) );
2826
2827 _ftprintf( stderr, _T("SUCCESS: %s\n"), szMessage );
2828 }
2829 }
2830 fclose( fptemp );
2831 }
2832 else
2833 {
2834 TCHAR szMessage[1024];
2835
2836 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_DISK_FULL, szMessage, elementsof(szMessage) );
2837
2838 if ( hwndParent )
2839 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
2840 else
2841 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage );
2842 }
2843
2844 return success;
2845 }
2846
2847 //***************************************************************************
2848
2849 #ifdef __MINGW32__
WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR,int)2850 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR /*lpCmdLine*/, int )
2851 #else
2852 int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR /*lpCmdLine*/, int )
2853 #endif
2854 {
2855 int exitcode = -1;
2856 int argc = __argc;
2857
2858 #ifdef __MINGW32__
2859 char **argv = __argv;
2860 #else
2861 #ifdef _UNICODE
2862 char **argv = new char *[argc + 1];
2863
2864 for ( int argn = 0; argn < argc; argn++ )
2865 {
2866 int nBytes = WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, NULL, 0, NULL, NULL );
2867 argv[argn] = new char[nBytes];
2868 WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, argv[argn], nBytes, NULL, NULL );
2869 }
2870 argv[argc] = NULL;
2871 #else
2872 char **argv = __targv;
2873 #endif
2874 #endif
2875
2876 osl_setCommandArgs( argc, argv );
2877
2878 PEXCEPTION_POINTERS pExceptionPointers = NULL;
2879 DWORD dwProcessId = 0;
2880 DWORD dwThreadId = 0;
2881
2882 WSADATA wsaData;
2883 WORD wVersionRequested;
2884
2885 wVersionRequested = MAKEWORD(1, 1);
2886 WSAStartup(wVersionRequested, &wsaData);
2887
2888 CrashReportParams Params;
2889
2890 Params.ReadFromRegistry();
2891 Params.ReadFromEnvironment();
2892
2893 if ( ReadBootstrapParams( Params ) &&
2894 ParseCommandArgs( &dwProcessId, &pExceptionPointers, &dwThreadId ) )
2895 {
2896 bool bGotDumpFile;
2897
2898 if ( g_bLoadReport )
2899 bGotDumpFile = FindDumpFile();
2900 else
2901 bGotDumpFile = WriteDumpFile( dwProcessId, pExceptionPointers, dwThreadId );
2902
2903 if( bGotDumpFile )
2904 {
2905 hash_map< string, string > aLibraries;
2906
2907 if ( g_bLoadReport )
2908 {
2909 g_fpStackFile = _open_reportfile( _T(".stk"), _T("rb") );
2910 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("rb") );
2911 }
2912 else
2913 {
2914 if ( g_bSendReport )
2915 {
2916 g_fpStackFile = _tmpfile();
2917 g_fpChecksumFile = _tmpfile();
2918 }
2919 else
2920 {
2921 g_fpStackFile = _open_reportfile( _T(".stk"), _T("w+b") );
2922 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("w+b") );
2923
2924 FILE *fpUnsent = _open_reportfile( _T(".lck"), _T("w+b") );
2925 if ( fpUnsent )
2926 {
2927 fprintf( fpUnsent, "Unsent\r\n" );
2928 fclose( fpUnsent );
2929 }
2930 }
2931
2932 WriteStackFile( g_fpStackFile, aLibraries, dwProcessId, pExceptionPointers );
2933 WriteChecksumFile( g_fpChecksumFile, aLibraries );
2934 WriteReportFile( &Params );
2935
2936 FILE *fpPreview = _open_reportfile( _T(".prv"), _T("w+b") );
2937
2938 if ( fpPreview )
2939 {
2940 FILE *fp = fopen( g_szReportFileNameA, "rb" );
2941 if ( fp )
2942 {
2943 fcopy( fp, fpPreview );
2944 fclose( fp );
2945 }
2946 fclose( fpPreview );
2947 }
2948 }
2949
2950 if ( g_bSendReport )
2951 {
2952 InitCommonControls();
2953
2954 // Actually this should never be true anymore
2955 if ( !g_bNoUserInterface && InitRichEdit() )
2956 {
2957
2958 INT_PTR result = DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_DIALOG_FRAME), NULL, DialogProc, (LPARAM)&Params );
2959
2960 if ( result > 0 )
2961 {
2962 exitcode = 0;
2963 }
2964 DeinitRichEdit();
2965 }
2966 else
2967 {
2968 WriteCommentFile( Params.sComment.c_str() );
2969 WriteReportFile( &Params );
2970 if ( SendCrashReport( NULL, Params ) )
2971 exitcode = 0;
2972 }
2973
2974
2975 if ( g_szReportFileNameA[0] )
2976 DeleteFileA( g_szReportFileNameA );
2977
2978 if ( g_szCommentFileNameA[0] )
2979 DeleteFileA( g_szCommentFileNameA );
2980 }
2981 else
2982 {
2983 if ( g_szReportFileNameA[0] )
2984 DeleteFileA( g_szReportFileNameA );
2985 exitcode = 0;
2986 }
2987
2988 if ( g_szDumpFileNameA[0] && g_bSendReport )
2989 DeleteFileA( g_szDumpFileNameA );
2990
2991 if ( g_fpStackFile )
2992 fclose( g_fpStackFile );
2993
2994 if ( g_fpChecksumFile )
2995 fclose( g_fpChecksumFile );
2996 }
2997 }
2998
2999
3000 return exitcode;
3001 }
3002