/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT (C) Microsoft Corporation, 1989                                 */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME =  VDSK.C
 *
 * DESCRIPTIVE NAME =  Virtual Disk Device Driver (VDSK)
 *
 *
 *
 * VERSION = V2.0
 *
 * DATE      03/20/92
 *
 * DESCRIPTION
 *
 *          This module contains all the VDSK's initialization
 *          procedures, event handler procedures, and global
 *          as well as VDM instance data declarations.
 *
 * FUNCTIONS      VDDInit              VDSKExit
 *                VDSKCreateVDM        VDSKDOSLink
 *                VDSKTerminateVDM     VDSKOpenVirtDisks
 *                VDSKCloseVirtDisks   vdskVDDEntry
 *
 *
 *
 * ENTRY POINTS:
 *
 * DEPENDENCIES:
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/

#define  INCL_MI
#include <mvdm.h>
#include <propname.h>
#include "vdskp.h"
#define  INCL_DOSERRORS                                 /* NoPdd            */
#include <bseerr.h>                                     /* NoPdd            */
#include <vfdvdd.h>                                     /*                  */

#ifdef   VDDSTRICT
MODNAME = __FILE__;
#endif

/* protocols inside VMUSER.C*/
/* VM_Boot*/

VOID HOOKENTRY VDSKDOSLink(PVOID p,PCRF pcrf);

                                                         /*******************/
                                                         /* VM_Boot
** VDSK Global Data
                                                                            */
                                                         /*******************/

#pragma  BEGIN_GLOBAL_DATA
HVDM hvdmDiskReq = HVDM_NOVDM;                          /* handle of VDM
                                                           doing disk
                                                           request          */
BOOL *pbBusyFlagPtr;                                    /*                  */

#ifdef   VDDSTRICT
CHAR szAssertMsg[] = "VDSK assertion failure in %s, line %d\n";
#endif

#ifdef   VDDDEBUG
CHAR szModule[] = "VDSK: ";
#endif
HVDHSEM semDiskReq;

/*HVDHSEM semVM_Boot;      Serialize VM_Boot's use of dskt image VM_Boot*/
/* Suspend support ? SHORT    flPDDSuspend=-1;                     */

HVDD hVDDVFLPY = NULL;                                  /*                  */
#pragma  END_GLOBAL_DATA
#pragma  BEGIN_SWAP_DATA

/*             FPFNPDD         fpfnPDSKVDDProc = (FPFNPDD)0;  16:32 PDD entry point*/

HVDM hvdmDiskChanged = HVDM_NOVDM;                      /* handle of VDM
                                                           detect disk
                                                           changed          */
DISKREQ PS2_DiskTable;                                  /* Int 13h return
                                                           fixed drv
                                                           parameters pb
                                                                      @516  */

/* Media Type Table*/

MEDIATYPE amtMediaTable[NUMMEDIAS] =
{
  {
    40,             9
  } ,                                                   /* 360K             */
  {
    80,             15
  } ,                                                   /* 1.2M             */
  {
    80,             9
  } ,                                                   /* 720K             */
  {
    80,             18
  }                                                     /* 1.44M            */
} ;

/* Port Hooking Data*/

IOH iotVDSKPort =
{
  VDSKReadPort,   VDSKWritePort,  NULL,           NULL,           NULL
} ;

PSZ pszVMBootName = PROP_NAME_VM_BOOT;
#pragma  END_SWAP_DATA
#define  DSKT_RESTART  0                                /*            IOCTL */
#define  DSKT_SUSPEND  1                                /*            IOCTL */
#define  DSKT_IODC_QD  0X005d                           /*            IOCTL */
typedef GETDEVICEPARMSPARM *PSUSPENDRESTARTPARM;        /*                  */

/*
**    VDSK Instance Data
*/

#pragma  BEGIN_INSTANCE_DATA
HFILE hfTmp;                                            /*                  */
ULONG ulAction;                                         /*                  */
HFILE DriveHandle;                                      /* NoPdd            */
USHORT Number_Physical_Disks;
HFILE DeviceHandle;                                     /* NoPdd            */
ULONG ActionTaken;                                      /* NoPdd            */
CHAR FileName[3] = " :\0";                              /* NoPdd            */
GETDEVICEPARMSPARM GetDeviceParmsParmPacket;            /* NoPdd            */
GETDEVICEPARMSDATA GetDeviceParmsDataPacket;            /* NoPdd            */
BYTE LockParmsParmPacket;                               /*                  */

