home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / image / drwatson / ui.c < prev    next >
C/C++ Source or Header  |  1996-06-06  |  22KB  |  751 lines

  1. /*++
  2.  
  3. Copyright (c) 1993  Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     drwtsnui.c
  8.  
  9. Abstract:
  10.  
  11.     This function implements the ui (dialog) that controls the
  12.     options maintenace for drwatson.
  13.  
  14. Author:
  15.  
  16.     Wesley Witt (wesw) 1-May-1993
  17.  
  18. Environment:
  19.  
  20.     User Mode
  21.  
  22. --*/
  23.  
  24. #include <windows.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <mmsystem.h>
  29. #include <direct.h>
  30. #include <shellapi.h>
  31.  
  32. #include "drwatson.h"
  33. #include "proto.h"
  34. #include "resource.h"
  35.  
  36.  
  37. void InitializeDialog( HWND hwnd );
  38. void InitializeCrashList( HWND hwnd );
  39. BOOL GetDialogValues( HWND hwnd );
  40. BOOL CALLBACK LogFileViewerDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  41. LRESULT DrWatsonWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
  42. LPSTR ExpandPath(LPSTR lpPath);
  43.  
  44.  
  45. void
  46. DrWatsonWinMain( void )
  47.  
  48. /*++
  49.  
  50. Routine Description:
  51.  
  52.     This is the entry point for DRWTSN32
  53.  
  54. Arguments:
  55.  
  56.     None.
  57.  
  58. Return Value:
  59.  
  60.     None.
  61.  
  62. --*/
  63.  
  64. {
  65.     HWND           hwnd;
  66.     MSG            msg;
  67.     WNDCLASS       wndclass;
  68.     HINSTANCE      hInst;
  69.  
  70.  
  71.     hInst                   = GetModuleHandle( NULL );
  72.     wndclass.style          = CS_HREDRAW | CS_VREDRAW;
  73.     wndclass.lpfnWndProc    = DrWatsonWndProc;
  74.     wndclass.cbClsExtra     = 0;
  75.     wndclass.cbWndExtra     = DLGWINDOWEXTRA;
  76.     wndclass.hInstance      = hInst;
  77.     wndclass.hIcon          = LoadIcon( hInst, MAKEINTRESOURCE(APPICON) );
  78.     wndclass.hCursor        = LoadCursor( NULL, IDC_ARROW );
  79.     wndclass.hbrBackground  = (HBRUSH) (COLOR_3DFACE + 1);
  80.     wndclass.lpszMenuName   = NULL;
  81.     wndclass.lpszClassName  = "DrWatsonDialog";
  82.     RegisterClass( &wndclass );
  83.  
  84.     hwnd = CreateDialog( hInst,
  85.                          MAKEINTRESOURCE( DRWATSONDIALOG ),
  86.                          0,
  87.                          DrWatsonWndProc
  88.                        );
  89.  
  90.     ShowWindow( hwnd, SW_SHOWNORMAL );
  91.  
  92.     while (GetMessage (&msg, NULL, 0, 0)) {
  93.         if (!IsDialogMessage( hwnd, &msg )) {
  94.             TranslateMessage (&msg) ;
  95.             DispatchMessage (&msg) ;
  96.         }
  97.     }
  98.  
  99.     return;
  100. }
  101.  
  102. LRESULT
  103. DrWatsonWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  104.  
  105. /*++
  106.  
  107. Routine Description:
  108.  
  109.     Window procedure for the DRWTSN32.EXE main user interface.
  110.  
  111. Arguments:
  112.  
  113.     hwnd       - window handle to the dialog box
  114.     message    - message number
  115.     wParam     - first message parameter
  116.     lParam     - second message parameter
  117.  
  118. Return Value:
  119.  
  120.     TRUE       - did not process the message
  121.     FALSE      - did process the message
  122.  
  123. --*/
  124.  
  125. {
  126.     DWORD    helpId;
  127.     UINT     Checked;
  128.     char     szCurrDir[MAX_PATH];
  129.     char     szWave[MAX_PATH];
  130.     char     szDump[MAX_PATH];
  131.     char     szHelpFileName[MAX_PATH];
  132.     LPSTR    p;
  133.  
  134.  
  135.     switch (message) {
  136.         case WM_CREATE:
  137.             return 0;
  138.  
  139.         case WM_INITDIALOG:
  140.             SubclassControls( hwnd );
  141.             InitializeDialog( hwnd );
  142.             SetTimer( hwnd, 1, 50, NULL );
  143.             return 1;
  144.  
  145.         case WM_TIMER:
  146.             if (GetKeyState(VK_F1) & 0x8000) {
  147.                 if ((GetFocus() != hwnd) && (GetParent(GetFocus()) != hwnd)) {
  148.                     return 0;
  149.                 }
  150.                 switch (GetDlgCtrlID( GetFocus() )) {
  151.                     case ID_LOGPATH:
  152.                         helpId = IDH_LOGFILELOCATION;
  153.                         break;
  154.  
  155.                     case ID_BROWSE_LOGPATH:
  156.                         helpId = IDH_LOGFILELOCATION;
  157.                         break;
  158.  
  159.                     case ID_WAVEFILE_TEXT:
  160.                         helpId = IDH_WAVEFILE;
  161.                         break;
  162.  
  163.                     case ID_WAVE_FILE:
  164.                         helpId = IDH_WAVEFILE;
  165.                         break;
  166.  
  167.                     case ID_BROWSE_WAVEFILE:
  168.                         helpId = IDH_WAVEFILE;
  169.                         break;
  170.  
  171.                     case ID_TEST_WAVE:
  172.                         helpId = IDH_WAVEFILE;
  173.                         break;
  174.  
  175.                     case ID_INSTRUCTIONS:
  176.                         helpId = IDH_NUMBEROFINSTR;
  177.                         break;
  178.  
  179.                     case ID_NUM_CRASHES:
  180.                         helpId = IDH_NUMBEROFCRASHES;
  181.                         break;
  182.  
  183.                     case ID_DUMPSYMBOLS:
  184.                         helpId = IDH_DUMPSYMBOLS;
  185.                         break;
  186.  
  187.                     case ID_DUMPALLTHREADS:
  188.                         helpId = IDH_DUMPALLTHREADS;
  189.                         break;
  190.  
  191.                     case ID_APPENDTOLOGFILE:
  192.                         helpId = IDH_APPENDTOLOGFILE;
  193.                         break;
  194.  
  195.                     case ID_VISUAL:
  196.                         helpId = IDH_VISUAL;
  197.                         break;
  198.  
  199.                     case ID_SOUND:
  200.                         helpId = IDH_SOUND;
  201.                         break;
  202.  
  203.                     case ID_CRASHES:
  204.                         helpId = IDH_APPERRORS;
  205.                         break;
  206.  
  207.                     case ID_LOGFILE_VIEW:
  208.                         helpId = IDH_VIEW;
  209.                         break;
  210.  
  211.                     case ID_CLEAR:
  212.                         helpId = IDH_CLEAR;
  213.                         break;
  214.  
  215.                     case ID_CRASH:
  216.                         helpId = IDH_CRASH;
  217.                         break;
  218.  
  219.                     case ID_CRASH_DUMP:
  220.                         helpId = IDH_CRASH_DUMP;
  221.                         break;
  222.  
  223.                     case IDOK:
  224.                         helpId = IDH_INDEX;
  225.                         break;
  226.  
  227.                     case IDCANCEL:
  228.                         helpId = IDH_INDEX;
  229.                         break;
  230.  
  231.                     case ID_HELP:
  232.                         helpId = IDH_INDEX;
  233.                         break;
  234.  
  235.                     default:
  236.                         helpId = IDH_INDEX;
  237.                         break;
  238.                 }
  239.                 //
  240.                 // call winhelp
  241.                 //
  242.                 GetHelpFileName( szHelpFileName, sizeof(szHelpFileName ) );
  243.                 WinHelp( hwnd, szHelpFileName, HELP_FINDER, helpId );
  244.             }
  245.             return 1;
  246.  
  247.         case WM_ACTIVATEAPP:
  248.         case WM_SETFOCUS:
  249.             SetFocusToCurrentControl();
  250.             return 0;
  251.  
  252.         case WM_SYSCOMMAND:
  253.             if (wParam == ID_ABOUT) {
  254.                 char title[256];
  255.                 char extra[256];
  256.  
  257.                 strcpy( title, LoadRcString( IDS_ABOUT_TITLE ) );
  258.                 strcpy( extra, LoadRcString( IDS_ABOUT_EXTRA ) );
  259.  
  260.                 ShellAbout( hwnd,
  261.                             title,
  262.                             extra,
  263.                             LoadIcon( GetModuleHandle(NULL),
  264.                                       MAKEINTRESOURCE(APPICON)
  265.                                     )
  266.                           );
  267.  
  268.                 return 0;
  269.             }
  270.             break;
  271.  
  272.         case WM_COMMAND:
  273.             switch (wParam) {
  274.                 case IDOK:
  275.                     if (GetDialogValues( hwnd )) {
  276.                         PostQuitMessage( 0 );
  277.                     }
  278.                     break;
  279.  
  280.                 case IDCANCEL:
  281.                     PostQuitMessage( 0 );
  282.                     break;
  283.  
  284.                 case ID_BROWSE_LOGPATH:
  285.                     GetDlgItemText( hwnd, ID_LOGPATH, szCurrDir, MAX_PATH );
  286.                     p = ExpandPath( szCurrDir );
  287.                     if (p) {
  288.                         strcpy( szCurrDir, p );
  289.                         free( p );
  290.                     }
  291.                     EnableWindow( GetDlgItem( hwnd, ID_BROWSE_LOGPATH ), FALSE );
  292.                     if (BrowseForDirectory( szCurrDir )) {
  293.                         SetDlgItemText( hwnd, ID_LOGPATH, szCurrDir );
  294.                     }
  295.                     EnableWindow( GetDlgItem( hwnd, ID_BROWSE_LOGPATH ), TRUE );
  296.                     SetFocus( GetDlgItem(hwnd, ID_BROWSE_LOGPATH) );
  297.                     return FALSE;
  298.                     break;
  299.  
  300.                 case ID_BROWSE_WAVEFILE:
  301.                     szWave[0] = '\0';
  302.                     EnableWindow( GetDlgItem( hwnd, ID_BROWSE_WAVEFILE ), FALSE );
  303.                     if (GetWaveFileName( szWave )) {
  304.                         SetDlgItemText( hwnd, ID_WAVE_FILE, szWave );
  305.                     }
  306.                     EnableWindow( GetDlgItem( hwnd, ID_BROWSE_WAVEFILE ), TRUE );
  307.                     SetFocus( GetDlgItem(hwnd, ID_BROWSE_WAVEFILE) );
  308.                     return FALSE;
  309.                     break;
  310.  
  311.                 case ID_BROWSE_CRASH:
  312.                     szDump[0] = '\0';
  313.                     EnableWindow( GetDlgItem( hwnd, ID_BROWSE_CRASH ), FALSE );
  314.                     if (GetDumpFileName( szDump )) {
  315.                         SetDlgItemText( hwnd, ID_CRASH_DUMP, szDump );
  316.                     }
  317.                     EnableWindow( GetDlgItem( hwnd, ID_BROWSE_CRASH ), TRUE );
  318.                     SetFocus( GetDlgItem(hwnd, ID_BROWSE_CRASH) );
  319.                     return FALSE;
  320.                     break;
  321.  
  322.                 case ID_CLEAR:
  323.                     ElClearAllEvents();
  324.                     InitializeCrashList( hwnd );
  325.                     break;
  326.  
  327.                 case ID_TEST_WAVE:
  328.                     GetDlgItemText( hwnd, ID_WAVE_FILE, szWave, sizeof(szWave) );
  329.                     PlaySound( szWave, NULL, SND_FILENAME );
  330.                     break;
  331.  
  332.                 case ID_LOGFILE_VIEW:
  333.                     DialogBoxParam( GetModuleHandle( NULL ),
  334.                            MAKEINTRESOURCE( LOGFILEVIEWERDIALOG ),
  335.                            hwnd,
  336.                            LogFileViewerDialogProc,
  337.                            SendMessage((HWND)GetDlgItem(hwnd,ID_CRASHES),
  338.                                         LB_GETCURSEL,0,0)
  339.                          );
  340.                     break;
  341.  
  342.                 case ID_HELP:
  343.                     //
  344.                     // call winhelp
  345.                     //
  346.                     GetHelpFileName( szHelpFileName, sizeof(szHelpFileName ) );
  347.                     WinHelp( hwnd, szHelpFileName, HELP_FINDER, IDH_INDEX );
  348.                     SetFocus( GetDlgItem(hwnd, ID_HELP) );
  349.                     break;
  350.  
  351.                 default:
  352.                     if (((HWND)lParam == GetDlgItem( hwnd, ID_CRASHES )) &&
  353.                         (HIWORD( wParam ) == LBN_DBLCLK)) {
  354.                         DialogBoxParam( GetModuleHandle( NULL ),
  355.                                MAKEINTRESOURCE( LOGFILEVIEWERDIALOG ),
  356.                                hwnd,
  357.                                LogFileViewerDialogProc,
  358.                                SendMessage((HWND)lParam,LB_GETCURSEL,0,0)
  359.                              );
  360.                     }
  361.                     if (((HWND)lParam == GetDlgItem( hwnd, ID_CRASH )) &&
  362.                         (HIWORD( wParam ) == BN_CLICKED)) {
  363.                         Checked = IsDlgButtonChecked( hwnd, ID_CRASH );
  364.                         EnableWindow( GetDlgItem( hwnd, ID_CRASH_DUMP_TEXT ), Checked == 1 );
  365.                         EnableWindow( GetDlgItem( hwnd, ID_CRASH_DUMP ), Checked == 1 );
  366.                         EnableWindow( GetDlgItem( hwnd, ID_BROWSE_CRASH ), Checked == 1 );
  367.                     }
  368.                     break;
  369.             }
  370.             break;
  371.  
  372.         case WM_DESTROY:
  373.             PostQuitMessage( 0 );
  374.             return 0;
  375.     }
  376.  
  377.     return DefWindowProc( hwnd, message, wParam, lParam );
  378. }
  379.  
  380. BOOL CALLBACK
  381. EnumCrashes( PCRASHINFO crashInfo )
  382.  
  383. /*++
  384.  
  385. Routine Description:
  386.  
  387.     Enumeration function for crash records.  This function is called
  388.     once for each crash record.  This function places the formatted
  389.     crash data in a listbox.
  390.  
  391. Arguments:
  392.  
  393.     crashInfo      - pointer to a CRASHINFO structure
  394.  
  395. Return Value:
  396.  
  397.     TRUE           - caller should continue calling the enum procedure
  398.     FALSE          - caller should stop calling the enum procedure
  399.  
  400. --*/
  401.  
  402. {
  403.     SIZE size;
  404.     char buf[1024];
  405.  
  406.     wsprintf( buf, "%s  %08x  %s(%08x)",
  407.               crashInfo->crash.szAppName,
  408.               crashInfo->crash.dwExceptionCode,
  409.               crashInfo->crash.szFunction,
  410.               crashInfo->crash.dwAddress
  411.             );
  412.     SendMessage( crashInfo->hList, LB_ADDSTRING, 0, (LPARAM)buf );
  413.  
  414.  
  415.     GetTextExtentPoint( crashInfo->hdc, buf, strlen(buf), &size );
  416.     if (size.cx > (LONG)crashInfo->cxExtent) {
  417.         crashInfo->cxExtent = size.cx;
  418.     }
  419.  
  420.     return TRUE;
  421. }
  422.  
  423.  
  424. void
  425. InitializeCrashList( HWND hwnd )
  426.  
  427. /*++
  428.  
  429. Routine Description:
  430.  
  431.     Initializes the listbox that contains the crash information.
  432.  
  433. Arguments:
  434.  
  435.     None.
  436.  
  437. Return Value:
  438.  
  439.     None.
  440.  
  441. --*/
  442.  
  443. {
  444.     CRASHINFO     crashInfo;
  445.     TEXTMETRIC    tm;
  446.     HFONT         hFont;
  447.  
  448.     crashInfo.hList = GetDlgItem( hwnd, ID_CRASHES );
  449.     SendMessage( crashInfo.hList, LB_RESETCONTENT, FALSE, 0L );
  450.     SendMessage( crashInfo.hList, WM_SETREDRAW, FALSE, 0L );
  451.     crashInfo.hdc = GetDC( crashInfo.hList );
  452.     crashInfo.cxExtent = 0;
  453.  
  454.     ElEnumCrashes( &crashInfo, EnumCrashes );
  455.  
  456.     hFont = (HFONT)SendMessage( crashInfo.hList, WM_GETFONT, 0, 0L );
  457.     if (hFont != NULL) {
  458.         SelectObject( crashInfo.hdc, hFont );
  459.     }
  460.     GetTextMetrics( crashInfo.hdc, &tm );
  461.     ReleaseDC( crashInfo.hList, crashInfo.hdc );
  462.     SendMessage( crashInfo.hList, LB_SETHORIZONTALEXTENT, crashInfo.cxExtent, 0L );
  463.     SendMessage( crashInfo.hList, WM_SETREDRAW, TRUE, 0L );
  464.  
  465.     return;
  466. }
  467.  
  468. void
  469. InitializeDialog( HWND hwnd )
  470.  
  471. /*++
  472.  
  473. Routine Description:
  474.  
  475.     Initializes the DRWTSN32 user interface dialog with the values
  476.     stored in the registry.
  477.  
  478. Arguments:
  479.  
  480.     hwnd       - window handle to the dialog
  481.  
  482. Return Value:
  483.  
  484.     None.
  485.  
  486. --*/
  487.  
  488. {
  489.     OPTIONS       o;
  490.     char          buf[256];
  491.     HMENU         hMenu;
  492.  
  493.  
  494.     RegInitialize( &o );
  495.     SetDlgItemText( hwnd, ID_LOGPATH, o.szLogPath );
  496.     SetDlgItemText( hwnd, ID_WAVE_FILE, o.szWaveFile );
  497.     SetDlgItemText( hwnd, ID_CRASH_DUMP, o.szCrashDump );
  498.     wsprintf( buf, "%d", o.dwMaxCrashes );
  499.     SetDlgItemText( hwnd, ID_NUM_CRASHES, buf );
  500.     wsprintf( buf, "%d", o.dwInstructions );
  501.     SetDlgItemText( hwnd, ID_INSTRUCTIONS, buf );
  502.     SendMessage( GetDlgItem( hwnd, ID_DUMPSYMBOLS ), BM_SETCHECK, o.fDumpSymbols, 0 );
  503.     SendMessage( GetDlgItem( hwnd, ID_DUMPALLTHREADS ), BM_SETCHECK, o.fDumpAllThreads, 0 );
  504.     SendMessage( GetDlgItem( hwnd, ID_APPENDTOLOGFILE ), BM_SETCHECK, o.fAppendToLogFile, 0 );
  505.     SendMessage( GetDlgItem( hwnd, ID_VISUAL ), BM_SETCHECK, o.fVisual, 0 );
  506.     SendMessage( GetDlgItem( hwnd, ID_SOUND ), BM_SETCHECK, o.fSound, 0 );
  507.     SendMessage( GetDlgItem( hwnd, ID_CRASH ), BM_SETCHECK, o.fCrash, 0 );
  508.  
  509.     if (waveOutGetNumDevs() == 0) {
  510.         EnableWindow( GetDlgItem( hwnd, ID_WAVEFILE_TEXT ), FALSE );
  511.         EnableWindow( GetDlgItem( hwnd, ID_WAVE_FILE ), FALSE );
  512.         EnableWindow( GetDlgItem( hwnd, ID_BROWSE_WAVEFILE ), FALSE );
  513.     }
  514.  
  515.     EnableWindow( GetDlgItem( hwnd, ID_CRASH_DUMP_TEXT ), o.fCrash );
  516.     EnableWindow( GetDlgItem( hwnd, ID_CRASH_DUMP ), o.fCrash );
  517.     EnableWindow( GetDlgItem( hwnd, ID_BROWSE_CRASH ), o.fCrash );
  518.  
  519.     InitializeCrashList( hwnd );
  520.  
  521.     if (SendMessage( GetDlgItem( hwnd, ID_CRASHES ), LB_GETCOUNT, 0 ,0 ) == 0) {
  522.         EnableWindow( GetDlgItem( hwnd, ID_CLEAR ), FALSE );
  523.         EnableWindow( GetDlgItem( hwnd, ID_LOGFILE_VIEW ), FALSE );
  524.     }
  525.  
  526.     hMenu = GetSystemMenu( hwnd, FALSE );
  527.     if (hMenu != NULL) {
  528.         AppendMenu( hMenu, MF_SEPARATOR, 0, NULL );
  529.         AppendMenu( hMenu, MF_STRING, ID_ABOUT, LoadRcString( IDS_ABOUT ) );
  530.     }
  531.  
  532.     return;
  533. }
  534.  
  535. BOOL
  536. GetDialogValues( HWND hwnd )
  537.  
  538. /*++
  539.  
  540. Routine Description:
  541.  
  542.     Retrieves the values in the DRWTSN32 dialog controls and saves
  543.     them in the registry.
  544.  
  545. Arguments:
  546.  
  547.     hwnd       - window handle to the dialog
  548.  
  549. Return Value:
  550.  
  551.     TRUE       - all values were retrieved and saved
  552.     FALSE      - an error occurred
  553.  
  554. --*/
  555.  
  556. {
  557.     OPTIONS  o;
  558.     char     buf[256];
  559.     DWORD    dwFa;
  560.     LPSTR    p,p1;
  561.     char     szDrive    [_MAX_DRIVE];
  562.     char     szDir      [_MAX_DIR];
  563.     char     szPath     [MAX_PATH];
  564.  
  565.  
  566.     RegInitialize( &o );
  567.  
  568.     GetDlgItemText( hwnd, ID_LOGPATH, buf, sizeof(buf) );
  569.     p = ExpandPath( buf );
  570.     if (p) {
  571.         dwFa = GetFileAttributes( p );
  572.         free( p );
  573.     } else {
  574.         dwFa = GetFileAttributes( buf );
  575.     }
  576.     if ((dwFa == 0xffffffff) || (!(dwFa&FILE_ATTRIBUTE_DIRECTORY))) {
  577.         NonFatalError( LoadRcString(IDS_INVALID_PATH) );
  578.         return FALSE;
  579.     }
  580.     if (strlen(buf) > 0) {
  581.         strcpy( o.szLogPath, buf );
  582.     }
  583.  
  584.     o.fCrash = SendMessage( GetDlgItem( hwnd, ID_CRASH ), BM_GETCHECK, 0, 0 );
  585.  
  586.     GetDlgItemText( hwnd, ID_CRASH_DUMP, buf, sizeof(buf) );
  587.     if (o.fCrash) {
  588.         p = ExpandPath( buf );
  589.         if (p) {
  590.             dwFa = GetFileAttributes( p );
  591.             free( p );
  592.         } else {
  593.             dwFa = GetFileAttributes( buf );
  594.         }
  595.         if (dwFa == 0xffffffff) {
  596.             //
  597.             // file does not exist, check to see if the dir is ok
  598.             //
  599.             p = ExpandPath( buf );
  600.             if (p) {
  601.                 p1 = p;
  602.             } else {
  603.                 p1 = buf;
  604.             }
  605.             _splitpath( p1, szDrive, szDir, NULL, NULL );
  606.             _makepath( szPath, szDrive, szDir, NULL, NULL );
  607.             if (p) {
  608.                 free( p );
  609.             }
  610.             dwFa = GetFileAttributes( szPath );
  611.             if (dwFa == 0xffffffff) {
  612.                 NonFatalError( LoadRcString(IDS_INVALID_CRASH_PATH) );
  613.                 return FALSE;
  614.             }
  615.         } else if (dwFa & FILE_ATTRIBUTE_DIRECTORY) {
  616.             NonFatalError( LoadRcString(IDS_INVALID_CRASH_PATH) );
  617.             return FALSE;
  618.         }
  619.         if (strlen(buf) > 0) {
  620.             strcpy( o.szCrashDump, buf );
  621.         }
  622.     }
  623.  
  624.     GetDlgItemText( hwnd, ID_WAVE_FILE, buf, sizeof(buf) );
  625.     if (strlen(buf) > 0) {
  626.         dwFa = GetFileAttributes( buf );
  627.         if ((dwFa == 0xffffffff) || (dwFa&FILE_ATTRIBUTE_DIRECTORY)) {
  628.             NonFatalError( LoadRcString(IDS_INVALID_WAVE) );
  629.             return FALSE;
  630.         }
  631.     }
  632.  
  633.     strcpy( o.szWaveFile, buf );
  634.  
  635.     GetDlgItemText( hwnd, ID_NUM_CRASHES, buf, sizeof(buf) );
  636.     o.dwMaxCrashes = (DWORD) atol( buf );
  637.  
  638.     GetDlgItemText( hwnd, ID_INSTRUCTIONS, buf, sizeof(buf) );
  639.     o.dwInstructions = (DWORD) atol( buf );
  640.  
  641.     o.fDumpSymbols = SendMessage( GetDlgItem( hwnd, ID_DUMPSYMBOLS ), BM_GETCHECK, 0, 0 );
  642.     o.fDumpAllThreads = SendMessage( GetDlgItem( hwnd, ID_DUMPALLTHREADS ), BM_GETCHECK, 0, 0 );
  643.     o.fAppendToLogFile = SendMessage( GetDlgItem( hwnd, ID_APPENDTOLOGFILE ), BM_GETCHECK, 0, 0 );
  644.     o.fVisual = SendMessage( GetDlgItem( hwnd, ID_VISUAL ), BM_GETCHECK, 0, 0 );
  645.     o.fSound = SendMessage( GetDlgItem( hwnd, ID_SOUND ), BM_GETCHECK, 0, 0 );
  646.  
  647.     RegSave( &o );
  648.  
  649.     return TRUE;
  650. }
  651.  
  652. BOOL CALLBACK
  653. EnumCrashesForViewer( PCRASHINFO crashInfo )
  654.  
  655. /*++
  656.  
  657. Routine Description:
  658.  
  659.     Enumeration function for crash records.  This function is called
  660.     once for each crash record.  This function looks for s specific crash
  661.     that is identified by the crashIndex.
  662.  
  663. Arguments:
  664.  
  665.     crashInfo      - pointer to a CRASHINFO structure
  666.  
  667. Return Value:
  668.  
  669.     TRUE           - caller should continue calling the enum procedure
  670.     FALSE          - caller should stop calling the enum procedure
  671.  
  672. --*/
  673.  
  674. {
  675.     char *p;
  676.  
  677.     if ((crashInfo->dwIndex == crashInfo->dwIndexDesired) &&
  678.         (crashInfo->dwCrashDataSize > 0) ) {
  679.         p = crashInfo->pCrashData;
  680.         crashInfo->pCrashData = malloc( crashInfo->dwCrashDataSize+10 );
  681.         memcpy( crashInfo->pCrashData, p, crashInfo->dwCrashDataSize+10 );
  682.         crashInfo->pCrashData[crashInfo->dwCrashDataSize] = 0;
  683.         return FALSE;
  684.     }
  685.  
  686.     crashInfo->dwIndex++;
  687.  
  688.     return TRUE;
  689. }
  690.  
  691. BOOL CALLBACK
  692. LogFileViewerDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  693.  
  694. /*++
  695.  
  696. Routine Description:
  697.  
  698.     Window procedure for the log file viewer dialog box.
  699.  
  700. Arguments:
  701.  
  702.     hwnd       - window handle to the dialog box
  703.     message    - message number
  704.     wParam     - first message parameter
  705.     lParam     - second message parameter
  706.  
  707. Return Value:
  708.  
  709.     TRUE       - did not process the message
  710.     FALSE      - did process the message
  711.  
  712. --*/
  713.  
  714. {
  715.     static CRASHINFO    crashInfo;
  716.     HFONT               hFont;
  717.  
  718.     switch (message) {
  719.         case WM_INITDIALOG:
  720.             crashInfo.dwIndex = 0;
  721.             crashInfo.dwIndexDesired = lParam;
  722.             ElEnumCrashes( &crashInfo, EnumCrashesForViewer );
  723.             if (crashInfo.dwIndex != crashInfo.dwIndexDesired) {
  724.                 MessageBeep( 0 );
  725.                 EndDialog( hwnd, 0 );
  726.                 return FALSE;
  727.             }
  728.             SetDlgItemText( hwnd, ID_LOGFILE_VIEW, crashInfo.pCrashData );
  729.  
  730.             hFont = GetStockObject( SYSTEM_FIXED_FONT );
  731.             Assert( hFont != NULL );
  732.  
  733.             SendDlgItemMessage( hwnd,
  734.                                 ID_LOGFILE_VIEW,
  735.                                 WM_SETFONT,
  736.                                 (WPARAM) hFont,
  737.                                 (LPARAM) FALSE
  738.                               );
  739.             return TRUE;
  740.  
  741.         case WM_COMMAND:
  742.             if (wParam == IDOK) {
  743.                 free( crashInfo.pCrashData );
  744.                 EndDialog( hwnd, 0 );
  745.             }
  746.             break;
  747.     }
  748.  
  749.     return FALSE;
  750. }
  751.