#include <Windows.h>

#include <IO.h>
#include <StdIO.h>
#include <StdLib.h>
#include <String.h>

#include "DDrive.h"
#include "DiskDriv.h"
#include "HandleSt.h"
#include "IOStatus.h"
#include "Sample.h"

#ifdef DEBUG
#include "DebugOut.h"
#endif

BOOL bCancel ;
BOOL bIdle ;
BOOL bRegisteredClass ;

char czIconMessage[64] ;
char czNormalMessage[512] ;

FARPROC lpfnHandleStatus ;

HINSTANCE hInstance ;

HWND hWnd ;

UINT nNumberOfDrives ;
UINT nPercentageToColor ;

VOID far * pCDebugOut ;

VOID far * pCVDriveTest ;

VOID far *pCVDrives[26] ;

VOID far * pCDiskImage ;

VOID far * pCDiskTemporary ;

int PASCAL WinMain ( HINSTANCE hCurrentInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, UINT nCmdShow)
{
    MSG msg;

    UINT n ;

#ifdef DEBUG
    pCDebugOut = DebugOutCreate ( lpCmdLine ) ;
#endif

    bRegisteredClass = FALSE ;
    if (!hPrevInstance)
       {
       if (!InitApplication(hCurrentInstance)) return (FALSE);
       bRegisteredClass = TRUE ;
       }

    if (!InitInstance(hCurrentInstance, nCmdShow)) return (FALSE);

    hInstance = hCurrentInstance ;

    while (GetMessage(&msg, NULL, NULL, NULL))
       {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
       }

    if ( nNumberOfDrives )
       {
       for ( n=0; n<nNumberOfDrives; n++ ) DDriveDelete ( pCVDrives[n] ) ;
       }

    if ( bRegisteredClass ) UnregisterClass ( "SampleWClass", hInstance ) ;

    return ( msg.wParam ) ;
}

BOOL InitApplication ( HINSTANCE hInstance )
{
    WNDCLASS  wc;

    wc.style = NULL;
    wc.lpfnWndProc = MainWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = GetStockObject(WHITE_BRUSH); 
    wc.lpszMenuName =  "SampleMenu";
    wc.lpszClassName = "SampleWClass";
    return (RegisterClass(&wc));
}