/*    GETPHYSDEVICEPARMSPARM GetPhysDeviceParmsParmPacket;  NoPdd*/

GETPHYSDEVICEPARMSDATA GetPhysDeviceParmsDataPacket;    /* NoPdd            */
RWVPARM RWVParmPacket;                                  /* NoPdd            */
FORMATPARM FormatParmPacket;                            /* NoPdd            */
FORMATDATA FormatDataPacket;                            /* NoPdd            */
ULONG LengthParm,LengthData;                            /* NoPdd            */
ERRORIOCTLTOINT13 ErrorIOCTLtoINT13Table[MAX_INT13Error+1] =
{
  {
    ERROR_INVALID_DRIVE,            INT13STATUS_BADCMD
  } ,                                                   /* NoPdd            */
  {
    ERROR_BAD_UNIT, INT13STATUS_BADCMD
  } ,
  {
    ERROR_INVALID_PARAMETER,        INT13STATUS_BADCMD
  } ,
  {
    ERROR_NOT_READY,                INT13STATUS_DRVNOTREADY
  } ,
  {
    ERROR_BAD_COMMAND,              INT13STATUS_BADCMD
  } ,
  {
    ERROR_CRC,      INT13STATUS_BADCRCECC
  } ,
  {
    ERROR_SEEK,     INT13STATUS_BADSEEK
  } ,
  {
    ERROR_SECTOR_NOT_FOUND,         INT13STATUS_RECNOTFOUND
  } ,
  {
    ERROR_WRITE_PROTECT,            INT13STATUS_WRTPROTECT
  } ,
  {
    0,              INT13STATUS_BADCNTLR
  }
} ;

PVOID LinearESBX;                                       /*                  */
HLOCK hLockMem = NULL;                                  /*                  */
ULONG flResp;                                           /* Popup response
                                                           flag ** NoPdd    */
GETDEVICEPARMSPARM SuspendRestartParmPacket;            /*           
                                                           SUSPEND/RESTART
                                                           IOCTL            */

                                                         /*******************/
                                                         /* call parm       */
                                                         /* packet          */
                                                         /*******************/

#pragma  END_INSTANCE_DATA
#pragma  BEGIN_SWAP_INSTANCE                            /* start of
                                                           instance data    */
HVDM hvdmThisVDM;                                       /* handle of VDM    */
VIRTFLOPPY virtFloppy[MAX_FD];                          /* virtual floppy
                                                           attributes/states*/
HHOOK hhookWaitRequest;                                 /* hook handle for
                                                           VDSKWaitRequest  */
HHOOK hhookDiskRequest;                                 /* hook handle for
                                                           VDSKDiskRequest  */
HHOOK hhookInt13Return;                                 /* hook handle for
                                                           VDSKDiskRequest  */
INT nFunc = -1;                                         /* original
                                                           function #       */
INT iDriveOriginal = -1;                                /* original drive #
                                                           for INT 13h
                                                           request          */
MAPDISK amdInfo[MAX_DRIVES];                            /* remapping info
                                                           for up to 4
                                                           drives           */
REQSTATUS ReqStatusPkt;                                 /* Int 13h request
                                                           status packet
                                                           xxxx             */
DISKREQ DiskReqPkt;                                     /* Int 13h request
                                                           packet xxxx      */
BOOL fInt13Floppy = FALSE;                              /* flag to force
                                                           FLOPPY Int 13 in
                                                           VDSK             */
PSZ pszVMBoot = NULL;                                   /* pointer to
                                                           VMBOOT property
                                                           value            */
PSYS_CONFIG_TABLE pSysConfigTable;                      /* pointer to
                                                           system
                                                           configuration    */

                                                         /*******************/
                                                         /*                 */
                                                         /*******************/

#pragma  END_SWAP_INSTANCE                              /* end of instance
                                                           data             */
#pragma  BEGIN_INIT_CODE

