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:
parent
875c64148c
commit
1578146bfe
|
@ -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
|
||||
// ******************************************************************
|
||||
|
|
|
@ -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());
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
// ******************************************************************
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue