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