branch update for HEAD-2003050101
[reactos.git] / lib / kernel32 / misc / console.c
index bb2a5c0..117d364 100644 (file)
@@ -56,17 +56,35 @@ ConsoleMenuControl (HANDLE  hConsole,
   return FALSE;
 }
 
-BOOL STDCALL
+HANDLE STDCALL
 DuplicateConsoleHandle (HANDLE hConsole,
-                       DWORD   Unknown1,
-                       DWORD   Unknown2,
-                       DWORD   Unknown3)
-     /*
-      * Undocumented
-      */
+                       DWORD   dwDesiredAccess,
+                       BOOL    bInheritHandle,
+                       DWORD   dwOptions)
 {
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+
+  if (IsConsoleHandle (hConsole) == FALSE)
+    {
+      SetLastError (ERROR_INVALID_PARAMETER);
+      return INVALID_HANDLE_VALUE;
+    }
+  
+  Request.Type = CSRSS_DUPLICATE_HANDLE;
+  Request.Data.DuplicateHandleRequest.Handle = hConsole;
+  Request.Data.DuplicateHandleRequest.ProcessId = GetCurrentProcessId();
+  Status = CsrClientCallServer(&Request,
+                              &Reply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status=Reply.Status))
+    {
+      SetLastErrorByStatus(Status);
+      return INVALID_HANDLE_VALUE;
+    }
+  return Reply.Data.DuplicateHandleReply.Handle;
 }
 
 DWORD STDCALL
@@ -500,16 +518,39 @@ ShowConsoleCursor (DWORD  Unknown0,
   return 0;
 }
 
-DWORD STDCALL
-VerifyConsoleIoHandle (DWORD   Unknown0)
-     /*
-      * Undocumented
-      */
+
+/*
+ * FUNCTION: Checks whether the given handle is a valid console handle.
+ * ARGUMENTS:
+ *      Handle - Handle to be checked
+ * RETURNS:
+ *      TRUE: Handle is a valid console handle
+ *      FALSE: Handle is not a valid console handle.
+ * STATUS: Officially undocumented
+ */
+BOOL STDCALL
+VerifyConsoleIoHandle(HANDLE Handle)
 {
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return 0;
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+
+  Request.Type = CSRSS_VERIFY_HANDLE;
+  Request.Data.VerifyHandleRequest.Handle = Handle;
+  Status = CsrClientCallServer(&Request,
+                              &Reply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status))
+    {
+      SetLastErrorByStatus(Status);
+      return FALSE;
+    }
+
+  return (BOOL)NT_SUCCESS(Reply.Status);
 }
 
