/*++ Copyright (c) 1993 Microsoft Corporation Module Name: drwtsnui.c Abstract: This function implements the ui (dialog) that controls the options maintenace for drwatson. Author: Wesley Witt (wesw) 1-May-1993 Environment: User Mode --*/ #include #include #include #include #include #include #include #include "drwatson.h" #include "proto.h" #include "resource.h" void InitializeDialog( HWND hwnd ); void InitializeCrashList( HWND hwnd ); BOOL GetDialogValues( HWND hwnd ); BOOL CALLBACK LogFileViewerDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); LRESULT DrWatsonWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); LPSTR ExpandPath(LPSTR lpPath); void DrWatsonWinMain( void ) /*++ Routine Description: This is the entry point for DRWTSN32 Arguments: None. Return Value: None. --*/ { HWND hwnd; MSG msg; WNDCLASS wndclass; HINSTANCE hInst; hInst = GetModuleHandle( NULL ); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = DrWatsonWndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = DLGWINDOWEXTRA; wndclass.hInstance = hInst; wndclass.hIcon = LoadIcon( hInst, MAKEINTRESOURCE(APPICON) ); wndclass.hCursor = LoadCursor( NULL, IDC_ARROW ); wndclass.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = "DrWatsonDialog"; RegisterClass( &wndclass ); hwnd = CreateDialog( hInst, MAKEINTRESOURCE( DRWATSONDIALOG ), 0, DrWatsonWndProc ); ShowWindow( hwnd, SW_SHOWNORMAL ); while (GetMessage (&msg, NULL, 0, 0)) { if (!IsDialogMessage( hwnd, &msg )) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } } return; } LRESULT DrWatsonWndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /*++ Routine Description: Window procedure for the DRWTSN32.EXE main user interface. Arguments: hwnd - window handle to the dialog box message - message number wParam - first message parameter lParam - second message parameter Return Value: TRUE - did not process the message FALSE - did process the message --*/ { DWORD helpId; UINT Checked; char szCurrDir[MAX_PATH]; char szWave[MAX_PATH]; char szDump[MAX_PATH]; char szHelpFileName[MAX_PATH]; LPSTR p; switch (message) { case WM_CREATE: return 0; case WM_INITDIALOG: SubclassControls( hwnd ); InitializeDialog( hwnd ); SetTimer( hwnd, 1, 50, NULL ); return 1; case WM_TIMER: if (GetKeyState(VK_F1) & 0x8000) { if ((GetFocus() != hwnd) && (GetParent(GetFocus()) != hwnd)) { return 0; } switch (GetDlgCtrlID( GetFocus() )) { case ID_LOGPATH: helpId = IDH_LOGFILELOCATION; break; case ID_BROWSE_LOGPATH: helpId = IDH_LOGFILELOCATION; break; case ID_WAVEFILE_TEXT: helpId = IDH_WAVEFILE; break; case ID_WAVE_FILE: helpId = IDH_WAVEFILE; break; case ID_BROWSE_WAVEFILE: helpId = IDH_WAVEFILE; break; case ID_TEST_WAVE: helpId = IDH_WAVEFILE; break; case ID_INSTRUCTIONS: helpId = IDH_NUMBEROFINSTR; break; case ID_NUM_CRASHES: helpId = IDH_NUMBEROFCRASHES; break; case ID_DUMPSYMBOLS: helpId = IDH_DUMPSYMBOLS; break; case ID_DUMPALLTHREADS: helpId = IDH_DUMPALLTHREADS; break; case ID_APPENDTOLOGFILE: helpId = IDH_APPENDTOLOGFILE; break; case ID_VISUAL: helpId = IDH_VISUAL; break; case ID_SOUND: helpId = IDH_SOUND; break; case ID_CRASHES: helpId = IDH_APPERRORS; break; case ID_LOGFILE_VIEW: helpId = IDH_VIEW; break; case ID_CLEAR: helpId = IDH_CLEAR; break; case ID_CRASH: helpId = IDH_CRASH; break; case ID_CRASH_DUMP: helpId = IDH_CRASH_DUMP; break; case IDOK: helpId = IDH_INDEX; break; case IDCANCEL: helpId = IDH_INDEX; break; case ID_HELP: helpId = IDH_INDEX; break; default: helpId = IDH_INDEX; break; } // // call winhelp // GetHelpFileName( szHelpFileName, sizeof(szHelpFileName ) ); WinHelp( hwnd, szHelpFileName, HELP_FINDER, helpId ); } return 1; case WM_ACTIVATEAPP: case WM_SETFOCUS: SetFocusToCurrentControl(); return 0; case WM_SYSCOMMAND: if (wParam == ID_ABOUT) { char title[256]; char extra[256]; strcpy( title, LoadRcString( IDS_ABOUT_TITLE ) ); strcpy( extra, LoadRcString( IDS_ABOUT_EXTRA ) ); ShellAbout( hwnd, title, extra, LoadIcon( GetModuleHandle(NULL), MAKEINTRESOURCE(APPICON) ) ); return 0; } break; case WM_COMMAND: switch (wParam) { case IDOK: if (GetDialogValues( hwnd )) { PostQuitMessage( 0 ); } break; case IDCANCEL: PostQuitMessage( 0 ); break; case ID_BROWSE_LOGPATH: GetDlgItemText( hwnd, ID_LOGPATH, szCurrDir, MAX_PATH ); p = ExpandPath( szCurrDir ); if (p) { strcpy( szCurrDir, p ); free( p ); } EnableWindow( GetDlgItem( hwnd, ID_BROWSE_LOGPATH ), FALSE ); if (BrowseForDirectory( szCurrDir )) { SetDlgItemText( hwnd, ID_LOGPATH, szCurrDir ); } EnableWindow( GetDlgItem( hwnd, ID_BROWSE_LOGPATH ), TRUE ); SetFocus( GetDlgItem(hwnd, ID_BROWSE_LOGPATH) ); return FALSE; break; case ID_BROWSE_WAVEFILE: szWave[0] = '\0'; EnableWindow( GetDlgItem( hwnd, ID_BROWSE_WAVEFILE ), FALSE ); if (GetWaveFileName( szWave )) { SetDlgItemText( hwnd, ID_WAVE_FILE, szWave ); } EnableWindow( GetDlgItem( hwnd, ID_BROWSE_WAVEFILE ), TRUE ); SetFocus( GetDlgItem(hwnd, ID_BROWSE_WAVEFILE) ); return FALSE; break; case ID_BROWSE_CRASH: szDump[0] = '\0'; EnableWindow( GetDlgItem( hwnd, ID_BROWSE_CRASH ), FALSE ); if (GetDumpFileName( szDump )) { SetDlgItemText( hwnd, ID_CRASH_DUMP, szDump ); } EnableWindow( GetDlgItem( hwnd, ID_BROWSE_CRASH ), TRUE ); SetFocus( GetDlgItem(hwnd, ID_BROWSE_CRASH) ); return FALSE; break; case ID_CLEAR: ElClearAllEvents(); InitializeCrashList( hwnd ); break; case ID_TEST_WAVE: GetDlgItemText( hwnd, ID_WAVE_FILE, szWave, sizeof(szWave) ); PlaySound( szWave, NULL, SND_FILENAME ); break; case ID_LOGFILE_VIEW: DialogBoxParam( GetModuleHandle( NULL ), MAKEINTRESOURCE( LOGFILEVIEWERDIALOG ), hwnd, LogFileViewerDialogProc, SendMessage((HWND)GetDlgItem(hwnd,ID_CRASHES), LB_GETCURSEL,0,0) ); break; case ID_HELP: // // call winhelp // GetHelpFileName( szHelpFileName, sizeof(szHelpFileName ) ); WinHelp( hwnd, szHelpFileName, HELP_FINDER, IDH_INDEX ); SetFocus( GetDlgItem(hwnd, ID_HELP) ); break; default: if (((HWND)lParam == GetDlgItem( hwnd, ID_CRASHES )) && (HIWORD( wParam ) == LBN_DBLCLK)) { DialogBoxParam( GetModuleHandle( NULL ), MAKEINTRESOURCE( LOGFILEVIEWERDIALOG ), hwnd, LogFileViewerDialogProc, SendMessage((HWND)lParam,LB_GETCURSEL,0,0) ); } if (((HWND)lParam == GetDlgItem( hwnd, ID_CRASH )) && (HIWORD( wParam ) == BN_CLICKED)) { Checked = IsDlgButtonChecked( hwnd, ID_CRASH ); EnableWindow( GetDlgItem( hwnd, ID_CRASH_DUMP_TEXT ), Checked == 1 ); EnableWindow( GetDlgItem( hwnd, ID_CRASH_DUMP ), Checked == 1 ); EnableWindow( GetDlgItem( hwnd, ID_BROWSE_CRASH ), Checked == 1 ); } break; } break; case WM_DESTROY: PostQuitMessage( 0 ); return 0; } return DefWindowProc( hwnd, message, wParam, lParam ); } BOOL CALLBACK EnumCrashes( PCRASHINFO crashInfo ) /*++ Routine Description: Enumeration function for crash records. This function is called once for each crash record. This function places the formatted crash data in a listbox. Arguments: crashInfo - pointer to a CRASHINFO structure Return Value: TRUE - caller should continue calling the enum procedure FALSE - caller should stop calling the enum procedure --*/ { SIZE size; char buf[1024]; wsprintf( buf, "%s %08x %s(%08x)", crashInfo->crash.szAppName, crashInfo->crash.dwExceptionCode, crashInfo->crash.szFunction, crashInfo->crash.dwAddress ); SendMessage( crashInfo->hList, LB_ADDSTRING, 0, (LPARAM)buf ); GetTextExtentPoint( crashInfo->hdc, buf, strlen(buf), &size ); if (size.cx > (LONG)crashInfo->cxExtent) { crashInfo->cxExtent = size.cx; } return TRUE; } void InitializeCrashList( HWND hwnd ) /*++ Routine Description: Initializes the listbox that contains the crash information. Arguments: None. Return Value: None. --*/ { CRASHINFO crashInfo; TEXTMETRIC tm; HFONT hFont; crashInfo.hList = GetDlgItem( hwnd, ID_CRASHES ); SendMessage( crashInfo.hList, LB_RESETCONTENT, FALSE, 0L ); SendMessage( crashInfo.hList, WM_SETREDRAW, FALSE, 0L ); crashInfo.hdc = GetDC( crashInfo.hList ); crashInfo.cxExtent = 0; ElEnumCrashes( &crashInfo, EnumCrashes ); hFont = (HFONT)SendMessage( crashInfo.hList, WM_GETFONT, 0, 0L ); if (hFont != NULL) { SelectObject( crashInfo.hdc, hFont ); } GetTextMetrics( crashInfo.hdc, &tm ); ReleaseDC( crashInfo.hList, crashInfo.hdc ); SendMessage( crashInfo.hList, LB_SETHORIZONTALEXTENT, crashInfo.cxExtent, 0L ); SendMessage( crashInfo.hList, WM_SETREDRAW, TRUE, 0L ); return; } void InitializeDialog( HWND hwnd ) /*++ Routine Description: Initializes the DRWTSN32 user interface dialog with the values stored in the registry. Arguments: hwnd - window handle to the dialog Return Value: None. --*/ { OPTIONS o; char buf[256]; HMENU hMenu; RegInitialize( &o ); SetDlgItemText( hwnd, ID_LOGPATH, o.szLogPath ); SetDlgItemText( hwnd, ID_WAVE_FILE, o.szWaveFile ); SetDlgItemText( hwnd, ID_CRASH_DUMP, o.szCrashDump ); wsprintf( buf, "%d", o.dwMaxCrashes ); SetDlgItemText( hwnd, ID_NUM_CRASHES, buf ); wsprintf( buf, "%d", o.dwInstructions ); SetDlgItemText( hwnd, ID_INSTRUCTIONS, buf ); SendMessage( GetDlgItem( hwnd, ID_DUMPSYMBOLS ), BM_SETCHECK, o.fDumpSymbols, 0 ); SendMessage( GetDlgItem( hwnd, ID_DUMPALLTHREADS ), BM_SETCHECK, o.fDumpAllThreads, 0 ); SendMessage( GetDlgItem( hwnd, ID_APPENDTOLOGFILE ), BM_SETCHECK, o.fAppendToLogFile, 0 ); SendMessage( GetDlgItem( hwnd, ID_VISUAL ), BM_SETCHECK, o.fVisual, 0 ); SendMessage( GetDlgItem( hwnd, ID_SOUND ), BM_SETCHECK, o.fSound, 0 ); SendMessage( GetDlgItem( hwnd, ID_CRASH ), BM_SETCHECK, o.fCrash, 0 ); if (waveOutGetNumDevs() == 0) { EnableWindow( GetDlgItem( hwnd, ID_WAVEFILE_TEXT ), FALSE ); EnableWindow( GetDlgItem( hwnd, ID_WAVE_FILE ), FALSE ); EnableWindow( GetDlgItem( hwnd, ID_BROWSE_WAVEFILE ), FALSE ); } EnableWindow( GetDlgItem( hwnd, ID_CRASH_DUMP_TEXT ), o.fCrash ); EnableWindow( GetDlgItem( hwnd, ID_CRASH_DUMP ), o.fCrash ); EnableWindow( GetDlgItem( hwnd, ID_BROWSE_CRASH ), o.fCrash ); InitializeCrashList( hwnd ); if (SendMessage( GetDlgItem( hwnd, ID_CRASHES ), LB_GETCOUNT, 0 ,0 ) == 0) { EnableWindow( GetDlgItem( hwnd, ID_CLEAR ), FALSE ); EnableWindow( GetDlgItem( hwnd, ID_LOGFILE_VIEW ), FALSE ); } hMenu = GetSystemMenu( hwnd, FALSE ); if (hMenu != NULL) { AppendMenu( hMenu, MF_SEPARATOR, 0, NULL ); AppendMenu( hMenu, MF_STRING, ID_ABOUT, LoadRcString( IDS_ABOUT ) ); } return; } BOOL GetDialogValues( HWND hwnd ) /*++ Routine Description: Retrieves the values in the DRWTSN32 dialog controls and saves them in the registry. Arguments: hwnd - window handle to the dialog Return Value: TRUE - all values were retrieved and saved FALSE - an error occurred --*/ { OPTIONS o; char buf[256]; DWORD dwFa; LPSTR p,p1; char szDrive [_MAX_DRIVE]; char szDir [_MAX_DIR]; char szPath [MAX_PATH]; RegInitialize( &o ); GetDlgItemText( hwnd, ID_LOGPATH, buf, sizeof(buf) ); p = ExpandPath( buf ); if (p) { dwFa = GetFileAttributes( p ); free( p ); } else { dwFa = GetFileAttributes( buf ); } if ((dwFa == 0xffffffff) || (!(dwFa&FILE_ATTRIBUTE_DIRECTORY))) { NonFatalError( LoadRcString(IDS_INVALID_PATH) ); return FALSE; } if (strlen(buf) > 0) { strcpy( o.szLogPath, buf ); } o.fCrash = SendMessage( GetDlgItem( hwnd, ID_CRASH ), BM_GETCHECK, 0, 0 ); GetDlgItemText( hwnd, ID_CRASH_DUMP, buf, sizeof(buf) ); if (o.fCrash) { p = ExpandPath( buf ); if (p) { dwFa = GetFileAttributes( p ); free( p ); } else { dwFa = GetFileAttributes( buf ); } if (dwFa == 0xffffffff) { // // file does not exist, check to see if the dir is ok // p = ExpandPath( buf ); if (p) { p1 = p; } else { p1 = buf; } _splitpath( p1, szDrive, szDir, NULL, NULL ); _makepath( szPath, szDrive, szDir, NULL, NULL ); if (p) { free( p ); } dwFa = GetFileAttributes( szPath ); if (dwFa == 0xffffffff) { NonFatalError( LoadRcString(IDS_INVALID_CRASH_PATH) ); return FALSE; } } else if (dwFa & FILE_ATTRIBUTE_DIRECTORY) { NonFatalError( LoadRcString(IDS_INVALID_CRASH_PATH) ); return FALSE; } if (strlen(buf) > 0) { strcpy( o.szCrashDump, buf ); } } GetDlgItemText( hwnd, ID_WAVE_FILE, buf, sizeof(buf) ); if (strlen(buf) > 0) { dwFa = GetFileAttributes( buf ); if ((dwFa == 0xffffffff) || (dwFa&FILE_ATTRIBUTE_DIRECTORY)) { NonFatalError( LoadRcString(IDS_INVALID_WAVE) ); return FALSE; } } strcpy( o.szWaveFile, buf ); GetDlgItemText( hwnd, ID_NUM_CRASHES, buf, sizeof(buf) ); o.dwMaxCrashes = (DWORD) atol( buf ); GetDlgItemText( hwnd, ID_INSTRUCTIONS, buf, sizeof(buf) ); o.dwInstructions = (DWORD) atol( buf ); o.fDumpSymbols = SendMessage( GetDlgItem( hwnd, ID_DUMPSYMBOLS ), BM_GETCHECK, 0, 0 ); o.fDumpAllThreads = SendMessage( GetDlgItem( hwnd, ID_DUMPALLTHREADS ), BM_GETCHECK, 0, 0 ); o.fAppendToLogFile = SendMessage( GetDlgItem( hwnd, ID_APPENDTOLOGFILE ), BM_GETCHECK, 0, 0 ); o.fVisual = SendMessage( GetDlgItem( hwnd, ID_VISUAL ), BM_GETCHECK, 0, 0 ); o.fSound = SendMessage( GetDlgItem( hwnd, ID_SOUND ), BM_GETCHECK, 0, 0 ); RegSave( &o ); return TRUE; } BOOL CALLBACK EnumCrashesForViewer( PCRASHINFO crashInfo ) /*++ Routine Description: Enumeration function for crash records. This function is called once for each crash record. This function looks for s specific crash that is identified by the crashIndex. Arguments: crashInfo - pointer to a CRASHINFO structure Return Value: TRUE - caller should continue calling the enum procedure FALSE - caller should stop calling the enum procedure --*/ { char *p; if ((crashInfo->dwIndex == crashInfo->dwIndexDesired) && (crashInfo->dwCrashDataSize > 0) ) { p = crashInfo->pCrashData; crashInfo->pCrashData = malloc( crashInfo->dwCrashDataSize+10 ); memcpy( crashInfo->pCrashData, p, crashInfo->dwCrashDataSize+10 ); crashInfo->pCrashData[crashInfo->dwCrashDataSize] = 0; return FALSE; } crashInfo->dwIndex++; return TRUE; } BOOL CALLBACK LogFileViewerDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /*++ Routine Description: Window procedure for the log file viewer dialog box. Arguments: hwnd - window handle to the dialog box message - message number wParam - first message parameter lParam - second message parameter Return Value: TRUE - did not process the message FALSE - did process the message --*/ { static CRASHINFO crashInfo; HFONT hFont; switch (message) { case WM_INITDIALOG: crashInfo.dwIndex = 0; crashInfo.dwIndexDesired = lParam; ElEnumCrashes( &crashInfo, EnumCrashesForViewer ); if (crashInfo.dwIndex != crashInfo.dwIndexDesired) { MessageBeep( 0 ); EndDialog( hwnd, 0 ); return FALSE; } SetDlgItemText( hwnd, ID_LOGFILE_VIEW, crashInfo.pCrashData ); hFont = GetStockObject( SYSTEM_FIXED_FONT ); Assert( hFont != NULL ); SendDlgItemMessage( hwnd, ID_LOGFILE_VIEW, WM_SETFONT, (WPARAM) hFont, (LPARAM) FALSE ); return TRUE; case WM_COMMAND: if (wParam == IDOK) { free( crashInfo.pCrashData ); EndDialog( hwnd, 0 ); } break; } return FALSE; }