NT4/private/windows/cmd/display.c
2020-09-30 17:12:29 +02:00

1299 lines
27 KiB
C

#include "cmd.h"
extern TCHAR ThousandSeparator[];
STATUS
FormatFileSize(
IN DWORD rgfSwitchs,
IN PLARGE_INTEGER FileSize,
IN DWORD Width,
OUT PTCHAR FormattedSize
);
// Entry is displayed.
// If not /b,
// Cursor is left at end of entry on screen.
// FileCnt, FileCntTotal, FileSiz, FileSizTotal are updated.
// If /b,
// Cursor is left at beginning of next line.
// Cnt's and Siz's aren't updated.
//
// Create a manager for these totals
#define DIR_SIZE_WIDTH 17
#define DIR_OLD_TO_SIZE 14
#define DIR_OLD_PAST_SIZE 32
#define DIR_NEW_DIR_PAST_TIME_DATE 24
#define DIR_NEW_FILE_PAST_TIME_DATE 21
#define DIR_NEW_PAST_SIZE 39
extern TCHAR Fmt00[], Fmt01[], Fmt03[], Fmt08[], Fmt09[], Fmt14[], Fmt19[], Fmt26[] ;
extern BOOL CtrlCSeen;
BOOLEAN GetDrive( PTCHAR , PTCHAR );
STATUS
DisplayFileListHeader(
IN PSCREEN pscr,
IN ULONG rgfSwitchs,
IN PTCHAR pszDir
)
/*++
Routine Description:
Display the header for a complete file list. This will include
the current directory.
Arguments:
pscr - screen handle
rgfSwtichs - switchs from command line.
pszDir - directory to print.
Return Value:
--*/
{
//
// If /b then do not display the header
// you want just a file list.
//
if (rgfSwitchs & BAREFORMATSWITCH) {
return( SUCCESS );
}
if (rgfSwitchs & RECURSESWITCH) {
//
// recursing down a tree so put a blank line before header
// and last listing
//
CHECKSTATUS ( WriteEol( pscr ));
}
return( WriteMsgString(pscr, MSG_DIR_OF, ONEARG, pszDir) );
}
STATUS
DisplayFileList (
IN PSCREEN pscr,
OUT PULONG pcffTotal,
OUT PLARGE_INTEGER pcbFileTotal,
IN ULONG rgfSwitchs,
IN ULONG dwTimeType,
IN PFS pfsFiles
)
/*++
Routine Description:
Displays a list of files and directories in the specified format.
Arguments:
pscr - screen handle
rgfSwitchs - command line switch (controls formating)
pfsFile - pointer to files to display
Return Value:
return SUCCESS
FAILURE
pcffTotal - number of files displayed
pcbFileTotal - number of bytes for all files displayed.
--*/
{
ULONG cff;
ULONG irgpff;
ULONG cffColMax;
ULONG crowMax;
ULONG crow, cffCol;
STATUS rc=SUCCESS;
BOOL notPrintedEarly;
//
// check if we already printed early
//
notPrintedEarly = (rgfSwitchs & (RECURSESWITCH | WIDEFORMATSWITCH | SORTDOWNFORMATSWITCH | SORTSWITCH));
//
// Number of things we are going to display
//
cff = pfsFiles->cff;
//
// Do not display any header information if there are no files
//
if ((notPrintedEarly && cff == 0) || (!notPrintedEarly && pfsFiles->cffDisplayed == 0)) {
return( SUCCESS );
} else {
//
// if it is not the bare format (no header, no tail)
// then display which directory, volume etc.
//
if (notPrintedEarly && !(rgfSwitchs & BAREFORMATSWITCH )) {
CHECKSTATUS(DisplayFileListHeader(pscr, rgfSwitchs, pfsFiles->pszDir ));
}
}
//
// Setting tabs to 0 forces single line output
//
SetTab(pscr, 0);
//
// Compute the tab spacing on the line from the size of the file names.
// add 3 spaces to seperate each field
//
// If multiple files per line then base tabs on the max file/dir size
//
if (rgfSwitchs & WIDEFORMATSWITCH) {
SetTab(pscr, (USHORT)(GetMaxCbFileSize( pfsFiles ) + 3));
}
DEBUG((ICGRP, DISLVL, "\t count of files %d",cff));
if (rgfSwitchs & SORTDOWNFORMATSWITCH) {
//
// no. of files on a line.
//
cffColMax = (pscr->ccolMax / pscr->ccolTab);
//
// number of row required for entire list
//
if (cffColMax == 0) // wider than a line
goto abort_wide; // abort wide format for this list
else
crowMax = (cff + cffColMax) / cffColMax;
//
// move down each rown picking the elements cffCols aport down the list.
//
for (crow = 0; crow < crowMax; crow++) {
for (cffCol = 0, irgpff = crow;
cffCol < cffColMax;
cffCol++, irgpff += crowMax) {
if (CtrlCSeen) {
return( FAILURE );
}
if (irgpff < cff) {
rc = DisplayFile(pscr,
rgfSwitchs,
dwTimeType,
&pfsFiles->cbFileTotal,
pfsFiles,
pfsFiles->prgpff[irgpff]);
if (rc != SUCCESS) {
return( rc );
}
} else {
//
// If we have run past the end of the file list terminate
// line and start over back inside the line
//
CHECKSTATUS( WriteEol(pscr) );
break;
}
}
}
} else {
if (notPrintedEarly) {
abort_wide:
if (CtrlCSeen) {
return( FAILURE );
}
for(irgpff = 0; irgpff < cff; irgpff++) {
if (CtrlCSeen) {
return( FAILURE );
}
rc = DisplayFile(pscr,
rgfSwitchs,
dwTimeType,
&pfsFiles->cbFileTotal,
pfsFiles,
pfsFiles->prgpff[irgpff]);
if (rc != SUCCESS) {
return( rc );
}
}
}
}
//
// Before writing the tailer make sure buffer is
// empty. (Could have something from doing WIDEFORMATSWITCH
//
CHECKSTATUS( WriteFlushAndEol( pscr ) );
pcbFileTotal->QuadPart = pfsFiles->cbFileTotal.QuadPart + pcbFileTotal->QuadPart;
*pcffTotal += pfsFiles->cffDisplayed;
if (!(rgfSwitchs & BAREFORMATSWITCH)) {
CHECKSTATUS( DisplayFileSizes(pscr, &pfsFiles->cbFileTotal, pfsFiles->cffDisplayed, rgfSwitchs) );
}
return( SUCCESS );
}
STATUS
DisplayFile (
IN PSCREEN pscr,
IN ULONG rgfSwitchs,
IN ULONG dwTimeType,
OUT PLARGE_INTEGER pcbFileTotal,
IN PFS pfs,
IN PFF pff
)
/*++
Routine Description:
Displays a single file in 1 of several formats.
Arguments:
pscr - screen handle
rgfSwitchs - command line switch (controls formating)
pfs - current directory (used for full path information)
pff - current file
Return Value:
return SUCCESS
FAILURE
pcbFileTotal - number of bytes for displayed file is added to this large integer.
--*/
{
STATUS rc = SUCCESS;
ULONG obFileName;
PWIN32_FIND_DATA pdata;
LARGE_INTEGER cbFile;
pdata = &(pff->data);
//
// Do any checks here to see if file should not be printed.
//
cbFile.LowPart = pdata->nFileSizeLow;
cbFile.HighPart = pdata->nFileSizeHigh;
if (rgfSwitchs & BAREFORMATSWITCH) {
rc = DisplayBare(pscr, rgfSwitchs, pfs->pszDir, pdata);
} else {
// dos5 has a call to DisplayNext here (to move to next field)
// I do this inside of DisplayWide. May want to change this.
if (rgfSwitchs & WIDEFORMATSWITCH) {
rc = DisplayWide(pscr, rgfSwitchs, pdata);
} else {
if ((rgfSwitchs & NEWFORMATSWITCH) ||
(rgfSwitchs & SHORTFORMATSWITCH)) {
rc = DisplayNewRest(pscr, dwTimeType, rgfSwitchs, pdata);
obFileName = 32;
if (rc == SUCCESS) {
if (rgfSwitchs & SHORTFORMATSWITCH) {
if (pff->obAlternate) {
FillToCol(pscr, DIR_NEW_PAST_SIZE);
rc = DisplayDotForm(pscr,
rgfSwitchs,
&(pdata->cFileName[pff->obAlternate]));
}
FillToCol(pscr, DIR_NEW_PAST_SIZE + 16);
rc = DisplayDotForm(pscr, rgfSwitchs, pdata->cFileName);
} else {
FillToCol(pscr, DIR_NEW_PAST_SIZE);
rc = DisplayDotForm(pscr, rgfSwitchs, pdata->cFileName);
}
}
} else {
rc = DisplaySpacedForm(pscr, rgfSwitchs, pdata);
if (rc == SUCCESS) {
FillToCol(pscr, DIR_OLD_TO_SIZE);
rc = DisplayOldRest(pscr, dwTimeType, rgfSwitchs, pdata);
}
}
rc = WriteEol(pscr);
}
}
if (rc == SUCCESS) {
pcbFileTotal->QuadPart = cbFile.QuadPart + pcbFileTotal->QuadPart;
pfs->cffDisplayed += 1;
}
return( rc );
}
STATUS
DisplayBare (
IN PSCREEN pscr,
IN ULONG rgfSwitchs,
IN PTCHAR pszDir,
IN PWIN32_FIND_DATA pdata
)
/*++
Routine Description:
Displays a single file in bare format. This is with no header, tail and
no file information other then it's name. If it is a recursive catalog
then the full file path is displayed. This mode is used to feed other
utitilies such as grep.
Arguments:
pscr - screen handle
rgfSwitchs - command line switch (controls formating)
pszDir - current directory (used for full path information)
pdata - data gotten back from FindNext API
Return Value:
return SUCCESS
FAILURE
--*/
{
TCHAR szDirString[MAX_PATH + 2];
STATUS rc;
DEBUG((ICGRP, DISLVL, "DisplayBare `%ws'", pdata->cFileName));
//
// Do not display '.' and '..' in a bare listing
//
if ((_tcscmp(pdata->cFileName, TEXT(".")) == 0) || (_tcscmp(pdata->cFileName, TEXT("..")) == 0)) {
return( SUCCESS );
}
//
// If we are recursing down then display full name else just the
// name in the find buffer
//
//
// BUGBUG What happens if you can fit the directory on the line
// but you can not fit the filename. construct the full
// name locally before you try and write it out.
//
if (rgfSwitchs & RECURSESWITCH) {
mystrcpy(szDirString, pszDir);
if (rgfSwitchs & LOWERCASEFORMATSWITCH) {
//
// BUGBUG Unicode translation issue!
//
_tcslwr(szDirString);
}
CHECKSTATUS( WriteString(pscr, szDirString) );
if (*lastc(szDirString) != BSLASH) {
CHECKSTATUS( WriteString(pscr, TEXT("\\")));
}
}
if ((rc = DisplayDotForm(pscr, rgfSwitchs, pdata->cFileName)) == SUCCESS) {
return( WriteEol(pscr));
} else {
return( rc );
}
}
VOID
SetDotForm (
IN PTCHAR pszFileName,
IN ULONG rgfSwitchs
)
/*++
Routine Description:
If FATFORMAT and there is a '.' with a blank extension, the '.' is
removed so it does not get displayed. This is by convension and is very
silly but that's life. Also a lower case mapping is done.
Arguments:
pszFileName - file to remove '.' from.
rgfSwitchs - command line switches (tell wither in FATFORMAT or not)
Return Value:
return SUCCESS
FAILURE
--*/
{
PTCHAR pszT;
if (rgfSwitchs & FATFORMAT) {
//
// Under DOS if there is a . with a blank extension
// then do not display '.'.
//
if (pszT = mystrrchr(pszFileName, DOT)) {
//
// FAT will not allow foo. ba as a valid name so
// see of any blanks in extensions and if so then assume
// the entire extension is blank
//
if (mystrchr(pszT, SPACE)) {
*pszT = NULLC;
}
}
}
}
STATUS
DisplayDotForm (
IN PSCREEN pscr,
IN ULONG rgfSwitchs,
IN PTCHAR pszFileName
)
/*++
Routine Description:
Displays a single file in DOT form (see SetDotForm).
Arguments:
pscr - screen handle
rgfSwitchs - command line switch (tell wither to lowercase or not)
pdata - data gotten back from FindNext API
Return Value:
return SUCCESS
FAILURE
--*/
{
TCHAR szFileName[MAX_PATH + 2];
mystrcpy(szFileName, pszFileName);
SetDotForm(szFileName, rgfSwitchs);
if (rgfSwitchs & LOWERCASEFORMATSWITCH) {
_tcslwr(szFileName);
}
return( WriteString( pscr, szFileName ) );
}
STATUS
DisplaySpacedForm(
IN PSCREEN pscr,
IN ULONG rgfSwitchs,
IN PWIN32_FIND_DATA pdata
)
/*++
Routine Description:
Display name in expanded format. name <spaces> ext.
This is ONLY called for a FAT partition. This is controled by the
NEWFORMATSWITCH. This is set for any file system other then FAT. There
is no OLDFORMATSWITCH so we can never be called on an HPFS or NTFS
volume. If this is changed then the entire spacing of the display will
be blown due to non-fixed max file names. (i.e. 8.3).
Arguments:
pscr - screen handle
rgfSwitchs - command line switch (tell wither to lowercase or not)
pdata - data gotten back from FindNext API
Return Value:
return SUCCESS
FAILURE
--*/
{
TCHAR szFileName[MAX_PATH + 2];
PTCHAR pszExt, pszName;
USHORT cbName;
#if defined(JAPAN) && defined(UNICODE)
int i;
int l;
#endif /* defined(JAPAN) && defined(UNICODE) */
mytcsnset(szFileName, SPACE, MAX_PATH + 2);
pszName = pdata->cFileName;
cbName = 0;
if ((_tcscmp(pszName, TEXT(".")) == 0) || (_tcscmp(pszName, TEXT("..")) == 0)) {
//
// If it is either of these then do not get it
// confused with extensions
//
pszExt = NULL;
} else {
pszExt = mystrrchr(pszName, (int)DOT);
cbName = (USHORT)(pszExt - pszName)*sizeof(WCHAR);
}
//
// if no extension or name is extension only
//
if ((pszExt == NULL) || (cbName == 0)) {
cbName = (USHORT)_tcslen(pszName)*sizeof(TCHAR);
}
memcpy(szFileName, pszName, cbName );
#if defined(JAPAN) && defined(UNICODE)
//
// If we had an extension then print it after
// all the spaces
//
i = 9;
for (l=0 ; l<8 ; l++) {
if (IsFullWidth(szFileName[l]))
i--;
}
if (pszExt) {
mystrcpy(szFileName + i, pszExt + 1);
}
//
// terminate at max end for a FAT name
//
szFileName[i+3] = NULLC;
if (pszExt) {
//
// Only 1 of three can be full width, since 3/2=1.
// If the first isn't, only the second could be.
//
if (IsFullWidth(*(pszExt+1)) || IsFullWidth(*(pszExt+2)))
szFileName[i+2] = NULLC;
}
#else /* defined(JAPAN) && defined(UNICODE) */
if (pszExt) {
//
// move pszExt past dot. use 9 not 8 to pass
// over 1 space between name and extension
//
mystrcpy(szFileName + 9, pszExt + 1);
}
//
// terminate at max end for a FAT name
//
szFileName[12] = NULLC;
#endif /* defined(JAPAN) && defined(UNICODE) */
if (rgfSwitchs & LOWERCASEFORMATSWITCH) {
//
// BUGBUG this _tcslwr is not dbcs will have to covert later
//
_tcslwr(szFileName);
}
return( WriteString( pscr, szFileName ) );
}
STATUS
DisplayOldRest(
IN PSCREEN pscr,
IN ULONG dwTimeType,
IN ULONG rgfSwitchs,
IN PWIN32_FIND_DATA pdata
)
/*++
Routine Description:
Used with DisplaySpacedForm to write out file information such as size
and last write time.
Arguments:
pscr - screen handle
pdata - data gotten back from FindNext API
Return Value:
return SUCCESS
FAILURE
--*/
{
TCHAR szSize [ MAX_PATH];
DWORD Length;
LARGE_INTEGER FileSize;
//
// If directory put <DIR> after name instead of file size
//
if (pdata->dwFileAttributes & A_D) {
CHECKSTATUS( WriteMsgString(pscr, MSG_DIR,0) );
} else {
FileSize.LowPart = pdata->nFileSizeLow;
FileSize.HighPart = pdata->nFileSizeHigh;
Length = FormatFileSize( rgfSwitchs, &FileSize, 0, szSize );
if (Length < DIR_SIZE_WIDTH) {
FillToCol(pscr, DIR_OLD_TO_SIZE+DIR_SIZE_WIDTH-Length);
}
WriteFmtString(pscr, Fmt14, (PVOID)szSize);
}
FillToCol(pscr, DIR_OLD_PAST_SIZE);
return( DisplayTimeDate( pscr, dwTimeType, pdata) );
}
STATUS
DisplayTimeDate (
IN PSCREEN pscr,
IN ULONG dwTimeType,
IN PWIN32_FIND_DATA pdata
)
/*++
Routine Description:
Display time/data information for a file
Arguments:
pscr - screen handle
pdata - data gotten back from FindNext API
Return Value:
return SUCCESS
FAILURE
--*/
{
struct tm FileTime;
TCHAR szT[MAX_PATH + 2];
FILETIME ft;
switch (dwTimeType) {
case LAST_ACCESS_TIME:
ft = pdata->ftLastAccessTime;
break;
case LAST_WRITE_TIME:
ft = pdata->ftLastWriteTime;
break;
case CREATE_TIME:
ft = pdata->ftCreationTime;
break;
}
if (ConvertFileTimeToTime( &ft, &FileTime )) {
PrintDate(&FileTime, PD_DIR, szT, MAX_PATH) ;
CHECKSTATUS( WriteFmtString(pscr, TEXT("%s "), (PVOID)szT));
PrintTime(&FileTime, PT_DIR, szT, MAX_PATH) ;
CHECKSTATUS( WriteFmtString(pscr, TEXT("%s "), (PVOID)szT) );
} else {
return( FAILURE );
}
return( SUCCESS );
}
STATUS
DisplayNewRest(
IN PSCREEN pscr,
IN ULONG dwTimeType,
IN ULONG rgfSwitchs,
IN PWIN32_FIND_DATA pdata
)
/*++
Routine Description:
Display file information for new format (comes before file name).
This is used with NEWFORMATSWITCH which is active on any non-FAT
partition.
Arguments:
pscr - screen handle
pdata - data gotten back from FindNext API
Return Value:
return SUCCESS
FAILURE
--*/
{
STATUS rc;
LARGE_INTEGER FileSize;
rc = DisplayTimeDate( pscr, dwTimeType, pdata);
if (rc == SUCCESS) {
//
// If directory put <DIR> after name instead of file size
//
if (pdata->dwFileAttributes & A_D) {
FillToCol(pscr, DIR_NEW_DIR_PAST_TIME_DATE);
rc = WriteMsgString(pscr, MSG_DIR,0);
} else {
TCHAR szSize [ MAX_PATH];
DWORD Length;
FillToCol(pscr, DIR_NEW_FILE_PAST_TIME_DATE);
FileSize.LowPart = pdata->nFileSizeLow;
FileSize.HighPart = pdata->nFileSizeHigh;
Length = FormatFileSize( rgfSwitchs, &FileSize, 0, szSize );
if (Length < DIR_SIZE_WIDTH) {
FillToCol(pscr, DIR_NEW_FILE_PAST_TIME_DATE+DIR_SIZE_WIDTH-Length);
}
rc = WriteFmtString(pscr, Fmt14, (PVOID)szSize);
}
}
return( rc );
}
STATUS
DisplayWide (
IN PSCREEN pscr,
IN ULONG rgfSwitchs,
IN PWIN32_FIND_DATA pdata
)
/*++
Routine Description:
Displays a single file used in the /w or /d switchs. That is with a
multiple file column display.
Arguments:
pscr - screen handle
rgfSwitchs - command line switchs (controls formating)
pdata - data gotten back from FindNext API
Return Value:
return SUCCESS
FAILURE
--*/
{
TCHAR szFileName[MAX_PATH + 2];
PTCHAR pszFmt;
STATUS rc;
pszFmt = Fmt14; // assume non-dir format
//
// Provides [] around directories
//
if (pdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
pszFmt = Fmt09;
}
mystrcpy(szFileName, pdata->cFileName);
SetDotForm(szFileName, rgfSwitchs);
if (rgfSwitchs & LOWERCASEFORMATSWITCH) {
//
// BUGBUG this _tcslwr is not dbcs will have to covert later
//
_tcslwr(szFileName);
}
rc = WriteFmtString(pscr, pszFmt, szFileName);
if (rc == SUCCESS) {
rc = WriteTab(pscr);
}
return( rc );
}
USHORT
GetMaxCbFileSize(
IN PFS pfsFiles
)
/*++
Routine Description:
Determines the longest string size in a file list. Used in computing
the number of possible columns in a catalog listing.
Arguments:
pfsFiles - file list.
Return Value:
return # of characters in largest file name
--*/
{
ULONG cff;
ULONG irgff;
USHORT cb;
PFF pffCur;
cb = 0;
for(irgff = 0, cff = pfsFiles->cff, pffCur = pfsFiles->prgpff[irgff];
irgff < cff;
irgff++) {
#if defined(JAPAN) && defined(UNICODE)
cb = max(cb, (USHORT)SizeOfHalfWidthString(((pfsFiles->prgpff[irgff])->data).cFileName));
#else /* defined(JAPAN) && defined(UNICODE) */
cb = max(cb, (USHORT)mystrlen( ((pfsFiles->prgpff[irgff])->data).cFileName ));
#endif /* defined(JAPAN) && defined(UNICODE) */
}
return( cb );
}
STATUS
DisplayFileSizes(
IN PSCREEN pscr,
IN PLARGE_INTEGER cbFileTotal,
IN ULONG cffTotal,
IN ULONG rgfSwitchs
)
/*++
Routine Description:
Does tailer display of # of files displayed and # of bytes
in all files displayed.
Arguments:
pscr - screen handle
cbFileTotal - bytes in all files displayed
cffTotal - number of files displayed.
Return Value:
return SUCCESS
FAILURE
--*/
{
TCHAR szSize [ MAX_PATH];
FillToCol(pscr, 6);
FormatFileSize( rgfSwitchs, cbFileTotal, 14, szSize );
return( WriteMsgString(pscr, MSG_FILES_COUNT_FREE, TWOARGS,
(ULONG)argstr1(TEXT("%5lu"), cffTotal ),
szSize ) );
}
STATUS
DisplayTotals(
IN PSCREEN pscr,
IN ULONG cffTotal,
IN PLARGE_INTEGER cbFileTotal,
IN ULONG rgfSwitchs
)
/*++
Routine Description:
Does tailer display of # of files displayed and # of bytes
in all files displayed.
Arguments:
pscr - screen handle
cbFileTotal - bytes in all files displayed
cffTotal - number of files displayed.
Return Value:
return SUCCESS
FAILURE
--*/
{
STATUS rc;
if ((rc = WriteMsgString(pscr, MSG_FILE_TOTAL, 0) ) == SUCCESS ) {
if ((rc = DisplayFileSizes( pscr, cbFileTotal, cffTotal, rgfSwitchs )) == SUCCESS) {
rc = WriteFlush(pscr) ;
}
}
return ( rc );
}
STATUS
DisplayDiskFreeSpace(
IN PSCREEN pscr,
IN PTCHAR pszDrive,
IN ULONG rgfSwitchs
)
/*++
Routine Description:
Displays total free space on volume.
Arguments:
pscr - screen handle
pszDrive - volume drive letter
Return Value:
return SUCCESS
FAILURE
--*/
{
TCHAR szPath [ MAX_PATH + 2];
DWORD dwSectorsPerCluster;
DWORD dwBytesPerSector;
DWORD dwNumberOfFreeClusters;
DWORD dwTotalNumberOfClusters;
LARGE_INTEGER cbFree;
DWORD Length;
CheckPause( pscr );
//
// If no drive do not print total
//
if (!GetDrive(pszDrive, szPath)) {
return ( SUCCESS );
}
mystrcat(szPath, TEXT("\\"));
cbFree.LowPart = cbFree.HighPart = 0;
if (GetDiskFreeSpace( szPath,&dwSectorsPerCluster, &dwBytesPerSector,
&dwNumberOfFreeClusters, &dwTotalNumberOfClusters)) {
cbFree.QuadPart = UInt32x32To64(dwSectorsPerCluster, dwNumberOfFreeClusters);
cbFree.QuadPart = cbFree.QuadPart * dwBytesPerSector;
}
Length = FormatFileSize( rgfSwitchs, &cbFree, 0, szPath );
if (Length <= DIR_SIZE_WIDTH) {
FillToCol(pscr, DIR_SIZE_WIDTH-Length);
}
return( WriteMsgString(pscr,
MSG_FILES_TOTAL_FREE,
ONEARG,
szPath ));
}
STATUS
DisplayVolInfo(
IN PSCREEN pscr,
IN PTCHAR pszDrive
)
/*++
Routine Description:
Displays the volume trailer information. Used before switching to
a catalog of another drive (dir a:* b:*)
Arguments:
pscr - screen handle
pszDrive - volume drive letter
Return Value:
return SUCCESS
FAILURE
--*/
{
DWORD Vsn[2];
TCHAR szVolName[MAX_PATH + 2];
TCHAR szVolRoot[MAX_PATH + 2];
TCHAR szT[256];
STATUS rc = SUCCESS;
if (!GetDrive(pszDrive, szVolRoot)) {
return( SUCCESS );
}
mystrcat(szVolRoot, TEXT("\\"));
if (!GetVolumeInformation(szVolRoot,szVolName,MAX_PATH,Vsn,NULL,NULL,NULL,0)) {
DEBUG((ICGRP, DISLVL, "DisplayVolInfo: GetVolumeInformation ret'd %d", GetLastError())) ;
// don't fail if we're a substed drive
if (GetLastError() == ERROR_DIR_NOT_ROOT) {
return SUCCESS;
}
PutStdErr(GetLastError(), NOARGS);
return( FAILURE ) ;
} else {
if (szVolRoot[0] == BSLASH) {
*lastc(szVolRoot) = NULLC;
} else {
szVolRoot[1] = NULLC;
}
if (szVolName[0]) {
rc = WriteMsgString(pscr,
MSG_DR_VOL_LABEL,
TWOARGS,
argstr1(TEXT("%s"), (ULONG)(szVolRoot)),
argstr2(TEXT("%s"), (ULONG)szVolName ) ) ;
} else {
rc = WriteMsgString(pscr,
MSG_HAS_NO_LABEL,
ONEARG,
argstr1(TEXT("%s"), (ULONG)(szVolRoot)) ) ;
}
if ((rc == SUCCESS) && (Vsn)) {
wsprintf(szT,Fmt26,(Vsn[0] & 0xffff0000)>>16, (Vsn[0] & 0xffff) );
rc = WriteMsgString(pscr, MSG_DR_VOL_SERIAL, ONEARG, szT);
}
}
return( rc );
}
ULONG
FormatFileSize(
IN DWORD rgfSwitchs,
IN PLARGE_INTEGER FileSize,
IN DWORD Width,
OUT PTCHAR FormattedSize
)
{
TCHAR Buffer[ 100 ];
PTCHAR s, s1;
ULONG DigitIndex, Digit;
ULONG nThousandSeparator;
ULONGLONG Size;
nThousandSeparator = _tcslen(ThousandSeparator);
s = &Buffer[ 99 ];
*s = TEXT('\0');
DigitIndex = 0;
Size = FileSize->QuadPart;
while (Size != 0) {
Digit = (ULONG)(Size % 10);
Size = Size / 10;
*--s = (TCHAR)(TEXT('0') + Digit);
if ((++DigitIndex % 3) == 0 && (rgfSwitchs & THOUSANDSEPSWITCH)) {
// If non-null Thousand separator, insert it.
if (nThousandSeparator) {
s -= nThousandSeparator;
_tcsncpy(s, ThousandSeparator, nThousandSeparator);
}
}
}
if (DigitIndex == 0) {
*--s = TEXT('0');
}
else
if ((rgfSwitchs & THOUSANDSEPSWITCH) && !_tcsncmp(s, ThousandSeparator, nThousandSeparator)) {
s += nThousandSeparator;
}
Size = _tcslen( s );
if (Width != 0 && Size < Width) {
s1 = FormattedSize;
while (Width > Size) {
Width -= 1;
*s1++ = SPACE;
}
_tcscpy( s1, s );
} else {
_tcscpy( FormattedSize, s );
}
return _tcslen( FormattedSize );
}