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

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.  *  Includes
  37.  */
  38. #include "fswtchr.h"
  39. #include "hxassert.h"
  40. #include "qtffrefcounter.h"
  41. /****************************************************************************
  42.  *  Local Defines
  43.  */
  44. #define MAX_CHUNK_SIZE 0x0000FFFF  // 64K
  45. #define MAX_CONSECUTIVE_FRAGMENT_LOADS 8     // Do not set to 0
  46. /****************************************************************************
  47.  *  Class CFileSwitcher
  48.  */
  49. /****************************************************************************
  50.  *  Constructor/Destructor
  51.  */
  52. CFileSwitcher::CFileSwitcher(void)
  53.     : m_uMaxChildCount(0)
  54.     , m_uCurrentChildCount(0)
  55.     , m_pHandleTable(NULL)
  56.     , m_ulFlags(0)
  57.     , m_ulSize(0)
  58.     , m_ulChunkSize(0)
  59.     , m_ulProcessedSize(0)
  60.     , m_ulFragmentCount(0)
  61.     , m_bRelative(FALSE)
  62.     , m_pBuffer(NULL)
  63.     , m_pClassFactory(NULL)
  64.     , m_pCurrentHandle(NULL)
  65.     , m_pResponse(NULL)
  66.     , m_pScheduler(NULL)
  67.     , m_State(FSWCHR_Offline)
  68.     , m_lRefCount(0)
  69.     , m_uLastDisownedChild(0)
  70.     , m_bClosing(FALSE)
  71.     , m_CloseStatus(HXR_OK)
  72.     , m_bSyncMode(FALSE)
  73. {
  74.     g_nRefCount_qtff++;
  75. }
  76. CFileSwitcher::~CFileSwitcher()
  77. {
  78.     Reset();
  79.     g_nRefCount_qtff--;
  80. }
  81. /****************************************************************************
  82.  *  IHXFileSwitcher private methods
  83.  */
  84. /****************************************************************************
  85.  *  Reset
  86.  */
  87. inline void CFileSwitcher::Reset(void)
  88. {
  89.     HX_VECTOR_DELETE(m_pHandleTable);
  90.     HX_RELEASE(m_pResponse);
  91.     HX_RELEASE(m_pBuffer);
  92.     HX_RELEASE(m_pClassFactory);
  93.     HX_RELEASE(m_pScheduler);
  94.     m_uCurrentChildCount = 0;
  95. }
  96. /****************************************************************************
  97.  *  HandleFailureAsync
  98.  */
  99. HX_RESULT CFileSwitcher::HandleFailureAsync(HX_RESULT status)
  100. {
  101.     // Asynchronous failures occur only during Read, Write or Seek
  102.     // process while a new FileHandle is beeing formed (since the
  103.     // operation was requested on a file without a handle present
  104.     // in tha HandleTable).
  105.     HX_RESULT retVal;
  106.     HX_ASSERT(status != HXR_OK);
  107.     HX_ASSERT(m_pCurrentHandle);
  108.     HX_RELEASE(m_pBuffer);
  109.     if (m_pCurrentHandle != m_pHandleTable)
  110.     {
  111. m_pCurrentHandle->Clear();
  112. m_uCurrentChildCount--;
  113.     }
  114.     switch (m_State)
  115.     {
  116.     case FSWCHR_ProcRead:
  117. retVal = ReadDone(status, NULL);
  118. break;
  119.     case FSWCHR_ProcSeek:
  120. retVal = SeekDone(status);
  121. break;
  122.     case FSWCHR_ProcWrite:
  123. retVal = WriteDone(status);
  124. break;
  125.     case FSWCHR_ProcAdvise:
  126. retVal = HXR_OK;    // Silent failure
  127. break;
  128.     default:
  129. retVal = HXR_UNEXPECTED;
  130. break;
  131.     }
  132.     return retVal;
  133. }
  134. /****************************************************************************
  135.  *  HandleFailureSync
  136.  */
  137. HX_RESULT CFileSwitcher::HandleFailureSync(HX_RESULT status)
  138. {
  139.     // Synchronous failures may occur during Read, Write, Seek
  140.     // process while a correct FileHandle is preformed and known.
  141.     // Sync. failure also may occur during initalization of this
  142.     // object.
  143.     HX_ASSERT(status != HXR_OK);
  144.     HX_RELEASE(m_pResponse);
  145.     HX_RELEASE(m_pBuffer);
  146.     if (m_State == FSWCHR_ProcInit)
  147.     {
  148. HX_VECTOR_DELETE(m_pHandleTable);
  149. m_State = FSWCHR_Offline;
  150.     }
  151.     else
  152.     {
  153. m_State = FSWCHR_Ready;
  154.     }
  155.     return status;
  156. }
  157. /****************************************************************************
  158.  *  FindFileHandle
  159.  */
  160. inline CFileSwitcher::FileHandle* CFileSwitcher::FindFileHandle(const char* pFileName)
  161. {
  162.     FileHandle* pFileHandle;
  163.     FileHandle* pFreeHandle = NULL;
  164.     UINT16 uChildrenExamined;
  165.     
  166.     if (pFileName == NULL)
  167.     {
  168. return m_pHandleTable;
  169.     }
  170.     
  171.     for (uChildrenExamined = 0, pFileHandle = m_pHandleTable + 1;
  172.  uChildrenExamined < m_uCurrentChildCount;
  173.  pFileHandle++)
  174.     {
  175. if (pFileHandle->m_pFileName)
  176. {
  177.     if (!strcmp(pFileHandle->m_pFileName, pFileName))
  178.     {
  179. return pFileHandle;
  180.     }
  181.     
  182.     uChildrenExamined++;
  183. }
  184. else
  185. {
  186.     pFreeHandle = pFileHandle;
  187. }
  188.     }
  189.     
  190.     if (m_State == FSWCHR_ProcAdvise)
  191.     {
  192. // Do not page-in on attempt to Advise. Advise must be synchronous.
  193. return NULL;
  194.     }
  195.     // Appropriate file handle wasn't found, so find a
  196.     // free one to make a new one
  197.     pFileHandle = pFreeHandle;
  198.     if (m_uCurrentChildCount < m_uMaxChildCount)
  199.     {
  200. pFileHandle = m_pHandleTable + m_uCurrentChildCount + 1;
  201. HX_ASSERT(!pFileHandle->m_pFileName);
  202. HX_ASSERT(!pFileHandle->m_pFileObject);
  203.     }
  204.     // make new handle
  205.     if (pFileHandle)
  206.     {
  207. if (pFileHandle->SetName(pFileName))
  208. {
  209.     m_uCurrentChildCount++;
  210. }
  211. else
  212. {
  213.     pFileHandle = NULL;
  214. }
  215.     }
  216.     return pFileHandle;
  217. }
  218. /****************************************************************************
  219.  *  SelectStaleHandle
  220.  */
  221. inline CFileSwitcher::FileHandle* CFileSwitcher::SelectStaleHandle(void)
  222. {
  223.     FileHandle *pFileHandle = NULL;
  224.     
  225.     // Getting a stale handle is only valid when
  226.     // there is no more room for the child handles
  227.     HX_ASSERT(m_uMaxChildCount == m_uCurrentChildCount);
  228.     if (m_uMaxChildCount > 0)
  229.     {
  230. if (m_uLastDisownedChild < m_uMaxChildCount)
  231. {
  232.     m_uLastDisownedChild++;
  233. }
  234. else
  235. {
  236.     m_uLastDisownedChild = 1;
  237. }
  238. pFileHandle = m_pHandleTable + m_uLastDisownedChild;
  239. HX_ASSERT(pFileHandle->m_pFileName);
  240.     }
  241.     return pFileHandle;
  242. }
  243. /****************************************************************************
  244.  *  GetFileHandle
  245.  */
  246. HX_RESULT CFileSwitcher::GetFileHandle(const char* pFileName)
  247. {
  248.     HX_RESULT retVal;
  249.     m_pCurrentHandle = FindFileHandle(pFileName);
  250.     if (m_pCurrentHandle)
  251.     {
  252. if (m_pCurrentHandle->m_pFileObject)
  253. {
  254.     // A set-up handle exists
  255.     retVal = FileHandleReady();
  256. }
  257. else
  258. {
  259.     IHXGetFileFromSamePool* pFilePool;
  260.     // Handle was made but needs set-up
  261.     HX_ASSERT(m_pHandleTable->m_pFileObject);
  262.     retVal = m_pHandleTable->m_pFileObject->QueryInterface(
  263. IID_IHXGetFileFromSamePool,
  264. (void**) &pFilePool);
  265.     if (SUCCEEDED(retVal))
  266.     {
  267. // Set-up is made by duplicating the root file object
  268. retVal = pFilePool->GetFileObjectFromPool(
  269.     (IHXGetFileFromSamePoolResponse*) this);
  270. pFilePool->Release();
  271.     }
  272. }
  273.     }
  274.     else if (m_State == FSWCHR_ProcAdvise)
  275.     {
  276. // Cannot advise paged-out file object
  277. retVal = HXR_FAIL;
  278.     }
  279.     else
  280.     {
  281. // If the file handle table is full, select a stale
  282. // handle and dispose of it so the room is made for
  283. // the currently needed handle,
  284. if (m_uMaxChildCount == m_uCurrentChildCount)
  285. {
  286.     m_pCurrentHandle = SelectStaleHandle();
  287.     if (m_pCurrentHandle)
  288.     {
  289. m_pCurrentHandle->SetName(pFileName);
  290. retVal = CloseFileHandleObject(m_pCurrentHandle);
  291.     }
  292.     else
  293.     {
  294. retVal = HXR_FAIL;
  295.     }
  296. }
  297. else
  298. {
  299.     // We must be out memory if we failed to find or
  300.     // make a file handle and the file handle table
  301.     // still has slots available.
  302.     retVal = HXR_OUTOFMEMORY;
  303. }
  304.     }
  305.     if (FAILED(retVal))
  306.     {
  307. retVal = HandleFailureSync(retVal);
  308.     }
  309.     return retVal;
  310. }
  311. /****************************************************************************
  312.  *  CloseFileHandle
  313.  */
  314. HX_RESULT CFileSwitcher::CloseFileHandleObject(FileHandle *pFileHandle)
  315. {
  316.     HX_RESULT retVal;
  317.     IHXFileObject *pFileObject;
  318.     HX_ASSERT(pFileHandle);
  319.     pFileObject = pFileHandle->m_pFileObject;
  320.     if (pFileObject)
  321.     {
  322. pFileHandle->m_pFileObject = NULL;
  323. retVal = pFileObject->Close();
  324. pFileObject->Release();
  325.     }
  326.     else
  327.     {
  328. CloseDone(HXR_OK);
  329. retVal = HXR_OK;
  330.     }
  331.     return retVal;
  332. }
  333. /****************************************************************************
  334.  *  FileHandleReady
  335.  */
  336. HX_RESULT CFileSwitcher::FileHandleReady(void)
  337. {
  338.     HX_RESULT retVal;
  339.     HX_ASSERT(m_pCurrentHandle);
  340.     HX_ASSERT(m_pCurrentHandle->m_pFileObject);
  341.     switch (m_State)
  342.     {
  343.     case FSWCHR_ProcRead:
  344. m_ulProcessedSize = 0;
  345. return ProcessRead();
  346.     case FSWCHR_ProcSeek:
  347. return m_pCurrentHandle->m_pFileObject->Seek(m_ulSize, m_bRelative);
  348.     case FSWCHR_ProcWrite:
  349. {
  350.     IHXBuffer* pBuffer;
  351.     HX_RESULT retVal;
  352.     
  353.     HX_ASSERT(m_pBuffer);
  354.     HX_RELEASE(m_pBuffer);
  355.     pBuffer = m_pBuffer;
  356.     m_pBuffer = NULL;
  357.     
  358.     retVal = m_pCurrentHandle->m_pFileObject->Write(pBuffer);
  359.     
  360.     pBuffer->Release();
  361.     
  362.     return retVal;
  363. }
  364.     case FSWCHR_ProcAdvise:
  365. retVal = m_pCurrentHandle->m_pFileObject->Advise(m_ulSize);
  366. if (SUCCEEDED(retVal))
  367. {
  368.     if (m_ulSize == HX_FILEADVISE_SYNCACCESS)
  369.     {
  370. m_bSyncMode = TRUE;
  371.     }
  372.     else if (m_ulSize == HX_FILEADVISE_ASYNCACCESS)
  373.     {
  374. m_bSyncMode = FALSE;
  375.     }
  376. }
  377. m_State = FSWCHR_Ready;
  378. return retVal;
  379.     default:
  380. // nothing to do
  381. break;
  382.     }
  383.     return HXR_UNEXPECTED;
  384. }
  385. /****************************************************************************
  386.  *  ProcessRead
  387.  */
  388. HX_RESULT CFileSwitcher::ProcessRead(void)
  389. {
  390.     ULONG32 ulSize = m_ulSize - m_ulProcessedSize;
  391.     m_ulChunkSize = (ulSize <= MAX_CHUNK_SIZE) ? 
  392.      ulSize : MAX_CHUNK_SIZE;
  393.     return m_pCurrentHandle->m_pFileObject->Read(m_ulChunkSize);
  394. }
  395. /****************************************************************************
  396.  *  ReadNextFragment
  397.  */
  398. HX_RESULT CFileSwitcher::ReadNextFragment(void)
  399. {
  400.     HX_RESULT retVal = HXR_FAIL;
  401.     if ((!m_bClosing) &&
  402. m_pCurrentHandle &&
  403. m_pCurrentHandle->m_pFileObject)
  404.     {
  405. if (m_bSyncMode ||
  406.     (m_ulFragmentCount < MAX_CONSECUTIVE_FRAGMENT_LOADS))
  407. {
  408.     retVal = ProcessRead();
  409. }
  410. else
  411. {
  412.     m_ulFragmentCount = 0;
  413.     retVal = m_pScheduler->RelativeEnter(this, 0);
  414. }
  415.     }
  416.     if (FAILED(retVal))
  417.     {
  418. retVal = ReadDone(HXR_FAIL, NULL);
  419.     }
  420.     return retVal;
  421. }
  422. /****************************************************************************
  423.  *  IHXFileSwitcher methods - Main interface
  424.  */
  425. /****************************************************************************
  426.  *  Init
  427.  */
  428. STDMETHODIMP CFileSwitcher::Init(IHXFileObject* pFileObject,
  429.  ULONG32 ulFlags,
  430.  IHXFileResponse* pResponse,
  431.  IUnknown* pContext,
  432.  UINT16 uMaxChildCount)
  433. {
  434.     HX_RESULT retVal = HXR_OK;
  435.     if (m_State != FSWCHR_Offline)
  436.     {
  437. retVal = HXR_UNEXPECTED;
  438.     }
  439.     if (SUCCEEDED(retVal))
  440.     {
  441. Reset();
  442. HX_ASSERT(pFileObject);
  443. HX_ASSERT(pResponse);
  444. HX_ASSERT(pContext);
  445. m_uMaxChildCount = uMaxChildCount;
  446. m_ulFlags = ulFlags;
  447.     
  448. // First Entry in the table is used as RootHandle
  449. m_pHandleTable = new FileHandle[m_uMaxChildCount + 1];
  450. if (m_pHandleTable == NULL)
  451. {
  452.     retVal = HXR_OUTOFMEMORY;
  453. }
  454.     }
  455.     if (SUCCEEDED(retVal))
  456.     {
  457. retVal = pContext->QueryInterface(
  458.     IID_IHXCommonClassFactory,
  459.     (void**) &m_pClassFactory);
  460.     }
  461.     if (SUCCEEDED(retVal))
  462.     {
  463. retVal = pContext->QueryInterface(
  464.     IID_IHXScheduler, 
  465.     (void**) &m_pScheduler);
  466.     }
  467.     if (SUCCEEDED(retVal))
  468.     {
  469. HX_ASSERT(!m_pResponse);
  470. m_pHandleTable = m_pHandleTable;
  471. m_pHandleTable->m_pFileObject = pFileObject;
  472. pFileObject->AddRef();
  473. m_State = FSWCHR_ProcInit;
  474. m_pResponse = pResponse;
  475. m_pResponse->AddRef();
  476. retVal = pFileObject->Init(m_ulFlags, (IHXFileResponse*) this);
  477. if (FAILED(retVal))
  478. {
  479.     retVal = HandleFailureSync(retVal);
  480. }
  481.     }
  482.     return retVal;
  483. }
  484. /****************************************************************************
  485.  *  Read
  486.  */
  487. STDMETHODIMP CFileSwitcher::Read(ULONG32 ulSize,
  488.  IHXFileResponse* pResponse,
  489.  const char* pFileName)
  490. {
  491.     HX_RESULT retVal = HXR_UNEXPECTED;
  492.     if ((m_State == FSWCHR_Ready) && (!m_bClosing))
  493.     {
  494. HX_ASSERT(!m_pResponse);
  495. m_ulSize = ulSize;
  496. m_pResponse = pResponse;
  497. m_pResponse->AddRef();
  498. m_State = FSWCHR_ProcRead;
  499. retVal = GetFileHandle(pFileName);
  500.     }
  501.     return retVal;
  502. }
  503. /****************************************************************************
  504.  *  Write
  505.  */
  506. STDMETHODIMP CFileSwitcher::Write(IHXBuffer* pBuffer,
  507.   IHXFileResponse* pResponse,
  508.   const char* pFileName)
  509. {
  510.     HX_RESULT retVal = HXR_UNEXPECTED;
  511.     if ((m_State == FSWCHR_Ready) && (!m_bClosing))
  512.     {
  513. HX_ASSERT(!m_pResponse);
  514. HX_ASSERT(!m_pBuffer);
  515. m_pBuffer = pBuffer;
  516. m_pBuffer->AddRef();
  517. m_pResponse = pResponse;
  518. m_pResponse->AddRef();
  519. m_State = FSWCHR_ProcWrite;
  520. retVal = GetFileHandle(pFileName);
  521.     }
  522.     return retVal;
  523. }
  524. /****************************************************************************
  525.  *  Seek
  526.  */
  527. STDMETHODIMP CFileSwitcher::Seek(ULONG32 ulOffset,
  528.  BOOL bRelative,
  529.  IHXFileResponse* pResponse,
  530.  const char* pFileName)
  531. {
  532.     HX_RESULT retVal = HXR_UNEXPECTED;
  533.     if ((m_State == FSWCHR_Ready) && (!m_bClosing))
  534.     {
  535. HX_ASSERT(!m_pResponse);
  536. m_ulSize = ulOffset;
  537. m_bRelative = bRelative;
  538. m_pResponse = pResponse;
  539. m_pResponse->AddRef();
  540. m_State = FSWCHR_ProcSeek;
  541. retVal = GetFileHandle(pFileName);
  542.     }
  543.     return retVal;
  544. }
  545. /****************************************************************************
  546.  *  Advise
  547.  */
  548. STDMETHODIMP CFileSwitcher::Advise(ULONG32 ulInfo,
  549.    const char* pFileName)
  550. {
  551.     HX_RESULT retVal = HXR_UNEXPECTED;
  552.     if ((m_State == FSWCHR_Ready) && (!m_bClosing))
  553.     {
  554. HX_ASSERT(!m_pResponse);
  555. m_ulSize = ulInfo;
  556. m_State = FSWCHR_ProcAdvise;
  557. retVal = GetFileHandle(pFileName);
  558.     }
  559.     return retVal;
  560. }
  561. /****************************************************************************
  562.  *  Close
  563.  */
  564. STDMETHODIMP CFileSwitcher::Close(IHXFileResponse *pResponse,
  565.   const char* pFileName)
  566. {
  567.     HX_RESULT retVal = HXR_UNEXPECTED;
  568.     if ((m_State != FSWCHR_Offline) && (!m_bClosing))
  569.     {
  570. if (pFileName)
  571. {
  572.     // File Specific Closing - must be synchronous
  573.     if (m_State == FSWCHR_Ready)
  574.     {
  575. FileHandle *pFileHandle;
  576. HX_ASSERT(!m_pResponse);
  577. m_pResponse = pResponse;
  578. pResponse->AddRef();
  579. retVal = HXR_OK;
  580. m_State = FSWCHR_ProcClose;
  581. pFileHandle = FindFileHandle(pFileName);
  582. if (pFileHandle)
  583. {
  584.     if (pFileHandle->m_pFileName)
  585.     {
  586. pFileHandle->SetName(NULL);
  587. HX_ASSERT(m_uCurrentChildCount > 0);
  588. m_uCurrentChildCount--;
  589.     }
  590.     
  591.     retVal = CloseFileHandleObject(pFileHandle);
  592. }
  593. else
  594. {
  595.     CloseDone(HXR_OK);
  596. }
  597.     }
  598. }
  599. else
  600. {
  601.     // This is a general closure (shutdown)
  602.     // which need not be synchronous
  603.     UINT16 i;
  604.     FileHandle* pFileHandle;
  605.     
  606.     HX_ASSERT(m_pHandleTable);
  607.     
  608.     retVal = HXR_OK;
  609.     m_bClosing = TRUE;
  610.     m_CloseStatus = HXR_OK;
  611.     HX_RELEASE(m_pResponse);
  612.     m_pResponse = pResponse;
  613.     pResponse->AddRef();
  614.     
  615.     if (m_State == FSWCHR_ProcClose)
  616.     {
  617. // there is an additional outstanding Close to complete 
  618. // for a child
  619. m_uCurrentChildCount++;
  620.     }
  621.     
  622.     // Close Children
  623.     HX_ASSERT(m_uCurrentChildCount <= m_uMaxChildCount);
  624.     
  625.     for (i = m_uCurrentChildCount, pFileHandle = m_pHandleTable + 1;
  626.  i > 0;
  627.  i--, pFileHandle++)
  628.     {
  629. if (pFileHandle->m_pFileName)
  630. {
  631.     pFileHandle->SetName(NULL);
  632.     
  633.     if (FAILED(CloseFileHandleObject(pFileHandle)))
  634.     {
  635. // Recover by forcing the closing on this level
  636. CloseDone(HXR_OK);
  637.     }
  638. }
  639.     }
  640.     // Close the root file
  641.     if (FAILED(CloseFileHandleObject(m_pHandleTable)))
  642.     {
  643. // Recover by forcing the closing on this level
  644. CloseDone(HXR_OK);
  645.     }
  646. }
  647.     }
  648.     return retVal;
  649. }
  650. /****************************************************************************
  651.  *  IHXFileResponse methods
  652.  */
  653. /****************************************************************************
  654.  *  InitDone
  655.  */
  656. STDMETHODIMP CFileSwitcher::InitDone(HX_RESULT status)
  657. {
  658.     HX_RESULT retVal = HXR_OK;
  659.     if (m_State != FSWCHR_Offline)
  660.     {
  661. if (m_State != FSWCHR_ProcInit)
  662. {
  663.     HX_ASSERT(m_pCurrentHandle);
  664.     HX_ASSERT(m_pCurrentHandle->m_pFileObject);
  665.     // This must be initialization completion
  666.     // as part of obtaining file handle during
  667.     // Read, Write or Seek
  668.     if (SUCCEEDED(status))
  669.     {
  670. status = FileHandleReady();
  671.     }
  672.     if (FAILED(status))
  673.     {
  674. m_pCurrentHandle->Clear();
  675. // Must report Failure to the requestor
  676. retVal = HandleFailureAsync(status);
  677.     }
  678. }
  679. else
  680. {
  681.     // Initialization complete
  682.     IHXFileResponse* pResponse = m_pResponse;
  683.     HX_ASSERT(pResponse);
  684.     m_pResponse = NULL;
  685.     if (SUCCEEDED(status))
  686.     {
  687. m_State = FSWCHR_Ready;
  688.     }
  689.     retVal = pResponse->InitDone(status);
  690.     pResponse->Release();
  691. }
  692.     }
  693.     else
  694.     {
  695. retVal = HXR_UNEXPECTED;
  696.     }
  697.     return retVal;
  698. }
  699. /****************************************************************************
  700.  *  CloseDone
  701.  */
  702. STDMETHODIMP CFileSwitcher::CloseDone(HX_RESULT status)
  703. {
  704.     HX_RESULT retVal = HXR_UNEXPECTED;
  705.     if (m_State != FSWCHR_Offline)
  706.     {
  707. if (((m_State == FSWCHR_ProcRead) ||
  708.      (m_State == FSWCHR_ProcWrite) ||
  709.      (m_State == FSWCHR_ProcSeek) ||
  710.      (m_State == FSWCHR_ProcAdvise)) &&
  711.     (!m_bClosing))
  712. {
  713.     // It must be a close due to freeing of a stale
  714.     // file handle so we can create a new one
  715.     retVal = HXR_OK;
  716.     if (SUCCEEDED(status))
  717.     {
  718. IHXGetFileFromSamePool* pFilePool;
  719. // Handle was made but needs set-up
  720. HX_ASSERT(m_pHandleTable->m_pFileObject);
  721. status = m_pHandleTable->m_pFileObject->QueryInterface(
  722.     IID_IHXGetFileFromSamePool,
  723.     (void**) &pFilePool);
  724. if (SUCCEEDED(status))
  725. {
  726.     // Set-up is made by duplicating the root file object
  727.     status = pFilePool->GetFileObjectFromPool(
  728. (IHXGetFileFromSamePoolResponse*) this);
  729.     pFilePool->Release();
  730. }
  731.     }
  732.     
  733.     if (FAILED(status))
  734.     {
  735. retVal = HandleFailureAsync(status);
  736.     }
  737. }
  738. else if ((m_State == FSWCHR_ProcClose) ||
  739.          (m_bClosing))
  740. {
  741.     retVal = HXR_OK;
  742.     if (!m_bClosing || (m_uCurrentChildCount == 0))
  743.     {
  744. // Close completion
  745. IHXFileResponse *pResponse = m_pResponse;
  746. m_pResponse = NULL;
  747. if (m_bClosing)
  748. {
  749.     Reset();
  750.     m_State = FSWCHR_Offline;
  751.     if (FAILED(m_CloseStatus))
  752.     {
  753. status = m_CloseStatus;
  754.     }
  755. }
  756. else
  757. {
  758.     m_State = FSWCHR_Ready;
  759. }
  760. if (pResponse)
  761. {
  762.     retVal = pResponse->CloseDone(status);
  763.     pResponse->Release();
  764. }
  765.     }
  766.     else
  767.     {
  768. // Still Closing files
  769. m_uCurrentChildCount--;
  770. if (SUCCEEDED(m_CloseStatus))
  771. {
  772.     m_CloseStatus = status;
  773. }
  774.     }
  775. }
  776.     }
  777.     return retVal;
  778. }
  779. /****************************************************************************
  780.  *  ReadDone
  781.  */
  782. STDMETHODIMP CFileSwitcher::ReadDone(HX_RESULT status,
  783.      IHXBuffer* pBuffer)
  784. {
  785.     HX_RESULT retVal = HXR_UNEXPECTED;
  786.     if (m_State == FSWCHR_ProcRead)
  787.     {
  788. HX_ASSERT(m_pResponse);
  789. if (m_ulChunkSize == m_ulSize)
  790. {
  791.     IHXFileResponse *pResponse = m_pResponse;
  792.     m_pResponse = NULL;
  793.     m_State = FSWCHR_Ready;
  794.     retVal = pResponse->ReadDone(status, pBuffer);
  795.     pResponse->Release();
  796. }
  797. else
  798. {
  799.     // The read of a fragment is completed
  800.     // Initialize fragment buffer if just starting
  801.     if (SUCCEEDED(status))
  802.     {
  803. if (m_ulProcessedSize == 0)
  804. {
  805.     // Starting the fragmented read - 
  806.     HX_ASSERT(m_pBuffer == NULL);
  807.     HX_ASSERT(m_ulSize != 0);
  808.     
  809.     m_ulFragmentCount = 0;
  810.     HX_RELEASE(m_pBuffer);
  811.     
  812.     status = m_pClassFactory->CreateInstance(
  813. IID_IHXBuffer, 
  814. (void **) &m_pBuffer);
  815.     
  816.     if (SUCCEEDED(status))
  817.     {
  818. status = m_pBuffer->SetSize(m_ulSize);
  819. if (FAILED(status))
  820. {
  821.     HX_RELEASE(m_pBuffer);
  822. }
  823.     }
  824. }
  825.     }
  826.     if (SUCCEEDED(status))
  827.     {
  828. ULONG32 ulSize = pBuffer->GetSize();
  829. memcpy(m_pBuffer->GetBuffer() + m_ulProcessedSize, /* Flawfinder: ignore */
  830.        pBuffer->GetBuffer(),
  831.        ulSize);
  832. m_ulProcessedSize += ulSize;
  833.     }
  834.     if ((m_ulProcessedSize >= m_ulSize) || FAILED(status))
  835.     {
  836. HX_ASSERT(m_ulProcessedSize <= m_ulSize);
  837. if (FAILED(status) && m_pBuffer)
  838. {
  839.     if (m_ulProcessedSize != 0)
  840.     {
  841. // Trim the buffer to what was read successfully
  842. m_pBuffer->SetSize(m_ulProcessedSize);
  843. status = HXR_OK;
  844.     }
  845.     else
  846.     {
  847. HX_RELEASE(m_pBuffer);
  848.     }
  849. }
  850. IHXBuffer* pBuffer = m_pBuffer;
  851. IHXFileResponse *pResponse = m_pResponse;
  852. m_pResponse = NULL;
  853. m_pBuffer = NULL;
  854. m_State = FSWCHR_Ready;
  855. retVal = pResponse->ReadDone(status, pBuffer);
  856. HX_RELEASE(pBuffer);
  857. pResponse->Release();
  858.     }
  859.     else
  860.     {
  861. m_ulFragmentCount++;
  862. retVal = ReadNextFragment();
  863.     }
  864. }
  865.     }
  866.     return retVal;
  867. }
  868. /****************************************************************************
  869.  *  WriteDone
  870.  */
  871. STDMETHODIMP CFileSwitcher::WriteDone(HX_RESULT status)
  872. {
  873.     HX_RESULT retVal = HXR_UNEXPECTED;
  874.     if (m_State == FSWCHR_ProcWrite)
  875.     {
  876. IHXFileResponse *pResponse = m_pResponse;
  877. HX_ASSERT(m_pResponse);
  878. m_pResponse = NULL;
  879. m_State = FSWCHR_Ready;
  880. retVal = pResponse->WriteDone(status);
  881. pResponse->Release();
  882.     }
  883.     return retVal;
  884. }
  885. /****************************************************************************
  886.  *  SeekDone
  887.  */
  888. STDMETHODIMP CFileSwitcher::SeekDone(HX_RESULT status)
  889. {
  890.     HX_RESULT retVal = HXR_UNEXPECTED;
  891.     if (m_State == FSWCHR_ProcSeek)
  892.     {
  893. IHXFileResponse *pResponse = m_pResponse;
  894. HX_ASSERT(m_pResponse);
  895. m_pResponse = NULL;
  896. m_State = FSWCHR_Ready;
  897. retVal = pResponse->SeekDone(status);
  898. pResponse->Release();
  899.     }
  900.     return retVal;
  901. }
  902. /****************************************************************************
  903.  *  IHXCallback methods
  904.  */
  905. /****************************************************************************
  906.  *  Func
  907.  */
  908. STDMETHODIMP CFileSwitcher::Func(void)
  909. {
  910.     HX_RESULT retVal = HXR_UNEXPECTED;
  911.     if (m_State == FSWCHR_ProcRead)
  912.     {
  913. retVal = ReadNextFragment();
  914.     }
  915.     return retVal;
  916. }
  917. /****************************************************************************
  918.  *  IHXThreadSafeMethods method
  919.  */
  920. /****************************************************************************
  921.  *  IsThreadSafe
  922.  */
  923. STDMETHODIMP_(UINT32)
  924. CFileSwitcher::IsThreadSafe()
  925. {
  926.     return HX_THREADSAFE_METHOD_FSR_READDONE;
  927. }
  928. /****************************************************************************
  929.  *  IHXGetFileFromSamePoolResponse method
  930.  */
  931. /****************************************************************************
  932.  *  FileObjectReady
  933.  */
  934. STDMETHODIMP CFileSwitcher::FileObjectReady(HX_RESULT status,
  935.     IUnknown* pFileObject)
  936. {
  937.     HX_RESULT retVal = HXR_UNEXPECTED;
  938.     if (m_State != FSWCHR_Offline)
  939.     {
  940. HX_ASSERT(m_pCurrentHandle);
  941. HX_ASSERT(m_pCurrentHandle->m_pFileName);
  942. HX_ASSERT(!m_pCurrentHandle->m_pFileObject);
  943. if (SUCCEEDED(status))
  944. {
  945.     IHXRequestHandler* pRequestHandler = NULL;
  946.     IHXRequest* pRequest = NULL;
  947.     if (!m_bClosing)
  948.     {
  949. status = pFileObject->QueryInterface(
  950.     IID_IHXFileObject, 
  951.     (void **) &(m_pCurrentHandle->m_pFileObject));
  952.     }
  953.     else
  954.     {
  955. status = HXR_ABORT;
  956.     }
  957.     if (status == HXR_OK)
  958.     {
  959. status = m_pClassFactory->CreateInstance(
  960.     IID_IHXRequest, 
  961.     (void **) &pRequest);
  962.     }
  963.     
  964.     if (status == HXR_OK)
  965.     {
  966. status = pRequest->SetURL(m_pCurrentHandle->m_pFileName);
  967.     }
  968.     if (status == HXR_OK)
  969.     {
  970. status = pFileObject->QueryInterface(
  971.     IID_IHXRequestHandler, 
  972.     (void**) &pRequestHandler);
  973.     }
  974.     
  975.     if (status == HXR_OK)
  976.     {
  977. status = pRequestHandler->SetRequest(pRequest);
  978.     }
  979.     HX_RELEASE(pRequest);
  980.     HX_RELEASE(pRequestHandler);
  981.     
  982.     if (status == HXR_OK)
  983.     {
  984. status = m_pCurrentHandle->m_pFileObject->Init
  985.     (m_ulFlags, 
  986.     (IHXFileResponse*) this);
  987.     }
  988. }
  989. if (status != HXR_OK)
  990. {
  991.     retVal = HandleFailureAsync(status);
  992. }
  993.     }
  994.     return retVal;
  995. }
  996. /****************************************************************************
  997.  *  IUnknown methods
  998.  */
  999. /////////////////////////////////////////////////////////////////////////
  1000. //  Method:
  1001. // IUnknown::QueryInterface
  1002. //
  1003. STDMETHODIMP CFileSwitcher::QueryInterface(REFIID riid, void** ppvObj)
  1004. {
  1005.     if (IsEqualIID(riid, IID_IHXFileSwitcher))
  1006.     {
  1007. AddRef();
  1008. *ppvObj = (IHXFileSwitcher*) this;
  1009. return HXR_OK;
  1010.     }
  1011.     else if (IsEqualIID(riid, IID_IHXCallback))
  1012.     {
  1013.         AddRef();
  1014.         *ppvObj = (IHXCallback*)this;
  1015.         return HXR_OK;
  1016.     }
  1017.     else if (IsEqualIID(riid, IID_IHXGetFileFromSamePoolResponse))
  1018.     {
  1019. AddRef();
  1020. *ppvObj = (IHXGetFileFromSamePoolResponse*) this;
  1021. return HXR_OK;
  1022.     }
  1023.     else if (IsEqualIID(riid, IID_IHXFileResponse))
  1024.     {
  1025. AddRef();
  1026. *ppvObj = (IHXFileResponse*) this;
  1027. return HXR_OK;
  1028.     }
  1029.     else if (IsEqualIID(riid, IID_IUnknown))
  1030.     {
  1031. AddRef();
  1032. *ppvObj = this;
  1033. return HXR_OK;
  1034.     }
  1035.     else if (IsEqualIID(riid, IID_IHXThreadSafeMethods))
  1036.     {
  1037. AddRef();
  1038. *ppvObj = (IHXThreadSafeMethods*) this;
  1039. return HXR_OK;
  1040.     }
  1041.     *ppvObj = NULL;
  1042.     return HXR_NOINTERFACE;
  1043. }
  1044. /////////////////////////////////////////////////////////////////////////
  1045. //  Method:
  1046. // IUnknown::AddRef
  1047. //
  1048. STDMETHODIMP_(ULONG32) CFileSwitcher::AddRef()
  1049. {
  1050.     return InterlockedIncrement(&m_lRefCount);
  1051. }
  1052. /////////////////////////////////////////////////////////////////////////
  1053. //  Method:
  1054. // IUnknown::Release
  1055. //
  1056. STDMETHODIMP_(ULONG32) CFileSwitcher::Release()
  1057. {
  1058.     if (InterlockedDecrement(&m_lRefCount) > 0)
  1059.     {
  1060.         return m_lRefCount;
  1061.     }
  1062.     delete this;
  1063.     return 0;
  1064. }