[CSRSRV] Only when CSRSRV is compiled in debugging mode, should we display debugging...
[reactos.git] / subsystems / win32 / csrsrv / api.c
index 9446400..9c86c58 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 ******************************************************************/
@@ -52,8 +54,7 @@ CsrCallServerFromServer(IN PCSR_API_MESSAGE ReceiveMsg,
     ULONG ServerId;
     PCSR_SERVER_DLL ServerDll;
     ULONG ApiId;
-    ULONG Reply;
-    NTSTATUS Status;
+    CSR_REPLY_CODE ReplyCode = CsrReplyImmediately;
 
     /* Get the Server ID */
     ServerId = CSR_API_NUMBER_TO_SERVER_ID(ReceiveMsg->ApiNumber);
@@ -64,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
@@ -77,32 +78,34 @@ 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
     {
-        /* Call the API and get the result */
-        /// CsrApiCallHandler(ReplyMsg, /*ProcessData*/ &ReplyCode); ///
-        Status = (ServerDll->DispatchTable[ApiId])(ReceiveMsg, &Reply);
-
-        /* Return the result, no matter what it is */
-        ReplyMsg->Status = Status;
+        /* Call the API, get the reply code and return the result */
+        ReplyMsg->Status = ServerDll->DispatchTable[ApiId](ReceiveMsg, &ReplyCode);
     }
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
@@ -139,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;
@@ -153,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);
-
-            /* Release the lock */
-            CsrReleaseProcessLock();
+            CsrLockedReferenceProcess(CsrProcess);
 
-            /* 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 */
@@ -202,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 || (AllowConnection && CsrProcess));
     Status = NtAcceptConnectPort(&ServerPort,
                                  AllowConnection ? UlongToPtr(CsrProcess->SequenceNumber) : 0,
                                  &ApiMessage->Header,
@@ -274,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)
@@ -294,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,
@@ -308,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");
@@ -350,6 +335,7 @@ CsrApiRequestThread(IN PVOID Parameter)
     LARGE_INTEGER TimeOut;
     PCSR_THREAD CurrentThread, CsrThread;
     NTSTATUS Status;
+    CSR_REPLY_CODE ReplyCode;
     PCSR_API_MESSAGE ReplyMsg;
     CSR_API_MESSAGE ReceiveMsg;
     PCSR_PROCESS CsrProcess;
@@ -358,7 +344,7 @@ CsrApiRequestThread(IN PVOID Parameter)
     PCSR_SERVER_DLL ServerDll;
     PCLIENT_DIED_MSG ClientDiedMsg;
     PDBGKM_MSG DebugMessage;
-    ULONG ServerId, ApiId, Reply, MessageType, i;
+    ULONG ServerId, ApiId, MessageType, i;
     HANDLE ReplyPort;
 
     /* Setup LPC loop port and message */
@@ -387,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 */
@@ -397,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)
         {
@@ -406,6 +393,7 @@ CsrApiRequestThread(IN PVOID Parameter)
                     &ReceiveMsg, ReplyMsg);
             DbgBreakPoint();
         }
+#endif
 
         /* Wait for a message to come through */
         Status = NtReplyWaitReceivePort(ReplyPort,
@@ -419,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;
@@ -436,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;
 
@@ -453,8 +446,9 @@ CsrApiRequestThread(IN PVOID Parameter)
         {
             /* Handle the Connection Request */
             CsrApiHandleConnectionRequest(&ReceiveMsg);
-            ReplyPort = CsrApiPort;
+
             ReplyMsg = NULL;
+            ReplyPort = CsrApiPort;
             continue;
         }
 
@@ -507,7 +501,7 @@ CsrApiRequestThread(IN PVOID Parameter)
                         if ((ServerDll) && (ServerDll->HardErrorCallback))
                         {
                             /* Call it */
-                            ServerDll->HardErrorCallback(NULL /* CsrThread == NULL */, HardErrorMsg);
+                            ServerDll->HardErrorCallback(NULL /* == CsrThread */, HardErrorMsg);
 
                             /* If it's handled, get out of here */
                             if (HardErrorMsg->Response != ResponseNotHandled) break;
@@ -516,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)
@@ -527,6 +521,7 @@ CsrApiRequestThread(IN PVOID Parameter)
                 else
                 {
                     ReplyMsg = &ReceiveMsg;
+                    ReplyPort = CsrApiPort;
                 }
             }
             else if (MessageType == LPC_REQUEST)
