* 27-Feb-2005 (Konstantinos Paliouras <squarious@gmail.com>)
* Implemented all the switches that were missing, and made
* the ros dir very similar to windows dir. Major part of
- * the code is rewritten. /p is removed, to be rewriten in
+ * the code is rewritten. /p is removed, to be rewritten in
* the main cmd code.
*
* 1-Jul-2004 (Brandon Turner <turnerb7@msu.edu>)
*
* 3-feb-2007 (Paolo Devoti devotip at gmail)
* Removed variables formerly in use to handle pagination
- * Pagination belongs to ConOutPrintfPaging
- * Removed already commented out code of old pagination
+ * Pagination belongs to ConOutPrintfPaging
+ * Removed already commented out code of old pagination
+ *
+ * 25-Aug-2015 (Pierre Schweitzer)
+ * Implemented /R switch
*/
-#include <precomp.h>
+#include "precomp.h"
#ifdef INCLUDE_CMD_DIR
-
-
/* Time Field enumeration */
enum ETimeField
{
- TF_CREATIONDATE = 0,
- TF_MODIFIEDDATE = 1,
- TF_LASTACCESSEDDATE = 2
+ TF_CREATIONDATE = 0,
+ TF_MODIFIEDDATE = 1,
+ TF_LASTACCESSEDDATE = 2
};
/* Ordered by enumeration */
enum EOrderBy
{
- ORDER_NAME = 0,
- ORDER_SIZE = 1,
- ORDER_DIRECTORY = 2,
- ORDER_EXTENSION = 3,
- ORDER_TIME = 4
+ ORDER_NAME = 0,
+ ORDER_SIZE = 1,
+ ORDER_DIRECTORY = 2,
+ ORDER_EXTENSION = 3,
+ ORDER_TIME = 4
};
/* The struct for holding the switches */
typedef struct _DirSwitchesFlags
{
- BOOL bBareFormat; /* Bare Format */
- BOOL bTSeperator; /* Thousands seperator */
- BOOL bWideList; /* Wide list format */
- BOOL bWideListColSort; /* Wide list format but sorted by column */
- BOOL bLowerCase; /* Uses lower case */
- BOOL bNewLongList; /* New long list */
- BOOL bPause; /* Pause per page */
- BOOL bUser; /* Displays the owner of file */
- BOOL bRecursive; /* Displays files in specified directory and all sub */
- BOOL bShortName; /* Displays the sort name of files if exist */
- BOOL b4Digit; /* Four digit year */
- struct
- {
- DWORD dwAttribVal; /* The desired state of attribute */
- DWORD dwAttribMask; /* Which attributes to check */
- } stAttribs; /* Displays files with this attributes only */
- struct
- {
- enum EOrderBy eCriteria[3]; /* Criterias used to order by */
- BOOL bCriteriaRev[3]; /* If the criteria is in reversed order */
- short sCriteriaCount; /* The quantity of criterias */
- } stOrderBy; /* Ordered by criterias */
- struct
- {
- enum ETimeField eTimeField; /* The time field that will be used for */
- } stTimeField; /* The time field to display or use for sorting */
+ BOOL bBareFormat; /* Bare Format */
+ BOOL bTSeparator; /* Thousands separator */
+ BOOL bWideList; /* Wide list format */
+ BOOL bWideListColSort; /* Wide list format but sorted by column */
+ BOOL bLowerCase; /* Uses lower case */
+ BOOL bNewLongList; /* New long list */
+ BOOL bPause; /* Pause per page */
+ BOOL bUser; /* Displays the owner of file */
+ BOOL bRecursive; /* Displays files in specified directory and all sub */
+ BOOL bShortName; /* Displays the sort name of files if exist */
+ BOOL b4Digit; /* Four digit year */
+ BOOL bDataStreams; /* Displays alternate data streams */
+ struct
+ {
+ DWORD dwAttribVal; /* The desired state of attribute */
+ DWORD dwAttribMask; /* Which attributes to check */
+ } stAttribs; /* Displays files with this attributes only */
+ struct
+ {
+ enum EOrderBy eCriteria[3]; /* Criterias used to order by */
+ BOOL bCriteriaRev[3]; /* If the criteria is in reversed order */
+ short sCriteriaCount; /* The quantity of criterias */
+ } stOrderBy; /* Ordered by criterias */
+ struct
+ {
+ enum ETimeField eTimeField; /* The time field that will be used for */
+ } stTimeField; /* The time field to display or use for sorting */
} DIRSWITCHFLAGS, *LPDIRSWITCHFLAGS;
+typedef struct _DIRFINDSTREAMNODE
+{
+ WIN32_FIND_STREAM_DATA stStreamInfo;
+ struct _DIRFINDSTREAMNODE *ptrNext;
+} DIRFINDSTREAMNODE, *PDIRFINDSTREAMNODE;
+
+typedef struct _DIRFINDINFO
+{
+ WIN32_FIND_DATA stFindInfo;
+ PDIRFINDSTREAMNODE ptrHead;
+} DIRFINDINFO, *PDIRFINDINFO;
typedef struct _DIRFINDLISTNODE
{
- WIN32_FIND_DATA stFindInfo;
- struct _DIRFINDLISTNODE *ptrNext;
+ DIRFINDINFO stInfo;
+ struct _DIRFINDLISTNODE *ptrNext;
} DIRFINDLISTNODE, *PDIRFINDLISTNODE;
-
typedef BOOL
(WINAPI *PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
-
/* Globally save the # of dirs, files and bytes,
- * probabaly later pass them to functions. Rob Lake */
+ * probably later pass them to functions. Rob Lake */
static ULONG recurse_dir_cnt;
static ULONG recurse_file_cnt;
static ULONGLONG recurse_bytes;
-
/*
* help
*
static VOID
DirHelp(VOID)
{
- ConOutResPaging(TRUE, STRING_DIR_HELP1);
+ ConOutResPaging(TRUE, STRING_DIR_HELP1);
}
-
-
/*
* DirReadParameters
*
* Parse the parameters and switches of the command line and exports them
*/
static BOOL
-DirReadParam(LPTSTR Line, /* [IN] The line with the parameters & switches */
- LPTSTR** params, /* [OUT] The parameters after parsing */
- LPINT entries, /* [OUT] The number of parameters after parsing */
- LPDIRSWITCHFLAGS lpFlags) /* [IN/OUT] The flags after calculating switches */
+DirReadParam(LPTSTR Line, /* [IN] The line with the parameters & switches */
+ LPTSTR** params, /* [OUT] The parameters after parsing */
+ LPINT entries, /* [OUT] The number of parameters after parsing */
+ LPDIRSWITCHFLAGS lpFlags) /* [IN/OUT] The flags after calculating switches */
{
- TCHAR cCurSwitch; /* The current switch */
- TCHAR cCurChar; /* Current examing character */
- TCHAR cCurUChar; /* Current upper examing character */
- BOOL bNegative; /* Negative switch */
- BOOL bPNegative; /* Negative switch parameter */
- BOOL bIntoQuotes; /* A flag showing if we are in quotes (") */
- LPTSTR ptrStart; /* A pointer to the first character of a parameter */
- LPTSTR ptrEnd; /* A pointer to the last character of a parameter */
- BOOL bOrderByNoPar; /* A flag to indicate /O with no switch parameter */
- LPTSTR temp;
-
- /* Initialize parameter array */
- *params = NULL;
- *entries = 0;
-
- /* Initialize variables; */
- cCurSwitch = _T(' ');
- bNegative = FALSE;
- bPNegative = FALSE;
-
- /* We suppose that switch parameters
- were given to avoid setting them to default
- if the switch was not given */
- bOrderByNoPar = FALSE;
-
- /* Main Loop (see README_DIR.txt) */
- /* scan the command line char per char, and we process its char */
- while (*Line)
- {
- /* we save current character as it is and its upper case */
- cCurChar = *Line;
- cCurUChar = _totupper(*Line);
-
- /* 1st section (see README_DIR.txt) */
- /* When a switch is expecting */
- if (cCurSwitch == _T('/'))
- {
- while (*Line == _T(' '))
- Line++;
-
- bNegative = (*Line == _T('-'));
- Line += bNegative;
-
- cCurChar = *Line;
- cCurUChar = _totupper(*Line);
-
- if ((cCurUChar == _T('A')) ||(cCurUChar == _T('T')) || (cCurUChar == _T('O')))
- {
- /* If positive, prepare for parameters... if negative, reset to defaults */
- switch (cCurUChar)
- {
- case _T('A'):
- lpFlags->stAttribs.dwAttribVal = 0L;
- lpFlags->stAttribs.dwAttribMask = 0L;
- if (bNegative)
- lpFlags->stAttribs.dwAttribMask = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
- break;
- case _T('T'):
- if (bNegative)
- lpFlags->stTimeField.eTimeField = TF_MODIFIEDDATE;
- break;
- case _T('O'):
- bOrderByNoPar = !bNegative;
- lpFlags->stOrderBy.sCriteriaCount = 0;
- break;
- }
-
- if (!bNegative)
- {
- /* Positive switch, so it can take parameters. */
- cCurSwitch = cCurUChar;
- Line++;
- /* Skip optional leading colon */
- if (*Line == _T(':'))
- Line++;
- continue;
- }
- }
- else if (cCurUChar == _T('L'))
- lpFlags->bLowerCase = ! bNegative;
- else if (cCurUChar == _T('B'))
- lpFlags->bBareFormat = ! bNegative;
- else if (cCurUChar == _T('C'))
- lpFlags->bTSeperator = ! bNegative;
- else if (cCurUChar == _T('W'))
- lpFlags->bWideList = ! bNegative;
- else if (cCurUChar == _T('D'))
- lpFlags->bWideListColSort = ! bNegative;
- else if (cCurUChar == _T('N'))
- lpFlags->bNewLongList = ! bNegative;
- else if (cCurUChar == _T('P'))
- lpFlags->bPause = ! bNegative;
- else if (cCurUChar == _T('Q'))
- lpFlags->bUser = ! bNegative;
- else if (cCurUChar == _T('S'))
- lpFlags->bRecursive = ! bNegative;
- else if (cCurUChar == _T('X'))
- lpFlags->bShortName = ! bNegative;
- else if (cCurChar == _T('4'))
- lpFlags->b4Digit = ! bNegative;
- else if (cCurChar == _T('?'))
- {
- DirHelp();
- return FALSE;
- }
- else
- {
- error_invalid_switch ((TCHAR)_totupper (*Line));
- return FALSE;
- }
-
- /* Make sure there's no extra characters at the end of the switch */
- if (Line[1] && Line[1] != _T('/') && Line[1] != _T(' '))
- {
- error_parameter_format(Line[1]);
- return FALSE;
- }
-
- cCurSwitch = _T(' ');
- }
- else if (cCurSwitch == _T(' '))
- {
- /* 2nd section (see README_DIR.txt) */
- /* We are expecting parameter or the unknown */
-
- if (cCurChar == _T('/'))
- cCurSwitch = _T('/');
- else if (cCurChar == _T(' '))
- /* do nothing */;
- else
- {
- /* This is a file/directory name parameter. Find its end */
- ptrStart = Line;
- bIntoQuotes = FALSE;
- while (*Line)
- {
- if (!bIntoQuotes && (*Line == _T('/') || *Line == _T(' ')))
- break;
- bIntoQuotes ^= (*Line == _T('"'));
- Line++;
- }
- ptrEnd = Line;
-
- /* Copy it to the entries list */
- temp = cmd_alloc((ptrEnd - ptrStart + 1) * sizeof (TCHAR));
- if(!temp)
- return FALSE;
- memcpy(temp, ptrStart, (ptrEnd - ptrStart) * sizeof (TCHAR));
- temp[ptrEnd - ptrStart] = _T('\0');
- StripQuotes(temp);
- if(!add_entry(entries, params, temp))
- {
- cmd_free(temp);
- freep(*params);
- return FALSE;
- }
-
- cmd_free(temp);
- continue;
- }
- }
- else
- {
- /* 3rd section (see README_DIR.txt) */
- /* We are waiting for switch parameters */
-
- /* Check if there are no more switch parameters */
- if ((cCurChar == _T('/')) || ( cCurChar == _T(' ')))
- {
- /* Wrong desicion path, reprocess current character */
- cCurSwitch = _T(' ');
- continue;
- }
- /* Process parameter switch */
- switch(cCurSwitch)
- {
- case _T('A'): /* Switch parameters for /A (attributes filter) */
- if(cCurChar == _T('-'))
- bPNegative = TRUE;
- else if(cCurUChar == _T('D'))
- {
- lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_DIRECTORY;
- if (bPNegative)
- lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_DIRECTORY;
- else
- lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_DIRECTORY;
- }
- else if(cCurUChar == _T('R'))
- {
- lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_READONLY;
- if (bPNegative)
- lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_READONLY;
- else
- lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_READONLY;
- }
- else if(cCurUChar == _T('H'))
- {
- lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_HIDDEN;
- if (bPNegative)
- lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_HIDDEN;
- else
- lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_HIDDEN;
- }
- else if(cCurUChar == _T('A'))
- {
- lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_ARCHIVE;
- if (bPNegative)
- lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_ARCHIVE;
- else
- lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_ARCHIVE;
- }
- else if(cCurUChar == _T('S'))
- {
- lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_SYSTEM;
- if (bPNegative)
- lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_SYSTEM;
- else
- lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_SYSTEM;
- }
- else
- {
- error_parameter_format((TCHAR)_totupper (*Line));
- return FALSE;
- }
- break;
- case _T('T'): /* Switch parameters for /T (time field) */
- if(cCurUChar == _T('C'))
- lpFlags->stTimeField.eTimeField= TF_CREATIONDATE ;
- else if(cCurUChar == _T('A'))
- lpFlags->stTimeField.eTimeField= TF_LASTACCESSEDDATE ;
- else if(cCurUChar == _T('W'))
- lpFlags->stTimeField.eTimeField= TF_MODIFIEDDATE ;
- else
- {
- error_parameter_format((TCHAR)_totupper (*Line));
- return FALSE;
- }
- break;
- case _T('O'): /* Switch parameters for /O (order) */
- /* Ok a switch parameter was given */
- bOrderByNoPar = FALSE;
-
- if(cCurChar == _T('-'))
- bPNegative = TRUE;
- else if(cCurUChar == _T('N'))
- {
- if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
- lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
- lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_NAME;
- }
- else if(cCurUChar == _T('S'))
- {
- if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
- lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
- lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_SIZE;
- }
- else if(cCurUChar == _T('G'))
- {
- if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
- lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
- lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_DIRECTORY;
- }
- else if(cCurUChar == _T('E'))
- {
- if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
- lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
- lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_EXTENSION;
- }
- else if(cCurUChar == _T('D'))
- {
- if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
- lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
- lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_TIME;
- }
-
- else
- {
- error_parameter_format((TCHAR)_totupper (*Line));
- return FALSE;
- }
-
-
- }
- /* We check if we calculated the negative value and realese the flag */
- if ((cCurChar != _T('-')) && bPNegative)
- bPNegative = FALSE;
- }
-
- Line++;
- }
-
- /* /O with no switch parameters acts like /O:GN */
- if (bOrderByNoPar)
- {
- lpFlags->stOrderBy.sCriteriaCount = 2;
- lpFlags->stOrderBy.eCriteria[0] = ORDER_DIRECTORY;
- lpFlags->stOrderBy.bCriteriaRev[0] = FALSE;
- lpFlags->stOrderBy.eCriteria[1] = ORDER_NAME;
- lpFlags->stOrderBy.bCriteriaRev[1] = FALSE;
- }
-
- return TRUE;
+ TCHAR cCurSwitch; /* The current switch */
+ TCHAR cCurChar; /* Current examined character */
+ TCHAR cCurUChar; /* Current upper examined character */
+ BOOL bNegative; /* Negative switch */
+ BOOL bPNegative; /* Negative switch parameter */
+ BOOL bIntoQuotes; /* A flag showing if we are in quotes (") */
+ LPTSTR ptrStart; /* A pointer to the first character of a parameter */
+ LPTSTR ptrEnd; /* A pointer to the last character of a parameter */
+ BOOL bOrderByNoPar; /* A flag to indicate /O with no switch parameter */
+ LPTSTR temp;
+
+ /* Initialize parameter array */
+ *params = NULL;
+ *entries = 0;
+
+ /* Initialize variables; */
+ cCurSwitch = _T(' ');
+ bNegative = FALSE;
+ bPNegative = FALSE;
+
+ /* We suppose that switch parameters
+ were given to avoid setting them to default
+ if the switch was not given */
+ bOrderByNoPar = FALSE;
+
+ /* Main Loop (see README_DIR.txt) */
+ /* scan the command line char per char, and we process its char */
+ while (*Line)
+ {
+ /* we save current character as it is and its upper case */
+ cCurChar = *Line;
+ cCurUChar = _totupper(*Line);
+
+ /* 1st section (see README_DIR.txt) */
+ /* When a switch is expecting */
+ if (cCurSwitch == _T('/'))
+ {
+ while (_istspace(*Line))
+ Line++;
+
+ bNegative = (*Line == _T('-'));
+ Line += bNegative;
+
+ cCurChar = *Line;
+ cCurUChar = _totupper(*Line);
+
+ if ((cCurUChar == _T('A')) ||(cCurUChar == _T('T')) || (cCurUChar == _T('O')))
+ {
+ /* If positive, prepare for parameters... if negative, reset to defaults */
+ switch (cCurUChar)
+ {
+ case _T('A'):
+ lpFlags->stAttribs.dwAttribVal = 0L;
+ lpFlags->stAttribs.dwAttribMask = 0L;
+ if (bNegative)
+ lpFlags->stAttribs.dwAttribMask = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
+ break;
+ case _T('T'):
+ if (bNegative)
+ lpFlags->stTimeField.eTimeField = TF_MODIFIEDDATE;
+ break;
+ case _T('O'):
+ bOrderByNoPar = !bNegative;
+ lpFlags->stOrderBy.sCriteriaCount = 0;
+ break;
+ }
+
+ if (!bNegative)
+ {
+ /* Positive switch, so it can take parameters. */
+ cCurSwitch = cCurUChar;
+ Line++;
+ /* Skip optional leading colon */
+ if (*Line == _T(':'))
+ Line++;
+ continue;
+ }
+ }
+ else if (cCurUChar == _T('L'))
+ lpFlags->bLowerCase = ! bNegative;
+ else if (cCurUChar == _T('B'))
+ lpFlags->bBareFormat = ! bNegative;
+ else if (cCurUChar == _T('C'))
+ lpFlags->bTSeparator = ! bNegative;
+ else if (cCurUChar == _T('W'))
+ lpFlags->bWideList = ! bNegative;
+ else if (cCurUChar == _T('D'))
+ lpFlags->bWideListColSort = ! bNegative;
+ else if (cCurUChar == _T('N'))
+ lpFlags->bNewLongList = ! bNegative;
+ else if (cCurUChar == _T('P'))
+ lpFlags->bPause = ! bNegative;
+ else if (cCurUChar == _T('Q'))
+ lpFlags->bUser = ! bNegative;
+ else if (cCurUChar == _T('S'))
+ lpFlags->bRecursive = ! bNegative;
+ else if (cCurUChar == _T('X'))
+ lpFlags->bShortName = ! bNegative;
+ else if (cCurUChar == _T('R'))
+ lpFlags->bDataStreams = ! bNegative;
+ else if (cCurChar == _T('4'))
+ lpFlags->b4Digit = ! bNegative;
+ else if (cCurChar == _T('?'))
+ {
+ DirHelp();
+ return FALSE;
+ }
+ else
+ {
+ error_invalid_switch ((TCHAR)_totupper(*Line));
+ return FALSE;
+ }
+
+ /* Make sure there's no extra characters at the end of the switch */
+ if (Line[1] && Line[1] != _T('/') && !_istspace(Line[1]))
+ {
+ error_parameter_format(Line[1]);
+ return FALSE;
+ }
+
+ cCurSwitch = _T(' ');
+ }
+ else if (cCurSwitch == _T(' '))
+ {
+ /* 2nd section (see README_DIR.txt) */
+ /* We are expecting parameter or the unknown */
+
+ if (cCurChar == _T('/'))
+ cCurSwitch = _T('/');
+ else if (_istspace(cCurChar))
+ /* do nothing */;
+ else
+ {
+ /* This is a file/directory name parameter. Find its end */
+ ptrStart = Line;
+ bIntoQuotes = FALSE;
+ while (*Line)
+ {
+ if (!bIntoQuotes && (*Line == _T('/') || _istspace(*Line)))
+ break;
+ bIntoQuotes ^= (*Line == _T('"'));
+ Line++;
+ }
+ ptrEnd = Line;
+
+ /* Copy it to the entries list */
+ temp = cmd_alloc((ptrEnd - ptrStart + 1) * sizeof(TCHAR));
+ if (!temp)
+ return FALSE;
+ memcpy(temp, ptrStart, (ptrEnd - ptrStart) * sizeof(TCHAR));
+ temp[ptrEnd - ptrStart] = _T('\0');
+ StripQuotes(temp);
+ if (!add_entry(entries, params, temp))
+ {
+ cmd_free(temp);
+ freep(*params);
+ return FALSE;
+ }
+
+ cmd_free(temp);
+ continue;
+ }
+ }
+ else
+ {
+ /* 3rd section (see README_DIR.txt) */
+ /* We are waiting for switch parameters */
+
+ /* Check if there are no more switch parameters */
+ if ((cCurChar == _T('/')) || _istspace(cCurChar))
+ {
+ /* Wrong decision path, reprocess current character */
+ cCurSwitch = _T(' ');
+ continue;
+ }
+ /* Process parameter switch */
+ switch (cCurSwitch)
+ {
+ case _T('A'): /* Switch parameters for /A (attributes filter) */
+ if (cCurChar == _T('-'))
+ bPNegative = TRUE;
+ else if (cCurUChar == _T('D'))
+ {
+ lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_DIRECTORY;
+ if (bPNegative)
+ lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_DIRECTORY;
+ else
+ lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_DIRECTORY;
+ }
+ else if (cCurUChar == _T('R'))
+ {
+ lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_READONLY;
+ if (bPNegative)
+ lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_READONLY;
+ else
+ lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_READONLY;
+ }
+ else if (cCurUChar == _T('H'))
+ {
+ lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_HIDDEN;
+ if (bPNegative)
+ lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_HIDDEN;
+ else
+ lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_HIDDEN;
+ }
+ else if (cCurUChar == _T('A'))
+ {
+ lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_ARCHIVE;
+ if (bPNegative)
+ lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_ARCHIVE;
+ else
+ lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_ARCHIVE;
+ }
+ else if (cCurUChar == _T('S'))
+ {
+ lpFlags->stAttribs.dwAttribMask |= FILE_ATTRIBUTE_SYSTEM;
+ if (bPNegative)
+ lpFlags->stAttribs.dwAttribVal &= ~FILE_ATTRIBUTE_SYSTEM;
+ else
+ lpFlags->stAttribs.dwAttribVal |= FILE_ATTRIBUTE_SYSTEM;
+ }
+ else
+ {
+ error_parameter_format((TCHAR)_totupper (*Line));
+ return FALSE;
+ }
+ break;
+ case _T('T'): /* Switch parameters for /T (time field) */
+ if (cCurUChar == _T('C'))
+ lpFlags->stTimeField.eTimeField= TF_CREATIONDATE ;
+ else if (cCurUChar == _T('A'))
+ lpFlags->stTimeField.eTimeField= TF_LASTACCESSEDDATE ;
+ else if (cCurUChar == _T('W'))
+ lpFlags->stTimeField.eTimeField= TF_MODIFIEDDATE ;
+ else
+ {
+ error_parameter_format((TCHAR)_totupper (*Line));
+ return FALSE;
+ }
+ break;
+ case _T('O'): /* Switch parameters for /O (order) */
+ /* Ok a switch parameter was given */
+ bOrderByNoPar = FALSE;
+
+ if (cCurChar == _T('-'))
+ bPNegative = TRUE;
+ else if (cCurUChar == _T('N'))
+ {
+ if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
+ lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
+ lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_NAME;
+ }
+ else if (cCurUChar == _T('S'))
+ {
+ if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
+ lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
+ lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_SIZE;
+ }
+ else if (cCurUChar == _T('G'))
+ {
+ if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
+ lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
+ lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_DIRECTORY;
+ }
+ else if (cCurUChar == _T('E'))
+ {
+ if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
+ lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
+ lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_EXTENSION;
+ }
+ else if (cCurUChar == _T('D'))
+ {
+ if (lpFlags->stOrderBy.sCriteriaCount < 3) lpFlags->stOrderBy.sCriteriaCount++;
+ lpFlags->stOrderBy.bCriteriaRev[lpFlags->stOrderBy.sCriteriaCount - 1] = bPNegative;
+ lpFlags->stOrderBy.eCriteria[lpFlags->stOrderBy.sCriteriaCount - 1] = ORDER_TIME;
+ }
+
+ else
+ {
+ error_parameter_format((TCHAR)_totupper (*Line));
+ return FALSE;
+ }
+
+
+ }
+ /* We check if we calculated the negative value and release the flag */
+ if ((cCurChar != _T('-')) && bPNegative)
+ bPNegative = FALSE;
+ }
+
+ Line++;
+ }
+
+ /* /O with no switch parameters acts like /O:GN */
+ if (bOrderByNoPar)
+ {
+ lpFlags->stOrderBy.sCriteriaCount = 2;
+ lpFlags->stOrderBy.eCriteria[0] = ORDER_DIRECTORY;
+ lpFlags->stOrderBy.bCriteriaRev[0] = FALSE;
+ lpFlags->stOrderBy.eCriteria[1] = ORDER_NAME;
+ lpFlags->stOrderBy.bCriteriaRev[1] = FALSE;
+ }
+
+ return TRUE;
}
/* Print either with or without paging, depending on /P switch */
-static INT
+static BOOL
DirPrintf(LPDIRSWITCHFLAGS lpFlags, LPTSTR szFormat, ...)
{
- INT iReturn = 0;
- va_list arg_ptr;
- va_start(arg_ptr, szFormat);
- if (lpFlags->bPause)
- iReturn = ConPrintfPaging(FALSE, szFormat, arg_ptr, STD_OUTPUT_HANDLE);
- else
- ConPrintf(szFormat, arg_ptr, STD_OUTPUT_HANDLE);
- va_end(arg_ptr);
- return iReturn;
+ BOOL Done = TRUE;
+ va_list arg_ptr;
+ va_start(arg_ptr, szFormat);
+ if (lpFlags->bPause)
+ Done = ConPrintfVPaging(&StdOutPager, FALSE, szFormat, arg_ptr);
+ else
+ ConPrintfV(StdOut, szFormat, arg_ptr);
+ va_end(arg_ptr);
+ return Done;
}
* print the header for the dir command
*/
static BOOL
-PrintDirectoryHeader(LPTSTR szPath, LPDIRSWITCHFLAGS lpFlags)
+PrintDirectoryHeader(LPCTSTR szPath, LPDIRSWITCHFLAGS lpFlags)
{
- TCHAR szMsg[RC_STRING_MAX_SIZE];
- TCHAR szFullDir[MAX_PATH];
- TCHAR szRootName[MAX_PATH];
- TCHAR szVolName[80];
- LPTSTR pszFilePart;
- DWORD dwSerialNr;
-
- if (lpFlags->bBareFormat)
- return TRUE;
+ TCHAR szMsg[RC_STRING_MAX_SIZE];
+ TCHAR szFullDir[MAX_PATH];
+ TCHAR szRootName[MAX_PATH];
+ TCHAR szVolName[80];
+ LPTSTR pszFilePart;
+ DWORD dwSerialNr;
+
+ if (lpFlags->bBareFormat)
+ return TRUE;
- if (GetFullPathName(szPath, sizeof(szFullDir) / sizeof(TCHAR), szFullDir, &pszFilePart) == 0)
+ if (GetFullPathName(szPath, ARRAYSIZE(szFullDir), szFullDir, &pszFilePart) == 0)
{
- ErrorMessage(GetLastError(), _T("Failed to build full directory path"));
- return FALSE;
+ ErrorMessage(GetLastError(), _T("Failed to build full directory path"));
+ return FALSE;
}
- if (pszFilePart != NULL)
- *pszFilePart = _T('\0');
+ if (pszFilePart != NULL)
+ *pszFilePart = _T('\0');
- /* get the media ID of the drive */
- if (!GetVolumePathName(szFullDir, szRootName, sizeof(szRootName) / sizeof(TCHAR)) ||
- !GetVolumeInformation(szRootName, szVolName, 80, &dwSerialNr,
- NULL, NULL, NULL, 0))
+ /* Get the media ID of the drive */
+ if (!GetVolumePathName(szFullDir, szRootName, ARRAYSIZE(szRootName)) ||
+ !GetVolumeInformation(szRootName, szVolName, ARRAYSIZE(szVolName),
+ &dwSerialNr, NULL, NULL, NULL, 0))
{
- return(TRUE);
+ return TRUE;
}
- /* print drive info */
- if (szVolName[0] != _T('\0'))
+ /* Print drive info */
+ if (szVolName[0] != _T('\0'))
{
- LoadString(CMD_ModuleHandle, STRING_DIR_HELP2, szMsg, RC_STRING_MAX_SIZE);
- DirPrintf(lpFlags, szMsg, szRootName[0], szVolName);
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP2, szMsg, ARRAYSIZE(szMsg));
+ DirPrintf(lpFlags, szMsg, _totupper(szRootName[0]), szVolName);
}
- else
+ else
{
- LoadString(CMD_ModuleHandle, STRING_DIR_HELP3, szMsg, RC_STRING_MAX_SIZE);
- DirPrintf(lpFlags, szMsg, szRootName[0]);
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP3, szMsg, ARRAYSIZE(szMsg));
+ DirPrintf(lpFlags, szMsg, _totupper(szRootName[0]));
}
- /* print the volume serial number if the return was successful */
- LoadString(CMD_ModuleHandle, STRING_DIR_HELP4, (LPTSTR) szMsg, RC_STRING_MAX_SIZE);
- DirPrintf(lpFlags, szMsg, HIWORD(dwSerialNr), LOWORD(dwSerialNr));
+ /* Print the volume serial number if the return was successful */
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP4, szMsg, ARRAYSIZE(szMsg));
+ DirPrintf(lpFlags, szMsg, HIWORD(dwSerialNr), LOWORD(dwSerialNr));
- return TRUE;
+ return TRUE;
}
LPWIN32_FIND_DATA lpFile,
LPDIRSWITCHFLAGS lpFlags)
{
- FILETIME ft;
- SYSTEMTIME dt;
-
- /* Select the right time field */
- switch (lpFlags->stTimeField.eTimeField)
- {
- case TF_CREATIONDATE:
- if (!FileTimeToLocalFileTime(&lpFile->ftCreationTime, &ft))
- return;
- FileTimeToSystemTime(&ft, &dt);
- break;
-
- case TF_LASTACCESSEDDATE :
- if (!FileTimeToLocalFileTime(&lpFile->ftLastAccessTime, &ft))
- return;
- FileTimeToSystemTime(&ft, &dt);
- break;
-
- case TF_MODIFIEDDATE:
- if (!FileTimeToLocalFileTime(&lpFile->ftLastWriteTime, &ft))
- return;
- FileTimeToSystemTime(&ft, &dt);
- break;
- }
-
- FormatDate(lpDate, &dt, lpFlags->b4Digit);
- FormatTime(lpTime, &dt);
+ FILETIME ft;
+ SYSTEMTIME dt;
+
+ /* Select the right time field */
+ switch (lpFlags->stTimeField.eTimeField)
+ {
+ case TF_CREATIONDATE:
+ if (!FileTimeToLocalFileTime(&lpFile->ftCreationTime, &ft))
+ return;
+ FileTimeToSystemTime(&ft, &dt);
+ break;
+
+ case TF_LASTACCESSEDDATE :
+ if (!FileTimeToLocalFileTime(&lpFile->ftLastAccessTime, &ft))
+ return;
+ FileTimeToSystemTime(&ft, &dt);
+ break;
+
+ case TF_MODIFIEDDATE:
+ if (!FileTimeToLocalFileTime(&lpFile->ftLastWriteTime, &ft))
+ return;
+ FileTimeToSystemTime(&ft, &dt);
+ break;
+ }
+
+ FormatDate(lpDate, &dt, lpFlags->b4Digit);
+ FormatTime(lpTime, &dt);
}
INT
FormatDate(TCHAR *lpDate, LPSYSTEMTIME dt, BOOL b4Digit)
{
- /* Format date */
- WORD wYear = b4Digit ? dt->wYear : dt->wYear%100;
- switch (nDateFormat)
- {
- case 0: /* mmddyy */
- default:
- return _stprintf(lpDate, _T("%02d%c%02d%c%0*d"),
- dt->wMonth, cDateSeparator,
- dt->wDay, cDateSeparator,
- b4Digit?4:2, wYear);
- break;
-
- case 1: /* ddmmyy */
- return _stprintf(lpDate, _T("%02d%c%02d%c%0*d"),
- dt->wDay, cDateSeparator, dt->wMonth,
- cDateSeparator, b4Digit?4:2, wYear);
- break;
-
- case 2: /* yymmdd */
- return _stprintf(lpDate, _T("%0*d%c%02d%c%02d"),
- b4Digit?4:2, wYear, cDateSeparator,
- dt->wMonth, cDateSeparator, dt->wDay);
- break;
- }
+ /* Format date */
+ WORD wYear = b4Digit ? dt->wYear : dt->wYear%100;
+ switch (nDateFormat)
+ {
+ case 0: /* mmddyy */
+ default:
+ return _stprintf(lpDate, _T("%02d%c%02d%c%0*d"),
+ dt->wMonth, cDateSeparator,
+ dt->wDay, cDateSeparator,
+ b4Digit?4:2, wYear);
+ break;
+
+ case 1: /* ddmmyy */
+ return _stprintf(lpDate, _T("%02d%c%02d%c%0*d"),
+ dt->wDay, cDateSeparator, dt->wMonth,
+ cDateSeparator, b4Digit?4:2, wYear);
+ break;
+
+ case 2: /* yymmdd */
+ return _stprintf(lpDate, _T("%0*d%c%02d%c%02d"),
+ b4Digit?4:2, wYear, cDateSeparator,
+ dt->wMonth, cDateSeparator, dt->wDay);
+ break;
+ }
}
INT
FormatTime(TCHAR *lpTime, LPSYSTEMTIME dt)
{
- /* Format Time */
- switch (nTimeFormat)
- {
- case 0: /* 12 hour format */
- default:
- return _stprintf(lpTime,_T("%02d%c%02u %cM"),
- (dt->wHour == 0 ? 12 : (dt->wHour <= 12 ? dt->wHour : dt->wHour - 12)),
- cTimeSeparator,
- dt->wMinute, (dt->wHour <= 11 ? _T('A') : _T('P')));
- break;
-
- case 1: /* 24 hour format */
- return _stprintf(lpTime, _T("%02d%c%02u"),
- dt->wHour, cTimeSeparator, dt->wMinute);
- break;
- }
+ /* Format Time */
+ switch (nTimeFormat)
+ {
+ case 0: /* 12 hour format */
+ default:
+ return _stprintf(lpTime,_T("%02d%c%02u %cM"),
+ (dt->wHour == 0 ? 12 : (dt->wHour <= 12 ? dt->wHour : dt->wHour - 12)),
+ cTimeSeparator,
+ dt->wMinute, (dt->wHour <= 11 ? _T('A') : _T('P')));
+ break;
+
+ case 1: /* 24 hour format */
+ return _stprintf(lpTime, _T("%02d%c%02u"),
+ dt->wHour, cTimeSeparator, dt->wMinute);
+ break;
+ }
}
static VOID
GetUserDiskFreeSpace(LPCTSTR lpRoot,
- PULARGE_INTEGER lpFreeSpace)
+ PULARGE_INTEGER lpFreeSpace)
{
- PGETFREEDISKSPACEEX pGetFreeDiskSpaceEx;
- HINSTANCE hInstance;
- DWORD dwSecPerCl;
- DWORD dwBytPerSec;
- DWORD dwFreeCl;
- DWORD dwTotCl;
- ULARGE_INTEGER TotalNumberOfBytes, TotalNumberOfFreeBytes;
-
- lpFreeSpace->QuadPart = 0;
-
- hInstance = GetModuleHandle(_T("KERNEL32"));
- if (hInstance != NULL)
+ PGETFREEDISKSPACEEX pGetFreeDiskSpaceEx;
+ HINSTANCE hInstance;
+ DWORD dwSecPerCl;
+ DWORD dwBytPerSec;
+ DWORD dwFreeCl;
+ DWORD dwTotCl;
+ ULARGE_INTEGER TotalNumberOfBytes, TotalNumberOfFreeBytes;
+
+ lpFreeSpace->QuadPart = 0;
+
+ hInstance = GetModuleHandle(_T("KERNEL32"));
+ if (hInstance != NULL)
{
- pGetFreeDiskSpaceEx = (PGETFREEDISKSPACEEX)GetProcAddress(hInstance,
+ pGetFreeDiskSpaceEx = (PGETFREEDISKSPACEEX)GetProcAddress(hInstance,
#ifdef _UNICODE
- "GetDiskFreeSpaceExW");
+ "GetDiskFreeSpaceExW");
#else
- "GetDiskFreeSpaceExA");
+ "GetDiskFreeSpaceExA");
#endif
- if (pGetFreeDiskSpaceEx != NULL)
- {
- if (pGetFreeDiskSpaceEx(lpRoot, lpFreeSpace, &TotalNumberOfBytes, &TotalNumberOfFreeBytes) == TRUE)
- return;
- }
+ if (pGetFreeDiskSpaceEx != NULL)
+ {
+ if (pGetFreeDiskSpaceEx(lpRoot, lpFreeSpace, &TotalNumberOfBytes, &TotalNumberOfFreeBytes) != FALSE)
+ return;
+ }
}
- GetDiskFreeSpace(lpRoot,
- &dwSecPerCl,
- &dwBytPerSec,
- &dwFreeCl,
- &dwTotCl);
+ GetDiskFreeSpace(lpRoot,
+ &dwSecPerCl,
+ &dwBytPerSec,
+ &dwFreeCl,
+ &dwTotCl);
- lpFreeSpace->QuadPart = dwSecPerCl * dwBytPerSec * dwFreeCl;
+ lpFreeSpace->QuadPart = dwSecPerCl * dwBytPerSec * dwFreeCl;
}
* print_summary: prints dir summary
* Added by Rob Lake 06/17/98 to compact code
* Just copied Tim's Code and patched it a bit
- *
*/
static INT
-PrintSummary(LPTSTR szPath,
- ULONG ulFiles,
- ULONG ulDirs,
- ULONGLONG u64Bytes,
- LPDIRSWITCHFLAGS lpFlags,
- BOOL TotalSummary)
+PrintSummary(LPCTSTR szPath,
+ ULONG ulFiles,
+ ULONG ulDirs,
+ ULONGLONG u64Bytes,
+ LPDIRSWITCHFLAGS lpFlags,
+ BOOL TotalSummary)
{
- TCHAR szMsg[RC_STRING_MAX_SIZE];
- TCHAR szBuffer[64];
- ULARGE_INTEGER uliFree;
-
-
- /* Here we check if we didn't find anything */
- if (!(ulFiles + ulDirs))
- {
- if (!lpFlags->bRecursive || (TotalSummary && lpFlags->bRecursive))
- error_file_not_found();
- return 1;
- }
-
-
- /* In bare format we don't print results */
- if (lpFlags->bBareFormat)
- return 0;
-
- /* Print recursive specific results */
-
- /* Take this code offline to fix /S does not print duoble info */
- if (TotalSummary && lpFlags->bRecursive)
- {
- ConvertULargeInteger(u64Bytes, szBuffer, sizeof(szBuffer), lpFlags->bTSeperator);
- LoadString(CMD_ModuleHandle, STRING_DIR_HELP5, szMsg, RC_STRING_MAX_SIZE);
- DirPrintf(lpFlags, szMsg, ulFiles, szBuffer);
- }
- else
- {
- /* Print File Summary */
- /* Condition to print summary is:
- If we are not in bare format and if we have results! */
- ConvertULargeInteger(u64Bytes, szBuffer, 20, lpFlags->bTSeperator);
- LoadString(CMD_ModuleHandle, STRING_DIR_HELP8, szMsg, RC_STRING_MAX_SIZE);
- DirPrintf(lpFlags, szMsg, ulFiles, szBuffer);
- }
-
- /* Print total directories and freespace */
- if (!lpFlags->bRecursive || TotalSummary)
- {
- GetUserDiskFreeSpace(szPath, &uliFree);
- ConvertULargeInteger(uliFree.QuadPart, szBuffer, sizeof(szBuffer), lpFlags->bTSeperator);
- LoadString(CMD_ModuleHandle, STRING_DIR_HELP6, (LPTSTR) szMsg, RC_STRING_MAX_SIZE);
- DirPrintf(lpFlags, szMsg, ulDirs, szBuffer);
- }
-
- return 0;
+ TCHAR szMsg[RC_STRING_MAX_SIZE];
+ TCHAR szBuffer[64];
+ ULARGE_INTEGER uliFree;
+
+ /* Here we check if we didn't find anything */
+ if (!(ulFiles + ulDirs))
+ {
+ if (!lpFlags->bRecursive || (TotalSummary && lpFlags->bRecursive))
+ error_file_not_found();
+ return 1;
+ }
+
+ /* In bare format we don't print results */
+ if (lpFlags->bBareFormat)
+ return 0;
+
+ /* Print recursive specific results */
+
+ /* Take this code offline to fix /S does not print double info */
+ if (TotalSummary && lpFlags->bRecursive)
+ {
+ ConvertULargeInteger(u64Bytes, szBuffer, ARRAYSIZE(szBuffer), lpFlags->bTSeparator);
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP5, szMsg, ARRAYSIZE(szMsg));
+ DirPrintf(lpFlags, szMsg, ulFiles, szBuffer);
+ }
+ else
+ {
+ /* Print File Summary */
+ /* Condition to print summary is:
+ If we are not in bare format and if we have results! */
+ ConvertULargeInteger(u64Bytes, szBuffer, ARRAYSIZE(szBuffer), lpFlags->bTSeparator);
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP8, szMsg, ARRAYSIZE(szMsg));
+ DirPrintf(lpFlags, szMsg, ulFiles, szBuffer);
+ }
+
+ /* Print total directories and free space */
+ if (!lpFlags->bRecursive || TotalSummary)
+ {
+ GetUserDiskFreeSpace(szPath, &uliFree);
+ ConvertULargeInteger(uliFree.QuadPart, szBuffer, ARRAYSIZE(szBuffer), lpFlags->bTSeparator);
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP6, szMsg, ARRAYSIZE(szMsg));
+ DirPrintf(lpFlags, szMsg, ulDirs, szBuffer);
+ }
+
+ return 0;
}
/*
*/
TCHAR* getExt(const TCHAR* file)
{
- static TCHAR *NoExt = _T("");
- TCHAR* lastdot = _tcsrchr(file, _T('.'));
- return (lastdot != NULL ? lastdot + 1 : NoExt);
+ static TCHAR *NoExt = _T("");
+ TCHAR* lastdot = _tcsrchr(file, _T('.'));
+ return (lastdot != NULL ? lastdot + 1 : NoExt);
}
/*
static LPTSTR
getName(const TCHAR* file, TCHAR * dest)
{
- int iLen;
- LPTSTR end;
+ INT_PTR iLen;
+ LPTSTR end;
- /* Check for "." and ".." folders */
- if ((_tcscmp(file, _T(".")) == 0) ||
- (_tcscmp(file, _T("..")) == 0))
- {
- _tcscpy(dest,file);
- return dest;
- }
-
- end = _tcsrchr(file, _T('.'));
- if (!end)
- iLen = _tcslen(file);
- else
- iLen = (end - file);
+ /* Check for "." and ".." folders */
+ if ((_tcscmp(file, _T(".")) == 0) ||
+ (_tcscmp(file, _T("..")) == 0))
+ {
+ _tcscpy(dest,file);
+ return dest;
+ }
+ end = _tcsrchr(file, _T('.'));
+ if (!end)
+ iLen = _tcslen(file);
+ else
+ iLen = (end - file);
- _tcsncpy(dest, file, iLen);
- *(dest + iLen) = _T('\0');
+ _tcsncpy(dest, file, iLen);
+ *(dest + iLen) = _T('\0');
- return dest;
+ return dest;
}
* The function that prints in new style
*/
static VOID
-DirPrintNewList(LPWIN32_FIND_DATA ptrFiles[], /* [IN]Files' Info */
- DWORD dwCount, /* [IN] The quantity of files */
- TCHAR *szCurPath, /* [IN] Full path of current directory */
- LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
+DirPrintNewList(PDIRFINDINFO ptrFiles[], /* [IN]Files' Info */
+ DWORD dwCount, /* [IN] The quantity of files */
+ LPCTSTR szCurPath, /* [IN] Full path of current directory */
+ LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
{
- DWORD i;
- TCHAR szSize[30];
- TCHAR szShortName[15];
- TCHAR szDate[20];
- TCHAR szTime[20];
- INT iSizeFormat;
- ULARGE_INTEGER u64FileSize;
-
- for (i = 0; i < dwCount && !bCtrlBreak; i++)
- {
- /* Calculate size */
- if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ DWORD i;
+ TCHAR szSize[30];
+ TCHAR szShortName[15];
+ TCHAR szDate[20];
+ TCHAR szTime[20];
+ INT iSizeFormat;
+ ULARGE_INTEGER u64FileSize;
+ PDIRFINDSTREAMNODE ptrCurStream;
+
+ for (i = 0; i < dwCount && !CheckCtrlBreak(BREAK_INPUT); i++)
{
- /* Junction */
- iSizeFormat = -14;
- _tcscpy(szSize, _T("<JUNCTION>"));
+ /* Calculate size */
+ if (ptrFiles[i]->stFindInfo.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ {
+ /* Junction */
+ iSizeFormat = -14;
+ _tcscpy(szSize, _T("<JUNCTION>"));
+ }
+ else if (ptrFiles[i]->stFindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ /* Directory */
+ iSizeFormat = -14;
+ _tcscpy(szSize, _T("<DIR>"));
+ }
+ else
+ {
+ /* File */
+ iSizeFormat = 14;
+ u64FileSize.HighPart = ptrFiles[i]->stFindInfo.nFileSizeHigh;
+ u64FileSize.LowPart = ptrFiles[i]->stFindInfo.nFileSizeLow;
+ ConvertULargeInteger(u64FileSize.QuadPart, szSize, 20, lpFlags->bTSeparator);
+ }
+
+ /* Calculate short name */
+ szShortName[0] = _T('\0');
+ if (lpFlags->bShortName)
+ _stprintf(szShortName, _T(" %-12s"), ptrFiles[i]->stFindInfo.cAlternateFileName);
+
+ /* Format date and time */
+ DirPrintFileDateTime(szDate, szTime, &ptrFiles[i]->stFindInfo, lpFlags);
+
+ /* Print the line */
+ DirPrintf(lpFlags, _T("%10s %-6s %*s%s %s\n"),
+ szDate,
+ szTime,
+ iSizeFormat,
+ szSize,
+ szShortName,
+ ptrFiles[i]->stFindInfo.cFileName);
+
+ /* Now, loop on the streams */
+ ptrCurStream = ptrFiles[i]->ptrHead;
+ while (ptrCurStream)
+ {
+ ConvertULargeInteger(ptrCurStream->stStreamInfo.StreamSize.QuadPart, szSize, 20, lpFlags->bTSeparator);
+
+ /* Print the line */
+ DirPrintf(lpFlags, _T("%10s %-6s %*s%s %s%s\n"),
+ L"",
+ L"",
+ 16,
+ szSize,
+ L"",
+ ptrFiles[i]->stFindInfo.cFileName,
+ ptrCurStream->stStreamInfo.cStreamName);
+ ptrCurStream = ptrCurStream->ptrNext;
+ }
}
- else if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- /* Directory */
- iSizeFormat = -14;
- _tcscpy(szSize, _T("<DIR>"));
- }
- else
- {
- /* File */
- iSizeFormat = 14;
- u64FileSize.HighPart = ptrFiles[i]->nFileSizeHigh;
- u64FileSize.LowPart = ptrFiles[i]->nFileSizeLow;
- ConvertULargeInteger(u64FileSize.QuadPart, szSize, 20, lpFlags->bTSeperator);
- }
-
- /* Calculate short name */
- szShortName[0] = _T('\0');
- if (lpFlags->bShortName)
- _stprintf(szShortName, _T(" %-12s"), ptrFiles[i]->cAlternateFileName);
-
- /* Format date and time */
- DirPrintFileDateTime(szDate, szTime, ptrFiles[i], lpFlags);
-
- /* Print the line */
- DirPrintf(lpFlags, _T("%10s %-6s %*s%s %s\n"),
- szDate,
- szTime,
- iSizeFormat,
- szSize,
- szShortName,
- ptrFiles[i]->cFileName);
- }
}
* The function that prints in wide list
*/
static VOID
-DirPrintWideList(LPWIN32_FIND_DATA ptrFiles[], /* [IN] Files' Info */
- DWORD dwCount, /* [IN] The quantity of files */
- TCHAR *szCurPath, /* [IN] Full path of current directory */
- LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
+DirPrintWideList(PDIRFINDINFO ptrFiles[], /* [IN] Files' Info */
+ DWORD dwCount, /* [IN] The quantity of files */
+ LPCTSTR szCurPath, /* [IN] Full path of current directory */
+ LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
{
- SHORT iScreenWidth;
- USHORT iColumns;
- USHORT iLines;
- UINT iLongestName;
- TCHAR szTempFname[MAX_PATH];
- DWORD i;
- DWORD j;
- DWORD temp;
-
- /* Calculate longest name */
- iLongestName = 1;
- for (i = 0; i < dwCount; i++)
- {
- if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- /* Directories need 2 additinal characters for brackets */
- if ((_tcslen(ptrFiles[i]->cFileName) + 2) > iLongestName)
- iLongestName = _tcslen(ptrFiles[i]->cFileName) + 2;
- }
- else
+ SHORT iScreenWidth;
+ USHORT iColumns;
+ USHORT iLines;
+ UINT_PTR iLongestName;
+ TCHAR szTempFname[MAX_PATH];
+ DWORD i;
+ DWORD j;
+ DWORD temp;
+
+ /* Calculate longest name */
+ iLongestName = 1;
+ for (i = 0; i < dwCount; i++)
{
- if (_tcslen(ptrFiles[i]->cFileName) > iLongestName)
- iLongestName = _tcslen(ptrFiles[i]->cFileName);
+ if (ptrFiles[i]->stFindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ /* Directories need 2 additional characters for brackets */
+ if ((_tcslen(ptrFiles[i]->stFindInfo.cFileName) + 2) > iLongestName)
+ iLongestName = _tcslen(ptrFiles[i]->stFindInfo.cFileName) + 2;
+ }
+ else
+ {
+ if (_tcslen(ptrFiles[i]->stFindInfo.cFileName) > iLongestName)
+ iLongestName = _tcslen(ptrFiles[i]->stFindInfo.cFileName);
+ }
}
- }
- /* Count the highest number of columns */
- GetScreenSize(&iScreenWidth, 0);
- iColumns = iScreenWidth / iLongestName;
+ /* Count the highest number of columns */
+ GetScreenSize(&iScreenWidth, NULL);
+ iColumns = (USHORT)(iScreenWidth / iLongestName);
- /* Check if there is enough space for spaces between names */
- if (((iLongestName * iColumns) + iColumns) >= (UINT)iScreenWidth)
- iColumns --;
+ /* Check if there is enough space for spaces between names */
+ if (((iLongestName * iColumns) + iColumns) >= (UINT)iScreenWidth)
+ iColumns --;
- /* A last check at iColumns to avoid division by zero */
- if (!(iColumns))
- iColumns = 1;
+ /* A last check at iColumns to avoid division by zero */
+ if (!iColumns) iColumns = 1;
- /* Calculate the lines that will be printed */
- iLines = (USHORT)((dwCount + iColumns - 1) / iColumns);
+ /* Calculate the lines that will be printed */
+ iLines = (USHORT)((dwCount + iColumns - 1) / iColumns);
- for (i = 0; i < iLines && !bCtrlBreak; i++)
- {
- for (j = 0; j < iColumns; j++)
+ for (i = 0; i < iLines && !CheckCtrlBreak(BREAK_INPUT); i++)
{
- if (lpFlags->bWideListColSort)
- {
- /* Print Column sorted */
- temp = (j * iLines) + i;
- }
- else
- {
- /* Print Line sorted */
- temp = (i * iColumns) + j;
- }
-
- if (temp >= dwCount)
- break;
-
- if (ptrFiles[temp]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- _stprintf(szTempFname, _T("[%s]"), ptrFiles[temp]->cFileName);
- else
- _stprintf(szTempFname, _T("%s"), ptrFiles[temp]->cFileName);
-
- DirPrintf(lpFlags, _T("%-*s"), iLongestName + 1, szTempFname);
+ for (j = 0; j < iColumns; j++)
+ {
+ if (lpFlags->bWideListColSort)
+ {
+ /* Print Column sorted */
+ temp = (j * iLines) + i;
+ }
+ else
+ {
+ /* Print Line sorted */
+ temp = (i * iColumns) + j;
+ }
+
+ if (temp >= dwCount) break;
+
+ if (ptrFiles[temp]->stFindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ _stprintf(szTempFname, _T("[%s]"), ptrFiles[temp]->stFindInfo.cFileName);
+ else
+ _stprintf(szTempFname, _T("%s"), ptrFiles[temp]->stFindInfo.cFileName);
+
+ DirPrintf(lpFlags, _T("%-*s"), iLongestName + 1, szTempFname);
+ }
+
+ /* Add a new line after the last item in the column */
+ DirPrintf(lpFlags, _T("\n"));
}
-
- /* Add a new line after the last item in the column */
- DirPrintf(lpFlags, _T("\n"));
- }
}
* The function that prints in old style
*/
static VOID
-DirPrintOldList(LPWIN32_FIND_DATA ptrFiles[], /* [IN] Files' Info */
- DWORD dwCount, /* [IN] The quantity of files */
- TCHAR * szCurPath, /* [IN] Full path of current directory */
- LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
+DirPrintOldList(PDIRFINDINFO ptrFiles[], /* [IN] Files' Info */
+ DWORD dwCount, /* [IN] The quantity of files */
+ LPCTSTR szCurPath, /* [IN] Full path of current directory */
+ LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
{
-DWORD i; /* An indexer for "for"s */
-TCHAR szName[10]; /* The name of file */
-TCHAR szExt[5]; /* The extension of file */
-TCHAR szDate[30],szTime[30]; /* Used to format time and date */
-TCHAR szSize[30]; /* The size of file */
-int iSizeFormat; /* The format of size field */
-ULARGE_INTEGER u64FileSize; /* The file size */
-
- for (i = 0; i < dwCount && !bCtrlBreak; i++)
- {
- /* Broke 8.3 format */
- if (*ptrFiles[i]->cAlternateFileName )
- {
- /* If the file is long named then we read the alter name */
- getName( ptrFiles[i]->cAlternateFileName, szName);
- _tcscpy(szExt, getExt( ptrFiles[i]->cAlternateFileName));
- }
- else
- {
- /* If the file is not long name we read its original name */
- getName( ptrFiles[i]->cFileName, szName);
- _tcscpy(szExt, getExt( ptrFiles[i]->cFileName));
- }
-
- /* Calculate size */
- if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- /* Directory, no size it's a directory*/
- iSizeFormat = -17;
- _tcscpy(szSize, _T("<DIR>"));
- }
- else
- {
- /* File */
- iSizeFormat = 17;
- u64FileSize.HighPart = ptrFiles[i]->nFileSizeHigh;
- u64FileSize.LowPart = ptrFiles[i]->nFileSizeLow;
- ConvertULargeInteger(u64FileSize.QuadPart, szSize, 20, lpFlags->bTSeperator);
- }
-
- /* Format date and time */
- DirPrintFileDateTime(szDate,szTime,ptrFiles[i],lpFlags);
-
- /* Print the line */
- DirPrintf(lpFlags, _T("%-8s %-3s %*s %s %s\n"),
- szName, /* The file's 8.3 name */
- szExt, /* The file's 8.3 extension */
- iSizeFormat, /* print format for size column */
- szSize, /* The size of file or "<DIR>" for dirs */
- szDate, /* The date of file/dir */
- szTime); /* The time of file/dir */
- }
+ DWORD i; /* An indexer for "for"s */
+ TCHAR szName[10]; /* The name of file */
+ TCHAR szExt[5]; /* The extension of file */
+ TCHAR szDate[30],szTime[30]; /* Used to format time and date */
+ TCHAR szSize[30]; /* The size of file */
+ int iSizeFormat; /* The format of size field */
+ ULARGE_INTEGER u64FileSize; /* The file size */
+
+ for (i = 0; i < dwCount && !CheckCtrlBreak(BREAK_INPUT); i++)
+ {
+ /* Broke 8.3 format */
+ if (*ptrFiles[i]->stFindInfo.cAlternateFileName )
+ {
+ /* If the file is long named then we read the alter name */
+ getName( ptrFiles[i]->stFindInfo.cAlternateFileName, szName);
+ _tcscpy(szExt, getExt( ptrFiles[i]->stFindInfo.cAlternateFileName));
+ }
+ else
+ {
+ /* If the file is not long name we read its original name */
+ getName( ptrFiles[i]->stFindInfo.cFileName, szName);
+ _tcscpy(szExt, getExt( ptrFiles[i]->stFindInfo.cFileName));
+ }
+
+ /* Calculate size */
+ if (ptrFiles[i]->stFindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ /* Directory, no size it's a directory */
+ iSizeFormat = -17;
+ _tcscpy(szSize, _T("<DIR>"));
+ }
+ else
+ {
+ /* File */
+ iSizeFormat = 17;
+ u64FileSize.HighPart = ptrFiles[i]->stFindInfo.nFileSizeHigh;
+ u64FileSize.LowPart = ptrFiles[i]->stFindInfo.nFileSizeLow;
+ ConvertULargeInteger(u64FileSize.QuadPart, szSize, 20, lpFlags->bTSeparator);
+ }
+
+ /* Format date and time */
+ DirPrintFileDateTime(szDate,szTime,&ptrFiles[i]->stFindInfo,lpFlags);
+
+ /* Print the line */
+ DirPrintf(lpFlags, _T("%-8s %-3s %*s %s %s\n"),
+ szName, /* The file's 8.3 name */
+ szExt, /* The file's 8.3 extension */
+ iSizeFormat, /* print format for size column */
+ szSize, /* The size of file or "<DIR>" for dirs */
+ szDate, /* The date of file/dir */
+ szTime); /* The time of file/dir */
+ }
}
/*
* The function that prints in bare format
*/
static VOID
-DirPrintBareList(LPWIN32_FIND_DATA ptrFiles[], /* [IN] Files' Info */
- DWORD dwCount, /* [IN] The number of files */
- LPTSTR lpCurPath, /* [IN] Full path of current directory */
- LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
+DirPrintBareList(PDIRFINDINFO ptrFiles[], /* [IN] Files' Info */
+ DWORD dwCount, /* [IN] The number of files */
+ LPCTSTR szCurPath, /* [IN] Full path of current directory */
+ LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
{
- DWORD i;
-
- for (i = 0; i < dwCount && !bCtrlBreak; i++)
- {
- if ((_tcscmp(ptrFiles[i]->cFileName, _T(".")) == 0) ||
- (_tcscmp(ptrFiles[i]->cFileName, _T("..")) == 0))
- {
- /* at bare format we don't print "." and ".." folder */
- continue;
- }
- if (lpFlags->bRecursive)
- {
- /* at recursive mode we print full path of file */
- DirPrintf(lpFlags, _T("%s\\%s\n"), lpCurPath, ptrFiles[i]->cFileName);
- }
- else
- {
- /* if we are not in recursive mode we print the file names */
- DirPrintf(lpFlags, _T("%s\n"), ptrFiles[i]->cFileName);
- }
- }
+ DWORD i;
+
+ for (i = 0; i < dwCount && !CheckCtrlBreak(BREAK_INPUT); i++)
+ {
+ if ((_tcscmp(ptrFiles[i]->stFindInfo.cFileName, _T(".")) == 0) ||
+ (_tcscmp(ptrFiles[i]->stFindInfo.cFileName, _T("..")) == 0))
+ {
+ /* at bare format we don't print "." and ".." folder */
+ continue;
+ }
+ if (lpFlags->bRecursive)
+ {
+ /* at recursive mode we print full path of file */
+ DirPrintf(lpFlags, _T("%s\\%s\n"), szCurPath, ptrFiles[i]->stFindInfo.cFileName);
+ }
+ else
+ {
+ /* if we are not in recursive mode we print the file names */
+ DirPrintf(lpFlags, _T("%s\n"), ptrFiles[i]->stFindInfo.cFileName);
+ }
+ }
}
* The functions that prints the files list
*/
static VOID
-DirPrintFiles(LPWIN32_FIND_DATA ptrFiles[], /* [IN] Files' Info */
- DWORD dwCount, /* [IN] The quantity of files */
- TCHAR *szCurPath, /* [IN] Full path of current directory */
- LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
+DirPrintFiles(PDIRFINDINFO ptrFiles[], /* [IN] Files' Info */
+ DWORD dwCount, /* [IN] The quantity of files */
+ LPCTSTR szCurPath, /* [IN] Full path of current directory */
+ LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags used */
{
- TCHAR szMsg[RC_STRING_MAX_SIZE];
- TCHAR szTemp[MAX_PATH]; /* A buffer to format the directory header */
-
- /* Print trailing backslash for root directory of drive */
- _tcscpy(szTemp, szCurPath);
- if (_tcslen(szTemp) == 2 && szTemp[1] == _T(':'))
- _tcscat(szTemp, _T("\\"));
-
- /* Condition to print header:
- We are not printing in bare format
- and if we are in recursive mode... we must have results */
- if (!(lpFlags->bBareFormat ) && !((lpFlags->bRecursive) && (dwCount <= 0)))
- {
- LoadString(CMD_ModuleHandle, STRING_DIR_HELP7, szMsg, RC_STRING_MAX_SIZE);
- if (DirPrintf(lpFlags, szMsg, szTemp))
- return;
- }
-
- if (lpFlags->bBareFormat)
- {
- /* Bare format */
- DirPrintBareList(ptrFiles, dwCount, szCurPath, lpFlags);
- }
- else if(lpFlags->bShortName)
- {
- /* New list style / Short names */
- DirPrintNewList(ptrFiles, dwCount, szCurPath, lpFlags);
- }
- else if(lpFlags->bWideListColSort || lpFlags->bWideList)
- {
- /* Wide list */
- DirPrintWideList(ptrFiles, dwCount, szCurPath, lpFlags);
- }
- else if (lpFlags->bNewLongList )
- {
- /* New list style*/
- DirPrintNewList(ptrFiles, dwCount, szCurPath, lpFlags);
- }
- else
- {
- /* If nothing is selected old list is the default */
- DirPrintOldList(ptrFiles, dwCount, szCurPath, lpFlags);
- }
-}
-
+ TCHAR szMsg[RC_STRING_MAX_SIZE];
+ TCHAR szTemp[MAX_PATH]; /* A buffer to format the directory header */
+
+ /* Print trailing backslash for root directory of drive */
+ _tcscpy(szTemp, szCurPath);
+ if (_tcslen(szTemp) == 2 && szTemp[1] == _T(':'))
+ _tcscat(szTemp, _T("\\"));
+
+ /* Condition to print header:
+ We are not printing in bare format
+ and if we are in recursive mode... we must have results */
+ if (!lpFlags->bBareFormat && !(lpFlags->bRecursive && (dwCount <= 0)))
+ {
+ LoadString(CMD_ModuleHandle, STRING_DIR_HELP7, szMsg, ARRAYSIZE(szMsg));
+ if (!DirPrintf(lpFlags, szMsg, szTemp))
+ return;
+ }
+ if (lpFlags->bBareFormat)
+ {
+ /* Bare format */
+ DirPrintBareList(ptrFiles, dwCount, szCurPath, lpFlags);
+ }
+ else if (lpFlags->bShortName)
+ {
+ /* New list style / Short names */
+ DirPrintNewList(ptrFiles, dwCount, szCurPath, lpFlags);
+ }
+ else if (lpFlags->bWideListColSort || lpFlags->bWideList)
+ {
+ /* Wide list */
+ DirPrintWideList(ptrFiles, dwCount, szCurPath, lpFlags);
+ }
+ else if (lpFlags->bNewLongList )
+ {
+ /* New list style*/
+ DirPrintNewList(ptrFiles, dwCount, szCurPath, lpFlags);
+ }
+ else
+ {
+ /* If nothing is selected old list is the default */
+ DirPrintOldList(ptrFiles, dwCount, szCurPath, lpFlags);
+ }
+}
/*
* CompareFiles
* Compares 2 files based on the order criteria
*/
static BOOL
-CompareFiles(LPWIN32_FIND_DATA lpFile1, /* [IN] A pointer to WIN32_FIND_DATA of file 1 */
- LPWIN32_FIND_DATA lpFile2, /* [IN] A pointer to WIN32_FIND_DATA of file 2 */
- LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags that we use to list */
+CompareFiles(PDIRFINDINFO lpFile1, /* [IN] A pointer to WIN32_FIND_DATA of file 1 */
+ PDIRFINDINFO lpFile2, /* [IN] A pointer to WIN32_FIND_DATA of file 2 */
+ LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags that we use to list */
{
ULARGE_INTEGER u64File1;
ULARGE_INTEGER u64File2;
int i;
- long iComp = 0; /* The comparison result */
-
- /* Calculate critiries by order given from user */
- for (i = 0;i < lpFlags->stOrderBy.sCriteriaCount;i++)
- {
-
- /* Calculate criteria */
- switch(lpFlags->stOrderBy.eCriteria[i])
- {
- case ORDER_SIZE: /* Order by size /o:s */
- /* concat the 32bit integers to a 64bit */
- u64File1.LowPart = lpFile1->nFileSizeLow;
- u64File1.HighPart = lpFile1->nFileSizeHigh;
- u64File2.LowPart = lpFile2->nFileSizeLow;
- u64File2.HighPart = lpFile2->nFileSizeHigh;
-
- /* In case that differnce is too big for a long */
- if (u64File1.QuadPart < u64File2.QuadPart)
- iComp = -1;
- else if (u64File1.QuadPart > u64File2.QuadPart)
- iComp = 1;
- else
- iComp = 0;
- break;
-
- case ORDER_DIRECTORY: /* Order by directory attribute /o:g */
- iComp = ((lpFile2->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)-
- (lpFile1->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
- break;
-
- case ORDER_EXTENSION: /* Order by extension name /o:e */
- iComp = _tcsicmp(getExt(lpFile1->cFileName),getExt(lpFile2->cFileName));
- break;
-
- case ORDER_NAME: /* Order by filename /o:n */
- iComp = _tcsicmp(lpFile1->cFileName, lpFile2->cFileName);
- break;
-
- case ORDER_TIME: /* Order by file's time /o:t */
- /* We compare files based on the time field selected by /t */
- switch(lpFlags->stTimeField.eTimeField)
- {
- case TF_CREATIONDATE:
- /* concat the 32bit integers to a 64bit */
- u64File1.LowPart = lpFile1->ftCreationTime.dwLowDateTime;
- u64File1.HighPart = lpFile1->ftCreationTime.dwHighDateTime ;
- u64File2.LowPart = lpFile2->ftCreationTime.dwLowDateTime;
- u64File2.HighPart = lpFile2->ftCreationTime.dwHighDateTime ;
- break;
- case TF_LASTACCESSEDDATE :
- /* concat the 32bit integers to a 64bit */
- u64File1.LowPart = lpFile1->ftLastAccessTime.dwLowDateTime;
- u64File1.HighPart = lpFile1->ftLastAccessTime.dwHighDateTime ;
- u64File2.LowPart = lpFile2->ftLastAccessTime.dwLowDateTime;
- u64File2.HighPart = lpFile2->ftLastAccessTime.dwHighDateTime ;
- break;
- case TF_MODIFIEDDATE:
- /* concat the 32bit integers to a 64bit */
- u64File1.LowPart = lpFile1->ftLastWriteTime.dwLowDateTime;
- u64File1.HighPart = lpFile1->ftLastWriteTime.dwHighDateTime ;
- u64File2.LowPart = lpFile2->ftLastWriteTime.dwLowDateTime;
- u64File2.HighPart = lpFile2->ftLastWriteTime.dwHighDateTime ;
- break;
- }
-
- /* In case that differnce is too big for a long */
- if (u64File1.QuadPart < u64File2.QuadPart)
- iComp = -1;
- else if (u64File1.QuadPart > u64File2.QuadPart)
- iComp = 1;
- else
- iComp = 0;
- break;
- }
-
- /* Reverse if desired */
- if (lpFlags->stOrderBy.bCriteriaRev[i])
- iComp *= -1;
-
- /* If that criteria was enough for distinguishing
- the files/dirs,there is no need to calculate the others*/
- if (iComp != 0) break;
- }
-
- /* Translate the value of iComp to boolean */
- return iComp > 0;
+ long iComp = 0; /* The comparison result */
+
+ /* Calculate criteria by order given from user */
+ for (i = 0; i < lpFlags->stOrderBy.sCriteriaCount; i++)
+ {
+
+ /* Calculate criteria */
+ switch (lpFlags->stOrderBy.eCriteria[i])
+ {
+ case ORDER_SIZE: /* Order by size /o:s */
+ /* concat the 32bit integers to a 64bit */
+ u64File1.LowPart = lpFile1->stFindInfo.nFileSizeLow;
+ u64File1.HighPart = lpFile1->stFindInfo.nFileSizeHigh;
+ u64File2.LowPart = lpFile2->stFindInfo.nFileSizeLow;
+ u64File2.HighPart = lpFile2->stFindInfo.nFileSizeHigh;
+
+ /* In case that difference is too big for a long */
+ if (u64File1.QuadPart < u64File2.QuadPart)
+ iComp = -1;
+ else if (u64File1.QuadPart > u64File2.QuadPart)
+ iComp = 1;
+ else
+ iComp = 0;
+ break;
+
+ case ORDER_DIRECTORY: /* Order by directory attribute /o:g */
+ iComp = ((lpFile2->stFindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)-
+ (lpFile1->stFindInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY));
+ break;
+
+ case ORDER_EXTENSION: /* Order by extension name /o:e */
+ iComp = _tcsicmp(getExt(lpFile1->stFindInfo.cFileName),getExt(lpFile2->stFindInfo.cFileName));
+ break;
+
+ case ORDER_NAME: /* Order by filename /o:n */
+ iComp = _tcsicmp(lpFile1->stFindInfo.cFileName, lpFile2->stFindInfo.cFileName);
+ break;
+
+ case ORDER_TIME: /* Order by file's time /o:t */
+ /* We compare files based on the time field selected by /t */
+ switch (lpFlags->stTimeField.eTimeField)
+ {
+ case TF_CREATIONDATE:
+ /* concat the 32bit integers to a 64bit */
+ u64File1.LowPart = lpFile1->stFindInfo.ftCreationTime.dwLowDateTime;
+ u64File1.HighPart = lpFile1->stFindInfo.ftCreationTime.dwHighDateTime ;
+ u64File2.LowPart = lpFile2->stFindInfo.ftCreationTime.dwLowDateTime;
+ u64File2.HighPart = lpFile2->stFindInfo.ftCreationTime.dwHighDateTime ;
+ break;
+ case TF_LASTACCESSEDDATE :
+ /* concat the 32bit integers to a 64bit */
+ u64File1.LowPart = lpFile1->stFindInfo.ftLastAccessTime.dwLowDateTime;
+ u64File1.HighPart = lpFile1->stFindInfo.ftLastAccessTime.dwHighDateTime ;
+ u64File2.LowPart = lpFile2->stFindInfo.ftLastAccessTime.dwLowDateTime;
+ u64File2.HighPart = lpFile2->stFindInfo.ftLastAccessTime.dwHighDateTime ;
+ break;
+ case TF_MODIFIEDDATE:
+ /* concat the 32bit integers to a 64bit */
+ u64File1.LowPart = lpFile1->stFindInfo.ftLastWriteTime.dwLowDateTime;
+ u64File1.HighPart = lpFile1->stFindInfo.ftLastWriteTime.dwHighDateTime ;
+ u64File2.LowPart = lpFile2->stFindInfo.ftLastWriteTime.dwLowDateTime;
+ u64File2.HighPart = lpFile2->stFindInfo.ftLastWriteTime.dwHighDateTime ;
+ break;
+ }
+
+ /* In case that difference is too big for a long */
+ if (u64File1.QuadPart < u64File2.QuadPart)
+ iComp = -1;
+ else if (u64File1.QuadPart > u64File2.QuadPart)
+ iComp = 1;
+ else
+ iComp = 0;
+ break;
+ }
+
+ /* Reverse if desired */
+ if (lpFlags->stOrderBy.bCriteriaRev[i])
+ iComp *= -1;
+
+ /* If that criteria was enough for distinguishing
+ the files/dirs,there is no need to calculate the others*/
+ if (iComp != 0) break;
+ }
+
+ /* Translate the value of iComp to boolean */
+ return iComp > 0;
}
/*
* Sort files by the order criterias using quicksort method
*/
static VOID
-QsortFiles(LPWIN32_FIND_DATA ptrArray[], /* [IN/OUT] The array with file info pointers */
- int i, /* [IN] The index of first item in array */
- int j, /* [IN] The index to last item in array */
- LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags that we will use to sort */
+QsortFiles(PDIRFINDINFO ptrArray[], /* [IN/OUT] The array with file info pointers */
+ int i, /* [IN] The index of first item in array */
+ int j, /* [IN] The index to last item in array */
+ LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags that we will use to sort */
{
- LPWIN32_FIND_DATA lpTemp; /* A temporary pointer */
- BOOL Way;
-
- if (i < j)
- {
- int First = i, Last = j, Temp;
- Way = TRUE;
- while (i != j)
- {
- if (Way == CompareFiles(ptrArray[i], ptrArray[j], lpFlags))
- {
- /* Swap the pointers of the array */
- lpTemp = ptrArray[i];
- ptrArray[i]= ptrArray[j];
- ptrArray[j] = lpTemp;
-
- /* Swap the indexes for inverting sorting */
- Temp = i;
- i = j;
- j =Temp;
-
- Way = !Way;
- }
-
- j += (!Way - Way);
- }
-
- QsortFiles(ptrArray,First, i-1, lpFlags);
- QsortFiles(ptrArray,i+1,Last, lpFlags);
- }
-}
+ PDIRFINDINFO lpTemp; /* A temporary pointer */
+ BOOL Way;
+ if (i < j)
+ {
+ int First = i, Last = j, Temp;
+ Way = TRUE;
+ while (i != j)
+ {
+ if (Way == CompareFiles(ptrArray[i], ptrArray[j], lpFlags))
+ {
+ /* Swap the pointers of the array */
+ lpTemp = ptrArray[i];
+ ptrArray[i]= ptrArray[j];
+ ptrArray[j] = lpTemp;
+
+ /* Swap the indexes for inverting sorting */
+ Temp = i;
+ i = j;
+ j =Temp;
+
+ Way = !Way;
+ }
+
+ j += (!Way - Way);
+ }
+
+ QsortFiles(ptrArray,First, i-1, lpFlags);
+ QsortFiles(ptrArray,i+1,Last, lpFlags);
+ }
+}
+static VOID
+DirNodeCleanup(PDIRFINDLISTNODE ptrStartNode,
+ PDWORD pdwCount)
+{
+ PDIRFINDLISTNODE ptrNextNode;
+ PDIRFINDSTREAMNODE ptrFreeNode;
+ while (ptrStartNode)
+ {
+ ptrNextNode = ptrStartNode->ptrNext;
+ while (ptrStartNode->stInfo.ptrHead)
+ {
+ ptrFreeNode = ptrStartNode->stInfo.ptrHead;
+ ptrStartNode->stInfo.ptrHead = ptrFreeNode->ptrNext;
+ cmd_free(ptrFreeNode);
+ }
+ cmd_free(ptrStartNode);
+ ptrStartNode = ptrNextNode;
+ --(*pdwCount);
+ }
+}
/*
* DirList
*
- * The functions that does everything except for printing results
+ * The function that does everything except for printing results
*/
static INT
-DirList(LPTSTR szPath, /* [IN] The path that dir starts */
- LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags of the listing */
-{
- BOOL fPoint; /* If szPath is a file with extension fPoint will be True*/
- HANDLE hSearch; /* The handle of the search */
- HANDLE hRecSearch; /* The handle for searching recursivly */
- WIN32_FIND_DATA wfdFileInfo; /* The info of file that found */
- LPWIN32_FIND_DATA * ptrFileArray; /* An array of pointers with all the files */
- PDIRFINDLISTNODE ptrStartNode; /* The pointer to the first node */
- PDIRFINDLISTNODE ptrNextNode; /* A pointer used for relatives refernces */
- TCHAR szFullPath[MAX_PATH]; /* The full path that we are listing with trailing \ */
- TCHAR szSubPath[MAX_PATH];
- LPTSTR pszFilePart;
- DWORD dwCount; /* A counter of files found in directory */
- DWORD dwCountFiles; /* Counter for files */
- DWORD dwCountDirs; /* Counter for directories */
- ULONGLONG u64CountBytes; /* Counter for bytes */
- ULARGE_INTEGER u64Temp; /* A temporary counter */
-
- /* Initialize Variables */
- ptrStartNode = NULL;
- ptrNextNode = NULL;
- dwCount = 0;
- dwCountFiles = 0;
- dwCountDirs = 0;
- u64CountBytes = 0;
- fPoint= FALSE;
-
- /* Create szFullPath */
- if (GetFullPathName(szPath, sizeof(szFullPath) / sizeof(TCHAR), szFullPath, &pszFilePart) == 0)
- {
- _tcscpy (szFullPath, szPath);
- pszFilePart = NULL;
- }
-
- /* If no wildcard or file was specified and this is a directory, then
- display all files in it */
- if (pszFilePart == NULL || IsExistingDirectory(szFullPath))
- {
- pszFilePart = &szFullPath[_tcslen(szFullPath)];
- if (pszFilePart[-1] != _T('\\'))
- *pszFilePart++ = _T('\\');
- _tcscpy(pszFilePart, _T("*"));
- }
-
- /* Prepare the linked list, first node is allocated */
- ptrStartNode = cmd_alloc(sizeof(DIRFINDLISTNODE));
- if (ptrStartNode == NULL)
- {
- WARN("DEBUG: Cannot allocate memory for ptrStartNode!\n");
- return 1; /* Error cannot allocate memory for 1st object */
- }
- ptrNextNode = ptrStartNode;
-
- /*Checking ir szPath is a File with/wout extension*/
- if (szPath[_tcslen(szPath) - 1] == _T('.'))
- fPoint= TRUE;
-
- /* Collect the results for the current folder */
- hSearch = FindFirstFile(szFullPath, &wfdFileInfo);
- if (hSearch != INVALID_HANDLE_VALUE)
- {
- do
- {
- /*If retrieved FileName has extension,and szPath doesnt have extension then JUMP the retrieved FileName*/
- if(_tcschr(wfdFileInfo.cFileName,_T('.'))&&(fPoint==TRUE))
- {
- continue;
- /* Here we filter all the specified attributes */
- }else if ((wfdFileInfo.dwFileAttributes & lpFlags->stAttribs.dwAttribMask )
- == (lpFlags->stAttribs.dwAttribMask & lpFlags->stAttribs.dwAttribVal ))
- {
- ptrNextNode->ptrNext = cmd_alloc(sizeof(DIRFINDLISTNODE));
- if (ptrNextNode->ptrNext == NULL)
- {
- WARN("DEBUG: Cannot allocate memory for ptrNextNode->ptrNext!\n");
- while (ptrStartNode)
- {
- ptrNextNode = ptrStartNode->ptrNext;
- cmd_free(ptrStartNode);
- ptrStartNode = ptrNextNode;
- dwCount --;
- }
- FindClose(hSearch);
- return 1;
- }
-
- /* If cmd_alloc fails we go to next file in hope it works,
- without braking the linked list! */
- if (ptrNextNode->ptrNext)
- {
- /* Copy the info of search at linked list */
- memcpy(&ptrNextNode->ptrNext->stFindInfo,
- &wfdFileInfo,
- sizeof(WIN32_FIND_DATA));
-
- /* If lower case is selected do it here */
- if (lpFlags->bLowerCase)
- {
- _tcslwr(ptrNextNode->ptrNext->stFindInfo.cAlternateFileName);
- _tcslwr(ptrNextNode->ptrNext->stFindInfo.cFileName);
- }
-
- /* Continue at next node at linked list */
- ptrNextNode = ptrNextNode->ptrNext;
- dwCount ++;
-
- /* Grab statistics */
- if (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- /* Directory */
- dwCountDirs++;
- }
- else
- {
- /* File */
- dwCountFiles++;
- u64Temp.HighPart = wfdFileInfo.nFileSizeHigh;
- u64Temp.LowPart = wfdFileInfo.nFileSizeLow;
- u64CountBytes += u64Temp.QuadPart;
- }
- }
- }
- } while (FindNextFile(hSearch, &wfdFileInfo));
- FindClose(hSearch);
- }
-
- /* Terminate list */
- ptrNextNode->ptrNext = NULL;
-
- /* Calculate and allocate space need for making an array of pointers */
- ptrFileArray = cmd_alloc(sizeof(LPWIN32_FIND_DATA) * dwCount);
- if (ptrFileArray == NULL)
- {
- WARN("DEBUG: Cannot allocate memory for ptrFileArray!\n");
- while (ptrStartNode)
- {
- ptrNextNode = ptrStartNode->ptrNext;
- cmd_free(ptrStartNode);
- ptrStartNode = ptrNextNode;
- dwCount --;
- }
- return 1;
- }
-
- /*
- * Create an array of pointers from the linked list
- * this will be used to sort and print data, rather than the list
- */
- ptrNextNode = ptrStartNode;
- dwCount = 0;
- while (ptrNextNode->ptrNext)
- {
- *(ptrFileArray + dwCount) = &ptrNextNode->ptrNext->stFindInfo;
- ptrNextNode = ptrNextNode->ptrNext;
- dwCount++;
- }
-
- /* Sort Data if requested*/
- if (lpFlags->stOrderBy.sCriteriaCount > 0)
- QsortFiles(ptrFileArray, 0, dwCount-1, lpFlags);
-
- /* Print Data */
- pszFilePart[-1] = _T('\0'); /* truncate to directory name only */
- DirPrintFiles(ptrFileArray, dwCount, szFullPath, lpFlags);
- pszFilePart[-1] = _T('\\');
-
- if (lpFlags->bRecursive)
- {
- PrintSummary(szFullPath,
- dwCountFiles,
- dwCountDirs,
- u64CountBytes,
- lpFlags,
- FALSE);
- }
-
- /* Free array */
- cmd_free(ptrFileArray);
- /* Free linked list */
- while (ptrStartNode)
- {
- ptrNextNode = ptrStartNode->ptrNext;
- cmd_free(ptrStartNode);
- ptrStartNode = ptrNextNode;
- dwCount --;
- }
-
- if (CheckCtrlBreak(BREAK_INPUT))
- return 1;
-
-
- /* Add statistics to recursive statistics*/
- recurse_dir_cnt += dwCountDirs;
- recurse_file_cnt += dwCountFiles;
- recurse_bytes += u64CountBytes;
-
- /* Do the recursive job if requested
- the recursive is be done on ALL(indepent of their attribs)
- directoried of the current one.*/
- if (lpFlags->bRecursive)
- {
- /* The new search is involving any *.* file */
- memcpy(szSubPath, szFullPath, (pszFilePart - szFullPath) * sizeof(TCHAR));
- _tcscpy(&szSubPath[pszFilePart - szFullPath], _T("*.*"));
-
- hRecSearch = FindFirstFile (szSubPath, &wfdFileInfo);
- if (hRecSearch != INVALID_HANDLE_VALUE)
- {
- do
- {
- /* We search for directories other than "." and ".." */
- if ((_tcsicmp(wfdFileInfo.cFileName, _T(".")) != 0) &&
- (_tcsicmp(wfdFileInfo.cFileName, _T("..")) != 0 ) &&
- (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
- {
- /* Concat the path and the directory to do recursive */
- memcpy(szSubPath, szFullPath, (pszFilePart - szFullPath) * sizeof(TCHAR));
- _tcscpy(&szSubPath[pszFilePart - szFullPath], wfdFileInfo.cFileName);
- _tcscat(szSubPath, _T("\\"));
- _tcscat(szSubPath, pszFilePart);
-
- /* We do the same for the folder */
- if (DirList(szSubPath, lpFlags) != 0)
- {
- FindClose(hRecSearch);
- return 1;
- }
- }
- } while(FindNextFile(hRecSearch, &wfdFileInfo));
- }
- FindClose(hRecSearch);
- }
-
- return 0;
-}
+DirList(LPTSTR szPath, /* [IN] The path that dir starts */
+ LPDIRSWITCHFLAGS lpFlags) /* [IN] The flags of the listing */
+{
+ BOOL fPoint; /* If szPath is a file with extension fPoint will be True */
+ HANDLE hSearch; /* The handle of the search */
+ HANDLE hRecSearch; /* The handle for searching recursively */
+ HANDLE hStreams; /* The handle for alternate streams */
+ WIN32_FIND_DATA wfdFileInfo; /* The info of file that found */
+ PDIRFINDINFO * ptrFileArray; /* An array of pointers with all the files */
+ PDIRFINDLISTNODE ptrStartNode; /* The pointer to the first node */
+ PDIRFINDLISTNODE ptrNextNode; /* A pointer used for relatives references */
+ TCHAR szFullPath[MAX_PATH]; /* The full path that we are listing with trailing '\' */
+ TCHAR szSubPath[MAX_PATH];
+ LPTSTR pszFilePart;
+ DWORD dwCount; /* A counter of files found in directory */
+ DWORD dwCountFiles; /* Counter for files */
+ DWORD dwCountDirs; /* Counter for directories */
+ ULONGLONG u64CountBytes; /* Counter for bytes */
+ ULARGE_INTEGER u64Temp; /* A temporary counter */
+ WIN32_FIND_STREAM_DATA wfsdStreamInfo;
+ PDIRFINDSTREAMNODE * ptrCurNode; /* The pointer to the first stream */
+ static HANDLE (WINAPI *pFindFirstStreamW)(LPCWSTR, STREAM_INFO_LEVELS, LPVOID, DWORD);
+ static BOOL (WINAPI *pFindNextStreamW)(HANDLE, LPVOID);
+
+ /* Initialize variables */
+ ptrStartNode = NULL;
+ ptrNextNode = NULL;
+ dwCount = 0;
+ dwCountFiles = 0;
+ dwCountDirs = 0;
+ u64CountBytes = 0;
+ fPoint= FALSE;
+
+ /* Create szFullPath */
+ if (GetFullPathName(szPath, ARRAYSIZE(szFullPath), szFullPath, &pszFilePart) == 0)
+ {
+ _tcscpy (szFullPath, szPath);
+ pszFilePart = NULL;
+ }
+
+ /* If no wildcard or file was specified and this is a directory, then
+ display all files in it */
+ if (pszFilePart == NULL || IsExistingDirectory(szFullPath))
+ {
+ pszFilePart = &szFullPath[_tcslen(szFullPath)];
+ if (pszFilePart[-1] != _T('\\'))
+ *pszFilePart++ = _T('\\');
+ _tcscpy(pszFilePart, _T("*"));
+ }
+
+ /* Prepare the linked list, first node is allocated */
+ ptrStartNode = cmd_alloc(sizeof(DIRFINDLISTNODE));
+ if (ptrStartNode == NULL)
+ {
+ WARN("DEBUG: Cannot allocate memory for ptrStartNode!\n");
+ return 1; /* Error cannot allocate memory for 1st object */
+ }
+ ptrStartNode->stInfo.ptrHead = NULL;
+ ptrNextNode = ptrStartNode;
+ /* Checking if szPath is a File with/wout extension */
+ if (szPath[_tcslen(szPath) - 1] == _T('.'))
+ fPoint= TRUE;
+ /* Collect the results for the current folder */
+ hSearch = FindFirstFile(szFullPath, &wfdFileInfo);
+ if (hSearch != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ /* If retrieved FileName has extension,and szPath doesnt have extension then JUMP the retrieved FileName */
+ if (_tcschr(wfdFileInfo.cFileName,_T('.')) && (fPoint != FALSE))
+ {
+ continue;
+ /* Here we filter all the specified attributes */
+ }
+ else if ((wfdFileInfo.dwFileAttributes & lpFlags->stAttribs.dwAttribMask )
+ == (lpFlags->stAttribs.dwAttribMask & lpFlags->stAttribs.dwAttribVal ))
+ {
+ ptrNextNode->ptrNext = cmd_alloc(sizeof(DIRFINDLISTNODE));
+ if (ptrNextNode->ptrNext == NULL)
+ {
+ WARN("DEBUG: Cannot allocate memory for ptrNextNode->ptrNext!\n");
+ DirNodeCleanup(ptrStartNode, &dwCount);
+ FindClose(hSearch);
+ return 1;
+ }
+
+ /* Copy the info of search at linked list */
+ memcpy(&ptrNextNode->ptrNext->stInfo.stFindInfo,
+ &wfdFileInfo,
+ sizeof(WIN32_FIND_DATA));
+
+ /* If lower case is selected do it here */
+ if (lpFlags->bLowerCase)
+ {
+ _tcslwr(ptrNextNode->ptrNext->stInfo.stFindInfo.cAlternateFileName);
+ _tcslwr(ptrNextNode->ptrNext->stInfo.stFindInfo.cFileName);
+ }
+
+ /* No streams (yet?) */
+ ptrNextNode->ptrNext->stInfo.ptrHead = NULL;
+
+ /* Alternate streams are only displayed with new long list */
+ if (lpFlags->bNewLongList && lpFlags->bDataStreams)
+ {
+ if (!pFindFirstStreamW)
+ {
+ pFindFirstStreamW = (PVOID)GetProcAddress(GetModuleHandle(_T("kernel32")), "FindFirstStreamW");
+ pFindNextStreamW = (PVOID)GetProcAddress(GetModuleHandle(_T("kernel32")), "FindNextStreamW");
+ }
+
+ /* Try to get stream information */
+ if (pFindFirstStreamW && pFindNextStreamW)
+ {
+ hStreams = pFindFirstStreamW(wfdFileInfo.cFileName, FindStreamInfoStandard, &wfsdStreamInfo, 0);
+ }
+ else
+ {
+ hStreams = INVALID_HANDLE_VALUE;
+ ERR("FindFirstStreamW not supported!\n");
+ }
+
+ if (hStreams != INVALID_HANDLE_VALUE)
+ {
+ /* We totally ignore first stream. It contains data about ::$DATA */
+ ptrCurNode = &ptrNextNode->ptrNext->stInfo.ptrHead;
+ while (pFindNextStreamW(hStreams, &wfsdStreamInfo))
+ {
+ *ptrCurNode = cmd_alloc(sizeof(DIRFINDSTREAMNODE));
+ if (*ptrCurNode == NULL)
+ {
+ WARN("DEBUG: Cannot allocate memory for *ptrCurNode!\n");
+ DirNodeCleanup(ptrStartNode, &dwCount);
+ FindClose(hStreams);
+ FindClose(hSearch);
+ return 1;
+ }
+
+ memcpy(&(*ptrCurNode)->stStreamInfo, &wfsdStreamInfo,
+ sizeof(WIN32_FIND_STREAM_DATA));
+
+ /* If lower case is selected do it here */
+ if (lpFlags->bLowerCase)
+ {
+ _tcslwr((*ptrCurNode)->stStreamInfo.cStreamName);
+ }
+
+ ptrCurNode = &(*ptrCurNode)->ptrNext;
+ }
+
+ FindClose(hStreams);
+ *ptrCurNode = NULL;
+ }
+ }
+
+ /* Continue at next node at linked list */
+ ptrNextNode = ptrNextNode->ptrNext;
+ dwCount++;
+
+ /* Grab statistics */
+ if (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ /* Directory */
+ dwCountDirs++;
+ }
+ else
+ {
+ /* File */
+ dwCountFiles++;
+ u64Temp.HighPart = wfdFileInfo.nFileSizeHigh;
+ u64Temp.LowPart = wfdFileInfo.nFileSizeLow;
+ u64CountBytes += u64Temp.QuadPart;
+ }
+ }
+ } while (FindNextFile(hSearch, &wfdFileInfo));
+ FindClose(hSearch);
+ }
+
+ /* Terminate list */
+ ptrNextNode->ptrNext = NULL;
+
+ /* Calculate and allocate space need for making an array of pointers */
+ ptrFileArray = cmd_alloc(sizeof(PDIRFINDINFO) * dwCount);
+ if (ptrFileArray == NULL)
+ {
+ WARN("DEBUG: Cannot allocate memory for ptrFileArray!\n");
+ DirNodeCleanup(ptrStartNode, &dwCount);
+ return 1;
+ }
+
+ /*
+ * Create an array of pointers from the linked list
+ * this will be used to sort and print data, rather than the list
+ */
+ ptrNextNode = ptrStartNode;
+ dwCount = 0;
+ while (ptrNextNode->ptrNext)
+ {
+ ptrFileArray[dwCount] = &ptrNextNode->ptrNext->stInfo;
+ ptrNextNode = ptrNextNode->ptrNext;
+ dwCount++;
+ }
+
+ /* Sort Data if requested */
+ if (lpFlags->stOrderBy.sCriteriaCount > 0)
+ QsortFiles(ptrFileArray, 0, dwCount-1, lpFlags);
+
+ /* Print Data */
+ pszFilePart[-1] = _T('\0'); /* truncate to directory name only */
+ DirPrintFiles(ptrFileArray, dwCount, szFullPath, lpFlags);
+ pszFilePart[-1] = _T('\\');
+
+ if (lpFlags->bRecursive)
+ {
+ PrintSummary(szFullPath,
+ dwCountFiles,
+ dwCountDirs,
+ u64CountBytes,
+ lpFlags,
+ FALSE);
+ }
+
+ /* Free array */
+ cmd_free(ptrFileArray);
+
+ /* Free linked list */
+ DirNodeCleanup(ptrStartNode, &dwCount);
+
+ if (CheckCtrlBreak(BREAK_INPUT))
+ return 1;
+
+ /* Add statistics to recursive statistics */
+ recurse_dir_cnt += dwCountDirs;
+ recurse_file_cnt += dwCountFiles;
+ recurse_bytes += u64CountBytes;
+
+ /*
+ * Do the recursive job if requested.
+ * The recursion is done on ALL (independent of their attributes)
+ * directories of the current one.
+ */
+ if (lpFlags->bRecursive)
+ {
+ /* The new search is involving any *.* file */
+ memcpy(szSubPath, szFullPath, (pszFilePart - szFullPath) * sizeof(TCHAR));
+ _tcscpy(&szSubPath[pszFilePart - szFullPath], _T("*.*"));
+
+ hRecSearch = FindFirstFile(szSubPath, &wfdFileInfo);
+ if (hRecSearch != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ /* We search for directories other than "." and ".." */
+ if ((_tcsicmp(wfdFileInfo.cFileName, _T(".")) != 0) &&
+ (_tcsicmp(wfdFileInfo.cFileName, _T("..")) != 0) &&
+ (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
+ {
+ /* Concat the path and the directory to do recursive */
+ memcpy(szSubPath, szFullPath, (pszFilePart - szFullPath) * sizeof(TCHAR));
+ _tcscpy(&szSubPath[pszFilePart - szFullPath], wfdFileInfo.cFileName);
+ _tcscat(szSubPath, _T("\\"));
+ _tcscat(szSubPath, pszFilePart);
+
+ /* We do the same for the folder */
+ if (DirList(szSubPath, lpFlags) != 0)
+ {
+ FindClose(hRecSearch);
+ return 1;
+ }
+ }
+ } while (FindNextFile(hRecSearch, &wfdFileInfo));
+ }
+ FindClose(hRecSearch);
+ }
+
+ return 0;
+}
/*
* dir
INT
CommandDir(LPTSTR rest)
{
- TCHAR dircmd[256]; /* A variable to store the DIRCMD enviroment variable */
- TCHAR path[MAX_PATH];
- TCHAR prev_volume[MAX_PATH];
- LPTSTR* params = NULL;
- LPTSTR pszFilePart;
- INT entries = 0;
- UINT loop = 0;
- DIRSWITCHFLAGS stFlags;
- INT ret = 1;
- BOOL ChangedVolume;
-
- /* Initialize Switch Flags < Default switches are setted here!> */
- stFlags.b4Digit = TRUE;
- stFlags.bBareFormat = FALSE;
- stFlags.bLowerCase = FALSE;
- stFlags.bNewLongList = TRUE;
- stFlags.bPause = FALSE;
- stFlags.bRecursive = FALSE;
- stFlags.bShortName = FALSE;
- stFlags.bTSeperator = TRUE;
- stFlags.bUser = FALSE;
- stFlags.bWideList = FALSE;
- stFlags.bWideListColSort = FALSE;
- stFlags.stTimeField.eTimeField = TF_MODIFIEDDATE;
- stFlags.stAttribs.dwAttribMask = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
- stFlags.stAttribs.dwAttribVal = 0L;
- stFlags.stOrderBy.sCriteriaCount = 0;
-
- nErrorLevel = 0;
-
- /* read the parameters from the DIRCMD environment variable */
- if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256))
- if (!DirReadParam(dircmd, ¶ms, &entries, &stFlags))
- {
- nErrorLevel = 1;
- goto cleanup;
- }
-
- /* read the parameters */
- if (!DirReadParam(rest, ¶ms, &entries, &stFlags) || CheckCtrlBreak(BREAK_INPUT))
- {
- nErrorLevel = 1;
- goto cleanup;
- }
-
- /* default to current directory */
- if(entries == 0) {
- if(!add_entry(&entries, ¶ms, _T("*"))) {
- nErrorLevel = 1;
- goto cleanup;
- }
- }
-
- prev_volume[0] = _T('\0');
-
- /* Reset paging state */
- if (stFlags.bPause)
- ConOutPrintfPaging(TRUE, _T(""));
-
- for(loop = 0; loop < (UINT)entries; loop++)
- {
- if (CheckCtrlBreak(BREAK_INPUT))
- {
- nErrorLevel = 1;
- goto cleanup;
- }
-
- recurse_dir_cnt = 0L;
- recurse_file_cnt = 0L;
- recurse_bytes = 0;
-
- /* <Debug :>
- Uncomment this to show the final state of switch flags*/
- {
- int i;
- TRACE("Attributes mask/value %x/%x\n",stFlags.stAttribs.dwAttribMask,stFlags.stAttribs.dwAttribVal );
- TRACE("(B) Bare format : %i\n", stFlags.bBareFormat );
- TRACE("(C) Thousand : %i\n", stFlags.bTSeperator );
- TRACE("(W) Wide list : %i\n", stFlags.bWideList );
- TRACE("(D) Wide list sort by column : %i\n", stFlags.bWideListColSort );
- TRACE("(L) Lowercase : %i\n", stFlags.bLowerCase );
- TRACE("(N) New : %i\n", stFlags.bNewLongList );
- TRACE("(O) Order : %i\n", stFlags.stOrderBy.sCriteriaCount );
- for (i =0;i<stFlags.stOrderBy.sCriteriaCount;i++)
- TRACE(" Order Criteria [%i]: %i (Reversed: %i)\n",i, stFlags.stOrderBy.eCriteria[i], stFlags.stOrderBy.bCriteriaRev[i] );
- TRACE("(P) Pause : %i\n", stFlags.bPause );
- TRACE("(Q) Owner : %i\n", stFlags.bUser );
- TRACE("(S) Recursive : %i\n", stFlags.bRecursive );
- TRACE("(T) Time field : %i\n", stFlags.stTimeField.eTimeField );
- TRACE("(X) Short names : %i\n", stFlags.bShortName );
- TRACE("Parameter : %s\n", debugstr_aw(params[loop]) );
- }
-
- /* Print the drive header if the volume changed */
- ChangedVolume = TRUE;
-
- if (!stFlags.bBareFormat &&
- GetVolumePathName(params[loop], path, sizeof(path) / sizeof(TCHAR)))
- {
- if (!_tcscmp(path, prev_volume))
- ChangedVolume = FALSE;
- else
- _tcscpy(prev_volume, path);
- }
- else if (GetFullPathName(params[loop], sizeof(path) / sizeof(TCHAR), path, &pszFilePart) != 0)
- {
- if (pszFilePart != NULL)
- *pszFilePart = _T('\0');
- }
- else
- _tcscpy(path, params[loop]);
-
- if (ChangedVolume && !stFlags.bBareFormat) {
- if (!PrintDirectoryHeader (params[loop], &stFlags)) {
- nErrorLevel = 1;
- goto cleanup;
- }
- }
-
- /* do the actual dir */
- if (DirList (params[loop], &stFlags))
- {
- nErrorLevel = 1;
- goto cleanup;
- }
-
- /* print the footer */
- PrintSummary(path,
- recurse_file_cnt,
- recurse_dir_cnt,
- recurse_bytes,
- &stFlags,
- TRUE);
- }
-
- ret = 0;
+ TCHAR dircmd[MAX_PATH]; /* A variable to store the DIRCMD environment variable */
+ TCHAR path[MAX_PATH];
+ TCHAR prev_volume[MAX_PATH];
+ LPTSTR* params = NULL;
+ LPTSTR pszFilePart;
+ INT entries = 0;
+ UINT loop = 0;
+ DIRSWITCHFLAGS stFlags;
+ INT ret = 1;
+ BOOL ChangedVolume;
+
+ /* Initialize Switch Flags < Default switches are set here! > */
+ stFlags.b4Digit = TRUE;
+ stFlags.bBareFormat = FALSE;
+ stFlags.bDataStreams = FALSE;
+ stFlags.bLowerCase = FALSE;
+ stFlags.bNewLongList = TRUE;
+ stFlags.bPause = FALSE;
+ stFlags.bRecursive = FALSE;
+ stFlags.bShortName = FALSE;
+ stFlags.bTSeparator = TRUE;
+ stFlags.bUser = FALSE;
+ stFlags.bWideList = FALSE;
+ stFlags.bWideListColSort = FALSE;
+ stFlags.stTimeField.eTimeField = TF_MODIFIEDDATE;
+ stFlags.stAttribs.dwAttribMask = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;
+ stFlags.stAttribs.dwAttribVal = 0L;
+ stFlags.stOrderBy.sCriteriaCount = 0;
+
+ nErrorLevel = 0;
+
+ /* Read the parameters from the DIRCMD environment variable */
+ if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, ARRAYSIZE(dircmd)))
+ {
+ if (!DirReadParam(dircmd, ¶ms, &entries, &stFlags))
+ {
+ nErrorLevel = 1;
+ goto cleanup;
+ }
+ }
+
+ /* Read the parameters */
+ if (!DirReadParam(rest, ¶ms, &entries, &stFlags) || CheckCtrlBreak(BREAK_INPUT))
+ {
+ nErrorLevel = 1;
+ goto cleanup;
+ }
+
+ /* Default to current directory */
+ if (entries == 0)
+ {
+ if (!add_entry(&entries, ¶ms, _T("*")))
+ {
+ nErrorLevel = 1;
+ goto cleanup;
+ }
+ }
+
+ prev_volume[0] = _T('\0');
+
+ /* Reset paging state */
+ if (stFlags.bPause)
+ ConOutPrintfPaging(TRUE, _T(""));
+
+ for (loop = 0; loop < (UINT)entries; loop++)
+ {
+ if (CheckCtrlBreak(BREAK_INPUT))
+ {
+ nErrorLevel = 1;
+ goto cleanup;
+ }
+
+ recurse_dir_cnt = 0L;
+ recurse_file_cnt = 0L;
+ recurse_bytes = 0;
+
+ /* <Debug :>
+ Uncomment this to show the final state of switch flags*/
+ {
+ int i;
+ TRACE("Attributes mask/value %x/%x\n",stFlags.stAttribs.dwAttribMask,stFlags.stAttribs.dwAttribVal);
+ TRACE("(B) Bare format : %i\n", stFlags.bBareFormat);
+ TRACE("(C) Thousand : %i\n", stFlags.bTSeparator);
+ TRACE("(W) Wide list : %i\n", stFlags.bWideList);
+ TRACE("(D) Wide list sort by column : %i\n", stFlags.bWideListColSort);
+ TRACE("(L) Lowercase : %i\n", stFlags.bLowerCase);
+ TRACE("(N) New : %i\n", stFlags.bNewLongList);
+ TRACE("(O) Order : %i\n", stFlags.stOrderBy.sCriteriaCount);
+ for (i =0;i<stFlags.stOrderBy.sCriteriaCount;i++)
+ TRACE(" Order Criteria [%i]: %i (Reversed: %i)\n",i, stFlags.stOrderBy.eCriteria[i], stFlags.stOrderBy.bCriteriaRev[i]);
+ TRACE("(P) Pause : %i\n", stFlags.bPause);
+ TRACE("(Q) Owner : %i\n", stFlags.bUser);
+ TRACE("(R) Data stream : %i\n", stFlags.bDataStreams);
+ TRACE("(S) Recursive : %i\n", stFlags.bRecursive);
+ TRACE("(T) Time field : %i\n", stFlags.stTimeField.eTimeField);
+ TRACE("(X) Short names : %i\n", stFlags.bShortName);
+ TRACE("Parameter : %s\n", debugstr_aw(params[loop]));
+ }
+
+ /* Print the drive header if the volume changed */
+ ChangedVolume = TRUE;
+
+ if (!stFlags.bBareFormat &&
+ GetVolumePathName(params[loop], path, ARRAYSIZE(path)))
+ {
+ if (!_tcscmp(path, prev_volume))
+ ChangedVolume = FALSE;
+ else
+ _tcscpy(prev_volume, path);
+ }
+ else if (GetFullPathName(params[loop], ARRAYSIZE(path), path, &pszFilePart) != 0)
+ {
+ if (pszFilePart != NULL)
+ *pszFilePart = _T('\0');
+ }
+ else
+ {
+ _tcscpy(path, params[loop]);
+ }
+
+ /* Print the header */
+ if (ChangedVolume && !stFlags.bBareFormat &&
+ !PrintDirectoryHeader(params[loop], &stFlags))
+ {
+ nErrorLevel = 1;
+ goto cleanup;
+ }
+
+ /* Perform the actual directory listing */
+ if (DirList(params[loop], &stFlags) != 0)
+ {
+ nErrorLevel = 1;
+ goto cleanup;
+ }
+
+ /* Print the footer */
+ PrintSummary(path,
+ recurse_file_cnt,
+ recurse_dir_cnt,
+ recurse_bytes,
+ &stFlags,
+ TRUE);
+ }
+
+ ret = 0;
cleanup:
- freep(params);
+ freep(params);
- return ret;
+ return ret;
}
#endif