[WIN32CSR] Implement FILE_SHARE_* flags for console handles. Fixes some more winetests.
authorJeffrey Morlan <mrnobo1024@yahoo.com>
Sun, 23 May 2010 09:10:02 +0000 (09:10 +0000)
committerJeffrey Morlan <mrnobo1024@yahoo.com>
Sun, 23 May 2010 09:10:02 +0000 (09:10 +0000)
svn path=/trunk/; revision=47319

reactos/dll/win32/kernel32/misc/console.c
reactos/include/reactos/subsys/csrss/csrss.h
reactos/subsystems/win32/csrss/win32csr/conio.c
reactos/subsystems/win32/csrss/win32csr/dllmain.c
reactos/subsystems/win32/csrss/win32csr/handle.c
reactos/subsystems/win32/csrss/win32csr/win32csr.h

index 594b8ac..419f437 100644 (file)
@@ -1022,6 +1022,7 @@ OpenConsoleW(LPCWSTR wsName,
     /* Structures for GET_INPUT_HANDLE and GET_OUTPUT_HANDLE requests are identical */
     Request.Data.GetInputHandleRequest.Access = dwDesiredAccess;
     Request.Data.GetInputHandleRequest.Inheritable = bInheritHandle;
+    Request.Data.GetInputHandleRequest.ShareMode = dwShareMode;
 
     Status = CsrClientCallServer(&Request,
                                  NULL,
@@ -1033,7 +1034,7 @@ OpenConsoleW(LPCWSTR wsName,
         return INVALID_HANDLE_VALUE;
     }
 
-    return Request.Data.GetInputHandleRequest.InputHandle;
+    return Request.Data.GetInputHandleRequest.Handle;
 }
 
 
index 0119bad..9e87a4d 100644 (file)
@@ -320,15 +320,10 @@ typedef struct
 {
   DWORD Access;
   BOOL Inheritable;
-  HANDLE InputHandle;
-} CSRSS_GET_INPUT_HANDLE, *PCSRSS_GET_INPUT_HANDLE;
-
-typedef struct
-{
-  DWORD Access;
-  BOOL Inheritable;
-  HANDLE OutputHandle;
-} CSRSS_GET_OUTPUT_HANDLE, *PCSRSS_GET_OUTPUT_HANDLE;
+  HANDLE Handle;
+  DWORD ShareMode;
+} CSRSS_GET_INPUT_HANDLE, *PCSRSS_GET_INPUT_HANDLE,
+  CSRSS_GET_OUTPUT_HANDLE, *PCSRSS_GET_OUTPUT_HANDLE;
 
 typedef struct
 {
index 92d6855..ee89dad 100644 (file)
@@ -317,7 +317,8 @@ CSR_API(CsrAllocConsole)
                                       &Request->Data.AllocConsoleRequest.InputHandle,
                                       &Console->Header,
                                       GENERIC_READ | GENERIC_WRITE,
-                                      TRUE);
+                                      TRUE,
+                                      FILE_SHARE_READ | FILE_SHARE_WRITE);
         if (! NT_SUCCESS(Status))
         {
             DPRINT1("Failed to insert object\n");
@@ -331,7 +332,8 @@ CSR_API(CsrAllocConsole)
                                       &Request->Data.AllocConsoleRequest.OutputHandle,
                                       &Console->ActiveBuffer->Header,
                                       GENERIC_READ | GENERIC_WRITE,
-                                      TRUE);
+                                      TRUE,
+                                      FILE_SHARE_READ | FILE_SHARE_WRITE);
         if (!NT_SUCCESS(Status))
         {
             DPRINT1("Failed to insert object\n");
@@ -1975,7 +1977,8 @@ CSR_API(CsrCreateScreenBuffer)
             &Request->Data.CreateScreenBufferRequest.OutputHandle,
             &Buff->Header,
             Request->Data.CreateScreenBufferRequest.Access,
-            Request->Data.CreateScreenBufferRequest.Inheritable);
+            Request->Data.CreateScreenBufferRequest.Inheritable,
+            Request->Data.CreateScreenBufferRequest.ShareMode);
         }
     }
   else