@@ -547,11 +542,14 @@ 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();
-                    ReplyPort = CsrApiPort;
+                    if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
+
                     ReplyMsg = NULL;
+                    ReplyPort = CsrApiPort;
                     continue;
                 }
 
@@ -565,11 +563,13 @@ CsrApiRequestThread(IN PVOID Parameter)
                     DPRINT1("CSRSS: %lx is invalid ApiTableIndex for %Z\n",
                             CSR_API_NUMBER_TO_API_ID(ReceiveMsg.ApiNumber),
                             &ServerDll->Name);
+
                     ReplyPort = CsrApiPort;
                     ReplyMsg = NULL;
                     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;
@@ -589,13 +590,13 @@ CsrApiRequestThread(IN PVOID Parameter)
                     /* Make sure we have enough threads */
                     CsrpCheckRequestThreads();
 
-                    /* Call the API and get the result */
+                    /* Call the API and get the reply code */
                     ReplyMsg = NULL;
                     ReplyPort = CsrApiPort;
-                    ServerDll->DispatchTable[ApiId](&ReceiveMsg, &Reply);
+                    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);
 
@@ -644,6 +648,7 @@ CsrApiRequestThread(IN PVOID Parameter)
 
                 /* Release the lock and keep looping */
                 CsrReleaseProcessLock();
+
                 ReplyMsg = NULL;
                 ReplyPort = CsrApiPort;
                 continue;
@@ -702,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)
@@ -741,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;
@@ -770,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;
@@ -807,36 +818,43 @@ CsrApiRequestThread(IN PVOID Parameter)
 
             Teb->CsrClientThread = CsrThread;
 
-            /* Call the API and get the result */
-            Reply = 0;
-            ServerDll->DispatchTable[ApiId](&ReceiveMsg, &Reply);
+            /* Call the API, get the reply code and return the result */
+            ReplyCode = CsrReplyImmediately;
+            ReplyMsg->Status = ServerDll->DispatchTable[ApiId](&ReceiveMsg, &ReplyCode);
 
             /* Increase the static thread count */
-            _InterlockedIncrement(&CsrpStaticThreadCount);
+            InterlockedIncrementUL(&CsrpStaticThreadCount);
 
             Teb->CsrClientThread = CurrentThread;
 
-            if (Reply == 3)
+            if (ReplyCode == CsrReplyAlreadySent)
             {
-                ReplyMsg = NULL;
                 if (ReceiveMsg.CsrCaptureData)
                 {
                     CsrReleaseCapturedArguments(&ReceiveMsg);
                 }
-                CsrDereferenceThread(CsrThread);
+                ReplyMsg = NULL;
                 ReplyPort = CsrApiPort;
+                CsrDereferenceThread(CsrThread);
             }
-            else if (Reply == 2)
+            else if (ReplyCode == CsrReplyDeadClient)
             {
-                NtReplyPort(ReplyPort, &ReplyMsg->Header);
-                ReplyPort = CsrApiPort;
+                /* Reply to the death message */
+                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 (Reply == 1)
+            else if (ReplyCode == CsrReplyPending)
             {
-                ReplyPort = CsrApiPort;
                 ReplyMsg = NULL;
+                ReplyPort = CsrApiPort;
             }
             else
             {
@@ -869,8 +887,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.
  *
@@ -904,7 +921,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 */
@@ -914,13 +931,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))
     {
@@ -1000,7 +1017,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;
@@ -1041,8 +1057,9 @@ CsrConnectToUser(VOID)
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
         Connected = FALSE;
-    } _SEH2_END;
-    
+    }
+    _SEH2_END;
+
     if (!Connected)
     {
         DPRINT1("CSRSS: CsrConnectToUser failed\n");
@@ -1057,19 +1074,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
 }
 
 /*++
@@ -1089,7 +1093,6 @@ HANDLE
 NTAPI
 CsrQueryApiPort(VOID)
 {
-    DPRINT("CSRSRV: %s called\n", __FUNCTION__);
     return CsrApiPort;
 }
 
@@ -1120,7 +1123,9 @@ CsrCaptureArguments(IN PCSR_THREAD CsrThread,
     PCSR_CAPTURE_BUFFER LocalCaptureBuffer = NULL, RemoteCaptureBuffer = NULL;
     SIZE_T BufferDistance;
     ULONG Length = 0;
-    ULONG i;
+    ULONG PointerCount;
+    PULONG_PTR OffsetPointer;
+    ULONG_PTR CurrentOffset;
 
     /* Use SEH to make sure this is valid */
     _SEH2_TRY
