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
GetFileMode(uint32_t dwMode,uint32_t & dwAccess,uint32_t & dwShare,uint32_t & dwCreation)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
Create()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
CFX_FileAccess_Windows()51 CFX_FileAccess_Windows::CFX_FileAccess_Windows() : m_hFile(nullptr) {}
52
~CFX_FileAccess_Windows()53 CFX_FileAccess_Windows::~CFX_FileAccess_Windows() {
54 Close();
55 }
56
Open(const ByteStringView & fileName,uint32_t dwMode)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
Open(const WideStringView & fileName,uint32_t dwMode)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
Close()88 void CFX_FileAccess_Windows::Close() {
89 if (!m_hFile)
90 return;
91
92 ::CloseHandle(m_hFile);
93 m_hFile = nullptr;
94 }
95
GetSize() const96 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
GetPosition() const107 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
SetPosition(FX_FILESIZE pos)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
Read(void * pBuffer,size_t szBuffer)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
Write(const void * pBuffer,size_t szBuffer)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
ReadPos(void * pBuffer,size_t szBuffer,FX_FILESIZE pos)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
WritePos(const void * pBuffer,size_t szBuffer,FX_FILESIZE pos)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
Flush()183 bool CFX_FileAccess_Windows::Flush() {
184 if (!m_hFile)
185 return false;
186
187 return !!::FlushFileBuffers(m_hFile);
188 }
189
Truncate(FX_FILESIZE szFile)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