/****************************************************************************
 *
 * FUNCTION NAME = VDDInit
 *
 * DESCRIPTION   =
 *
 *  EP  VDDInit - Virtual Disk Initialization Entry Point
 *
 *      VDSK initialization routine
 *      See VDD Manager for complete semantics.
 *
 *      This dynamically exported subroutine is called during
 *      system initialization.
 *
 *      ENTRY
 *          psz - pointer to configuration strings (not used)
 *
 *      EXIT
 *          SUCCESS
 *              return TRUE
 *          FAILURE
 *              return FALSE - unable to open PDD (PDD absent)
 *                           - unable to open disk VIRQ
 *
 *      CONTEXT
 *          Init-time
 *
 *      PSEUDOCODE
 *          install exit handler;
 *          get entry point from disk PDD (fpfnPDSKVDDProc);
 *          give VDSKPDDProc entry point to PDD;
 *          define user event hooks (VDSKCreateVDM, VDSKTerminateVDM);
 *
 * INPUT         = (PSZ psz)
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

BOOL EXPENTRY VDDInit(PSZ psz)
{

  /*
  **                VDHInstallUserHook(VDD_EXIT, VDSKExit);
  ** Register with PDD
  **                fpfnPDSKVDDProc = VDHOpenPDD(DSK_NAME, VDSKPDDProc);
  **             fpfnPDSKVDDProc = NULL;
  */

  if (!VDHCreateSem(&semDiskReq,
                    VDH_EVENTSEM))
    return  FALSE;

/*
**    if (!VDHCreateSem (&semVM_Boot, VDH_EVENTSEM))        VM_Boot
**          return FALSE;
*/

  VDHInstallUserHook(VDM_CREATE,
                     VDSKCreateVDM);
  VDHInstallUserHook(VDM_TERMINATE,
                     VDSKTerminateVDM);

  /* Register entry point for Int 13 support*/

  if (!VDHRegisterVDD(VDSK_NAME,
                      NULL,
                      vdskVDDEntry))                    /* 6.4              */
    return  FALSE;
  hVDDVFLPY = VDHOpenVDD(VFLPY_NAME);                   /*                  */
  return  TRUE;
}                                                       /* VDDInit          */
#pragma  END_INIT_CODE
#pragma  BEGIN_SWAP_CODE

/****************************************************************************
 *
 * FUNCTION NAME = VDSKExit
 *
 * DESCRIPTION   =
 *
 *  LP  VDSKExit - Virtual disk driver exit handler
 *
 *      VDM Exit Handler
 *      See VDHInstallUserHook for complete semantics.
 *
 *      This registered subroutine is called when MVDM is going to
 *      to shut down.  This allows the disk VDD to clean up resouces
 *      that it has allocated.
 *
 *      ENTRY
 *          None
 *
 *      EXIT
 *          return TRUE
 *
 *      CONTEXT
 *          Initialization
 *          VDM Task-time
 *
 *      PSEUDOCODE
 *          if register with PDSK
 *              call PDD to do de-registration;
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/
/*
**                 HOOKENTRY VDSKExit(VOID)
**             
**                if (fpfnPDSKVDDProc)
**                    (*fpfnPDSKVDDProc)(PDSKCMD_DEREGISTER, F16PNULL, F16PNULL);
**                return TRUE;
**                     VDSKExit
*/
/****************************************************************************
 *
 * FUNCTION NAME = VDSKCreateVDM
 *
 * DESCRIPTION   =
 *
 *  LP  VDSKCreateVDM - VDM creation
 *
 *      VDM creation notification
 *      See VDHInstallUserHook for complete semantics.
 *
 *      This registered subroutine is called each time a new VDM
 *      is created.  Note that not a lot of initialization should be
 *      needed (ie, static initialization for most of the instance
 *      data suffices).
 *
 *      ENTRY
 *          hvdm - handle of VDM
 *
 *      EXIT
 *          SUCCESS
 *              return TRUE
 *          FAILURE
 *              return FALSE - failed to install I/O hooks
 *
 *      CONTEXT
 *          VDM Task-time
 *
 *      PSEUDOCODE
 *          define I/O port hooks;
 *          define Int 13h interrupt vector hook;
 *          initialize instance data;
 *
 * INPUT         = (HVDM hvdm)
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

BOOL HOOKENTRY VDSKCreateVDM(HVDM hvdm)
{
  register ULONG nDrive;
  register PSZ psz;
  pbBusyFlagPtr = VDHGetBusyFlagPtr();                  /*                  */

  /*register IO hook for current VDM*/

  if (VDHInstallIOHook(hvdm,
                       PORT_HF,
                       8,                               /* eight ports      */
                       &iotVDSKPort,
                       !VDH_ASM_HOOK) == 0)
    return  FALSE;
  VDHInstallIntHook(hvdm,
                    BIOSINT_DISKIO,
                    VDSKInt13Proc,
                    !VDH_ASM_HOOK);

  if ((hhookWaitRequest = VDHAllocHook(VDH_WAITVIRRS_HOOK,
                                       VDSKWaitRequest,
                                       0)) == NULL)
    return  FALSE;

  /*
  **                if ((hhookDiskRequest = VDHAllocHook(VDH_WAITVIRRS_HOOK,
  **                                                     VDSKDiskRequest,
  **                                                     sizeof(ULONG))) == NULL)
  **                    return FALSE;
  */

  if ((hhookInt13Return = VDHAllocHook(VDH_RETURN_HOOK,
                                       VDSKInt13Return,
                                       0)) == NULL)
    return  FALSE;

    /* Install Int Hook for VDD - DOS communication*/
