CyberEngineMkIII
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
CYBWin32File.cpp
Go to the documentation of this file.
1 #include "CYB.hpp"
3 
4 using namespace CYB::Platform::Win32;
5 
6 CYB::Platform::System::File::File(Path&& APath, const Mode AMode, const Method AMethod) :
7  FPath(std::move(APath)),
8  FOpenMode(AMode)
9 {
10  if (AMode == Mode::READ && AMethod == Method::TRUNCATE)
12 
13  auto& MM(Core().FModuleManager);
14 
15  const auto DesiredAccess([&]() -> DWORD {
16  switch (AMode)
17  {
18  case Mode::READ:
19  return GENERIC_READ;
20  case Mode::WRITE:
21  return GENERIC_WRITE;
22  case Mode::READ_WRITE:
23  return GENERIC_READ | GENERIC_WRITE;
24  default:
26  }
27  }()), CreationDisposition([&]() -> DWORD {
28  switch (AMethod) {
29  case Method::ANY:
30  return OPEN_ALWAYS;
31  case Method::CREATE:
32  return CREATE_NEW;
33  case Method::EXIST:
34  return OPEN_EXISTING;
35  case Method::TRUNCATE:
36  return CREATE_ALWAYS;
37  default:
39  }
40  }());
41 
42  const auto FilePath(FPath.WidePath().WString());
43  //Maintain POSIX compatibility, no locking
44  FHandle = MM.Call<Modules::Kernel32::CreateFileW>(FilePath, DesiredAccess, static_cast<DWORD>(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), nullptr, CreationDisposition, static_cast<DWORD>(FILE_ATTRIBUTE_NORMAL), nullptr);
45 
46  if (FHandle == INVALID_HANDLE_VALUE) {
47  const auto Error(MM.Call<Modules::Kernel32::GetLastError>());
48  API::Assert::NotEqual<DWORD>(Error, ERROR_INVALID_PARAMETER);
49 
50  //I know this could be a switch but CodeCoverage.exe hates it
51 
52  if (Error == ERROR_FILE_NOT_FOUND || Error == ERROR_PATH_NOT_FOUND || Error == ERROR_INVALID_NAME)
54  if (Error == ERROR_FILE_EXISTS)
56  if (Error == ERROR_ACCESS_DENIED) {
57  //Keep things DRY
58  //Translate properly to the directory error
59  //We don't care how screwed up FPath is, it has a different exception spec to us
60  //DO NOT LET IT PROPAGATE
61  bool IsDir;
62  try {
63  IsDir = FPath.IsDirectory();
64  }
65  catch (CYB::Exception::Base& AException) {
67  IsDir = false;
68  }
69  if (IsDir)
71  }
72  if (AMode == Mode::READ)
75 
76  }
77 
78  if (AMethod == Method::ANY) {
79  if (MM.Call<Modules::Kernel32::GetLastError>() == ERROR_ALREADY_EXISTS)
81  else
83  }
84  else
85  FOpenMethod = AMethod;
86 }
87 
89  FHandle(AMove.FHandle)
90 {
91  AMove.FHandle = INVALID_HANDLE_VALUE;
92 }
93 
94 void CYB::Platform::System::File::Close(void) const noexcept {
95  if (FHandle != INVALID_HANDLE_VALUE)
96  Core().FModuleManager.Call<Modules::Kernel32::CloseHandle>(FHandle);
97 }
98 
100  Close();
101  FHandle = AMove.FHandle;
102  AMove.FHandle = INVALID_HANDLE_VALUE;
103  FOpenMode = AMove.FOpenMode;
104  FOpenMethod = AMove.FOpenMethod;
105  return *this;
106 }
107 
108 unsigned long long CYB::Platform::System::File::Size(const System::Path& APath) {
109  auto& K32(Core().FModuleManager);
110 
111  WIN32_FILE_ATTRIBUTE_DATA Attributes;
112  if (K32.Call<Modules::Kernel32::GetFileAttributesExW>(APath.WidePath().WString(), GetFileExInfoStandard, &Attributes) != 0) {
113  LARGE_INTEGER Size;
114  Size.HighPart = static_cast<LONG>(Attributes.nFileSizeHigh);
115  Size.LowPart = Attributes.nFileSizeLow;
116  return static_cast<unsigned long long>(Size.QuadPart);
117  }
118 
119  const auto Error(K32.Call<Modules::Kernel32::GetLastError>());
120  if (Error == ERROR_ACCESS_DENIED || Error == ERROR_SHARING_VIOLATION)
123 }
124 
125 unsigned long long CYB::Platform::System::File::Size(void) const {
126  LARGE_INTEGER Size;
127  if (Core().FModuleManager.Call<Modules::Kernel32::GetFileSizeEx>(FHandle, &Size) == 0)
129  return static_cast<unsigned long long>(Size.QuadPart);
130 }
131 
132 unsigned long long CYB::Platform::System::File::Seek(const long long AOffset, const SeekLocation ALocation) const {
133  LARGE_INTEGER Distance, Location;
134  Distance.QuadPart = AOffset;
135 
136  const auto WinLocation([&]() -> DWORD {
137  switch (ALocation) {
138  case SeekLocation::BEGIN:
139  return FILE_BEGIN;
140  case SeekLocation::CURSOR:
141  return FILE_CURRENT;
142  case SeekLocation::END:
143  return FILE_END;
144  default:
146  }
147  }());
148 
149  if (Core().FModuleManager.Call<Modules::Kernel32::SetFilePointerEx>(FHandle, Distance, &Location, WinLocation) == 0)
151 
152  return static_cast<unsigned long long>(Location.QuadPart);
153 }
154 
155 unsigned long long CYB::Platform::System::File::Read(void* const ABuffer, const unsigned long long AMaxAmount) const {
156  if (FOpenMode == Mode::WRITE)
158  DWORD BytesRead(0);
159  //error checks not required, see msdn return conditions
160  Core().FModuleManager.Call<Modules::Kernel32::ReadFile>(FHandle, ABuffer, static_cast<DWORD>(AMaxAmount), &BytesRead, nullptr);
161  return BytesRead;
162 }
163 
164 unsigned long long CYB::Platform::System::File::Write(const void* const ABuffer, const unsigned long long AAmount) {
165  if (FOpenMode == Mode::READ)
167  DWORD BytesWritten(0);
168  //error checks not required, see msdn return conditions
169  Core().FModuleManager.Call<Modules::Kernel32::WriteFile>(FHandle, ABuffer, static_cast<DWORD>(AAmount), &BytesWritten, nullptr);
170  return BytesWritten;
171 }
File() noexcept=default
See Default Constructors and Destructor.
unsigned long long Read(void *const ABuffer, const unsigned long long AMaxAmount) const finaloverride
Read data from a Stream at the current cursor position and advance the cursor by that amount...
Method
The method of handling Files that already exist.
Definition: File.hpp:8
System::Path FPath
The Path indicating this File.
Definition: CYBFile.hpp:8
Mode
The available operations for the Stream. Bitset.
Definition: Stream.hpp:10
The File must not exist. It will be created.
Win32::HANDLE FHandle
The file handle.
unsigned long long Size(void) const finaloverride
Get the current size of the File.
bool IsDirectory(void) const finaloverride
Check if the current path is a directory.
Contains the basic File interface. Does not perform locking of any kind, be aware of possible race co...
Definition: CYBFile.hpp:6
SeekLocation
The location to begin a seek operation at.
Definition: Stream.hpp:16
Platform::Modules::Manager FModuleManager
Loads and contains required modules.
Definition: CYBCore.hpp:20
void Close(void) const noexcept
Closes the file's handle if it is valid.
const API::String::UTF16 & WidePath(void) const noexcept
Accessor for other Win32 implementations that require the UTF16 Path.
A required file was not found in the filesystem.
Definition: Exception.hpp:71
Method FOpenMethod
The method used to open the file.
Definition: CYBFile.hpp:10
File & operator=(File &&AMove) noexcept
See Default Constructors and Destructor.
The File may or may not exist. It will be created if it doesn't. OpenMethod will be set to EXIST or C...
Exceptions caused by external call failures or invalid external data. Only classifies ones that can p...
Definition: Exception.hpp:65
static void Equal(const AType &ALHS, const AType &ARHS) noexcept
Equivalence assertion function. May not be evaluated.
The current arrangment of arguments passed the function is invalid.
Definition: Exception.hpp:39
const wchar_t * WString(void) const noexcept
Get the underlying const wide char array.
const Level FLevel
The type of the exception.
Definition: Exception.hpp:19
unsigned long long Seek(const long long AOffset, const SeekLocation ALocation) const finaloverride
Set the cursor position in the Stream.
Generic error for read failures. See functions for further documentation.
Definition: Exception.hpp:72
Precompiled header for inter-engine operations.
Any existing File will be overwritten and an empty file will be created.
A file that was to be created exists.
Definition: Exception.hpp:70
Engine::Core & Core(void) noexcept
Retrieve the Core singleton.
Definition: CYBCore.cpp:69
Illegal call given prexisting conditions.
Definition: Exception.hpp:38
Used for manipulating Paths. Paths will always exist either as a file or directory. Paths are '/' delimited when forming though may not be while retrieving. File names ".." will ascend a directory and '.' represents a no-op.
Definition: CYBPath.hpp:10
auto Call(AArgs &&...AArguments)
Call a loaded function.
The File must exist.
Exceptions indicating an API contract violation. Should not be anticipated.
Definition: Exception.hpp:32
Generic error for write failures. See functions for further documentation.
Definition: Exception.hpp:73
unsigned long long Write(const void *const ABuffer, const unsigned long long AAmount) finaloverride
Write data to the Stream at the current cursor position and advance the cursor by that amount...
The base exception recognized by the entire engine.
Definition: Exception.hpp:7
An operation was attempted with an invalid enum code.
Definition: Exception.hpp:36