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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: minifileobj.cpp,v 1.14.2.2 2004/07/09 02:04:12 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. /****************************************************************************
  50.  * Includes
  51.  */
  52. #include "hxtypes.h"
  53. #include "hlxclib/stdio.h"    /* FILE */
  54. #include "hlxclib/string.h"   /* strcpy, etc. */
  55. #include "hlxclib/sys/stat.h" /* stat() */
  56. #if defined (_WINDOWS ) && defined (_WIN32)
  57. #include <atlbase.h>
  58. #ifndef _WINCE
  59. #include <direct.h>    /* mkdir, etc. */
  60. #endif
  61. #elif defined (_MACINTOSH)
  62. #include <unix.h>      /* fileno */
  63. #endif
  64. #include "hxcom.h"     /* IUnknown */
  65. #include "hxcomm.h"    /* IHXCommonClassFactory */
  66. #include "ihxpckts.h"  /* IHXValues, IHXBuffers */
  67. #include "rtsputil.h"
  68. #include "minifilesys.h"  /* FILE_SYS_PROTOCOL */
  69. #include "minifileobj.h"  /* CHXMiniFileObject */
  70. #include "debug.h" /* DPRINTF */
  71. #include "hxdir.h" /* OS_SEPERATOR_STRING */
  72. #define D_MINI_FO 0x1000000
  73. // CHXMiniFileObject Class Methods
  74. /****************************************************************************
  75.  *  CHXMiniFileObject::CHXMiniFileObject
  76.  *
  77.  *  Constructor
  78.  */
  79. CHXMiniFileObject::CHXMiniFileObject(IHXCommonClassFactory* pClassFactory, const char* pBasePath): m_RefCount(0),
  80.       m_pClassFactory  (pClassFactory),
  81.       m_pFileResponse  (NULL),
  82.       m_pFile          (NULL),
  83.       m_pFilename      (NULL),
  84.       m_pRequest       (NULL),
  85.       m_pBasePath      (NULL),
  86. #if defined (_WINDOWS ) && defined (_WIN32)
  87.       m_hFileHandle    (0),
  88. #endif
  89.       m_FileAccessMode (0),
  90.       m_pDirResponse   (NULL),
  91.       m_bInReadDone(FALSE),
  92.       m_pPendingReadBuf(NULL)
  93. {
  94.     DPRINTF(D_MINI_FO, ("CHXMiniFO::CHXMiniFileObject()n"));
  95.     // Signify that we need to keep a reference to this object
  96.     if (m_pClassFactory != NULL)
  97.     {
  98.         m_pClassFactory->AddRef();
  99.     }
  100.     if (pBasePath)
  101.     {
  102.         m_pBasePath = new char[strlen(pBasePath) + 1];
  103.         if (m_pBasePath)
  104.         {
  105.             strcpy(m_pBasePath, pBasePath);
  106.         }
  107.     }
  108. }
  109. /****************************************************************************
  110.  *  CHXMiniFileObject::~CHXMiniFileObject
  111.  *
  112.  *  Destructor. It is essential to call the Close() routine before destroying
  113.  *  this object.
  114.  */
  115. CHXMiniFileObject::~CHXMiniFileObject(void)
  116. {
  117.     DPRINTF(D_MINI_FO, ("CHXMiniFO::~CHXMiniFileObject()n"));
  118.     Close();
  119.     delete [] m_pBasePath;
  120.     m_pBasePath = 0;
  121.     if (m_pFilename != NULL)
  122.     {
  123.         delete[] m_pFilename;
  124.         m_pFilename = 0;
  125.     }
  126.     if (m_pClassFactory != NULL)
  127.     {
  128.         m_pClassFactory->Release();
  129.         m_pClassFactory = NULL;
  130.     }
  131. }
  132. /****************************************************************************
  133.  *  CHXMiniFileObject::OpenFile
  134.  *
  135.  *  This routine opens a file according to the access mode given. It is
  136.  *  called while initializing the File Object.
  137.  */
  138. STDMETHODIMP CHXMiniFileObject::OpenFile(UINT32 fileAccessMode)
  139. {
  140.     HX_RESULT   result    = HXR_OK;
  141.     // Construct the proper access mode string
  142.     char modeStr[4];
  143.     if (fileAccessMode & HX_FILE_READ)
  144.     {
  145.         strcpy(modeStr, "r");
  146.         if (fileAccessMode & HX_FILE_WRITE)
  147.         {
  148.             strcat(modeStr, "+");
  149.         }
  150.         if (fileAccessMode & HX_FILE_BINARY)
  151.         {
  152.             strcat(modeStr, "b");
  153.         }
  154.     }
  155.     else if (fileAccessMode & HX_FILE_WRITE)
  156.     {
  157.         strcpy(modeStr, "w");
  158.         if (fileAccessMode & HX_FILE_BINARY)
  159.         {
  160.             strcat(modeStr, "b");
  161.         }
  162.     }
  163.     else if (fileAccessMode == 0)
  164.     {
  165.         fileAccessMode = HX_FILE_READ | HX_FILE_BINARY;
  166.         strcpy(modeStr, "rb");
  167.     }
  168.     else
  169.     {
  170.         result = HXR_INVALID_PARAMETER;
  171.     }
  172.     // Open the file with the proper access mode
  173.     if (result == HXR_OK)
  174.     {
  175.         m_pFile = fopen(m_pFilename, modeStr);
  176.         result =  m_pFile ? HXR_OK : HXR_DOC_MISSING;
  177.     }
  178.     return result;
  179. }
  180. /****************************************************************************
  181.  *  CHXMiniFileObject::ConvertToPlatformPath
  182.  *
  183.  *  This routine converts the given file path to a platform specific file
  184.  *  path based upon the naming conventions of that platform. The platform
  185.  *  specific path name is required to properly open the file.
  186.  */
  187. STDMETHODIMP CHXMiniFileObject::ConvertToPlatformPath(REF(char*)  pFilePathPlatform, const char* pFilePath)
  188. {
  189.     HX_RESULT res = HXR_OUTOFMEMORY;
  190.     pFilePathPlatform =  0;
  191.     if (m_pBasePath && pFilePath)
  192.     {
  193.         // Create new string
  194.         pFilePathPlatform =
  195.             new char[ strlen(m_pBasePath) + strlen(pFilePath) + 2 ];
  196.     }
  197.     UINT32 length = strlen(FILE_SYS_PROTOCOL) + 1; // Add 1 for the colon
  198.     char* pProtocolString = new char[length + 1];
  199.     if (pFilePathPlatform && pProtocolString && m_pBasePath)
  200.     {
  201.         // Prepend base path, if any
  202.         if (strlen(m_pBasePath) > 0)
  203.         {
  204.             strcpy(pFilePathPlatform, m_pBasePath);
  205.             strcat(pFilePathPlatform, OS_SEPARATOR_STRING);
  206.             strcat(pFilePathPlatform, pFilePath);
  207.         }
  208.         else
  209.         {
  210.             strcpy(pFilePathPlatform, pFilePath);
  211.         }
  212.         // Strip protocol string, if any
  213.         strcpy(pProtocolString, FILE_SYS_PROTOCOL);
  214.         strcat(pProtocolString, ":");
  215.         if (strnicmp(pFilePathPlatform, pProtocolString, length) == 0)
  216.         {
  217.             //copy the rest of the string back onto itself.
  218.             memmove( (void*) pFilePathPlatform,
  219.                      (void*) &pFilePathPlatform[length],
  220.                      (strlen( &pFilePathPlatform[length] )+1)*sizeof(char)
  221.                      );
  222.             if ((pFilePathPlatform[0] == '/') &&
  223.                 (pFilePathPlatform[1] == '/'))
  224.             {
  225.                 // "file://" forms
  226.                 // Find next '/'
  227.                 const char* pNext = strchr(pFilePathPlatform + 2, '/');
  228.                 if (pNext)
  229.                 {
  230.                     // "file://host/path" or "file:///path" form.
  231.                     // Copy everything after the third '/'
  232.                     memmove( (void*) pFilePathPlatform,
  233.                              (void*) (pNext+1),
  234.                              (strlen(pNext+1)+1)*sizeof(char)
  235.                              );
  236.                     pNext = 0;
  237.                     res = HXR_OK;
  238.                 }
  239.                 else
  240.                 {
  241.                     // Forms: file://c:file.ra
  242.                     //        file://file.ra
  243.                     memmove( (void*) pFilePathPlatform,
  244.                              (void*) (pFilePathPlatform+2),
  245.                              (strlen(pFilePathPlatform+2)+1)*sizeof(char)
  246.                              );
  247.                     res = HXR_OK;
  248.                 }
  249.             }
  250.             else
  251.             {
  252.                 res = HXR_OK;
  253.             }
  254.             if (HXR_OK == res)
  255.             {
  256.                 // Replace path slashes with platform specific path separators
  257.                 // and watch for the parameter delimiter
  258.                 char* pCur = pFilePathPlatform;
  259.                 for (; *pCur && (*pCur != '?'); pCur++)
  260.                 {
  261.                     if (*pCur == '/')
  262.                     {
  263.                         *pCur = OS_SEPARATOR_CHAR;
  264.                     }
  265.                 }
  266.                 /*
  267.                  * Strip off the parameters
  268.                  */
  269.                 if (*pCur == '?')
  270.                 {
  271.                     *pCur = '';
  272.                 }
  273.             }
  274.         }
  275.         else
  276.         {
  277. if (NULL == strstr(pFilePathPlatform,"//"))
  278. res = HXR_OK; // allow path/file w/o file://
  279. else
  280.             res = HXR_INVALID_PROTOCOL;
  281.         }
  282.     }
  283.     delete [] pProtocolString;
  284.     pProtocolString = 0;
  285.     if (res != HXR_OK)
  286.     {
  287.         delete [] pFilePathPlatform;
  288.         pFilePathPlatform = 0;
  289.     }
  290.     return res;
  291. }
  292. // IHXFileObject Interface Methods
  293. /****************************************************************************
  294.  *  IHXFileObject::Init
  295.  *
  296.  *  This routine associates this File Object with a File Response object
  297.  *  which is notified when file operations (read, write, seek, etc.) are
  298.  *  complete. This method also checks the validity of the file by actually
  299.  *  opening it.
  300.  */
  301. STDMETHODIMP CHXMiniFileObject::Init( UINT32 fileAccessMode, IHXFileResponse* pFileResponse )
  302. {
  303.     /*
  304.      * Associate this File Object with a File Response object for completion
  305.      * notification.
  306.      */
  307.     DPRINTF(D_MINI_FO, ("CHXMiniFO::Init()n"));
  308.     if (pFileResponse != NULL)
  309.     {
  310.         // Release any previous File Response objects
  311.         if (m_pFileResponse != NULL)
  312.         {
  313.             m_pFileResponse->Release();
  314.         }
  315.         m_pFileResponse = pFileResponse;
  316.         m_pFileResponse->AddRef();
  317.     }
  318.     else
  319.     {
  320.         return HXR_INVALID_PARAMETER;
  321.     }
  322.     /*
  323.      * Open the file and notify File Response when complete
  324.      */
  325.     if (m_pFile != NULL) // File is already open
  326.     {
  327.         // Has requested access mode changed?
  328.         if ((fileAccessMode == m_FileAccessMode) ||
  329.             (fileAccessMode == 0))
  330.         {
  331.             // reset to start of file
  332.             fseek(m_pFile, 0, SEEK_SET);
  333.             // notify that file is ready
  334.             m_pFileResponse->InitDone(HXR_OK);
  335.             return HXR_OK;
  336.         }
  337.         else // Access mode has changed
  338.         {
  339.             fclose(m_pFile);
  340.             m_pFile = NULL;
  341.         }
  342.     }
  343.     m_FileAccessMode = fileAccessMode;
  344.     HX_RESULT fileOpenResult = OpenFile(fileAccessMode);
  345.     m_pFileResponse->InitDone(fileOpenResult);
  346.     return fileOpenResult;
  347. }
  348. /****************************************************************************
  349.  *  IHXFileObject::GetFilename
  350.  *
  351.  *  This routine returns the name of the requested file (without any path
  352.  *  information). This method may be called by the File Format plug-in if the
  353.  *  short name of the file is required.
  354.  */
  355. STDMETHODIMP CHXMiniFileObject::GetFilename( REF(const char*) pFileName )
  356. {
  357.     DPRINTF(D_MINI_FO, ("CHXMiniFO::GetFilename()n"));
  358.     pFileName = NULL;
  359.     HX_RESULT   result = HXR_OK;
  360.     // Find the separator character before the file name
  361.     pFileName = ::strrchr(m_pFilename, OS_SEPARATOR_CHAR);
  362.     if (pFileName != NULL) // Found
  363.     {
  364.         // File name starts after the separator charactor
  365.         pFileName++;
  366.     }
  367.     else // Not found
  368.     {
  369.         pFileName = m_pFilename;
  370.     }
  371.     return result;
  372. }
  373. /****************************************************************************
  374.  *  IHXFileObject::Read
  375.  *
  376.  *  This routine reads a block of data of the specified length from the file.
  377.  *  When reading has completed, the caller is asynchronously notified via the
  378.  *  File Response object associated with this File Object. This method is
  379.  *  called by the File Format plug-in when it needs to read from the file.
  380.  */
  381. STDMETHODIMP CHXMiniFileObject::Read( UINT32 byteCount )
  382. {
  383.     DPRINTF(D_MINI_FO, ("CHXMiniFO::Read(%u)n", byteCount));
  384.     HX_RESULT result = HXR_UNEXPECTED;
  385.     if ((m_pPendingReadBuf == NULL) && (m_pClassFactory != NULL))
  386.     {
  387. if (byteCount > 0x000FFFFF)
  388. {
  389.     m_bInReadDone = FALSE;
  390.     m_pFileResponse->ReadDone(HXR_FAILED, NULL);
  391.     return HXR_INVALID_PARAMETER;
  392. }
  393. m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&m_pPendingReadBuf);
  394.         if (m_pPendingReadBuf != NULL)
  395.         {
  396.             result =  m_pPendingReadBuf->SetSize(byteCount);
  397.             if (HXR_OK != result)
  398.             {
  399.                 HX_RELEASE(m_pPendingReadBuf);
  400.             }
  401.             else if (!m_bInReadDone)
  402.             {
  403.                 // We use a loop here so we can service Read() calls
  404.                 // occurred inside the ReadDone() callback
  405.                 while (m_pPendingReadBuf)
  406.                 {
  407.                     // Transfer ownership of the pending buffer to
  408.                     // this local variable. This prepares for the
  409.                     // possibility that Read() may be called from
  410.                     // ReadDone()
  411.                     IHXBuffer* pBuffer = m_pPendingReadBuf;
  412.                     m_pPendingReadBuf = NULL;
  413.                     // Read from the file directly into the buffer object
  414.                     UINT32 actualCount = fread(pBuffer->GetBuffer(),
  415.                                                sizeof(UCHAR),
  416.                                                pBuffer->GetSize(), m_pFile);
  417.                     result = pBuffer->SetSize(actualCount);
  418.                     // Notify the caller that the read is done
  419.                     HX_RESULT readResult = actualCount > 0 ? HXR_OK : HXR_FAILED;
  420.                     m_bInReadDone = TRUE;
  421.                     // If heap gets low, memory allocations for new file read
  422.                     // buffers is one of the first places we notice it, and
  423.                     // if we're not careful to report this error, we can get
  424.                     // into a state where the renderer is stuck trying to
  425.                     // rebuffer, but the front end can't get any new data
  426.                     // because we can't allocate any new buffers. If we replace
  427.                     // this with a caching buffer system, this issue goes away.
  428.                     if( result == HXR_OK )
  429.                     {
  430.                         result = m_pFileResponse->ReadDone(readResult, pBuffer);
  431.                     }
  432.                     m_bInReadDone = FALSE;
  433.                     // Release our handle on the buffer
  434.                     HX_RELEASE(pBuffer);
  435.                 }
  436.             }
  437.         }
  438.         else
  439.         {
  440.             result = HXR_OUTOFMEMORY;
  441.         }
  442.     }
  443.     return result;
  444. }
  445. /****************************************************************************
  446.  *  IHXFileObject::Write
  447.  *
  448.  *  This routine writes a block of data to the file. When writing has
  449.  *  completed, the caller is asynchronously notified via the File Response
  450.  *  object associated with this File Object. This method called by the File
  451.  *  Format plug-in when it needs to write to the file.
  452.  */
  453. STDMETHODIMP CHXMiniFileObject::Write(IHXBuffer* pDataToWrite)
  454. {
  455.     DPRINTF(D_MINI_FO, ("CHXMiniFO::Write()n"));
  456.     UINT32 byteCount =  pDataToWrite->GetSize();
  457.     UINT32 actualCount = fwrite(pDataToWrite->GetBuffer(), sizeof(UCHAR), byteCount, m_pFile);
  458.     // Notify the caller that the write is done
  459.     HX_RESULT writeResult = (actualCount == byteCount) ? HXR_OK : HXR_FAILED;
  460.     m_pFileResponse->WriteDone(writeResult);
  461.     return HXR_OK;
  462. }
  463. /****************************************************************************
  464.  *  IHXFileObject::Seek
  465.  *
  466.  *  This routine moves to a given position in the file. The move can be
  467.  *  either from the beginning of the file (absolute), or relative to the
  468.  *  current file position. When seeking has completed, the caller is
  469.  *  asynchronously notified via the File Response object associated with this
  470.  *  File Object. This method called by the File Format plug-in when it needs
  471.  *  to seek to a location within the file.
  472.  */
  473. STDMETHODIMP CHXMiniFileObject::Seek( UINT32 offset, BOOL bIsRelative )
  474. {
  475.     DPRINTF(D_MINI_FO, ("CHXMiniFO::Seek()n"));
  476.     // Cancel any pending reads
  477.     HX_RELEASE(m_pPendingReadBuf);
  478.     int fromWhere = SEEK_SET; // absolute
  479.     if (bIsRelative == TRUE)
  480.     {
  481.                 fromWhere = SEEK_CUR; // relative
  482.     }
  483.     int seekResult = HXR_FAIL;
  484.     if (m_pFile)
  485.         seekResult = fseek(m_pFile, offset, fromWhere);
  486.     // Notify the caller that the seek is done
  487.     HX_RESULT result = !seekResult ? HXR_OK : HXR_FAILED;
  488.     HX_RESULT retVal = m_pFileResponse->SeekDone(result);
  489.     // Memory allocations can be attempted in the execution of SeekDone, and we
  490.     // want to catch these if they fail.
  491.     if( retVal != HXR_OUTOFMEMORY )
  492.     {
  493.         retVal = result;
  494.     }
  495.     return (retVal);
  496. }
  497. /****************************************************************************
  498.  *  IHXFileObject::Advise
  499.  *
  500.  *  This routine is passed information about the intended usage of this
  501.  *  object. The useage will indicate whether sequential or random requests
  502.  *  for information will be made. This may be useful, for example, in
  503.  *  developing a caching scheme.
  504.  */
  505. STDMETHODIMP CHXMiniFileObject::Advise(UINT32 ui/* useage */)
  506. {
  507.     DPRINTF(D_MINI_FO, ("CHXMiniFO::Advise()n"));
  508.     return HXR_UNEXPECTED;
  509. }
  510. /****************************************************************************
  511.  *  IHXFileObject::Close
  512.  *
  513.  *  This routine closes the file resource and releases all resources
  514.  *  associated with the object. This routine is crucial and must be called
  515.  *  before the File Object is destroyed.
  516.  */
  517. STDMETHODIMP CHXMiniFileObject::Close(void)
  518. {
  519.     DPRINTF(D_MINI_FO, ("CHXMiniFO::Close()n"));
  520.     if (m_pFile != NULL)
  521.     {
  522.         fclose(m_pFile);
  523.         m_pFile = NULL;
  524.     }
  525.     if (m_pRequest != NULL)
  526.     {
  527.         m_pRequest->Release();
  528.         m_pRequest = NULL;
  529.     }
  530. #if defined (_WINDOWS ) && defined (_WIN32)
  531.     if (m_hFileHandle)
  532.     {
  533.         ::FindClose( m_hFileHandle );
  534.         m_hFileHandle = 0;
  535.     }
  536. #endif
  537.     /*
  538.      * Store this in temp so that if calling CloseDone
  539.      * causes our descructor to get called we will
  540.      * have pCallCloseDone on the stack to safely release.
  541.      */
  542.     IHXFileResponse* pCallCloseDone = m_pFileResponse;
  543.     if (m_pFileResponse != NULL)
  544.     {
  545.         m_pFileResponse = NULL;
  546.         pCallCloseDone->CloseDone(HXR_OK);
  547.         pCallCloseDone->Release();
  548.     }
  549.     return HXR_OK;
  550. }
  551. // IHXRequestHandler Interface Methods
  552. /****************************************************************************
  553.  *  IHXRequestHandler::SetRequest
  554.  *
  555.  *  This routine associates this File Object with the file Request object
  556.  *  passed to it from the Helix core. This Request object is primarily used to
  557.  *  obtain the requested URL. This method is called just after the File
  558.  *  Object is created.
  559.  */
  560. STDMETHODIMP CHXMiniFileObject::SetRequest(IHXRequest* pRequest)
  561. {
  562.     HX_RESULT res = HXR_FAIL;
  563.     DPRINTF(D_MINI_FO, ("CHXMiniFO::SetRequest()n"));
  564.     // Reset the current request object and associated filename
  565.     HX_RELEASE(m_pRequest);
  566.     m_pRequest = pRequest;
  567.     HX_VECTOR_DELETE(m_pFilename);
  568.     if (m_pRequest)
  569.     {
  570.         m_pRequest->AddRef();
  571.         const char* pURL;
  572.         if (m_pRequest->GetURL(pURL) == HXR_OK && pURL)
  573.         {
  574.             // Ensure that we are working with an unescaped URL
  575.             INT32 cchEscaped = strlen(pURL);
  576.             // Unescaped URL is at most same size or smaller
  577.             char* pUnescaped = new char [cchEscaped + 1];
  578.             if( pUnescaped)
  579.             {
  580.                 INT32 cchNew = URLUnescapeBuffer(pURL, cchEscaped, pUnescaped);
  581.                 if(cchNew > 0)
  582.                 {
  583.                     pUnescaped[cchNew] = '';
  584.                     res = ConvertToPlatformPath(m_pFilename, pUnescaped);
  585.                 }
  586.                 delete[] pUnescaped;
  587.             }
  588.         }
  589.     }
  590.     return res;
  591. }
  592. /****************************************************************************
  593.  *  IHXRequestHandler::GetRequest
  594.  *
  595.  *  This routine retrieves the Request object associated with this File
  596.  *  Object. It is called just after the SetRequest() method.
  597.  */
  598. STDMETHODIMP CHXMiniFileObject::GetRequest(REF(IHXRequest*) pRequest)
  599. {
  600.     DPRINTF(D_MINI_FO, ("CHXMiniFO::GetRequest()n"));
  601.     pRequest = m_pRequest;
  602.     if (pRequest != NULL)
  603.     {
  604.         pRequest->AddRef();
  605.     }
  606.     return HXR_OK;
  607. }
  608. /****************************************************************************
  609.  *  IHXFileExists::DoesExist
  610.  *
  611.  *  This routine determines if the given file exists, and notifies the File
  612.  *  Response object. It is called by the server after the File Object has
  613.  *  been created to determine if the requested file does actually exist. If
  614.  *  it does the File Object is handed off to the File Format object.
  615.  */
  616. STDMETHODIMP CHXMiniFileObject::DoesExist( const char* pFilePath, IHXFileExistsResponse* pFileResponse )
  617. {
  618.     DPRINTF(D_MINI_FO, ("CHXMiniFO::DoesExist()n"));
  619.     BOOL  bDoesExist = FALSE;
  620.     char* pFilePathPlatform   = NULL;
  621.     // Convert file path to platform specific file path
  622.     HX_RESULT result = ConvertToPlatformPath(pFilePathPlatform, pFilePath);
  623.     // Determine if the file can be opened
  624.     if (result == HXR_OK)
  625.     {
  626.         struct stat statbuf;
  627.         if (stat(pFilePathPlatform, &statbuf) == 0)
  628.         {
  629.             bDoesExist = TRUE;
  630.         }
  631.     }
  632.     // Notify the caller if the file exists
  633.     pFileResponse->DoesExistDone(bDoesExist);
  634.     if (pFilePathPlatform != NULL)
  635.     {
  636.         delete [] pFilePathPlatform;
  637.     }
  638.     return HXR_OK;
  639. }
  640. // IUnknown COM Interface Methods
  641. /****************************************************************************
  642.  *  IUnknown::AddRef
  643.  *
  644.  *  This routine increases the object reference count in a thread safe
  645.  *  manner. The reference count is used to manage the lifetime of an object.
  646.  *  This method must be explicitly called by the user whenever a new
  647.  *  reference to an object is used.
  648.  */
  649. STDMETHODIMP_(UINT32) CHXMiniFileObject::AddRef(void)
  650. {
  651.     return InterlockedIncrement(&m_RefCount);
  652. }
  653. /****************************************************************************
  654.  *  IUnknown::Release
  655.  *
  656.  *  This routine decreases the object reference count in a thread safe
  657.  *  manner, and deletes the object if no more references to it exist. It must
  658.  *  be called explicitly by the user whenever an object is no longer needed.
  659.  */
  660. STDMETHODIMP_(UINT32) CHXMiniFileObject::Release(void)
  661. {
  662.     if (InterlockedDecrement(&m_RefCount) > 0)
  663.     {
  664.         return m_RefCount;
  665.     }
  666.     delete this;
  667.     return 0;
  668. }
  669. /****************************************************************************
  670.  *  IUnknown::QueryInterface
  671.  *
  672.  *  This routine indicates which interfaces this object supports. If a given
  673.  *  interface is supported, the object's reference count is incremented, and
  674.  *  a reference to that interface is returned. Otherwise a NULL object and
  675.  *  error code are returned. This method is called by other objects to
  676.  *  discover the functionality of this object.
  677.  */
  678. STDMETHODIMP CHXMiniFileObject::QueryInterface(REFIID interfaceID, void** ppInterfaceObj)
  679. {
  680.     QInterfaceList qiList[] =
  681.     {
  682. { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXFileObject*)this },
  683. { GET_IIDHANDLE(IID_IHXFileObject), (IHXFileObject*) this },
  684. { GET_IIDHANDLE(IID_IHXDirHandler), (IHXDirHandler*) this },
  685. { GET_IIDHANDLE(IID_IHXRequestHandler), (IHXRequestHandler*) this },
  686. { GET_IIDHANDLE(IID_IHXFileExists), (IHXFileExists*) this },
  687. { GET_IIDHANDLE(IID_IHXFileStat), (IHXFileStat*) this },
  688. { GET_IIDHANDLE(IID_IHXGetFileFromSamePool), (IHXGetFileFromSamePool*) this },
  689.     };
  690.     return ::QIFind(qiList, QILISTSIZE(qiList), interfaceID, ppInterfaceObj);
  691. }
  692. /************************************************************************
  693.  * Method:
  694.  *      IHXFileObject::Stat
  695.  * Purpose:
  696.  *      Collects information about the file that is returned to the
  697.  *      caller in an IHXStat object
  698.  */
  699. STDMETHODIMP CHXMiniFileObject::Stat(IHXFileStatResponse* pFileStatResponse)
  700. {
  701.     DPRINTF(D_MINI_FO, ("CHXMiniFO::Stat()n"));
  702.     struct stat StatBuffer;
  703.     if((m_pFile && fstat((int)fileno(m_pFile), &StatBuffer) == 0) ||
  704.         stat(m_pFilename, &StatBuffer) == 0)
  705.     {
  706. pFileStatResponse->StatDone(HXR_OK,
  707.     StatBuffer.st_size,
  708.     StatBuffer.st_ctime,
  709.     StatBuffer.st_atime,
  710.     StatBuffer.st_mtime,
  711.     StatBuffer.st_mode);
  712. return HXR_OK;
  713.     }
  714.     return HXR_FAIL;
  715. }
  716. STDMETHODIMP CHXMiniFileObject::InitDirHandler( IHXDirHandlerResponse* pDirResponse )
  717. {
  718.     DPRINTF(D_MINI_FO, ("CHXMiniFO::InitDirHandler()n"));
  719.     m_pDirResponse = pDirResponse;
  720.     m_pDirResponse->AddRef();
  721.     m_pDirResponse->InitDirHandlerDone(HXR_OK);
  722.     return HXR_OK;
  723. }
  724. STDMETHODIMP CHXMiniFileObject::CloseDirHandler()
  725. {
  726.     DPRINTF(D_MINI_FO, ("CHXMiniFO::CloseDirHandler()n"));
  727.     m_pDirResponse->CloseDirHandlerDone(HXR_OK);
  728.     m_pDirResponse->Release();
  729.     m_pDirResponse = NULL;
  730.     return HXR_OK;
  731. }
  732. STDMETHODIMP CHXMiniFileObject::MakeDir()
  733. {
  734.     DPRINTF(D_MINI_FO, ("CHXMiniFO::MakeDir()n"));
  735. #if defined (_WINDOWS ) || defined (_WIN32)
  736.         USES_CONVERSION;
  737.     if( ::CreateDirectory(A2T(m_pFilename), NULL) == 0 )
  738.         return HXR_FAIL;
  739. #elif defined UNIX
  740.     if(mkdir(m_pFilename, 0x644) < 0)
  741.         return HXR_FAIL;
  742. #else
  743.     //XXXGH...don't know how to do this on Mac
  744.     return HXR_FAIL;
  745. #endif
  746.     m_pDirResponse->MakeDirDone(HXR_OK);
  747.     return HXR_OK;
  748. }
  749. STDMETHODIMP CHXMiniFileObject::ReadDir()
  750. {
  751.     DPRINTF(D_MINI_FO, ("CHXMiniFO::ReadDir()n"));
  752.     char pDirname[1024];
  753. #if defined (_WINDOWS ) && defined (_WIN32)
  754.     USES_CONVERSION;
  755.     if (!m_hFileHandle)
  756.     {
  757.         strcpy(pDirname, m_pFilename);
  758.         strcat(pDirname, "\*");
  759.         m_hFileHandle = ::FindFirstFile( A2T(pDirname), &m_FileInfo );
  760.         if ( INVALID_HANDLE_VALUE == m_hFileHandle )
  761.         {
  762.             m_hFileHandle = 0;
  763.             return HXR_FAILED;
  764.         }
  765.     }
  766.     else
  767.     {
  768.         if ( ::FindNextFile(m_hFileHandle, &m_FileInfo) == 0 )
  769.         {
  770.             ::FindClose( m_hFileHandle );
  771.             m_hFileHandle = 0;
  772.             m_pDirResponse->ReadDirDone(HXR_FILE_NOT_FOUND, 0);
  773.             return HXR_OK;
  774.         }
  775.     }
  776.     strcpy( pDirname, T2A(m_FileInfo.cFileName) );
  777. #else
  778.     return HXR_FAIL;
  779. #endif
  780.     HX_RESULT result;
  781.     IHXBuffer* pBuffer = 0;
  782.     result = m_pClassFactory->CreateInstance(CLSID_IHXBuffer, (void**)&pBuffer);
  783.     if (HXR_OK != result)
  784.     {
  785.         return result;
  786.     }
  787.     pBuffer->Set( (Byte*) pDirname, strlen(pDirname) + 1 );
  788.     m_pDirResponse->ReadDirDone(HXR_OK, pBuffer);
  789.     pBuffer->Release();
  790.     return HXR_OK;
  791. }
  792. /************************************************************************
  793.  *      Method:
  794.  *          IHXFileObject::GetFileObjectFromPool
  795.  *      Purpose:
  796.  *      To get another FileObject from the same pool.
  797.  */
  798. STDMETHODIMP CHXMiniFileObject::GetFileObjectFromPool( IHXGetFileFromSamePoolResponse* response )
  799. {
  800.     DPRINTF(D_MINI_FO, ("CHXMiniFO::GetFileObjectFromPool()n"));
  801.     HX_RESULT lReturnVal = HXR_OUTOFMEMORY;
  802.     if ( m_pFilename )
  803.     {
  804.         delete [] m_pBasePath;
  805.         m_pBasePath = new char[strlen(m_pFilename) + 1];
  806.         if (m_pBasePath)
  807.         {
  808.             // Chop off the current path to create a base path.
  809.             strcpy(m_pBasePath, m_pFilename);
  810.             char* pLastSeparator = strrchr(m_pBasePath, OS_SEPARATOR_CHAR);
  811.             *pLastSeparator = '';
  812.             CHXMiniFileObject* pFileObject = new CHXMiniFileObject(m_pClassFactory, m_pBasePath);
  813.             if (pFileObject)
  814.             {
  815.                 IUnknown* pUnknown = 0;
  816.                 lReturnVal = pFileObject->QueryInterface(IID_IUnknown, (void**)&pUnknown);
  817.                 response->FileObjectReady((lReturnVal == HXR_OK) ? HXR_OK : HXR_FAILED, pUnknown);
  818.                 HX_RELEASE(pUnknown);
  819.             }
  820.         }
  821.     }
  822.     return lReturnVal;
  823. }