/*
**   VDHInstallIntHook(hvdm,                  VM_Boot                
**                     0x66,                  VM_Boot                
**                     VDSKDOSLink,           VM_Boot                
**                     !VDH_ASM_HOOK);        VM_Boot                
*/
/*
** VDHInstallIntHook(hvdm,                    VM_Boot
**                   0x66,                    VM_Boot
**                   VDSKDOSLink,             VM_Boot
**                   !VDH_ASM_HOOK);          VM_Boot
*/

  VDHRegisterAPI(VDSK_NAME,
                 (PFNHOOK)VDSKDOSLink,
                 0);                                    /*                  */

  if (hVDDVFLPY == NULL)                                /*                  */
    hVDDVFLPY = VDHOpenVDD(VFLPY_NAME);                 /*                  */

  /* initialize instance data*/

  hvdmThisVDM = hvdm;

/*
**   See if PDD supports SUSPEND/RESUME IOCTL calls
**   Suspend support ?     if (flPDDSuspend == -1) {
**
** Suspend support ?         FileName[0] = (CHAR) ('A');                                                                        NoPdd                    
** Suspend support ?         VDHOpen( FileName, &DeviceHandle, &ActionTaken, 0L, 0L,                                       NoPdd                    
** Suspend support ?             VDHOPEN_ACTION_OPEN_IF_EXISTS, VDHOPEN_FLAGS_FAIL_ON_ERROR+VDHOPEN_FLAGS_DASD+VDHOPEN_SHARE_DENYNONE                      
** Suspend support ?             +VDHOPEN_ACCESS_READWRITE, NULL);                                                            NoPdd                    
** Suspend support ?         SuspendRestartParmPacket.Command = DSKT_SUSPEND;
** Suspend support ?         LengthParm = sizeof(SuspendRestartParmPacket);        \
** Suspend support ?
** Suspend support ?         SuspendRestartParmPacket.DriveNum=0;     alex
** Suspend support ?         if ( flPDDSuspend=VDHDevIOCtl ( DeviceHandle, IOCTL_DISK, DSKT_IODC_QD, &SuspendRestartParmPacket, LengthParm, &LengthParm, NULL, NULL, NULL) ){              
** Suspend support ?               SuspendRestartParmPacket.Command = DSKT_RESTART;           \
** Suspend support ?               VDHDevIOCtl ( DeviceHandle, IOCTL_DISK, DSKT_IODC_QD, &SuspendRestartParmPacket, LengthParm, &LengthParm, NULL, NULL, NULL);
** Suspend support ?         }
** Suspend support ?         VDHClose( DeviceHandle);                                          NoPdd                            
** Suspend support ?     }  endif *
** Suspend support ?     for (nDrive = 0; nDrive < MAX_FD; nDrive++)
**        if(fpfnPDSKVDDProc) {                        NoPdd                                 
**          if ((*fpfnPDSKVDDProc)(PDSKCMD_QUERYDRVTYPE,                                     
**                                 (F16PVOID)nDrive,                                         
**                                 F16PFROMP(&virtFloppy[nDrive].vf_bDriveType))) {          
**              DRVTYPE_NONE does not come in here because PDD returns FALSE                 
**              virtFloppy[nDrive].vf_fDiskChanged = TRUE;                                   
**              virtFloppy[nDrive].vf_usFormatTracks =                                       
**                  amtMediaTable[virtFloppy[nDrive].vf_bDriveType-1].mt_usTracks;           
**              virtFloppy[nDrive].vf_usFormatSectors =                                      
**                  amtMediaTable[virtFloppy[nDrive].vf_bDriveType-1].mt_usSectors;          
**          }                                                                                
**        } else {                                                                                                         NoPdd
** Suspend support ?      if (!flPDDSuspend) {
** Suspend support ?           FileName[0] = (CHAR) (nDrive+'A');        max # floppy drives                                    NoPdd
** Suspend support ?           if( !VDHOpen( FileName, &DeviceHandle, &ActionTaken, 0L, 0L,                                        NoPdd
** Suspend support ?               VDHOPEN_ACTION_OPEN_IF_EXISTS, VDHOPEN_FLAGS_FAIL_ON_ERROR+VDHOPEN_FLAGS_DASD+VDHOPEN_SHARE_DENYNONE
** Suspend support ?               +VDHOPEN_ACCESS_READWRITE, NULL) ) {                                                           NoPdd
** Suspend support ?                 DeviceHandle = -1; }
** Suspend support ?             GetDeviceParmsParmPacket.Command = RECOMMENDED_BPB;                                              NoPdd
** Suspend support ?             LengthParm = sizeof( GetDeviceParmsParmPacket);                                                  NoPdd
** Suspend support ?             LengthData = sizeof( GetDeviceParmsDataPacket);                                                  NoPdd
** Suspend support ?             GetDeviceParmsParmPacket.DriveNum=nDrive;
** Suspend support ?             VDHDevIOCtl (DeviceHandle, IOCTL_DISK, DSK_GETDEVICEPARAMS, (PVOID) &GetDeviceParmsParmPacket, LengthParm, (PULONG) &LengthParm,  NoPdd
** Suspend support ?                          (PVOID) &GetDeviceParmsDataPacket, LengthData, (PULONG) &LengthData);               NoPdd
** Suspend support ?             if (GetDeviceParmsDataPacket.DeviceType<=2)        0-based   (0=360Kb, 1=1.2Mb, 2=720Kb)       NoPdd
** Suspend support ?                virtFloppy[nDrive].vf_bDriveType = GetDeviceParmsDataPacket.DeviceType+1;  1-based          NoPdd
** Suspend support ?             else if (GetDeviceParmsDataPacket.DeviceType==7)   7 == Other                                  NoPdd
** Suspend support ?                virtFloppy[nDrive].vf_bDriveType   = DRVTYPE_1440K;                                           NoPdd
** Suspend support ?             virtFloppy[nDrive].vf_fDiskChanged    = TRUE;                                                    NoPdd
** Suspend support ?             virtFloppy[nDrive].vf_usFormatTracks  = GetDeviceParmsDataPacket.NumCyl;                         NoPdd
** Suspend support ?             virtFloppy[nDrive].vf_usFormatSectors = GetDeviceParmsDataPacket.ExtendedBPB.sectors_per_track;  NoPdd
** Suspend support ?             if(DeviceHandle!=0xffff) VDHClose( DeviceHandle);                                                                         NoPdd
** Suspend support ?      }                                                                                                      NoPdd
*/

  psz = (PSZ)VDHQueryProperty(pszVMBootName);
  pszVMBoot = psz;

  while (*psz == ' ')
    psz++;

  if (*psz)
    return (VDSKOpenVirtDisks(psz));                    /*                  */
  return  TRUE;
}                                                       /* VDSKCreateVDM    */