index a8fdd41..bd0409c 100644 (file)
@@ -24,8 +24,8 @@ static CSRSS_EXPORTED_FUNCS CsrExports;
 
 static CSRSS_API_DEFINITION Win32CsrApiDefinitions[] =
   {
-    CSRSS_DEFINE_API(GET_INPUT_HANDLE,             CsrGetInputHandle),
-    CSRSS_DEFINE_API(GET_OUTPUT_HANDLE,            CsrGetOutputHandle),
+    CSRSS_DEFINE_API(GET_INPUT_HANDLE,             CsrGetHandle),
+    CSRSS_DEFINE_API(GET_OUTPUT_HANDLE,            CsrGetHandle),
     CSRSS_DEFINE_API(CLOSE_HANDLE,                 CsrCloseHandle),
     CSRSS_DEFINE_API(VERIFY_HANDLE,                CsrVerifyHandle),
     CSRSS_DEFINE_API(DUPLICATE_HANDLE,             CsrDuplicateHandle),
index e7b28b1..87f5c63 100644 (file)
@@ -23,17 +23,26 @@ CsrIsConsoleHandle(HANDLE Handle)
     return ((ULONG_PTR)Handle & 0x10000003) == 0x3;
 }
 
+static INT
+AdjustHandleCounts(PCSRSS_HANDLE Entry, INT Change)
+{
+    Object_t *Object = Entry->Object;
+    if (Entry->Access & GENERIC_READ)           Object->AccessRead += Change;
+    if (Entry->Access & GENERIC_WRITE)          Object->AccessWrite += Change;
+    if (!(Entry->ShareMode & FILE_SHARE_READ))  Object->ExclusiveRead += Change;
+    if (!(Entry->ShareMode & FILE_SHARE_WRITE)) Object->ExclusiveWrite += Change;
+    Object->HandleCount += Change;
+    return Object->HandleCount;
+}
+
 static VOID
 Win32CsrCreateHandleEntry(
-    PCSRSS_HANDLE Entry,
-    Object_t *Object,
-    DWORD Access,
-    BOOL Inheritable)
+    PCSRSS_HANDLE Entry)
 {
-    Entry->Object = Object;
-    Entry->Access = Access;
-    Entry->Inheritable = Inheritable;
-    _InterlockedIncrement(&Object->HandleCount);
+    Object_t *Object = Entry->Object;
+    EnterCriticalSection(&Object->Console->Lock);
+    AdjustHandleCounts(Entry, +1);
+    LeaveCriticalSection(&Object->Console->Lock);
 }
 
 static VOID
@@ -43,21 +52,21 @@ Win32CsrCloseHandleEntry(
     Object_t *Object = Entry->Object;
     if (Object != NULL)
     {
-        Entry->Object = NULL;
+        PCSRSS_CONSOLE Console = Object->Console;
+        EnterCriticalSection(&Console->Lock);
         /* If the last handle to a screen buffer is closed, delete it */
-        if (_InterlockedDecrement(&Object->HandleCount) == 0
+        if (AdjustHandleCounts(Entry, -1) == 0
             && Object->Type == CONIO_SCREEN_BUFFER_MAGIC)
         {
-            PCSRSS_CONSOLE Console = Object->Console;
             PCSRSS_SCREEN_BUFFER Buffer = (PCSRSS_SCREEN_BUFFER)Object;
-            EnterCriticalSection(&Console->Lock);
             /* ...unless it's the only buffer left. Windows allows deletion
              * even of the last buffer, but having to deal with a lack of
              * any active buffer might be error-prone. */
             if (Buffer->ListEntry.Flink != Buffer->ListEntry.Blink)
                 ConioDeleteScreenBuffer(Buffer);
-            LeaveCriticalSection(&Console->Lock);
         }
+        LeaveCriticalSection(&Console->Lock);
+        Entry->Object = NULL;
     }
 }
 
@@ -163,7 +172,8 @@ Win32CsrInsertObject(
     PHANDLE Handle,
     Object_t *Object,
     DWORD Access,
-    BOOL Inheritable)
+    BOOL Inheritable,
+    DWORD ShareMode)
 {
     ULONG i;
     PCSRSS_HANDLE Block;
@@ -194,7 +204,11 @@ Win32CsrInsertObject(
         ProcessData->HandleTable = Block;
         ProcessData->HandleTableSize += 64;
     }
-    Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i], Object, Access, Inheritable);
+    ProcessData->HandleTable[i].Object      = Object;
+    ProcessData->HandleTable[i].Access      = Access;
+    ProcessData->HandleTable[i].Inheritable = Inheritable;
+    ProcessData->HandleTable[i].ShareMode   = ShareMode;
+    Win32CsrCreateHandleEntry(&ProcessData->HandleTable[i]);
     *Handle = UlongToHandle((i << 2) | 0x3);
     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
     return(STATUS_SUCCESS);
@@ -232,62 +246,60 @@ Win32CsrDuplicateHandleTable(
         if (SourceProcessData->HandleTable[i].Object != NULL &&
             SourceProcessData->HandleTable[i].Inheritable)
         {
-            Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i],
-                                       SourceProcessData->HandleTable[i].Object,
-                                       SourceProcessData->HandleTable[i].Access,
-                                       SourceProcessData->HandleTable[i].Inheritable);
+            TargetProcessData->HandleTable[i] = SourceProcessData->HandleTable[i];
+            Win32CsrCreateHandleEntry(&TargetProcessData->HandleTable[i]);
         }
     }
     RtlLeaveCriticalSection(&SourceProcessData->HandleTableLock);
     return(STATUS_SUCCESS);
 }
 
-CSR_API(CsrGetInputHandle)
+CSR_API(CsrGetHandle)
 {
-    Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
-    Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
-
-    RtlEnterCriticalSection(&ProcessData->HandleTableLock);
-    if (ProcessData->Console)
-    {
-        Request->Status = Win32CsrInsertObject(ProcessData,
-                                               &Request->Data.GetInputHandleRequest.InputHandle,
-                                               &ProcessData->Console->Header,
-                                               Request->Data.GetInputHandleRequest.Access,
-                                               Request->Data.GetInputHandleRequest.Inheritable);
-    }
-    else
-    {
-        Request->Data.GetInputHandleRequest.InputHandle = INVALID_HANDLE_VALUE;
-        Request->Status = STATUS_SUCCESS;
-    }
-    RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
-
-    return Request->Status;
-}
+    NTSTATUS Status = STATUS_SUCCESS;
 
