[CSRSRV] CsrApiHandleConnectionRequest(): Remove ASSERT() redundant condition (#2858)
[reactos.git] / subsystems / win32 / csrsrv / api.c
index d013e15..6ff8694 100644 (file)
@@ -3,7 +3,7 @@
  * 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"
 
-//#define NDEBUG
+#include <ndk/kefuncs.h>
+
+#define NDEBUG
 #include <debug.h>
 
 /* GLOBALS ********************************************************************/
 
 BOOLEAN (*CsrClientThreadSetup)(VOID) = NULL;
 UNICODE_STRING CsrApiPortName;
-volatile LONG CsrpStaticThreadCount;
-volatile LONG CsrpDynamicThreadTotal;
+volatile ULONG CsrpStaticThreadCount;
+volatile ULONG CsrpDynamicThreadTotal;
 extern ULONG CsrMaxApiRequestThreads;
 
 /* FUNCTIONS ******************************************************************/
@@ -63,7 +65,7 @@ CsrCallServerFromServer(IN PCSR_API_MESSAGE ReceiveMsg,
     {
         /* 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
@@ -76,22 +78,28 @@ CsrCallServerFromServer(IN PCSR_API_MESSAGE ReceiveMsg,
             ((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
@@ -134,7 +142,7 @@ CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage)
     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;
@@ -148,47 +156,28 @@ CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage)
     /* 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 */
@@ -197,9 +186,10 @@ CsrApiHandleConnectionRequest(IN PCSR_API_MESSAGE ApiMessage)
     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,
@@ -269,7 +259,7 @@ CsrpCheckRequestThreads(VOID)
     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)
@@ -289,8 +279,8 @@ CsrpCheckRequestThreads(VOID)
             if (NT_SUCCESS(Status))
             {
                 /* Increase the thread counts */
-                _InterlockedIncrement(&CsrpStaticThreadCount);
-                _InterlockedIncrement(&CsrpDynamicThreadTotal);
+                InterlockedIncrementUL(&CsrpStaticThreadCount);
+                InterlockedIncrementUL(&CsrpDynamicThreadTotal);
 
                 /* Add a new server thread */
                 if (CsrAddStaticServerThread(hThread,
@@ -303,8 +293,8 @@ CsrpCheckRequestThreads(VOID)
                 else
                 {
                     /* Failed to create a new static thread */
-                    _InterlockedDecrement(&CsrpStaticThreadCount);
-                    _InterlockedDecrement(&CsrpDynamicThreadTotal);
+                    InterlockedDecrementUL(&CsrpStaticThreadCount);
+                    InterlockedDecrementUL(&CsrpDynamicThreadTotal);
 
                     /* Terminate it */
                     DPRINT1("Failing\n");
@@ -383,8 +373,8 @@ CsrApiRequestThread(IN PVOID Parameter)
         ASSERT(NT_SUCCESS(Status));
 
         /* Increase the Thread Counts */
-        _InterlockedIncrement(&CsrpStaticThreadCount);
-        _InterlockedIncrement(&CsrpDynamicThreadTotal);
+        InterlockedIncrementUL(&CsrpStaticThreadCount);
+        InterlockedIncrementUL(&CsrpDynamicThreadTotal);
     }
 
     /* Now start the loop */
@@ -393,6 +383,7 @@ CsrApiRequestThread(IN PVOID Parameter)
         /* Make sure the real CID is set */
         Teb->RealClientId = Teb->ClientId;
 
+#ifdef CSR_DBG
         /* Debug check */
         if (Teb->CountOfOwnedCriticalSections)
         {
@@ -402,6 +393,7 @@ CsrApiRequestThread(IN PVOID Parameter)
                     &ReceiveMsg, ReplyMsg);
             DbgBreakPoint();
         }
+#endif
 
         /* Wait for a message to come through */
         Status = NtReplyWaitReceivePort(ReplyPort,
@@ -415,15 +407,17 @@ CsrApiRequestThread(IN PVOID Parameter)
             /* 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;
@@ -432,12 +426,15 @@ CsrApiRequestThread(IN PVOID Parameter)
             }
             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;
 
@@ -513,7 +510,7 @@ CsrApiRequestThread(IN PVOID Parameter)
                 }
 
                 /* Increase the thread count */
-                _InterlockedIncrement(&CsrpStaticThreadCount);
+                InterlockedIncrementUL(&CsrpStaticThreadCount);
 
                 /* If the response was 0xFFFFFFFF, we'll ignore it */
                 if (HardErrorMsg->Response == 0xFFFFFFFF)
@@ -545,9 +542,11 @@ CsrApiRequestThread(IN PVOID Parameter)
                     (!(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;
@@ -570,6 +569,7 @@ CsrApiRequestThread(IN PVOID Parameter)
                     continue;
                 }
 
+#ifdef CSR_DBG
                 if (CsrDebug & 2)
                 {
                     DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
@@ -579,6 +579,7 @@ CsrApiRequestThread(IN PVOID Parameter)
                             ServerDll->NameTable[ApiId],
                             NULL);
                 }
+#endif
 
                 /* Assume success */
                 ReceiveMsg.Status = STATUS_SUCCESS;
@@ -595,7 +596,7 @@ CsrApiRequestThread(IN PVOID Parameter)
                     ServerDll->DispatchTable[ApiId](&ReceiveMsg, &ReplyCode);
 
                     /* Increase the static thread count */
-                    _InterlockedIncrement(&CsrpStaticThreadCount);
+                    InterlockedIncrementUL(&CsrpStaticThreadCount);
                 }
                 _SEH2_EXCEPT(CsrUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
                 {
@@ -625,6 +626,9 @@ CsrApiRequestThread(IN PVOID Parameter)
                 ClientDiedMsg = (PCLIENT_DIED_MSG)&ReceiveMsg;
                 if (ClientDiedMsg->CreateTime.QuadPart == CsrThread->CreateTime.QuadPart)
                 {
+                    /* Now we reply to the dying client */
+                    ReplyPort = CsrThread->Process->ClientPort;
+
                     /* Reference the thread */
                     CsrLockedReferenceThread(CsrThread);
 
@@ -703,7 +707,7 @@ CsrApiRequestThread(IN PVOID Parameter)
                 }
 
                 /* Increase the thread count */
-                _InterlockedIncrement(&CsrpStaticThreadCount);
+                InterlockedIncrementUL(&CsrpStaticThreadCount);
 
                 /* If the response was 0xFFFFFFFF, we'll ignore it */
                 if (HardErrorMsg->Response == 0xFFFFFFFF)
@@ -742,9 +746,11 @@ CsrApiRequestThread(IN PVOID Parameter)
             (!(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;
@@ -771,15 +777,19 @@ CsrApiRequestThread(IN PVOID Parameter)
             continue;
         }
 
+#ifdef CSR_DBG
         if (CsrDebug & 2)
         {
-            DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x\n",
+            DPRINT1("[%02x] CSRSS: [%02x,%02x] - %s Api called from %08x, Process %08x - %08x\n",
                     Teb->ClientId.UniqueThread,
                     ReceiveMsg.Header.ClientId.UniqueProcess,
                     ReceiveMsg.Header.ClientId.UniqueThread,
                     ServerDll->NameTable[ApiId],
-                    CsrThread);
+                    CsrThread,
+                    CsrThread->Process,
+                    CsrProcess);
         }
+#endif
 
         /* Assume success */
         ReplyMsg = &ReceiveMsg;
@@ -813,11 +823,11 @@ CsrApiRequestThread(IN PVOID Parameter)
             ReplyMsg->Status = ServerDll->DispatchTable[ApiId](&ReceiveMsg, &ReplyCode);
 
             /* Increase the static thread count */
-            _InterlockedIncrement(&CsrpStaticThreadCount);
+            InterlockedIncrementUL(&CsrpStaticThreadCount);
 
             Teb->CsrClientThread = CurrentThread;
 
-            if (ReplyCode == CsrReplyAlreadyDone)
+            if (ReplyCode == CsrReplyAlreadySent)
             {
                 if (ReceiveMsg.CsrCaptureData)
                 {
@@ -830,12 +840,14 @@ CsrApiRequestThread(IN PVOID Parameter)
             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)
@@ -874,8 +886,7 @@ CsrApiRequestThread(IN PVOID Parameter)
  *
  * @param None
  *
- * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
- *         otherwise.
+ * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
  *
  * @remarks None.
  *
@@ -909,7 +920,7 @@ CsrApiPortInitialize(VOID)
     {
         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 */
@@ -919,13 +930,13 @@ CsrApiPortInitialize(VOID)
                                &CsrApiPortName,
                                0,
                                NULL,
-                               NULL /* FIXME*/);
+                               NULL /* FIXME: Use the Security Descriptor */);
 
     /* Create the Port Object */
     Status = NtCreatePort(&CsrApiPort,
                           &ObjectAttributes,
-                          LPC_MAX_DATA_LENGTH, // HACK: the real value is: sizeof(CSR_CONNECTION_INFO),
-                          LPC_MAX_MESSAGE_LENGTH, // HACK: the real value is: sizeof(CSR_API_MESSAGE),
+                          sizeof(CSR_API_CONNECTINFO),
+                          sizeof(CSR_API_MESSAGE),
                           16 * PAGE_SIZE);
     if (NT_SUCCESS(Status))
     {
@@ -1005,7 +1016,6 @@ PCSR_THREAD
 NTAPI
 CsrConnectToUser(VOID)
 {
-#if 0 // This code is OK, however it is ClientThreadSetup which sucks.
     NTSTATUS Status;
     ANSI_STRING DllName;
     UNICODE_STRING TempName;
@@ -1046,8 +1056,9 @@ CsrConnectToUser(VOID)
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
         Connected = FALSE;
-    } _SEH2_END;
-    
+    }
+    _SEH2_END;
+
     if (!Connected)
     {
         DPRINT1("CSRSS: CsrConnectToUser failed\n");
@@ -1062,19 +1073,6 @@ CsrConnectToUser(VOID)
 
     /* 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
 }
 
 /*++
@@ -1094,7 +1092,6 @@ HANDLE
 NTAPI
 CsrQueryApiPort(VOID)
 {
-    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
     return CsrApiPort;
 }
 
@@ -1122,105 +1119,193 @@ NTAPI
 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 i;
+    ULONG Length;
+    ULONG PointerCount;
+    PULONG_PTR OffsetPointer;
+    ULONG_PTR CurrentOffset;
+
+    /* Get the buffer we got from whoever called NTDLL */
+    ClientCaptureBuffer = ApiMessage->CsrCaptureData;
 
-    /* Use SEH to make sure this is valid */
+    /* 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);
+        }
+
+        /* Capture the buffer length */
+        Length = ((volatile CSR_CAPTURE_BUFFER*)ClientCaptureBuffer)->Size;
 
-        /* Now check if the buffer is inside our mapped section */
-        if (((ULONG_PTR)LocalCaptureBuffer < CsrThread->Process->ClientViewBase) ||
-            (((ULONG_PTR)LocalCaptureBuffer + Length) >= CsrThread->Process->ClientViewBounds))
+        /*
+         * 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.
      */
-    for (i = 0 ; i < RemoteCaptureBuffer->PointerCount ; ++i)
+    // PointerCount  = ServerCaptureBuffer->PointerCount;
+    OffsetPointer = ServerCaptureBuffer->PointerOffsetsArray;
+    while (PointerCount--)
     {
-        if (RemoteCaptureBuffer->PointerOffsetsArray[i] != 0)
+        CurrentOffset = *OffsetPointer;
+
+        if (CurrentOffset != 0)
         {
-            /* Temporarily transform the offset into a pointer */
-            RemoteCaptureBuffer->PointerOffsetsArray[i] += (ULONG_PTR)ApiMessage;
+            /*
+             * 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)RemoteCaptureBuffer->PointerOffsetsArray[i] >= CsrThread->Process->ClientViewBase) &&
-                (*(PULONG_PTR)RemoteCaptureBuffer->PointerOffsetsArray[i] < 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)RemoteCaptureBuffer->PointerOffsetsArray[i] += BufferDistance;
+                *(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;
             }
-
-            /* Transform back into an offset */
-            RemoteCaptureBuffer->PointerOffsetsArray[i] -= (ULONG_PTR)ApiMessage;
         }
+
+        ++OffsetPointer;
     }
 
     /* 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 */
@@ -1247,54 +1332,71 @@ VOID
 NTAPI
 CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
 {
-    PCSR_CAPTURE_BUFFER RemoteCaptureBuffer, LocalCaptureBuffer;
+    PCSR_CAPTURE_BUFFER ServerCaptureBuffer, ClientCaptureBuffer;
     SIZE_T BufferDistance;
-    ULONG i;
+    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()).
      */
-    for (i = 0 ; i < RemoteCaptureBuffer->PointerCount ; ++i)
+    PointerCount  = ServerCaptureBuffer->PointerCount;
+    OffsetPointer = ServerCaptureBuffer->PointerOffsetsArray;
+    while (PointerCount--)
     {
-        if (RemoteCaptureBuffer->PointerOffsetsArray[i] != 0)
+        CurrentOffset = *OffsetPointer;
+
+        if (CurrentOffset != 0)
         {
-            /* Temporarily transform the offset into a pointer */
-            RemoteCaptureBuffer->PointerOffsetsArray[i] += (ULONG_PTR)ApiMessage;
+            /* Get the pointer corresponding to the offset */
+            CurrentOffset += (ULONG_PTR)ApiMessage;
 
             /* Modify the pointed pointer to take into account its new position */
-            *(PULONG_PTR)RemoteCaptureBuffer->PointerOffsetsArray[i] -= BufferDistance;
-
-            /* Transform back into an offset */
-            RemoteCaptureBuffer->PointerOffsetsArray[i] -= (ULONG_PTR)ApiMessage;
+            *(PULONG_PTR)CurrentOffset -= BufferDistance;
         }
+
+        ++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
@@ -1314,7 +1416,7 @@ CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
  * @param ElementSize
  *        Size of each element.
  *
- * @return TRUE if validation suceeded, FALSE otherwise.
+ * @return TRUE if validation succeeded, FALSE otherwise.
  *
  * @remarks None.
  *
@@ -1328,14 +1430,15 @@ CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage,
 {
     PCSR_CAPTURE_BUFFER CaptureBuffer = ApiMessage->CsrCaptureData;
     SIZE_T BufferDistance = (ULONG_PTR)Buffer - (ULONG_PTR)ApiMessage;
-    ULONG i;
+    ULONG PointerCount;
+    PULONG_PTR OffsetPointer;
 
     /*
      * Check whether we have a valid buffer pointer, elements
      * 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;
     }
@@ -1348,10 +1451,7 @@ CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage,
     /* 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)
         {
@@ -1360,60 +1460,36 @@ CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage,
     }
     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))
         {
-            for (i = 0 ; i < CaptureBuffer->PointerCount ; ++i)
+            /* Perform the validation test */
+            PointerCount  = CaptureBuffer->PointerCount;
+            OffsetPointer = CaptureBuffer->PointerOffsetsArray;
+            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 (CaptureBuffer->PointerOffsetsArray[i] == BufferDistance)
+                if (*OffsetPointer == BufferDistance)
                 {
                     return TRUE;
                 }
+                ++OffsetPointer;
             }
         }
     }
 
     /* 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
@@ -1427,7 +1503,7 @@ Win32CsrValidateBuffer(PCSR_PROCESS ProcessData, PVOID Buffer,
  * @param MessageString
  *        Pointer to the buffer containing the string to validate.
  *
- * @return TRUE if validation suceeded, FALSE otherwise.
+ * @return TRUE if validation succeeded, FALSE otherwise.
  *
  * @remarks None.
  *
@@ -1435,7 +1511,7 @@ Win32CsrValidateBuffer(PCSR_PROCESS ProcessData, PVOID Buffer,
 BOOLEAN
 NTAPI
 CsrValidateMessageString(IN PCSR_API_MESSAGE ApiMessage,
-                         IN LPWSTR *MessageString)
+                         IN PWSTR *MessageString)
 {
     if (MessageString)
     {