Restore console title after running a command
[reactos.git] / reactos / subsys / system / cmd / cmd.c
index 9a9c67f..d9327a5 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: cmd.c,v 1.1 2003/03/20 19:19:22 rcampbell Exp $
- *
+/*
  *  CMD.C - command-line interface.
  *
  *
@@ -37,7 +36,7 @@
  *        message!
  *
  *        changed the format to call internal commands (again) so that if
- *        they want to split their commands, they can do it themselves 
+ *        they want to split their commands, they can do it themselves
  *        (none of the internal functions so far need that much power, anyway)
  *
  *    27 Aug 1996 (Tim Norman)
  *
  *    23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>)
  *        %envvar% replacement conflicted with for.
+ *
+ *    30-Apr-2004 (Filip Navara <xnavara@volny.cz>)
+ *       Make MakeSureDirectoryPathExistsEx unicode safe.
+ *
+ *    28-Mai-2004 (Hartmut Birr)
+ *       Removed MakeSureDirectoryPathExistsEx.
+ *       Use the current directory if GetTempPath fails.
+ *
+ *    12-Jul-2004 (Jens Collin <jens.collin@lakhei.com>)
+ *       Added ShellExecute call when all else fails to be able to "launch" any file.
+ *
+ *    02-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
+ *        Remove all hardcode string to En.rc
+ *
+ *    06-May-2005 (Klemens Friedl <frik85@gmail.com>)
+ *        Add 'help' command (list all commands plus description)
+ *
+ *    06-jul-2005 (Magnus Olsen <magnus@greatlord.com>)
+ *        translate '%errorlevel%' to the internal value.
+ *        Add proper memmory alloc ProcessInput, the error 
+ *        handling for memmory handling need to be improve
  */
 
-#include "config.h"
-
-#include <windows.h>
-#include <tchar.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdio.h>
+#include <precomp.h>
+#include "resource.h"
 
-#include "cmd.h"
-#include "batch.h"
+#ifndef NT_SUCCESS
+#define NT_SUCCESS(StatCode)  ((NTSTATUS)(StatCode) >= 0)
+#endif
 
+typedef NTSTATUS (STDCALL *NtQueryInformationProcessProc)(HANDLE, PROCESSINFOCLASS,
+                                                          PVOID, ULONG, PULONG);
+typedef NTSTATUS (STDCALL *NtReadVirtualMemoryProc)(HANDLE, PVOID, PVOID, ULONG, PULONG);
 
 BOOL bExit = FALSE;       /* indicates EXIT was typed */
 BOOL bCanExit = TRUE;     /* indicates if this shell is exitable */
@@ -144,13 +162,18 @@ DWORD dwChildProcessId = 0;
 OSVERSIONINFO osvi;
 HANDLE hIn;
 HANDLE hOut;
+HANDLE hConsole;
+HANDLE CMD_ModuleHandle;
+HMODULE NtDllModule;
+
+static NtQueryInformationProcessProc NtQueryInformationProcessPtr = NULL;
+static NtReadVirtualMemoryProc       NtReadVirtualMemoryPtr = NULL;
 
 #ifdef INCLUDE_CMD_COLOR
 WORD wColor;              /* current color */
 WORD wDefColor;           /* default color */
 #endif
 
-
 /*
  *  is character a delimeter when used on first word?
  *
@@ -161,43 +184,218 @@ static BOOL IsDelimiter (TCHAR c)
        return (c == _T('/') || c == _T('=') || c == _T('\0') || _istspace (c));
 }
 
+/*
+ * Is a process a console process?
+ */
+static BOOL IsConsoleProcess(HANDLE Process)
+{
+       NTSTATUS Status;
+       PROCESS_BASIC_INFORMATION Info;
+       PEB ProcessPeb;
+       ULONG BytesRead;
+
+       if (NULL == NtQueryInformationProcessPtr || NULL == NtReadVirtualMemoryPtr)
+       {
+               return TRUE;
+       }
+
+       Status = NtQueryInformationProcessPtr(Process, ProcessBasicInformation,
+                                              &Info, sizeof(PROCESS_BASIC_INFORMATION), NULL);
+       if (! NT_SUCCESS(Status))
+       {
+#ifdef _DEBUG
+               DebugPrintf (_T("NtQueryInformationProcess failed with status %08x\n"), Status);
+#endif
+               return TRUE;
+       }
+       Status = NtReadVirtualMemoryPtr(Process, Info.PebBaseAddress, &ProcessPeb,
+                                        sizeof(PEB), &BytesRead);
+       if (! NT_SUCCESS(Status) || sizeof(PEB) != BytesRead)
+       {
+#ifdef _DEBUG
+               DebugPrintf (_T("Couldn't read virt mem status %08x bytes read %lu\n"), Status, BytesRead);
+#endif
+               return TRUE;
+       }
+
+       return IMAGE_SUBSYSTEM_WINDOWS_CUI == ProcessPeb.ImageSubSystem;
+}
+
+
+
+#ifdef _UNICODE
+#define SHELLEXECUTETEXT       "ShellExecuteW"
+#else
+#define SHELLEXECUTETEXT       "ShellExecuteA"
+#endif
+
+typedef HINSTANCE (WINAPI *MYEX)(
+    HWND hwnd,
+    LPCTSTR lpOperation,
+    LPCTSTR lpFile,
+    LPCTSTR lpParameters,
+    LPCTSTR lpDirectory,
+    INT nShowCmd
+);
+
+
+
+static BOOL RunFile(LPTSTR filename)
+{
+       HMODULE         hShell32;
+       MYEX            hShExt;
+       HINSTANCE       ret;
+
+#ifdef _DEBUG
+               DebugPrintf (_T("RunFile(%s)\n"), filename);
+#endif
+       hShell32 = LoadLibrary(_T("SHELL32.DLL"));
+       if (!hShell32)
+       {
+#ifdef _DEBUG
+               DebugPrintf (_T("RunFile: couldn't load SHELL32.DLL!\n"));
+#endif
+               return FALSE;
+       }
+
+       hShExt = (MYEX)(FARPROC)GetProcAddress(hShell32, SHELLEXECUTETEXT);
+       if (!hShExt)
+       {
+#ifdef _DEBUG
+               DebugPrintf (_T("RunFile: couldn't find ShellExecuteA/W in SHELL32.DLL!\n"));
+#endif
+               FreeLibrary(hShell32);
+               return FALSE;
+       }
+
+#ifdef _DEBUG
+       DebugPrintf (_T("RunFile: ShellExecuteA/W is at %x\n"), hShExt);
+#endif
+
+       ret = (hShExt)(NULL, _T("open"), filename, NULL, NULL, SW_SHOWNORMAL);
+
+#ifdef _DEBUG
+       DebugPrintf (_T("RunFile: ShellExecuteA/W returned %d\n"), (DWORD)ret);
+#endif
+
+       FreeLibrary(hShell32);
+       return (((DWORD)ret) > 32);
+}
+
+
 
 /*
  * This command (in first) was not found in the command table
  *
- * first - first word on command line
- * rest  - rest of command line
+ * Full  - whole command line
+ * First - first word on command line
+ * Rest  - rest of command line
  */
 
 static VOID