-CSR_API(CsrGetOutputHandle)
-{
     Request->Header.u1.s1.TotalLength = sizeof(CSR_API_MESSAGE);
     Request->Header.u1.s1.DataLength = sizeof(CSR_API_MESSAGE) - sizeof(PORT_MESSAGE);
 
+    Request->Data.GetInputHandleRequest.Handle = INVALID_HANDLE_VALUE;
+
     RtlEnterCriticalSection(&ProcessData->HandleTableLock);
     if (ProcessData->Console)
     {
-        Request->Status = Win32CsrInsertObject(ProcessData,
-                                               &Request->Data.GetOutputHandleRequest.OutputHandle,
-                                               &ProcessData->Console->ActiveBuffer->Header,
-                                               Request->Data.GetOutputHandleRequest.Access,
-                                               Request->Data.GetOutputHandleRequest.Inheritable);
-    }
-    else
-    {
-        Request->Data.GetOutputHandleRequest.OutputHandle = INVALID_HANDLE_VALUE;
-        Request->Status = STATUS_SUCCESS;
+        DWORD DesiredAccess = Request->Data.GetInputHandleRequest.Access;
+        DWORD ShareMode = Request->Data.GetInputHandleRequest.ShareMode;
+
+        PCSRSS_CONSOLE Console = ProcessData->Console;
+        Object_t *Object;
+        
+        EnterCriticalSection(&Console->Lock);
+        if (Request->Type == GET_OUTPUT_HANDLE)
+            Object = &Console->ActiveBuffer->Header;
+        else
+            Object = &Console->Header;
+
+        if (((DesiredAccess & GENERIC_READ)  && Object->ExclusiveRead  != 0) ||
+            ((DesiredAccess & GENERIC_WRITE) && Object->ExclusiveWrite != 0) ||
+            (!(ShareMode & FILE_SHARE_READ)  && Object->AccessRead     != 0) ||
+            (!(ShareMode & FILE_SHARE_WRITE) && Object->AccessWrite    != 0))
+        {
+            DPRINT1("Sharing violation\n");
+            Status = STATUS_SHARING_VIOLATION;
+        }
+        else
+        {
+            Status = Win32CsrInsertObject(ProcessData,
+                                          &Request->Data.GetInputHandleRequest.Handle,
+                                          Object,
+                                          DesiredAccess,
+                                          Request->Data.GetInputHandleRequest.Inheritable,
+                                          ShareMode);
+        }
+        LeaveCriticalSection(&Console->Lock);
     }
     RtlLeaveCriticalSection(&ProcessData->HandleTableLock);
 
-    return Request->Status;
+    return Status;
 }
 
 CSR_API(CsrCloseHandle)
@@ -359,7 +371,8 @@ CSR_API(CsrDuplicateHandle)
                                            &Request->Data.DuplicateHandleRequest.Handle,
                                            Entry->Object,
                                            DesiredAccess,
-                                           Request->Data.DuplicateHandleRequest.Inheritable);
+                                           Request->Data.DuplicateHandleRequest.Inheritable,
+                                           Entry->ShareMode);
     if (NT_SUCCESS(Request->Status)
         && Request->Data.DuplicateHandleRequest.Options & DUPLICATE_CLOSE_SOURCE)
     {
index 0bb4440..111c27d 100644 (file)
@@ -18,6 +18,8 @@ typedef struct Object_tt
 {
   LONG Type;
   struct tagCSRSS_CONSOLE *Console;
+  LONG AccessRead, AccessWrite;
+  LONG ExclusiveRead, ExclusiveWrite;
   LONG HandleCount;
 } Object_t;
 
@@ -26,6 +28,7 @@ typedef struct _CSRSS_HANDLE
   Object_t *Object;
   DWORD Access;
   BOOL Inheritable;
+  DWORD ShareMode;
 } CSRSS_HANDLE, *PCSRSS_HANDLE;
 
 typedef VOID (WINAPI *CSR_CLEANUP_OBJECT_PROC)(Object_t *Object);
@@ -41,7 +44,8 @@ NTSTATUS FASTCALL Win32CsrInsertObject(PCSRSS_PROCESS_DATA ProcessData,
                                        PHANDLE Handle,
                                        Object_t *Object,
                                        DWORD Access,
-                                       BOOL Inheritable);
+                                       BOOL Inheritable,
+                                       DWORD ShareMode);
 NTSTATUS FASTCALL Win32CsrLockObject(PCSRSS_PROCESS_DATA ProcessData,
                                      HANDLE Handle,
                                      Object_t **Object,
@@ -53,8 +57,7 @@ NTSTATUS FASTCALL Win32CsrReleaseObject(PCSRSS_PROCESS_DATA ProcessData,
 NTSTATUS WINAPI Win32CsrReleaseConsole(PCSRSS_PROCESS_DATA ProcessData);
 NTSTATUS WINAPI Win32CsrDuplicateHandleTable(PCSRSS_PROCESS_DATA SourceProcessData,
                                              PCSRSS_PROCESS_DATA TargetProcessData);
-CSR_API(CsrGetInputHandle);
-CSR_API(CsrGetOutputHandle);
+CSR_API(CsrGetHandle);
 CSR_API(CsrCloseHandle);
 CSR_API(CsrVerifyHandle);
 CSR_API(CsrDuplicateHandle);