mirror of
https://github.com/Team-Resurgent/XBMC4Xbox.git
synced 2026-08-15 11:18:13 -07:00
If ever adding the XBMC4Xbox source to GitHub use "git add -f -A" or it wont add all the files.
191 lines
4.9 KiB
C++
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;
|
|
}
|