-Execute (LPTSTR first, LPTSTR rest)
+Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
 {
        TCHAR szFullName[MAX_PATH];
-#ifndef __REACTOS__
+       TCHAR *first = NULL;
+       TCHAR *rest = NULL; 
+       TCHAR *full = NULL; 
        TCHAR szWindowTitle[MAX_PATH];
-#endif
        DWORD dwExitCode = 0;
 
 #ifdef _DEBUG
-       DebugPrintf ("Execute: \'%s\' \'%s\'\n", first, rest);
+       DebugPrintf (_T("Execute: \'%s\' \'%s\'\n"), first, rest);
 #endif
 
+       /* we need biger buffer that First, Rest, Full are already 
+          need rewrite some code to use realloc when it need instead 
+          of add 512bytes extra */
+
+       first = malloc ( _tcslen(First) + 512 * sizeof(TCHAR)); 
+       if (first == NULL)
+       {
+        error_out_of_memory();
+        return ;
+       }
+
+       rest =  malloc ( _tcslen(Rest) + 512 * sizeof(TCHAR)); 
+       if (rest == NULL)
+       {
+        free (full);
+        error_out_of_memory();
+        return ;
+       }
+
+       full =  malloc ( _tcslen(Full) + 512 * sizeof(TCHAR));
+       if (full == NULL)
+       {
+        free (full);
+        free (rest);
+        error_out_of_memory();
+        return ;
+       }
+
+
+       /* Though it was already parsed once, we have a different set of rules
+          for parsing before we pass to CreateProccess */
+       if(!_tcschr(Full,_T('\"')))
+       {                
+               _tcscpy(first,First);
+               _tcscpy(rest,Rest);
+               _tcscpy(full,Full);
+       }
+       else
+       {
+               INT i = 0;              
+               BOOL bInside = FALSE;
+               rest[0] = _T('\0');
+               full[0] = _T('\0');
+               first[0] = _T('\0');
+               _tcscpy(first,Full);
+               /* find the end of the command and start of the args */
+               for(i = 0; i < _tcslen(first); i++)
+               {
+                       if(!_tcsncmp(&first[i], _T("\""), 1))
+                               bInside = !bInside;
+                       if(!_tcsncmp(&first[i], _T(" "), 1) && !bInside)
+                       {
+                               _tcscpy(rest,&first[i]);
+                               first[i] = _T('\0');
+                               break;
+                       }
+
+               }
+               i = 0;
+               /* remove any slashes */
+               while(i < _tcslen(first))
+               {
+                       if(first[i] == _T('\"'))
+                               memmove(&first[i],&first[i + 1], _tcslen(&first[i]) * sizeof(TCHAR));
+                       else
+                               i++;
+               }
+               /* Drop quotes around it just in case there is a space */
+               _tcscpy(full,_T("\""));
+               _tcscat(full,first);
+               _tcscat(full,_T("\" "));
+               _tcscat(full,rest);
+       }
+
        /* check for a drive change */
        if ((_istalpha (first[0])) && (!_tcscmp (first + 1, _T(":"))))
-       {       
+       {
                BOOL working = TRUE;
                if (!SetCurrentDirectory(first))
                /* Guess they changed disc or something, handle that gracefully and get to root */
                {
                        TCHAR str[4];
                        str[0]=first[0];
-                       str[1]=':';
-                       str[2]='\\';
+                       str[1]=_T(':');
+                       str[2]=_T('\\');
                        str[3]=0;
                        working = SetCurrentDirectory(str);
                }
 
-               if (!working) ConErrPuts (INVALIDDRIVE);
+               if (!working) ConErrResPuts (STRING_FREE_ERROR1);
 
                return;
        }
@@ -210,33 +408,27 @@ Execute (LPTSTR first, LPTSTR rest)
                return;
        }
 
-#ifndef __REACTOS__
        GetConsoleTitle (szWindowTitle, MAX_PATH);
-#endif
 
        /* check if this is a .BAT or .CMD file */
        if (!_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".bat")) ||
                !_tcsicmp (_tcsrchr (szFullName, _T('.')), _T(".cmd")))
        {
 #ifdef _DEBUG
-               DebugPrintf ("[BATCH: %s %s]\n", szFullName, rest);
+               DebugPrintf (_T("[BATCH: %s %s]\n"), szFullName, rest);
 #endif
                Batch (szFullName, first, rest);
        }
        else
        {
                /* exec the program */
-               TCHAR szFullCmdLine [CMDLINE_LENGTH];
                PROCESS_INFORMATION prci;
                STARTUPINFO stui;
 
 #ifdef _DEBUG
-               DebugPrintf ("[EXEC: %s %s]\n", szFullName, rest);
+               DebugPrintf (_T("[EXEC: %s %s]\n"), full, rest);
 #endif
                /* build command line for CreateProcess() */
-               _tcscpy (szFullCmdLine, first);
-               _tcscat (szFullCmdLine, _T(" "));
-               _tcscat (szFullCmdLine, rest);
 
                /* fill startup info */
                memset (&stui, 0, sizeof (STARTUPINFO));
@@ -245,47 +437,64 @@ Execute (LPTSTR first, LPTSTR rest)
                stui.wShowWindow = SW_SHOWDEFAULT;
 
                // return console to standard mode
-               SetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ),
-                                 ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
-               
+               SetConsoleMode (GetStdHandle(STD_INPUT_HANDLE),
+                               ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
+
                if (CreateProcess (szFullName,
-                                  szFullCmdLine,
+                                  full,
                                   NULL,
                                   NULL,
-                                  FALSE,
+                                  TRUE,
                                   CREATE_NEW_PROCESS_GROUP,
                                   NULL,
                                   NULL,
                                   &stui,
                                   &prci))
                {
-                       /* FIXME: Protect this with critical section */
-                       bChildProcessRunning = TRUE;
-                       dwChildProcessId = prci.dwProcessId;
+                       if (IsConsoleProcess(prci.hProcess))
+                       {
+                               /* FIXME: Protect this with critical section */
+                               bChildProcessRunning = TRUE;
+                               dwChildProcessId = prci.dwProcessId;
 
-                       WaitForSingleObject (prci.hProcess, INFINITE);
+                               WaitForSingleObject (prci.hProcess, INFINITE);
 
-                       /* FIXME: Protect this with critical section */
-                       bChildProcessRunning = TRUE;
+                               /* FIXME: Protect this with critical section */
+                               bChildProcessRunning = FALSE;
 
-                       GetExitCodeProcess (prci.hProcess, &dwExitCode);
-                       nErrorLevel = (INT)dwExitCode;
+                               GetExitCodeProcess (prci.hProcess, &dwExitCode);
+                               nErrorLevel = (INT)dwExitCode;
+                       }
                        CloseHandle (prci.hThread);
                        CloseHandle (prci.hProcess);
                }
                else
                {
-                       ErrorMessage (GetLastError (),
-                                     "Error executing CreateProcess()!!\n");
+#ifdef _DEBUG
+                       DebugPrintf (_T("[ShellExecute: %s]\n"), full);
+#endif
+                       // See if we can run this with ShellExecute() ie myfile.xls
+                       if (!RunFile(full))
+                       {
+#ifdef _DEBUG
+                               DebugPrintf (_T("[ShellExecute failed!: %s]\n"), full);
+#endif
+                               error_bad_command ();
+                       }
                }
                // restore console mode
                SetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ),
                                ENABLE_PROCESSED_INPUT );
        }
 
