riff.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:24k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: RCSL 1.0/RPSL 1.0
  3.  *
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
  5.  *
  6.  * The contents of this file, and the files included with this file, are
  7.  * subject to the current version of the RealNetworks Public Source License
  8.  * Version 1.0 (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the RealNetworks Community Source License Version 1.0
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
  12.  * in which case the RCSL will apply. You may also obtain the license terms
  13.  * directly from RealNetworks.  You may not use this file except in
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or
  16.  * RCSL for the rights, obligations and limitations governing use of the
  17.  * contents of the file.
  18.  *
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the
  20.  * developer of the Original Code and owns the copyrights in the portions
  21.  * it created.
  22.  *
  23.  * This file, and the files included with this file, is distributed and made
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  28.  *
  29.  * Technology Compatibility Kit Test Suite(s) Location:
  30.  *    http://www.helixcommunity.org/content/tck
  31.  *
  32.  * Contributor(s):
  33.  *
  34.  * ***** END LICENSE BLOCK ***** */
  35. #include "hlxclib/string.h"
  36. #include "hxtypes.h"
  37. #include "hxcom.h"
  38. #include "hxmarsh.h"
  39. #include "ihxpckts.h"
  40. #include "hxfiles.h"
  41. #include "riff.h"
  42. #include "riffres.h"
  43. #include "hxassert.h"
  44. #include "hxcomm.h"
  45. #include "hxheap.h"
  46. #ifdef _DEBUG
  47. #undef HX_THIS_FILE
  48. static const char HX_THIS_FILE[] = __FILE__;
  49. #endif
  50. #define LIST_CHUNK_ID 0x4c495354    /* 'LIST' */
  51. #define IFF_FILE_MAGIC_NUMBER 0x464f524d  /* 'FORM' */
  52. STDMETHODIMP CRIFFReader::QueryInterface(REFIID riid, void** ppvObj)
  53. {
  54.     QInterfaceList  qiList[] =
  55.     {
  56. { GET_IIDHANDLE(IID_IUnknown), this},
  57. { GET_IIDHANDLE(IID_IHXFileResponse), (IHXFileResponse*)this},
  58. { GET_IIDHANDLE(IID_IHXThreadSafeMethods), (IHXThreadSafeMethods*)this},
  59.     };
  60.     HX_RESULT retVal = ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  61.     if (FAILED(retVal) && m_pResponse)
  62.     {
  63.         retVal = m_pResponse->QueryInterface(riid, ppvObj);
  64.     }
  65.     return retVal;
  66. }
  67. /////////////////////////////////////////////////////////////////////////
  68. //  Method:
  69. //  IUnknown::AddRef
  70. //  Purpose:
  71. //  Everyone usually implements this the same... feel free to use
  72. //  this implementation.
  73. //
  74. STDMETHODIMP_(ULONG32) CRIFFReader::AddRef()
  75. {
  76.     return InterlockedIncrement(&m_lRefCount);
  77. }
  78. /////////////////////////////////////////////////////////////////////////
  79. //  Method:
  80. //  IUnknown::Release
  81. //  Purpose:
  82. //  Everyone usually implements this the same... feel free to use
  83. //  this implementation.
  84. //
  85. STDMETHODIMP_(ULONG32) CRIFFReader::Release()
  86. {
  87.     if ( InterlockedDecrement(&m_lRefCount) > 0 )
  88.     {
  89.         return m_lRefCount;
  90.     }
  91.     delete this;
  92.     return 0;
  93. }
  94. CRIFFReader::CRIFFReader(IUnknown* pContext,
  95.                          CRIFFResponse* pResponse,
  96.                          IHXFileObject* pFileObject)
  97.     : m_pReassemblyBuffer(NULL)
  98.     , m_ulChunkBytesRead(0)
  99.     , m_ulChunkSize(0)
  100. {
  101.     m_pContext = pContext;
  102.     m_pResponse = pResponse;
  103.     m_pFileObject = pFileObject;
  104.     if ( m_pFileObject )
  105.     {
  106.         m_pFileObject->AddRef();
  107.     }
  108.     if ( m_pContext )
  109.         m_pContext->AddRef();
  110.     if ( m_pResponse )
  111.         m_pResponse->AddRef();
  112.     m_bFileIsOpen = FALSE;
  113.     m_lRefCount = 0;
  114.     m_pFilename = 0;
  115.     m_ulSizeDiff = 0;
  116.     m_ulThisChunkOffset = 0;
  117.     //Every time we Read() a data chunk and the amount of the Read is
  118.     // odd, we add one to byte-align for the next Read, but we want to
  119.     // know that we did this in ReadDone() so we use the following to
  120.     // keep track so, in ReadDone(), we can reduce the buffer size by
  121.     // one if necessary so the renderer will get just the bytes it
  122.     // needs:
  123.     m_ulFileSpecifiedReadSize = 0;
  124. }
  125. CRIFFReader::~CRIFFReader()
  126. {
  127.     if ( m_bFileIsOpen )
  128.         Close();
  129.     if ( m_pFilename )
  130.     {
  131.         delete [] m_pFilename;
  132.         m_pFilename = 0;
  133.     }
  134. }
  135. HX_RESULT
  136. CRIFFReader::Open(char* filename)
  137. {
  138.     if ( !m_pFileObject )
  139.         return HXR_UNEXPECTED;
  140.     if ( filename )
  141.     {
  142.         m_pFilename = new char[strlen(filename) + 1];
  143.         strcpy(m_pFilename, filename); /* Flawfinder: ignore */
  144.     }
  145.     m_state = RS_InitPending;
  146.     m_ulCurOffset = 0;
  147.     m_levelInfo[0].m_startOffset = 0;
  148.     m_ulLevel = 0;
  149. /*
  150.     if(filename)
  151.     {
  152.     IHXRequest* pRequest;
  153.     if (m_pFileObject->GetRequest(pRequest) == HXR_OK)
  154.     {
  155.         pRequest->SetURL(filename);
  156.         pRequest->Release();
  157.     }
  158.     else
  159.     {
  160.         return HXR_FAILED;
  161.     }
  162.     }
  163. */
  164.     return m_pFileObject->Init(HX_FILE_READ | HX_FILE_BINARY, this);
  165. //    return HXR_OK;
  166. }
  167. STDMETHODIMP
  168. CRIFFReader::InitDone(HX_RESULT status)
  169. {
  170.     if ( status != HXR_OK )
  171.     {
  172.         m_state = RS_Ready;
  173.         m_pResponse->RIFFOpenDone(status);
  174.         return HXR_OK;
  175.     }
  176.     m_bFileIsOpen = TRUE;
  177.     m_state = RS_GetFileTypePending;
  178.     return m_pFileObject->Read(sizeof(UINT32) * 2);
  179. }
  180. HX_RESULT
  181. CRIFFReader::Close()
  182. {
  183.     if ( m_pFileObject )
  184.     {
  185.         m_pFileObject->Close();
  186.         m_pFileObject->Release();
  187.         m_pFileObject = NULL;
  188.     }
  189.     if ( m_pContext )
  190.     {
  191.         m_pContext->Release();
  192.         m_pContext = NULL;
  193.     }
  194.     if ( m_pResponse )
  195.     {
  196.         m_pResponse->Release();
  197.         m_pResponse = NULL;
  198.     }
  199.     m_bFileIsOpen = FALSE;
  200.     return HXR_OK;
  201. }
  202. HX_RESULT
  203. CRIFFReader::FindChunk(UINT32 id, BOOL bRelative)
  204. {
  205.     m_ulFindChunkId = id;
  206.     m_state = RS_FileStartSeekPending;
  207.     if ( bRelative && m_levelInfo[m_ulLevel].started )
  208.         m_ulSeekOffset = m_levelInfo[m_ulLevel].m_nextChunkOffset;
  209.     else
  210.         m_ulSeekOffset = m_levelInfo[m_ulLevel].m_startOffset;
  211.     m_levelInfo[m_ulLevel].started = TRUE;
  212.     return(m_pFileObject->Seek(m_ulSeekOffset, FALSE) );
  213. }
  214. HX_RESULT
  215. CRIFFReader::GetChunk()
  216. {
  217.     m_state = RS_ReadChunkHeaderPending;
  218.     return(m_pFileObject->Read(sizeof(UINT32) * 2) ); /* Get type and len */
  219. }
  220. STDMETHODIMP
  221. CRIFFReader::ReadDone(HX_RESULT status, IHXBuffer* pBuffer)
  222. {
  223.     UCHAR* buf;
  224.     UINT32 len;
  225.     UINT16 uRem = 0;
  226.     HX_RESULT result = HXR_OK;
  227.     if ( !m_pResponse )
  228.         return HXR_FAIL;
  229.     if ( pBuffer )
  230.         pBuffer->Get(buf, len);
  231.     m_ulCurOffset += len;
  232.     //Keep track of "bytes read" value so CRIFFReader::ReadDone()
  233.     // can know whether or not it needs to decrement by one the size
  234.     // of the buffer it passes off, since some codecs (Intel's ILVC,
  235.     // for one) allow for odd numbered video frame sizes:
  236.     UINT32 ulActualLenOfBuffToUse = len;
  237.     if ( RS_ReadChunkBodyPending == m_state  && pBuffer )
  238.     {
  239.         ulActualLenOfBuffToUse = m_ulFileSpecifiedReadSize;
  240.         if ( len > ulActualLenOfBuffToUse  &&
  241.              len - ulActualLenOfBuffToUse == 1 )
  242.         {
  243.             //Then a Read(n+1) was done becuase n was odd, so
  244.             // make sure buffer has size of n so renderer will
  245.             // get just the bytes it needs:
  246.             pBuffer->SetSize(ulActualLenOfBuffToUse);
  247.         }
  248.     }
  249.     if ( m_ulFileType == RIFF_FILE_MAGIC_NUMBER ||
  250.          m_ulFileType == IFF_FILE_MAGIC_NUMBER )
  251.     {
  252.         // Make sure the offset is aligned(2 bytes)
  253.         uRem = (UINT16)(m_ulCurOffset % 2);
  254.         if ( uRem != 0 )
  255.         {
  256.             m_ulCurOffset += 1;
  257.         }
  258.     }
  259.     switch ( m_state )
  260.     {
  261.         case RS_GetFileTypePending:
  262.             if ( len != sizeof(UINT32) * 2 )
  263.             {
  264.                 m_state = RS_Ready;
  265.                 m_pResponse->RIFFOpenDone(HXR_FAILED);
  266.                 return HXR_UNEXPECTED;
  267.             }
  268.             if ( (UINT32)getlong(buf) == RIFF_FILE_MAGIC_NUMBER )
  269.             {
  270.                 m_state = RS_GetActualFileTypePending;
  271.                 m_ulFileType = RIFF_FILE_MAGIC_NUMBER;
  272.                 m_bLittleEndian = TRUE;
  273.                 m_ulChunkBodyLen = GetLong(&buf[4]);
  274.                 m_ulSizeDiff = 0;
  275.                 m_levelInfo[m_ulLevel].m_nextChunkOffset = m_ulCurOffset + m_ulChunkBodyLen;
  276.                 m_pFileObject->Read(sizeof(UINT32));
  277.                 return status;
  278.             }
  279.             else if ( (UINT32)getlong(buf) == IFF_FILE_MAGIC_NUMBER )
  280.             {
  281.                 m_state = RS_GetActualFileTypePending;
  282.                 m_ulFileType = IFF_FILE_MAGIC_NUMBER;
  283.                 m_bLittleEndian = FALSE;
  284.                 m_ulChunkBodyLen = GetLong(&buf[4]);
  285.                 m_ulSizeDiff = 0;
  286.                 m_levelInfo[m_ulLevel].m_nextChunkOffset = m_ulCurOffset + m_ulChunkBodyLen;
  287.                 m_levelInfo[m_ulLevel].m_startOffset = 12;
  288.                 m_pFileObject->Read(sizeof(UINT32));
  289.                 return status;
  290.             }
  291.             else
  292.             {
  293.                 m_ulFileType = (UINT32)getlong(buf);
  294.                 m_bLittleEndian = FALSE;
  295.                 m_ulChunkBodyLen = GetLong(&buf[4]);
  296.                 m_ulSizeDiff = 8;
  297.                 m_levelInfo[m_ulLevel].m_nextChunkOffset = m_ulCurOffset + m_ulChunkBodyLen - 8;
  298.             }
  299.             m_state = RS_Ready;
  300.             result = m_pResponse->RIFFOpenDone(status);
  301.             return(HXR_OK==status? result:status);
  302.         case RS_GetActualFileTypePending:
  303.             if ( len != sizeof(UINT32) )
  304.             {
  305.                 m_state = RS_Ready;
  306.                 m_pResponse->RIFFOpenDone(HXR_FAILED);
  307.                 return HXR_UNEXPECTED;
  308.             }
  309.             m_ulSubFileType = (UINT32)GetLong(buf);
  310.             m_state = RS_Ready;
  311.             result = m_pResponse->RIFFOpenDone(status);
  312.             return(HXR_OK==status? result:status);
  313.         case RS_ChunkHeaderReadPending:
  314.             if ( len != sizeof(UINT32) + sizeof(UINT32) ||
  315.                  (HXR_OK != status) )
  316.             {
  317.                 m_state = RS_Ready;
  318.                 m_pResponse->RIFFFindChunkDone(HXR_FAILED, 0);
  319.                 return HXR_UNEXPECTED;
  320.             }
  321.             if ( (UINT32)getlong(buf) == m_ulFindChunkId )
  322.             {
  323.                 // Found the chunk we were asked for
  324.                 m_state = RS_Ready;
  325.                 m_ulChunkBodyLen = GetLong(&buf[4]);
  326.                 // Make sure the body length is aligned(2 bytes)
  327.                 if ( m_ulFileType == RIFF_FILE_MAGIC_NUMBER )
  328.                 {
  329.                     uRem = (UINT16)(m_ulChunkBodyLen % 2);
  330.                     if ( uRem != 0 )
  331.                     {
  332.                         m_ulChunkBodyLen += 1;
  333.                     }
  334.                 }
  335.                 m_levelInfo[m_ulLevel].m_nextChunkOffset = m_ulCurOffset + m_ulChunkBodyLen;
  336.                 m_ulThisChunkOffset = m_ulCurOffset;
  337.                 m_levelInfo[m_ulLevel].m_nextChunkOffset -= m_ulSizeDiff;
  338.                 m_ulChunkType = m_ulFindChunkId;
  339.                 if ( m_ulFindChunkId == LIST_CHUNK_ID )
  340.                 {
  341.                     m_state = RS_GetListTypePending;
  342.                     m_pFileObject->Read(sizeof(UINT32));
  343.                 }
  344.                 else
  345.                 {
  346.                     m_state = RS_Ready;
  347.                     m_pResponse->RIFFFindChunkDone(status,
  348.                                                    m_ulChunkBodyLen - m_ulSizeDiff);
  349.                 }
  350.                 return status;
  351.             }
  352.             else
  353.             {
  354.                 // Didn't find it, go to the next chunk.
  355.                 m_state = RS_ChunkBodySeekPending;
  356.                 m_ulSeekOffset = m_ulCurOffset + GetLong(&buf[4]);
  357.                 /* Are we at the end of .rm file */
  358.                 if ( m_ulSeekOffset == m_ulCurOffset &&
  359.                      m_ulFileType != RIFF_FILE_MAGIC_NUMBER &&
  360.                      m_ulFileType != IFF_FILE_MAGIC_NUMBER )
  361.                 {
  362.                     m_pResponse->RIFFFindChunkDone(HXR_FAILED, 0);
  363.                     return HXR_OK;
  364.                 }
  365.                 if ( m_ulFileType == RIFF_FILE_MAGIC_NUMBER ||
  366.                      m_ulFileType == IFF_FILE_MAGIC_NUMBER )
  367.                 {
  368.                     // Make sure the seek offset is aligned(2 bytes)
  369.                     uRem = (UINT16)(m_ulSeekOffset % 2);
  370.                     if ( uRem != 0 )
  371.                     {
  372.                         m_ulSeekOffset += 1;
  373.                     }
  374.                 }
  375.                 m_ulSeekOffset -= m_ulSizeDiff;
  376.                 if ( m_ulSeekOffset == m_ulCurOffset )
  377.                 {
  378.                     m_state = RS_ChunkHeaderReadPending;
  379.                     return m_pFileObject->Read(sizeof(UINT32) * 2);
  380.                 }
  381.                 m_state = RS_ChunkBodySeekPending;
  382.                 return m_pFileObject->Seek(m_ulSeekOffset, FALSE);
  383.             }
  384.         case RS_GetListTypePending:
  385.             if ( len != sizeof(UINT32) )
  386.             {
  387.                 m_state = RS_Ready;
  388.                 m_pResponse->RIFFFindChunkDone(HXR_FAILED, 0);
  389.                 return HXR_UNEXPECTED;
  390.             }
  391.             m_ulChunkSubType = getlong(buf);
  392.             m_state = RS_Ready;
  393.             m_pResponse->RIFFFindChunkDone(status, m_ulChunkBodyLen);
  394.             return HXR_OK;
  395.         case RS_ReadChunkHeaderPending:
  396.             {
  397.                 if ( HXR_OK != status )
  398.                 {
  399.                     m_state = RS_Ready;
  400.                     m_pResponse->RIFFGetChunkDone(HXR_FAILED, 0, NULL);
  401.                     return HXR_OK;
  402.                 }
  403.                 m_ulGetChunkType = (UINT32)getlong(buf);
  404.                 m_state = RS_ReadChunkBodyPending;
  405.                 LONG32 baseLen = GetLong(&buf[4]);
  406.                 if ( (m_ulFileType == RIFF_FILE_MAGIC_NUMBER) &&
  407.                      (m_ulGetChunkType == (UINT32)0) )
  408.                 {
  409.                     m_state = RS_Ready;
  410.                     m_pResponse->RIFFGetChunkDone(HXR_FAILED, 0, NULL);
  411.                     return HXR_OK;
  412.                 }
  413.                 if ( baseLen == 0 )
  414.                 {
  415.                     m_state = RS_Ready;
  416.                     m_pResponse->RIFFGetChunkDone(HXR_OK, m_ulGetChunkType, NULL);
  417.                     return HXR_OK;
  418.                 }
  419.                 HX_RESULT resultOfRead = HXR_OK;
  420. #ifdef CHUNK_READ_SIZE_LIMIT
  421.                 // If the chunk is greater than MAX_READ_SIZE, we break the
  422.                 // read into smaller portions to improve performance under the
  423.                 // Simple File System:
  424.                 if (baseLen > MAX_READ_SIZE)
  425.                 {
  426.                     IHXCommonClassFactory* pClassFactory = NULL;
  427.                     if (m_pContext && SUCCEEDED(m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  428.                                                                           (void**) &pClassFactory)))
  429.                     {
  430.                         pClassFactory->CreateInstance(IID_IHXBuffer, (void**) &m_pReassemblyBuffer);
  431.                     }
  432.                     if (m_pReassemblyBuffer)
  433.                     {
  434.                         m_pReassemblyBuffer->SetSize(baseLen);
  435.                         m_ulChunkBytesRead = 0;
  436.                         m_ulChunkSize = baseLen;
  437.                         // Here we munge baselen in the interests of code
  438.                         // simplicity:
  439.                         baseLen = MAX_READ_SIZE;
  440.                     }
  441.                 }
  442. #endif // CHUNK_READ_SIZE_LIMIT
  443.                 if ( m_ulFileType == RIFF_FILE_MAGIC_NUMBER ||
  444.                      m_ulFileType == IFF_FILE_MAGIC_NUMBER )
  445.                 {
  446.                     // Make sure the chunk is aligned(2 bytes)
  447.                     uRem = (UINT16)((baseLen) % 2);
  448.                     //NOTE: if m_ulCurOffset is greater than 0x7FFFFFFF, GetLong
  449.                     // returns a negative number.  Any negative number % 2 (at
  450.                     // least in Windows) returns 0 or -1, and ((UINT16)-1) == 0xFFFF
  451.                     // so uRem thus can be one of the following: {0, 1, 0xFFFF}.
  452.                     // The following if() conditional will, however, still work as
  453.                     // expected:
  454.                     if ( uRem != 0 )
  455.                     {
  456.                         m_ulFileSpecifiedReadSize = baseLen;
  457.                         resultOfRead = m_pFileObject->Read(baseLen+1);
  458.                     }
  459.                     else
  460.                     {
  461.                         m_ulFileSpecifiedReadSize = baseLen;
  462.                         resultOfRead = m_pFileObject->Read(baseLen);
  463.                     }
  464.                 }
  465.                 else
  466.                 {
  467.                     m_ulFileSpecifiedReadSize = baseLen;
  468.                     resultOfRead = m_pFileObject->Read(baseLen);
  469.                 }
  470.                 return resultOfRead;
  471.             }
  472.         case RS_ReadChunkBodyPending:
  473. #ifdef CHUNK_READ_SIZE_LIMIT
  474.             if (m_pReassemblyBuffer)
  475.             {
  476.                 BYTE* pAssemblyStart = m_pReassemblyBuffer->GetBuffer();
  477.                 HX_ASSERT(pAssemblyStart);
  478.                 HX_ASSERT(m_ulChunkSize - m_ulChunkBytesRead >= pBuffer->GetSize());
  479.                 UINT32 ulBytesToCopy = pBuffer->GetSize();
  480.                 if (pBuffer->GetSize() > m_ulChunkSize - m_ulChunkBytesRead)
  481.                     ulBytesToCopy = m_ulChunkSize - m_ulChunkBytesRead;
  482.                 memcpy(pAssemblyStart + m_ulChunkBytesRead, pBuffer->GetBuffer(), /* Flawfinder: ignore */
  483.                        ulBytesToCopy);
  484.                 m_ulChunkBytesRead += pBuffer->GetSize();
  485.                 if (m_ulChunkBytesRead == m_ulChunkSize || FAILED(status) ||
  486.                     pBuffer->GetSize() == 0)
  487.                 {
  488.                     m_state = RS_Ready;
  489.                     IHXBuffer* pOldBuffer = m_pReassemblyBuffer;
  490.                     m_pReassemblyBuffer = NULL;
  491.                     m_pResponse->RIFFGetChunkDone(status, m_ulGetChunkType, pOldBuffer);
  492.                     HX_RELEASE(pOldBuffer);
  493.                     return HXR_OK;
  494.                 }
  495.                 else
  496.                 {
  497.                     UINT32 baseLen = m_ulChunkSize - m_ulChunkBytesRead;
  498.                     if (baseLen > MAX_READ_SIZE)
  499.                     {
  500.                         baseLen = MAX_READ_SIZE;
  501.                     }
  502.                     HX_RESULT resultOfRead = HXR_OK;
  503.                     if ( m_ulFileType == RIFF_FILE_MAGIC_NUMBER ||
  504.                          m_ulFileType == IFF_FILE_MAGIC_NUMBER )
  505.                     {
  506.                         // Make sure the chunk is aligned(2 bytes)
  507.                         uRem = (UINT16)((baseLen) % 2);
  508.                         //NOTE: if m_ulCurOffset is greater than 0x7FFFFFFF, GetLong
  509.                         // returns a negative number.  Any negative number % 2 (at
  510.                         // least in Windows) returns 0 or -1, and ((UINT16)-1) == 0xFFFF
  511.                         // so uRem thus can be one of the following: {0, 1, 0xFFFF}.
  512.                         // The following if() conditional will, however, still work as
  513.                         // expected:
  514.                         if ( uRem != 0 )
  515.                         {
  516.                             m_ulFileSpecifiedReadSize = baseLen;
  517.                             resultOfRead = m_pFileObject->Read(baseLen+1);
  518.                         }
  519.                         else
  520.                         {
  521.                             m_ulFileSpecifiedReadSize = baseLen;
  522.                             resultOfRead = m_pFileObject->Read(baseLen);
  523.                         }
  524.                     }
  525.                     else
  526.                     {
  527.                         m_ulFileSpecifiedReadSize = baseLen;
  528.                         resultOfRead = m_pFileObject->Read(baseLen);
  529.                     }
  530.                     return resultOfRead;
  531.                 }
  532.             }
  533. #endif // CHUNK_READ_SIZE_LIMIT
  534.             m_state = RS_Ready;
  535.             m_pResponse->RIFFGetChunkDone(status, m_ulGetChunkType, pBuffer);
  536.             return HXR_OK;
  537.         case RS_DataReadPending:
  538.             m_state = RS_Ready;
  539.             return m_pResponse->RIFFReadDone(status, pBuffer);
  540.         default:
  541.             //m_state = RS_Ready;
  542.             return HXR_UNEXPECTED;
  543.     }
  544.     return status;
  545. }
  546. STDMETHODIMP
  547. CRIFFReader::SeekDone(HX_RESULT status)
  548. {
  549.     /* This may happen in HTTP streaming when the file system
  550.      * is in still a seeking mode when the next seek is issued.
  551.      * The file system will then call SeekDone with a status of
  552.      * HXR_CANCELLED for the pending seek.
  553.      */
  554.     if ( status == HXR_CANCELLED )
  555.     {
  556.         return HXR_OK;
  557.     }
  558.     if ( status == HXR_OK )
  559.     {
  560.         m_ulCurOffset = m_ulSeekOffset;
  561.     }
  562.     HX_RESULT result = HXR_OK;
  563.     switch ( m_state )
  564.     {
  565.         case RS_ChunkBodySeekPending:
  566.             m_state = RS_ChunkHeaderReadPending;
  567.             result = m_pFileObject->Read(sizeof(UINT32) + sizeof(UINT32));
  568.             return(HXR_OK == status? result:status);
  569.         case RS_FileStartSeekPending:
  570.             m_state = RS_ChunkHeaderReadPending;
  571.             result = m_pFileObject->Read(sizeof(UINT32) + sizeof(UINT32));
  572.             return(HXR_OK == status? result:status);
  573.         case RS_AscendSeekPending:
  574.             m_state = RS_Ready;
  575.             result = m_pResponse->RIFFAscendDone(status);
  576.             return(HXR_OK == status? result:status);
  577.         case RS_UserSeekPending:
  578.             m_state = RS_Ready;
  579.             result = m_pResponse->RIFFSeekDone(status);
  580.             return(HXR_OK == status? result:status);
  581.         default:
  582.             return HXR_UNEXPECTED;
  583.     }
  584. }
  585. HX_RESULT
  586. CRIFFReader::Seek(UINT32 offset, BOOL bRelative)
  587. {
  588.     m_ulSeekOffset = bRelative ?
  589.                      m_ulCurOffset + offset :
  590.                      m_ulThisChunkOffset + offset;
  591.     m_state = RS_UserSeekPending;
  592.     return m_pFileObject->Seek(m_ulSeekOffset, FALSE);
  593. }
  594. UINT32
  595. CRIFFReader::IsThreadSafe()
  596. {
  597.     return HX_THREADSAFE_METHOD_FSR_READDONE;
  598. }
  599. HX_RESULT
  600. CRIFFReader::FileSeek(UINT32 offset)
  601. {
  602.     m_ulSeekOffset = offset;
  603.     m_state = RS_UserSeekPending;
  604.     return m_pFileObject->Seek(m_ulSeekOffset, FALSE);
  605. }
  606. HX_RESULT
  607. CRIFFReader::Descend()
  608. {
  609.     if ( m_ulLevel > 0 && m_ulChunkType != LIST_CHUNK_ID )
  610.     {
  611.         m_pResponse->RIFFDescendDone(HXR_FAILED);
  612.         return HXR_UNEXPECTED;
  613.     }
  614.     m_ulLevel++;
  615.     m_levelInfo[m_ulLevel].m_startOffset = m_ulCurOffset;
  616.     m_levelInfo[m_ulLevel].started     = FALSE;
  617.     return m_pResponse->RIFFDescendDone(HXR_OK);
  618. }
  619. HX_RESULT
  620. CRIFFReader::Ascend()
  621. {
  622.     m_ulLevel--;
  623.     m_state = RS_AscendSeekPending;
  624.     if ( m_ulLevel == 0 )
  625.         m_ulSeekOffset = 0;
  626.     else
  627.     {
  628.         m_ulSeekOffset = m_levelInfo[m_ulLevel].m_nextChunkOffset;
  629.     }
  630.     m_pFileObject->Seek(m_ulSeekOffset, FALSE);
  631.     return HXR_NOTIMPL;
  632. }
  633. STDMETHODIMP
  634. CRIFFReader::CloseDone(HX_RESULT status)
  635. {
  636.     return HXR_OK;
  637. }
  638. STDMETHODIMP
  639. CRIFFReader::WriteDone(HX_RESULT status)
  640. {
  641.     return HXR_NOTIMPL;
  642. }
  643. /************************************************************************
  644.  *  Method:
  645.  *      IHXFileResponse::FileObjectReady
  646.  *  Purpose:
  647.  *      Notification interface provided by users of the IHXFileObject
  648.  *      interface. This method is called by the IHXFileObject when the
  649.  *      requested FileObject is ready. It may return NULL with
  650.  *      HX_RESULT_FAIL if the requested filename did not exist in the
  651.  *      same pool.
  652.  */
  653. STDMETHODIMP
  654. CRIFFReader::FileObjectReady
  655. (
  656. HX_RESULT status,
  657. IHXFileObject* pFileObject)
  658. {
  659.     return HXR_OK;
  660. }
  661. HX_RESULT
  662. CRIFFReader::InternalClose()
  663. {
  664.     return HXR_OK;
  665. }
  666. HX_RESULT
  667. CRIFFReader::Read(UINT32 len)
  668. {
  669.     // Read from the file on our owner's behalf
  670.     m_state = RS_DataReadPending;
  671.     return m_pFileObject->Read(len);
  672. }
  673. UINT32
  674. CRIFFReader::GetListType()
  675. {
  676.     return m_ulChunkSubType;
  677. }
  678. UINT32
  679. CRIFFReader::GetOffset()
  680. {
  681.     return m_ulCurOffset;
  682. }
  683. UINT32
  684. CRIFFReader::FileType()
  685. {
  686.     return m_ulFileType;
  687. }
  688. UINT32
  689. CRIFFReader::FileSubtype()
  690. {
  691.     return m_ulSubFileType;
  692. }