Files
Rocky5 921f9fe9f8 Clean Copy
If ever adding the XBMC4Xbox source to GitHub use "git add -f -A" or it wont add all the files.
2024-01-08 19:01:29 +00:00

191 lines
4.9 KiB
C++

#include "utils/log.h"
#include "FatXDevice.h"
#include "xbox/Undocumented.h"
#include "utils/CharsetConverter.h"
typedef STRING OBJECT_STRING;
typedef PSTRING POBJECT_STRING;
#define IRP_MJ_READ 0x02
#define IRP_MJ_WRITE 0x03
struct FAT_VOLUME_HEADER {
ULONG Signature;
ULONG SerialNumber;
ULONG SectorsPerCluster;
ULONG RootDirFirstCluster;
WCHAR VolumeName[32];
};
#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
CFatXDevice::CFatXDevice(unsigned long port, unsigned long slot, void *device)
:IDevice(port, slot, device)
{
m_drive = 'H' + (char)((port << 1) | slot);
}
void CFatXDevice::LogInfo()
{
}
const char *CFatXDevice::GetFileSystem()
{
return "FATX";
}
void CFatXDevice::UnMount()
{
CLog::Log(LOGDEBUG, __FUNCTION__ " attempting unmount of drive %c:", m_drive);
// grab the symbolic link
char mountPoint[64];
sprintf(mountPoint, "\\??\\%c:" , m_drive);
STRING symLink =
{
strlen(mountPoint),
strlen(mountPoint) + 1,
mountPoint
};
// open our symbolic link to grab a handle on the filesystem
// we want to dismount
OBJECT_ATTRIBUTES obja;
HANDLE handle;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS status;
InitializeObjectAttributes(
&obja,
(POBJECT_STRING)&symLink,
OBJ_CASE_INSENSITIVE,
NULL
);
CLog::Log(LOGDEBUG, __FUNCTION__ " opening symlink %c:", m_drive);
status = NtCreateFile(
&handle,
SYNCHRONIZE,
&obja,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT
);
// if successful, we close the filesystem
if (NT_SUCCESS(status))
{
CLog::Log(LOGDEBUG, __FUNCTION__ " success opening symlink, unmounting");
status = NtFsControlFile(handle, NULL, NULL, NULL, &IoStatusBlock, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);
CLog::Log(LOGDEBUG, __FUNCTION__ " filesystem dismount returned %08x", status);
NtClose(handle);
}
CLog::Log(LOGDEBUG, __FUNCTION__ " Deleting symbolic link");
// and now we unlink our symbolic link
IoDeleteSymbolicLink(&symLink);
}
bool CFatXDevice::ReadVolumeName()
{
LARGE_INTEGER StartingOffset;
BYTE buffer[PAGE_SIZE];
FAT_VOLUME_HEADER *VolumeHeader = (FAT_VOLUME_HEADER *)buffer;
// the first sector contains the FATX drive information
StartingOffset.QuadPart = 0;
NTSTATUS Status = IoSynchronousFsdRequest(IRP_MJ_READ, (PDEVICE_OBJECT)m_device,
VolumeHeader, PAGE_SIZE, &StartingOffset);
if (NT_SUCCESS(Status))
{
// Check we have a FATX drive, and if so, read the metadata
if (VolumeHeader->Signature == 'XTAF')
{
g_charsetConverter.wToUTF8(VolumeHeader->VolumeName, m_volumeName);
return true;
}
}
return false;
}
bool CFatXDevice::Mount(const char *device)
{
char name[64];
OBJECT_STRING DeviceName;
DeviceName.Length = strlen(device)+1;
DeviceName.MaximumLength = sizeof(name)/sizeof(CHAR)-1;
DeviceName.Buffer = name;
strcpy(name, device);
//Add a back slash to so we can open the root directory
name[DeviceName.Length - 1] = '\\';
name[DeviceName.Length] = '\0';
//Attempt to open the root directory (this effectively mounts the drive).
OBJECT_ATTRIBUTES Obja;
HANDLE DirHandle;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status;
InitializeObjectAttributes(
&Obja,
(POBJECT_STRING)&DeviceName,
OBJ_CASE_INSENSITIVE,
NULL
);
CLog::Log(LOGDEBUG, __FUNCTION__" Attempting to open as FATX volume");
Status = NtCreateFile(
&DirHandle,
FILE_LIST_DIRECTORY | SYNCHRONIZE,
&Obja,
&IoStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT
);
if (NT_SUCCESS(Status))
{ // yes, we have a fatx volume
CLog::Log(LOGDEBUG, __FUNCTION__" Success opening FATX volume");
NtClose(DirHandle); //Close the handle, we no longer need it
// attempt to create the symbolic link
// we need this so that we can just use the built in filesystem stuff.
// only way around it would be to use the NtQueryFile() stuff, which is
// much uglier than FindFirstFile() et. al.
char szDosDevice[64];
sprintf(szDosDevice, "\\??\\%c:" , m_drive);
STRING DosDevice =
{
strlen(szDosDevice),
strlen(szDosDevice) + 1,
szDosDevice
};
DeviceName.Length--;
name[DeviceName.Length] = '\0';
Status = IoCreateSymbolicLink(&DosDevice, &DeviceName);
if (NT_SUCCESS(Status))
{
if (!ReadVolumeName())
{
UnMount();
return false;
}
return true;
}
}
return false;
}