227 lines
6.9 KiB
C
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;
|
|
}
|