/* * * 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; }