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