LONG APIENTRY CONVProc( PVOID pmmioStr,
                        USHORT  usMsg,
                        LONG lParam1,
                        LONG lParam2 )

{
   PCONVPROCINFO pInfo;             // Converter I/O Procedure Info Block
   PMMIOINFO pmmioinfo;             // I/O information block
   MMIOINFO mmioinfoSS;             // I/O info block for Storage System
   PMMFORMATINFO pmmformatinfo;     // formatinfo for this ioproc.
   PCONVHEADERINFO pconvHeaderInfo; // pointer to header struct for FFT files.
   PSZ pszFileName;                 // file name passed in from caller
   PSZ pszFormatString;             // format string to return.
   PSZ pszData;
   CHAR szHeaderLength[2];          // storage for header length (USHORT)
   PCHAR pTemp;                     // temp pointer for use in Header manip.
   HFILE hFileHandle;               // file handle created or passed in
   HMMIO hmmioSS;                   // handle for Storage System
   FOURCC fccStorageSystem;         // SS I/O Proc FOURCC
   USHORT usReturnCode;             // return code from mmioClose
   ULONG ulReturnCode;              // return code from mmio API calls
   LONG lReturnCode;                // return code from mmio API calls
   LONG lBytesCopied;               // num of bytes of format string.
   LONG lBytesRead;                 // return from mmioRead
   LONG lBytesWritten;              // return from mmioWrite
   LONG lHeaderLength;              // storage for CONV header length input
   LONG lFilePosition;              // return from mmioSeek
   LONG lSavedFilePosition;         // saved LFP for the file.
   ULONG ulTempFlags;               // temp flags for flags to be removed.

   /*
    *  Initalize local file handle and Return Codes.
    */

   hFileHandle = 0L;
   ulReturnCode = 0L;
   usReturnCode = 0;

   /*
    * Clear the error return before anything happens to insure valid results.
    */

   if (pmmioStr)
      {
      pmmioinfo = (PMMIOINFO) pmmioStr;
      pInfo = (PCONVPROCINFO) &pmmioinfo->aulInfo;
      pmmioinfo->ulErrorRet = MMIO_SUCCESS;
      }
   else
      {
      pmmioinfo = NULL;
      pInfo = NULL;
      }

   /*
    *  Route the MMIO message to the proper code handler.
    */

   switch( usMsg )
      {
      case MMIOM_OPEN:

         /*
          * Get the filename from parameter. Then create a File Format header
          * in memory since this message will use this structure.
          */

         pszFileName = (CHAR *)lParam1;
         pconvHeaderInfo =
            (PCONVHEADERINFO)HhpAllocBuffer( sizeof(CONVHEADERINFO), 0);
         if (!pconvHeaderInfo)
            {
            return (MMIO_ERROR);
            }

         /*
          * If no Storage System I/O proc was determined from mmioOpen,
          * either determine the SS from the name (CREATE case) or
          * search I/O proc list for SS type. If the file is being created
          * and the storage system cannot be determined from the name,
          * default the storage system to DOS.
          */

         if (!pmmioinfo->fccChildIOProc)
            {
            /*
             * Since no Storage system has been determined from mmioOpen, we
             * need to determine the Storage system from the filename. If
             * it cannot be determined from the name, since it's a create we
             * will default the storage system to DOS.
             */

            if (pmmioinfo->ulFlags & MMIO_CREATE)
               {
               if (mmioDetermineSSIOProc( pszFileName,
                                          pmmioinfo,
                                          &fccStorageSystem,
                                          NULL ))
                  {
                  fccStorageSystem = FOURCC_DOS;
                  }
               }
            else
               {

               /*
                * The file already exists, so we need to determine the storage
                * system by looping through all the SS I/O procs until the SS
                * is determined or it is not. If it is not then this file
                * cannot be opened, so return an error.
                */

               if (mmioIdentifyStorageSystem( pszFileName,
                                              pmmioinfo,
                                              &fccStorageSystem ))
                  {
                  return (MMIO_ERROR);
                  }
               }

            /*
             * Now we either have a SS, and if so assign it to the SS I/O
             * proc field of the pmmioinfo sent in, or we don't so return.
             */

            if (!fccStorageSystem)
               {
               return (MMIO_ERROR);
               }
            else
               {
               pmmioinfo->fccChildIOProc = fccStorageSystem;
               }
            }

         /*
          * We have the Storage System FOURCC so open the SS.
          * To set up the mmioOpen call to the storage system :
          *
          *  1. Initialize the mmioinfo passed in for the Storage System.
          *  2. Set fccIOProc to the Storage System FOURCC.
          *  3. Save the hmmcf handle in aulInfo[1] if sent in.
          *  4. IMPORTANT: Use flags sent in EXCEPT Buffered I/O flags.
          *     VERY IMPORTANT: Set the NOIDENTIFY flag before calling the
          *     mmioOpen below to avoid and endless loop.
          *  5. The open call will handle the DELETE flag.
          *  6. Use the name passed in to this I/O proc for the open because
          *     at this point the SS I/O proc will know how to deal with it.
          */

         memset( &mmioinfoSS, '\0', sizeof(MMIOINFO));
         mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc;
         memmove( &mmioinfoSS.aulInfo, pmmioinfo->aulInfo,(4*sizeof(ULONG)));
         mmioinfoSS.ulFlags = pmmioinfo->ulFlags;

         ulTempFlags = (MMIO_CREATE|MMIO_READ|MMIO_WRITE|MMIO_READWRITE|
                        MMIO_COMPAT|MMIO_EXCLUSIVE|MMIO_DENYWRITE|
                        MMIO_DENYREAD|MMIO_DENYNONE|MMIO_DELETE|MMIO_VERTBAR|
                        MMIO_APPEND|MMIO_USE_TEMP|MMIO_RWMODE|MMIO_SHAREMODE|
                        MMIO_NOTRANSLATE|MMIO_TRANSLATEDATA|
                        MMIO_TRANSLATEHEADER);

         mmioinfoSS.ulFlags &= ulTempFlags;
         mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY;

         hmmioSS = mmioOpen( pszFileName, &mmioinfoSS, mmioinfoSS.ulFlags );

         if (hmmioSS)
            {
            /*
             * Handle a DELETE request for the file format by returning
             * success if ( hmmio = TRUE = 1).
             */

            if (pmmioinfo->ulFlags & MMIO_DELETE)
               {
               return (MMIO_SUCCESS);
               }
            pInfo->hmmioSS = hmmioSS;
            }
         else
            {
            return (mmioinfoSS.ulErrorRet);
            }

         /*
          * Get the header for the file if it already exists and
          * store it with the MMIOINFO for the file.
          */

         if (!(pmmioinfo->ulFlags & MMIO_CREATE))
            {
            /*
             * Seek the file to the beginning to read in the header.
             */

            lFilePosition = mmioSeek( hmmioSS,
                                      0L,
                                      SEEK_SET );

            if (lFilePosition < 0L)
               {
               mmioClose( hmmioSS, 0L );
               return (MMIO_ERROR);
               }

            /*
             * Read the header of the file into the provided buffer for the
             * given length.
             */

            lBytesRead = mmioRead( hmmioSS,
                                   (PSZ)pconvHeaderInfo,
                                   sizeof(CONVHEADERINFO) );

            if (lBytesRead < 0L)
               {
               mmioClose( hmmioSS, 0L );
               return (MMIO_ERROR);
               }
            }
         else
            {
            /*
             * Make a new header for the file and write it to the beginning.
             */

            pconvHeaderInfo->ulHeaderLength = sizeof(CONVHEADERINFO);
            strcpy( pconvHeaderInfo->szHeaderText, HEADER_STRING );

            lFilePosition = mmioSeek( hmmioSS,
                                      0L,
                                      SEEK_SET );

            if (lFilePosition < 0L)
               {
               mmioClose( hmmioSS, 0L );
               return (MMIO_ERROR);
               }

            /*
             * Write the newly created header to the file.
             */

            lBytesWritten = mmioWrite( hmmioSS,
                                       (PSZ)pconvHeaderInfo,
                                       sizeof(CONVHEADERINFO) );

            if (lBytesWritten < 0L)
               {
               mmioClose( hmmioSS, 0L );
               return (MMIO_ERROR);
               }
            }

         pconvHeaderInfo->ulFlags = 0;
         pmmioinfo->pExtraInfoStruct = (PVOID)pconvHeaderInfo;

         /*
          * Seek the file past the header to allow reads/writes to occur
          * at the first byte of non-header data if the file already exists.
          */

         lReturnCode = mmioSeek( hmmioSS,
                                 sizeof(CONVHEADERINFO),
                                 SEEK_SET );

         if (lReturnCode >= 0L)
            {
            pmmioinfo->lLogicalFilePos = lReturnCode;
            }
         else
            {
            mmioClose( hmmioSS, 0L );
            return (lReturnCode);
            }

         return (0L);

         break;

      case MMIOM_READ:
         /*
          * Call the read API with the Storage System handle using the
          * parameters that have been passed in to this I/O proc.
          */

         lBytesRead = mmioRead( pInfo->hmmioSS,
                                (CHAR *) lParam1,
                                lParam2 );

         /*
          *  Check the return code and determine if read was successful.
          *  Read must return:
          *    -1 - an error occurred with mmioRead or somewhere internally.
          *     x - number of bytes actually read by mmioRead.
          */

         if ( lBytesRead < 0L )
            {
            return( -1L );
            }
         else
            {
            return( lBytesRead );
            }

         break;

      case MMIOM_WRITE:
         /*
          * Call the write API with the Storage System handle using the
          * parameters that have been passed in to this I/O proc.
          */

         lBytesWritten = mmioWrite( pInfo->hmmioSS,
                                    (CHAR *) lParam1,
                                    lParam2 );

         /*
          *  Check the return code and determine if write was successful.
          *  Write must return:
          *    -1 - an error occurred with mmioWrite or somewhere internally.
          *     x - number of bytes actually written by mmioWrite.
          */

         if ( lBytesWritten < 0L )
            {
            return( -1L );
            }
         else if ( lBytesWritten != lParam2 )
            {
            pmmioinfo->ulErrorRet = MMIOERR_CANNOTWRITE;
            return( lBytesWritten );
            }
         else
            {

            /*
             * Set the Flags field in the CONV header to show it was modified.
             */

            pconvHeaderInfo = (PCONVHEADERINFO)pmmioinfo->pExtraInfoStruct;

            if (pconvHeaderInfo)
               pconvHeaderInfo->ulFlags = CONV_MODIFIED_FILE;

            return( lBytesWritten );
            }

         break;

      case MMIOM_SEEK:
         /*
          * Call the seek API with the Storage System handle using the
          * parameters that have been passed in to this I/O proc.
          */

         lReturnCode = mmioSeek( pInfo->hmmioSS,
                                 lParam1,
                                 lParam2 );

         /*
          *  Check the return code and determine if seek was successful.
          *  Seek must return:
          *    -1 - an error occurred with mmioSeek or somewhere internally.
          *     x - new current file postion from the beginning of the file.
          */

         if ( lReturnCode < 0L )
            {
            return( -1L );
            }

         return( lReturnCode );

         break;

      case MMIOM_CLOSE:
            /*
             * If the CONV header structure was maintained in pExtraInfoStruct,
             * write it back to the beginning of the file.
             */

            if (((pmmioinfo->ulFlags & MMIO_WRITE) ||
                 (pmmioinfo->ulFlags & MMIO_READWRITE)) &&
                 (pmmioinfo->pExtraInfoStruct))

               {
               pconvHeaderInfo = (PCONVHEADERINFO)pmmioinfo->pExtraInfoStruct;

               lReturnCode = mmioSeek( pInfo->hmmioSS,
                                       0L,
                                       SEEK_SET );

               if (lReturnCode < 0L)
                  {
                  return (lReturnCode);
                  }

               ulReturnCode = mmioSetHeader( pmmioinfo->hmmio,
                                             (PVOID)pmmioinfo->pExtraInfoStruct,
                                             sizeof(CONVHEADERINFO),
                                             &lBytesWritten,
                                             0L, 0L );
               if (ulReturnCode)
                  {
                  return (ulReturnCode);
                  }
               }

            if (pmmioinfo->pExtraInfoStruct)
               HhpFreeBuffer((PBYTE)pmmioinfo->pExtraInfoStruct);

            /*
             * Call the close API with the Storage System handle using any
             * parameters that have been passed in to this I/O proc.
             */

            usReturnCode = mmioClose( pInfo->hmmioSS, 0L );
            return ((ULONG)usReturnCode);

         break;

      case MMIOM_IDENTIFYFILE:
         /*
          * Get the filename from parameter. Then create a File Format header
          * in memory since this message use this structure.
          */

         pszFileName = (CHAR *)lParam1;  // get the filename from parameter.

         pconvHeaderInfo =
            (PCONVHEADERINFO)HhpAllocBuffer( sizeof(CONVHEADERINFO), 0);

         if (!pconvHeaderInfo)
            {
            return (MMIO_ERROR);
            }

         hmmioSS = (HMMIO)lParam2;       // get the SS handle to the file.

         if ( !hmmioSS )
            {
            HhpFreeBuffer((PBYTE)pconvHeaderInfo);
            return (MMIO_ERROR);
            }
         else
            {

            /*
             * Seek the file to the beginning to read in the file header.
             */

            lFilePosition = mmioSeek( hmmioSS,
                                      0L,
                                      SEEK_SET );

            if (lFilePosition < 0L)
               {
               HhpFreeBuffer((PBYTE)pconvHeaderInfo);
               return (MMIO_ERROR);
               }

            /*
             * Compare convHeaderInfo.szHeaderText with text string defined
             * in the convproc.h header file.
             */

            lBytesRead = mmioRead( hmmioSS,
                                   (PSZ)pconvHeaderInfo,
                                   sizeof(CONVHEADERINFO) );

            if ( lBytesRead <= 0L )
               {
               HhpFreeBuffer((PBYTE)pconvHeaderInfo);
               return( -1L );
               }

            pTemp = (CHAR *)pconvHeaderInfo;
            pTemp += 2 * sizeof(ULONG);

            if (!strncmp( pTemp, HEADER_STRING, strlen(HEADER_STRING) ))
               {
               HhpFreeBuffer((PBYTE)pconvHeaderInfo);
               return( 0L );
               }
            else
               {
               HhpFreeBuffer((PBYTE)pconvHeaderInfo);
               return( -1L );
               }
            }

         break;

      case MMIOM_GETFORMATINFO:

         /*
          * Fill in the mmformatinfo for the CONVProc.
          */

         pmmformatinfo = (PMMFORMATINFO)lParam1;

         if (pmmformatinfo == NULL)
            {
            return( -1L );
            }

         pmmformatinfo->ulStructLen = sizeof(MMFORMATINFO);
         pmmformatinfo->fccIOProc = FOURCC_FFT;
         pmmformatinfo->ulIOProcType = MMIO_IOPROC_FILEFORMAT;
         pmmformatinfo->ulMediaType = MMIO_MEDIATYPE_OTHER;
         pmmformatinfo->ulFlags = MMIO_CANREADUNTRANSLATED      |
                                  MMIO_CANWRITEUNTRANSLATED     |
                                  MMIO_CANREADWRITEUNTRANSLATED |
                                  MMIO_CANSEEKUNTRANSLATED;

         memset( pmmformatinfo->szDefaultFormatExt,  '\0',
            sizeof(pmmformatinfo->szDefaultFormatExt)  );
         strcpy( pmmformatinfo->szDefaultFormatExt,  "FFT" );

         if (convhlpGetNLSData( &pmmformatinfo->ulCodePage,
                                &pmmformatinfo->ulLanguage ))
            {
            return( -1L );
            }

         if (convhlpGetFormatStringLength( FOURCC_FFT,
                                           &(pmmformatinfo->lNameLength) ))
            {
            return( -1L );
            }

         return( 0L );
         break;

      case MMIOM_GETFORMATNAME:

         /*
          * The string is in a resource file (CONVPROC.RC) for NLS purposes.
          */

         pszFormatString = (CHAR *)lParam1;

         lBytesCopied = convhlpGetFormatString( FOURCC_FFT,
                                                pszFormatString,
                                                lParam2 );

         return( lBytesCopied );
         break;

      case MMIOM_QUERYHEADERLENGTH:

         /*
          * Save current file position for later restore. Then
          * seek the file to the beginning to read in the header.
          */

         lSavedFilePosition = pmmioinfo->lLogicalFilePos;

         lFilePosition = mmioSeek( pInfo->hmmioSS,
                                   0L,
                                   SEEK_SET );

         if (lFilePosition < 0L)
            {
            return (0L);
            }

         /*
          * Read in the header length for the file. It is the first 4 bytes.
          */

         lBytesRead = mmioRead( pInfo->hmmioSS,
                                szHeaderLength,
                                sizeof(ULONG) );

         lReturnCode = mmioSeek( pInfo->hmmioSS,
                                 lSavedFilePosition,
                                 SEEK_SET );

         if (lReturnCode != lSavedFilePosition)
            {
            return (0L);
            }

         if (lBytesRead <= 0L)
            {
            return (0L);
            }
         else
            {
            lHeaderLength = (LONG)(*((LONG *)szHeaderLength));
            return (lHeaderLength);
            }

         break;

      case MMIOM_GETHEADER:

         /*
          * Save current file position for later restore. Then
          * seek the file to the beginning to read in the header.
          */

         lSavedFilePosition = pmmioinfo->lLogicalFilePos;

         lFilePosition = mmioSeek( pInfo->hmmioSS,
                                   0L,
                                   SEEK_SET );

         if (lFilePosition < 0L)
            {
            return (0L);
            }

         /*
          * Read the header of the file into the provided buffer for the
          * given length. Then seek the file back to the saved position.
          */

         lBytesRead = mmioRead( pInfo->hmmioSS,
                                (CHAR *)lParam1,
                                lParam2 );

         lReturnCode = mmioSeek( pInfo->hmmioSS,
                                 lSavedFilePosition,
                                 SEEK_SET );

         if (lReturnCode != lSavedFilePosition)
            {
            return (0L);
            }

         if (lBytesRead <= 0L)
            {
            return (0L);
            }
         else
            {
            return (lBytesRead);
            }

         break;

      case MMIOM_SETHEADER:

         /*
          * Save current file position for later restore. Then
          * seek the file to the beginning to read in the header.
          */

         lSavedFilePosition = pmmioinfo->lLogicalFilePos;

         lFilePosition = mmioSeek( pInfo->hmmioSS,
                                   0L,
                                   SEEK_SET );

         if (lFilePosition < 0L)
            {
            return (0L);
            }

         /*
          * Write the entire header to the file. Then seek the file back
          * to the saved file position.
          */

         lBytesWritten = mmioWrite( pInfo->hmmioSS,
                                    (CHAR *)lParam1,
                                    lParam2 );

         lReturnCode = mmioSeek( pInfo->hmmioSS,
                                 lSavedFilePosition,
                                 SEEK_SET );

         if (lReturnCode != lSavedFilePosition)
            {
            return (0L);
            }

         if (lBytesWritten <= 0L)
            {
            return (0L);
            }
         else
            {
            return (lBytesWritten);
            }

         break;

      case CONVM_TOUPPER:

         pszData = (CHAR *)lParam1;
         convhlpToUpper( (PUCHAR)pszData );
         return (MMIO_SUCCESS);

         break;

      case CONVM_TOLOWER:

         pszData = (CHAR *)lParam1;
         convhlpToLower( (PUCHAR)pszData );
         return (MMIO_SUCCESS);

         break;

      default:

         /*
          * If an IO Proc has a child IO Proc, then instead of
          * returning UNSUPPORTED_MESSAGE, send the message to
          * the child IO Proc to see if it can understand and
          * process the message.
          *
          * Since message is unexpected, need to check for valid
          * pointers.
          */

         if (pInfo)
            {
            if (pInfo->hmmioSS)
               {
               lReturnCode = ( mmioSendMessage( pInfo->hmmioSS,
                                                usMsg,
                                                lParam1,
                                                lParam2 ));
           
               if (!lReturnCode)
                   pmmioinfo->ulErrorRet = mmioGetLastError(pInfo->hmmioSS);
               return (lReturnCode);
               }
            }
          else
            {
            if (pmmioinfo)
                pmmioinfo->ulErrorRet = MMIOERR_UNSUPPORTED_MESSAGE;
            }

          return (MMIOERR_UNSUPPORTED_MESSAGE);

      }

}
Exemplo n.º 2
0
static LONG APIENTRY IOProc_Entry2(PVOID pmmioStr, USHORT usMsg, LONG lParam1,
                     LONG lParam2) {
	PMMIOINFO pmmioinfo = (PMMIOINFO)pmmioStr;
	switch (usMsg) {
	case MMIOM_OPEN:
		{	
     		HMMIO hmmioSS;
     		MMIOINFO mmioinfoSS;
	    	PSZ pszFileName = (char *)lParam1;
   	 		if (!pmmioinfo) return MMIO_ERROR;
  	  		if ((pmmioinfo->ulFlags & MMIO_READWRITE)) {
#ifdef DEBUG
			fprintf(file,"ReadWrite - requested.\n");
#endif
   	  		   return MMIO_ERROR;
  	  		}
			if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) &&
			    !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) return MMIO_ERROR;
			if (!pmmioinfo->fccChildIOProc) {
				FOURCC fccFileStorageSystem;
				if (pmmioinfo->ulFlags & MMIO_CREATE) {
       				if (mmioDetermineSSIOProc(pszFileName, pmmioinfo, &fccFileStorageSystem, NULL)) {
              			fccFileStorageSystem = FOURCC_DOS;
              		}
       			} else {
	        		if (mmioIdentifyStorageSystem(pszFileName, pmmioinfo, &fccFileStorageSystem)) {
 		           		return MMIO_ERROR;
    	        	}
    	        }
            	if (!fccFileStorageSystem) {
             	  	return MMIO_ERROR;
            	} else {
             	  	pmmioinfo->fccChildIOProc = fccFileStorageSystem;
            	} /* endif */
			}
			memmove(&mmioinfoSS, pmmioinfo, sizeof(MMIOINFO));
			mmioinfoSS.pIOProc = NULL;
			mmioinfoSS.fccIOProc = pmmioinfo->fccChildIOProc;
			mmioinfoSS.ulFlags |= MMIO_NOIDENTIFY;
			
			hmmioSS = mmioOpen (pszFileName, &mmioinfoSS, mmioinfoSS.ulFlags);
			if (pmmioinfo->ulFlags & MMIO_DELETE) {
      			if (!hmmioSS) {
            		pmmioinfo->ulErrorRet = MMIOERR_DELETE_FAILED;
            		return MMIO_ERROR;
            	}
            	else return MMIO_SUCCESS;
			}
   			if (!hmmioSS) return MMIO_ERROR;
   			if (pmmioinfo->ulFlags & MMIO_READ) {
 			   DecInfo *decInfo = (DecInfo *)malloc(sizeof(DecInfo));
#ifdef DEBUG
			fprintf(file,"File Read: %s\n",pszFileName);
#endif
        		if (!decInfo) {
  	          		mmioClose(hmmioSS, 0);
            		return MMIO_ERROR;
	            }
				decInfo->t = READNUM;
			    decInfo->vorbisOptions = pmmioinfo->pExtraInfoStruct;
 	      		pmmioinfo->pExtraInfoStruct = (PVOID)decInfo;
  	     		{
            		ov_callbacks cb;
   	         		cb.read_func = mread;
            		cb.seek_func = mseek;
            		cb.close_func = mclose;
            		cb.tell_func = mtell;
	       			if(0 != ov_open_callbacks((void *)hmmioSS, &decInfo->oggfile, 0, 0, cb)) {
           	  			free(decInfo);
	            		mmioClose(hmmioSS, 0);
 	           			return MMIO_ERROR;
             		}
            	}
#ifdef DEBUG
				fprintf(file,"Open successfull\n");
#endif
				return MMIO_SUCCESS;
			} else if (pmmioinfo->ulFlags & MMIO_WRITE) {
	       		EncInfo *encInfo = (EncInfo *)malloc(sizeof(EncInfo));
#ifdef DEBUG
			fprintf(file,"File Write: %s\n",pszFileName);
#endif
	       		if (!encInfo) {
  	          		mmioClose(hmmioSS, 0);
            		return MMIO_ERROR;
                }
	       		memset(encInfo, 0, sizeof(EncInfo));
	       		encInfo->t = WRITENUM;
	       		encInfo->hmmioSS = hmmioSS;
				encInfo->vorbisOptions = (PVORBISOPTIONS)pmmioinfo->pExtraInfoStruct;
 	      		pmmioinfo->pExtraInfoStruct = (PVOID)encInfo;
 	      		return MMIO_SUCCESS;
      		}
#ifdef DEBUG
			fprintf(file,"File not read nor write: %s\n",pszFileName);
#endif
      		return MMIO_ERROR;
		}
	    break;                                                 
	case MMIOM_READ: {
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct || !lParam1) return MMIO_ERROR;
		
		if (!pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) {
     		return MMIO_ERROR;
//     		return mmioRead (ogginfo->hmmioSS, (PVOID) lParam1, (ULONG) lParam2);
     	} else {
			OggVorbis_File *oggfile;
			long rc = 0;
			int current_section;
			long total = 0;
			
			oggfile = &((DecInfo *)pmmioinfo->pExtraInfoStruct)->oggfile;
			if (READNUM != ((DecInfo *)pmmioinfo->pExtraInfoStruct)->t) return MMIO_ERROR;
			while (lParam2 > 0) {
	         	rc = ov_read(oggfile, (char *)lParam1, (int)lParam2, 0, 2, 1,  &current_section);
	         	if (rc < 0) {
#ifdef DEBUG
fprintf(file, "Read failed once\n");
#endif
				continue;
				}
				if (rc <= 0) break;
				lParam2 -= rc;
				lParam1 += rc;
				total += rc;
			}
#ifdef DEBUG
fprintf(file,"Read rc:%ld total:%ld\n",rc,total);
#endif
         	if (rc < 0) return MMIO_ERROR;
         	return total;
        }
   	}
	break;
	case MMIOM_SEEK: {
        LONG lPosDesired;
		OggVorbis_File *oggfile;
    	vorbis_info *vi;
		
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return MMIO_ERROR;
		if (!pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA) return MMIO_ERROR;    	
		
		oggfile = &((DecInfo *)pmmioinfo->pExtraInfoStruct)->oggfile;
		if (READNUM != ((DecInfo *)pmmioinfo->pExtraInfoStruct)->t) return MMIO_ERROR;
		vi = ov_info(oggfile, -1);
		if (!vi) return MMIO_ERROR;
	
		if (SEEK_SET == lParam2) {
     		lPosDesired = lParam1/(2*vi->channels);
        } else if (SEEK_CUR == lParam2) {
            if (0 == lParam1) {
               return ov_pcm_tell(oggfile)*2*vi->channels;
            } /* endif */
           	lPosDesired = ov_pcm_tell(oggfile) + lParam1/(2*vi->channels);
        } else if (SEEK_END == lParam2) {
           	lPosDesired = ov_pcm_total(oggfile,-1) + lParam1/(2*vi->channels);
        } else {
           return MMIO_ERROR;
        }
#ifdef DEBUG
fprintf(file,"Seek to %ld by %d\n",lPosDesired, lParam2);
#endif
		if (ov_pcm_seek(oggfile, lPosDesired) < 0) return MMIO_ERROR;

    	return lPosDesired*2*vi->channels;
	}
    break;

	case MMIOM_CLOSE: {
		int rc;
#ifdef DEBUG
       	    fprintf(file,"start CLOSE\n");
#endif		
		if (!pmmioinfo) return MMIO_ERROR;
		
		if (pmmioinfo->pExtraInfoStruct) {
     		DecInfo *decInfo = (DecInfo *)pmmioinfo->pExtraInfoStruct;
#ifdef DEBUG
       	    fprintf(file,"ready CLOSE\n");
#endif		
			if (READNUM == decInfo->t) {
#ifdef DEBUG
       	    fprintf(file,"read CLOSE\n");
#endif		
     			ov_clear(&decInfo->oggfile);
     			free(decInfo);
     			decInfo = 0;
                rc=MMIO_SUCCESS;
     		} else if (WRITENUM == decInfo->t) {
   	           EncInfo *encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct;
#ifdef DEBUG
       	    fprintf(file,"write CLOSE\n");
#endif		
			   if (encInfo->headerSet) {
	               vorbis_analysis_wrote(&encInfo->vd,0);
 	               rc = oggWrite(encInfo,1);
	               ogg_stream_clear(&encInfo->os);
	               vorbis_block_clear(&encInfo->vb);
	               vorbis_dsp_clear(&encInfo->vd);
 	               vorbis_comment_clear(&encInfo->vc);
	               vorbis_info_clear(&encInfo->vi);
               }
   	           mmioClose(encInfo->hmmioSS, 0);
  	           free(encInfo);
 	           encInfo = 0;
               rc = MMIO_SUCCESS;
	        } else rc = MMIO_ERROR;
     		pmmioinfo->pExtraInfoStruct = 0;
#ifdef DEBUG
       	    fprintf(file,"CLOSE\n");
#endif		
			return rc;
        }
     	return MMIO_ERROR;
    }
    break;
	case MMIOM_IDENTIFYFILE: {
    	unsigned char buf[4];
		HMMIO hmmioTemp;
		ULONG ulTempFlags = MMIO_READ | MMIO_DENYWRITE | MMIO_NOIDENTIFY;
		LONG rc = MMIO_ERROR;

		if (!lParam1 && !lParam2) return MMIO_ERROR;
    	hmmioTemp = (HMMIO)lParam2;
    	if (!hmmioTemp) {
        	hmmioTemp = mmioOpen((PSZ)lParam1, NULL, ulTempFlags);
        }

		if (hmmioTemp) {
			rc = mmioRead(hmmioTemp, buf, 4);
			if (rc == 4 && buf[0] == 'O' && buf[1] == 'g' &&
					buf[2] == 'g' && buf[3] == 'S') {
				rc = MMIO_SUCCESS;
          	}
			if (!lParam2) mmioClose(hmmioTemp, 0);
		}
		return rc;
	}
    break;
	case MMIOM_GETFORMATINFO: {
    	PMMFORMATINFO pmmformatinfo;
    	pmmformatinfo = (PMMFORMATINFO)lParam1;
    	pmmformatinfo->ulStructLen = sizeof(MMFORMATINFO);
    	pmmformatinfo->fccIOProc = FOURCC_Vorbis;
    	pmmformatinfo->ulIOProcType = MMIO_IOPROC_FILEFORMAT;
    	pmmformatinfo->ulMediaType = MMIO_MEDIATYPE_AUDIO;
    	pmmformatinfo->ulFlags = MMIO_CANREADTRANSLATED 
    	   | MMIO_CANWRITETRANSLATED
           | MMIO_CANSEEKTRANSLATED;
    	strcpy(pmmformatinfo->szDefaultFormatExt, "OGG");
    	pmmformatinfo->ulCodePage = 0;
    	pmmformatinfo->ulLanguage = 0;
    	pmmformatinfo->lNameLength = 21;
    	return MMIO_SUCCESS;
    }
    break;
	case MMIOM_GETFORMATNAME:
		if (lParam2 > 21) { 
     		strcpy((PSZ)lParam1, "Ogg Vorbis");
     		return MMIO_SUCCESS;
     	} else return MMIO_ERROR;
    break;
    case MMIOM_QUERYHEADERLENGTH: return (sizeof (MMAUDIOHEADER));
    break;
	case MMIOM_GETHEADER: {
		OggVorbis_File *oggfile;
		DecInfo *decInfo;
    	PMMAUDIOHEADER mmaudioheader;
    	vorbis_info *vi;
    	
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return 0;
		if (!(pmmioinfo->ulFlags & MMIO_READ)) return 0;
		decInfo = (DecInfo *)pmmioinfo->pExtraInfoStruct;
		oggfile = &decInfo->oggfile;
		if (READNUM != decInfo->t){
            pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
            return 0;
        }
		
#ifdef DEBUG
		fprintf(file,"HERE\n");
#endif
		if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) &&
		    !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) return 0;
		mmaudioheader = (MMAUDIOHEADER *)lParam1;
		if (sizeof(MMAUDIOHEADER) > lParam2) {
            pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
			return 0;
		}

