Implemented Symbolic Link kernel API using code from Dxbx

Dxbx contains a LOT of improvements that did not make it back into Cxbx
This commit is contained in:
Luke Usher 2016-08-18 20:40:36 +01:00
parent 875c64148c
commit 1578146bfe
9 changed files with 858 additions and 490 deletions

View File

@ -46,7 +46,11 @@ XBSYSAPI EXPORTNUM(187) NTSTATUS NTAPI NtClose
IN HANDLE Handle
);
XBSYSAPI VOID *NtCreateDirectoryObject;
XBSYSAPI EXPORTNUM(188) NTSTATUS NTAPI NtCreateDirectoryObject
(
OUT PHANDLE DirectoryHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
// ******************************************************************
// * NtCreateEvent
@ -59,6 +63,8 @@ XBSYSAPI EXPORTNUM(189) NTSTATUS NTAPI NtCreateEvent
IN BOOLEAN InitialState
);
// ******************************************************************
// * NtCreateFile
// ******************************************************************

View File

@ -43,6 +43,7 @@ namespace xboxkrnl
#include "CxbxKrnl.h"
#include "Emu.h"
#include "EmuFile.h"
#include "EmuFS.h"
#include "EmuShared.h"
#include "HLEIntercept.h"
@ -68,6 +69,9 @@ extern CXBXKRNL_API HWND CxbxKrnl_hEmuParent = NULL;
/*! thread handles */
static HANDLE g_hThreads[MAXIMUM_XBOX_THREADS] = { 0 };
std::string CxbxBasePath;
HANDLE CxbxBasePathHandle;
static uint32 funcAddr[]=
{
0x001396D1, // -> 0x00139709 (Size : 56 bytes)
@ -159,6 +163,53 @@ extern "C" CXBXKRNL_API bool CxbxKrnlVerifyVersion(const char *szVersion)
return true;
}
void CxbxLaunchXbe(void(*Entry)())
{
//
// Xbe entry point
//
__try
{
EmuSwapFS(); // XBox FS
// _USE_XGMATH Disabled in mesh :[
// halo : dword_0_2E2D18
// halo : 1744F0 (bink)
//_asm int 3;
/*
for(int v=0;v<sizeof(funcAddr)/sizeof(uint32);v++)
{
bool bExclude = false;
for(int r=0;r<sizeof(funcExclude)/sizeof(uint32);r++)
{
if(funcAddr[v] == funcExclude[r])
{
bExclude = true;
break;
}
}
if(!bExclude)
{
*(uint08*)(funcAddr[v]) = 0xCC;
}
}
//*/
Entry();
EmuSwapFS(); // Win2k/XP FS
}
__except (EmuException(GetExceptionInformation()))
{
printf("Emu: WARNING!! Problem with ExceptionFilter\n");
}
}
extern "C" CXBXKRNL_API void CxbxKrnlInit
(
HWND hwndParent,
@ -180,6 +231,10 @@ extern "C" CXBXKRNL_API void CxbxKrnlInit
// for unicode conversions
setlocale(LC_ALL, "English");
#ifdef _DEBUG
MessageBoxA(NULL, "Attach a Debugger", "DEBUG", 0);
#endif
// debug console allocation (if configured)
if(DbgMode == DM_CONSOLE)
{
@ -264,134 +319,66 @@ extern "C" CXBXKRNL_API void CxbxKrnlInit
memcpy((void*)pXbeHeader->dwCertificateAddr, &((uint08*)pXbeHeader)[pXbeHeader->dwCertificateAddr - 0x00010000], sizeof(Xbe::Certificate));
}
//
// initialize current directory
//
// Initialize devices :
{
char szBuffer[260];
char szBuffer[260];
SHGetSpecialFolderPath(NULL, szBuffer, CSIDL_APPDATA, TRUE);
strcat(szBuffer, "\\Cxbx\\");
g_EmuShared->GetXbePath(szBuffer);
std::string basePath(szBuffer);
CxbxBasePath = basePath + "\\EmuDisk\\";
if(szBuffer && *szBuffer)
SetCurrentDirectory(szBuffer);
else
GetCurrentDirectory(260, szBuffer);
memset(szBuffer, 0, 260);
GetCurrentDirectory(260, szBuffer);
if (szBuffer[strlen(szBuffer)] != '\\')
szBuffer[strlen(szBuffer)+1] = '\\';
g_strCurDrive = _strdup(szBuffer);
std::string xbePath(szBuffer);
CxbxBasePathHandle = CreateFile(CxbxBasePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
g_hCurDir = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
memset(szBuffer, 0, 260);
sprintf(szBuffer, "%08X", ((Xbe::Certificate*)pXbeHeader->dwCertificateAddr)->dwTitleId);
if(g_hCurDir == INVALID_HANDLE_VALUE)
CxbxKrnlCleanup("Could not map D:\\\n");
std::string titleId(szBuffer);
DbgPrintf("EmuMain (0x%X): CurDir := %s\n", GetCurrentThreadId(), szBuffer);
}
// Games may assume they are running from CdRom :
CxbxRegisterDeviceNativePath(DeviceCdrom0, xbePath);
//
// initialize EmuDisk
//
// Partition 0 contains configuration data, and is accessed as a native file, instead as a folder :
CxbxRegisterDeviceNativePath(DeviceHarddisk0Partition0, CxbxBasePath + "Partition0_ConfigData.bin", true); /*IsFile=*/
// The first two partitions are for Data and Shell files, respectively :
CxbxRegisterDeviceNativePath(DeviceHarddisk0Partition1, CxbxBasePath + "Partition1");
CxbxRegisterDeviceNativePath(DeviceHarddisk0Partition2, CxbxBasePath + "Partition2");
// The following partitions are for caching purposes - for now we allocate up to 7 (as xbmp needs that many) :
CxbxRegisterDeviceNativePath(DeviceHarddisk0Partition3, CxbxBasePath + "Partition3");
CxbxRegisterDeviceNativePath(DeviceHarddisk0Partition4, CxbxBasePath + "Partition4");
CxbxRegisterDeviceNativePath(DeviceHarddisk0Partition5, CxbxBasePath + "Partition5");
CxbxRegisterDeviceNativePath(DeviceHarddisk0Partition6, CxbxBasePath + "Partition6");
CxbxRegisterDeviceNativePath(DeviceHarddisk0Partition7, CxbxBasePath + "Partition7");
{
char szBuffer[260];
DbgPrintf("EmuMain : Creating default symbolic links.\n");
SHGetSpecialFolderPath(NULL, szBuffer, CSIDL_APPDATA, TRUE);
// Create default symbolic links :
{
// Arrange that the Xbe path can reside outside the partitions, and put it to g_hCurDir :
CxbxCreateSymbolicLink(DriveC, (xbePath));
g_hCurDir = ((EmuNtSymbolicLinkObject*)FindNtSymbolicLinkObjectByVolumeLetter(CxbxDefaultXbeVolumeLetter))->RootDirectoryHandle;
// TODO -oDxbx: Make sure this path is set in g_EmuXbePath (xboxkrnl_XeImageFileName) too.
/*
CxbxCreateSymbolicLink(DriveD, DeviceCdrom0); // CdRom goes to D:
CxbxCreateSymbolicLink(DriveE, DeviceHarddisk0Partition1); // Partition1 goes to E: (Data files, savegames, etc.)
CxbxCreateSymbolicLink(DriveF, DeviceHarddisk0Partition2); // Partition2 goes to F: (Shell files, dashboard, etc.)
CxbxCreateSymbolicLink(DriveT, DeviceHarddisk0Partition1 + "\\TDATA\\" + titleId + "\\"); // Partition1\Title data goes to T:
CxbxCreateSymbolicLink(DriveU, DeviceHarddisk0Partition1 + "\\UDATA\\" + titleId + "\\"); // Partition1\User data goes to U:
CxbxCreateSymbolicLink(DriveX, DeviceHarddisk0Partition3); // Partition3 goes to X:
CxbxCreateSymbolicLink(DriveY, DeviceHarddisk0Partition4); // Partition4 goes to Y: */
strcat(szBuffer, "\\Cxbx\\");
CreateDirectory(szBuffer, NULL);
sint32 spot = -1;
for(int v=0;v<260;v++)
{
if(szBuffer[v] == '\\') { spot = v; }
else if(szBuffer[v] == '\0') { break; }
}
if(spot != -1) { szBuffer[spot] = '\0'; }
Xbe::Certificate *pCertificate = (Xbe::Certificate*)pXbeHeader->dwCertificateAddr;
//
// create EmuDisk directory
//
strcpy(&szBuffer[spot], "\\EmuDisk");
CreateDirectory(szBuffer, NULL);
//
// create T:\ directory
//
{
strcpy(&szBuffer[spot], "\\EmuDisk\\T");
CreateDirectory(szBuffer, NULL);
sprintf(&szBuffer[spot+10], "\\%08x", pCertificate->dwTitleId);
CreateDirectory(szBuffer, NULL);
g_strTDrive = _strdup(szBuffer);
g_hTDrive = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if(g_hTDrive == INVALID_HANDLE_VALUE)
CxbxKrnlCleanup("Could not map T:\\\n");
DbgPrintf("EmuMain (0x%X): T Data := %s\n", GetCurrentThreadId(), szBuffer);
}
//
// create U:\ directory
//
{
strcpy(&szBuffer[spot], "\\EmuDisk\\U");
CreateDirectory(szBuffer, NULL);
sprintf(&szBuffer[spot+10], "\\%08x", pCertificate->dwTitleId);
CreateDirectory(szBuffer, NULL);
g_strUDrive = _strdup(szBuffer);
g_hUDrive = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if(g_hUDrive == INVALID_HANDLE_VALUE)
CxbxKrnlCleanup("Could not map U:\\\n");
DbgPrintf("EmuMain (0x%X): U Data := %s\n", GetCurrentThreadId(), szBuffer);
}
//
// create Z:\ directory
//
{
strcpy(&szBuffer[spot], "\\EmuDisk\\Z");
CreateDirectory(szBuffer, NULL);
//* is it necessary to make this directory title unique?
sprintf(&szBuffer[spot+10], "\\%08x", pCertificate->dwTitleId);
CreateDirectory(szBuffer, NULL);
//*/
g_strZDrive = _strdup(szBuffer);
g_hZDrive = CreateFile(szBuffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if(g_hUDrive == INVALID_HANDLE_VALUE)
CxbxKrnlCleanup("Could not map Z:\\\n");
DbgPrintf("EmuMain (0x%X): Z Data := %s\n", GetCurrentThreadId(), szBuffer);
}
}
// Mount the Utility drive (Z:) conditionally :
if (CxbxKrnl_XbeHeader->dwInitFlags.bMountUtilityDrive)
CxbxMountUtilityDrive(CxbxKrnl_XbeHeader->dwInitFlags.bFormatUtilityDrive);/*fFormatClean=*/
}
//
// duplicate handle in order to retain Suspend/Resume thread rights from a remote thread
@ -429,47 +416,7 @@ extern "C" CXBXKRNL_API void CxbxKrnlInit
DbgPrintf("EmuMain (0x%X): Initial thread starting.\n", GetCurrentThreadId());
//
// Xbe entry point
//
__try
{
EmuSwapFS(); // XBox FS
// _USE_XGMATH Disabled in mesh :[
// halo : dword_0_2E2D18
// halo : 1744F0 (bink)
//_asm int 3;
/*
for(int v=0;v<sizeof(funcAddr)/sizeof(uint32);v++)
{
bool bExclude = false;
for(int r=0;r<sizeof(funcExclude)/sizeof(uint32);r++)
{
if(funcAddr[v] == funcExclude[r])
{
bExclude = true;
break;
}
}
if(!bExclude)
{
*(uint08*)(funcAddr[v]) = 0xCC;
}
}
//*/
Entry();
EmuSwapFS(); // Win2k/XP FS
}
__except(EmuException(GetExceptionInformation()))
{
printf("Emu: WARNING!! Problem with ExceptionFilter\n");
}
CxbxLaunchXbe(Entry);
DbgPrintf("EmuMain (0x%X): Initial thread ended.\n", GetCurrentThreadId());

View File

@ -1,126 +1,434 @@
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->Win32->CxbxKrnl->EmuFile.cpp
// *
// * 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) 2002-2003 Aaron Robinson <caustik@caustik.com>
// *
// * All rights reserved
// *
// ******************************************************************
#define _CXBXKRNL_INTERNAL
#define _XBOXKRNL_DEFEXTRN_
#include "EmuFile.h"
// Array of EmuHandles in the system
EmuHandle EmuHandle::Handles[EMU_MAX_HANDLES];
// Pointer to first free handle in array, or NULL if none
volatile EmuHandle *EmuHandle::FirstFree;
// Pointer to last free handle in array, or NULL if none
volatile EmuHandle *EmuHandle::LastFree;
// Lock on the handle system
CRITICAL_SECTION EmuHandle::HandleLock;
// ******************************************************************
// * Initialize the handle database
// ******************************************************************
bool EmuHandle::Initialize()
{
size_t x;
// Initialize the critical section
InitializeCriticalSection(&HandleLock);
// Mark all handles as free. We also set up the linked list of
// free handles here.
for (x = 0; x < EMU_MAX_HANDLES; x++)
{
Handles[x].m_Type = EMUHANDLE_TYPE_EMPTY;
Handles[x].m_NextFree = &Handles[x + 1];
}
// The last entry should have a NULL next entry
Handles[EMU_MAX_HANDLES - 1].m_NextFree = NULL;
// Set up the head and tail pointers
FirstFree = &Handles[0];
LastFree = &Handles[EMU_MAX_HANDLES];
return true;
}
// ******************************************************************
// * func: EmuHandle::Lock
// * Locks the handle database
// ******************************************************************
inline void EmuHandle::Lock(void)
{
EnterCriticalSection(&HandleLock);
}
// ******************************************************************
// * func: EmuHandle::Unlock
// * Unlocks the handle database
// ******************************************************************
inline void EmuHandle::Unlock(void)
{
LeaveCriticalSection(&HandleLock);
}
// ******************************************************************
// * func: EmuHandle::Allocate
// * Allocates a new handle
// ******************************************************************
EmuHandle volatile *EmuHandle::Allocate(void)
{
volatile EmuHandle *Handle;
// Lock the database
Lock();
// Get the first free entry
Handle = FirstFree;
// Remove it from the list
FirstFree = Handle->m_NextFree;
// If it was the last handle, clear LastFree
if (!Handle->m_NextFree)
LastFree = NULL;
// Initialize the handle's fields
Handle->m_Type = EMUHANDLE_TYPE_ALLOCATED;
Handle->m_Object = NULL;
// Unlock the database
Unlock();
return Handle;
}
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->Win32->CxbxKrnl->EmuFile.cpp
// *
// * 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) 2002-2003 Aaron Robinson <caustik@caustik.com>
// *
// * All rights reserved
// *
// ******************************************************************
#define _CXBXKRNL_INTERNAL
#define _XBOXKRNL_DEFEXTRN_
#include "EmuFile.h"
#include <vector>
#include <string>
#include <Shlobj.h>
#include <ntstatus.h>
#include "CxbxKrnl.h"
std::string DriveSerial = "\\??\\serial:";
std::string DriveCdRom0 = "\\??\\CdRom0:"; // CD-ROM device
std::string DriveMbfs = "\\??\\mbfs:"; // media board's file system area device
std::string DriveMbcom = "\\??\\mbcom:"; // media board's communication area device
std::string DriveMbrom = "\\??\\mbrom:"; // media board's boot ROM device
std::string DriveC = "\\??\\C:"; // C: is HDD0
std::string DriveD = "\\??\\D:"; // D: is DVD Player
std::string DriveE = "\\??\\E:";
std::string DriveF = "\\??\\F:";
std::string DriveT = "\\??\\T:"; // T: is Title persistent data region
std::string DriveU = "\\??\\U:"; // U: is User persistent data region
std::string DriveV = "\\??\\V:";
std::string DriveW = "\\??\\W:";
std::string DriveX = "\\??\\X:";
std::string DriveY = "\\??\\Y:"; // Y: is Dashboard volume (contains "xboxdash.xbe" and "XDASH" folder + contents)
std::string DriveZ = "\\??\\Z:"; // Z: is Title utility data region
std::string DeviceCdrom0 = "\\Device\\CdRom0";
std::string DeviceHarddisk0 = "\\Device\\Harddisk0";
std::string DeviceHarddisk0Partition0 = "\\Device\\Harddisk0\\partition0"; // Contains raw config sectors (like XBOX_REFURB_INFO) + entire hard disk
std::string DeviceHarddisk0Partition1 = "\\Device\\Harddisk0\\partition1"; // Data partition. Contains TDATA and UDATA folders.
std::string DeviceHarddisk0Partition2 = "\\Device\\Harddisk0\\partition2"; // Shell partition. Contains Dashboard (cpxdash.xbe, evoxdash.xbe or xboxdash.xbe)
std::string DeviceHarddisk0Partition3 = "\\Device\\Harddisk0\\partition3"; // First cache partition. Contains cache data (from here up to largest number)
std::string DeviceHarddisk0Partition4 = "\\Device\\Harddisk0\\partition4";
std::string DeviceHarddisk0Partition5 = "\\Device\\Harddisk0\\partition5";
std::string DeviceHarddisk0Partition6 = "\\Device\\Harddisk0\\partition6";
std::string DeviceHarddisk0Partition7 = "\\Device\\Harddisk0\\partition7";
std::string DeviceHarddisk0Partition8 = "\\Device\\Harddisk0\\partition8";
std::string DeviceHarddisk0Partition9 = "\\Device\\Harddisk0\\partition9";
std::string DeviceHarddisk0Partition10 = "\\Device\\Harddisk0\\partition10";
std::string DeviceHarddisk0Partition11 = "\\Device\\Harddisk0\\partition11";
std::string DeviceHarddisk0Partition12 = "\\Device\\Harddisk0\\partition12";
std::string DeviceHarddisk0Partition13 = "\\Device\\Harddisk0\\partition13";
std::string DeviceHarddisk0Partition14 = "\\Device\\Harddisk0\\partition14";
std::string DeviceHarddisk0Partition15 = "\\Device\\Harddisk0\\partition15";
std::string DeviceHarddisk0Partition16 = "\\Device\\Harddisk0\\partition16";
std::string DeviceHarddisk0Partition17 = "\\Device\\Harddisk0\\partition17";
std::string DeviceHarddisk0Partition18 = "\\Device\\Harddisk0\\partition18";
std::string DeviceHarddisk0Partition19 = "\\Device\\Harddisk0\\partition19";
std::string DeviceHarddisk0Partition20 = "\\Device\\Harddisk0\\partition20"; // 20 = Largest possible partition number
char CxbxDefaultXbeVolumeLetter = 'C';
// Array of EmuHandles in the system
EmuHandle EmuHandle::Handles[EMU_MAX_HANDLES];
// Pointer to first free handle in array, or NULL if none
volatile EmuHandle *EmuHandle::FirstFree;
// Pointer to last free handle in array, or NULL if none
volatile EmuHandle *EmuHandle::LastFree;
// Lock on the handle system
CRITICAL_SECTION EmuHandle::HandleLock;
EmuNtSymbolicLinkObject* NtSymbolicLinkObjects[26];
struct XboxDevice {
std::string XboxFullPath;
std::string NativePath;
HANDLE NativeRootHandle;
};
std::vector<XboxDevice> Devices;
bool CxbxRegisterDeviceNativePath(std::string XboxFullPath, std::string NativePath, bool IsFile)
{
bool result = false;
int i = 0;
if (IsFile) {
result = true; // Actually, this is the Config sectors partition (partition0) registered as a file
}
else
{
int status = SHCreateDirectoryEx(NULL, NativePath.c_str(), NULL);
result = status == STATUS_SUCCESS || ERROR_ALREADY_EXISTS;
}
if (result)
{
XboxDevice newDevice;
newDevice.XboxFullPath = XboxFullPath;
newDevice.NativePath = NativePath;
Devices.push_back(newDevice);
}
return result;
}
NTSTATUS CxbxCreateSymbolicLink(std::string SymbolicLinkName, std::string FullPath)
{
NTSTATUS result = 0;
EmuNtSymbolicLinkObject* SymbolicLinkObject = FindNtSymbolicLinkObjectByName(SymbolicLinkName);
if ((SymbolicLinkObject != NULL)) {
// In that case, close it :
SymbolicLinkObject->NtClose();
}
// Now (re)create a symbolic link object, and initialize it with the new definition :
SymbolicLinkObject = new EmuNtSymbolicLinkObject();
result = SymbolicLinkObject->Init(SymbolicLinkName, FullPath);
if (result != STATUS_SUCCESS)
SymbolicLinkObject->NtClose();
return result;
}
// ******************************************************************
// * Initialize the handle database
// ******************************************************************
bool EmuHandle::Initialize()
{
size_t x;
// Initialize the critical section
InitializeCriticalSection(&HandleLock);
// Mark all handles as free. We also set up the linked list of
// free handles here.
for (x = 0; x < EMU_MAX_HANDLES; x++)
{
Handles[x].m_Type = EMUHANDLE_TYPE_EMPTY;
Handles[x].m_NextFree = &Handles[x + 1];
}
// The last entry should have a NULL next entry
Handles[EMU_MAX_HANDLES - 1].m_NextFree = NULL;
// Set up the head and tail pointers
FirstFree = &Handles[0];
LastFree = &Handles[EMU_MAX_HANDLES];
return true;
}
// ******************************************************************
// * func: EmuHandle::Lock
// * Locks the handle database
// ******************************************************************
inline void EmuHandle::Lock(void)
{
EnterCriticalSection(&HandleLock);
}
// ******************************************************************
// * func: EmuHandle::Unlock
// * Unlocks the handle database
// ******************************************************************
inline void EmuHandle::Unlock(void)
{
LeaveCriticalSection(&HandleLock);
}
// ******************************************************************
// * func: EmuHandle::Allocate
// * Allocates a new handle
// ******************************************************************
EmuHandle volatile *EmuHandle::Allocate(void)
{
volatile EmuHandle *Handle;
// Lock the database
Lock();
// Get the first free entry
Handle = FirstFree;
// Remove it from the list
FirstFree = Handle->m_NextFree;
// If it was the last handle, clear LastFree
if (!Handle->m_NextFree)
LastFree = NULL;
// Initialize the handle's fields
Handle->m_Type = EMUHANDLE_TYPE_ALLOCATED;
Handle->m_Object = NULL;
// Unlock the database
Unlock();
return Handle;
}
NTSTATUS EmuNtSymbolicLinkObject::Init(std::string aSymbolicLinkName, std::string aFullPath)
{
NTSTATUS result = 0;
bool IsNativePath = false;
int i = 0;
std::string ExtraPath;
int DeviceIndex = 0;
result = STATUS_OBJECT_NAME_INVALID;
DriveLetter = SymbolicLinkToDriveLetter(aSymbolicLinkName);
if (DriveLetter > 'A' && DriveLetter < 'Z')
{
result = STATUS_OBJECT_NAME_COLLISION;
if (FindNtSymbolicLinkObjectByVolumeLetter(DriveLetter) == NULL)
{
// Look up the partition in the list of pre-registered devices :
result = STATUS_DEVICE_DOES_NOT_EXIST; // TODO : Is this the correct error?
// Make a distinction between Xbox paths (starting with '\Device'...) and Native paths :
std::string deviceString = "\\Device";
IsNativePath = aFullPath.compare(0, deviceString.length(), deviceString) != 0;
if (IsNativePath)
DeviceIndex = 0;
else
{
DeviceIndex = -1;
for (int i = 0; i < Devices.size(); i++) {
int compare = aFullPath.compare(Devices[i].XboxFullPath);
if (aFullPath.compare(0, Devices[i].XboxFullPath.length(), Devices[i].XboxFullPath) == 0)
{
DeviceIndex = i;
break;
}
}
}
if (DeviceIndex >= 0)
{
result = STATUS_SUCCESS;
SymbolicLinkName = aSymbolicLinkName;
XboxFullPath = aFullPath; // TODO : What path do we remember in IsNativePath mode?
if (IsNativePath)
{
NativePath = "";
ExtraPath = aFullPath;
}
else
{
NativePath = Devices[DeviceIndex].NativePath;
// Handle the case where a sub folder of the partition is mounted (instead of it's root) :
ExtraPath = aFullPath.substr(Devices[DeviceIndex].XboxFullPath.length(), std::string::npos);
}
if (!ExtraPath.empty())
NativePath = NativePath + ExtraPath;
SHCreateDirectoryEx(NULL, NativePath.c_str(), NULL);
RootDirectoryHandle = CreateFile(NativePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (RootDirectoryHandle == INVALID_HANDLE_VALUE)
{
result = STATUS_DEVICE_DOES_NOT_EXIST; // TODO : Is this the correct error?
CxbxKrnlCleanup((std::string("Could not map ") + NativePath).c_str());
}
else
{
NtSymbolicLinkObjects[DriveLetter - 'A'] = this;
DbgPrintf("EmuMain : Linked \"%s\" to \"%s\" (residing at \"%s\")\n", aSymbolicLinkName.c_str(), aFullPath.c_str(), NativePath.c_str());
}
}
}
}
return result;
}
void EmuNtSymbolicLinkObject::Free()
{
return;
}
bool CxbxMountUtilityDrive(bool formatClean)
{
Xbe::Certificate* pCertificate;
std::string TitleStr;
NTSTATUS status;
// TODO -oDxbx : Select the oldest cache partition somehow.
// For now, select partition6 as 'Utility data' drive, and link it to Z:
pCertificate = (Xbe::Certificate*)CxbxKrnl_XbeHeader->dwCertificateAddr;
char szBuffer[255];
sprintf(szBuffer, "%08X", ((Xbe::Certificate*)CxbxKrnl_XbeHeader->dwCertificateAddr)->dwTitleId);
TitleStr = szBuffer;
status = CxbxCreateSymbolicLink(DriveZ, DeviceHarddisk0Partition6 + "\\Cxbx_ZDATA_" + TitleStr + "\\");
// Dxbx note : The ZDATA convention is not actually what the Xbox does, but for now
// allows us to skip the partition-selection and formatting of the Utility drive,
// by creating a unique subfolder per title.
// TODO -oDxbx : Implement 'formatting' (cleaning) of the Utility drive
return status == STATUS_SUCCESS;
}
char SymbolicLinkToDriveLetter(std::string SymbolicLinkName)
{
char result = '\0';
// SymbolicLinkName must look like this : "\??\D:"
if ((SymbolicLinkName.size() == 6) && (SymbolicLinkName[0] == '\\') && (SymbolicLinkName[1] == '?') && (SymbolicLinkName[2] == '?') && (SymbolicLinkName[3] == '\\') && (SymbolicLinkName[5] == ':'))
{
result = SymbolicLinkName[4];
switch (result)
{
case /*# 'A' .. 'Z' */ 'A':
case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K':
case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
case 'V': case 'W': case 'X': case 'Y': case 'Z':
return result;
break;
case /*# 'a' .. 'z' */ 'a':
case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
case 'v': case 'w': case 'x': case 'y': case 'z':
{
result = (int(result) + int('A') - int('a'));
return result;
}
break;
}
}
result = '\x00';
return result;
}
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByVolumeLetter(const char VolumeLetter)
{
EmuNtSymbolicLinkObject* result = NULL;
switch (VolumeLetter)
{
case /*# 'A' .. 'Z' */ 'A':
case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K':
case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
case 'V': case 'W': case 'X': case 'Y': case 'Z':
result = NtSymbolicLinkObjects[VolumeLetter - 65];
break;
case /*# 'a' .. 'z' */ 'a':
case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k':
case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
case 'v': case 'w': case 'x': case 'y': case 'z':
result = NtSymbolicLinkObjects[VolumeLetter + 'A' - 'a' - 65];
break;
default:
result = NULL;
}
return result;
}
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByName(std::string SymbolicLinkName)
{
EmuNtSymbolicLinkObject* result = NULL;
result = FindNtSymbolicLinkObjectByVolumeLetter(SymbolicLinkToDriveLetter(SymbolicLinkName));
return result;
}
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByDevice(std::string DeviceName)
{
EmuNtSymbolicLinkObject* result = NULL;
char VolumeLetter = '\0';
for (int stop = 'Z', VolumeLetter = 'A'; VolumeLetter <= stop; VolumeLetter++)
{
result = NtSymbolicLinkObjects[VolumeLetter - 65];
if ((result != NULL) && DeviceName.compare(0, result->XboxFullPath.length(), result->XboxFullPath) == 0)
return result;
}
result = NULL;
return result;
}
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByRootHandle(const HANDLE Handle)
{
EmuNtSymbolicLinkObject* result = NULL;
char VolumeLetter = '\0';
for (int stop = 'Z', VolumeLetter = 'A'; VolumeLetter <= stop; VolumeLetter++)
{
result = NtSymbolicLinkObjects[VolumeLetter - 65];
if ((result != NULL) && (Handle == result->RootDirectoryHandle))
return result;
}
result = NULL;
return result;
}
NTSTATUS EmuNtObject::NtClose()
{
NTSTATUS result = 0;
RefCount--;
if (RefCount <= 0)
Free();
result = STATUS_SUCCESS;
return result;
}
EmuNtObject* EmuNtObject::NtDuplicateObject(DWORD Options)
{
EmuNtObject* result = NULL;
RefCount++;
result = this;
return result;
}

View File

@ -43,6 +43,7 @@ namespace xboxkrnl
};
#include <cstdio>
#include <string>
// ******************************************************************
// * prevent name collisions
@ -54,11 +55,56 @@ namespace NtDll
#include "Emu.h"
extern std::string DriveSerial;
extern std::string DriveCdRom0;
extern std::string DriveMbfs;
extern std::string DriveMbcom;
extern std::string DriveMbrom;
extern std::string DriveC;
extern std::string DriveD;
extern std::string DriveE;
extern std::string DriveF;
extern std::string DriveT;
extern std::string DriveU;
extern std::string DriveV;
extern std::string DriveW;
extern std::string DriveX;
extern std::string DriveY;
extern std::string DriveZ;
extern std::string DeviceCdrom0;
extern std::string DeviceHarddisk0;
extern std::string DeviceHarddisk0Partition0;
extern std::string DeviceHarddisk0Partition1;
extern std::string DeviceHarddisk0Partition2;
extern std::string DeviceHarddisk0Partition3;
extern std::string DeviceHarddisk0Partition4;
extern std::string DeviceHarddisk0Partition5;
extern std::string DeviceHarddisk0Partition6;
extern std::string DeviceHarddisk0Partition7;
extern std::string DeviceHarddisk0Partition8;
extern std::string DeviceHarddisk0Partition9;
extern std::string DeviceHarddisk0Partition10;
extern std::string DeviceHarddisk0Partition11;
extern std::string DeviceHarddisk0Partition12;
extern std::string DeviceHarddisk0Partition13;
extern std::string DeviceHarddisk0Partition14;
extern std::string DeviceHarddisk0Partition15;
extern std::string DeviceHarddisk0Partition16;
extern std::string DeviceHarddisk0Partition17;
extern std::string DeviceHarddisk0Partition18;
extern std::string DeviceHarddisk0Partition19;
extern std::string DeviceHarddisk0Partition20;
extern char CxbxDefaultXbeVolumeLetter;
extern std::string CxbxBasePath;
extern HANDLE CxbxBasePathHandle;
// ******************************************************************
// * Maximum number of open handles in the system
// ******************************************************************
#define EMU_MAX_HANDLES 1024
// ******************************************************************
// * Wrapper of a handle object
// ******************************************************************
@ -134,14 +180,14 @@ class EmuNtObject
{
public:
// Decrements the reference count of this object (never override)
void NtClose(void);
NTSTATUS NtClose(void);
// These functions mimic the Nt* calls
// Increments the reference count of this object
// For file handles, a whole new EmuFile structure is returned.
// For other objects (the default implementation), "this" is returned.
virtual EmuNtObject *NtDuplicateObject(void);
EmuNtObject *NtDuplicateObject(DWORD options);
protected:
// Object name (Unicode, because we handle after-conversion strings)
@ -152,10 +198,7 @@ class EmuNtObject
// Called by close() when the reference count reaches zero
virtual void Free(void) = 0;
// Constructor
EmuNtObject(void);
// Destructor
virtual ~EmuNtObject() = 0;
private:
// Reference count
@ -177,6 +220,20 @@ class EmuNtFile : public EmuNtObject
//EmuNtVolume *Volume;
};
// ******************************************************************
// * Emulated symbolic link handle
// ******************************************************************
class EmuNtSymbolicLinkObject : public EmuNtObject {
public:
char DriveLetter;
std::string SymbolicLinkName;
std::string XboxFullPath;
std::string NativePath;
HANDLE RootDirectoryHandle;
NTSTATUS Init(std::string aSymbolicLinkName, std::string aFullPath);
void Free();
};
// ******************************************************************
// * is hFile a 'special' emulated handle?
// ******************************************************************
@ -203,4 +260,15 @@ static inline HANDLE PtrToEmuHandle(EmuHandle *pEmuHandle)
return (HANDLE)((uint32)pEmuHandle + 0x80000000);
}
char SymbolicLinkToDriveLetter(std::string aSymbolicLinkName);
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByVolumeLetter(const char VolumeLetter);
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByName(std::string SymbolicLinkName);
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByDevice(std::string DeviceName);
EmuNtSymbolicLinkObject* FindNtSymbolicLinkObjectByRootHandle(HANDLE Handle);
void CleanupSymbolicLinks();
bool CxbxRegisterDeviceNativePath(std::string XboxFullPath, std::string NativePath, bool IsFile = false);
HANDLE CxbxGetDeviceNativeRootHandle(std::string XboxFullPath);
NTSTATUS CxbxCreateSymbolicLink(std::string SymbolicLinkName, std::string FullPath);
bool CxbxMountUtilityDrive(bool formatClean);
#endif

View File

@ -86,6 +86,15 @@ struct INTERNAL_CRITICAL_SECTION
NtDll::_RTL_CRITICAL_SECTION NativeCriticalSection;
};
struct NativeObjectAttributes {
wchar_t wszObjectName[160];
NtDll::UNICODE_STRING NtUnicodeString;
NtDll::OBJECT_ATTRIBUTES NtObjAttr;
// This is what should be passed on to Windows
// after CxbxObjectAttributesToNT() has been called :
NtDll::POBJECT_ATTRIBUTES NtObjAttrPtr;
};
#define MAX_XBOX_CRITICAL_SECTIONS 1024
INTERNAL_CRITICAL_SECTION GlobalCriticalSections[MAX_XBOX_CRITICAL_SECTIONS] = {0};
@ -1153,6 +1162,135 @@ callComplete:
}
#pragma warning(pop)
NTSTATUS CxbxObjectAttributesToNT(xboxkrnl::POBJECT_ATTRIBUTES ObjectAttributes, NativeObjectAttributes& nativeObjectAttributes, std::string aFileAPIName = "")
{
NTSTATUS result = 0;
std::string OriginalPath;
std::string RelativePath;
std::string XboxFullPath;
std::string NativePath;
EmuNtSymbolicLinkObject* NtSymbolicLinkObject = NULL;
result = STATUS_SUCCESS;
if (ObjectAttributes == NULL)
{
// When the pointer is nil, make sure we pass nil to Windows too :
nativeObjectAttributes.NtObjAttrPtr = NULL;
return result;
}
// ObjectAttributes are given, so make sure the pointer we're going to pass to Windows is assigned :
nativeObjectAttributes.NtObjAttrPtr = &nativeObjectAttributes.NtObjAttr;
RelativePath = std::string(ObjectAttributes->ObjectName->Buffer, ObjectAttributes->ObjectName->Length);
OriginalPath = RelativePath;
// Always trim '\??\' off :
if ((RelativePath.length() >= 4) && (RelativePath[0] == '\\') && (RelativePath[1] == '?') && (RelativePath[2] == '?') && (RelativePath[3] == '\\'))
RelativePath.erase(0, 4);
// Check if we where called from a File-handling API :
if (!aFileAPIName.empty())
{
NtSymbolicLinkObject = NULL;
// Check if the path starts with a volume indicator :
if ((RelativePath.length() >= 2) && (RelativePath[1] == ':'))
{
// Look up the symbolic link information using the drive letter :
NtSymbolicLinkObject = FindNtSymbolicLinkObjectByVolumeLetter(RelativePath[0]);
RelativePath.erase(0, 2); // Remove 'C:'
// If the remaining path starts with a ':', remove it (to prevent errors) :
if ((RelativePath.length() > 0) && (RelativePath[0] == ':'))
RelativePath.erase(0, 1); // xbmp needs this, as it accesses 'e::\'
}
// Check if the path starts with a macro indicator :
else
if (RelativePath.compare(0, 1, "$") == 0)
{
if (RelativePath.compare(0, 5, "$HOME") == 0) // "xbmp" needs this
{
NtSymbolicLinkObject = FindNtSymbolicLinkObjectByRootHandle(g_hCurDir);
RelativePath.erase(0, 5); // Remove '$HOME'
}
else
CxbxKrnlCleanup(("Unsupported path macro : " + OriginalPath).c_str());
}
// Check if the path starts with a relative path indicator :
else
if (RelativePath.compare(0, 1, ".") == 0) // "4x4 Evo 2" needs this
{
NtSymbolicLinkObject = FindNtSymbolicLinkObjectByRootHandle(g_hCurDir);
RelativePath.erase(0, 1); // Remove the '.'
}
else
{
// The path seems to be a device path, look it up :
NtSymbolicLinkObject = FindNtSymbolicLinkObjectByDevice(RelativePath);
// Fixup RelativePath path here
if ((NtSymbolicLinkObject != NULL))
RelativePath.erase(0, NtSymbolicLinkObject->XboxFullPath.length()); // Remove '\Device\Harddisk0\Partition2'
}
if ((NtSymbolicLinkObject != NULL))
{
// If the remaining path starts with a '\', remove it (to prevent working in a native root) :
if ((RelativePath.length() > 0) && (RelativePath[0] == '\\'))
RelativePath.erase(0, 1);
XboxFullPath = NtSymbolicLinkObject->XboxFullPath;
NativePath = NtSymbolicLinkObject->NativePath;
ObjectAttributes->RootDirectory = NtSymbolicLinkObject->RootDirectoryHandle;
}
else
{
// No symbolic link - as last resort, check if the path accesses a partition from Harddisk0 :
if (RelativePath.compare(0, (DeviceHarddisk0 + "\\partition").length(), DeviceHarddisk0 + "\\partition") != 0)
{
result = STATUS_UNRECOGNIZED_VOLUME; // TODO : Is this the correct error?
EmuWarning((("Path not available : ") + OriginalPath).c_str());
return result;
}
XboxFullPath = RelativePath;
// Remove Harddisk0 prefix, in the hope that the remaining path might work :
RelativePath.erase(0, DeviceHarddisk0.length() + 1);
// And set Root to the folder containing the partition-folders :
ObjectAttributes->RootDirectory = CxbxBasePathHandle;
NativePath = CxbxBasePath;
}
// Check for special case : Partition0
if (XboxFullPath.compare(DeviceHarddisk0Partition0) == 0)
{
CxbxKrnlCleanup("Partition0 access not implemented yet! Tell PatrickvL what title triggers this.");
// TODO : Redirect raw sector-access to the 'Partition0_ConfigData.bin' file
// (This file probably needs to be pre-initialized somehow too).
}
DbgPrintf("EmuKrnl : %s Corrected path...", aFileAPIName.c_str());
DbgPrintf(" Org:\"%s\"", OriginalPath.c_str());
if (NativePath.compare(CxbxBasePath) == 0)
{
DbgPrintf(" New:\"$CxbxPath\\EmuDisk%s%s\"", (NativePath.substr(CxbxBasePath.length(), std::string::npos)).c_str(), RelativePath.c_str());
}
else
DbgPrintf(" New:\"$XbePath\\%s\"", RelativePath.c_str());
}
else
{
// For non-file API calls, prefix with '\??\' again :
RelativePath = "\\??\\" + RelativePath;
ObjectAttributes->RootDirectory = 0;
}
// Convert Ansi to Unicode :
mbstowcs(nativeObjectAttributes.wszObjectName, RelativePath.c_str(), 160);
NtDll::RtlInitUnicodeString(&nativeObjectAttributes.NtUnicodeString, nativeObjectAttributes.wszObjectName);
// Initialize the NT ObjectAttributes :
InitializeObjectAttributes(&nativeObjectAttributes.NtObjAttr, &nativeObjectAttributes.NtUnicodeString, ObjectAttributes->Attributes, ObjectAttributes->RootDirectory, NULL);
return result;
}
using namespace xboxkrnl;
// ******************************************************************
@ -1729,8 +1867,7 @@ XBSYSAPI EXPORTNUM(67) xboxkrnl::NTSTATUS NTAPI xboxkrnl::IoCreateSymbolicLink
GetCurrentThreadId(), SymbolicLinkName, SymbolicLinkName->Buffer,
DeviceName, DeviceName->Buffer);
// TODO: Actually um...implement this function
NTSTATUS ret = STATUS_OBJECT_NAME_COLLISION;
NTSTATUS ret = CxbxCreateSymbolicLink(SymbolicLinkName->Buffer, DeviceName->Buffer);
EmuSwapFS(); // Xbox FS
@ -1753,8 +1890,12 @@ XBSYSAPI EXPORTNUM(69) xboxkrnl::NTSTATUS NTAPI xboxkrnl::IoDeleteSymbolicLink
");\n",
GetCurrentThreadId(), SymbolicLinkName, SymbolicLinkName->Buffer);
// TODO: Actually um...implement this function
NTSTATUS ret = STATUS_OBJECT_NAME_NOT_FOUND;
EmuNtSymbolicLinkObject* symbolicLink = FindNtSymbolicLinkObjectByName(SymbolicLinkName->Buffer);
NTSTATUS ret = STATUS_OBJECT_NAME_NOT_FOUND;
if ((symbolicLink != NULL))
ret = symbolicLink->NtClose();
EmuSwapFS(); // Xbox FS
@ -2726,6 +2867,49 @@ XBSYSAPI EXPORTNUM(187) xboxkrnl::NTSTATUS NTAPI xboxkrnl::NtClose
return ret;
}
// ******************************************************************
// * 0x00BC - NtCreateDirectoryObject
// ******************************************************************
XBSYSAPI EXPORTNUM(189) xboxkrnl::NTSTATUS NTAPI xboxkrnl::NtCreateDirectoryObject
(
OUT PHANDLE DirectoryHandle,
IN POBJECT_ATTRIBUTES ObjectAttributes
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuKrnl (0x%X): NtCreateDirectoryObject\n"
"(\n"
" DirectoryHandle : 0x%.08X\n"
" ObjectAttributes : 0x%.08X (\"%s\")\n"
");\n",
GetCurrentThreadId(), DirectoryHandle, ObjectAttributes);
NTSTATUS ret = 0;
NativeObjectAttributes nativeObjectAttributes;
ACCESS_MASK DesiredAccess = 0;
ret = CxbxObjectAttributesToNT(ObjectAttributes, nativeObjectAttributes, "NtCreateDirectoryObject");
if (ret == STATUS_SUCCESS)
{
// TODO -oDxbx : Is this the correct ACCESS_MASK? :
DesiredAccess = DIRECTORY_CREATE_OBJECT;
ret = /*# JwaNative::*/ NtDll::NtCreateDirectoryObject(DirectoryHandle, DesiredAccess, nativeObjectAttributes.NtObjAttrPtr);
}
if (FAILED(ret))
EmuWarning("NtCreateDirectoryObject Failed!");
DbgPrintf("EmuKrnl (0x%X): NtCreateDirectoryObject DirectoryHandle = 0x%.08X\n", GetCurrentThreadId(), *DirectoryHandle);
EmuSwapFS(); // Xbox FS
return ret;
}
// ******************************************************************
// * 0x00BD - NtCreateEvent
// ******************************************************************
@ -2739,38 +2923,30 @@ XBSYSAPI EXPORTNUM(189) xboxkrnl::NTSTATUS NTAPI xboxkrnl::NtCreateEvent
{
EmuSwapFS(); // Win2k/XP FS
char *szBuffer = (ObjectAttributes != 0) ? ObjectAttributes->ObjectName->Buffer : 0;
DbgPrintf("EmuKrnl (0x%X): NtCreateEvent\n"
"(\n"
" EventHandle : 0x%.08X\n"
" ObjectAttributes : 0x%.08X (\"%s\")\n"
" ObjectAttributes : 0x%.08X\n"
" EventType : 0x%.08X\n"
" InitialState : 0x%.08X\n"
");\n",
GetCurrentThreadId(), EventHandle, ObjectAttributes, szBuffer,
EventType, InitialState);
GetCurrentThreadId(), EventHandle, ObjectAttributes, EventType, InitialState);
wchar_t wszObjectName[160];
NativeObjectAttributes nativeObjectAttributes;
ACCESS_MASK DesiredAccess = 0;
NtDll::UNICODE_STRING NtUnicodeString;
NtDll::OBJECT_ATTRIBUTES NtObjAttr;
// initialize object attributes
NTSTATUS ret = CxbxObjectAttributesToNT(ObjectAttributes, nativeObjectAttributes); /*var*/
if (ret == STATUS_SUCCESS)
{
// TODO -oDxbx : Is this the correct ACCESS_MASK? :
DesiredAccess = EVENT_ALL_ACCESS;
// initialize object attributes
if(szBuffer != 0)
{
mbstowcs(wszObjectName, "\\??\\", 4);
mbstowcs(wszObjectName+4, szBuffer, 160);
NtDll::RtlInitUnicodeString(&NtUnicodeString, wszObjectName);
InitializeObjectAttributes(&NtObjAttr, &NtUnicodeString, ObjectAttributes->Attributes, ObjectAttributes->RootDirectory, NULL);
}
NtObjAttr.RootDirectory = 0;
// redirect to NtCreateEvent
NTSTATUS ret = NtDll::NtCreateEvent(EventHandle, EVENT_ALL_ACCESS, (szBuffer != 0) ? &NtObjAttr : 0, (NtDll::EVENT_TYPE)EventType, InitialState);
// redirect to Win2k/XP
ret = NtDll::NtCreateEvent(EventHandle, DesiredAccess, nativeObjectAttributes.NtObjAttrPtr, (NtDll::EVENT_TYPE)EventType, InitialState);
// TODO : Instead of the above, we should consider using the Ke*Event APIs, but
// that would require us to create the event's kernel object with the Ob* api's too!
}
if(FAILED(ret))
EmuWarning("NtCreateEvent Failed!");
@ -2815,170 +2991,12 @@ XBSYSAPI EXPORTNUM(190) xboxkrnl::NTSTATUS NTAPI xboxkrnl::NtCreateFile
GetCurrentThreadId(), FileHandle, DesiredAccess, ObjectAttributes, ObjectAttributes->ObjectName->Buffer,
IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions);
char ReplaceChar = '\0';
int ReplaceIndex = -1;
char *szBuffer = ObjectAttributes->ObjectName->Buffer;
if(szBuffer == (char*) 0xFFFFFFFF)
szBuffer = NULL;
if(szBuffer != NULL)
{
//printf("Orig : %s\n", szBuffer);
// trim this off
if(szBuffer[0] == '\\' && szBuffer[1] == '?' && szBuffer[2] == '?' && szBuffer[3] == '\\')
{
szBuffer += 4;
}
// D:\ should map to current directory
if( (szBuffer[0] == 'D' || szBuffer[0] == 'd') && szBuffer[1] == ':' && szBuffer[2] == '\\')
{
szBuffer += 3;
ObjectAttributes->RootDirectory = g_hCurDir;
DbgPrintf("EmuKrnl (0x%X): NtCreateFile Corrected path...\n", GetCurrentThreadId());
DbgPrintf(" Org:\"%s\"\n", ObjectAttributes->ObjectName->Buffer);
DbgPrintf(" New:\"$XbePath\\%s\"\n", szBuffer);
}
// Going to map Y:\ to current directory as well (dashboard test, 3944)
else if( (szBuffer[0] == 'Y' || szBuffer[0] == 'y') && szBuffer[1] == ':' && szBuffer[2] == '\\')
{
szBuffer += 3;
ObjectAttributes->RootDirectory = g_hCurDir;
DbgPrintf("EmuKrnl (0x%X): NtCreateFile Corrected path...\n", GetCurrentThreadId());
DbgPrintf(" Org:\"%s\"\n", ObjectAttributes->ObjectName->Buffer);
DbgPrintf(" New:\"$XbePath\\%s\"\n", szBuffer);
}
else if( (szBuffer[0] == 'T' || szBuffer[0] == 't') && szBuffer[1] == ':' && szBuffer[2] == '\\')
{
szBuffer += 3;
ObjectAttributes->RootDirectory = g_hTDrive;
DbgPrintf("EmuKrnl (0x%X): NtCreateFile Corrected path...\n", GetCurrentThreadId());
DbgPrintf(" Org:\"%s\"\n", ObjectAttributes->ObjectName->Buffer);
DbgPrintf(" New:\"$CxbxPath\\EmuDisk\\T\\%s\"\n", szBuffer);
}
else if( (szBuffer[0] == 'U' || szBuffer[0] == 'u') && szBuffer[1] == ':' && szBuffer[2] == '\\')
{
szBuffer += 3;
ObjectAttributes->RootDirectory = g_hUDrive;
DbgPrintf("EmuKrnl (0x%X): NtCreateFile Corrected path...\n", GetCurrentThreadId());
DbgPrintf(" Org:\"%s\"\n", ObjectAttributes->ObjectName->Buffer);
DbgPrintf(" New:\"$CxbxPath\\EmuDisk\\U\\%s\"\n", szBuffer);
}
else if( (szBuffer[0] == 'Z' || szBuffer[0] == 'z') && szBuffer[1] == ':' && szBuffer[2] == '\\')
{
szBuffer += 3;
ObjectAttributes->RootDirectory = g_hZDrive;
DbgPrintf("EmuKrnl (0x%X): NtCreateFile Corrected path...\n", GetCurrentThreadId());
DbgPrintf(" Org:\"%s\"\n", ObjectAttributes->ObjectName->Buffer);
DbgPrintf(" New:\"$CxbxPath\\EmuDisk\\Z\\%s\"\n", szBuffer);
}
// Ignore wildcards. Xapi FindFirstFile uses the same path buffer for
// NtOpenFile and NtQueryDirectoryFile. Wildcards are only parsed by
// the latter.
{
for(int v=0;szBuffer[v] != '\0';v++)
{
// FIXME: Fallback to parent directory if wildcard is found.
if(szBuffer[v] == '*')
{
ReplaceIndex = v;
break;
}
}
}
// Note: Hack: Not thread safe (if problems occur, create a temp buffer)
if(ReplaceIndex != -1)
{
ReplaceChar = szBuffer[ReplaceIndex];
szBuffer[ReplaceIndex] = '\0';
}
//printf("Aftr : %s\n", szBuffer);
}
wchar_t wszObjectName[160];
NtDll::UNICODE_STRING NtUnicodeString;
NtDll::OBJECT_ATTRIBUTES NtObjAttr;
// initialize object attributes
if(szBuffer != NULL)
{
mbstowcs(wszObjectName, szBuffer, 160);
}
else
{
wszObjectName[0] = L'\0';
}
NtDll::RtlInitUnicodeString(&NtUnicodeString, wszObjectName);
InitializeObjectAttributes(&NtObjAttr, &NtUnicodeString, ObjectAttributes->Attributes, ObjectAttributes->RootDirectory, NULL);
NativeObjectAttributes nativeObjectAttributes;
NTSTATUS ret = CxbxObjectAttributesToNT(ObjectAttributes, nativeObjectAttributes, "NtCreateFile"); /*var*/
// redirect to NtCreateFile
NTSTATUS ret = NtDll::NtCreateFile
(
FileHandle, DesiredAccess, &NtObjAttr, (NtDll::IO_STATUS_BLOCK*)IoStatusBlock,
(NtDll::LARGE_INTEGER*)AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, NULL, 0
);
// If we're trying to open a regular file as a directory, fallback to
// parent directory. This behavior is required by Xapi FindFirstFile.
if(ret == STATUS_NOT_A_DIRECTORY)
{
DbgPrintf("EmuKrnl (0x%X): NtCreateFile fallback to parent directory\n", GetCurrentThreadId());
// Restore original buffer.
if(ReplaceIndex != -1)
{
szBuffer[ReplaceIndex] = ReplaceChar;
}
// Strip filename from path.
int CurIndex = strlen(szBuffer);
while(CurIndex--)
{
if(szBuffer[CurIndex] == '\\')
{
ReplaceIndex = CurIndex;
break;
}
}
if(CurIndex == -1)
{
ReplaceIndex = 0;
}
// Modify buffer again.
ReplaceChar = szBuffer[ReplaceIndex];
szBuffer[ReplaceIndex] = '\0';
DbgPrintf(" New:\"$CurRoot\\%s\"\n", szBuffer);
mbstowcs(wszObjectName, szBuffer, 160);
NtDll::RtlInitUnicodeString(&NtUnicodeString, wszObjectName);
ret = NtDll::NtCreateFile
(
FileHandle, DesiredAccess, &NtObjAttr, (NtDll::IO_STATUS_BLOCK*)IoStatusBlock,
(NtDll::LARGE_INTEGER*)AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, NULL, 0
);
}
ret = NtDll::NtCreateFile(FileHandle, DesiredAccess | GENERIC_READ, nativeObjectAttributes.NtObjAttrPtr, NtDll::PIO_STATUS_BLOCK(IoStatusBlock), NtDll::PLARGE_INTEGER(AllocationSize), FileAttributes, ShareAccess, CreateDisposition, CreateOptions, NULL, 0);
if(FAILED(ret))
{
DbgPrintf("EmuKrnl (0x%X): NtCreateFile Failed! (0x%.08X)\n", GetCurrentThreadId(), ret);
@ -2988,12 +3006,7 @@ XBSYSAPI EXPORTNUM(190) xboxkrnl::NTSTATUS NTAPI xboxkrnl::NtCreateFile
DbgPrintf("EmuKrnl (0x%X): NtCreateFile = 0x%.08X\n", GetCurrentThreadId(), *FileHandle);
}
// restore original buffer
if(ReplaceIndex != -1)
{
szBuffer[ReplaceIndex] = ReplaceChar;
}
// NOTE: We can map this to IoCreateFile once implemented (if ever necessary)
// xboxkrnl::IoCreateFile(FileHandle, DesiredAccess, ObjectAttributes, IoStatusBlock, AllocationSize, FileAttributes, ShareAccess, CreateDisposition, CreateOptions, 0);
@ -4604,6 +4617,8 @@ XBSYSAPI EXPORTNUM(308) xboxkrnl::NTSTATUS NTAPI xboxkrnl::RtlUnicodeStringToAns
return ret;
}
// ******************************************************************
// * 0x0142 - XboxHardwareInfo
// ******************************************************************

