Allow ObIniSystem to succeed

This commit is contained in:
ergo720 2021-12-27 02:02:34 +01:00
parent 3e5272d91a
commit a7cf67cd71
12 changed files with 394 additions and 153 deletions

View File

@ -190,6 +190,7 @@ file (GLOB CXBXR_HEADER_EMU
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuFile.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuFS.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuNtDll.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/NativeHandle.h"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/PatchRdtsc.hpp"
"${CXBXR_ROOT_DIR}/src/devices/ADM1032Device.h"
"${CXBXR_ROOT_DIR}/src/devices/EEPROMDevice.h"
@ -371,6 +372,7 @@ file (GLOB CXBXR_SOURCE_EMU
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuFile.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuFS.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/EmuNtDll.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/NativeHandle.cpp"
"${CXBXR_ROOT_DIR}/src/core/kernel/support/PatchRdtsc.cpp"
"${CXBXR_ROOT_DIR}/src/devices/ADM1032Device.cpp"
"${CXBXR_ROOT_DIR}/src/devices/EEPROMDevice.cpp"

View File

@ -133,7 +133,7 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(XAudioDownloadEffectsImage)
ANSI_STRING file_name;
IO_STATUS_BLOCK io_status_block;
RtlInitAnsiString(&file_name, pszImageName);
XB_InitializeObjectAttributes(&obj, &file_name, obj_case_insensitive, ObDosDevicesDirectory());
X_InitializeObjectAttributes(&obj, &file_name, OBJ_CASE_INSENSITIVE, ObDosDevicesDirectory());
HANDLE hFile;
ntstatus_xt NtStatusCreateFile = NtCreateFile(

View File

@ -1629,7 +1629,7 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(XReadMUMetaData)
std::string mu_path_str(DrivePrefix + lett + ":");
ANSI_STRING mu_path;
RtlInitAnsiString(&mu_path, mu_path_str.data());
XB_InitializeObjectAttributes(&obj, &mu_path, obj_case_insensitive, ObDosDevicesDirectory());
X_InitializeObjectAttributes(&obj, &mu_path, OBJ_CASE_INSENSITIVE, ObDosDevicesDirectory());
HANDLE handle;
IO_STATUS_BLOCK io_status_block;

View File

@ -35,8 +35,6 @@ typedef struct _OBJECT_HEADER_NAME_INFO {
OBJECT_STRING Name;
} OBJECT_HEADER_NAME_INFO, *POBJECT_HEADER_NAME_INFO;
inline constexpr dword_xt obj_case_insensitive = 0x40;
#define ObDosDevicesDirectory() ((HANDLE)-3)
#define ObWin32NamedObjectsDirectory() ((HANDLE)-4)
@ -54,6 +52,15 @@ inline constexpr dword_xt obj_case_insensitive = 0x40;
#define OB_FLAG_PERMANENT_OBJECT 0x02
#define OB_FLAG_ATTACHED_OBJECT 0x04
#define OBJ_INHERIT 0x00000002L
#define OBJ_PERMANENT 0x00000010L
#define OBJ_EXCLUSIVE 0x00000020L
#define OBJ_CASE_INSENSITIVE 0x00000040L
#define OBJ_OPENIF 0x00000080L
#define OBJ_OPENLINK 0x00000100L
#define OBJ_KERNEL_HANDLE 0x00000200L
#define OBJ_VALID_ATTRIBUTES 0x000003F2L
#define OBJECT_TO_OBJECT_HEADER(Object) CONTAINING_RECORD(Object, OBJECT_HEADER, Body)
#define OBJECT_TO_OBJECT_HEADER_NAME_INFO(Object) ((POBJECT_HEADER_NAME_INFO)OBJECT_TO_OBJECT_HEADER(Object) - 1)
#define OBJECT_HEADER_NAME_INFO_TO_OBJECT_HEADER(ObjectHeaderNameInfo) ((POBJECT_HEADER)((POBJECT_HEADER_NAME_INFO)(ObjectHeaderNameInfo)+1))
@ -75,7 +82,8 @@ ntstatus_xt ObpReferenceObjectByName(
OUT PVOID *ReturnedObject
);
#define XB_InitializeObjectAttributes(p, n, a, r){\
// Avoid a conflict with the InitializeObjectAttributes macro imported by the windows headers
#define X_InitializeObjectAttributes(p, n, a, r){\
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
@ -86,7 +94,10 @@ boolean_xt ObpExtendObjectHandleTable();
void_xt ObDissectName(OBJECT_STRING Path, POBJECT_STRING FirstName, POBJECT_STRING RemainingName);
PVOID ObpGetObjectHandleContents(HANDLE Handle);
PVOID ObpGetObjectHandleReference(HANDLE Handle);
ulong_xt FASTCALL ObpComputeHashIndex(IN POBJECT_STRING ElementName);
ulong_xt FASTCALL ObpComputeHashIndex(POBJECT_STRING ElementName);
PVOID ObpDestroyObjectHandle(HANDLE Handle);
void_xt ObpDetachNamedObject(PVOID Object, KIRQL OldIrql);
ntstatus_xt ObpClose(HANDLE Handle);
boolean_xt ObpLookupElementNameInDirectory(
IN POBJECT_DIRECTORY Directory,

View File

@ -103,6 +103,7 @@ typedef void* LPSECURITY_ATTRIBUTES;
#define X_STATUS_MEMORY_NOT_ALLOCATED 0xC00000A0L
#define X_STATUS_NOT_COMMITTED 0xC000002DL
#define X_STATUS_UNRECOGNIZED_VOLUME 0xC000014FL
#define X_STATUS_OBJECT_PATH_NOT_FOUND 0xC000003AL
// ******************************************************************
// * Registry value types

View File

@ -44,6 +44,7 @@ namespace NtDll
#include "core\kernel\support\Emu.h" // For EmuLog(LOG_LEVEL::WARNING, )
#include "core\kernel\support\EmuFile.h" // For EmuNtSymbolicLinkObject, NtStatusToString(), etc.
#include "core\kernel\memory-manager\VMManager.h" // For g_VMManager
#include "core\kernel\support\NativeHandle.h"
#include "CxbxDebugger.h"
#pragma warning(disable:4005) // Ignore redefined status values
@ -142,32 +143,43 @@ XBSYSAPI EXPORTNUM(187) xbox::ntstatus_xt NTAPI xbox::NtClose
NTSTATUS ret = X_STATUS_SUCCESS;
if (EmuHandle::IsEmuHandle(Handle))
{
if (EmuHandle::IsEmuHandle(Handle)) {
// EmuHandles are only created for symbolic links with NtOpenSymbolicLinkObject, and ob handles are currently not created
// for those, so we can skip the call to ObpClose for now
// delete 'special' handles
auto iEmuHandle = (EmuHandle*)Handle;
ret = iEmuHandle->NtClose();
LOG_UNIMPLEMENTED(); // TODO : Base this on the Ob* functions
}
else
{
else {
// Handle everything else
if (CxbxDebugger::CanReport())
{
CxbxDebugger::ReportFileClosed(Handle);
}
if (const auto &nativeHandle = GetNativeHandle(Handle)) {
// This was a handle created by Ob
if (ntstatus_xt status = ObpClose(Handle) != X_STATUS_SUCCESS) {
RETURN(status);
}
RemoveXboxHandle(Handle);
Handle = *nativeHandle;
}
// Now also close the native handle
// Prevent exceptions when using invalid NTHandle
DWORD flags = 0;
if (GetHandleInformation(Handle, &flags) != 0) {
// This was a native handle, call NtDll::NtClose
ret = NtDll::NtClose(Handle);
// Delete duplicate threads created by our implementation of NtQueueApcThread()
if( GetHandleInformation( g_DuplicateHandles[Handle], &flags ) != 0 )
if (GetHandleInformation(g_DuplicateHandles[Handle], &flags) != 0)
{
EmuLog(LOG_LEVEL::DEBUG, "Closing duplicate handle..." );
EmuLog(LOG_LEVEL::DEBUG, "Closing duplicate handle...");
CloseHandle( g_DuplicateHandles[Handle] );
CloseHandle(g_DuplicateHandles[Handle]);
g_DuplicateHandles.erase(Handle);
}
}
@ -190,29 +202,19 @@ XBSYSAPI EXPORTNUM(188) xbox::ntstatus_xt NTAPI xbox::NtCreateDirectoryObject
LOG_FUNC_ARG(ObjectAttributes)
LOG_FUNC_END;
NativeObjectAttributes nativeObjectAttributes;
NTSTATUS ret = CxbxObjectAttributesToNT(
ObjectAttributes,
nativeObjectAttributes,
"NtCreateDirectoryObject");
POBJECT_DIRECTORY directoryObject;
ntstatus_xt status = ObCreateObject(&ObDirectoryObjectType, ObjectAttributes, sizeof(OBJECT_DIRECTORY), reinterpret_cast<PVOID *>(&directoryObject));
if (ret == X_STATUS_SUCCESS)
{
// TODO : Is this the correct ACCESS_MASK? :
const ACCESS_MASK DesiredAccess = DIRECTORY_CREATE_OBJECT;
if (X_NT_SUCCESS(status)) {
std::memset(directoryObject, 0, sizeof(OBJECT_DIRECTORY));
status = ObInsertObject(directoryObject, ObjectAttributes, 0, DirectoryHandle);
ret = NtDll::NtCreateDirectoryObject(
/*OUT*/DirectoryHandle,
DesiredAccess,
nativeObjectAttributes.NtObjAttrPtr);
if (X_NT_SUCCESS(status)) {
RegisterXboxHandle(*DirectoryHandle, NULL); // we don't need to create a native handle for a directory object
}
}
if (FAILED(ret))
EmuLog(LOG_LEVEL::WARNING, "NtCreateDirectoryObject Failed!");
else
EmuLog(LOG_LEVEL::DEBUG, "NtCreateDirectoryObject DirectoryHandle = 0x%.8X", *DirectoryHandle);
RETURN(ret);
RETURN(status);
}
// ******************************************************************
@ -707,50 +709,71 @@ XBSYSAPI EXPORTNUM(197) xbox::ntstatus_xt NTAPI xbox::NtDuplicateObject
LOG_FUNC_ARG(Options)
LOG_FUNC_END;
NTSTATUS result = X_STATUS_SUCCESS;
#ifdef CXBX_KERNEL_REWORK_ENABLED
PVOID Object;
result = ObReferenceObjectByHandle(SourceHandle, /*ObjectType=*/nullptr, &Object);
if (X_NT_SUCCESS(result)) {
if (ObpIsFlagSet(Options, DUPLICATE_CLOSE_SOURCE))
NtClose(SourceHandle);
result = ObOpenObjectByPointer(Object, OBJECT_TO_OBJECT_HEADER(Object)->Type, /*OUT*/TargetHandle);
ObfDereferenceObject(Object);
}
else
*TargetHandle = NULL;
#else
ntstatus_xt status;
if (EmuHandle::IsEmuHandle(SourceHandle)) {
auto iEmuHandle = (EmuHandle*)SourceHandle;
result = iEmuHandle->NtDuplicateObject(TargetHandle, Options);
status = iEmuHandle->NtDuplicateObject(TargetHandle, Options);
}
else
{
else {
// On the xbox, the duplicated handle always has the same access rigths of the source handle
const ACCESS_MASK DesiredAccess = 0;
const ULONG Attributes = 0;
Options |= (DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS);
dword_xt nativeOptions = (Options | DUPLICATE_SAME_ATTRIBUTES | DUPLICATE_SAME_ACCESS);
// redirect to Win2k/XP
result = NtDll::NtDuplicateObject(
/*SourceProcessHandle=*/g_CurrentProcessHandle,
SourceHandle,
/*TargetProcessHandle=*/g_CurrentProcessHandle,
TargetHandle,
DesiredAccess,
Attributes,
Options);
if (const auto &nativeHandle = GetNativeHandle(SourceHandle)) {
// This was a handle created by Ob
PVOID Object;
status = ObReferenceObjectByHandle(SourceHandle, /*ObjectType=*/nullptr, &Object);
if (X_NT_SUCCESS(status)) {
if (ObpIsFlagSet(Options, DUPLICATE_CLOSE_SOURCE)) {
NtClose(SourceHandle);
}
status = ObOpenObjectByPointer(Object, OBJECT_TO_OBJECT_HEADER(Object)->Type, /*OUT*/TargetHandle);
if (!X_NT_SUCCESS(status)) {
*TargetHandle = NULL;
RETURN(status);
}
ObfDereferenceObject(Object);
// If nativeHandle is NULL, then skip NtDll::NtDuplicateObject. This happens when SourceHandle is an xbox handle with a corresponding
// NULL native handle (e.g. directory objects hit this case)
if (*nativeHandle != NULL) {
::HANDLE dupHandle;
status = NtDll::NtDuplicateObject(
/*SourceProcessHandle=*/g_CurrentProcessHandle,
*nativeHandle,
/*TargetProcessHandle=*/g_CurrentProcessHandle,
&dupHandle,
DesiredAccess,
Attributes,
nativeOptions);
RegisterXboxHandle(*TargetHandle, dupHandle);
}
else {
RegisterXboxHandle(*TargetHandle, NULL);
}
}
}
else {
status = NtDll::NtDuplicateObject(
/*SourceProcessHandle=*/g_CurrentProcessHandle,
SourceHandle,
/*TargetProcessHandle=*/g_CurrentProcessHandle,
TargetHandle,
DesiredAccess,
Attributes,
nativeOptions);
}
if (!X_NT_SUCCESS(status)) {
CxbxrKrnlAbort("NtDll::NtDuplicateObject failed to duplicate the handle 0x%.8X!", SourceHandle);
}
}
if (result != X_STATUS_SUCCESS)
EmuLog(LOG_LEVEL::WARNING, "Object was not duplicated!");
#endif
RETURN(result);
RETURN(status);
}
// ******************************************************************
@ -894,7 +917,9 @@ XBSYSAPI EXPORTNUM(201) xbox::ntstatus_xt NTAPI xbox::NtOpenDirectoryObject
{
LOG_FORWARD("ObOpenObjectByName");
return ObOpenObjectByName(ObjectAttributes, &ObDirectoryObjectType, NULL, DirectoryHandle);
xbox::ntstatus_xt status = ObOpenObjectByName(ObjectAttributes, &ObDirectoryObjectType, NULL, DirectoryHandle);
RegisterXboxHandle(*DirectoryHandle, NULL); // we don't need to create a native handle for a directory object
return status;
}
// ******************************************************************

View File

@ -31,7 +31,6 @@
// TODO: What needs proper implement from Ob functions' side: (use CXBX_KERNEL_REWORK_ENABLED defined to evaluate what needs fixing)
// ObpDeleteSymbolicLink - internal function which would need a call to ObDereferenceObject with LinkTargetObject pass down.
// Plus it require proper IoCreateSymbolicLink implement as well, not emulated implement method.
// ObpDefaultObject - Find out how to initialize this. Then connect the dots from TODO message.
// OBJECT_DIRECTORY interface (root, dos, device, and named object, you can find global varables about 30 lines below)
// etc (add more above this line)
@ -42,6 +41,7 @@
#include "core\kernel\init\CxbxKrnl.h" // For CxbxrKrnlAbort
#include "EmuKrnl.h" // For OBJECT_TO_OBJECT_HEADER()
#include "core\kernel\support\EmuFile.h" // For EmuNtSymbolicLinkObject, NtStatusToString(), etc.
#include "core\kernel\support\NativeHandle.h"
#include <cassert>
#pragma warning(disable:4005) // Ignore redefined status values
@ -64,6 +64,7 @@ xbox::POBJECT_DIRECTORY ObpDosDevicesDirectoryObject;
xbox::POBJECT_DIRECTORY ObpWin32NamedObjectsDirectoryObject;
xbox::POBJECT_DIRECTORY ObpRootDirectoryObject;
xbox::POBJECT_DIRECTORY ObpIoDevicesDirectoryObject;
xbox::KEVENT ObpDefaultObject;
XBSYSAPI EXPORTNUM(245) xbox::OBJECT_HANDLE_TABLE xbox::ObpObjectHandleTable = {
@ -71,6 +72,9 @@ XBSYSAPI EXPORTNUM(245) xbox::OBJECT_HANDLE_TABLE xbox::ObpObjectHandleTable = {
xbox::PVOID ObpDosDevicesDriveLetterMap['Z' - 'A' + 1];
// This mutex is necessary to guard access to the global ob variables above
std::recursive_mutex g_ObMtx;
xbox::boolean_xt xbox::ObpCreatePermanentDirectoryObject(
IN POBJECT_STRING DirectoryName OPTIONAL,
OUT POBJECT_DIRECTORY *DirectoryObject
@ -82,23 +86,23 @@ xbox::boolean_xt xbox::ObpCreatePermanentDirectoryObject(
LOG_FUNC_END;
OBJECT_ATTRIBUTES ObjectAttributes;
XB_InitializeObjectAttributes(&ObjectAttributes, DirectoryName, OBJ_PERMANENT, NULL);
X_InitializeObjectAttributes(&ObjectAttributes, DirectoryName, OBJ_PERMANENT, NULL);
HANDLE Handle;
NTSTATUS status = NtCreateDirectoryObject(&Handle, &ObjectAttributes);
NTSTATUS result = NtCreateDirectoryObject(&Handle, &ObjectAttributes);
if (!X_NT_SUCCESS(status)) {
if (!X_NT_SUCCESS(result)) {
RETURN(FALSE);
}
status = ObReferenceObjectByHandle(Handle, &ObDirectoryObjectType, (PVOID *)DirectoryObject);
result = ObReferenceObjectByHandle(Handle, &ObDirectoryObjectType, (PVOID *)DirectoryObject);
if (!X_NT_SUCCESS(status)) {
if (!X_NT_SUCCESS(result)) {
RETURN(FALSE);
}
NtClose(Handle);
RETURN(TRUE);
}
@ -111,10 +115,12 @@ xbox::ntstatus_xt xbox::ObpReferenceObjectByName(
OUT PVOID *ReturnedObject
)
{
NTSTATUS status;
NTSTATUS result;
*ReturnedObject = NULL;
KIRQL OldIrql = KeRaiseIrqlToDpcLevel();
// Raising the irql to dpc level doesn't prevent thread switching, so acquire a lock
std::unique_lock<std::recursive_mutex> lck(g_ObMtx);
OBJECT_STRING RemainingName;
if (ObjectName != NULL) {
@ -135,14 +141,14 @@ xbox::ntstatus_xt xbox::ObpReferenceObjectByName(
FoundObject = (POBJECT_DIRECTORY)ObpGetObjectHandleContents(RootDirectoryHandle);
if (FoundObject == NULL) {
status = X_STATUS_INVALID_HANDLE;
result = X_STATUS_INVALID_HANDLE;
goto CleanupAndExit;
}
}
if ((RemainingName.Length != 0) &&
(RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR)) {
status = X_STATUS_OBJECT_NAME_INVALID;
result = X_STATUS_OBJECT_NAME_INVALID;
goto CleanupAndExit;
}
@ -153,7 +159,7 @@ xbox::ntstatus_xt xbox::ObpReferenceObjectByName(
if ((RemainingName.Length == 0) ||
(RemainingName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR)) {
status = X_STATUS_OBJECT_NAME_INVALID;
result = X_STATUS_OBJECT_NAME_INVALID;
goto CleanupAndExit;
}
@ -171,7 +177,7 @@ xbox::ntstatus_xt xbox::ObpReferenceObjectByName(
if (RemainingName.Length != 0) {
if (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) {
status = X_STATUS_OBJECT_NAME_INVALID;
result = X_STATUS_OBJECT_NAME_INVALID;
goto CleanupAndExit;
}
} else {
@ -182,7 +188,7 @@ xbox::ntstatus_xt xbox::ObpReferenceObjectByName(
if (!ObpLookupElementNameInDirectory(Directory, &ElementName,
ResolveSymbolicLink, &FoundObject)) {
status = (RemainingName.Length != 0) ? STATUS_OBJECT_PATH_NOT_FOUND : X_STATUS_OBJECT_NAME_NOT_FOUND;
result = (RemainingName.Length != 0) ? STATUS_OBJECT_PATH_NOT_FOUND : X_STATUS_OBJECT_NAME_NOT_FOUND;
goto CleanupAndExit;
}
@ -195,19 +201,19 @@ OpenRootDirectory:
}
if ((ObjectType != NULL) && (ObjectType != ObjectHeader->Type)) {
status = STATUS_OBJECT_TYPE_MISMATCH;
result = STATUS_OBJECT_TYPE_MISMATCH;
goto CleanupAndExit;
}
ObjectHeader->PointerCount++;
*ReturnedObject = FoundObject;
status = X_STATUS_SUCCESS;
result = X_STATUS_SUCCESS;
goto CleanupAndExit;
}
if (ObjectHeader->Type != &ObDirectoryObjectType) {
if (ObjectHeader->Type->ParseProcedure == NULL) {
status = STATUS_OBJECT_PATH_NOT_FOUND;
result = STATUS_OBJECT_PATH_NOT_FOUND;
goto CleanupAndExit;
}
@ -222,25 +228,25 @@ InvokeParseProcedure:
}
PVOID ParsedObject = NULL;
status = ObjectHeader->Type->ParseProcedure(FoundObject, ObjectType, Attributes, ObjectName, &RemainingName, ParseContext, &ParsedObject);
result = ObjectHeader->Type->ParseProcedure(FoundObject, ObjectType, Attributes, ObjectName, &RemainingName, ParseContext, &ParsedObject);
ObfDereferenceObject(FoundObject);
if (X_NT_SUCCESS(status)) {
if (X_NT_SUCCESS(result)) {
if ((ObjectType == NULL) || (ObjectType == OBJECT_TO_OBJECT_HEADER(ParsedObject)->Type)) {
*ReturnedObject = ParsedObject;
status = X_STATUS_SUCCESS;
result = X_STATUS_SUCCESS;
} else {
ObfDereferenceObject(ParsedObject);
status = STATUS_OBJECT_TYPE_MISMATCH;
result = STATUS_OBJECT_TYPE_MISMATCH;
}
}
return status;
return result;
}
}
CleanupAndExit:
KfLowerIrql(OldIrql);
return status;
return result;
}
xbox::boolean_xt xbox::ObInitSystem()
@ -250,7 +256,11 @@ xbox::boolean_xt xbox::ObInitSystem()
ObpObjectHandleTable.NextHandleNeedingPool = 0;
ObpObjectHandleTable.RootTable = NULL;
RtlZeroMemory(ObpDosDevicesDriveLetterMap, sizeof(ObpDosDevicesDriveLetterMap));
std::memset(ObpDosDevicesDriveLetterMap, 0, sizeof(ObpDosDevicesDriveLetterMap));
ObpDefaultObject.Header.Absolute = FALSE;
ObpDefaultObject.Header.Inserted = FALSE;
KeInitializeEvent(&ObpDefaultObject, SynchronizationEvent, TRUE);
if (!ObpCreatePermanentDirectoryObject(NULL, &ObpRootDirectoryObject)) {
return FALSE;
@ -389,17 +399,20 @@ xbox::void_xt xbox::ObDissectName(OBJECT_STRING Path, POBJECT_STRING FirstName,
return;
}
static inline xbox::HANDLE ObpGetHandleByObjectThenDereferenceInline(const xbox::PVOID Object, xbox::ntstatus_xt& result) {
xbox::HANDLE newHandle = nullptr;
static inline xbox::HANDLE ObpGetHandleByObjectThenDereferenceInline(const xbox::PVOID Object, xbox::ntstatus_xt& result)
{
xbox::HANDLE newHandle = NULL;
if (X_NT_SUCCESS(result)) {
xbox::KIRQL oldIrql = xbox::KeRaiseIrqlToDpcLevel();
// Raising the irql to dpc level doesn't prevent thread switching, so acquire a lock
std::unique_lock<std::recursive_mutex> lck(g_ObMtx);
newHandle = xbox::ObpCreateObjectHandle(Object);
xbox::KfLowerIrql(oldIrql);
if (newHandle == nullptr) {
if (newHandle == NULL) {
xbox::ObfDereferenceObject(Object);
result = X_STATUS_INSUFFICIENT_RESOURCES;
}
@ -498,7 +511,7 @@ XBSYSAPI EXPORTNUM(240) xbox::OBJECT_TYPE xbox::ObDirectoryObjectType =
NULL,
NULL,
NULL,
NULL, // TODO : &xbox::ObpDefaultObject,
&ObpDefaultObject,
'eriD' // = first four characters of "Directory" in reverse
};
@ -552,6 +565,8 @@ xbox::PVOID xbox::ObpGetObjectHandleReference(HANDLE Handle)
PVOID *HandleContents;
Handle = ObpMaskOffApplicationBits(Handle);
KIRQL OldIrql = KeRaiseIrqlToDpcLevel();
// Raising the irql to dpc level doesn't prevent thread switching, so acquire a lock
std::unique_lock<std::recursive_mutex> lck(g_ObMtx);
if (HandleToUlong(Handle) < HandleToUlong(ObpObjectHandleTable.NextHandleNeedingPool)) {
HandleContents = ObpGetHandleContentsPointer(Handle);
@ -613,6 +628,116 @@ xbox::boolean_xt xbox::ObpLookupElementNameInDirectory(
return FALSE;
}
xbox::PVOID xbox::ObpDestroyObjectHandle(
IN HANDLE Handle
)
{
Handle = ObpMaskOffApplicationBits(Handle);
if (HandleToUlong(Handle) < HandleToUlong(ObpObjectHandleTable.NextHandleNeedingPool)) {
PVOID *HandleContents = ObpGetHandleContentsPointer(Handle);
PVOID Object = *HandleContents;
if (Object != NULL && !ObpIsFreeHandleLink(Object)) {
*HandleContents = (PVOID)ObpObjectHandleTable.FirstFreeTableEntry;
ObpObjectHandleTable.FirstFreeTableEntry = ObpEncodeFreeHandleLink(Handle);
ObpObjectHandleTable.HandleCount--;
return Object;
}
}
return NULL;
}
xbox::void_xt xbox::ObpDetachNamedObject(
IN PVOID Object,
IN KIRQL OldIrql
)
{
POBJECT_HEADER_NAME_INFO ObjectHeaderNameInfo = OBJECT_TO_OBJECT_HEADER_NAME_INFO(Object);
POBJECT_DIRECTORY Directory = ObjectHeaderNameInfo->Directory;
if ((Directory == ObpDosDevicesDirectoryObject) &&
(ObjectHeaderNameInfo->Name.Length == sizeof(char_xt) * 2) &&
(ObjectHeaderNameInfo->Name.Buffer[1] == (char_xt)':')) {
char_xt DriveLetter = ObjectHeaderNameInfo->Name.Buffer[0];
if (DriveLetter >= 'a' && DriveLetter <= 'z') {
ObpDosDevicesDriveLetterMap[DriveLetter - 'a'] = NULL;
}
else if (DriveLetter >= 'A' && DriveLetter <= 'Z') {
ObpDosDevicesDriveLetterMap[DriveLetter - 'A'] = NULL;
}
}
ulong_xt HashIndex = ObpComputeHashIndex(&ObjectHeaderNameInfo->Name);
POBJECT_HEADER_NAME_INFO LastObjectHeaderNameInfo = NULL;
POBJECT_HEADER_NAME_INFO CurrentObjectHeaderNameInfo = Directory->HashBuckets[HashIndex];
while (CurrentObjectHeaderNameInfo != ObjectHeaderNameInfo) {
LastObjectHeaderNameInfo = CurrentObjectHeaderNameInfo;
CurrentObjectHeaderNameInfo = CurrentObjectHeaderNameInfo->ChainLink;
}
if (LastObjectHeaderNameInfo == NULL) {
Directory->HashBuckets[HashIndex] = CurrentObjectHeaderNameInfo->ChainLink;
}
else {
LastObjectHeaderNameInfo->ChainLink = CurrentObjectHeaderNameInfo->ChainLink;
}
ObjectHeaderNameInfo->ChainLink = NULL;
ObjectHeaderNameInfo->Directory = NULL;
KfLowerIrql(OldIrql);
g_ObMtx.unlock();
ObfDereferenceObject(Directory);
ObfDereferenceObject(Object);
}
xbox::ntstatus_xt xbox::ObpClose(
IN HANDLE Handle
)
{
KIRQL OldIrql = KeRaiseIrqlToDpcLevel();
// Raising the irql to dpc level doesn't prevent thread switching, so acquire a lock
std::unique_lock<std::recursive_mutex> lck(g_ObMtx);
PVOID Object = ObpDestroyObjectHandle(Handle);
if (Object != NULL) {
POBJECT_HEADER ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
ulong_xt HandleCount = ObjectHeader->HandleCount;
ObjectHeader->HandleCount--;
if (ObjectHeader->Type->CloseProcedure != NULL) {
KfLowerIrql(OldIrql);
lck.unlock();
ObjectHeader->Type->CloseProcedure(Object, HandleCount);
OldIrql = KeRaiseIrqlToDpcLevel();
lck.lock();
}
if ((ObjectHeader->HandleCount == 0) &&
ObpIsFlagSet(ObjectHeader->Flags, OB_FLAG_ATTACHED_OBJECT) &&
ObpIsFlagClear(ObjectHeader->Flags, OB_FLAG_PERMANENT_OBJECT)) {
ObpDetachNamedObject(Object, OldIrql);
}
else {
KfLowerIrql(OldIrql);
lck.unlock();
}
ObfDereferenceObject(Object);
return X_STATUS_SUCCESS;
}
else {
KfLowerIrql(OldIrql);
return X_STATUS_INVALID_HANDLE;
}
}
// ******************************************************************
// * 0x00F1 - ObInsertObject()
// ******************************************************************
@ -631,10 +756,12 @@ XBSYSAPI EXPORTNUM(241) xbox::ntstatus_xt NTAPI xbox::ObInsertObject
LOG_FUNC_ARG_OUT(ReturnedHandle)
LOG_FUNC_END;
NTSTATUS status;
NTSTATUS result;
POBJECT_DIRECTORY Directory;
KIRQL OldIrql = KeRaiseIrqlToDpcLevel();
// Raising the irql to dpc level doesn't prevent thread switching, so acquire a lock
std::unique_lock<std::recursive_mutex> lck(g_ObMtx);
HANDLE Handle = NULL;
PVOID InsertObject = Object;
@ -644,7 +771,7 @@ XBSYSAPI EXPORTNUM(241) xbox::ntstatus_xt NTAPI xbox::ObInsertObject
if (RootDirectoryHandle != NULL) {
if (RemainingName.Buffer[0] == OBJ_NAME_PATH_SEPARATOR) {
status = STATUS_OBJECT_NAME_INVALID;
result = STATUS_OBJECT_NAME_INVALID;
goto CleanupAndExit;
}
@ -656,18 +783,18 @@ XBSYSAPI EXPORTNUM(241) xbox::ntstatus_xt NTAPI xbox::ObInsertObject
Directory = (POBJECT_DIRECTORY)ObpGetObjectHandleContents(RootDirectoryHandle);
if (Directory == NULL) {
status = STATUS_INVALID_HANDLE;
result = STATUS_INVALID_HANDLE;
goto CleanupAndExit;
}
if (OBJECT_TO_OBJECT_HEADER(Directory)->Type != &ObDirectoryObjectType) {
status = STATUS_OBJECT_TYPE_MISMATCH;
result = STATUS_OBJECT_TYPE_MISMATCH;
goto CleanupAndExit;
}
}
} else {
if (RemainingName.Buffer[0] != OBJ_NAME_PATH_SEPARATOR) {
status = STATUS_OBJECT_NAME_INVALID;
result = STATUS_OBJECT_NAME_INVALID;
goto CleanupAndExit;
}
@ -686,25 +813,25 @@ XBSYSAPI EXPORTNUM(241) xbox::ntstatus_xt NTAPI xbox::ObInsertObject
Directory = NULL;
break;
} else {
status = STATUS_OBJECT_TYPE_MISMATCH;
result = STATUS_OBJECT_TYPE_MISMATCH;
goto CleanupAndExit;
}
} else {
status = X_STATUS_OBJECT_NAME_COLLISION;
result = X_STATUS_OBJECT_NAME_COLLISION;
goto CleanupAndExit;
}
}
if (OBJECT_TO_OBJECT_HEADER(FoundObject)->Type !=
&ObDirectoryObjectType) {
status = STATUS_OBJECT_PATH_NOT_FOUND;
result = STATUS_OBJECT_PATH_NOT_FOUND;
goto CleanupAndExit;
}
Directory = (POBJECT_DIRECTORY)FoundObject;
} else {
if (RemainingName.Length != 0) {
status = STATUS_OBJECT_PATH_NOT_FOUND;
result = STATUS_OBJECT_PATH_NOT_FOUND;
goto CleanupAndExit;
}
@ -718,7 +845,7 @@ XBSYSAPI EXPORTNUM(241) xbox::ntstatus_xt NTAPI xbox::ObInsertObject
Handle = ObpCreateObjectHandle(InsertObject);
if (Handle == NULL) {
status = X_STATUS_INSUFFICIENT_RESOURCES;
result = X_STATUS_INSUFFICIENT_RESOURCES;
goto CleanupAndExit;
}
@ -758,14 +885,14 @@ XBSYSAPI EXPORTNUM(241) xbox::ntstatus_xt NTAPI xbox::ObInsertObject
ObjectHeader->Flags |= OB_FLAG_PERMANENT_OBJECT;
}
status = (Object == InsertObject) ? X_STATUS_SUCCESS : STATUS_OBJECT_NAME_EXISTS;
result = (Object == InsertObject) ? X_STATUS_SUCCESS : STATUS_OBJECT_NAME_EXISTS;
CleanupAndExit:
KfLowerIrql(OldIrql);
ObfDereferenceObject(Object);
*ReturnedHandle = Handle;
RETURN(status);
RETURN(result);
}
// ******************************************************************
@ -800,21 +927,20 @@ XBSYSAPI EXPORTNUM(243) xbox::ntstatus_xt NTAPI xbox::ObOpenObjectByName
LOG_FUNC_ARG_OUT(Handle)
LOG_FUNC_END;
#ifdef CXBX_KERNEL_REWORK_ENABLED
PVOID Object;
ntstatus_xt result = ObpReferenceObjectByName(ObjectAttributes->RootDirectory, ObjectAttributes->ObjectName,
ObjectAttributes->Attributes, ObjectType, ParseContext, &Object);
ntstatus_xt result = X_STATUS_OBJECT_PATH_NOT_FOUND;
*Handle = ObpGetHandleByObjectThenDereferenceInline(Object, result);
#else
ntstatus_xt result = STATUS_OBJECT_PATH_NOT_FOUND;
// Use this place for any interface implementation since
// it is origin of creating new handle. In other case, "ObpCreateObjectHandle" handle it directly.
// But global variables with POBJECT_DIRECTORY are not initialized properly.
// Along with IoCreateSymbolicLink for ObSymbolicLinkObjectType linkage in order to work.
if (ObjectType == &ObSymbolicLinkObjectType) {
if (const auto &nativeHandle = GetNativeHandle(Handle)) {
// This was a handle created by Ob
PVOID Object;
result = ObpReferenceObjectByName(ObjectAttributes->RootDirectory, ObjectAttributes->ObjectName,
ObjectAttributes->Attributes, ObjectType, ParseContext, &Object);
*Handle = ObpGetHandleByObjectThenDereferenceInline(Object, result);
}
else if (ObjectType == &ObSymbolicLinkObjectType) {
// Use this place for any interface implementation since
// it is origin of creating new handle. In other case, "ObpCreateObjectHandle" handle it directly.
// But global variables with POBJECT_DIRECTORY are not initialized properly.
// Along with IoCreateSymbolicLink for ObSymbolicLinkObjectType linkage in order to work.
EmuNtSymbolicLinkObject* symbolicLinkObject =
FindNtSymbolicLinkObjectByName(PSTRING_to_string(ObjectAttributes->ObjectName));
@ -837,7 +963,6 @@ XBSYSAPI EXPORTNUM(243) xbox::ntstatus_xt NTAPI xbox::ObOpenObjectByName
assert(false);
result = X_STATUS_SUCCESS;
}
#endif
RETURN(result);
}
@ -858,17 +983,9 @@ XBSYSAPI EXPORTNUM(244) xbox::ntstatus_xt NTAPI xbox::ObOpenObjectByPointer
LOG_FUNC_ARG_OUT(Handle)
LOG_FUNC_END;
#ifdef CXBX_KERNEL_REWORK_ENABLED
ntstatus_xt result = ObReferenceObjectByPointer(Object, ObjectType);
*Handle = ObpGetHandleByObjectThenDereferenceInline(Object, result);
RETURN(result);
#else
LOG_UNIMPLEMENTED();
assert(false);
RETURN(X_STATUS_SUCCESS);
#endif
}
// ******************************************************************
@ -893,7 +1010,7 @@ XBSYSAPI EXPORTNUM(246) xbox::ntstatus_xt NTAPI xbox::ObReferenceObjectByHandle
LOG_FUNC_ARG_OUT(ReturnedObject)
LOG_FUNC_END;
NTSTATUS status;
NTSTATUS result;
PVOID Object;
POBJECT_HEADER ObjectHeader;
@ -905,7 +1022,7 @@ XBSYSAPI EXPORTNUM(246) xbox::ntstatus_xt NTAPI xbox::ObReferenceObjectByHandle
*ReturnedObject = Object;
return X_STATUS_SUCCESS;
} else {
status = STATUS_OBJECT_TYPE_MISMATCH;
result = STATUS_OBJECT_TYPE_MISMATCH;
}
} else {
Object = ObpGetObjectHandleReference(Handle);
@ -918,7 +1035,7 @@ XBSYSAPI EXPORTNUM(246) xbox::ntstatus_xt NTAPI xbox::ObReferenceObjectByHandle
return X_STATUS_SUCCESS;
} else {
ObfDereferenceObject(Object);
status = STATUS_OBJECT_TYPE_MISMATCH;
result = STATUS_OBJECT_TYPE_MISMATCH;
}
} else {
// HACK: Since we forward to NtDll::NtCreateEvent, this *might* be a Windows handle instead of our own
@ -931,13 +1048,13 @@ XBSYSAPI EXPORTNUM(246) xbox::ntstatus_xt NTAPI xbox::ObReferenceObjectByHandle
return X_STATUS_SUCCESS;
}
status = STATUS_INVALID_HANDLE;
result = STATUS_INVALID_HANDLE;
}
}
*ReturnedObject = NULL;
RETURN(status);
RETURN(result);
}
// ******************************************************************

View File

@ -1491,8 +1491,7 @@ static void CxbxrKrnlInitHacks()
InitXboxThread();
g_AffinityPolicy->SetAffinityXbox();
if (!xbox::ObInitSystem()) {
// TODO: Replace EmuLogEx to CxbxrKrnlAbortEx when ObInitSystem's calls are properly implement.
EmuLogEx(LOG_PREFIX_INIT, LOG_LEVEL::WARNING, "Unable to intialize xbox::ObInitSystem.");
CxbxrKrnlAbortEx(LOG_PREFIX_INIT, "Unable to intialize ObInitSystem.");
}
xbox::KiInitSystem();

View File

@ -698,7 +698,7 @@ NTSTATUS CxbxConvertFilePath(
// Convert the relative path to unicode
RelativeHostPath = string_to_wstring(RelativePath);
return X_STATUS_SUCCESS;
return STATUS_SUCCESS;
}
NTSTATUS CxbxObjectAttributesToNT(
@ -711,7 +711,7 @@ NTSTATUS CxbxObjectAttributesToNT(
{
// When the pointer is nil, make sure we pass nil to Windows too :
nativeObjectAttributes.NtObjAttrPtr = nullptr;
return X_STATUS_SUCCESS;
return STATUS_SUCCESS;
}
// Pick up the ObjectName, and let's see what to make of it :
@ -743,7 +743,7 @@ NTSTATUS CxbxObjectAttributesToNT(
// ObjectAttributes are given, so make sure the pointer we're going to pass to Windows is assigned :
nativeObjectAttributes.NtObjAttrPtr = &nativeObjectAttributes.NtObjAttr;
return X_STATUS_SUCCESS;
return STATUS_SUCCESS;
}
int CxbxDeviceIndexByDevicePath(const char *XboxDevicePath)

View File

@ -293,18 +293,6 @@ typedef struct _RTL_CRITICAL_SECTION
}
RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION;
// ******************************************************************
// * Valid values for the Attributes field
// ******************************************************************
#define OBJ_INHERIT 0x00000002L
#define OBJ_PERMANENT 0x00000010L
#define OBJ_EXCLUSIVE 0x00000020L
#define OBJ_CASE_INSENSITIVE 0x00000040L
#define OBJ_OPENIF 0x00000080L
#define OBJ_OPENLINK 0x00000100L
#define OBJ_KERNEL_HANDLE 0x00000200L
#define OBJ_VALID_ATTRIBUTES 0x000003F2L
// ******************************************************************
// * UNICODE_STRING
// ******************************************************************

View File

@ -0,0 +1,64 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2021 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#include <core\kernel\exports\xboxkrnl.h>
#include <unordered_map>
#include <shared_mutex>
#include "Windows.h"
#include "assert.h"
#include "NativeHandle.h"
std::unordered_map<xbox::HANDLE, HANDLE> g_RegisteredHandles;
std::shared_mutex g_MapMtx;
void RegisterXboxHandle(xbox::HANDLE xhandle, HANDLE nhandle)
{
std::unique_lock<std::shared_mutex> lck(g_MapMtx);
[[maybe_unused]] const auto &ret = g_RegisteredHandles.emplace(xhandle, nhandle);
// Even when duplicating xbox handles with NtDuplicateObject, the duplicate will still be different then the source handle
assert(ret.second == true);
}
void RemoveXboxHandle(xbox::HANDLE xhandle)
{
std::unique_lock<std::shared_mutex> lck(g_MapMtx);
[[maybe_unused]] auto ret = g_RegisteredHandles.erase(xhandle);
assert(ret == 1);
}
std::optional<HANDLE> GetNativeHandle(xbox::HANDLE xhandle)
{
std::shared_lock<std::shared_mutex> lck(g_MapMtx);
auto &it = g_RegisteredHandles.find(xhandle);
if (it == g_RegisteredHandles.end()) {
return std::nullopt;
}
else {
return it->second;
}
}

View File

@ -0,0 +1,34 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
// ******************************************************************
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2021 ergo720
// *
// * All rights reserved
// *
// ******************************************************************
#pragma once
#include <optional>
void RegisterXboxHandle(xbox::HANDLE xhandle, HANDLE nhandle);
void RemoveXboxHandle(xbox::HANDLE xhandle);
std::optional<HANDLE> GetNativeHandle(xbox::HANDLE xhandle);