#ifdef DEBUG
		fprintf(file,"THERE\n");
#endif

		vi = ov_info(oggfile, -1);
		if (!vi) {
            pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
            return 0;
        }

		mmaudioheader->ulContentType = MMIO_MIDI_UNKNOWN;
		mmaudioheader->ulMediaType = MMIO_MEDIATYPE_AUDIO;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usFormatTag=DATATYPE_WAVEFORM;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels = vi->channels;
		mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec = vi->rate;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample = 16;
		mmaudioheader->mmXWAVHeader.WAVEHeader.ulAvgBytesPerSec=
			mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels * 
			mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec *
			mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8;
		mmaudioheader->mmXWAVHeader.WAVEHeader.usBlockAlign=
			mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels * 
			mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample / 8;
		mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS=
			(unsigned long)(ov_time_total(oggfile, -1)*1000.0);
		mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes=
		    (unsigned long)ov_pcm_total(oggfile, -1)*
		    mmaudioheader->mmXWAVHeader.WAVEHeader.usBlockAlign;

#ifdef DEBUG
		fprintf(file,"time: %ld size: %ld rate: %ld\n",
			mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInMS,
			mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.ulAudioLengthInBytes,
			mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec);
	
#endif
		if (0 != decInfo->vorbisOptions && VORBIS_COOKIE == decInfo->vorbisOptions->cookie) {
			decInfo->vorbisOptions->nominal_bitrate = ov_bitrate(oggfile, -1);
			mmaudioheader->mmXWAVHeader.XWAVHeaderInfo.pAdditionalInformation = decInfo->vorbisOptions;
        }
		return (sizeof (MMAUDIOHEADER));
    }
    break;

	case MMIOM_SETHEADER: {
    	EncInfo *encInfo;
    	PMMAUDIOHEADER mmaudioheader;
        int totalout = 0;
        int rc;

		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return 0;
		encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct;
		if (WRITENUM != encInfo->t) return 0;
#ifdef DEBUG
fprintf(file,"write header: %x, %x, %x\n",!(pmmioinfo->ulFlags & MMIO_WRITE),
	encInfo->headerSet, (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && 
		        !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)));
