Merge pull request #2146 from NZJenkins/handle-handling

Implement IsEmuHandle by keeping a lookup of EmuHandle objects
This commit is contained in:
PatrickvL 2021-02-27 01:09:49 +01:00 committed by GitHub
commit 8f848f8dda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 34 deletions

View File

@ -142,10 +142,10 @@ XBSYSAPI EXPORTNUM(187) xbox::ntstatus_xt NTAPI xbox::NtClose
NTSTATUS ret = xbox::status_success;
if (IsEmuHandle(Handle))
if (EmuHandle::IsEmuHandle(Handle))
{
// delete 'special' handles
EmuHandle *iEmuHandle = HandleToEmuHandle(Handle);
auto iEmuHandle = (EmuHandle*)Handle;
ret = iEmuHandle->NtClose();
LOG_UNIMPLEMENTED(); // TODO : Base this on the Ob* functions
@ -682,8 +682,8 @@ XBSYSAPI EXPORTNUM(197) xbox::ntstatus_xt NTAPI xbox::NtDuplicateObject
NTSTATUS ret = xbox::status_success;
if (IsEmuHandle(SourceHandle)) {
EmuHandle* iEmuHandle = HandleToEmuHandle(SourceHandle);
if (EmuHandle::IsEmuHandle(SourceHandle)) {
auto iEmuHandle = (EmuHandle*)SourceHandle;
ret = iEmuHandle->NtDuplicateObject(TargetHandle, Options);
/*
PVOID Object;
@ -739,7 +739,7 @@ XBSYSAPI EXPORTNUM(198) xbox::ntstatus_xt NTAPI xbox::NtFlushBuffersFile
LOG_FUNC_END;
NTSTATUS ret = xbox::status_success;
if (IsEmuHandle(FileHandle))
if (EmuHandle::IsEmuHandle(FileHandle))
LOG_UNIMPLEMENTED();
else
ret = NtDll::NtFlushBuffersFile(FileHandle, (NtDll::IO_STATUS_BLOCK*)IoStatusBlock);
@ -1371,13 +1371,16 @@ XBSYSAPI EXPORTNUM(215) xbox::ntstatus_xt NTAPI xbox::NtQuerySymbolicLinkObject
LOG_FUNC_ARG_OUT(ReturnedLength)
LOG_FUNC_END;
NTSTATUS ret = 0;
NTSTATUS ret = STATUS_INVALID_HANDLE;
EmuNtSymbolicLinkObject* symbolicLinkObject = NULL;
// Check that we actually got an EmuHandle :
ret = STATUS_INVALID_HANDLE;
// We expect LinkHandle to always be an EmuHandle
if (!EmuHandle::IsEmuHandle(LinkHandle)) {
LOG_UNIMPLEMENTED();
return ret;
}
EmuHandle* iEmuHandle = HandleToEmuHandle(LinkHandle);
auto iEmuHandle = (EmuHandle*)LinkHandle;
// Retrieve the NtSymbolicLinkObject and populate the output arguments :
ret = xbox::status_success;
symbolicLinkObject = (EmuNtSymbolicLinkObject*)iEmuHandle->NtObject;

View File

@ -255,9 +255,39 @@ EmuHandle::EmuHandle(EmuNtObject* ntObject)
NtObject = ntObject;
}
std::unordered_set<EmuHandle*> EmuHandle::EmuHandleLookup = {};
std::shared_mutex EmuHandle::EmuHandleLookupLock = {};
EmuHandle* EmuHandle::CreateEmuHandle(EmuNtObject* ntObject) {
auto emuHandle = new EmuHandle(ntObject);
// Register EmuHandle
{
std::unique_lock scopedLock(EmuHandleLookupLock);
EmuHandleLookup.insert(emuHandle);
}
return emuHandle;
}
NTSTATUS EmuHandle::NtClose()
{
return NtObject->NtClose();
auto status = NtObject->NtClose();
// Unregister the handle
if (status == STATUS_SUCCESS) {
std::unique_lock scopedLock(EmuHandleLookupLock);
EmuHandleLookup.erase(this);
}
return status;
}
bool EmuHandle::IsEmuHandle(HANDLE Handle)
{
std::shared_lock scopedLock(EmuHandleLookupLock);
auto iter = EmuHandleLookup.find((EmuHandle*) Handle);
return !(iter == EmuHandleLookup.end());
}
NTSTATUS EmuHandle::NtDuplicateObject(PHANDLE TargetHandle, DWORD Options)
@ -274,7 +304,7 @@ EmuNtObject::EmuNtObject()
HANDLE EmuNtObject::NewHandle()
{
RefCount++;
return EmuHandleToHandle(new EmuHandle(this));
return EmuHandle::CreateEmuHandle(this);
}
NTSTATUS EmuNtObject::NtClose()
@ -292,21 +322,6 @@ EmuNtObject* EmuNtObject::NtDuplicateObject(DWORD Options)
return this;
}
bool IsEmuHandle(HANDLE Handle)
{
return ((uint32_t)Handle > 0x80000000) && ((uint32_t)Handle < 0xFFFFFFFE);
}
EmuHandle* HandleToEmuHandle(HANDLE Handle)
{
return (EmuHandle*)((uint32_t)Handle & 0x7FFFFFFF);
}
HANDLE EmuHandleToHandle(EmuHandle* emuHandle)
{
return (HANDLE)((uint32_t)emuHandle | 0x80000000);
}
std::wstring string_to_wstring(std::string const & src)
{
std::wstring result = std::wstring(src.length(), L' ');

View File

@ -30,6 +30,8 @@
#include <cstdio>
#include <string>
#include <memory>
#include <unordered_set>
#include <shared_mutex>
// ******************************************************************
// * prevent name collisions
@ -160,10 +162,21 @@ NTSTATUS CxbxConvertFilePath(std::string RelativeXboxPath, OUT std::wstring &Rel
class EmuHandle
{
public:
EmuHandle(EmuNtObject* ntObject);
NTSTATUS NtClose();
NTSTATUS NtDuplicateObject(PHANDLE TargetHandle, DWORD Options);
EmuNtObject* NtObject;
static EmuHandle* CreateEmuHandle(EmuNtObject* ntObject);
static bool IsEmuHandle(HANDLE Handle);
private:
EmuHandle(EmuNtObject* ntObject);
// Keep track of every EmuHandle wrapper
// If we remember what EmuHandle objects we hand out, we can tell the difference between an EmuHandle and garbage
// We used to rely on the high bit to differentiatean EmuHandles
// But titles may attempt to operate on invalid handles with the high bit set
// Test case: Amped sets a handle value to 0xFDFDFDFD (coincidentally a VS debugger guard value)
static std::unordered_set<EmuHandle*> EmuHandleLookup;
static std::shared_mutex EmuHandleLookupLock;
};
// ******************************************************************
@ -204,13 +217,6 @@ struct XboxDevice {
HANDLE HostRootHandle;
};
// ******************************************************************
// * is Handle a 'special' emulated handle?
// ******************************************************************
bool IsEmuHandle(HANDLE Handle);
EmuHandle* HandleToEmuHandle(HANDLE Handle);
HANDLE EmuHandleToHandle(EmuHandle* emuHandle);
CHAR* NtStatusToString(IN NTSTATUS Status);
int CxbxRegisterDeviceHostPath(std::string XboxFullPath, std::string HostDevicePath, bool IsFile = false);