Home | History | Annotate | Download | only in fxcrt
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/fxcrt/cfx_fileaccess_windows.h"
      8 
      9 #include <memory>
     10 
     11 #include "core/fxcrt/fx_string.h"
     12 #include "third_party/base/ptr_util.h"
     13 
     14 #if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_
     15 
     16 namespace {
     17 
     18 void GetFileMode(uint32_t dwMode,
     19                  uint32_t& dwAccess,
     20                  uint32_t& dwShare,
     21                  uint32_t& dwCreation) {
     22   dwAccess = GENERIC_READ;
     23   dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
     24   if (!(dwMode & FX_FILEMODE_ReadOnly)) {
     25     dwAccess |= GENERIC_WRITE;
     26     dwCreation = (dwMode & FX_FILEMODE_Truncate) ? CREATE_ALWAYS : OPEN_ALWAYS;
     27   } else {
     28     dwCreation = OPEN_EXISTING;
     29   }
     30 }
     31 
     32 }  // namespace
     33 
     34 // static
     35 std::unique_ptr<IFX_FileAccess> IFX_FileAccess::Create() {
     36   return pdfium::MakeUnique<CFX_FileAccess_Windows>();
     37 }
     38 
     39 #ifdef __cplusplus
     40 extern "C" {
     41 #endif
     42 WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize);
     43 WINBASEAPI BOOL WINAPI SetFilePointerEx(HANDLE hFile,
     44                                         LARGE_INTEGER liDistanceToMove,
     45                                         PLARGE_INTEGER lpNewFilePointer,
     46                                         DWORD dwMoveMethod);
     47 #ifdef __cplusplus
     48 }
     49 #endif
     50 
     51 CFX_FileAccess_Windows::CFX_FileAccess_Windows() : m_hFile(nullptr) {}
     52 
     53 CFX_FileAccess_Windows::~CFX_FileAccess_Windows() {
     54   Close();
     55 }
     56 
     57 bool CFX_FileAccess_Windows::Open(const ByteStringView& fileName,
     58                                   uint32_t dwMode) {
     59   if (m_hFile)
     60     return false;
     61 
     62   uint32_t dwAccess, dwShare, dwCreation;
     63   GetFileMode(dwMode, dwAccess, dwShare, dwCreation);
     64   m_hFile = ::CreateFileA(fileName.unterminated_c_str(), dwAccess, dwShare,
     65                           nullptr, dwCreation, FILE_ATTRIBUTE_NORMAL, nullptr);
     66   if (m_hFile == INVALID_HANDLE_VALUE)
     67     m_hFile = nullptr;
     68 
     69   return !!m_hFile;
     70 }
     71 
     72 bool CFX_FileAccess_Windows::Open(const WideStringView& fileName,
     73                                   uint32_t dwMode) {
     74   if (m_hFile)
     75     return false;
     76 
     77   uint32_t dwAccess, dwShare, dwCreation;
     78   GetFileMode(dwMode, dwAccess, dwShare, dwCreation);
     79   m_hFile =
     80       ::CreateFileW((LPCWSTR)fileName.unterminated_c_str(), dwAccess, dwShare,
     81                     nullptr, dwCreation, FILE_ATTRIBUTE_NORMAL, nullptr);
     82   if (m_hFile == INVALID_HANDLE_VALUE)
     83     m_hFile = nullptr;
     84 
     85   return !!m_hFile;
     86 }
     87 
     88 void CFX_FileAccess_Windows::Close() {
     89   if (!m_hFile)
     90     return;
     91 
     92   ::CloseHandle(m_hFile);
     93   m_hFile = nullptr;
     94 }
     95 
     96 FX_FILESIZE CFX_FileAccess_Windows::GetSize() const {
     97   if (!m_hFile)
     98     return 0;
     99 
    100   LARGE_INTEGER size = {};
    101   if (!::GetFileSizeEx(m_hFile, &size))
    102     return 0;
    103 
    104   return (FX_FILESIZE)size.QuadPart;
    105 }
    106 
    107 FX_FILESIZE CFX_FileAccess_Windows::GetPosition() const {
    108   if (!m_hFile)
    109     return (FX_FILESIZE)-1;
    110 
    111   LARGE_INTEGER dist = {};
    112   LARGE_INTEGER newPos = {};
    113   if (!::SetFilePointerEx(m_hFile, dist, &newPos, FILE_CURRENT))
    114     return (FX_FILESIZE)-1;
    115 
    116   return (FX_FILESIZE)newPos.QuadPart;
    117 }
    118 
    119 FX_FILESIZE CFX_FileAccess_Windows::SetPosition(FX_FILESIZE pos) {
    120   if (!m_hFile)
    121     return (FX_FILESIZE)-1;
    122 
    123   LARGE_INTEGER dist;
    124   dist.QuadPart = pos;
    125   LARGE_INTEGER newPos = {};
    126   if (!::SetFilePointerEx(m_hFile, dist, &newPos, FILE_BEGIN))
    127     return (FX_FILESIZE)-1;
    128 
    129   return (FX_FILESIZE)newPos.QuadPart;
    130 }
    131 
    132 size_t CFX_FileAccess_Windows::Read(void* pBuffer, size_t szBuffer) {
    133   if (!m_hFile)
    134     return 0;
    135 
    136   size_t szRead = 0;
    137   if (!::ReadFile(m_hFile, pBuffer, (DWORD)szBuffer, (LPDWORD)&szRead,
    138                   nullptr)) {
    139     return 0;
    140   }
    141   return szRead;
    142 }
    143 
    144 size_t CFX_FileAccess_Windows::Write(const void* pBuffer, size_t szBuffer) {
    145   if (!m_hFile)
    146     return 0;
    147 
    148   size_t szWrite = 0;
    149   if (!::WriteFile(m_hFile, pBuffer, (DWORD)szBuffer, (LPDWORD)&szWrite,
    150                    nullptr)) {
    151     return 0;
    152   }
    153   return szWrite;
    154 }
    155 
    156 size_t CFX_FileAccess_Windows::ReadPos(void* pBuffer,
    157                                        size_t szBuffer,
    158                                        FX_FILESIZE pos) {
    159   if (!m_hFile)
    160     return 0;
    161 
    162   if (pos >= GetSize())
    163     return 0;
    164 
    165   if (SetPosition(pos) == (FX_FILESIZE)-1)
    166     return 0;
    167 
    168   return Read(pBuffer, szBuffer);
    169 }
    170 
    171 size_t CFX_FileAccess_Windows::WritePos(const void* pBuffer,
    172                                         size_t szBuffer,
    173                                         FX_FILESIZE pos) {
    174   if (!m_hFile) {
    175     return 0;
    176   }
    177   if (SetPosition(pos) == (FX_FILESIZE)-1) {
    178     return 0;
    179   }
    180   return Write(pBuffer, szBuffer);
    181 }
    182 
    183 bool CFX_FileAccess_Windows::Flush() {
    184   if (!m_hFile)
    185     return false;
    186 
    187   return !!::FlushFileBuffers(m_hFile);
    188 }
    189 
    190 bool CFX_FileAccess_Windows::Truncate(FX_FILESIZE szFile) {
    191   if (SetPosition(szFile) == (FX_FILESIZE)-1)
    192     return false;
    193 
    194   return !!::SetEndOfFile(m_hFile);
    195 }
    196 #endif
    197