xbox-kernel/private/ntos/dm/xbdm/dmfile.c
2020-09-30 17:17:25 +02:00

227 lines
6.9 KiB
C

/*
*
* dmfile.c
*
* Utility functions for dealing with filenames and
* files.
*
*/
#include "dmp.h"
//-----------------------------------------------------------------------------------------------------
// Table for converting drive names to object manager names
//-----------------------------------------------------------------------------------------------------
const OCHAR EDRIVE_OBNAME[]=OTEXT("\\Device\\Harddisk0\\Partition1\\Devkit");
const OCHAR SDRIVE_OBNAME[]=OTEXT("\\Device\\Harddisk0\\Partition1\\TDATA");
const OCHAR VDRIVE_OBNAME[]=OTEXT("\\Device\\Harddisk0\\Partition1\\UDATA");
const OCHAR CDROM_OBNAME[]=OTEXT("\\Device\\Cdrom0");
const OCHAR CDDEVKIT_OBNAME[]=OTEXT("\\Device\\Cdrom0\\Devkit");
const OCHAR ILLEGAL_OBNAME[]=OTEXT("\\Badpath");
const OCHAR SYMLINK_OBNAME[]=OTEXT("\\??\\0:");
typedef struct _DRIVENAME_CONVERSION_ENTRY
{
PCOSTR ObjectName;
ULONG ObjectNameLength; //Without a terminating NULL
OCHAR DriveName;
BOOL Visible;
} DRIVENAME_TABLE_ENTRY, *PDRIVENAME_TABLE_ENTRY;
DRIVENAME_TABLE_ENTRY DriveNameConversionTable[] =
{
{ EDRIVE_OBNAME, sizeof(EDRIVE_OBNAME)/sizeof(OCHAR)-1, 'E', 1 },
{ SDRIVE_OBNAME, sizeof(SDRIVE_OBNAME)/sizeof(OCHAR)-1, 'S', 1 },
{ VDRIVE_OBNAME, sizeof(VDRIVE_OBNAME)/sizeof(OCHAR)-1, 'V', 1 },
{ CDROM_OBNAME, sizeof(CDROM_OBNAME)/sizeof(OCHAR)-1, 'A', 1, },
// block the C and Y drives if they're mapped by the shell
{ ILLEGAL_OBNAME, sizeof(ILLEGAL_OBNAME)/sizeof(OCHAR)-1, 'C', 0 },
{ ILLEGAL_OBNAME, sizeof(ILLEGAL_OBNAME)/sizeof(OCHAR)-1, 'Y', 0 },
// include a drive for the use of recovery
{ CDDEVKIT_OBNAME, sizeof(CDDEVKIT_OBNAME)/sizeof(OCHAR)-1, 1, },
// and space for more
{ NULL, 0, 0, 0, },
{ NULL, 0, 0, 0, },
{ NULL, 0, 0, 0, },
{ NULL, 0, 0, 0, },
{ NULL, 0, 0, 0, },
};
void MapDebugDrive(OCHAR chDrive, PCOSTR szPrefix)
{
PDRIVENAME_TABLE_ENTRY pdte;
for(pdte = DriveNameConversionTable; pdte->ObjectName; ++pdte)
if(pdte->DriveName == chDrive)
break;
/* Only fill it in if we're prior to the last entry */
if((BYTE *)(pdte + 1) < (BYTE *)DriveNameConversionTable +
sizeof DriveNameConversionTable)
{
pdte->ObjectName = szPrefix;
if(szPrefix) {
pdte->ObjectNameLength = ocslen(szPrefix);
pdte->DriveName = chDrive;
pdte->Visible = TRUE;
} else if(pdte[1].ObjectName) {
/* We've unmapped a drive in the middle of the table */
PDRIVENAME_TABLE_ENTRY pdteLast;
for(pdteLast = pdte; pdteLast[1].ObjectName; ++pdteLast);
*pdte = *pdteLast;
pdteLast->ObjectName = NULL;
}
}
}
VOID
FObNameToFileName(
IN POBJECT_STRING objectName,
OUT LPSTR pszFileName,
int cchMax
)
/*++
Routine Description:
Uses the conversion table to subsitute the object manager
path with a common drive letter exposed by the debugger.
This routine also converts OBJECT_STRING (OCHAR) to CHAR.
--*/
{
PCOSTR pocSource;
CHAR *pcDestination = pszFileName;
ULONG ulCount;
PDRIVENAME_TABLE_ENTRY pDriveNameEntry = DriveNameConversionTable;
cchMax--; //save room for the NULL termination
while(pDriveNameEntry->ObjectName)
{
if(objectName->Length >= pDriveNameEntry->ObjectNameLength * sizeof(OCHAR))
{
if(0 == _ocsnicmp(pDriveNameEntry->ObjectName, objectName->Buffer,
pDriveNameEntry->ObjectNameLength))
{
*pcDestination++ = (char)pDriveNameEntry->DriveName;
*pcDestination++ = ':';
cchMax -= 2;
ulCount = objectName->Length-pDriveNameEntry->ObjectNameLength;
pocSource = objectName->Buffer+pDriveNameEntry->ObjectNameLength;
while(ulCount-- && (cchMax-- > 0)) *pcDestination++ = (CHAR)*pocSource++;
*pcDestination = 0; //NULL terminate
return;
}
}
pDriveNameEntry++;
}
//
// If we haven't converted it, just copy it.
//
ulCount = objectName->Length;
pocSource = objectName->Buffer;
while(ulCount-- && (cchMax-- > 0)) *pcDestination++ = (CHAR)*pocSource++;
*pcDestination = 0; //NULL terminate
return;
}
BOOL FFileNameToObName(LPCSTR sz, OCHAR *osz, int cchMax)
{
int ich;
OCHAR chDrive;
PCOSTR oszPrefix;
PDRIVENAME_TABLE_ENTRY pdte;
if(!sz)
return FALSE;
/* The file name must start with drive letter, then ':' then '\' for us
* to consider it valid. If we have a filename of the form "XC:\...",
* we'll accept that as well */
if(sz[0] == 'x' || sz[0] == 'X' && sz[1] != ':')
++sz;
if(sz[1] != ':' || sz[2] != '\\')
return FALSE;
chDrive = sz[0];
if(chDrive >= 'a' && chDrive <= 'z')
chDrive -= 'a' - 'A';
/* Look in the table to find a map for this drive letter */
oszPrefix = NULL;
for(pdte = DriveNameConversionTable; pdte->ObjectName; ++pdte)
if(chDrive == pdte->DriveName) {
oszPrefix = pdte->ObjectName;
chDrive = 0;
break;
}
/* If we didn't find a match, we use DosDevices, as long as it's a valid
* drive */
if(!oszPrefix) {
if(chDrive < 'A' || chDrive > 'Z')
return FALSE;
oszPrefix = SYMLINK_OBNAME;
}
for(ich = 0; oszPrefix[ich]; ++ich)
osz[ich] = oszPrefix[ich];
if(chDrive)
osz[ich - 2] = chDrive;
sz += 2;
while(*sz && ich < cchMax)
osz[ich++] = *sz++;
osz[ich] = 0;
return TRUE;
}
NTSTATUS
FCreateFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN LPCSTR FileName,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions
)
/*++
Routine Description:
Wraps CreateFile to use ANSI names passed over the debugger protocol.
1) Do any name conversion to the Object Manager Name.
2) Initialize OBJECT_ATTRIBUTES structure.
3) Call NtCreateFile
--*/
{
OBJECT_STRING objectName;
OBJECT_ATTRIBUTES objectAttributes;
IO_STATUS_BLOCK ioStatusBlock;
OCHAR oszObName[MAX_OBJ_PATH+1];
NTSTATUS status;
if(!FFileNameToObName(FileName, oszObName, sizeof(oszObName)/sizeof(OCHAR)))
{
status = STATUS_NO_SUCH_FILE;
} else
{
RtlInitObjectString(&objectName, oszObName);
InitializeObjectAttributes(
&objectAttributes,
&objectName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
);
status = NtCreateFile(
FileHandle,
DesiredAccess,
&objectAttributes,
&ioStatusBlock,
AllocationSize,
FileAttributes,
ShareAccess,
CreateDisposition,
CreateOptions);
}
return status;
}