/*++ Copyright (c) 1993-2001 Microsoft Corporation Module Name: ui.cpp 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 "pch.cpp" void InitializeDialog( HWND hwnd ); void InitializeCrashList( HWND hwnd ); BOOL GetDialogValues( HWND hwnd ); INT_PTR CALLBACK LogFileViewerDialogProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); INT_PTR CALLBACK DrWatsonDialogProc ( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam ); PTSTR ExpandPath( PTSTR lpPath ); const DWORD DrWatsonHelpIds[] = { ID_LOGPATH_TEXT, IDH_LOG_FILE_PATH, ID_LOGPATH, IDH_LOG_FILE_PATH, ID_BROWSE_LOGPATH, IDH_BROWSE, ID_CRASH_DUMP_TEXT, IDH_CRASH_DUMP, ID_CRASH_DUMP, IDH_CRASH_DUMP, ID_BROWSE_CRASH, IDH_BROWSE, ID_WAVEFILE_TEXT, IDH_WAVE_FILE, ID_WAVE_FILE, IDH_WAVE_FILE, ID_BROWSE_WAVEFILE, IDH_BROWSE, ID_INSTRUCTIONS, IDH_NUMBER_OF_INSTRUCTIONS, ID_NUM_CRASHES, IDH_NUMBER_OF_ERRORS_TO_SAVE, ID_DUMPSYMBOLS, IDH_DUMP_SYMBOL_TABLE, ID_DUMPALLTHREADS, IDH_DUMP_ALL_THREAD_CONTEXTS, ID_APPENDTOLOGFILE, IDH_APPEND_TO_EXISTING_LOGFILE, ID_VISUAL, IDH_VISUAL_NOTIFICATION, ID_SOUND, IDH_SOUND_NOTIFICATION, ID_CRASH, IDH_CREATE_CRASH_DUMP_FILE, ID_LOGFILE_VIEW, IDH_VIEW, ID_CLEAR, IDH_CLEAR, ID_CRASHES, IDH_APPLICATION_ERRORS, ID_TEST_WAVE, IDH_WAVE_FILE, psh15, IDH_INDEX, 0, 0 }; void DrWatsonWinMain( void ) /*++ Routine Description: This is the entry point for DRWTSN32 Arguments: None. Return Value: None. --*/ { HWND hwnd; MSG msg; HINSTANCE hInst; WNDCLASS wndclass; hInst = GetModuleHandle( NULL ); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = (WNDPROC)DrWatsonDialogProc; 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 = _T("DrWatsonDialog"); RegisterClass( &wndclass ); hwnd = CreateDialog( hInst, MAKEINTRESOURCE( DRWATSONDIALOG ), 0, DrWatsonDialogProc ); if (hwnd == NULL) { return; } ShowWindow( hwnd, SW_SHOWNORMAL ); while (GetMessage (&msg, NULL, 0, 0)) { if (!IsDialogMessage( hwnd, &msg )) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } } return; } INT_PTR CALLBACK DrWatsonDialogProc ( 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; DWORD ctlId; UINT Checked; _TCHAR szCurrDir[MAX_PATH]; _TCHAR szWave[MAX_PATH]; _TCHAR szDump[MAX_PATH]; _TCHAR szHelpFileName[MAX_PATH]; PTSTR p; PDWORD pdw; switch (message) { case WM_CREATE: return 0; case WM_INITDIALOG: SubclassControls( hwnd ); InitializeDialog( hwnd ); return 1; case WM_HELP: // F1 key and ? ctlId = ((LPHELPINFO)lParam)->iCtrlId; helpId = IDH_INDEX; for (pdw = (PDWORD)DrWatsonHelpIds; *pdw; pdw+=2) { if (*pdw == ctlId) { helpId = pdw[1]; break; } } if ( helpId == IDH_BROWSE ) { _tcscpy( szHelpFileName, _T("windows.hlp") ); } else { GetWinHelpFileName( szHelpFileName, sizeof(szHelpFileName) / sizeof(_TCHAR) ); } WinHelp( (HWND)((LPHELPINFO) lParam)->hItemHandle, szHelpFileName, HELP_WM_HELP, (DWORD_PTR)(LPVOID)DrWatsonHelpIds ); return TRUE; case WM_CONTEXTMENU: // right mouse click if( hwnd == (HWND) wParam ) { POINT pt; GetCursorPos(&pt); ScreenToClient(hwnd, &pt); wParam = (WPARAM) ChildWindowFromPoint(hwnd, pt); } ctlId = GetDlgCtrlID((HWND)wParam); helpId = IDH_INDEX; for (pdw = (PDWORD)DrWatsonHelpIds; *pdw; pdw+=2) { if (*pdw == ctlId) { helpId = pdw[1]; break; } } if ( helpId == IDH_BROWSE ) { _tcscpy( szHelpFileName, _T("windows.hlp") ); } else { GetWinHelpFileName( szHelpFileName, sizeof(szHelpFileName) / sizeof(_TCHAR) ); } WinHelp((HWND)wParam, szHelpFileName, HELP_CONTEXTMENU, (DWORD_PTR)DrWatsonHelpIds ); return TRUE; case WM_ACTIVATEAPP: case WM_SETFOCUS: SetFocusToCurrentControl(); return 0; case WM_SYSCOMMAND: if (wParam == ID_ABOUT) { _TCHAR title[256]; _TCHAR extra[256]; _tcscpy( title, LoadRcString( IDS_ABOUT_TITLE ) ); _tcscpy( 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 )) { HtmlHelp( NULL, NULL, HH_CLOSE_ALL, 0); PostQuitMessage( 0 ); } break; case IDCANCEL: HtmlHelp( NULL, NULL, HH_CLOSE_ALL, 0); PostQuitMessage( 0 ); break; case ID_BROWSE_LOGPATH: GetDlgItemText( hwnd, ID_LOGPATH, szCurrDir, MAX_PATH ); p = ExpandPath( szCurrDir ); if (p) { _tcscpy( szCurrDir, p ); free( p ); } EnableWindow( GetDlgItem( hwnd, ID_BROWSE_LOGPATH ), FALSE ); if (BrowseForDirectory(hwnd, 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] = _T('\0'); GetDlgItemText( hwnd, ID_WAVE_FILE, szWave, MAX_PATH ); EnableWindow( GetDlgItem( hwnd, ID_BROWSE_WAVEFILE ), FALSE ); if (GetWaveFileName(hwnd, 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] = _T('\0'); GetDlgItemText( hwnd, ID_CRASH_DUMP, szDump, MAX_PATH ); EnableWindow( GetDlgItem( hwnd, ID_BROWSE_CRASH ), FALSE ); if (GetDumpFileName(hwnd, 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) / sizeof(_TCHAR) ); 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 IDHELP: // // call HtmlHelp // GetHtmlHelpFileName( szHelpFileName, sizeof(szHelpFileName) / sizeof(_TCHAR) ); HtmlHelp( hwnd, szHelpFileName, HH_DISPLAY_TOPIC, (DWORD_PTR)(IDHH_INDEX) ); SetFocus( GetDlgItem(hwnd, IDHELP) ); 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 ); EnableWindow( GetDlgItem( hwnd, ID_DUMP_TYPE_TEXT ), Checked == 1 ); EnableWindow( GetDlgItem( hwnd, ID_DUMP_TYPE_FULL_OLD ), Checked == 1 ); EnableWindow( GetDlgItem( hwnd, ID_DUMP_TYPE_MINI ), Checked == 1 ); EnableWindow( GetDlgItem( hwnd, ID_DUMP_TYPE_FULLMINI ), Checked == 1 ); } if (((HWND)lParam == GetDlgItem( hwnd, ID_SOUND )) && (HIWORD( wParam ) == BN_CLICKED)) { Checked = IsDlgButtonChecked( hwnd, ID_SOUND ); EnableWindow( GetDlgItem( hwnd, ID_WAVEFILE_TEXT ), Checked == 1 ); EnableWindow( GetDlgItem( hwnd, ID_WAVE_FILE ), Checked == 1 ); EnableWindow( GetDlgItem( hwnd, ID_BROWSE_WAVEFILE ), Checked == 1 ); } break; } break; case IDH_WAVE_FILE: // // call HtmlHelp // GetHtmlHelpFileName( szHelpFileName, sizeof(szHelpFileName) / sizeof(_TCHAR) ); HtmlHelp(hwnd, szHelpFileName, HH_DISPLAY_TOPIC, (DWORD_PTR)(IDHH_WAVEFILE) ); break; case IDH_CRASH_DUMP: // // call HtmlHelp // GetHtmlHelpFileName( szHelpFileName, sizeof(szHelpFileName) / sizeof(_TCHAR) ); HtmlHelp( hwnd, szHelpFileName, HH_DISPLAY_TOPIC, (DWORD_PTR)(IDHH_LOGFILELOCATION) ); break; case WM_DESTROY: HtmlHelp( NULL, NULL, HH_CLOSE_ALL, 0); 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; _TCHAR buf[1024]; _stprintf( buf, _T("%s %08x %s(%08p)"), crashInfo->crash.szAppName, crashInfo->crash.dwExceptionCode, crashInfo->crash.szFunction, crashInfo->crash.dwAddress ); SendMessage( crashInfo->hList, LB_ADDSTRING, 0, (LPARAM)buf ); GetTextExtentPoint( crashInfo->hdc, buf, _tcslen(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 ); } if (crashInfo.hdc != NULL) { 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; _TCHAR 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 ); _stprintf( buf, _T("%d"), o.dwMaxCrashes ); SetDlgItemText( hwnd, ID_NUM_CRASHES, buf ); _stprintf( buf, _T("%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 ); SendMessage( GetDlgItem( hwnd, ID_DUMP_TYPE_FULL_OLD ), BM_SETCHECK, o.dwType == FullDump, 0 ); SendMessage( GetDlgItem( hwnd, ID_DUMP_TYPE_MINI ), BM_SETCHECK, o.dwType == MiniDump, 0 ); SendMessage( GetDlgItem( hwnd, ID_DUMP_TYPE_FULLMINI ), BM_SETCHECK, o.dwType == FullMiniDump, 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 ); } else { EnableWindow( GetDlgItem( hwnd, ID_WAVEFILE_TEXT ), o.fSound ); EnableWindow( GetDlgItem( hwnd, ID_WAVE_FILE ), o.fSound ); EnableWindow( GetDlgItem( hwnd, ID_BROWSE_WAVEFILE ), o.fSound ); } 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 ); EnableWindow( GetDlgItem( hwnd, ID_DUMP_TYPE_TEXT ), o.fCrash ); EnableWindow( GetDlgItem( hwnd, ID_DUMP_TYPE_FULL_OLD ), o.fCrash ); EnableWindow( GetDlgItem( hwnd, ID_DUMP_TYPE_MINI ), o.fCrash ); EnableWindow( GetDlgItem( hwnd, ID_DUMP_TYPE_FULLMINI ), 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; _TCHAR buf[256]; DWORD dwFa; PTSTR p,p1; _TCHAR szDrive [_MAX_DRIVE]; _TCHAR szDir [_MAX_DIR]; _TCHAR szPath [MAX_PATH]; RegInitialize( &o ); GetDlgItemText( hwnd, ID_LOGPATH, buf, sizeof(buf) / sizeof(_TCHAR) ); 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 (_tcslen(buf) > 0) { _tcscpy( o.szLogPath, buf ); } o.fCrash = SendMessage( GetDlgItem( hwnd, ID_CRASH ), BM_GETCHECK, 0, 0 ) ? TRUE : FALSE; GetDlgItemText( hwnd, ID_CRASH_DUMP, buf, sizeof(buf) / sizeof(_TCHAR) ); 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; } _tsplitpath( p1, szDrive, szDir, NULL, NULL ); _tmakepath( 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 (_tcslen(buf) > 0) { _tcscpy( o.szCrashDump, buf ); } if (SendMessage( GetDlgItem( hwnd, ID_DUMP_TYPE_FULL_OLD ), BM_GETCHECK, 0, 0 )) { o.dwType = FullDump; } else if (SendMessage( GetDlgItem( hwnd, ID_DUMP_TYPE_MINI ), BM_GETCHECK, 0, 0 )) { o.dwType = MiniDump; } else if (SendMessage( GetDlgItem( hwnd, ID_DUMP_TYPE_FULLMINI ), BM_GETCHECK, 0, 0 )) { o.dwType = FullMiniDump; } } GetDlgItemText( hwnd, ID_WAVE_FILE, buf, sizeof(buf) / sizeof(_TCHAR) ); if (_tcslen(buf) > 0) { dwFa = GetFileAttributes( buf ); if ((dwFa == 0xffffffff) || (dwFa&FILE_ATTRIBUTE_DIRECTORY)) { NonFatalError( LoadRcString(IDS_INVALID_WAVE) ); return FALSE; } } _tcscpy( o.szWaveFile, buf ); GetDlgItemText( hwnd, ID_NUM_CRASHES, buf, sizeof(buf) / sizeof(_TCHAR) ); o.dwMaxCrashes = (DWORD) _ttol( buf ); GetDlgItemText( hwnd, ID_INSTRUCTIONS, buf, sizeof(buf) / sizeof(_TCHAR) ); o.dwInstructions = (DWORD) _ttol( buf ); o.fDumpSymbols = SendMessage( GetDlgItem( hwnd, ID_DUMPSYMBOLS ), BM_GETCHECK, 0, 0 ) ? TRUE : FALSE; o.fDumpAllThreads = SendMessage( GetDlgItem( hwnd, ID_DUMPALLTHREADS ), BM_GETCHECK, 0, 0 ) ? TRUE : FALSE; o.fAppendToLogFile = SendMessage( GetDlgItem( hwnd, ID_APPENDTOLOGFILE ), BM_GETCHECK, 0, 0 ) ? TRUE : FALSE; o.fVisual = SendMessage( GetDlgItem( hwnd, ID_VISUAL ), BM_GETCHECK, 0, 0 ) ? TRUE : FALSE; o.fSound = SendMessage( GetDlgItem( hwnd, ID_SOUND ), BM_GETCHECK, 0, 0 ) ? TRUE : FALSE; 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 --*/ { PWSTR p; if ((crashInfo->dwIndex == crashInfo->dwIndexDesired) && (crashInfo->dwCrashDataSize > 0) ) { p = (PWSTR)crashInfo->pCrashData; crashInfo->pCrashData = (PBYTE) calloc( crashInfo->dwCrashDataSize+10, sizeof(BYTE) ); if (crashInfo->pCrashData != NULL) { if (IsTextUnicode(p, crashInfo->dwCrashDataSize, NULL)) { WideCharToMultiByte(CP_ACP, WC_SEPCHARS | WC_COMPOSITECHECK, p, crashInfo->dwCrashDataSize, (LPSTR)crashInfo->pCrashData, crashInfo->dwCrashDataSize + 10, NULL, NULL); } else { memcpy( crashInfo->pCrashData, p, crashInfo->dwCrashDataSize+10 ); } crashInfo->pCrashData[crashInfo->dwCrashDataSize] = 0; } return FALSE; } crashInfo->dwIndex++; return TRUE; } INT_PTR 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: hFont = (HFONT)GetStockObject( SYSTEM_FIXED_FONT ); Assert( hFont != NULL ); SendDlgItemMessage( hwnd, ID_LOGFILE_VIEW, WM_SETFONT, (WPARAM) hFont, (LPARAM) FALSE ); crashInfo.dwIndex = 0; crashInfo.dwIndexDesired = (DWORD)lParam; ElEnumCrashes( &crashInfo, EnumCrashesForViewer ); if (crashInfo.dwIndex != crashInfo.dwIndexDesired) { MessageBeep( 0 ); EndDialog( hwnd, 0 ); return FALSE; } SetDlgItemTextA( hwnd, ID_LOGFILE_VIEW, (LPSTR)crashInfo.pCrashData ); return TRUE; case WM_COMMAND: if (wParam == IDOK) { free( crashInfo.pCrashData ); EndDialog( hwnd, 0 ); } break; case WM_CLOSE: free( crashInfo.pCrashData ); EndDialog( hwnd, 0 ); return TRUE; } return FALSE; }