/* VM_Boot*/
/****************************************************************************
 *
 * FUNCTION NAME = VDSKDOSLink
 *
 * DESCRIPTION   =
 *
 *  LP  VDSKDOSLink -  Provide an interface for DOS Device driver
 *
 *      This function is called by our stub
 *      (which is sitting in VDM memory).  The register frame
 *      contains the registers as when invoked by the application.
 *
 *      ENTRY   p     - reserved
 *              pcrf  - client's register frame.
 *                      Registers contain input parameters
 *                      for services.
 *
 *      EXIT    Always succeeds;
 *              client's registers contain information, depending
 *                      on which service was called.
 *
 *      GLOBAL EFFECTS
 *          depends on service called
 *
 *      METHOD
 *          use VDHPopInt to remove ROM return address from pcrf
 *          service = client's AH
 *
 * INPUT         = (PVOID p,PCRF pcrf)
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

VOID HOOKENTRY VDSKDOSLink(PVOID p,PCRF pcrf)
{
  UINT uFunction;

  /*             PVOID pVDDName;*/

  PVOID pBreakPnt;
  register PMAPDISK pmd;
  VPVOID vpretaddr;

/*             pVDDName = PFROMVADDR(DS(pcrf),SI(pcrf));*/
/*             if((*(PULONG)pVDDName)==0x4B534456) {    Look for the letters VDSK*/

  if (VDHPopStack(4,
                  SSToDS(&vpretaddr)))
  {
    IP(pcrf) = OFFSETOF16(vpretaddr);
    CS(pcrf) = SEGMENTOF16(vpretaddr);

    /*               VDHPopInt();     prevent return to ROM*/

    pmd = &amdInfo[0];
    uFunction = AH(pcrf);

    if (uFunction == 1)
    {                                                   /* get breakpoint
                                                           cmd              */
      AL(pcrf) = !(pmd->md_fbPhysDisk == MDFLAGS_PHYSICAL);/* (0:physical   */
                                                         /* drive; !0:dskt  */
                                                         /* image)          */

    }

    else

      if (uFunction == 2)
      {                                                 /* get breakpoint
                                                           cmd              */
        pmd->md_iPhysical = -1;

        if (pmd->md_fbPhysDisk == MDFLAGS_VIRTUAL)
        {

/*                            VDHDevIOCtl ( REFHVDM(CURRENT_VDM, HFILE, hfTmp), IOCTL_DISK, DSK_UNLOCKDRIVE, (PVOID) &LockParmsParmPacket, LengthParm, (PULONG) &LengthParm, NULL, NULL, NULL);  NoPdd             */

          VDHClose(REFHVDM(CURRENT_VDM,
                           HFILE,
                           hfTmp));
        }

        /* deadlock       } else*/
/* deadlock            VDHRequestVDD( hVDDVFLPY,CURRENT_VDM, RESUME_PDD_CMD, NULL, NULL);               */

        pmd->md_fbPhysDisk &= !MDFLAGS_PHYSICAL;
        pmd->md_fbPhysDisk &= !MDFLAGS_VIRTUAL;
      }
  }
  return ;
}                                                       /* end VDSKDOSLink  */

