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

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Version: RCSL 1.0/RPSL 1.0
  3.  *
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved.
  5.  *
  6.  * The contents of this file, and the files included with this file, are
  7.  * subject to the current version of the RealNetworks Public Source License
  8.  * Version 1.0 (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the RealNetworks Community Source License Version 1.0
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
  12.  * in which case the RCSL will apply. You may also obtain the license terms
  13.  * directly from RealNetworks.  You may not use this file except in
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or
  16.  * RCSL for the rights, obligations and limitations governing use of the
  17.  * contents of the file.
  18.  *
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the
  20.  * developer of the Original Code and owns the copyrights in the portions
  21.  * it created.
  22.  *
  23.  * This file, and the files included with this file, is distributed and made
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
  28.  *
  29.  * Technology Compatibility Kit Test Suite(s) Location:
  30.  *    http://www.helixcommunity.org/content/tck
  31.  *
  32.  * Contributor(s):
  33.  *
  34.  * ***** END LICENSE BLOCK ***** */
  35. /////////////////////////////////////////////////////////////////////////////
  36. //
  37. //  Simple File System for simple synchronous local files
  38. //
  39. //  This is a very simple file system, it just calls basic standard lib
  40. //  calls for open, seek, read, etc...
  41. //
  42. #define INITGUID    1
  43. #include "hxcom.h"
  44. #include "hxtypes.h"
  45. #include "../smplfsys.ver"
  46. #include "hxcomm.h"
  47. #include "ihxpckts.h"
  48. #include "hxfiles.h"
  49. #include "hxplugn.h"
  50. #include "hxengin.h"
  51. #include "hxcore.h"
  52. #include "hxprefs.h"
  53. #include "hxrendr.h"
  54. #include "hxmon.h"
  55. #include "hxauth.h"
  56. #include "hxauthn.h"
  57. #include "hxplgns.h"
  58. #include "hxdataf.h"
  59. #include "hxtick.h"
  60. #include "debug.h"
  61. #undef INITGUID
  62. #include "hxathsp.h"
  63. #include "hxcorsp.h"
  64. #include "hxpktsp.h"
  65. #include "hxcomsp.h"
  66. #include "hxplnsp.h"
  67. #include "hxspriv.h"
  68. #include "hlxosstr.h"
  69. #include "timeval.h"
  70. #include "tparse.h"
  71. #include "dbcs.h" // for HXCompareStrings
  72. #include "hxstring.h" // for CHXString
  73. #include "hxxfile.h" // for HXXFile::GetReasonableLocalFileName()
  74. #include "hxstrutl.h"
  75. #include "hxver.h"
  76. #include "chxpckts.h"
  77. #include "hxurl.h"
  78. #include "hxperf.h"
  79. #include "hxcbobj.h"
  80. #include "hxdir.h"
  81. #include <stdio.h>
  82. #include <string.h>
  83. #ifdef _MACINTOSH
  84. #include <fcntl.h>
  85. #include "chxdataf.h" // Macintosh file i/o
  86. #include "macasyncfile.h"  // Macintosh interrupt file i/o
  87. #ifdef _MAC_MACHO
  88. #include <sys/stat.h>
  89. #include "hlxclib/fcntl.h"
  90. #include <unistd.h> // for unlink
  91. #else
  92. #include <unix.h> // for unlink
  93. #endif
  94. #ifdef _UNIX /* including unix.h defines _UNIX */
  95. #undef _UNIX
  96. #endif
  97. #elif (defined (_WINDOWS ) || defined (_WIN32)) && !defined(WIN32_PLATFORM_PSPC)
  98. #include <direct.h>
  99. #include "datffact.h"
  100. #else
  101. #include "hlxclib/sys/types.h"
  102. #include "hlxclib/sys/stat.h"
  103. #include "hlxclib/fcntl.h"
  104. #include "datffact.h"
  105. #endif
  106. #include "findfile.h"
  107. #include "smplmlog.h"
  108. #include "baseobj.h"
  109. #if defined(HELIX_FEATURE_PROGDOWN)
  110. #include "progdown.h"
  111. #include "microsleep.h"
  112. #endif
  113. #include "smplfsys.h"
  114. #include "hxperf.h"
  115. #ifdef _AIX
  116. #include "hxtbuf.h"
  117. #include "dllpath.h"
  118. ENABLE_MULTILOAD_DLLACCESS_PATHS(Smplfsys);
  119. #endif
  120. // same for all the platforms...may need to tweak it, if necessary
  121. #define MAX_ITERATION_COUNT    200
  122. #include "hxheap.h"
  123. #ifdef _DEBUG
  124. #undef HX_THIS_FILE
  125. static const char HX_THIS_FILE[] = __FILE__;
  126. #endif
  127. #ifndef HELIX_CONFIG_NOSTATICS
  128. INT32 smpl_nRefCount = 0;
  129. #endif // HELIX_CONFIG_NOSTATICS
  130. HX_ENABLE_CHECKPOINTS_FOR_MODULE( "SmplFsys", "SmplFsysPerf.log" )
  131. const char* const CSimpleFileSystem::zm_pDescription = "RealNetworks Local File System";
  132. const char* const CSimpleFileSystem::zm_pCopyright = HXVER_COPYRIGHT;
  133. const char* const CSimpleFileSystem::zm_pMoreInfoURL = HXVER_MOREINFO;
  134. const char* const CSimpleFileSystem::zm_pShortName = "pn-local";
  135. const char* const CSimpleFileSystem::zm_pProtocol = "file";
  136. /****************************************************************************
  137.  *
  138.  *  Function:
  139.  *
  140.  * HXCreateInstance()
  141.  *
  142.  *  Purpose:
  143.  *
  144.  * Function implemented by all plugin DLL's to create an instance of
  145.  * any of the objects supported by the DLL. This method is similar to
  146.  * Window's CoCreateInstance() in its purpose, except that it only
  147.  * creates objects from this plugin DLL.
  148.  *
  149.  * NOTE: Aggregation is never used. Therefore and outer unknown is
  150.  * not passed to this function, and you do not need to code for this
  151.  * situation.
  152.  *
  153.  */
  154. STDAPI ENTRYPOINT(HXCREATEINSTANCE)
  155. (
  156.     IUnknown**  /*OUT*/ ppIUnknown
  157. )
  158. {
  159.     // Do NOT check for expiration.  Needed for Auto Upgrade.
  160.     *ppIUnknown = (IUnknown*)(IHXPlugin*)new CSimpleFileSystem();
  161.     if (*ppIUnknown)
  162.     {
  163. (*ppIUnknown)->AddRef();
  164. return HXR_OK;
  165.     }
  166.     return HXR_OUTOFMEMORY;
  167. }
  168. /****************************************************************************
  169.  *
  170.  *  Function:
  171.  *
  172.  * CanUnload()
  173.  *
  174.  *  Purpose:
  175.  *
  176.  * Function implemented by all plugin DLL's if it returns HXR_OK
  177.  * then the pluginhandler can unload the DLL
  178.  *
  179.  */
  180. STDAPI ENTRYPOINT(CanUnload)(void)
  181. {
  182. #ifdef HELIX_CONFIG_NOSTATICS
  183.     return HXR_FAIL;
  184. #else // HELIX_CONFIG_NOSTATICS
  185.     return (smpl_nRefCount ? HXR_FAIL : HXR_OK);
  186. #endif // HELIX_CONFIG_NOSTATICS
  187. }
  188. /****************************************************************************
  189.  *
  190.  *  Function:
  191.  *
  192.  * HXShutdown()
  193.  *
  194.  *  Purpose:
  195.  *
  196.  * Function implemented by all plugin DLL's to free any *global*
  197.  * resources. This method is called just before the DLL is unloaded.
  198.  *
  199.  */
  200. STDAPI ENTRYPOINT(HXSHUTDOWN)(void)
  201. {
  202.     return HXR_OK;
  203. }
  204. CSimpleFileSystem::CSimpleFileSystem()
  205.     : m_lRefCount(0)
  206.     , m_pContext(0)
  207.     , m_options(NULL)
  208.     , m_ulMaxIterationLevel(MAX_ITERATION_COUNT)
  209.     , m_pCommonObj(NULL)
  210.     , m_bDisableMemoryMappedIO(FALSE)
  211.     , m_bEnableFileLocking(FALSE)
  212.     , m_ulChunkSize(0)
  213. {
  214. #ifndef HELIX_CONFIG_NOSTATICS
  215.     smpl_nRefCount++;
  216. #endif // HELIX_CONFIG_NOSTATICS
  217. }
  218. CSimpleFileSystem::~CSimpleFileSystem()
  219. {
  220. #ifndef HELIX_CONFIG_NOSTATICS
  221.     smpl_nRefCount--;
  222. #endif // HELIX_CONFIG_NOSTATICS
  223.     if (m_pContext)
  224.     {
  225. m_pContext->Release();
  226. m_pContext = 0;
  227.     }
  228.     if(m_options)
  229.     {
  230. m_options->Release();
  231. m_options = 0;
  232.     }
  233.     HX_RELEASE(m_pCommonObj);
  234. }
  235. /************************************************************************
  236.  *  Method:
  237.  *    IHXPlugin::InitPlugin
  238.  *  Purpose:
  239.  *    Initializes the plugin for use. This interface must always be
  240.  *    called before any other method is called. This is primarily needed
  241.  *    so that the plugin can have access to the context for creation of
  242.  *    IHXBuffers and IMalloc.
  243.  */
  244. STDMETHODIMP CSimpleFileSystem::InitPlugin(IUnknown* /*IN*/ pContext)
  245. {
  246.     HX_LOG_BLOCK( "CSimpleFileSystem::InitPlugin" );
  247.     HX_RESULT lResult;
  248.     IHXPreferences* prefs = 0;
  249.     IHXBuffer* base_path_buf = 0;
  250.     if (pContext && !m_pContext)
  251.     {
  252.         m_pContext = pContext;
  253. m_pContext->AddRef();
  254. IHXRegistry* pReg = NULL;
  255. if (m_pContext->QueryInterface(IID_IHXRegistry, (void**)&pReg) == HXR_OK)
  256. {
  257.     INT32 lCS = 0;
  258.     if (HXR_OK == pReg->GetIntByName("config.MMapChunkSize", lCS) && lCS)
  259.     {
  260. m_ulChunkSize = lCS;
  261.     }
  262.     pReg->Release();
  263. }
  264. if(!m_options ||
  265.    (HXR_OK != m_options->GetPropertyBuffer("BasePath", base_path_buf)))
  266. {
  267.     lResult = pContext->QueryInterface(IID_IHXPreferences,
  268.        (void**) &prefs);
  269.     if (lResult == HXR_OK)
  270.     {
  271. lResult = prefs->ReadPref("BasePath", base_path_buf);
  272. if (lResult == HXR_OK)
  273. {
  274.     m_base_path = CHXString((char*)base_path_buf->GetBuffer());
  275. }
  276.     }
  277. }
  278. else
  279. {
  280.     m_base_path = CHXString((char*)base_path_buf->GetBuffer());
  281. }
  282.     }
  283.     if (prefs)
  284.     {
  285. prefs->Release();
  286. prefs = 0;
  287.     }
  288.     if (base_path_buf)
  289.     {
  290. base_path_buf->Release();
  291. base_path_buf = 0;
  292.     }
  293.     IHXGetRecursionLevel* pGet;
  294.     lResult = pContext->QueryInterface(IID_IHXGetRecursionLevel,
  295.        (void**) &pGet);
  296.     if (lResult == HXR_OK)
  297.     {
  298. m_ulMaxIterationLevel = pGet->GetRecursionLevel();
  299. pGet->Release();
  300.     }
  301.     return HXR_OK;
  302. }
  303. /************************************************************************
  304.  *  Method:
  305.  *    IHXPlugin::GetPluginInfo
  306.  *  Purpose:
  307.  *    Returns the basic information about this plugin. Including:
  308.  *
  309.  *    unInterfaceCount the number of standard RMA interfaces
  310.  * supported by this plugin DLL.
  311.  *    pIIDList array of IID's for standard RMA interfaces
  312.  * supported by this plugin DLL.
  313.  *    bLoadMultiple whether or not this plugin DLL can be loaded
  314.  * multiple times. All File Formats must set
  315.  * this value to TRUE.
  316.  *    pDescription which is used in about UIs (can be NULL)
  317.  *    pCopyright which is used in about UIs (can be NULL)
  318.  *    pMoreInfoURL which is used in about UIs (can be NULL)
  319.  */
  320. STDMETHODIMP CSimpleFileSystem::GetPluginInfo
  321. (
  322.     REF(BOOL)        /*OUT*/ bLoadMultiple,
  323.     REF(const char*) /*OUT*/ pDescription,
  324.     REF(const char*) /*OUT*/ pCopyright,
  325.     REF(const char*) /*OUT*/ pMoreInfoURL,
  326.     REF(ULONG32)     /*OUT*/ ulVersionNumber
  327. )
  328. {
  329.     bLoadMultiple = TRUE;
  330.     pDescription    = zm_pDescription;
  331.     pCopyright     = zm_pCopyright;
  332.     pMoreInfoURL    = zm_pMoreInfoURL;
  333.     ulVersionNumber = TARVER_ULONG32_VERSION;
  334.     return HXR_OK;
  335. }
  336. // *** IUnknown methods ***
  337. /////////////////////////////////////////////////////////////////////////
  338. //  Method:
  339. // IUnknown::QueryInterface
  340. //  Purpose:
  341. // Implement this to export the interfaces supported by your
  342. // object.
  343. //
  344. STDMETHODIMP CSimpleFileSystem::QueryInterface(REFIID riid, void** ppvObj)
  345. {
  346.     QInterfaceList qiList[] =
  347.     {
  348. { GET_IIDHANDLE(IID_IUnknown), this },
  349. { GET_IIDHANDLE(IID_IHXPlugin), (IHXPlugin*) this },
  350. { GET_IIDHANDLE(IID_IHXFileSystemObject), (IHXFileSystemObject*) this },
  351.     };
  352.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  353. }
  354. /////////////////////////////////////////////////////////////////////////
  355. //  Method:
  356. // IUnknown::AddRef
  357. //  Purpose:
  358. // Everyone usually implements this the same... feel free to use
  359. // this implementation.
  360. //
  361. STDMETHODIMP_(ULONG32) CSimpleFileSystem::AddRef()
  362. {
  363.     return InterlockedIncrement(&m_lRefCount);
  364. }
  365. /////////////////////////////////////////////////////////////////////////
  366. //  Method:
  367. // IUnknown::Release
  368. //  Purpose:
  369. // Everyone usually implements this the same... feel free to use
  370. // this implementation.
  371. //
  372. STDMETHODIMP_(ULONG32) CSimpleFileSystem::Release()
  373. {
  374.     if (InterlockedDecrement(&m_lRefCount) > 0)
  375.     {
  376.         return m_lRefCount;
  377.     }
  378.     delete this;
  379.     return 0;
  380. }
  381. STDMETHODIMP CSimpleFileSystem::GetFileSystemInfo
  382. (
  383.     REF(const char*) /*OUT*/ pShortName,
  384.     REF(const char*) /*OUT*/ pProtocol
  385. )
  386. {
  387.     pShortName = zm_pShortName;
  388.     pProtocol = zm_pProtocol;
  389.     return HXR_OK;
  390. }
  391. STDMETHODIMP
  392. CSimpleFileSystem::InitFileSystem(IHXValues* options)
  393. {
  394.     HX_LOG_BLOCK( "CSimpleFileSystem::InitFileSystem" );
  395.     IHXBuffer* base_path_buf = 0;
  396.     m_options = options;
  397.     if (m_options)
  398.     {
  399. m_options->AddRef();
  400. if (HXR_OK == m_options->GetPropertyBuffer("BasePath", base_path_buf))
  401. {
  402.     m_base_path = CHXString((char*)base_path_buf->GetBuffer());
  403. }
  404. ULONG32 ulTemp = 0;
  405. BOOL bLog = FALSE;
  406. /*
  407.          *  XXX PM this is weak.  I need a way to show these options
  408.  *  but only if explicitly asked to do so.  Ideally we would
  409.  *  use the IRMErrorMessages with HXLOG_DEBUG and --sdm for
  410.  *  server but I can't here because no context gets passed
  411.  *  to file system object until its first connection.
  412.  *  Can you believe that?
  413.  */
  414. m_options->GetPropertyULONG32("LogOptionalParams",
  415. ulTemp);
  416. bLog = ulTemp ? TRUE : FALSE;
  417. ulTemp = 0;
  418. m_options->GetPropertyULONG32("DisableMemoryMappedIO",
  419.     ulTemp);
  420. m_bDisableMemoryMappedIO = ulTemp ? TRUE : FALSE;
  421. ulTemp = 0;
  422. m_options->GetPropertyULONG32("EnableFileLocking",
  423. ulTemp);
  424. m_bEnableFileLocking = ulTemp ? TRUE : FALSE;
  425. ulTemp = 0;
  426. m_options->GetPropertyULONG32("MaxIterationLevel", ulTemp);
  427. if (ulTemp)
  428. {
  429.             m_ulMaxIterationLevel = ulTemp;
  430. }
  431. if (bLog)
  432. {
  433.     char pNumericMount[50]; /* Flawfinder: ignore */
  434.     IHXBuffer* pBuffer = 0;
  435.     const char* pMount;
  436.     m_options->GetPropertyCString("MountPoint", pBuffer);
  437.     if (!pBuffer)
  438.     {
  439. m_options->GetPropertyBuffer("MountPoint", pBuffer);
  440. if (!pBuffer)
  441. {
  442.     m_options->GetPropertyULONG32("MountPount", ulTemp);
  443. }
  444.     }
  445.     if (pBuffer)
  446.     {
  447. pMount = (const char*)pBuffer->GetBuffer();
  448.     }
  449.     else
  450.     {
  451. pMount = pNumericMount;
  452. sprintf(pNumericMount, "%lu", ulTemp); /* Flawfinder: ignore */
  453.     }
  454.     printf("Optional smplfsys (pn-local) parameters for"
  455.     " MountPoint: %sn", pMount);
  456.     HX_RELEASE(pBuffer);
  457.     printf("DisableMemoryMappedIO: %sn",
  458.     m_bDisableMemoryMappedIO ? "TRUE" : "FALSE");
  459.     printf("EnableFileLocking: %sn",
  460.     m_bEnableFileLocking ? "TRUE" : "FALSE");
  461.     printf("MaxIterationLevel: %lun",
  462.     m_ulMaxIterationLevel);
  463.     ulTemp = 0;
  464.     m_options->GetPropertyULONG32("MMapChunkSize", ulTemp);
  465.     if (ulTemp)
  466.     {
  467. printf("MMapChunkSize: %lun", ulTemp);
  468.     }
  469. }
  470.     }
  471.     if (base_path_buf)
  472.     {
  473. base_path_buf->Release();
  474.     }
  475.     return HXR_OK;
  476. }
  477. /////////////////////////////////////////////////////////////////////////
  478. //  Method:
  479. // IHXFileSystemObject::CreateFile
  480. //  Purpose:
  481. // TBD
  482. //
  483. STDMETHODIMP CSimpleFileSystem::CreateFile
  484. (
  485.     IUnknown** /*OUT*/ ppFileObject
  486. )
  487. {
  488.     HX_LOG_BLOCK( "CSimpleFileSystem::CreateFile" );
  489.     CSimpleFileObject* pFileObj =
  490. new CSimpleFileObject(m_base_path,
  491.       this,
  492.       m_pContext,
  493.       m_ulMaxIterationLevel);
  494.     if (pFileObj)
  495.     {
  496. if (HXR_OK == pFileObj->QueryInterface(IID_IUnknown,
  497.     (void**)ppFileObject))
  498. {
  499.     return HXR_OK;
  500. }
  501. return HXR_UNEXPECTED;
  502.     }
  503.     return HXR_OUTOFMEMORY;
  504. }
  505. /////////////////////////////////////////////////////////////////////////
  506. //  Method:
  507. // CSimpleFileSystem::CreateDir
  508. //  Purpose:
  509. // TBD
  510. //
  511. STDMETHODIMP CSimpleFileSystem::CreateDir
  512. (
  513.     IUnknown** /*OUT*/ ppDirObject
  514. )
  515. {
  516.     return HXR_NOTIMPL;
  517. }
  518. CSimpleFileObject::CSimpleFileObject(CHXString& base_path,
  519.      CSimpleFileSystem *pFS,
  520.      IUnknown* pContext,
  521.      UINT32 ulMaxIterationLevel)
  522.     : m_lRefCount(0)
  523.     , m_ulFlags(0)
  524.     , m_bLocalClose(FALSE)
  525.     , m_pContext(pContext)
  526.     , m_pCommonClassFactory(NULL)
  527.     , m_pFileResponse(NULL)
  528.     , m_pFileSystem(pFS)
  529.     , m_pFilename(NULL)
  530.     , m_pRequest(0)
  531.     , m_pDescriptorReg(0)
  532.     , m_pDirResponse(NULL)
  533.     , m_pDirList(NULL)
  534.     , m_pScheduler(NULL)
  535.     , m_pStackCallback(NULL)
  536.     , m_bInRead(FALSE)
  537.     , m_bReadPending(FALSE)
  538.     , m_bAsyncReadPending(FALSE)
  539.     , m_ulPendingReadCount(0)
  540.     , m_ulSize(0)
  541.     , m_ulPos(0)
  542.     , m_bAsyncAccess(TRUE)
  543.     , m_bCanBeReOpened(0)
  544. #ifdef _MACINTOSH
  545.     , m_pDataFile(NULL)
  546.     , m_pAsyncFileResponse(NULL)
  547.     , m_pInterruptState(NULL)
  548.     , m_pFileStatResponse(NULL)
  549.     , m_eSeekReason(EXTERNAL_SEEK)
  550.     , m_ulPreSeekPosition(0)
  551.     , m_bFileToBeClosed(FALSE)
  552. #endif
  553.     , m_nFd(-1)
  554.     , m_ulMaxIterationLevel(ulMaxIterationLevel)
  555.     , m_pUnknownUserContext(NULL)
  556.     , m_ulPendingSeekOffset(0)
  557.     , m_usPendingSeekWhence(SEEK_SET)
  558. #if defined(HELIX_FEATURE_PROGDOWN)
  559.     , m_pProgDownMon(NULL)
  560.     , m_ulCallbackState(CallbackStateUnknown)
  561.     , m_bProgDownEnabled(TRUE)
  562. #endif /* #if defined(HELIX_FEATURE_PROGDOWN) */
  563. {
  564.     MLOG_LEAK("CON CSimpleFileObject this=0x%08xn", this);
  565. #ifndef HELIX_CONFIG_NOSTATICS
  566.     smpl_nRefCount++;
  567. #endif //  HELIX_CONFIG_NOSTATICS
  568.     m_base_path = base_path;
  569.     if (m_pFileSystem)
  570.     {
  571. m_pFileSystem->AddRef();
  572.     }
  573.     if (m_pContext)
  574.     {
  575. m_pContext->AddRef();
  576. #ifdef USE_THREADSAFE_SCHEDULER
  577. m_pContext->QueryInterface(IID_IHXThreadSafeScheduler, (void**) &m_pScheduler);
  578. if (!m_pScheduler)
  579. {
  580.     m_pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
  581. }
  582. #else
  583. m_pContext->QueryInterface(IID_IHXScheduler, (void**) &m_pScheduler);
  584. #endif //USE_THREADSAFE_SCHEDULER
  585. #if !defined _MACINTOSH
  586. IHXDataFileFactory* pDFFact = new HXDataFileFactory;;
  587. pDFFact->AddRef();
  588. {
  589.     DPRINTF(0x5d000000, ("CSFO::CSFO() -- after QIn"));
  590.     {
  591. pDFFact->CreateFile(m_pDataFile, m_pContext,
  592.     pFS->m_pCommonObj, pFS->m_bDisableMemoryMappedIO,
  593.     pFS->m_ulChunkSize, pFS->m_bEnableFileLocking,
  594.     TRUE);  // Always prefer async I/O
  595. if (!m_pDataFile)
  596. {
  597. #ifndef _WIN16
  598.     DPRINTF(0x5d000000, ("Internal Error s/546n"));
  599. #endif
  600.     pDFFact->Release();
  601.     return;
  602. }
  603.     }
  604. }
  605. pDFFact->Release();
  606. #endif /* !defined _MACINTOSH */
  607. m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  608.    (void **)&m_pCommonClassFactory);
  609.     }
  610.     m_pStackCallback = new CHXGenericCallback(this, CSimpleFileObject::StackCallback);
  611.     if (m_pStackCallback)
  612.     {
  613.         m_pStackCallback->AddRef();
  614.     }
  615. #if defined (_MACINTOSH)
  616.     m_pAsyncFileResponse = new SMPLAsyncResponse(this);
  617.     if (m_pContext)
  618.     {
  619. m_pContext->QueryInterface(IID_IHXInterruptState, (void**) &m_pInterruptState);
  620.     }
  621. #endif
  622. #if defined(HELIX_FEATURE_PROGDOWN)
  623.     m_pProgDownMon = new CProgressiveDownloadMonitor();
  624. #endif /* #if defined(HELIX_FEATURE_PROGDOWN) */
  625. };
  626. CSimpleFileObject::~CSimpleFileObject()
  627. {
  628.     MLOG_LEAK("DES CSimpleFileObject this=0x%08xn", this);
  629. #ifndef HELIX_CONFIG_NOSTATICS
  630.     smpl_nRefCount--;
  631. #endif  // HELIX_CONFIG_NOSTATICS
  632.     m_bLocalClose = TRUE;
  633.     Close();
  634. };
  635. // *** IUnknown methods ***
  636. /////////////////////////////////////////////////////////////////////////
  637. //  Method:
  638. // IUnknown::QueryInterface
  639. //  Purpose:
  640. // Implement this to export the interfaces supported by your
  641. //   object.
  642. //
  643. STDMETHODIMP CSimpleFileObject::QueryInterface(REFIID riid, void** ppvObj)
  644. {
  645.     QInterfaceList qiList[] =
  646.     {
  647. { GET_IIDHANDLE(IID_IUnknown), this },
  648. { GET_IIDHANDLE(IID_IHXFileObject), (IHXFileObject*) this },
  649. { GET_IIDHANDLE(IID_IHXDirHandler), (IHXDirHandler*) this },
  650. { GET_IIDHANDLE(IID_IHXFileStat), (IHXFileStat*) this },
  651. { GET_IIDHANDLE(IID_IHXFileExists), (IHXFileExists*) this },
  652. { GET_IIDHANDLE(IID_IHXGetFileFromSamePool), (IHXGetFileFromSamePool*) this },
  653. { GET_IIDHANDLE(IID_IHXRequestHandler), (IHXRequestHandler*) this },
  654. { GET_IIDHANDLE(IID_IHXFileRename), (IHXFileRename*) this },
  655. { GET_IIDHANDLE(IID_IHXFileRemove), (IHXFileRemove*) this },
  656. { GET_IIDHANDLE(IID_IHXFileMove), (IHXFileMove*) this },
  657. { GET_IIDHANDLE(IID_IHXThreadSafeMethods), (IHXThreadSafeMethods*) this },
  658.     };
  659.     return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
  660. }
  661. /////////////////////////////////////////////////////////////////////////
  662. //  Method:
  663. // IUnknown::AddRef
  664. //  Purpose:
  665. // Everyone usually implements this the same... feel free to use
  666. // this implementation.
  667. //
  668. STDMETHODIMP_(ULONG32) CSimpleFileObject::AddRef()
  669. {
  670.     return InterlockedIncrement(&m_lRefCount);
  671. }
  672. /////////////////////////////////////////////////////////////////////////
  673. //  Method:
  674. // IUnknown::Release
  675. //  Purpose:
  676. // Everyone usually implements this the same... feel free to use
  677. // this implementation.
  678. //
  679. STDMETHODIMP_(ULONG32) CSimpleFileObject::Release()
  680. {
  681.     if (InterlockedDecrement(&m_lRefCount) > 0)
  682.     {
  683. return m_lRefCount;
  684.     }
  685.     delete this;
  686.     return 0;
  687. }
  688. /************************************************************************
  689.  *  Method:
  690.  * IHXFileObject::Init
  691.  *  Purpose:
  692.  * Associates a file object with the file response object it should
  693.  * notify of operation completness. This method should also check
  694.  * for validity of the object (for example by opening it if it is
  695.  * a local file).
  696.  */
  697. STDMETHODIMP
  698. CSimpleFileObject::Init
  699. (
  700.     ULONG32 /*IN*/ ulFlags,
  701.     IHXFileResponse*   /*IN*/ pFileResponse
  702. )
  703. {
  704.     MLOG_GEN(NULL, "CSimpleFileObject::Init(0x%08x,0x%08x) this=0x%08xn",
  705.              ulFlags, pFileResponse, this);
  706.     HX_LOG_BLOCK( "CSimpleFileObject::Init" );
  707.     DPRINTF(0x5d000000, ("CSFO::Init(flags(0x%x), pFileResponse(%p)) "
  708.     "-- fd(%d)n", ulFlags, pFileResponse, m_nFd));
  709.     HX_RESULT lReturnVal = HXR_OK;
  710.     HX_RESULT resultInitDone = HXR_OK;
  711.     IHXRequestContext* pIHXRequestContextCurrent = NULL;
  712.     if (!pFileResponse) return HXR_INVALID_PARAMETER;
  713.     if (!m_pRequest) return HXR_INVALID_PARAMETER;
  714.     /* Release any previous reponses */
  715.     if (m_pFileResponse)
  716.     {
  717. m_pFileResponse->Release();
  718.     }
  719.     m_pFileResponse = pFileResponse;
  720.     m_pFileResponse->AddRef();
  721.     /* have we already opened/created a file */
  722.     if (m_nFd != -1)
  723.     {
  724. m_bReadPending      = FALSE;
  725. m_ulPendingReadCount = 0;
  726. /* remove any pending callbacks */
  727.         if (m_pStackCallback) m_pStackCallback->Cancel(m_pScheduler);
  728. /* if flags are same, then we are all set and there
  729.  * is no need to do anything further
  730.  */
  731. if (m_ulFlags == ulFlags || ulFlags == 0)
  732. {
  733.     /* If we have already opened a file, then seek back
  734.      * to zero during re-initialization
  735.      */
  736. #ifndef _MACINTOSH
  737.     HX_RESULT result = m_pDataFile->Seek(0, SEEK_SET);
  738.     m_pFileResponse->InitDone(result);
  739.     return result;
  740. #else
  741.     BOOL bAtInterrupt = FALSE;
  742.     if (m_pInterruptState)
  743.     {
  744. bAtInterrupt = m_pInterruptState->AtInterruptTime();
  745.     }
  746.     /* I want to know if we ever reach here at interrupt time
  747.      * Please e-mail me a repro case if you hit this assert
  748.      * - RA
  749.      */
  750.     HX_ASSERT(bAtInterrupt == FALSE);
  751.     m_eSeekReason = REINIT_SEEK;
  752.     HX_RESULT theResult = m_pDataFile->SafeSeek(0, SEEK_SET, bAtInterrupt);
  753.     if (theResult != HXR_OK)
  754.     {
  755. m_pFileResponse->InitDone(HXR_FAIL);
  756.     }
  757.     return theResult;
  758. #endif
  759.     /*
  760.     m_pFileResponse->InitDone(HXR_OK);
  761.     return HXR_OK;
  762.     */
  763. }
  764. #ifdef _MACINTOSH
  765. HX_RELEASE(m_pDataFile);
  766. m_pDataFile = NULL;
  767. #else
  768. DPRINTF(0x5d000000, ("CSFO::Init() -- m_pDataFile->Close()n"));
  769.         if (m_pDescriptorReg)
  770. {
  771.     m_pDescriptorReg->UnRegisterDescriptors(1);
  772. }
  773.         m_pDataFile->Close();
  774. m_nFd = -1;
  775. #endif
  776.     }
  777.     m_ulFlags = ulFlags;
  778.     if (!m_pCommonClassFactory)
  779.     {
  780. m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  781.                                     (void **)&m_pCommonClassFactory);
  782.     }
  783.     HX_RELEASE(m_pUnknownUserContext);
  784.     if (m_pRequest && SUCCEEDED(m_pRequest->QueryInterface(
  785. IID_IHXRequestContext, (void**)&pIHXRequestContextCurrent)))
  786.     {
  787. pIHXRequestContextCurrent->GetUserContext(m_pUnknownUserContext);
  788. pIHXRequestContextCurrent->Release();
  789.     }
  790.     DPRINTF(0x5d000000, ("CSFO::Init() -- (2) _OpenFile()n"));
  791.     lReturnVal = _OpenFile(ulFlags);
  792.     DPRINTF(0x5d000000, ("CSFO::Init(flags(0x%x), pFileResponse(%p)) "
  793.     "-- result(0x%x), m_nFd(%d)n",
  794.     ulFlags, pFileResponse, lReturnVal, m_nFd));
  795.     if ((m_nFd == -1 || FAILED(lReturnVal)))
  796.     {
  797. // XXXSSH -- probably obsolete
  798. if (lReturnVal != HXR_NOT_AUTHORIZED)
  799. {
  800.     lReturnVal = HXR_DOC_MISSING;
  801. }
  802.     }
  803.     else
  804.     {
  805. lReturnVal = HXR_OK;
  806.     }
  807. #if defined(HELIX_FEATURE_PROGDOWN)
  808.     // If we are writing to the file, then disable
  809.     // the progressive download features
  810.     m_bProgDownEnabled = (m_ulFlags & HX_FILE_WRITE ? FALSE : TRUE);
  811.     if (m_pProgDownMon && m_bProgDownEnabled)
  812.     {
  813.         m_pProgDownMon->Init(m_pContext, m_pDataFile, this);
  814.     }
  815. #endif /* #if defined(HELIX_FEATURE_PROGDOWN) */
  816.     resultInitDone =
  817. m_pFileResponse->InitDone(lReturnVal);
  818.     lReturnVal = resultInitDone;
  819.     DPRINTF(0x5d000000, ("CSFO::Init() "
  820.     "-- resultInitDone(0x%x), m_nFd(%d)n",
  821.     resultInitDone, m_nFd));
  822.     return (lReturnVal);
  823. }
  824. /************************************************************************
  825.  *  Method:
  826.  *      IHXFileObject::GetFilename
  827.  *  Purpose:
  828.  *      Returns the filename (without any path information) associated
  829.  *      with a file object.
  830.  */
  831. STDMETHODIMP CSimpleFileObject::GetFilename
  832. (
  833.     REF(const char*) /*OUT*/ pFilename
  834. )
  835. {
  836.     UpdateFileNameMember();
  837.     // Find the separator character before the file name
  838.     pFilename = ::strrchr(m_pFilename, OS_SEPARATOR_CHAR);
  839.     if (pFilename != NULL) // Found
  840.     {
  841. // File name starts after the separator charactor
  842. pFilename++;
  843.     }
  844.     else // Not found
  845.     {
  846. pFilename = m_pFilename;
  847.     }
  848.     return HXR_OK;
  849. }
  850. /************************************************************************
  851.  *  Method:
  852.  * IHXFileObject::Close
  853.  *  Purpose:
  854.  * Closes the file resource and releases all resources associated
  855.  * with the object.
  856.  */
  857. STDMETHODIMP CSimpleFileObject::Close()
  858. {
  859.     MLOG_GEN(NULL, "CSimpleFileObject::Close() this=0x%08xn", this);
  860.     HX_LOG_BLOCK( "CSimpleFileObject::Close" );
  861.     // If there is a pending callback, be sure to remove it!
  862.     if (m_pStackCallback) m_pStackCallback->Cancel(m_pScheduler);
  863.     HX_RELEASE(m_pStackCallback);
  864.     HX_RELEASE(m_pScheduler);
  865.     HX_RELEASE(m_pUnknownUserContext);
  866.     if (m_pContext)
  867.     {
  868. m_pContext->Release();
  869. m_pContext = NULL;
  870.     }
  871.     if (m_pCommonClassFactory)
  872.     {
  873. m_pCommonClassFactory->Release();
  874. m_pCommonClassFactory = NULL;
  875.     }
  876.     if (m_pFileSystem)
  877.     {
  878. m_pFileSystem->Release();
  879. m_pFileSystem = NULL;
  880.     }
  881.     if (m_pRequest)
  882.     {
  883. m_pRequest->Release();
  884. m_pRequest = NULL;
  885.     }
  886.     if (m_pDescriptorReg && (m_nFd != -1))
  887.     {
  888. m_pDescriptorReg->UnRegisterDescriptors(1);
  889. m_pDescriptorReg->Release();
  890. m_pDescriptorReg = 0;
  891.     }
  892. #if defined(HELIX_FEATURE_PROGDOWN)
  893.     // XXXMEH
  894.     // IMPORTANT!!
  895.     // Since the progressive download monitor does now not
  896.     // hold a ref on m_pDataFile, then we MUST make sure
  897.     // and call m_pProgDownMon->Close() BEFORE we close
  898.     // and release m_pDataFile. This is because there could
  899.     // be pending callbacks which will attempt to use
  900.     // the IHXDataFile. Callling m_pProgDownMon->Close()
  901.     // will cancel these pending callbacks.
  902.     if (m_pProgDownMon)
  903.     {
  904.         // Close the progressive download monitor. Closing
  905.         // also cancels any pending callbacks
  906.         m_pProgDownMon->Close();
  907.     }
  908.     HX_DELETE(m_pProgDownMon);
  909. #endif /* #if defined(HELIX_FEATURE_PROGDOWN) */
  910.     if (m_pDataFile)
  911.     {
  912. #if defined _MACINTOSH
  913.     HX_RELEASE(m_pDataFile);
  914.     HX_DELETE(m_pAsyncFileResponse);
  915.     HX_RELEASE(m_pInterruptState);
  916.     HX_RELEASE(m_pFileStatResponse);
  917. #else
  918. DPRINTF(0x5d000000, ("CSFO::Close() -- m_pDataFile->Close()n"));
  919. m_pDataFile->Close();
  920. HX_RELEASE(m_pDataFile);
  921. #endif
  922.     }
  923.     m_nFd = -1;
  924.     if(m_pFilename)
  925.     {
  926. HX_VECTOR_DELETE(m_pFilename);
  927. m_pFilename = NULL;
  928.     }
  929.     if (m_pDirResponse)
  930.     {
  931. m_pDirResponse->Release();
  932. m_pDirResponse = NULL;
  933.     }
  934.     if (m_pDirList)
  935.     {
  936. delete m_pDirList;
  937. m_pDirList = NULL;
  938.     }
  939.     // Make sure we do not attempt to schedule any more replies which
  940.     // would result in a crash after this point
  941.     m_bReadPending = FALSE;
  942. // It is vitally important that the CloseDone be the last step in
  943.     // this method, as the last reference to this object may be
  944.     // released inside CloseDone!  Do not place code after this if block!
  945.     // MBO: Access to stack variables after CloseDone is OK.
  946.     if (!m_bLocalClose)
  947.     {
  948. if(m_pFileResponse)
  949. {
  950.     // This keeps us from getting into an infinite loop when
  951.     // CSimpleFileObject::Close() calls m_pFileResponse->Release()
  952.     // which calls ~CRIFFReader() which calls Close() and so on,
  953.     // never hitting the line that sets m_pFileResponse to NULL...
  954.     IHXFileResponse* pTempFileResponse = m_pFileResponse;
  955.     m_pFileResponse = NULL;
  956.     pTempFileResponse->CloseDone(HXR_OK);
  957.     pTempFileResponse->Release();
  958.         }
  959.     }
  960.     else if (m_pFileResponse)
  961.     {
  962. m_pFileResponse->Release();
  963. m_pFileResponse = NULL;
  964.     }
  965.     return HXR_OK;
  966. }
  967. /************************************************************************
  968.  *  Method:
  969.  * IHXFileObject::Read
  970.  *  Purpose:
  971.  * Reads a buffer of data of the specified length from the file
  972.  * and asynchronously returns it to the caller via the
  973.  * IHXFileResponse interface passed in to Init.
  974.  */
  975. STDMETHODIMP CSimpleFileObject::Read(ULONG32 ulCount)
  976. {
  977.     MLOG_GEN(NULL, "CSimpleFileObject::Read(%lu) this=0x%08x tick=%lun",
  978.              ulCount, this, HX_GET_BETTERTICKCOUNT());
  979.     HX_LOG_BLOCK( "CSimpleFileObject::Read" );
  980.     // XXXBHG, For now, you cant read more than 1MB at a time!
  981.     if (ulCount > 0x000FFFFF)
  982.     {
  983. //Force the system to recognize a failed Read so infinite
  984. // buffering does not occur with the core waiting for EOF:
  985. ActualAsyncReadDone(HXR_FAIL, NULL);
  986. return HXR_INVALID_PARAMETER;
  987.     }
  988.     if((m_nFd == -1) && m_bCanBeReOpened)
  989.     {
  990. DPRINTF(0x5d000000, ("CSFO::Read() -- _OpenFile()n"));
  991. _OpenFile(m_ulFlags);
  992. m_bCanBeReOpened = FALSE;
  993. #ifndef _MACINTOSH
  994. m_pDataFile->Seek(m_ulPos, SEEK_SET);
  995. #endif
  996.     }
  997.     if (m_nFd != -1)
  998.     {
  999. if(!(m_ulFlags & HX_FILE_READ))
  1000.     return HXR_UNEXPECTED;
  1001. if (m_bReadPending)
  1002. {
  1003.     return HXR_UNEXPECTED;
  1004. }
  1005. m_bReadPending = TRUE;
  1006. m_ulPendingReadCount = ulCount;
  1007. if (m_bInRead && m_bAsyncAccess)
  1008. {
  1009.     return HXR_OK;
  1010. }
  1011. m_bInRead = TRUE;
  1012. HX_RESULT theErr = HXR_OK;
  1013. UINT16 uIterationCount;
  1014. uIterationCount = 0;
  1015. AddRef(); // Make sure we do not destruct in ReadDone()
  1016.         BOOL bProgFail = FALSE;
  1017. do
  1018. {
  1019.             bProgFail = FALSE;
  1020.     theErr = DoRead(bProgFail);
  1021.     uIterationCount++;
  1022. } while (m_bReadPending && !m_bAsyncReadPending && !theErr && uIterationCount < m_ulMaxIterationLevel && !bProgFail);
  1023. /* have we exceeded our iteration count? */
  1024. if (m_bReadPending && !m_bAsyncReadPending && !theErr && m_bAsyncAccess && !bProgFail)
  1025. {
  1026.             MLOG_PD(NULL, "tScheduling stack callbackn");
  1027.     HX_ASSERT(!m_pStackCallback->IsCallbackPending() &&
  1028.      uIterationCount >= m_ulMaxIterationLevel);
  1029.             // Schedule a callback if there is not one already scheduled
  1030.             m_pStackCallback->ScheduleRelative(m_pScheduler, 0);
  1031. }
  1032. m_bInRead = FALSE;
  1033. Release();
  1034. return theErr;
  1035.     }
  1036.     return HXR_UNEXPECTED;
  1037. }
  1038. HX_RESULT
  1039. CSimpleFileObject::DoRead(REF(BOOL) rbProgFail)
  1040. {
  1041.     MLOG_PD(NULL, "CSimpleFileObject::DoRead() this=0x%08x tick=%lu curoffset=%lun",
  1042.             this, HX_GET_BETTERTICKCOUNT(), m_ulPos);
  1043.     HX_LOG_BLOCK( "CSimpleFileObject::DoRead" );
  1044.     HX_ASSERT(m_bReadPending);
  1045.     HX_RESULT theErr = HXR_OK;
  1046.     UINT32 ulCount = m_ulPendingReadCount;
  1047. #ifndef _MACINTOSH
  1048.     // Create buffer object here, notice that we call the
  1049.     // CreateInstance method of the controller, but we could
  1050.     // have implemented our own object that exposed the IHXBuffer
  1051.     // interface.
  1052.     IHXBuffer* pBuffer = NULL;
  1053.     ULONG32 actual = m_pDataFile->Read(pBuffer, ulCount);
  1054. #if defined(HELIX_FEATURE_PROGDOWN)
  1055.     MLOG_PD(NULL, "tulCount = %lu actual = %lun", ulCount, actual);
  1056.     // Sanity check. Unlikely we'd even make it here
  1057.     // if we failed to allocate m_pProgDownMon, but 
  1058.     // if so, then just behave like HELIX_FEATURE_PROGDOWN
  1059.     // is not defined
  1060.     if (m_pProgDownMon && m_bProgDownEnabled)
  1061.     {
  1062.         // Did we read all the bytes we were asked for?
  1063.         if (actual < ulCount)
  1064.         {
  1065.             MLOG_PD(NULL, "tt******** FAILED to read requested bytesn");
  1066.             // The read failed to read all the requested bytes
  1067.             //
  1068.             // Do we have a history of progressive download
  1069.             // with this file?
  1070.             if (m_pProgDownMon->HasBeenProgressive())
  1071.             {
  1072.                 MLOG_PD(NULL, "tttFile HAS been progressiven");
  1073.                 // This file has been progressive sometime in
  1074.                 // the past. However, we need to
  1075.                 // check the *current* state.
  1076.                 if (m_pProgDownMon->IsProgressive())
  1077.                 {
  1078.                     MLOG_PD(NULL, "ttttFile currently IS progressiven");
  1079.                     // The file is still currently downloading.
  1080.                     //
  1081.                     // Can we callback asynchronously?
  1082.                     if (m_bAsyncAccess)
  1083.                     {
  1084.                         // Set the flag saying we failed due to
  1085.                         // progressive download
  1086.                         rbProgFail = TRUE;
  1087.                         // Schedule the callback
  1088.                         return FinishDoReadWithCallback(actual);
  1089.                     }
  1090.                     else
  1091.                     {
  1092.                         // Try synchronously
  1093.                         return FinishDoReadWithoutCallback(actual);
  1094.                     }
  1095.                 }
  1096.                 else
  1097.                 {
  1098.                     MLOG_PD(NULL, "ttttFile currently is NOT progressiven");
  1099.                     // The file has been progressive in the past
  1100.                     // but the current state is NOT progressive.
  1101.                     // That could mean that either the download has
  1102.                     // finished or that the download agent is paused.
  1103.                     // With our current implementation we can't tell
  1104.                     // the difference (we would need to know the "true"
  1105.                     // file size to know for sure). Therefore, we will
  1106.                     // ask the fileformat whether or not it would "expect"
  1107.                     // a failure at this point. The fileformat should have
  1108.                     // knowledge to know whether or not a failure of this
  1109.                     // read would indicate failure or not. Sometimes fileformats
  1110.                     // read in large chunks and *expect* to get a failure.
  1111.                     // On the other hand, file formats sometimes do a read
  1112.                     // and are NOT expecting it to fail.
  1113.                     if (RequireFullRead())
  1114.                     {
  1115.                         MLOG_PD(NULL, "ttttFileResponse requires full readsn");
  1116.                         // The response says it requires full reads
  1117.                         //
  1118.                         // Can we callback asynchronously?
  1119.                         if (m_bAsyncAccess)
  1120.                         {
  1121.                             // Set the flag saying we failed due to
  1122.                             // progressive download
  1123.                             rbProgFail = TRUE;
  1124.                             // Schedule the callback
  1125.                             return FinishDoReadWithCallback(actual);
  1126.                         }
  1127.                         else
  1128.                         {
  1129.                             // Try synchronously
  1130.                             return FinishDoReadWithoutCallback(actual);
  1131.                         }
  1132.                     }
  1133.                     else if (m_pProgDownMon->GetFormerProgressiveRetryCount() > 0)
  1134.                     {
  1135.                         MLOG_PD(NULL, "ttttRetrying former progressive, count = %lun",
  1136.                                 m_pProgDownMon->GetFormerProgressiveRetryCount());
  1137.                         // We do not require a full read, but we are going
  1138.                         // to retry a certain number of times before calling
  1139.                         // back with ReadDone().
  1140.                         //
  1141.                         // Decrement the retry count. If the file becomes
  1142.                         // progressive again, then this count gets reset.
  1143.                         m_pProgDownMon->DecrementFormerProgressiveRetryCount();
  1144.                         // Can we callback asynchronously?
  1145.                         if (m_bAsyncAccess)
  1146.                         {
  1147.                             // Set the flag saying we failed due to
  1148.                             // progressive download
  1149.                             rbProgFail = TRUE;
  1150.                             // Schedule the callback
  1151.                             return FinishDoReadWithCallback(actual);
  1152.                         }
  1153.                         else
  1154.                         {
  1155.                             // Try synchronously
  1156.                             return FinishDoReadWithoutCallback(actual);
  1157.                         }
  1158.                     }
  1159.                     else
  1160.                     {
  1161.                         MLOG_PD(NULL, "ttttCannot retry former progressive any moren");
  1162.                         // We have retried on this formerly progressive
  1163.                         // file as long as we can, so just call back
  1164.                         // with ReadDone().
  1165.                         //
  1166.                         // Clear the progressive download failure flag
  1167.                         rbProgFail = FALSE;
  1168.                         // Finish the DoRead
  1169.                         return FinishDoRead(actual, pBuffer);
  1170.                     }
  1171.                 }
  1172.             }
  1173.             else /* if (m_pProgDownMon->HasBeenProgressive()) */
  1174.             {
  1175.                 MLOG_PD(NULL, "tttFile has NOT been progressive, checking file sizen");
  1176.                 // This file has never yet been progressive
  1177.                 //
  1178.                 // Do a filesize check. This will check
  1179.                 // the filesize against the filesize at
  1180.                 // the time that m_pProgDownMon->Init()
  1181.                 // was called. If the filesize has changed,
  1182.                 // then the m_pProgDownMon->HasBeenProgressive()
  1183.                 // flag will change.
  1184.                 m_pProgDownMon->MonitorFileSize();
  1185.                 // Has the filesize changed?
  1186.                 if (m_pProgDownMon->HasBeenProgressive())
  1187.                 {
  1188.                     MLOG_PD(NULL, "ttttFile size HAS changed, beginning size monitoring and retryingn");
  1189.                     // The filesize has indeed changed.
  1190.                     //
  1191.                     // Begin the monitoring of the file size
  1192.                     m_pProgDownMon->BeginSizeMonitoring();
  1193.                     // Can we callback asynchronously?
  1194.                     if (m_bAsyncAccess)
  1195.                     {
  1196.                         // Set the flag saying we failed due to
  1197.                         // progressive download
  1198.                         rbProgFail = TRUE;
  1199.                         // Schedule the callback
  1200.                         return FinishDoReadWithCallback(actual);
  1201.                     }
  1202.                     else
  1203.                     {
  1204.                         // Try synchronously
  1205.                         return FinishDoReadWithoutCallback(actual);
  1206.                     }
  1207.                 }
  1208.                 else
  1209.                 {
  1210.                     MLOG_PD(NULL, "ttttFile size has NOT changed.n");
  1211.                     // The filesize has NOT changed. This is most likely
  1212.                     // just a normal file and the fileformat has attempted
  1213.                     // to read past the end of the file. However, we will
  1214.                     // first ask the fileformat if it expected a failure.
  1215.                     if (RequireFullRead() &&
  1216.                         m_pProgDownMon->GetNotProgressiveRetryCount() > 0)
  1217.                     {
  1218.                         MLOG_PD(NULL, "tttttRetrying not progressive, count = %lun",
  1219.                                 m_pProgDownMon->GetNotProgressiveRetryCount());
  1220.                         // Decrement the retry count. If the file becomes
  1221.                         // progressive, then this count gets reset.
  1222.                         m_pProgDownMon->DecrementNotProgressiveRetryCount();
  1223.                         // The fileformat had the Advise interface and 
  1224.                         // said it did not expect a failure here. Also,
  1225.                         // we have not retried our maximum number of attempts
  1226.                         // yet, so we will retry the read.
  1227.                         //
  1228.                         // Can we callback asynchronously?
  1229.                         if (m_bAsyncAccess)
  1230.                         {
  1231.                             // Set the flag saying we failed due to
  1232.                             // progressive download
  1233.                             rbProgFail = TRUE;
  1234.                             // Schedule the callback
  1235.                             return FinishDoReadWithCallback(actual);
  1236.                         }
  1237.                         else
  1238.                         {
  1239.                             // Try synchronously
  1240.                             return FinishDoReadWithoutCallback(actual);
  1241.                         }
  1242.                     }
  1243.                     else
  1244.                     {
  1245.                         // Either:
  1246.                         // a) the fileformat either didn't have the Advise interface;
  1247.                         // b) the fileformat did have the interface and said it
  1248.                         //    was expecting a failure; or
  1249.                         // c) the fileformat had the Advise interface and said it
  1250.                         //    wasn't expecting a failure, but we've retried all the
  1251.                         //    times we can.
  1252.                         //
  1253.                         // Clear the progressive download failure flag
  1254.                         rbProgFail = FALSE;
  1255.                         // Finish the DoRead
  1256.                         return FinishDoRead(actual, pBuffer);
  1257.                     }
  1258.                 }
  1259.             } /* if (m_pProgDownMon->HasBeenProgressive()) else */
  1260.         }
  1261.         else /* if (actual < ulCount) */
  1262.         {
  1263.             // The read succeeded
  1264.             //
  1265.             // Reset the not progressive retry count
  1266.             m_pProgDownMon->ResetNotProgressiveRetryCount();
  1267.             // Clear the progressive download failure flag
  1268.             rbProgFail = FALSE;
  1269.             // Finish the DoRead
  1270.             return FinishDoRead(actual, pBuffer);
  1271.         }
  1272.     }
  1273.     else /* if (m_pProgDownMon) */
  1274. #endif /* #if defined(HELIX_FEATURE_PROGDOWN) */
  1275.     {
  1276.         // Clear the progressive download failure flag
  1277.         rbProgFail = FALSE;
  1278.         // Finish the DoRead
  1279.         return FinishDoRead(actual, pBuffer);
  1280.     }
  1281. #else /* #ifndef _MACINTOSH */
  1282.     BOOL bAtInterrupt = FALSE;
  1283.     if (m_pInterruptState)
  1284.     {
  1285. bAtInterrupt = m_pInterruptState->AtInterruptTime();
  1286.     }
  1287.     m_bAsyncReadPending = TRUE;
  1288.     theErr = m_pDataFile->SafeRead(ulCount, bAtInterrupt);
  1289. #endif /* #ifndef _MACINTOSH #else */
  1290.     return theErr;
  1291. }
  1292. /************************************************************************
  1293.  *  Method:
  1294.  * IHXFileObject::Write
  1295.  *  Purpose:
  1296.  * Writes a buffer of data to the file and asynchronously notifies
  1297.  * the caller via the IHXFileResponse interface passed in to Init,
  1298.  * of the completeness of the operation.
  1299.  */
  1300. STDMETHODIMP CSimpleFileObject::Write(IHXBuffer* pBuffer)
  1301. {
  1302.     if (m_nFd == -1 || !(m_ulFlags & HX_FILE_WRITE))
  1303.     {
  1304. return HXR_UNEXPECTED;
  1305.     }
  1306.     pBuffer->AddRef();
  1307. #ifdef _MACINTOSH
  1308. BOOL bAtInterrupt = FALSE;
  1309. if (m_pInterruptState)
  1310. {
  1311.     bAtInterrupt = m_pInterruptState->AtInterruptTime();
  1312. }
  1313.     UINT32 actual = m_pDataFile->SafeWrite(pBuffer, bAtInterrupt);
  1314. #else
  1315.     UINT32 actual = m_pDataFile->Write(pBuffer);
  1316. #endif
  1317.     pBuffer->Release();
  1318.     if (actual > 0)
  1319.     {
  1320. m_ulPos += actual;
  1321.     }
  1322.     if(actual == pBuffer->GetSize())
  1323. m_pFileResponse->WriteDone(HXR_OK);
  1324.     else
  1325. m_pFileResponse->WriteDone(HXR_FAILED);
  1326.     return HXR_OK;
  1327. }
  1328. /************************************************************************
  1329.  *  Method:
  1330.  * IHXFileObject::Seek
  1331.  *  Purpose:
  1332.  * Seeks to an offset in the file and asynchronously notifies
  1333.  * the caller via the IHXFileResponse interface passed in to Init,
  1334.  * of the completeness of the operation.
  1335.  */
  1336. STDMETHODIMP CSimpleFileObject::Seek(ULONG32 ulOffset, BOOL bRelative)
  1337. {
  1338.     MLOG_GEN(NULL, "CSimpleFileObject::Seek(%lu,%lu) this=0x%08x tick=%lun",
  1339.              ulOffset, bRelative, this, HX_GET_BETTERTICKCOUNT());
  1340.     HX_LOG_BLOCK( "CSimpleFileObject::Seek" );
  1341.     if((m_nFd == -1) && m_bCanBeReOpened)
  1342.     {
  1343. DPRINTF(0x5d000000, ("CSFO::Seek() -- _OpenFile()n"));
  1344. _OpenFile(m_ulFlags);
  1345.     }
  1346.     if (m_nFd != -1)
  1347.     {
  1348. /* remove any pending callbacks */
  1349.         if (m_pStackCallback) m_pStackCallback->Cancel(m_pScheduler);
  1350. #if defined(HELIX_FEATURE_PROGDOWN)
  1351.         // Seeks can interrupt other seeks, and cancel them
  1352.         // out. Therefore, if we had scheduled a callback to
  1353.         // handle a failed seek or a failed read, then we need
  1354.         // to cancel that callback.
  1355.         if (m_pProgDownMon && m_pProgDownMon->IsCallbackPending())
  1356.         {
  1357.             m_pProgDownMon->CancelCallback();
  1358.         }
  1359. #endif /* #if defined(HELIX_FEATURE_PROGDOWN) */
  1360. AddRef(); // Make sure we do not destruct on possible ReadDone
  1361. /*
  1362.  *  Seek cancels pending Reads.
  1363.  */
  1364. if (m_bReadPending)
  1365. {
  1366.     ActualAsyncReadDone(HXR_CANCELLED, NULL);
  1367. }
  1368. int whence = SEEK_SET;
  1369. if(bRelative)
  1370.     whence = SEEK_CUR;
  1371. #ifndef _MACINTOSH
  1372.         // Save the pending seek parameters
  1373.         m_ulPendingSeekOffset = ulOffset;
  1374.         m_usPendingSeekWhence = (UINT16) whence;
  1375.         // Do the seek
  1376.         HX_RESULT seekDoneResult = HXR_OK;
  1377.         HX_RESULT result = DoSeek(seekDoneResult);
  1378.         // Undo the AddRef();
  1379.         Release();
  1380. return ((result == HXR_OK) ? seekDoneResult : result);
  1381. #else
  1382. BOOL bAtInterrupt = FALSE;
  1383. if (m_pInterruptState)
  1384. {
  1385.     bAtInterrupt = m_pInterruptState->AtInterruptTime();
  1386. }
  1387. m_eSeekReason = EXTERNAL_SEEK;
  1388. HX_RESULT seekDoneResult = m_pDataFile->SafeSeek(ulOffset, whence, bAtInterrupt);
  1389. Release();
  1390. return seekDoneResult;
  1391. #endif
  1392.     }
  1393.     return HXR_UNEXPECTED;
  1394. }
  1395. HX_RESULT CSimpleFileObject::DoSeek(REF(HX_RESULT) rSeekDoneResult)
  1396. {
  1397.     MLOG_PD(NULL, "CSimpleFileObject::DoSeek() this=0x%08x tick=%lu offset=%lu whence=%un",
  1398.             this, HX_GET_BETTERTICKCOUNT(), m_ulPendingSeekOffset, m_usPendingSeekWhence);
  1399.     HX_RESULT result = m_pDataFile->Seek(m_ulPendingSeekOffset,
  1400.                                          m_usPendingSeekWhence);
  1401.     if (result == HXR_OK)
  1402.     {
  1403. if (m_usPendingSeekWhence == SEEK_SET)
  1404. {
  1405.     m_ulPos = m_ulPendingSeekOffset;
  1406. }
  1407. else
  1408. {
  1409.     m_ulPos += m_ulPendingSeekOffset;
  1410. }
  1411.     }
  1412. #if defined(HELIX_FEATURE_PROGDOWN)
  1413.     // For the purposes of progressive download, we
  1414.     // will assume that seeking never fails. We will
  1415.     // add the assert below to catch anytime it does.
  1416.     // If we are finding that this assert is tripping,
  1417.     // then we need to add equivalent support in DoSeek()
  1418.     // for progressive download that we have in DoRead().
  1419.     HX_ASSERT(SUCCEEDED(result));
  1420. #endif /* #if defined(HELIX_FEATURE_PROGDOWN) */
  1421.     rSeekDoneResult = ActualAsyncSeekDone(result);
  1422.     return result;
  1423. }
  1424. void CSimpleFileObject::SeekBackwards(UINT32 ulNumBytes)
  1425. {
  1426.     if (m_pDataFile && ulNumBytes)
  1427.     {
  1428.         // Get the current offset
  1429.         UINT32 ulCurOffset = m_pDataFile->Tell();
  1430.         // Make sure the number of bytes we 
  1431.         // are supposed to back up is not greater
  1432.         // than the current offset
  1433.         if (ulNumBytes > ulCurOffset) ulNumBytes = ulCurOffset;
  1434.         // Compute the new absolute offset
  1435.         UINT32 ulNewOffset = ulCurOffset - ulNumBytes;
  1436.         // Seek the data file to this offset
  1437.         m_pDataFile->Seek(ulNewOffset, SEEK_SET);
  1438.     }
  1439. }
  1440. HX_RESULT CSimpleFileObject::FinishDoRead(UINT32 actual, REF(IHXBuffer*) pBuffer)
  1441. {
  1442.     /*
  1443.      * If they get to the end of the file, then close it and reset.
  1444.      */
  1445.     if (actual > 0 && pBuffer)
  1446.     {
  1447.         m_ulPos += actual;
  1448.     }
  1449. #if defined(HELIX_FEATURE_PROGDOWN)
  1450.     if (m_ulSize && (!m_bProgDownEnabled || (m_pProgDownMon && !m_pProgDownMon->HasBeenProgressive())))
  1451. #else
  1452.     if (m_ulSize)
  1453. #endif
  1454.     {
  1455.         if(m_ulPos >= m_ulSize)
  1456.         {
  1457.     DPRINTF(0x5d000000, ("CSFO::Read() -- m_pDataFile->Close()n"));
  1458.     m_pDataFile->Close();
  1459.     m_nFd = -1;
  1460.     if (m_pDescriptorReg)
  1461.     {
  1462.         m_pDescriptorReg->UnRegisterDescriptors(1);
  1463.     }
  1464.     m_bCanBeReOpened = 1;
  1465.         }
  1466.     }
  1467.     /* ignore return value from readdone! */
  1468.     ActualAsyncReadDone((actual > 0 && pBuffer) ? HXR_OK : HXR_FAILED, pBuffer);
  1469.     // Release our reference on the buffer!
  1470.     HX_RELEASE(pBuffer);
  1471.     return HXR_OK;
  1472. }
  1473. STDMETHODIMP CSimpleFileObject::InitDirHandler
  1474. (
  1475.     IHXDirHandlerResponse*    /*IN*/  pDirResponse
  1476. )
  1477. {
  1478.     m_pDirResponse = pDirResponse;
  1479.     m_pDirResponse->AddRef();
  1480.     m_pDirResponse->InitDirHandlerDone(HXR_OK);
  1481.     return HXR_OK;
  1482. }
  1483. STDMETHODIMP CSimpleFileObject::CloseDirHandler()
  1484. {
  1485.     // Members must not be accessed after async ...Done() response
  1486.     if (m_pDirResponse)
  1487.     {
  1488. IHXDirHandlerResponse *pTmpDirResponse = m_pDirResponse;
  1489. m_pDirResponse = NULL;
  1490. pTmpDirResponse->CloseDirHandlerDone(HXR_OK);
  1491. pTmpDirResponse->Release();
  1492.     }
  1493.     return HXR_OK;
  1494. }
  1495. STDMETHODIMP CSimpleFileObject::MakeDir()
  1496. {
  1497.     CHXString strFileName;
  1498.     HX_RESULT retVal = HXR_OK;
  1499.     UpdateFileNameMember();
  1500.     GetFullPathname(m_pFilename, &strFileName);
  1501. #if defined (_WINDOWS ) || defined (_WIN32)
  1502.     if (CreateDirectory(OS_STRING((const char*) strFileName), 0) == 0)
  1503.     {
  1504. retVal = HXR_FAIL;
  1505.     }
  1506. #elif defined (_UNIX)
  1507.     if (mkdir((const char*) strFileName, 0755) < 0)
  1508.     {
  1509. retVal = HXR_FAIL;
  1510.     }
  1511. #elif defined (_MACINTOSH)
  1512.     //XXXGH...don't know how to do this on Mac
  1513.     retVal = HXR_FAIL;
  1514. #else
  1515.     XHXDirectory* pHXDirectory = XHXDirectory::Construct(&m_pFileSystem->m_pCommonObj);
  1516.     retVal = HXR_OUTOFMEMORY;
  1517.     if (pHXDirectory)
  1518.     {
  1519. retVal = HXR_FAIL;
  1520. pHXDirectory->SetPath((const char*) strFileName);
  1521. if (pHXDirectory->Create())
  1522. {
  1523.     retVal = HXR_OK;
  1524. }
  1525. delete pHXDirectory;
  1526.     }
  1527. #endif
  1528.     m_pDirResponse->MakeDirDone(retVal);
  1529.     return HXR_OK;
  1530. }
  1531. STDMETHODIMP CSimpleFileObject::ReadDir()
  1532. {
  1533.     const char* pDirname = 0;
  1534.     if (!m_pDirList)
  1535.     {
  1536. CHXString strFileName;
  1537. UpdateFileNameMember();
  1538. GetFullPathname(m_pFilename, &strFileName);
  1539. m_pDirList =
  1540.     CFindFile::CreateFindFile((const char*)strFileName, 0, "*");
  1541. if (!m_pDirList)
  1542. {
  1543.     m_pDirResponse->ReadDirDone(HXR_FAIL, 0);
  1544.     return HXR_OK;
  1545. }
  1546. pDirname = m_pDirList->FindFirst();
  1547.     }
  1548.     else
  1549.     {
  1550. pDirname = m_pDirList->FindNext();
  1551.     }
  1552.     if (!pDirname)
  1553.     {
  1554. delete m_pDirList;
  1555. m_pDirList = 0;
  1556. m_pDirResponse->ReadDirDone(HXR_FILE_NOT_FOUND, 0);
  1557. return HXR_OK;
  1558.     }
  1559.     HX_RESULT result;
  1560.     if (!m_pCommonClassFactory)
  1561.     {
  1562. result = m_pContext->QueryInterface(IID_IHXCommonClassFactory,
  1563.                                     (void **)&m_pCommonClassFactory);
  1564. if (HXR_OK != result)
  1565. {
  1566.     return result;
  1567. }
  1568.     }
  1569.     IHXBuffer* pBuffer = 0;
  1570.     result = m_pCommonClassFactory->CreateInstance(CLSID_IHXBuffer,
  1571.                                                    (void**)&pBuffer);
  1572.     if (HXR_OK != result)
  1573.     {
  1574. return result;
  1575.     }
  1576.     pBuffer->Set((Byte*)pDirname, strlen(pDirname)+1);
  1577.     m_pDirResponse->ReadDirDone(HXR_OK, pBuffer);
  1578.     pBuffer->Release();
  1579.     return HXR_OK;
  1580. }
  1581. /************************************************************************
  1582.  * Method:
  1583.  * IHXFileObject::Stat
  1584.  * Purpose:
  1585.  * Collects information about the file that is returned to the
  1586.  * caller in an IHXStat object
  1587.  */
  1588. STDMETHODIMP CSimpleFileObject::Stat(IHXFileStatResponse* pFileStatResponse)
  1589. {
  1590.     MLOG_GEN(NULL, "CSimpleFileObject::Stat(0x%08x) this=0x%08xn", pFileStatResponse, this);
  1591.     HX_LOG_BLOCK( "CSimpleFileObject::Stat" );
  1592.     struct stat StatBuffer;
  1593.     CHXString strFileName;
  1594. #ifdef _MACINTOSH
  1595.         // if fstat fails
  1596. #ifdef _MAC_MACHO
  1597. GetFullPathname(m_pFilename, &strFileName);
  1598.         int res = stat(strFileName, &StatBuffer);
  1599. #else
  1600.         int res = stat(m_pFilename, &StatBuffer);
  1601. #endif
  1602. if ( res != 0 )
  1603. {
  1604. // return failure code
  1605. return HXR_FAIL;
  1606. }
  1607. #else
  1608.     if(m_nFd == -1)
  1609.     {
  1610. CHXString   strURL;
  1611. UpdateFileNameMember();
  1612. strURL = m_pFilename;
  1613. GetFullPathname(strURL, &strFileName);
  1614. m_pDataFile->Bind((const char *)strFileName);
  1615.     }
  1616.     if (m_pDataFile->Stat(&StatBuffer) != HXR_OK)
  1617.     {
  1618. pFileStatResponse->StatDone(HXR_FAIL,
  1619.     0,
  1620.     0,
  1621.     0,
  1622.     0,
  1623.     0);
  1624. return HXR_OK;
  1625.     }
  1626. #endif
  1627.     /*
  1628.      * XXXSMP:
  1629.      *    We we need this because RealPix opens up tons of files
  1630.      *    just to stat them.  If you are reading this comment
  1631.      *    and the date is past July 31, then please yell at
  1632.      *    Sujal.
  1633.      */
  1634. #if !defined(_MACINTOSH)
  1635.     if(m_nFd != -1)
  1636.     {
  1637. DPRINTF(0x5d000000, ("CSFO::Stat() -- m_pDataFile->Close()n"));
  1638. if (m_pDescriptorReg)
  1639. {
  1640.     m_pDescriptorReg->UnRegisterDescriptors(1);
  1641. }
  1642. m_pDataFile->Close();
  1643. m_nFd = -1;
  1644. m_bCanBeReOpened = 1;
  1645.     }
  1646. #endif
  1647.     m_ulSize = StatBuffer.st_size;
  1648.     pFileStatResponse->StatDone(HXR_OK,
  1649. StatBuffer.st_size,
  1650. StatBuffer.st_ctime,
  1651. StatBuffer.st_atime,
  1652. StatBuffer.st_mtime,
  1653. StatBuffer.st_mode);
  1654.     return HXR_OK;
  1655. }
  1656. /************************************************************************
  1657.  *  Method:
  1658.  * IHXFileObject::Advise
  1659.  *  Purpose:
  1660.  * To pass information to the File Object
  1661.  */
  1662. STDMETHODIMP CSimpleFileObject::Advise(ULONG32 ulInfo)
  1663. {
  1664.     MLOG_GEN(NULL, "CSimpleFileObject::Advise(%s) this=0x%08xn",
  1665.              (ulInfo == HX_FILEADVISE_RANDOMACCESS ? "HX_FILEADVISE_RANDOMACCESS" :
  1666.                 (ulInfo == HX_FILEADVISE_SYNCACCESS ? "HX_FILEADVISE_SYNCACCESS" :
  1667.                    (ulInfo == HX_FILEADVISE_ASYNCACCESS ? "HX_FILEADVISE_ASYNCACCESS" :
  1668.                       (ulInfo == HX_FILEADVISE_RANDOMACCESSONLY ? "HX_FILEADVISE_RANDOMACCESSONLY" :
  1669.                          (ulInfo == HX_FILEADVISE_ANYACCESS ? "HX_FILEADVISE_ANYACCESS" : "Unknown"))))),
  1670.              this);
  1671.     HX_RESULT retVal = HXR_FAIL;
  1672. #ifndef _MACINTOSH
  1673.     if (ulInfo == HX_FILEADVISE_SYNCACCESS)
  1674.     {
  1675. m_bAsyncAccess = FALSE;
  1676. retVal = HXR_OK;
  1677.     }
  1678.     else if (ulInfo == HX_FILEADVISE_ASYNCACCESS)
  1679.     {
  1680. m_bAsyncAccess = TRUE;
  1681. retVal = HXR_OK;
  1682.     }
  1683. #if defined(HELIX_FEATURE_PROGDOWN)
  1684.     else if (ulInfo == HX_FILEADVISE_RANDOMACCESS)
  1685.     {
  1686.         retVal = HXR_OK;
  1687.         if (m_pProgDownMon && m_bProgDownEnabled)
  1688.         {
  1689.             // Has this file ever been progressive?
  1690.             if (m_pProgDownMon->HasBeenProgressive())
  1691.             {
  1692.                 // It has been in the past, but
  1693.                 // is it currently progressive?
  1694.                 if (m_pProgDownMon->IsProgressive())
  1695.                 {
  1696.                     // Set the linear return value
  1697.                     retVal = HXR_ADVISE_PREFER_LINEAR;
  1698.                 }
  1699.             }
  1700.             else
  1701.             {
  1702.                 // Manually monitor the file size. This
  1703.                 // will trigger HasBeenProgressive() to 
  1704.                 // be true if the file is progressive
  1705.                 m_pProgDownMon->MonitorFileSize();
  1706.                 // Are we now progressive?
  1707.                 if (m_pProgDownMon->HasBeenProgressive())
  1708.                 {
  1709.                     // Set the linear return value
  1710.                     retVal = HXR_ADVISE_PREFER_LINEAR;
  1711.                     // Begin the monitoring of the file size
  1712.                     m_pProgDownMon->BeginSizeMonitoring();
  1713.                 }
  1714.             }
  1715.         }
  1716.     }
  1717. #endif /* #if defined(HELIX_FEATURE_PROGDOWN) */
  1718. #endif // _MACINTOSH
  1719.     MLOG_GEN(NULL, "treturn %sn",
  1720.              (retVal == HXR_OK ? "HXR_OK" :
  1721.                 (retVal == HXR_FAIL ? "HXR_FAIL" :
  1722.                    (retVal == HXR_ADVISE_PREFER_LINEAR ? "HXR_ADVISE_PREFER_LINEAR" :
  1723.                       "Unknown"))));
  1724.     return retVal;
  1725. }
  1726. /************************************************************************
  1727.  * Method:
  1728.  *     IHXFileObject::GetFileObjectFromPool
  1729.  * Purpose:
  1730.  *      To get another FileObject from the same pool.
  1731.  */
  1732. STDMETHODIMP CSimpleFileObject::GetFileObjectFromPool (
  1733.     IHXGetFileFromSamePoolResponse* response
  1734. )
  1735. {
  1736.     HX_RESULT lReturnVal = HXR_FAILED;
  1737.     CSimpleFileObject* pFileObject = 0;
  1738.     CHXString new_path;
  1739.     CHXString strFileName;
  1740.     CHXString strURL;
  1741.     IUnknown* pUnknown = 0;
  1742.     char* pNewPath    = 0;
  1743.     char* pSeparator  = 0;
  1744.     UpdateFileNameMember();
  1745.     if(!m_pFilename)
  1746.     {
  1747. pNewPath = new char[strlen(m_base_path) + 1];
  1748. strcpy(pNewPath, m_base_path); /* Flawfinder: ignore */
  1749.     }
  1750.     else
  1751.     {
  1752. strURL = m_pFilename;
  1753. // Make a nice local file name from the URL!
  1754. GetFullPathname(strURL, &strFileName);
  1755. pNewPath = new char[strlen(strFileName) + 1];
  1756. strcpy(pNewPath, (const char*)strFileName); /* Flawfinder: ignore */
  1757. pSeparator = ::strrchr(pNewPath, OS_SEPARATOR_CHAR);
  1758. if(pSeparator)
  1759. {
  1760.     /* Separator will be added in seturl */
  1761.     *pSeparator = 0;
  1762. }
  1763. else
  1764. {
  1765.     // started w/filename. no separator implies no path
  1766.     pNewPath[0] = 0;
  1767. }
  1768.     }
  1769.     new_path = pNewPath;
  1770.     if (pNewPath)
  1771.     {
  1772. delete [] pNewPath;
  1773. pNewPath = 0;
  1774.     }
  1775.     pFileObject = new CSimpleFileObject(new_path,
  1776. m_pFileSystem,
  1777. m_pContext,
  1778. m_ulMaxIterationLevel);
  1779.     if (!pFileObject)
  1780.     {
  1781. return HXR_OUTOFMEMORY;
  1782.     }
  1783.     lReturnVal = pFileObject->QueryInterface(IID_IUnknown,
  1784.      (void**)&pUnknown);
  1785.     response->FileObjectReady(lReturnVal == HXR_OK ?
  1786.       HXR_OK : HXR_FAILED,
  1787.       pUnknown);
  1788.     if(pUnknown)
  1789.     {
  1790. pUnknown->Release();
  1791. pUnknown = NULL;
  1792.     }
  1793.     return lReturnVal;
  1794. }
  1795. // IHXFileExists interface
  1796. /************************************************************************
  1797.  * Method:
  1798.  *     IHXFileExists::DoesExist
  1799.  * Purpose:
  1800.  */
  1801. STDMETHODIMP CSimpleFileObject::DoesExist(const char* /*IN*/  pPath,
  1802. IHXFileExistsResponse* /*IN*/  pFileResponse)
  1803. {
  1804.     BOOL bExists = FALSE;
  1805.     BOOL bPlusURL = FALSE;
  1806.     CHXString   strFileName;
  1807.     CHXString strPath;
  1808.     CHXString   plusFileName;
  1809.     CHXString   plusPath;
  1810.     strPath = pPath;
  1811.     bPlusURL = HXXFile::IsPlusURL(pPath);
  1812.     if (bPlusURL)
  1813.     {
  1814. INT32 index = strPath.ReverseFind('+');
  1815. plusFileName = strPath.Right(strPath.GetLength() - (index+1));
  1816. strPath = strPath.Left(index);
  1817. index = strPath.ReverseFind('/');
  1818. if (index >= 0)
  1819. {
  1820.     plusPath = strPath.Left(index+1);
  1821.     plusPath = plusPath + plusFileName;
  1822. }
  1823. else
  1824. {
  1825.     plusPath = plusFileName;
  1826. }
  1827. HXXFile::GetReasonableLocalFileName(plusPath);
  1828. GetFullPathname(plusPath, &plusFileName);
  1829.     }
  1830.     // Make a nice local file name from the URL!
  1831.     HXXFile::GetReasonableLocalFileName(strPath);
  1832.     GetFullPathname(strPath, &strFileName);
  1833. #ifdef _MACINTOSH
  1834.     CHXDataFile*     pDataFile = 0; /* cross-platform file object */
  1835.     pDataFile = CHXDataFile::Construct();
  1836.     if (pDataFile->Open((const char*)strFileName,O_RDONLY) == HXR_OK)
  1837.     {
  1838. if (bPlusURL)
  1839. {
  1840.     if (pDataFile->Open((const char*)plusFileName,O_RDONLY) == HXR_OK)
  1841.     {
  1842. bExists = TRUE;
  1843.     }
  1844. }
  1845. else
  1846. {
  1847.     bExists = TRUE;
  1848. }
  1849.     }
  1850.     delete pDataFile;
  1851. #else
  1852.     struct stat statbuf;
  1853.     m_pDataFile->Bind((const char *)strFileName);
  1854.     if (m_pDataFile->Stat(&statbuf) == 0)
  1855.     {
  1856. if (bPlusURL)
  1857. {
  1858.     m_pDataFile->Bind((const char *)plusFileName);
  1859.     if (m_pDataFile->Stat(&statbuf) == 0)
  1860.     {
  1861. DPRINTF(0x5d000000, ("CSFO::DoesExist() -- both r TRUEn"));
  1862. bExists = TRUE;
  1863.     }
  1864. }
  1865. else
  1866. {
  1867.     DPRINTF(0x5d000000, ("CSFO::DoesExist() -- TRUEn"));
  1868.     bExists = TRUE;
  1869. }
  1870.     }
  1871.     else
  1872. DPRINTF(0x5d000000, ("CSFO::DoesExist() -- FALSEn"));
  1873. #endif
  1874.     pFileResponse->DoesExistDone(bExists);
  1875.     return HXR_OK;
  1876. }
  1877. /************************************************************************
  1878.  * Method:
  1879.  *     Private interface::OpenFile
  1880.  * Purpose:
  1881.  *     This common method is used from Init() and GetFileObjectFromPool()
  1882.  */
  1883. STDMETHODIMP CSimpleFileObject::_OpenFile(ULONG32     ulFlags)
  1884. {
  1885.     HX_LOG_BLOCK( "CSimpleFileObject::_OpenFile" );
  1886.     DPRINTF(0x5d000000, ("CSFO::_OpenFile(%lu)n", ulFlags));
  1887.     HX_RESULT lReturnVal = HXR_OK;
  1888.     IHXUserImpersonation* pUserImpersonationThis = NULL;
  1889.     CHXString strFileName;
  1890.     CHXString strURL;
  1891.     m_ulFlags = ulFlags;
  1892.     UpdateFileNameMember();
  1893.     strURL = m_pFilename;
  1894.     // Make a nice local file name from the URL!
  1895.     GetFullPathname(strURL, &strFileName);
  1896.     if (m_pUnknownUserContext)
  1897.     {
  1898. m_pUnknownUserContext->QueryInterface(IID_IHXUserImpersonation,
  1899.     (void**)&pUserImpersonationThis);
  1900.     }
  1901.     if (pUserImpersonationThis)
  1902.     {
  1903. // see ntauth plugin
  1904. pUserImpersonationThis->Start();
  1905.     }
  1906.     UINT16 flags = 0;
  1907. #ifdef _MACINTOSH
  1908.     // use native modes
  1909.     if (ulFlags & HX_FILE_READ)
  1910. flags |= O_RDONLY;
  1911.     if (ulFlags & HX_FILE_WRITE)
  1912. flags |= O_WRONLY;
  1913.     if (ulFlags & HX_FILE_BINARY)
  1914. flags |= O_BINARY;
  1915.     if (!ulFlags)
  1916.     {
  1917. flags = O_RDONLY | O_BINARY;
  1918. m_ulFlags = HX_FILE_READ | HX_FILE_BINARY;
  1919.     }
  1920.     // XXXGH must do HX_FILE_REPLACE for MAC
  1921.     m_pDataFile = (CMacAsyncFile*) CMacAsyncFile::Construct();
  1922.     m_pDataFile->SetAsyncResponse(m_pAsyncFileResponse);
  1923.     BOOL bAtInterrupt = FALSE;
  1924.     if (m_pInterruptState)
  1925.     {
  1926.          bAtInterrupt = m_pInterruptState->AtInterruptTime();
  1927.     }
  1928.     m_nFd = m_pDataFile->SafeOpen((const char*)strFileName,flags, 0, bAtInterrupt);
  1929. #else
  1930.     if (ulFlags & HX_FILE_READ)
  1931. flags |= HX_FILEFLAG_READ;
  1932.     if (ulFlags & HX_FILE_WRITE)
  1933. flags |= HX_FILEFLAG_WRITE;
  1934.     if (ulFlags & HX_FILE_BINARY)
  1935. flags |= HX_FILEFLAG_BINARY;
  1936.     if (!ulFlags)
  1937.     {
  1938. flags = HX_FILEFLAG_READ | HX_FILEFLAG_BINARY;
  1939. m_ulFlags = HX_FILE_READ | HX_FILE_BINARY;
  1940.     }
  1941.     DPRINTF(0x5d000000, ("CSFO::_OpenFile() -- flags(%u)n", flags));
  1942.     HX_ASSERT(m_pDataFile);
  1943.     MLOG_GEN(NULL, "CSimpleFileObject::_OpenFile() this=0x%08x tick=%lu filename=%sn",
  1944.              this, HX_GET_BETTERTICKCOUNT(), (const char*) strFileName);
  1945.     m_pDataFile->Bind((const char *)strFileName);
  1946.     if (HXR_OK == m_pDataFile->Open((UINT16)m_ulFlags))
  1947.     {
  1948. m_nFd = m_pDataFile->GetFd();
  1949. DPRINTF(0x5d000000, ("CSFO::_OpenFile() "
  1950. "-- fd(%d), filename(%s)n", m_nFd,
  1951. ((const char *)strFileName) ? (const char *)strFileName : "NULL"));
  1952.     }
  1953.     else
  1954.     {
  1955. m_nFd = -1;
  1956.     }
  1957. #endif
  1958.     if (pUserImpersonationThis)
  1959.     {
  1960. pUserImpersonationThis->Stop();
  1961.     }
  1962.     /* InitDone may result in close/destruction of this object.Mime mapper
  1963.      * is only interested in the mimetype. This is the sequence of events:
  1964.      * InitDone->FinishSetup->Close MimeMapper.. Release it. load right ff
  1965.      * hand over file system to the file format.
  1966.      * So by the time control returns back here, this object may already be
  1967.      * closed, resulting in m_nFd = -1
  1968.      */
  1969.     if (m_nFd != -1)
  1970.     {
  1971. lReturnVal = HXR_OK;
  1972.     }
  1973.     else if (pUserImpersonationThis)
  1974.     {
  1975. lReturnVal = HXR_NOT_AUTHORIZED;
  1976.     }
  1977.     else
  1978.     {
  1979. DPRINTF(0x5d000000, ("Error: file missingn"));
  1980. lReturnVal = HXR_DOC_MISSING;
  1981.     }
  1982.     HX_RELEASE(pUserImpersonationThis);
  1983.     if (lReturnVal == HXR_OK)
  1984.     {
  1985. if (!m_pDescriptorReg)
  1986. {
  1987.     m_pContext->QueryInterface(IID_IHXDescriptorRegistration,
  1988. (void **)&m_pDescriptorReg);
  1989. }
  1990. if (m_pDescriptorReg)
  1991. {
  1992.     m_pDescriptorReg->RegisterDescriptors(1);
  1993. }
  1994.     }
  1995.     return lReturnVal;
  1996. }
  1997. void
  1998. CSimpleFileObject::UpdateFileNameMember()
  1999. {
  2000.     const char* pURL;
  2001.     if (m_base_path.GetLength() > 0)
  2002.     {
  2003.        /* Running on the Server, do this without wasting CPU! */
  2004.        if (m_pRequest->GetURL(pURL) != HXR_OK)
  2005.        {
  2006.    HX_VECTOR_DELETE(m_pFilename);
  2007.    return;
  2008.        }
  2009.        UINT32 ulIndex = 0;
  2010.        while (pURL[ulIndex] != 0)
  2011.        {
  2012.    // HP - allow '$' in directory/file names
  2013.    //
  2014.    // still need to take care of that obsolete $ sign option:
  2015.    // rtsp://moe.cr.prognet.com/ambush.rm$1:00
  2016.    // time after the $ is assumed to be the start time.
  2017.    //
  2018.    // the solution is to compare the string following the $ to
  2019.    // a properly formed time. If the string is a time and only
  2020.    // a time, then we know its the old-style start-time option
  2021.    // otherwise, '$' is part of the directory/file name and we
  2022.    // will keep it.
  2023.    if (pURL[ulIndex] == '$')
  2024.    {
  2025.        const char* pszOption = &pURL[ulIndex + 1];
  2026.        if (::TimeParse(pszOption))
  2027.        {
  2028.    goto strip_and_duplicate;
  2029.        }
  2030.    }
  2031.    else
  2032.    {
  2033. #if !defined(_MACINTOSH) && !defined(_MAC_UNIX) // ? # and + are legal in Mac file names and shouldn't be stripped (yes, we're seeing a file name, not a URL here)
  2034.        switch (pURL[ulIndex])
  2035.        {
  2036.        case '?':
  2037.        case '#':
  2038.        case '+':
  2039.    goto strip_and_duplicate;
  2040.        default:
  2041.    break;
  2042.        }
  2043. #endif
  2044.    }
  2045.    ulIndex++;
  2046.        }
  2047.        HX_VECTOR_DELETE(m_pFilename);
  2048. #if defined(_MACINTOSH) || defined(_MAC_UNIX)
  2049.        m_pFilename = new_string(pURL); // on Mac, new_path_string mangles legal filenames which have / or  in them
  2050. #else
  2051.        m_pFilename = new_path_string(pURL);
  2052. #endif
  2053.        return;
  2054. strip_and_duplicate:
  2055.        HX_VECTOR_DELETE(m_pFilename);
  2056. #if defined(_MACINTOSH) || defined(_MAC_UNIX)
  2057.        m_pFilename = new_string(pURL); // on Mac, new_path_string mangles legal filenames which have / or  in them
  2058. #else
  2059.        m_pFilename = new_path_string(pURL);
  2060. #endif
  2061.        m_pFilename[ulIndex] = 0;
  2062.        return;
  2063.     }
  2064.     pURL = 0;
  2065.     if (m_pRequest)
  2066.     {
  2067. if (m_pRequest->GetURL(pURL) != HXR_OK)
  2068. {
  2069.     HX_VECTOR_DELETE(m_pFilename);
  2070.     m_pFilename = 0;
  2071. }
  2072. IHXValues* pReqHeader = NULL;
  2073. BOOL bVerbatimFileName = FALSE;
  2074. if (SUCCEEDED(m_pRequest->GetRequestHeaders(pReqHeader)) &&
  2075.     pReqHeader)
  2076. {
  2077.     ULONG32 ulVal = 0;
  2078.     if (SUCCEEDED(pReqHeader->GetPropertyULONG32("VerbatimFileName",
  2079.  ulVal)))
  2080.     {
  2081. bVerbatimFileName = (ulVal ? TRUE : FALSE);
  2082.     }
  2083. }
  2084. HX_RELEASE(pReqHeader);
  2085. CHXString strFilename;
  2086. if (bVerbatimFileName)
  2087. {
  2088.     if (pURL)
  2089.     {
  2090. strFilename = pURL;
  2091.     }
  2092. }
  2093. else
  2094. {
  2095.     CHXURL* pCHXURL = new CHXURL(pURL, m_pCommonClassFactory);
  2096.     if (pCHXURL)
  2097.     {
  2098. IHXValues* pHeader = pCHXURL->GetProperties();
  2099. if(pHeader)
  2100. {
  2101.     IHXBuffer* pUrlBuffer = NULL;
  2102.     if(HXR_OK == pHeader->GetPropertyBuffer(PROPERTY_URL, pUrlBuffer) &&
  2103. pUrlBuffer)
  2104.     {
  2105. strFilename = (const char*)pUrlBuffer->GetBuffer();
  2106. HX_RELEASE(pUrlBuffer);
  2107.     }
  2108.     HX_RELEASE(pHeader);
  2109. }
  2110. delete pCHXURL;
  2111.     }
  2112.     /*
  2113.     * Strip off the parameters
  2114.     */
  2115.     INT32 index = strFilename.Find('?');
  2116.     if (index >= 0)
  2117.     {
  2118. strFilename = strFilename.Left(index);
  2119.     }
  2120.     if (HXXFile::IsPlusURL(pURL))
  2121.     {
  2122. index = strFilename.ReverseFind('+');
  2123. if (index >= 0)
  2124. {
  2125.     strFilename = strFilename.Left(index);
  2126. }
  2127.     }
  2128. }
  2129. HXXFile::GetReasonableLocalFileName(strFilename);
  2130. HX_VECTOR_DELETE(m_pFilename);
  2131. #if defined(_CARBON) || defined(_MAC_UNIX)
  2132. // Under Carbon, GetReasonableLocalFileName returns a proper Mac path, possibly including
  2133. // slashes which shouldn't be mucked with.
  2134. m_pFilename = new_string((const char *) strFilename);
  2135. #else
  2136. m_pFilename = new_path_string((const char*)strFilename);
  2137. #endif
  2138.     }
  2139. }
  2140. STDMETHODIMP CSimpleFileObject::SetRequest
  2141. (
  2142.     IHXRequest* pRequest
  2143. )
  2144. {
  2145.     if (!pRequest)
  2146.     {
  2147. return HXR_INVALID_PARAMETER;
  2148.     }
  2149.     HX_RELEASE(m_pRequest);
  2150.     m_pRequest = pRequest;
  2151.     m_pRequest->AddRef();
  2152.     UpdateFileNameMember();
  2153.     return HXR_OK;
  2154. }
  2155. STDMETHODIMP CSimpleFileObject::GetRequest
  2156. (
  2157.     REF(IHXRequest*) pRequest
  2158. )
  2159. {
  2160.     pRequest = m_pRequest;
  2161.     if (pRequest)
  2162.     {
  2163. pRequest->AddRef();
  2164.     }
  2165.     return HXR_OK;
  2166. }
  2167. static BOOL DoRename(const char* pOldName,
  2168.      const char* pNewName,
  2169.      IUnknown** ppCommonObj)
  2170. {
  2171.     BOOL ret = FALSE;
  2172. #if defined(_MACINTOSH) || defined(_SYMBIAN)
  2173.     XHXDirectory* pHXDir =  XHXDirectory::Construct(ppCommonObj);
  2174.     if (pHXDir)
  2175.     {
  2176. if (SUCCEEDED(pHXDir->Rename(pOldName, pNewName)))
  2177. {
  2178.     ret = TRUE;
  2179. }
  2180. delete pHXDir;
  2181.     }
  2182. #elif defined(WIN32_PLATFORM_PSPC)
  2183.     if (MoveFile(OS_STRING(pOldName), OS_STRING(pNewName)) != 0)
  2184.     {
  2185. ret = TRUE;
  2186.     }
  2187. #else
  2188.     if (rename(pOldName, pNewName) == 0)
  2189.     {
  2190. ret = TRUE;
  2191.     }
  2192. #endif /* !defined(WIN32_PLATFORM_PSPC) */
  2193.     return ret;
  2194. }
  2195. STDMETHODIMP CSimpleFileObject::Rename
  2196. (
  2197.     const char* pFilename
  2198. )
  2199. {
  2200.     CHXString strFilename;
  2201.     CHXString newFilename;
  2202.     UpdateFileNameMember();
  2203.     strFilename = m_pFilename;
  2204.     INT32 index = strFilename.ReverseFind(OS_SEPARATOR_CHAR);
  2205.     if (index != -1)
  2206.     {
  2207. newFilename = strFilename.Left(index+1);
  2208. newFilename += pFilename;
  2209.     }
  2210.     else
  2211.     {
  2212. newFilename = pFilename;
  2213.     }
  2214.     GetFullPathname((const char*)newFilename, &newFilename);
  2215.     GetFullPathname((const char*)strFilename, &strFilename);
  2216.     if (DoRename(strFilename, newFilename, &m_pFileSystem->m_pCommonObj) == FALSE)
  2217.     {
  2218. return HXR_FAIL;
  2219.     }
  2220.     return HXR_OK;
  2221. }
  2222. STDMETHODIMP CSimpleFileObject::Move
  2223. (
  2224.     const char* pFilename
  2225. )
  2226. {
  2227.     CHXString strFilename;
  2228.     CHXString newFilename;
  2229.     HX_RESULT retVal = HXR_OK;
  2230.     UpdateFileNameMember();
  2231.     newFilename = pFilename;
  2232.     HXXFile::GetReasonableLocalFileName(newFilename);
  2233.     GetFullPathname((const char*) newFilename, &newFilename);
  2234.     GetFullPathname(m_pFilename, &strFilename);
  2235.     if (DoRename(strFilename, newFilename, &m_pFileSystem->m_pCommonObj) == FALSE)
  2236.     {
  2237. #ifdef _UNIX
  2238. // We'll attempt to move the file manually since on UNIX
  2239. // rename accross devices (file systems) is not supported
  2240. FILE* pSource = fopen((const char*) strFilename, "rb");
  2241. FILE* pTarget = fopen((const char*) newFilename, "rb");
  2242. retVal = HXR_FAIL;
  2243. if (pTarget)
  2244. {
  2245.     // Target file already exists -> fail.
  2246.     fclose(pTarget);
  2247.     pTarget = NULL;
  2248. }
  2249. else
  2250. {
  2251.     pTarget = fopen((const char*) newFilename, "wb");
  2252. }
  2253. if (pSource && pTarget)
  2254. {
  2255.     retVal = HXR_OK;
  2256. }
  2257. if (retVal == HXR_OK)
  2258. {
  2259.     const ULONG32 COPY_BUF_SIZE = 1024;
  2260.     UINT8 pBuffer[COPY_BUF_SIZE];
  2261.     size_t bufLen;
  2262.     do
  2263.     {
  2264. bufLen = fread(pBuffer, 1, COPY_BUF_SIZE, pSource);
  2265. if (bufLen > 0)
  2266. {
  2267.     if (fwrite(pBuffer, 1, bufLen, pTarget) != bufLen)
  2268.     {
  2269. retVal = HXR_FAIL;
  2270. break;
  2271.     }
  2272. }
  2273.     } while (bufLen == COPY_BUF_SIZE);
  2274. }
  2275. // Make sure no erorrs occured
  2276. if (retVal == HXR_OK)
  2277. {
  2278.     retVal = HXR_FAIL;
  2279.     if (feof(pSource) &&
  2280. (ferror(pSource) == 0) &&
  2281. (ferror(pTarget) == 0))
  2282.     {
  2283. retVal = HXR_OK;
  2284.     }
  2285. }
  2286. if (pSource)
  2287. {
  2288.     fclose(pSource);
  2289.     pSource = NULL;
  2290. }
  2291. // Remove the source file - only if copied OK
  2292. if (retVal == HXR_OK)
  2293. {
  2294.     if (remove((const char*) strFilename) != 0)
  2295.     {
  2296. retVal = HXR_FAIL;
  2297.     }
  2298. }
  2299. if (pTarget)
  2300. {
  2301.     fclose(pTarget);
  2302.     pTarget = NULL;
  2303.     // In case of failure, remove the target
  2304.     if (retVal != HXR_OK)
  2305.     {
  2306. remove((const char*) newFilename);
  2307.     }
  2308. }
  2309. #else // _UNIX
  2310. retVal = HXR_FAIL;
  2311. #endif // _UNIX
  2312.     }
  2313.     return retVal;
  2314. }
  2315. STDMETHODIMP
  2316. CSimpleFileObject::Remove()
  2317. {
  2318. #ifdef _MACINTOSH
  2319.     CHXString strFilename;
  2320.     UpdateFileNameMember();
  2321.     strFilename = m_pFilename;
  2322.     GetFullPathname((const char*)strFilename, &strFilename);
  2323.     if (unlink((const char*)strFilename) != 0)
  2324.     {
  2325. return HXR_FAIL;
  2326.     }
  2327.     return HXR_OK;
  2328. #else
  2329.     UpdateFileNameMember();
  2330.     CHXString strFileName;
  2331.     CHXString strUrl = m_pFilename;
  2332.     // Make a nice local file name from the URL!
  2333.     HXXFile::GetReasonableLocalFileName(strUrl);
  2334.     GetFullPathname(strUrl, &strFileName);
  2335.     m_pDataFile->Bind((const char*)strFileName);
  2336.     HX_RESULT res = m_pDataFile->Delete();
  2337.     if (res == HXR_OK)
  2338.     {
  2339. m_nFd = -1;
  2340.     }
  2341.     return res;
  2342. #endif
  2343. }
  2344. void
  2345. CSimpleFileObject::GetFullPathname(const char* pPath, CHXString* pPathname)
  2346. {
  2347.     if (m_base_path.GetLength() > 0)
  2348.     {
  2349. INT32 lLevel = 0;
  2350. for (const char* pTemp = pPath; *pTemp; pTemp++)
  2351. {
  2352.     /*
  2353.      * Increment directory level if we have a slash, and it's
  2354.      * not a leading slash, and it's not right after a slash
  2355.      * (doesn't count on most OSes).
  2356.      */
  2357.     if (((*pTemp == OS_SEPARATOR_CHAR) ||
  2358.          (*pTemp == '/')) && (pTemp != pPath) &&
  2359.       ((*(pTemp-1)) != OS_SEPARATOR_CHAR) &&
  2360.       ((*(pTemp-1)) != '/'))
  2361.     {
  2362. lLevel++;
  2363.     }
  2364.     if ((pTemp != pPath) &&
  2365.      (*pTemp == '.') &&
  2366.      (*(pTemp - 1) == '.'))
  2367.     {
  2368. lLevel--;
  2369. if (((*(pTemp + 1)) == OS_SEPARATOR_CHAR) ||
  2370.     ((*(pTemp + 1)) == '/'))
  2371. {
  2372.     pTemp++;
  2373. }
  2374. if (lLevel < 0)
  2375. {
  2376.     *pPathname = "!$InvalidPath";
  2377.     return;
  2378. }
  2379.     }
  2380. }
  2381. if (*pPath)
  2382. {
  2383. #if defined(_MACINTOSH) && !defined(_CARBON)
  2384.     CHXString strPath;
  2385.     CHXURL::decodeURL(pPath, strPath);
  2386.             pPath = (const char*)strPath;
  2387.             UINT32 ulPathLen = strPath.GetLength();
  2388. #else
  2389.             UINT32 ulPathLen = strlen(pPath);
  2390. #endif
  2391.             UINT32 ulBaseLen = m_base_path.GetLength();
  2392.             char* pStr = new char[ulBaseLen + ulPathLen + 2];
  2393.             char* pTmp = pStr;
  2394.             if (ulBaseLen)
  2395.             {
  2396.                 memcpy(pTmp, (const char*)m_base_path, ulBaseLen); /* Flawfinder: ignore */
  2397.                 pTmp += ulBaseLen;
  2398.             }
  2399.             *pTmp = OS_SEPARATOR_CHAR;
  2400.             pTmp++;
  2401.             memcpy(pTmp, pPath, ulPathLen + 1); /* Flawfinder: ignore */
  2402.             CHXString strResult(pStr, ulBaseLen + ulPathLen + 2);
  2403.             *pPathname = strResult;
  2404.             delete[] pStr;
  2405. }
  2406. else
  2407. {
  2408.     *pPathname = m_base_path;
  2409. }
  2410.     }
  2411.     else
  2412.     {
  2413. #if defined (_MACINTOSH) && !defined(_CARBON)
  2414.         CHXString strPath;
  2415.         CHXURL::decodeURL(pPath, strPath);
  2416. #else
  2417.         CHXString strPath(pPath, strlen(pPath));
  2418. #endif
  2419.         *pPathname = strPath;
  2420.     }
  2421. }
  2422. HX_RESULT
  2423. CSimpleFileObject::ActualAsyncReadDone(HX_RESULT result, IHXBuffer* pBuffer)
  2424. {
  2425.     MLOG_PD(NULL, "CSimpleFileObject::ActualAsyncReadDone(0x%08x,0x%08x) tick=%lun",
  2426.             result, pBuffer, HX_GET_BETTERTICKCOUNT());
  2427.     HX_LOG_BLOCK( "CSimpleFileObject::ActualAsyncReadDone" );
  2428.     m_bReadPending = FALSE;
  2429.     m_bAsyncReadPending = FALSE;
  2430.     // Let the file response sink know about the buffer...
  2431.     HX_RESULT rv = m_pFileResponse->ReadDone(result, pBuffer);
  2432.     MLOG_PD(NULL, "treturning 0x%08x from ActualAsyncReadDone() tick=%lun",
  2433.             rv, HX_GET_BETTERTICKCOUNT());
  2434.     return rv;
  2435. }
  2436. HX_RESULT
  2437. CSimpleFileObject::ActualAsyncSeekDone(HX_RESULT result)
  2438. {
  2439. #ifndef _MACINTOSH
  2440.     MLOG_PD(NULL, "CSimpleFileObject::ActualAsyncSeekDone(0x%08x) tick=%lun",
  2441.             result, HX_GET_BETTERTICKCOUNT());
  2442.     HX_RESULT rv = m_pFileResponse->SeekDone(result);
  2443.     MLOG_PD(NULL, "treturning 0x%08x from ActualAsyncSeekDone() tick=%lun",
  2444.             rv, HX_GET_BETTERTICKCOUNT());
  2445.     return rv;
  2446. #else
  2447.     switch (m_eSeekReason)
  2448.     {
  2449. case REINIT_SEEK:
  2450.     return m_pFileResponse->InitDone(!result ? HXR_OK : HXR_FAIL);
  2451. case EXTERNAL_SEEK:
  2452.     return m_pFileResponse->SeekDone(result);
  2453. case PRE_TELL_SEEK:
  2454.     {
  2455. m_ulSize = m_pDataFile->Tell();
  2456. BOOL bAtInterrupt = FALSE;
  2457. if (m_pInterruptState)
  2458. {
  2459.     bAtInterrupt = m_pInterruptState->AtInterruptTime();
  2460. }
  2461. m_eSeekReason = POST_TELL_SEEK;
  2462. /* If we need to close the file, why waste time in seeking back
  2463.  * to the original position
  2464.  */
  2465. if (!m_bFileToBeClosed)
  2466. {
  2467.     m_pDataFile->SafeSeek(m_ulPreSeekPosition,SEEK_SET);
  2468. }
  2469. else
  2470. {
  2471.     ActualAsyncSeekDone(result);
  2472. }
  2473.     }
  2474.     break;
  2475. case POST_TELL_SEEK:
  2476.     {
  2477. if (m_bFileToBeClosed && m_pDataFile)
  2478. {
  2479.     m_bFileToBeClosed = FALSE;
  2480.     HX_RELEASE(m_pDataFile);
  2481.     m_pDataFile = NULL;
  2482.     m_nFd = -1;
  2483. }
  2484. struct stat StatBuffer;
  2485. StatBuffer.st_size = m_ulSize;
  2486. StatBuffer.st_ctime = 0;
  2487. StatBuffer.st_atime = 0;
  2488. StatBuffer.st_mtime = 0;
  2489. StatBuffer.st_mode = 0;
  2490. if (m_pFileStatResponse)
  2491. {
  2492.     // Access to members after async ..Done() call is invalid
  2493.     IHXFileStatResponse *pTmpFileStatResponse = m_pFileStatResponse;
  2494.     m_pFileStatResponse = NULL;
  2495.     pTmpFileStatResponse->StatDone( HXR_OK,
  2496.     StatBuffer.st_size,
  2497.     StatBuffer.st_ctime,
  2498.     StatBuffer.st_atime,
  2499.     StatBuffer.st_mtime,
  2500.     StatBuffer.st_mode);
  2501.     pTmpFileStatResponse->Release();
  2502. }
  2503.     }
  2504.     break;
  2505. default:
  2506.     HX_ASSERT(FALSE);
  2507.     return HXR_FAIL;
  2508.     }
  2509.     return HXR_OK;
  2510. #endif
  2511. }
  2512. STDMETHODIMP_(UINT32)
  2513. CSimpleFileObject::IsThreadSafe()
  2514. {
  2515.     return HX_THREADSAFE_METHOD_FS_READ;
  2516. }
  2517. #ifdef _MACINTOSH
  2518. // SMPLAsyncResponse
  2519. CSimpleFileObject::SMPLAsyncResponse::SMPLAsyncResponse(CSimpleFileObject* pFileObject)
  2520. {
  2521.     m_pSMPLFileObject = pFileObject;
  2522. }
  2523. CSimpleFileObject::SMPLAsyncResponse::~SMPLAsyncResponse()
  2524. {
  2525. }
  2526. HX_RESULT
  2527. CSimpleFileObject::SMPLAsyncResponse::AsyncReadDone (HX_RESULT result, IHXBuffer* pBuffer)
  2528. {
  2529.     m_pSMPLFileObject->ActualAsyncReadDone(result, pBuffer);
  2530.     return HXR_OK;
  2531. }
  2532. HX_RESULT
  2533. CSimpleFileObject::SMPLAsyncResponse::AsyncSeekDone (HX_RESULT result)
  2534. {
  2535.     m_pSMPLFileObject->ActualAsyncSeekDone(result);
  2536.     return HXR_OK;
  2537. }
  2538. #endif /*_MACINTOSH*/
  2539. #if defined(HELIX_FEATURE_PROGDOWN)
  2540. STDMETHODIMP CSimpleFileObject::ProgressiveCallback()
  2541. {
  2542.     if (m_ulCallbackState == CallbackStateSeek)
  2543.     {
  2544.         MLOG_PD(NULL, "CSimpleFileObject::ProgressiveCallback() this=0x%08x tick=%lu state=%sn",
  2545.                 this, HX_GET_BETTERTICKCOUNT(), "CallbackStateSeek");
  2546.         // Make sure we do not destruct during SeekDone()
  2547.         AddRef();
  2548.         // Do the seek
  2549.         HX_RESULT seekDoneResult = HXR_OK;
  2550.         DoSeek(seekDoneResult);
  2551.         // Undo the AddRef();
  2552.         Release();
  2553.     }
  2554.     else if (m_ulCallbackState == CallbackStateRead)
  2555.     {
  2556.         MLOG_PD(NULL, "CSimpleFileObject::ProgressiveCallback() this=0x%08x tick=%lu state=%sn",
  2557.                 this, HX_GET_BETTERTICKCOUNT(), "CallbackStateRead");
  2558.         // Make sure we do not destruct in ReadDone()
  2559.         AddRef();
  2560.         // Call DoRead()
  2561.         BOOL bProgFail = FALSE;
  2562.         DoRead(bProgFail);
  2563.         // Undo the AddRef()
  2564.         Release();
  2565.     }
  2566.     return HXR_OK;
  2567. }
  2568. BOOL CSimpleFileObject::RequireFullRead()
  2569. {
  2570.     BOOL bRet = FALSE;
  2571.     if (m_pFileResponse)
  2572.     {
  2573.         // QueryInterface for the IHXAdvise interface
  2574.         IHXAdvise* pAdvise = NULL;
  2575.         m_pFileResponse->QueryInterface(IID_IHXAdvise, (void**) &pAdvise);
  2576.         if (pAdvise)
  2577.         {
  2578.             if (SUCCEEDED(pAdvise->Advise(HX_FILERESPONSEADVISE_REQUIREFULLREAD)))
  2579.             {
  2580.                 bRet = TRUE;
  2581.             }
  2582.         }
  2583.         HX_RELEASE(pAdvise);
  2584.     }
  2585.     return bRet;
  2586. }
  2587. HX_RESULT CSimpleFileObject::FinishDoReadWithCallback(UINT32 actual)
  2588. {
  2589.     // Seek backwards if necessary
  2590.     SeekBackwards(actual);
  2591.     // Set the callback state
  2592.     m_ulCallbackState = CallbackStateRead;
  2593.     // Schedule a callback to try the read again
  2594.     m_pProgDownMon->ScheduleCallback();
  2595.     return HXR_OK;
  2596. }
  2597. HX_RESULT CSimpleFileObject::FinishDoReadWithoutCallback(UINT32 actual)
  2598. {
  2599.     // Seek backwards if necessary
  2600.     SeekBackwards(actual);
  2601.     // Since we can't employ callback when m_bAsyncAccess is FALSE,
  2602.     // then we must sleep. We'll sleep for 100ms (or 100000 microsec)
  2603.     microsleep(100000);
  2604.     return HXR_OK;
  2605. }
  2606. #endif /* #if defined(HELIX_FEATURE_PROGDOWN) */
  2607. void CSimpleFileObject::StackCallback(void* pArg)
  2608. {
  2609.     MLOG_PD(NULL, "CSimpleFileObject::StackCallback() tick=%lun", HX_GET_BETTERTICKCOUNT());
  2610.     if (pArg)
  2611.     {
  2612.         CSimpleFileObject* pFileObject = (CSimpleFileObject*) pArg;
  2613.         pFileObject->AddRef();
  2614.         BOOL bProgFail = FALSE;
  2615.         pFileObject->DoRead(bProgFail);
  2616.         pFileObject->Release();
  2617.     }
  2618. }