AuroraRuntime/Source/IO/FS/FileAdvisory.NT.cpp
Jamie Reece Wilson 828430889c [+] IIOHandle::SectionLock
[+] IIOHandle::SectionUnlock
[*] FileSteam.NT.cpp clean up
2023-09-23 04:48:48 +01:00

195 lines
5.4 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: FileAdvisory.NT.cpp
Date: 2022-1-29
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "FS.hpp"
#include "FileAdvisory.hpp"
#include "FileAdvisory.NT.hpp"
namespace Aurora::IO::FS
{
DWORD NtLockAdvisoryToShare(EFileAdvisoryLockLevel level)
{
switch (level)
{
case EFileAdvisoryLockLevel::eEnumCount:
case EFileAdvisoryLockLevel::eNoSafety:
return FILE_SHARE_READ | FILE_SHARE_WRITE;
case EFileAdvisoryLockLevel::eBlockWrite:
return FILE_SHARE_READ;
case EFileAdvisoryLockLevel::eBlockReadWrite:
return 0;
}
return 0;
}
bool ApplyFileSectionLock(AuSPtr<IIOHandle> pHandle,
EFileAdvisoryLockLevel level,
AuUInt64 uOffset,
AuUInt64 uLength)
{
DWORD dwFlags {};
OVERLAPPED overlapped {};
HANDLE hEventHandle { INVALID_HANDLE_VALUE };
if (!pHandle)
{
SysPushErrorUninitialized();
return false;
}
if (!pHandle->IsFile())
{
SysPushErrorIOResourceRejected();
return false;
}
switch (level)
{
case EFileAdvisoryLockLevel::eEnumCount:
case EFileAdvisoryLockLevel::eNoSafety:
return true;
case EFileAdvisoryLockLevel::eBlockWrite:
break;
case EFileAdvisoryLockLevel::eBlockReadWrite:
dwFlags |= LOCKFILE_EXCLUSIVE_LOCK;
break;
}
auto hHandle = (HANDLE)pHandle->GetOSHandleSafe().ValueOr((AuUInt)INVALID_HANDLE_VALUE);
if (hHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorIOResourceRejected();
return false;
}
bool bIsAsync = pHandle->IsAsync();
if (bIsAsync)
{
hEventHandle = ::CreateEventA(nullptr, false, false, nullptr);
if (!hEventHandle)
{
SysPushErrorGeneric();
return false;
}
overlapped.hEvent = hEventHandle;
}
overlapped.Offset = AuBitsToLower(uOffset);
overlapped.OffsetHigh = AuBitsToHigher(uOffset);
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
if (!LockFileEx(hHandle,
dwFlags,
0,
AuBitsToLower(uLength),
AuBitsToHigher(uLength),
&overlapped))
{
if (GetLastError() == ERROR_IO_PENDING)
{
::WaitForSingleObject(hEventHandle, 0);
DWORD idc {};
if (!::GetOverlappedResult(hHandle,
&overlapped,
&idc,
true))
{
AuWin32CloseHandle(hEventHandle);
return false;
}
}
else
{
AuWin32CloseHandle(hEventHandle);
return false;
}
}
AuWin32CloseHandle(hEventHandle);
return true;
}
bool UnapplyFileSectionLock(AuSPtr<IIOHandle> pHandle,
AuUInt64 uOffset,
AuUInt64 uLength)
{
DWORD dwFlags {};
OVERLAPPED overlapped {};
HANDLE hEventHandle { INVALID_HANDLE_VALUE };
if (!pHandle)
{
SysPushErrorUninitialized();
return false;
}
if (!pHandle->IsFile())
{
SysPushErrorIOResourceRejected();
return false;
}
auto hHandle = (HANDLE)pHandle->GetOSHandleSafe().ValueOr((AuUInt)INVALID_HANDLE_VALUE);
if (hHandle == INVALID_HANDLE_VALUE)
{
SysPushErrorIOResourceRejected();
return false;
}
bool bIsAsync = pHandle->IsAsync();
if (bIsAsync)
{
hEventHandle = ::CreateEventA(nullptr, false, false, nullptr);
if (!hEventHandle)
{
SysPushErrorGeneric();
return false;
}
overlapped.hEvent = hEventHandle;
}
dwFlags |= LOCKFILE_FAIL_IMMEDIATELY;
overlapped.Offset = AuBitsToLower(uOffset);
overlapped.OffsetHigh = AuBitsToHigher(uOffset);
if (!UnlockFileEx(hHandle,
0,
AuBitsToLower(uLength),
AuBitsToHigher(uLength),
&overlapped))
{
if (GetLastError() == ERROR_IO_PENDING)
{
::WaitForSingleObject(hEventHandle, 0);
DWORD idc {};
if (!::GetOverlappedResult(hHandle,
&overlapped,
&idc,
true))
{
AuWin32CloseHandle(hEventHandle);
return false;
}
}
else
{
AuWin32CloseHandle(hEventHandle);
return false;
}
}
AuWin32CloseHandle(hEventHandle);
return true;
}
}