take care of Bug#: 1084
[reactos.git] / reactos / subsys / system / cmd / dir.c
index 925938d..7239811 100644 (file)
  *
  *    01-Mar-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
  *        Replaced all runtime io functions by their Win32 counterparts.
- *  
+ *
  *    23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
  *        dir /s now works in deeper trees
  *
  *        the code is rewritten. /p is removed, to be rewriten in
  *        the main cmd code.
  *
+ *    1-Jul-2004 (Brandon Turner <turnerb7@msu.edu>)
+ *        Added /p back in using ConOutPrintfPaging
  */
 
-#include "precomp.h"
+#include <precomp.h>
 #include "resource.h"
 
 #ifdef INCLUDE_CMD_DIR
@@ -197,8 +199,8 @@ typedef struct _DIRFINDLISTNODE
 } DIRFINDLISTNODE, *PDIRFINDLISTNODE;
 
 
-typedef BOOL STDCALL
-(*PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
+typedef BOOL
+(WINAPI *PGETFREEDISKSPACEEX)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
 
 
 /* Globally save the # of dirs, files and bytes,
@@ -214,9 +216,10 @@ static ULARGE_INTEGER recurse_bytes;
  * displays help screen for dir
  * Rob Lake
  */
-static VOID DirHelp(VOID)
+static VOID 
+DirHelp(VOID)
 {
-  ConOutResPuts(STRING_DIR_HELP1);
+  ConOutResPaging(TRUE, STRING_DIR_HELP1);
 }
 
 
@@ -226,18 +229,30 @@ static VOID DirHelp(VOID)
  *
  * Parse the parameters and switches of the command line and exports them
  */
-static BOOL
+static BOOL 
 DirReadParam(LPTSTR Line,                              /* [IN] The line with the parameters & switches */
-            LPTSTR *param,                     /* [OUT] The parameters after parsing */
-            LPDIRSWITCHFLAGS lpFlags)  /* [IN/OUT] The flags after calculating 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 ptrLast;      /* A pointer to the last character of param */
+       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 */
+       LPTSTR temp;
+
+       /* Initialize parameter array */
+       *params = malloc(sizeof(LPTSTR));
+       if(!params)
+               return FALSE;
+       *params = NULL;
+       *entries = 0;
+       ptrStart = NULL;
+       ptrEnd = NULL;
 
        /* Initialize variables; */
        cCurSwitch = _T(' ');
@@ -245,10 +260,6 @@ DirReadParam(LPTSTR Line,                          /* [IN] The line with the parameters & switches */
        bPNegative = FALSE;
        bIntoQuotes = FALSE;
 
-       /* No parameters yet  */
-       *param = NULL;
-       ptrLast = NULL;
-       
        /* We suppose that switch parameters
           were given to avoid setting them to default
           if the switch was not given */
@@ -256,14 +267,15 @@ DirReadParam(LPTSTR Line,                         /* [IN] The line with the parameters & switches */
        lpFlags->stOrderBy.bParSetted = TRUE;
        lpFlags->stTimeField.bParSetted = TRUE;
 
+       
        /* 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 = _toupper(*Line);
-               
+               cCurUChar = _totupper(*Line);
+
                /* 1st section (see README_DIR.txt) */
                /* When a switch is expecting */
                if (cCurSwitch == _T('/'))
@@ -347,8 +359,25 @@ DirReadParam(LPTSTR Line,                          /* [IN] The line with the parameters & switches */
                                if (!bIntoQuotes)
                                {
                                        cCurSwitch = _T(' ');
-                                       if ((*param) && !(ptrLast))
-                                               ptrLast = Line;
+                                       if(ptrStart && ptrEnd)
+                                       {               
+                                               temp = malloc((ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+                                               if(!temp)
+                                                       return FALSE;
+                                               memcpy(temp, ptrStart, (ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+                                               temp[(ptrEnd - ptrStart + 1)] = _T('\0');
+                                               if(!add_entry(entries, params, temp))
+                                               {
+                                                       free(temp);
+                                                       freep(*params);
+                                                       return FALSE;
+                                               }
+
+                                               free(temp);
+
+                                               ptrStart = NULL;
+                                               ptrEnd = NULL;
+                                       }
                                }
 
                        }
@@ -356,19 +385,35 @@ DirReadParam(LPTSTR Line,                         /* [IN] The line with the parameters & switches */
                        {
                                /* Process a quote */
                                bIntoQuotes = !bIntoQuotes;
-                               if (!bIntoQuotes) ptrLast = Line;
+                               if(!bIntoQuotes)
+                                       ptrEnd = Line;
                        }
                        else
                        {
                                /* Process a character for parameter */
-                               if ((cCurSwitch == _T(' ')) && (*param))
-                               {
-                                       error_too_many_parameters(Line);
-                                       return FALSE;
+                               if ((cCurSwitch == _T(' ')) && ptrStart && ptrEnd)
+                               {               
+                                       temp = malloc((ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+                                       if(!temp)
+                                               return FALSE;
+                                       memcpy(temp, ptrStart, (ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+                                       temp[(ptrEnd - ptrStart + 1)] = _T('\0');
+                                       if(!add_entry(entries, params, temp))
+                                       {
+                                               free(temp);
+                                               freep(*params);
+                                               return FALSE;
+                                       }
+
+                                       free(temp);
+
+                                       ptrStart = NULL;
+                                       ptrEnd = NULL;
                                }
                                cCurSwitch = _T('P');
-                               if (!(*param))
-                                       *param = Line;
+                               if(!ptrStart)
+                                       ptrStart = ptrEnd = Line;
+                               ptrEnd = Line;
                        }
                }
                else
@@ -513,11 +558,29 @@ DirReadParam(LPTSTR Line,                         /* [IN] The line with the parameters & switches */
                        if ((cCurChar != _T('-')) && bPNegative)
                                bPNegative = FALSE;
                }
-       
+
                Line++;
        }
        /* Terminate the parameters */
-       if (ptrLast) *ptrLast = 0;
+       if(ptrStart && ptrEnd)
+       {               
+               temp = malloc((ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+               if(!temp)
+                       return FALSE;
+               memcpy(temp, ptrStart, (ptrEnd - ptrStart) + 2 * sizeof (TCHAR));
+               temp[(ptrEnd - ptrStart + 1)] = _T('\0');
+               if(!add_entry(entries, params, temp))
+               {
+                       free(temp);
+                       freep(*params);
+                       return FALSE;
+               }
+
+               free(temp);
+
+               ptrStart = NULL;
+               ptrEnd = NULL;
+       }
 
        /* Calculate the switches with no switch paramater  */
        if (!(lpFlags->stAttribs.bParSetted))
@@ -568,6 +631,7 @@ ExtendFilespec (LPTSTR file)
        if (!file)
                return;
 
+
        /* if no file spec, change to "*.*" */
        if (*file == _T('\0'))
        {
@@ -575,6 +639,12 @@ ExtendFilespec (LPTSTR file)
                return;
        }
 
+       // add support for *.
+       if ((file[0] == _T('*')) && (file[1] == _T('.') ))
+        {
+                return;
+        }
+
        /* if starts with . add * in front */
        if (*file == _T('.'))
        {
@@ -589,6 +659,8 @@ ExtendFilespec (LPTSTR file)
                return;
        }
 
+
+
        /* if last character is '.' add '*' */
        len = _tcslen (file);
        if (file[len - 1] == _T('.'))
@@ -838,19 +910,34 @@ PrintDirectoryHeader(LPTSTR szPath, LPINT pLine, LPDIRSWITCHFLAGS lpFlags)
   if (szVolName[0] != _T('\0'))
     {
       LoadString(CMD_ModuleHandle, STRING_DIR_HELP2, szMsg, RC_STRING_MAX_SIZE);
-      ConOutPrintf((LPTSTR)szMsg, szRootName[0], szVolName);
+      //needs to have first paramter as TRUE because
+         //this is the first output and need to clear the static
+         if(lpFlags->bPause)
+                ConOutPrintfPaging(TRUE,szMsg, szRootName[0], szVolName);
+         else
+                ConOutPrintf(szMsg, szRootName[0], szVolName);
+                
     }
   else
     {
       LoadString(CMD_ModuleHandle, STRING_DIR_HELP3, szMsg, RC_STRING_MAX_SIZE);
-      ConOutPrintf(szMsg, szRootName[0]);
+       if(lpFlags->bPause)
+                ConOutPrintfPaging(TRUE,szMsg, szRootName[0]);
+       else
+                ConOutPrintf(szMsg, szRootName[0]);
     }
 
   /* print the volume serial number if the return was successful */
   LoadString(CMD_ModuleHandle, STRING_DIR_HELP4, (LPTSTR) szMsg, RC_STRING_MAX_SIZE);
-  ConOutPrintf((LPTSTR)szMsg,
+  if(lpFlags->bPause)
+        ConOutPrintfPaging(FALSE,szMsg,
                HIWORD(dwSerialNr),
                LOWORD(dwSerialNr));
+  else
+        ConOutPrintf(szMsg,
+               HIWORD(dwSerialNr),
+               LOWORD(dwSerialNr));
+
 
   return TRUE;
 }
@@ -895,38 +982,6 @@ ConvertULong (ULONG num, LPTSTR des, INT len)
 }
 #endif
 
-static INT
-ConvertULargeInteger (ULARGE_INTEGER num, LPTSTR des, INT len, BOOL bPutSeperator)
-{
-       TCHAR temp[32];
-       INT c = 0;
-       INT n = 0;
-
-       if (num.QuadPart == 0)
-       {
-               des[0] = _T('0');
-               des[1] = _T('\0');
-               n = 1;
-       }
-       else
-       {
-               temp[31] = 0;
-               while (num.QuadPart > 0)
-               {
-                       if ((((c + 1) % (nNumberGroups + 1)) == 0) && (bPutSeperator))
-                               temp[30 - c++] = cThousandSeparator;
-   temp[30 - c++] = (TCHAR)(num.QuadPart % 10) + _T('0');
-                       num.QuadPart /= 10;
-               }
-
-               for (n = 0; n <= c; n++)
-                       des[n] = temp[31 - c + n];
-       }
-
-       return n;
-}
-
-
 static VOID
 DirPrintFileDateTime(TCHAR *lpDate,
                      TCHAR *lpTime,
@@ -1075,25 +1130,63 @@ PrintSummary(LPTSTR szPath,
                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 (lpFlags->bRecursive)
        {
                ConvertULargeInteger(u64Bytes, szBuffer, sizeof(szBuffer), lpFlags->bTSeperator);
 
                LoadString(CMD_ModuleHandle, STRING_DIR_HELP5, szMsg, RC_STRING_MAX_SIZE);
-               ConOutPrintf(szMsg,ulFiles, szBuffer);
+               if(lpFlags->bPause)
+                  ConOutPrintfPaging(FALSE,szMsg,ulFiles, szBuffer);
+               else
+                  ConOutPrintf(szMsg,ulFiles, szBuffer);
+                  
+                  if (ulFiles > 0)
+       {
+               ConvertULargeInteger(u64Bytes, szBuffer, 20, lpFlags->bTSeperator);
+               LoadString(CMD_ModuleHandle, STRING_DIR_HELP8, szMsg, RC_STRING_MAX_SIZE);
+               if(lpFlags->bPause)
+                  ConOutPrintfPaging(FALSE,szMsg,ulFiles, szBuffer);
+               else
+                  ConOutPrintf(szMsg,ulFiles, szBuffer);
+
        }
+       
+       }
+     else
+     {
+     
+       /* Print File Summary */
+       /* Condition to print summary is:
+          If we are not in bare format and if we have results! */
+       if (ulFiles > 0)
+       {
+               ConvertULargeInteger(u64Bytes, szBuffer, 20, lpFlags->bTSeperator);
+               LoadString(CMD_ModuleHandle, STRING_DIR_HELP8, szMsg, RC_STRING_MAX_SIZE);
+               if(lpFlags->bPause)
+                  ConOutPrintfPaging(FALSE,szMsg,ulFiles, szBuffer);
+               else
+                  ConOutPrintf(szMsg,ulFiles, szBuffer);
 
-       /* Print total  directories and freespace */
+       }
+       
+}
+       /* Print total directories and freespace */
        szRoot[0] = szPath[0];
        GetUserDiskFreeSpace(szRoot, &uliFree);
        ConvertULargeInteger(uliFree, szBuffer, sizeof(szBuffer), lpFlags->bTSeperator);
        LoadString(CMD_ModuleHandle, STRING_DIR_HELP6, (LPTSTR) szMsg, RC_STRING_MAX_SIZE);
-       ConOutPrintf((LPTSTR)szMsg,ulDirs, szBuffer);
+       if(lpFlags->bPause)
+          ConOutPrintfPaging(FALSE,szMsg,ulDirs, szBuffer);
+       else
+          ConOutPrintf(szMsg,ulDirs, szBuffer);
 
        return 0;
 }
@@ -1101,7 +1194,7 @@ PrintSummary(LPTSTR szPath,
 /*
  * getExt
  *
- * Get the extension of a filename 
+ * Get the extension of a filename
  */
 TCHAR* getExt(const TCHAR* file)
 {
@@ -1115,7 +1208,8 @@ TCHAR* getExt(const TCHAR* file)
  *
  * Get the name of the file without extension
  */
-static LPTSTR getName(const TCHAR* file, TCHAR * dest)
+static LPTSTR 
+getName(const TCHAR* file, TCHAR * dest)
 {
        int iLen;
        LPTSTR end;
@@ -1133,11 +1227,11 @@ static LPTSTR getName(const TCHAR* file, TCHAR * dest)
                iLen = _tcslen(file);
        else
                iLen = (end - file);
-       
+
 
        _tcsncpy(dest, file, iLen);
        *(dest + iLen) = _T('\0');
-       
+
        return dest;
 }
 
@@ -1188,13 +1282,22 @@ DirPrintNewList(LPWIN32_FIND_DATA ptrFiles[],   /* [IN]Files' Info */
     DirPrintFileDateTime(szDate, szTime, ptrFiles[i], lpFlags);
 
     /* Print the line */
-    ConOutPrintf(_T("%10s  %-8s    %*s%s %s\n"),
-                szDate,
-                szTime,
-                iSizeFormat,
-                szSize,
-                szShortName,
-                ptrFiles[i]->cFileName);
+    if(lpFlags->bPause)
+               ConOutPrintfPaging(FALSE,_T("%10s  %-8s    %*s%s %s\n"),
+                                                       szDate,
+                                                       szTime,
+                                                       iSizeFormat,
+                                                       szSize,
+                                                       szShortName,
+                                                       ptrFiles[i]->cFileName);
+       else
+               ConOutPrintf(_T("%10s  %-8s    %*s%s %s\n"),
+                                                       szDate,
+                                                       szTime,
+                                                       iSizeFormat,
+                                                       szSize,
+                                                       szShortName,
+                                                       ptrFiles[i]->cFileName);
   }
 }
 
@@ -1206,14 +1309,14 @@ DirPrintNewList(LPWIN32_FIND_DATA ptrFiles[],   /* [IN]Files' Info */
  */
 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 */
+                                DWORD dwCount,                 /* [IN] The quantity of files */
+                                TCHAR *szCurPath,              /* [IN] Full path of current directory */
+                                LPDIRSWITCHFLAGS lpFlags)      /* [IN] The flags used */
 {
   SHORT iScreenWidth;
   USHORT iColumns;
   USHORT iLines;
-  INT iLongestName;
+  UINT iLongestName;
   TCHAR szTempFname[MAX_PATH];
   DWORD i;
   DWORD j;
@@ -1241,7 +1344,7 @@ DirPrintWideList(LPWIN32_FIND_DATA ptrFiles[],    /* [IN] Files' Info */
   iColumns = iScreenWidth / iLongestName;
 
   /* Check if there is enough space for spaces between names */
-  if (((iLongestName * iColumns) + iColumns) >= iScreenWidth)
+  if (((iLongestName * iColumns) + iColumns) >= (UINT)iScreenWidth)
     iColumns --;
 
   /* A last check at iColumns to avoid division by zero */
@@ -1253,7 +1356,7 @@ DirPrintWideList(LPWIN32_FIND_DATA ptrFiles[],    /* [IN] Files' Info */
   {
     /* Calculate the lines that will be printed */
 //    iLines = ceil((float)dwCount/(float)iColumns);
-    iLines = dwCount / iColumns;
+    iLines = (USHORT)(dwCount / iColumns);
 
     for (i = 0;i < iLines;i++)
     {
@@ -1268,10 +1371,16 @@ DirPrintWideList(LPWIN32_FIND_DATA ptrFiles[],  /* [IN] Files' Info */
         else
           _stprintf(szTempFname, _T("%s"), ptrFiles[temp]->cFileName);
 
-        ConOutPrintf(_T("%-*s"), iLongestName + 1 , szTempFname);
+        if(lpFlags->bPause)
+                  ConOutPrintfPaging(FALSE,_T("%-*s"), iLongestName + 1 , szTempFname);
+               else
+                  ConOutPrintf(_T("%-*s"), iLongestName + 1 , szTempFname);
       }
 
-      ConOutPrintf(_T("\n"));
+      if(lpFlags->bPause)
+                ConOutPrintfPaging(FALSE,_T("\n"));
+         else
+                ConOutPrintf(_T("\n"));
     }
   }
   else
@@ -1284,18 +1393,29 @@ DirPrintWideList(LPWIN32_FIND_DATA ptrFiles[],  /* [IN] Files' Info */
       else
         _stprintf(szTempFname, _T("%s"), ptrFiles[i]->cFileName);
 
-      ConOutPrintf(_T("%-*s"), iLongestName + 1, szTempFname );
+      if(lpFlags->bPause)
+                ConOutPrintfPaging(FALSE,_T("%-*s"), iLongestName + 1, szTempFname );
+         else
+                ConOutPrintf(_T("%-*s"), iLongestName + 1, szTempFname );
 
       /*
        * We print a new line at the end of each column
        * except for the case that it is the last item.
        */
-      if (!((i + 1) % iColumns) && (i < (dwCount - 1)))
-        ConOutPrintf(_T("\n"));
+         if (!((i + 1) % iColumns) && (i < (dwCount - 1)))
+         {
+                 if(lpFlags->bPause)
+                        ConOutPrintfPaging(FALSE,_T("\n"));
+                 else
+                    ConOutPrintf(_T("\n"));
+         }
     }
 
     /* Add a new line after the last item */
-    ConOutPrintf(_T("\n"));
+    if(lpFlags->bPause)
+          ConOutPrintfPaging(FALSE,_T("\n"));
+       else
+          ConOutPrintf(_T("\n"));
   }
 }
 
@@ -1335,14 +1455,14 @@ ULARGE_INTEGER u64FileSize;             /* The file size */
                        _tcscpy(szExt, getExt( ptrFiles[i]->cFileName));
                }
 
-               /* Calculate size */            
-               if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)           
+               /* Calculate size */
+               if (ptrFiles[i]->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                {
                        /* Directory, no size it's a directory*/
                        iSizeFormat = -17;
                        _tcscpy(szSize, _T("<DIR>"));
                }
-               else            
+               else
                {
                        /* File */
                        iSizeFormat = 17;
@@ -1350,18 +1470,27 @@ ULARGE_INTEGER u64FileSize;             /* The file size */
                        u64FileSize.LowPart = ptrFiles[i]->nFileSizeLow;
                        ConvertULargeInteger(u64FileSize, szSize, 20, lpFlags->bTSeperator);
                }
-               
+
                /* Format date and time */
                DirPrintFileDateTime(szDate,szTime,ptrFiles[i],lpFlags);
 
                /* Print the line */
-               ConOutPrintf(_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 */
+               if(lpFlags->bPause)
+                  ConOutPrintfPaging(FALSE,_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 */
+               else
+                  ConOutPrintf(_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 */
        }
 }
 
@@ -1372,9 +1501,9 @@ ULARGE_INTEGER u64FileSize;               /* The file size */
  */
 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 */
+                                DWORD dwCount,                 /* [IN] The number of files */
+                                LPTSTR lpCurPath,              /* [IN] Full path of current directory */
+                                LPDIRSWITCHFLAGS lpFlags)      /* [IN] The flags used */
 {
        TCHAR szFullName[MAX_PATH];
        DWORD i;
@@ -1392,12 +1521,18 @@ DirPrintBareList(LPWIN32_FIND_DATA ptrFiles[],  /* [IN] Files' Info */
                        /* at recursive mode we print full path of file */
                        _tcscpy(szFullName, lpCurPath);
                        _tcscat(szFullName, ptrFiles[i]->cFileName);
-                       ConOutPrintf(_T("%s\n"), szFullName);
+                       if(lpFlags->bPause)
+                          ConOutPrintfPaging(FALSE,_T("%s\n"), szFullName);
+                       else
+                          ConOutPrintf(_T("%s\n"), szFullName);
                }
                else
                {
                        /* if we are not in recursive mode we print the file names */
-                       ConOutPrintf(_T("%s\n"),ptrFiles[i]->cFileName);
+                       if(lpFlags->bPause)
+                          ConOutPrintfPaging(FALSE,_T("%s\n"),ptrFiles[i]->cFileName);
+                       else
+                          ConOutPrintf(_T("%s\n"),ptrFiles[i]->cFileName);
                }
        }
 }
@@ -1405,14 +1540,14 @@ DirPrintBareList(LPWIN32_FIND_DATA ptrFiles[],  /* [IN] Files' Info */
 
 /*
  * DirPrintFiles
- * 
+ *
  * 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 */
+                         DWORD dwCount,                        /* [IN] The quantity of files */
+                         TCHAR *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 */
@@ -1429,7 +1564,10 @@ DirPrintFiles(LPWIN32_FIND_DATA ptrFiles[],      /* [IN] Files' Info */
        if (!(lpFlags->bBareFormat ) && !((lpFlags->bRecursive) && (dwCount <= 0)))
        {
                LoadString(CMD_ModuleHandle, STRING_DIR_HELP7, szMsg, RC_STRING_MAX_SIZE);
-               ConOutPrintf(szMsg, szTemp);
+               if(lpFlags->bPause)
+                  ConOutPrintfPaging(FALSE,szMsg, szTemp);
+               else
+                  ConOutPrintf(szMsg, szTemp);
        }
 
        if (lpFlags->bBareFormat)
@@ -1468,8 +1606,8 @@ DirPrintFiles(LPWIN32_FIND_DATA ptrFiles[],       /* [IN] Files' Info */
  */
 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 */
+                        LPWIN32_FIND_DATA 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;
@@ -1536,9 +1674,9 @@ CompareFiles(LPWIN32_FIND_DATA lpFile1,   /* [IN] A pointer to WIN32_FIND_DATA of
                                u64File1.HighPart = lpFile1->ftLastWriteTime.dwHighDateTime ;
                                u64File2.LowPart = lpFile2->ftLastWriteTime.dwLowDateTime;
                                u64File2.HighPart = lpFile2->ftLastWriteTime.dwHighDateTime ;
-                               break;                  
+                               break;
                        }
-                       
+
                        /* In case that differnce is too big for a long */
                        if (u64File1.QuadPart < u64File2.QuadPart)
                                iComp = -1;
@@ -1557,7 +1695,7 @@ CompareFiles(LPWIN32_FIND_DATA lpFile1,   /* [IN] A pointer to WIN32_FIND_DATA of
                   the files/dirs,there is no need to calculate the others*/
                if (iComp != 0) break;
        }
-       
+
        /* Translate the value of iComp to boolean */
        if (iComp > 0)
                return TRUE;
@@ -1619,9 +1757,9 @@ QsortFiles(LPWIN32_FIND_DATA ptrArray[],  /* [IN/OUT] The array with file info po
  */
 static INT
 DirList(LPTSTR szPath,                 /* [IN] The path that dir starts */
-       LPTSTR szFilespec,              /* [IN] The type of file that we are looking for */
-       LPINT pLine,                    /* FIXME: Maybe used for paginating */
-       LPDIRSWITCHFLAGS lpFlags)       /* [IN] The flags of the listing */
+               LPTSTR szFilespec,              /* [IN] The type of file that we are looking for */
+               LPINT pLine,                    /* FIXME: Maybe used for paginating */
+               LPDIRSWITCHFLAGS lpFlags)       /* [IN] The flags of the listing */
 {
        HANDLE hSearch;                                                 /* The handle of the search */
        HANDLE hRecSearch;                                              /* The handle for searching recursivly */
@@ -1631,13 +1769,11 @@ DirList(LPTSTR szPath,                  /* [IN] The path that dir starts */
        PDIRFINDLISTNODE ptrNextNode;   /* A pointer used for relatives refernces */
 TCHAR szFullPath[MAX_PATH];                            /* The full path that we are listing with trailing \ */
 TCHAR szFullFileSpec[MAX_PATH];                        /* The full path with file specs that we ll request\ */
-TCHAR szBytes[20];                                             /* A string for converting ULARGE integer */
 DWORD dwCount;                                                 /* A counter of files found in directory */
 DWORD dwCountFiles;                                            /* Counter for files */
 DWORD dwCountDirs;                                             /* Counter for directories */
 ULARGE_INTEGER u64CountBytes;                  /* Counter for bytes */
 ULARGE_INTEGER u64Temp;                                        /* A temporary counter */
-TCHAR szMsg[RC_STRING_MAX_SIZE];
 
        /* Initialize Variables */
        ptrStartNode = NULL;
@@ -1659,7 +1795,7 @@ TCHAR szMsg[RC_STRING_MAX_SIZE];
        if (ptrStartNode == NULL)
        {
 #ifdef _DEBUG
-               ConErrPrintf("DEBUG: Cannot allocate memory for ptrStartNode!\n");
+               ConErrPrintf(_T("DEBUG: Cannot allocate memory for ptrStartNode!\n"));
 #endif
                return 1;       /* Error cannot allocate memory for 1st object */
        }
@@ -1679,7 +1815,7 @@ TCHAR szMsg[RC_STRING_MAX_SIZE];
                                if (ptrNextNode->ptrNext == NULL)
                                {
 #ifdef _DEBUG
-                                       ConErrPrintf("DEBUG: Cannot allocate memory for ptrNextNode->ptrNext!\n");
+                                       ConErrPrintf(_T("DEBUG: Cannot allocate memory for ptrNextNode->ptrNext!\n"));
 #endif
                                        while (ptrStartNode)
                                        {
@@ -1710,7 +1846,7 @@ TCHAR szMsg[RC_STRING_MAX_SIZE];
                                        /* Continue at next node at linked list */
                                        ptrNextNode = ptrNextNode->ptrNext;
                                        dwCount ++;
-                               
+
                                        /* Grab statistics */
                                        if (wfdFileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                                        {
@@ -1734,12 +1870,12 @@ TCHAR szMsg[RC_STRING_MAX_SIZE];
        /* Terminate list */
        ptrNextNode->ptrNext = NULL;
 
-       /* Calculate and allocate space need for making an array of pointers */ 
+       /* Calculate and allocate space need for making an array of pointers */
        ptrFileArray = malloc(sizeof(LPWIN32_FIND_DATA) * dwCount);
        if (ptrFileArray == NULL)
        {
 #ifdef _DEBUG
-               ConErrPrintf("DEBUG: Cannot allocate memory for ptrFileArray!\n");
+               ConErrPrintf(_T("DEBUG: Cannot allocate memory for ptrFileArray!\n"));
 #endif
                while (ptrStartNode)
                {
@@ -1747,7 +1883,7 @@ TCHAR szMsg[RC_STRING_MAX_SIZE];
                        free(ptrStartNode);
                        ptrStartNode = ptrNextNode;
                        dwCount --;
-               }
+               }               
                return 1;
        }
 
@@ -1770,20 +1906,10 @@ TCHAR szMsg[RC_STRING_MAX_SIZE];
 
        /* Print Data */
        DirPrintFiles(ptrFileArray, dwCount, szFullPath, lpFlags);
-       
+
        /* Free array */
        free(ptrFileArray);
 
-       /* Print Directory Summary */
-       /* Condition to print summary is:
-          If we are not in bare format and if we have results! */
-       if (!(lpFlags->bBareFormat) && (dwCount > 0))
-       {
-               ConvertULargeInteger(u64CountBytes, szBytes, 20, lpFlags->bTSeperator);
-               LoadString(CMD_ModuleHandle, STRING_DIR_HELP8, szMsg, RC_STRING_MAX_SIZE);
-               ConOutPrintf(szMsg,dwCountFiles, szBytes);
-       }
-
        /* Add statistics to recursive statistics*/
        recurse_dir_cnt += dwCountDirs;
        recurse_file_cnt += dwCountFiles;
@@ -1837,16 +1963,21 @@ TCHAR szMsg[RC_STRING_MAX_SIZE];
  *
  * internal dir command
  */
-INT CommandDir(LPTSTR first, LPTSTR rest)
+INT 
+CommandDir(LPTSTR first, LPTSTR rest)
 {
-       TCHAR  dircmd[256];     /* A variable to store the DIRCMD enviroment variable */
-       TCHAR  szPath[MAX_PATH];
-       TCHAR  szFilespec[MAX_PATH];
-       LPTSTR param;
-       INT    nLine = 0;
+       TCHAR   dircmd[256];    /* A variable to store the DIRCMD enviroment variable */
+       TCHAR   cDrive;
+       TCHAR   szPath[MAX_PATH];
+       TCHAR   szFilespec[MAX_PATH];
+       LPTSTR* params;
+       INT             entries = 0;
+       INT             nLine = 0;
+       UINT    loop = 0;
        DIRSWITCHFLAGS stFlags;
 
        /* Initialize variables */
+       cDrive = 0;
        recurse_dir_cnt = 0L;
        recurse_file_cnt = 0L;
        recurse_bytes.QuadPart = 0;
@@ -1871,53 +2002,82 @@ INT CommandDir(LPTSTR first, LPTSTR rest)
        stFlags.stOrderBy.sCriteriaCount = 0;
        stFlags.stOrderBy.bUnSet = FALSE;
 
+       nErrorLevel = 0;
+       
        /* read the parameters from the DIRCMD environment variable */
        if (GetEnvironmentVariable (_T("DIRCMD"), dircmd, 256))
-               if (!DirReadParam(dircmd, &param, &stFlags))
+               if (!DirReadParam(dircmd, &params, &entries, &stFlags))
+               {
+                       nErrorLevel = 1;
                        return 1;
+               }
 
        /* read the parameters */
-       if (!DirReadParam(rest, &param, &stFlags))
+       if (!DirReadParam(rest, &params, &entries, &stFlags) || CheckCtrlBreak(BREAK_INPUT))
+       {
+               nErrorLevel = 1;
                return 1;
+       }
 
        /* default to current directory */
-       if (!param)
-               param = _T(".");
-
-       /* parse the directory info */
-       if (DirParsePathspec (param, szPath, szFilespec))
-               return 1;
+       if(entries == 0) {
+               if(!add_entry(&entries, &params, _T("."))) {
+                       nErrorLevel = 1;
+                       return 1;
+               }
+       }
 
-/* <Debug :>
-   Uncomment this to show the final state of switch flags*/
-/*
-       ConOutPrintf("Attributes mask/value %x/%x\n",stFlags.stAttribs.dwAttribMask,stFlags.stAttribs.dwAttribVal  );
-       ConOutPrintf("(B) Bare format : %i\n", stFlags.bBareFormat );
-       ConOutPrintf("(C) Thousand : %i\n", stFlags.bTSeperator );
-       ConOutPrintf("(W) Wide list : %i\n", stFlags.bWideList );
-       ConOutPrintf("(D) Wide list sort by column : %i\n", stFlags.bWideListColSort );
-       ConOutPrintf("(L) Lowercase : %i\n", stFlags.bLowerCase );
-       ConOutPrintf("(N) New : %i\n", stFlags.bNewLongList );
-       ConOutPrintf("(O) Order : %i\n", stFlags.stOrderBy.sCriteriaCount );
-       int i;
-       for (i =0;i<stFlags.stOrderBy.sCriteriaCount;i++)
-               ConOutPrintf(" Order Criteria [%i]: %i (Reversed: %i)\n",i, stFlags.stOrderBy.eCriteria[i], stFlags.stOrderBy.bCriteriaRev[i] );
-       ConOutPrintf("(P) Pause : %i\n", stFlags.bPause  );
-       ConOutPrintf("(Q) Owner : %i\n", stFlags.bUser );
-       ConOutPrintf("(S) Recursive : %i\n", stFlags.bRecursive );
-       ConOutPrintf("(T) Time field : %i\n", stFlags.stTimeField.eTimeField );
-       ConOutPrintf("(X) Short names : %i\n", stFlags.bShortName );
-       ConOutPrintf("Parameter : %s\n", param );
-*/
-
-       /* print the header  */
-       if (!stFlags.bBareFormat)
-               if (!PrintDirectoryHeader (szPath, &nLine, &stFlags))
+       for(loop = 0; loop < entries; loop++)
+       {
+               /* parse the directory info */
+               if (DirParsePathspec (params[loop], szPath, szFilespec) || CheckCtrlBreak(BREAK_INPUT))
+               {
+                       nErrorLevel = 1;
                        return 1;
+               }
 
-       /* do the actual dir */
-       if (DirList (szPath, szFilespec, &nLine, &stFlags))
-               return 1;
+       /* <Debug :>
+          Uncomment this to show the final state of switch flags*/
+       #ifdef _DEBUG
+               {
+                       int i;
+                       ConOutPrintf(_T("Attributes mask/value %x/%x\n"),stFlags.stAttribs.dwAttribMask,stFlags.stAttribs.dwAttribVal  );
+                       ConOutPrintf(_T("(B) Bare format : %i\n"), stFlags.bBareFormat );
+                       ConOutPrintf(_T("(C) Thousand : %i\n"), stFlags.bTSeperator );
+                       ConOutPrintf(_T("(W) Wide list : %i\n"), stFlags.bWideList );
+                       ConOutPrintf(_T("(D) Wide list sort by column : %i\n"), stFlags.bWideListColSort );
+                       ConOutPrintf(_T("(L) Lowercase : %i\n"), stFlags.bLowerCase );
+                       ConOutPrintf(_T("(N) New : %i\n"), stFlags.bNewLongList );
+                       ConOutPrintf(_T("(O) Order : %i\n"), stFlags.stOrderBy.sCriteriaCount );
+                       for (i =0;i<stFlags.stOrderBy.sCriteriaCount;i++)
+                               ConOutPrintf(_T(" Order Criteria [%i]: %i (Reversed: %i)\n"),i, stFlags.stOrderBy.eCriteria[i], stFlags.stOrderBy.bCriteriaRev[i] );
+                       ConOutPrintf(_T("(P) Pause : %i\n"), stFlags.bPause  );
+                       ConOutPrintf(_T("(Q) Owner : %i\n"), stFlags.bUser );
+                       ConOutPrintf(_T("(S) Recursive : %i\n"), stFlags.bRecursive );
+                       ConOutPrintf(_T("(T) Time field : %i\n"), stFlags.stTimeField.eTimeField );
+                       ConOutPrintf(_T("(X) Short names : %i\n"), stFlags.bShortName );
+                       ConOutPrintf(_T("Parameter : %s\n"), params[loop] );
+               }
+       #endif
+
+               /* Print the drive header if the drive changed */
+               if(cDrive != szPath[0] && !stFlags.bBareFormat) {
+                       if (!PrintDirectoryHeader (szPath, &nLine, &stFlags)) {
+                               nErrorLevel = 1;
+                               return 1;
+                       }
+
+                       cDrive = szPath[0];
+               }
+               
+
+               /* do the actual dir */
+               if (DirList (szPath, szFilespec, &nLine, &stFlags))
+               {
+                       nErrorLevel = 1;
+                       return 1;
+               }
+       }
 
        /* print the footer */
        PrintSummary(szPath,
@@ -1926,7 +2086,7 @@ INT CommandDir(LPTSTR first, LPTSTR rest)
                recurse_bytes,
                &nLine,
                &stFlags);
-
+       
        return 0;
 }