[WIN32CSR] Implement FILE_SHARE_* flags for console handles. Fixes some more winetests.

svn path=/trunk/; revision=47319
This commit is contained in:
Jeffrey Morlan 2010-05-23 09:10:02 +00:00
parent 85b0f2bc12
commit 0b077c2961
6 changed files with 89 additions and 74 deletions

View 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;
}

View 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
{

View 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

View 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),

View 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)
{
NTSTATUS Status = STATUS_SUCCESS;
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.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;
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;
}
CSR_API(CsrGetOutputHandle)
{
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.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;
}
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)
{

View 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);