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 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 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 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 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 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 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 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 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 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 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 472 static BOOL WINAPI InitRichEdit() 473 { 474 return (NULL != LoadLibrary( RICHEDIT )); 475 } 476 477 //*************************************************************************** 478 479 static BOOL WINAPI DeinitRichEdit() 480 { 481 return FreeLibrary( GetModuleHandle( RICHEDIT ) ); 482 } 483 484 //*************************************************************************** 485 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 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 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 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 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 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 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 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 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 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 779 static BOOL ScreenToClientRect( HWND hwnd, LPRECT lprc ) 780 { 781 return ScreenToClient( hwnd, (LPPOINT)&lprc->left ) && ScreenToClient( hwnd, (LPPOINT)&lprc->right ); 782 } 783 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 794 static BOOL SetGrowMode( HWND hwnd, DWORD dwGrowMode ) 795 { 796 return SetProp( hwnd, TEXT("GrowMode"), (HANDLE)dwGrowMode ); 797 } 798 799 static DWORD GetGrowMode( HWND hwnd ) 800 { 801 return (DWORD)GetProp( hwnd, TEXT("GrowMode") ); 802 } 803 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 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 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 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 //*************************************************************************** 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 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 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 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 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 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 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 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. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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__ 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