BOOL InitInstance ( HINSTANCE hInstance, UINT nCmdShow )
{

    char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
    char czBuffer[256] ;

    HMENU hMainMenu ;
    HMENU hPopupMenu ;

    int i ;

    UINT nMenuID ;
    UINT nPopupMenuID ;

    VOID far * pCVDriveTest ;

    hWnd = CreateWindow( "SampleWClass", "Sample SABDU001.DLL Application", WS_OVERLAPPEDWINDOW,
                         100, 200, 400, 200,
                         NULL, NULL, hInstance, NULL );
    if (!hWnd) return (FALSE);

#ifdef DEBUG
    /* The following will be executed if the program is invoked with /D1 on the command line   */
    /* It will be written to a trace file unless /M1 is also on the command line in which case */
    /* it will be displayed in a MessageBox on the screen                                      */
    wsprintf ( DebugOutczDebugBuffer(), "This is a sample of a debug trace.\n hWnd = %4.4X", hWnd ) ;
    DebugOutOutputIf ( 0x00000001L, DebugOutczDebugBuffer(), "Sample Trace", MB_OK ) ;
#endif

    nMenuID = 0 ;
    nNumberOfDrives = 0 ;
    hMainMenu = GetMenu ( hWnd ) ;
    for ( i = 0; i < sizeof(alphabet)/sizeof(alphabet[0])-1 ; i++ )
       {
       pCVDriveTest = (VOID far *) DDriveCreate ( alphabet[i] ) ;
       if (pCVDriveTest==NULL)
          {
          ; /* Memory problems or worse */
          return ( FALSE ) ;
          break ;
          }
       if ((VDriveIsUseable ( pCVDriveTest ))&&(!VDriveIsRemote ( pCVDriveTest ))&&(VDriveIsRemovable ( pCVDriveTest )))
          {
          pCVDrives[nNumberOfDrives] = pCVDriveTest ;
          nNumberOfDrives++ ;
          nMenuID += 100 ;
          hPopupMenu = CreatePopupMenu () ;
          nPopupMenuID = nMenuID ;
          AppendMenu ( hPopupMenu, MF_ENABLED|MF_STRING, ++nPopupMenuID, "&Compare" ) ;
          nPopupMenuID++ ;
          if ( FD0360 & VDriveType  ( pCVDriveTest ) ) AppendMenu ( hPopupMenu, MF_ENABLED|MF_STRING, nPopupMenuID, "Format 0&360KB" ) ;
          nPopupMenuID++ ;
          if ( FD0720 & VDriveType  ( pCVDriveTest ) ) AppendMenu ( hPopupMenu, MF_ENABLED|MF_STRING, nPopupMenuID, "Format 0&720KB" ) ;
          nPopupMenuID++ ;
          if ( FD1200H & VDriveType ( pCVDriveTest ) ) AppendMenu ( hPopupMenu, MF_ENABLED|MF_STRING, nPopupMenuID, "Format 1&200KB" ) ;
          nPopupMenuID++ ;
          if ( FD1440H & VDriveType ( pCVDriveTest ) ) AppendMenu ( hPopupMenu, MF_ENABLED|MF_STRING, nPopupMenuID, "Format 1&440KB" ) ;
          nPopupMenuID++ ;
          if ( FD2880H & VDriveType ( pCVDriveTest ) ) AppendMenu ( hPopupMenu, MF_ENABLED|MF_STRING, nPopupMenuID, "Format 2&880KB" ) ;
          AppendMenu ( hPopupMenu, MF_ENABLED|MF_STRING, ++nPopupMenuID, "&Read" ) ;
          AppendMenu ( hPopupMenu, MF_ENABLED|MF_STRING, ++nPopupMenuID, "&Write" ) ;
          czBuffer[0] = '&' ;
          czBuffer[1] = VDriveLetter ( pCVDriveTest ) ;
          czBuffer[2] = ':' ;
          czBuffer[3] = '\0' ;
          AppendMenu ( hMainMenu, MF_ENABLED|MF_STRING|MF_POPUP, hPopupMenu, czBuffer ) ;
          }
       else
          {
          DDriveDelete ( pCVDriveTest ) ;
          }
       }

    if ( !nNumberOfDrives ) return ( FALSE ) ;

    bCancel = FALSE ;
    bIdle   = TRUE ;

    pCDiskImage = NULL ;

    lpfnHandleStatus = MakeProcInstance ( (FARPROC)HandleStatus, hInstance ) ;

    (*(lpfnHANDLESTATUS)lpfnHandleStatus) ( STATUS1_INIT, 0, (UINT)hWnd, (UINT)hInstance, MAKELONG ( TIMER_INTERVAL, 0x0000 ), MAKELONG ( 0x0001, 0x0001 ) ) ;

    ShowWindow( hWnd, nCmdShow ) ;
    UpdateWindow( hWnd ) ;
    return ( TRUE ) ;

}