@@ -1142,11 +1147,13 @@ CsrCaptureArguments(IN PCSR_THREAD CsrThread,
         /* Check if the Length is valid */
         if ((FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray) +
                 (LocalCaptureBuffer->PointerCount * sizeof(PVOID)) > Length) ||
-            (Length > MAXWORD))
+            (LocalCaptureBuffer->PointerCount > MAXUSHORT))
         {
-            /* Return failure */
+#ifdef CSR_DBG
             DPRINT1("*** CSRSS: CaptureBuffer %p has bad length\n", LocalCaptureBuffer);
-            DbgBreakPoint();
+            if (NtCurrentPeb()->BeingDebugged) DbgBreakPoint();
+#endif
+            /* Return failure */
             ApiMessage->Status = STATUS_INVALID_PARAMETER;
             _SEH2_YIELD(return FALSE);
         }
@@ -1159,7 +1166,7 @@ CsrCaptureArguments(IN PCSR_THREAD CsrThread,
     } _SEH2_END;
 
     /* We validated the incoming buffer, now allocate the remote one */
-    RemoteCaptureBuffer = RtlAllocateHeap(CsrHeap, 0, Length);
+    RemoteCaptureBuffer = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, Length);
     if (!RemoteCaptureBuffer)
     {
         /* We're out of memory */
@@ -1174,42 +1181,51 @@ CsrCaptureArguments(IN PCSR_THREAD CsrThread,
     BufferDistance = (ULONG_PTR)RemoteCaptureBuffer - (ULONG_PTR)LocalCaptureBuffer;
 
     /*
-     * Convert all the pointer offsets into real pointers, and make
-     * them point to the remote data buffer instead of the local one.
+     * All the pointer offsets correspond to pointers which point
+     * to the remote data buffer instead of the local one.
      */
-    for (i = 0 ; i < RemoteCaptureBuffer->PointerCount ; ++i)
+    PointerCount  = RemoteCaptureBuffer->PointerCount;
+    OffsetPointer = RemoteCaptureBuffer->PointerOffsetsArray;
+    while (PointerCount--)
     {
-        if (RemoteCaptureBuffer->PointerOffsetsArray[i] != 0)
+        CurrentOffset = *OffsetPointer;
+
+        if (CurrentOffset != 0)
         {
-            RemoteCaptureBuffer->PointerOffsetsArray[i] += (ULONG_PTR)ApiMessage;
+            /* Get the pointer corresponding to the offset */
+            CurrentOffset += (ULONG_PTR)ApiMessage;
 
-            /* Validate the bounds of the current pointer */
-            if ((*(PULONG_PTR)RemoteCaptureBuffer->PointerOffsetsArray[i] >= CsrThread->Process->ClientViewBase) &&
-                (*(PULONG_PTR)RemoteCaptureBuffer->PointerOffsetsArray[i] < CsrThread->Process->ClientViewBounds))
+            /* Validate the bounds of the current pointed pointer */
+            if ((*(PULONG_PTR)CurrentOffset >= CsrThread->Process->ClientViewBase) &&
+                (*(PULONG_PTR)CurrentOffset < CsrThread->Process->ClientViewBounds))
             {
-                /* Modify the pointer to take into account its new position */
-                *(PULONG_PTR)RemoteCaptureBuffer->PointerOffsetsArray[i] += BufferDistance;
+                /* 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;
             }
         }
+
+        ++OffsetPointer;
     }
 
     /* Check if we got success */
     if (ApiMessage->Status != STATUS_SUCCESS)
     {
-        /* Failure. Free the buffer and return*/
+        /* Failure. Free the buffer and return */
         RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
         return FALSE;
     }
     else
     {
-        /* Success, save the previous buffer */
+        /* Success, save the previous buffer and use the remote capture buffer */
         RemoteCaptureBuffer->PreviousCaptureBuffer = LocalCaptureBuffer;
         ApiMessage->CsrCaptureData = RemoteCaptureBuffer;
     }
@@ -1240,33 +1256,47 @@ CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
 {
     PCSR_CAPTURE_BUFFER RemoteCaptureBuffer, LocalCaptureBuffer;
     SIZE_T BufferDistance;
-    ULONG i;
+    ULONG PointerCount;
+    PULONG_PTR OffsetPointer;
+    ULONG_PTR CurrentOffset;
 
-    /* Get the capture buffers */
+    /* Get the remote capture buffer */
     RemoteCaptureBuffer = ApiMessage->CsrCaptureData;
-    LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer;
 
     /* Do not continue if there is no captured buffer */
     if (!RemoteCaptureBuffer) return;
 
-    /* Free the previous one */
+    /* If there is one, get the corresponding local capture buffer */
+    LocalCaptureBuffer = RemoteCaptureBuffer->PreviousCaptureBuffer;
+
+    /* Free the previous one and use again the local capture buffer */
     RemoteCaptureBuffer->PreviousCaptureBuffer = NULL;
+    ApiMessage->CsrCaptureData = LocalCaptureBuffer;
 
     /* Calculate the difference between our buffer and the client's */
     BufferDistance = (ULONG_PTR)RemoteCaptureBuffer - (ULONG_PTR)LocalCaptureBuffer;
 
     /*
-     * Convert back all the pointers into pointer offsets, and make them
-     * point to the local data buffer instead of the remote one (revert
+     * All the pointer offsets correspond to pointers which point
+     * to the local data buffer instead of the remote one (revert
      * the logic of CsrCaptureArguments).
      */
-    for (i = 0 ; i < RemoteCaptureBuffer->PointerCount ; ++i)
+    PointerCount  = RemoteCaptureBuffer->PointerCount;
+    OffsetPointer = RemoteCaptureBuffer->PointerOffsetsArray;
+    while (PointerCount--)
     {
-        if (RemoteCaptureBuffer->PointerOffsetsArray[i] != 0)
+        CurrentOffset = *OffsetPointer;
+
+        if (CurrentOffset != 0)
         {
-            *(PULONG_PTR)RemoteCaptureBuffer->PointerOffsetsArray[i] -= BufferDistance;
-            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)CurrentOffset -= BufferDistance;
         }
+
+        ++OffsetPointer;
     }
 
     /* Copy the data back */
@@ -1276,7 +1306,6 @@ CsrReleaseCapturedArguments(IN PCSR_API_MESSAGE ApiMessage)
     RtlFreeHeap(CsrHeap, 0, RemoteCaptureBuffer);
 }
 
-
 /*++
  * @name CsrValidateMessageBuffer
  * @implemented NT5.1
@@ -1296,7 +1325,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.
  *
@@ -1309,8 +1338,9 @@ CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage,
                          IN ULONG ElementSize)
 {
     PCSR_CAPTURE_BUFFER CaptureBuffer = ApiMessage->CsrCaptureData;
-    // SIZE_T BufferDistance = (ULONG_PTR)Buffer - (ULONG_PTR)ApiMessage;
-    ULONG i;
+    SIZE_T BufferDistance = (ULONG_PTR)Buffer - (ULONG_PTR)ApiMessage;
+    ULONG PointerCount;
+    PULONG_PTR OffsetPointer;
 
     /*
      * Check whether we have a valid buffer pointer, elements
@@ -1346,56 +1376,32 @@ CsrValidateMessageBuffer(IN PCSR_API_MESSAGE ApiMessage,
         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--)
             {
                 /*
-                 * If the pointer offset is in fact equal to the
-                 * real address of the buffer then it's OK.
+                 * The pointer offset must be equal to the delta between
+                 * the addresses of the buffer and of the API message.
                  */
-                if (CaptureBuffer->PointerOffsetsArray[i] == (ULONG_PTR)Buffer /* BufferDistance + (ULONG_PTR)ApiMessage */)
+                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
@@ -1409,7 +1415,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.
  *
@@ -1417,7 +1423,7 @@ Win32CsrValidateBuffer(PCSR_PROCESS ProcessData, PVOID Buffer,
 BOOLEAN
 NTAPI
 CsrValidateMessageString(IN PCSR_API_MESSAGE ApiMessage,
-                         IN LPWSTR *MessageString)
+                         IN PWSTR *MessageString)
 {
     if (MessageString)
     {