office-gobmx/crashrep/source/win32/soreport.cpp
Rüdiger Timm 6ca5bf11b9 INTEGRATION: CWS geordi2q12 (1.8.2); FILE MERGED
2004/01/07 15:07:36 hr 1.8.2.1: #111934#: merge CWS crashrep7pp2 -> SRC680
2004-01-07 15:18:35 +00:00

2562 lines
80 KiB
C++
Executable file

/*************************************************************************
*
* $RCSfile: soreport.cpp,v $
*
* $Revision: 1.9 $
*
* last change: $Author: rt $ $Date: 2004-01-07 16:18:35 $
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc., October, 2000
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2000 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* =================================================
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 (the "License"); You may not use this file
* except in compliance with the License. You may obtain a copy of the
* License at http://www.openoffice.org/license.html.
*
* Software provided under this License is provided on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
* See the License for the specific provisions governing your rights and
* obligations concerning the Software.
*
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
* Copyright: 2000 by Sun Microsystems, Inc.
*
* All Rights Reserved.
*
* Contributor(s): _______________________________________
*
*
************************************************************************/
#define UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <windowsx.h>
#include <mapi.h>
#include <commctrl.h>
#include <commdlg.h>
#include <psapi.h>
#include <shellapi.h>
#define _UNICODE
#include <tchar.h>
#define _RICHEDIT_VER 0x0200
#include <richedit.h>
#if _RICHEDIT_VER >= 0x0200
#define RICHEDIT TEXT("riched20.dll")
#else
#define RICHEDIT TEXT("riched32.dll")
#endif
#include <systools/win32/uwinapi.h>
#include <rtl/digest.h>
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <string>
#include <hash_map>
#include <winsock.h>
#include <malloc.h>
#include <process.h>
#if _MSC_VER < 1300
#define COMEX "9"
#else
#define COMEX "8"
#endif
#ifdef PRODUCT
#define _INPATH "wntmsci" COMEX ".pro"
#else
#define _INPATH "wntmsci" COMEX
#endif
#include "resource.h"
#include "base64.h"
#define FORMATBUFSIZE (8*1024)
#define MAX_TEXT_BUFFER (32*1024-1)
#define MAX_HOSTNAME (1024)
#include <dbghelp.h>
using namespace ::std;
wstring g_wstrProductKey;
string g_strDefaultLanguage;
FILE *g_fpStackFile = NULL;
FILE *g_fpChecksumFile = NULL;
DWORD g_dwExceptionCode = 0;
CHAR g_szReportServerA[MAX_HOSTNAME] = "";
USHORT g_uReportPort = 80;
TCHAR g_szBuildId[256] = TEXT("");
TCHAR g_szDumpFileName[MAX_PATH] = TEXT("");
CHAR g_szDumpFileNameA[MAX_PATH] = "";
CHAR g_szCommentFileNameA[MAX_PATH] = "";
CHAR g_szReportFileNameA[MAX_PATH] = "";
#define REPORT_SERVER g_szReportServerA
#define REPORT_PORT g_uReportPort
//***************************************************************************
// tmpfile from msvcrt creates the temporary file in the root of the current
// volume and can fail.
static FILE *_tmpfile(void)
{
FILE *fp = NULL;
TCHAR szTempPath[MAX_PATH];
if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
{
TCHAR szFileName[MAX_PATH];
if ( GetTempFileName( szTempPath, TEXT("CRT"), 0, szFileName ) )
{
HANDLE hFile = CreateFile(
szFileName,
GENERIC_READ | GENERIC_WRITE,
0, NULL,
OPEN_EXISTING,
FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_NORMAL,
NULL );
if ( IsValidHandle( hFile ) )
{
int fd = _open_osfhandle( (int)hFile, 0 );
fp = _fdopen( fd, "w+b" );
}
}
}
return fp;
}
//***************************************************************************
struct CrashReportParams
{
BOOL fAllowContact;
TCHAR szEmail[1024];
TCHAR szTitle[1024];
TCHAR szComment[2048];
ULONG uInternetConnection;
TCHAR szProxyServer[1024];
TCHAR szProxyPort[50];
CrashReportParams();
void WriteToRegistry();
void ReadFromRegistry();
};
bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams );
BOOL WriteCommentFile( LPCTSTR lpComment );
//***************************************************************************
LONG RegReadValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPVOID lpData, DWORD cbData )
{
HKEY hKey = NULL;
LONG lResult;
lResult = RegOpenKeyEx( hBaseKey, lpSubKey, 0, KEY_QUERY_VALUE, &hKey );
if ( ERROR_SUCCESS == lResult )
{
lResult = RegQueryValueEx( hKey, lpValueName, NULL, NULL, (LPBYTE)lpData, &cbData );
RegCloseKey( hKey );
}
return lResult;
}
//***************************************************************************
LONG RegWriteValue( HKEY hBaseKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData )
{
HKEY hKey = NULL;
LONG lResult;
lResult = RegCreateKeyEx( hBaseKey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL );
if ( ERROR_SUCCESS == lResult )
{
lResult = RegSetValueEx( hKey, lpValueName, NULL, dwType, (CONST BYTE *)lpData, cbData );
RegCloseKey( hKey );
}
return lResult;
}
//***************************************************************************
CrashReportParams::CrashReportParams()
{
fAllowContact = FALSE;
_tcscpy( szTitle, TEXT("") );
_tcscpy( szComment, TEXT("") );
_tcscpy( szEmail, TEXT("") );
uInternetConnection = 0;
_tcscpy( szProxyServer, TEXT("") );
_tcscpy( szProxyPort, TEXT("") );
}
//***************************************************************************
void CrashReportParams::ReadFromRegistry()
{
RegReadValue(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
TEXT("HTTPProxyServer"),
szProxyServer,
sizeof(szProxyServer) );
DWORD dwProxyPort;
if ( ERROR_SUCCESS == RegReadValue(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
TEXT("HTTPProxyPort"),
&dwProxyPort,
sizeof(dwProxyPort) ) )
_stprintf( szProxyPort, TEXT("%d"), dwProxyPort );
RegReadValue(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
TEXT("ReturnAddress"),
szEmail,
sizeof(szEmail) );
RegReadValue(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
TEXT("AllowContact"),
&fAllowContact,
sizeof(fAllowContact) );
RegReadValue(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
TEXT("HTTPConnection"),
&uInternetConnection,
sizeof(uInternetConnection) );
}
//***************************************************************************
void CrashReportParams::WriteToRegistry()
{
RegWriteValue(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
TEXT("HTTPProxyServer"), REG_SZ,
szProxyServer,
sizeof(TCHAR) * (_tcslen( szProxyServer ) + 1) );
LPTSTR endptr = NULL;
DWORD dwProxyPort = _tcstoul( szProxyPort, &endptr, 10 );
RegWriteValue(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
TEXT("HTTPProxyPort"), REG_DWORD,
&dwProxyPort,
sizeof(DWORD) );
RegWriteValue(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
TEXT("AllowContact"), REG_DWORD,
&fAllowContact,
sizeof(DWORD) );
RegWriteValue(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
TEXT("HTTPConnection"), REG_DWORD,
&uInternetConnection,
sizeof(DWORD) );
RegWriteValue(
HKEY_CURRENT_USER,
TEXT("SOFTWARE\\OpenOffice.org\\CrashReport"),
TEXT("ReturnAddress"), REG_SZ,
szEmail,
sizeof(TCHAR) * (_tcslen( szEmail ) + 1) );
}
//***************************************************************************
typedef BOOL (WINAPI *MiniDumpWriteDump_PROC)(
IN HANDLE hProcess,
IN DWORD ProcessId,
IN HANDLE hFile,
IN MINIDUMP_TYPE DumpType,
IN CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, OPTIONAL
IN CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, OPTIONAL
IN CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam OPTIONAL
);
//***************************************************************************
static BOOL WINAPI InitRichEdit()
{
return (NULL != LoadLibrary( RICHEDIT ));
}
//***************************************************************************
static BOOL WINAPI DeinitRichEdit()
{
return FreeLibrary( GetModuleHandle( RICHEDIT ) );
}
//***************************************************************************
static string trim_string( const string& rString )
{
string temp = rString;
while ( temp.length() && temp[0] == ' ' || temp[0] == '\t' )
temp.erase( 0, 1 );
string::size_type len = temp.length();
while ( len && temp[len-1] == ' ' || temp[len-1] == '\t' )
{
temp.erase( len - 1, 1 );
len = temp.length();
}
return temp;
}
//***************************************************************************
static int LoadAndFormatString( HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax )
{
TCHAR szBuffer[FORMATBUFSIZE];
TCHAR szBuffer2[FORMATBUFSIZE];
LoadString( hInstance, uID, szBuffer, elementsof(szBuffer) );
LPCTSTR src;
LPTSTR dest;
for ( dest = szBuffer2, src = szBuffer; *src; src++, dest++ )
{
switch ( *src )
{
case '~':
*dest = '&';
break;
case '\\':
switch ( *(++src) )
{
case 'n':
*dest = '\n';
break;
case 'r':
*dest = '\r';
break;
default:
*dest = *src;
break;
}
break;
default:
*dest = *src;
break;
}
}
*dest = *src;
return ExpandEnvironmentStrings( szBuffer2, lpBuffer, nBufferMax );
}
//***************************************************************************
static string wstring2utf8( const wstring &rString )
{
int nBufSize = WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, NULL, 0, NULL, FALSE );
LPSTR pBuffer = (LPSTR)alloca( nBufSize );
WideCharToMultiByte( CP_UTF8, 0, rString.c_str(), -1, pBuffer, nBufSize, NULL, FALSE );
return string( pBuffer );
}
//***************************************************************************
static string xml_encode( const string &rString )
{
string temp = rString;
string::size_type pos = 0;
// First replace all occurences of '&' because it may occur in further
// encoded chardters too
for( pos = 0; (pos = temp.find( '&', pos )) != string::npos; pos += 4 )
temp.replace( pos, 1, "&amp;" );
for( pos = 0; (pos = temp.find( '<', pos )) != string::npos; pos += 4 )
temp.replace( pos, 1, "&lt;" );
for( pos = 0; (pos = temp.find( '>', pos )) != string::npos; pos += 4 )
temp.replace( pos, 1, "&gt;" );
return temp;
}
//***************************************************************************
static size_t fcopy( FILE *fpin, FILE *fpout )
{
char buffer[1024];
size_t nBytes;
size_t nBytesWritten = 0;
if ( fpin && fpout )
{
while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) )
{
nBytesWritten += fwrite( buffer, 1, nBytes, fpout );
}
}
return nBytesWritten;
}
//***************************************************************************
static string GetModuleDirectory( HMODULE hModule )
{
TCHAR szBuffer[256] = TEXT("");
TCHAR szModuleName[MAX_PATH] = TEXT("");
TCHAR szDrive[_MAX_DRIVE];
TCHAR szDir[_MAX_DIR];
TCHAR szFName[_MAX_FNAME];
TCHAR szExt[_MAX_EXT];
if ( GetModuleFileName( hModule, szModuleName, MAX_PATH ) )
{
_tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
_tmakepath( szModuleName, szDrive, szDir, _T(""), _T("") );
}
CHAR szModuleNameUTF8[MAX_PATH] = "";
WideCharToMultiByte( CP_UTF8, 0, szModuleName, -1, szModuleNameUTF8, elementsof(szModuleNameUTF8), NULL, NULL );
return string( szModuleNameUTF8 );
}
//***************************************************************************
string GetFileDirectory( const string& rFilePath )
{
string aDir = rFilePath;
size_t pos = aDir.rfind( '\\' );
if ( string::npos != pos )
aDir.erase( pos + 1 );
else
aDir = "";
return aDir;
}
//***************************************************************************
string GetFileName( const string& rFilePath )
{
string aName = rFilePath;
size_t pos = aName.rfind( '\\' );
if ( string::npos != pos )
return aName.substr( pos + 1 );
else
return aName;
}
//***************************************************************************
BOOL WriteReportFile( CrashReportParams *pParams )
{
BOOL fSuccess = FALSE;
TCHAR szTempPath[MAX_PATH];
if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
{
TCHAR szFileName[MAX_PATH];
if ( GetTempFileName( szTempPath, TEXT("RPM"), 0, szFileName ) )
{
HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile )
{
int fd = _open_osfhandle( (LONG)hFile, _O_TEXT );
FILE *fp = _fdopen( fd, "w+t" );
CHAR szTitle[1024] = "";
CHAR szBuildId[1024] = "";
CHAR szEmail[1024] = "";
const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
WideCharToMultiByte( CP_UTF8, 0, pParams->szTitle, -1, szTitle, sizeof(szTitle), NULL, NULL );
WideCharToMultiByte( CP_UTF8, 0, g_szBuildId, -1, szBuildId, sizeof(szBuildId), NULL, NULL );
WideCharToMultiByte( CP_UTF8, 0, pParams->szEmail, -1, szEmail, sizeof(szEmail), NULL, NULL );
fprintf( fp,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE errormail:errormail PUBLIC \"-//OpenOffice.org//DTD ErrorMail 1.0//EN\" \"errormail.dtd\">\n"
"<errormail:errormail xmlns:errormail=\"http://openoffice.org/2002/errormail\" usertype=\"%s\">\n"
"<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.1\" feedback=\"%s\" email=\"%s\">\n",
pszUserType ? pszUserType : "",
pParams->fAllowContact ? "true" : "false",
pParams->fAllowContact ? xml_encode(szEmail).c_str() : ""
);
fprintf( fp,
"<reportmail:title>%s</reportmail:title>\n",
xml_encode(szTitle).c_str() );
fprintf( fp,
"<reportmail:attachment name=\"description.txt\" media-type=\"text/plain;charset=UTF-8\" class=\"UserComment\"/>\n"
"<reportmail:attachment name=\"user.dmp\" media-type=\"application/octet-stream\" class=\"UserDump\"/>\n"
"</reportmail:mail>\n"
"<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" procpath=\"%s\" exceptiontype=\"0x%08X\" product=\"%s\"/>\n",
szBuildId,
_INPATH,
xml_encode(g_strDefaultLanguage).c_str(),
xml_encode(GetModuleDirectory( NULL )).c_str(),
g_dwExceptionCode,
xml_encode(wstring2utf8(g_wstrProductKey)).c_str()
);
OSVERSIONINFO VersionInfo;
ZeroMemory( &VersionInfo, sizeof(VersionInfo) );
VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo );
GetVersionEx( &VersionInfo );
fprintf( fp,
"<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
"<systeminfo:System name=\"%s\" version=\"%d.%d\" build=\"%d\" locale=\"0x%08x\"/>\n"
,
VER_PLATFORM_WIN32_NT == VersionInfo.dwPlatformId ? "Windows NT" : "Windows",
VersionInfo.dwMajorVersion, VersionInfo.dwMinorVersion,
VersionInfo.dwBuildNumber,
GetUserDefaultLangID()
);
fprintf( fp, "<systeminfo:CPU type=\"x86\"/>\n" );
fprintf( fp, "</systeminfo:systeminfo>\n" );
fseek( g_fpStackFile, 0, SEEK_SET );
fcopy( g_fpStackFile, fp );
fseek( g_fpChecksumFile, 0, SEEK_SET );
fcopy( g_fpChecksumFile, fp );
fprintf( fp, "</errormail:errormail>\n" );
fclose( fp );
fSuccess = TRUE;
WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szReportFileNameA, MAX_PATH, NULL, NULL );
}
if ( !fSuccess )
DeleteFile( szFileName );
}
}
return fSuccess;
}
//***************************************************************************
static BOOL SaveDumpFile( HWND hwndOwner )
{
OPENFILENAME ofn;
TCHAR szFileName[MAX_PATH] = TEXT("");
ZeroMemory( &ofn, sizeof(ofn) );
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwndOwner;
ofn.lpstrFilter = TEXT("*.dmp\0*.dmp\0*.*\0*.*\0");
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_ENABLESIZING | OFN_LONGNAMES | OFN_OVERWRITEPROMPT;
ofn.lpstrDefExt = TEXT("dmp");
if ( GetSaveFileName( &ofn ) )
{
return CopyFile( g_szDumpFileName, szFileName, FALSE );
}
return FALSE;
}
//***************************************************************************
static BOOL ScreenToClientRect( HWND hwnd, LPRECT lprc )
{
return ScreenToClient( hwnd, (LPPOINT)&lprc->left ) && ScreenToClient( hwnd, (LPPOINT)&lprc->right );
}
static BOOL SetWindowRect( HWND hwnd, const RECT *lprc, BOOL fRepaint )
{
return MoveWindow( hwnd, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top, fRepaint );
}
#define GM_LOX 0x01
#define GM_HIX 0x02
#define GM_LOY 0x04
#define GM_HIY 0x08
static BOOL SetGrowMode( HWND hwnd, DWORD dwGrowMode )
{
return SetProp( hwnd, TEXT("GrowMode"), (HANDLE)dwGrowMode );
}
static DWORD GetGrowMode( HWND hwnd )
{
return (DWORD)GetProp( hwnd, TEXT("GrowMode") );
}
static BOOL GrowWindow( HWND hwnd, LONG dxClient, LONG dyClient, BOOL fRepaint )
{
DWORD dwGrowMode = GetGrowMode( hwnd );
RECT rc;
GetWindowRect( hwnd, &rc );
if ( dwGrowMode & GM_LOX )
rc.left += dxClient;
if ( dwGrowMode & GM_HIX )
rc.right += dxClient;
if ( dwGrowMode & GM_LOY )
rc.top += dyClient;
if ( dwGrowMode & GM_HIY )
rc.bottom += dyClient;
ScreenToClientRect( GetParent( hwnd ), &rc );
SetWindowRect( hwnd, &rc, fRepaint );
return TRUE;
}
BOOL CALLBACK GrowChildWindows(
HWND hwnd, // handle to child window
LPARAM lParam // application-defined value
)
{
LONG cx = (SHORT)LOWORD( lParam );
LONG cy = (SHORT)HIWORD( lParam );
GrowWindow( hwnd, cx, cy, TRUE );
return TRUE;
}
/*
BOOL CALLBACK EnumChildProc(HWND hwndChild, LPARAM lParam)
{
HFONT aFont = *((HFONT*) lParam);
HDC hDC = GetDC( hwndChild );
SelectObject( hDC, aFont );
ReleaseDC( hwndChild, hDC );
return TRUE;
}
void ApplySystemFont( HWND hwndDlg )
{
NONCLIENTMETRICSA aNonClientMetrics;
aNonClientMetrics.cbSize = sizeof( aNonClientMetrics );
if ( SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof( aNonClientMetrics ), &aNonClientMetrics, 0 ) )
{
HFONT aSysFont = CreateFontIndirectA( &aNonClientMetrics.lfMessageFont );
EnumChildWindows(hwndDlg, EnumChildProc, (LPARAM) &aSysFont);
}
}
*/
BOOL CALLBACK PreviewDialogProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
static RECT rcClient;
switch ( uMsg )
{
case WM_SIZE:
{
LONG cx = LOWORD( lParam );
LONG cy = HIWORD( lParam );
LONG dxClient, dyClient;
dxClient = cx - rcClient.right;
dyClient = cy - rcClient.bottom;
EnumChildWindows( hwndDlg, GrowChildWindows, MAKELONG( (SHORT)dxClient, (SHORT)dyClient) );
GetClientRect( hwndDlg, &rcClient );
}
break;
case WM_INITDIALOG:
{
GetClientRect( hwndDlg, &rcClient );
SetGrowMode( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GM_HIX | GM_HIY );
SetGrowMode( GetDlgItem(hwndDlg, IDOK), GM_LOX | GM_HIX | GM_LOY | GM_HIY );
CrashReportParams *pParams = (CrashReportParams *)lParam;
TCHAR szBuffer[256] = TEXT("");
HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
GetWindowText( hwndParent, szBuffer, elementsof(szBuffer) );
SetWindowText( hwndDlg, szBuffer );
LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
basic_string<TCHAR> aString;
aString.append( pParams->szTitle );
aString.append( _T("\r\n\r\n") );
aString.append( pParams->szComment );
aString.append( _T("\r\n---------- report ----------\r\n") );
FILE *fp = fopen( g_szReportFileNameA, "r" );
if ( fp )
{
char buf[1024];
while ( fgets( buf, elementsof(buf), fp ) != NULL )
{
WCHAR bufW[1024];
MultiByteToWideChar( CP_UTF8, 0, buf, -1, bufW, elementsof(bufW) );
aString.append( bufW );
}
fclose( fp );
}
aString.append( _T("\r\n---------- stack ----------\r\n") );
fp = fopen( g_szDumpFileNameA, "rb" );
if ( fp )
{
unsigned char buf[16];
int count;
do
{
int i;
count = fread( buf, sizeof(buf[0]), sizeof(buf)/sizeof(buf[0]), fp );
for ( i = 0; i < count; i++ )
{
TCHAR output[16];
_sntprintf( output, elementsof(output), _T("%02X\x20"), buf[i] );
aString.append( output );
}
for ( ; i < elementsof(buf); i++ )
{
aString.append( _T("\x20\x20\x20") );
}
for ( i = 0; i < count; i++ )
{
TCHAR output[2];
if ( (int)buf[i] >= 0x20 && (int)buf[i] <= 0x7F )
output[0] = (int)buf[i];
else
output[0] = '.';
output[1] = 0;
aString.append( output );
}
aString.append( _T("\r\n") );
} while ( count );
fclose( fp );
}
Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), aString.c_str() );
SetWindowFont( GetDlgItem(hwndDlg, IDC_EDIT_PREVIEW), GetStockObject( SYSTEM_FIXED_FONT ), TRUE );
}
return TRUE;
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDOK:
case IDCANCEL:
EndDialog( hwndDlg, wParam );
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
//***************************************************************************
static void PreviewReport( HWND hwndParent, CrashReportParams *pParams )
{
HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE );
WriteReportFile( pParams );
DialogBoxParam(
hInstance,
MAKEINTRESOURCE(IDD_PREVIEW_FRAME),
hwndParent,
PreviewDialogProc,
(LPARAM)pParams
);
DeleteFileA( g_szReportFileNameA );
}
//***************************************************************************
void UpdateOptionsDialogControls( HWND hwndDlg )
{
if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED )
{
EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), TRUE );
EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), TRUE );
}
else
{
EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), FALSE );
EnableWindow( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), FALSE );
}
}
//***************************************************************************
BOOL CALLBACK OptionsDialogProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
static CrashReportParams *pParams;
switch ( uMsg )
{
case WM_INITDIALOG:
{
TCHAR szBuffer[1024] = TEXT("");
HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
pParams = (CrashReportParams *)lParam;
LoadAndFormatString( hInstance, IDS_OPTIONS_CAPTION, szBuffer, elementsof(szBuffer) );
SetWindowText( hwndDlg, szBuffer );
LoadAndFormatString( hInstance, IDS_PROXY_SETTINGS_HEADER, szBuffer, elementsof(szBuffer) );
Static_SetText( GetDlgItem(hwndDlg, IDC_PROXY_SETTINGS), szBuffer );
LoadAndFormatString( hInstance, IDS_PROXY_SYSTEM, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM), szBuffer );
LoadAndFormatString( hInstance, IDS_PROXY_DIRECT, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT), szBuffer );
LoadAndFormatString( hInstance, IDS_PROXY_MANUAL, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL), szBuffer );
LoadAndFormatString( hInstance, IDS_LABEL_PROXYSERVER, szBuffer, elementsof(szBuffer) );
Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYSERVER), szBuffer );
LoadAndFormatString( hInstance, IDS_LABEL_PROXYPORT, szBuffer, elementsof(szBuffer) );
Static_SetText( GetDlgItem(hwndDlg, IDC_LABEL_PROXYPORT), szBuffer );
LoadAndFormatString( hInstance, IDS_OK_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDOK), szBuffer );
LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), pParams->szProxyServer );
Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), pParams->szProxyPort );
Button_SetCheck( GetDlgItem(hwndDlg, IDC_RADIO_SYSTEM + pParams->uInternetConnection), BST_CHECKED );
SendMessage(
GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION),
EM_SETBKGNDCOLOR,
(WPARAM)FALSE,
GetSysColor( COLOR_3DFACE ) );
LoadAndFormatString( hInstance, IDS_PROXY_DESCRIPTION, szBuffer, elementsof(szBuffer) );
Edit_SetText( GetDlgItem(hwndDlg, IDC_PROXY_DESCRIPTION), szBuffer );
UpdateOptionsDialogControls( hwndDlg );
}
return TRUE;
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDC_RADIO_SYSTEM:
case IDC_RADIO_DIRECT:
case IDC_RADIO_MANUAL:
if ( BN_CLICKED == HIWORD(wParam) )
UpdateOptionsDialogControls( hwndDlg );
break;
case IDOK:
{
Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYSERVER), pParams->szProxyServer, elementsof(pParams->szProxyServer) );
Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_PROXYPORT), pParams->szProxyPort, elementsof(pParams->szProxyPort) );
if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_DIRECT) ) & BST_CHECKED )
pParams->uInternetConnection = 1;
else if ( Button_GetCheck( GetDlgItem(hwndDlg, IDC_RADIO_MANUAL) ) & BST_CHECKED )
pParams->uInternetConnection = 2;
else
pParams->uInternetConnection = 0;
}
case IDCANCEL:
EndDialog( hwndDlg, wParam );
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
//***************************************************************************
static void OptionsDialog( HWND hwndParent, CrashReportParams *pParams )
{
HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE );
if ( IDOK == DialogBoxParam(
hInstance,
MAKEINTRESOURCE(IDD_OPTIONS_FRAME),
hwndParent,
OptionsDialogProc,
(LPARAM)pParams
) )
pParams->WriteToRegistry();
}
//***************************************************************************
void UpdateReportDialogControls( HWND hwndDlg )
{
EnableWindow(
GetDlgItem(hwndDlg, IDC_EDIT_EMAIL),
Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE );
EnableWindow(
GetDlgItem(hwndDlg, IDC_LABEL_EMAIL),
Button_GetCheck(GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT)) & BST_CHECKED ? TRUE : FALSE );
}
//***************************************************************************
BOOL CALLBACK ReportDialogProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch ( uMsg )
{
case WM_INITDIALOG:
{
CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
TCHAR szBuffer[FORMATBUFSIZE];
LoadAndFormatString( hInstance, IDS_REPORT_INTRO, szBuffer, elementsof(szBuffer) );
Static_SetText( GetDlgItem(hwndDlg, IDC_REPORT_INTRO), szBuffer );
Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT3), szBuffer );
LoadAndFormatString( hInstance, IDS_ENTER_TITLE, szBuffer, elementsof(szBuffer) );
Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_TITLE), szBuffer );
LoadAndFormatString( hInstance, IDS_ENTER_DESCRIPTION, szBuffer, elementsof(szBuffer) );
Static_SetText( GetDlgItem(hwndDlg, IDC_ENTER_DESCRIPTION), szBuffer );
LoadAndFormatString( hInstance, IDS_SHOW_REPORT_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDC_SHOW_REPORT), szBuffer );
LoadAndFormatString( hInstance, IDS_SAVE_REPORT_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), szBuffer );
const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
if ( pszUserType )
ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_SHOW );
else
ShowWindow( GetDlgItem(hwndDlg, IDC_SAVE_REPORT), SW_HIDE );
LoadAndFormatString( hInstance, IDS_OPTIONS_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDC_OPTIONS), szBuffer );
LoadAndFormatString( hInstance, IDS_ALLOW_CONTACT, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), szBuffer );
Button_SetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT), pParams->fAllowContact ? BST_CHECKED : BST_UNCHECKED );
LoadAndFormatString( hInstance, IDS_LABEL_EMAIL, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDC_LABEL_EMAIL), szBuffer );
Edit_SetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), pParams->szEmail );
UpdateReportDialogControls( hwndDlg );
}
return TRUE;
case WM_SHOWWINDOW:
if ( (BOOL)wParam )
{
HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
TCHAR szBuffer[FORMATBUFSIZE];
LoadAndFormatString( hInstance, IDS_REPORT_CAPTION, szBuffer, elementsof(szBuffer) );
SetWindowText( GetParent(hwndDlg), szBuffer );
LoadAndFormatString( hInstance, IDS_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
LoadAndFormatString( hInstance, IDS_DONOT_SEND_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer );
ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), TRUE );
ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), TRUE );
ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), FALSE );
/*
SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE,
GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDFINISH), GWL_STYLE) | BS_DEFPUSHBUTTON );
SetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE,
GetWindowLong( GetDlgItem(GetParent(hwndDlg),IDBACK), GWL_STYLE) &~ BS_DEFPUSHBUTTON );
*/
SetFocus( GetDlgItem(hwndDlg,IDC_EDIT_TITLE) );
}
break;
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDC_SHOW_REPORT:
{
CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndDlg, IDC_ALLOW_CONTACT) ) ? TRUE : FALSE;
Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_TITLE), pParams->szTitle, elementsof(pParams->szTitle) );
Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_DESCRIPTION), pParams->szComment, elementsof(pParams->szComment) );
Edit_GetText( GetDlgItem(hwndDlg, IDC_EDIT_EMAIL), pParams->szEmail, elementsof(pParams->szEmail) );
PreviewReport( GetParent(hwndDlg), pParams );
}
return TRUE;
case IDC_SAVE_REPORT:
SaveDumpFile( GetParent(hwndDlg) );
return TRUE;
case IDC_OPTIONS:
{
CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( GetParent(hwndDlg), GWL_USERDATA );
OptionsDialog( GetParent(hwndDlg), pParams );
}
return TRUE;
case IDC_ALLOW_CONTACT:
if ( BN_CLICKED == HIWORD(wParam) )
UpdateReportDialogControls( hwndDlg );
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
//***************************************************************************
BOOL CALLBACK WelcomeDialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg )
{
case WM_INITDIALOG:
{
HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
HWND hwndRichEdit = GetDlgItem(hwndDlg, IDC_RICHEDIT21);
TCHAR szBuffer[FORMATBUFSIZE];
TCHAR szBuffer2[FORMATBUFSIZE];
TCHAR szURL[256];
TCHAR szCaption[256];
SendMessage(
hwndRichEdit,
EM_SETBKGNDCOLOR,
(WPARAM)FALSE,
GetSysColor( COLOR_3DFACE ) );
SendMessage( hwndRichEdit, EM_SETEVENTMASK, 0, ENM_LINK );
SendMessage( hwndRichEdit, EM_AUTOURLDETECT, TRUE, 0 );
LoadAndFormatString( hInstance, IDS_WELCOME_BODY1, szBuffer, elementsof(szBuffer) );
LoadAndFormatString( hInstance, IDS_WELCOME_BODY2, szBuffer2, elementsof(szBuffer2) );
_tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) );
LoadAndFormatString( hInstance, IDS_WELCOME_BODY3, szBuffer2, elementsof(szBuffer2) );
_tcsncat( szBuffer, szBuffer2, elementsof(szBuffer) );
LoadString( hInstance, IDS_PRIVACY_URL, szURL, elementsof(szURL) );
_tcsncat( szBuffer, szURL, elementsof(szBuffer) );
SetWindowText( hwndRichEdit, szBuffer );
LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szCaption, elementsof(szCaption) );
SetWindowText( GetParent(hwndDlg), szCaption );
}
return TRUE;
case WM_SHOWWINDOW:
if ( (BOOL)wParam )
{
HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
TCHAR szBuffer[FORMATBUFSIZE];
LoadAndFormatString( hInstance, IDS_WELCOME_CAPTION, szBuffer, elementsof(szBuffer) );
SetWindowText( GetParent(hwndDlg), szBuffer );
LoadAndFormatString( hInstance, IDS_WELCOME_HEADER, szBuffer, elementsof(szBuffer) );
SetWindowText( GetDlgItem(GetParent(hwndDlg), IDC_HEADER), szBuffer );
LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(GetParent(hwndDlg), IDCANCEL), szBuffer );
ShowWindow( GetDlgItem(GetParent(hwndDlg),IDBACK), FALSE );
ShowWindow( GetDlgItem(GetParent(hwndDlg),IDFINISH), FALSE );
ShowWindow( GetDlgItem(GetParent(hwndDlg),IDNEXT), TRUE );
SetFocus( GetDlgItem(GetParent(hwndDlg),IDNEXT) );
}
break;
case WM_NOTIFY:
{
LPNMHDR pnmh = (LPNMHDR)lParam;
if ( pnmh->idFrom == IDC_RICHEDIT21 && pnmh->code == EN_LINK )
{
ENLINK *plink = (ENLINK*)lParam;
if ( plink->msg == WM_LBUTTONUP )
{
TCHAR szBuffer[256];
TEXTRANGE range;
range.chrg = plink->chrg;
range.lpstrText = szBuffer;
SendMessage( pnmh->hwndFrom, EM_GETTEXTRANGE, 0, (LPARAM)&range );
ShellExecute( hwndDlg, NULL, szBuffer, NULL, NULL, SW_SHOWDEFAULT );
}
}
}
break;
default:
break;
}
return FALSE;
}
//***************************************************************************
BOOL CALLBACK DialogProc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
static HWND hwndPages[2] = { NULL };
static int iActualPage = 0;
switch ( uMsg )
{
case WM_INITDIALOG:
{
HINSTANCE hInstance = (HINSTANCE)GetWindowLong(hwndDlg, GWL_HINSTANCE );
TCHAR szBuffer[FORMATBUFSIZE];
SetWindowLong( hwndDlg, GWL_USERDATA, (LONG)lParam );
hwndPages[0] = CreateDialog(
hInstance,
MAKEINTRESOURCE(IDD_WELCOME_PAGE),
hwndDlg,
WelcomeDialogProc );
hwndPages[1] = CreateDialog(
hInstance,
MAKEINTRESOURCE(IDD_REPORT_PAGE),
hwndDlg,
ReportDialogProc );
CHARFORMAT chfmt;
chfmt.cbSize = sizeof(chfmt);
chfmt.dwMask = CFM_BOLD;
chfmt.dwEffects = CFE_BOLD;
SendMessage(
GetDlgItem(hwndDlg, IDC_HEADER),
EM_SETCHARFORMAT,
SCF_ALL,
(LPARAM)&chfmt );
LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
LoadAndFormatString( hInstance, IDS_NEXT_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDNEXT), szBuffer );
LoadAndFormatString( hInstance, IDS_SEND_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDFINISH), szBuffer );
LoadAndFormatString( hInstance, IDS_BACK_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDBACK), szBuffer );
ShowWindow( hwndPages[1], SW_HIDE );
ShowWindow( hwndPages[0], SW_SHOW );
// Let Crash Reporter window stay on top of all other windows
SetWindowPos( hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
}
return FALSE;
case WM_CTLCOLORSTATIC:
return (BOOL)CreateSolidBrush(GetSysColor(COLOR_WINDOW));
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDBACK:
if ( iActualPage > 0 )
{
ShowWindow( hwndPages[iActualPage], SW_HIDE );
ShowWindow( hwndPages[--iActualPage], SW_SHOW );
}
return TRUE;
case IDNEXT:
if ( iActualPage < elementsof(hwndPages) - 1 )
{
ShowWindow( hwndPages[iActualPage], SW_HIDE );
ShowWindow( hwndPages[++iActualPage], SW_SHOW );
}
return TRUE;
case IDFINISH:
{
CrashReportParams *pParams = (CrashReportParams*)GetWindowLong( hwndDlg, GWL_USERDATA );
pParams->fAllowContact = Button_GetCheck( GetDlgItem(hwndPages[1], IDC_ALLOW_CONTACT) ) ? TRUE : FALSE;
Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_TITLE), pParams->szTitle, elementsof(pParams->szTitle) );
Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_DESCRIPTION), pParams->szComment, elementsof(pParams->szComment) );
Edit_GetText( GetDlgItem(hwndPages[1], IDC_EDIT_EMAIL), pParams->szEmail, elementsof(pParams->szEmail) );
if ( pParams->fAllowContact && !pParams->szEmail[0] )
{
TCHAR szMessage[MAX_TEXT_BUFFER];
LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_NOEMAILADDRESS, szMessage, elementsof(szMessage) );
MessageBox( hwndDlg, szMessage, NULL, MB_ICONERROR | MB_OK );
break; // Don't end the dialog
}
else
{
pParams->WriteToRegistry();
WriteCommentFile( pParams->szComment );
WriteReportFile( pParams );
if ( !SendCrashReport( hwndDlg, *pParams ) )
break; // Don't end the dialog
}
}
// Fallthrough !!!
case IDCANCEL:
EndDialog( hwndDlg, wParam );
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
//*****************************************************************************
//* Generate MD5 checksum
//*****************************************************************************
#define MAGIC_DESCRIPTION_FILLER 'x'
#define MAGIC_DESCRIPTION_COUNT 80
static void repatch_soffice_exe( void *pBuffer, size_t nBufSize )
{
wchar_t DescriptionBuffer[MAGIC_DESCRIPTION_COUNT];
memset( DescriptionBuffer, 0, sizeof(DescriptionBuffer) );
wcsncpy( DescriptionBuffer, g_wstrProductKey.c_str(), elementsof(DescriptionBuffer) - 1 );
bool bPatched = false;
do
{
void *pFound = memchr( pBuffer, ((char *)DescriptionBuffer)[0], nBufSize );
if ( pFound )
{
size_t distance = (char *)pFound - (char *)pBuffer;
if ( nBufSize >= distance )
{
nBufSize -= distance;
if ( nBufSize >= sizeof(DescriptionBuffer) &&
0 == memcmp( pFound, DescriptionBuffer, sizeof(DescriptionBuffer) ) )
{
for ( int i = 0; i < 80; i++ )
{
((wchar_t *)pFound)[i] = MAGIC_DESCRIPTION_FILLER;
}
bPatched = true;
}
else
{
pBuffer = (void *)(((char *)pFound) + 1);
nBufSize--;
}
}
else
nBufSize = 0;
}
else
nBufSize = 0;
} while ( !bPatched && nBufSize );
}
static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
{
sal_uInt32 nBytesProcessed = 0;
FILE *fp = fopen( filename, "rb" );
if ( fp )
{
long nFileSize;
if ( 0 == fseek( fp, 0, SEEK_END ) && -1 != (nFileSize = ftell(fp)) )
{
rewind( fp );
sal_uInt8 *pBuffer = new sal_uInt8[nFileSize];
size_t nBytesRead = fread( pBuffer, 1, nFileSize, fp );
if ( nBytesRead == nFileSize )
{
if ( 0 == stricmp( GetFileName(filename).c_str(), "soffice.exe" ) )
repatch_soffice_exe( pBuffer, nBytesRead );
rtlDigestError error = rtl_digest_MD5 (
pBuffer, nBytesRead,
pChecksum, nChecksumLen );
if ( rtl_Digest_E_None == error )
nBytesProcessed = nBytesRead;
}
delete[] pBuffer;
}
fclose( fp );
}
return nBytesProcessed;
}
#if 0
static sal_uInt32 calc_md5_checksum( const char *filename, sal_uInt8 *pChecksum, sal_uInt32 nChecksumLen )
{
sal_uInt32 nBytesProcessed = 0;
FILE *fp = fopen( filename, "rb" );
if ( fp )
{
rtlDigest digest = rtl_digest_createMD5();
if ( digest )
{
size_t nBytesRead;
sal_uInt8 buffer[4096];
rtlDigestError error = rtl_Digest_E_None;
while ( rtl_Digest_E_None == error &&
0 != (nBytesRead = fread( buffer, 1, sizeof(buffer), fp )) )
{
error = rtl_digest_updateMD5( digest, buffer, nBytesRead );
nBytesProcessed += nBytesRead;
}
if ( rtl_Digest_E_None == error )
{
error = rtl_digest_getMD5( digest, pChecksum, nChecksumLen );
}
if ( rtl_Digest_E_None != error )
nBytesProcessed = 0;
rtl_digest_destroyMD5( digest );
}
fclose( fp );
}
return nBytesProcessed;
}
#endif
//***************************************************************************
static bool WriteStackFile( FILE *fout, hash_map< string, string >& rLibraries, DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers )
{
bool fSuccess = false;
if ( fout && dwProcessId && pExceptionPointers )
{
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
if ( IsValidHandle(hProcess) )
{
EXCEPTION_POINTERS aExceptionPointers;
CONTEXT aContextRecord;
ReadProcessMemory(
hProcess,
pExceptionPointers,
&aExceptionPointers,
sizeof(aExceptionPointers),
NULL );
ReadProcessMemory(
hProcess,
aExceptionPointers.ContextRecord,
&aContextRecord,
sizeof(aContextRecord),
NULL );
STACKFRAME frame;
ZeroMemory( &frame, sizeof(frame) );
frame.AddrPC.Offset = aContextRecord.Eip;
frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = aContextRecord.Ebp;
frame.AddrFrame.Mode = AddrModeFlat;
BOOL bSuccess;
int frameNum = 0;
SymInitialize( hProcess, NULL, TRUE );
fprintf( fout, "<errormail:Stack type=\"Win32\">\n" );
do
{
fSuccess = true;
bSuccess = StackWalk( IMAGE_FILE_MACHINE_I386,
hProcess,
NULL,
&frame,
&aContextRecord,
(PREAD_PROCESS_MEMORY_ROUTINE)ReadProcessMemory,
SymFunctionTableAccess,
SymGetModuleBase,
NULL );
if ( bSuccess )
{
// Note: ImageHelp ANSI functions do not have an A postfix while
// Unicode versions have a W postfix. There's no macro
// that depends on define UNICODE
IMAGEHLP_MODULE moduleInfo;
ZeroMemory( &moduleInfo, sizeof(moduleInfo) );
moduleInfo.SizeOfStruct = sizeof(moduleInfo);
if ( SymGetModuleInfo( hProcess, frame.AddrPC.Offset, &moduleInfo ) )
{
rLibraries[ GetFileName( moduleInfo.LoadedImageName ).c_str() ] = moduleInfo.LoadedImageName;
DWORD dwRelOffset = 0;
BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL) + 256 ];
PIMAGEHLP_SYMBOL pSymbol = (PIMAGEHLP_SYMBOL)symbolBuffer;
ZeroMemory( symbolBuffer, sizeof(symbolBuffer) );
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
pSymbol->MaxNameLength = 256;
if ( SymGetSymFromAddr( hProcess, frame.AddrPC.Offset, &dwRelOffset, pSymbol ) )
fprintf( fout, "<errormail:StackInfo " \
"pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" ordinal=\"%s+0x%p\" name=\"%s\" path=\"%s\"/>\n",
frameNum,
frame.AddrPC.Offset,
frame.AddrPC.Offset - moduleInfo.BaseOfImage,
xml_encode(pSymbol->Name).c_str(),
frame.AddrPC.Offset - pSymbol->Address,
xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
xml_encode( GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
);
else
fprintf( fout, "<errormail:StackInfo " \
"pos=\"%d\" ip=\"0x%p\" rel=\"0x%p\" name=\"%s\" path=\"%s\"/>\n",
frameNum,
frame.AddrPC.Offset,
frame.AddrPC.Offset - moduleInfo.BaseOfImage,
xml_encode(GetFileName( moduleInfo.LoadedImageName )).c_str(),
xml_encode(GetFileDirectory( moduleInfo.LoadedImageName )).c_str()
);
}
else
fprintf( fout, "<errormail:StackInfo pos=\"%d\" ip=\"0x%p\"/>\n",
frameNum,
frame.AddrPC.Offset
);
frameNum++;
}
} while ( bSuccess );
fprintf( fout, "</errormail:Stack>\n" );
SymCleanup( hProcess );
CloseHandle( hProcess );
}
}
return fSuccess;
}
bool WriteChecksumFile( FILE *fchksum, const hash_map< string, string >& rLibraries )
{
bool success = false;
if ( fchksum && rLibraries.size() )
{
fprintf( fchksum, "<errormail:Checksums type=\"MD5\">\n" );
hash_map< string, string >::const_iterator iter;
for ( iter = rLibraries.begin();
iter != rLibraries.end();
iter++ )
{
sal_uInt8 checksum[RTL_DIGEST_LENGTH_MD5];
sal_uInt32 nBytesProcessed = calc_md5_checksum(
iter->second.c_str(),
checksum, sizeof(checksum) );
if ( nBytesProcessed )
{
fprintf( fchksum, "<errormail:Checksum sum=\"0x" );
for ( int i = 0; i < sizeof(checksum); fprintf( fchksum, "%02X", checksum[i++] ) );
fprintf( fchksum, "\" bytes=\"%d\" file=\"%s\"/>\n",
nBytesProcessed,
GetFileName( iter->first ) );
}
}
fprintf( fchksum, "</errormail:Checksums>\n" );
success = true;
}
return success;
}
//***************************************************************************
BOOL WriteDumpFile( DWORD dwProcessId, PEXCEPTION_POINTERS pExceptionPointers, DWORD dwThreadId )
{
BOOL fSuccess = FALSE;
PMINIDUMP_EXCEPTION_INFORMATION lpExceptionParam = NULL;
MINIDUMP_EXCEPTION_INFORMATION ExceptionParam;
HMODULE hDbgHelp = LoadLibrary( _T("DBGHELP.DLL" ) );
MiniDumpWriteDump_PROC pMiniDumpWriteDump = NULL;
if ( hDbgHelp )
{
pMiniDumpWriteDump = (MiniDumpWriteDump_PROC)GetProcAddress( hDbgHelp, "MiniDumpWriteDump" );
if ( !pMiniDumpWriteDump )
{
FreeLibrary( hDbgHelp );
return false;
}
}
if ( !pMiniDumpWriteDump )
return false;
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId );
if ( IsValidHandle(hProcess) )
{
TCHAR szTempPath[MAX_PATH];
if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
{
TCHAR szFileName[MAX_PATH];
if ( GetTempFileName( szTempPath, TEXT("DMP"), 0, szFileName ) )
{
HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile )
{
if ( pExceptionPointers && dwThreadId )
{
ExceptionParam.ThreadId = dwThreadId;
ExceptionParam.ExceptionPointers = pExceptionPointers;
ExceptionParam.ClientPointers = TRUE;
EXCEPTION_POINTERS aExceptionPointers;
EXCEPTION_RECORD aExceptionRecord;
ReadProcessMemory(
hProcess,
pExceptionPointers,
&aExceptionPointers,
sizeof(aExceptionPointers),
NULL );
ReadProcessMemory(
hProcess,
aExceptionPointers.ExceptionRecord,
&aExceptionRecord,
sizeof(aExceptionRecord),
NULL );
g_dwExceptionCode = aExceptionRecord.ExceptionCode;
lpExceptionParam = &ExceptionParam;
}
fSuccess = pMiniDumpWriteDump( hProcess, dwProcessId, hFile, MiniDumpNormal, lpExceptionParam, NULL, NULL );
CloseHandle( hFile );
WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szDumpFileNameA, MAX_PATH, NULL, NULL );
_tcscpy( g_szDumpFileName, szFileName );
}
if ( !fSuccess )
DeleteFile( szFileName );
}
}
CloseHandle( hProcess );
}
FreeLibrary( hDbgHelp );
return fSuccess;
}
//***************************************************************************
static DWORD FindProcessForImage( LPCTSTR lpImagePath )
{
DWORD dwProcessId = 0;
DWORD aProcesses[1024];
DWORD dwSize = 0;
TCHAR szShortImagePath[MAX_PATH];
if ( GetShortPathName( lpImagePath, szShortImagePath, elementsof(szShortImagePath) ) &&
EnumProcesses( aProcesses, sizeof(aProcesses), &dwSize ) )
{
unsigned nProcesses = dwSize / sizeof(aProcesses[0]);
for ( unsigned i = 0; !dwProcessId && i < nProcesses; i++ )
{
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, aProcesses[i] );
if ( IsValidHandle(hProcess) )
{
TCHAR szModulePath[MAX_PATH+1];
if ( GetModuleFileNameEx( hProcess, NULL, szModulePath, MAX_PATH ) )
{
TCHAR szShortModulePath[MAX_PATH];
if ( GetShortPathName( szModulePath, szShortModulePath, elementsof(szShortModulePath) ) )
{
if ( 0 == _tcsicmp( szShortModulePath, szShortImagePath ) )
dwProcessId = aProcesses[i];
}
}
CloseHandle( hProcess );
}
}
}
return dwProcessId;
}
//***************************************************************************
static bool ParseCommandArgs( LPDWORD pdwProcessId, PEXCEPTION_POINTERS* ppException, LPDWORD pdwThreadId )
{
int argc = __argc;
TCHAR **argv = __targv;
bool bSuccess = true;
for ( int argn = 1; bSuccess && argn < argc; argn++ )
{
if ( 0 == _tcsicmp( argv[argn], _T("-h") ) ||
0 == _tcsicmp( argv[argn], _T("/h") ) ||
0 == _tcsicmp( argv[argn], _T("-?") ) ||
0 == _tcsicmp( argv[argn], _T("/?") ) ||
0 == _tcsicmp( argv[argn], _T("/help") ) ||
0 == _tcsicmp( argv[argn], _T("-help") ) ||
0 == _tcsicmp( argv[argn], _T("--help") )
)
{
HINSTANCE hInstance = GetModuleHandle(NULL);
TCHAR szUsage[FORMATBUFSIZE];
TCHAR szProcess[FORMATBUFSIZE];
TCHAR szProcessDescription[FORMATBUFSIZE];
TCHAR szHelpDescription[FORMATBUFSIZE];
LoadAndFormatString( hInstance, IDS_MSG_CMDLINE_USAGE, szUsage, elementsof(szUsage) );
LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID, szProcess, elementsof(szProcess) );
LoadAndFormatString( hInstance, IDS_MSG_PARAM_PROCESSID_DESCRIPTION, szProcessDescription, elementsof(szProcessDescription) );
LoadAndFormatString( hInstance, IDS_MSG_PARAM_HELP_DESCRIPTION, szHelpDescription, elementsof(szHelpDescription) );
_tprintf(
TEXT("\n%s: crashrep %s\n\n")
TEXT("/?, -h[elp] %s\n\n")
TEXT("%-20s %s\n\n"),
szUsage, szProcess, szHelpDescription, szProcess, szProcessDescription
);
return true;
}
else if ( 0 == _tcsicmp( argv[argn], _T("-p") ) ||
0 == _tcsicmp( argv[argn], _T("/p") ) )
{
if ( ++argn < argc )
*pdwProcessId = _tcstoul( argv[argn], NULL, 0 );
else
bSuccess = false;
}
else if ( 0 == _tcsicmp( argv[argn], _T("-excp") ) ||
0 == _tcsicmp( argv[argn], _T("/excp") ) )
{
if ( ++argn < argc )
*ppException = (PEXCEPTION_POINTERS)_tcstoul( argv[argn], NULL, 0 );
else
bSuccess = false;
}
else if ( 0 == _tcsicmp( argv[argn], _T("-t") ) ||
0 == _tcsicmp( argv[argn], _T("/t") ) )
{
if ( ++argn < argc )
*pdwThreadId = _tcstoul( argv[argn], NULL, 0 );
else
bSuccess = false;
}
else // treat parameter as image path
{
TCHAR szImagePath[MAX_PATH];
LPTSTR lpImageName;
if ( GetFullPathName( argv[argn], MAX_PATH, szImagePath, &lpImageName ) )
{
DWORD dwProcessId = FindProcessForImage( szImagePath );
if ( dwProcessId )
*pdwProcessId = dwProcessId;
else
bSuccess = false;
}
}
}
if ( !*pdwProcessId )
{
TCHAR szImagePath[MAX_PATH];
LPTSTR lpImageName;
if ( GetFullPathName( TEXT("soffice.exe"), MAX_PATH, szImagePath, &lpImageName ) )
{
DWORD dwProcessId = FindProcessForImage( szImagePath );
if ( dwProcessId )
*pdwProcessId = dwProcessId;
else
bSuccess = false;
}
}
return bSuccess;
}
//***************************************************************************
BOOL WriteCommentFile( LPCTSTR lpComment )
{
BOOL fSuccess = FALSE;
TCHAR szTempPath[MAX_PATH];
if ( GetTempPath( elementsof(szTempPath), szTempPath ) )
{
TCHAR szFileName[MAX_PATH];
if ( GetTempFileName( szTempPath, TEXT("CMT"), 0, szFileName ) )
{
HANDLE hFile = CreateFile( szFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile )
{
DWORD dwBytesWritten;
int needed = WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, NULL, 0, NULL, NULL );
if ( needed )
{
char *lpCommentUTF8 = (char *)alloca( needed );
WideCharToMultiByte( CP_UTF8, 0, lpComment, -1, lpCommentUTF8, needed, NULL, NULL );
fSuccess = WriteFile( hFile, lpCommentUTF8, strlen(lpCommentUTF8), &dwBytesWritten, NULL );
}
else
fSuccess = TRUE;
CloseHandle( hFile );
WideCharToMultiByte( CP_ACP, 0, szFileName, -1, g_szCommentFileNameA, MAX_PATH, NULL, NULL );
}
if ( !fSuccess )
DeleteFile( szFileName );
}
}
return fSuccess;
}
//***************************************************************************
static int _tsetenv( const _TCHAR *lpVar, const _TCHAR *lpValue )
{
if ( !lpValue )
lpValue = _T("");
_TCHAR *envstr = (TCHAR *)alloca( (_tcslen( lpVar ) + _tcslen( lpValue ) + 2) * sizeof(_TCHAR) );
_tcscpy( envstr, lpVar );
_tcscat( envstr, _T("=") );
_tcscat( envstr, lpValue );
return _tputenv( envstr );
}
static bool read_line( FILE *fp, string& rLine )
{
char szBuffer[1024];
bool bSuccess = false;
bool bEOL = false;
string line;
while ( !bEOL && fgets( szBuffer, sizeof(szBuffer), fp ) )
{
int len = strlen(szBuffer);
bSuccess = true;
while ( len && szBuffer[len - 1] == '\n' )
{
szBuffer[--len] = 0;
bEOL = true;
}
line.append( szBuffer );
}
rLine = line;
return bSuccess;
}
static string get_script_string( const char *pFileName, const char *pKeyName )
{
FILE *fp = fopen( pFileName, "rt" );
string retValue;
if ( fp )
{
string line;
string section;
while ( read_line( fp, line ) )
{
line = trim_string( line );
string::size_type iEqualSign = line.find( '=', 0 );
if ( iEqualSign != string::npos )
{
string keyname = line.substr( 0, iEqualSign );
keyname = trim_string( keyname );
string value = line.substr( iEqualSign + 1, -1 );
value = trim_string( value );
if ( value.length() && '\"' == value[0] )
{
value.erase( 0, 1 );
string::size_type iQuotes = value.find( '"', 0 );
if ( iQuotes != string::npos )
value.erase( iQuotes );
}
if ( 0 == stricmp( keyname.c_str(), pKeyName ) )
{
retValue = value;
break;
}
}
}
fclose( fp );
}
return retValue;
}
static bool ReadBootstrapParams()
{
TCHAR szBuffer[256] = TEXT("");
TCHAR szModuleName[MAX_PATH];
TCHAR szDrive[_MAX_DRIVE];
TCHAR szDir[_MAX_DIR];
TCHAR szFName[_MAX_FNAME];
TCHAR szExt[_MAX_EXT];
TCHAR szReportServer[MAX_HOSTNAME];
TCHAR szReportPort[256];
bool bSuccess = false;
GetModuleFileName( NULL, szModuleName, MAX_PATH );
_tsplitpath( szModuleName, szDrive, szDir, szFName, szExt );
_tmakepath( szModuleName, szDrive, szDir, _T("bootstrap"), _T(".ini") );
if (
GetPrivateProfileString(
TEXT("Bootstrap"),
TEXT("ProductKey"),
TEXT("OpenOffice.org"),
szBuffer,
elementsof(szBuffer),
szModuleName )
)
{
TCHAR *pVersion = _tcschr( szBuffer, ' ' );
g_wstrProductKey = szBuffer;
if ( pVersion )
{
*pVersion = 0;
pVersion++;
}
else
pVersion = TEXT("");
if ( !_tgetenv( _T("PRODUCTNAME") ) )
{
_tsetenv( TEXT("PRODUCTNAME"), szBuffer );
}
if ( !_tgetenv( _T("PRODUCTVERSION") ) )
_tsetenv( TEXT("PRODUCTVERSION"), pVersion );
}
GetPrivateProfileString(
TEXT("Bootstrap"),
TEXT("buildid"),
TEXT("unknown"),
g_szBuildId, elementsof(g_szBuildId),
szModuleName );
g_strDefaultLanguage = get_script_string( "instdb.inf", "DefaultLanguage" );
if ( GetPrivateProfileString(
TEXT("ErrorReport"),
TEXT("ErrorReportPort"),
TEXT("80"),
szReportPort, elementsof(szReportPort),
szModuleName
) )
{
TCHAR *endptr = NULL;
unsigned short uReportPort = (unsigned short)_tcstoul( szReportPort, &endptr, 10 );
if ( uReportPort )
g_uReportPort = uReportPort;
}
if ( GetPrivateProfileString(
TEXT("ErrorReport"),
TEXT("ErrorReportServer"),
TEXT(""),
szReportServer, elementsof(szReportServer),
szModuleName
) )
{
bSuccess = 0 != WideCharToMultiByte( CP_ACP, 0, szReportServer, -1, g_szReportServerA, elementsof(g_szReportServerA), NULL, NULL );
}
return bSuccess;
}
//***************************************************************************
bool SendHTTPRequest(
FILE *fp,
const char *pszServer,
unsigned short uPort = 80,
const char *pszProxyServer = NULL,
unsigned short uProxyPort = 8080 )
{
bool success = false;
struct hostent *hp;
if ( pszProxyServer )
hp = gethostbyname( pszProxyServer );
else
hp = gethostbyname( pszServer );
if ( hp )
{
SOCKET s = socket( AF_INET, SOCK_STREAM, 0 );
if ( s )
{
struct sockaddr_in address;
memcpy(&(address.sin_addr.s_addr), *(hp->h_addr_list),sizeof(struct in_addr));
address.sin_family = AF_INET;
if ( pszProxyServer )
address.sin_port = ntohs( uProxyPort );
else
address.sin_port = ntohs( uPort );
if ( 0 == connect( s, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) )
{
fseek( fp, 0, SEEK_END );
size_t length = ftell( fp );
fseek( fp, 0, SEEK_SET );
char buffer[2048];
if ( pszProxyServer )
sprintf( buffer,
"POST http://%s:%d/soap/servlet/rpcrouter HTTP/1.0\r\n"
"Content-Type: text/xml; charset=\"utf-8\"\r\n"
"Content-Length: %d\r\n"
"SOAPAction: \"\"\r\n\r\n",
pszServer,
uPort,
length
);
else
sprintf( buffer,
"POST /soap/servlet/rpcrouter HTTP/1.0\r\n"
"Content-Type: text/xml; charset=\"utf-8\"\r\n"
"Content-Length: %d\r\n"
"SOAPAction: \"\"\r\n\r\n",
length
);
if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
{
size_t nBytes;
do
{
nBytes = fread( buffer, 1, sizeof(buffer), fp );
if ( nBytes )
success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
} while( nBytes && success );
if ( success )
{
memset( buffer, 0, sizeof(buffer) );
success = SOCKET_ERROR != recv( s, buffer, sizeof(buffer), 0 );
if ( success )
{
char szHTTPSignature[sizeof(buffer)] = "";
unsigned uHTTPReturnCode = 0;
sscanf( buffer, "%s %d ", szHTTPSignature, &uHTTPReturnCode );
success = uHTTPReturnCode == 200;
}
}
}
}
closesocket( s );
}
}
return success;
}
//***************************************************************************
static void WriteSOAPRequest( FILE *fp )
{
fprintf( fp,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"\n"
"xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\"\n"
"xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\"\n"
"xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\"\n"
"xmlns:rds=\"urn:ReportDataService\"\n"
"xmlns:apache=\"http://xml.apache.org/xml-soap\"\n"
"SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n"
"<SOAP-ENV:Body>\n"
);
fprintf( fp, "<rds:submitReport>\n" );
fprintf( fp, "<body xsi:type=\"xsd:string\">This is an autogenerated crash report mail.</body>\n" );
fprintf( fp, "<hash xsi:type=\"apache:Map\">\n" );
FILE *fpin = fopen( g_szReportFileNameA, "r" );
if ( fpin )
{
fprintf( fp,
"<item>\n"
"<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
"<value xsi:type=\"xsd:string\"><![CDATA[" );
fcopy( fpin, fp );
fprintf( fp, "]]></value></item>\n" );
fclose( fpin );
}
fpin = fopen( g_szCommentFileNameA, "r" );
if ( fpin )
{
fprintf( fp,
"<item>\n"
"<key xsi:type=\"xsd:string\">description.txt</key>\n"
"<value xsi:type=\"xsd:string\"><![CDATA[" );
fcopy( fpin, fp );
fprintf( fp, "]]></value></item>\n" );
fclose( fpin );
};
fpin = fopen( g_szDumpFileNameA, "rb" );
if ( fpin )
{
FILE *fptemp = _tmpfile();
if ( fptemp )
{
if ( base64_encode( fpin, fptemp ) )
{
fseek( fptemp, 0, SEEK_SET );
fprintf( fp,
"<item>\n"
"<key xsi:type=\"xsd:string\">user.dmp</key>\n"
"<value xsi:type=\"xsd:string\">" );
fcopy( fptemp, fp );
fprintf( fp, "</value></item>\n" );
}
fclose( fptemp );
}
fclose( fpin );
}
fprintf( fp,
"</hash>\n"
"</rds:submitReport>\n"
"</SOAP-ENV:Body>\n"
"</SOAP-ENV:Envelope>\n"
);
}
//***************************************************************************
struct RequestParams
{
bool success;
FILE *fpin;
const char *lpServer;
unsigned short uPort;
const char *lpProxyServer;
unsigned short uProxyPort;
HWND hwndStatus;
};
void _cdecl SendingThread( void *lpArgs )
{
RequestParams *pParams = (RequestParams *)lpArgs;
pParams->success = SendHTTPRequest( pParams->fpin, pParams->lpServer, pParams->uPort, pParams->lpProxyServer, pParams->uProxyPort );
PostMessage( pParams->hwndStatus, WM_COMMAND, IDOK, 0 );
}
//***************************************************************************
BOOL CALLBACK SendingStatusDialogProc(
HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
static RequestParams *pRequest = NULL;
static HANDLE hSendingThread = NULL;
switch ( uMsg )
{
case WM_INITDIALOG:
{
TCHAR szBuffer[1024] = TEXT("");
HINSTANCE hInstance = (HINSTANCE)GetWindowLong( hwndDlg, GWL_HINSTANCE );
HWND hwndParent = (HWND)GetWindowLong( hwndDlg, GWL_HWNDPARENT );
pRequest = (RequestParams *)lParam;
LoadAndFormatString( hInstance, IDS_SENDING_REPORT_HEADER, szBuffer, elementsof(szBuffer) );
SetWindowText( hwndDlg, szBuffer );
LoadAndFormatString( hInstance, IDS_SENDING_REPORT_STATUS, szBuffer, elementsof(szBuffer) );
Static_SetText( GetDlgItem(hwndDlg, IDC_SENDING_REPORT_STATUS), szBuffer );
LoadAndFormatString( hInstance, IDS_CANCEL_BUTTON, szBuffer, elementsof(szBuffer) );
Button_SetText( GetDlgItem(hwndDlg, IDCANCEL), szBuffer );
pRequest->hwndStatus = hwndDlg;
hSendingThread = (HANDLE)_beginthread( SendingThread, 0, pRequest );
}
return TRUE;
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDCANCEL:
TerminateThread( hSendingThread, 0 );
case IDOK:
WaitForSingleObject( hSendingThread, INFINITE );
CloseHandle( hSendingThread );
EndDialog( hwndDlg, wParam );
return TRUE;
}
break;
default:
break;
}
return FALSE;
}
//***************************************************************************
bool SendCrashReport( HWND hwndParent, const CrashReportParams &rParams )
{
bool success = false;
char szProxyServer[1024] = "";
unsigned short uProxyPort = 8080;
TCHAR *endptr = NULL;
switch ( rParams.uInternetConnection )
{
case 2:
{
WideCharToMultiByte(
CP_ACP, 0, rParams.szProxyServer, -1,
szProxyServer, sizeof(szProxyServer), NULL, NULL );
uProxyPort = (unsigned short)_tcstoul( rParams.szProxyPort, &endptr, 10 );
}
break;
case 0:
{
DWORD dwProxyEnable = 0;
RegReadValue( HKEY_CURRENT_USER,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"),
TEXT("ProxyEnable"),
&dwProxyEnable,
sizeof(dwProxyEnable) );
if ( dwProxyEnable )
{
TCHAR tszProxyServers[1024] = TEXT("");
if ( ERROR_SUCCESS == RegReadValue( HKEY_CURRENT_USER,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"), TEXT("ProxyServer"),
tszProxyServers,
sizeof(tszProxyServers) ) )
{
TCHAR *lpHttpStart = _tcsstr( tszProxyServers, TEXT("http=") );
if ( lpHttpStart )
lpHttpStart += 5;
else
lpHttpStart = tszProxyServers;
TCHAR *lpHttpEnd = _tcschr( lpHttpStart, ';' );
if ( lpHttpEnd )
*lpHttpEnd = 0;
char szHTTPProxyServer[1024] = "";
WideCharToMultiByte( CP_ACP, 0, lpHttpStart, -1, szHTTPProxyServer, sizeof(szHTTPProxyServer), NULL, NULL );
char *lpColon = strchr( szHTTPProxyServer, ':' );
if ( lpColon )
{
char *endptr = NULL;
*lpColon = 0;
uProxyPort = (unsigned short)strtoul( lpColon + 1, &endptr, 10 );
}
else
uProxyPort = 8080;
strcpy( szProxyServer, szHTTPProxyServer );
}
}
}
break;
default:
case 1:
break;
}
FILE *fptemp = _tmpfile();
if ( fptemp )
{
WriteSOAPRequest( fptemp );
fseek( fptemp, 0, SEEK_SET );
RequestParams request;
request.success = false;
request.fpin = fptemp;
request.lpServer = REPORT_SERVER;
request.uPort = REPORT_PORT;
request.lpProxyServer = szProxyServer[0] ? szProxyServer : NULL;
request.uProxyPort = uProxyPort;
request.hwndStatus = NULL;
int retid = DialogBoxParam(
GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_SENDING_STATUS),
hwndParent,
SendingStatusDialogProc,
(LPARAM)&request
);
success = request.success;
if ( IDOK == retid )
{
if ( !success )
{
TCHAR szMessage[1024];
LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_PROXY, szMessage, elementsof(szMessage) );
MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
}
else
{
TCHAR szMessage[1024];
TCHAR szTitle[1024];
LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_STATUS_FINISHED, szMessage, elementsof(szMessage) );
LoadAndFormatString( GetModuleHandle(NULL), IDS_SENDING_REPORT_HEADER, szTitle, elementsof(szTitle) );
MessageBox( hwndParent, szMessage, szTitle, MB_ICONINFORMATION | MB_OK );
}
}
fclose( fptemp );
}
else
{
TCHAR szMessage[1024];
LoadAndFormatString( GetModuleHandle(NULL), IDS_ERROR_MSG_DISK_FULL, szMessage, elementsof(szMessage) );
MessageBox( hwndParent, szMessage, NULL, MB_ICONERROR | MB_OK );
}
return success;
}
//***************************************************************************
int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE, LPTSTR lpCmdLine, int )
{
int exitcode = -1;
PEXCEPTION_POINTERS pExceptionPointers = NULL;
DWORD dwProcessId = 0;
DWORD dwThreadId = 0;
WSADATA wsaData;
WORD wVersionRequested;
wVersionRequested = MAKEWORD(1, 1);
WSAStartup(wVersionRequested, &wsaData);
if ( ReadBootstrapParams() && ParseCommandArgs( &dwProcessId, &pExceptionPointers, &dwThreadId ) && dwProcessId )
{
if ( WriteDumpFile( dwProcessId, pExceptionPointers, dwThreadId ) )
{
hash_map< string, string > aLibraries;
g_fpStackFile = _tmpfile();
WriteStackFile( g_fpStackFile, aLibraries, dwProcessId, pExceptionPointers );
g_fpChecksumFile = _tmpfile();
WriteChecksumFile( g_fpChecksumFile, aLibraries );
InitCommonControls();
if ( InitRichEdit() )
{
CrashReportParams Params;
Params.ReadFromRegistry();
INT_PTR result = DialogBoxParam( hInstance, MAKEINTRESOURCE(IDD_DIALOG_FRAME), NULL, DialogProc, (LPARAM)&Params );
if ( result > 0 )
{
exitcode = 0;
}
DeinitRichEdit();
}
if ( g_szReportFileNameA[0] )
DeleteFileA( g_szReportFileNameA );
if ( g_szCommentFileNameA[0] )
DeleteFileA( g_szCommentFileNameA );
DeleteFileA( g_szDumpFileNameA );
if ( g_fpStackFile )
fclose( g_fpStackFile );
if ( g_fpChecksumFile )
fclose( g_fpChecksumFile );
}
}
return exitcode;
}