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( (int)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("${$BRAND_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.org\\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.org\\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.org\\CrashReport"), 325 TEXT("ReturnAddress"), 326 szBuffer, 327 sizeof(szBuffer) ) ) 328 sEmail = szBuffer; 329 330 RegReadValue( 331 HKEY_CURRENT_USER, 332 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"), 333 TEXT("AllowContact"), 334 &fAllowContact, 335 sizeof(fAllowContact) ); 336 337 RegReadValue( 338 HKEY_CURRENT_USER, 339 TEXT("SOFTWARE\\OpenOffice.org\\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.org\\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.org\\CrashReport"), 362 TEXT("HTTPProxyPort"), REG_DWORD, 363 &dwProxyPort, 364 sizeof(DWORD) ); 365 366 RegWriteValue( 367 HKEY_CURRENT_USER, 368 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"), 369 TEXT("AllowContact"), REG_DWORD, 370 &fAllowContact, 371 sizeof(DWORD) ); 372 373 374 RegWriteValue( 375 HKEY_CURRENT_USER, 376 TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"), 377 TEXT("HTTPConnection"), REG_DWORD, 378 &uInternetConnection, 379 sizeof(DWORD) ); 380 381 RegWriteValue( 382 HKEY_CURRENT_USER, 383 TEXT("SOFTWARE\\OpenOffice.org\\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 occurences of '&' because it may occur in further 569 // encoded chardters 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( (LONG)hFile, _O_TEXT ); 670 FILE *fp = _fdopen( fd, "w+t" ); 671 CHAR szTitle[1024] = ""; 672 CHAR szBuildId[1024] = ""; 673 CHAR szEmail[1024] = ""; 674 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" ); 675 676 WideCharToMultiByte( CP_UTF8, 0, pParams->sTitle.c_str(), -1, szTitle, sizeof(szTitle), NULL, NULL ); 677 WideCharToMultiByte( CP_UTF8, 0, g_szBuildId, -1, szBuildId, sizeof(szBuildId), NULL, NULL ); 678 WideCharToMultiByte( CP_UTF8, 0, pParams->sEmail.c_str(), -1, szEmail, sizeof(szEmail), NULL, NULL ); 679 680 fprintf( fp, 681 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 682 "<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n" 683 "<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n" 684 "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n", 685 pszUserType ? pszUserType : "", 686 pParams->fAllowContact ? "true" : "false", 687 pParams->fAllowContact ? xml_encode(szEmail).c_str() : "" 688 ); 689 690 fprintf( fp, 691 "<reportmail:title>%s</reportmail:title>\n", 692 xml_encode(szTitle).c_str() ); 693 694 fprintf( fp, 695 "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain;charset=UTF-8\" class=\"UserComment\"/>\n" 696 "<reportmail:attachment name=\"user.dmp\" media-type=\"application/octet-stream\" class=\"UserDump\"/>\n" 697 "</reportmail:mail>\n" 698 699 "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" procpath=\"%s\" exceptiontype=\"0x%08X\" product=\"%s\"/>\n", 700 szBuildId, 701 _INPATH, 702 xml_encode(g_strDefaultLanguage).c_str(), 703 xml_encode(GetModuleDirectory( NULL )).c_str(), 704 g_dwExceptionCode, 705 xml_encode(wstring2utf8(g_wstrProductKey)).c_str() 706 ); 707 708 OSVERSIONINFO VersionInfo; 709 710 ZeroMemory( &VersionInfo, sizeof(VersionInfo) ); 711 VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo ); 712 713 GetVersionEx( &VersionInfo ); 714 715 fprintf( fp, 716 "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n" 717 "<systeminfo:System name=\"%s\" version=\"%d.%d\" build=\"%d\" locale=\"0x%08x\"/>\n" 718 , 719 VER_PLATFORM_WIN32_NT == VersionInfo.dwPlatformId ? "Windows NT" : "Windows", 720 VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion, 721 VersionInfo.dwBuildNumber, 722 GetUserDefaultLangID() 723 724 ); 725 fprintf( fp, "<systeminfo:CPU type=\"x86\"/>\n" ); 726 fprintf( fp, "</systeminfo:systeminfo>\n" ); 727 728 fseek( g_fpStackFile, 0, SEEK_SET ); 729 fcopy( g_fpStackFile, fp ); 730 731 fseek( g_fpChecksumFile, 0, SEEK_SET ); 732 fcopy( g_fpChecksumFile, fp ); 733 734 fprintf( fp, "</errormail:errormail>\n" ); 735 736 fclose( fp ); 737 738 fSuccess = TRUE; 739 740 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szReportFileNameA, MAX_PATH, NULL, NULL ); 741 } 742 743 if ( !fSuccess ) 744 DeleteFile( szFileName ); 745 } 746 } 747 748 return fSuccess; 749 } 750 751 //*************************************************************************** 752 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 BOOL CALLBACK PreviewDialogProc( 862 HWND hwndDlg, 863 UINT uMsg, 864 WPARAM wParam, 865 LPARAM lParam 866 ) 867 { 868 static RECT rcClient; 869 870 switch ( uMsg ) 871 { 872 case WM_SIZE: 873 { 874 LONG cx = LOWORD( lParam ); 875 LONG cy = HIWORD( lParam ); 876 LONG dxClient, dyClient; 877 878 dxClient = cx - rcClient.right; 879 dyClient = cy - rcClient.bottom; 880 881 EnumChildWindows( hwndDlg, GrowChildWindows, MAKELONG( (SHORT)dxClient, (SHORT)dyClient) ); 882 883 GetClientRect( hwndDlg, &rcClient ); 884 } 885 break; 886 case WM_INITDIALOG: 887 { 888 GetClientRect( hwndDlg, &rcClient ); 889 SetGrowMode( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GM_HIX | GM_HIY ); 890 SetGrowMode( GetDlgItem(hwndDlg, IDOK), GM_LOX | GM_HIX | GM_LOY | GM_HIY ); 891 892 CrashReportParams *pParams = (CrashReportParams *)lParam; 893 894 TCHAR szBuffer[256] = TEXT(""); 895 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE ); 896 HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT ); 897 898 GetWindowText( hwndParent, szBuffer, elementsof(szBuffer) ); 899 SetWindowText( hwndDlg, szBuffer ); 900 901 LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) ); 902 Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer ); 903 904 basic_string<TCHAR> aString; 905 906 aString.append( pParams->sTitle ); 907 aString.append( _T("\r\n\r\n") ); 908 aString.append( pParams->sComment ); 909 aString.append( _T("\r\n---------- report ----------\r\n") ); 910 911 FILE *fp = fopen( g_szReportFileNameA, "r" ); 912 913 if ( fp ) 914 { 915 char buf[1024]; 916 917 while ( fgets( buf, elementsof(buf), fp ) != NULL ) 918 { 919 WCHAR bufW[1024]; 920 921 MultiByteToWideChar( CP_UTF8, 0, buf, -1, bufW, elementsof(bufW) ); 922 923 aString.append( bufW ); 924 } 925 926 fclose( fp ); 927 } 928 929 aString.append( _T("\r\n---------- stack ----------\r\n") ); 930 931 fp = fopen( g_szDumpFileNameA, "rb" ); 932 933 if ( fp ) 934 { 935 unsigned char buf[16]; 936 int count; 937 938 do 939 { 940 int i; 941 942 count = fread( buf, sizeof(buf[0]), sizeof(buf)/sizeof(buf[0]), fp ); 943 944 for ( i = 0; i < count; i++ ) 945 { 946 TCHAR output[16]; 947 948 _sntprintf( output, elementsof(output), _T("%02X\x20"), buf[i] ); 949 aString.append( output ); 950 } 951 for ( ; i < elementsof(buf); i++ ) 952 { 953 aString.append( _T("\x20\x20\x20") ); 954 } 955 956 for ( i = 0; i < count; i++ ) 957 { 958 TCHAR output[2]; 959 960 if ( (int)buf[i] >= 0x20 && (int)buf[i] <= 0x7F ) 961 output[0] = (TCHAR)buf[i]; 962 else 963 output[0] = '.'; 964 output[1] = 0; 965 aString.append( output ); 966 } 967 968 aString.append( _T("\r\n") ); 969 970 } while ( count ); 971 972 fclose( fp ); 973 } 974 975 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), aString.c_str() ); 976 977 978 SetWindowFont( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GetStockObject( SYSTEM_FIXED_FONT ), TRUE ); 979 } 980 return TRUE; 981 case WM_COMMAND: 982 switch ( LOWORD(wParam) ) 983 { 984 case IDOK: 985 case IDCANCEL: 986 EndDialog( hwndDlg, wParam ); 987 return TRUE; 988 } 989 break; 990 default: 991 break; 992 } 993 994 return FALSE; 995 } 996 //*************************************************************************** 997 998 static void PreviewReport( HWND hwndParent, CrashReportParams *pParams ) 999 { 1000 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE ); 1001 1002 WriteReportFile( pParams ); 1003 1004 DialogBoxParam( 1005 hInstance, 1006 MAKEINTRESOURCE(IDD_PREVIEW_FRAME), 1007 hwndParent, 1008 PreviewDialogProc, 1009 (LPARAM)pParams 1010 ); 1011 1012 DeleteFileA( g_szReportFileNameA ); 1013 } 1014 //*************************************************************************** 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 BOOL CALLBACK OptionsDialogProc( 1032 HWND hwndDlg, 1033 UINT uMsg, 1034 WPARAM wParam, 1035 LPARAM lParam 1036 ) 1037 { 1038 static CrashReportParams *pParams; 1039 1040 switch ( uMsg ) 1041 { 1042 case WM_INITDIALOG: 1043 { 1044 TCHAR szBuffer[1024] = TEXT(""); 1045 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE ); 1046 //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT ); 1047 1048 pParams = (CrashReportParams *)lParam; 1049 1050 LoadAndFormatString( hInstance, IDS_OPTIONS_CAPTION, szBuffer, elementsof(szBuffer) ); 1051 SetWindowText( hwndDlg, szBuffer ); 1052 1053 LoadAndFormatString( hInstance, IDS_PROXY_SETTINGS_HEADER, szBuffer, elementsof(szBuffer) ); 1054 Static_SetText( GetDlgItem(hwndDlg, IDC_PROXY_SETTINGS), szBuffer ); 1055 1056 LoadAndFormatString( hInstance, IDS_PROXY_SYSTEM, szBuffer, elementsof(szBuffer) ); 1057 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM), szBuffer ); 1058 1059 LoadAndFormatString( hInstance, IDS_PROXY_DIRECT, szBuffer, elementsof(szBuffer) ); 1060 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT), szBuffer ); 1061 1062 LoadAndFormatString( hInstance, IDS_PROXY_MANUAL, szBuffer, elementsof(szBuffer) ); 1063 Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL), szBuffer ); 1064 1065 LoadAndFormatString( hInstance, IDS_LABEL_PROXYSERVER, szBuffer, elementsof(szBuffer) ); 1066 Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYSERVER), szBuffer ); 1067 1068 LoadAndFormatString( hInstance, IDS_LABEL_PROXYPORT, szBuffer, elementsof(szBuffer) ); 1069 Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYPORT), szBuffer ); 1070 1071 LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) ); 1072 Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer ); 1073 1074 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) ); 1075 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer ); 1076 1077 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), pParams->sProxyServer.c_str() ); 1078 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), pParams->sProxyPort.c_str() ); 1079 1080 Button_SetCheck( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM + pParams->uInternetConnection), BST_CHECKED ); 1081 1082 SendMessage( 1083 GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), 1084 EM_SETBKGNDCOLOR, 1085 (WPARAM)FALSE, 1086 GetSysColor( COLOR_3DFACE ) ); 1087 LoadAndFormatString( hInstance, IDS_PROXY_DESCRIPTION, szBuffer, elementsof(szBuffer) ); 1088 Edit_SetText( GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), szBuffer ); 1089 1090 UpdateOptionsDialogControls( hwndDlg ); 1091 } 1092 return TRUE; 1093 case WM_COMMAND: 1094 switch ( LOWORD(wParam) ) 1095 { 1096 case IDC_RADIO_SYSTEM: 1097 case IDC_RADIO_DIRECT: 1098 case IDC_RADIO_MANUAL: 1099 if ( BN_CLICKED == HIWORD(wParam) ) 1100 UpdateOptionsDialogControls( hwndDlg ); 1101 break; 1102 case IDOK: 1103 { 1104 TCHAR szBuffer[1024]; 1105 1106 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), szBuffer, elementsof(szBuffer) ); 1107 pParams->sProxyServer = szBuffer; 1108 1109 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), szBuffer, elementsof(szBuffer) ); 1110 pParams->sProxyPort = szBuffer; 1111 1112 if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT) ) & BST_CHECKED ) 1113 pParams->uInternetConnection = 1; 1114 else if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED ) 1115 pParams->uInternetConnection = 2; 1116 else 1117 pParams->uInternetConnection = 0; 1118 } 1119 case IDCANCEL: 1120 EndDialog( hwndDlg, wParam ); 1121 return TRUE; 1122 } 1123 break; 1124 default: 1125 break; 1126 } 1127 1128 return FALSE; 1129 } 1130 1131 //*************************************************************************** 1132 1133 static void OptionsDialog( HWND hwndParent, CrashReportParams *pParams ) 1134 { 1135 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE ); 1136 1137 if ( IDOK == DialogBoxParam( 1138 hInstance, 1139 MAKEINTRESOURCE(IDD_OPTIONS_FRAME), 1140 hwndParent, 1141 OptionsDialogProc, 1142 (LPARAM)pParams 1143 ) ) 1144 pParams->WriteToRegistry(); 1145 1146 } 1147 //*************************************************************************** 1148 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 BOOL CALLBACK ReportDialogProc( 1162 HWND hwndDlg, 1163 UINT uMsg, 1164 WPARAM wParam, 1165 LPARAM 1166 ) 1167 { 1168 switch ( uMsg ) 1169 { 1170 case WM_INITDIALOG: 1171 { 1172 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); 1173 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); 1174 TCHAR szBuffer[FORMATBUFSIZE]; 1175 1176 LoadAndFormatString( hInstance, IDS_REPORT_INTRO, szBuffer, elementsof(szBuffer) ); 1177 Static_SetText( GetDlgItem(hwndDlg, IDC_REPORT_INTRO), szBuffer ); 1178 1179 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT3), szBuffer ); 1180 1181 LoadAndFormatString( hInstance, IDS_ENTER_TITLE, szBuffer, elementsof(szBuffer) ); 1182 Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_TITLE), szBuffer ); 1183 1184 LoadAndFormatString( hInstance, IDS_ENTER_DESCRIPTION, szBuffer, elementsof(szBuffer) ); 1185 Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_DESCRIPTION), szBuffer ); 1186 1187 LoadAndFormatString( hInstance, IDS_SHOW_REPORT_BUTTON, szBuffer, elementsof(szBuffer) ); 1188 Button_SetText( GetDlgItem(hwndDlg, IDC_SHOW_REPORT), szBuffer ); 1189 1190 LoadAndFormatString( hInstance, IDS_SAVE_REPORT_BUTTON, szBuffer, elementsof(szBuffer) ); 1191 Button_SetText( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), szBuffer ); 1192 1193 const char *pszUserType = getenv( "STAROFFICE_USERTYPE" ); 1194 if ( pszUserType ) 1195 ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_SHOW ); 1196 else 1197 ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_HIDE ); 1198 1199 LoadAndFormatString( hInstance, IDS_OPTIONS_BUTTON, szBuffer, elementsof(szBuffer) ); 1200 Button_SetText( GetDlgItem(hwndDlg, IDC_OPTIONS), szBuffer ); 1201 1202 LoadAndFormatString( hInstance, IDS_ALLOW_CONTACT, szBuffer, elementsof(szBuffer) ); 1203 Button_SetText( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), szBuffer ); 1204 Button_SetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), pParams->fAllowContact ? BST_CHECKED : BST_UNCHECKED ); 1205 1206 LoadAndFormatString( hInstance, IDS_LABEL_EMAIL, szBuffer, elementsof(szBuffer) ); 1207 Button_SetText( GetDlgItem(hwndDlg, IDC_LABEL_EMAIL), szBuffer ); 1208 1209 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), pParams->sEmail.c_str() ); 1210 1211 UpdateReportDialogControls( hwndDlg ); 1212 } 1213 return TRUE; 1214 case WM_SHOWWINDOW: 1215 if ( (BOOL)wParam ) 1216 { 1217 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); 1218 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); 1219 TCHAR szBuffer[FORMATBUFSIZE]; 1220 1221 LoadAndFormatString( hInstance, IDS_REPORT_CAPTION, szBuffer, elementsof(szBuffer) ); 1222 SetWindowText( GetParent(hwndDlg), szBuffer ); 1223 1224 LoadAndFormatString( hInstance, IDS_REPORT_HEADER, szBuffer, elementsof(szBuffer) ); 1225 SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer ); 1226 1227 LoadAndFormatString( hInstance, IDS_DONOT_SEND_BUTTON, szBuffer, elementsof(szBuffer) ); 1228 Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer ); 1229 1230 1231 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), TRUE ); 1232 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), TRUE ); 1233 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), FALSE ); 1234 1235 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), pParams->sTitle.c_str() ); 1236 Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), pParams->sComment.c_str() ); 1237 1238 /* 1239 SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE, 1240 GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE) | BS_DEFPUSHBUTTON ); 1241 SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE, 1242 GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE) &~ BS_DEFPUSHBUTTON ); 1243 */ 1244 SetFocus( GetDlgItem(hwndDlg,IDC_EDIT_TITLE) ); 1245 } 1246 break; 1247 case WM_COMMAND: 1248 switch ( LOWORD(wParam) ) 1249 { 1250 case IDC_SHOW_REPORT: 1251 { 1252 TCHAR szBuffer[32767]; 1253 1254 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); 1255 1256 pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT) ) ? TRUE : FALSE; 1257 1258 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), szBuffer, elementsof(szBuffer) ); 1259 pParams->sTitle = szBuffer; 1260 1261 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), szBuffer, elementsof(szBuffer) ); 1262 pParams->sComment = szBuffer; 1263 1264 Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), szBuffer, elementsof(szBuffer) ); 1265 pParams->sEmail = szBuffer; 1266 1267 PreviewReport( GetParent(hwndDlg), pParams ); 1268 } 1269 return TRUE; 1270 case IDC_SAVE_REPORT: 1271 SaveDumpFile( GetParent(hwndDlg) ); 1272 return TRUE; 1273 case IDC_OPTIONS: 1274 { 1275 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA ); 1276 OptionsDialog( GetParent(hwndDlg), pParams ); 1277 } 1278 return TRUE; 1279 case IDC_ALLOW_CONTACT: 1280 if ( BN_CLICKED == HIWORD(wParam) ) 1281 UpdateReportDialogControls( hwndDlg ); 1282 return TRUE; 1283 } 1284 break; 1285 default: 1286 break; 1287 } 1288 1289 return FALSE; 1290 } 1291 //*************************************************************************** 1292 1293 BOOL CALLBACK WelcomeDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) 1294 { 1295 switch ( uMsg ) 1296 { 1297 case WM_INITDIALOG: 1298 { 1299 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); 1300 HWND hwndRichEdit = GetDlgItem(hwndDlg, IDC_RICHEDIT21); 1301 TCHAR szBuffer[FORMATBUFSIZE]; 1302 TCHAR szBuffer2[FORMATBUFSIZE]; 1303 TCHAR szURL[256]; 1304 TCHAR szCaption[256]; 1305 1306 SendMessage( 1307 hwndRichEdit, 1308 EM_SETBKGNDCOLOR, 1309 (WPARAM)FALSE, 1310 GetSysColor( COLOR_3DFACE ) ); 1311 1312 SendMessage( hwndRichEdit, EM_SETEVENTMASK, 0, ENM_LINK ); 1313 SendMessage( hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0 ); 1314 1315 LoadAndFormatString( hInstance, IDS_WELCOME_BODY1, szBuffer, elementsof(szBuffer) ); 1316 LoadAndFormatString( hInstance, IDS_WELCOME_BODY2, szBuffer2, elementsof(szBuffer2) ); 1317 _tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) ); 1318 LoadAndFormatString( hInstance, IDS_WELCOME_BODY3, szBuffer2, elementsof(szBuffer2) ); 1319 _tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) ); 1320 LoadString( hInstance, IDS_PRIVACY_URL, szURL, elementsof(szURL) ); 1321 _tcsncat( szBuffer, szURL, elementsof(szBuffer) ); 1322 SetWindowText( hwndRichEdit, szBuffer ); 1323 1324 LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szCaption, elementsof(szCaption) ); 1325 SetWindowText( GetParent(hwndDlg), szCaption ); 1326 1327 } 1328 return TRUE; 1329 case WM_SHOWWINDOW: 1330 if ( (BOOL)wParam ) 1331 { 1332 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); 1333 TCHAR szBuffer[FORMATBUFSIZE]; 1334 1335 LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szBuffer, elementsof(szBuffer) ); 1336 SetWindowText( GetParent(hwndDlg), szBuffer ); 1337 1338 LoadAndFormatString( hInstance, IDS_WELCOME_HEADER, szBuffer, elementsof(szBuffer) ); 1339 SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer ); 1340 1341 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) ); 1342 Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer ); 1343 1344 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), FALSE ); 1345 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), FALSE ); 1346 ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), TRUE ); 1347 1348 SetFocus( GetDlgItem(GetParent(hwndDlg),IDNEXT) ); 1349 } 1350 break; 1351 case WM_NOTIFY: 1352 { 1353 LPNMHDR pnmh = (LPNMHDR)lParam; 1354 1355 if ( pnmh->idFrom == IDC_RICHEDIT21 && pnmh->code == EN_LINK ) 1356 { 1357 ENLINK *plink = (ENLINK*)lParam; 1358 1359 if ( plink->msg == WM_LBUTTONUP ) 1360 { 1361 TCHAR szBuffer[256]; 1362 TEXTRANGE range; 1363 1364 range.chrg = plink->chrg; 1365 range.lpstrText = szBuffer; 1366 1367 SendMessage( pnmh->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&range ); 1368 1369 ShellExecute( hwndDlg, NULL, szBuffer, NULL, NULL, SW_SHOWDEFAULT ); 1370 } 1371 1372 } 1373 } 1374 break; 1375 default: 1376 break; 1377 } 1378 1379 return FALSE; 1380 } 1381 //*************************************************************************** 1382 1383 BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) 1384 { 1385 static HWND hwndPages[2] = { NULL }; 1386 static int iActualPage = 0; 1387 1388 switch ( uMsg ) 1389 { 1390 case WM_INITDIALOG: 1391 { 1392 HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE ); 1393 TCHAR szBuffer[FORMATBUFSIZE]; 1394 1395 SetWindowLong( hwndDlg, GWL_USERDATA, (LONG)lParam ); 1396 hwndPages[0] = CreateDialog( 1397 hInstance, 1398 MAKEINTRESOURCE(IDD_WELCOME_PAGE), 1399 hwndDlg, 1400 WelcomeDialogProc ); 1401 1402 hwndPages[1] = CreateDialog( 1403 hInstance, 1404 MAKEINTRESOURCE(IDD_REPORT_PAGE), 1405 hwndDlg, 1406 ReportDialogProc ); 1407 1408 CHARFORMAT chfmt; 1409 1410 chfmt.cbSize = sizeof(chfmt); 1411 chfmt.dwMask = CFM_BOLD; 1412 chfmt.dwEffects = CFE_BOLD; 1413 1414 SendMessage( 1415 GetDlgItem(hwndDlg, IDC_HEADER), 1416 EM_SETCHARFORMAT, 1417 SCF_ALL, 1418 (LPARAM)&chfmt ); 1419 1420 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) ); 1421 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer ); 1422 1423 LoadAndFormatString( hInstance, IDS_NEXT_BUTTON, szBuffer, elementsof(szBuffer) ); 1424 Button_SetText( GetDlgItem(hwndDlg, IDNEXT), szBuffer ); 1425 1426 LoadAndFormatString( hInstance, IDS_SEND_BUTTON, szBuffer, elementsof(szBuffer) ); 1427 Button_SetText( GetDlgItem(hwndDlg, IDFINISH), szBuffer ); 1428 1429 LoadAndFormatString( hInstance, IDS_BACK_BUTTON, szBuffer, elementsof(szBuffer) ); 1430 Button_SetText( GetDlgItem(hwndDlg, IDBACK), szBuffer ); 1431 1432 ShowWindow( hwndPages[1], SW_HIDE ); 1433 ShowWindow( hwndPages[0], SW_SHOW ); 1434 1435 // Let Crash Reporter window stay on top of all other windows 1436 SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE ); 1437 } 1438 return FALSE; 1439 case WM_CTLCOLORSTATIC: 1440 return (BOOL)CreateSolidBrush(GetSysColor(COLOR_WINDOW)); 1441 case WM_COMMAND: 1442 switch ( LOWORD(wParam) ) 1443 { 1444 case IDBACK: 1445 if ( iActualPage > 0 ) 1446 { 1447 ShowWindow( hwndPages[iActualPage], SW_HIDE ); 1448 ShowWindow( hwndPages[--iActualPage], SW_SHOW ); 1449 } 1450 return TRUE; 1451 case IDNEXT: 1452 if ( iActualPage < elementsof(hwndPages) - 1 ) 1453 { 1454 ShowWindow( hwndPages[iActualPage], SW_HIDE ); 1455 ShowWindow( hwndPages[++iActualPage], SW_SHOW ); 1456 } 1457 return TRUE; 1458 case IDFINISH: 1459 { 1460 TCHAR szBuffer[32767]; 1461 CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( hwndDlg, GWL_USERDATA ); 1462 1463 pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndPages[1], IDC_ALLOW_CONTACT) ) ? TRUE : FALSE; 1464 1465 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_TITLE), szBuffer, elementsof(szBuffer) ); 1466 pParams->sTitle = szBuffer; 1467 1468 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_DESCRIPTION), szBuffer, elementsof(szBuffer) ); 1469 pParams->sComment = szBuffer; 1470 1471 Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_EMAIL), szBuffer, elementsof(szBuffer) ); 1472 pParams->sEmail = szBuffer; 1473 1474 if ( pParams->fAllowContact && !pParams->sEmail.length() ) 1475 { 1476 TCHAR szMessage[MAX_TEXT_BUFFER]; 1477 1478 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_NOEMAILADDRESS, szMessage, elementsof(szMessage) ); 1479 1480 MessageBox( hwndDlg, szMessage, NULL, MB_ICONERROR | MB_OK ); 1481 break; // Don't end the dialog 1482 } 1483 else 1484 { 1485 pParams->WriteToRegistry(); 1486 1487 WriteCommentFile( pParams->sComment.c_str() ); 1488 WriteReportFile( pParams ); 1489 1490 if ( !SendCrashReport( hwndDlg, *pParams ) ) 1491 break; // Don't end the dialog 1492 } 1493 } 1494 // Fallthrough !!! 1495 case IDCANCEL: 1496 EndDialog( hwndDlg, wParam ); 1497 return TRUE; 1498 } 1499 break; 1500 default: 1501 break; 1502 } 1503 1504 return FALSE; 1505 } 1506 1507 1508 1509 //***************************************************************************** 1510 //* Generate MD5 checksum 1511 //***************************************************************************** 1512 1513 #define MAGIC_DESCRIPTION_FILLER 'x' 1514 #define MAGIC_DESCRIPTION_COUNT 80 1515 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 frame.AddrPC.Offset = aContextRecord.Eip; 1729 frame.AddrPC.Mode = AddrModeFlat; 1730 frame.AddrFrame.Offset = aContextRecord.Ebp; 1731 frame.AddrFrame.Mode = AddrModeFlat; 1732 1733 BOOL bSuccess; 1734 int frameNum = 0; 1735 1736 SymInitialize( hProcess, NULL, TRUE ); 1737 1738 fprintf( fout, "<errormail:Stack type=\"Win32\">\n" ); 1739 1740 do 1741 { 1742 fSuccess = true; 1743 1744 bSuccess = StackWalk( IMAGE_FILE_MACHINE_I386, 1745 hProcess, 1746 NULL, 1747 &frame, 1748 &aContextRecord, 1749 (PREAD_PROCESS_MEMORY_ROUTINE)ReadProcessMemory, 1750 SymFunctionTableAccess, 1751 SymGetModuleBase, 1752 NULL ); 1753 1754 if ( bSuccess ) 1755 { 1756 // Note: ImageHelp ANSI functions do not have an A postfix while 1757 // Unicode versions have a W postfix. There's no macro 1758 // that depends on define UNICODE 1759 1760 IMAGEHLP_MODULE moduleInfo; 1761 1762 ZeroMemory( &moduleInfo, sizeof(moduleInfo) ); 1763 moduleInfo.SizeOfStruct = sizeof(moduleInfo); 1764 1765 if ( SymGetModuleInfo( hProcess, frame.AddrPC.Offset, &moduleInfo ) ) 1766 { 1767 rLibraries[ GetFileName( moduleInfo.LoadedImageName ).c_str() ] = moduleInfo.LoadedImageName; 1768 1769 DWORD dwRelOffset = 0; 1770 BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 256 ]; 1771 PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer; 1772 1773 ZeroMemory( symbolBuffer, sizeof(symbolBuffer) ); 1774 pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); 1775 pSymbol->MaxNameLength = 256; 1776 1777 if ( SymGetSymFromAddr( hProcess, frame.AddrPC.Offset, &dwRelOffset, pSymbol ) ) 1778 fprintf( fout, "<errormail:StackInfo " \ 1779 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" ordinal=\"%s+0x%p\" name=\"%s\" path=\"%s\"/>\n", 1780 frameNum, 1781 frame.AddrPC.Offset, 1782 frame.AddrPC.Offset - moduleInfo.BaseOfImage, 1783 xml_encode(pSymbol->Name).c_str(), 1784 frame.AddrPC.Offset - pSymbol->Address, 1785 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(), 1786 xml_encode( GetFileDirectory( moduleInfo.LoadedImageName )).c_str() 1787 ); 1788 else 1789 fprintf( fout, "<errormail:StackInfo " \ 1790 "pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" name=\"%s\" path=\"%s\"/>\n", 1791 frameNum, 1792 frame.AddrPC.Offset, 1793 frame.AddrPC.Offset - moduleInfo.BaseOfImage, 1794 xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(), 1795 xml_encode(GetFileDirectory( moduleInfo.LoadedImageName )).c_str() 1796 ); 1797 } 1798 else 1799 fprintf( fout, "<errormail:StackInfo pos=\"%d\" ip=\"0x%p\"/>\n", 1800 frameNum, 1801 frame.AddrPC.Offset 1802 ); 1803 1804 frameNum++; 1805 } 1806 1807 } while ( bSuccess ); 1808 1809 fprintf( fout, "</errormail:Stack>\n" ); 1810 1811 SymCleanup( hProcess ); 1812 1813 CloseHandle( hProcess ); 1814 } 1815 1816 } 1817 1818 return fSuccess; 1819 } 1820 1821 bool WriteChecksumFile( FILE *fchksum, const hash_map< string, string >& rLibraries ) 1822 { 1823 bool success = false; 1824 1825 if ( fchksum && rLibraries.size() ) 1826 { 1827 fprintf( fchksum, "<errormail:Checksums type=\"MD5\">\n" ); 1828 1829 hash_map< string, string >::const_iterator iter; 1830 1831 for ( iter = rLibraries.begin(); 1832 iter != rLibraries.end(); 1833 iter++ ) 1834 { 1835 sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5]; 1836 sal_uInt32 nBytesProcessed = calc_md5_checksum( 1837 iter->second.c_str(), 1838 checksum, sizeof(checksum) ); 1839 1840 if ( nBytesProcessed ) 1841 { 1842 fprintf( fchksum, "<errormail:Checksum sum=\"0x" ); 1843 for ( int i = 0; i < sizeof(checksum); fprintf( fchksum, "%02X", checksum[i++] ) ); 1844 fprintf( fchksum, "\" bytes=\"%d\" file=\"%s\"/>\n", 1845 nBytesProcessed, 1846 GetFileName( iter->first ).c_str() ); 1847 } 1848 } 1849 1850 fprintf( fchksum, "</errormail:Checksums>\n" ); 1851 1852 success = true; 1853 } 1854 1855 return success; 1856 } 1857 1858 //*************************************************************************** 1859 1860 BOOL FindDumpFile() 1861 { 1862 TCHAR szFileName[MAX_PATH]; 1863 1864 if ( GetCrashDataPath( szFileName ) ) 1865 { 1866 _tcscat( szFileName, _T("\\crashdat.dmp") ); 1867 1868 HANDLE hFile = CreateFile( 1869 szFileName, 1870 GENERIC_READ, 1871 0, NULL, 1872 OPEN_EXISTING, 1873 FILE_ATTRIBUTE_NORMAL, NULL ); 1874 1875 if ( hFile ) 1876 { 1877 CloseHandle( hFile ); 1878 1879 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL ); 1880 _tcscpy( g_szDumpFileName, szFileName ); 1881 1882 return TRUE; 1883 } 1884 } 1885 1886 return FALSE; 1887 } 1888 1889 BOOL WriteDumpFile( DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers, DWORD dwThreadId ) 1890 { 1891 BOOL fSuccess = FALSE; 1892 PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam = NULL; 1893 MINIDUMP_EXCEPTION_INFORMATION ExceptionParam; 1894 1895 HMODULE hDbgHelp = LoadLibrary( _T("DBGHELP.DLL" ) ); 1896 MiniDumpWriteDump_PROC pMiniDumpWriteDump = NULL; 1897 1898 if ( hDbgHelp ) 1899 { 1900 pMiniDumpWriteDump = (MiniDumpWriteDump_PROC)GetProcAddress( hDbgHelp, "MiniDumpWriteDump" ); 1901 1902 if ( !pMiniDumpWriteDump ) 1903 { 1904 FreeLibrary( hDbgHelp ); 1905 return false; 1906 } 1907 } 1908 1909 if ( !pMiniDumpWriteDump ) 1910 return false; 1911 1912 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId ); 1913 1914 if ( IsValidHandle(hProcess) ) 1915 { 1916 TCHAR szTempPath[MAX_PATH]; 1917 1918 // if ( GetTempPath( elementsof(szTempPath), szTempPath ) ) 1919 if ( GetCrashDataPath( szTempPath ) ) 1920 { 1921 TCHAR szFileName[MAX_PATH]; 1922 1923 // if ( GetTempFileName( szTempPath, TEXT("DMP"), 0, szFileName ) ) 1924 _tcscpy( szFileName, szTempPath ); 1925 _tcscat( szFileName, _T("\\crashdat.dmp") ); 1926 { 1927 HANDLE hFile = CreateFile( 1928 szFileName, 1929 GENERIC_READ | GENERIC_WRITE, 1930 0, NULL, 1931 // OPEN_EXISTING, 1932 CREATE_ALWAYS, 1933 FILE_ATTRIBUTE_NORMAL, NULL ); 1934 1935 if ( hFile ) 1936 { 1937 if ( pExceptionPointers && dwThreadId ) 1938 { 1939 ExceptionParam.ThreadId = dwThreadId; 1940 ExceptionParam.ExceptionPointers = pExceptionPointers; 1941 ExceptionParam.ClientPointers = TRUE; 1942 1943 EXCEPTION_POINTERS aExceptionPointers; 1944 EXCEPTION_RECORD aExceptionRecord; 1945 1946 ReadProcessMemory( 1947 hProcess, 1948 pExceptionPointers, 1949 &aExceptionPointers, 1950 sizeof(aExceptionPointers), 1951 NULL ); 1952 1953 1954 ReadProcessMemory( 1955 hProcess, 1956 aExceptionPointers.ExceptionRecord, 1957 &aExceptionRecord, 1958 sizeof(aExceptionRecord), 1959 NULL ); 1960 1961 g_dwExceptionCode = aExceptionRecord.ExceptionCode; 1962 1963 lpExceptionParam = &ExceptionParam; 1964 } 1965 1966 fSuccess = pMiniDumpWriteDump( hProcess, dwProcessId, hFile, MiniDumpNormal, lpExceptionParam, NULL, NULL ); 1967 1968 CloseHandle( hFile ); 1969 1970 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL ); 1971 _tcscpy( g_szDumpFileName, szFileName ); 1972 } 1973 1974 if ( !fSuccess ) 1975 DeleteFile( szFileName ); 1976 } 1977 } 1978 1979 CloseHandle( hProcess ); 1980 } 1981 1982 FreeLibrary( hDbgHelp ); 1983 1984 return fSuccess; 1985 } 1986 1987 //*************************************************************************** 1988 1989 static DWORD FindProcessForImage( LPCTSTR lpImagePath ) 1990 { 1991 DWORD dwProcessId = 0; 1992 DWORD aProcesses[1024]; 1993 DWORD dwSize = 0; 1994 TCHAR szShortImagePath[MAX_PATH]; 1995 1996 if ( GetShortPathName( lpImagePath, szShortImagePath, elementsof(szShortImagePath) ) && 1997 EnumProcesses( aProcesses, sizeof(aProcesses), &dwSize ) ) 1998 { 1999 unsigned nProcesses = dwSize / sizeof(aProcesses[0]); 2000 2001 for ( unsigned i = 0; !dwProcessId && i < nProcesses; i++ ) 2002 { 2003 HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] ); 2004 2005 if ( IsValidHandle(hProcess) ) 2006 { 2007 TCHAR szModulePath[MAX_PATH+1]; 2008 2009 if ( GetModuleFileNameEx( hProcess, NULL, szModulePath, MAX_PATH ) ) 2010 { 2011 TCHAR szShortModulePath[MAX_PATH]; 2012 2013 if ( GetShortPathName( szModulePath, szShortModulePath, elementsof(szShortModulePath) ) ) 2014 { 2015 if ( 0 == _tcsicmp( szShortModulePath, szShortImagePath ) ) 2016 dwProcessId = aProcesses[i]; 2017 } 2018 } 2019 2020 CloseHandle( hProcess ); 2021 } 2022 } 2023 } 2024 2025 return dwProcessId; 2026 } 2027 //*************************************************************************** 2028 2029 static bool ParseCommandArgs( LPDWORD pdwProcessId, PEXCEPTION_POINTERS* ppException, LPDWORD pdwThreadId ) 2030 { 2031 int argc = __argc; 2032 #ifdef __MINGW32__ 2033 #ifdef _UNICODE 2034 TCHAR **argv = reinterpret_cast<TCHAR **>(alloca((argc+1)*sizeof(WCHAR*))); 2035 int *sizes = reinterpret_cast<int *>(alloca(argc*sizeof(int))); 2036 int argsize=0; 2037 char **ptr; 2038 int i; 2039 ptr=__argv; 2040 for (i = 0; i < argc; ++i) 2041 { 2042 sizes[i]=MultiByteToWideChar(CP_ACP, 0, *ptr, -1, NULL, 0); 2043 argsize+=sizes[i]+1; 2044 ++ptr; 2045 } 2046 ++argsize; 2047 TCHAR *args = reinterpret_cast<TCHAR *>(alloca(argsize*sizeof(WCHAR))); 2048 ptr=__argv; 2049 TCHAR *cptr=args; 2050 for (i = 0; i < argc; ++i) 2051 { 2052 argv[i]=cptr; 2053 MultiByteToWideChar( CP_ACP, 0, *ptr, -1, cptr, sizes[i] ); 2054 ++ptr; 2055 cptr+=sizes[i]; 2056 *cptr=0; 2057 ++cptr; 2058 } 2059 argv[i]=cptr; 2060 *cptr=0; 2061 #else 2062 TCHAR **argv = __argv; 2063 #endif 2064 #else 2065 TCHAR **argv = __targv; 2066 #endif 2067 bool bSuccess = true; 2068 2069 for ( int argn = 1; bSuccess && argn < argc; argn++ ) 2070 { 2071 if ( 0 == _tcsicmp( argv[argn], _T("-h") ) || 2072 0 == _tcsicmp( argv[argn], _T("/h") ) || 2073 0 == _tcsicmp( argv[argn], _T("-?") ) || 2074 0 == _tcsicmp( argv[argn], _T("/?") ) || 2075 0 == _tcsicmp( argv[argn], _T("/help") ) || 2076 0 == _tcsicmp( argv[argn], _T("-help") ) || 2077 0 == _tcsicmp( argv[argn], _T("--help") ) 2078 ) 2079 { 2080 HINSTANCE hInstance = GetModuleHandle(NULL); 2081 TCHAR szUsage[FORMATBUFSIZE]; 2082 TCHAR szProcess[FORMATBUFSIZE]; 2083 TCHAR szProcessDescription[FORMATBUFSIZE]; 2084 TCHAR szHelpDescription[FORMATBUFSIZE]; 2085 2086 LoadAndFormatString( hInstance, IDS_MSG_CMDLINE_USAGE, szUsage, elementsof(szUsage) ); 2087 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID, szProcess, elementsof(szProcess) ); 2088 LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID_DESCRIPTION, szProcessDescription, elementsof(szProcessDescription) ); 2089 LoadAndFormatString( hInstance, IDS_MSG_PARAM_HELP_DESCRIPTION, szHelpDescription, elementsof(szHelpDescription) ); 2090 2091 _tprintf( 2092 TEXT("\n%s: crashrep %s\n\n") 2093 TEXT("/?, -h[elp] %s\n\n") 2094 TEXT("%-20s %s\n\n"), 2095 szUsage, szProcess, szHelpDescription, szProcess, szProcessDescription 2096 ); 2097 2098 return true; 2099 } 2100 else if ( 0 == _tcsicmp( argv[argn], _T("-p") ) || 2101 0 == _tcsicmp( argv[argn], _T("/p") ) ) 2102 { 2103 if ( ++argn < argc ) 2104 *pdwProcessId = _tcstoul( argv[argn], NULL, 0 ); 2105 else 2106 bSuccess = false; 2107 } 2108 else if ( 0 == _tcsicmp( argv[argn], _T("-excp") ) || 2109 0 == _tcsicmp( argv[argn], _T("/excp") ) ) 2110 { 2111 if ( ++argn < argc ) 2112 *ppException = (PEXCEPTION_POINTERS)_tcstoul( argv[argn], NULL, 0 ); 2113 else 2114 bSuccess = false; 2115 } 2116 else if ( 0 == _tcsicmp( argv[argn], _T("-t") ) || 2117 0 == _tcsicmp( argv[argn], _T("/t") ) ) 2118 { 2119 if ( ++argn < argc ) 2120 *pdwThreadId = _tcstoul( argv[argn], NULL, 0 ); 2121 else 2122 bSuccess = false; 2123 } 2124 else if ( 0 == _tcsicmp( argv[argn], _T("-noui") ) || 2125 0 == _tcsicmp( argv[argn], _T("/noui") ) ) 2126 { 2127 g_bNoUserInterface = true; 2128 } 2129 else if ( 0 == _tcsicmp( argv[argn], _T("-send") ) || 2130 0 == _tcsicmp( argv[argn], _T("/send") ) ) 2131 { 2132 g_bSendReport = true; 2133 } 2134 else if ( 0 == _tcsicmp( argv[argn], _T("-load") ) || 2135 0 == _tcsicmp( argv[argn], _T("/load") ) ) 2136 { 2137 g_bLoadReport = true; 2138 } 2139 else // treat parameter as image path 2140 { 2141 TCHAR szImagePath[MAX_PATH]; 2142 LPTSTR lpImageName; 2143 2144 if ( GetFullPathName( argv[argn], MAX_PATH, szImagePath, &lpImageName ) ) 2145 { 2146 DWORD dwProcessId = FindProcessForImage( szImagePath ); 2147 2148 if ( dwProcessId ) 2149 *pdwProcessId = dwProcessId; 2150 else 2151 bSuccess = false; 2152 } 2153 } 2154 } 2155 2156 if ( !*pdwProcessId && !g_bLoadReport ) 2157 { 2158 TCHAR szImagePath[MAX_PATH]; 2159 LPTSTR lpImageName; 2160 2161 if ( GetFullPathName( TEXT("soffice.exe"), MAX_PATH, szImagePath, &lpImageName ) ) 2162 { 2163 DWORD dwProcessId = FindProcessForImage( szImagePath ); 2164 2165 if ( dwProcessId ) 2166 *pdwProcessId = dwProcessId; 2167 else 2168 bSuccess = false; 2169 } 2170 } 2171 2172 return bSuccess; 2173 } 2174 2175 //*************************************************************************** 2176 2177 BOOL WriteCommentFile( LPCTSTR lpComment ) 2178 { 2179 BOOL fSuccess = FALSE; 2180 TCHAR szTempPath[MAX_PATH]; 2181 2182 if ( GetTempPath( elementsof(szTempPath), szTempPath ) ) 2183 { 2184 TCHAR szFileName[MAX_PATH]; 2185 2186 if ( GetTempFileName( szTempPath, TEXT("CMT"), 0, szFileName ) ) 2187 { 2188 HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); 2189 2190 if ( hFile ) 2191 { 2192 DWORD dwBytesWritten; 2193 2194 int needed = WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, NULL, 0, NULL, NULL ); 2195 if ( needed ) 2196 { 2197 char *lpCommentUTF8 = (char *)alloca( needed ); 2198 WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, lpCommentUTF8, needed, NULL, NULL ); 2199 fSuccess = WriteFile( hFile, lpCommentUTF8, strlen(lpCommentUTF8), &dwBytesWritten, NULL ); 2200 } 2201 else 2202 fSuccess = TRUE; 2203 2204 2205 CloseHandle( hFile ); 2206 2207 WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szCommentFileNameA, MAX_PATH, NULL, NULL ); 2208 } 2209 2210 if ( !fSuccess ) 2211 DeleteFile( szFileName ); 2212 } 2213 } 2214 2215 return fSuccess; 2216 } 2217 2218 //*************************************************************************** 2219 2220 static int _tsetenv( const _TCHAR *lpVar, const _TCHAR *lpValue ) 2221 { 2222 if ( !lpValue ) 2223 lpValue = _T(""); 2224 2225 _TCHAR *envstr = (TCHAR *)alloca( (_tcslen( lpVar ) + _tcslen( lpValue ) + 2) * sizeof(_TCHAR) ); 2226 2227 _tcscpy( envstr, lpVar ); 2228 _tcscat( envstr, _T("=") ); 2229 _tcscat( envstr, lpValue ); 2230 2231 return _tputenv( envstr ); 2232 } 2233 2234 static bool read_line( FILE *fp, string& rLine ) 2235 { 2236 char szBuffer[1024]; 2237 bool bSuccess = false; 2238 bool bEOL = false; 2239 string line; 2240 2241 2242 while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) ) 2243 { 2244 int len = strlen(szBuffer); 2245 2246 bSuccess = true; 2247 2248 while ( len && szBuffer[len - 1] == '\n' ) 2249 { 2250 szBuffer[--len] = 0; 2251 bEOL = true; 2252 } 2253 2254 line.append( szBuffer ); 2255 } 2256 2257 rLine = line; 2258 return bSuccess; 2259 } 2260 2261 static string get_script_string( const char *pFileName, const char *pKeyName ) 2262 { 2263 FILE *fp = fopen( pFileName, "rt" ); 2264 string retValue; 2265 2266 if ( fp ) 2267 { 2268 string line; 2269 string section; 2270 2271 while ( read_line( fp, line ) ) 2272 { 2273 line = trim_string( line ); 2274 2275 2276 string::size_type iEqualSign = line.find( '=', 0 ); 2277 2278 if ( iEqualSign != string::npos ) 2279 { 2280 string keyname = line.substr( 0, iEqualSign ); 2281 keyname = trim_string( keyname ); 2282 2283 string value = line.substr( sal::static_int_cast<string::size_type>(iEqualSign + 1) ); 2284 value = trim_string( value ); 2285 2286 if ( value.length() && '\"' == value[0] ) 2287 { 2288 value.erase( 0, 1 ); 2289 2290 string::size_type iQuotes = value.find( '"', 0 ); 2291 2292 if ( iQuotes != string::npos ) 2293 value.erase( iQuotes ); 2294 } 2295 2296 if ( 0 == stricmp( keyname.c_str(), pKeyName ) ) 2297 { 2298 retValue = value; 2299 break; 2300 } 2301 } 2302 } 2303 2304 fclose( fp ); 2305 } 2306 2307 return retValue; 2308 } 2309 2310 static bool ReadBootstrapParams( CrashReportParams &rParams ) 2311 { 2312 TCHAR szBuffer[256] = TEXT(""); 2313 TCHAR szModuleName[MAX_PATH]; 2314 TCHAR szModuleVersionName[MAX_PATH]; 2315 TCHAR szDrive[_MAX_DRIVE]; 2316 TCHAR szDir[_MAX_DIR]; 2317 TCHAR szFName[_MAX_FNAME]; 2318 TCHAR szExt[_MAX_EXT]; 2319 TCHAR szReportServer[MAX_HOSTNAME]; 2320 TCHAR szReportPort[256]; 2321 bool bSuccess = false; 2322 2323 GetModuleFileName( NULL, szModuleName, MAX_PATH ); 2324 _tsplitpath( szModuleName, szDrive, szDir, szFName, szExt ); 2325 _tmakepath( szModuleName, szDrive, szDir, _T("bootstrap"), _T(".ini") ); 2326 _tmakepath( szModuleVersionName, szDrive, szDir, _T("version"), _T(".ini") ); 2327 2328 if ( 2329 GetPrivateProfileString( 2330 TEXT("Bootstrap"), 2331 TEXT("ProductKey"), 2332 TEXT("OpenOffice.org"), 2333 szBuffer, 2334 elementsof(szBuffer), 2335 szModuleName ) 2336 ) 2337 { 2338 TCHAR *pVersion = _tcschr( szBuffer, ' ' ); 2339 2340 g_wstrProductKey = szBuffer; 2341 2342 if ( pVersion ) 2343 { 2344 *pVersion = 0; 2345 pVersion++; 2346 } 2347 else 2348 pVersion = TEXT(""); 2349 2350 if ( !_tgetenv( _T("PRODUCTNAME") ) ) 2351 { 2352 _tsetenv( TEXT("PRODUCTNAME"), szBuffer ); 2353 } 2354 if ( !_tgetenv( _T("PRODUCTVERSION") ) ) 2355 _tsetenv( TEXT("PRODUCTVERSION"), pVersion ); 2356 } 2357 2358 GetPrivateProfileString( 2359 TEXT("Version"), 2360 TEXT("buildid"), 2361 TEXT("unknown"), 2362 g_szBuildId, elementsof(g_szBuildId), 2363 szModuleVersionName ); 2364 2365 g_strDefaultLanguage = get_script_string( "instdb.inf", "DefaultLanguage" ); 2366 2367 if ( GetPrivateProfileString( 2368 TEXT("ErrorReport"), 2369 TEXT("ErrorReportPort"), 2370 TEXT("80"), 2371 szReportPort, elementsof(szReportPort), 2372 szModuleName 2373 ) ) 2374 { 2375 TCHAR *endptr = NULL; 2376 2377 unsigned short uReportPort = (unsigned short)_tcstoul( szReportPort, &endptr, 10 ); 2378 if ( uReportPort ) 2379 g_uReportPort = uReportPort; 2380 } 2381 2382 if ( GetPrivateProfileString( 2383 TEXT("ErrorReport"), 2384 TEXT("ErrorReportServer"), 2385 TEXT(""), 2386 szReportServer, elementsof(szReportServer), 2387 szModuleName 2388 ) ) 2389 { 2390 bSuccess = 0 != WideCharToMultiByte( CP_ACP, 0, szReportServer, -1, g_szReportServerA, elementsof(g_szReportServerA), NULL, NULL ); 2391 } 2392 2393 LPCTSTR lpEnvString; 2394 2395 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYSERVER") )) ) 2396 rParams.sProxyServer = lpEnvString; 2397 2398 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_PROXYPORT") )) ) 2399 rParams.sProxyPort = lpEnvString; 2400 2401 if ( 0 != (lpEnvString = _tgetenv( _T("ERRORREPORT_SENDERADDRESS") )) ) 2402 rParams.sEmail = lpEnvString; 2403 2404 return bSuccess; 2405 } 2406 2407 //*************************************************************************** 2408 2409 bool SendHTTPRequest( 2410 FILE *fp, 2411 const char *pszServer, 2412 unsigned short uPort = 80, 2413 const char *pszProxyServer = NULL, 2414 unsigned short uProxyPort = 8080 ) 2415 { 2416 bool success = false; 2417 2418 struct hostent *hp; 2419 2420 if ( pszProxyServer ) 2421 hp = gethostbyname( pszProxyServer ); 2422 else 2423 hp = gethostbyname( pszServer ); 2424 2425 if ( hp ) 2426 { 2427 SOCKET s = socket( AF_INET, SOCK_STREAM, 0 ); 2428 2429 if ( s ) 2430 { 2431 struct sockaddr_in address; 2432 2433 memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr)); 2434 address.sin_family = AF_INET; 2435 2436 if ( pszProxyServer ) 2437 address.sin_port = ntohs( uProxyPort ); 2438 else 2439 address.sin_port = ntohs( uPort ); 2440 2441 if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) ) 2442 { 2443 fseek( fp, 0, SEEK_END ); 2444 size_t length = ftell( fp ); 2445 fseek( fp, 0, SEEK_SET ); 2446 2447 char buffer[2048]; 2448 2449 if ( pszProxyServer ) 2450 sprintf( buffer, 2451 "POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n" 2452 "Content-Type: text/xml; charset=\"utf-8\"\r\n" 2453 "Content-Length: %d\r\n" 2454 "SOAPAction: \"\"\r\n\r\n", 2455 pszServer, 2456 uPort, 2457 length 2458 ); 2459 else 2460 sprintf( buffer, 2461 "POST /soap/servlet/rpcrouter HTTP/1.0\r\n" 2462 "Content-Type: text/xml; charset=\"utf-8\"\r\n" 2463 "Content-Length: %d\r\n" 2464 "SOAPAction: \"\"\r\n\r\n", 2465 length 2466 ); 2467 2468 if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) ) 2469 { 2470 size_t nBytes; 2471 2472 do 2473 { 2474 nBytes = fread( buffer, 1, sizeof(buffer), fp ); 2475 2476 if ( nBytes ) 2477 success = SOCKET_ERROR != send( s, buffer, nBytes, 0 ); 2478 } while( nBytes && success ); 2479 2480 if ( success ) 2481 { 2482 memset( buffer, 0, sizeof(buffer) ); 2483 success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 ); 2484 if ( success ) 2485 { 2486 char szHTTPSignature[sizeof(buffer)] = ""; 2487 unsigned uHTTPReturnCode = 0; 2488 2489 sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode ); 2490 success = uHTTPReturnCode == 200; 2491 } 2492 } 2493 } 2494 2495 } 2496 2497 closesocket( s ); 2498 } 2499 } 2500 2501 return success; 2502 } 2503 2504 //*************************************************************************** 2505 2506 static void WriteSOAPRequest( FILE *fp ) 2507 { 2508 fprintf( fp, 2509 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" 2510 "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" 2511 "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n" 2512 "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n" 2513 "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n" 2514 "xmlns:rds=\"urn:ReportDataService\"\n" 2515 "xmlns:apache=\"http://xml.apache.org/xml-soap\"\n" 2516 "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" 2517 "<SOAP-ENV:Body>\n" 2518 ); 2519 2520 fprintf( fp, "<rds:submitReport>\n" ); 2521 fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" ); 2522 fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" ); 2523 2524 FILE *fpin = fopen( g_szReportFileNameA, "r" ); 2525 if ( fpin ) 2526 { 2527 fprintf( fp, 2528 "<item>\n" 2529 "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n" 2530 "<value xsi:type=\"xsd:string\"><![CDATA[" ); 2531 fcopy( fpin, fp ); 2532 fprintf( fp, "]]></value></item>\n" ); 2533 fclose( fpin ); 2534 } 2535 2536 fpin = fopen( g_szCommentFileNameA, "r" ); 2537 if ( fpin ) 2538 { 2539 fprintf( fp, 2540 "<item>\n" 2541 "<key xsi:type=\"xsd:string\">description.txt</key>\n" 2542 "<value xsi:type=\"xsd:string\"><![CDATA[" ); 2543 fcopy( fpin, fp ); 2544 fprintf( fp, "]]></value></item>\n" ); 2545 fclose( fpin ); 2546 }; 2547 2548 2549 fpin = fopen( g_szDumpFileNameA, "rb" ); 2550 if ( fpin ) 2551 { 2552 FILE *fptemp = _tmpfile(); 2553 2554 if ( fptemp ) 2555 { 2556 if ( base64_encode( fpin, fptemp ) ) 2557 { 2558 fseek( fptemp, 0, SEEK_SET ); 2559 fprintf( fp, 2560 "<item>\n" 2561 "<key xsi:type=\"xsd:string\">user.dmp</key>\n" 2562 "<value xsi:type=\"xsd:string\">" ); 2563 fcopy( fptemp, fp ); 2564 fprintf( fp, "</value></item>\n" ); 2565 } 2566 fclose( fptemp ); 2567 } 2568 fclose( fpin ); 2569 } 2570 2571 fprintf( fp, 2572 "</hash>\n" 2573 "</rds:submitReport>\n" 2574 "</SOAP-ENV:Body>\n" 2575 "</SOAP-ENV:Envelope>\n" 2576 ); 2577 } 2578 2579 //*************************************************************************** 2580 2581 struct RequestParams 2582 { 2583 bool success; 2584 FILE *fpin; 2585 const char *lpServer; 2586 unsigned short uPort; 2587 const char *lpProxyServer; 2588 unsigned short uProxyPort; 2589 HWND hwndStatus; 2590 }; 2591 2592 void _cdecl SendingThread( void *lpArgs ) 2593 { 2594 RequestParams *pParams = (RequestParams *)lpArgs; 2595 2596 pParams->success = SendHTTPRequest( pParams->fpin, pParams->lpServer, pParams->uPort, pParams->lpProxyServer, pParams->uProxyPort ); 2597 2598 PostMessage( pParams->hwndStatus, WM_COMMAND, IDOK, 0 ); 2599 } 2600 2601 //*************************************************************************** 2602 2603 BOOL CALLBACK SendingStatusDialogProc( 2604 HWND hwndDlg, 2605 UINT uMsg, 2606 WPARAM wParam, 2607 LPARAM lParam 2608 ) 2609 { 2610 static RequestParams *pRequest = NULL; 2611 static HANDLE hSendingThread = NULL; 2612 2613 switch ( uMsg ) 2614 { 2615 case WM_INITDIALOG: 2616 { 2617 TCHAR szBuffer[1024] = TEXT(""); 2618 HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE ); 2619 //HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT ); 2620 2621 pRequest = (RequestParams *)lParam; 2622 2623 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_HEADER, szBuffer, elementsof(szBuffer) ); 2624 SetWindowText( hwndDlg, szBuffer ); 2625 2626 LoadAndFormatString( hInstance, IDS_SENDING_REPORT_STATUS, szBuffer, elementsof(szBuffer) ); 2627 Static_SetText( GetDlgItem(hwndDlg, IDC_SENDING_REPORT_STATUS), szBuffer ); 2628 2629 LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) ); 2630 Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer ); 2631 2632 pRequest->hwndStatus = hwndDlg; 2633 2634 hSendingThread = (HANDLE)_beginthread( SendingThread, 0, pRequest ); 2635 } 2636 return TRUE; 2637 case WM_COMMAND: 2638 switch ( LOWORD(wParam) ) 2639 { 2640 case IDCANCEL: 2641 TerminateThread( hSendingThread, 0 ); 2642 case IDOK: 2643 WaitForSingleObject( hSendingThread, INFINITE ); 2644 CloseHandle( hSendingThread ); 2645 EndDialog( hwndDlg, wParam ); 2646 return TRUE; 2647 } 2648 break; 2649 default: 2650 break; 2651 } 2652 2653 return FALSE; 2654 } 2655 2656 //*************************************************************************** 2657 2658 bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams ) 2659 { 2660 bool success = false; 2661 char szProxyServer[1024] = ""; 2662 unsigned short uProxyPort = 8080; 2663 TCHAR *endptr = NULL; 2664 2665 switch ( rParams.uInternetConnection ) 2666 { 2667 case 2: 2668 { 2669 WideCharToMultiByte( 2670 CP_ACP, 0, rParams.sProxyServer.c_str(), -1, 2671 szProxyServer, sizeof(szProxyServer), NULL, NULL ); 2672 uProxyPort = (unsigned short)_tcstoul( rParams.sProxyPort.c_str(), &endptr, 10 ); 2673 } 2674 break; 2675 case 0: 2676 { 2677 DWORD dwProxyEnable = 0; 2678 2679 RegReadValue( HKEY_CURRENT_USER, 2680 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), 2681 TEXT("ProxyEnable"), 2682 &dwProxyEnable, 2683 sizeof(dwProxyEnable) ); 2684 2685 if ( dwProxyEnable ) 2686 { 2687 TCHAR tszProxyServers[1024] = TEXT(""); 2688 2689 if ( ERROR_SUCCESS == RegReadValue( HKEY_CURRENT_USER, 2690 TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), TEXT("ProxyServer"), 2691 tszProxyServers, 2692 sizeof(tszProxyServers) ) ) 2693 { 2694 TCHAR *lpHttpStart = _tcsstr( tszProxyServers, TEXT("http=") ); 2695 2696 if ( lpHttpStart ) 2697 lpHttpStart += 5; 2698 else 2699 lpHttpStart = tszProxyServers; 2700 2701 TCHAR *lpHttpEnd = _tcschr( lpHttpStart, ';' ); 2702 2703 if ( lpHttpEnd ) 2704 *lpHttpEnd = 0; 2705 2706 char szHTTPProxyServer[1024] = ""; 2707 WideCharToMultiByte( CP_ACP, 0, lpHttpStart, -1, szHTTPProxyServer, sizeof(szHTTPProxyServer), NULL, NULL ); 2708 2709 char *lpColon = strchr( szHTTPProxyServer, ':' ); 2710 2711 if ( lpColon ) 2712 { 2713 char *endptr = NULL; 2714 2715 *lpColon = 0; 2716 uProxyPort = (unsigned short)strtoul( lpColon + 1, &endptr, 10 ); 2717 } 2718 else 2719 uProxyPort = 8080; 2720 2721 strcpy( szProxyServer, szHTTPProxyServer ); 2722 2723 } 2724 } 2725 } 2726 break; 2727 default: 2728 case 1: 2729 break; 2730 } 2731 2732 FILE *fptemp = _tmpfile(); 2733 if ( fptemp ) 2734 { 2735 RequestParams request; 2736 2737 request.success = false; 2738 request.fpin = fptemp; 2739 request.lpServer = REPORT_SERVER; 2740 request.uPort = REPORT_PORT; 2741 request.lpProxyServer = szProxyServer[0] ? szProxyServer : NULL; 2742 request.uProxyPort = uProxyPort; 2743 request.hwndStatus = NULL; 2744 2745 WriteSOAPRequest( fptemp ); 2746 fseek( fptemp, 0, SEEK_SET ); 2747 2748 if ( hwndParent ) 2749 { 2750 int retid = DialogBoxParam( 2751 GetModuleHandle(NULL), 2752 MAKEINTRESOURCE(IDD_SENDING_STATUS), 2753 hwndParent, 2754 SendingStatusDialogProc, 2755 (LPARAM)&request 2756 ); 2757 2758 success = request.success; 2759 2760 if ( IDOK == retid ) 2761 { 2762 if ( !success ) 2763 { 2764 TCHAR szMessage[1024]; 2765 2766 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) ); 2767 2768 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK ); 2769 } 2770 else 2771 { 2772 TCHAR szMessage[1024]; 2773 TCHAR szTitle[1024]; 2774 2775 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) ); 2776 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_HEADER, szTitle, elementsof(szTitle) ); 2777 2778 MessageBox( hwndParent, szMessage, szTitle, MB_ICONINFORMATION | MB_OK ); 2779 } 2780 } 2781 2782 } 2783 else 2784 { 2785 HANDLE hSendingThread = (HANDLE)_beginthread( SendingThread, 0, (void *)&request ); 2786 2787 WaitForSingleObject( hSendingThread, INFINITE ); 2788 2789 success = request.success; 2790 if ( !success ) 2791 { 2792 TCHAR szMessage[1024]; 2793 2794 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) ); 2795 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage ); 2796 } 2797 else 2798 { 2799 TCHAR szMessage[1024]; 2800 2801 LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) ); 2802 2803 _ftprintf( stderr, _T("SUCCESS: %s\n"), szMessage ); 2804 } 2805 } 2806 fclose( fptemp ); 2807 } 2808 else 2809 { 2810 TCHAR szMessage[1024]; 2811 2812 LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_DISK_FULL, szMessage, elementsof(szMessage) ); 2813 2814 if ( hwndParent ) 2815 MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK ); 2816 else 2817 _ftprintf( stderr, _T("ERROR: %s\n"), szMessage ); 2818 } 2819 2820 return success; 2821 } 2822 2823 //*************************************************************************** 2824 2825 #ifdef __MINGW32__ 2826 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR /*lpCmdLine*/, int ) 2827 #else 2828 int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR /*lpCmdLine*/, int ) 2829 #endif 2830 { 2831 int exitcode = -1; 2832 int argc = __argc; 2833 2834 #ifdef __MINGW32__ 2835 char **argv = __argv; 2836 #else 2837 #ifdef _UNICODE 2838 char **argv = new char *[argc + 1]; 2839 2840 for ( int argn = 0; argn < argc; argn++ ) 2841 { 2842 int nBytes = WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, NULL, 0, NULL, NULL ); 2843 argv[argn] = new char[nBytes]; 2844 WideCharToMultiByte( CP_ACP, 0, __targv[argn], -1, argv[argn], nBytes, NULL, NULL ); 2845 } 2846 argv[argc] = NULL; 2847 #else 2848 char **argv = __targv; 2849 #endif 2850 #endif 2851 2852 osl_setCommandArgs( argc, argv ); 2853 2854 PEXCEPTION_POINTERS pExceptionPointers = NULL; 2855 DWORD dwProcessId = 0; 2856 DWORD dwThreadId = 0; 2857 2858 WSADATA wsaData; 2859 WORD wVersionRequested; 2860 2861 wVersionRequested = MAKEWORD(1, 1); 2862 WSAStartup(wVersionRequested, &wsaData); 2863 2864 CrashReportParams Params; 2865 2866 Params.ReadFromRegistry(); 2867 Params.ReadFromEnvironment(); 2868 2869 if ( ReadBootstrapParams( Params ) && 2870 ParseCommandArgs( &dwProcessId, &pExceptionPointers, &dwThreadId ) ) 2871 { 2872 bool bGotDumpFile; 2873 2874 if ( g_bLoadReport ) 2875 bGotDumpFile = FindDumpFile(); 2876 else 2877 bGotDumpFile = WriteDumpFile( dwProcessId, pExceptionPointers, dwThreadId ); 2878 2879 if( bGotDumpFile ) 2880 { 2881 hash_map< string, string > aLibraries; 2882 2883 if ( g_bLoadReport ) 2884 { 2885 g_fpStackFile = _open_reportfile( _T(".stk"), _T("rb") ); 2886 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("rb") ); 2887 } 2888 else 2889 { 2890 if ( g_bSendReport ) 2891 { 2892 g_fpStackFile = _tmpfile(); 2893 g_fpChecksumFile = _tmpfile(); 2894 } 2895 else 2896 { 2897 g_fpStackFile = _open_reportfile( _T(".stk"), _T("w+b") ); 2898 g_fpChecksumFile = _open_reportfile( _T(".chk"), _T("w+b") ); 2899 2900 FILE *fpUnsent = _open_reportfile( _T(".lck"), _T("w+b") ); 2901 if ( fpUnsent ) 2902 { 2903 fprintf( fpUnsent, "Unsent\r\n" ); 2904 fclose( fpUnsent ); 2905 } 2906 } 2907 2908 WriteStackFile( g_fpStackFile, aLibraries, dwProcessId, pExceptionPointers ); 2909 WriteChecksumFile( g_fpChecksumFile, aLibraries ); 2910 WriteReportFile( &Params ); 2911 2912 FILE *fpPreview = _open_reportfile( _T(".prv"), _T("w+b") ); 2913 2914 if ( fpPreview ) 2915 { 2916 FILE *fp = fopen( g_szReportFileNameA, "rb" ); 2917 if ( fp ) 2918 { 2919 fcopy( fp, fpPreview ); 2920 fclose( fp ); 2921 } 2922 fclose( fpPreview ); 2923 } 2924 } 2925 2926 if ( g_bSendReport ) 2927 { 2928 InitCommonControls(); 2929 2930 // Actually this should never be true anymore 2931 if ( !g_bNoUserInterface && InitRichEdit() ) 2932 { 2933 2934 INT_PTR result = DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_DIALOG_FRAME), NULL, DialogProc, (LPARAM)&Params ); 2935 2936 if ( result > 0 ) 2937 { 2938 exitcode = 0; 2939 } 2940 DeinitRichEdit(); 2941 } 2942 else 2943 { 2944 WriteCommentFile( Params.sComment.c_str() ); 2945 WriteReportFile( &Params ); 2946 if ( SendCrashReport( NULL, Params ) ) 2947 exitcode = 0; 2948 } 2949 2950 2951 if ( g_szReportFileNameA[0] ) 2952 DeleteFileA( g_szReportFileNameA ); 2953 2954 if ( g_szCommentFileNameA[0] ) 2955 DeleteFileA( g_szCommentFileNameA ); 2956 } 2957 else 2958 { 2959 if ( g_szReportFileNameA[0] ) 2960 DeleteFileA( g_szReportFileNameA ); 2961 exitcode = 0; 2962 } 2963 2964 if ( g_szDumpFileNameA[0] && g_bSendReport ) 2965 DeleteFileA( g_szDumpFileNameA ); 2966 2967 if ( g_fpStackFile ) 2968 fclose( g_fpStackFile ); 2969 2970 if ( g_fpChecksumFile ) 2971 fclose( g_fpChecksumFile ); 2972 } 2973 } 2974 2975 2976 return exitcode; 2977 } 2978 2979