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

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: mmapdatf.cpp,v 1.4.42.4 2004/07/09 01:44:27 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. #include "hxcom.h"
  50. #include "hxresult.h"
  51. #include "hxtypes.h"
  52. #include "hlxclib/sys/stat.h"
  53. #include "hlxclib/sys/types.h"
  54. #include "hlxclib/io.h"
  55. #include "hlxclib/fcntl.h"
  56. #include "hlxclib/windows.h"
  57. #include "hxbuffer.h"
  58. #include "mmapdatf.h"
  59. #include "mmapmgr.h"
  60. #include "hxfiles.h"
  61. #include "hxprefs.h"
  62. #include "filespec.h"
  63. #include "filespecutils.h"
  64. #include "platform/win/filetimeutil.h"
  65. #include "hxcore.h"
  66. MemoryMapManager* MemoryMapDataFile::m_zpMMM = NULL;
  67. BOOL MemoryMapDataFile::g_NT = FALSE;
  68. MemoryMapDataFile::MemoryMapDataFile(IUnknown* pContext,
  69.     REF(IUnknown*) pPersistantObject, BOOL bDisableMemoryMappedIO,
  70.     UINT32 ulChunkSize, BOOL bEnableFileLocking)
  71.     : m_lRefCount(0)
  72.     , m_hFile(INVALID_HANDLE_VALUE)
  73.     , m_pFilename(0)
  74.     , m_ulPos(-1)
  75.     , MmapHandle(0)
  76.     , m_ulChunkSize(ulChunkSize)
  77.     , m_ulLastError(HXR_OK)
  78. {
  79.     m_pContext = pContext;
  80.     m_pContext->AddRef();
  81.     if (m_zpMMM == NULL)
  82.     {
  83. m_zpMMM = new MemoryMapManager(pContext, bDisableMemoryMappedIO,
  84. m_ulChunkSize);
  85. OSVERSIONINFO vinfo;
  86. vinfo.dwOSVersionInfoSize = sizeof(vinfo);
  87. if (GetVersionEx(&vinfo))
  88. {
  89.     if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  90.     {
  91. g_NT = TRUE;
  92.     }
  93. }
  94.     }
  95.     if (!pPersistantObject)
  96.     {
  97. pPersistantObject = m_zpMMM;
  98. pPersistantObject->AddRef();
  99.     }
  100. }
  101. MemoryMapDataFile::~MemoryMapDataFile()
  102. {
  103.     if (m_hFile != INVALID_HANDLE_VALUE)
  104.     {
  105. CloseHandle(m_hFile);
  106. m_hFile = INVALID_HANDLE_VALUE;
  107.     }
  108.     if (m_pFilename)
  109.     {
  110. delete[] m_pFilename;
  111. m_pFilename = 0;
  112.     }
  113.     HX_RELEASE(m_pContext);
  114. }
  115. /*
  116.  *  IUnknown methods
  117.  */
  118. STDMETHODIMP
  119. MemoryMapDataFile::QueryInterface(REFIID riid,
  120. void** ppvObj)
  121. {
  122.     if (IsEqualIID(IID_IUnknown, riid))
  123.     {
  124. AddRef();
  125. *ppvObj = this;
  126. return HXR_OK;
  127.     }
  128.     else if(IsEqualIID(IID_IHXDataFile, riid))
  129.     {
  130. AddRef();
  131. *ppvObj = (IHXDataFile*)this;
  132. return HXR_OK;
  133.     }
  134.     *ppvObj = 0;
  135.     return HXR_NOINTERFACE;
  136. }
  137. STDMETHODIMP_(ULONG32)
  138. MemoryMapDataFile::AddRef()
  139. {
  140.     return InterlockedIncrement(&m_lRefCount);
  141. }
  142. STDMETHODIMP_(ULONG32)
  143. MemoryMapDataFile::Release()
  144. {
  145.     if (InterlockedDecrement(&m_lRefCount) > 0)
  146.     {
  147. return m_lRefCount;
  148.     }
  149.     delete this;
  150.     return 0;
  151. }
  152.     
  153. /*
  154.  *  IHXDataFile methods
  155.  */
  156. /* Bind DataFile Object with FileName */
  157. STDMETHODIMP_(void)
  158. MemoryMapDataFile::Bind(const char* FileName)
  159. {
  160.     /* XXXPM
  161.     if (m_hFile != INVALID_HANDLE_VALUE)
  162.     {
  163. CloseHandle(m_hFile);
  164. m_hFile = INVALID_HANDLE_VALUE;
  165.     }*/
  166.     if (m_pFilename)
  167.     {
  168. delete[] m_pFilename;
  169. m_pFilename = 0;
  170.     }
  171.     m_pFilename = new char[strlen(FileName) + 1];
  172.     strcpy(m_pFilename, FileName); /* Flawfinder: ignore */
  173. }
  174. /* Creates a datafile using the specified mode
  175.  * uOpenMode --- File Open mode - HX_FILE_READ/HX_FILE_WRITE/HX_FILE_BINARY
  176.  */
  177. STDMETHODIMP
  178. MemoryMapDataFile::Create(UINT16 uOpenMode)
  179. {
  180.     return HXR_NOTIMPL;
  181. }
  182. /*
  183.  *  Open will open a file with the specified mode
  184.  */
  185. STDMETHODIMP
  186. MemoryMapDataFile::Open(UINT16 uOpenMode)
  187. {
  188.     m_ulLastError = HXR_OK;
  189.     if (m_hFile != INVALID_HANDLE_VALUE)
  190.     {
  191. CloseHandle(m_hFile);
  192. m_hFile = INVALID_HANDLE_VALUE;
  193.     }
  194.     
  195.     DWORD dwAccess = 0;
  196.     DWORD dwShare = 0;
  197.     DWORD dwCreate = 0;
  198.     DWORD dwFlags = FILE_ATTRIBUTE_NORMAL;
  199.     m_uOpenMode = uOpenMode;
  200.     if (uOpenMode & HX_FILE_WRITE)
  201.     {
  202.         // Set read access so file can be opened read-only simultaneously
  203.         uOpenMode |= HX_FILE_READ;
  204. dwAccess |= GENERIC_WRITE;
  205. dwShare |= FILE_SHARE_WRITE;
  206. if (g_NT)
  207. {
  208.     dwShare |= FILE_SHARE_DELETE;
  209. }
  210. if (uOpenMode & HX_FILE_NOTRUNC)
  211. {
  212.     dwCreate = OPEN_ALWAYS;
  213. }
  214. else
  215. {
  216.     dwCreate = CREATE_ALWAYS;
  217. }
  218.     }
  219.     if (uOpenMode & HX_FILE_READ)
  220.     {
  221. dwAccess |= GENERIC_READ;
  222. dwShare |= FILE_SHARE_READ;
  223. if (!(uOpenMode & HX_FILE_WRITE))
  224. {
  225.     dwCreate = OPEN_EXISTING;
  226. }
  227. IHXPreferences* pPref = NULL;
  228. if (m_pContext && 
  229.     (m_pContext->QueryInterface(IID_IHXPreferences, (void**) &pPref) == HXR_OK) &&
  230.     pPref)
  231. {
  232.     IHXBuffer* pBuffer = NULL;
  233.     if (pPref->ReadPref("FileReadWriteAccess", pBuffer) == HXR_OK &&
  234. pBuffer &&
  235. (::atoi((char*) pBuffer->GetBuffer()) == 1))
  236.     {
  237. dwShare |= FILE_SHARE_WRITE;
  238. if (g_NT)
  239. {
  240.     dwShare |= FILE_SHARE_DELETE;
  241. }
  242.     }
  243.     HX_RELEASE(pBuffer);
  244.     HX_RELEASE(pPref);
  245. }
  246.     }
  247.     /*
  248.      * Nothing to be done for HX_FILE_BINARY
  249.      */
  250.     m_hFile = CreateFile(OS_STRING(m_pFilename), dwAccess, dwShare, NULL,
  251.     dwCreate, dwFlags, NULL);
  252.     
  253.     if (m_hFile == INVALID_HANDLE_VALUE)
  254.     {
  255.         if (::GetLastError() == ERROR_FILE_NOT_FOUND)
  256. {
  257.             m_ulLastError = HXR_FAIL;
  258.     return HXR_FILE_NOT_FOUND;
  259. }
  260. /*
  261.  * Check if we are trying to truncate.  If this is the
  262.  * case the file is probably mapped and we have to unmap
  263.  * it.
  264.  */
  265. BOOL bReopen = FALSE;
  266. if ((uOpenMode & (HX_FILE_WRITE|HX_FILE_NOTRUNC)) == HX_FILE_WRITE)
  267. {
  268.     _AttemptUnmap();
  269.     bReopen = TRUE;
  270. }
  271. /*
  272.  * Check if we tried to do read only.  Perhaps the file
  273.  * is mapped read/write.  We'll have to open it like that too.
  274.  */
  275. if (!(uOpenMode & HX_FILE_WRITE))
  276. {
  277.     dwAccess |= GENERIC_WRITE;
  278.     dwShare |= FILE_SHARE_WRITE;
  279.     if (g_NT)
  280.     {
  281. dwShare |= FILE_SHARE_DELETE;
  282.     }
  283.     dwCreate = OPEN_ALWAYS;
  284.     bReopen = TRUE;
  285. }
  286. if (!bReopen)
  287. {
  288.             m_ulLastError = HXR_FAIL;
  289.     return HXR_FAIL;
  290. }
  291. m_hFile = CreateFile(OS_STRING(m_pFilename), dwAccess, dwShare, NULL,
  292. dwCreate, dwFlags, NULL);
  293. if (m_hFile == INVALID_HANDLE_VALUE)
  294. {
  295.             m_ulLastError = HXR_FAIL;
  296.     return HXR_FAIL;
  297. }
  298.     }
  299.     m_ulPos = 0;
  300. //  On windows we do now want to use memory mapped IO if we are going across
  301. //  a network share. And we only want to disable this for clients, not servers.
  302.     //check to see if we are within the player...
  303.     IHXClientEngine* pEngine = NULL;
  304.     if (HXR_OK == m_pContext->QueryInterface(IID_IHXClientEngine, (void**)&pEngine))
  305.     {
  306.         HX_RELEASE(pEngine);
  307.         CHXDirSpecifier  dirspec(m_pFilename);
  308.         if (!CHXFileSpecUtils::IsDiskLocal( dirspec) || CHXFileSpecUtils::IsDiskEjectable(dirspec) )
  309.         {
  310.             if (MmapHandle)
  311.             {
  312.         m_zpMMM->CloseMap(MmapHandle);
  313.         MmapHandle = 0;
  314.             }
  315.             return HXR_OK;
  316.         }
  317.     }
  318.     
  319.     if (MmapHandle)
  320.     {
  321. m_zpMMM->CloseMap(MmapHandle);
  322. MmapHandle = 0;
  323.     }
  324.     MmapHandle = m_zpMMM->OpenMap(m_hFile, m_pContext);
  325.     
  326.     return HXR_OK;
  327. }
  328. /*
  329.  * Original Version
  330.  */
  331.     
  332. /*
  333.     if (m_hFile != INVALID_HANDLE_VALUE)
  334.     {
  335. CloseHandle(m_hFile);
  336. m_hFile = INVALID_HANDLE_VALUE;
  337.     }
  338.     DWORD dwPlatformSpecific = 0;
  339.     if (g_NT)
  340.     {
  341. dwPlatformSpecific = FILE_SHARE_DELETE;
  342.     }
  343.     DWORD dwFlags = 0;
  344.     DWORD dwShare = dwPlatformSpecific;
  345.     DWORD dwCreate = 0;
  346.     m_uOpenMode = uOpenMode;
  347.     if (uOpenMode & HX_FILE_WRITE)
  348.     {
  349. dwShare |= FILE_SHARE_WRITE;
  350. dwFlags |= GENERIC_WRITE;
  351. if (uOpenMode & HX_FILE_NOTRUNC)
  352. {
  353.     dwCreate |= OPEN_ALWAYS;
  354. }
  355. else
  356. {
  357.     dwCreate |= CREATE_ALWAYS;
  358. }
  359.     }
  360.     if (uOpenMode & HX_FILE_READ)
  361.     {
  362. dwShare |= FILE_SHARE_READ;
  363. dwFlags |= GENERIC_READ;
  364.   if (!(uOpenMode & HX_FILE_WRITE))
  365. {
  366.     dwCreate |= OPEN_EXISTING;
  367. }
  368.     }
  369.     if (uOpenMode & HX_FILE_BINARY)
  370.     {
  371.     }
  372.     m_hFile = CreateFile(m_pFilename,
  373.     GENERIC_READ | GENERIC_WRITE,
  374.     FILE_SHARE_READ | FILE_SHARE_WRITE | dwPlatformSpecific,
  375.     NULL,
  376.     dwCreate,
  377.     FILE_ATTRIBUTE_NORMAL,
  378.     NULL);
  379.     if (m_hFile == INVALID_HANDLE_VALUE)
  380.     {
  381. if (::GetLastError() == ERROR_FILE_NOT_FOUND)
  382. {
  383.     return HXR_FAIL;
  384. }
  385. /*
  386.  * File may be mapped and we are trying to truncate it.
  387.  * It will only let us do that if we unmap the file NOW.
  388.  *
  389. if (uOpenMode & HX_FILE_WRITE && dwCreate == CREATE_ALWAYS)
  390. {
  391.     _AttemptUnmap();
  392.     /*
  393.      * We are now going to open the file, so make
  394.      * sure there is always a read mixed this this write.
  395.      *
  396.     dwFlags |= GENERIC_READ;
  397.     dwShare |= FILE_SHARE_READ;
  398. }
  399. /*
  400.  * Try and re-open the file.  This will either be read only
  401.  * if we failed reading, in case it is a readonly file,
  402.  * of it could be another attempt at "w" after unampping
  403.  * the file.  All vars are set up for either case.
  404.  *
  405. m_hFile = CreateFile(m_pFilename,
  406.     dwFlags,
  407.     dwShare,
  408.     NULL,
  409.     dwCreate,
  410.     FILE_ATTRIBUTE_NORMAL,
  411.     NULL);
  412. if (m_hFile == INVALID_HANDLE_VALUE)
  413. {
  414.     return HXR_FAIL;
  415. }
  416.     }
  417.     m_ulPos = 0;
  418.     if (MmapHandle)
  419.     {
  420. m_zpMMM->CloseMap(MmapHandle);
  421. MmapHandle = 0;
  422.     }
  423.     MmapHandle = m_zpMMM->OpenMap(m_hFile, m_pContext);
  424.     return HXR_OK;
  425. }
  426. */
  427. /* Delete File */
  428. STDMETHODIMP
  429. MemoryMapDataFile::Delete()
  430. {
  431.     Close();
  432.     if (!m_pFilename)
  433.     {
  434. return HXR_UNEXPECTED;
  435.     }
  436.     if (DeleteFile(OS_STRING(m_pFilename)))
  437.     {
  438. return HXR_OK;
  439.     }
  440.     else if (_AttemptUnmap())
  441.     {
  442.         if (DeleteFile(OS_STRING(m_pFilename)))
  443. {
  444.     return HXR_OK;
  445. }
  446.     }
  447.     return HXR_FAIL;
  448. }
  449. /* Close closes a file 
  450.  * If the reference count on the IHXDataFile object is greater than 1, 
  451.  * then the underlying file cannot be safely closed, so Close() becomes 
  452.  * a noop in that case. Close it only when the object is destroyed. 
  453.  * This would be safe, but could lead to a file descriptor leak.
  454.  */
  455. STDMETHODIMP
  456. MemoryMapDataFile::Close()
  457. {
  458.     m_ulLastError = HXR_OK;
  459.     if (m_hFile != INVALID_HANDLE_VALUE)
  460.     {
  461. CloseHandle(m_hFile);
  462. m_hFile = INVALID_HANDLE_VALUE;
  463.     }
  464.     m_ulPos = -1;
  465.     if (MmapHandle)
  466.     {
  467. m_zpMMM->CloseMap(MmapHandle);
  468. MmapHandle = 0;
  469.     }
  470.     return HXR_OK;
  471. }
  472. /* Name returns the currently bound file name in FileName.
  473.  * and returns TRUE, if the a name has been bound.  Otherwise
  474.  * FALSE is returned.
  475.  */
  476. STDMETHODIMP_(BOOL)
  477. MemoryMapDataFile::Name(REF(IHXBuffer*) pFileName)
  478. {
  479.     if (!m_pFilename)
  480.     {
  481. return FALSE;
  482.     }
  483.     pFileName = new CHXBuffer();
  484.     pFileName->AddRef();
  485.     pFileName->Set((const unsigned char*)m_pFilename,
  486. strlen(m_pFilename) + 1);
  487.     return TRUE;
  488. }
  489. /*
  490.  * IsOpen returns TRUE if file is open.  Otherwise FALSE.
  491.  */
  492. STDMETHODIMP_(BOOL)
  493. MemoryMapDataFile::IsOpen()
  494. {
  495.     if (m_hFile != INVALID_HANDLE_VALUE)
  496.     {
  497. return TRUE;
  498.     }
  499.     return FALSE;
  500. }
  501. /* Seek moves the current file position to the offset from the
  502.  * fromWhere specifier returns current position of file or -1 on
  503.  * error.
  504.  */
  505. STDMETHODIMP
  506. MemoryMapDataFile::Seek(ULONG32 offset, UINT16 fromWhere)
  507. {
  508.     LONG32 lHighOffset = 0;
  509.     m_ulLastError = HXR_OK;
  510.     DWORD fw = 0;
  511.     switch (fromWhere)
  512.     {
  513. case SEEK_CUR:
  514.     fw = FILE_CURRENT;
  515.     m_ulPos += offset;
  516.     if (((LONG32) offset) < 0)
  517.     {
  518. lHighOffset = -1;
  519.     }
  520.     break;
  521. case SEEK_END:
  522.     fw = FILE_END;
  523.     if (offset > m_ulPos)
  524.     {
  525. m_ulPos = 0;
  526.     }
  527.     else
  528.     {
  529. m_ulPos -= offset;
  530.     }
  531.     break;
  532. case SEEK_SET:
  533.     fw = FILE_BEGIN;
  534.     m_ulPos = offset;
  535.     break;
  536.     }
  537.     DWORD dwRet = SetFilePointer(m_hFile, offset, &lHighOffset, fw);
  538.     if (dwRet == -1)
  539.     {
  540. if (GetLastError() != NO_ERROR)
  541. {
  542.     m_ulPos = -1;
  543.     m_ulLastError = HXR_FAIL;
  544.     return HXR_FAIL;
  545. }
  546.     }
  547.     
  548.     return 0;
  549. }
  550. /* Tell returns the current file position in the file */
  551. STDMETHODIMP_(ULONG32)
  552. MemoryMapDataFile::Tell()
  553. {
  554.     m_ulLastError = HXR_OK;
  555.     return m_ulPos;
  556. }
  557. void MemoryMapDataFile::StopMmap()
  558. {
  559.     if (MmapHandle == NULL)
  560. return;
  561.     m_zpMMM->CloseMap(MmapHandle);
  562.     MmapHandle = 0;
  563.     Seek(m_ulPos, SEEK_SET);
  564. }
  565. /* Read reads up to count bytes of data into buf.
  566.  * returns the number of bytes read, EOF, or -1 if the read failed 
  567.  */
  568. STDMETHODIMP_(ULONG32)
  569. MemoryMapDataFile::Read(REF(IHXBuffer*) pBuf, 
  570. ULONG32 count)
  571. {
  572.     m_ulLastError = HXR_OK;
  573.     if (!(m_uOpenMode & HX_FILE_READ))
  574.     {
  575. return 0;
  576.     }
  577.     UINT32 ulRead = 0;
  578.     if (MmapHandle)
  579.     {
  580. ulRead = m_zpMMM->GetBlock(pBuf, MmapHandle, m_ulPos, count);
  581. if (ulRead >= MMAP_EXCEPTION)
  582. {
  583.     if (ulRead != MMAP_EOF_EXCEPTION)
  584.     {
  585. StopMmap();
  586.     }
  587.     else
  588.     {
  589. Seek(m_ulPos, SEEK_SET);
  590.     }
  591.     goto normal_read;
  592. }
  593. if (ulRead > 0)
  594. {
  595.     m_ulPos += ulRead;
  596. }
  597. return ulRead;
  598.     }
  599. normal_read:
  600.     if (m_hFile == INVALID_HANDLE_VALUE)
  601.     {
  602. pBuf = NULL;
  603. return 0;
  604.     }
  605.     pBuf = new CHXBuffer;
  606.     pBuf->AddRef();
  607.     pBuf->SetSize(count);
  608.     if (!ReadFile(m_hFile, (void*)pBuf->GetBuffer(), count, &ulRead, NULL))
  609.     {
  610.         m_ulLastError = HXR_FAIL;
  611.     }
  612.     m_ulPos += ulRead;
  613.     if (ulRead < count)
  614.     {
  615.         pBuf->SetSize(ulRead);
  616.     }
  617.     return ulRead;
  618. }
  619. /* Write writes up to count bytes of data from buf.
  620.  * returns the number of bytes written, or -1 if the write failed 
  621.  */
  622. STDMETHODIMP_(ULONG32)
  623. MemoryMapDataFile::Write(REF(IHXBuffer*) pBuf)
  624. {
  625.     m_ulLastError = HXR_OK;
  626.     if (!(m_uOpenMode & HX_FILE_WRITE))
  627.     {
  628. return 0;
  629.     }
  630.     StopMmap();
  631.     UINT32 ulWritten = 0;
  632.     if (m_hFile == INVALID_HANDLE_VALUE)
  633.     {
  634. return 0;
  635.     }
  636.     if (!WriteFile(m_hFile, (void*)pBuf->GetBuffer(), pBuf->GetSize(),
  637.                    &ulWritten, NULL))
  638.     {
  639.         m_ulLastError = HXR_FAIL;
  640.     }
  641.     return ulWritten;
  642. }
  643. /* Flush out the data in case of unbuffered I/O
  644.  */
  645. STDMETHODIMP
  646. MemoryMapDataFile::Flush()
  647. {
  648.     StopMmap();
  649.     return HXR_NOTIMPL;
  650. }
  651. /*
  652.  * Return info about the data file such as permissions, time of creation
  653.  * size in bytes, etc.
  654.  */
  655. STDMETHODIMP
  656. MemoryMapDataFile::Stat(struct stat* buffer)
  657. {
  658.     if (!m_pFilename)
  659.     {
  660. return HXR_UNEXPECTED;
  661.     }
  662.     BOOL bClose = FALSE;
  663.     HANDLE hUse = m_hFile;
  664.     if (hUse == INVALID_HANDLE_VALUE)
  665.     {
  666. bClose = TRUE;
  667. hUse = CreateFile(OS_STRING(m_pFilename),
  668. 0, //query
  669. FILE_SHARE_READ,
  670. NULL,
  671. OPEN_EXISTING,
  672. FILE_ATTRIBUTE_NORMAL,
  673. NULL);
  674.     }
  675.     if (hUse == INVALID_HANDLE_VALUE)
  676.     {
  677. return HXR_FAIL;
  678.     }
  679.     BY_HANDLE_FILE_INFORMATION mss;
  680.     memset(buffer, 0, sizeof(*buffer));
  681.     buffer->st_nlink = 1;
  682.     
  683.     HX_RESULT res;
  684.     if (GetFileInformationByHandle(hUse,
  685.     &mss))
  686.     {
  687. buffer->st_atime = FileTimeTotime_t(&mss.ftLastAccessTime);
  688. buffer->st_ctime = FileTimeTotime_t(&mss.ftCreationTime);
  689. buffer->st_mtime = FileTimeTotime_t(&mss.ftLastWriteTime);
  690. buffer->st_size  = mss.nFileSizeLow;
  691. res = HXR_OK;
  692.     }
  693.     else
  694.     {
  695. res = HXR_FAIL;
  696.     }
  697.     if (bClose)
  698.     {
  699. CloseHandle(hUse);
  700.     }
  701.     return res;
  702. }
  703. /* Return the file descriptor */
  704. STDMETHODIMP_(INT16)
  705. MemoryMapDataFile::GetFd()
  706. {
  707.     if (m_hFile != INVALID_HANDLE_VALUE)
  708.     {
  709. return 1;
  710.     }
  711.     return -1;
  712. }
  713. /* GetLastError returns the platform specific file error */
  714. STDMETHODIMP
  715. MemoryMapDataFile::GetLastError()
  716. {
  717.     return m_ulLastError;
  718. }
  719. /* GetLastError returns the platform specific file error in
  720.  * string form.
  721.  */
  722. STDMETHODIMP_(void)
  723. MemoryMapDataFile::GetLastError(REF(IHXBuffer*) err)
  724. {
  725.     err = 0;
  726.     return;
  727. }
  728. BOOL
  729. MemoryMapDataFile::_AttemptUnmap()
  730. {
  731.     HANDLE hFile;
  732.     hFile = CreateFile(OS_STRING(m_pFilename),
  733.     GENERIC_READ,
  734.     FILE_SHARE_READ |
  735. (g_NT ? FILE_SHARE_DELETE : 0),
  736.     NULL,
  737.     OPEN_EXISTING,
  738.     FILE_ATTRIBUTE_NORMAL,
  739.     NULL);
  740.     if (hFile == INVALID_HANDLE_VALUE)
  741.     {
  742. return FALSE;
  743.     }
  744.     void* pHandle = m_zpMMM->GetMMHandle(hFile);
  745.     CloseHandle(hFile);
  746.     if (!pHandle)
  747.     {
  748. return FALSE;
  749.     }
  750.     m_zpMMM->AttemptCloseMapNow(pHandle);
  751.     return TRUE;
  752. }