/****************************************************************************
 *
 * FUNCTION NAME = VDSKTerminateVDM
 *
 * DESCRIPTION   =
 *
 *  LP  VDSKTerminateVDM - VDM Destruction
 *
 *      VDM destruction notification
 *      See VDHInstallUserHook for complete semantics.
 *
 *      This registered subroutine is called each time a VDM
 *      is destroyed.  This handler deallocates the per VDM
 *      resources used by the VDM being destroyed.
 *
 *      ENTRY
 *          hvdm - handle of VDM
 *
 *      EXIT
 *          return TRUE
 *
 *      CONTEXT
 *          VDM Task-time
 *
 *      PSEUDOCODE
 *          deallocate I/O port hooks;
 *
 * INPUT         = (HVDM hvdm)
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

BOOL HOOKENTRY VDSKTerminateVDM(HVDM hvdm)
{
  VDSKCloseVirtDisks();

  if (pszVMBoot)
  {
    VDHFreeMem(pszVMBoot);                              /* 6.30             */
    pszVMBoot = NULL;
  }

  /* 59697 Unlock locked memory before exiting.*/

  if (REFHVDM(hvdm,
              HLOCK,
              hLockMem))
  {                                                     /*                  */
    VDHUnlockMem(REFHVDM(hvdm,
                         HLOCK,
                         hLockMem));                    /*                  */
    REFHVDM(hvdm,
            HLOCK,
            hLockMem) = NULL;                           /*                  */
  }
  return  TRUE;
}                                                       /* VDSKTerminateVDM */

