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

Symbian

开发平台:

Visual 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. /****************************************************************************
  36.  *  Defines
  37.  */
  38. #define ATMZR_SEEK_RELATIVE  TRUE
  39. #define ATMZR_SEEK_ABSOLUTE  FALSE
  40. #define ATMZR_MAX_RECURSION_LEVEL   20
  41. #ifdef HELIX_FEATURE_MIN_HEAP
  42. #define ATMZR_PAGING_THRESHOLD     0x00000400 // 1K
  43. #else // HELIX_FEATURE_MIN_HEAP
  44. #define ATMZR_PAGING_THRESHOLD     0x0000FFFF // 64K
  45. #endif // HELIX_FEATURE_MIN_HEAP
  46. #define ATMZR_MAX_FILE_SIZE     0xFFFFFFFF
  47. /****************************************************************************
  48.  *  Includes
  49.  */
  50. #include "atomizer.h"
  51. #include "qtatoms.h"
  52. #include "mempager.h"
  53. #include "qtffrefcounter.h"
  54. /****************************************************************************
  55.  *  Data Types
  56.  */
  57. struct QTHeader
  58. {
  59.     UINT8 pSize[4];
  60.     UINT8 pType[4];
  61. };
  62. struct QTNewHeader
  63. {
  64.     UINT8 pSize[4];
  65.     UINT8 pType[4];
  66.     UINT8 pAtomID[4];
  67.     UINT8 pRsvd1[2];
  68.     UINT8 pChildCount[2];
  69.     UINT8 pRsvd2[4];
  70. };
  71. /****************************************************************************
  72.  *  Class CAtomizer
  73.  */
  74. /****************************************************************************
  75.  *  Constructor/Destructor
  76.  */
  77. CAtomizer::CAtomizer(void)
  78.     : m_pFileSwitcher(NULL)
  79.     , m_pResponse(NULL)
  80.     , m_pCommander(NULL)
  81.     , m_pScheduler(NULL)
  82.     , m_pRoot(NULL)
  83.     , m_pCurrentRoot(NULL)
  84.     , m_pNewAtom(NULL)
  85.     , m_ulStartOffset(0)
  86.     , m_ulFinalOffset(0)
  87.     , m_ulCurrentOffset(0)
  88.     , m_ulNewAtomOffset(0)
  89.     , m_ulNewAtomDataSize(0)
  90.     , m_AtomType(0)
  91.     , m_ulTotalSize(0)
  92.     , m_State(ATMZR_Offline)
  93.     , m_bSyncAccessEnabled(FALSE)
  94.     , m_bPreferLinearAccess(FALSE)
  95.     , m_pRecursionCallback(NULL)
  96.     , m_ulRecursionCount(0)
  97.     , m_lRefCount(0)
  98. {
  99.     g_nRefCount_qtff++;
  100. }
  101. CAtomizer::~CAtomizer()
  102. {
  103.     Close();
  104.     g_nRefCount_qtff--;
  105. }
  106. /****************************************************************************
  107.  *  Main Interface
  108.  */
  109. /****************************************************************************
  110.  *  Init
  111.  */
  112. HX_RESULT CAtomizer::Init(IUnknown *pSource,
  113.   IUnknown *pResponse,
  114.   IUnknown *pCommander)
  115. {
  116.     HX_RESULT retVal;
  117.     if ((m_State != ATMZR_Offline) &&
  118. (m_State != ATMZR_Ready))
  119.     {
  120. return HXR_UNEXPECTED;
  121.     }
  122.     HX_ASSERT(pSource);
  123.     HX_ASSERT(pResponse);
  124.     // Reset
  125.     HX_RELEASE(m_pFileSwitcher);
  126.     HX_RELEASE(m_pResponse);
  127.     HX_RELEASE(m_pCommander);
  128.     HX_RELEASE(m_pRoot);
  129.     HX_RELEASE(m_pNewAtom);
  130.     HX_RELEASE(m_pRecursionCallback);
  131.     m_ulCurrentOffset = 0;
  132.     m_ulRecursionCount = 0;
  133.     // Find Input Interface
  134.     retVal = pSource->QueryInterface(IID_IHXFileSwitcher, (void**) &m_pFileSwitcher);
  135.     // Find out if syncrhonous use of input is possible
  136.     if (SUCCEEDED(retVal))
  137.     {
  138. if (SUCCEEDED(m_pFileSwitcher->Advise(HX_FILEADVISE_SYNCACCESS)))
  139. {
  140.     m_bSyncAccessEnabled = TRUE;
  141.     m_pFileSwitcher->Advise(HX_FILEADVISE_ASYNCACCESS);
  142. }
  143. HX_RESULT adviseRes = 
  144.     m_pFileSwitcher->Advise(HX_FILEADVISE_RANDOMACCESS);
  145. if (HXR_ADVISE_PREFER_LINEAR == adviseRes)
  146. {
  147.     m_bPreferLinearAccess = TRUE;
  148. }
  149.     }
  150.     // Find Output Interface
  151.     if (SUCCEEDED(retVal))
  152.     {
  153. retVal = pResponse->QueryInterface(IID_IHXAtomizerResponse, (void**) &m_pResponse);
  154.     }
  155.     // Find Scheduler Interface
  156.     if (SUCCEEDED(retVal))
  157.     {
  158. retVal = pResponse->QueryInterface(IID_IHXScheduler, (void **) &m_pScheduler);
  159. if (FAILED(retVal))
  160. {
  161.     retVal = pSource->QueryInterface(IID_IHXScheduler, (void **) &m_pScheduler);
  162. }
  163.     }
  164.     // See if the Atomization Commander is given
  165.     if (SUCCEEDED(retVal))
  166.     {
  167. if (pCommander)
  168. {
  169.     pCommander->QueryInterface(IID_IHXAtomizationCommander, (void**) &m_pCommander);
  170. }
  171. if (!m_pCommander)
  172. {
  173.     // No commander given, Atomizer will command itself
  174.     m_pCommander = (IHXAtomizationCommander *) this;
  175.     m_pCommander->AddRef();
  176. }
  177. m_State = ATMZR_Ready;
  178.     }
  179.     // Allocate Recursion breaker callback
  180. #ifdef QTCONFIG_RECURSION_PROTECTION
  181.     if (SUCCEEDED(retVal))
  182.     {
  183. m_pRecursionCallback = new CRecursionCallback(this);
  184. if (m_pRecursionCallback)
  185. {
  186.     m_pRecursionCallback->AddRef();
  187. }
  188. else
  189. {
  190.     retVal = HXR_OUTOFMEMORY;
  191. }
  192.     }
  193. #endif // QTCONFIG_RECURSION_PROTECTION
  194.     return retVal;
  195. }
  196. /****************************************************************************
  197.  *  Close
  198.  */
  199. void CAtomizer::Close(void)
  200. {
  201.     m_State = ATMZR_Offline;
  202.     HX_RELEASE(m_pFileSwitcher);
  203.     HX_RELEASE(m_pResponse);
  204.     HX_RELEASE(m_pCommander);
  205.     HX_RELEASE(m_pScheduler);
  206.     HX_RELEASE(m_pRoot);
  207.     HX_RELEASE(m_pNewAtom);
  208.     HX_RELEASE(m_pRecursionCallback);
  209. }
  210. /****************************************************************************
  211.  *  Atomize
  212.  */
  213. HX_RESULT CAtomizer::Atomize(ULONG32 ulOffset, ULONG32 ulSize)
  214. {
  215.     if (m_State != ATMZR_Ready)
  216.     {
  217. return HXR_UNEXPECTED;
  218.     }
  219.     if ((m_pFileSwitcher == NULL) ||
  220. (m_pResponse == NULL) ||
  221. (m_pCommander == NULL))
  222.     {
  223. return HXR_FAIL;
  224.     }
  225.     // Reset
  226.     HX_RELEASE(m_pRoot);
  227.     HX_RELEASE(m_pNewAtom);
  228.     m_ulCurrentOffset = 0;
  229.     // Take on parameters
  230.     m_ulStartOffset = ulOffset;
  231.     m_ulNewAtomOffset = ulOffset;
  232.     m_ulTotalSize = ulSize;
  233.     m_ulFinalOffset = (m_ulTotalSize == ATOMIZE_ALL) ? ATOMIZE_ALL : m_ulStartOffset + m_ulTotalSize;
  234.     // Prepare the root
  235.     m_pRoot = new CQTRootAtom();
  236.     if (m_pRoot == NULL)
  237.     {
  238. return HXR_OUTOFMEMORY;
  239.     }
  240.     m_pRoot->AddRef();
  241.     m_pRoot->SetSize(m_ulTotalSize);
  242.     m_pRoot->SetOffset(m_ulStartOffset);
  243.     m_pCurrentRoot = m_pRoot;
  244.     // Start of the atomization process
  245.     m_State = ATMZR_ProcHeader;
  246.     SeekDataCB(m_ulStartOffset);
  247.     return HXR_OK;
  248. }
  249. /****************************************************************************
  250.  *  Private Methods
  251.  */
  252. /****************************************************************************
  253.  *  SeekData
  254.  */
  255. HX_RESULT CAtomizer::SeekData(ULONG32 ulOffset, BOOL bRelative)
  256. {
  257.     if (m_State == ATMZR_Offline)
  258.     {
  259. return HXR_UNEXPECTED;
  260.     }
  261.     if (bRelative)
  262.     {
  263. m_ulCurrentOffset += ulOffset;
  264.     }
  265.     else
  266.     {
  267. m_ulCurrentOffset = ulOffset;
  268.     }
  269.     if (IsOffsetInRange(m_ulCurrentOffset))
  270.     {
  271. HX_RESULT retVal;
  272. // Initiate the Seek
  273. retVal = m_pFileSwitcher->Seek( ulOffset,
  274. bRelative,
  275. (IHXFileResponse *) this);
  276. if (FAILED(retVal))
  277. {
  278.     CompleteAtomization(retVal);
  279. }
  280.     }
  281.     else
  282.     {
  283. CompleteAtomization(HXR_OK);
  284.     }
  285.     return HXR_ABORT;
  286. }
  287. /****************************************************************************
  288.  *  ReadData
  289.  */
  290. HX_RESULT CAtomizer::ReadData(ULONG32 ulSize)
  291. {
  292.     HX_RESULT retVal = HXR_OK;
  293.     if (m_State == ATMZR_Offline)
  294.     {
  295. return HXR_UNEXPECTED;
  296.     }
  297.     if (m_State == ATMZR_ProcHeader)
  298.     {
  299. retVal = AdjustCurrentRoot();
  300. if (FAILED(retVal))
  301. {
  302.     if (retVal == HXR_CHUNK_MISSING)
  303.     {
  304. // udta Atom terminator encountered, must skip over the
  305. // terminator chunk
  306. m_ulNewAtomOffset = m_ulCurrentOffset +
  307.     QT_UDTA_TERMINATOR_LENGTH;
  308. return SeekDataCB(m_ulNewAtomOffset);
  309.     }
  310.     else
  311.     {
  312. CompleteAtomization(retVal);
  313. return HXR_ABORT;
  314.     }
  315. }
  316.     }
  317.     m_ulCurrentOffset += ulSize;
  318.     if (IsOffsetInRange(m_ulCurrentOffset - 1))
  319.     {
  320. HX_RESULT retVal;
  321. // Initiate the Read
  322. retVal = m_pFileSwitcher->Read( ulSize,
  323. (IHXFileResponse *) this);
  324. if (SUCCEEDED(retVal))
  325. {
  326.     return retVal;
  327. }
  328.     }
  329.     CompleteAtomization(retVal);
  330.     return HXR_ABORT;
  331. }
  332. /****************************************************************************
  333.  *  ReadDataCB
  334.  */
  335. HX_RESULT CAtomizer::ReadDataCB(ULONG32 ulSize)
  336. {
  337. #ifdef QTCONFIG_RECURSION_PROTECTION
  338.     if (m_ulRecursionCount < ATMZR_MAX_RECURSION_LEVEL)
  339.     {
  340. m_ulRecursionCount++;
  341. return ReadData(ulSize);
  342.     }
  343.     else
  344.     {
  345. CallbackHandle retVal;
  346. m_ulRecursionCount = 0;
  347. m_ulSize = ulSize;
  348. m_CallbackStep = ATMZR_CBSTEP_Read;
  349. retVal = m_pScheduler->RelativeEnter(m_pRecursionCallback, 0);
  350. if (!retVal)
  351. {
  352.     CompleteAtomization(HXR_FAIL);
  353. }
  354. return HXR_OK;
  355.     }
  356. #else // QTCONFIG_RECURSION_PROTECTION
  357.     return ReadData(ulSize);
  358. #endif // QTCONFIG_RECURSION_PROTECTION
  359. }
  360. /****************************************************************************
  361.  *  SeekDataCB
  362.  */
  363. HX_RESULT CAtomizer::SeekDataCB(ULONG32 ulOffset, BOOL bRelative)
  364. {
  365. #ifdef QTCONFIG_RECURSION_PROTECTION
  366.     if (m_ulRecursionCount < ATMZR_MAX_RECURSION_LEVEL)
  367.     {
  368. m_ulRecursionCount++;
  369. return SeekData(ulOffset, bRelative);
  370.     }
  371.     else
  372.     {
  373. CallbackHandle retVal;
  374. m_ulRecursionCount = 0;
  375. m_ulSize = ulOffset;
  376. m_bRelative = bRelative;
  377. m_CallbackStep = ATMZR_CBSTEP_Seek;
  378. retVal = m_pScheduler->RelativeEnter(m_pRecursionCallback, 0);
  379. if (!retVal)
  380. {
  381.     CompleteAtomization(HXR_FAIL);
  382. }
  383. return HXR_OK;
  384.     }
  385. #else // QTCONFIG_RECURSION_PROTECTION
  386.     return SeekData(ulOffset, bRelative);
  387. #endif // QTCONFIG_RECURSION_PROTECTION
  388. }
  389. /****************************************************************************
  390.  *  AdjustCurrentRoot
  391.  */
  392. HX_RESULT CAtomizer::AdjustCurrentRoot(void)
  393. {
  394.     CQTAtom *pRootParent;
  395.     HX_ASSERT(m_pCurrentRoot);
  396.     while ((m_pCurrentRoot->GetSize() != ATOMIZE_ALL) &&
  397.    ((m_pCurrentRoot->GetOffset() +
  398.      m_pCurrentRoot->GetSize() -
  399.      m_ulNewAtomOffset) <
  400.     QT_HEADER_SIZE))
  401.     {
  402. if (m_ulNewAtomOffset ==
  403.     (m_pCurrentRoot->GetOffset() + m_pCurrentRoot->GetSize()))
  404. {
  405.     // Current Atom is completed, move to the parent
  406.     pRootParent = m_pCurrentRoot->GetParent();
  407.     if (pRootParent)
  408.     {
  409. m_pCurrentRoot = pRootParent;
  410. continue;
  411.     }
  412.     else
  413.     {
  414. // We are at the absolute root
  415. break;
  416.     }
  417. }
  418. else
  419. {
  420.     // Not enough room in current parent to read a header, but
  421.     // still some data left over
  422.     if ((m_pCurrentRoot->GetType() == QT_udta) &&
  423. ((m_ulNewAtomOffset + QT_UDTA_TERMINATOR_LENGTH) ==
  424. (m_pCurrentRoot->GetOffset() + m_pCurrentRoot->GetSize())))
  425.     {
  426. // Legacy udta Atom termination - need to skip over the
  427. // terminator
  428. return HXR_CHUNK_MISSING;
  429.     }
  430.     else
  431.     {
  432. // Data is corrupted
  433. return HXR_PARSE_ERROR;
  434.     }
  435. }
  436.     }
  437.     return HXR_OK;
  438. }
  439. /****************************************************************************
  440.  *  CompleteAtomization
  441.  */
  442. void CAtomizer::CompleteAtomization(HX_RESULT status)
  443. {
  444.     CQTAtom* pRoot;
  445.     if (!m_pRoot)
  446.     {
  447. return;
  448.     }
  449.     if (SUCCEEDED(status))
  450.     {
  451. // Record the amount of data atomized
  452. CQTAtom *pRoot = m_pCurrentRoot;
  453. HX_ASSERT(pRoot);
  454. // If we have the position of where next atom would be,
  455. // compute unspecified atom sizes
  456. if (m_ulNewAtomOffset != ATOMIZE_ALL)
  457. {
  458.     while (pRoot)
  459.     {
  460. if (pRoot->GetSize() == ATOMIZE_ALL)
  461. {
  462.     pRoot->SetSize(m_ulNewAtomOffset - m_ulStartOffset);
  463. }
  464. // Move to the parent
  465. pRoot = pRoot->GetParent();
  466.     }
  467.     m_pRoot->SetSize(m_ulNewAtomOffset - m_ulStartOffset);
  468. }
  469. status = AdjustCurrentRoot();
  470.     }
  471.     if (SUCCEEDED(status))
  472.     {
  473. // See if parsing fully completed
  474. if (((m_ulFinalOffset != ATOMIZE_ALL) &&
  475.      (m_ulFinalOffset != m_ulCurrentOffset)) ||
  476.     (m_pRoot != m_pCurrentRoot))
  477. {
  478.     status = HXR_CORRUPT_FILE;
  479. }
  480.     }
  481.     else
  482.     {
  483. // Data compromizing failure occured during atomization
  484. HX_RELEASE(m_pRoot);
  485.     }
  486.     HX_RELEASE(m_pNewAtom);
  487.     m_State = ATMZR_Ready;
  488.     pRoot = m_pRoot;
  489.     m_pRoot = NULL;
  490.     m_pCurrentRoot = NULL;
  491.     m_pResponse->AtomReady(status, pRoot);
  492.     if (pRoot)
  493.     {
  494. pRoot->Release();
  495.     }
  496. }
  497. /****************************************************************************
  498.  *  IHXFileResponse methods
  499.  */
  500. /////////////////////////////////////////////////////////////////////////
  501. //  Method:
  502. // IHXFileResponse::ReadDone
  503. //  Purpose:
  504. // Notification interface provided by users of the IHXFileObject
  505. // interface. This method is called by the IHXFileObject when the
  506. // last read from the file is complete and a buffer is available.
  507. //
  508. STDMETHODIMP CAtomizer::ReadDone
  509. (
  510.     HX_RESULT status,
  511.     IHXBuffer* pBuffer
  512. )
  513. {
  514.     HX_RESULT retVal = HXR_OK;
  515.     QTAtomType AtomType = 0;
  516.     ULONG32 ulAtomSize = 0;
  517.     UINT8* pData = NULL;
  518.     ULONG32 ulDataLen = 0;
  519.     ULONG32 ulNormalizedLen = 0;
  520.     ULONG32 ulAtomID = 0;
  521.     UINT16 uChildCount = 0;
  522.     BOOL bLoop = FALSE;
  523.     if (SUCCEEDED(status) && (m_State != ATMZR_Offline))
  524.     {
  525. HX_ASSERT(pBuffer);
  526. pBuffer->Get(pData, ulDataLen);
  527. ulNormalizedLen = ulDataLen;
  528. do
  529. {
  530.     bLoop = FALSE;
  531.     switch (m_State)
  532.     {
  533.     case ATMZR_ProcNewHeader:
  534. ulNormalizedLen -= (QT_NEW_HEADER_SIZE - QT_HEADER_SIZE);
  535. {
  536.     QTNewHeader *pHeader = (QTNewHeader *) (pData);
  537.     ulAtomID = CQTAtom::GetUL32(pHeader->pAtomID);
  538.     uChildCount = CQTAtom::GetUI16(pHeader->pChildCount);
  539. }
  540. // drop to case below
  541.     case ATMZR_ProcHeader:
  542. if (ulNormalizedLen == QT_HEADER_SIZE)
  543. {
  544.     QTHeader *pHeader = (QTHeader *) (pData);
  545.     AtomType = CQTAtom::GetUL32(pHeader->pType);
  546.     ulAtomSize = CQTAtom::GetUL32(pHeader->pSize);
  547.     if (AtomType == 0)
  548.     {
  549. if (m_State == ATMZR_ProcHeader)
  550. {
  551.     // Try to interpret this as CQTNewAtom
  552.     m_State = ATMZR_ProcNewHeader;
  553.     SeekDataCB(QT_NEW_HEADER_GAP, ATMZR_SEEK_RELATIVE);
  554.     return retVal;
  555. }
  556. status = HXR_PARSE_ERROR;
  557.     }
  558.     else if (ulAtomSize == 1)
  559.     {
  560. // This must be the Atom with extended size
  561. m_State = ATMZR_ProcExtendedSize;
  562. m_AtomType = AtomType;
  563. ReadDataCB(QT_EXTENDED_SIZE);
  564. return retVal;
  565.     }
  566.     else if (ulAtomSize == 0)
  567.     {
  568. // This Atom extends to the of enclosing container
  569. ulAtomSize = ATOMIZE_ALL;
  570.     }
  571.     // drop to case below;
  572.     m_State = ATMZR_MakeAtom;
  573. }
  574. else
  575. {
  576.     break;
  577. }
  578.     case ATMZR_MakeAtom:
  579. {
  580.     QTAtomizerCmd AtomCmd;
  581.     HX_ASSERT(!m_pNewAtom);
  582.     AtomCmd = m_pCommander->GetAtomCommand( AtomType,
  583.     m_pCurrentRoot);
  584.     if (ulAtomSize == ATOMIZE_ALL)
  585.     {
  586. if (m_pCurrentRoot->GetSize() != ATOMIZE_ALL)
  587. {
  588.     ulAtomSize = m_pCurrentRoot->GetOffset() +
  589.  m_pCurrentRoot->GetSize() -
  590.  m_ulNewAtomOffset;
  591.     HX_ASSERT(ulAtomSize != 0);
  592.     if (ulAtomSize == 0)
  593.     {
  594. status = HXR_PARSE_ERROR;
  595. break;
  596.     }
  597. }
  598.     }
  599.     switch (AtomCmd)
  600.     {
  601.     case ATMZR_CMD_LOAD:
  602.     case ATMZR_CMD_OUTLINE:
  603. m_pNewAtom = CreateQTAtom(  AtomType,
  604.     m_ulNewAtomOffset,
  605.     ulAtomSize,
  606.     NULL, // no parent
  607.     ulAtomID,
  608.     uChildCount);
  609. if (m_pNewAtom != NULL)
  610. {
  611.     if (m_pNewAtom->IsLeafType())
  612.     {
  613. // A Leaf Atom
  614. if (AtomCmd == ATMZR_CMD_LOAD)
  615. {
  616.     m_ulNewAtomDataSize = 0;
  617.     if (ulAtomSize != ATOMIZE_ALL)
  618.     {
  619. m_ulNewAtomDataSize = ulAtomSize - ulDataLen;
  620.     }
  621. #ifndef QTCONFIG_NO_PAGING
  622.     if ((m_ulNewAtomDataSize > ATMZR_PAGING_THRESHOLD)
  623. && m_pNewAtom->IsPagingAtom()
  624. #ifdef QTCONFIG_NO_ASYNC_PAGING
  625. && m_bSyncAccessEnabled
  626. #endif // QTCONFIG_NO_ASYNC_PAGING
  627. && (m_ulNewAtomDataSize != ATOMIZE_ALL)
  628.        )
  629.     {
  630. CMemPager* pMemPager = new CMemPager;
  631. status = HXR_OUTOFMEMORY;
  632. if (pMemPager)
  633. {
  634.     pMemPager->AddRef();
  635.     status = pMemPager->Init(m_pFileSwitcher,
  636.      m_ulCurrentOffset,
  637.      m_ulNewAtomDataSize);
  638.     if (SUCCEEDED(status))
  639.     {
  640. m_pNewAtom->AddRef();
  641. m_State = ATMZR_ProcBody;
  642. m_pNewAtom->SetMemPager(pMemPager);
  643. status = pMemPager->LoadPage((IHXFileResponse*) this);
  644.     }
  645.     pMemPager->Release();
  646.     if (SUCCEEDED(status))
  647.     {
  648. return retVal;
  649.     }
  650. }
  651. // Failure
  652. HX_ASSERT(status != HXR_OK);
  653. break;
  654.     }
  655.     else
  656. #endif // QTCONFIG_NO_PAGING
  657.     if ((m_ulNewAtomDataSize != 0) ||
  658. (ulAtomSize == ATOMIZE_ALL))
  659.     {
  660. // Leaf atom with data
  661. m_pNewAtom->AddRef();
  662. m_State = ATMZR_ProcBody;
  663. if (m_ulNewAtomDataSize != 0)
  664. {
  665.     ReadDataCB(m_ulNewAtomDataSize);
  666.     return retVal;
  667. }
  668. else
  669. {
  670.     ReadDataCB(ATMZR_MAX_FILE_SIZE - m_ulCurrentOffset);
  671.     return retVal;
  672. }
  673.     }
  674.     else
  675.     {
  676. // Leaf atom with no data
  677. m_pCurrentRoot->AddPresentChild(m_pNewAtom);
  678. m_ulNewAtomOffset = m_ulCurrentOffset;
  679. m_pNewAtom = NULL;
  680. m_State = ATMZR_ProcHeader;
  681. ReadDataCB(QT_HEADER_SIZE);
  682.     }
  683. }
  684. else
  685. {
  686.     // We are not to load the data
  687.     // so we are ready to attach the atom shell
  688.     // to the atom tree.
  689.     m_pCurrentRoot->AddPresentChild(m_pNewAtom);
  690.     m_pNewAtom = NULL;
  691.     if (ulAtomSize != ATOMIZE_ALL)
  692.     {
  693. m_ulNewAtomOffset = m_ulCurrentOffset +
  694.     ulAtomSize -
  695.     ulDataLen;
  696. m_State = ATMZR_ProcHeader;
  697. SeekDataCB(m_ulNewAtomOffset);
  698. return retVal;
  699.     }
  700.     // Location of the end of file - unknown
  701.     m_ulNewAtomOffset = ATOMIZE_ALL;
  702. }
  703.     }
  704.     else
  705.     {
  706. // A Non Leaf Atom - has no direct data
  707. m_pCurrentRoot->AddPresentChild(m_pNewAtom);
  708. m_pCurrentRoot = m_pNewAtom;
  709. m_ulNewAtomOffset = m_ulCurrentOffset;
  710. m_pNewAtom = NULL;
  711. m_State = ATMZR_ProcHeader;
  712. ReadDataCB(QT_HEADER_SIZE);
  713. return retVal;
  714.     }
  715.     break;
  716. }
  717. // If we couldn't create the atom, skip it.
  718. // Drop down to case below.
  719.     case ATMZR_CMD_SKIP:
  720. if (ulAtomSize != ATOMIZE_ALL)
  721. {
  722.     m_ulNewAtomOffset = m_ulCurrentOffset +
  723. ulAtomSize -
  724. ulDataLen;
  725.     m_State = ATMZR_ProcHeader;
  726.     /* Check to see if we are trying to skip
  727.      * an mdat atom while using a file object
  728.      * that prefers linear access (ie. HTTP/1.0)
  729.      */
  730.     if (m_bPreferLinearAccess && (QT_mdat == AtomType))
  731.     {
  732. HX_RESULT completionRes = HXR_INVALID_FILE;
  733. if ((m_pCurrentRoot) &&
  734.     (m_pCurrentRoot->FindPresentChild(QT_moov)))
  735. {
  736.     /* We have the moov atom already so
  737.      * this file is likely formatted for 
  738.      * progressive download
  739.      */
  740.     completionRes = HXR_OK;
  741. }
  742. CompleteAtomization(completionRes);
  743.     }
  744.     else
  745.     {
  746. SeekDataCB(m_ulNewAtomOffset);
  747.     }
  748.     return retVal;
  749. }
  750. else
  751. {
  752.     m_ulNewAtomOffset = ATOMIZE_ALL;
  753.     break;
  754. }
  755. // If we couldn't skip the atom, stop.
  756. // Drop to case below
  757.     case ATMZR_CMD_STOP:
  758. break;
  759.     default:
  760. status = HXR_INVALID_PARAMETER;
  761. break;
  762.     }
  763. }
  764. break;
  765.     case ATMZR_ProcExtendedSize:
  766. if (ulNormalizedLen == QT_EXTENDED_SIZE)
  767. {
  768.     AtomType = m_AtomType;
  769.     ulAtomSize = CQTAtom::GetUL32(pData);
  770.     HX_ASSERT(ulAtomSize == 0);
  771.     if (ulAtomSize == 0)
  772.     {
  773. ulAtomSize = CQTAtom::GetUL32(pData + 4);
  774. m_State = ATMZR_MakeAtom;
  775. bLoop = TRUE;
  776.     }
  777.     else
  778.     {
  779. // can't handle atom size beyond 4GB
  780. status = HXR_ABORT;
  781.     }
  782. }
  783. break;
  784.     case ATMZR_ProcBody:
  785. HX_ASSERT(m_pNewAtom);
  786. if (m_ulNewAtomDataSize != ATOMIZE_ALL)
  787. {
  788.     if ((!m_pNewAtom->IsPagingEnabled()) &&
  789. (ulDataLen == m_ulNewAtomDataSize))
  790.     {
  791. HX_ASSERT(pBuffer);
  792. m_pNewAtom->SetBuffer(pBuffer);
  793. m_pCurrentRoot->AddPresentChild(m_pNewAtom);
  794. m_ulNewAtomOffset = m_ulCurrentOffset;
  795. m_pNewAtom->Release();
  796. m_pNewAtom = NULL;
  797. m_State = ATMZR_ProcHeader;
  798. ReadDataCB(QT_HEADER_SIZE);
  799. return retVal;
  800.     }
  801.     else if (m_pNewAtom->IsPagingEnabled() &&
  802.      (ulDataLen != 0))
  803.     {
  804. m_ulCurrentOffset += ulDataLen;
  805. m_pCurrentRoot->AddPresentChild(m_pNewAtom);
  806. HX_ASSERT(m_ulNewAtomDataSize >= ulDataLen);
  807. m_ulNewAtomOffset = m_ulCurrentOffset +
  808.     m_ulNewAtomDataSize -
  809.     ulDataLen;
  810. m_pNewAtom->Release();
  811. m_pNewAtom = NULL;
  812. m_State = ATMZR_ProcHeader;
  813. if (m_ulNewAtomOffset != m_ulCurrentOffset)
  814. {
  815.     SeekDataCB(m_ulNewAtomOffset);
  816. }
  817. else
  818. {
  819.     ReadDataCB(QT_HEADER_SIZE);
  820. }
  821. return retVal;
  822.     }
  823. }
  824. else if (ulDataLen > 0)
  825. {
  826.     // Body extended to the end of file - stop here
  827.     HX_ASSERT(pBuffer);
  828.     m_ulNewAtomDataSize = ulDataLen;
  829.     m_pNewAtom->SetBuffer(pBuffer);
  830.     m_pNewAtom->SetSize(m_ulNewAtomDataSize);
  831.     m_ulNewAtomOffset = m_ulCurrentOffset;
  832.     m_pNewAtom->Release();
  833.     m_pNewAtom = NULL;
  834. }
  835. break;
  836.     default:
  837. status = HXR_FAIL;
  838. retVal = HXR_UNEXPECTED;
  839. break;
  840.     }
  841. } while (bLoop);
  842.     }
  843.     else
  844.     {
  845. // Did not clear for processing
  846. if (m_State == ATMZR_Offline)
  847. {
  848.     return HXR_UNEXPECTED;
  849. }
  850. else
  851. {
  852.     // The read must have failed - complete atomization as is
  853.     status = HXR_OK;
  854. }
  855.     }
  856.     CompleteAtomization(status);
  857.     return retVal;
  858. }
  859. /////////////////////////////////////////////////////////////////////////
  860. //  Method:
  861. // IHXFileResponse::SeekDone
  862. //  Purpose:
  863. // Notification interface provided by users of the IHXFileObject
  864. // interface. This method is called by the IHXFileObject when the
  865. // last seek in the file is complete.
  866. //
  867. STDMETHODIMP CAtomizer::SeekDone(HX_RESULT status)
  868. {
  869.     HX_RESULT retVal = HXR_OK;
  870.     if (SUCCEEDED(status) && (m_State != ATMZR_Offline))
  871.     {
  872. // We seek headers only, so start the read of a header
  873. switch(m_State)
  874. {
  875. case ATMZR_ProcHeader:
  876.     ReadDataCB(QT_HEADER_SIZE);
  877.     return retVal;
  878. case ATMZR_ProcNewHeader:
  879.     ReadDataCB(QT_NEW_HEADER_SIZE);
  880.     return retVal;
  881. default:
  882.     status = HXR_FAIL;
  883.     retVal = HXR_UNEXPECTED;
  884.     break;
  885. }
  886.     }
  887.     else
  888.     {
  889. // Did not clear for processing
  890. if (m_State == ATMZR_Offline)
  891. {
  892.     return HXR_UNEXPECTED;
  893. }
  894. else
  895. {
  896.     // The seek must have failed - complete atomization as is
  897.     status = HXR_OK;
  898. }
  899.     }
  900.     CompleteAtomization(status);
  901.     return retVal;
  902. }
  903. /****************************************************************************
  904.  *  IUnknown methods
  905.  */
  906. /////////////////////////////////////////////////////////////////////////
  907. //  Method:
  908. // IUnknown::QueryInterface
  909. //
  910. STDMETHODIMP CAtomizer::QueryInterface(REFIID riid, void** ppvObj)
  911. {
  912.     if (IsEqualIID(riid, IID_IHXFileResponse))
  913.     {
  914. AddRef();
  915. *ppvObj = (IHXFileResponse*) this;
  916. return HXR_OK;
  917.     }
  918.     else if (IsEqualIID(riid, IID_IHXAtomizationCommander))
  919.     {
  920. AddRef();
  921. *ppvObj = (IHXAtomizationCommander*) this;
  922. return HXR_OK;
  923.     }
  924.     else if (IsEqualIID(riid, IID_IHXThreadSafeMethods))
  925.     {
  926. AddRef();
  927. *ppvObj = (IHXThreadSafeMethods*) this;
  928. return HXR_OK;
  929.     }
  930.     else if (IsEqualIID(riid, IID_IUnknown))
  931.     {
  932. AddRef();
  933. *ppvObj = this;
  934. return HXR_OK;
  935.     }
  936.     *ppvObj = NULL;
  937.     return HXR_NOINTERFACE;
  938. }
  939. /////////////////////////////////////////////////////////////////////////
  940. //  Method:
  941. // IUnknown::AddRef
  942. //
  943. STDMETHODIMP_(ULONG32) CAtomizer::AddRef()
  944. {
  945.     return InterlockedIncrement(&m_lRefCount);
  946. }
  947. /////////////////////////////////////////////////////////////////////////
  948. //  Method:
  949. // IUnknown::Release
  950. //
  951. STDMETHODIMP_(ULONG32) CAtomizer::Release()
  952. {
  953.     if (InterlockedDecrement(&m_lRefCount) > 0)
  954.     {
  955.         return m_lRefCount;
  956.     }
  957.     delete this;
  958.     return 0;
  959. }
  960. ///////////////////////////////////////////////////////////////////////////////
  961. //  Method:
  962. // IHXThreadSafeMethods::IsThreadsafe
  963. //
  964. //  Purpose:
  965. // This routine returns threadsafeness information about the file object
  966. // which is used by the server for improved performance.
  967. //
  968. STDMETHODIMP_(UINT32)
  969. CAtomizer::IsThreadSafe()
  970. {
  971.     return HX_THREADSAFE_METHOD_FF_GETPACKET | HX_THREADSAFE_METHOD_FSR_READDONE;
  972. }
  973. /****************************************************************************
  974.  *  Class CAtomizer::RecursionCallback
  975.  */
  976. #ifdef QTCONFIG_RECURSION_PROTECTION
  977. /****************************************************************************
  978.  *  Constructor/Destructor
  979.  */
  980. CAtomizer::CRecursionCallback::CRecursionCallback(CAtomizer *pAtomizer)
  981.     : m_pAtomizer(pAtomizer)
  982.     , m_lRefCount(0)
  983. {
  984.     HX_ASSERT(m_pAtomizer);
  985.     m_pAtomizer->AddRef();
  986. }
  987. CAtomizer::CRecursionCallback::~CRecursionCallback(void)
  988. {
  989.     HX_RELEASE(m_pAtomizer);
  990. }
  991. /****************************************************************************
  992.  *  IHXCallback methods
  993.  */
  994. /****************************************************************************
  995.  *  Func
  996.  */
  997. STDMETHODIMP CAtomizer::CRecursionCallback::Func(void)
  998. {
  999.     switch (m_pAtomizer->m_CallbackStep)
  1000.     {
  1001.     case ATMZR_CBSTEP_Read:
  1002. m_pAtomizer->ReadData(m_pAtomizer->m_ulSize);
  1003. return HXR_OK;
  1004.     case ATMZR_CBSTEP_Seek:
  1005. m_pAtomizer->SeekData(m_pAtomizer->m_ulSize,
  1006.       m_pAtomizer->m_bRelative);
  1007. return HXR_OK;
  1008.     default:
  1009. // nothing to do
  1010. break;
  1011.     }
  1012.     return HXR_UNEXPECTED;
  1013. }
  1014. /****************************************************************************
  1015.  *  IUnknown methods
  1016.  */
  1017. /////////////////////////////////////////////////////////////////////////
  1018. //  Method:
  1019. // IUnknown::QueryInterface
  1020. //
  1021. STDMETHODIMP CAtomizer::CRecursionCallback::QueryInterface(
  1022.     REFIID riid,
  1023.     void** ppvObj)
  1024. {
  1025.     if (IsEqualIID(riid, IID_IUnknown))
  1026.     {
  1027. AddRef();
  1028. *ppvObj = this;
  1029. return HXR_OK;
  1030.     }
  1031.     else if (IsEqualIID(riid, IID_IHXCallback))
  1032.     {
  1033.         AddRef();
  1034.         *ppvObj = (IHXCallback*)this;
  1035.         return HXR_OK;
  1036.     }
  1037.     *ppvObj = NULL;
  1038.     return HXR_NOINTERFACE;
  1039. }
  1040. /////////////////////////////////////////////////////////////////////////
  1041. //  Method:
  1042. // IUnknown::AddRef
  1043. //
  1044. STDMETHODIMP_(ULONG32) CAtomizer::CRecursionCallback::AddRef()
  1045. {
  1046.     return InterlockedIncrement(&m_lRefCount);
  1047. }
  1048. /////////////////////////////////////////////////////////////////////////
  1049. //  Method:
  1050. // IUnknown::Release
  1051. //
  1052. STDMETHODIMP_(ULONG32) CAtomizer::CRecursionCallback::Release()
  1053. {
  1054.     if (InterlockedDecrement(&m_lRefCount) > 0)
  1055.     {
  1056.         return m_lRefCount;
  1057.     }
  1058.     delete this;
  1059.     return 0;
  1060. }
  1061. #endif // QTCONFIG_RECURSION_PROTECTION