* PROJECT: ReactOS Client/Server Runtime SubSystem
* FILE: subsystems/win32/csrsrv/api.c
* PURPOSE: CSR Server DLL API LPC Implementation
- * "\windows\ApiPort" port process management functions
+ * "\Windows\ApiPort" port process management functions
* PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/
#include "srv.h"
+#include <ndk/kefuncs.h>
+
#define NDEBUG
#include <debug.h>
BOOLEAN (*CsrClientThreadSetup)(VOID) = NULL;
UNICODE_STRING CsrApiPortName;
-volatile LONG CsrpStaticThreadCount;
-volatile LONG CsrpDynamicThreadTotal;
+volatile ULONG CsrpStaticThreadCount;
+volatile ULONG CsrpDynamicThreadTotal;
extern ULONG CsrMaxApiRequestThreads;
/* FUNCTIONS ******************************************************************/
{
/* We are beyond the Maximum Server ID */
DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n", ServerId, ServerDll);
- ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
+ ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
return STATUS_ILLEGAL_FUNCTION;
}
else
((ServerDll->ValidTable) && !(ServerDll->ValidTable[ApiId])))
{
/* We are beyond the Maximum API ID, or it doesn't exist */
+#ifdef CSR_DBG
+ DPRINT1("API: %d\n", ApiId);
DPRINT1("CSRSS: %lx (%s) is invalid ApiTableIndex for %Z or is an "
"invalid API to call from the server.\n",
- ServerDll->ValidTable[ApiId],
+ ApiId,
((ServerDll->NameTable) && (ServerDll->NameTable[ApiId])) ?
- ServerDll->NameTable[ApiId] : "*** UNKNOWN ***", &ServerDll->Name);
- DbgBreakPoint();
- ReplyMsg->Status = (ULONG)STATUS_ILLEGAL_FUNCTION;
+ ServerDll->NameTable[ApiId] : "*** UNKNOWN ***",
+ &ServerDll->Name);
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
+ ReplyMsg->Status = STATUS_ILLEGAL_FUNCTION;
return STATUS_ILLEGAL_FUNCTION;
}
}
+#ifdef CSR_DBG
if (CsrDebug & 2)
{
DPRINT1("CSRSS: %s Api Request received from server process\n",
ServerDll->NameTable[ApiId]);
}
+#endif
/* Validation complete, start SEH */
_SEH2_TRY
PCSR_THREAD CsrThread = NULL;
PCSR_PROCESS CsrProcess = NULL;
NTSTATUS Status = STATUS_SUCCESS;
- PCSR_CONNECTION_INFO ConnectInfo = &ApiMessage->ConnectionInfo;
+ PCSR_API_CONNECTINFO ConnectInfo = &ApiMessage->ConnectionInfo;
BOOLEAN AllowConnection = FALSE;
REMOTE_PORT_VIEW RemotePortView;
HANDLE ServerPort;
/* Check if we have a thread */
if (CsrThread)
{
- /* Get the Process */
+ /* Get the Process and make sure we have it as well */
CsrProcess = CsrThread->Process;
-
- /* Make sure we have a Process as well */
if (CsrProcess)
{
/* Reference the Process */
- CsrLockedReferenceProcess(CsrThread->Process);
+ CsrLockedReferenceProcess(CsrProcess);
- /* Release the lock */
- CsrReleaseProcessLock();
-
- /* Duplicate the Object Directory */
- Status = NtDuplicateObject(NtCurrentProcess(),
- CsrObjectDirectory,
- CsrProcess->ProcessHandle,
- &ConnectInfo->ObjectDirectory,
- 0,
- 0,
- DUPLICATE_SAME_ACCESS |
- DUPLICATE_SAME_ATTRIBUTES);
-
- /* Acquire the lock */
- CsrAcquireProcessLock();
-
- /* Check for success */
+ /* Attach the Shared Section */
+ Status = CsrSrvAttachSharedSection(CsrProcess, ConnectInfo);
if (NT_SUCCESS(Status))
{
- /* Attach the Shared Section */
- Status = CsrSrvAttachSharedSection(CsrProcess, ConnectInfo);
-
- /* Check how this went */
- if (NT_SUCCESS(Status)) AllowConnection = TRUE;
+ /* Allow the connection and return debugging flag */
+ ConnectInfo->DebugFlags = CsrDebug;
+ AllowConnection = TRUE;
}
- /* Dereference the project */
+ /* Dereference the Process */
CsrLockedDereferenceProcess(CsrProcess);
}
}
- /* Release the lock */
+ /* Release the Process Lock */
CsrReleaseProcessLock();
/* Setup the Port View Structure */
RemotePortView.ViewBase = NULL;
/* Save the Process ID */
- ConnectInfo->ProcessId = NtCurrentTeb()->ClientId.UniqueProcess;
+ ConnectInfo->ServerProcessId = NtCurrentTeb()->ClientId.UniqueProcess;
/* Accept the Connection */
+ ASSERT(!AllowConnection || CsrProcess);
Status = NtAcceptConnectPort(&ServerPort,
AllowConnection ? UlongToPtr(CsrProcess->SequenceNumber) : 0,
&ApiMessage->Header,
NTSTATUS Status;
/* Decrease the count, and see if we're out */
- if (!(_InterlockedDecrement(&CsrpStaticThreadCount)))
+ if (InterlockedDecrementUL(&CsrpStaticThreadCount) == 0)
{
/* Check if we've still got space for a Dynamic Thread */
if (CsrpDynamicThreadTotal < CsrMaxApiRequestThreads)
if (NT_SUCCESS(Status))
{
/* Increase the thread counts */
- _InterlockedIncrement(&CsrpStaticThreadCount);
- _InterlockedIncrement(&CsrpDynamicThreadTotal);
+ InterlockedIncrementUL(&CsrpStaticThreadCount);
+ InterlockedIncrementUL(&CsrpDynamicThreadTotal);
/* Add a new server thread */
if (CsrAddStaticServerThread(hThread,
else
{
/* Failed to create a new static thread */
- _InterlockedDecrement(&CsrpStaticThreadCount);
- _InterlockedDecrement(&CsrpDynamicThreadTotal);
+ InterlockedDecrementUL(&CsrpStaticThreadCount);
+ InterlockedDecrementUL(&CsrpDynamicThreadTotal);
/* Terminate it */
DPRINT1("Failing\n");
ASSERT(NT_SUCCESS(Status));
/* Increase the Thread Counts */
- _InterlockedIncrement(&CsrpStaticThreadCount);
- _InterlockedIncrement(&CsrpDynamicThreadTotal);
+ InterlockedIncrementUL(&CsrpStaticThreadCount);
+ InterlockedIncrementUL(&CsrpDynamicThreadTotal);
}
/* Now start the loop */
/* Make sure the real CID is set */
Teb->RealClientId = Teb->ClientId;
+#ifdef CSR_DBG
/* Debug check */
if (Teb->CountOfOwnedCriticalSections)
{
&ReceiveMsg, ReplyMsg);
DbgBreakPoint();
}
+#endif
/* Wait for a message to come through */
Status = NtReplyWaitReceivePort(ReplyPort,
/* Was it a failure or another success code? */
if (!NT_SUCCESS(Status))
{
+#ifdef CSR_DBG
/* Check for specific status cases */
if ((Status != STATUS_INVALID_CID) &&
(Status != STATUS_UNSUCCESSFUL) &&
- ((Status == STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort)))
+ ((Status != STATUS_INVALID_HANDLE) || (ReplyPort == CsrApiPort)))
{
/* Notify the debugger */
DPRINT1("CSRSS: ReceivePort failed - Status == %X\n", Status);
DPRINT1("CSRSS: ReplyPortHandle %lx CsrApiPort %lx\n", ReplyPort, CsrApiPort);
}
+#endif
/* We failed big time, so start out fresh */
ReplyMsg = NULL;
}
else
{
- /* A bizare "success" code, just try again */
+ /* A strange "success" code, just try again */
DPRINT1("NtReplyWaitReceivePort returned \"success\" status 0x%x\n", Status);
continue;
}
}
+ // ASSERT(ReceiveMsg.Header.u1.s1.TotalLength >= sizeof(PORT_MESSAGE));
+ // ASSERT(ReceiveMsg.Header.u1.s1.TotalLength < sizeof(ReceiveMsg));
+
/* Use whatever Client ID we got */
Teb->RealClientId = ReceiveMsg.Header.ClientId;
}
/* Increase the thread count */
- _InterlockedIncrement(&CsrpStaticThreadCount);
+ InterlockedIncrementUL(&CsrpStaticThreadCount);
/* If the response was 0xFFFFFFFF, we'll ignore it */
if (HardErrorMsg->Response == 0xFFFFFFFF)
(!(ServerDll = CsrLoadedServerDll[ServerId])))
{
/* We are beyond the Maximum Server ID */
+#ifdef CSR_DBG
DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
ServerId, ServerDll);
- DbgBreakPoint();
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
ReplyMsg = NULL;
ReplyPort = CsrApiPort;
continue;
}
+#ifdef CSR_DBG
if (CsrDebug & 2)
{
DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
ServerDll->NameTable[ApiId],
NULL);
}
+#endif
/* Assume success */
ReceiveMsg.Status = STATUS_SUCCESS;
ServerDll->DispatchTable[ApiId](&ReceiveMsg, &ReplyCode);
/* Increase the static thread count */
- _InterlockedIncrement(&CsrpStaticThreadCount);
+ InterlockedIncrementUL(&CsrpStaticThreadCount);
}
_SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
{
}
/* Increase the thread count */
- _InterlockedIncrement(&CsrpStaticThreadCount);
+ InterlockedIncrementUL(&CsrpStaticThreadCount);
/* If the response was 0xFFFFFFFF, we'll ignore it */
if (HardErrorMsg->Response == 0xFFFFFFFF)
(!(ServerDll = CsrLoadedServerDll[ServerId])))
{
/* We are beyond the Maximum Server ID */
+#ifdef CSR_DBG
DPRINT1("CSRSS: %lx is invalid ServerDllIndex (%08x)\n",
ServerId, ServerDll);
- DbgBreakPoint();
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
ReplyPort = CsrApiPort;
ReplyMsg = &ReceiveMsg;
continue;
}
+#ifdef CSR_DBG
if (CsrDebug & 2)
{
DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x, Process %08x - %08x\n",
CsrThread->Process,
CsrProcess);
}
+#endif
/* Assume success */
ReplyMsg = &ReceiveMsg;
ReplyMsg->Status = ServerDll->DispatchTable[ApiId](&ReceiveMsg, &ReplyCode);
/* Increase the static thread count */
- _InterlockedIncrement(&CsrpStaticThreadCount);
+ InterlockedIncrementUL(&CsrpStaticThreadCount);
Teb->CsrClientThread = CurrentThread;
else if (ReplyCode == CsrReplyDeadClient)
{
/* Reply to the death message */
- NtReplyPort(ReplyPort, &ReplyMsg->Header);
+ NTSTATUS Status2;
+ Status2 = NtReplyPort(ReplyPort, &ReplyMsg->Header);
+ if (!NT_SUCCESS(Status2))
+ DPRINT1("CSRSS: Error while replying to the death message, Status 0x%lx\n", Status2);
/* Reply back to the API port now */
ReplyMsg = NULL;
ReplyPort = CsrApiPort;
-
CsrDereferenceThread(CsrThread);
}
else if (ReplyCode == CsrReplyPending)
*
* @param None
*
- * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
- * otherwise.
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
*
* @remarks None.
*
{
DPRINT1("CSRSS: Creating %wZ port and associated threads\n", &CsrApiPortName);
DPRINT1("CSRSS: sizeof( CONNECTINFO ) == %ld sizeof( API_MSG ) == %ld\n",
- sizeof(CSR_CONNECTION_INFO), sizeof(CSR_API_MESSAGE));
+ sizeof(CSR_API_CONNECTINFO), sizeof(CSR_API_MESSAGE));
}
/* FIXME: Create a Security Descriptor */
/* Create the Port Object */
Status = NtCreatePort(&CsrApiPort,
&ObjectAttributes,
- sizeof(CSR_CONNECTION_INFO),
+ sizeof(CSR_API_CONNECTINFO),
sizeof(CSR_API_MESSAGE),
16 * PAGE_SIZE);
if (NT_SUCCESS(Status))
NTAPI
CsrConnectToUser(VOID)
{
-#if 0 // This code is OK, however it is ClientThreadSetup which sucks.
NTSTATUS Status;
ANSI_STRING DllName;
UNICODE_STRING TempName;
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Connected = FALSE;
- } _SEH2_END;
-
+ }
+ _SEH2_END;
+
if (!Connected)
{
DPRINT1("CSRSS: CsrConnectToUser failed\n");
/* Return it */
return CsrThread;
-
-#else
-
- PTEB Teb = NtCurrentTeb();
- PCSR_THREAD CsrThread;
-
- /* Save pointer to this thread in TEB */
- CsrThread = CsrLocateThreadInProcess(NULL, &Teb->ClientId);
- if (CsrThread) Teb->CsrClientThread = CsrThread;
-
- /* Return it */
- return CsrThread;
-#endif
}
/*++
NTAPI
CsrQueryApiPort(VOID)
{
- DPRINT("CSRSRV: %s called\n", __FUNCTION__);
return CsrApiPort;
}
CsrCaptureArguments(IN PCSR_THREAD CsrThread,
IN PCSR_API_MESSAGE ApiMessage)
{
- PCSR_CAPTURE_BUFFER LocalCaptureBuffer = NULL, RemoteCaptureBuffer = NULL;
+ PCSR_PROCESS CsrProcess = CsrThread->Process;
+ PCSR_CAPTURE_BUFFER ClientCaptureBuffer, ServerCaptureBuffer = NULL;
+ ULONG_PTR EndOfClientBuffer;
+ SIZE_T SizeOfBufferThroughOffsetsArray;
SIZE_T BufferDistance;
- ULONG Length = 0;
+ ULONG Length;
ULONG PointerCount;
PULONG_PTR OffsetPointer;
ULONG_PTR CurrentOffset;
- /* Use SEH to make sure this is valid */
+ /* Get the buffer we got from whoever called NTDLL */
+ ClientCaptureBuffer = ApiMessage->CsrCaptureData;
+
+ /* Use SEH to validate and capture the client buffer */
_SEH2_TRY
{
- /* Get the buffer we got from whoever called NTDLL */
- LocalCaptureBuffer = ApiMessage->CsrCaptureData;
- Length = LocalCaptureBuffer->Size;
+ /* Check whether at least the buffer's header is inside our mapped section */
+ if ( ((ULONG_PTR)ClientCaptureBuffer < CsrProcess->ClientViewBase) ||
+ (((ULONG_PTR)ClientCaptureBuffer + FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray))
+ >= CsrProcess->ClientViewBounds) )
+ {
+#ifdef CSR_DBG
+ DPRINT1("*** CSRSS: CaptureBuffer outside of ClientView 1\n");
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
+ /* Return failure */
+ ApiMessage->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_YIELD(return FALSE);
+ }
- /* Now check if the buffer is inside our mapped section */
- if (((ULONG_PTR)LocalCaptureBuffer < CsrThread->Process->ClientViewBase) ||
- (((ULONG_PTR)LocalCaptureBuffer + Length) >= CsrThread->Process->ClientViewBounds))
+ /* Capture the buffer length */
+ Length = ((volatile CSR_CAPTURE_BUFFER*)ClientCaptureBuffer)->Size;
+
+ /*
+ * Now check if the remaining of the buffer is inside our mapped section.
+ * Take also care for any possible wrap-around of the buffer end-address.
+ */
+ EndOfClientBuffer = (ULONG_PTR)ClientCaptureBuffer + Length;
+ if ( (EndOfClientBuffer < (ULONG_PTR)ClientCaptureBuffer) ||
+ (EndOfClientBuffer >= CsrProcess->ClientViewBounds) )
{
+#ifdef CSR_DBG
+ DPRINT1("*** CSRSS: CaptureBuffer outside of ClientView 2\n");
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
/* Return failure */
- DPRINT1("*** CSRSS: CaptureBuffer outside of ClientView\n");
ApiMessage->Status = STATUS_INVALID_PARAMETER;
_SEH2_YIELD(return FALSE);
}
- /* Check if the Length is valid */
- if ((FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray) +
- (LocalCaptureBuffer->PointerCount * sizeof(PVOID)) > Length) ||
- (Length > MAXWORD))
+ /* Capture the pointer count */
+ PointerCount = ((volatile CSR_CAPTURE_BUFFER*)ClientCaptureBuffer)->PointerCount;
+
+ /*
+ * Check whether the total buffer size and the pointer count are consistent
+ * -- the array of offsets must be contained inside the buffer.
+ */
+ SizeOfBufferThroughOffsetsArray =
+ FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray) +
+ (PointerCount * sizeof(PVOID));
+ if ( (PointerCount > MAXUSHORT) ||
+ (SizeOfBufferThroughOffsetsArray > Length) )
{
+#ifdef CSR_DBG
+ DPRINT1("*** CSRSS: CaptureBuffer %p has bad length\n", ClientCaptureBuffer);
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
/* Return failure */
- DPRINT1("*** CSRSS: CaptureBuffer %p has bad length\n", LocalCaptureBuffer);
- DbgBreakPoint();
ApiMessage->Status = STATUS_INVALID_PARAMETER;
_SEH2_YIELD(return FALSE);
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
+#ifdef CSR_DBG
+ DPRINT1("*** CSRSS: Took exception during capture %x\n", _SEH2_GetExceptionCode());
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
/* Return failure */
ApiMessage->Status = STATUS_INVALID_PARAMETER;
_SEH2_YIELD(return FALSE);
- } _SEH2_END;
+ }
+ _SEH2_END;
- /* We validated the incoming buffer, now allocate the remote one */
- RemoteCaptureBuffer = RtlAllocateHeap(CsrHeap, 0, Length);
- if (!RemoteCaptureBuffer)
+ /* We validated the client buffer, now allocate the server buffer */
+ ServerCaptureBuffer = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length);
+ if (!ServerCaptureBuffer)
{
/* We're out of memory */
ApiMessage->Status = STATUS_NO_MEMORY;
return FALSE;
}
- /* Copy the client's buffer */
- RtlMoveMemory(RemoteCaptureBuffer, LocalCaptureBuffer, Length);
+ /*
+ * Copy the client's buffer and ensure we use the correct buffer length
+ * and pointer count we captured and used for validation earlier on.
+ */
+ _SEH2_TRY
+ {
+ RtlMoveMemory(ServerCaptureBuffer, ClientCaptureBuffer, Length);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+#ifdef CSR_DBG
+ DPRINT1("*** CSRSS: Took exception during capture %x\n", _SEH2_GetExceptionCode());
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
+ /* Failure, free the buffer and return */
+ RtlFreeHeap(CsrHeap, 0, ServerCaptureBuffer);
+ ApiMessage->Status = STATUS_INVALID_PARAMETER;
+ _SEH2_YIELD(return FALSE);
+ }
+ _SEH2_END;
+
+ ServerCaptureBuffer->Size = Length;
+ ServerCaptureBuffer->PointerCount = PointerCount;
/* Calculate the difference between our buffer and the client's */
- BufferDistance = (ULONG_PTR)RemoteCaptureBuffer - (ULONG_PTR)LocalCaptureBuffer;
+ BufferDistance = (ULONG_PTR)ServerCaptureBuffer - (ULONG_PTR)ClientCaptureBuffer;
/*
- * All the pointer offsets correspond to pointers which point
- * to the remote data buffer instead of the local one.
+ * All the pointer offsets correspond to pointers that point
+ * to the server data buffer instead of the client one.
*/
- PointerCount = RemoteCaptureBuffer->PointerCount;
- OffsetPointer = RemoteCaptureBuffer->PointerOffsetsArray;
+ // PointerCount = ServerCaptureBuffer->PointerCount;
+ OffsetPointer = ServerCaptureBuffer->PointerOffsetsArray;
while (PointerCount--)
{
CurrentOffset = *OffsetPointer;
if (CurrentOffset != 0)
{
+ /*
+ * Check whether the offset is pointer-aligned and whether
+ * it points inside CSR_API_MESSAGE::Data.ApiMessageData.
+ */
+ if ( ((CurrentOffset & (sizeof(PVOID)-1)) != 0) ||
+ (CurrentOffset < FIELD_OFFSET(CSR_API_MESSAGE, Data.ApiMessageData)) ||
+ (CurrentOffset >= sizeof(CSR_API_MESSAGE)) )
+ {
+#ifdef CSR_DBG
+ DPRINT1("*** CSRSS: CaptureBuffer MessagePointer outside of message\n");
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
+ /* Invalid pointer, fail */
+ ApiMessage->Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
/* Get the pointer corresponding to the offset */
CurrentOffset += (ULONG_PTR)ApiMessage;
/* Validate the bounds of the current pointed pointer */
- if ((*(PULONG_PTR)CurrentOffset >= CsrThread->Process->ClientViewBase) &&
- (*(PULONG_PTR)CurrentOffset < CsrThread->Process->ClientViewBounds))
+ if ( (*(PULONG_PTR)CurrentOffset >= ((ULONG_PTR)ClientCaptureBuffer +
+ SizeOfBufferThroughOffsetsArray)) &&
+ (*(PULONG_PTR)CurrentOffset <= (EndOfClientBuffer - sizeof(PVOID))) )
{
/* Modify the pointed pointer to take into account its new position */
*(PULONG_PTR)CurrentOffset += BufferDistance;
}
else
{
- /* Invalid pointer, fail */
+#ifdef CSR_DBG
DPRINT1("*** CSRSS: CaptureBuffer MessagePointer outside of ClientView\n");
- DbgBreakPoint();
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
+ /* Invalid pointer, fail */
ApiMessage->Status = STATUS_INVALID_PARAMETER;
+ break;
}
}
/* Check if we got success */
if (ApiMessage->Status != STATUS_SUCCESS)
{
- /* Failure. Free the buffer and return */
- RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
+ /* Failure, free the buffer and return */
+ RtlFreeHeap(CsrHeap, 0, ServerCaptureBuffer);
return FALSE;
}
else
{
- /* Success, save the previous buffer and use the remote capture buffer */
- RemoteCaptureBuffer->PreviousCaptureBuffer = LocalCaptureBuffer;
- ApiMessage->CsrCaptureData = RemoteCaptureBuffer;
+ /* Success, save the previous buffer and use the server capture buffer */
+ ServerCaptureBuffer->PreviousCaptureBuffer = ClientCaptureBuffer;
+ ApiMessage->CsrCaptureData = ServerCaptureBuffer;
}
/* Success */
NTAPI
CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
{
- PCSR_CAPTURE_BUFFER RemoteCaptureBuffer, LocalCaptureBuffer;
+ PCSR_CAPTURE_BUFFER ServerCaptureBuffer, ClientCaptureBuffer;
SIZE_T BufferDistance;
ULONG PointerCount;
PULONG_PTR OffsetPointer;
ULONG_PTR CurrentOffset;
- /* Get the remote capture buffer */
- RemoteCaptureBuffer = ApiMessage->CsrCaptureData;
+ /* Get the server capture buffer */
+ ServerCaptureBuffer = ApiMessage->CsrCaptureData;
/* Do not continue if there is no captured buffer */
- if (!RemoteCaptureBuffer) return;
+ if (!ServerCaptureBuffer) return;
- /* If there is one, get the corresponding local capture buffer */
- LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer;
+ /* If there is one, get the corresponding client capture buffer */
+ ClientCaptureBuffer = ServerCaptureBuffer->PreviousCaptureBuffer;
- /* Free the previous one and use again the local capture buffer */
- RemoteCaptureBuffer->PreviousCaptureBuffer = NULL;
- ApiMessage->CsrCaptureData = LocalCaptureBuffer;
+ /* Free the previous one and use again the client capture buffer */
+ ServerCaptureBuffer->PreviousCaptureBuffer = NULL;
+ ApiMessage->CsrCaptureData = ClientCaptureBuffer;
/* Calculate the difference between our buffer and the client's */
- BufferDistance = (ULONG_PTR)RemoteCaptureBuffer - (ULONG_PTR)LocalCaptureBuffer;
+ BufferDistance = (ULONG_PTR)ServerCaptureBuffer - (ULONG_PTR)ClientCaptureBuffer;
/*
- * All the pointer offsets correspond to pointers which point
- * to the local data buffer instead of the remote one (revert
- * the logic of CsrCaptureArguments).
+ * All the pointer offsets correspond to pointers that point
+ * to the client data buffer instead of the server one (reverse
+ * the logic of CsrCaptureArguments()).
*/
- PointerCount = RemoteCaptureBuffer->PointerCount;
- OffsetPointer = RemoteCaptureBuffer->PointerOffsetsArray;
+ PointerCount = ServerCaptureBuffer->PointerCount;
+ OffsetPointer = ServerCaptureBuffer->PointerOffsetsArray;
while (PointerCount--)
{
CurrentOffset = *OffsetPointer;
++OffsetPointer;
}
- /* Copy the data back */
- RtlMoveMemory(LocalCaptureBuffer, RemoteCaptureBuffer, RemoteCaptureBuffer->Size);
+ /* Copy the data back into the client buffer */
+ _SEH2_TRY
+ {
+ RtlMoveMemory(ClientCaptureBuffer, ServerCaptureBuffer, ServerCaptureBuffer->Size);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+#ifdef CSR_DBG
+ DPRINT1("*** CSRSS: Took exception during release %x\n", _SEH2_GetExceptionCode());
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
+ /* Return failure */
+ ApiMessage->Status = _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
/* Free our allocated buffer */
- RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
+ RtlFreeHeap(CsrHeap, 0, ServerCaptureBuffer);
}
-
/*++
* @name CsrValidateMessageBuffer
* @implemented NT5.1
* of non-trivial size and that we don't overflow.
*/
if (!Buffer || ElementSize == 0 ||
- (ULONGLONG)ElementCount * ElementSize > (ULONGLONG)0xFFFFFFFF)
+ (ULONGLONG)ElementCount * ElementSize > (ULONGLONG)MAXULONG)
{
return FALSE;
}
/* Check if we have no capture buffer */
if (!CaptureBuffer)
{
- /*
- * In this case, check only the Process ID
- * and if there is a match, we succeed.
- */
+ /* In this case, succeed only if the caller is CSRSS */
if (NtCurrentTeb()->ClientId.UniqueProcess ==
ApiMessage->Header.ClientId.UniqueProcess)
{
}
else
{
- /* Make sure that there is still space left in the buffer */
+ /* Make sure that there is still space left in the capture buffer */
if ((CaptureBuffer->Size - (ULONG_PTR)*Buffer + (ULONG_PTR)CaptureBuffer) >=
(ElementCount * ElementSize))
{
while (PointerCount--)
{
/*
- * The pointer offset must be equal to the delta between
- * the addresses of the buffer and of the API message.
+ * Find in the array, the pointer offset (from the
+ * API message) that corresponds to the buffer.
*/
if (*OffsetPointer == BufferDistance)
{
}
/* Failure */
+#ifdef CSR_DBG
DPRINT1("CSRSRV: Bad message buffer %p\n", ApiMessage);
- DbgBreakPoint();
+ if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
return FALSE;
}
-/*** This is what we have in consrv/server.c ***
-
-/\* Ensure that a captured buffer is safe to access *\/
-BOOL FASTCALL
-Win32CsrValidateBuffer(PCSR_PROCESS ProcessData, PVOID Buffer,
- SIZE_T NumElements, SIZE_T ElementSize)
-{
- /\* Check that the following conditions are true:
- * 1. The start of the buffer is somewhere within the process's
- * shared memory section view.
- * 2. The remaining space in the view is at least as large as the buffer.
- * (NB: Please don't try to "optimize" this by using multiplication
- * instead of division; remember that 2147483648 * 2 = 0.)
- * 3. The buffer is DWORD-aligned.
- *\/
- ULONG_PTR Offset = (BYTE *)Buffer - (BYTE *)ProcessData->ClientViewBase;
- if (Offset >= ProcessData->ClientViewBounds
- || NumElements > (ProcessData->ClientViewBounds - Offset) / ElementSize
- || (Offset & (sizeof(DWORD) - 1)) != 0)
- {
- DPRINT1("Invalid buffer %p(%u*%u); section view is %p(%u)\n",
- Buffer, NumElements, ElementSize,
- ProcessData->ClientViewBase, ProcessData->ClientViewBounds);
- return FALSE;
- }
- return TRUE;
-}
-
-***********************************************/
-
/*++
* @name CsrValidateMessageString
* @implemented NT5.1
BOOLEAN
NTAPI
CsrValidateMessageString(IN PCSR_API_MESSAGE ApiMessage,
- IN LPWSTR *MessageString)
+ IN PWSTR *MessageString)
{
if (MessageString)
{