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_stream.h"
12 #include "core/fxcrt/fx_string.h"
13 #include "third_party/base/ptr_util.h"
14
15 namespace {
16
GetFileMode(uint32_t dwMode,uint32_t & dwAccess,uint32_t & dwShare,uint32_t & dwCreation)17 void GetFileMode(uint32_t dwMode,
18 uint32_t& dwAccess,
19 uint32_t& dwShare,
20 uint32_t& dwCreation) {
21 dwAccess = GENERIC_READ;
22 dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
23 if (!(dwMode & FX_FILEMODE_ReadOnly)) {
24 dwAccess |= GENERIC_WRITE;
25 dwCreation = (dwMode & FX_FILEMODE_Truncate) ? CREATE_ALWAYS : OPEN_ALWAYS;
26 } else {
27 dwCreation = OPEN_EXISTING;
28 }
29 }
30
31 } // namespace
32
33 // static
Create()34 std::unique_ptr<FileAccessIface> FileAccessIface::Create() {
35 return pdfium::MakeUnique<CFX_FileAccess_Windows>();
36 }
37
CFX_FileAccess_Windows()38 CFX_FileAccess_Windows::CFX_FileAccess_Windows() : m_hFile(nullptr) {}
39
~CFX_FileAccess_Windows()40 CFX_FileAccess_Windows::~CFX_FileAccess_Windows() {
41 Close();
42 }
43
Open(ByteStringView fileName,uint32_t dwMode)44 bool CFX_FileAccess_Windows::Open(ByteStringView fileName, uint32_t dwMode) {
45 if (m_hFile)
46 return false;
47
48 uint32_t dwAccess, dwShare, dwCreation;
49 GetFileMode(dwMode, dwAccess, dwShare, dwCreation);
50 m_hFile = ::CreateFileA(fileName.unterminated_c_str(), dwAccess, dwShare,
51 nullptr, dwCreation, FILE_ATTRIBUTE_NORMAL, nullptr);
52 if (m_hFile == INVALID_HANDLE_VALUE)
53 m_hFile = nullptr;
54
55 return !!m_hFile;
56 }
57
Open(WideStringView fileName,uint32_t dwMode)58 bool CFX_FileAccess_Windows::Open(WideStringView fileName, 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 =
65 ::CreateFileW((LPCWSTR)fileName.unterminated_c_str(), dwAccess, dwShare,
66 nullptr, dwCreation, FILE_ATTRIBUTE_NORMAL, nullptr);
67 if (m_hFile == INVALID_HANDLE_VALUE)
68 m_hFile = nullptr;
69
70 return !!m_hFile;
71 }
72
Close()73 void CFX_FileAccess_Windows::Close() {
74 if (!m_hFile)
75 return;
76
77 ::CloseHandle(m_hFile);
78 m_hFile = nullptr;
79 }
80
GetSize() const81 FX_FILESIZE CFX_FileAccess_Windows::GetSize() const {
82 if (!m_hFile)
83 return 0;
84
85 LARGE_INTEGER size = {};
86 if (!::GetFileSizeEx(m_hFile, &size))
87 return 0;
88
89 return (FX_FILESIZE)size.QuadPart;
90 }
91
GetPosition() const92 FX_FILESIZE CFX_FileAccess_Windows::GetPosition() const {
93 if (!m_hFile)
94 return (FX_FILESIZE)-1;
95
96 LARGE_INTEGER dist = {};
97 LARGE_INTEGER newPos = {};
98 if (!::SetFilePointerEx(m_hFile, dist, &newPos, FILE_CURRENT))
99 return (FX_FILESIZE)-1;
100
101 return (FX_FILESIZE)newPos.QuadPart;
102 }
103
SetPosition(FX_FILESIZE pos)104 FX_FILESIZE CFX_FileAccess_Windows::SetPosition(FX_FILESIZE pos) {
105 if (!m_hFile)
106 return (FX_FILESIZE)-1;
107
108 LARGE_INTEGER dist;
109 dist.QuadPart = pos;
110 LARGE_INTEGER newPos = {};
111 if (!::SetFilePointerEx(m_hFile, dist, &newPos, FILE_BEGIN))
112 return (FX_FILESIZE)-1;
113
114 return (FX_FILESIZE)newPos.QuadPart;
115 }
116
Read(void * pBuffer,size_t szBuffer)117 size_t CFX_FileAccess_Windows::Read(void* pBuffer, size_t szBuffer) {
118 if (!m_hFile)
119 return 0;
120
121 size_t szRead = 0;
122 if (!::ReadFile(m_hFile, pBuffer, (DWORD)szBuffer, (LPDWORD)&szRead,
123 nullptr)) {
124 return 0;
125 }
126 return szRead;
127 }
128
Write(const void * pBuffer,size_t szBuffer)129 size_t CFX_FileAccess_Windows::Write(const void* pBuffer, size_t szBuffer) {
130 if (!m_hFile)
131 return 0;
132
133 size_t szWrite = 0;
134 if (!::WriteFile(m_hFile, pBuffer, (DWORD)szBuffer, (LPDWORD)&szWrite,
135 nullptr)) {
136 return 0;
137 }
138 return szWrite;
139 }
140
ReadPos(void * pBuffer,size_t szBuffer,FX_FILESIZE pos)141 size_t CFX_FileAccess_Windows::ReadPos(void* pBuffer,
142 size_t szBuffer,
143 FX_FILESIZE pos) {
144 if (!m_hFile)
145 return 0;
146
147 if (pos >= GetSize())
148 return 0;
149
150 if (SetPosition(pos) == (FX_FILESIZE)-1)
151 return 0;
152
153 return Read(pBuffer, szBuffer);
154 }
155
WritePos(const void * pBuffer,size_t szBuffer,FX_FILESIZE pos)156 size_t CFX_FileAccess_Windows::WritePos(const void* pBuffer,
157 size_t szBuffer,
158 FX_FILESIZE pos) {
159 if (!m_hFile) {
160 return 0;
161 }
162 if (SetPosition(pos) == (FX_FILESIZE)-1) {
163 return 0;
164 }
165 return Write(pBuffer, szBuffer);
166 }
167
Flush()168 bool CFX_FileAccess_Windows::Flush() {
169 if (!m_hFile)
170 return false;
171
172 return !!::FlushFileBuffers(m_hFile);
173 }
174
Truncate(FX_FILESIZE szFile)175 bool CFX_FileAccess_Windows::Truncate(FX_FILESIZE szFile) {
176 if (SetPosition(szFile) == (FX_FILESIZE)-1)
177 return false;
178
179 return !!::SetEndOfFile(m_hFile);
180 }
181