View File

@ -87,6 +87,7 @@ NtDll::FPTR_NtCreateMutant NtDll::NtCreateMutant =
NtDll::FPTR_NtReleaseMutant NtDll::NtReleaseMutant = (NtDll::FPTR_NtReleaseMutant)GetProcAddress(hNtDll, "NtReleaseMutant");
NtDll::FPTR_NtCreateSemaphore NtDll::NtCreateSemaphore = (NtDll::FPTR_NtCreateSemaphore)GetProcAddress(hNtDll, "NtCreateSemaphore");
NtDll::FPTR_NtReleaseSemaphore NtDll::NtReleaseSemaphore = (NtDll::FPTR_NtReleaseSemaphore)GetProcAddress(hNtDll, "NtReleaseSemaphore");
NtDll::FPTR_NtCreateDirectoryObject NtDll::NtCreateDirectoryObject = (NtDll::FPTR_NtCreateDirectoryObject)GetProcAddress(hNtDll, "NtCreateDirectoryObject");
NtDll::FPTR_NtCreateFile NtDll::NtCreateFile = (NtDll::FPTR_NtCreateFile)GetProcAddress(hNtDll, "NtCreateFile");
NtDll::FPTR_NtReadFile NtDll::NtReadFile = (NtDll::FPTR_NtReadFile)GetProcAddress(hNtDll, "NtReadFile");
NtDll::FPTR_NtWriteFile NtDll::NtWriteFile = (NtDll::FPTR_NtWriteFile)GetProcAddress(hNtDll, "NtWriteFile");

