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

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