620 lines
22 KiB
C
620 lines
22 KiB
C
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 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 "fmifs.h"
|
|
|
|
// Internal global variable(s).
|
|
//
|
|
static BOOL g_bSuccess;
|
|
static HWND g_hProgressDlg;
|
|
static HICON g_hIconScan[3];
|
|
|
|
|
|
// External global variable(s).
|
|
//
|
|
extern HINSTANCE g_hInstance;
|
|
extern DWORD g_dwFlags;
|
|
|
|
|
|
// Internal function prototype(s).
|
|
//
|
|
static DWORD WINAPI ThreadChkdsk(LPVOID);
|
|
static BOOL CALLBACK FmifsCallback(FMIFS_PACKET_TYPE, ULONG, PVOID);
|
|
static VOID UpdateStatus(LPSTR);
|
|
static VOID SummaryDialog(HWND, LPTSTR, BOOL);
|
|
static INT_PTR CALLBACK SummaryProc(HWND, UINT, WPARAM, LPARAM);
|
|
static BOOL Summary_OnInitDialog(HWND, HWND, LPARAM);
|
|
static FARPROC LoadDllFunction(LPTSTR, LPCSTR, HINSTANCE *);
|
|
|
|
|
|
HANDLE SpawnChkdsk(HWND hDlg, DWORD dwDrives)
|
|
{
|
|
DWORD dwThreadId;
|
|
|
|
// Set that we are scanning a drive currently.
|
|
//
|
|
g_dwFlags |= SCANDISK_SCANNING;
|
|
g_dwFlags &= ~SCANDISK_CANCELSCAN;
|
|
|
|
// Set up the global variables needed.
|
|
//
|
|
g_bSuccess = FALSE;
|
|
g_hProgressDlg = hDlg;
|
|
|
|
// Load the icons for the scanning animation.
|
|
//
|
|
g_hIconScan[0] = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SCAN1));
|
|
g_hIconScan[1] = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SCAN2));
|
|
g_hIconScan[2] = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_SCAN3));
|
|
|
|
// Create the thread that will run chkdsk.
|
|
//
|
|
return CreateThread(NULL, 0, ThreadChkdsk, (LPVOID)(ULONG_PTR)dwDrives, 0, &dwThreadId);
|
|
}
|
|
|
|
|
|
static DWORD WINAPI ThreadChkdsk(LPVOID dwDrives)
|
|
{
|
|
HINSTANCE hFmifsDll;
|
|
FARPROC Chkdsk;
|
|
WCHAR szwFileSystem[16],
|
|
szwDrive[] = L"A:\\";
|
|
TCHAR szBuffer[256];
|
|
INT nCount,
|
|
nIndex;
|
|
LPINT lpnSelected,
|
|
lpnIndex;
|
|
LPTSTR lpBuffer,
|
|
lpCaption,
|
|
lpCapPre;
|
|
DWORD_PTR dwMask;
|
|
BOOL bContinue,
|
|
bSurface,
|
|
bFix,
|
|
bAllHappy = FALSE;
|
|
|
|
// Load and run the Chkdsk function.
|
|
//
|
|
if ( (Chkdsk = LoadDllFunction(_T("FMIFS.DLL"), "Chkdsk", &hFmifsDll)) == NULL )
|
|
return 0;
|
|
|
|
// Get the number of selected items and allocate a buffer to hold all the indexs.
|
|
//
|
|
if ( ( (nCount = (INT)SendDlgItemMessage(g_hProgressDlg, IDC_DRIVES, LB_GETSELCOUNT, 0, 0L)) > 0 ) &&
|
|
( lpnSelected = (LPINT) MALLOC(nCount * sizeof(INT)) ) )
|
|
{
|
|
// Now get the list of selected items.
|
|
//
|
|
if ( (nCount = (INT)SendDlgItemMessage(g_hProgressDlg, IDC_DRIVES, LB_GETSELITEMS, nCount, (LPARAM) lpnSelected)) > 0 )
|
|
{
|
|
// Disable the controls.
|
|
//
|
|
EnableWindow(GetDlgItem(g_hProgressDlg, IDOK), FALSE);
|
|
EnableWindow(GetDlgItem(g_hProgressDlg, IDC_DRIVESTEXT), FALSE);
|
|
EnableWindow(GetDlgItem(g_hProgressDlg, IDC_DRIVES), FALSE);
|
|
EnableWindow(GetDlgItem(g_hProgressDlg, IDC_SURFACE), FALSE);
|
|
EnableWindow(GetDlgItem(g_hProgressDlg, IDC_AUTOFIX), FALSE);
|
|
|
|
// Change the text of the IDCANCEL button to Cancel (from Close).
|
|
//
|
|
if ( lpBuffer = AllocateString(NULL, IDS_CANCEL) )
|
|
{
|
|
SetDlgItemText(g_hProgressDlg, IDCANCEL, lpBuffer);
|
|
FREE(lpBuffer);
|
|
}
|
|
|
|
// Get the scan options.
|
|
//
|
|
bSurface = IsDlgButtonChecked(g_hProgressDlg, IDC_SURFACE);
|
|
bFix = IsDlgButtonChecked(g_hProgressDlg, IDC_AUTOFIX);
|
|
|
|
// Get the caption prefix.
|
|
//
|
|
lpCapPre = AllocateString(NULL, IDS_RESULTS);
|
|
|
|
// Loop through all the drives in the list box to see if they
|
|
// are selected.
|
|
//
|
|
lpnIndex = lpnSelected;
|
|
nIndex = 0;
|
|
bAllHappy = TRUE;
|
|
for (dwMask = 1; ((DWORD_PTR) dwDrives & ~(dwMask - 1)) && ( !(g_dwFlags & SCANDISK_CANCELSCAN) ); dwMask <<= 1)
|
|
{
|
|
// Is this drive in the list box.
|
|
//
|
|
if ( (DWORD_PTR) dwDrives & dwMask )
|
|
{
|
|
// Test to see if this item is the
|
|
// next selected one.
|
|
//
|
|
if ( *lpnIndex == nIndex )
|
|
{
|
|
//
|
|
// Ok, try and run chkdsk on this drive.
|
|
//
|
|
|
|
// Get the file system type.
|
|
//
|
|
bContinue = TRUE;
|
|
while ( bContinue && !GetVolumeInformationW(szwDrive, NULL, 0, NULL, NULL, NULL, szwFileSystem, sizeof(szwFileSystem)) )
|
|
{
|
|
bContinue = FALSE;
|
|
if ( ( GetLastError() == ERROR_NOT_READY ) &&
|
|
( lpBuffer = AllocateString(NULL, IDS_NOTREADY) ) )
|
|
{
|
|
if ( MessageBox(g_hProgressDlg, lpBuffer, NULL, MB_RETRYCANCEL | MB_ICONERROR) == IDRETRY )
|
|
bContinue = TRUE;
|
|
FREE(lpBuffer);
|
|
}
|
|
}
|
|
|
|
if ( bContinue )
|
|
{
|
|
// Now finally launch Chkdsk.
|
|
//
|
|
Chkdsk(szwDrive, szwFileSystem, FALSE, FALSE, FALSE, bSurface, NULL, FALSE, FmifsCallback);
|
|
|
|
// Make sure the user didn't cancel.
|
|
//
|
|
if ( !(g_dwFlags & SCANDISK_CANCELSCAN) )
|
|
{
|
|
// Check to see if the scan on this drive returned with errors or not.
|
|
//
|
|
if ( g_bSuccess )
|
|
{
|
|
// Get the text to use as the caption for the summary box.
|
|
//
|
|
if (lpCapPre)
|
|
lstrcpy(szBuffer, lpCapPre);
|
|
else
|
|
szBuffer[0] = _T('\0');
|
|
if ( SendDlgItemMessage(g_hProgressDlg, IDC_DRIVES, LB_GETTEXT, *lpnIndex, (LPARAM) szBuffer + (lstrlen(szBuffer) * sizeof(TCHAR))) > 0 )
|
|
lpCaption = szBuffer;
|
|
else
|
|
lpCaption = NULL;
|
|
|
|
// Display the summary message for this drive.
|
|
//
|
|
SummaryDialog(g_hProgressDlg, NULL, g_bSuccess);
|
|
|
|
}
|
|
else
|
|
{
|
|
bAllHappy = FALSE;
|
|
|
|
// If there were errors on this drive and the user
|
|
// wants to automatically fix them, we need to run
|
|
// the check disk function again with the fix error
|
|
// flag set (/F). We don't do this first because if
|
|
// the drive can't be locked it won't even scan the
|
|
// drive to see if there is an error before asking to
|
|
// check on reboot.
|
|
//
|
|
if ( bFix )
|
|
Chkdsk(szwDrive, szwFileSystem, TRUE, FALSE, FALSE, bSurface, NULL, FALSE, FmifsCallback);
|
|
}
|
|
}
|
|
|
|
// Make sure the memory for the summary dialog is freed.
|
|
//
|
|
SummaryDialog(NULL, NULL, FALSE);
|
|
|
|
// Reset the progress control.
|
|
//
|
|
SendDlgItemMessage(g_hProgressDlg, IDC_PROGRESS, PBM_SETPOS, 0, 0L);
|
|
SetDlgItemText(g_hProgressDlg, IDC_STATUS, NULLSTR);
|
|
}
|
|
lpnIndex++;
|
|
}
|
|
// Keep an index of what list box
|
|
// item this should be.
|
|
//
|
|
nIndex++;
|
|
}
|
|
|
|
// Go look at the next drive
|
|
//
|
|
szwDrive[0]++;
|
|
}
|
|
|
|
// Free the caption prefix.
|
|
//
|
|
FREE(lpCapPre);
|
|
|
|
// Renable the controls.
|
|
//
|
|
EnableWindow(GetDlgItem(g_hProgressDlg, IDOK), TRUE);
|
|
EnableWindow(GetDlgItem(g_hProgressDlg, IDC_DRIVES), TRUE);
|
|
EnableWindow(GetDlgItem(g_hProgressDlg, IDC_DRIVESTEXT), TRUE);
|
|
EnableWindow(GetDlgItem(g_hProgressDlg, IDC_SURFACE), TRUE);
|
|
EnableWindow(GetDlgItem(g_hProgressDlg, IDC_AUTOFIX), TRUE);
|
|
|
|
// Change the text of the IDCANCEL button back to Close.
|
|
//
|
|
if ( lpBuffer = AllocateString(NULL, IDS_CLOSE) )
|
|
{
|
|
SetDlgItemText(g_hProgressDlg, IDCANCEL, lpBuffer);
|
|
FREE(lpBuffer);
|
|
}
|
|
}
|
|
|
|
FREE(lpnSelected);
|
|
}
|
|
|
|
// Free the DLL library.
|
|
//
|
|
FreeLibrary(hFmifsDll);
|
|
|
|
// Reset the scaning bit.
|
|
//
|
|
g_dwFlags &= ~SCANDISK_SCANNING;
|
|
|
|
// If we are in SAGERUN mode, end the dialog now that
|
|
// we are finished scanning.
|
|
//
|
|
if ( g_dwFlags & SCANDISK_SAGERUN )
|
|
EndDialog(g_hProgressDlg, 0);
|
|
|
|
// Return the success or failure.
|
|
//
|
|
return (DWORD) bAllHappy;
|
|
}
|
|
|
|
|
|
|
|
|
|
static BOOL CALLBACK FmifsCallback(FMIFS_PACKET_TYPE PacketType, ULONG PacketLength, PVOID PacketData)
|
|
{
|
|
|
|
#ifdef _DEBUG
|
|
DWORD dwBytes;
|
|
TCHAR szDebug[1024] = NULLSTR;
|
|
HANDLE hFile = CreateFile(_T("C:\\SCANDISK.LOG"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
switch (PacketType)
|
|
{
|
|
case FmIfsPercentCompleted:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsPercentCompleted (%d%%)\r\n"), ((PFMIFS_PERCENT_COMPLETE_INFORMATION) PacketData)->PercentCompleted);
|
|
break;
|
|
case FmIfsFormatReport:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsFormatReport\r\n"));
|
|
break;
|
|
case FmIfsInsertDisk:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsInsertDisk\r\n"));
|
|
break;
|
|
case FmIfsIncompatibleFileSystem:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsIncompatibleFileSystem\r\n"));
|
|
break;
|
|
case FmIfsFormattingDestination:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsFormattingDestination\r\n"));
|
|
break;
|
|
case FmIfsIncompatibleMedia:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsIncompatibleMedia\r\n"));
|
|
break;
|
|
case FmIfsAccessDenied:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsAccessDenied\r\n"));
|
|
break;
|
|
case FmIfsMediaWriteProtected:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsMediaWriteProtected\r\n"));
|
|
break;
|
|
case FmIfsCantLock:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsCantLock\r\n"));
|
|
break;
|
|
case FmIfsCantQuickFormat:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsCantQuickFormat\r\n"));
|
|
break;
|
|
case FmIfsIoError:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsIoError\r\n"));
|
|
break;
|
|
case FmIfsFinished:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsFinished (%s)\r\n"), ((PFMIFS_FINISHED_INFORMATION) PacketData)->Success ? _T("TRUE") : _T("FALSE"));
|
|
break;
|
|
case FmIfsBadLabel:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsBadLabel\r\n"));
|
|
break;
|
|
case FmIfsCheckOnReboot:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsCheckOnReboot\r\n"));
|
|
break;
|
|
case FmIfsTextMessage:
|
|
break;
|
|
case FmIfsHiddenStatus:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsHiddenStatus\r\n"));
|
|
break;
|
|
case FmIfsClusterSizeTooSmall:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsClusterSizeTooSmall\r\n"));
|
|
break;
|
|
case FmIfsClusterSizeTooBig:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsClusterSizeTooBig\r\n"));
|
|
break;
|
|
case FmIfsVolumeTooSmall:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsVolumeTooSmall\r\n"));
|
|
break;
|
|
case FmIfsVolumeTooBig:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsVolumeTooBig\r\n"));
|
|
break;
|
|
case FmIfsNoMediaInDevice:
|
|
wsprintf(szDebug, _T("DEBUG: FmifsCallback() - FmIfsNoMediaInDevice\r\n"));
|
|
break;
|
|
}
|
|
|
|
if ( hFile != INVALID_HANDLE_VALUE )
|
|
{
|
|
if ( szDebug[0] )
|
|
{
|
|
SetFilePointer(hFile, 0, 0, FILE_END);
|
|
WriteFile(hFile, szDebug, lstrlen(szDebug) * sizeof(TCHAR), &dwBytes, NULL);
|
|
}
|
|
CloseHandle(hFile);
|
|
}
|
|
#endif // _DEBUG
|
|
|
|
switch (PacketType)
|
|
{
|
|
case FmIfsPercentCompleted:
|
|
// Advance the current position of the progress bar
|
|
// to the percent returned.
|
|
//
|
|
SendDlgItemMessage(g_hProgressDlg, IDC_PROGRESS, PBM_SETPOS, ((PFMIFS_PERCENT_COMPLETE_INFORMATION) PacketData)->PercentCompleted, 0L);
|
|
SendDlgItemMessage(g_hProgressDlg, IDC_SCANDISK, STM_SETIMAGE, IMAGE_ICON, (LPARAM) g_hIconScan[((PFMIFS_PERCENT_COMPLETE_INFORMATION) PacketData)->PercentCompleted % 3]);
|
|
break;
|
|
|
|
case FmIfsFinished:
|
|
g_bSuccess = !((PFMIFS_FINISHED_INFORMATION) PacketData)->Success;
|
|
break;
|
|
|
|
case FmIfsTextMessage:
|
|
UpdateStatus(((PFMIFS_TEXT_MESSAGE) PacketData)->Message);
|
|
break;
|
|
|
|
case FmIfsCheckOnReboot:
|
|
((PFMIFS_CHECKONREBOOT_INFORMATION) PacketData)->QueryResult =
|
|
(MessageBox(g_hProgressDlg, _T("This drive contains errors and must be checked on startup.\n\n")
|
|
_T("Do you want this drive to be checked next time you restart you computer?"), _T("Scandisk"), MB_YESNO | MB_ICONERROR) == IDYES);
|
|
break;
|
|
}
|
|
|
|
return ( !(g_dwFlags & SCANDISK_CANCELSCAN) );
|
|
}
|
|
|
|
|
|
static VOID UpdateStatus(LPSTR lpText)
|
|
{
|
|
TCHAR szTextOut[256];
|
|
LPTSTR lpChkDsk = NULL,
|
|
lpScanDisk = NULL,
|
|
lpSearch,
|
|
lpCopy,
|
|
lpNewText;
|
|
DWORD dwLen;
|
|
HANDLE hFile = INVALID_HANDLE_VALUE;
|
|
#ifdef _UNICODE
|
|
TCHAR wcHeader = 0x0000;
|
|
TCHAR szNewText[256];
|
|
#endif // _UNICODE
|
|
|
|
#ifdef _UNICODE
|
|
if ( MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, lpText, -1, szNewText, sizeof(szNewText)) )
|
|
{
|
|
// If this is unicode, make sure the poitner passed in points to a unicode string.
|
|
//
|
|
lpNewText = szNewText;
|
|
|
|
// See if we need to write the header bit so that notepad will
|
|
// see the file as unicode.
|
|
//
|
|
if ( (hFile = CreateFile(_T("C:\\SCANDISK.LOG"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE )
|
|
wcHeader = 0xFEFF;
|
|
#else // _UNICODE
|
|
lpNewText = lpText;
|
|
#endif // _UNICODE
|
|
|
|
// Write to the log file.
|
|
//
|
|
if ( ( hFile != INVALID_HANDLE_VALUE ) ||
|
|
( (hFile = CreateFile(_T("C:\\SCANDISK.LOG"), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE ) )
|
|
{
|
|
#ifdef _UNICODE
|
|
if ( wcHeader )
|
|
WriteFile(hFile, &wcHeader, sizeof(WCHAR), &dwLen, NULL);
|
|
#endif // _UNICODE
|
|
SetFilePointer(hFile, 0, 0, FILE_END);
|
|
WriteFile(hFile, (LPTSTR) lpNewText, lstrlen((LPTSTR) lpNewText) * sizeof(TCHAR), &dwLen, NULL);
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
// Remove proceeding characters we don't want (space, \r, \n, \t).
|
|
//
|
|
for (lpSearch = (LPTSTR) lpNewText; (*lpSearch == _T(' ')) || (*lpSearch == _T('\r')) || (*lpSearch == _T('\n')) || (*lpSearch == _T('\t')); lpSearch++);
|
|
|
|
if ( ISNUM(*lpSearch) )
|
|
{
|
|
// We want this info for the summary page.
|
|
//
|
|
SummaryDialog(g_hProgressDlg, lpSearch, FALSE);
|
|
}
|
|
else
|
|
{
|
|
if ( ( lpChkDsk = AllocateString(NULL, IDS_CHKDSK) ) &&
|
|
( lpScanDisk = AllocateString(NULL, IDS_SCANDISK) ) )
|
|
{
|
|
dwLen = lstrlen(lpChkDsk);
|
|
lpCopy = szTextOut;
|
|
while ( (*lpSearch != _T('\0')) && (*lpSearch != _T('\r')) )
|
|
{
|
|
if ( _tcsncmp(lpSearch, lpChkDsk, dwLen) == 0 )
|
|
{
|
|
lstrcpy(lpCopy, lpScanDisk);
|
|
lpSearch += dwLen;
|
|
lpCopy += lstrlen(lpScanDisk);
|
|
}
|
|
else
|
|
*lpCopy++ = *lpSearch++;
|
|
}
|
|
*lpCopy = _T('\0');
|
|
SetDlgItemText(g_hProgressDlg, IDC_STATUS, szTextOut);
|
|
}
|
|
FREE(lpScanDisk);
|
|
FREE(lpChkDsk);
|
|
}
|
|
#ifdef _UNICODE
|
|
}
|
|
#endif // _UNICODE
|
|
}
|
|
|
|
|
|
static VOID SummaryDialog(HWND hWndParent, LPTSTR lpText, BOOL bSuccess)
|
|
{
|
|
static LPTSTR lpSumText[16];
|
|
static DWORD dwIndex = 0;
|
|
|
|
LPTSTR lpSearch;
|
|
|
|
// First check to make sure lpText is a valid pointer. If it is NULL
|
|
// then we must be showing the summary dialog and/or freeing the memory.
|
|
//
|
|
if ( lpText )
|
|
{
|
|
// Make sure we don't already have 16 strings in our buffer.
|
|
//
|
|
if ( dwIndex < 16 )
|
|
{
|
|
//
|
|
// lpText should already point to the first digit of the number
|
|
// part of the summary.
|
|
//
|
|
|
|
// We need a pointer to the text after the number. We will search
|
|
// for the first space, which should divide the number and the text.
|
|
//
|
|
for (lpSearch = lpText; (*lpSearch) && (*lpSearch != _T(' ')); lpSearch++);
|
|
|
|
// Now that we know where the number ends, we can allocate a buffer for it
|
|
// and copy the number into it.
|
|
//
|
|
if ( lpSumText[dwIndex++] = (LPTSTR) MALLOC((size_t)((lpSearch - lpText + 1) * sizeof(TCHAR))) )
|
|
lstrcpyn(lpSumText[dwIndex - 1], lpText, (size_t)(lpSearch - lpText + 1));
|
|
|
|
// We should advance lpSearch to point to the text description, because now
|
|
// it should point to a space (unless we hit the end of the string before the space).
|
|
//
|
|
if ( *lpSearch )
|
|
lpSearch++;
|
|
|
|
// Now we need to know where the text description ends. We just want to search
|
|
// for the first new line or line feed character.
|
|
//
|
|
for (lpText = lpSearch; (*lpSearch) && (*lpSearch != _T('\r')) && (*lpSearch != _T('\n')); lpSearch++);
|
|
|
|
// Now that we know where the text ends, we can allocate a buffer for it
|
|
// also and copy the text into it.
|
|
//
|
|
if ( lpSumText[dwIndex++] = (LPTSTR) MALLOC((size_t)((lpSearch - lpText + 1) * sizeof(TCHAR))) )
|
|
lstrcpyn(lpSumText[dwIndex - 1], lpText, (size_t)(lpSearch - lpText + 1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// We check to make sure dwIndex still isn't zero, because if it is,
|
|
// there is no text to display in the summary dialog or to free.
|
|
//
|
|
if ( dwIndex > 0 )
|
|
{
|
|
// If the hwnd is valid and the text is null, then we are
|
|
// going to display the summary box.
|
|
//
|
|
if ( hWndParent )
|
|
DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_SUMMARY), hWndParent, SummaryProc, (LPARAM) lpSumText);
|
|
|
|
//
|
|
// Now free the memory because eaither a NULL was passed in for the hwnd
|
|
// or we already displayed the dialog and now the memory needs to be freed.
|
|
//
|
|
|
|
// Loop through all the strings that may have
|
|
// been allocated by going back from where the index
|
|
// is now.
|
|
//
|
|
// Note that some of the pointers may contain NULL
|
|
// if a malloc failed, but the FREE() macro will check
|
|
// with that before freeing the memory.
|
|
//
|
|
while ( dwIndex-- > 0 )
|
|
FREE(lpSumText[dwIndex]);
|
|
|
|
// Reset the index so that it doesn't get messed up
|
|
// the next time we display a summary.
|
|
//
|
|
dwIndex = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static INT_PTR CALLBACK SummaryProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
HANDLE_MSG(hDlg, WM_INITDIALOG, Summary_OnInitDialog);
|
|
case WM_COMMAND:
|
|
if ( (INT) LOWORD(wParam) != IDOK )
|
|
return TRUE;
|
|
case WM_CLOSE:
|
|
EndDialog(hDlg, 0);
|
|
return 0;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static BOOL Summary_OnInitDialog(HWND hDlg, HWND hwndFocus, LPARAM lParam)
|
|
{
|
|
INT nSumId[] =
|
|
{
|
|
IDC_SUM1A, IDC_SUM1B, IDC_SUM2A, IDC_SUM2B,
|
|
IDC_SUM3A, IDC_SUM3B, IDC_SUM4A, IDC_SUM4B,
|
|
IDC_SUM5A, IDC_SUM5B, IDC_SUM6A, IDC_SUM6B,
|
|
IDC_SUM7A, IDC_SUM7B, IDC_SUM8A, IDC_SUM8B
|
|
};
|
|
|
|
LPTSTR *lpStrings = (LPTSTR *) lParam;
|
|
DWORD dwIndex;
|
|
|
|
for (dwIndex = 0; dwIndex < 16; dwIndex++)
|
|
SetDlgItemText(hDlg, nSumId[dwIndex], *(lpStrings++));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static FARPROC LoadDllFunction(LPTSTR lpDll, LPCSTR lpFunction, HINSTANCE * lphDll)
|
|
{
|
|
FARPROC hFunc = NULL;
|
|
|
|
if ( (*lphDll) = LoadLibrary(lpDll) )
|
|
{
|
|
if ( (hFunc = GetProcAddress(*lphDll, lpFunction)) == NULL )
|
|
{
|
|
FreeLibrary(*lphDll);
|
|
*lphDll = NULL;
|
|
}
|
|
}
|
|
else
|
|
*lphDll = NULL;
|
|
|
|
return hFunc;
|
|
}
|