AuroraRuntime/Source/IO/AuIOHandle.NT.cpp

260 lines
8.6 KiB
C++

/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuIOHandle.NT.cpp
Date: 2023-7-28
Author: Reece
***/
#include <RuntimeInternal.hpp>
#include "AuIOHandle.hpp"
#include "AuIOHandle.NT.hpp"
#include "FS/FS.hpp"
#include "FS/FileAdvisory.NT.hpp"
namespace Aurora::IO
{
AuUInt64 AFileHandle::DupHandle(AuUInt64 uOSHandle, bool bWriteAccess)
{
HANDLE hTargetHandle = (HANDLE)uOSHandle;
HANDLE hTargetProcess = ::GetCurrentProcess();
HANDLE hHandle {};
if (!::DuplicateHandle(hTargetProcess,
hTargetHandle,
hTargetProcess,
&hHandle,
bWriteAccess ? GENERIC_WRITE | GENERIC_READ : GENERIC_READ,
FALSE,
FALSE))
{
return 0;
}
return AuUInt64(hHandle);
}
void AFileHandle::CloseHandle(AuUInt64 uOSHandle)
{
HANDLE hHandle = (HANDLE)uOSHandle;
AuWin32CloseHandle(hHandle);
}
struct NTIOHandle final : AFileHandle
{
bool InitFromPath(HandleCreate create) override
{
HANDLE hFileHandle;
DWORD dwFlags {};
DWORD dwShare {};
if (create.path.empty())
{
SysPushErrorArg("Cannot open an IO handle to the provided empty path");
return false;
}
if (!FS::EFileOpenModeIsValid(create.eMode))
{
SysPushErrorParam("Invalid open mode");
return false;
}
if (!FS::EFileAdvisoryLockLevelIsValid(create.eAdvisoryLevel))
{
SysPushErrorParam("Invalid lock mode");
return false;
}
auto pathex = FS::NormalizePathRet(create.path);
if (pathex.empty())
{
SysPushErrorMemory();
return false;
}
auto win32Path = Locale::ConvertFromUTF8(pathex);
if (win32Path.empty())
{
SysPushErrorMemory();
return false;
}
hFileHandle = INVALID_HANDLE_VALUE;
dwShare = FS::NtLockAdvisoryToShare(create.eAdvisoryLevel);
if (create.bAsyncHandle)
{
dwFlags |= FILE_FLAG_OVERLAPPED;
}
if (create.bDirectIOMode)
{
dwFlags |= FILE_FLAG_NO_BUFFERING;
}
if (!dwFlags)
{
dwFlags |= FILE_ATTRIBUTE_NORMAL;
}
switch (create.eMode)
{
case FS::EFileOpenMode::eRead:
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_READ,
dwShare,
NULL,
OPEN_EXISTING,
dwFlags,
NULL);
if (hFileHandle != INVALID_HANDLE_VALUE)
{
this->uOSReadHandle = AuUInt64(hFileHandle);
}
break;
}
case FS::EFileOpenMode::eReadWrite:
{
if (create.bAlwaysCreateDirTree)
{
FS::CreateDirectories(pathex, true);
}
if (create.bFailIfNonEmptyFile)
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | GENERIC_READ | DELETE,
NULL,
NULL,
CREATE_NEW,
dwFlags,
NULL);
if (hFileHandle == INVALID_HANDLE_VALUE)
{
if (AuFS::FileExists(pathex.c_str()))
{
SysPushErrorResourceExists("File {} already exists", create.path);
return false;
}
}
}
else
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | GENERIC_READ | DELETE,
dwShare,
NULL,
OPEN_EXISTING,
dwFlags,
NULL);
if (hFileHandle == INVALID_HANDLE_VALUE)
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | GENERIC_READ | DELETE,
dwShare,
NULL,
CREATE_NEW,
dwFlags,
NULL);
}
}
if (hFileHandle != INVALID_HANDLE_VALUE)
{
this->uOSReadHandle = AuUInt64(hFileHandle);
this->uOSWriteHandle = AuUInt64(hFileHandle);
}
break;
}
case FS::EFileOpenMode::eWrite:
{
if (create.bAlwaysCreateDirTree)
{
FS::CreateDirectories(pathex, true);
}
if (create.bFailIfNonEmptyFile)
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | DELETE,
NULL,
NULL,
CREATE_NEW,
dwFlags,
NULL);
if (hFileHandle == INVALID_HANDLE_VALUE)
{
if (AuFS::FileExists(pathex.c_str()))
{
SysPushErrorResourceExists("File {} already exists", create.path);
return false;
}
}
}
else
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | FILE_READ_ATTRIBUTES | DELETE,
dwShare,
NULL,
OPEN_EXISTING,
dwFlags,
NULL);
if (hFileHandle == INVALID_HANDLE_VALUE)
{
hFileHandle = ::CreateFileW(win32Path.c_str(),
GENERIC_WRITE | DELETE,
dwShare,
NULL,
CREATE_NEW,
dwFlags,
NULL);
}
}
if (hFileHandle != INVALID_HANDLE_VALUE)
{
this->uOSWriteHandle = AuUInt64(hFileHandle);
}
break;
}
}
if (hFileHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorIO("Couldn't open: {}", create.path);
return false;
}
this->bIsAsync = create.bAsyncHandle;
this->path = create.path;
return this->IsValid();
}
};
AUKN_SYM IIOHandle *IOHandleNew()
{
return _new NTIOHandle();
}
AUKN_SYM void IOHandleRelease(IIOHandle *pIOHandle)
{
AuSafeDelete<NTIOHandle *>(pIOHandle);
}
AUROXTL_INTERFACE_SOO_SRC_EX(AURORA_SYMBOL_EXPORT, IOHandle, NTIOHandle)
}