home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mmpm21tk.zip / TK / MMOTTK / MMOTPROC.C < prev    next >
C/C++ Source or Header  |  1993-02-09  |  87KB  |  1,713 lines

  1. /********************** START OF SPECIFICATIONS *************************/
  2. /*                                                                      */
  3. /* SOURCE FILE NAME: MMOTPROC.C                                         */
  4. /*                                                                      */
  5. /* DESCRIPTIVE NAME: Multi-Media I/O Procedure for M-Motion Video       */
  6. /*                                                                      */
  7. /* COPYRIGHT:                                                           */
  8. /*              Copyright (c) IBM Corporation  1990, 1993               */
  9. /*                        All Rights Reserved                           */
  10. /*                                                                      */
  11. /* STATUS:   MMPM/2 Release 1.10                                        */
  12. /*                                                                      */
  13. /* ABSTRACT: This file contains the MMIO                                */
  14. /*           IOProc for M-Motion Still Video files.                     */
  15. /*                                                                      */
  16. /*           This IOProc is intended to be a sample for how IOprocs     */
  17. /*           can be written, and is most applicable to Image data.      */
  18. /*           Note that there are many areas that are specific to the    */
  19. /*           M-Motion Still Video Image file format.  These sections    */
  20. /*           and structures should be changed as necessary for use      */
  21. /*           with other image file formats.                             */
  22. /*                                                                      */
  23. /*           Note also that this image IOProc uses large buffering      */
  24. /*           schemes, due to the ordering of image data (top-down)      */
  25. /*           in the file, whereas the MMIO function and messages rely   */
  26. /*           on this data being made available in the normal OS/2 PM    */
  27. /*           bottom-up form.  This forces the IOproc to pre-read,       */
  28. /*           buffer and flip image data before it can supply the data   */
  29. /*           to the application.  It must perform the reverse order     */
  30. /*           when writing (get the data, buffer it, flip and write to   */
  31. /*           to disk.                                                   */
  32. /*                                                                      */
  33. /*********************** END OF SPECIFICATIONS **************************/
  34.  
  35. /************************************************************************/
  36. /* Put all #defines here                                                */
  37. /************************************************************************/
  38.  
  39. #define INCL_32                         /* force 32 bit compile */
  40. #define INCL_GPIBITMAPS
  41. #define INCL_DOSFILEMGR
  42. #define INCL_WIN
  43. #define INCL_GPI
  44. #define INCL_PM                         
  45.  
  46. #define MEMCHECK
  47.  
  48. /************************************************************************/
  49. /* Put all #includes here                                               */
  50. /************************************************************************/
  51.  
  52. #include <os2.h>
  53. #include <stdio.h>
  54. #include <string.h>
  55. #include <stdlib.h>
  56. #include <os2medef.h>
  57. #include <mmioos2.h>
  58. #include "mmotproc.h"
  59.  
  60. /************************************************************************/
  61. /* MMOT IOProc                                                          */
  62. /*                                                                      */
  63. /* ARGUMENTS:                                                           */
  64. /*                                                                      */
  65. /*     PSZ pmmioStr - pointer to MMIOINFO block                         */
  66. /*     USHORT usMsg - MMIO message being sent                           */
  67. /*     LONG lParam1 - filename or other parameter depending on message  */
  68. /*     LONG lParam2 - used with some messages as values                 */
  69. /*                                                                      */
  70. /*                                                                      */
  71. /*  RETURN:                                                             */
  72. /*                                                                      */
  73. /*      MMIOM_OPEN                                                      */
  74. /*          Success           - MMIO_SUCCESS     (0)                    */
  75. /*          Failure           - MMIO_ERROR      (-1)                    */
  76. /*                                                                      */
  77. /*      MMIOM_READ                                                      */
  78. /*          Success           - Returns the number of bytes actually    */
  79. /*                              read.  Return 0L if no more bytes can   */
  80. /*                              be read.                                */
  81. /*          Failure           - MMIO_ERROR      (-1)                    */
  82. /*                                                                      */
  83. /*      MMIOM_WRITE                                                     */
  84. /*          Success           - Returns the number of bytes actually    */
  85. /*                              written.                                */
  86. /*          Failure           - MMIO_ERROR      (-1)                    */
  87. /*                                                                      */
  88. /*      MMIOM_SEEK                                                      */
  89. /*          Success           - Returns the new file position           */
  90. /*          Failure           - MMIO_ERROR      (-1)                    */
  91. /*                                                                      */
  92. /*      MMIOM_CLOSE                                                     */
  93. /*          Success           - MMIO_SUCCESS     (0)                    */
  94. /*          Failure           - MMIO_ERROR      (-1)                    */
  95. /*          Other             - MMIO_WARNING, file was closed but the   */
  96. /*                              IOProc expected additional data         */
  97. /*                                                                      */
  98. /*      MMIOM_GETFORMATNAME                                             */
  99. /*          Success           - Returns the number of bytes read into   */
  100. /*                              the buffer (size of format name)        */
  101. /*          Failure           - Return 0                                */
  102. /*                                                                      */
  103. /*      MMIOM_GETFORMATINFO                                             */
  104. /*          Success           - MMIO_SUCCESS     (0)                    */
  105. /*          Failure           - MMIO_ERROR      (-1)                    */
  106. /*                                                                      */
  107. /*      MMIOM_QUERYHEADERLENGTH                                         */
  108. /*          Success           - Returns the size of the header in bytes */
  109. /*          Failure           - Return 0                                */
  110. /*                                                                      */
  111. /*      MMIOM_IDENTIFYFILE                                              */
  112. /*          Success           - MMIO_SUCCESS     (0)                    */
  113. /*          Failure           - MMIO_ERROR      (-1)                    */
  114. /*                                                                      */
  115. /*      MMIOM_GETHEADER                                                 */
  116. /*          Success           - Returns number of bytes copied into     */
  117. /*                              the header structure.                   */
  118. /*          Failure           - Return 0                                */
  119. /*          Other             - If length passed in was not large       */
  120. /*                              enough to hold header then,             */
  121. /*                              MMIOERR_INVALID_BUFFER_LENGTH is set    */
  122. /*                              in ulErrorRet.                          */
  123. /*                            - If header is bad,                       */
  124. /*                              MMIOERR_INVALID_STRUCTURE is set in     */
  125. /*                              ulErrorRet                              */
  126. /*                                                                      */
  127. /*      MMIOM_SETHEADER                                                 */
  128. /*          Success           - Returns number of bytes written         */
  129. /*          Failure           - Return 0                                */
  130. /*          Other             - If header is bad,                       */
  131. /*                              MMIOERR_INVALID_STRUCTURE is set in     */
  132. /*                              ulErrorRet                              */
  133. /*                                                                      */
  134. /*  DESCRIPTION:                                                        */
  135. /*                                                                      */
  136. /*      This routine will translate IBM M-Motion YUV Video data into    */
  137. /*      OS/2 2.0 memory bitmap data and back again.  The IOProc is part */
  138. /*      of OS/2 MultiMedia Extentions File Format Conversion Utility.   */
  139. /*                                                                      */
  140. /*  GLOBAL VARS REFERENCED:                                             */
  141. /*                                                                      */
  142. /*      None                                                            */
  143. /*                                                                      */
  144. /*  GLOBAL VARS MODIFIED:                                               */
  145. /*                                                                      */
  146. /*      None                                                            */
  147. /*                                                                      */
  148. /*  NOTES:                                                              */
  149. /*                                                                      */
  150. /*      None                                                            */
  151. /*                                                                      */
  152. /*  SIDE EFFECTS:                                                       */
  153. /*                                                                      */
  154. /*      None                                                            */
  155. /*                                                                      */
  156. /************************************************************************/
  157.  
  158. LONG EXPENTRY IOProc_Entry (PVOID  pmmioStr,
  159.                              USHORT usMsg,
  160.                              LONG   lParam1,
  161.                              LONG   lParam2)
  162.  
  163.     {
  164.     PMMIOINFO   pmmioinfo;                      /* MMIOINFO block */
  165.  
  166.     pmmioinfo = (PMMIOINFO) pmmioStr;
  167.  
  168.     switch (usMsg)
  169.         {
  170.         /*#############################################################*
  171.          * When Closing the file, perform the following:
  172.          * 1) Setup Variables
  173.          * 2) Process the Image buffer
  174.          * 3) Compress the Image to appropriate format
  175.          *#############################################################*/
  176.         case MMIOM_CLOSE:
  177.             {
  178.             /************************************************************
  179.              * Declare local variables.
  180.              ************************************************************/
  181.             PMMFILESTATUS   pVidInfo;         /* MMotionIOProc instance data */
  182.  
  183.             ULONG           ulHeight;         /* Image height                */
  184.             USHORT          usBitCount;
  185.             /* Image width, including overflow in 1bpp & 4bpp                */
  186.             ULONG           ulImgPelWidth;
  187.             PBYTE           lpYUVLine;        /* One line of packed YUV      */
  188.             LONG            lYUVBytesPerLine;
  189.  
  190.             ULONG           ulMaxPelWidth;    /* # pels on 4-pel boundaries  */
  191.             /* # pels on a YUV line in the output file                       */
  192.             ULONG           ulYUVPelWidth;
  193.             ULONG           ulRGBMaxBytesPerLine; /* #bytes on 4-pel bounds  */
  194.             PBYTE           lpRGBLine;        /* One line of 24bit RGB       */
  195.  
  196.             PBYTE           lpImgBufPtr;      /* Current loc in RGB image buf*/
  197.             LONG            lRGBBytesPerLine; /* #bytes on a line in image   */
  198.             ULONG           ulRowCount;       /* loop counter                */
  199.             LONG            lBytesWritten;    /* #bytes output on a write    */
  200.             LONG            lRetCode;
  201.             USHORT          rc;
  202.  
  203.             /***********************************************************
  204.              * Check for valid MMIOINFO block.
  205.              ***********************************************************/
  206.             if (!pmmioinfo)
  207.                 return (MMIO_ERROR);
  208.  
  209.             /***********************************************************
  210.              * Set up our working file status variable.
  211.              ***********************************************************/
  212.             pVidInfo = (PMMFILESTATUS)pmmioinfo->pExtraInfoStruct;
  213.  
  214.             /***********************************************************
  215.              * Assume success for the moment....
  216.              ***********************************************************/
  217.             lRetCode = MMIO_SUCCESS;
  218.  
  219.             /************************************************************
  220.              * see if we are in Write mode and have a buffer to write out.
  221.              *    We have no image buffer in UNTRANSLATED mode.
  222.              ************************************************************/
  223.             if ((pmmioinfo->ulFlags & MMIO_WRITE) && (pVidInfo->lpImgBuf))
  224.                 {
  225.                 /*******************************************************
  226.                  * The buffer should be in palettized or 24-bit RGB
  227.                  * We must convert it to YUV to be written to the file.
  228.                  *******************************************************
  229.                  * The buffer should be complete.  If not, then we
  230.                  * should still close, but can flag an error to the
  231.                  * user that the data may be corrupted.  The only way
  232.                  * we can estimate if this is true is to check the final
  233.                  * position.  If not at the end...
  234.                  *******************************************************/
  235.                 if (pVidInfo->lImgBytePos !=
  236.                                           (LONG)pVidInfo->ulImgTotalBytes)
  237.                     {
  238.                     lRetCode = MMIO_WARNING;
  239.                     }
  240.  
  241.                 /*******************************************************
  242.                  * Set up width and height of image in the buffer.
  243.                  *******************************************************/
  244.                 ulHeight = pVidInfo->mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cy;
  245.                 usBitCount =
  246.                     pVidInfo->mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount;
  247.  
  248.                 /*******************************************************
  249.                  * Get the line width in YUV pels and packed bytes.
  250.                  *******************************************************/
  251.                 ulYUVPelWidth = pVidInfo->mmotHeader.mmXlen;
  252.                 lYUVBytesPerLine = (LONG)(ulYUVPelWidth * 3) >> 1;
  253.  
  254.  
  255.                 /*******************************************************
  256.                  * This changes from OS/2 PM bottom-up bitmap form
  257.                  *    to M-Motion's top-down form.  Flip all pad, boundary
  258.                  *    bytes as well
  259.                  *******************************************************/
  260.                 ImgBufferFlip ((PBYTE)pVidInfo->lpImgBuf,
  261.                                         pVidInfo->ulImgPaddedBytesPerLine,
  262.                                         ulHeight);
  263.  
  264.                 /*******************************************************
  265.                  * Determine number of POSSIBLE pels on a line, tho some
  266.                  *   may be overflow in 1bpp and 4bpp modes.
  267.                  *
  268.                  * From that, we can calc the number of RGB pels we will
  269.                  *   create to represent this line.
  270.                  *******************************************************/
  271.                 ulImgPelWidth = (pVidInfo->ulImgPelBytesPerLine << 3) /
  272.                                              usBitCount;
  273.                 lRGBBytesPerLine = ulImgPelWidth * 3;
  274.  
  275.                 /*******************************************************
  276.                  * Ensure the width is on a 4-pel boundary, necessary for
  277.                  *     M-Motion.  We will buffer with black
  278.                  *    *** THIS IS ONLY NECESSARY FOR M-MOTION IMAGES
  279.                  *******************************************************/
  280.                 if (ulImgPelWidth % 4)
  281.                     ulMaxPelWidth = (((ulImgPelWidth >> 2) + 1) << 2);
  282.                 else
  283.                     ulMaxPelWidth = ulImgPelWidth;
  284.  
  285.                 /* #RGB bytes/line = #pels * 3 bytes/pel */
  286.                 ulRGBMaxBytesPerLine = ulMaxPelWidth * 3;
  287.  
  288.  
  289.                 /*******************************************************
  290.                  * Create a buffer for one line of RGB data, accounting for
  291.                  *   the 4-pel boundary required.  Extra bytes won't be used.
  292.                  *******************************************************/
  293.                 if (DosAllocMem ((PPVOID) &lpRGBLine,
  294.                                  ulRGBMaxBytesPerLine,
  295.                                  fALLOC))
  296.                     return (MMIO_ERROR);
  297.  
  298.                 /*******************************************************
  299.                  * Create a buffer for one line of YUV data.
  300.                  *******************************************************/
  301.                 if (DosAllocMem ((PPVOID) &lpYUVLine,
  302.                                  lYUVBytesPerLine,
  303.                                  fALLOC))
  304.                     return (MMIO_ERROR);
  305.  
  306.                 /*******************************************************
  307.                  * Zero out RGB buffer to cover for any extra black pels
  308.                  * needed at the end.
  309.                  *******************************************************/
  310.                 memset (lpRGBLine, 0, ulRGBMaxBytesPerLine);
  311.  
  312.                 /*******************************************************
  313.                  * Initialize start position of RGB buffer.
  314.                  *******************************************************/
  315.                 lpImgBufPtr = pVidInfo->lpImgBuf;
  316.  
  317.                 /*******************************************************
  318.                  * Process Image Buffer - Save to file
  319.                  * Place "your" processing code here, if full image
  320.                  *      buffering is performed.
  321.                  * For MMotion:
  322.                  *    Loop
  323.                  *       1.Convert and copy a line of 1bpp, 4bpp, 8 bpp or
  324.                  *            24bpp data into a temporary 24 bpp RGB line.
  325.                  *            This line may contain overflow garbage
  326.                  *            pels from 1bpp and 4bpp modes (where
  327.                  *            width does not fall on even byte boundaries.)
  328.                  *       2.Convert the temporary RGB line contents into a
  329.                  *           YUV line.  ONLY that data necessary converted.
  330.                  *           Overflow from bitmap data ignored.
  331.                  *       3.Write the YUV line to the file
  332.                  *******************************************************/
  333.                 for (ulRowCount = 0;
  334.                      ulRowCount < ulHeight;
  335.                      ulRowCount++)
  336.                     {
  337.                     /***************************************************
  338.                      * Convert 1 line of Image data into RGB data
  339.                      ***************************************************/
  340.                    switch (usBitCount)
  341.                        {
  342.                        case 1:
  343.                            {
  344.                            /* Convert 1bpp padded image buffer into 24-bit */
  345.                            /*    RGB line buffer, w/pads                   */
  346.                            Convert1BitTo24Bit (
  347.                                    (PBYTE)lpImgBufPtr,
  348.                                    (PRGB) lpRGBLine,
  349.                                    (PRGB) &(pVidInfo->rgbPalette),
  350.                                    pVidInfo->ulImgPelBytesPerLine);
  351.                            break;
  352.                            }
  353.  
  354.                        case 4:
  355.                            {
  356.                            /* Convert data from app buffer into 24-bit and */
  357.                            /*    copy into image buffer                    */
  358.                            Convert4BitTo24Bit (
  359.                                    (PBYTE)lpImgBufPtr,
  360.                                    (PRGB) lpRGBLine,
  361.                                    (PRGB) &(pVidInfo->rgbPalette),
  362.                                    pVidInfo->ulImgPelBytesPerLine);
  363.                            break;
  364.                            }
  365.  
  366.                        case 8:
  367.                            {
  368.                            /* Convert data from app buffer into 24-bit and */
  369.                            /*    copy into image buffer                    */
  370.                            Convert8BitTo24Bit (
  371.                                    (PBYTE)lpImgBufPtr,
  372.                                    (PRGB) lpRGBLine,
  373.                                    (PRGB) &(pVidInfo->rgbPalette),
  374.                                    pVidInfo->ulImgPelBytesPerLine);
  375.                            break;
  376.                            }
  377.  
  378.                        case 24:
  379.                            {
  380.                            /* Copy raw RGB data from the image buffer into */
  381.                            /*    the temporary                             */
  382.                            /*   RGB line.  Only copy those pels necessary. */
  383.                            /*    No conversion required                    */
  384.                            memcpy ((PVOID) lpRGBLine,
  385.                                           (PVOID) lpImgBufPtr,
  386.                                           ulYUVPelWidth * 3);
  387.                            break;
  388.                            }
  389.  
  390.                        }   /* end of Switch for Bit Conversion block */
  391.  
  392.                     /***************************************************
  393.                      * Convert one line at a time from RGB to YUV.
  394.                      ***************************************************/
  395.                     ConvertOneLineRGBtoYUV (lpRGBLine,
  396.                                             lpYUVLine,
  397.                                             ulYUVPelWidth);
  398.  
  399.                     /***************************************************
  400.                      * Write out line of YUV data to the file.
  401.                      ***************************************************/
  402.                     lBytesWritten  = mmioWrite (pVidInfo->hmmioSS,
  403.                                                 (PVOID) lpYUVLine,
  404.                                                 lYUVBytesPerLine);
  405.  
  406.                     /* Check if error or EOF  */
  407.                     if (lBytesWritten != lYUVBytesPerLine)
  408.                        {
  409.                        lRetCode = lBytesWritten;
  410.                        break;
  411.                        }
  412.  
  413.                     /***************************************************
  414.                      * Make sure bitmap image buffer pointer is correct
  415.                      *    for next line to be converted.  Move forward ALL
  416.                      *    the bytes in the bitmap line, including overflow
  417.                      *    and pad bytes.
  418.                      ***************************************************/
  419.                     lpImgBufPtr += pVidInfo->ulImgPaddedBytesPerLine;
  420.                     }
  421.  
  422.                 /*******************************************************
  423.                  * Free temp buffers.
  424.                  *******************************************************/
  425.                 if (lpRGBLine)
  426.                    {
  427.                    DosFreeMem ((PVOID) lpRGBLine);
  428.                    }
  429.  
  430.                 if (lpYUVLine)
  431.                    {
  432.                    DosFreeMem ((PVOID) lpYUVLine);
  433.                    }
  434.                 }  /* end IF WRITE & IMAGE BUFFER block */
  435.  
  436.             /***********************************************************
  437.              * Free the RGB buffer, if it exists, that was created
  438.              * for the translated READ operations.
  439.              ***********************************************************/
  440.             if (pVidInfo->lpRGBBuf)
  441.                {
  442.                DosFreeMem ((PVOID) pVidInfo->lpRGBBuf);
  443.                }
  444.  
  445.             /***********************************************************
  446.              * Free the IMG buffer, if it exists, that was created
  447.              * for the translated  WRITE operations.
  448.              ***********************************************************/
  449.             if (pVidInfo->lpImgBuf)
  450.                {
  451.                DosFreeMem ((PVOID) pVidInfo->lpImgBuf);
  452.                }
  453.  
  454.             /***********************************************************
  455.              * Close the file with mmioClose.
  456.              ***********************************************************/
  457.             rc = mmioClose (pVidInfo->hmmioSS, 0);
  458.  
  459.             DosFreeMem ((PVOID) pVidInfo);
  460.  
  461.             if (rc != MMIO_SUCCESS)
  462.                return (rc);
  463.  
  464.             return (lRetCode);
  465.             }  /* end case of MMIOM_CLOSE */
  466.  
  467.         /*#############################################################*
  468.          * Get the NLS format Information.
  469.          *#############################################################*/
  470.         case MMIOM_GETFORMATINFO:
  471.             {
  472.             /***********************************************************
  473.              * Declare local variables.
  474.              ***********************************************************/
  475.             PMMFORMATINFO       pmmformatinfo;
  476.  
  477.             /************************************************************
  478.              * Set pointer to MMFORMATINFO structure.
  479.              ************************************************************/
  480.             pmmformatinfo = (PMMFORMATINFO) lParam1;
  481.  
  482.             /************************************************************
  483.              * Fill in the values for the MMFORMATINFO structure.
  484.              ************************************************************/
  485.             pmmformatinfo->ulStructLen  = sizeof (MMFORMATINFO);
  486.             pmmformatinfo->fccIOProc    = FOURCC_MMOT;
  487.             pmmformatinfo->ulIOProcType = MMIO_IOPROC_FILEFORMAT;
  488.             pmmformatinfo->ulMediaType  = MMIO_MEDIATYPE_IMAGE;
  489.  
  490.             pmmformatinfo->ulFlags      = MMIO_CANREADTRANSLATED        |
  491.                                           MMIO_CANREADUNTRANSLATED      |
  492.                                           MMIO_CANWRITETRANSLATED       |
  493.                                           MMIO_CANWRITEUNTRANSLATED     |
  494.                                           MMIO_CANREADWRITEUNTRANSLATED |
  495.                                           MMIO_CANSEEKTRANSLATED        |
  496.                                           MMIO_CANSEEKUNTRANSLATED;
  497.  
  498.             strcpy ((PSZ) pmmformatinfo->szDefaultFormatExt, pszMotionExt);
  499.             if (GetNLSData( &pmmformatinfo->ulCodePage,
  500.                             &pmmformatinfo->ulLanguage ))
  501.                {
  502.                return( -1L );
  503.                }
  504.  
  505.             if (GetFormatStringLength( FOURCC_MMOT,
  506.                                        &(pmmformatinfo->lNameLength) ))
  507.                {
  508.                return( -1L );
  509.                }
  510.  
  511.  
  512.             /************************************************************
  513.              * Return success back to the application.
  514.              ************************************************************/
  515.             return (MMIO_SUCCESS);
  516.             } /* end case of MMIOM_GETFORMATINFO */
  517.  
  518.         /*#############################################################*
  519.          * Get the NLS format name.
  520.          *#############################################################*/
  521.         case MMIOM_GETFORMATNAME:
  522.             {
  523.             LONG lBytesCopied;
  524.  
  525.             /************************************************************
  526.              * Copy the M-Motion format string into buffer supplied by
  527.              * lParam1.  Only put in the amount of my string up to the
  528.              * allocated amount which is in lParam2.  Leave enough room
  529.              * for the NULL termination.
  530.              ************************************************************/
  531.             lBytesCopied = GetFormatString( FOURCC_MMOT,
  532.                                             (char *)lParam1,
  533.                                             lParam2 );
  534.  
  535.             return (lBytesCopied);
  536.             } /* end case of MMIOM_GETFORMATNAME */
  537.  
  538.         /*#############################################################*
  539.          * Get the file header.
  540.          *#############################################################*/
  541.         case MMIOM_GETHEADER:
  542.             {
  543.             /************************************************************
  544.              * Declare local variables.
  545.              ************************************************************/
  546.             PMMFILESTATUS       pVidInfo;
  547.  
  548.             /************************************************************
  549.              * Check for valid MMIOINFO block.
  550.              ************************************************************/
  551.             if (!pmmioinfo)
  552.                 return (0);
  553.  
  554.             /************************************************************
  555.              * Set up our working file status variable.
  556.              ************************************************************/
  557.             pVidInfo = (PMMFILESTATUS)pmmioinfo->pExtraInfoStruct;
  558.  
  559.             /**************************************************
  560.              * Getheader only valid in READ or READ/WRITE mode.
  561.              * There is no header to get in WRITE mode.  We
  562.              * must also have a valid file handle to read from
  563.              **************************************************/
  564.             if ((pmmioinfo->ulFlags & MMIO_WRITE) ||
  565.                 (!(pVidInfo->hmmioSS)))
  566.                return (0);
  567.  
  568.             /************************************************************
  569.              * Check for Translation mode.
  570.              ************************************************************/
  571.             if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER))
  572.                 {
  573.                 /********************************************************
  574.                  * Translation is off.
  575.                  ********************************************************/
  576.                 if (lParam2 < sizeof (MMOTIONHEADER))
  577.                     {
  578.                     pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
  579.                     return (0);
  580.                     }
  581.  
  582.                 if (!lParam1)
  583.                     {
  584.                     pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
  585.                     return (0);
  586.                     }
  587.  
  588.                 /********************************************************
  589.                  * Read in first 16 bytes to fill up MMotion header.
  590.                  ********************************************************/
  591.                 memcpy ((PVOID) lParam1,
  592.                         (PVOID)&pVidInfo->mmotHeader,
  593.                         sizeof (MMOTIONHEADER));
  594.  
  595.                 /* Indicate that the header has been set, which    */
  596.                 /* is meaningless in read mode, but allows the     */
  597.                 /* application to do writes in read/write mode     */
  598.                 pVidInfo->bSetHeader = TRUE;
  599.  
  600.                 return (sizeof (MMOTIONHEADER));
  601.                 }   /* end IF NOT TRANSLATED block */
  602.  
  603.             /******************
  604.              * TRANSLATION IS ON
  605.              ******************/
  606.             if (lParam2 < sizeof (MMIMAGEHEADER))
  607.                 {
  608.                 pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
  609.                 return (0);
  610.                 }
  611.  
  612.             if (!lParam1)
  613.                 {
  614.                 pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
  615.                 return (0);
  616.                 }
  617.  
  618.             memcpy ((PVOID)lParam1,
  619.                     (PVOID)&pVidInfo->mmImgHdr,
  620.                     sizeof (MMIMAGEHEADER));
  621.  
  622.             return (sizeof (MMIMAGEHEADER));
  623.             } /* end case of MMIOM_GETHEADER */
  624.  
  625.         /*#############################################################*
  626.          * Identify whether this file can be processed.
  627.          *#############################################################*/
  628.         case MMIOM_IDENTIFYFILE:
  629.             {
  630.             /************************************************************
  631.              * Declare local variables.
  632.              ************************************************************/
  633.             MMOTIONHEADER   mmotHeader;    /* MMotion structure variable*/
  634.             HMMIO           hmmioTemp;     /* MMIO File Handle          */
  635.             ULONG           ulWidth;
  636.             ULONG           ulHeight;
  637.             ULONG           ulRequiredFileLength;
  638.             ULONG           ulActualFileLength;
  639.             BOOL             fValidMMotionFile = FALSE;
  640.  
  641.             ULONG           ulTempFlags = MMIO_READ | MMIO_DENYWRITE |
  642.                                           MMIO_NOIDENTIFY;
  643.                                            /* flags used for temp open  */
  644.                                            /* and close                 */
  645.  
  646.             /************************************************************
  647.              * We need either a file name (lParam1) or file handle (lParam2)
  648.              ************************************************************/
  649.             if (!lParam1 && !lParam2)
  650.                 return (MMIO_ERROR);
  651.  
  652.             /* Copy the file handle, assuming one was provided... */
  653.             hmmioTemp = (HMMIO)lParam2;
  654.  
  655.             /************************************************************
  656.              * If no handle, then open the file using the string name
  657.              ************************************************************/
  658.             if (!hmmioTemp)
  659.                {
  660.                if (!(hmmioTemp = mmioOpen ((PSZ) lParam1,
  661.                                           NULL,
  662.                                           ulTempFlags)))
  663.                    {
  664.                    return (MMIO_ERROR);
  665.                    }
  666.                }
  667.  
  668.             /************************************************************
  669.              * Read in enough bytes to check out file.
  670.              ************************************************************/
  671.             if (sizeof (MMOTIONHEADER) !=
  672.                             mmioRead (hmmioTemp,
  673.                                       (PVOID) &mmotHeader,
  674.                                       (ULONG) sizeof (MMOTIONHEADER)))
  675.                 {
  676.                 /********************************************************
  677.                  * Fail so close file and then return.
  678.                  ********************************************************/
  679.                 if (!lParam2) /* Don't close handle if provided to us  */
  680.                    mmioClose (hmmioTemp, 0);
  681.                 return (MMIO_ERROR);
  682.                 }
  683.  
  684.             /************************************************************
  685.              * Close file before returning.
  686.              ************************************************************/
  687.             if (!lParam2) /* Don't close handle if provided to us  */
  688.                mmioClose (hmmioTemp, 0);
  689.  
  690.             /************************************************************
  691.              * Check validity of file and return result.
  692.              ************************************************************/
  693.             if (memcmp (mmotHeader.mmID, "YUV12C", 6) == 0)
  694.                 {
  695.                 ulWidth = mmotHeader.mmXlen;
  696.                 ulHeight = mmotHeader.mmYlen;
  697.  
  698.                 /* Calculate what the length of the file SHOULD be based on the */
  699.                 /*   header contents                                            */
  700.                 ulRequiredFileLength = (((ulWidth >> 2) * 6) * ulHeight) +
  701.                                                        sizeof (MMOTIONHEADER);
  702.  
  703.                 /* Query what the ACTUAL length of the file is                  */
  704.                 ulActualFileLength = (ULONG)mmioSeek (hmmioTemp, 0, SEEK_END);
  705.  
  706.                 /* If these don't match, then it isn't a VALID M-Motion file    */
  707.                 /*     - regardless of what the header says.                    */
  708.                 if (ulRequiredFileLength == ulActualFileLength)
  709.                    fValidMMotionFile = TRUE;
  710.                 else
  711.                    fValidMMotionFile = FALSE;
  712.                 }  /* end header check block */
  713.  
  714.             /************************************************************
  715.              * Close file before returning.
  716.              ************************************************************/
  717.             if (!lParam2)  /* Don't close handle if provided to us      */
  718.                mmioClose (hmmioTemp, 0);
  719.  
  720.             if (fValidMMotionFile)
  721.                return (MMIO_SUCCESS);
  722.             else
  723.                return (MMIO_ERROR);
  724.             } /* end case of MMIOM_IDENTIFYFILE */
  725.  
  726.         /*#############################################################*/
  727.         /*#############################################################*/
  728.         case MMIOM_OPEN:
  729.             {
  730.             /************************************************************
  731.              * Declare local variables
  732.              ************************************************************/
  733.             PMMFILESTATUS   pVidInfo;   /* pointer to a MMOTION file    */
  734.                                         /* status structure that we will*/
  735.                                         /* use for this file instance   */
  736.             MMIMAGEHEADER   MMImgHdr;
  737.             ULONG           ulRequiredFileLength;
  738.             ULONG           ulActualFileLength;
  739.             ULONG           ulWidth;
  740.             ULONG           ulHeight;
  741.             PBYTE           lpYUVBuf;
  742.             ULONG           ulRowCount;
  743.             ULONG           ulRGBBytesPerLine;
  744.             ULONG           ulYUVBytesPerLine;
  745.             LONG            rc;
  746.             HMMIO           hmmioSS;
  747.             PBYTE           lpRGBBufPtr;
  748.             FOURCC          fccStorageSystem;   /* SS I/O Proc FOURCC       */
  749.             MMIOINFO        mmioinfoSS;         /* I/O info block for SS ref*/
  750.             PSZ pszFileName = (CHAR *)lParam1;  /* get the filename from    */
  751.                                                 /* parameter                */
  752.  
  753.             /************************************************************
  754.              * Check for valid MMIOINFO block.
  755.              ************************************************************/
  756.             if (!pmmioinfo)
  757.                 return (MMIO_ERROR);
  758.  
  759.             /************************************************************
  760.              * If flags show read and write then send back an error.  We
  761.              * only support reading or writing but not both at the same
  762.              * time on the same file.
  763.              ************************************************************/
  764.             if ((pmmioinfo->ulFlags & MMIO_READWRITE) &&
  765.                 ((pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) ||
  766.                  (pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER)))
  767.                 {
  768.                 return (MMIO_ERROR);
  769.                 }
  770.  
  771.             /*********************************************************
  772.              * Determine the storage system/child IOProc that actually
  773.              *   obtains the data for us.   The M-Motion data may be contained
  774.              *   in a memory (RAM) file, as a component in a database or
  775.              *   library (a Compound file), or as a stand-alone disk file.
  776.              *
  777.              * While the Application uses this M-Motion IOProc to obtain
  778.              *   untranslated (MMotion) or translated (Bitmap) data,
  779.              *   the IOProc must obtain it's data from something that
  780.              *   reads and writes to a storage media.  The exact storage
  781.              *   media is immaterial - so long as the read and write
  782.              *   operations generate data that LOOKS like it is part
  783.              *   of a standard file.
  784.              *********************************************************/
  785.             if (!pmmioinfo->fccChildIOProc)
  786.                {
  787.                /* Need to determine SS if create from pmmioinfo and filename. */
  788.                if (pmmioinfo->ulFlags & MMIO_CREATE)
  789.                   {
  790.                   if (mmioDetermineSSIOProc( pszFileName,
  791.                                              pmmioinfo,
  792.                                              &fccStorageSystem,
  793.                                              NULL ))
  794.                      {
  795.                      fccStorageSystem = FOURCC_DOS;
  796.                      }
  797.                   }
  798.                else
  799.                   {
  800.                   if (mmioIdentifyStorageSystem( pszFileName,
  801.                                                  pmmioinfo,
  802.                                                  &fccStorageSystem ))
  803.                      {
  804.                      return (MMIO_ERROR);
  805.                      }
  806.  
  807.                   }
  808.  
  809.                if (!fccStorageSystem)
  810.                   {
  811.                   return (MMIO_ERROR);
  812.                   }
  813.                else
  814.                   {
  815.                   pmmioinfo->fccChildIOProc = fccStorageSystem;
  816.                   }
  817.                } /* end storage system identification block */
  818.  
  819.             /**************************************************************
  820.              * Direct the open to the specific storage system necessary
  821.              **************************************************************/
  822.             memset( &mmioinfoSS, '\0', sizeof(MMIOINFO));
  823.             memmove( &mmioinfoSS, pmmioinfo, sizeof(MMIOINFO));
  824.             mmioinfoSS.pIOProc = NULL;
  825.             mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc;
  826.             mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY;
  827.  
  828.             /************************************************************
  829.              * Try to open the file.  Add the NO IDENTIFY flag to
  830.              *    ENSURE THAT WE DON'T LOOP RECURSIVELY!!!
  831.              ************************************************************/
  832.             hmmioSS = mmioOpen (pszFileName,
  833.                                 &mmioinfoSS,
  834.                                 mmioinfoSS.ulFlags);
  835.  
  836.             /************************************************************
  837.              * Check if a DELETE was requested - mmioOpen returns a 1,
  838.              *    so we much check this separately
  839.              ************************************************************/
  840.             if (pmmioinfo->ulFlags & MMIO_DELETE)
  841.                {
  842.                /* was the delete successful?         */
  843.                if (!hmmioSS)
  844.                   {
  845.                   pmmioinfo->ulErrorRet = MMIOERR_DELETE_FAILED;
  846.                   return (MMIO_ERROR);
  847.                   }
  848.                else
  849.                   {
  850.                   return (MMIO_SUCCESS);
  851.                   }
  852.                }
  853.  
  854.             /************************************************************
  855.              * Check the return code from the open call for an error.
  856.              *    If not delete, then the open should have worked.
  857.              ************************************************************/
  858.             if (!hmmioSS)
  859.                 return (MMIO_ERROR);
  860.  
  861.             /************************************************************
  862.              * Allocate memory for one MMotion FileStatus structures
  863.              ************************************************************/
  864.             DosAllocMem ((PPVOID) &pVidInfo,
  865.                                   sizeof (MMFILESTATUS),
  866.                                   fALLOC);
  867.  
  868.             /************************************************************
  869.              * Ensure the allocate was successful.  If not, then
  870.              *   close the file and return open as unsucessful...
  871.              ************************************************************/
  872.             if (!pVidInfo)
  873.                {
  874.                mmioClose (hmmioSS, 0);
  875.                return (MMIO_ERROR);
  876.                }
  877.  
  878.             pVidInfo->hmmioSS = hmmioSS;
  879.  
  880.             /************************************************************
  881.              * Store pointer to our MMFILESTATUS structure in
  882.              * pExtraInfoStruct field that is provided for our use.
  883.              ************************************************************/
  884.             pmmioinfo->pExtraInfoStruct = (PVOID)pVidInfo;
  885.  
  886.             /************************************************************
  887.              * Set the fields of the FileStatus structure that the
  888.              * IOProc is responsible for.
  889.              ************************************************************/
  890.             InitFileStruct (pVidInfo);
  891.  
  892.             /*********************************************************
  893.              * If this is a read, we need to check that is a M-Motion
  894.              *    file and perhaps get the data.
  895.              *********************************************************/
  896.             if (pmmioinfo->ulFlags & MMIO_READ)
  897.                {
  898.                /*********************************************************
  899.                 * First we must get some basic information from the file
  900.                 * Read in data to fill up the MMOTIONHEADER structure.
  901.                 *
  902.                 * If the read is unsuccessful, this is not a M-Motion file
  903.                 *    and we should return a failure on the open
  904.                 *********************************************************/
  905.                if (sizeof (MMOTIONHEADER) !=
  906.                                    mmioRead (pVidInfo->hmmioSS,
  907.                                              (PVOID) &pVidInfo->mmotHeader,
  908.                                              (ULONG) sizeof (MMOTIONHEADER)))
  909.                    {
  910.                    mmioClose (pVidInfo->hmmioSS, 0);
  911.                    DosFreeMem ((PVOID) pVidInfo);
  912.                    return (MMIO_ERROR);
  913.                    }
  914.  
  915.                /* Ensure this IS an MMotion file header before we continue  */
  916.                if (strcmp (pVidInfo->mmotHeader.mmID, "YUV12C"))
  917.                    {
  918.                    mmioClose (pVidInfo->hmmioSS, 0);
  919.                    DosFreeMem ((PVOID) pVidInfo);
  920.                    return (MMIO_ERROR);
  921.                    }
  922.  
  923.                /********************************************************
  924.                 * Set up width and height of image.
  925.                 ********************************************************/
  926.                ulWidth  = (ULONG)pVidInfo->mmotHeader.mmXlen;
  927.                ulHeight = (ULONG)pVidInfo->mmotHeader.mmYlen;
  928.  
  929.                /* Calculate what the length of the file SHOULD be based on the */
  930.                /*   header contents                                            */
  931.                ulRequiredFileLength = (((ulWidth >> 2) * 6) * ulHeight) +
  932.                                                       sizeof (MMOTIONHEADER);
  933.  
  934.                /* Query what the ACTUAL length of the file is,                 */
  935.                /*   then move back to just after the header.                   */
  936.                ulActualFileLength = (ULONG)mmioSeek (pVidInfo->hmmioSS,
  937.                                                     0, SEEK_END);
  938.  
  939.                mmioSeek (pVidInfo->hmmioSS, sizeof (MMOTIONHEADER), SEEK_SET);
  940.  
  941.                /* If these don't match, then it isn't a VALID M-Motion file    */
  942.                /*    - regardless of what the header says.                     */
  943.                if (ulRequiredFileLength != ulActualFileLength)
  944.                    {
  945.                    mmioClose (pVidInfo->hmmioSS, 0);
  946.                    DosFreeMem ((PVOID) pVidInfo);
  947.                    return (MMIO_ERROR);
  948.                    }
  949.  
  950.                /************************************************************
  951.                 * If the app intends to read in translation mode, we must
  952.                 * allocate and set-up the buffer that will contain the RGB data
  953.                 *
  954.                 * We must also read in the data to insure that the first
  955.                 * read, seek, or get-header operation will have data
  956.                 * to use.  This is ONLY NECESSARY FOR TRANSLATED MODE
  957.                 * operations, since we must process reads/writes pretending
  958.                 * the image is stored from the Bottom-up.
  959.                 *
  960.                 ************************************************************
  961.                 ************************************************************
  962.                 * Fill out the MMIMAGEHEADER structure.
  963.                 ************************************************************/
  964.                MMImgHdr.ulHeaderLength = sizeof (MMIMAGEHEADER);
  965.                MMImgHdr.ulContentType  = MMIO_IMAGE_PHOTO;
  966.                MMImgHdr.ulMediaType    = MMIO_MEDIATYPE_IMAGE;
  967.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cbFix =
  968.                            sizeof (BITMAPINFOHEADER2);
  969.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cx              = ulWidth;
  970.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cy              = ulHeight;
  971.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cPlanes         = 1;
  972.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount       = 24;
  973.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.ulCompression   =
  974.                    BCA_UNCOMP;
  975.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cbImage         =
  976.                    ulWidth * ulHeight * 3;
  977.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cxResolution    = 0L;
  978.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cyResolution    = 0L;
  979.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cclrUsed        = 0L;
  980.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cclrImportant   = 0L;
  981.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usUnits         = 0L;
  982.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usReserved      = 0L;
  983.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usRecording     =
  984.                    BRA_BOTTOMUP;
  985.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.usRendering     =
  986.                    BRH_NOTHALFTONED;
  987.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cSize1          = 0L;
  988.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.cSize2          = 0L;
  989.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.ulColorEncoding = 0L;
  990.                MMImgHdr.mmXDIBHeader.BMPInfoHeader2.ulIdentifier    = 0L;
  991.  
  992.                /************************************************************
  993.                 * Copy the image header into private area for later use.
  994.                 * This will be returned on a mmioGetHeader () call
  995.                 ************************************************************/
  996.                pVidInfo->mmImgHdr = MMImgHdr;
  997.  
  998.                /********************************************************
  999.                 * YUV Bytes/Line are = 1 1/2 times the number of pels
  1000.                 ********************************************************/
  1001.                ulYUVBytesPerLine = ulWidth + (ulWidth >> 1);
  1002.  
  1003.                /********************************************************
  1004.                 * RGB Bytes/Line are = 2* YUV bytes/line
  1005.                 ********************************************************/
  1006.                ulRGBBytesPerLine = (ulYUVBytesPerLine << 1);
  1007.  
  1008.                /********************************************************
  1009.                 * Determine total bytes in image
  1010.                 ********************************************************/
  1011.                pVidInfo->ulRGBTotalBytes = ulWidth * ulHeight * 3;
  1012.  
  1013.                /********************************************************
  1014.                 * MMotion Images are ALWAYS on 4-pel boundaries, which also
  1015.                 *   makes them on 4-byte/LONG boundaries which is used for
  1016.                 *   Bitmaps.  Therefore, there are no extra pad bytes necessary
  1017.                 ********************************************************/
  1018.                pVidInfo->ulImgPaddedBytesPerLine = ulWidth * 3;
  1019.                pVidInfo->ulImgTotalBytes = pVidInfo->ulRGBTotalBytes;
  1020.  
  1021.                /*********************************************************
  1022.                 * For translated data READ mode, we must allocate a buffer,
  1023.                 *    then get the YUV data from the file and load the RGB
  1024.                 *    buffer.
  1025.                 * PLACE FORMAT SPECIFIC CODE HERE TO LOAD IMAGE INTO BUFFER
  1026.                 * The code below is M-Motion format specific.
  1027.                 *********************************************************/
  1028.                if (pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)
  1029.                   {
  1030.                   /********************************************************
  1031.                    * Get space for full image buffer.
  1032.                    * This will be retained until the file is closed.
  1033.                    ********************************************************/
  1034.                   if (DosAllocMem ((PPVOID) &(pVidInfo->lpRGBBuf),
  1035.                                     pVidInfo->ulRGBTotalBytes,
  1036.                                     fALLOC))
  1037.                       {
  1038.                       mmioClose (pVidInfo->hmmioSS, 0);
  1039.                       DosFreeMem ((PVOID) pVidInfo);
  1040.                       return (MMIO_ERROR);
  1041.                       }
  1042.  
  1043.                   /********************************************************
  1044.                    * Get temporary space for one line YUV Buffer.
  1045.                    ********************************************************/
  1046.                   if (DosAllocMem ((PPVOID) &lpYUVBuf,
  1047.                                    ulYUVBytesPerLine,
  1048.                                    fALLOC))
  1049.                       {
  1050.                       mmioClose (pVidInfo->hmmioSS, 0);
  1051.                       DosFreeMem ((PVOID) pVidInfo);
  1052.                       return (MMIO_ERROR);
  1053.                       }
  1054.  
  1055.                   /********************************************************
  1056.                    * Initialize beginning buffer position
  1057.                    ********************************************************/
  1058.                   lpRGBBufPtr = pVidInfo->lpRGBBuf;
  1059.  
  1060.                   /********************************************************
  1061.                    * Read in YUV data one line at a time, converting
  1062.                    * from YUV to RGB, then placing in the image buffer
  1063.                    ********************************************************/
  1064.                   for (ulRowCount = 0;
  1065.                        ulRowCount < ulHeight;
  1066.                        ulRowCount++)
  1067.  
  1068.                       {
  1069.                       /****************************************************
  1070.                        * Read in one line.
  1071.                        ****************************************************/
  1072.                       rc = mmioRead (pVidInfo->hmmioSS,
  1073.                                      (PVOID) lpYUVBuf,
  1074.                                      (ULONG) ulYUVBytesPerLine);
  1075.  
  1076.                       /****************************************************
  1077.                        * Convert one line at a time.
  1078.                        ****************************************************/
  1079.                       ConvertOneLineYUVtoRGB (lpYUVBuf,
  1080.                                               lpRGBBufPtr,
  1081.                                               ulYUVBytesPerLine);
  1082.  
  1083.                       /****************************************************
  1084.                        * Make sure buffer ptr is correct for next convert.
  1085.                        ****************************************************/
  1086.                       lpRGBBufPtr += (LONG)ulRGBBytesPerLine;
  1087.                       }   /* end of FOR loop to read YUV data */
  1088.  
  1089.                   DosFreeMem (lpYUVBuf);
  1090.  
  1091.                   /********************************************************
  1092.                    * This changes from M-Motion's top-down form to OS/2
  1093.                    * PM's bottom-up bitmap form.
  1094.                    ********************************************************/
  1095.                   ImgBufferFlip (pVidInfo->lpRGBBuf,
  1096.                                  pVidInfo->ulImgPaddedBytesPerLine,
  1097.                                  ulHeight);
  1098.  
  1099.                   /********************************************************
  1100.                    * RGB Buffer now full, set position pointers to the
  1101.                    * beginning of the buffer.
  1102.                    ********************************************************/
  1103.                   pVidInfo->lImgBytePos =  0;
  1104.                   }   /*  end IF TRANSLATED block */
  1105.                } /* end IF READ block */
  1106.  
  1107.             return (MMIO_SUCCESS);
  1108.             } /* end case of MMIOM_OPEN */
  1109.  
  1110.         /*#############################################################*/
  1111.         /*#############################################################*/
  1112.         case MMIOM_QUERYHEADERLENGTH:
  1113.             {
  1114.             /************************************************************
  1115.              * If there is no MMIOINFO block then return an error.
  1116.              ************************************************************/
  1117.             if (!pmmioinfo)
  1118.                 return (0);
  1119.  
  1120.             /************************************************************
  1121.              * If header is in translated mode then return the media
  1122.              * type specific structure size.
  1123.              ************************************************************/
  1124.             if (pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER)
  1125.                 return (sizeof (MMIMAGEHEADER));
  1126.  
  1127.             else
  1128.                 /********************************************************
  1129.                  * Header is not in translated mode so return the size
  1130.                  * of the MMotion header.
  1131.                  ********************************************************/
  1132.                 return (sizeof (MMOTIONHEADER));
  1133.  
  1134.             break;
  1135.             } /* end case of MMIOM_QUERYHEADERLENGTH */
  1136.  
  1137.         /*#############################################################*/
  1138.         /*#############################################################*/
  1139.         case MMIOM_READ:
  1140.             {
  1141.             /************************************************************
  1142.              * Declare Local Variables
  1143.              ************************************************************/
  1144.             PMMFILESTATUS   pVidInfo;
  1145.             LONG            rc;
  1146.             LONG            lBytesToRead;
  1147.  
  1148.             /************************************************************
  1149.              * Check for valid MMIOINFO block.
  1150.              ************************************************************/
  1151.             if (!pmmioinfo)
  1152.                 return (MMIO_ERROR);
  1153.  
  1154.             /************************************************************
  1155.              * Set up our working file status variable.
  1156.              ************************************************************/
  1157.             pVidInfo = (PMMFILESTATUS)pmmioinfo->pExtraInfoStruct;
  1158.  
  1159.             /************************************************************
  1160.              * Is Translate Data off?
  1161.              ************************************************************/
  1162.             if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))
  1163.                 {
  1164.                 /********************************************************
  1165.                  * Since no translation, provide exact number of bytes req
  1166.                  ********************************************************/
  1167.                 if (!lParam1)
  1168.                     return (MMIO_ERROR);
  1169.  
  1170.                 rc = mmioRead (pVidInfo->hmmioSS,
  1171.                                (PVOID) lParam1,
  1172.                                (ULONG) lParam2);
  1173.  
  1174.                 return (rc);
  1175.                 }
  1176.  
  1177.             /************************************************************
  1178.              * Otherwise, Translate Data is on...
  1179.              ************************************************************/
  1180.  
  1181.             /************************************************************
  1182.              * Ensure we do NOT write more data out than is remaining
  1183.              *    in the buffer.  The length of read was requested in
  1184.              *    image bytes, so confirm that there are that many of
  1185.              *    virtual bytes remaining.
  1186.              ************************************************************/
  1187.             if ((ULONG)(pVidInfo->lImgBytePos + lParam2) >
  1188.                  pVidInfo->ulImgTotalBytes)
  1189.                lBytesToRead =
  1190.                    pVidInfo->ulImgTotalBytes - pVidInfo->lImgBytePos;
  1191.             else
  1192.                lBytesToRead = (ULONG)lParam2;
  1193.  
  1194.             /************************************************************
  1195.              * Perform this block on ALL reads.  The image data should
  1196.              * be in the RGB buffer at this point, and can be handed
  1197.              * to the application.
  1198.              *
  1199.              * Conveniently, the virtual image position is the same
  1200.              *    as the RGB buffer position, since both are 24 bit-RGB
  1201.              ************************************************************/
  1202.             memcpy ((PVOID)lParam1,
  1203.                     &(pVidInfo->lpRGBBuf[pVidInfo->lImgBytePos]),
  1204.                     lBytesToRead);
  1205.  
  1206.             /************************************************************
  1207.              * Move RGB Buffer pointer forward by number of bytes read.
  1208.              * The Img buffer pos is identical, since both are 24 bits
  1209.              ************************************************************/
  1210.             pVidInfo->lImgBytePos += lBytesToRead;
  1211.  
  1212.             return (lBytesToRead);
  1213.             }   /* end case  of MMIOM_READ */
  1214.  
  1215.         /*#############################################################*/
  1216.         /*#############################################################*/
  1217.         case MMIOM_SEEK:
  1218.             {
  1219.             /************************************************************
  1220.              * Set up locals.
  1221.              ************************************************************/
  1222.             PMMFILESTATUS   pVidInfo;
  1223.             LONG            lNewFilePosition;
  1224.             LONG            lPosDesired;
  1225.             SHORT           sSeekMode;
  1226.  
  1227.             /************************************************************
  1228.              * Check to make sure MMIOINFO block is valid.
  1229.              ************************************************************/
  1230.             if (!pmmioinfo)
  1231.                 return (MMIO_ERROR);
  1232.  
  1233.             /************************************************************
  1234.              * Set up our working file status variable.
  1235.              ************************************************************/
  1236.             pVidInfo = (PMMFILESTATUS)pmmioinfo->pExtraInfoStruct;
  1237.  
  1238.             lPosDesired = lParam1;
  1239.             sSeekMode = (SHORT)lParam2;
  1240.  
  1241.             /************************************************************
  1242.              * Is Translate Data on?
  1243.              ************************************************************/
  1244.             if (pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)
  1245.                 {
  1246.                 /********************************************************
  1247.                  * Attempt to move the Image buffer pointer to the
  1248.                  *    desired location.  App sends SEEK requests in
  1249.                  *    positions relative to the image planes & bits/pel
  1250.                  * We must also convert this to RGB positions
  1251.                  ********************************************************/
  1252.                 switch (sSeekMode)
  1253.                     {
  1254.                     case SEEK_SET:
  1255.                         {
  1256.                         lNewFilePosition = lPosDesired;
  1257.                         break;
  1258.                         }
  1259.                     case SEEK_CUR:
  1260.                         {
  1261.                         lNewFilePosition = pVidInfo->lImgBytePos + lPosDesired;
  1262.                         break;
  1263.                         }
  1264.                     case SEEK_END:
  1265.                         {
  1266.  
  1267.                         lNewFilePosition =
  1268.                                      pVidInfo->ulImgTotalBytes += lPosDesired;
  1269.                         break;
  1270.                         }
  1271.  
  1272.                     default :
  1273.                        return (MMIO_ERROR);
  1274.                     }
  1275.  
  1276.                 /********************************************************
  1277.                  * Make sure seek did not go before start of file.
  1278.                  * If so, then don't change anything, just return an error
  1279.                  ********************************************************/
  1280.                 if (lNewFilePosition < 0)
  1281.                    {
  1282.                    return (MMIO_ERROR);
  1283.                    }
  1284.  
  1285.                 /********************************************************
  1286.                  * Make sure seek did not go past the end of file.
  1287.                  ********************************************************/
  1288.                 if (lNewFilePosition > (LONG)pVidInfo->ulImgTotalBytes)
  1289.                     lNewFilePosition = pVidInfo->ulImgTotalBytes;
  1290.  
  1291.                 pVidInfo->lImgBytePos = lNewFilePosition;
  1292.  
  1293.                 return (pVidInfo->lImgBytePos);
  1294.                 } /* end  IF DATA TRANSLATED */
  1295.  
  1296.             /************************************************************
  1297.              * Translate Data is OFF...
  1298.              ************************************************************
  1299.              * if this is a seek from the beginning of the file,
  1300.              *    we must account for and pass the header
  1301.              ************************************************************/
  1302.             if (lParam2==SEEK_SET)
  1303.                lPosDesired += MMOTION_HEADER_SIZE;
  1304.  
  1305.             lNewFilePosition = mmioSeek (pVidInfo->hmmioSS,
  1306.                                          lPosDesired,
  1307.                                          sSeekMode);
  1308.  
  1309.             /********************************************
  1310.              * Ensure we did not move to within the header
  1311.              ********************************************/
  1312.             if ((lNewFilePosition != MMIO_ERROR) &&
  1313.                 (lNewFilePosition < MMOTION_HEADER_SIZE))
  1314.                {
  1315.                lNewFilePosition = mmioSeek (pVidInfo->hmmioSS,
  1316.                                              (LONG)MMOTION_HEADER_SIZE,
  1317.                                              SEEK_SET);
  1318.                }
  1319.  
  1320.             /************************************************************
  1321.              * Return new position.  Always remove the length of the
  1322.              *    header from the this position value
  1323.              ************************************************************/
  1324.             if (lNewFilePosition != MMIO_ERROR)
  1325.                lNewFilePosition -= MMOTION_HEADER_SIZE;
  1326.  
  1327.             return (lNewFilePosition);
  1328.             }  /* end case of MMIOM_SEEK */
  1329.  
  1330.         /*#############################################################*/
  1331.         /*#############################################################*/
  1332.         case MMIOM_SETHEADER:
  1333.             {
  1334.             /************************************************************
  1335.              * Declare local variables.
  1336.              ************************************************************/
  1337.             PMMIMAGEHEADER          pMMImgHdr;
  1338.             PMMFILESTATUS           pVidInfo;
  1339.             USHORT                  usNumColors;
  1340.             ULONG                   ulImgBitsPerLine;
  1341.             ULONG                   ulImgBytesPerLine;
  1342.             ULONG                   ulBytesWritten;
  1343.             ULONG                   ulWidth;
  1344.             ULONG                   ul4PelWidth;
  1345.             ULONG                   ulHeight;
  1346.             USHORT                  usPlanes;
  1347.             USHORT                  usBitCount;
  1348.             USHORT                  usPadBytes;
  1349.  
  1350.             /************************************************************
  1351.              * Check for valid MMIOINFO block.
  1352.              ************************************************************/
  1353.             if (!pmmioinfo)
  1354.                 return (MMIO_ERROR);
  1355.  
  1356.             /************************************************************
  1357.              * Set up our working variable MMFILESTATUS.
  1358.              ************************************************************/
  1359.             pVidInfo = (PMMFILESTATUS) pmmioinfo->pExtraInfoStruct;
  1360.  
  1361.             /************************************************************
  1362.              * Only allow this function if we are in WRITE mode
  1363.              * And only if we have not already set the header
  1364.              ************************************************************/
  1365.             if ((!(pmmioinfo->ulFlags & MMIO_WRITE)) ||
  1366.                 (!(pVidInfo->hmmioSS)) ||
  1367.                 (pVidInfo->bSetHeader))
  1368.                 return (0);
  1369.  
  1370.             /********************************************************
  1371.              * Make sure lParam1 is a valid pointer
  1372.              ********************************************************/
  1373.             if (!lParam1)
  1374.                 {
  1375.                 pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
  1376.                 return (0);
  1377.                 }
  1378.  
  1379.             /************************************************************
  1380.              * Header is not in translated mode.
  1381.              ************************************************************/
  1382.             if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER))
  1383.                 {
  1384.                 /********************************************************
  1385.                  * Make sure lParam2 is correct size
  1386.                  ********************************************************/
  1387.                 if (lParam2 != MMOTION_HEADER_SIZE)
  1388.                     {
  1389.                     pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
  1390.                     return (0);
  1391.                     }
  1392.  
  1393.                 /********************************************************
  1394.                  * Ensure that the header at least begins with "YUV12C"
  1395.                  ********************************************************/
  1396.                 if (strncmp ((char *)lParam1, "YUV12C", 6))
  1397.                    {
  1398.                    pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
  1399.                    return (0);
  1400.                    }
  1401.  
  1402.                 /********************************************************
  1403.                  * Take 16 byte buffer (lParam1), write to file and .
  1404.                  *    copy to internal structure.
  1405.                  ********************************************************/
  1406.                 memcpy ((PVOID)&pVidInfo->mmotHeader,
  1407.                         (PVOID)lParam1, (ULONG) MMOTION_HEADER_SIZE);
  1408.                 ulBytesWritten = mmioWrite (pVidInfo->hmmioSS,
  1409.                                             (PVOID) lParam1,
  1410.                                             (ULONG) MMOTION_HEADER_SIZE);
  1411.  
  1412.                 /*********************************
  1413.                  * Check for an error on the write..
  1414.                  *********************************/
  1415.                 if (ulBytesWritten != MMOTION_HEADER_SIZE)
  1416.                     return (0);   /* 0 indicates error */
  1417.  
  1418.                 /*********************************
  1419.                  * Success...
  1420.                  *********************************/
  1421.                 pVidInfo->bSetHeader = TRUE;
  1422.                 return (sizeof (MMOTIONHEADER));
  1423.                 }  /* end IF NOT TRANSLATED block */
  1424.  
  1425.             /************************************************************
  1426.              * Header is translated.
  1427.              ************************************************************/
  1428.  
  1429.             /************************************************************
  1430.              * Create local pointer media specific structure.
  1431.              ************************************************************/
  1432.             pMMImgHdr = (PMMIMAGEHEADER) lParam1;
  1433.  
  1434.  
  1435.             /************************************************************
  1436.              * Check for validity of header contents supplied
  1437.              ************************************************************
  1438.              *  --  Length must be that of the standard header
  1439.              *  --  NO Compression
  1440.              *      1 plane
  1441.              *      24, 8, 4 or 1 bpp
  1442.              ************************************************************/
  1443.             usBitCount = pMMImgHdr->mmXDIBHeader.BMPInfoHeader2.cBitCount;
  1444.             if ((pMMImgHdr->mmXDIBHeader.BMPInfoHeader2.ulCompression !=
  1445.                  BCA_UNCOMP) ||
  1446.                 (pMMImgHdr->mmXDIBHeader.BMPInfoHeader2.cPlanes != 1) ||
  1447.                 (! ((usBitCount == 24) || (usBitCount == 8) ||
  1448.                     (usBitCount == 4) || (usBitCount == 1)))
  1449.                )
  1450.                 {
  1451.                 pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
  1452.                 return (0);
  1453.                 }
  1454.  
  1455.             if (lParam2 != sizeof (MMIMAGEHEADER))
  1456.                {
  1457.                pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
  1458.                return (0);
  1459.                }
  1460.  
  1461.             /************************************************************
  1462.              * Complete MMOTIONHEADER.
  1463.              ************************************************************/
  1464.             memcpy ((PVOID)&pVidInfo->mmotHeader.mmID, "YUV12C", 6);
  1465.             pVidInfo->mmotHeader.mmXorg  = 0;
  1466.             pVidInfo->mmotHeader.mmYorg  = 0;
  1467.  
  1468.             /********************************************************
  1469.              * Ensure we will save stuff on 4-pel boundaries when
  1470.              *     we actually convert to YUV and pack the bits.
  1471.              * We DON'T change what the user is actually going to
  1472.              *     give us.  HE thinks he is on 1-pel boundaries,
  1473.              *     and that is how we buffer the RGB data.
  1474.              ********************************************************/
  1475.             ulWidth  = pMMImgHdr->mmXDIBHeader.BMPInfoHeader2.cx;
  1476.             ulHeight = pMMImgHdr->mmXDIBHeader.BMPInfoHeader2.cy;
  1477.             if (ulWidth % 4)
  1478.                 ul4PelWidth = (((ulWidth >> 2) + 1) << 2);
  1479.             else
  1480.                 ul4PelWidth = ulWidth;
  1481.             pVidInfo->mmotHeader.mmXlen  = (USHORT) ul4PelWidth;
  1482.             pVidInfo->mmotHeader.mmYlen  = (USHORT) ulHeight;
  1483.  
  1484.             /************************************************************
  1485.              * Write the MMotion Header.
  1486.              ************************************************************/
  1487.             ulBytesWritten = mmioWrite (pVidInfo->hmmioSS,
  1488.                                         (PVOID) &pVidInfo->mmotHeader,
  1489.                                         (ULONG) MMOTION_HEADER_SIZE);
  1490.  
  1491.             /***************************************
  1492.              * Check for an error on the write...
  1493.              ***************************************/
  1494.             if (ulBytesWritten != MMOTION_HEADER_SIZE)
  1495.                 return (0);
  1496.  
  1497.             /************************************************************
  1498.              * Flag that MMIOM_SETHEADER has been done.  It can only
  1499.              *    be done ONCE for a file.  All future attempts will
  1500.              *    be flagged as errors.
  1501.              ************************************************************/
  1502.             pVidInfo->bSetHeader = TRUE;
  1503.  
  1504.             /************************************************************
  1505.              * Create copy of MMIMAGEHEADER for future use.
  1506.              ************************************************************/
  1507.             pVidInfo->mmImgHdr = *pMMImgHdr;
  1508.  
  1509.             /************************************************************
  1510.              * Check bitcount, set palette if less than 24.
  1511.              ************************************************************/
  1512.             if (usBitCount < 24)
  1513.                {
  1514.                /*********************************************************
  1515.                 * Find out how many colors are in the palette.
  1516.                 *********************************************************/
  1517.                usNumColors = (USHORT)(1 << usBitCount);
  1518.  
  1519.                /*********************************************************
  1520.                 * Take the RGB2 Palette and convert it to an RGB palette
  1521.                 *    Place the converted palette in MMFILESTATUS struct
  1522.                 *********************************************************/
  1523.                RGB2_To_RGB (pVidInfo->mmImgHdr.bmiColors,
  1524.                             (PRGB) &(pVidInfo->rgbPalette),
  1525.                             usNumColors);
  1526.                }
  1527.  
  1528.             /*********************************************************
  1529.              * We must allocate the buffer.  The app will load the
  1530.              * buffer on subsequent write calls
  1531.              *********************************************************/
  1532.             usPlanes = pVidInfo->mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cPlanes;
  1533.  
  1534.             /********************************************************
  1535.              * Determine total Image size
  1536.              ********************************************************
  1537.              * Find bits-per-line BEFORE padding and 1bpp or 4bpp pel overflow
  1538.              ********************************************************/
  1539.             ulImgBitsPerLine = ulWidth * usPlanes * usBitCount;
  1540.             ulImgBytesPerLine = ulImgBitsPerLine >> 3;
  1541.  
  1542.             /********************************************************
  1543.              * Account for extra pels not on an even byte boundary
  1544.              *   for 1bpp and 4bpp
  1545.              ********************************************************/
  1546.             if (ulImgBitsPerLine % 8)
  1547.                ulImgBytesPerLine ++;
  1548.  
  1549.             pVidInfo->ulImgPelBytesPerLine = ulImgBytesPerLine;
  1550.  
  1551.             /********************************************************
  1552.              * Ensure the row length in bytes accounts for byte padding.
  1553.              *   All bitmap data rows are aligned on LONG/4-BYTE boundaries.
  1554.              *   The data FROM an application should always appear in this form
  1555.              ********************************************************/
  1556.             usPadBytes = (USHORT)(ulImgBytesPerLine % 4);
  1557.             if (usPadBytes)
  1558.                ulImgBytesPerLine += 4 - usPadBytes;
  1559.  
  1560.             pVidInfo->ulImgPaddedBytesPerLine  = ulImgBytesPerLine;
  1561.             pVidInfo->ulImgTotalBytes = ulImgBytesPerLine * ulHeight;
  1562.  
  1563.             /********************************************************
  1564.              * Get space for full image buffer.
  1565.              ********************************************************/
  1566.             if (DosAllocMem ((PPVOID) &(pVidInfo->lpImgBuf),
  1567.                               pVidInfo->ulImgTotalBytes,
  1568.                               fALLOC))
  1569.                 return (MMIO_ERROR);
  1570.  
  1571.             /********************************************************
  1572.              * Set up initial pointer value within RGB buffer & image
  1573.              ********************************************************/
  1574.             pVidInfo->lImgBytePos = 0;
  1575.  
  1576.             return (sizeof (MMIMAGEHEADER));
  1577.             }  /* end case of MMIOM_SETHEADER */
  1578.  
  1579.         /*#############################################################*/
  1580.         /*#############################################################*/
  1581.         case MMIOM_WRITE:
  1582.             {
  1583.             /************************************************************
  1584.              * Declare Local Variables.
  1585.              ************************************************************/
  1586.             PMMFILESTATUS       pVidInfo;
  1587.             USHORT              usBitCount;
  1588.             LONG                lBytesWritten;
  1589.             ULONG               ulImgBytesToWrite;
  1590.  
  1591.             /************************************************************
  1592.              * Check for valid MMIOINFO block.
  1593.              ************************************************************/
  1594.             if (!pmmioinfo)
  1595.                 return (MMIO_ERROR);
  1596.  
  1597.             /************************************************************
  1598.              * Set up our working variable MMFILESTATUS.
  1599.              ************************************************************/
  1600.             pVidInfo = (PMMFILESTATUS) pmmioinfo->pExtraInfoStruct;
  1601.  
  1602.             /************************************************************
  1603.              * See if a SetHeader has been done on this file.
  1604.              ************************************************************/
  1605.             if ((!pVidInfo) || (!pVidInfo->bSetHeader))
  1606.                 {
  1607.                 return (MMIO_ERROR);
  1608.                 }
  1609.  
  1610.             if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))
  1611.                 {
  1612.                 /********************************************************
  1613.                  * Translation is off, take amount of bytes sent and
  1614.                  * write to the file.
  1615.                  ********************************************************
  1616.                  * Ensure that there is a data buffer to write from
  1617.                  ********************************************************/
  1618.                 if (!lParam1)
  1619.                     return (MMIO_ERROR);
  1620.  
  1621.                 lBytesWritten = mmioWrite (pVidInfo->hmmioSS,
  1622.                                            (PVOID) lParam1,
  1623.                                            (ULONG) lParam2);
  1624.  
  1625.                 return (lBytesWritten);
  1626.                 }
  1627.  
  1628.             /************************************************************
  1629.              ************************************************************
  1630.              * Translation is on.
  1631.              ************************************************************
  1632.              ************************************************************
  1633.              ************************************************************
  1634.              * Set up local variables
  1635.              ************************************************************/
  1636.             usBitCount =
  1637.                pVidInfo->mmImgHdr.mmXDIBHeader.BMPInfoHeader2.cBitCount;
  1638.  
  1639.  
  1640.             /************************************************************
  1641.              * Ensure we do not attempt to write past the end of the
  1642.              *    buffer...
  1643.              ************************************************************/
  1644.             if ((ULONG)(pVidInfo->lImgBytePos + lParam2) >
  1645.                pVidInfo->ulImgTotalBytes)
  1646.                ulImgBytesToWrite =
  1647.                    pVidInfo->ulImgTotalBytes - pVidInfo->lImgBytePos;
  1648.             else
  1649.                ulImgBytesToWrite = (ULONG)lParam2;
  1650.  
  1651.             /************************************************************
  1652.              * Write the data into the image buffer.  It will be converted to
  1653.              *   RGB, then YUV  when the file is closed.  This allows the
  1654.              *   application to seek to arbitrary  positions within the
  1655.              *   image in terms of the bits/pel, etc they are writing.
  1656.              ************************************************************/
  1657.             memcpy (&(pVidInfo->lpImgBuf[pVidInfo->lImgBytePos]),
  1658.                     (PVOID)lParam1,
  1659.                     ulImgBytesToWrite);
  1660.  
  1661.             /* Update current position in the image buffer */
  1662.             pVidInfo->lImgBytePos += ulImgBytesToWrite;
  1663.  
  1664.             return (ulImgBytesToWrite);
  1665.             }   /* end case of MMIOM_WRITE */
  1666.  
  1667.         /* 
  1668.          * If the IOProc has a child IOProc, then pass the message on to the Child, otherwise 
  1669.          * return Unsupported Message
  1670.          */
  1671.         default: 
  1672.             {
  1673.              /*
  1674.               * Declare Local Variables.
  1675.               */
  1676.              PMMFILESTATUS       pVidInfo;
  1677.              LONG                lRC;
  1678.  
  1679.              /************************************************************
  1680.               * Check for valid MMIOINFO block.
  1681.               ************************************************************/
  1682.              if (!pmmioinfo)
  1683.                  return (MMIO_ERROR);
  1684.  
  1685.              /************************************************************
  1686.               * Set up our working variable MMFILESTATUS.
  1687.               ************************************************************/
  1688.              pVidInfo = (PMMFILESTATUS) pmmioinfo->pExtraInfoStruct;
  1689.  
  1690.              if (pVidInfo != NULL && pVidInfo->hmmioSS)
  1691.                 {
  1692.                  lRC = mmioSendMessage (pVidInfo->hmmioSS,
  1693.                                         usMsg,
  1694.                                         lParam1,
  1695.                                         lParam2);
  1696.                  if (!lRC)
  1697.                     pmmioinfo->ulErrorRet = mmioGetLastError (pVidInfo->hmmioSS);
  1698.                  return (lRC);
  1699.                 }
  1700.             else
  1701.                {
  1702.                 if (pmmioinfo != NULL) 
  1703.                    pmmioinfo->ulErrorRet = MMIOERR_UNSUPPORTED_MESSAGE;
  1704.                 return (MMIOERR_UNSUPPORTED_MESSAGE);
  1705.                }
  1706.  
  1707.             }   /* end case of Default */
  1708.  
  1709.         } /* end SWITCH statement for MMIO messages */
  1710.  
  1711.     return (0);
  1712.     }      /* end of window procedure */
  1713.