+
 DWORD STDCALL
 WriteConsoleInputVDMA (DWORD   Unknown0,
                       DWORD    Unknown1,
@@ -530,21 +571,38 @@ WriteConsoleInputVDMW (DWORD      Unknown0,
   return 0;
 }
 
-WINBOOL STDCALL 
+WINBOOL STDCALL
 CloseConsoleHandle(HANDLE Handle)
      /*
       * Undocumented
       */
 {
+  CSRSS_API_REQUEST Request;
+  CSRSS_API_REPLY Reply;
+  NTSTATUS Status;
+
   if (IsConsoleHandle (Handle) == FALSE)
     {
       SetLastError (ERROR_INVALID_PARAMETER);
       return FALSE;
     }
-  /* FIXME: call CSRSS */
-  return TRUE/*FALSE*/;
+
+  Request.Type = CSRSS_CLOSE_HANDLE;
+  Request.Data.CloseHandleRequest.Handle = Handle;
+  Status = CsrClientCallServer(&Request,
+                              &Reply,
+                              sizeof(CSRSS_API_REQUEST),
+                              sizeof(CSRSS_API_REPLY));
+  if (!NT_SUCCESS(Status))
+    {
+       SetLastErrorByStatus(Status);
+       return FALSE;
+    }
+
+  return TRUE;
 }
 
+
 BOOLEAN STDCALL 
 IsConsoleHandle(HANDLE Handle)
 {
@@ -567,14 +625,20 @@ GetStdHandle(DWORD nStdHandle)
       */
 {
   PRTL_USER_PROCESS_PARAMETERS Ppb;
-  
-  Ppb = NtCurrentPeb()->ProcessParameters;  
+
+  Ppb = NtCurrentPeb()->ProcessParameters;
   switch (nStdHandle)
     {
-    case STD_INPUT_HANDLE:     return Ppb->hStdInput;
-    case STD_OUTPUT_HANDLE:    return Ppb->hStdOutput;
-    case STD_ERROR_HANDLE:     return Ppb->hStdError;
+      case STD_INPUT_HANDLE:
+       return Ppb->hStdInput;
+
+      case STD_OUTPUT_HANDLE:
+       return Ppb->hStdOutput;
+
+      case STD_ERROR_HANDLE:
+       return Ppb->hStdError;
     }
+
   SetLastError (ERROR_INVALID_PARAMETER);
   return INVALID_HANDLE_VALUE;
 }
@@ -592,29 +656,33 @@ SetStdHandle(DWORD nStdHandle,
       */
 {
   PRTL_USER_PROCESS_PARAMETERS Ppb;
-   
+
   Ppb = NtCurrentPeb()->ProcessParameters;
-  
+
   /* More checking needed? */
   if (hHandle == INVALID_HANDLE_VALUE)
     {
       SetLastError (ERROR_INVALID_HANDLE);
       return FALSE;
     }
-   
+
   SetLastError(ERROR_SUCCESS); /* OK */
+
   switch (nStdHandle)
     {
-    case STD_INPUT_HANDLE:
-      Ppb->hStdInput = hHandle;
-      return TRUE;
-    case STD_OUTPUT_HANDLE:
-      Ppb->hStdOutput = hHandle;
-      return TRUE;
-    case STD_ERROR_HANDLE:
-      Ppb->hStdError = hHandle;
-      return TRUE;
+      case STD_INPUT_HANDLE:
+       Ppb->hStdInput = hHandle;
+       return TRUE;
+
+      case STD_OUTPUT_HANDLE:
+       Ppb->hStdOutput = hHandle;
+       return TRUE;
+
+      case STD_ERROR_HANDLE:
+       Ppb->hStdError = hHandle;
+       return TRUE;
     }
+
   SetLastError (ERROR_INVALID_PARAMETER);
   return FALSE;
 }
@@ -635,7 +703,7 @@ WriteConsoleA(HANDLE hConsoleOutput,
   NTSTATUS Status;
   USHORT Size;
   ULONG MessageSize;
-  
+
   Request = RtlAllocateHeap(GetProcessHeap(),
                            HEAP_ZERO_MEMORY,
                            sizeof(CSRSS_API_REQUEST) + 
@@ -645,7 +713,7 @@ WriteConsoleA(HANDLE hConsoleOutput,
       SetLastError(ERROR_OUTOFMEMORY);
       return(FALSE);
     }
-  
+
   Request->Type = CSRSS_WRITE_CONSOLE;
   Request->Data.WriteConsoleRequest.ConsoleHandle = hConsoleOutput;
   if (lpNumberOfCharsWritten != NULL)
@@ -661,7 +729,7 @@ WriteConsoleA(HANDLE hConsoleOutput,
          Size = nNumberOfCharsToWrite;
        }
       Request->Data.WriteConsoleRequest.NrCharactersToWrite = Size;
-      
+
       memcpy(Request->Data.WriteConsoleRequest.Buffer, lpBuffer, Size);
 
       MessageSize = CSRSS_REQUEST_HEADER_SIZE + 
@@ -670,7 +738,7 @@ WriteConsoleA(HANDLE hConsoleOutput,
                                   &Reply,
                                   MessageSize,
                                   sizeof(CSRSS_API_REPLY));
-      
+
       if (!NT_SUCCESS(Status) || !NT_SUCCESS(Status = Reply.Status))
        {
          RtlFreeHeap(GetProcessHeap(), 0, Request);
@@ -680,7 +748,9 @@ WriteConsoleA(HANDLE hConsoleOutput,
       nNumberOfCharsToWrite -= Size;
       lpBuffer += Size;
     }
+
   RtlFreeHeap(GetProcessHeap(), 0, Request);
+
   return TRUE;
 }
 
@@ -786,6 +856,7 @@ WINBOOL STDCALL AllocConsole(VOID)
    CSRSS_API_REQUEST Request;
    CSRSS_API_REPLY Reply;
    NTSTATUS Status;
+   HANDLE hStdError;
 
    Request.Type = CSRSS_ALLOC_CONSOLE;
    Status = CsrClientCallServer( &Request, &Reply, sizeof( CSRSS_API_REQUEST ), sizeof( CSRSS_API_REPLY ) );
@@ -796,7 +867,11 @@ WINBOOL STDCALL AllocConsole(VOID)
       }
    SetStdHandle( STD_INPUT_HANDLE, Reply.Data.AllocConsoleReply.InputHandle );
    SetStdHandle( STD_OUTPUT_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle );
-   SetStdHandle( STD_ERROR_HANDLE, Reply.Data.AllocConsoleReply.OutputHandle );
+   hStdError = DuplicateConsoleHandle(Reply.Data.AllocConsoleReply.OutputHandle,
+                                      0,
+                                     TRUE,
+                                     DUPLICATE_SAME_ACCESS);
+   SetStdHandle( STD_ERROR_HANDLE, hStdError );
    return TRUE;
 }
 
@@ -2125,7 +2200,6 @@ GenerateConsoleCtrlEvent(
 /*--------------------------------------------------------------
  *     GetConsoleTitleW
  */
-#define MAX_CONSOLE_TITLE_LENGTH 80
 
 WINBASEAPI
 DWORD
@@ -2135,60 +2209,51 @@ GetConsoleTitleW(
        DWORD           nSize
        )
 {
-       union {
-       CSRSS_API_REQUEST       quest;
-       CSRSS_API_REPLY         ply;
-       } Re;
-       NTSTATUS                Status;
-
-       /* Marshall data */
-       Re.quest.Type = CSRSS_GET_TITLE;
-       Re.quest.Data.GetTitleRequest.ConsoleHandle =
-               GetStdHandle (STD_INPUT_HANDLE);
-
-       /* Call CSRSS */
-       Status = CsrClientCallServer (
-                       & Re.quest,
-                       & Re.ply,
-                       (sizeof (CSRSS_GET_TITLE_REQUEST) +
-                       sizeof (LPC_MESSAGE) +
-                       sizeof (ULONG)),
-                       sizeof (CSRSS_API_REPLY)
-                       );
-       if (    !NT_SUCCESS(Status)
-               || !NT_SUCCESS (Status = Re.ply.Status)
-               )
-       {
-               SetLastErrorByStatus (Status);
-               return (0);
-       }
+   CSRSS_API_REQUEST Request;
+   PCSRSS_API_REPLY Reply;
+   NTSTATUS Status;
+   HANDLE hConsole;
 
-       /* Convert size in characters to size in bytes */
-       nSize = sizeof (WCHAR) * nSize;
+   hConsole = CreateFileW(L"CONIN$", GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+   if (hConsole == INVALID_HANDLE_VALUE)
+   {
+      return 0;
+   }
 
-       /* Unmarshall data */
-       if (nSize < Re.ply.Data.GetTitleReply.Length)
-       {
-               DbgPrint ("%s: ret=%d\n", __FUNCTION__, Re.ply.Data.GetTitleReply.Length);
-               nSize /= sizeof (WCHAR);
-               if (nSize > 1)
-               {
-                       wcsncpy (
-                               lpConsoleTitle,
-                               Re.ply.Data.GetTitleReply.Title,
-                               (nSize - 1)
-                               );
-                       /* Add null */
-                       lpConsoleTitle [nSize --] = L'\0';
-               }
-       }
-       else
-       {
-               nSize = Re.ply.Data.GetTitleReply.Length / sizeof (WCHAR);
-               wcscpy (lpConsoleTitle, Re.ply.Data.GetTitleReply.Title);
-       }
+   Reply = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CSRSS_API_REPLY) + CSRSS_MAX_TITLE_LENGTH * sizeof(WCHAR));
+   if(Reply == NULL)
+   {
+      CloseHandle(hConsole);   
+      SetLastError(ERROR_OUTOFMEMORY);
+      return 0;
+   }
 
-       return nSize;
+   Request.Type = CSRSS_GET_TITLE;
+   Request.Data.GetTitleRequest.ConsoleHandle = hConsole;
+   
+   Status = CsrClientCallServer(&Request, Reply, sizeof(CSRSS_API_REQUEST), sizeof(CSRSS_API_REPLY) + CSRSS_MAX_TITLE_LENGTH * sizeof(WCHAR));
+   CloseHandle(hConsole);
+   if(!NT_SUCCESS(Status) || !(NT_SUCCESS(Status = Reply->Status)))
+   {
+      SetLastErrorByStatus(Status);
+      RtlFreeHeap(GetProcessHeap(), 0, Reply);
+      return 0;
+   }
+   
+   if(nSize * sizeof(WCHAR) < Reply->Data.GetTitleReply.Length)
+   {
+      wcsncpy(lpConsoleTitle, Reply->Data.GetTitleReply.Title, nSize - 1);
+      lpConsoleTitle[nSize--] = L'\0';
+   }
+   else
+   {  
+      nSize = Reply->Data.GetTitleReply.Length / sizeof (WCHAR);
+      wcscpy(lpConsoleTitle, Reply->Data.GetTitleReply.Title);
+      lpConsoleTitle[nSize] = L'\0';
+   }
+   
+   RtlFreeHeap(GetProcessHeap(), 0, Reply);
+   return nSize;
 }
 
 
@@ -2205,14 +2270,14 @@ GetConsoleTitleA(
        DWORD           nSize
        )
 {
-       wchar_t WideTitle [MAX_CONSOLE_TITLE_LENGTH];
+       wchar_t WideTitle [CSRSS_MAX_TITLE_LENGTH];
        DWORD   nWideTitle = sizeof WideTitle;
-//     DWORD   nWritten;
+       DWORD   nWritten;
        
        if (!lpConsoleTitle || !nSize) return 0;
        nWideTitle = GetConsoleTitleW( (LPWSTR) WideTitle, nWideTitle );
        if (!nWideTitle) return 0;
-#if 0
+
        if ( (nWritten = WideCharToMultiByte(
                CP_ACP,                 // ANSI code page 
                0,                      // performance and mapping flags 
@@ -2227,7 +2292,7 @@ GetConsoleTitleA(
                lpConsoleTitle[nWritten] = '\0';
                return nWritten;
        }
-#endif
+
        return 0;
 }
 
@@ -2246,18 +2311,26 @@ SetConsoleTitleW(
   CSRSS_API_REPLY Reply;
   NTSTATUS Status;
   unsigned int c;
+  HANDLE hConsole;
+
+  hConsole = CreateFileW(L"CONIN$", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+  if (hConsole == INVALID_HANDLE_VALUE)
+  {
+     return FALSE;
+  }
   
   Request = RtlAllocateHeap(GetProcessHeap(),
                            HEAP_ZERO_MEMORY,
                            sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST);
   if (Request == NULL)
     {
+      CloseHandle(hConsole);
       SetLastError(ERROR_OUTOFMEMORY);
       return(FALSE);
     }
   
   Request->Type = CSRSS_SET_TITLE;
-  Request->Data.SetTitleRequest.Console = GetStdHandle( STD_INPUT_HANDLE );
+  Request->Data.SetTitleRequest.Console = hConsole;
   
   for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ )
     Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
@@ -2266,12 +2339,10 @@ SetConsoleTitleW(
   Request->Data.SetTitleRequest.Length = c;  
   Status = CsrClientCallServer(Request,
                               &Reply,
-                              sizeof(CSRSS_SET_TITLE_REQUEST) +
-                              c +
-                              sizeof( LPC_MESSAGE ) +
-                              sizeof( ULONG ),
+                              sizeof(CSRSS_API_REQUEST) + 
+                              c * sizeof(WCHAR),
                               sizeof(CSRSS_API_REPLY));
-  
+  CloseHandle(hConsole);
   if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
     {
       RtlFreeHeap( GetProcessHeap(), 0, Request );
@@ -2299,18 +2370,26 @@ SetConsoleTitleA(
   CSRSS_API_REPLY Reply;
   NTSTATUS Status;
   unsigned int c;
+  HANDLE hConsole;
+
+  hConsole = CreateFileW(L"CONIN$", GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
+  if (hConsole == INVALID_HANDLE_VALUE)
+  {
+     return FALSE;
+  }
   
   Request = RtlAllocateHeap(GetProcessHeap(),
                            HEAP_ZERO_MEMORY,
                            sizeof(CSRSS_API_REQUEST) + CSRSS_MAX_SET_TITLE_REQUEST);
   if (Request == NULL)
     {
+      CloseHandle(hConsole);
       SetLastError(ERROR_OUTOFMEMORY);
       return(FALSE);
     }
   
   Request->Type = CSRSS_SET_TITLE;
-  Request->Data.SetTitleRequest.Console = GetStdHandle( STD_INPUT_HANDLE );
+  Request->Data.SetTitleRequest.Console = hConsole;
   
   for( c = 0; lpConsoleTitle[c] && c < CSRSS_MAX_TITLE_LENGTH; c++ )
     Request->Data.SetTitleRequest.Title[c] = lpConsoleTitle[c];
@@ -2319,12 +2398,10 @@ SetConsoleTitleA(
   Request->Data.SetTitleRequest.Length = c;
   Status = CsrClientCallServer(Request,
                               &Reply,
-                              sizeof(CSRSS_SET_TITLE_REQUEST) +
-                              c +
-                              sizeof( LPC_MESSAGE ) +
-                              sizeof( ULONG ),
+                              sizeof(CSRSS_API_REQUEST) + 
+                              c * sizeof(WCHAR),
                               sizeof(CSRSS_API_REPLY));
-  
+  CloseHandle(hConsole);
   if (!NT_SUCCESS(Status) || !NT_SUCCESS( Status = Reply.Status ) )
     {
       RtlFreeHeap( GetProcessHeap(), 0, Request );