home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cdrom.zip / DDK / BASE / SRC / VDEV / VCDROM / vcdrom2f.c < prev    next >
C/C++ Source or Header  |  1996-06-18  |  50KB  |  1,439 lines

  1. /**************************************************************************
  2.  *
  3.  * SOURCE FILE NAME = VCDROM2F.C
  4.  *
  5.  * DESCRIPTIVE NAME = VCDROM MSCDEX 2F support for CD-ROM in a DOS session.
  6.  *
  7.  * DESCRIPTION This module contains the (MSCDEX) int 2fh and DOS CD-ROM
  8.  *             device driver service routines.
  9.  *
  10.  * Copyright : COPYRIGHT IBM CORPORATION, 1991, 1992
  11.  *             Copyright Microsoft Corporation, 1990
  12.  *             LICENSED MATERIAL - PROGRAM PROPERTY OF IBM
  13.  *             REFER TO COPYRIGHT INSTRUCTION FORM#G120-2083
  14.  *             RESTRICTED MATERIALS OF IBM
  15.  *             IBM CONFIDENTIAL
  16.  *
  17.  * ENTRY POINTS:
  18.  *             VCDROMDosLink
  19.  *               SendDeviceRequest
  20.  *               ResetMedia
  21.  *               GetDriveHandle
  22.  *               MapOS2toDosCode
  23.  *               GetPlayStatus
  24.  *               HsgToRedbook
  25.  *               AddSectors
  26.  *
  27.  * EXTERNAL REFERENCES:
  28.  *
  29.  * CHANGE ACTIVITY =
  30.  *  DATE      FLAG        APAR   CHANGE DESCRIPTION
  31.  *  --------  ----------  -----  --------------------------------------
  32.  *  mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
  33.  *  08/16/91  @V2.0DTF           Created.
  34.  *
  35.  *  09/26/92  @V2.1FJS00         Added MSCDEX 0x2f calls previously not
  36.  *                               supported.  Converted VCDROMDosLink from
  37.  *                               0x66 to 0x2f routine.
  38.  *
  39.  *  03/34/92  @V2.1FJS01         Deleted message includes in reqhdr.h and added
  40.  *                               systemwide bseerr.h.  Added media check for
  41.  *                               MSCDEX api.  Could have done open/close around
  42.  *                               each VDHFSCtl call but too much performance
  43.  *                               penalty.
  44.  *
  45.  *  04/12/93  @V2.1FJS02         Removed VdhQueryLin call from MSCDEX calls
  46.  *                               since segment portion of pointers can only be
  47.  *                               real mode segment value (per MSCDEX 2.21 spec).
  48.  *
  49.  *  08/06/93  @V2.1FJS03         Changed Absolute Disk Read to clear carry flag
  50.  *                               and set AX=0 when function succeeds for Bible
  51.  *                               Library Version 1.1. MSCDEX specification does
  52.  *                               not require AX=0.
  53.  *
  54.  *  04/04/95  @V113078           Allow raw Read_Longs.  These Read_Longs do use
  55.  *                               the File System as they are non-standard
  56.  *                               sector sizes (2352).  However, there is a
  57.  *                               direct IOCTL to the device manager to read
  58.  *                               this type of sector (Cat 80 Fun 72)
  59.  *
  60.  ****************************************************************************/
  61.  
  62.  
  63. #define INCL_DOSERRORS
  64. #include <bseerr.h>
  65. #include <mvdm.h>
  66. #include <mscdex.h>
  67. #include "vcdromp.h"
  68. #include "reqhdr.h"
  69. #include "ctrlblk.h"
  70.  
  71.  
  72. #ifdef  VDDSTRICT
  73. MODNAME = __FILE__;
  74. #endif
  75.  
  76. /*
  77. **  External References
  78. */
  79.  
  80. /*
  81. **  Global Data
  82. */
  83. extern
  84. BOOL    flSLAVE;
  85. extern
  86. PFN     pfnSlaveRequest;
  87.  
  88. extern
  89. struct
  90. CategoryCode
  91. IoctlInputCodes [];
  92.  
  93. extern
  94. struct
  95. CategoryCode
  96. IoctlOutputCodes [];
  97.  
  98. extern
  99. USHORT  NumberOfDrives;
  100. extern
  101. USHORT  FirstDriveNumber;
  102.  
  103. extern
  104. HFILE
  105. DriveHandle [MAX_NUMBER_OF_DRIVES];         /* DASD-open drive handles      */
  106.  
  107. extern
  108. UCHAR
  109. DriveString [];                             /* Drive letter strings         */
  110.  
  111. extern
  112. VPDOSDDTYPE DosDDHeader;                    /* V86FAR address of dos driver */
  113.  
  114.  
  115. /*
  116. **  Instance Data
  117. */
  118. extern
  119. HVDM        hvdmCurrent;
  120. extern
  121. ULONG       slaveparms [];
  122. extern
  123. ULONG       DataArea[];
  124. extern
  125. ULONG       ParmList[];
  126. extern
  127. ULONG       DataLengthInOut;
  128. extern
  129. ULONG       ParmLengthInOut;
  130. extern
  131. HFILE       FileHandle;                     /* for VDHOpen                  */
  132. extern
  133. ULONG       ActionTaken;                    /* for VDHOpen                  */
  134.  
  135.  
  136. #pragma BEGIN_GLOBAL_CODE
  137.  
  138. #pragma END_GLOBAL_CODE
  139.  
  140. #pragma BEGIN_SWAP_CODE
  141.  
  142.  
  143. /****************************************************************************
  144.  *
  145.  * FUNCTION NAME = VCDROMDosLink
  146.  *
  147.  * DESCRIPTION   = Handle MSCDEX 2f interrupts ( AH == 15h )
  148.  *
  149.  *       The DOS stub device driver hooks the MSCDEX 2f interrupts and
  150.  *       calls this function by use of an ARPL instruction.
  151.  *
  152.  *       Some MSCDEX (DOS CD-ROM file system driver) 2f services are
  153.  *       implemented here others by the OS/2 CD-ROM installable file
  154.  *       system (CDROM.IFS).  VCDROM calls the installable file system
  155.  *       via the VDHFSCtl service.
  156.  *
  157.  *       MSCDEX API parameters must be real mode addresses (per the
  158.  *       MSCDEX 2.21 Specification).
  159.  *
  160.  *       Audio and other ioctls are supported through Send Driver Request.
  161.  *       The app formats an ioctl input or ioctl output DOS driver request
  162.  *       packet to be forwarded to the CD-ROM device driver for service.
  163.  *       The format of these requests is described in the Microsoft
  164.  *       MSCDEX spec. The method used here is to convert the DOS request
  165.  *       into an OS/2 generic ioctl that is sent to the OS/2 CD-ROM device
  166.  *       driver through the VDHDevIOCtl call. The format of the OS/2 CD-ROM
  167.  *       ioctls is described in the CDFS (OS/2 file system driver) spec.
  168.  *
  169.  *       Some DOS apps (Groliers) bypass MSCDEX, calling the dos driver
  170.  *       directly. The DOS stub converts these requests into 2f Send Driver
  171.  *       Request format for consistency.
  172.  *
  173.  *       CONTEXT:
  174.  *          VDM Task-time
  175.  *
  176.  *       PSEUDOCODE:
  177.  *          VDHPopInt to prevent ROM code execution.
  178.  *          If MSCDEX function 10h, call SendDeviceRequest,
  179.  *           otherwise either call the installable file system for service
  180.  *           or service it here.
  181.  *
  182.  * INPUT         = pcrf   - pointer to client register frame
  183.  *
  184.  * OUTPUT        = returns TRUE == serviced interrupt
  185.  *                 returns FALSE == not mine
  186.  *
  187.  * RETURN-NORMAL =
  188.  * RETURN-ERROR  =
  189.  *
  190.  ****************************************************************************/
  191.  
  192. BOOL HOOKENTRY VCDROMDosLink (PVOID pHookData, register PCRF pcrf)
  193. {
  194.     register
  195.     struct
  196.     DosRh   *reqhdr;                      /* dos request header              */
  197.     register
  198.     PUCHAR  buffer;
  199.     PUCHAR  szpathname;                   /* ptr to path name                */
  200.     USHORT  i;                            /* counter                         */
  201.     PUCHAR  ptmp1;                        /* temp ptr                        */
  202.     ULONG   drive_number;
  203.     ULONG   n;
  204.     ULONG   rc;
  205.     PULONG  vdd_name;
  206.     HFILE   handle;
  207.     ULONG   sector_index;
  208.  
  209. /* INT_3; */
  210.     VDHPopInt();                          /* to prevent ROM code execution   */
  211.  
  212.     if ( AL (pcrf) == SEND_DEVICE_REQUEST )
  213.     {
  214.         reqhdr = PFROMVADDR ( ES (pcrf), BX (pcrf) );
  215.         drive_number = CX (pcrf);
  216.         if ( drive_number == 0 )               /* 0 = no drive number        */
  217.         {
  218.             drive_number = UNIT_TO_DRIVE_NUMBER ( reqhdr->subunit );
  219.         }
  220.         SendDeviceRequest ( reqhdr, drive_number );
  221.  
  222.     }
  223.     else                                       /* infrequent 2f services     */
  224.     {
  225.         switch ( AL (pcrf) )
  226.         {
  227.             case GET_NUMBER_CDROM_DRIVE_LETTERS:
  228.  
  229.                 BX (pcrf) = NumberOfDrives;
  230.                 CX (pcrf) = FirstDriveNumber;
  231.                 break;
  232.  
  233.             case GET_CDROM_DRIVE_DEVICE_LIST:
  234.  
  235.                 buffer = PFROMVADDR ( ES (pcrf), BX (pcrf) );
  236.                 for ( n = 0; n < NumberOfDrives; ++n )
  237.                 {
  238.                     *buffer = (UCHAR) n;       /* subunit number             */
  239.                     ++buffer;
  240.                     * ((PULONG) buffer) = (ULONG) DosDDHeader;
  241.                     buffer += 4;
  242.                 }
  243.                 break;
  244.  
  245.             case GET_COPYRIGHT_FILE_NAME:
  246.             case GET_ABSTRACT_FILE_NAME:
  247.             case GET_BIBLIOGRAPHIC_FILE_NAME:
  248.  
  249.                /*
  250.                ** get VDHOpen handle to CD-ROM drive specified in CX
  251.                */
  252.                drive_number = CX (pcrf);
  253.                handle = GetDriveHandle (drive_number);
  254.                if (handle == NULL)
  255.                {
  256.                   AX (pcrf) = ERROR_I24_WRONG_DISK;      // INVALID_DRIVE
  257.                   FL (pcrf) |= CARRY_FLAG;
  258.                   break;
  259.                }
  260.  
  261.                /*
  262.                ** convert virtual address to 0:32 flat address
  263.                */
  264.                buffer = (PUCHAR)((ULONG)PFROMVADDR(ES(pcrf),BX(pcrf))+
  265.                                                   (ULONG)hvdmCurrent);
  266.  
  267.                                                 /* set user buffer length    */
  268.                DataLengthInOut=MAX_FILE_ID_LEN;
  269.                                                 /* set MSCDEX function code  */
  270.                ((PGETFILE)ParmList)->ulFunction=(ULONG)AL(pcrf);
  271.                                                 /* set structure length      */
  272.                ParmLengthInOut=sizeof(GETFILE);
  273.  
  274.                /*
  275.                ** call CD-ROM IFS for file name
  276.                */
  277.                rc = VDHFSCtl((PVOID)buffer,
  278.                              (ULONG)DataLengthInOut,
  279.                              (PVOID)&DataLengthInOut,
  280.                              (PVOID)&ParmList,
  281.                              (ULONG)ParmLengthInOut,
  282.                              (PVOID)&ParmLengthInOut,
  283.                              (ULONG)FSCTL_ARG_MSCDEX,
  284.                              (PSZ)NULL,
  285.                              handle,
  286.                              FSCTL_HANDLE);
  287.  
  288.                if ( rc == VDH_FAILURE )
  289.                {
  290.                    rc = VDHGetError ();
  291.                    AX (pcrf) = ERROR_I24_NOT_READY;      // DRIVE_NOT_READY
  292.                    FL (pcrf) |= CARRY_FLAG;
  293.                    break;
  294.                }
  295.                FL (pcrf) &= ~CARRY_FLAG;
  296.                break;
  297.  
  298.             case READ_VTOC:
  299.  
  300.                /*
  301.                ** get VDHOpen handle to CD-ROM drive specified in CX
  302.                */
  303.                drive_number = CX (pcrf);
  304.                handle = GetDriveHandle (drive_number);
  305.                if (handle == NULL)
  306.                {
  307.                   AX (pcrf) = ERROR_I24_WRONG_DISK;      // INVALID_DRIVE
  308.                   FL (pcrf) |= CARRY_FLAG;
  309.                   break;
  310.                }
  311.  
  312.                /*
  313.                ** convert virtual address to 0:32 flat address
  314.                */
  315.                buffer = (PUCHAR)((ULONG)PFROMVADDR(ES(pcrf),BX(pcrf))+
  316.                                                   (ULONG)hvdmCurrent);
  317.  
  318.                                                 /* set user buffer length    */
  319.                DataLengthInOut=CDROM_SECTOR_SIZE;
  320.                                                 /* set MSCDEX function code  */
  321.                ((PREADVTOC)ParmList)->ulFunction=(ULONG)AL(pcrf);
  322.                                                 /* set MSCDEX sector index   */
  323.                ((PREADVTOC)ParmList)->ulSectorIndex=(ULONG)DX(pcrf);
  324.                                                 /* set structure length      */
  325.                ParmLengthInOut=sizeof(READVTOC);
  326.  
  327.                /*
  328.                ** call CD-ROM IFS to read VTOC
  329.                */
  330.                rc = VDHFSCtl((PVOID)buffer,
  331.                              (ULONG)DataLengthInOut,
  332.                              (PVOID)&DataLengthInOut,
  333.                              (PVOID)&ParmList,
  334.                              (ULONG)ParmLengthInOut,
  335.                              (PVOID)&ParmLengthInOut,
  336.                              (ULONG)FSCTL_ARG_MSCDEX,
  337.                              (PSZ)NULL,
  338.                              handle,
  339.                              FSCTL_HANDLE);
  340.  
  341.                if ( rc == VDH_FAILURE )
  342.                {
  343.                    rc = VDHGetError ();
  344.                    AX (pcrf) = ERROR_I24_NOT_READY;      // DRIVE_NOT_READY
  345.                    FL (pcrf) |= CARRY_FLAG;
  346.                    break;
  347.                }
  348.                else
  349.                {
  350.                    if (*(PUCHAR)ParmList == STANDARD_VOLUME_DESCRIPTOR)
  351.                         AX (pcrf) = STANDARD_VOLUME_DESCRIPTOR;
  352.                    else
  353.                    {
  354.                         if (*(PUCHAR)ParmList == VOLUME_DESCRIPTOR_TERMINATOR)
  355.                              AX (pcrf) = VOLUME_DESCRIPTOR_TERMINATOR;
  356.                         else
  357.                              AX (pcrf) = OTHER_VOLUME_DESCRIPTOR;
  358.                    }
  359.                    FL (pcrf) &= ~CARRY_FLAG;
  360.                }
  361.                break;
  362.  
  363.             case ABSOLUTE_DISK_READ:
  364.  
  365.                /*
  366.                ** get VDHOpen handle to CD-ROM drive specified in CX
  367.                */
  368.                drive_number = CX (pcrf);
  369.                handle = GetDriveHandle (drive_number);
  370.                if (handle == NULL)
  371.                {
  372.                   AX (pcrf) = ERROR_I24_WRONG_DISK;      // INVALID_DRIVE
  373.                   FL (pcrf) |= CARRY_FLAG;
  374.                   break;
  375.                }
  376.  
  377.                /*
  378.                ** convert virtual address to 0:32 flat address
  379.                */
  380.                buffer = (PUCHAR)((ULONG)PFROMVADDR(ES(pcrf),BX(pcrf))+
  381.                                                   (ULONG)hvdmCurrent);
  382.  
  383.                                                 /* set user buffer length    */
  384.                DataLengthInOut=CDROM_SECTOR_SIZE * DX(pcrf);
  385.                                                 /* set MSCDEX function code  */
  386.                ((PABSREAD)ParmList)->ulFunction=(ULONG)AL(pcrf);
  387.                                                 /* set MSCDEX sector count   */
  388.                ((PABSREAD)ParmList)->ulSectorCount=(ULONG)DX(pcrf);
  389.                                                 /* set MSCDEX sector start   */
  390.                ((PABSREAD)ParmList)->usSectStartLo=DI(pcrf);
  391.                                                 /* set MSCDEX sector start   */
  392.                ((PABSREAD)ParmList)->usSectStartHi=SI(pcrf);
  393.                                                 /* set structure length      */
  394.                ParmLengthInOut=sizeof(ABSREAD);
  395.  
  396.                if (flSLAVE)                     /* if INT_DURING_IO property */
  397.                {
  398.                  slaveparms[0] = (ULONG)buffer;
  399.                  slaveparms[1] = DataLengthInOut;
  400.                  slaveparms[2] = (ULONG)&DataLengthInOut;
  401.                  slaveparms[3] = (ULONG)&ParmList;
  402.                  slaveparms[4] = ParmLengthInOut;
  403.                  slaveparms[5] = (ULONG)&ParmLengthInOut;
  404.                  slaveparms[6] = FSCTL_ARG_MSCDEX;
  405.                  slaveparms[7] = NULL;
  406.                  slaveparms[8] = (ULONG)handle;
  407.                  slaveparms[9] = FSCTL_HANDLE;
  408.  
  409.                  pcrf->crf_eax = (ULONG)&slaveparms[0]; /* pass parameters   */
  410.                  pfnSlaveRequest (pcrf);        /* call slave thread         */
  411.                }
  412.                else
  413.                {
  414.                  /*
  415.                  ** call CD-ROM IFS for ABSOLUTE DISK READ
  416.                  */
  417.                  rc = VDHFSCtl((PVOID)buffer,
  418.                                (ULONG)DataLengthInOut,
  419.                                (PVOID)&DataLengthInOut,
  420.                                (PVOID)&ParmList,
  421.                                (ULONG)ParmLengthInOut,
  422.                                (PVOID)&ParmLengthInOut,
  423.                                (ULONG)FSCTL_ARG_MSCDEX,
  424.                                (PSZ)NULL,
  425.                                handle,
  426.                                FSCTL_HANDLE);
  427.  
  428.                  if ( rc == VDH_FAILURE )
  429.                  {
  430.                      rc = VDHGetError ();
  431.                      AX (pcrf) = ERROR_I24_NOT_READY;    // DRIVE_NOT_READY
  432.                      FL (pcrf) |= CARRY_FLAG;
  433.                      break;
  434.                  }
  435.                } /* endif */
  436.  
  437.                /* successful return. */
  438.                AX (pcrf) = NO_ERROR;
  439.                FL (pcrf) &= ~CARRY_FLAG;
  440.                break;
  441.  
  442.             case ABSOLUTE_DISK_WRITE:
  443.                 break;
  444.  
  445.             case CDROM_DRIVE_CHECK:
  446.  
  447.                 BX (pcrf) = MSCDEX_SIGNATURE;
  448.                 drive_number = CX (pcrf);
  449.                 if ( drive_number < FirstDriveNumber  ||
  450.                      drive_number >= FirstDriveNumber + NumberOfDrives )
  451.                 {
  452.                     AX (pcrf) = 0;
  453.                 }
  454.                 break;
  455.  
  456.             case GET_MSCDEX_VERSION:
  457.  
  458.                 BX (pcrf) = MSCDEX_VERSION;
  459.                 break;
  460.  
  461.             case GET_CDROM_DRIVE_LETTERS:
  462.  
  463.                 buffer = PFROMVADDR ( ES (pcrf), BX (pcrf) );
  464.                 for ( n = 0; n < NumberOfDrives; ++n )
  465.                 {
  466.                     *buffer = (UCHAR) ( FirstDriveNumber + n );
  467.                     ++buffer;
  468.                 }
  469.                 break;
  470.  
  471.             case VOLUME_DESCRIPTOR_PREFERENCE:
  472.  
  473.                /*
  474.                ** get VDHOpen handle to CD-ROM drive specified in CX
  475.                */
  476.                drive_number = CX (pcrf);
  477.                handle = GetDriveHandle (drive_number);
  478.                if (handle == NULL)
  479.                {
  480.                   AX (pcrf) = ERROR_I24_WRONG_DISK;      // INVALID_DRIVE
  481.                   FL (pcrf) |= CARRY_FLAG;
  482.                   break;
  483.                }
  484.                                          /* set MSCDEX function code         */
  485.                ((PVOLDESCPREF)ParmList)->ulFunction=(ULONG)AL(pcrf);
  486.                                          /* set MSCDEX get/set pref request  */
  487.                ((PVOLDESCPREF)ParmList)->ulPrefReq=(ULONG)BX(pcrf);
  488.                                          /* set MSCDEX get/set pref value    */
  489.                ((PVOLDESCPREF)ParmList)->ulPrefVal=(ULONG)DX(pcrf);
  490.                                          /* set structure length             */
  491.                ParmLengthInOut=sizeof(VOLDESCPREF);
  492.                                          /* set user buffer length           */
  493.                DataLengthInOut=0;
  494.  
  495.                /*
  496.                ** call CD-ROM IFS for GET DIRECTORY ENTRY
  497.                */
  498.                rc = VDHFSCtl((PVOID)buffer,
  499.                              (ULONG)DataLengthInOut,
  500.                              (PVOID)&DataLengthInOut,
  501.                              (PVOID)&ParmList,
  502.                              (ULONG)ParmLengthInOut,
  503.                              (PVOID)&ParmLengthInOut,
  504.                              (ULONG)FSCTL_ARG_MSCDEX,
  505.                              (PSZ)NULL,
  506.                              handle,
  507.                              FSCTL_HANDLE);
  508.  
  509.                if ( rc == VDH_FAILURE )
  510.                {
  511.                    rc = VDHGetError ();
  512.                    AX (pcrf) = (USHORT) rc;
  513.                    FL (pcrf) |= CARRY_FLAG;
  514.                    break;
  515.                }
  516.  
  517.                /*
  518.                ** return volume descriptor preference
  519.                */
  520.                if (BX(pcrf) == GET_VOL_DESC_PREF)
  521.                    DX(pcrf) = (USHORT)((PVOLDESCPREF)ParmList)->ulPrefVal;
  522.  
  523.                FL (pcrf) &= ~CARRY_FLAG;
  524.                break;
  525.  
  526.             case GET_DIRECTORY_ENTRY:
  527.  
  528.                /*
  529.                ** get VDHOpen handle to CD-ROM drive specified in CH
  530.                */
  531.                drive_number = CL (pcrf);
  532.                handle = GetDriveHandle (drive_number);
  533.                if (handle == NULL)
  534.                {
  535.                   AX (pcrf) = ERROR_I24_WRONG_DISK;      // INVALID_DRIVE
  536.                   FL (pcrf) |= CARRY_FLAG;
  537.                   break;
  538.                }
  539.  
  540.                /*
  541.                ** Directory Entry buffer
  542.                ** convert virtual address to 0:32 flat address
  543.                */
  544.                buffer = (PUCHAR)((ULONG)PFROMVADDR(SI(pcrf),DI(pcrf))+
  545.                                                   (ULONG)hvdmCurrent);
  546.  
  547.                if (CH(pcrf) == 0)                  /* set user buffer length */
  548.                   DataLengthInOut=DIR_ENTRY_SPECIFIC_LEN;
  549.                else                                /* set user buffer length */
  550.                   DataLengthInOut=DIR_ENTRY_GENERAL_LEN;
  551.  
  552.                /*
  553.                ** ASCIIZ filename buffer
  554.                ** convert virtual address to 0:32 flat address
  555.                */
  556.                szpathname = PFROMVADDR(ES(pcrf),BX(pcrf));
  557.  
  558.                                                  /* set MSCDEX function code */
  559.                ((PGETDIRENTRY)ParmList)->ulFunction=(ULONG)AL(pcrf);
  560.                                                  /* set MSCDEX copy flags    */
  561.                ((PGETDIRENTRY)ParmList)->ulFlags=(ULONG)CH(pcrf);
  562.  
  563.                i=0;
  564.                ptmp1=(PUCHAR)ParmList;           /* get ptr to variable part */
  565.                ptmp1+=sizeof(GETDIRENTRY);
  566.                do
  567.                {
  568.                  *ptmp1=*szpathname;
  569.                  ptmp1++;
  570.                  szpathname++;
  571.                  i++;
  572.                } while (*(szpathname-1) != NULL); /* enddo */
  573.                                                  /* set structure length     */
  574.                ParmLengthInOut=(ULONG)(i+sizeof(GETDIRENTRY));
  575.  
  576.                /*
  577.                ** call CD-ROM IFS for GET DIRECTORY ENTRY
  578.                */
  579.                rc = VDHFSCtl((PVOID)buffer,
  580.                              (ULONG)DataLengthInOut,
  581.                              (PVOID)&DataLengthInOut,
  582.                              (PVOID)&ParmList,
  583.                              (ULONG)ParmLengthInOut,
  584.                              (PVOID)&ParmLengthInOut,
  585.                              (ULONG)FSCTL_ARG_MSCDEX,
  586.                              (PSZ)NULL,
  587.                              handle,
  588.                              FSCTL_HANDLE);
  589.  
  590.                if ( rc == VDH_FAILURE )
  591.                {
  592.                    rc = VDHGetError ();
  593.                    AX (pcrf) = (USHORT) rc;
  594.                    FL (pcrf) |= CARRY_FLAG;
  595.                    break;
  596.                } else
  597.                    /* High Sierra = 0, ISO-9660 = 1 */
  598.                    AX (pcrf) = (USHORT)((PGETDIRENTRY)ParmList)->ulFlags;
  599.  
  600.                FL (pcrf) &= ~CARRY_FLAG;
  601.                break;
  602.  
  603.             default:
  604.  
  605.                 AX (pcrf) = ERROR_INVALID_2F_FUNCTION;
  606.                 FL (pcrf) |= CARRY_FLAG;
  607.         }
  608.     }
  609.  
  610.     return TRUE;                                  /* claimed the interrupt   */
  611. }
  612.  
  613.  
  614. /****************************************************************************
  615.  *
  616.  * FUNCTION NAME = SendDeviceRequest
  617.  *
  618.  * DESCRIPTION   = SendDeviceRequest to the OS/2 driver
  619.  *
  620.  *       This function converts the supported DOS driver request packets
  621.  *       to VDHDevIOCtl calls and directs them to the OS/2 CD-ROM device
  622.  *       driver.
  623.  *
  624.  *       COMPARISON OF PARAM/DATA AREAS
  625.  *
  626.  *            DOS PARAMS       DOS DATA           OS/2 PARAMS
  627.  *           ------------     ------------      --------------
  628.  *                                                   C
  629.  *                                                   D
  630.  *                                                   0
  631.  *           command code                            1
  632.  *           param byte 1      data byte 1       param byte 1
  633.  *           param byte 2      data byte 1       param byte 2
  634.  *                 .                .                .
  635.  *                 .                .                .
  636.  *                 .                .                .
  637.  *
  638.  *           The parameters generally line up, with some exceptions. Data
  639.  *           overlaps parameters in DOS, not in OS/2.
  640.  *
  641.  *       CONTEXT:
  642.  *           VDM Task-time
  643.  *
  644.  *       PSEUDOCODE:
  645.  *           Verify the drive number.
  646.  *           Get the drive handle.
  647.  *           Map the 2f call to VDHDevIOCtl and call it.
  648.  *           Map the os/2 return code to a dos rc.
  649.  *           Reset media if necessary, otherwise
  650.  *            check for drive playing and update the rc.
  651.  *
  652.  * INPUT         = reqhdr - flat address of dos request packet
  653.  *                 drive_number - of the CD-ROM (0=A, 1=B...)
  654.  *
  655.  * OUTPUT        = void
  656.  *
  657.  * RETURN-NORMAL =
  658.  * RETURN-ERROR  =
  659.  *
  660.  ****************************************************************************/
  661.  
  662. VOID PRIVENTRY SendDeviceRequest ( register
  663.                                    struct
  664.                                    DosRh   *reqhdr,         /* flat address  */
  665.                                    ULONG    drive_number )
  666. {
  667.     register
  668.     PCHAR       control_block;
  669.     register
  670.     ULONG       rc;
  671.     ULONG       saveCD01area;
  672.     ULONG       save_number_of_sectors;
  673.     ULONG       save_volume_size;
  674.     F16PVOID    save_transfer_area;
  675.     HFILE       handle;
  676.     struct
  677.     CategoryCode ioctl;
  678.     PVOID       parm_list;
  679.     PVOID       data_area;
  680.     BOOL        media_check_in_progress;
  681.  
  682.     if ( drive_number < FirstDriveNumber  ||
  683.          drive_number >= FirstDriveNumber + NumberOfDrives )
  684.     {
  685.         reqhdr->status = ERROR + DONE + ERROR_I24_BAD_UNIT;
  686.         return;
  687.     }
  688.  
  689.     handle = GetDriveHandle ( drive_number );
  690.     if ( handle == NULL )
  691.     {
  692.         reqhdr->status = ERROR + DONE + ERROR_I24_NOT_READY;
  693.         return;
  694.     }                                         /* error exit                  */
  695.  
  696.     ParmLengthInOut = PARM_LENGTH_MAX;        /* these are just dummies for  */
  697.     DataLengthInOut = DATA_LENGTH_MAX;        /*  the VDHDevIOCtl call       */
  698.  
  699.     switch ( reqhdr->command )
  700.     {
  701.         case DOS_IOCTL_INPUT:
  702.             control_block = PFROMVADDR ( FP_SEG ((RH(3) reqhdr)->control_block),
  703.                                          FP_OFF ((RH(3) reqhdr)->control_block)
  704.                                        );
  705.             if ( *control_block == RADDR )    /* dos driver address          */
  706.             {
  707.                 rc = NO_ERROR;
  708.                 * ((PULONG) (control_block + 1)) = (ULONG) DosDDHeader;
  709.                 break;
  710.             }                              /* return address of device header*/
  711.  
  712.             ioctl = IoctlInputCodes [*control_block];
  713.  
  714.             if ( ioctl.code == MEDIA_CHANGED_EXCEPTION )  /* not in OS/2     */
  715.             {
  716.                 media_check_in_progress = TRUE;
  717.                 ioctl.code = RETURN_VOLUME_SIZE;    /* generates the error   */
  718.                 save_volume_size = * ( (PULONG) ( control_block + 1 ) );
  719.             }
  720.             else
  721.             {
  722.                 media_check_in_progress = FALSE;
  723.             }
  724.  
  725.             parm_list = control_block - 3;         /* "CD01" then param then */
  726.                                                    /*   data area in DOS     */
  727.             if ( *control_block == LOCHEAD  ||
  728.                  *control_block == SECTSIZE ||
  729.                  *control_block == TNOINFO )
  730.             {
  731.                 data_area = control_block + 2;     /* skip over a param      */
  732.             }
  733.             else
  734.             {
  735.                 data_area = control_block + 1;     /* skip over control code */
  736.             }
  737.  
  738.             saveCD01area = * ( (PULONG) ( control_block - 3 ) );
  739.             * ( (PULONG) ( control_block - 3 ) ) = CD01;
  740.  
  741.             rc = VDHDevIOCtl ( handle,
  742.                                ioctl.category,
  743.                                ioctl.code,
  744.                                parm_list,
  745.                                PARM_LENGTH_MAX,
  746.                                &ParmLengthInOut,
  747.                                data_area,
  748.                                DATA_LENGTH_MAX,
  749.                                &DataLengthInOut );
  750.  
  751.             if ( rc == VDH_FAILURE )
  752.                 rc = VDHGetError ();
  753.             else
  754.                 rc = NO_ERROR;
  755.  
  756.             * ( (PULONG) ( control_block - 3 ) ) = saveCD01area;
  757.  
  758.             if (( *control_block == SECTSIZE ) && ( rc == NO_ERROR )) /*@V113078*/
  759.             {                                                         /*@V113078*/
  760.                if ( * (PCHAR) ( control_block + 1 ) == RAW_MODE )     /*@V113078*/
  761.                {                                                      /*@V113078*/
  762.                   *(PUSHORT) data_area = CDROM_LONG_SECTOR_SIZE;      /*@V113078*/
  763.                }                                                      /*@V113078*/
  764.             }                                                         /*@V113078*/
  765.  
  766.             if ( media_check_in_progress )
  767.             {
  768.                 * ( (PULONG) ( control_block + 1 ) ) = save_volume_size;
  769.                 if ( (rc & 0xFF) == ERROR_I24_UNCERTAIN_MEDIA )
  770.                     * ( (PUCHAR) ( control_block + 1 ) ) = MEDIA_UNCERTAIN;
  771.                 else
  772.                     * ( (PUCHAR) ( control_block + 1 ) ) = MEDIA_NOT_CHANGED;
  773.             }
  774.             break;
  775.  
  776.         case DOS_IOCTL_OUTPUT:
  777.             control_block = PFROMVADDR ( FP_SEG ((RH(3) reqhdr)->control_block),
  778.                                          FP_OFF ((RH(3) reqhdr)->control_block)
  779.                                        );
  780.  
  781.             ioctl = IoctlOutputCodes [*control_block];
  782.             parm_list = control_block - 3;          /* CD01 then param and   */
  783.             data_area = control_block + 1;          /*  data which overlap   */
  784.  
  785.             saveCD01area = * ( (PULONG) ( control_block - 3 ) );
  786.             * ( (PULONG) ( control_block - 3 ) ) = CD01;
  787.  
  788.             rc = VDHDevIOCtl ( handle,
  789.                                ioctl.category,
  790.                                ioctl.code,
  791.                                parm_list,
  792.                                PARM_LENGTH_MAX,
  793.                                &ParmLengthInOut,
  794.                                data_area,
  795.                                DATA_LENGTH_MAX,
  796.                                &DataLengthInOut );
  797.  
  798.             if ( rc == VDH_FAILURE )
  799.                 rc = VDHGetError ();
  800.             else
  801.                 rc = NO_ERROR;
  802.  
  803.             * ( (PULONG) ( control_block - 3 ) ) = saveCD01area;
  804.             break;
  805.  
  806.         case DOS_READ_LONG:                         /* OS/2 read command (4) */
  807.             if ((RH(128) reqhdr)->read_mode == COOKED_MODE )          /*@V113078*/
  808.             {                                                         /*@V113078*/
  809.                if ((RH(128) reqhdr)->address_mode != HSG_ADDRESS )    /*@V113078*/
  810.                {
  811.                    rc = DEVIOCTL_ERROR + ERROR_I24_BAD_COMMAND;
  812.                    break;
  813.                }
  814.                rc = VDHSeek ( handle,
  815.                               (RH(128) reqhdr)->start_sector * CDROM_SECTOR_SIZE,
  816.                               VDHSK_ABSOLUTE );
  817.                if ( rc == VDH_ERROR )
  818.                {
  819.                    rc = VDHGetError ();
  820.                    break;
  821.                }
  822.                rc = VDHRead ( handle,
  823.                               PFROMVADDR (FP_SEG ((RH(128) reqhdr)->transfer_area),
  824.                                           FP_OFF ((RH(128) reqhdr)->transfer_area)
  825.                                          ),
  826.                               (ULONG) (RH(128) reqhdr)->transfer_count *
  827.                                                         CDROM_SECTOR_SIZE
  828.                             );
  829.                if ( rc == VDH_ERROR )
  830.                {
  831.                    rc = VDHGetError ();
  832.                    (RH(128) reqhdr)->transfer_count = 0;
  833.                }
  834.                else
  835.                {
  836.                    rc = NO_ERROR;
  837.                }
  838.             }
  839.             else if ((RH(128) reqhdr)->read_mode == RAW_MODE )          /*@V113078*/
  840.             {                                                           /*VVVVVVVV*/
  841.  
  842.                ioctl.code     = IOCD_READ_LONG;
  843.                ioctl.category = IOC_CDROM;
  844.  
  845.                control_block = PFROMVADDR (FP_SEG ((RH(128) reqhdr)->transfer_area),
  846.                                           FP_OFF ((RH(128) reqhdr)->transfer_area));
  847.  
  848.                parm_list = control_block;              /* CD01 then param and   */
  849.                data_area = control_block;              /*  data which overlap   */
  850.  
  851.                ((PREADLONGPARMS)parm_list)->ID_code = CD01;
  852.  
  853.                if ((RH(128) reqhdr)->address_mode == HSG_ADDRESS )
  854.                {
  855.                   ((PREADLONGPARMS)parm_list)->address_mode = HSG_ADDRESS;
  856.                }
  857.                else if ((RH(128) reqhdr)->address_mode == REDBOOK_ADDRESS )
  858.                {
  859.                   ((PREADLONGPARMS)parm_list)->address_mode = REDBOOK_ADDRESS;
  860.                }
  861.                else /* invalid addressing mode */
  862.                {
  863.                   rc = DEVIOCTL_ERROR + ERROR_I24_BAD_COMMAND;
  864.                   break;
  865.                }
  866.  
  867.                ((PREADLONGPARMS)parm_list)->transfer_count         =
  868.                                     (ULONG) (RH(128) reqhdr)->transfer_count;
  869.                ((PREADLONGPARMS)parm_list)->start_sector           =
  870.                                     (RH(128) reqhdr)->start_sector;
  871.                ((PREADLONGPARMS)parm_list)->reserved               = 0;
  872.                ((PREADLONGPARMS)parm_list)->interleave_size        = 0;
  873.                ((PREADLONGPARMS)parm_list)->interleave_skip_factor = 0;
  874.  
  875.                rc = VDHDevIOCtl ( handle,
  876.                                   ioctl.category,
  877.                                   ioctl.code,
  878.                                   parm_list,
  879.                                   PARM_LENGTH_MAX,
  880.                                   &ParmLengthInOut,
  881.                                   data_area,
  882.                                   DATA_LENGTH_MAX,
  883.                                   &DataLengthInOut );
  884.  
  885.                if ( rc == VDH_FAILURE )
  886.                    rc = VDHGetError ();
  887.                else
  888.                    rc = NO_ERROR;
  889.  
  890.             }
  891.             else /* invalid read mode */
  892.             {
  893.                 rc = DEVIOCTL_ERROR + ERROR_I24_BAD_COMMAND;       /*AAAAAAAA*/
  894.             }                                                      /*@V113078*/
  895.             break;
  896.  
  897.         case DOS_READ_LONG_PREFETCH:                /* fall thru             */
  898.         case DOS_SEEK:
  899.             control_block = (PCHAR) reqhdr;
  900.             parm_list = control_block + 9;          /* CD01 then params      */
  901.             data_area = 0;
  902.  
  903.             save_transfer_area = (RH(131) reqhdr)->transfer_area;
  904.             * ( (PULONG) &(RH(131) reqhdr)->transfer_area ) =
  905.                                             (RH(131) reqhdr)->start_sector;
  906.  
  907.             saveCD01area = * ( (PULONG) ( control_block + 9 ) );
  908.             * ( (PULONG) ( control_block + 9 ) ) = CD01;
  909.  
  910.             rc = VDHDevIOCtl ( handle,
  911.                                0x0080,
  912.                                0x0050,
  913.                                parm_list,
  914.                                PARM_LENGTH_MAX,
  915.                                &ParmLengthInOut,
  916.                                data_area,
  917.                                DATA_LENGTH_MAX,
  918.                                &DataLengthInOut );
  919.  
  920.             if ( rc == VDH_FAILURE )
  921.                 rc = VDHGetError ();
  922.             else
  923.                 rc = NO_ERROR;
  924.  
  925.             * ( (PULONG) ( control_block + 9 ) ) = saveCD01area;
  926.             (RH(131) reqhdr)->transfer_area = save_transfer_area;
  927.             break;
  928.  
  929.         case DOS_PLAY_AUDIO:
  930.             control_block = (PCHAR) reqhdr;
  931.             parm_list = control_block + 9;          /* CD01 then params      */
  932.             data_area = 0;
  933.  
  934.             save_number_of_sectors = (RH(132) reqhdr)->number_of_sectors;
  935.             * ( (PULONG) &(RH(132) reqhdr)->number_of_sectors ) =
  936.                      AddSectors ( (RH(132) reqhdr)->start_sector,
  937.                                         (RH(132) reqhdr)->number_of_sectors,
  938.                                         (RH(132) reqhdr)->address_mode
  939.                                       );
  940.             saveCD01area = * ( (PULONG) ( control_block + 9 ) );
  941.             * ( (PULONG) ( control_block + 9 ) ) = CD01;
  942.  
  943.             rc = VDHDevIOCtl ( handle,
  944.                                0x0081,
  945.                                0x0050,
  946.                                parm_list,
  947.                                PARM_LENGTH_MAX,
  948.                                &ParmLengthInOut,
  949.                                data_area,
  950.                                DATA_LENGTH_MAX,
  951.                                &DataLengthInOut );
  952.  
  953.             if ( rc == VDH_FAILURE )
  954.                 rc = VDHGetError ();
  955.             else
  956.                 rc = NO_ERROR;
  957.  
  958.             * ( (PULONG) ( control_block + 9 ) ) = saveCD01area;
  959.             * ( (PULONG) &(RH(132) reqhdr)->number_of_sectors ) =
  960.                                                     save_number_of_sectors;
  961.             break;
  962.  
  963.         case DOS_STOP_AUDIO:
  964.             control_block = (PCHAR) reqhdr;
  965.             parm_list = control_block + 9;          /* CD01 then params      */
  966.             data_area = 0;
  967.  
  968.             saveCD01area = * ( (PULONG) ( control_block + 9 ) );
  969.             * ( (PULONG) ( control_block + 9 ) ) = CD01;
  970.  
  971.             rc = VDHDevIOCtl ( handle,
  972.                                0x0081,
  973.                                0x0051,
  974.                                parm_list,
  975.                                PARM_LENGTH_MAX,
  976.                                &ParmLengthInOut,
  977.                                data_area,
  978.                                DATA_LENGTH_MAX,
  979.                                &DataLengthInOut );
  980.  
  981.             if ( rc == VDH_FAILURE )
  982.                 rc = VDHGetError ();
  983.             else
  984.                 rc = NO_ERROR;
  985.  
  986.             * ( (PULONG) ( control_block + 9 ) ) = saveCD01area;
  987.             break;
  988.  
  989.         case DOS_RESUME_AUDIO:
  990.             control_block = (PCHAR) reqhdr;
  991.             parm_list = control_block + 9;          /* CD01 then params      */
  992.             data_area = 0;
  993.  
  994.             saveCD01area = * ( (PULONG) ( control_block + 9 ) );
  995.             * ( (PULONG) ( control_block + 9 ) ) = CD01;
  996.  
  997.             rc = VDHDevIOCtl ( handle,
  998.                                0x0081,
  999.                                0x0052,
  1000.                                parm_list,
  1001.                                PARM_LENGTH_MAX,
  1002.                                &ParmLengthInOut,
  1003.                                data_area,
  1004.                                DATA_LENGTH_MAX,
  1005.                                &DataLengthInOut );
  1006.  
  1007.             if ( rc == VDH_FAILURE )
  1008.                 rc = VDHGetError ();
  1009.             else
  1010.                 rc = NO_ERROR;
  1011.  
  1012.             * ( (PULONG) ( control_block + 9 ) ) = saveCD01area;
  1013.             break;
  1014.         default:
  1015.             switch ( reqhdr->command )
  1016.             {
  1017.                 case DOS_DEVICE_OPEN:
  1018.                     ResetMedia ( drive_number );
  1019.                 case DOS_INPUT_FLUSH:
  1020.                 case DOS_DEVICE_CLOSE:
  1021.                     rc = NO_ERROR;
  1022.                     break;
  1023.                 default:
  1024.                     rc = DEVIOCTL_ERROR + ERROR_I24_BAD_COMMAND;
  1025.             }
  1026.     }
  1027.  
  1028.     reqhdr->status = MapOS2toDosCode ( rc );
  1029.     if ( (reqhdr->status & 0xFF) == ERROR_I24_WRONG_DISK )   //INV_DISK_CHANGE
  1030.         ResetMedia ( drive_number );
  1031.     else
  1032.         reqhdr->status |= GetPlayStatus ( handle );
  1033.  
  1034.     return;
  1035. }
  1036.  
  1037.  
  1038. /****************************************************************************
  1039.  *
  1040.  * FUNCTION NAME = ResetMedia
  1041.  *
  1042.  * DESCRIPTION   = This function resets the uncertain media condition for the
  1043.  *                 device.  It is necessary because we are bypassing the file
  1044.  *                 system with user-defined generic ioctls.
  1045.  *
  1046.  *                 CONTEXT:
  1047.  *                    VDM Task-time
  1048.  *
  1049.  *                 PSEUDOCODE:
  1050.  *                    Close and open the drive handle to reset media.
  1051.  *
  1052.  * INPUT         = drive_number - of the CD-ROM (0=A, 1=B...)
  1053.  *
  1054.  * OUTPUT        = void
  1055.  *
  1056.  * RETURN-NORMAL =
  1057.  * RETURN-ERROR  =
  1058.  *
  1059.  ****************************************************************************/
  1060.  
  1061. VOID PRIVENTRY ResetMedia (ULONG drive_number)
  1062. {
  1063.     register
  1064.     ULONG   rc;
  1065.  
  1066.     VDHClose ( DriveHandle [ drive_number ] );
  1067.  
  1068.     rc = VDHOpen ( GET_DRIVE_STRING ( drive_number ),
  1069.                    &FileHandle,
  1070.                    &ActionTaken,
  1071.                    FILESIZE,
  1072.                    FILEATTRIBUTE,
  1073.                    OPENFLAG,
  1074.                    OPENMODE,
  1075.                    EABUF );
  1076.  
  1077.     if ( rc == VDH_FAILURE )
  1078.     {
  1079.         rc = VDHGetError ();                            /* for debugging     */
  1080.         FileHandle = NULL;
  1081.     }
  1082.  
  1083.     DriveHandle [ drive_number ] = FileHandle;          /* NULL if error     */
  1084.  
  1085. }
  1086.  
  1087.  
  1088. /****************************************************************************
  1089.  *
  1090.  * FUNCTION NAME = GetDriveHandle
  1091.  *
  1092.  * DESCRIPTION   = This function maps the drive number to a possibly already
  1093.  *                 opened drive handle.  If the handle is not opened, one is
  1094.  *                 opened and returned.  If the handle is opened, a media check
  1095.  *                 is performed to determine if the handle is still valid.  If
  1096.  *                 the handle is invalid, the handle is closed and a new handle
  1097.  *                 is opened, stored, and returned. Performing a media check is
  1098.  *                 faster than closing and openning the file handle especially
  1099.  *                 for each MSCDEX api.  The open is required to (re)mount the
  1100.  *                 removable media volume.  We only want to take the
  1101.  *                 performance penalty of open/close when the media has truly
  1102.  *                 changed.
  1103.  *
  1104.  *                 CONTEXT:
  1105.  *                    VDM Task-time
  1106.  *
  1107.  *                 PSEUDOCODE:
  1108.  *                    If the drive is not open,
  1109.  *                      open drive and save handle
  1110.  *                    else the drive is open
  1111.  *                      perform media check
  1112.  *                      if media changed
  1113.  *                         close handle, open new handle and save it
  1114.  *                      endif
  1115.  *                    endif
  1116.  *                    return handle
  1117.  *
  1118.  * INPUT         = drive_number - of the CD-ROM (0=A, 1=B...)
  1119.  *
  1120.  * OUTPUT        = DASD-open file handle  (NULL == failure)
  1121.  *
  1122.  * RETURN-NORMAL =
  1123.  * RETURN-ERROR  =
  1124.  *
  1125.  ****************************************************************************/
  1126.  
  1127. HFILE PRIVENTRY GetDriveHandle (ULONG drive_number)
  1128. {
  1129.     register
  1130.     ULONG   rc;
  1131.  
  1132.     FileHandle = DriveHandle [ drive_number ];
  1133.  
  1134.     if ( FileHandle == NULL )
  1135.     {
  1136.         rc = VDHOpen ( GET_DRIVE_STRING ( drive_number ),
  1137.                        &FileHandle,
  1138.                        &ActionTaken,
  1139.                        FILESIZE,
  1140.                        FILEATTRIBUTE,
  1141.                        OPENFLAG,
  1142.                        OPENMODE,
  1143.                        EABUF );
  1144.  
  1145.         if ( rc == VDH_FAILURE )
  1146.         {
  1147.             rc = VDHGetError ();                          /* for debugging   */
  1148.             FileHandle = NULL;
  1149.         }
  1150.         DriveHandle [ drive_number ] = FileHandle;        /* NULL if error   */
  1151.     }
  1152.     else
  1153.     {
  1154.         DataArea[0] = 0x0000;
  1155.         DataLengthInOut = sizeof(USHORT);
  1156.         ParmLengthInOut = 0x0000;
  1157.  
  1158.         /* call CD-ROM IFS to see if media has changed */
  1159.         rc = VDHFSCtl((PVOID)&DataArea,
  1160.                       (ULONG)DataLengthInOut,
  1161.                       (PVOID)&DataLengthInOut,
  1162.                       (PVOID)&ParmList,
  1163.                       (ULONG)ParmLengthInOut,
  1164.                       (PVOID)&ParmLengthInOut,
  1165.                       (ULONG)FSCTL_ARG_MEDIACHG,
  1166.                       (PSZ)NULL,
  1167.                       FileHandle,
  1168.                       FSCTL_HANDLE);
  1169.  
  1170.         if ( rc == VDH_FAILURE ) {
  1171.             rc = VDHGetError ();
  1172.         }
  1173.  
  1174.         if (DataArea[0] == ERROR_VOLUME_CHANGED)
  1175.         {
  1176.             ResetMedia ( drive_number );
  1177.             FileHandle = DriveHandle [ drive_number ];
  1178.         }
  1179.     }
  1180.     return FileHandle;
  1181. }
  1182.  
  1183.  
  1184. /****************************************************************************
  1185.  *
  1186.  * FUNCTION NAME = MapOS2toDosCode
  1187.  *
  1188.  * DESCRIPTION   =
  1189.  *      This function converts the OS/2 return code to a DOS device
  1190.  *      driver status code.
  1191.  *
  1192.  *      CONTEXT:
  1193.  *         VDM Task-time
  1194.  *
  1195.  *      TYPES OF OS/2 CODES:
  1196.  *         0000  = no error
  1197.  *         FFxx  = device driver error code
  1198.  *         other = system error code
  1199.  *
  1200.  *      PSEUDOCODE:
  1201.  *         Map the code according to its type.
  1202.  *
  1203.  * INPUT         = OS/2 rc
  1204.  *
  1205.  * OUTPUT        = DOS status code
  1206.  *
  1207.  * RETURN-NORMAL =
  1208.  *
  1209.  * RETURN-ERROR  =
  1210.  *
  1211.  ****************************************************************************/
  1212.  
  1213. USHORT PRIVENTRY MapOS2toDosCode (register ULONG rc)
  1214. {
  1215.     register
  1216.     ULONG   dos_rc;
  1217.  
  1218.     if (rc == 0)
  1219.     {
  1220.        dos_rc = DONE;
  1221.     }
  1222.     else
  1223.        if (((USHORT)rc & 0xFF00) == DEVIOCTL_ERROR)
  1224.        {
  1225.           if (((USHORT)rc & 0xFF) == ERROR_I24_UNCERTAIN_MEDIA)
  1226.           {
  1227.              dos_rc = ERROR + DONE + ERROR_I24_WRONG_DISK;  //INV_DISK_CHANGE
  1228.           }
  1229.           else
  1230.           {
  1231.              dos_rc = ERROR + DONE + ((USHORT) rc & 0xFF);
  1232.           }
  1233.        }
  1234.        else
  1235.        {                                     /* DosCall system error code    */
  1236.           if (rc >= ERROR_WRITE_PROTECT && rc <= ERROR_WRONG_DISK)
  1237.           {
  1238.              dos_rc = ERROR + DONE + (USHORT)rc - ERROR_WRITE_PROTECT;
  1239.           }
  1240.           else
  1241.           {
  1242.              dos_rc = ERROR + DONE + ERROR_I24_GEN_FAILURE;
  1243.           }
  1244.        }
  1245.     if (dos_rc > ERROR + DONE + ERROR_I24_WRONG_DISK)     //INV_DISK_CHANGE
  1246.     {
  1247.        dos_rc = ERROR + DONE + ERROR_I24_GEN_FAILURE;
  1248.     }
  1249.     return (USHORT)dos_rc;
  1250.  
  1251. }
  1252.  
  1253.  
  1254. /****************************************************************************
  1255.  *
  1256.  * FUNCTION NAME = GetPlayStatus
  1257.  *
  1258.  * DESCRIPTION   = This function determines if the drive is currently playing
  1259.  *                 audio.
  1260.  *
  1261.  *                 CONTEXT:
  1262.  *                    VDM Task-time
  1263.  *
  1264.  *                 PSEUDOCODE:
  1265.  *                    Make a device-status call to the OS/2 CD-ROM driver.
  1266.  *                    If playing, set the busy bit.
  1267.  *
  1268.  * INPUT         = DASD-open file handle
  1269.  *
  1270.  * OUTPUT        = 0200h == playing
  1271.  *                 0000h == not playing
  1272.  *
  1273.  * RETURN-NORMAL =
  1274.  * RETURN-ERROR  =
  1275.  *
  1276.  ****************************************************************************/
  1277.  
  1278. USHORT PRIVENTRY GetPlayStatus (HFILE handle)
  1279. {
  1280.     register
  1281.     ULONG   rc;
  1282.  
  1283.     ParmLengthInOut = PARM_LENGTH_MAX;      /* these are just dummies for   */
  1284.     DataLengthInOut = DATA_LENGTH_MAX;      /*  the VDHDevIOCtl call        */
  1285.  
  1286.     *ParmList = CD01;
  1287.  
  1288.     rc = VDHDevIOCtl ( handle,
  1289.                        0x0080,
  1290.                        0x0060,              /* device status                */
  1291.                        ParmList,
  1292.                        PARM_LENGTH_MAX,
  1293.                        &ParmLengthInOut,
  1294.                        DataArea,
  1295.                        DATA_LENGTH_MAX,
  1296.                        &DataLengthInOut );
  1297.  
  1298.     if ( rc == VDH_FAILURE )
  1299.         rc = VDHGetError ();
  1300.     else
  1301.         rc = NO_ERROR;
  1302.  
  1303.     if ( rc == NO_ERROR  &&  (*DataArea & DRIVE_PLAYING) )
  1304.         return BUSY;                        /* busy bit == playing in DOS   */
  1305.     else
  1306.         return 0;
  1307. }
  1308.  
  1309.  
  1310. /****************************************************************************
  1311.  *
  1312.  * FUNCTION NAME = HsgToRedbook
  1313.  *
  1314.  * DESCRIPTION   = This function converts an HSG number-of-sectors to a Redbook
  1315.  *                 (min:sec:frames) number-of-sectors.
  1316.  *
  1317.  *                 CONTEXT:
  1318.  *                    VDM Task-time
  1319.  *
  1320.  *                 PSEUDOCODE:
  1321.  *                    Convert long relative sector number to
  1322.  *                    long 0:min:sec:frames.
  1323.  *                      75 frames per second
  1324.  *                      60 seconds per minute
  1325.  *                      1 frame == 1 HSG sector
  1326.  *
  1327.  * INPUT         = HSG number_of_sectors
  1328.  *
  1329.  * OUTPUT        = Redbook number_of_sectors
  1330.  *
  1331.  * RETURN-NORMAL =
  1332.  * RETURN-ERROR  =
  1333.  *
  1334.  ****************************************************************************/
  1335.  
  1336. ULONG PRIVENTRY HsgToRedbook (register ULONG hsg_value)
  1337. {
  1338.     UCHAR   minutes;
  1339.     UCHAR   seconds;
  1340.     UCHAR   frames;
  1341.     register
  1342.     ULONG   redbook;
  1343.  
  1344.     redbook = 0;
  1345.  
  1346.     redbook |= ( (hsg_value / (60 * 75)) << 16 );       /* minutes           */
  1347.     hsg_value %= (60 * 75);                             /* remaining frames  */
  1348.     redbook |= ( (hsg_value / 75) << 8 );               /* seconds           */
  1349.     redbook |= ( hsg_value % 75 );                      /* frames            */
  1350.  
  1351.     return ( redbook );
  1352. }
  1353.  
  1354.  
  1355. /****************************************************************************
  1356.  *
  1357.  * FUNCTION NAME = AddSectors
  1358.  *
  1359.  * DESCRIPTION   = This function adds two sector values, returning the sum. It
  1360.  *                 is necessary because the OS/2 call requires the ending sector
  1361.  *                 number, but the DOS parameter is number-of-sectors.
  1362.  *
  1363.  *                 CONTEXT:
  1364.  *                    VDM Task-time
  1365.  *
  1366.  *                 PSEUDOCODE:
  1367.  *                    If HSG (normal numbers), just add them.
  1368.  *                    If RedBook (minutes, seconds, frames), convert the HSG
  1369.  *                      value to redbook and then add each field separately,
  1370.  *                      with carry.
  1371.  *
  1372.  * INPUT         = start_sector
  1373.  *                 number_of_sectors
  1374.  *                 address_mode - HSG or RedBook
  1375.  *
  1376.  * OUTPUT        = sum of the sectors
  1377.  *                 0 = invalid address mode
  1378.  *
  1379.  * RETURN-NORMAL =
  1380.  * RETURN-ERROR  =
  1381.  *
  1382.  ****************************************************************************/
  1383.  
  1384. ULONG PRIVENTRY AddSectors (register ULONG start_sector,
  1385.                             register ULONG number_of_sectors,
  1386.                                      ULONG address_mode)
  1387. {
  1388.     register
  1389.     ULONG   value;
  1390.     UCHAR   carry;
  1391.     UCHAR   byte;
  1392.  
  1393.     switch ( address_mode )
  1394.     {
  1395.         case HSG_ADDRESS:
  1396.             value = start_sector + number_of_sectors;
  1397.             break;
  1398.  
  1399.         case REDBOOK_ADDRESS:
  1400.             number_of_sectors = HsgToRedbook ( number_of_sectors );
  1401.             value = 0;
  1402.             byte = FRAMES ( start_sector ) + FRAMES ( number_of_sectors );
  1403.             if ( byte > 74 )
  1404.             {
  1405.                 byte -= 75;
  1406.                 carry = 1;
  1407.             }
  1408.             else
  1409.             {
  1410.                 carry = 0;
  1411.             }
  1412.             value |= byte;
  1413.             byte = SECONDS ( start_sector ) + SECONDS ( number_of_sectors ) +
  1414.                    carry;
  1415.             if ( byte > 59 )
  1416.             {
  1417.                 byte -= 60;
  1418.                 carry = 1;
  1419.             }
  1420.             else
  1421.             {
  1422.                 carry = 0;
  1423.             }
  1424.             value |= byte << 8;
  1425.             byte = MINUTES ( start_sector ) + MINUTES ( number_of_sectors ) +
  1426.                    carry;
  1427.             value |= byte << 16;
  1428.             break;
  1429.  
  1430.         default:
  1431.             value = 0;
  1432.     }
  1433.  
  1434.     return value;
  1435. }
  1436.  
  1437.  
  1438. #pragma END_SWAP_CODE
  1439.