Jump to content
OGXbox.com

OG Development - FileSystem


mcgrane
 Share

Recommended Posts

Just wanted to see if anyone could help, I have got the devkit up and running on my xbox recently and have been messing around with making something. In general information is fairly hard to find but ive got one or two sites that have got me started. From the application i have created, i can see that i can only access my own folder, it comes up as the  D drive. Im guessing that this is done intentionally so as you cant access other folders etc, but how can i access other folders in the filesystem? In the case of the Dashboards, they obviously have access to the full system.. im just wondering how i could do this? If i was to make a Dashboard for example, i would want to be able to list the filesystem and open files etc.. Just hoping someone can help me Out

Link to comment
Share on other sites

By default the only paths available to access are:
 

D:\ (root directory of the currently running executable)
T:\ (mapped path to the E:\TDATA\{TitleId} folder, TitleId is specified by the currently running executable)
U:\ (mapped path to the E:\UDATA\{TitleId} folder, TitleId is specified by the currently running executable)
Z:\ (mapped to the X/Y/Z cache partitions if the XINIT_MOUNT_UTILITY_DRIVE flag was specified when compiling the executable or XMountUtilityDrive() is called manually)
W:\ (mapped path to the E:\TDATA\{AlternateTitleId} folder, only available if an alternate TitleId is specified and XMountAlternateTitle() is called manually)
X:\ (mapped path to the E:\UDATA\{AlternateTitleId} folder, only available if an alternate TitleId is specified and XMountAlternateTitle() is called manually)

Basically it gives you access to your running directory, cache, and the UDATA/TDATA folders specific to your set TitleId/AlternateTitleId's and that's it. If you want general access to the partitions you need to do as the dashboards do and mount the partitions or specific paths yourself

Since everything on the Xbox runs in kernel mode, you can call any function the kernel exports as long as you have the function signature or ordinal even if it's not exposed by the XAPI. The way to mount the partitions and create a mapping between a partition and drive letter is to use the "symbolic link" functions exported by the kernel, which is how dashboards get access to these areas

#include <xtl.h>
#include <stdio.h>

/*
	defines if needed:

	typedef char CHAR;
	typedef char* PCHAR;
	typedef char* PSTR;
	typedef int BOOL;
	typedef unsigned short USHORT;
	typedef long LONG;
	
	#define TRUE 1
	#define FALSE 0
	
	#define MAX_PATH 260
	
	#define XBOXAPI
	#define NTAPI __stdcall
	#define NTSTATUS LONG
			
		
	if using CPP use:
	
	extern "C" { 
		...
	};
	
	else use:
	
	extern {
		...
	};
*/

/*
	Kernel imports
*/

extern "C" {
	
	typedef struct _STRING {
		USHORT Length; 			// actual used character count in character buffer (literal string length)
		USHORT MaximumLength; 	// total size of character buffer
		PSTR Buffer; 			// pointer to character buffer
	} STRING, *PSTRING, ANSI_STRING, *PANSI_STRING;
	
	// create symlink between DOS device object and virtual drive letter
	XBOXAPI LONG NTAPI IoCreateSymbolicLink(PSTRING SymbolicLinkName, PSTRING DeviceName);

	// remove symlink, if exists
	XBOXAPI LONG NTAPI IoDeleteSymbolicLink(PSTRING SymbolicLinkName);
		
};

/*
	DOS device objects defines
*/

// disc drive (mountable)
PCHAR DVDROM = "\\Device\\CdRom0";

// raw hard drive I/O (not mountable, open a handle with NtOpenFile to access)
PCHAR HARDDRIVE = "\\Device\\Harddisk0\\Partition0";

// standard FATX partitions (mountable)
PCHAR E_Partition = "\\Device\\Harddisk0\\Partition1"; // title/user data partition
PCHAR C_Partition = "\\Device\\Harddisk0\\Partition2"; // system data partition
PCHAR X_Partition = "\\Device\\Harddisk0\\Partition3"; // cache partition
PCHAR Y_Partition = "\\Device\\Harddisk0\\Partition4"; // ^
PCHAR Z_Partition = "\\Device\\Harddisk0\\Partition5"; // ^

/*
	NOTE: 
	
	Extended partitions (homebrew) are not listed here, these partitions are mountable. To check if the LBA48 patch is present you
	must send a query to NtDeviceIoControlFile to retrieve LBA48 presence status and the extended partition table
	(see NKPatcher and/or XBPartitioner source code (found on xbins))
*/

/*
	Mounting functions
*/

