summaryrefslogtreecommitdiff
path: root/crashrep
diff options
context:
space:
mode:
authorHennes Rohling <hro@openoffice.org>2003-06-06 10:22:06 +0000
committerHennes Rohling <hro@openoffice.org>2003-06-06 10:22:06 +0000
commit477e657cc221f4085b5bae4943b87715140b188f (patch)
tree6056715da21ef64899fd6514e3601753f3c07b2c /crashrep
parentb26ea0541fefc955b21a58ed9302d47f988598dc (diff)
#i15275# Move crashrep sources to OOo cvs module
Diffstat (limited to 'crashrep')
-rwxr-xr-xcrashrep/prj/build.lst6
-rwxr-xr-xcrashrep/prj/d.lst44
-rwxr-xr-xcrashrep/source/unx/interface.cxx659
-rwxr-xr-xcrashrep/source/unx/interface.hxx158
-rwxr-xr-xcrashrep/source/unx/main.cxx1103
-rwxr-xr-xcrashrep/source/unx/makefile.mk101
-rwxr-xr-xcrashrep/source/unx/res.cxx108
-rwxr-xr-xcrashrep/source/unx/res/makefile.mk22
-rwxr-xr-xcrashrep/source/unx/res/unxcrashres.cxx80
-rwxr-xr-xcrashrep/source/win32/base64.cpp56
-rwxr-xr-xcrashrep/source/win32/base64.h19
-rwxr-xr-xcrashrep/source/win32/ctrylnglist.txt29
-rwxr-xr-xcrashrep/source/win32/makefile.mk117
-rwxr-xr-xcrashrep/source/win32/rcfooter.txt1
-rwxr-xr-xcrashrep/source/win32/rcheader.txt4
-rwxr-xr-xcrashrep/source/win32/rctemplate.txt168
-rwxr-xr-xcrashrep/source/win32/resource.h94
-rwxr-xr-xcrashrep/source/win32/soreport.cpp2272
18 files changed, 5041 insertions, 0 deletions
diff --git a/crashrep/prj/build.lst b/crashrep/prj/build.lst
new file mode 100755
index 000000000000..2ef317cc0022
--- /dev/null
+++ b/crashrep/prj/build.lst
@@ -0,0 +1,6 @@
+cr crashrep : sal sysui gtk tools NULL
+cr crashrep usr1 - all cr_mkout NULL
+cr crashrep\source\unx\res nmake - u cr_sures NULL
+cr crashrep\source\unx nmake - u cr_sunx cr_sures.u NULL
+cr crashrep nmake - u cr_supstack NULL
+cr crashrep\source\win32 nmake - n cr_swin32 NULL
diff --git a/crashrep/prj/d.lst b/crashrep/prj/d.lst
new file mode 100755
index 000000000000..75937ab3389f
--- /dev/null
+++ b/crashrep/prj/d.lst
@@ -0,0 +1,44 @@
+mkdir: %_DEST%\bin%_EXT%\01
+mkdir: %_DEST%\bin%_EXT%\03
+mkdir: %_DEST%\bin%_EXT%\07
+mkdir: %_DEST%\bin%_EXT%\30
+mkdir: %_DEST%\bin%_EXT%\31
+mkdir: %_DEST%\bin%_EXT%\33
+mkdir: %_DEST%\bin%_EXT%\34
+mkdir: %_DEST%\bin%_EXT%\39
+mkdir: %_DEST%\bin%_EXT%\45
+mkdir: %_DEST%\bin%_EXT%\46
+mkdir: %_DEST%\bin%_EXT%\48
+mkdir: %_DEST%\bin%_EXT%\49
+mkdir: %_DEST%\bin%_EXT%\66
+mkdir: %_DEST%\bin%_EXT%\81
+mkdir: %_DEST%\bin%_EXT%\82
+mkdir: %_DEST%\bin%_EXT%\86
+mkdir: %_DEST%\bin%_EXT%\88
+mkdir: %_DEST%\bin%_EXT%\90
+mkdir: %_DEST%\bin%_EXT%\96
+..\%__SRC%\bin\01\soreport.exe %_DEST%\bin%_EXT%\crashrep.exe
+..\%__SRC%\bin\soreport.exe.manifest %_DEST%\bin%_EXT%\crashrep.exe.manifest
+%_DEST%\bin%_EXT%\guistdio.com %_DEST%\bin%_EXT%\crashrep.com
+..\%__SRC%\bin\crash_report* %_DEST%\bin%_EXT%\crash_report*
+..\%__SRC%\bin\pstack %_DEST%\bin%_EXT%\pstack.bin
+..\%__SRC%\bin\crash_dump.res.01 %_DEST%\bin%_EXT%\01\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.03 %_DEST%\bin%_EXT%\03\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.07 %_DEST%\bin%_EXT%\07\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.30 %_DEST%\bin%_EXT%\30\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.31 %_DEST%\bin%_EXT%\31\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.33 %_DEST%\bin%_EXT%\33\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.34 %_DEST%\bin%_EXT%\34\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.39 %_DEST%\bin%_EXT%\39\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.45 %_DEST%\bin%_EXT%\45\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.46 %_DEST%\bin%_EXT%\46\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.48 %_DEST%\bin%_EXT%\48\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.49 %_DEST%\bin%_EXT%\49\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.66 %_DEST%\bin%_EXT%\66\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.81 %_DEST%\bin%_EXT%\81\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.82 %_DEST%\bin%_EXT%\82\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.86 %_DEST%\bin%_EXT%\86\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.88 %_DEST%\bin%_EXT%\88\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.90 %_DEST%\bin%_EXT%\90\crash_dump.res
+..\%__SRC%\bin\crash_dump.res.96 %_DEST%\bin%_EXT%\96\crash_dump.res
+%_DEST%\bin%_EXT%\guistdio.com %_DEST%\bin%_EXT%\crashrep.com
diff --git a/crashrep/source/unx/interface.cxx b/crashrep/source/unx/interface.cxx
new file mode 100755
index 000000000000..9c9cc57cb1bd
--- /dev/null
+++ b/crashrep/source/unx/interface.cxx
@@ -0,0 +1,659 @@
+#include <interface.hxx>
+#include <iostream.h>
+
+using namespace std;
+
+/*
+ * WizardPage
+ */
+WizardPage::~WizardPage()
+{
+}
+
+/*
+ * WizardDialog
+ */
+
+WizardDialog::WizardDialog()
+{
+ m_pStatusDialog = NULL;
+ m_pTopLevel = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+ gtk_window_set_title( GTK_WINDOW(m_pTopLevel), StringResource::get( "%WELCOME_CAPTION%" ) );
+
+ m_pVBox = gtk_vbox_new( FALSE, 5 );
+ gtk_widget_show( m_pVBox );
+ gtk_container_add( GTK_CONTAINER(m_pTopLevel), m_pVBox );
+
+ m_pViewPort = gtk_viewport_new( NULL, NULL );
+ gtk_widget_show( m_pViewPort );
+
+ // set wizard title style
+ gtk_widget_ensure_style( m_pViewPort );
+ GtkStyle* pStyle = gtk_style_copy( gtk_widget_get_style( m_pViewPort ) );
+ for( int i = 0; i < 5; i++ )
+ {
+ pStyle->bg[i] = pStyle->white;
+ pStyle->text[i] = pStyle->black;
+ pStyle->bg_gc[i] = pStyle->white_gc;
+ pStyle->text_gc[i] = pStyle->black_gc;
+ }
+ gint nFontSize = pango_font_description_get_size( pStyle->font_desc );
+ nFontSize = nFontSize * 3 / 2;
+ pango_font_description_set_size( pStyle->font_desc, nFontSize );
+ gtk_widget_set_style( m_pViewPort, pStyle );
+ gtk_viewport_set_shadow_type( GTK_VIEWPORT(m_pViewPort), GTK_SHADOW_NONE );
+ gtk_box_pack_start( GTK_BOX(m_pVBox), m_pViewPort, FALSE, FALSE, 0 );
+
+ m_pWizardTitle = gtk_label_new( "Wizard" ); // to be replaced by resp. page titles
+ gtk_widget_show( m_pWizardTitle );
+ gtk_label_set_justify( GTK_LABEL(m_pWizardTitle), GTK_JUSTIFY_LEFT );
+ gtk_misc_set_alignment( GTK_MISC(m_pWizardTitle), 0, 1 );
+ gtk_misc_set_padding( GTK_MISC(m_pWizardTitle), 10, 10 );
+ gtk_widget_set_style( m_pWizardTitle, pStyle );
+ gtk_container_add( GTK_CONTAINER(m_pViewPort), m_pWizardTitle );
+
+ // prepare the area for the single pages
+ m_pPageArea = gtk_vbox_new( FALSE, 1);
+ gtk_widget_show( m_pPageArea );
+ gtk_box_pack_start( GTK_BOX(m_pVBox), m_pPageArea, TRUE, TRUE, 0 );
+
+ m_pSeparator = gtk_hseparator_new();
+ gtk_widget_show( m_pSeparator );
+ gtk_box_pack_start( GTK_BOX(m_pVBox), m_pSeparator, FALSE, FALSE, 0 );
+
+ m_pButtonBox = gtk_hbutton_box_new();
+ gtk_widget_show( m_pButtonBox );
+ gtk_box_pack_start( GTK_BOX(m_pVBox), m_pButtonBox, FALSE, FALSE, 0 );
+ gtk_button_box_set_layout( GTK_BUTTON_BOX(m_pButtonBox), GTK_BUTTONBOX_END );
+ gtk_button_box_set_spacing( GTK_BUTTON_BOX(m_pButtonBox), 0 );
+
+ m_pBackButton = gtk_button_new_with_mnemonic( StringResource::get( "%BACK_BUTTON%" ) );
+ gtk_widget_show( m_pBackButton );
+ gtk_container_add( GTK_CONTAINER(m_pButtonBox), m_pBackButton );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pBackButton), 5 );
+ GTK_WIDGET_SET_FLAGS( m_pBackButton, GTK_CAN_DEFAULT );
+
+ m_pNextButton = gtk_button_new_with_mnemonic( StringResource::get( "%NEXT_BUTTON%" ) );
+ gtk_widget_show( m_pNextButton );
+ gtk_container_add( GTK_CONTAINER(m_pButtonBox), m_pNextButton );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pNextButton), 5 );
+ GTK_WIDGET_SET_FLAGS( m_pNextButton, GTK_CAN_DEFAULT );
+
+ m_pSendButton = gtk_button_new_with_mnemonic( StringResource::get( "%SEND_BUTTON%" ) );
+ gtk_widget_show( m_pSendButton );
+ gtk_container_add( GTK_CONTAINER(m_pButtonBox), m_pSendButton );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pSendButton), 5 );
+ GTK_WIDGET_SET_FLAGS( m_pSendButton, GTK_CAN_DEFAULT );
+
+ m_pCancelButton = gtk_button_new_with_mnemonic( StringResource::get( "%DONOT_SEND_BUTTON%" ) );
+ gtk_widget_show( m_pCancelButton );
+ gtk_container_add( GTK_CONTAINER(m_pButtonBox), m_pCancelButton );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pCancelButton), 5 );
+ GTK_WIDGET_SET_FLAGS( m_pCancelButton, GTK_CAN_DEFAULT );
+
+ gtk_signal_connect( GTK_OBJECT(m_pTopLevel), "delete-event", G_CALLBACK(gtk_main_quit), NULL );
+ gtk_signal_connect( GTK_OBJECT(m_pCancelButton), "clicked", G_CALLBACK(gtk_main_quit), NULL );
+ gtk_signal_connect( GTK_OBJECT(m_pNextButton), "clicked", G_CALLBACK(button_clicked), this );
+ gtk_signal_connect( GTK_OBJECT(m_pBackButton), "clicked", G_CALLBACK(button_clicked), this );
+ gtk_signal_connect( GTK_OBJECT(m_pSendButton), "clicked", G_CALLBACK(button_clicked), this );
+ gtk_widget_set_sensitive( m_pSendButton, FALSE );
+
+ m_nCurrentPage = -1;
+}
+
+WizardDialog::~WizardDialog()
+{
+ int nPages = m_aPages.size();
+ while( nPages-- )
+ delete m_aPages[nPages];
+}
+
+void WizardDialog::show_messagebox( const std::string& rMessage )
+{
+ GtkWidget* messagebox = NULL;
+ GtkMessageType eType = GTK_MESSAGE_ERROR;
+
+ messagebox = gtk_message_dialog_new( NULL,
+ (GtkDialogFlags)0,
+ eType,
+ GTK_BUTTONS_OK,
+ rMessage.c_str(),
+ NULL
+ );
+
+ gtk_dialog_run( GTK_DIALOG(messagebox) );
+ gtk_widget_destroy( GTK_WIDGET(messagebox) );
+}
+
+
+
+// bInProgress: true=sending, false=finished
+gint WizardDialog::show_sendingstatus( bool bInProgress )
+{
+ m_pStatusDialog = gtk_dialog_new_with_buttons( StringResource::get( "%SENDING_REPORT_HEADER%" ),
+ getTopLevel(),
+ GTK_DIALOG_MODAL,
+ bInProgress ? GTK_STOCK_CANCEL : GTK_STOCK_OK,
+ bInProgress ? GTK_RESPONSE_REJECT : GTK_RESPONSE_OK,
+ NULL );
+
+ gtk_window_set_default_size( GTK_WINDOW(m_pStatusDialog), 350, 130 );
+
+ GtkWidget *pLabel = gtk_label_new( bInProgress ? StringResource::get( "%SENDING_REPORT_STATUS%" ) :
+ StringResource::get( "%SENDING_REPORT_STATUS_FINISHED%" ) );
+ gtk_widget_show( pLabel );
+ gtk_label_set_justify( GTK_LABEL(pLabel), GTK_JUSTIFY_CENTER);
+ gtk_misc_set_alignment( GTK_MISC(pLabel), 0, 0 );
+
+ gtk_container_add( GTK_CONTAINER(GTK_DIALOG(m_pStatusDialog)->vbox), pLabel );
+
+ gint ret = gtk_dialog_run( GTK_DIALOG(m_pStatusDialog) );
+ gtk_widget_destroy( m_pStatusDialog );
+ m_pStatusDialog = NULL;
+
+ return ret;
+}
+
+void WizardDialog::hide_sendingstatus()
+{
+ if( m_pStatusDialog )
+ {
+ gtk_dialog_response( GTK_DIALOG(m_pStatusDialog), GTK_RESPONSE_OK );
+ }
+}
+
+
+gint WizardDialog::button_clicked( GtkWidget* pButton, WizardDialog* pThis )
+{
+ if( pButton == pThis->m_pNextButton )
+ pThis->nextPage();
+ else if( pButton == pThis->m_pBackButton )
+ pThis->lastPage();
+ else if( pButton == pThis->m_pSendButton )
+ {
+ if( pThis->m_nCurrentPage != -1 )
+ pThis->m_aPages[pThis->m_nCurrentPage]->update();
+
+ if( send_crash_report( *pThis, pThis->getSettings() ) )
+ gtk_main_quit();
+ }
+
+ return 0;
+}
+
+void WizardDialog::insertPage( WizardPage* pPage )
+{
+ m_aPages.push_back( pPage );
+ if( m_nCurrentPage == -1 )
+ {
+ m_nCurrentPage = 0;
+ gtk_label_set_text( GTK_LABEL(m_pWizardTitle), pPage->getTitle() );
+ gtk_box_pack_start( GTK_BOX(m_pPageArea), pPage->getContents(), TRUE, TRUE, 0 );
+ gtk_widget_set_sensitive( m_pNextButton, FALSE );
+ gtk_widget_set_sensitive( m_pBackButton, FALSE );
+ }
+ else
+ {
+ gtk_widget_set_sensitive( m_pNextButton, TRUE );
+ }
+}
+
+void WizardDialog::nextPage()
+{
+ if( m_aPages.empty() || m_nCurrentPage >= (int)m_aPages.size()-1 )
+ return;
+
+ m_aPages[m_nCurrentPage]->update();
+
+ gtk_container_remove( GTK_CONTAINER(m_pPageArea), m_aPages[m_nCurrentPage]->getContents() );
+ m_nCurrentPage++;
+ gtk_label_set_text( GTK_LABEL(m_pWizardTitle), m_aPages[m_nCurrentPage]->getTitle() );
+ gtk_box_pack_start( GTK_BOX(m_pPageArea), m_aPages[m_nCurrentPage]->getContents(), TRUE, TRUE, 0 );
+
+ if( m_nCurrentPage == (int)m_aPages.size()-1 )
+ {
+ gtk_widget_set_sensitive( m_pNextButton, FALSE );
+ gtk_widget_set_sensitive( m_pSendButton, TRUE );
+ }
+ if( m_aPages.size() > 1 )
+ gtk_widget_set_sensitive( m_pBackButton, TRUE );
+}
+
+void WizardDialog::lastPage()
+{
+ if( m_aPages.empty() || m_nCurrentPage <= 0 )
+ return;
+
+ m_aPages[m_nCurrentPage]->update();
+
+ gtk_container_remove( GTK_CONTAINER(m_pPageArea), m_aPages[m_nCurrentPage]->getContents() );
+ m_nCurrentPage--;
+ gtk_label_set_text( GTK_LABEL(m_pWizardTitle), m_aPages[m_nCurrentPage]->getTitle() );
+ gtk_box_pack_start( GTK_BOX(m_pPageArea), m_aPages[m_nCurrentPage]->getContents(), TRUE, TRUE, 0 );
+
+ if( m_nCurrentPage == 0 )
+ gtk_widget_set_sensitive( m_pBackButton, FALSE );
+ if( m_aPages.size() > 1 )
+ gtk_widget_set_sensitive( m_pNextButton, TRUE );
+}
+
+void WizardDialog::show( bool bShow )
+{
+ if( bShow )
+ gtk_widget_show( m_pTopLevel );
+ else
+ gtk_widget_hide( m_pTopLevel );
+}
+
+/*
+ * MainPage
+ */
+
+MainPage::MainPage( WizardDialog* pParent ) : WizardPage( pParent )
+{
+ hash_map< string, string >& rSettings = m_pDialog->getSettings();
+ m_aWizardTitle = StringResource::get( "%REPORT_HEADER%" );
+
+ m_pPageContents = gtk_vbox_new( FALSE, 0 );
+ gtk_widget_show( m_pPageContents );
+
+ m_pInfo = gtk_label_new( StringResource::get( "%REPORT_BODY%" ) );
+ gtk_widget_show( m_pInfo );
+ gtk_label_set_line_wrap( GTK_LABEL(m_pInfo), TRUE );
+ gtk_label_set_justify( GTK_LABEL(m_pInfo), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pInfo), 0, 1 );
+ gtk_misc_set_padding( GTK_MISC(m_pInfo ), 5, 5);
+ gtk_box_pack_start( GTK_BOX(m_pPageContents), m_pInfo, FALSE, FALSE, 0 );
+
+ m_pHBox = gtk_hbox_new( FALSE, 0 );
+ gtk_widget_show( m_pHBox );
+ gtk_box_pack_start( GTK_BOX(m_pPageContents), m_pHBox, TRUE, TRUE, 0 );
+
+ m_pLeftColumn = gtk_vbox_new( FALSE, 5 );
+ gtk_widget_show( m_pLeftColumn );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pLeftColumn), 5 );
+ gtk_box_pack_start( GTK_BOX(m_pHBox), m_pLeftColumn, TRUE, TRUE, 0 );
+
+ m_pRightColumn = gtk_vbutton_box_new();
+ gtk_widget_show( m_pRightColumn );
+ gtk_button_box_set_layout( GTK_BUTTON_BOX(m_pRightColumn), GTK_BUTTONBOX_END );
+ gtk_box_pack_start( GTK_BOX(m_pHBox), m_pRightColumn, FALSE, FALSE, 0 );
+
+ m_pEditLabel = gtk_label_new_with_mnemonic( StringResource::get( "%ENTER_TITLE%" ) );
+ gtk_widget_show( m_pEditLabel );
+ gtk_label_set_justify( GTK_LABEL(m_pEditLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pEditLabel), 0, 1 );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pEditLabel, FALSE, FALSE, 0 );
+
+ m_pEdit = gtk_entry_new();
+ gtk_widget_show( m_pEdit );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pEdit, FALSE, FALSE, 0 );
+
+ gtk_label_set_mnemonic_widget( GTK_LABEL(m_pEditLabel), m_pEdit );
+
+ m_pEntryVBox = gtk_vbox_new( FALSE, 5 );
+ gtk_widget_show( m_pEntryVBox );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pEntryVBox, TRUE, TRUE, 0 );
+
+ m_pEntryLabel = gtk_label_new_with_mnemonic( StringResource::get( "%ENTER_DESCRIPTION%" ) );
+ gtk_widget_show( m_pEntryLabel );
+ gtk_label_set_justify( GTK_LABEL(m_pEntryLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pEntryLabel), 0, 1 );
+ gtk_box_pack_start( GTK_BOX(m_pEntryVBox), m_pEntryLabel, FALSE, FALSE, 0 );
+
+ m_pScrolledEntry = gtk_scrolled_window_new( NULL, NULL );
+ gtk_widget_show( m_pScrolledEntry );
+ gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(m_pScrolledEntry), GTK_SHADOW_IN );
+ gtk_box_pack_start( GTK_BOX(m_pEntryVBox), m_pScrolledEntry, TRUE, TRUE, 0 );
+
+ m_pEntry = gtk_text_view_new();
+ gtk_widget_show( m_pEntry );
+ gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(m_pEntry), GTK_WRAP_WORD );
+ gtk_container_add( GTK_CONTAINER(m_pScrolledEntry), m_pEntry );
+
+ gtk_label_set_mnemonic_widget( GTK_LABEL(m_pEntryLabel), m_pEntry );
+
+ m_pDetails = gtk_button_new_with_mnemonic( StringResource::get( "%SHOW_REPORT_BUTTON%" ) );
+ gtk_widget_show(m_pDetails);
+ gtk_container_set_border_width( GTK_CONTAINER(m_pDetails), 5 );
+ gtk_container_add( GTK_CONTAINER(m_pRightColumn), m_pDetails );
+
+ m_pOptions = gtk_button_new_with_mnemonic( StringResource::get( "%OPTIONS_BUTTON%" ) );
+ gtk_widget_show(m_pOptions);
+ gtk_container_set_border_width( GTK_CONTAINER(m_pOptions), 5 );
+ gtk_container_add( GTK_CONTAINER(m_pRightColumn), m_pOptions );
+
+ // check env var for save button
+ const char *szUserType = getenv( "STAROFFICE_USERTYPE" );
+ if( szUserType && *szUserType )
+ {
+ m_pSave = gtk_button_new_with_mnemonic( StringResource::get( "%SAVE_REPORT_BUTTON%" ) );
+ gtk_widget_show(m_pSave);
+ gtk_container_set_border_width( GTK_CONTAINER(m_pSave), 5 );
+ gtk_container_add( GTK_CONTAINER(m_pRightColumn), m_pSave );
+ }
+ else
+ m_pSave = NULL;
+
+
+ m_pCheck = gtk_check_button_new_with_mnemonic( StringResource::get( "%ALLOW_CONTACT%" ) );
+ gtk_widget_show( m_pCheck );
+ gtk_container_set_border_width( GTK_CONTAINER(m_pCheck), 5 );
+ //gtk_box_pack_start( GTK_BOX(m_pPageContents), m_pCheck, FALSE, FALSE, 5 );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pCheck, FALSE, FALSE, 5 );
+
+ hash_map<string, string>::iterator aIter;
+ aIter = rSettings.find( "CONTACT" );
+ if( aIter != rSettings.end() )
+ {
+ const char *str = aIter->second.c_str();
+ if( str && !strcasecmp(str, "true") )
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(m_pCheck), TRUE );
+ }
+
+ m_pAddressLabel = gtk_label_new_with_mnemonic( StringResource::get( "%ENTER_EMAIL%" ) );
+ gtk_widget_show( m_pAddressLabel );
+ gtk_label_set_justify( GTK_LABEL(m_pAddressLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pAddressLabel), 0, 1 );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pAddressLabel, FALSE, FALSE, 5 );
+
+ m_pAddress = gtk_entry_new();
+ gtk_widget_show( m_pAddress );
+ gtk_box_pack_start( GTK_BOX(m_pLeftColumn), m_pAddress, FALSE, FALSE, 5 );
+
+ aIter = rSettings.find( "EMAIL" );
+ if( aIter != rSettings.end() )
+ gtk_entry_set_text( GTK_ENTRY(m_pAddress), aIter->second.c_str() );
+
+ gtk_signal_connect( GTK_OBJECT(m_pDetails), "clicked", G_CALLBACK(button_clicked), this );
+ gtk_signal_connect( GTK_OBJECT(m_pOptions), "clicked", G_CALLBACK(button_clicked), this );
+ if(m_pSave) // optional
+ gtk_signal_connect( GTK_OBJECT(m_pSave), "clicked", G_CALLBACK(button_clicked), this );
+
+ gtk_signal_connect( GTK_OBJECT(m_pCheck), "toggled", G_CALLBACK(button_toggled), this );
+ button_toggled( m_pCheck, this );
+
+ g_object_ref( G_OBJECT(m_pPageContents) );
+}
+
+MainPage::~MainPage()
+{
+ g_object_unref( G_OBJECT(m_pPageContents) );
+}
+
+void MainPage::update()
+{
+ hash_map< string, string >& rSettings = m_pDialog->getSettings();
+
+ GtkTextIter start, end;
+ GtkTextBuffer* pTextBuffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(m_pEntry) );
+ gtk_text_buffer_get_bounds( pTextBuffer, &start, &end );
+ rSettings[ "DESCRIPTION" ] = gtk_text_buffer_get_text( pTextBuffer, &start, &end, 1 );
+ rSettings[ "TITLE" ] = gtk_entry_get_text( GTK_ENTRY(m_pEdit) );
+ rSettings[ "CONTACT" ] = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(m_pCheck) ) ? "true" : "false";
+ rSettings[ "EMAIL" ] = gtk_entry_get_text( GTK_ENTRY(m_pAddress) );
+}
+
+gint MainPage::button_toggled( GtkWidget* pButton, MainPage* pThis )
+{
+ if ( GTK_TOGGLE_BUTTON (pThis->m_pCheck)->active )
+ {
+ gtk_widget_set_sensitive( pThis->m_pAddressLabel, TRUE);
+ gtk_widget_set_sensitive( pThis->m_pAddress, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive( pThis->m_pAddressLabel, FALSE);
+ gtk_widget_set_sensitive( pThis->m_pAddress, FALSE);
+ }
+ return 0;
+}
+
+gint MainPage::button_clicked( GtkWidget* pButton, MainPage* pThis )
+{
+ if( pButton == pThis->m_pSave )
+ {
+ GtkWidget* pFile = gtk_file_selection_new( StringResource::get( "%SAVE_REPORT_TITLE%" ) );
+ gint nRet = gtk_dialog_run( GTK_DIALOG(pFile) );
+ if( nRet == GTK_RESPONSE_OK )
+ {
+ string aFile = gtk_file_selection_get_filename( GTK_FILE_SELECTION(pFile) );
+ pThis->update();
+ if( save_crash_report( aFile, pThis->m_pDialog->getSettings() ) )
+ {
+ // gtk_main_quit();
+ }
+ }
+ gtk_widget_destroy( pFile );
+ }
+ else if( pButton == pThis->m_pDetails )
+ {
+ pThis->update();
+
+ GtkWidget* pDialog = gtk_dialog_new_with_buttons( StringResource::get( "%REPORT_CAPTION%" ),
+ pThis->m_pDialog->getTopLevel(),
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_OK,
+ GTK_RESPONSE_OK,
+ NULL );
+
+ gtk_window_set_default_size( GTK_WINDOW(pDialog), 500, 300 );
+ GtkWidget* pScroll = gtk_scrolled_window_new( NULL, NULL );
+ gtk_widget_show( pScroll );
+ gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(pScroll), GTK_SHADOW_IN );
+ gtk_container_add( GTK_CONTAINER(GTK_DIALOG(pDialog)->vbox), pScroll );
+
+ string aText = crash_get_details( pThis->m_pDialog->getSettings() );
+ GtkWidget* pView = gtk_text_view_new();
+ gtk_widget_show( pView );
+ gtk_text_view_set_wrap_mode( GTK_TEXT_VIEW(pView), GTK_WRAP_WORD );
+ gtk_text_view_set_editable( GTK_TEXT_VIEW(pView), FALSE );
+ GtkTextBuffer* pBuffer = gtk_text_view_get_buffer( GTK_TEXT_VIEW(pView) );
+ gtk_text_buffer_set_text( pBuffer, aText.data(), aText.size() );
+ gtk_container_add( GTK_CONTAINER(pScroll), pView );
+
+ gtk_dialog_run( GTK_DIALOG(pDialog) );
+ gtk_widget_destroy( pDialog );
+ }
+ else if( pButton == pThis->m_pOptions )
+ {
+ OptionsDialog aOptions( pThis->m_pDialog->getTopLevel(), pThis->m_pDialog->getSettings() );
+ //pThis->m_pDialog->show_sendingstatus( true );
+ //pThis->m_pDialog->show_sendingstatus( false );
+ //sleep(5);
+ //pThis->m_pDialog->hide_sendingstatus();
+ }
+
+ return 0;
+}
+
+/*
+ * OptionsDialog (Proxy-Settings)
+ */
+
+OptionsDialog::OptionsDialog( GtkWindow *pParent ,hash_map< string, string >& rSettings )
+{
+ m_pDialog = gtk_dialog_new_with_buttons( StringResource::get( "%OPTIONS_TITLE%" ),
+ pParent,
+ GTK_DIALOG_MODAL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
+ NULL );
+
+ gtk_window_set_default_size( GTK_WINDOW(m_pDialog), 500, 300 );
+
+ m_pPage = gtk_vbox_new( FALSE, 0 );
+ m_pLeftColumn = gtk_vbox_new( FALSE, 5 );
+
+ gtk_widget_show( m_pPage );
+ gtk_widget_show( m_pLeftColumn );
+
+ gtk_container_add( GTK_CONTAINER(GTK_DIALOG(m_pDialog)->vbox), m_pPage );
+
+ gtk_container_set_border_width( GTK_CONTAINER(m_pLeftColumn), 5 );
+ gtk_box_pack_start( GTK_BOX(m_pPage), m_pLeftColumn, FALSE, FALSE, 5 );
+
+ // frame for proxy settings
+ m_pFrame = gtk_frame_new(StringResource::get( "%PROXY_SETTINGS_HEADER%" ));
+ gtk_frame_set_shadow_type( GTK_FRAME(m_pFrame), GTK_SHADOW_ETCHED_IN );
+ gtk_widget_show(m_pFrame);
+ gtk_box_pack_start(GTK_BOX (m_pLeftColumn), m_pFrame, TRUE, TRUE, 0);
+
+ m_pVBox = gtk_vbox_new( FALSE, 0 );
+ gtk_widget_show( m_pVBox );
+ gtk_container_add( GTK_CONTAINER( m_pFrame ), m_pVBox );
+
+ // the radio buttons
+ m_pDirect = gtk_radio_button_new_with_mnemonic( NULL,
+ StringResource::get( "%PROXY_SETTINGS_DIRECT%" ) );
+ gtk_widget_show(m_pDirect);
+ gtk_box_pack_start(GTK_BOX (m_pVBox), m_pDirect, FALSE, FALSE, 0);
+
+ m_pManual = gtk_radio_button_new_with_mnemonic( gtk_radio_button_group( GTK_RADIO_BUTTON(m_pDirect) ),
+ StringResource::get( "%PROXY_SETTINGS_MANUAL%" ) );
+ gtk_widget_show(m_pManual);
+ gtk_box_pack_start(GTK_BOX (m_pVBox), m_pManual, FALSE, FALSE, 0);
+
+ hash_map<string, string>::iterator aIter;
+ const char *str = NULL;
+ aIter = rSettings.find( "USEPROXY" );
+ if( aIter != rSettings.end() )
+ str = aIter->second.c_str();
+ if( str && !strcasecmp(str, "true") )
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(m_pManual), TRUE );
+ else
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(m_pDirect), TRUE );
+
+ // the server and port edit controls
+ m_pHBox = gtk_hbox_new( FALSE, 0 );
+ gtk_widget_show( m_pHBox );
+ gtk_box_pack_start(GTK_BOX (m_pVBox), m_pHBox, FALSE, FALSE, 10);
+
+ m_pVBoxServer = gtk_vbox_new( FALSE, 5 );
+ gtk_widget_show( m_pVBoxServer );
+ gtk_box_pack_start(GTK_BOX (m_pHBox), m_pVBoxServer, TRUE, TRUE, 10);
+
+ m_pVBoxPort = gtk_vbox_new( FALSE, 5 );
+ gtk_widget_show( m_pVBoxPort );
+ gtk_box_pack_start(GTK_BOX (m_pHBox), m_pVBoxPort, FALSE, FALSE, 10);
+
+ m_pServerLabel = gtk_label_new_with_mnemonic( StringResource::get( "%PROXY_SETTINGS_ADDRESS%" ) );
+ gtk_widget_show( m_pServerLabel );
+ gtk_label_set_justify( GTK_LABEL(m_pServerLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pServerLabel), 0, 1 );
+ gtk_box_pack_start( GTK_BOX(m_pVBoxServer), m_pServerLabel, FALSE, FALSE, 0 );
+
+ m_pServer = gtk_entry_new();
+ gtk_widget_show( m_pServer );
+ gtk_box_pack_start( GTK_BOX(m_pVBoxServer), m_pServer, FALSE, FALSE, 0 );
+ gtk_label_set_mnemonic_widget( GTK_LABEL(m_pServerLabel), m_pServer );
+ aIter = rSettings.find( "SERVER" );
+ if( aIter != rSettings.end() )
+ gtk_entry_set_text( GTK_ENTRY(m_pServer), aIter->second.c_str() );
+
+ m_pPortLabel = gtk_label_new_with_mnemonic( StringResource::get( "%PROXY_SETTINGS_PORT%" ) );
+ gtk_widget_show( m_pPortLabel );
+ gtk_label_set_justify( GTK_LABEL(m_pPortLabel), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pPortLabel), 0, 1 );
+ gtk_box_pack_start( GTK_BOX(m_pVBoxPort), m_pPortLabel, FALSE, FALSE, 0 );
+
+ m_pPort = gtk_entry_new();
+ gtk_widget_show( m_pPort );
+ gtk_box_pack_start( GTK_BOX(m_pVBoxPort), m_pPort, FALSE, FALSE, 0 );
+ gtk_label_set_mnemonic_widget( GTK_LABEL(m_pPortLabel), m_pPort );
+ aIter = rSettings.find( "PORT" );
+ if( aIter != rSettings.end() )
+ gtk_entry_set_text( GTK_ENTRY(m_pPort), aIter->second.c_str() );
+
+ // help text
+ m_pNote = gtk_label_new( StringResource::get( "%PROXY_SETTINGS_DESCRIPTION%" ) );
+ gtk_widget_show( m_pNote );
+ gtk_label_set_justify( GTK_LABEL(m_pNote), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pNote), 0, 1 );
+ gtk_box_pack_start(GTK_BOX (m_pLeftColumn), m_pNote, FALSE, FALSE, 5);
+ gtk_label_set_line_wrap (GTK_LABEL (m_pNote), TRUE);
+
+
+ gtk_signal_connect( GTK_OBJECT(m_pDirect), "toggled", G_CALLBACK(button_toggled), this );
+ gtk_signal_connect( GTK_OBJECT(m_pManual), "toggled", G_CALLBACK(button_toggled), this );
+
+ button_toggled( m_pDirect, this );
+
+ if( gtk_dialog_run( GTK_DIALOG(m_pDialog) ) == GTK_RESPONSE_OK )
+ {
+ rSettings[ "SERVER" ] = getServer();
+ rSettings[ "PORT" ] = getPort();
+ rSettings[ "USEPROXY" ] = getUseProxy();
+ }
+ g_object_ref( G_OBJECT(m_pDialog) );
+}
+
+OptionsDialog::~OptionsDialog()
+{
+ gtk_widget_destroy( m_pDialog );
+ g_object_unref( G_OBJECT(m_pDialog) );
+}
+
+gint OptionsDialog::button_toggled( GtkWidget* pButton, OptionsDialog* pThis )
+{
+ if ( GTK_TOGGLE_BUTTON (pThis->m_pManual)->active )
+ {
+ gtk_widget_set_sensitive( pThis->m_pServerLabel, TRUE);
+ gtk_widget_set_sensitive( pThis->m_pServer, TRUE);
+ gtk_widget_set_sensitive( pThis->m_pPortLabel, TRUE);
+ gtk_widget_set_sensitive( pThis->m_pPort, TRUE);
+ }
+ else
+ {
+ gtk_widget_set_sensitive( pThis->m_pServerLabel, FALSE);
+ gtk_widget_set_sensitive( pThis->m_pServer, FALSE);
+ gtk_widget_set_sensitive( pThis->m_pPortLabel, FALSE);
+ gtk_widget_set_sensitive( pThis->m_pPort, FALSE);
+ }
+
+ return 0;
+}
+
+string OptionsDialog::getUseProxy()
+{
+ return gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(m_pDirect) ) ? "false" : "true";
+}
+string OptionsDialog::getServer()
+{
+ return gtk_entry_get_text( GTK_ENTRY(m_pServer) );
+}
+string OptionsDialog::getPort()
+{
+ return gtk_entry_get_text( GTK_ENTRY(m_pPort) );
+}
+
+/*
+ * WelcomePage
+ */
+WelcomePage::WelcomePage( WizardDialog* pParent ) : WizardPage( pParent )
+{
+ m_aWizardTitle = StringResource::get( "%WELCOME_HEADER%" );
+
+ string aBody = StringResource::get( "%WELCOME_BODY1%" );
+ aBody += StringResource::get( "%WELCOME_BODY2%" );
+ aBody += StringResource::get( "%WELCOME_BODY3%" );
+ aBody += "\n\n";
+ aBody += StringResource::get( "%PRIVACY_URL%" );
+ m_pPageContents = gtk_label_new( aBody.c_str() );
+ gtk_widget_show( m_pPageContents );
+ gtk_label_set_line_wrap( GTK_LABEL(m_pPageContents), TRUE );
+ gtk_label_set_justify( GTK_LABEL(m_pPageContents), GTK_JUSTIFY_LEFT);
+ gtk_misc_set_alignment( GTK_MISC(m_pPageContents), 0, 1 );
+ gtk_misc_set_padding( GTK_MISC(m_pPageContents ), 5, 5);
+
+ g_object_ref( G_OBJECT(m_pPageContents) );
+}
+
+WelcomePage::~WelcomePage()
+{
+ g_object_unref( G_OBJECT(m_pPageContents) );
+}
+
+void WelcomePage::update()
+{
+}
diff --git a/crashrep/source/unx/interface.hxx b/crashrep/source/unx/interface.hxx
new file mode 100755
index 000000000000..e48eab3c30fa
--- /dev/null
+++ b/crashrep/source/unx/interface.hxx
@@ -0,0 +1,158 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+
+#include <hash_map>
+#include <vector>
+#include <string>
+
+class WizardDialog;
+
+// returns success, on true application will quit
+bool save_crash_report( const std::string& rFileName, const std::hash_map< std::string, std::string >& rSettings );
+// returns success, on true application will quit
+bool send_crash_report( WizardDialog &rDialog, const std::hash_map< std::string, std::string >& rSettings );
+// must return a valid UTF8 string containing the message that will be sent
+std::string crash_get_details( const std::hash_map< std::string, std::string >& rSettings );
+
+class StringResource
+{
+public:
+ static void init( int argc, char** argv );
+ static const char* get( const char* pKey );
+};
+
+class WizardPage
+{
+protected:
+ std::string m_aWizardTitle;
+ GtkWidget* m_pPageContents;
+ WizardDialog* m_pDialog;
+public:
+ WizardPage( WizardDialog* pDialog ) : m_pDialog( pDialog ) {}
+ virtual ~WizardPage();
+
+ const char* getTitle() const { return m_aWizardTitle.c_str(); }
+ GtkWidget* getContents() const { return m_pPageContents; }
+
+ virtual void update() = 0;
+};
+
+class WizardDialog
+{
+ std::vector< WizardPage* > m_aPages;
+ int m_nCurrentPage;
+
+ GtkWidget* m_pTopLevel;
+ GtkWidget* m_pVBox;
+ GtkWidget* m_pViewPort;
+ GtkWidget* m_pWizardTitle;
+ GtkWidget* m_pPageArea;
+ GtkWidget* m_pSeparator;
+ GtkWidget* m_pButtonBox;
+ GtkWidget* m_pBackButton;
+ GtkWidget* m_pNextButton;
+ GtkWidget* m_pSendButton;
+ GtkWidget* m_pCancelButton;
+
+ GtkWidget* m_pStatusDialog;
+
+ std::hash_map< std::string, std::string > m_aSettings;
+
+ static gint button_clicked( GtkWidget* pButton, WizardDialog* pThis );
+
+ void nextPage();
+ void lastPage();
+public:
+ WizardDialog();
+ ~WizardDialog();
+
+ // takes ownership of page
+ void insertPage( WizardPage* pPage );
+
+ void show( bool bShow = true );
+ void show_messagebox( const std::string& rMessage );
+ gint show_sendingstatus( bool bInProgress );
+ void hide_sendingstatus();
+
+ std::hash_map< std::string, std::string >& getSettings() { return m_aSettings; }
+ GtkWindow* getTopLevel() const { return GTK_WINDOW(m_pTopLevel); }
+};
+
+class MainPage : public WizardPage
+{
+ GtkWidget* m_pInfo;
+ GtkWidget* m_pEditLabel;
+ GtkWidget* m_pEdit;
+ GtkWidget* m_pEntryLabel;
+ GtkWidget* m_pEntryVBox;
+ GtkWidget* m_pScrolledEntry;
+ GtkWidget* m_pEntry;
+ GtkWidget* m_pHBox;
+ GtkWidget* m_pRightColumn;
+ GtkWidget* m_pLeftColumn;
+ GtkWidget* m_pDetails;
+ GtkWidget* m_pSave;
+ GtkWidget* m_pCheck;
+ GtkWidget* m_pOptions;
+ GtkWidget* m_pAddressLabel;
+ GtkWidget* m_pAddress;
+
+ static gint button_clicked( GtkWidget* pButton, MainPage* pThis );
+ static gint button_toggled( GtkWidget* pButton, MainPage* pThis );
+
+public:
+ MainPage( WizardDialog* );
+ virtual ~MainPage();
+
+ virtual void update();
+};
+
+class WelcomePage : public WizardPage
+{
+public:
+ WelcomePage( WizardDialog* );
+ virtual ~WelcomePage();
+
+ virtual void update();
+};
+
+class OptionsDialog
+{
+ GtkWidget* m_pDialog;
+ GtkWidget* m_pPage;
+ GtkWidget* m_pLeftColumn;
+ GtkWidget* m_pFrame;
+ GtkWidget* m_pDirect;
+ GtkWidget* m_pManual;
+ GtkWidget* m_pServerLabel;
+ GtkWidget* m_pServer;
+ GtkWidget* m_pColon;
+ GtkWidget* m_pPortLabel;
+ GtkWidget* m_pPort;
+ GtkWidget* m_pNote;
+ GtkWidget* m_pOkButton;
+ GtkWidget* m_pCancelButton;
+ GtkWidget* m_pButtonBox;
+ GtkWidget* m_pVBox;
+ GtkWidget* m_pHBox;
+ GtkWidget* m_pVBoxServer;
+ GtkWidget* m_pVBoxPort;
+
+ static gint button_toggled( GtkWidget* pButton, OptionsDialog* pThis );
+
+public:
+ OptionsDialog( GtkWindow* pParent,
+ std::hash_map< std::string, std::string >& rSettings );
+ virtual ~OptionsDialog();
+
+ std::string getUseProxy();
+ std::string getServer();
+ std::string getPort();
+
+};
diff --git a/crashrep/source/unx/main.cxx b/crashrep/source/unx/main.cxx
new file mode 100755
index 000000000000..b5d6da33b3ec
--- /dev/null
+++ b/crashrep/source/unx/main.cxx
@@ -0,0 +1,1103 @@
+/*************************************************************************
+ *
+ * $RCSfile: main.cxx,v $
+ *
+ * $Revision: 1.1 $
+ *
+ * last change: $Author: hro $ $Date: 2003-06-06 11:21:57 $
+ *
+ * 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): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <interface.hxx>
+#include <cstdio>
+#include <sys/utsname.h>
+#include <_version.h>
+#include <errno.h>
+#include <string>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/socket.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <pthread.h>
+
+#ifdef LINUX
+#include <netinet/in.h>
+#endif
+
+typedef int SOCKET;
+
+#define closesocket close
+#define SOCKET_ERROR -1
+
+#ifdef SOLARIS
+const char *basename( const char *filename )
+{
+ const char *pSlash = strrchr( filename, '/' );
+
+ return pSlash ? pSlash + 1 : pSlash;
+}
+#endif
+
+using namespace std;
+
+static g_bDebugMode = false;
+static int g_signal = 0;
+
+static string g_strReportServer;
+static unsigned short g_uReportPort = 80;
+static string g_buildid;
+static string g_strDefaultLanguage;
+static string g_strXMLFileName;
+static string g_strPStackFileName;
+static string g_strProgramDir;
+
+static char g_szStackFile[L_tmpnam] = "";
+static char g_szDescriptionFile[2048] = "";
+static char g_szReportFile[2048] = "";
+
+#define SO_CRASHREPORT_MAIL "so-report@sun.com"
+#define PSTACK_CMD "pstack %d"
+#define PSTACKBIN_CMD "pstack.bin %d"
+
+#ifdef LINUX
+#define PMAP_CMD "cat /proc/%d/maps"
+#else
+#define PMAP_CMD "pmap %d"
+#endif
+
+#define REPORT_SERVER (g_strReportServer.c_str())
+#define REPORT_PORT g_uReportPort
+
+static string getprogramdir()
+{
+ return g_strProgramDir;
+}
+
+static const char *getlocale()
+{
+ const char * locale = getenv( "LC_ALL" );
+
+ if( NULL == locale )
+ locale = getenv( "LC_CTYPE" );
+
+ if( NULL == locale )
+ locale = getenv( "LANG" );
+
+ if( NULL == locale )
+ locale = "C";
+
+ return locale;
+}
+
+static const char *get_user_name()
+{
+ struct passwd *ppwd = getpwuid( getuid() );
+
+ return ppwd ? (ppwd->pw_name ? ppwd->pw_name : "") : "";
+}
+
+static const char *get_home_dir()
+{
+ struct passwd *ppwd = getpwuid( getuid() );
+
+ return ppwd ? (ppwd->pw_dir ? ppwd->pw_dir : "/") : "/";
+}
+
+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 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 *fpout, FILE *fpin )
+{
+ char buffer[1024];
+ size_t nBytes;
+ size_t nBytesWritten = 0;
+
+ while ( 0 != (nBytes = fread( buffer, 1, sizeof(buffer), fpin )) )
+ {
+ nBytesWritten += fwrite( buffer, 1, nBytes, fpout );
+ }
+
+ return nBytesWritten;
+}
+
+/*
+ writes the report to a temp-file
+ from which it can be reviewed and sent
+*/
+bool write_stack( long pid )
+{
+ bool bSuccess = false;
+
+ if ( pid )
+ {
+ char *stmp= tmpnam( g_szStackFile );
+ FILE *fout, *fin;
+ char buf[1024];
+
+ /* open mailfile */
+ fout = fopen(stmp, "w");
+
+ if ( fout )
+ {
+ char cmdbuf[1024];
+
+ fputs( "<***stacks***>\n", fout );
+
+ if ( !g_strPStackFileName.length() )
+ {
+
+ snprintf(cmdbuf, 1024, PSTACK_CMD, pid);
+ fin = popen(cmdbuf, "r");
+
+ if ( fin )
+ {
+ while (fgets(buf, 1024, fin) != NULL)
+ {
+ bSuccess = true;
+ fputs(buf, fout);
+ }
+ pclose( fin );
+
+ }
+
+ if ( !bSuccess )
+ {
+ snprintf(cmdbuf, 1024, PSTACKBIN_CMD, pid);
+ fin = popen(cmdbuf, "r");
+
+ if ( fin )
+ {
+ while (fgets(buf, 1024, fin) != NULL)
+ {
+ bSuccess = true;
+ fputs(buf, fout);
+ }
+ pclose( fin );
+
+ }
+ }
+
+ }
+ else
+ {
+ fin = fopen( g_strPStackFileName.c_str(), "r" );
+ if ( fin )
+ {
+ bSuccess = true;
+ fcopy( fout, fin );
+ fclose( fin );
+ }
+ }
+
+ fputs( "</***stacks***>\n", fout );
+
+ if ( bSuccess )
+ {
+ fputs( "<***maps***>\n", fout );
+ bSuccess = false;
+
+ snprintf(cmdbuf, 1024, PMAP_CMD, pid);
+ fin = popen(cmdbuf, "r");
+
+ if ( fin )
+ {
+ while (fgets(buf, 1024, fin) != NULL)
+ {
+ bSuccess = true;
+ fputs(buf, fout);
+ }
+ pclose( fin );
+
+ }
+ fputs( "</***maps***>\n", fout );
+ }
+
+ fclose ( fout );
+
+ }
+ }
+
+
+ return bSuccess;
+}
+
+
+bool write_report( const hash_map< string, string >& rSettings )
+{
+ FILE *fp = fopen( tmpnam( g_szReportFile ), "w" );
+ const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
+ const char *pszProductName = getenv( "PRODUCTNAME" );
+
+ 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\" uid=\"%s\" usertype=\"%s\">\n"
+ "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.0\" feedback=\"%s\" email=\"%s\">\n"
+ "<reportmail:title>%s</reportmail:title>\n"
+ "<reportmail:attachment name=\"description.txt\" media-type=\"text/plain\" class=\"UserComment\"/>\n"
+ "<reportmail:attachment name=\"stack.txt\" media-type=\"text/plain\" class=\"pstack output\"/>\n"
+ "</reportmail:mail>\n"
+ "<officeinfo:officeinfo xmlns:officeinfo=\"http://openoffice.org/2002/officeinfo\" build=\"%s\" platform=\"%s\" language=\"%s\" exceptiontype=\"%d\" product=\"%s\" procpath=\"%s\"/>\n"
+ ,
+ get_user_name(),
+ pszUserType ? pszUserType : "",
+ xml_encode(rSettings.find( "CONTACT" )->second).c_str(),
+ xml_encode(rSettings.find( "EMAIL" )->second).c_str(),
+ xml_encode(rSettings.find( "TITLE" )->second).c_str(),
+ g_buildid.length() ? g_buildid.c_str() : "unknown",
+ _INPATH,
+ g_strDefaultLanguage.c_str(),
+ g_signal,
+ pszProductName ? pszProductName : "unknown",
+ getprogramdir().c_str()
+ );
+
+ struct utsname info;
+
+ memset( &info, 0, sizeof(info) );
+ uname( &info );
+
+ fprintf( fp,
+ "<systeminfo:systeminfo xmlns:systeminfo=\"http://openoffice.org/2002/systeminfo\">\n"
+ "<systeminfo:System name=\"%s\" version=\"%s\" build=\"%s\" locale=\"%s\"/>\n"
+ ,
+ info.sysname,
+ info.version,
+ info.release,
+ getlocale()
+ );
+ fprintf( fp, "<systeminfo:CPU type=\"%s\"/>\n", info.machine );
+ fprintf( fp, "</systeminfo:systeminfo>\n" );
+
+ FILE *fpxml = fopen( g_strXMLFileName.c_str(), "r" );
+ if ( fpxml )
+ {
+ fcopy( fp, fpxml );
+ fclose( fpxml );
+ }
+ fprintf( fp, "</errormail:errormail>\n" );
+
+ fclose( fp );
+
+ return true;
+}
+
+
+bool write_description( const hash_map< string, string >& rSettings )
+{
+ bool bSuccess = false;
+ FILE *fp = fopen( tmpnam( g_szDescriptionFile ), "w" );
+
+ if ( fp )
+ {
+ bSuccess = true;
+ fprintf( fp, "\xEF\xBB\xBF" );
+ fprintf( fp, "%s\n", rSettings.find( "DESCRIPTION" )->second.c_str() );
+ fclose( fp );
+ }
+
+ return bSuccess;
+}
+
+
+static void printSettings( const hash_map<string,string>& rSettings )
+{
+ printf( "Settings:\n" );
+ for( hash_map<string,string>::const_iterator it = rSettings.begin(); it != rSettings.end(); ++it )
+ {
+ printf( "%s=\"%s\"\n", it->first.c_str(), it->second.c_str() );
+ }
+}
+
+bool save_crash_report( const string& rFileName, const hash_map< string, string >& rSettings )
+{
+ bool bSuccess = false;
+ FILE *fpout = fopen( rFileName.c_str(), "w" );
+
+ if ( fpout )
+ {
+ FILE *fpin = fopen( g_szStackFile, "r" );
+
+ if ( fpin )
+ {
+ char buf[1024];
+
+ while (fgets(buf, sizeof(buf), fpin) != NULL)
+ {
+ fputs(buf, fpout);
+ }
+
+ bSuccess = true;
+
+ fclose ( fpin );
+ }
+
+ fclose( fpout );
+ }
+
+ 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 ( g_bDebugMode )
+ {
+ printf( "*** Sending HTTP request ***\n\n" );
+ printf( buffer );
+ }
+
+ if ( SOCKET_ERROR != send( s, buffer, strlen(buffer), 0 ) )
+ {
+ size_t nBytes;
+
+ do
+ {
+ nBytes = fread( buffer, 1, sizeof(buffer), fp );
+
+ if ( nBytes )
+ {
+ if ( g_bDebugMode )
+ fwrite( buffer, 1, nBytes, stdout );
+ success = SOCKET_ERROR != send( s, buffer, nBytes, 0 );
+ }
+ } while( nBytes && success );
+
+ if ( success )
+ {
+ if ( g_bDebugMode )
+ printf( "*** Receiving HTTP response ***\n\n" );
+
+ 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;
+ }
+ if ( g_bDebugMode )
+ do
+ {
+ printf( buffer );
+ memset( buffer, 0, sizeof(buffer) );
+ } while ( 0 < recv( s, buffer, sizeof(buffer), 0 ) );
+ }
+ }
+
+ }
+
+ 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_szReportFile, "r" );
+ if ( fpin )
+ {
+ fprintf( fp,
+ "<item>\n"
+ "<key xsi:type=\"xsd:string\">reportmail.xml</key>\n"
+ "<value xsi:type=\"xsd:string\"><![CDATA[" );
+ fcopy( fp, fpin );
+ fprintf( fp, "]]></value></item>\n" );
+ fclose( fpin );
+ }
+
+ fpin = fopen( g_szDescriptionFile, "r" );
+ if ( fpin )
+ {
+ fprintf( fp,
+ "<item>\n"
+ "<key xsi:type=\"xsd:string\">description.txt</key>\n"
+ "<value xsi:type=\"xsd:string\"><![CDATA[" );
+ fcopy( fp, fpin );
+ fprintf( fp, "]]></value></item>\n" );
+ fclose( fpin );
+ };
+
+ fpin = fopen( g_szStackFile, "r" );
+ if ( fpin )
+ {
+ fprintf( fp,
+ "<item>\n"
+ "<key xsi:type=\"xsd:string\">description.txt</key>\n"
+ "<value xsi:type=\"xsd:string\"><![CDATA[" );
+ fcopy( fp, fpin );
+ fprintf( fp, "]]></value></item>\n" );
+ 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 *pServer;
+ unsigned short uPort;
+ const char *pProxyServer;
+ unsigned short uProxyPort;
+ WizardDialog *pDialog;
+};
+
+extern "C" void *http_send_thread( void *arg )
+{
+ RequestParams *request = (RequestParams *)arg;
+
+ int oldtype;
+
+ /* Killing me hardly ;-) */
+ pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype );
+
+ request->success = SendHTTPRequest(
+ request->fpin,
+ request->pServer,
+ request->uPort,
+ request->pProxyServer,
+ request->uProxyPort
+ );
+
+ request->pDialog->hide_sendingstatus();
+
+ return 0;
+}
+
+bool SendAsyncHTTPRequest(
+ WizardDialog &rDialog,
+ FILE *fp,
+ const char *pszServer,
+ unsigned short uPort = 80,
+ const char *pszProxyServer = NULL,
+ unsigned short uProxyPort = 8080 )
+{
+ RequestParams request;
+
+ request.success = false;
+ request.pDialog = &rDialog;
+ request.fpin = fp;
+ request.pServer = pszServer;
+ request.uPort = uPort;
+ request.pProxyServer = pszProxyServer;
+ request.uProxyPort = uProxyPort;
+
+ pthread_t thread = 0;
+
+ if (
+ 0 == pthread_create (
+ &thread,
+ NULL,
+ http_send_thread,
+ (void*)&request )
+ )
+ {
+ gint response = rDialog.show_sendingstatus( TRUE );
+
+ pthread_cancel( thread );
+
+ void *thread_result = NULL;
+
+ pthread_join( thread, &thread_result );
+ }
+
+ return request.success;
+}
+
+bool send_crash_report( WizardDialog &rDialog, const hash_map< string, string >& rSettings )
+{
+ if ( 0 == strcasecmp( rSettings.find( "CONTACT" )->second.c_str(), "true" ) &&
+ !trim_string(rSettings.find( "EMAIL" )->second).length() )
+ {
+ rDialog.show_messagebox( StringResource::get( "%ERROR_MSG_NOEMAILADDRESS%" ) );
+ return false;
+ }
+
+ char *endptr = NULL;
+
+ const char *pProxyServer = rSettings.find( "SERVER" )->second.c_str();
+ unsigned short uProxyPort = (unsigned short)strtoul( rSettings.find( "PORT" )->second.c_str(), &endptr, 10 );
+
+ bool bUseProxy = !strcasecmp( "true", rSettings.find( "USEPROXY" )->second.c_str() );
+
+
+ write_description( rSettings );
+ write_report( rSettings );
+
+ bool bSuccess = false;
+
+ FILE *fptemp = tmpfile();
+ if ( fptemp )
+ {
+ WriteSOAPRequest( fptemp );
+ fseek( fptemp, 0, SEEK_SET );
+
+ /*
+ bSuccess = SendHTTPRequest(
+ fptemp,
+ REPORT_SERVER, REPORT_PORT,
+ bUseProxy ? pProxyServer : NULL,
+ uProxyPort ? uProxyPort : 8080
+ );
+ */
+
+ bSuccess = SendAsyncHTTPRequest(
+ rDialog,
+ fptemp,
+ REPORT_SERVER, REPORT_PORT,
+ bUseProxy ? pProxyServer : NULL,
+ uProxyPort ? uProxyPort : 8080
+ );
+
+ fclose( fptemp );
+
+ if ( bSuccess )
+ rDialog.show_sendingstatus( FALSE );
+ else
+ rDialog.show_messagebox( StringResource::get( "%ERROR_MSG_PROXY%" ) );
+ }
+ else
+ rDialog.show_messagebox( "%ERROR_MSG_DISK_FULL%" );
+
+ unlink( g_szDescriptionFile );
+ unlink( g_szReportFile );
+
+ return bSuccess;
+}
+
+
+static bool append_file( const char *filename, string& rString )
+{
+ char buf[1024];
+ bool bSuccess = false;
+
+ FILE *fp = fopen( filename, "r" );
+ if ( fp )
+ {
+ bSuccess = true;
+ while (fgets(buf, sizeof(buf), fp) != NULL)
+ {
+ rString.append( buf );
+ }
+ fclose( fp );
+ }
+
+ return true;
+}
+
+string crash_get_details( const hash_map< string, string >& rSettings )
+{
+ string aRet;
+
+ FILE *fp;
+ char buf[1024];
+
+ write_description( rSettings );
+ write_report( rSettings );
+
+ aRet.append( rSettings.find( "TITLE" )->second.c_str() );
+ aRet.append( "\n\n" );
+ append_file( g_szDescriptionFile, aRet );
+ aRet.append( "\n\n-------\n\n" );
+ append_file( g_szReportFile, aRet );
+ aRet.append( "\n\n-------\n\n" );
+ append_file( g_szStackFile, aRet );
+
+ unlink( g_szDescriptionFile );
+ unlink( g_szReportFile );
+
+ return aRet;
+}
+
+
+// ensure validity of program relative paths
+static void setup_program_dir( const char* progname )
+{
+ string aDir = progname;
+ size_t pos = aDir.rfind( '/' );
+ // FIXME: search PATH if necessary
+ assert( pos != string::npos );
+ g_strProgramDir = aDir.substr( 0, pos + 1 );
+ aDir.erase( pos );
+ chdir( aDir.c_str() );
+}
+
+//*************************************************************************
+
+static long setup_commandline_arguments( int argc, char** argv, int *pSignal )
+{
+ long pid = 0;
+ int signal = 0;
+
+ for ( int n = 1; n < argc; n++ )
+ {
+ if ( 0 == strcmp( argv[n], "-p" ) )
+ {
+ if ( ++n < argc )
+ pid = strtol( argv[n], NULL, 0 );
+ }
+ else if ( 0 == strcmp( argv[n], "-s" ) )
+ {
+ if ( ++n < argc )
+ signal = strtol( argv[n], NULL, 0 );
+ }
+ else if ( 0 == strcmp( argv[n], "-debug" ) )
+ {
+ g_bDebugMode = true;
+ }
+ else if ( 0 == strcmp( argv[n], "-xml" ) )
+ {
+ if ( ++n < argc )
+ g_strXMLFileName = argv[n];
+ }
+ else if ( 0 == strcmp( argv[n], "-stack" ) )
+ {
+ if ( ++n < argc )
+ g_strPStackFileName = argv[n];
+ }
+ else if ( argv[n] && strlen(argv[n]) )
+ {
+ printf(
+ "\n%s crash_report %s\n\n" \
+ "/?, -h[elp] %s\n\n" \
+ "%-20s %s\n\n",
+ StringResource::get( "%MSG_CMDLINE_USAGE%" ),
+ StringResource::get( "%MSG_PARAM_PROCESSID%" ),
+ StringResource::get( "%MSG_PARAM_HELP_DESCRIPTION%" ),
+ StringResource::get( "%MSG_PARAM_PROCESSID%" ),
+ StringResource::get( "%MSG_PARAM_PROCESSID_DESCRIPTION%" )
+ );
+ break;
+ }
+ }
+
+ *pSignal = signal;
+
+ return pid;
+}
+
+//*************************************************************************
+
+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, "r" );
+ 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 == strcasecmp( keyname.c_str(), pKeyName ) )
+ {
+ retValue = value;
+ break;
+ }
+ }
+ }
+
+ fclose( fp );
+ }
+
+ return retValue;
+}
+
+static string get_profile_string( const char *pFileName, const char *pSectionName, const char *pKeyName, const char *pDefault = NULL )
+{
+ FILE *fp = fopen( pFileName, "r" );
+ string retValue = pDefault ? pDefault : "";
+
+ if ( fp )
+ {
+ string line;
+ string section;
+
+ while ( read_line( fp, line ) )
+ {
+ line = trim_string( line );
+
+ if ( line.length() && line[0] == '[' )
+ {
+ line.erase( 0, 1 );
+ string::size_type end = line.find( ']', 0 );
+
+ if ( string::npos != end )
+ section = trim_string( line.substr( 0, end ) );
+ }
+ else
+ {
+
+ 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 (
+ 0 == strcasecmp( section.c_str(), pSectionName ) &&
+ 0 == strcasecmp( keyname.c_str(), pKeyName )
+ )
+ {
+ retValue = value;
+ break;
+ }
+ }
+ }
+ }
+
+ fclose( fp );
+ }
+
+ return retValue;
+}
+
+#define RCFILE ".crash_reportrc"
+
+static bool write_settings( const hash_map< string, string >& rSettings )
+{
+ bool success = false;
+ string sRCFile = get_home_dir();
+
+ sRCFile += "/";
+ sRCFile += string(RCFILE);
+
+ FILE *fp = fopen( sRCFile.c_str(), "w" );
+
+ if ( fp )
+ {
+ fprintf( fp, "[Options]\n" );
+ fprintf( fp, "UseProxy=%s\n", rSettings.find( "USEPROXY" )->second.c_str() );
+ fprintf( fp, "ProxyServer=%s\n", rSettings.find( "SERVER" )->second.c_str() );
+ fprintf( fp, "ProxyPort=%s\n", rSettings.find( "PORT" )->second.c_str() );
+ fprintf( fp, "ReturnAddress=%s\n", rSettings.find( "EMAIL" )->second.c_str() );
+ fprintf( fp, "AllowContact=%s\n", rSettings.find( "CONTACT" )->second.c_str() );
+ fclose( fp );
+ }
+
+ return success;
+}
+
+static void read_settings( hash_map< string, string >& rSettings )
+{
+ string sRCFile = get_home_dir();
+
+ sRCFile += "/";
+ sRCFile += string(RCFILE);
+
+ rSettings[ "EMAIL" ] = get_profile_string( sRCFile.c_str(), "Options", "ReturnAddress" );
+ rSettings[ "SERVER" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyServer" );
+ rSettings[ "PORT" ] = get_profile_string( sRCFile.c_str(), "Options", "ProxyPort" );
+ rSettings[ "USEPROXY" ] = get_profile_string( sRCFile.c_str(), "Options", "UseProxy" );
+ rSettings[ "CONTACT" ] = get_profile_string( sRCFile.c_str(), "Options", "AllowContact" );
+}
+
+static bool setup_version()
+{
+ if ( !getenv( "PRODUCTNAME" ) )
+ {
+ string productkey = get_profile_string( "bootstraprc", "Bootstrap", "ProductKey" );
+
+ if ( productkey.length() )
+ {
+ static string productname;
+ static string productversion;
+ string::size_type iSpace = productkey.find( ' ', 0 );
+
+ if ( string::npos != iSpace )
+ {
+ productname = productkey.substr( 0, iSpace );
+ productversion = productkey.substr( iSpace + 1, -1 );
+ }
+ else
+ productname = productkey;
+
+ productname.insert( 0, "PRODUCTNAME=" );
+ putenv( (char *)productname.c_str() );
+
+ productversion.insert( 0, "PRODUCTVERSION=" );
+ putenv( (char *)productversion.c_str() );
+ }
+ }
+
+ g_buildid = get_profile_string( "bootstraprc", "Bootstrap", "BuildId" );
+ g_strDefaultLanguage = get_script_string( "instdb.ins", "DefaultLanguage" );
+
+ g_strReportServer = get_profile_string( "bootstraprc", "ErrorReport", "Server" );
+
+ string strReportPort = get_profile_string( "bootstraprc", "ErrorReport", "Port", "80" );
+ char *endptr = NULL;
+ unsigned short uReportPort = (unsigned short)strtoul( strReportPort.c_str(), &endptr, 10 );
+ g_uReportPort = uReportPort ? uReportPort : 80;
+
+ return 0 != g_strReportServer.length();
+}
+
+int main( int argc, char** argv )
+{
+ freopen( "/dev/null", "w", stderr );
+
+ if ( setup_version() )
+ {
+ gtk_set_locale ();
+ gtk_init (&argc, &argv);
+
+ StringResource::init( argc, argv );
+
+ setup_program_dir( argv[0] );
+
+ long pid = setup_commandline_arguments( argc, argv, &g_signal );
+
+ if ( write_stack( pid ) )
+ {
+ WizardDialog aDialog;
+
+ hash_map< string, string >& rDialogSettings = aDialog.getSettings();
+
+ read_settings( rDialogSettings );
+
+ aDialog.insertPage( new WelcomePage( &aDialog ) );
+ aDialog.insertPage( new MainPage( &aDialog ) );
+
+ aDialog.show();
+
+ gtk_main();
+
+ write_settings( rDialogSettings );
+
+ unlink( g_szStackFile );
+
+ return 0;
+ }
+ }
+
+ return -1;
+}
diff --git a/crashrep/source/unx/makefile.mk b/crashrep/source/unx/makefile.mk
new file mode 100755
index 000000000000..46f9fbc81b23
--- /dev/null
+++ b/crashrep/source/unx/makefile.mk
@@ -0,0 +1,101 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1 $
+#
+# last change: $Author: hro $ $Date: 2003-06-06 11:21:58 $
+#
+# 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): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=crashrep
+TARGET=crash_report.bin
+TARGETTYPE=CUI
+
+ENABLE_EXCEPTIONS=TRUE
+LIBTARGET=NO
+LIBSALCPPRT=$(0)
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+# ------------------------------------------------------------------
+
+CFLAGS+=`pkg-config --cflags gtk+-2.0`
+
+OBJFILES=\
+ $(OBJ)$/interface.obj \
+ $(OBJ)$/res.obj \
+ $(OBJ)$/main.obj
+
+APP1NOSAL=TRUE
+APP1TARGET=$(TARGET)
+APP1OBJS=$(OBJFILES)
+.IF "$(COM)" == "GCC"
+APP1STDLIBS=-Wl,-Bstatic `pkg-config --only-mod-libs --libs gtk+-2.0` -lpng -lzlib -ljpeg -ltiff -Wl,-Bdynamic -lXext -lX11 -ldl -lnsl
+.ELSE
+APP1STDLIBS=-Bstatic `pkg-config --only-mod-libs --libs gtk+-2.0` -lpng -lzlib -ljpeg -ltiff -Bdynamic -lXext -lX11 -ldl -lsocket -lnsl
+.ENDIF
+
+ALL: ALLTAR $(BIN)$/crash_dump.res.01
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+$(BIN)$/crash_dump.res.01: ..$/all$/crashrep.lng
+ $(BIN)$/unxcrashres ..$/all$/crashrep.lng $(BIN)$/crash_dump.res
diff --git a/crashrep/source/unx/res.cxx b/crashrep/source/unx/res.cxx
new file mode 100755
index 000000000000..e72a01ac4268
--- /dev/null
+++ b/crashrep/source/unx/res.cxx
@@ -0,0 +1,108 @@
+#if OSL_DEBUG_LEVEL == 0
+#define NDEBUG
+#endif
+#include <assert.h>
+
+#include <interface.hxx>
+#include <cstdio>
+#include <hash_map>
+#include <string>
+
+using namespace std;
+
+static hash_map< string, string >* pStringResources = NULL;
+
+static string getResFileName( const char* progname )
+{
+ string aRet = progname;
+ size_t pos = aRet.rfind( '/' );
+ // FIXME: search PATH if necessary
+ assert( pos != string::npos );
+ aRet.erase( pos );
+ aRet.append( "/resource/crash_dump.res" );
+
+ return aRet;
+}
+
+static void filterString( string& rString )
+{
+ static const char* pProductName = getenv( "PRODUCTNAME" );
+ static int nProductLen = pProductName ? strlen( pProductName ) : 0;
+ static const char* pProductVersion = getenv( "PRODUCTVERSION" );
+ static int nVersionLen = pProductVersion ? strlen( pProductVersion ) : 0;
+
+ // fill in eventually escaped characters
+ string::size_type pos = 0;
+ while( (pos = rString.find( '\\' ) ) != string::npos )
+ {
+ char cRep = 0;
+ switch( rString[pos+1] )
+ {
+ case 't': cRep = '\t';break;
+ case 'n': cRep = '\n';break;
+ case 'r': cRep = '\r';break;
+ case 'f': cRep = '\f';break;
+ default: cRep = rString[pos+1];
+ }
+ if( cRep )
+ rString.replace( pos, 2, &cRep, 1 );
+ }
+ while( (pos = rString.find( '~' ) ) != string::npos )
+ {
+ // replace mnemonic marker
+ rString.replace( pos, 1, "_", 1 );
+ }
+ while( (pos = rString.find( "%PRODUCTNAME%" ) ) != string::npos )
+ {
+ rString.replace( pos, 13, pProductName ? pProductName : "OpenOffice" );
+ }
+ while( (pos = rString.find( "%PRODUCTVERSION%" ) ) != string::npos )
+ {
+ rString.replace( pos, 16, pProductVersion ? pProductVersion : "" );
+ }
+ // remove whitespace at end
+ pos = rString.find_last_not_of( "\r\n\t\f " );
+ if( pos != string::npos )
+ rString.erase( pos+1 );
+}
+
+void StringResource::init( int argc, char** argv )
+{
+ pStringResources = new hash_map< string, string >();
+
+ string aResFile = getResFileName( argv[0] );
+
+ FILE* fp = fopen( aResFile.c_str(), "r" );
+ if( fp )
+ {
+ char buf[4096];
+ string aKey;
+ string aValue;
+ while( ! feof( fp ) )
+ {
+ if( ! fgets( buf, sizeof(buf), fp ) )
+ break;
+
+ char* pEq = strchr( buf, '=' );
+ if( ! pEq || *(pEq+1) == 0 ) // invalid line
+ continue;
+ aKey = string(buf, pEq-buf);
+ aValue = pEq+1;
+ while( (aValue.empty() || aValue[ aValue.size()-1 ] != '\n') && ! feof( fp ) )
+ {
+ if( fgets( buf, sizeof( buf ), fp ) )
+ aValue.append( buf );
+ }
+ filterString( aValue );
+ (*pStringResources)[aKey] = aValue;
+ }
+ fclose( fp );
+ }
+}
+
+const char* StringResource::get( const char* pKey )
+{
+ hash_map< string, string >::const_iterator it = pStringResources->find( pKey );
+ return (it == pStringResources->end()) ? "" : it->second.c_str();
+}
+
diff --git a/crashrep/source/unx/res/makefile.mk b/crashrep/source/unx/res/makefile.mk
new file mode 100755
index 000000000000..a787267156e0
--- /dev/null
+++ b/crashrep/source/unx/res/makefile.mk
@@ -0,0 +1,22 @@
+PRJ=..$/..$/..
+
+PRJNAME=crashrep
+TARGET=unxcrashres
+LIBTARGET=NO
+TARGETTYPE=CUI
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+
+# --- Files --------------------------------------------------------
+
+APP1TARGET=$(TARGET)
+APP1OBJS=$(OBJ)$/unxcrashres.obj
+APP1STDLIBS=$(TOOLSLIB) $(SALLIB)
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
diff --git a/crashrep/source/unx/res/unxcrashres.cxx b/crashrep/source/unx/res/unxcrashres.cxx
new file mode 100755
index 000000000000..8e722bfbdfd6
--- /dev/null
+++ b/crashrep/source/unx/res/unxcrashres.cxx
@@ -0,0 +1,80 @@
+#include <tools/config.hxx>
+#include <rtl/string.hxx>
+#include <osl/thread.h>
+#include <tools/l2txtenc.hxx>
+
+#include <hash_map>
+#include <string>
+#include <cstdio>
+#include <cerrno>
+
+using namespace std;
+using namespace rtl;
+
+void filterValue( ByteString& rValue, const OString& rGroup, const ByteString& rKey )
+{
+ USHORT nStartPos = rValue.Search( '"' );
+ USHORT nStopPos = rValue.SearchBackward( '"' );
+ if( nStartPos == STRING_NOTFOUND || nStopPos == STRING_NOTFOUND )
+ {
+ fprintf( stderr, "Error: invalid key in [%s] in key \"%s\"\n",
+ rGroup.getStr(),
+ rKey.GetBuffer() );
+ exit( 1 );
+ }
+ rValue.Erase( nStopPos );
+ rValue.Erase( 0, nStartPos+1 );
+}
+
+int main( int argc, char** argv )
+{
+ if( argc != 3 )
+ {
+ fprintf( stderr, "USAGE: unxcrashres <in_lng_file> <out_file_prefix>\n" );
+ exit( 1 );
+ }
+
+ ByteString tmp_argv1( argv[1] );
+ Config aConfig( String( tmp_argv1, osl_getThreadTextEncoding() ) );
+ hash_map< int, hash_map< OString, OString, OStringHash > > aFiles;
+
+ for( USHORT i = 0; i < aConfig.GetGroupCount(); i++ )
+ {
+ aConfig.SetGroup( aConfig.GetGroupName( i ) );
+ OString aGroup = aConfig.GetGroupName( i );
+ USHORT nKeys = aConfig.GetKeyCount();
+ for( USHORT n = 0; n < nKeys; n++ )
+ {
+ ByteString aKey = aConfig.GetKeyName( n );
+ ByteString aValue = aConfig.ReadKey( aKey );
+ int nRes = aKey.ToInt32();
+ // tailor key
+ filterValue( aValue, aGroup, aKey );
+
+ aFiles[nRes][aGroup] = ByteString( String( aValue, Langcode2TextEncoding( (USHORT)nRes ) ), RTL_TEXTENCODING_UTF8 );
+ }
+ }
+
+ for( hash_map< int, hash_map< OString, OString, OStringHash > >::const_iterator lang_it = aFiles.begin(); lang_it != aFiles.end(); ++lang_it )
+ {
+ ByteString aFile( argv[2] );
+ aFile.Append( '.' );
+ if( lang_it->first < 10 )
+ aFile.Append( '0' );
+ aFile.Append( ByteString::CreateFromInt32( lang_it->first ) );
+ FILE* fp = fopen( aFile.GetBuffer(), "w" );
+ if( ! fp )
+ {
+ fprintf( stderr, "Error: could not open \"%s\" for writing: %s\n",
+ aFile.GetBuffer(), strerror( errno ) );
+ exit(1);
+ }
+ for( hash_map< OString, OString, OStringHash >::const_iterator line_it = lang_it->second.begin(); line_it != lang_it->second.end(); ++line_it )
+ {
+ fprintf( fp, "%s=%s\n", line_it->first.getStr(), line_it->second.getStr() );
+ }
+ fclose( fp );
+ }
+
+ return 0;
+}
diff --git a/crashrep/source/win32/base64.cpp b/crashrep/source/win32/base64.cpp
new file mode 100755
index 000000000000..c707df380b8a
--- /dev/null
+++ b/crashrep/source/win32/base64.cpp
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <string.h>
+#include "base64.h"
+
+static const char base64_tab[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+extern "C" size_t base64_encode( FILE *fin, FILE *fout )
+{
+ size_t nBytesRead = 0;
+ size_t nLineLength = 0;
+ size_t nBytesWritten = 0;
+
+ size_t nBytes = 0;
+
+ do
+ {
+ unsigned char in_buffer[3];
+
+ memset( in_buffer, 0, sizeof(in_buffer) );
+ nBytes = fread( in_buffer, 1, sizeof(in_buffer), fin );
+ nBytesRead += nBytes;
+
+ if ( nBytes )
+ {
+ unsigned long value =
+ ((unsigned long)in_buffer[0]) << 16 |
+ ((unsigned long)in_buffer[1]) << 8 |
+ ((unsigned long)in_buffer[2]) << 0;
+
+ unsigned char out_buffer[4];
+
+ memset( out_buffer, '=', sizeof(out_buffer) );
+
+ out_buffer[0] = base64_tab[(value >> 18) & 0x3F];
+ out_buffer[1] = base64_tab[(value >> 12) & 0x3F];
+
+ if ( nBytes > 1 )
+ {
+ out_buffer[2] = base64_tab[(value >> 6) & 0x3F];
+ if ( nBytes > 2 )
+ out_buffer[3] = base64_tab[(value >> 0) & 0x3F];
+ }
+
+ if ( nLineLength >= 76 )
+ {
+ fputs( "\n", fout );
+ nLineLength = 0;
+ }
+
+ nBytesWritten += fwrite( out_buffer, 1, sizeof(out_buffer), fout );
+ nLineLength += sizeof(out_buffer);
+ }
+ } while ( nBytes );
+
+ return nBytesWritten;
+}
diff --git a/crashrep/source/win32/base64.h b/crashrep/source/win32/base64.h
new file mode 100755
index 000000000000..39dd1f88b1b3
--- /dev/null
+++ b/crashrep/source/win32/base64.h
@@ -0,0 +1,19 @@
+#ifndef __BASE64_H
+#define __BASE64_H
+
+#ifndef _INC_STDIO
+#include <stdio.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+size_t base64_encode( FILE *fin, FILE *fout );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BASE64_H */
+
diff --git a/crashrep/source/win32/ctrylnglist.txt b/crashrep/source/win32/ctrylnglist.txt
new file mode 100755
index 000000000000..91f633cef761
--- /dev/null
+++ b/crashrep/source/win32/ctrylnglist.txt
@@ -0,0 +1,29 @@
+1 LANG_ENGLISH SUBLANG_ENGLISH_US
+3 LANG_PORTUGUESE SUBLANG_PORTUGUESE
+4 LANG_GERMAN SUBLANG_GERMAN
+7 LANG_RUSSIAN SUBLANG_NEUTRAL
+30 LANG_GREEK SUBLANG_NEUTRAL
+31 LANG_DUTCH SUBLANG_DUTCH
+33 LANG_FRENCH SUBLANG_FRENCH
+34 LANG_SPANISH SUBLANG_SPANISH
+35 LANG_FINNISH SUBLANG_NEUTRAL
+36 LANG_HUNGARIAN SUBLANG_NEUTRAL
+39 LANG_ITALIAN SUBLANG_ITALIAN
+42 LANG_CZECH SUBLANG_NEUTRAL
+43 LANG_SLOVAK SUBLANG_NEUTRAL
+44 LANG_ENGLISH SUBLANG_ENGLISH_UK
+45 LANG_DANISH SUBLANG_NEUTRAL
+46 LANG_SWEDISH SUBLANG_SWEDISH
+47 LANG_NORWEGIAN SUBLANG_NORWEGIAN_BOKMAL
+48 LANG_POLISH SUBLANG_NEUTRAL
+49 LANG_GERMAN SUBLANG_NEUTRAL
+55 LANG_PORTUGUESE SUBLANG_PORTUGUESE_BRAZILIAN
+81 LANG_JAPANESE SUBLANG_NEUTRAL
+82 LANG_KOREAN SUBLANG_KOREAN
+86 LANG_CHINESE SUBLANG_CHINESE_SIMPLIFIED
+88 LANG_CHINESE SUBLANG_CHINESE_TRADITIONAL
+90 LANG_TURKISH SUBLANG_NEUTRAL
+96 LANG_ARABIC SUBLANG_NEUTRAL
+97 LANG_HEBREW SUBLANG_NEUTRAL
+37 LANG_CATALAN SUBLANG_NEUTRAL
+66 LANG_THAI SUBLANG_NEUTRAL
diff --git a/crashrep/source/win32/makefile.mk b/crashrep/source/win32/makefile.mk
new file mode 100755
index 000000000000..c18aef4c450d
--- /dev/null
+++ b/crashrep/source/win32/makefile.mk
@@ -0,0 +1,117 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1 $
+#
+# last change: $Author: hro $ $Date: 2003-06-06 11:22:04 $
+#
+# 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): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=crashrep
+TARGET=soreport
+LIBTARGET=NO
+ENABLE_EXCEPTIONS=TRUE
+TARGETTYPE=GUI
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Resources ----------------------------------------------------
+
+RCFILES=$(TARGET).rc
+
+# --- Files --------------------------------------------------------
+
+OBJFILES=\
+ $(OBJ)$/soreport.obj\
+ $(OBJ)$/mapi.obj\
+ $(OBJ)$/base64.obj
+
+LNGFILES=..$/all$/crashrep.lng
+
+APP1OBJS=$(OBJFILES)
+
+APP1NOSAL=TRUE
+
+APP1TARGET=$(TARGET)
+
+STDLIB1=\
+ gdi32.lib\
+ comctl32.lib\
+ comdlg32.lib\
+ advapi32.lib\
+ wsock32.lib\
+ dbghelp.lib
+
+APP1NOSVRES=$(RES)$/$(TARGET).res
+
+ALLTAR: $(BIN)$/$(TARGET).exe.manifest
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
+
+# Generate the native Windows resource file
+# using lngconvex.exe
+
+$(RCFILES) : $(LNGFILES) makefile.mk rcfooter.txt rcheader.txt rctemplate.txt ctrylnglist.txt
+ +lngconvex.exe -lng ..\all\crashrep.lng -rc $(TARGET).rc -c ctrylnglist.txt -rct rctemplate.txt -rch rcheader.txt -rcf rcfooter.txt
+
+$(BIN)$/$(TARGET).exe.manifest: soreport.manifest
+ +$(COPY) $< $@
diff --git a/crashrep/source/win32/rcfooter.txt b/crashrep/source/win32/rcfooter.txt
new file mode 100755
index 000000000000..43c268ca97d4
--- /dev/null
+++ b/crashrep/source/win32/rcfooter.txt
@@ -0,0 +1 @@
+// Footer \ No newline at end of file
diff --git a/crashrep/source/win32/rcheader.txt b/crashrep/source/win32/rcheader.txt
new file mode 100755
index 000000000000..fcd71a15c1f3
--- /dev/null
+++ b/crashrep/source/win32/rcheader.txt
@@ -0,0 +1,4 @@
+// Header
+#include "resource.h"
+#include "winres.h"
+
diff --git a/crashrep/source/win32/rctemplate.txt b/crashrep/source/win32/rctemplate.txt
new file mode 100755
index 000000000000..a0572063dc70
--- /dev/null
+++ b/crashrep/source/win32/rctemplate.txt
@@ -0,0 +1,168 @@
+LANGUAGE %LANGUAGE% , %SUBLANGUAGE%
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_WELCOME_PAGE DIALOGEX 0, 41, 327, 195
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ CONTROL "",IDC_RICHEDIT21,"RICHEDIT20W",TCS_RAGGEDRIGHT | ES_READONLY |
+ TCS_MULTISELECT | WS_VSCROLL,7,7,313,151
+END
+
+IDD_REPORT_PAGE DIALOGEX 0, 41, 327, 195
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x0
+BEGIN
+ LTEXT "1",IDC_REPORT_INTRO,7,7,313,48
+ LTEXT "2",IDC_ENTER_TITLE,7,58,233,8
+ EDITTEXT IDC_EDIT_TITLE,7,68,235,14,ES_AUTOHSCROLL
+ LTEXT "3",IDC_ENTER_DESCRIPTION,7,86,316,8
+ EDITTEXT IDC_EDIT_DESCRIPTION,7,97,235,49,ES_MULTILINE |
+ ES_WANTRETURN | WS_VSCROLL
+ CONTROL "4",IDC_ALLOW_CONTACT,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,7,148,303,10
+ LTEXT "4a",IDC_LABEL_EMAIL,18,162,226,
+ 8
+ EDITTEXT IDC_EDIT_EMAIL,17,173,224,14,ES_AUTOHSCROLL
+ PUSHBUTTON "5",IDC_SHOW_REPORT,249,94,74,14
+ PUSHBUTTON "6",IDC_OPTIONS,249,116,74,14
+ PUSHBUTTON "7",IDC_SAVE_REPORT,249,138,74,14
+END
+
+IDD_DIALOG_FRAME DIALOGEX 0, 0, 331, 265
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND |
+ DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "1"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ LTEXT "",IDC_STATIC,0,0,331,40
+ CONTROL "",IDC_HEADER,"RICHEDIT20W",TCS_VERTICAL | TCS_MULTISELECT | ES_READONLY,
+ 7,7,316,33
+ PUSHBUTTON "1",IDBACK,155,244,50,14
+ PUSHBUTTON "2",IDNEXT,214,244,50,14
+ PUSHBUTTON "3",IDFINISH,214,244,50,14
+ PUSHBUTTON "4",IDCANCEL,273,244,50,14
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,40,331,1
+ CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ,0,237,331,1
+END
+
+IDD_PREVIEW_FRAME DIALOGEX 0, 0, 251, 185
+STYLE DS_SETFONT | DS_MODALFRAME | DS_SETFOREGROUND |
+ DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU |
+ WS_SIZEBOX
+CAPTION "1"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ CONTROL "",IDC_EDIT_PREVIEW,"RICHEDIT20W",ES_MULTILINE |
+ ES_AUTOVSCROLL | WS_VSCROLL | ES_AUTOHSCROLL | WS_HSCROLL |
+ TCS_MULTISELECT | ES_READONLY | TCS_RAGGEDRIGHT |
+ WS_BORDER
+ ,
+ 7,7,237,150
+ DEFPUSHBUTTON "4",IDOK,193,164,50,14
+END
+
+
+IDD_OPTIONS_FRAME DIALOGEX 0, 0, 295, 182
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
+CAPTION "1"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ GROUPBOX "1",IDC_PROXY_SETTINGS,7,7,222,92
+ CONTROL "2",IDC_RADIO_SYSTEM,"Button",BS_AUTORADIOBUTTON,15,27,
+ 208,10
+ CONTROL "3",IDC_RADIO_DIRECT,"Button",BS_AUTORADIOBUTTON,15,39,
+ 208,10
+ CONTROL "4",IDC_RADIO_MANUAL,"Button",BS_AUTORADIOBUTTON,15,51,
+ 208,10
+ LTEXT "5",IDC_LABEL_PROXYSERVER,27,64,148,8
+ EDITTEXT IDC_EDIT_PROXYSERVER,27,76,148,14,ES_AUTOHSCROLL
+ LTEXT ":",IDC_STATIC,178,78,8,8
+ LTEXT "6",IDC_LABEL_PROXYPORT,184,64,40,8
+ EDITTEXT IDC_EDIT_PROXYPORT,184,76,40,14,ES_AUTOHSCROLL |
+ ES_NUMBER
+ DEFPUSHBUTTON "7",IDOK,238,7,50,14
+ PUSHBUTTON "8",IDCANCEL,238,26,50,14
+ CONTROL "",IDC_PROXY_DESCRIPTION,"RichEdit20W",ES_MULTILINE |
+ ES_READONLY | WS_VSCROLL,7,106,281,69
+END
+
+IDD_SENDING_STATUS DIALOGEX 0, 0, 216, 73
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
+CAPTION "1"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+ PUSHBUTTON "2",IDCANCEL,159,52,50,14
+ LTEXT "3",IDC_SENDING_REPORT_STATUS,7,7,202,34
+END
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE
+BEGIN
+ IDS_WELCOME_CAPTION %WELCOME_CAPTION%
+ IDS_WELCOME_HEADER %WELCOME_HEADER%
+ IDS_WELCOME_BODY1 %WELCOME_BODY1%
+ IDS_WELCOME_BODY2 %WELCOME_BODY2%
+ IDS_WELCOME_BODY3 %WELCOME_BODY3%
+ IDS_PRIVACY_URL %PRIVACY_URL%
+ IDS_NEXT_BUTTON %NEXT_BUTTON%
+ IDS_CANCEL_BUTTON %CANCEL_BUTTON%
+ IDS_OK_BUTTON %OK_BUTTON%
+END
+
+STRINGTABLE
+BEGIN
+ IDS_REPORT_CAPTION %REPORT_CAPTION%
+ IDS_REPORT_HEADER %REPORT_HEADER%
+ IDS_REPORT_INTRO %REPORT_BODY%
+ IDS_ENTER_TITLE %ENTER_TITLE%
+ IDS_ALLOW_CONTACT %ALLOW_CONTACT%
+ IDS_ENTER_DESCRIPTION %ENTER_DESCRIPTION%
+ IDS_BACK_BUTTON %BACK_BUTTON%
+ IDS_SEND_BUTTON %SEND_BUTTON%
+ IDS_DONOT_SEND_BUTTON %DONOT_SEND_BUTTON%
+ IDS_SHOW_REPORT_BUTTON %SHOW_REPORT_BUTTON%
+ IDS_SAVE_REPORT_BUTTON %SAVE_REPORT_BUTTON%
+ IDS_OPTIONS_BUTTON %OPTIONS_BUTTON%
+ IDS_LABEL_EMAIL %ENTER_EMAIL%
+END
+
+STRINGTABLE
+BEGIN
+ IDS_ERROR_MSG_SIMPLE_MAPI %ERROR_MSG_SIMPLE_MAPI%
+ IDS_ERROR_MSG_DISK_FULL %ERROR_MSG_DISK_FULL%
+ IDS_ERROR_MSG_PROXY %ERROR_MSG_PROXY%
+ IDS_ERROR_MSG_NOCONNECT %ERROR_MSG_NOCONNECT%
+ IDS_ERROR_MSG_NOEMAILADDRESS %ERROR_MSG_NOEMAILADDRESS%
+ IDS_SENDING_REPORT_HEADER %SENDING_REPORT_HEADER%
+ IDS_SENDING_REPORT_STATUS %SENDING_REPORT_STATUS%
+ IDS_SENDING_REPORT_STATUS_FINISHED %SENDING_REPORT_STATUS_FINISHED%
+ IDS_MSG_CMDLINE_USAGE %MSG_CMDLINE_USAGE%
+ IDS_MSG_PARAM_PROCESSID %MSG_PARAM_PROCESSID%
+ IDS_MSG_PARAM_PROCESSID_DESCRIPTION %MSG_PARAM_PROCESSID_DESCRIPTION%
+ IDS_MSG_PARAM_HELP_DESCRIPTION %MSG_PARAM_HELP_DESCRIPTION%
+END
+
+STRINGTABLE
+BEGIN
+ IDS_OPTIONS_CAPTION %OPTIONS_TITLE%
+ IDS_PROXY_SETTINGS_HEADER %PROXY_SETTINGS_HEADER%
+ IDS_PROXY_SYSTEM %PROXY_SETTINGS_SYSTEM%
+ IDS_PROXY_DIRECT %PROXY_SETTINGS_DIRECT%
+ IDS_PROXY_MANUAL %PROXY_SETTINGS_MANUAL%
+ IDS_LABEL_PROXYSERVER %PROXY_SETTINGS_ADDRESS%
+ IDS_LABEL_PROXYPORT %PROXY_SETTINGS_PORT%
+ IDS_PROXY_DESCRIPTION %PROXY_SETTINGS_DESCRIPTION%
+END
diff --git a/crashrep/source/win32/resource.h b/crashrep/source/win32/resource.h
new file mode 100755
index 000000000000..b4f70a695715
--- /dev/null
+++ b/crashrep/source/win32/resource.h
@@ -0,0 +1,94 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by soreport.rc
+//
+#define IDD_DIALOG_FRAME 101
+#define IDS_WELCOME_CAPTION 102
+#define IDS_WELCOME_HEADER 103
+#define IDS_WELCOME_BODY1 104
+#define IDS_PRIVACY_URL 105
+#define IDS_NEXT_BUTTON 106
+#define IDD_WELCOME_PAGE 107
+#define IDS_CANCEL_BUTTON 107
+#define IDD_REPORT_PAGE 108
+#define IDS_REPORT_CAPTION 108
+#define IDS_REPORT_HEADER 109
+#define IDS_DESCRIPTION 110
+#define IDS_REPORT_INTRO 110
+#define IDS_ENTER_TITLE 111
+#define IDS_ALLOW_CONTACT 112
+#define IDS_ENTER_DESCRIPTION 113
+#define IDS_BACK_BUTTON 114
+#define IDS_SEND_BUTTON 115
+#define IDS_DONOT_SEND_BUTTON 116
+#define IDS_SHOW_REPORT_BUTTON 117
+#define IDS_SAVE_REPORT_BUTTON 118
+#define IDD_PREVIEW_FRAME 119
+#define IDS_ERROR_MSG_SIMPLE_MAPI 120
+#define IDS_ERROR_MSG_DISK_FULL 121
+#define IDS_OK_BUTTON 122
+#define IDS_OPTIONS_BUTTON 123
+#define IDS_LABEL_EMAIL 124
+#define IDD_OPTIONS_FRAME 125
+#define IDS_OPTIONS_CAPTION 126
+#define IDS_PROXY_SETTINGS_HEADER 127
+#define IDS_PROXY_SYSTEM 128
+#define IDS_PROXY_DIRECT 129
+#define IDS_PROXY_MANUAL 130
+#define IDS_LABEL_PROXYSERVER 131
+#define IDS_LABEL_PROXYPORT 132
+#define IDS_PROXY_DESCRIPTION 133
+#define IDS_ERROR_MSG_PROXY 134
+#define IDS_ERROR_MSG_NOCONNECT 135
+#define IDS_SENDING_REPORT_HEADER 136
+#define IDS_SENDING_REPORT_STATUS 137
+#define IDS_SENDING_REPORT_STATUS_FINISHED 138
+#define IDD_SENDING_STATUS 139
+#define IDS_WELCOME_BODY2 140
+#define IDS_WELCOME_BODY3 141
+#define IDS_ERROR_MSG_NOEMAILADDRESS 142
+#define IDS_MSG_CMDLINE_USAGE 143
+#define IDS_MSG_PARAM_PROCESSID 144
+#define IDS_MSG_PARAM_PROCESSID_DESCRIPTION 145
+#define IDS_MSG_PARAM_HELP_DESCRIPTION 146
+#define IDC_RICHEDIT_HEADER 1005
+#define IDC_RICHEDIT21 1006
+#define IDC_ALLOW_CONTACT 1007
+#define IDC_EDIT_TITLE 1008
+#define IDC_EDIT_DESCRIPTION 1009
+#define IDC_SHOW_REPORT 1010
+#define IDC_SAVE_REPORT 1011
+#define IDNEXT 1012
+#define IDBACK 1014
+#define IDC_REPORT_INTRO 1015
+#define IDC_ENTER_TITLE 1016
+#define IDFINISH 1016
+#define IDC_ENTER_DESCRIPTION 1017
+#define IDC_EDIT3 1018
+#define IDC_HEADER 1019
+#define IDC_STATICBK 1020
+#define IDC_EDIT_PREVIEW 1021
+#define IDC_EDIT_EMAIL 1022
+#define IDC_OPTIONS 1023
+#define IDC_PROXY_SETTINGS 1024
+#define IDC_RADIO_SYSTEM 1025
+#define IDC_RADIO_DIRECT 1026
+#define IDC_RADIO_MANUAL 1027
+#define IDC_LABEL_PROXYSERVER 1028
+#define IDC_LABEL_PROXYPORT 1029
+#define IDC_EDIT_PROXYSERVER 1030
+#define IDC_EDIT_PROXYPORT 1031
+#define IDC_LABEL_EMAIL 1032
+#define IDC_PROXY_DESCRIPTION 1033
+#define IDC_SENDING_REPORT_STATUS 1034
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_NEXT_RESOURCE_VALUE 147
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1035
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/crashrep/source/win32/soreport.cpp b/crashrep/source/win32/soreport.cpp
new file mode 100755
index 000000000000..d4d2207bc8d5
--- /dev/null
+++ b/crashrep/source/win32/soreport.cpp
@@ -0,0 +1,2272 @@
+#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 <stdlib.h>
+#include <stdio.h>
+#include <io.h>
+#include <fcntl.h>
+#include <string>
+#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;
+
+
+string g_strDefaultLanguage;
+string g_strProductKey;
+FILE *g_fpStackFile = 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( (intptr_t)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 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( '\\' );
+ aDir.erase( pos + 1 );
+
+ return aDir;
+}
+
+//***************************************************************************
+
+string GetFileName( const string& rFilePath )
+{
+ string aName = rFilePath;
+ size_t pos = aName.rfind( '\\' );
+
+ return aName.substr( pos + 1 );
+}
+
+//***************************************************************************
+
+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] = "";
+ CHAR szUserName[256] = "";
+ TCHAR tszUserName[256] = TEXT("");
+ DWORD dwUserNameSize = elementsof(tszUserName);
+ const char *pszUserType = getenv( "STAROFFICE_USERTYPE" );
+
+ GetUserName( tszUserName, &dwUserNameSize );
+
+ 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 );
+ WideCharToMultiByte( CP_UTF8, 0, tszUserName, -1, szUserName, sizeof(szUserName), 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\" uid=\"%s\" usertype=\"%s\">\n"
+ "<reportmail:mail xmlns:reportmail=\"http://openoffice.org/2002/reportmail\" version=\"1.0\" feedback=\"%s\" email=\"%s\">\n",
+ szUserName,
+ 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,
+ g_strDefaultLanguage.c_str(),
+ GetModuleDirectory( NULL ).c_str(),
+ g_dwExceptionCode,
+ g_strProductKey.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 );
+
+ 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 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 );
+}
+
+//***************************************************************************
+
+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 );
+
+ 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 );
+ }
+ 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;
+}
+
+
+
+//***************************************************************************
+
+static bool WriteStackFile( FILE *fout, 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 ) )
+ {
+ 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,
+ pSymbol->Name,
+ frame.AddrPC.Offset - pSymbol->Address,
+ GetFileName( moduleInfo.LoadedImageName ).c_str(),
+ 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,
+ GetFileName( moduleInfo.LoadedImageName ).c_str(),
+ 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 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 )
+ )
+ {
+ int needed = WideCharToMultiByte( CP_UTF8, 0, szBuffer, -1, NULL, 0, NULL, NULL );
+ char *pszBufferA = (char *)alloca( needed );
+
+ WideCharToMultiByte( CP_UTF8, 0, szBuffer, -1, pszBufferA, needed, NULL, NULL );
+ g_strProductKey = pszBufferA;
+
+ TCHAR *pVersion = _tcschr( 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("Port"),
+ 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("Server"),
+ 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 )
+ {
+ char szHTTPProxyServer[1024] = "";
+
+ lpHttpStart += 5;
+ TCHAR *lpHttpEnd = _tcschr( lpHttpStart, ';' );
+
+ if ( lpHttpEnd )
+ *lpHttpEnd = 0;
+ WideCharToMultiByte( CP_ACP, 0, lpHttpStart, -1, szHTTPProxyServer, sizeof(szHTTPProxyServer), NULL, NULL );
+
+ char *lpColon = strchr( szHTTPProxyServer, ':' );
+
+ if ( lpColon )
+ {
+ char *endptr = NULL;
+
+ *lpColon = 0;
+ strcpy( szProxyServer, szHTTPProxyServer );
+ uProxyPort = (unsigned short)strtoul( lpColon + 1, &endptr, 10 );
+ }
+ else
+ {
+ strcpy( szProxyServer, szHTTPProxyServer );
+ uProxyPort = 8080;
+ }
+ }
+ }
+ }
+ }
+ 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 ) )
+ {
+ g_fpStackFile = _tmpfile();
+
+ WriteStackFile( g_fpStackFile, dwProcessId, pExceptionPointers );
+
+ 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 );
+ }
+ }
+
+
+ return exitcode;
+}
+