/****************************************************************************
 *
 * FUNCTION NAME = VDSKOpenVirtDisks
 *
 * DESCRIPTION   =
 *
 *  LP  VDSKOpenVirtDisks - Open all virtual disks specified
 *
 *      ENTRY
 *          None
 *
 *      EXIT
 *          amdInfo updated
 *
 *      CONTEXT
 *          VDM Task-time
 *
 *      PSEUDOCODE
 *          if the boot path is a disk
 *              get the disk number
 *              remap drive A: to that drive
 *          else
 *              open the file
 *              if the file isn't a diskette image
 *                  close the file
 *              if the file is open
 *                  remap the A: drive to this file handle
 *
 * INPUT         = (PSZ psz)
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

BOOL PRIVENTRY VDSKOpenVirtDisks(PSZ psz)               /*                  */
{
  INT iPhysical;
  register PMAPDISK pmd;
  register PSZ pszFile;
  ULONG flResp;                                         /* Popup response
                                                           flag VM_Boot     */
  pmd = &amdInfo[0];

  for (pszFile = psz; *psz; psz++)

    if (*psz == ' ')
    {
      *psz++ = 0;
      break;
    }

  if ((*(pszFile+2) == 0) || ((*(pszFile+2) == '\\') && (*(pszFile+3) == '\0')
     ))
  {                                                     /* 6.29             */
    iPhysical = *pszFile;

    if (iPhysical >= 'a' && iPhysical <= 'z')
      iPhysical -= 'a';

    else
      iPhysical -= 'A';

    /*      if (iPhysical >=0 && iPhysical < 26) {*/

    if (iPhysical == 0)
    {                                                   /* VM_Boot If
                                                           booting from C:
                                                           (DOS Partition)
                                                           we don't use A:  */

      if (iPhysical >= 2)
        iPhysical += (DRIVE_HDMASK-2);
      pmd->md_iPhysical = iPhysical;
      pmd->md_fbPhysDisk |= MDFLAGS_PHYSICAL;
    }
  }

  else
  {

/*
**        if (!VDHWaitEventSem( semVM_Boot, SEM_IMMEDIATE_RETURN)) {   VM_Boot
**             VDHPopup((PSZZ)SSToDS(pszFile),1,108,
**                      SSToDS(&flResp), VDHP_TERMINATE_SESSION, NULL);
**             return;
**          }
*/

    if (VDHOpen(pszFile,
                &hfTmp,
                &ulAction,
                0L,
                VDHOPEN_FILE_ARCHIVED,
                VDHOPEN_FILE_OPEN,                      /*                  */
                VDHOPEN_SHARE_DENYREADWRITE+VDHOPEN_ACCESS_READWRITE,
                NULL))
    {                                                   /*                  */
      LengthParm = sizeof(LockParmsParmPacket);         /*                  */

/*                         VDHDevIOCtl (hfTmp, IOCTL_DISK, DSK_LOCKDRIVE, (PVOID) &LockParmsParmPacket, LengthParm, (PULONG) &LengthParm, NULL, NULL, NULL);       NoPdd             */

      if (!(VDHRead(hfTmp,
                    &pmd->md_vdInfo,
                    sizeof(VIRTDISK)) == sizeof(VIRTDISK)))
      {                                                 /*                  */

/*                            VDHDevIOCtl (hfTmp, IOCTL_DISK, DSK_UNLOCKDRIVE, (PVOID) &LockParmsParmPacket, LengthParm, (PULONG) &LengthParm, NULL, NULL, NULL);  NoPdd             */

        VDHClose(hfTmp);
        hfTmp = NULL;
      }
    }

    else
    {                                                   /* There was a
                                                           problem opening
                                                           file **
                                                                            */

      switch (VDHGetError())
      {                                                 /*                  */
        case  ERROR_DRIVE_LOCKED :                      /*                  */
        case  ERROR_SHARING_VIOLATION :                 /*                  */
          VDHPopup(NULL,
                   0,
                   108,
                   SSToDS(&flResp),
                   VDHP_TERMINATE_SESSION,
                   NULL);                               /* MSG_ERROR_LOCKED */
          return  FALSE;
          break;                                        /*                  */
        case  ERROR_ACCESS_DENIED :                     /*                  */
          VDHOpen(pszFile,
                  &hfTmp,
                  &ulAction,
                  0L,
                  VDHOPEN_FILE_ARCHIVED,
                  VDHOPEN_FILE_OPEN,                    /*                  */
                  VDHOPEN_SHARE_DENYNONE+VDHOPEN_ACCESS_READONLY,
                  NULL);                                /*                  */
          LengthParm = sizeof(LockParmsParmPacket);     /*                  */

/*                          VDHDevIOCtl (&hfTmp, IOCTL_DISK, DSK_LOCKDRIVE, (PVOID) &LockParmsParmPacket, LengthParm, (PULONG) &LengthParm, NULL, NULL, NULL);       NoPdd             */

          if (!(VDHRead(hfTmp,
                        &pmd->md_vdInfo,
                        sizeof(VIRTDISK)) == sizeof(VIRTDISK)))
          {                                             /*                  */

/*                             VDHDevIOCtl (&hfTmp, IOCTL_DISK, DSK_UNLOCKDRIVE, (PVOID) &LockParmsParmPacket, LengthParm, (PULONG) &LengthParm, NULL, NULL, NULL);  NoPdd             */

            VDHClose(hfTmp);
            hfTmp = NULL;
          }
          break;                                        /*                  */
        default  :                                      /*                  */
          VDHPopup(NULL,
                   0,
                   110,
                   SSToDS(&flResp),
                   VDHP_TERMINATE_SESSION,
                   NULL);                               /*
                                                         MSG_ERROR_OPEN_FAILED
                                                                            */
          return  FALSE;
      }                                                 /* endswitch        */
                                                         /*                 */

    }

    if (hfTmp)
    {
      pmd->md_hfVirtDisk = hfTmp;
      pmd->md_fbPhysDisk |= MDFLAGS_VIRTUAL;
    }
  }
  return  TRUE;                                         /*                  */
}

