////////////////////////////////////////////////////////////////////////////// // // MAIN.C / ChkDskW // // Microsoft Confidential // Copyright (c) Microsoft Corporation 1998 // All rights reserved // // 8/98 - Jason Cohen (JCOHEN) // ////////////////////////////////////////////////////////////////////////////// // Include file(s). // #include "main.h" #include #include // Global variable(s). // HINSTANCE g_hInstance; DWORD g_dwDrives; DWORD g_dwFlags; TCHAR g_cSageId; // Internal function prototype(s). // static INT_PTR CALLBACK Dlg_Proc(HWND, UINT, WPARAM, LPARAM); static BOOL Dlg_OnInitDialog(HWND, HWND, LPARAM); static VOID Dlg_OnCommand(HWND, INT, HWND, UINT); static BOOL Dlg_OnDrawItem(HWND, const DRAWITEMSTRUCT *); static VOID SetSageSettings(HWND, TCHAR); static VOID RunSageSettings(HWND, TCHAR); static DWORD GetSelectedDrives(HWND, DWORD); static BOOL TanslateCommandLine(LPTSTR); static VOID ProcessCommandLine(VOID); static DWORD GetCommandLineOptions(LPTSTR **); // External function prototype(s). // HANDLE SpawnChkdsk(HWND, DWORD); WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) { INT nReturn; g_hInstance = hInstance; g_dwFlags = 0; g_dwDrives = 0; ProcessCommandLine(); nReturn = (INT)DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAIN), NULL, (DLGPROC) Dlg_Proc); return nReturn; } static INT_PTR CALLBACK Dlg_Proc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { // Message cracking macros. // HANDLE_MSG(hDlg, WM_INITDIALOG, Dlg_OnInitDialog); HANDLE_MSG(hDlg, WM_COMMAND, Dlg_OnCommand); case WM_DRAWITEM: return Dlg_OnDrawItem(hDlg, (const DRAWITEMSTRUCT *) lParam); case WM_CLOSE: if ( g_dwFlags & SCANDISK_SCANNING ) g_dwFlags |= SCANDISK_CANCELSCAN; else EndDialog(hDlg, 0); default: return FALSE; } return TRUE; } static BOOL Dlg_OnInitDialog(HWND hDlg, HWND hwndFocus, LPARAM lParam) { TCHAR szBuffer[256]; LPTSTR lpBuffer; INT nIndex; UINT uDriveType; DWORD dwMask, dwDefault; TCHAR chDrive[] = _T("A:\\"); SHFILEINFO SHFileInfo; // Init the common control library (for the progress bar). // InitCommonControls(); // Set the icon for the dialog. // SetClassLongPtr(hDlg, GCLP_HICON, (LONG_PTR) LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_MAIN))); // Load any SAGERUN settings. // if ( g_dwFlags & SCANDISK_SAGERUN ) RunSageSettings(hDlg, g_cSageId); // Get the system drive so we know what to default to if there // are not already default drives specified in g_dwDrives. // if ( g_dwDrives ) dwDefault = g_dwDrives; else { szBuffer[0] = _T('\0'); if ( GetEnvironmentVariable(_T("SystemDrive"), szBuffer, sizeof(szBuffer)) && szBuffer[0] ) dwDefault = 1 << (UPPER(szBuffer[0]) - _T('A')); else dwDefault = 4; // Default to the C: drive. } // Populate the list box with the drives to scan. // g_dwDrives = GetLogicalDrives(); for (dwMask = 1; g_dwDrives & ~(dwMask - 1); dwMask <<= 1) { // Is there a logical drive? // if ( g_dwDrives & dwMask ) { // Reset this bit, we will or it back in if it gets // added to the list box. // g_dwDrives &= ~dwMask; // Check the drive type and it is // removable or fixed, add it to the // list box along with the icon. // uDriveType = GetDriveType(chDrive); if ( ( uDriveType == DRIVE_FIXED ) || ( uDriveType == DRIVE_REMOVABLE ) ) { SHGetFileInfo(chDrive, 0, &SHFileInfo, sizeof(SHFILEINFO), SHGFI_ICON | SHGFI_SMALLICON | SHGFI_DISPLAYNAME | SHGFI_TYPENAME); if ( (nIndex = (INT)SendDlgItemMessage(hDlg, IDC_DRIVES, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) SHFileInfo.szDisplayName)) >= 0 ) { // Or back in this bit because we successfully added // the drive to the list box. // g_dwDrives |= dwMask; SendDlgItemMessage(hDlg, IDC_DRIVES, LB_SETITEMDATA, nIndex, (LPARAM) SHFileInfo.hIcon); // If this is the boot drive, we want to selecte it. // if (dwMask & dwDefault) SendDlgItemMessage(hDlg, IDC_DRIVES, LB_SETSEL, TRUE, (LPARAM) nIndex); } } } // Go look at the next drive // chDrive[0]++; } // Check for if we are in the SAGESET mode. // if ( g_dwFlags & SCANDISK_SAGESET ) { if ( lpBuffer = AllocateString(NULL, IDS_OK) ) { SetDlgItemText(hDlg, IDOK, lpBuffer); FREE(lpBuffer); } if ( lpBuffer = AllocateString(NULL, IDS_CANCEL) ) { SetDlgItemText(hDlg, IDCANCEL, lpBuffer); FREE(lpBuffer); } ShowWindow(GetDlgItem(hDlg, IDC_PROGRESS), SW_HIDE); } // Set the estimated time. // srand(GetTickCount()); wsprintf(szBuffer, _T("%d hour(s) %d minute(s)"), RANDOM(0, 1), RANDOM(1, 59)); SetDlgItemText(hDlg, IDC_ESTIMATED, szBuffer); // Set the default option. // CheckRadioButton(hDlg, IDC_FIX, IDC_REMIND, IDC_FIX); EnableWindow(GetDlgItem(hDlg, IDC_TIME), FALSE); // Set the default remind time. // SetDlgItemText(hDlg, IDC_TIME, _T("5:00 PM")); // Set the focus to the default button. // SetFocus(GetDlgItem(hDlg, IDOK)); // If we are in SAGERUN mode, start the scan automatically. // if ( g_dwFlags & SCANDISK_SAGERUN ) { if ( SpawnChkdsk(hDlg, g_dwDrives) == NULL ) EndDialog(hDlg, 0); } return FALSE; } static VOID Dlg_OnCommand(HWND hDlg, INT id, HWND hwndCtl, UINT codeNotify) { switch (id) { case IDOK: if ( g_dwFlags & SCANDISK_SAGESET ) { // Just save the settings and end the dialog. // SetSageSettings(hDlg, g_cSageId); EndDialog(hDlg, 0); } else { // Run chkdsk on the drive(s). // if ( SpawnChkdsk(hDlg, g_dwDrives) == NULL ) EndDialog(hDlg, 0); } break; case IDCANCEL: if ( g_dwFlags & SCANDISK_SCANNING ) g_dwFlags |= SCANDISK_CANCELSCAN; else EndDialog(hDlg, 0); break; case IDC_RESTART: case IDC_SKIP: case IDC_REMIND: EnableWindow(GetDlgItem(hDlg, IDC_TIME), id == IDC_REMIND); break; } } static BOOL Dlg_OnDrawItem(HWND hWnd, const DRAWITEMSTRUCT * lpDrawItem) { HICON hIcon; TCHAR szBuffer[MAX_PATH]; BOOL bRestore = FALSE; COLORREF crText, crBk; DWORD dwColor; RECT rect; HBRUSH hbrBack; // Make sure we are drawing the right control and an item. // if ( lpDrawItem->CtlID != IDC_DRIVES ) return FALSE; switch ( lpDrawItem->itemAction ) { case ODA_SELECT: case ODA_DRAWENTIRE: if (lpDrawItem->itemState & ODS_SELECTED) { // Set new text/background colors and store the old ones away. // crText = SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); crBk = SetBkColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHT)); // Restore the text and background colors when we are finished. // bRestore = TRUE; // Get the hightlight color to fill in the listbox item. // dwColor = GetSysColor(COLOR_HIGHLIGHT); } else { // Get the window color so we can clear the listbox item. // dwColor = GetSysColor(COLOR_WINDOW); } // Fill entire item rectangle with the appropriate color // hbrBack = CreateSolidBrush(dwColor); FillRect(lpDrawItem->hDC, &(lpDrawItem->rcItem), hbrBack); DeleteObject(hbrBack); // Display the icon associated with the item. // if ( hIcon = (HICON) SendMessage(lpDrawItem->hwndItem, LB_GETITEMDATA, lpDrawItem->itemID, (LPARAM) 0) ) { DrawIconEx( lpDrawItem->hDC, lpDrawItem->rcItem.left + 2, lpDrawItem->rcItem.top, hIcon, lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top, lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top, 0, 0, DI_NORMAL); } // Display the text associated with the item. // if ( SendMessage(lpDrawItem->hwndItem, LB_GETTEXT, lpDrawItem->itemID, (LPARAM) szBuffer) >= 0 ) { TextOut( lpDrawItem->hDC, lpDrawItem->rcItem.left + lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top + 4, lpDrawItem->rcItem.top + 1, szBuffer, lstrlen(szBuffer)); } if (bRestore) { // Restore original text and background colors. // SetTextColor(lpDrawItem->hDC, crText); SetBkColor(lpDrawItem->hDC, crBk); } break; case ODA_FOCUS: // Get rectangle coordinates for listbox item. // SendMessage(lpDrawItem->hwndItem, LB_GETITEMRECT, lpDrawItem->itemID, (LPARAM) &rect); DrawFocusRect(lpDrawItem->hDC, &rect); break; } return TRUE; } static VOID SetSageSettings(HWND hDlg, TCHAR cSageId) { TCHAR szRegKey[MAX_PATH + 1]; wsprintf(szRegKey, _T("%s\\%c"), SCANDISK_REGKEY_SAGE, cSageId); RegSetDword(HKCU, szRegKey, SCANDISK_REGVAL_DRIVES, GetSelectedDrives(hDlg, g_dwDrives)); RegSetString(HKCU, szRegKey, SCANDISK_REGVAL_FIX, IsDlgButtonChecked(hDlg, IDC_AUTOFIX) ? _T("1") : _T("0")); RegSetString(HKCU, szRegKey, SCANDISK_REGVAL_SURFACE, IsDlgButtonChecked(hDlg, IDC_SURFACE) ? _T("1") : _T("0")); } static VOID RunSageSettings(HWND hDlg, TCHAR cSageId) { TCHAR szRegKey[MAX_PATH + 1]; wsprintf(szRegKey, _T("%s\\%c"), SCANDISK_REGKEY_SAGE, cSageId); g_dwDrives = RegGetDword(HKCU, szRegKey, SCANDISK_REGVAL_DRIVES); CheckDlgButton(hDlg, IDC_AUTOFIX, RegCheck(HKCU, szRegKey, SCANDISK_REGVAL_FIX) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hDlg, IDC_SURFACE, RegCheck(HKCU, szRegKey, SCANDISK_REGVAL_SURFACE) ? BST_CHECKED : BST_UNCHECKED); } static DWORD GetSelectedDrives(HWND hDlg, DWORD dwDrives) { TCHAR szDrive[] = _T("A:\\"); INT nCount, nIndex; LPINT lpnSelected, lpnIndex; DWORD dwMask; // Get the number of selected items and allocate a buffer to hold all the indexs. // if ( ( (nCount = (INT)SendDlgItemMessage(hDlg, IDC_DRIVES, LB_GETSELCOUNT, 0, 0L)) > 0 ) && ( lpnSelected = (LPINT) MALLOC(nCount * sizeof(INT)) ) ) { // Now get the list of selected items. // if ( (nCount = (INT)SendDlgItemMessage(hDlg, IDC_DRIVES, LB_GETSELITEMS, nCount, (LPARAM) lpnSelected)) > 0 ) { // Loop through all the drives in the list box to see if they // are selected. // lpnIndex = lpnSelected; nIndex = 0; for (dwMask = 1; (DWORD) dwDrives & ~(dwMask - 1); dwMask <<= 1) { // Is this drive in the list box. // if ( (DWORD) dwDrives & dwMask ) { // Test to see if this item is the // next selected one. // if ( *lpnIndex == nIndex ) lpnIndex++; else // It isn't selected so set // the bit to zero. // dwDrives &= ~dwMask; // Keep an index of what list box // item this should be. // nIndex++; } // Go look at the next drive // szDrive[0]++; } } else dwDrives = 0; FREE(lpnSelected); } else dwDrives = 0; // Return drives selected (zero of failure). // return dwDrives; } static BOOL TanslateCommandLine(LPTSTR lpArg) { DWORD dwStrLen = lstrlen(lpArg); BOOL bTranslated = TRUE; // First check for the slash options. // if ( *lpArg == _T('/') ) { // Get rid of the slash. // lpArg++; // Check for /SAGESET:# // if ( _tcsncicmp(_T("SAGESET:"), lpArg, 8) == 0 ) { if ( !(g_dwFlags & (SCANDISK_SAGESET | SCANDISK_SAGERUN) ) ) { g_dwFlags |= SCANDISK_SAGESET; g_cSageId = *(lpArg + 8); } } // Check for /SAGERUN:# // else if ( _tcsncicmp(_T("SAGERUN:"), lpArg, 8) == 0 ) { if ( !(g_dwFlags & (SCANDISK_SAGESET | SCANDISK_SAGERUN) ) ) { g_dwFlags |= SCANDISK_SAGERUN; g_cSageId = *(lpArg + 8); } } // Unknown option. // else bTranslated = FALSE; } else { // Check to see if it is a drive letter to auto select. // if ( ( UPPER(*lpArg) >= _T('A') ) && ( UPPER(*lpArg) <= _T('Z') ) && // Make sure the first character is a letter. ( ( dwStrLen == 1) || ( ( dwStrLen > 1 ) && ( *(lpArg + 1) == _T(':') ) ) ) ) // Make sure it is one character or the second is a colon. { g_dwDrives |= 1 << (UPPER(*lpArg) - _T('A')); } // Unknown option. // else bTranslated = FALSE; } return bTranslated; } static VOID ProcessCommandLine() { LPTSTR *lpArgs = NULL; DWORD dwArgs, dwIndex; dwArgs = GetCommandLineOptions(&lpArgs); for (dwIndex = 1; dwIndex < dwArgs; dwIndex++) TanslateCommandLine((LPTSTR) *(lpArgs + dwIndex)); FREE(lpArgs); } static DWORD GetCommandLineOptions(LPTSTR **lpArgs) { TCHAR cParse; LPTSTR lpSearch, lpCommandLine; DWORD dwArgs = 0, dwMaxArgs = 0xFFFFFFFF; // Make sure we get the command line. // if ( (lpSearch = lpCommandLine = GetCommandLine()) == NULL ) return 0; // Get the number of arguments so we can allocate // the memory for the array of command line options. // if ( lpArgs ) { if ( (dwMaxArgs = GetCommandLineOptions(NULL)) == 0 ) return 0; if ( (*lpArgs = (LPTSTR *) MALLOC(sizeof(LPTSTR) * dwMaxArgs)) == NULL ) return 0; } // Now lets parse the arguments. // while ( *lpSearch && (dwArgs < dwMaxArgs) ) { // Eat all preceeding spaces. // while ( *lpSearch == _T(' ') ) lpSearch++; // Check to see if we need to look for a space or a quote // to separate the next argument. // if ( *lpSearch == _T('"') ) cParse = *lpSearch++; else cParse = _T(' '); // This is be the beginning of the next argument, but // it isn't NULL terminated yet. // if ( lpArgs ) *(*lpArgs + dwArgs) = lpSearch; dwArgs++; // Go through all the characters until we hit a separator. // do { // Once we get to a quote, we just want to keep going // until we get to a space. // if ( *lpSearch == _T('"') ) cParse = _T(' '); // Only end when we reach the parsing character, which will // always be the space by this time (but the space won't trigger // the end until we hit a quote, if that is what we were originally // looking for). We also need to make sure that we don't increment // past the NULL terminator. // } while ( ( *lpSearch != cParse ) && ( *lpSearch ) && ( *lpSearch++ ) ); // If the preceeding character is a quote, that is were we want to // place the NULL terminator. // if ( ( lpSearch > lpCommandLine ) && ( *(lpSearch - 1) == _T('"') ) ) lpSearch--; // Set and increment past the NULL terminator only if we aren't already at // the end if the string. // if ( lpArgs && *lpSearch ) *lpSearch++ = _T('\0'); else if ( *lpSearch ) lpSearch++; } return dwArgs; }