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 "fxcrt_windows.h"
8
9#include "core/include/fxcrt/fx_string.h"
10
11#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
12IFXCRT_FileAccess* FXCRT_FileAccess_Create() {
13  return new CFXCRT_FileAccess_Win64;
14}
15void FXCRT_Windows_GetFileMode(FX_DWORD dwMode,
16                               FX_DWORD& dwAccess,
17                               FX_DWORD& dwShare,
18                               FX_DWORD& dwCreation) {
19  dwAccess = GENERIC_READ;
20  dwShare = FILE_SHARE_READ | FILE_SHARE_WRITE;
21  if (!(dwMode & FX_FILEMODE_ReadOnly)) {
22    dwAccess |= GENERIC_WRITE;
23    dwCreation = (dwMode & FX_FILEMODE_Truncate) ? CREATE_ALWAYS : OPEN_ALWAYS;
24  } else {
25    dwCreation = OPEN_EXISTING;
26  }
27}
28#ifdef __cplusplus
29extern "C" {
30#endif
31WINBASEAPI BOOL WINAPI GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize);
32WINBASEAPI BOOL WINAPI SetFilePointerEx(HANDLE hFile,
33                                        LARGE_INTEGER liDistanceToMove,
34                                        PLARGE_INTEGER lpNewFilePointer,
35                                        DWORD dwMoveMethod);
36#ifdef __cplusplus
37}
38#endif
39CFXCRT_FileAccess_Win64::CFXCRT_FileAccess_Win64() : m_hFile(NULL) {}
40CFXCRT_FileAccess_Win64::~CFXCRT_FileAccess_Win64() {
41  Close();
42}
43FX_BOOL CFXCRT_FileAccess_Win64::Open(const CFX_ByteStringC& fileName,
44                                      FX_DWORD dwMode) {
45  if (m_hFile) {
46    return FALSE;
47  }
48  FX_DWORD dwAccess, dwShare, dwCreation;
49  FXCRT_Windows_GetFileMode(dwMode, dwAccess, dwShare, dwCreation);
50  m_hFile = ::CreateFileA(fileName.GetCStr(), dwAccess, dwShare, NULL,
51                          dwCreation, FILE_ATTRIBUTE_NORMAL, NULL);
52  if (m_hFile == INVALID_HANDLE_VALUE) {
53    m_hFile = NULL;
54  }
55  return m_hFile != NULL;
56}
57FX_BOOL CFXCRT_FileAccess_Win64::Open(const CFX_WideStringC& fileName,
58                                      FX_DWORD dwMode) {
59  if (m_hFile) {
60    return FALSE;
61  }
62  FX_DWORD dwAccess, dwShare, dwCreation;
63  FXCRT_Windows_GetFileMode(dwMode, dwAccess, dwShare, dwCreation);
64  m_hFile = ::CreateFileW((LPCWSTR)fileName.GetPtr(), dwAccess, dwShare, NULL,
65                          dwCreation, FILE_ATTRIBUTE_NORMAL, NULL);
66  if (m_hFile == INVALID_HANDLE_VALUE) {
67    m_hFile = NULL;
68  }
69  return m_hFile != NULL;
70}
71void CFXCRT_FileAccess_Win64::Close() {
72  if (!m_hFile) {
73    return;
74  }
75  ::CloseHandle(m_hFile);
76  m_hFile = NULL;
77}
78void CFXCRT_FileAccess_Win64::Release() {
79  delete this;
80}
81FX_FILESIZE CFXCRT_FileAccess_Win64::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}
91FX_FILESIZE CFXCRT_FileAccess_Win64::GetPosition() const {
92  if (!m_hFile) {
93    return (FX_FILESIZE)-1;
94  }
95  LARGE_INTEGER dist = {};
96  LARGE_INTEGER newPos = {};
97  if (!::SetFilePointerEx(m_hFile, dist, &newPos, FILE_CURRENT)) {
98    return (FX_FILESIZE)-1;
99  }
100  return (FX_FILESIZE)newPos.QuadPart;
101}
102FX_FILESIZE CFXCRT_FileAccess_Win64::SetPosition(FX_FILESIZE pos) {
103  if (!m_hFile) {
104    return (FX_FILESIZE)-1;
105  }
106  LARGE_INTEGER dist;
107  dist.QuadPart = pos;
108  LARGE_INTEGER newPos = {};
109  if (!::SetFilePointerEx(m_hFile, dist, &newPos, FILE_BEGIN)) {
110    return (FX_FILESIZE)-1;
111  }
112  return (FX_FILESIZE)newPos.QuadPart;
113}
114size_t CFXCRT_FileAccess_Win64::Read(void* pBuffer, size_t szBuffer) {
115  if (!m_hFile) {
116    return 0;
117  }
118  size_t szRead = 0;
119  if (!::ReadFile(m_hFile, pBuffer, (DWORD)szBuffer, (LPDWORD)&szRead, NULL)) {
120    return 0;
121  }
122  return szRead;
123}
124size_t CFXCRT_FileAccess_Win64::Write(const void* pBuffer, size_t szBuffer) {
125  if (!m_hFile) {
126    return 0;
127  }
128  size_t szWrite = 0;
129  if (!::WriteFile(m_hFile, pBuffer, (DWORD)szBuffer, (LPDWORD)&szWrite,
130                   NULL)) {
131    return 0;
132  }
133  return szWrite;
134}
135size_t CFXCRT_FileAccess_Win64::ReadPos(void* pBuffer,
136                                        size_t szBuffer,
137                                        FX_FILESIZE pos) {
138  if (!m_hFile) {
139    return 0;
140  }
141  if (pos >= GetSize()) {
142    return 0;
143  }
144  if (SetPosition(pos) == (FX_FILESIZE)-1) {
145    return 0;
146  }
147  return Read(pBuffer, szBuffer);
148}
149size_t CFXCRT_FileAccess_Win64::WritePos(const void* pBuffer,
150                                         size_t szBuffer,
151                                         FX_FILESIZE pos) {
152  if (!m_hFile) {
153    return 0;
154  }
155  if (SetPosition(pos) == (FX_FILESIZE)-1) {
156    return 0;
157  }
158  return Write(pBuffer, szBuffer);
159}
160FX_BOOL CFXCRT_FileAccess_Win64::Flush() {
161  if (!m_hFile) {
162    return FALSE;
163  }
164  return ::FlushFileBuffers(m_hFile);
165}
166FX_BOOL CFXCRT_FileAccess_Win64::Truncate(FX_FILESIZE szFile) {
167  if (SetPosition(szFile) == (FX_FILESIZE)-1) {
168    return FALSE;
169  }
170  return ::SetEndOfFile(m_hFile);
171}
172#endif
173