/****************************************************************************
 *
 * FUNCTION NAME = VDSKCloseVirtDisks
 *
 * DESCRIPTION   =
 *
 *  LP  VDSKCloseVirtDisks - Close all virtual disks currently open
 *
 *      ENTRY
 *          None
 *
 *      EXIT
 *          None
 *
 *      CONTEXT
 *          VDM Task-time
 *
 * INPUT         = ()
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

VOID PRIVENTRY VDSKCloseVirtDisks()
{
  register INT iDrive;

  for (iDrive = 0; iDrive < MAX_DRIVES; iDrive++)
  {

    if (amdInfo[iDrive].md_fbPhysDisk&MDFLAGS_VIRTUAL)
      VDHClose(amdInfo[iDrive].md_hfVirtDisk);
  }
}

/****************************************************************************
 *
 * FUNCTION NAME = vdskVDDEntry
 *
 * DESCRIPTION   =
 *
 *  LP  vdskVDDEntry - entry point for inter-vdd communication
 *
 *      This function is called by VDDs for special t value held in
 *      a POS register. It does not support any other requests.
 *
 *      ENTRY
 *          HVDM    hvdm    - VDM handle (must be 0)
 *          ULONG   ulCmd   - Command
 *          PVOID   pReqIn  - Input packet
 *          PVOID   pReqOut - output packet
 *
 *      EXIT SUCCESS
 *          TRUE
 *
 *      EXIT FAILURE
 *          FALSE
 *
 *      CONTEXT
 *          Current VDM
 *
 * INPUT         = (hvdm,ulCmd,pReqIn,pReqOut)
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 *
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/

LONG EXPENTRY vdskVDDEntry(hvdm,ulCmd,pReqIn,pReqOut)
  HVDM hvdm;
  ULONG ulCmd;
  PVOID pReqIn;
  PVOID pReqOut;
{
  PCRF pcrf;
  USHORT usSaveAX;

  switch (ulCmd)
  {
    case  VDSK_INT13BOOT :                              /* Read the boot
                                                           sector into VDM
                                                           space            */
      pcrf = (PCRF)pReqIn;
      usSaveAX = AX(pcrf);
      fInt13Floppy = TRUE;                              /* mark as
                                                           potential floppy
                                                           request          */
      VDSKInt13Proc(pcrf);

      if (FL(pcrf)&F_CARRY)
      {                                                 /* if failed, retry
                                                           once more        */
        AX(pcrf) = usSaveAX;
        VDSKInt13Proc(pcrf);
      }
      fInt13Floppy = FALSE;                             /* unmark           */
      break;
    default  :
      VDHSetError(VDSK_INVALID_FUNCTION);
      return  FALSE;
  }
  return  TRUE;
}

#pragma  END_SWAP_CODE