View File

@ -116,6 +116,12 @@ typedef unsigned __int64 ULONGLONG;
#define NT_SUCCESS(Status) ((NTSTATUS) (Status) >= 0)
#define DIRECTORY_QUERY 1
#define DIRECTORY_TRAVERSE 2
#define DIRECTORY_CREATE_OBJECT 4
#define DIRECTORY_CREATE_SUBDIRECTORY 8
// ******************************************************************
// * calling conventions
// ******************************************************************
@ -881,6 +887,17 @@ typedef NTSTATUS (NTAPI *FPTR_NtCreateFile)
IN ULONG EaLength
);
// ******************************************************************
// * NtCreateDirectoryObject
// ******************************************************************
typedef NTSTATUS(NTAPI *FPTR_NtCreateDirectoryObject)
(
OUT PHANDLE DirectoryHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
// ******************************************************************
// * NtClearEvent
// ******************************************************************
@ -1119,6 +1136,7 @@ extern FPTR_NtCreateMutant NtCreateMutant;
extern FPTR_NtReleaseMutant NtReleaseMutant;
extern FPTR_NtCreateSemaphore NtCreateSemaphore;
extern FPTR_NtReleaseSemaphore NtReleaseSemaphore;
extern FPTR_NtCreateDirectoryObject NtCreateDirectoryObject;
extern FPTR_NtCreateFile NtCreateFile;
extern FPTR_NtReadFile NtReadFile;
extern FPTR_NtWriteFile NtWriteFile;

View File

@ -68,9 +68,9 @@ void EmuHLEIntercept(Xbe::LibraryVersion *pLibraryVersion, Xbe::Header *pXbeHead
{
DbgPrintf("HLE: Detected Microsoft XDK application...\n");
uint32 dwLibraryVersions = pXbeHeader->dwLibraryVersions;
uint32 dwLibraryVersions = pXbeHeader->dwLibraryVersions;
// Find D3D Library Version, this is used within the HLE functions to account for minor differences between XDK revisions
for (uint32 v = 0;v < dwLibraryVersions;v++)
{
uint16 MajorVersion = pLibraryVersion[v].wMajorVersion;
@ -92,9 +92,14 @@ void EmuHLEIntercept(Xbe::LibraryVersion *pLibraryVersion, Xbe::Header *pXbeHead
// Save D3D8 build version
g_BuildVersion = BuildVersion;
g_OrigBuildVersion = OrigBuildVersion;
break;
}
}
// Load StoredPatternTrie
// Perform symbol matching
// Install wrappers
}
DbgPrintf("\n");

View File

@ -245,7 +245,7 @@ extern "C" CXBXKRNL_API uint32 CxbxKrnl_KernelThunkTable[367] =
(uint32)PANIC(0x00B9), // 0x00B9 (185) NtCancelTimer
(uint32)&xboxkrnl::NtClearEvent, // 0x00BA (186)
(uint32)&xboxkrnl::NtClose, // 0x00BB (187)
(uint32)PANIC(0x00BC), // 0x00BC (188) NtCreateDirectoryObject
(uint32)&xboxkrnl::NtCreateDirectoryObject, // 0x00BC (188) NtCreateDirectoryObject
(uint32)&xboxkrnl::NtCreateEvent, // 0x00BD (189)
(uint32)&xboxkrnl::NtCreateFile, // 0x00BE (190)
(uint32)PANIC(0x00BF), // 0x00BF (191) NtCreateIoCompletion