[+] IIOHandle::InitFromSharing
[+] IIOHandle::SharingGetString [+] IIOHandle::SharingIsShared [+] IIOHandle::SharingStop [+] HANDLEPipeServer.[h/c]pp
This commit is contained in:
parent
1c0efebd87
commit
ce1ae24506
@ -111,6 +111,8 @@ namespace Aurora::IO
|
||||
|
||||
virtual bool InitFromStreamEnum(EStandardStream eStream) = 0;
|
||||
|
||||
virtual bool InitFromSharing(const AuString &handle) = 0;
|
||||
|
||||
virtual AuUInt64 GetOSHandle() const = 0;
|
||||
|
||||
virtual AuOptionalEx<AuUInt64> GetOSHandleSafe() const = 0;
|
||||
@ -147,6 +149,12 @@ namespace Aurora::IO
|
||||
|
||||
virtual bool SectionUnlock(AuUInt64 uOffset,
|
||||
AuUInt64 uLength) = 0;
|
||||
|
||||
virtual AuString SharingGetString() = 0;
|
||||
|
||||
virtual bool SharingIsShared() = 0;
|
||||
|
||||
virtual void SharingStop() = 0;
|
||||
};
|
||||
|
||||
AUKN_SHARED_SOO_CC(IOHandle, IIOHandle, 256);
|
||||
|
22
Include/Aurora/IO/NT/HANDLEPipeServer.hpp
Normal file
22
Include/Aurora/IO/NT/HANDLEPipeServer.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
/***
|
||||
Copyright (C) 2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: HANDLEPipeServer.hpp
|
||||
Date: 2024-01-02
|
||||
Author: Reece
|
||||
|
||||
Note: These file is excluded from the default include tree.
|
||||
You must explicitly include this via:
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#include <Aurora/IO/NT/HANDLEPipeServer.hpp>
|
||||
#endif
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::IO::NT
|
||||
{
|
||||
AUKN_SYM AuString ShareFileDescriptor(HANDLE hHandle);
|
||||
AUKN_SYM void ShareFileDescriptorStop(const AuString &handle);
|
||||
|
||||
AUKN_SYM HANDLE ShareFileDescriptorAccept(const AuString &handle);
|
||||
}
|
@ -29,6 +29,9 @@
|
||||
#include "Extensions/Win32/DarkTheme.hpp"
|
||||
#include <timeapi.h>
|
||||
#endif
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#include <Source/IO/NT/HANDLEPipeServer.hpp>
|
||||
#endif
|
||||
#include "Debug/MemoryCrunch.hpp"
|
||||
#include "Process/Process.hpp"
|
||||
#include "Exit/AuExit.hpp"
|
||||
@ -160,6 +163,10 @@ static void RuntimeLateClean()
|
||||
|
||||
Aurora::Processes::Deinit();
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
Aurora::IO::NT::ShutdownNTIPCHandleServer();
|
||||
#endif
|
||||
|
||||
// Static variables we should probably manually release ->
|
||||
// (there is no real logic under the following functions)
|
||||
Aurora::IO::Deinit();
|
||||
|
@ -9,6 +9,14 @@
|
||||
#include "AuIOHandle.hpp"
|
||||
#include "FS/FileAdvisory.hpp"
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
#include <Aurora/IO/NT/HANDLEPipeServer.hpp>
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||
#include <Aurora/IO/UNIX/UNIX.hpp>
|
||||
#endif
|
||||
|
||||
namespace Aurora::IO
|
||||
{
|
||||
AFileHandle::~AFileHandle()
|
||||
@ -303,6 +311,87 @@ namespace Aurora::IO
|
||||
return FS::UnapplyFileSectionLock(AuUnsafeRaiiToShared(this), uOffset, uLength);
|
||||
}
|
||||
|
||||
bool AFileHandle::InitFromSharing(const AuString &handle)
|
||||
{
|
||||
if (this->uOSReadHandle ||
|
||||
this->uOSWriteHandle)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
auto hHandle = NT::ShareFileDescriptorAccept(handle);
|
||||
if (hHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto uOSWriteHandle = AuUInt(hHandle);
|
||||
this->uOSReadHandle = uOSWriteHandle;
|
||||
this->uOSWriteHandle = uOSWriteHandle;
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||
auto iHandle = UNIX::ShareFileDescriptorAccept(handle);
|
||||
if (iHandle == -1 ||
|
||||
iHandle == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto uOSWriteHandle = AuUInt(iHandle);
|
||||
this->uOSReadHandle = uOSWriteHandle;
|
||||
this->uOSWriteHandle = uOSWriteHandle;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AuString AFileHandle::SharingGetString()
|
||||
{
|
||||
AuString handle;
|
||||
|
||||
if (this->pIPCString)
|
||||
{
|
||||
return *this->pIPCString;
|
||||
}
|
||||
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
handle = NT::ShareFileDescriptor((HANDLE)this->GetOSHandleSafe().ValueOr(-1));
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||
handle = UNIX::ShareFileDescriptor((HANDLE)this->GetOSHandleSafe().ValueOr(-1));
|
||||
#endif
|
||||
|
||||
if (handle.empty())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
this->pIPCString = AuMakeSharedPanic<AuString>(handle);
|
||||
return *this->pIPCString;
|
||||
}
|
||||
|
||||
bool AFileHandle::SharingIsShared()
|
||||
{
|
||||
return bool(this->pIPCString);
|
||||
}
|
||||
|
||||
void AFileHandle::SharingStop()
|
||||
{
|
||||
if (auto pString = AuExchange(this->pIPCString, {}))
|
||||
{
|
||||
#if defined(AURORA_IS_MODERNNT_DERIVED)
|
||||
NT::ShareFileDescriptorStop(*pString);
|
||||
#endif
|
||||
|
||||
#if defined(AURORA_IS_POSIX_DERIVED)
|
||||
UNIX::ShareFileDescriptorStop(*pString);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM IIOHandle *IOHandleNew()
|
||||
{
|
||||
return _new AFileHandle();
|
||||
|
@ -32,6 +32,8 @@ namespace Aurora::IO
|
||||
|
||||
bool InitFromStreamEnum(EStandardStream eStream) override;
|
||||
|
||||
bool InitFromSharing(const AuString &handle) override;
|
||||
|
||||
bool InitFromPath(HandleCreate create) override;
|
||||
|
||||
AuUInt64 GetOSHandle() const override;
|
||||
@ -70,6 +72,10 @@ namespace Aurora::IO
|
||||
|
||||
bool SectionUnlock(AuUInt64 uOffset,
|
||||
AuUInt64 uLength) override;
|
||||
|
||||
AuString SharingGetString() override;
|
||||
bool SharingIsShared() override;
|
||||
void SharingStop() override;
|
||||
|
||||
AuOptionalEx<AuUInt64> uOSWriteHandle;
|
||||
AuOptionalEx<AuUInt64> uOSReadHandle;
|
||||
@ -81,6 +87,7 @@ namespace Aurora::IO
|
||||
mutable AuOptional<bool> optIsFile;
|
||||
mutable AuOptional<bool> optIsPipe;
|
||||
mutable AuOptional<bool> optIsTTY;
|
||||
mutable AuSPtr<AuString> pIPCString;
|
||||
|
||||
protected:
|
||||
// Implement me:
|
||||
|
@ -391,7 +391,11 @@ namespace Aurora::IO::IPC
|
||||
|
||||
auto path = token.ToNTPath();
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
auto name = "\\\\.\\pipe\\" + token.ToNTPath();
|
||||
#else
|
||||
auto name = "\\\\.\\pipe\\LOCAL\\" + token.ToNTPath();
|
||||
#endif
|
||||
auto pageSize = AuHwInfo::GetPageSize();
|
||||
auto maxLength = uBytesLength ? AuPageRound(uBytesLength, pageSize) : pageSize ? 16 * pageSize : 4096;
|
||||
auto pipeServer = CreateNamedPipeA(name.c_str(),
|
||||
@ -450,7 +454,11 @@ namespace Aurora::IO::IPC
|
||||
return {};
|
||||
}
|
||||
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
auto name = "\\\\.\\pipe\\" + token->token.ToNTPath();
|
||||
#else
|
||||
auto name = "\\\\.\\pipe\\LOCAL\\" + token->token.ToNTPath();
|
||||
#endif
|
||||
pipe = CreateFileA(name.c_str(),
|
||||
GENERIC_WRITE | GENERIC_READ,
|
||||
0,
|
||||
|
357
Source/IO/NT/HANDLEPipeServer.cpp
Normal file
357
Source/IO/NT/HANDLEPipeServer.cpp
Normal file
@ -0,0 +1,357 @@
|
||||
/***
|
||||
Copyright (C) 2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: HANDLEPipeServer.cpp
|
||||
Date: 2024-01-02
|
||||
Author: Reece
|
||||
Note: Rushed Windows HANDLE sharing of any unnamed kernel object
|
||||
***/
|
||||
#include <Source/RuntimeInternal.hpp>
|
||||
#include <Source/IO/IPC/AuIPCHandle.hpp>
|
||||
|
||||
namespace Aurora::IO::NT
|
||||
{
|
||||
static AuMutex gMutex;
|
||||
static AuBST<AuUInt32, HANDLE> gHANDLECookieMap;
|
||||
static AuThreads::ThreadUnique_t gServerThread {};
|
||||
static const auto kDefaultMessageSize = 8192u;
|
||||
|
||||
static AuString GetIPCServerNameOfPid(AuUInt32 uPid)
|
||||
{
|
||||
#if defined(AURORA_PLATFORM_WIN32)
|
||||
return fmt::format("\\\\.\\pipe\\_HANDLESOF_{}", uPid);
|
||||
#else
|
||||
return fmt::format("\\\\.\\pipe\\LOCAL\\_HANDLESOF_{}", uPid);
|
||||
#endif
|
||||
}
|
||||
|
||||
HANDLE GetHandleForToken(AuUInt32 uToken)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
|
||||
auto itr = gHANDLECookieMap.find(uToken);
|
||||
if (itr != gHANDLECookieMap.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: use AuLoop
|
||||
DWORD WINAPI WaitForCookieThread(LPVOID lpvParam)
|
||||
{
|
||||
AuUInt32 uTokenID {};
|
||||
HANDLE hHandle { INVALID_HANDLE_VALUE }, hPipe { (HANDLE)lpvParam };
|
||||
DWORD dwBytesRead {}, dwWritten {};
|
||||
BOOL bSuccess { true };
|
||||
|
||||
if (!lpvParam)
|
||||
{
|
||||
return (DWORD)-1;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
bSuccess = ReadFile(hPipe,
|
||||
&uTokenID,
|
||||
sizeof(uTokenID),
|
||||
&dwBytesRead,
|
||||
NULL);
|
||||
if (!bSuccess ||
|
||||
dwBytesRead == 0)
|
||||
{
|
||||
if (GetLastError() != ERROR_BROKEN_PIPE)
|
||||
{
|
||||
SysPushErrorIO("IO HANDLE Server Error");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
hHandle = GetHandleForToken(uTokenID);
|
||||
if (hHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SysPushErrorIO("Tried to serve bad token: {}", uTokenID);
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
ULONG pid {};
|
||||
if (!GetNamedPipeClientProcessId(hPipe, &pid))
|
||||
{
|
||||
SysPushErrorIO("IO HANDLE Server Error");
|
||||
break;
|
||||
}
|
||||
|
||||
HANDLE hProcess {};
|
||||
if (!(hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, pid)))
|
||||
{
|
||||
SysPushErrorIO("IO HANDLE Server Error");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!DuplicateHandle(GetCurrentProcess(),
|
||||
hHandle,
|
||||
hProcess,
|
||||
&hHandle,
|
||||
0,
|
||||
FALSE,
|
||||
DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
SysPushErrorIO("IO HANDLE Server Error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bSuccess = WriteFile(hPipe,
|
||||
&hHandle,
|
||||
sizeof(hHandle),
|
||||
&dwWritten,
|
||||
NULL);
|
||||
|
||||
if (!bSuccess ||
|
||||
sizeof(hHandle) != sizeof(HANDLE))
|
||||
{
|
||||
SysPushErrorIO("IO HANDLE Server Error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (false);
|
||||
|
||||
AuWin32CloseHandle(hPipe);
|
||||
return bSuccess ? 0 : (DWORD)-1;
|
||||
}
|
||||
|
||||
static void IPCServer()
|
||||
{
|
||||
HANDLE hPipe = INVALID_HANDLE_VALUE;
|
||||
HANDLE hThread = NULL;
|
||||
|
||||
auto name = GetIPCServerNameOfPid(GetCurrentProcessId());
|
||||
|
||||
while (AuIsThreadRunning())
|
||||
{
|
||||
// TODO: use AuLoop
|
||||
hPipe = CreateNamedPipeA(name.c_str(),
|
||||
PIPE_ACCESS_DUPLEX,
|
||||
PIPE_TYPE_MESSAGE |
|
||||
PIPE_READMODE_MESSAGE |
|
||||
PIPE_WAIT,
|
||||
PIPE_UNLIMITED_INSTANCES,
|
||||
kDefaultMessageSize,
|
||||
kDefaultMessageSize,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (hPipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
SysPushErrorIOResourceFailure("NO IPC Handle Server");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConnectNamedPipe(hPipe, NULL) ||
|
||||
(GetLastError() == ERROR_PIPE_CONNECTED))
|
||||
{
|
||||
// TODO: use AuLoop
|
||||
hThread = CreateThread(NULL,
|
||||
0,
|
||||
WaitForCookieThread,
|
||||
(LPVOID)hPipe,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (hThread == NULL)
|
||||
{
|
||||
DisconnectNamedPipe(hPipe);
|
||||
}
|
||||
else
|
||||
{
|
||||
AuWin32CloseHandle(hThread);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AuWin32CloseHandle(hPipe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void StartServerIfNotAlready()
|
||||
{
|
||||
static AuInitOnce gInitOnce;
|
||||
gInitOnce.Call([]()
|
||||
{
|
||||
gServerThread = AuThreads::Spawn(IPCServer);
|
||||
SysAssert(gServerThread, "No NT Handle Server Thread");
|
||||
gServerThread->SetName("Microsoft NT HANDLE IPC Server/IPC-Provider");
|
||||
});
|
||||
}
|
||||
|
||||
bool FDServe(HANDLE hHandle, IPC::IPCToken &outHandle)
|
||||
{
|
||||
if (!hHandle ||
|
||||
hHandle == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
StartServerIfNotAlready();
|
||||
}
|
||||
|
||||
{
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
|
||||
do
|
||||
{
|
||||
outHandle.cookie = AuRng::RngU32();
|
||||
}
|
||||
while (AuExists(gHANDLECookieMap, outHandle.cookie));
|
||||
|
||||
outHandle.word = outHandle.cookie;
|
||||
outHandle.pid = GetCurrentProcessId();
|
||||
outHandle.path[0] = '\x00'; // msvc removing something it shouldn't have?
|
||||
//strcat(outHandle.path, AuToString(outHandle.cookie).c_str()); // ignore warning
|
||||
|
||||
return AuTryInsert(gHANDLECookieMap, AuConstReference(outHandle.cookie), AuConstReference(hHandle));
|
||||
}
|
||||
}
|
||||
|
||||
void FDServeEnd(const IPC::IPCToken &handle)
|
||||
{
|
||||
AU_LOCK_GUARD(gMutex);
|
||||
AuTryRemove(gHANDLECookieMap, handle.cookie);
|
||||
}
|
||||
|
||||
bool FDAccept(const IPC::IPCToken &handle, HANDLE &outHandle)
|
||||
{
|
||||
outHandle = INVALID_HANDLE_VALUE;
|
||||
|
||||
HANDLE hPipe {};
|
||||
HANDLE hHandle {};
|
||||
BOOL bSuccess {};
|
||||
DWORD dwWritten {};
|
||||
auto name = GetIPCServerNameOfPid(handle.pid);
|
||||
|
||||
hPipe = CreateFileA(name.c_str(),
|
||||
GENERIC_WRITE | GENERIC_READ,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL);
|
||||
|
||||
if (hPipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetLastError() == ERROR_PIPE_BUSY)
|
||||
{
|
||||
SysPushErrorIO("Pipe is used -> a client has already connected or the nt server is not ready");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
SysPushErrorIO("No Server: {}", GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bSuccess = WriteFile(hPipe,
|
||||
&handle.cookie,
|
||||
sizeof(AuUInt32),
|
||||
&dwWritten,
|
||||
NULL);
|
||||
|
||||
if (!bSuccess)
|
||||
{
|
||||
AuWin32CloseHandle(hPipe);
|
||||
SysPushErrorIO("No Server");
|
||||
return false;
|
||||
}
|
||||
|
||||
FlushFileBuffers(hPipe);
|
||||
|
||||
bSuccess = ReadFile(hPipe,
|
||||
&hHandle,
|
||||
sizeof(hHandle),
|
||||
&dwWritten,
|
||||
NULL);
|
||||
if (!bSuccess)
|
||||
{
|
||||
AuWin32CloseHandle(hPipe);
|
||||
SysPushErrorIO("No Handle");
|
||||
return false;
|
||||
}
|
||||
|
||||
outHandle = hHandle;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShutdownNTIPCHandleServer()
|
||||
{
|
||||
gServerThread.reset();
|
||||
}
|
||||
|
||||
AUKN_SYM AuString ShareFileDescriptor(HANDLE hHandle)
|
||||
{
|
||||
IPC::IPCToken token;
|
||||
IPC::IPCHandle handle;
|
||||
|
||||
if (!FDServe(hHandle, token))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
handle.pid = token.pid;
|
||||
handle.PushId(IPC::EIPCHandleType::eIPCSharedFd, token);
|
||||
|
||||
return handle.ToString();
|
||||
}
|
||||
|
||||
AUKN_SYM void ShareFileDescriptorStop(const AuString &handle)
|
||||
{
|
||||
IPC::IPCHandle handle2;
|
||||
if (!handle2.FromString(handle))
|
||||
{
|
||||
SysPushErrorIO("Invalid handle string");
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto val = handle2.GetToken(IPC::EIPCHandleType::eIPCSharedFd, 0))
|
||||
{
|
||||
FDServeEnd(val->token);
|
||||
}
|
||||
else
|
||||
{
|
||||
SysPushErrorSyntax("Invalid handle string");
|
||||
}
|
||||
}
|
||||
|
||||
AUKN_SYM HANDLE ShareFileDescriptorAccept(const AuString &handle)
|
||||
{
|
||||
IPC::IPCHandle handle2;
|
||||
HANDLE hHandle { INVALID_HANDLE_VALUE };
|
||||
|
||||
if (!handle2.FromString(handle))
|
||||
{
|
||||
SysPushErrorIO("Invalid handle string");
|
||||
return hHandle;
|
||||
}
|
||||
|
||||
auto val = handle2.GetToken(IPC::EIPCHandleType::eIPCSharedFd, 0);
|
||||
if (!val)
|
||||
{
|
||||
SysPushErrorSyntax("Invalid handle string");
|
||||
return hHandle;
|
||||
}
|
||||
|
||||
if (!FDAccept(val->token, hHandle))
|
||||
{
|
||||
SysPushErrorNested();
|
||||
return hHandle;
|
||||
}
|
||||
|
||||
return hHandle;
|
||||
}
|
||||
}
|
13
Source/IO/NT/HANDLEPipeServer.hpp
Normal file
13
Source/IO/NT/HANDLEPipeServer.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
/***
|
||||
Copyright (C) 2024 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
||||
|
||||
File: HANDLEPipeServer.hpp
|
||||
Date: 2024-01-02
|
||||
Author: Reece
|
||||
***/
|
||||
#pragma once
|
||||
|
||||
namespace Aurora::IO::NT
|
||||
{
|
||||
void ShutdownNTIPCHandleServer();
|
||||
}
|
Loading…
Reference in New Issue
Block a user