-#ifndef __REACTOS__
-       SetConsoleTitle (szWindowTitle);
-#endif
+       /* Get code page if it has been change */
+       InputCodePage= GetConsoleCP();
+    OutputCodePage = GetConsoleOutputCP();
+    SetConsoleTitle (szWindowTitle);
+
+ free(first);
+ free(rest);
+ free(full);
 }
 
 
@@ -301,33 +510,55 @@ Execute (LPTSTR first, LPTSTR rest)
 static VOID
 DoCommand (LPTSTR line)
 {
-       TCHAR com[MAX_PATH];  /* the first word in the command */
+       TCHAR com[CMDLINE_LENGTH];  /* the first word in the command */
        LPTSTR cp = com;
        LPTSTR cstart;
-       LPTSTR rest = line;   /* pointer to the rest of the command line */
+       LPTSTR rest;   /* pointer to the rest of the command line */
        INT cl;
        LPCOMMAND cmdptr;
 
 #ifdef _DEBUG
-       DebugPrintf ("DoCommand: (\'%s\')\n", line);
+       DebugPrintf (_T("DoCommand: (\'%s\')\n"), line);
 #endif /* DEBUG */
 
        /* Skip over initial white space */
-       while (isspace (*rest))
-               rest++;
+       while (_istspace (*line))
+               line++;
+       rest = line;
 
        cstart = rest;
 
        /* Anything to do ? */
        if (*rest)
        {
-               /* Copy over 1st word as lower case */
-               while (!IsDelimiter (*rest))
-                       *cp++ = _totlower (*rest++);
+               if (*rest == _T('"'))
+               {
+                       /* treat quoted words specially */
+
+                       rest++;
+
+                       while(*rest != _T('\0') && *rest != _T('"'))
+                               *cp++ = _totlower (*rest++);
+                       if (*rest == _T('"'))
+                               rest++;
+               }
+               else
+               {
+                       while (!IsDelimiter (*rest))
+                               *cp++ = _totlower (*rest++);
+               }
+
 
                /* Terminate first word */
                *cp = _T('\0');
 
+               /* commands are limited to MAX_PATH */
+               if(_tcslen(com) > MAX_PATH)
+               {
+                 error_bad_command();
+                 return;
+               }
+
                /* Skip over whitespace to rest of line */
                while (_istspace (*rest))
                        rest++;
@@ -338,7 +569,7 @@ DoCommand (LPTSTR line)
                        /* If end of table execute ext cmd */
                        if (cmdptr->name == NULL)
                        {
-                               Execute (com, rest);
+                               Execute (line, com, rest);
                                break;
                        }
 
@@ -384,19 +615,22 @@ DoCommand (LPTSTR line)
 
 VOID ParseCommandLine (LPTSTR cmd)
 {
+       TCHAR szMsg[RC_STRING_MAX_SIZE];
        TCHAR cmdline[CMDLINE_LENGTH];
        LPTSTR s;
 #ifdef FEATURE_REDIRECTION
-       TCHAR in[CMDLINE_LENGTH] = "";
-       TCHAR out[CMDLINE_LENGTH] = "";
-       TCHAR err[CMDLINE_LENGTH] = "";
+       TCHAR in[CMDLINE_LENGTH] = _T("");
+       TCHAR out[CMDLINE_LENGTH] = _T("");
+       TCHAR err[CMDLINE_LENGTH] = _T("");
        TCHAR szTempPath[MAX_PATH] = _T(".\\");
-       TCHAR szFileName[2][MAX_PATH] = {"", ""};
+       TCHAR szFileName[2][MAX_PATH] = {_T(""), _T("")};
        HANDLE hFile[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
        LPTSTR t = NULL;
        INT  num = 0;
        INT  nRedirFlags = 0;
-
+       INT  Length;
+       UINT Attributes;
+       BOOL bNewBatch = TRUE;
        HANDLE hOldConIn;
        HANDLE hOldConOut;
        HANDLE hOldConErr;
@@ -406,7 +640,7 @@ VOID ParseCommandLine (LPTSTR cmd)
        s = &cmdline[0];
 
 #ifdef _DEBUG
-       DebugPrintf ("ParseCommandLine: (\'%s\')\n", s);
+       DebugPrintf (_T("ParseCommandLine: (\'%s\')\n"), s);
 #endif /* DEBUG */
 
 #ifdef FEATURE_ALIASES
@@ -416,7 +650,20 @@ VOID ParseCommandLine (LPTSTR cmd)
 
 #ifdef FEATURE_REDIRECTION
        /* find the temp path to store temporary files */
-       GetTempPath (MAX_PATH, szTempPath);
+       Length = GetTempPath (MAX_PATH, szTempPath);
+       if (Length > 0 && Length < MAX_PATH)
+       {
+               Attributes = GetFileAttributes(szTempPath);
+               if (Attributes == 0xffffffff ||
+                   !(Attributes & FILE_ATTRIBUTE_DIRECTORY))
+               {
+                       Length = 0;
+               }
+       }
+       if (Length == 0 || Length >= MAX_PATH)
+       {
+               _tcscpy(szTempPath, _T(".\\"));
+       }
        if (szTempPath[_tcslen (szTempPath) - 1] != _T('\\'))
                _tcscat (szTempPath, _T("\\"));
 
@@ -436,6 +683,20 @@ VOID ParseCommandLine (LPTSTR cmd)
                ;
        _tcscpy (err, t);
 
+       if(bc && !_tcslen (in) && _tcslen (bc->In))
+               _tcscpy(in, bc->In);
+       if(bc && !out[0] && _tcslen(bc->Out))
+       {
+               nRedirFlags |= OUTPUT_APPEND;
+               _tcscpy(out, bc->Out);
+       }
+       if(bc && !_tcslen (err) && _tcslen (bc->Err))
+       {
+               nRedirFlags |= ERROR_APPEND;
+               _tcscpy(err, bc->Err);
+       }
+               
+
        /* Set up the initial conditions ... */
        /* preserve STDIN, STDOUT and STDERR handles */
        hOldConIn  = GetStdHandle (STD_INPUT_HANDLE);
@@ -448,17 +709,23 @@ VOID ParseCommandLine (LPTSTR cmd)
                HANDLE hFile;
                SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
 
+    /* we need make sure the LastError msg is zero before calling CreateFile */
+               SetLastError(0); 
+
+    /* Set up pipe for the standard input handler */
                hFile = CreateFile (in, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING,
                                    FILE_ATTRIBUTE_NORMAL, NULL);
                if (hFile == INVALID_HANDLE_VALUE)
                {
-                       ConErrPrintf ("Can't redirect input from file %s\n", in);
+                       LoadString(CMD_ModuleHandle, STRING_CMD_ERROR1, szMsg, RC_STRING_MAX_SIZE);
+                       ConErrPrintf(szMsg, in);
                        return;
                }
 
                if (!SetStdHandle (STD_INPUT_HANDLE, hFile))
-               {
-                       ConErrPrintf ("Can't redirect input from file %s\n", in);
+               {      
+                       LoadString(CMD_ModuleHandle, STRING_CMD_ERROR1, szMsg, RC_STRING_MAX_SIZE);
+                       ConErrPrintf(szMsg, in);
                        return;
                }
 #ifdef _DEBUG
@@ -467,19 +734,30 @@ VOID ParseCommandLine (LPTSTR cmd)
        }
 
        /* Now do all but the last pipe command */
-       *szFileName[0] = '\0';
+       *szFileName[0] = _T('\0');
        hFile[0] = INVALID_HANDLE_VALUE;
 
        while (num-- > 1)
        {
                SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+    
+    /* Create unique temporary file name */
+               GetTempFileName (szTempPath, _T("CMD"), 0, szFileName[1]);
 
-               /* Create unique temporary file name */
-               GetTempFileName (szTempPath, "CMD", 0, szFileName[1]);
+    /* we need make sure the LastError msg is zero before calling CreateFile */
+                SetLastError(0); 
 
                /* Set current stdout to temporary file */
                hFile[1] = CreateFile (szFileName[1], GENERIC_WRITE, 0, &sa,
                                       TRUNCATE_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
+               
+    if (hFile[1] == INVALID_HANDLE_VALUE)
+               {            
+                       LoadString(CMD_ModuleHandle, STRING_CMD_ERROR2, szMsg, RC_STRING_MAX_SIZE);
+                       ConErrPrintf(szMsg);
+                       return;
+               }
+
                SetStdHandle (STD_OUTPUT_HANDLE, hFile[1]);
 
                DoCommand (s);
@@ -507,6 +785,9 @@ VOID ParseCommandLine (LPTSTR cmd)
                _tcscpy (szFileName[0], szFileName[1]);
                *szFileName[1] = _T('\0');
 
+    /* we need make sure the LastError msg is zero before calling CreateFile */
+               SetLastError(0); 
+
                /* open new stdin file */
                hFile[0] = CreateFile (szFileName[0], GENERIC_READ, 0, &sa,
                                       OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
@@ -522,19 +803,43 @@ VOID ParseCommandLine (LPTSTR cmd)
                /* Final output to here */
                HANDLE hFile;
                SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
+               
+    /* we need make sure the LastError msg is zero before calling CreateFile */
+               SetLastError(0); 
 
-               hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_READ, &sa,
+    hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa,
                                    (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
-                                   FILE_ATTRIBUTE_NORMAL, NULL);
-               if (hFile == INVALID_HANDLE_VALUE)
+                                   FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
+               
+    if (hFile == INVALID_HANDLE_VALUE)
                {
-                       ConErrPrintf ("Can't redirect to file %s\n", out);
-                       return;
+      INT size = _tcslen(out)-1;
+      
+      if (out[size] != _T(':'))
+      {
+                          LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
+                          ConErrPrintf(szMsg, out);
+                          return;
+      }
+      
+      out[size]=_T('\0');
+      hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa,
+                                   (nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
+                                   FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
+
+     if (hFile == INVALID_HANDLE_VALUE)
+     {
+                          LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
+                          ConErrPrintf(szMsg, out);
+                          return;
+      }
+      
                }
 
                if (!SetStdHandle (STD_OUTPUT_HANDLE, hFile))
                {
-                       ConErrPrintf ("Can't redirect to file %s\n", out);
+                       LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
+                       ConErrPrintf(szMsg, out);
                        return;
                }
 
@@ -580,20 +885,23 @@ VOID ParseCommandLine (LPTSTR cmd)
                {
                        hFile = CreateFile (err,
                                            GENERIC_WRITE,
-                                           0,
+                                           FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
                                            &sa,
                                            (nRedirFlags & ERROR_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
-                                           FILE_ATTRIBUTE_NORMAL,
+                                           FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
                                            NULL);
                        if (hFile == INVALID_HANDLE_VALUE)
                        {
-                               ConErrPrintf ("Can't redirect to file %s\n", err);
+                               LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
+                               ConErrPrintf(szMsg, err);
                                return;
                        }
                }
+
                if (!SetStdHandle (STD_ERROR_HANDLE, hFile))
                {
-                       ConErrPrintf ("Can't redirect to file %s\n", err);
+                       LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
+                       ConErrPrintf(szMsg, err);
                        return;
                }
 
@@ -617,16 +925,21 @@ VOID ParseCommandLine (LPTSTR cmd)
                        CloseHandle (hErr);
                hOldConErr = INVALID_HANDLE_VALUE;
        }
+
+       if(bc)
+               bNewBatch = FALSE;
 #endif
 
        /* process final command */
        DoCommand (s);
 
 #ifdef FEATURE_REDIRECTION
+       if(bNewBatch && bc)
+               AddBatchRedirection(in, out, err);
        /* close old stdin file */
 #if 0  /* buggy implementation */
        SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
-       if ((hFile[0] != INVALID_HANDLE_VALUE) && 
+       if ((hFile[0] != INVALID_HANDLE_VALUE) &&
                (hFile[0] != hOldConIn))
        {
                /* delete old stdin file, if it is a real file */
@@ -714,7 +1027,7 @@ VOID ParseCommandLine (LPTSTR cmd)
  *
  */
 
-static INT 
+static INT
 ProcessInput (BOOL bFlag)
 {
        TCHAR commandline[CMDLINE_LENGTH];
@@ -724,6 +1037,7 @@ ProcessInput (BOOL bFlag)
        LPTSTR cp;
        BOOL bEchoThisLine;
 
        do
        {
                /* if no batch input then... */
@@ -740,7 +1054,7 @@ ProcessInput (BOOL bFlag)
                cp = commandline;
                while (*ip)
                {
-                       if (*ip == _T('%'))
+         if (*ip == _T('%'))
                        {
                                switch (*++ip)
                                {
@@ -760,7 +1074,7 @@ ProcessInput (BOOL bFlag)
                                        case _T('9'):
                                                if ((tp = FindArg (*ip - _T('0'))))
                                                {
-                                                       cp = stpcpy (cp, tp);
+                                                       cp = _stpcpy (cp, tp);
                                                        ip++;
                                                }
                                                else
@@ -777,25 +1091,134 @@ ProcessInput (BOOL bFlag)
                                                if ((tp != NULL) &&
                                                    (tp <= _tcschr(ip, _T(' ')) - 1))
                                                {
-                                                       char evar[512];
+              INT size = 512;
+                                                       TCHAR *evar;
                                                        *tp = _T('\0');
 
-                                                       /* FIXME: This is just a quick hack!! */
-                                                       /* Do a proper memory allocation!! */
-                                                       if (GetEnvironmentVariable (ip, evar, 512))
-                                                               cp = stpcpy (cp, evar);
-
+              /* FIXME: Correct error handling when it can not alloc memmory */
+                               
+              /* %CD% */
+              if (_tcsicmp(ip,_T("cd")) ==0)
+              {
+                TCHAR szPath[MAX_PATH];
+                           GetCurrentDirectory (MAX_PATH, szPath);
+                cp = _stpcpy (cp, szPath);                 
+              }
+              /* %TIME% */
+              else if (_tcsicmp(ip,_T("time")) ==0)
+              {
+                TCHAR szTime[40];                                                                               
+                SYSTEMTIME t;
+                GetSystemTime(&t); 
+
+                _sntprintf(szTime ,40,_T("%02d%c%02d%c%02d%c%02d"), t.wHour, cTimeSeparator,t.wMinute , cTimeSeparator,t.wSecond , cDecimalSeparator, t.wMilliseconds );
+                cp = _stpcpy (cp, szTime);                                   
+              }
+              
+              /* %DATE% */
+              else if (_tcsicmp(ip,_T("date")) ==0)
+              {
+              TCHAR szDate[40];
+
+                   GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL, _T("ddd"), szDate, sizeof (szDate));
+              cp = _stpcpy (cp, szDate);        
+              cp = _stpcpy (cp, _T(" "));        
+              GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, szDate, sizeof (szDate));
+              cp = _stpcpy (cp, szDate);        
+              }
+
+              /* %RANDOM% */
+              else if (_tcsicmp(ip,_T("random")) ==0)
+              {
+               TCHAR szRand[40];               
+               /* Get random number */
+               _itot(rand(),szRand,10);
+               cp = _stpcpy (cp, szRand); 
+              }
+               
+              /* %CMDCMDLINE% */
+              else if (_tcsicmp(ip,_T("cmdcmdline")) ==0)
+              {                      
+               TCHAR *pargv;               
+               /* Get random number */        
+               pargv = GetCommandLine();
+               cp = _stpcpy (cp, pargv); 
+              }
+
+              /* %CMDEXTVERSION% */
+              else if (_tcsicmp(ip,_T("cmdextversion")) ==0)
+              {
+               TCHAR szVER[40];               
+               /* Set version number to 2 */
+               _itot(2,szVER,10);
+               cp = _stpcpy (cp, szVER); 
+              }
+                       
+              /* %ERRORLEVEL% */
+              else if (_tcsicmp(ip,_T("errorlevel")) ==0)
+              {
+                evar = malloc ( size * sizeof(TCHAR));
+                if (evar==NULL) 
+                    return 1; 
+
+                memset(evar,0,512 * sizeof(TCHAR));
+                _itot(nErrorLevel,evar,10);        
+                cp = _stpcpy (cp, evar);
+
+                free(evar);
+              }               
+                                                       else 
+              {
+                evar = malloc ( 512 * sizeof(TCHAR));
+                if (evar==NULL) 
+                    return 1; 
+                                        SetLastError(0);
+                size = GetEnvironmentVariable (ip, evar, 512);
+                                        if(GetLastError() == ERROR_ENVVAR_NOT_FOUND)
+                                        {
+                                                /* if no env var is found you must 
+                                                   continue with what was input*/
+                                          cp = _stpcpy (cp, _T("%"));
+                                               cp = _stpcpy (cp, ip);
+                                               cp = _stpcpy (cp, _T("%"));
+                                        }
+                                        else
+                                        {
+                if (size > 512)
+                {
+                    evar = realloc(evar,size * sizeof(TCHAR) );
+                    if (evar==NULL)
+                    {
+                      return 1;
+                    }
+                    size = GetEnvironmentVariable (ip, evar, size);
+                }
+
+                if (size)
+                {
+                                                                cp = _stpcpy (cp, evar);
+                }
+                                        }
+
+                free(evar);
+              }
+               
                                                        ip = tp + 1;
+
                                                }
                                                else
                                                {
                                                        *cp++ = _T('%');
-                                               }
+                                               }              
+           
                                                break;
                                }
                                continue;
                        }
 
+
+     
+
                        if (_istcntrl (*ip))
                                *ip = _T(' ');
                        *cp++ = *ip++;
@@ -804,10 +1227,10 @@ ProcessInput (BOOL bFlag)
                *cp = _T('\0');
 
                /* strip trailing spaces */
-               while ((--cp >= commandline) && _istspace (*cp));
+               while ((--cp >= commandline) && _istspace (*cp));     
 
                *(cp + 1) = _T('\0');
-
+   
                /* JPP 19980807 */
                /* Echo batch file line */
                if (bEchoThisLine)
@@ -833,8 +1256,9 @@ ProcessInput (BOOL bFlag)
 /*
  * control-break handler.
  */
-BOOL BreakHandler (DWORD dwCtrlType)
+BOOL WINAPI BreakHandler (DWORD dwCtrlType)
 {
+
        if ((dwCtrlType != CTRL_C_EVENT) &&
            (dwCtrlType != CTRL_BREAK_EVENT))
                return FALSE;
@@ -857,18 +1281,13 @@ BOOL BreakHandler (DWORD dwCtrlType)
 
 VOID AddBreakHandler (VOID)
 {
-#ifndef __REACTOS__
-       SetConsoleCtrlHandler ((PHANDLER_ROUTINE)&BreakHandler,
-                              TRUE);
-#endif
+       SetConsoleCtrlHandler ((PHANDLER_ROUTINE)BreakHandler, TRUE);
 }
 
 
 VOID RemoveBreakHandler (VOID)
 {
-#ifndef __REACTOS__
-       SetConsoleCtrlHandler (NULL, FALSE);
-#endif
+       SetConsoleCtrlHandler ((PHANDLER_ROUTINE)BreakHandler, FALSE);
 }
 
 
@@ -876,33 +1295,35 @@ VOID RemoveBreakHandler (VOID)
  * show commands and options that are available.
  *
  */
+#if 0
 static VOID
 ShowCommands (VOID)
 {
        /* print command list */
-       ConOutPrintf (_T("\nInternal commands available:\n"));
-       PrintCommandList ();
+       ConOutResPuts(STRING_CMD_HELP1);
+       PrintCommandList();
 
        /* print feature list */
-       ConOutPuts ("\nFeatures available:");
+       ConOutResPuts(STRING_CMD_HELP2);
+
 #ifdef FEATURE_ALIASES
-       ConOutPuts ("  [aliases]");
+       ConOutResPuts(STRING_CMD_HELP3);
 #endif
 #ifdef FEATURE_HISTORY
-       ConOutPuts ("  [history]");
+       ConOutResPuts(STRING_CMD_HELP4);
 #endif
 #ifdef FEATURE_UNIX_FILENAME_COMPLETION
-       ConOutPuts ("  [unix filename completion]");
+       ConOutResPuts(STRING_CMD_HELP5);
 #endif
 #ifdef FEATURE_DIRECTORY_STACK
-       ConOutPuts ("  [directory stack]");
+       ConOutResPuts(STRING_CMD_HELP6);
 #endif
 #ifdef FEATURE_REDIRECTION
-       ConOutPuts ("  [redirections and piping]");
+       ConOutResPuts(STRING_CMD_HELP7);
 #endif
-       ConOutChar ('\n');
+       ConOutChar(_T('\n'));
 }
-
+#endif
 
 /*
  * set up global initializations and process parameters
@@ -912,46 +1333,71 @@ ShowCommands (VOID)
  *
  */
 static VOID
-Initialize (int argc, char *argv[])
+Initialize (int argc, TCHAR* argv[])
 {
        TCHAR commandline[CMDLINE_LENGTH];
        TCHAR ModuleName[_MAX_PATH + 1];
        INT i;
+       TCHAR lpBuffer[2];
+
+       //INT len;
+       //TCHAR *ptr, *cmdLine;
+       
+       /* get version information */
+       osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+       GetVersionEx (&osvi);
+
+       /* Some people like to run ReactOS cmd.exe on Win98, it helps in the
+           build process. So don't link implicitly against ntdll.dll, load it
+           dynamically instead */
+
+       if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
+       {
+               /* ntdll is always present on NT */
+               NtDllModule = GetModuleHandle(TEXT("ntdll.dll"));
+       }
+       else
+       {
+               /* not all 9x versions have a ntdll.dll, try to load it */
+               NtDllModule = LoadLibrary(TEXT("ntdll.dll"));
+       }
+
+       if (NtDllModule != NULL)
+       {
+               NtQueryInformationProcessPtr = (NtQueryInformationProcessProc)GetProcAddress(NtDllModule, "NtQueryInformationProcess");
+               NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
+       }
+
 
 #ifdef _DEBUG
        INT x;
 
-       DebugPrintf ("[command args:\n");
+       DebugPrintf (_T("[command args:\n"));
        for (x = 0; x < argc; x++)
        {
-               DebugPrintf ("%d. %s\n", x, argv[x]);
+               DebugPrintf (_T("%d. %s\n"), x, argv[x]);
        }
-       DebugPrintf ("]\n");
+       DebugPrintf (_T("]\n"));
 #endif
 
-       /* get version information */
-       osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-       GetVersionEx (&osvi);
-
        InitLocale ();
 
        /* get default input and output console handles */
        hOut = GetStdHandle (STD_OUTPUT_HANDLE);
        hIn  = GetStdHandle (STD_INPUT_HANDLE);
 
+       /* Set EnvironmentVariable PROMPT if it does not exists any env value. 
+          for you can change the EnvirommentVariable for prompt before cmd start 
+          this patch are not 100% right, if it does not exists a PROMPT value cmd should use
+          $P$G as defualt not set EnvirommentVariable PROMPT to $P$G if it does not exists */
+       if (GetEnvironmentVariable(_T("PROMPT"),lpBuffer, 2 * sizeof(TCHAR)) == 0) 
+           SetEnvironmentVariable (_T("PROMPT"), _T("$P$G"));
+
 
        if (argc >= 2 && !_tcsncmp (argv[1], _T("/?"), 2))
        {
-               ConOutPuts (_T("Starts a new instance of the ReactOS command line interpreter.\n"
-                              "\n"
-                              "CMD [/[C|K] command][/P][/Q][/T:bf]\n"
-                              "\n"
-                              "  /C command  Runs the specified command and terminates.\n"
-                              "  /K command  Runs the specified command and remains.\n"
-                              "  /P          CMD becomes permanent and runs autoexec.bat\n"
-                              "              (cannot be terminated).\n"
-                              "  /T:bf       Sets the background/foreground color (see COLOR command)."));
-               ExitProcess (0);
+               ConOutResPaging(TRUE,STRING_CMD_HELP8);
+               ExitProcess(0);
        }
        SetConsoleMode (hIn, ENABLE_PROCESSED_INPUT);
 
@@ -969,13 +1415,13 @@ Initialize (int argc, char *argv[])
                {
                        if (!_tcsicmp (argv[i], _T("/p")))
                        {
-                               if (!IsValidFileName (_T("\\autoexec.bat")))
+                               if (!IsExistingFile (_T("\\autoexec.bat")))
                                {
 #ifdef INCLUDE_CMD_DATE
-                                       cmd_date ("", "");
+                                       cmd_date (_T(""), _T(""));
 #endif
 #ifdef INCLUDE_CMD_TIME
-                                       cmd_time ("", "");
+                                       cmd_time (_T(""), _T(""));
 #endif
                                }
                                else
@@ -988,12 +1434,12 @@ Initialize (int argc, char *argv[])
                        {
                                /* This just runs a program and exits */
                                ++i;
-                               if (argv[i])
+                               if (i < argc)
                                {
                                        _tcscpy (commandline, argv[i]);
-                                       while (argv[++i])
+                                       while (++i < argc)
                                        {
-                                               _tcscat (commandline, " ");
+                                               _tcscat (commandline, _T(" "));
                                                _tcscat (commandline, argv[i]);
                                        }
 
@@ -1009,12 +1455,12 @@ Initialize (int argc, char *argv[])
                        {
                                /* This just runs a program and remains */
                                ++i;
-                               if (argv[i])
+                               if (i < argc)
                                {
                                        _tcscpy (commandline, argv[i]);
-                                       while (argv[++i])
+                                       while (++i < argc)
                                        {
-                                               _tcscat (commandline, " ");
+                                               _tcscat (commandline, _T(" "));
                                                _tcscat (commandline, argv[i]);
                                        }
 
@@ -1025,7 +1471,7 @@ Initialize (int argc, char *argv[])
                        else if (!_tcsnicmp (argv[i], _T("/t:"), 3))
                        {
                                /* process /t (color) argument */
-                               wDefColor = (WORD)strtoul (&argv[i][3], NULL, 16);
+                               wDefColor = (WORD)_tcstoul (&argv[i][3], NULL, 16);
                                wColor = wDefColor;
                                SetScreenColor (wColor, TRUE);
                        }
@@ -1034,11 +1480,11 @@ Initialize (int argc, char *argv[])
        }
 
        /* run cmdstart.bat */
-       if (IsValidFileName (_T("cmdstart.bat")))
+       if (IsExistingFile (_T("cmdstart.bat")))
        {
                ParseCommandLine (_T("cmdstart.bat"));
        }
-       else if (IsValidFileName (_T("\\cmdstart.bat")))
+       else if (IsExistingFile (_T("\\cmdstart.bat")))
        {
                ParseCommandLine (_T("\\cmdstart.bat"));
        }
@@ -1052,9 +1498,10 @@ Initialize (int argc, char *argv[])
                p = _tcsrchr (commandline, _T('\\')) + 1;
                _tcscpy (p, _T("cmdstart.bat"));
 
-               if (IsValidFileName (_T("commandline")))
+               if (IsExistingFile (_T("commandline")))
                {
-                       ConErrPrintf ("Running %s...\n", commandline);
+                       LoadString(CMD_ModuleHandle, STRING_CMD_ERROR4, szMsg, RC_STRING_MAX_SIZE);
+                       ConErrPrintf(szMsg, commandline);
                        ParseCommandLine (commandline);
                }
        }
@@ -1083,17 +1530,22 @@ Initialize (int argc, char *argv[])
 }
 
 
-static VOID Cleanup (int argc, char *argv[])
+static VOID Cleanup (int argc, TCHAR *argv[])
 {
+#ifndef __REACTOS__
+       TCHAR szMsg[RC_STRING_MAX_SIZE];
+#endif
+
        /* run cmdexit.bat */
-       if (IsValidFileName (_T("cmdexit.bat")))
+       if (IsExistingFile (_T("cmdexit.bat")))
        {
-               ConErrPrintf ("Running cmdexit.bat...\n");
+               ConErrResPuts(STRING_CMD_ERROR5);
+
                ParseCommandLine (_T("cmdexit.bat"));
        }
-       else if (IsValidFileName (_T("\\cmdexit.bat")))
+       else if (IsExistingFile (_T("\\cmdexit.bat")))
        {
-               ConErrPrintf ("Running \\cmdexit.bat...\n");
+               ConErrResPuts (STRING_CMD_ERROR5);
                ParseCommandLine (_T("\\cmdexit.bat"));
        }
 #ifndef __REACTOS__
@@ -1107,9 +1559,10 @@ static VOID Cleanup (int argc, char *argv[])
                p = _tcsrchr (commandline, _T('\\')) + 1;
                _tcscpy (p, _T("cmdexit.bat"));
 
-               if (IsValidFileName (_T("commandline")))
+               if (IsExistingFile (_T("commandline")))
                {
-                       ConErrPrintf ("Running %s...\n", commandline);
+                       LoadString(CMD_ModuleHandle, STRING_CMD_ERROR4, szMsg, RC_STRING_MAX_SIZE);
+                       ConErrPrintf(szMsg, commandline);
                        ParseCommandLine (commandline);
                }
        }
@@ -1128,7 +1581,7 @@ static VOID Cleanup (int argc, char *argv[])
        FreeLastPath ();
 #endif
 
-#ifdef FEATURE_HISTORY 
+#ifdef FEATURE_HISTORY
        CleanHistory();
 #endif
 
@@ -1137,41 +1590,115 @@ static VOID Cleanup (int argc, char *argv[])
        RemoveBreakHandler ();
        SetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ),
                        ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
+
+       if (NtDllModule != NULL)
+       {
+               FreeLibrary(NtDllModule);
+       }
 }
 
+#ifdef __REACTOS__
+#ifdef _UNICODE
+PWCHAR * _CommandLineToArgvW(PWCHAR lpCmdLine, int *pNumArgs)
+{
+   PWCHAR * argvw = NULL;
+   PWCHAR ptr = lpCmdLine;
+   PWCHAR str;
+   int len;
+   int NumArgs;
+
+   NumArgs = 0;
+
+   while(lpCmdLine && *lpCmdLine)
+   {
+       while (iswspace(*lpCmdLine)) lpCmdLine++;
+       if (*lpCmdLine)
+       {
+          if ((NumArgs % 10)==0)
+          {
+               PWCHAR * old_argvw = argvw;
+              argvw = malloc((NumArgs + 10) * sizeof(PWCHAR));
+              memcpy(argvw, old_argvw, NumArgs * sizeof(PWCHAR));
+              free(old_argvw);
+          }
+          ptr = wcschr(lpCmdLine, L' ');
+          if (ptr)
+          {
+              len = ptr - lpCmdLine;
+          }
+          else
+          {
+              len = wcslen(lpCmdLine);
+          }
+          str = malloc((len + 1) * sizeof(WCHAR));
+          memcpy(str, lpCmdLine, len * sizeof(WCHAR));
+          str[len] = 0;
+          argvw[NumArgs]=str;
+          NumArgs++;
+          lpCmdLine = ptr;
+       }
+   }
+   *pNumArgs = NumArgs;
+   return argvw;
+}
+#endif
+#endif
 
 /*
  * main function
  */
-int main (int argc, char *argv[])
+#ifdef _UNICODE
+int _main(void)
+#else
+int _main (int argc, char *argv[])
+#endif
 {
+  TCHAR startPath[MAX_PATH];
   CONSOLE_SCREEN_BUFFER_INFO Info;
   INT nExitCode;
+#ifdef _UNICODE
+  PWCHAR * argv;
+  int argc=0;
+#ifdef __REACTOS__
+  argv = _CommandLineToArgvW(GetCommandLineW(), &argc);
+#else
+  argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+#endif
+#endif
+      
+  GetCurrentDirectory(MAX_PATH,startPath);
+  _tchdir(startPath);
 
   SetFileApisToOEM();
+  InputCodePage= 0;
+  OutputCodePage = 0;
 
-  AllocConsole();
-  if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &Info) == FALSE)
+  hConsole = CreateFile(_T("CONOUT$"), GENERIC_READ|GENERIC_WRITE,
+                        FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
+                       OPEN_EXISTING, 0, NULL);
+  if (GetConsoleScreenBufferInfo(hConsole, &Info) == FALSE)
     {
-      fprintf(stderr, "GetConsoleScreenBufferInfo: Error: %ld\n", GetLastError());
-#ifndef __REACTOS__
-      /* On ReactOS GetConsoleScreenBufferInfo returns an error if the stdin 
-         handle is redirected to a pipe or file. This stops windres from working. */
+      ConErrFormatMessage(GetLastError());
       return(1);
-#endif
     }
   wColor = Info.wAttributes;
   wDefColor = wColor;
 
+  InputCodePage= GetConsoleCP();
+  OutputCodePage = GetConsoleOutputCP();
+  CMD_ModuleHandle = GetModuleHandle(NULL);
+  
   /* check switches on command-line */
   Initialize(argc, argv);
 
   /* call prompt routine */
   nExitCode = ProcessInput(FALSE);
 
+  
   /* do the cleanup */
   Cleanup(argc, argv);
 
+  
   return(nExitCode);
 }