riff.cpp
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:25k
源码类别:

Symbian

开发平台:

Visual C++

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