long FAR PASCAL MainWndProc ( HWND hWnd, UINT nMessage, UINT nParam, LONG lParam )
{
    char  czMessageBuffer[512] ;

    HDC     hdc ;

    PAINTSTRUCT ps ;

    RECT    rClient ;

    STMESSAGE far *lpstMessage ;

    UINT nAction ;
    UINT nDrive ;

    char czApplicationTitle [] = "SAB Diskette Utility" ;
    char czFileName [] = "SABDU.SDU" ;
    char czVersionNumber [] = "2.00" ;
    char czFullPath [_MAX_PATH] ;

    switch ( nMessage )
       {
       case WM_PAINT:
          {
          hdc = BeginPaint ( hWnd, &ps ) ;

          if (!IsIconic( hWnd ))
             {
             GetClientRect ( hWnd, &rClient ) ;
             if (bIdle)
                {
                _fstrcpy ( czMessageBuffer, "Please select an item from the menu" ) ;
                }
             else
                {
                _fstrcpy ( czMessageBuffer, czNormalMessage ) ;
                }
             DrawText ( hdc, czMessageBuffer, -1, &rClient, DT_CENTER|DT_WORDBREAK ) ;
             }

          EndPaint ( hWnd, &ps ) ;
          return ( FALSE ) ;
          break ;
          }
       case USR_ACTIVE:
          {
          bIdle = FALSE ;

          lpstMessage = (STMESSAGE far *)lParam ;

          if (lpstMessage->pIconMessage)   _fstrcpy ( czIconMessage, lpstMessage->pIconMessage   )  ;
          if (lpstMessage->pNormalMessage) _fstrcpy ( czNormalMessage, lpstMessage->pNormalMessage ) ;
          nPercentageToColor = lpstMessage->nPercentageToColor ;

          InvalidateRect ( hWnd, NULL, TRUE ) ;
          UpdateWindow ( hWnd ) ;

          return ( !bCancel ) ;
          break ;
          }
       case USR_UPDATE:
          {
          bIdle = FALSE ;

          lpstMessage = (STMESSAGE far *)lParam ;

          if (lpstMessage->pIconMessage)   _fstrcpy ( czIconMessage, lpstMessage->pIconMessage   )  ;
          if (lpstMessage->pNormalMessage) _fstrcpy ( czNormalMessage, lpstMessage->pNormalMessage ) ;
          nPercentageToColor = lpstMessage->nPercentageToColor ;

          InvalidateRect ( hWnd, NULL, FALSE ) ;
          UpdateWindow ( hWnd ) ;

          return ( !bCancel ) ;
          break ;
          }
       case USR_INACTIVE:
          {
          bIdle = TRUE ;
          InvalidateRect ( hWnd, NULL, TRUE ) ;
          UpdateWindow ( hWnd ) ;
          return ( !bCancel ) ;
          break ;
          }
       case WM_COMMAND:
          {

          if ( nParam==IDCANCEL )
             {
             /*******************************************************/
             /*                                                     */
             /* The user wants to canceL the current activity       */
             /*                                                     */
             /*******************************************************/
             bCancel = TRUE ;
             return ( TRUE ) ;
             }

          if (!bIdle)
             {
             /*******************************************************/
             /*                                                     */
             /* The system does not support concurrent activities so*/
             /* ignore requests since we are not idle.              */
             /*                                                     */
             /*******************************************************/
             return ( TRUE ) ;
             }

          if ( nParam==IDM_OPEN )
             {
             /*******************************************************/
             /*                                                     */
             /* The user wants to open and read in a diskette image */
             /* file.                                               */
             /* Note: The sample uses the variable czFileName which */
             /* is initialized to "SABDU.SDU".  A file selection    */
             /* dialog would be usefull here.                       */
             /*                                                     */
             /*******************************************************/
             SetWindowText ( hWnd, "Openning" ) ;
             if (_access ( czFileName, 4 ) )
                {
                wsprintf ( (LPSTR)czMessageBuffer, (LPCSTR)"Unable to access file: %s", (LPCSTR)_fullpath ( czFullPath, czFileName, _MAX_PATH ) ) ;
                MessageBox ( hWnd, czMessageBuffer, "Sample", MB_ICONEXCLAMATION|MB_OK ) ;
                return ( TRUE ) ;
                }
             bCancel = FALSE ;
             pCDiskTemporary = (VOID far *) DiskDriveCreateFile ( czFileName, czApplicationTitle, czVersionNumber, FD0000, 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
             if (!DiskDriveHasData(pCDiskTemporary)) return ( TRUE ) ;
             if ( pCDiskImage != NULL )
                {
                DiskDriveDelete ( pCDiskImage ) ;
                pCDiskImage = NULL ;
                }
             pCDiskImage = DiskDriveCreateMemory ( (UINT)0, DiskDriveType ( pCDiskTemporary ), 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
             DiskDriveCopy ( pCDiskImage, pCDiskTemporary ) ;
             DiskDriveDelete ( pCDiskTemporary ) ;
             if ( bCancel )
                {
                DiskDriveDelete ( pCDiskImage ) ;
                pCDiskImage = NULL ;
                }
             bIdle = TRUE ;
             SetWindowText ( hWnd, "Sample SABDU001.DLL Application" ) ;
             return ( TRUE ) ;
             }
          if ( nParam==IDM_SAVE )
             {
             /*******************************************************/
             /*                                                     */
             /* The user wants to open and write out a diskette     */
             /* image file.                                         */
             /* Note: The sample uses the variable czFileName which */
             /* is initialized to "SABDU.SDU".  A file selection    */
             /* dialog would be usefull here.                       */
             /*                                                     */
             /*******************************************************/
             if ( pCDiskImage==NULL )
                {
                MessageBox ( hWnd, "You must first READ in a diskette image before saving", "Sample", MB_ICONEXCLAMATION|MB_OK ) ;
                return ( TRUE ) ;
                }
             SetWindowText ( hWnd, "Saving" ) ;
             bCancel = FALSE ;
             pCDiskTemporary = (VOID far *) DiskDriveCreateFile ( czFileName, czApplicationTitle, czVersionNumber, DiskDriveType ( pCDiskImage ), DiskDriveUsedCylinders ( pCDiskImage ), (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
             if (!DiskDriveType(pCDiskTemporary)) return ( TRUE ) ;
             DiskDriveCopy ( pCDiskTemporary, pCDiskImage ) ;
             DiskDriveDelete ( pCDiskTemporary ) ;
             if (bCancel) remove ( czFileName ) ;
             bIdle = TRUE ;
             SetWindowText ( hWnd, "Sample SABDU001.DLL Application" ) ;
             return ( TRUE ) ;
             }

          if ( nParam==IDM_EXIT )
             {
             /*******************************************************/
             /*                                                     */
             /* The user wants to exit.                             */
             /*                                                     */
             /*******************************************************/
             PostMessage ( hWnd, WM_DESTROY, 0, 0L ) ;
             return ( TRUE ) ;
             }

          if ( (nParam>=(UINT)100)&&(nParam<=(UINT)100*(nNumberOfDrives+1) ) )
             {
             /*******************************************************/
             /*                                                     */
             /* The use has selected a diskette drive function.     */
             /* The first digit of the three digit nParam identifies*/
             /* the device.  The next two identify the function.    */
             /*                                                     */
             /*******************************************************/
             nDrive = ( nParam / 100 ) - 1 ;
             nAction = nParam % 100 ;
             bCancel = FALSE ;
             switch ( nAction )
                {
                case 1: /* Compare */
                   {
                   if ( pCDiskImage==NULL )
                      {
                      MessageBox ( hWnd, "You must first READ in a diskette image before comparing.", "Sample", MB_ICONEXCLAMATION|MB_OK ) ;
                      return ( TRUE ) ;
                      }
                   SetWindowText ( hWnd, "Comparing" ) ;
                   pCDiskTemporary = DiskDriveCreateVDrive ( pCVDrives[nDrive], 0, 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   if (!DiskDriveHasData(pCDiskTemporary)) return ( TRUE ) ;
                   DiskDriveCompare ( pCDiskImage, pCDiskTemporary ) ;
                   DiskDriveReset ( pCDiskTemporary ) ;
                   DiskDriveDelete ( pCDiskTemporary ) ;
                   bIdle = TRUE ;
                   SetWindowText ( hWnd, "Sample SABDU001.DLL Application" ) ;
                   return ( TRUE ) ;
                   break ;
                   }
                case 2: /* Format  360KB */
                   {
                   SetWindowText ( hWnd, "Formating 0360KB" ) ;
                   pCDiskTemporary = DiskDriveCreateVDrive ( pCVDrives[nDrive], FD0360, 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveFormat ( pCDiskTemporary, "Sample 0360", NULL, NULL, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveReset ( pCDiskTemporary ) ;
                   DiskDriveDelete ( pCDiskTemporary ) ;
                   bIdle = TRUE ;
                   SetWindowText ( hWnd, "Sample SABDU001.DLL Application" ) ;
                   return ( TRUE ) ;
                   break ;
                   }
                case 3: /* Format  720KB */
                   {
                   SetWindowText ( hWnd, "Formating 0720KB" ) ;
                   pCDiskTemporary = DiskDriveCreateVDrive ( pCVDrives[nDrive], FD0720, 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveFormat ( pCDiskTemporary, "Sample 0720", NULL, NULL, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveReset ( pCDiskTemporary ) ;
                   DiskDriveDelete ( pCDiskTemporary ) ;
                   bIdle = TRUE ;
                   SetWindowText ( hWnd, "Sample SABDU001.DLL Application" ) ;
                   return ( TRUE ) ;
                   break ;
                   }
                case 4: /* Format 1200KB */
                   {
                   SetWindowText ( hWnd, "Formating 1200KB" ) ;
                   pCDiskTemporary = DiskDriveCreateVDrive ( pCVDrives[nDrive], FD1200, 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveFormat ( pCDiskTemporary, "Sample 1200", NULL, NULL, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveReset ( pCDiskTemporary ) ;
                   DiskDriveDelete ( pCDiskTemporary ) ;
                   bIdle = TRUE ;
                   SetWindowText ( hWnd, "Sample SABDU001.DLL Application" ) ;
                   return ( TRUE ) ;
                   break ;
                   }
                case 5: /* Format 1440KB */
                   {
                   SetWindowText ( hWnd, "Formating 1440KB" ) ;
                   pCDiskTemporary = DiskDriveCreateVDrive ( pCVDrives[nDrive], FD1440, 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveFormat ( pCDiskTemporary, "Sample 1440", NULL, NULL, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveReset ( pCDiskTemporary ) ;
                   DiskDriveDelete ( pCDiskTemporary ) ;
                   bIdle = TRUE ;
                   SetWindowText ( hWnd, "Sample SABDU001.DLL Application" ) ;
                   return ( TRUE ) ;
                   break ;
                   }
                case 6: /* Format 2880KB */
                   {
                   SetWindowText ( hWnd, "Formating 2880KB" ) ;
                   pCDiskTemporary = DiskDriveCreateVDrive ( pCVDrives[nDrive], FD2880, 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveFormat ( pCDiskTemporary, "Sample 2880", NULL, NULL, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveReset ( pCDiskTemporary ) ;
                   DiskDriveDelete ( pCDiskTemporary ) ;
                   bIdle = TRUE ;
                   SetWindowText ( hWnd, "Sample SABDU001.DLL Application" ) ;
                   return ( TRUE ) ;
                   break ;
                   }
                case 7: /* Read */
                   {
                   SetWindowText ( hWnd, "Reading" ) ;
                   pCDiskTemporary = DiskDriveCreateVDrive ( pCVDrives[nDrive], FD0000, 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   if (!DiskDriveHasData(pCDiskTemporary)) return ( TRUE ) ;
                   if ( pCDiskImage != NULL )
                      {
                      DiskDriveDelete ( pCDiskImage ) ;
                      pCDiskImage = NULL ;
                      }
                   pCDiskImage = DiskDriveCreateMemory ( (UINT)0, DiskDriveType ( pCDiskTemporary ), 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveCopy ( pCDiskImage, pCDiskTemporary ) ;
                   DiskDriveReset ( pCDiskTemporary ) ;
                   DiskDriveDelete ( pCDiskTemporary ) ;
                   if ( bCancel )
                      {
                      DiskDriveDelete ( pCDiskImage ) ;
                      pCDiskImage = NULL ;
                      }
                   bIdle = TRUE ;
                   SetWindowText ( hWnd, "Sample SABDU001.DLL Application" ) ;
                   return ( TRUE ) ;
                   break ;
                   }
                case 8: /* Write */
                   {
                   if ( pCDiskImage==NULL )
                      {
                      MessageBox ( hWnd, "You must first READ in a diskette image before writting.", "Sample", MB_ICONEXCLAMATION|MB_OK ) ;
                      return ( TRUE ) ;
                      }
                   SetWindowText ( hWnd, "Writing" ) ;
                   pCDiskTemporary = DiskDriveCreateVDrive ( pCVDrives[nDrive], 0, 0, (lpfnHANDLESTATUS) lpfnHandleStatus ) ;
                   DiskDriveCopy ( pCDiskTemporary, pCDiskImage ) ;
                   DiskDriveReset ( pCDiskTemporary ) ;
                   DiskDriveDelete ( pCDiskTemporary ) ;
                   bIdle = TRUE ;
                   SetWindowText ( hWnd, "Sample SABDU001.DLL Application" ) ;
                   return ( TRUE ) ;
                   break ;
                   }
                }
             }

          break ;
          }
       case WM_DESTROY:
          {
          PostQuitMessage( 0 ) ;
          break ;
          }
       default:
          {
          break ;
          }
       }
    return ( DefWindowProc ( hWnd, nMessage, nParam, lParam ) ) ;
}