fprintf(file,"flag: %x, trans: %x\n",pmmioinfo->ulFlags,pmmioinfo->ulTranslate);
#endif
		if (/*!(pmmioinfo->ulFlags & MMIO_WRITE) ||*/ encInfo->headerSet
		    || (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEHEADER) && 
		        !(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA))) return 0;
		if (!lParam1) {
     		pmmioinfo->ulErrorRet = MMIOERR_INVALID_STRUCTURE;
     		return 0;
     	}
     	mmaudioheader = (PMMAUDIOHEADER)lParam1;
     	if (lParam2 != sizeof(MMAUDIOHEADER)) {
         	pmmioinfo->ulErrorRet = MMIOERR_INVALID_BUFFER_LENGTH;
         	return 0;
        }
		  /********** Encode setup ************/
	if (0 != mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample%8) {
      /* Bit-rate must be multiple of 8 */
      return 0;
    }
	encInfo->bitsPerSample=mmaudioheader->mmXWAVHeader.WAVEHeader.usBitsPerSample;
#ifdef DEBUG
fprintf(file,"ready to write header: ");
#endif
    vorbis_info_init(&encInfo->vi);
	if (0 == encInfo->vorbisOptions || VORBIS_COOKIE != encInfo->vorbisOptions->cookie) {
#ifdef DEBUG
fprintf(file,"default quality 0.3\n");
#endif
	    rc = vorbis_encode_init_vbr(&encInfo->vi,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec, 0.3);
    } else {
#ifdef DEBUG
fprintf(file,"bitsPerSample: %d channels: %d samplesPerSec: %ld min: %ld nominal: %ld max: %ld\n",
	encInfo->bitsPerSample,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec,
	  	encInfo->vorbisOptions->max_bitrate,
	  	encInfo->vorbisOptions->nominal_bitrate,
	  	encInfo->vorbisOptions->min_bitrate);
#endif
	    rc = vorbis_encode_init(&encInfo->vi,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.usChannels,
	  	mmaudioheader->mmXWAVHeader.WAVEHeader.ulSamplesPerSec,
	  	encInfo->vorbisOptions->max_bitrate,
	  	encInfo->vorbisOptions->nominal_bitrate,
	  	encInfo->vorbisOptions->min_bitrate);
    }

    if (rc) {
#ifdef DEBUG
fprintf(file,"encodeInit failed: %d\n",rc);
#endif
       return 0;
    } /* endif */

  /* add a comment */
  vorbis_comment_init(&encInfo->vc);
  vorbis_comment_add_tag(&encInfo->vc,"ENCODER","mmioVorbis");

  /* set up the analysis state and auxiliary encoding storage */
  vorbis_analysis_init(&encInfo->vd,&encInfo->vi);
  vorbis_block_init(&encInfo->vd,&encInfo->vb);

  /* set up our packet->stream encoder */
  /* pick a random serial number; that way we can more likely build
     chained streams just by concatenation */
  srand(time(NULL));
  ogg_stream_init(&encInfo->os,rand());

  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout(&encInfo->vd,&encInfo->vc,&header,&header_comm,&header_code);
    ogg_stream_packetin(&encInfo->os,&header); /* automatically placed in its own
					 page */
    ogg_stream_packetin(&encInfo->os,&header_comm);
    ogg_stream_packetin(&encInfo->os,&header_code);
	while(1){
		int result=ogg_stream_flush(&encInfo->os,&encInfo->og);
		if(result==0)break;
		result = mmioWrite(encInfo->hmmioSS, encInfo->og.header,encInfo->og.header_len);
        totalout += result;
		if (result!=encInfo->og.header_len) {
	               ogg_stream_clear(&encInfo->os);
	               vorbis_block_clear(&encInfo->vb);
	               vorbis_dsp_clear(&encInfo->vd);
 	               vorbis_comment_clear(&encInfo->vc);
	               vorbis_info_clear(&encInfo->vi);
			return 0;
        }
		result = mmioWrite(encInfo->hmmioSS, encInfo->og.body,encInfo->og.body_len);
        totalout += result;
		if (result!=encInfo->og.body_len) {
	               ogg_stream_clear(&encInfo->os);
	               vorbis_block_clear(&encInfo->vb);
	               vorbis_dsp_clear(&encInfo->vd);
 	               vorbis_comment_clear(&encInfo->vc);
	               vorbis_info_clear(&encInfo->vi);
			return 0;
		}
	}
  }
  		encInfo->headerSet = 1;
  		return totalout;
    }
    break;
	case MMIOM_WRITE: {
    	EncInfo *encInfo;
		if (!pmmioinfo || !pmmioinfo->pExtraInfoStruct) return MMIO_ERROR;
		encInfo = (EncInfo*)pmmioinfo->pExtraInfoStruct;
		if (WRITENUM != encInfo->t) return MMIO_ERROR;
		if (!encInfo->headerSet) return MMIO_ERROR;
		if (!(pmmioinfo->ulTranslate & MMIO_TRANSLATEDATA)) {
     		if (!lParam1) return MMIO_ERROR;
     		return mmioWrite(encInfo->hmmioSS, (PVOID)lParam1, lParam2);
     	} else {
            if (lParam2 == 0) {
                vorbis_analysis_wrote(&encInfo->vd,0);
            } else {
                long i;
				int j, k;
                int num;
				float denom = 1;
                signed char *readbuffer = (char *)lParam1;
                /* data to encode */
                /* expose the buffer to submit data */
				int sampleSize = encInfo->vi.channels*encInfo->bitsPerSample/8;
				int samples = lParam2/sampleSize;
	            float **buffer=vorbis_analysis_buffer(&encInfo->vd, samples);
#ifdef DEBUG
fprintf(file,"write: %ld\n",lParam2);
#endif

  	            /* :TODO: Work with buffers not a multiple of sampleSize*/
                if (lParam2 % sampleSize != 0) {
#ifdef DEBUG
fprintf(file,"Bad Write Buffer Size\n");
#endif
                    return MMIO_ERROR;
                }
                for(i=0;i<samples;i++){
                   for (j=0;j<encInfo->vi.channels;j++) {
                    num=0; denom=0.5;
					if (encInfo->bitsPerSample<=8) {
        				buffer[j][i]=(float)((unsigned char)(readbuffer[i*sampleSize])-
							(1<<(encInfo->bitsPerSample-1)))/
							(float)(1<<(encInfo->bitsPerSample-1));
					} else {
						for (k=encInfo->bitsPerSample/8;k>0;k--) {
							if (k==encInfo->bitsPerSample/8) {
								num=(readbuffer[i*sampleSize+k-1]);
							} else {
								num=(num<<8)|((0xff)&(int)(readbuffer[i*sampleSize+k-1]));
    		    			}
							denom *= 256.0;
						}
 	                   buffer[j][i]=((float)num)/denom;
					}
                   } /* endfor */
                }
                vorbis_analysis_wrote(&encInfo->vd,i);
            } /* endif */
            if (oggWrite(encInfo,0)>=0) {
                return lParam2;
            } else {
                return MMIO_ERROR;
            } /* endif */
        }
    }
    break;
#ifdef DEBUG
	case MMIOM_TEMPCHANGE: {
        return MMIO_SUCCESS;
    }
    break;
#endif
	}
#ifdef DEBUG	
	fprintf(file,"unexpected command: %x\n",usMsg);
#endif
	return MMIOERR_UNSUPPORTED_MESSAGE;
}