//
// Creates a symbolic link between a device path and a virtual drive letter
//
// DevicePath: String containing the complete path to the driver device object
// (and any tacked on sub-directory, for example passing "\\Device\\Harddisk0\\Partition1\\TDATA" would mount the TDATA as the root of the specified drive letter)
// 
// DriveLetter: The requested drive letter to mount the passed path to (A-Z)
//
BOOL Mount(PCHAR DevicePath, CHAR DriveLetter) {
	
	// check null path
	if (!DevicePath)
		return FALSE;
	
	// continue only if valid drive letter
	if (DriveLetter >= 'A' || DriveLetter <= 'Z' ||
		DriveLetter >= 'a' || DriveLetter <= 'z') {
		
		// allocate buffers
		PCHAR DevicePathBuffer = (PCHAR)malloc(MAX_PATH);
		PCHAR DriveLetterBuffer = (PCHAR)malloc(MAX_PATH);
		
		// check allocation success
		if (!DevicePathBuffer || !DriveLetterBuffer)
			return FALSE;
		
		// zero buffers
		memset(DevicePathBuffer, 0, MAX_PATH);
		memset(DriveLetterBuffer, 0, MAX_PATH);
		
		// pack and format the passed variables into buffers
		sprintf(DevicePathBuffer, "%s", DevicePath);
		sprintf(DriveLetterBuffer, "\\??\\%c:", DriveLetter); // DOS format
		
		// create winnt compatible string buffers
		ANSI_STRING DeviceName;
		DeviceName.Buffer = DevicePathBuffer;
		DeviceName.Length = strlen(DevicePathBuffer);
		DeviceName.MaximumLength = MAX_PATH;
		
		ANSI_STRING SymbolicLinkName;
		SymbolicLinkName.Buffer = DriveLetterBuffer;
		SymbolicLinkName.Length = strlen(DriveLetterBuffer);
		SymbolicLinkName.MaximumLength = MAX_PATH;
		
		// request symbolic link
		LONG Result = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); // returns NTSTATUS (long)
		
		// free buffers
		free(DevicePathBuffer);
		free(DriveLetterBuffer);
		
		return (Result >= 0); // NT_SUCCESS check
	}
	
	return FALSE;
}

//
// Deletes a symbolic link between a device path and a virtual drive letter
//
// DriveLetter: The requested drive letter to unmount
//
BOOL Unmount(CHAR DriveLetter) {
	
	// continue only if valid drive letter
	if (DriveLetter >= 'A' || DriveLetter <= 'Z' ||
		DriveLetter >= 'a' || DriveLetter <= 'z') {
		
		// allocate buffer
		PCHAR DriveLetterBuffer = (PCHAR)malloc(MAX_PATH);
		
		// check allocation success
		if (!DriveLetterBuffer)
			return FALSE;
		
		// zero buffer
		memset(DriveLetterBuffer, 0, MAX_PATH);
		
		// pack and format buffer
		sprintf(DriveLetterBuffer, "\\??\\%c:", DriveLetter); // DOS format
		
		// create winnt compatible string buffers
		ANSI_STRING SymbolicLinkName;
		SymbolicLinkName.Buffer = DriveLetterBuffer;
		SymbolicLinkName.Length = strlen(DriveLetterBuffer);
		SymbolicLinkName.MaximumLength = MAX_PATH;
		
		// request remove symbolic link
		LONG Result = IoDeleteSymbolicLink(&SymbolicLinkName); // returns NTSTATUS (long)
		
		// free buffer
		free(DriveLetterBuffer);
		
		return (Result >= 0); // NT_SUCCESS check
	}
	
	return FALSE;
}

and to use this code to mount the title/user data partition (usually referred to as the the E: partition) for example:

void Example() {
	
	// define the drive letter you want to mount to
	char DriveLetter = 'E';
	
	// pass the device path and the drive letter you want to link together
	if (!Mount(E_Partition, DriveLetter)) {
		
		// failed to mount ...
	}
	
	// ... code to utilize the E:\ partition here
	
	// unmount when done
	Unmount(DriveLetter);
}

 

So if you want to access any other areas than the ones the XAPI provides to you, you will need to mount the partition or specific path yourself. I have a tool here where I was dealing with a bunch of partition and directory stuff if you need an example, the NXDK project has a bunch of kernel function definitions if you'd like to know more about that, and XBMC is fully open source and serves as a good resource for learning

One thing I'll mention since I don't know your intent or what you're trying to access and it's something that stumped me for a bit, something I couldn't find a single mention of anywhere is that you cannot access the TDATA/UDATA folders of other titles - even if you mount the partition yourself. There's some kind of restriction in the file system functions that will not allow a title with a different TitleId to access the TitleId folders in TDATA/UDATA that belong to other titles. Any other directories on any partition is fully accessible except the TDATA/UDATA folders of other titles, it's a very bizarre restriction and my solution was to "spoof" the TitleId of my running executable on-the-fly to gain access to these folders - don't know if this is useful for what you're trying to do but I thought I would mention it

// typedef unsigned int DWORD;
// typedef void VOID;

#define XBEBaseAddress 0x00010000

VOID SpoofAlternateTitleId(DWORD AlternateTitleId) {

	DWORD CertificateAddress = *(DWORD*)(XBEBaseAddress + 0x118);
	DWORD AlternateTitleIdsAddress = (CertificateAddress + 0x5C);

	*(DWORD*)AlternateTitleIdsAddress = AlternateTitleId;
}

 

Hope this helps

  • Thanks 1
Link to comment
Share on other sites

Feudalnate, thanks for taking the time for an amazing response. That is everything I need and more. I was aware of the source for xbmc and had a jump around the file system code, but there was a lot of abstraction and boiler plate code, so it was taking some time to figure out what was what- so I'm very glad I asked here in the same time. I'll have a deeper look at your post after work and will probably play around with it tonight.

As for my intentions, i don't have much at the minute. I am just getting used to the system for now. I had started making a very basic rendering engine, and as a mini project to get some functionality going i was just making a temporary dashboard project. At the minute this only consists of a rotating replicated tiled xbox sphere, but I needed access to the filesystem to display any useful information.

I'll definitely be recording down the above in my notes for future reference.

Thanks again! Appreciate it

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

Board Life Status


Board startup date: April 23, 2017 12:45:48
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.