home *** CD-ROM | disk | FTP | other *** search
Wrap
/*********************************************************************/ /* */ /* Name: HANDLEST.C */ /* */ /* Copyright (c) Stewart A. Berman 1992, All rights reserved */ /* */ /*********************************************************************/ #pragma warning (disable:4001) #include <Windows.h> #pragma warning (default:4001) #include <String.h> #include "HandleSt.h" #include "IOStatus.h" #ifdef DEBUG #include "DebugOut.h" #endif #ifdef _cplusplus extern "C" { #endif /* _cplusplus */ BOOL bTimerInterval ; int FAR PASCAL HandleStatus ( UINT nStatus1, UINT nStatus2, UINT nParam1, UINT nParam2, LONG lParam1, LONG lParam2 ) { /********************************************************************/ /* */ /* This is the callback function for disk activity status */ /* */ /* 1. Determine the type of callback (based on nStatus1) */ /* */ /* nStatus Action */ /* ------- ------ */ /* STATUS1_INIT Save hWnd and hInstance */ /* STATUS1_START Send USR_ACTIVE message */ /* STATUS1_BOOT_SECTOR Send USR_ACTIVE message */ /* STATUS1_DIRECTORY Send USR_ACTIVE message */ /* STATUS1_FAT Send USR_ACTIVE message */ /* STATUS1_SYSTEM_FILE Send USR_ACTIVE message */ /* STATUS1_CYLINDER Send USR_UPDATE message */ /* STATUS1_HEAD Ignore */ /* STATUS1_END Beep and/or Flash if option selected */ /* STATUS1_ERROR Error type dependent */ /* */ /********************************************************************/ static BOOL bFlash = FALSE ; static BOOL bSound = FALSE ; static HINSTANCE hInstance = NULL ; static HWND hWnd = NULL; static UINT nTimerInterval ; static TIMERPROC lpfnSABDUTimerFunc ; char czBuffer1[512] ; char czBuffer2[512] ; char czIconMessage[512] ; char czNormalMessage[512] ; STMESSAGE stMessage ; STMESSAGE far *lpstMessage ; MSG msg ; /********************************************************************/ /* */ /* We want to be a well behaved Windows application so we need to */ /* let go of the CPU and let other applications get some work done. */ /* */ /********************************************************************/ while ( PeekMessage ( &msg, NULL, NULL, NULL, PM_REMOVE ) ) { TranslateMessage ( &msg ) ; DispatchMessage ( &msg ) ; } /********************************************************************/ /* */ /* The following is a multilevel switch for processing callback */ /* requests. */ /* */ /* The first level is seperates the major areas. Most of them are */ /* normal operation and are provided so the application can keep */ /* the user informed on the progress of long running tasks. */ /* Most of the first level messages are sent via SendMessage. */ /* The response is passed back to the routine issuing the callback */ /* requests. This allows the application to stop a long running */ /* process by returning an IDCANCEL in response to the SendMessage */ /* request. */ /* */ /* The second level is used to seperate the various types of error */ /* notifications. Some of them prompt the user for a decision as */ /* to whether or not a retry should be attempted. Others simply */ /* notify the user of a problem. */ /* */ /* The general method used to kept the user informed is to update */ /* two messages used by our WM_PAINT routine. One is used when the */ /* application is running in Iconic state and the other is for when */ /* it is not running in Iconic state. The messages are built here */ /* and passed in a structure via a SendMessage call to a routine */ /* that stores them where the WM_PAINT routine can access them. */ /* This maintains complete independence between this routine and */ /* the WM_PAINT routine. */ /* */ /********************************************************************/ #ifdef DEBUG if ( pCDebugOut!=NULL ) { wsprintf ( (LPSTR)DebugOutczDebugBuffer(), (LPSTR)"Status1: %4.4X\n" "Status2: %4.4X\n" "nParam1: %4.4X\n" "nParam2: %4.4X\n" "lParam1: %8.8lX\n" "lParam2: %8.8lX", nStatus1, nStatus2, nParam1, nParam2, lParam1, lParam2 ) ; DebugOutOutputIf ( 0x00000001, DebugOutczDebugBuffer(), "HandleStatus", MB_ICONINFORMATION|MB_OK ) ; } #endif switch ( nStatus1 ) { case STATUS1_INIT: /* User is passing hWnd, hInstance, and timer controls */ { hWnd = (HWND)nParam1 ; hInstance = (HINSTANCE)nParam2 ; nTimerInterval = LOWORD ( lParam1 ) ; bFlash = HIWORD ( lParam2 ) ; bSound = LOWORD ( lParam2 ) ; return ( FALSE ) ; break ; } case STATUS1_START: /* We are starting a long running process */ { wsprintf ( (LPSTR)czIconMessage, (LPCSTR)"%2.2d %3.2d%%", 0, 0 ) ; stMessage.pIconMessage = czIconMessage ; wsprintf ( (LPSTR)czNormalMessage, (LPCSTR)"Cylinder %2.2d (%3.2d%%)", 0, 0 ) ; stMessage.pNormalMessage = czNormalMessage ; stMessage.nPercentageToColor = 0 ; lpstMessage = (STMESSAGE far *) &stMessage ; return ( LOWORD (SendMessage ( hWnd, USR_ACTIVE, 0, (LONG)lpstMessage ) ) ) ; break ; } case STATUS1_BOOT_SECTOR: /* We are installing a new boot sector */ { _fstrcpy ( (LPSTR)czIconMessage, (LPCSTR)"Boot" ) ; stMessage.pIconMessage = czIconMessage ; _fstrcpy ( (LPSTR)czNormalMessage, (LPCSTR)"Installing Boot Sector" ) ; stMessage.pNormalMessage = czNormalMessage ; stMessage.nPercentageToColor = 100 ; lpstMessage = (STMESSAGE far *) &stMessage ; return ( LOWORD ( SendMessage ( hWnd, USR_ACTIVE, 0, (LONG)lpstMessage ) ) ) ; break ; } case STATUS1_DIRECTORY: /* We are building a diskette directory */ { _fstrcpy ( (LPSTR)czIconMessage, (LPCSTR)"DIR" ) ; stMessage.pIconMessage = czIconMessage ; _fstrcpy ( (LPSTR)czNormalMessage, (LPCSTR)"Creating Directory" ) ; stMessage.pNormalMessage = czNormalMessage ; stMessage.nPercentageToColor = 100 ; lpstMessage = (STMESSAGE far *) &stMessage ; return ( LOWORD ( SendMessage ( hWnd, USR_ACTIVE, 0, (LONG)lpstMessage ) ) ) ; break ; } case STATUS1_FAT: /* We are building a diskette File Allocation Table */ { _fstrcpy ( (LPSTR)czIconMessage, (LPCSTR)"FAT" ) ; stMessage.pIconMessage = czIconMessage ; _fstrcpy ( (LPSTR)czNormalMessage, (LPCSTR)"Creating File Allocation Table" ) ; stMessage.pNormalMessage = czNormalMessage ; stMessage.nPercentageToColor = 100 ; lpstMessage = (STMESSAGE far *) &stMessage ; return ( LOWORD ( SendMessage ( hWnd, USR_ACTIVE, 0, (LONG)lpstMessage ) ) ) ; break ; } case STATUS1_SYSTEM_FILE: /* We are copying a system file */ { _fstrcpy ( (LPSTR)czIconMessage, (LPSTR)(_fstrrchr ( (LPCSTR)lParam1, '\\' ) + 1 ) ) ; *(strrchr( czIconMessage, '.' )) = '\n' ; stMessage.pIconMessage = czIconMessage ; _fstrcpy ( (LPSTR)czNormalMessage, (LPCSTR)"Copying System File: " ) ; _fstrcat ( (LPSTR)czNormalMessage, (LPCSTR)lParam1 ) ; stMessage.pNormalMessage = czNormalMessage ; stMessage.nPercentageToColor = 100 ; lpstMessage = (STMESSAGE far *) &stMessage ; return ( LOWORD ( SendMessage ( hWnd, USR_ACTIVE, 0, (LONG)lpstMessage ) ) ) ; break ; } case STATUS1_CYLINDER: /* We are about to start a new cylinder */ { /**********************************************************/ /* */ /* We will check to see if the user has specified a */ /* minimum amount of time to wait between cylinders. If */ /* they have we will start a timer and wait for it to */ /* complete before going on. */ /* */ /* Note that the PeekMessage loop is needed for two */ /* reasons. It is the way we can release control so */ /* other applications can run and it is needed so our */ /* own WM_TIMER message can be processed. */ /* */ /**********************************************************/ bTimerInterval = FALSE ; lpfnSABDUTimerFunc = MakeProcInstance ( (FARPROC)SABDUTimerFunc, hInstance ) ; SetTimer ( hWnd, TIMER_INTERVAL, nTimerInterval, lpfnSABDUTimerFunc ) ; while ( !bTimerInterval ) { while ( PeekMessage ( &msg, NULL, NULL, NULL, PM_REMOVE ) ) { TranslateMessage ( &msg ) ; DispatchMessage ( &msg ) ; } } KillTimer ( hWnd, TIMER_INTERVAL ) ; FreeProcInstance ( lpfnSABDUTimerFunc ) ; wsprintf ( (LPSTR)czIconMessage, (LPCSTR)"%2.2d %3.2d%%", nParam1, nParam2 ) ; stMessage.pIconMessage = czIconMessage ; wsprintf ( (LPSTR)czNormalMessage, (LPCSTR)"Cylinder %2.2d (%3.2d%%)", nParam1, nParam2 ) ; stMessage.pNormalMessage = czNormalMessage ; stMessage.nPercentageToColor = nParam2 ; lpstMessage = (STMESSAGE far *) &stMessage ; return ( LOWORD ( SendMessage ( hWnd, USR_UPDATE, 0, (LONG)lpstMessage ) ) ) ; break ; } case STATUS1_HEAD: /* We are about to start a new head */ { break ; } case STATUS1_END: /* We have completed a long running task */ { if ( (bFlash) && (hWnd!=GetActiveWindow())) { lpfnSABDUTimerFunc = MakeProcInstance ( (FARPROC)SABDUTimerFunc, hInstance ) ; SetTimer ( hWnd, TIMER_INTERVAL, 1000, lpfnSABDUTimerFunc ) ; while ( hWnd != GetActiveWindow() ) { FlashWindow ( hWnd, TRUE ) ; if (bSound) MessageBeep ( 0 ) ; bTimerInterval = FALSE ; while ( !bTimerInterval ) { while ( PeekMessage ( &msg, NULL, NULL, NULL, PM_REMOVE ) ) { TranslateMessage ( &msg ) ; DispatchMessage ( &msg ) ; } } } FlashWindow ( hWnd, FALSE ) ; KillTimer ( hWnd, TIMER_INTERVAL ) ; FreeProcInstance ( lpfnSABDUTimerFunc ) ; } else { if ( bSound ) MessageBeep ( 0 ) ; } PostMessage ( hWnd, USR_INACTIVE, 0, 0L ) ; break ; } case STATUS1_ERROR: /* We have an error that needs to be dealt with */ { switch (nStatus2) { case STATUS2_FILE: /* It is a file error */ { /****************************************************/ /* */ /* All file errors are unrecoverable. That is the */ /* file operation will terminate and control will */ /* return to the main routine. */ /* */ /* The nParam1 indicates the type of file error. */ /* A message is built for that particular error. */ /* At the end of the switch statement a MessageBox */ /* call is used to display the message */ /* */ /****************************************************/ switch ( nParam1 ) { case STATUS3_OPEN_FAIL: /* We could not open the file */ { wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Open failed for: %s", (LPCSTR)lParam1 ) ; break ; } case STATUS3_OPEN_FILE_IO_ERROR: /* We had an I/O error */ { wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"File I/O Error: %s", (LPCSTR)lParam1 ) ; break ; } case STATUS3_OPEN_INPUT_BAD: /* The file is not one of ours */ { wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Input file ID is invalid: %s", (LPCSTR)lParam1 ) ; break ; } case STATUS3_OPEN_FLAGS_BAD: /* We don't support a flagged option */ { wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Input file has unsupport option: %4.4X", nParam2 ) ; break ; } case STATUS3_OPEN_NOT_SUPPORTED: /* We don't support the device type */ { wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Device type, %4.4X, is not supported", nParam2 ) ; break ; } default: /* We don't know what went wrong */ { czBuffer1[0] = '\0' ; break ; } } GetWindowText ( hWnd, czBuffer1, 511) ; return (MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONEXCLAMATION|MB_OK )) ; break ; } case STATUS2_READ: /* It was a read error */ { /****************************************************/ /* */ /* We will tell the user about the error and let */ /* them decided if we should retry. The response */ /* from the user will be returned to the routine */ /* that issued the callback address. Hopefully, */ /* it will know what to do with it. */ /* */ /****************************************************/ wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"%s Error at Cylinder %d, Head %d", (LPCSTR)"Read", nParam1, nParam2 ) ; _fstrcat ( czBuffer2, "\nPossible causes:" ) ; _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ; _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ; _fstrcat ( czBuffer2, "\nDiskette is not formatted" ) ; GetWindowText ( hWnd, czBuffer1, 255 ) ; return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_RETRYCANCEL ) ) ; break ; } case STATUS2_WRITE: /* It was a write error */ { /****************************************************/ /* */ /* We will tell the user about the error and let */ /* them decided if we should retry. The response */ /* from the user will be returned to the routine */ /* that issued the callback address. Hopefully, */ /* it will know what to do with it. */ /* */ /****************************************************/ wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"%s Error at Cylinder %d, Head %d", (LPCSTR)"Write", nParam1, nParam2 ) ; _fstrcat ( czBuffer2, "\nPossible causes:" ) ; _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ; _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ; _fstrcat ( czBuffer2, "\nDiskette has write protect tab" ) ; _fstrcat ( czBuffer2, "\nDiskette is not formatted" ) ; GetWindowText ( hWnd, czBuffer1, 255 ) ; return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_RETRYCANCEL ) ) ; break ; } case STATUS2_FORMAT: /* It was a format error */ { /****************************************************/ /* */ /* We will tell the user about the error and let */ /* them decided if we should retry. The response */ /* from the user will be returned to the routine */ /* that issued the callback address. Hopefully, */ /* it will know what to do with it. */ /* */ /****************************************************/ wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"%s Error at Cylinder %d, Head %d", (LPCSTR)"Format", nParam1, nParam2 ) ; _fstrcat ( czBuffer2, "\nPossible causes:" ) ; _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ; _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ; _fstrcat ( czBuffer2, "\nDiskette has write protect tab" ) ; GetWindowText ( hWnd, czBuffer1, 255 ) ; return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_ABORTRETRYIGNORE ) ) ; break ; } case STATUS2_FILE_READ: /* It was a file read error */ case STATUS2_FILE_WRITE: /* It was a file write error */ { /****************************************************/ /* */ /* We will tell the user about the error and let */ /* them decided if we should retry. The response */ /* from the user will be returned to the routine */ /* that issued the callback address. Hopefully, */ /* it will know what to do with it. */ /* */ /****************************************************/ wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"File I/O Error: %s", (LPCSTR)lParam1 ) ; GetWindowText ( hWnd, czBuffer1, 255 ) ; return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_RETRYCANCEL ) ) ; break ; } case STATUS2_DISK_SPACE: /* We don't have enough disk space */ { wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Drive does not have enough space available for file\n%10ld Bytes Required\n%10ld Bytes Available", lParam1, lParam2 ) ; GetWindowText ( hWnd, czBuffer2, 511) ; return (MessageBox ( hWnd, czBuffer1, czBuffer2, MB_ICONEXCLAMATION|MB_OK )) ; break ; } case STATUS2_HEAD: /* We had an I/O error at the track (head) level */ { wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"%s Error at Cylinder %d, Head %d", (LPSTR)"", nParam1, nParam2 ) ; _fstrcat ( czBuffer2, "\nPossible causes:" ) ; _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ; _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ; GetWindowText ( hWnd, czBuffer1, 511) ; return (MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_RETRYCANCEL )) ; break ; } case STATUS2_MEMORY: /* We don't have enough memory */ { GetWindowText ( hWnd, czBuffer1, 511) ; return (MessageBox ( hWnd, "Unable to Allocate Memory", czBuffer1, MB_ICONEXCLAMATION|MB_OK )) ; break ; } case STATUS2_SYSTEM: /* We have a bad sector in the system are of the diskette */ case STATUS2_FAT: /* We have a bad sector in the File Allocation Table area of a diskette */ case STATUS2_DIRECTORY: /* We have a bad sector in the root directory area of a diskette */ { GetWindowText ( hWnd, czBuffer1, 511) ; return (MessageBox ( hWnd, "Bad Sector in System Area - Disk is unusable", czBuffer1, MB_ICONEXCLAMATION|MB_OK )) ; break ; } case STATUS2_BOOT_SECTOR: /* We couldn't write out a boot sector */ { wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Unable to Write the Boot Sector on the %c Drive", ' ' ) ; _fstrcat ( czBuffer2, "\nPossible causes:" ) ; _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ; _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ; _fstrcat ( czBuffer2, "\nDiskette has write protect tab" ) ; _fstrcat ( czBuffer2, "\nDiskette is not formatted" ) ; GetWindowText ( hWnd, czBuffer1, 255 ) ; return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_RETRYCANCEL ) ) ; break ; } case STATUS2_SYSTEM_FILE_MISSING: /* We couldn't find one of the system files */ { GetWindowText ( hWnd, czBuffer1, 511) ; return (MessageBox ( hWnd, "Unable to Find System Files", czBuffer1, MB_ICONEXCLAMATION|MB_OK )) ; break ; } case STATUS2_SYSTEM_FILE_OPEN: /* We couldn't open one of the system files */ { wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Unable to Open System File: %s", (LPCSTR)lParam1 ) ; GetWindowText ( hWnd, czBuffer1, 511) ; return (MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONEXCLAMATION|MB_OK )) ; break ; } case STATUS2_COMPARE: /* We were doing a compare and something didn't */ { _fstrcpy ( czBuffer1, "Difference found at Cylinder %d, head %d" ) ; _fstrcat ( czBuffer1, "\nContinue with %s?" ) ; wsprintf ( (LPSTR)czBuffer2, (LPCSTR)czBuffer1, nParam1, nParam2, (LPCSTR)"Compare" ) ; GetWindowText ( hWnd, czBuffer1, 511) ; return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONSTOP|MB_YESNO ) ) ; break ; } case STATUS2_DPT: /* It was a DPT error */ { /****************************************************/ /* */ /* We will tell the user about the error and let */ /* them decided if we should retry. The response */ /* from the user will be returned to the routine */ /* that issued the callback address. Hopefully, */ /* it will know what to do with it. */ /* */ /****************************************************/ wsprintf ( (LPSTR)czBuffer2, (LPCSTR)"Unable to Read Device Parameter Table of Diskette in Drive %c:", nParam1 ) ; _fstrcat ( czBuffer2, "\nPossible causes:" ) ; _fstrcat ( czBuffer2, "\nDiskette is not positioned properly in drive" ) ; _fstrcat ( czBuffer2, "\nDiskette drive door is not closed" ) ; _fstrcat ( czBuffer2, "\nDiskette is not formatted" ) ; GetWindowText ( hWnd, czBuffer1, 255 ) ; return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONEXCLAMATION|MB_OK ) ) ; break ; } case STATUS2_SECTORS: /* Target diskette does not have the same sectors/track as the source image */ { /****************************************************/ /* */ /* We will tell the user about the error and let */ /* them decided if we should continue. The response */ /* from the user will be returned to the routine */ /* that issued the callback address. Hopefully, */ /* it will know what to do with it. */ /* */ /****************************************************/ _fstrcpy ( czBuffer2, "The source image has a different structure than the target diskette:\n" ) ; wsprintf ( (LPSTR)czBuffer1, (LPCSTR)"%3.3u Sectors per track and %3.3u Cylinders in target diskette\n%3.3u Sectors per track and %3.3u Cylinders in source image", nParam1, LOWORD ( lParam1 ), nParam2, LOWORD ( lParam2 ) ) ; _fstrcat ( czBuffer2, czBuffer1 ) ; _fstrcat ( czBuffer2, "\nPress OK to continue or Cancel to stop" ) ; GetWindowText ( hWnd, czBuffer1, 255 ) ; return ( MessageBox ( hWnd, czBuffer2, czBuffer1, MB_ICONEXCLAMATION|MB_OKCANCEL ) ) ; break ; } default: /* We are confused */ { break ; } } break ; } default: /* We are confused */ { break ; } } return ( TRUE ) ; /* We are confused but the truth will stop most things from continuing to go wrong. */ } int FAR PASCAL SABDUTimerFunc ( HWND hWnd, UINT nMsg, UINT nIDEvent, DWORD dwTime ) { /* Kill unreferenced formal parameter warnings */ if (hWnd) ; if (nMsg) ; if (nIDEvent) ; if (dwTime) ; bTimerInterval = TRUE ; return ( FALSE ) ; } #ifdef _cplusplus } #endif /* _cplusplus */