[KERNEL32][BEEP]
[reactos.git] / reactos / dll / ntdll / csr / capture.c
index 3418123..1f1e695 100644 (file)
@@ -1,21 +1,24 @@
 /*
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
- * FILE:            lib/ntdll/csr/capture.c
+ * FILE:            dll/ntdll/csr/capture.c
  * PURPOSE:         Routines for probing and capturing CSR API Messages
- * PROGRAMMER:      Alex Ionescu (alex@relsoft.net)
+ * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ *                  Hermes Belusca-Maito (hermes.belusca@sfr.fr)
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES *******************************************************************/
 
 #include <ntdll.h>
+
 #define NDEBUG
 #include <debug.h>
 
-/* GLOBALS *******************************************************************/
+/* GLOBALS ********************************************************************/
+
 extern HANDLE CsrPortHeap;
 
-/* FUNCTIONS *****************************************************************/
+/* FUNCTIONS ******************************************************************/
 
 /*
  * @implemented
@@ -26,7 +29,7 @@ CsrProbeForRead(IN PVOID Address,
                 IN ULONG Length,
                 IN ULONG Alignment)
 {
-    PUCHAR Pointer;
+    volatile UCHAR *Pointer;
     UCHAR Data;
 
     /* Validate length */
@@ -39,11 +42,14 @@ CsrProbeForRead(IN PVOID Address,
         RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
     }
 
-    /* Do the probe */
-    Pointer = (PUCHAR)Address;
+    /* Probe first byte */
+    Pointer = Address;
     Data = *Pointer;
-    Pointer = (PUCHAR)((ULONG)Address + Length -1);
+
+    /* Probe last byte */
+    Pointer = (PUCHAR)Address + Length - 1;
     Data = *Pointer;
+    (void)Data;
 }
 
 /*
@@ -55,8 +61,7 @@ CsrProbeForWrite(IN PVOID Address,
                  IN ULONG Length,
                  IN ULONG Alignment)
 {
-    PUCHAR Pointer;
-    UCHAR Data;
+    volatile UCHAR *Pointer;
 
     /* Validate length */
     if (Length == 0) return;
@@ -68,46 +73,53 @@ CsrProbeForWrite(IN PVOID Address,
         RtlRaiseStatus(STATUS_DATATYPE_MISALIGNMENT);
     }
 
-    /* Do the probe */
-    Pointer = (PUCHAR)Address;
-    Data = *Pointer;
-    *Pointer = Data;
-    Pointer = (PUCHAR)((ULONG)Address + Length -1);
-    Data = *Pointer;
-    *Pointer = Data;
+    /* Probe first byte */
+    Pointer = Address;
+    *Pointer = *Pointer;
+
+    /* Probe last byte */
+    Pointer = (PUCHAR)Address + Length - 1;
+    *Pointer = *Pointer;
 }
 
 /*
  * @implemented
  */
-PVOID
+PCSR_CAPTURE_BUFFER
 NTAPI
-CsrAllocateCaptureBuffer(ULONG ArgumentCount,
-                         ULONG BufferSize)
+CsrAllocateCaptureBuffer(IN ULONG ArgumentCount,
+                         IN ULONG BufferSize)
 {
     PCSR_CAPTURE_BUFFER CaptureBuffer;
 
     /* Validate size */
     if (BufferSize >= MAXLONG) return NULL;
 
-    /* Add the size of the header and for each pointer to the pointers */
-    BufferSize += sizeof(CSR_CAPTURE_BUFFER) + (ArgumentCount * sizeof(PVOID));
+    /* Add the size of the header and for each offset to the pointers */
+    BufferSize += FIELD_OFFSET(CSR_CAPTURE_BUFFER, PointerOffsetsArray) +
+                    (ArgumentCount * sizeof(ULONG_PTR));
+
+    /* Align it to a 4-byte boundary */
+    BufferSize = (BufferSize + 3) & ~3;
+
+    /* Add the size of the alignment padding for each argument */
+    BufferSize += ArgumentCount * 3;
 
     /* Allocate memory from the port heap */
-    CaptureBuffer = RtlAllocateHeap(CsrPortHeap, 0, BufferSize);
+    CaptureBuffer = RtlAllocateHeap(CsrPortHeap, HEAP_ZERO_MEMORY, BufferSize);
     if (CaptureBuffer == NULL) return NULL;
 
     /* Initialize the header */
     CaptureBuffer->Size = BufferSize;
     CaptureBuffer->PointerCount = 0;
 
-    /* Initialize all the pointers */
-    RtlZeroMemory(CaptureBuffer->PointerArray,
+    /* Initialize all the offsets */
+    RtlZeroMemory(CaptureBuffer->PointerOffsetsArray,
                   ArgumentCount * sizeof(ULONG_PTR));
 
-    /* Point the start of the free buffer */
-    CaptureBuffer->BufferEnd = (ULONG_PTR)CaptureBuffer->PointerArray +
-                               ArgumentCount * sizeof(ULONG_PTR);
+    /* Point to the start of the free buffer */
+    CaptureBuffer->BufferEnd = (PVOID)((ULONG_PTR)CaptureBuffer->PointerOffsetsArray +
+                                       ArgumentCount * sizeof(ULONG_PTR));
 
     /* Return the address of the buffer */
     return CaptureBuffer;
@@ -118,20 +130,19 @@ CsrAllocateCaptureBuffer(ULONG ArgumentCount,
  */
 ULONG
 NTAPI
-CsrAllocateMessagePointer(PCSR_CAPTURE_BUFFER CaptureBuffer,
-                          ULONG MessageLength,
-                          PVOID *CaptureData)
+CsrAllocateMessagePointer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
+                          IN ULONG MessageLength,
+                          OUT PVOID* CapturedData)
 {
-    /* If there's no data, our job is easy. */
     if (MessageLength == 0)
     {
-        *CaptureData = NULL;
-        CaptureData = NULL;
+        *CapturedData = NULL;
+        CapturedData = NULL;
     }
     else
     {
         /* Set the capture data at our current available buffer */
-        *CaptureData = (PVOID)CaptureBuffer->BufferEnd;
+        *CapturedData = CaptureBuffer->BufferEnd;
 
         /* Validate the size */
         if (MessageLength >= MAXLONG) return 0;
@@ -140,14 +151,11 @@ CsrAllocateMessagePointer(PCSR_CAPTURE_BUFFER CaptureBuffer,
         MessageLength = (MessageLength + 3) & ~3;
 
         /* Move our available buffer beyond this space */
-        CaptureBuffer->BufferEnd += MessageLength;
+        CaptureBuffer->BufferEnd = (PVOID)((ULONG_PTR)CaptureBuffer->BufferEnd + MessageLength);
     }
 
-    /* Write down this pointer in the array */
-    CaptureBuffer->PointerArray[CaptureBuffer->PointerCount] = (ULONG_PTR)CaptureData;
-
-    /* Increase the pointer count */
-    CaptureBuffer->PointerCount++;
+    /* Write down this pointer in the array and increase the count */
+    CaptureBuffer->PointerOffsetsArray[CaptureBuffer->PointerCount++] = (ULONG_PTR)CapturedData;
 
     /* Return the aligned length */
     return MessageLength;
@@ -158,19 +166,19 @@ CsrAllocateMessagePointer(PCSR_CAPTURE_BUFFER CaptureBuffer,
  */
 VOID
 NTAPI
-CsrCaptureMessageBuffer(PCSR_CAPTURE_BUFFER CaptureBuffer,
-                        PVOID MessageString,
-                        ULONG StringLength,
-                        PVOID *CapturedData)
+CsrCaptureMessageBuffer(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
+                        IN PVOID MessageBuffer OPTIONAL,
+                        IN ULONG MessageLength,
+                        OUT PVOID* CapturedData)
 {
     /* Simply allocate a message pointer in the buffer */
-    CsrAllocateMessagePointer(CaptureBuffer, StringLength, CapturedData);
+    CsrAllocateMessagePointer(CaptureBuffer, MessageLength, CapturedData);
 
     /* Check if there was any data */
-    if (!MessageString || !StringLength) return;
+    if (!MessageBuffer || !MessageLength) return;
 
     /* Copy the data into the buffer */
-    RtlMoveMemory(*CapturedData, MessageString, StringLength);
+    RtlMoveMemory(*CapturedData, MessageBuffer, MessageLength);
 }
 
 /*
@@ -178,75 +186,127 @@ CsrCaptureMessageBuffer(PCSR_CAPTURE_BUFFER CaptureBuffer,
  */
 VOID
 NTAPI
-CsrFreeCaptureBuffer(PCSR_CAPTURE_BUFFER CaptureBuffer)
+CsrFreeCaptureBuffer(IN PCSR_CAPTURE_BUFFER CaptureBuffer)
 {
     /* Free it from the heap */
     RtlFreeHeap(CsrPortHeap, 0, CaptureBuffer);
 }
 
-/*
- * @implemented
- */
-NTSTATUS
-NTAPI
-CsrCaptureMessageMultiUnicodeStringsInPlace(IN PCSR_CAPTURE_BUFFER *CaptureBuffer,
-                                            IN ULONG MessageCount,
-                                            IN PVOID MessageStrings)
-{
-    /* FIXME: allocate a buffer if we don't have one, and return it */
-    /* FIXME: call CsrCaptureMessageUnicodeStringInPlace for each string */
-    UNIMPLEMENTED;
-    return STATUS_NOT_IMPLEMENTED;
-}
-
 /*
  * @implemented
  */
 VOID
 NTAPI
-CsrCaptureMessageString(PCSR_CAPTURE_BUFFER CaptureBuffer,
-                        LPSTR String,
+CsrCaptureMessageString(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
+                        IN PCSTR String OPTIONAL,
                         IN ULONG StringLength,
                         IN ULONG MaximumLength,
-                        OUT PANSI_STRING CapturedString)
+                        OUT PSTRING CapturedString)
 {
-    ULONG ReturnedLength;
+    ASSERT(CapturedString != NULL);
 
-    /* If we don't have a string, initialize an empty one */
+    /*
+     * If we don't have a string, initialize an empty one,
+     * otherwise capture the given string.
+     */
     if (!String)
     {
         CapturedString->Length = 0;
-        CapturedString->MaximumLength = MaximumLength;
+        CapturedString->MaximumLength = (USHORT)MaximumLength;
 
         /* Allocate a pointer for it */
         CsrAllocateMessagePointer(CaptureBuffer,
                                   MaximumLength,
                                   (PVOID*)&CapturedString->Buffer);
-        return;
+    }
+    else
+    {
+        /* Cut-off the string length if needed */
+        if (StringLength > MaximumLength)
+            StringLength = MaximumLength;
+
+        CapturedString->Length = (USHORT)StringLength;
+
+        /* Allocate a buffer and get its size */
+        CapturedString->MaximumLength =
+            (USHORT)CsrAllocateMessagePointer(CaptureBuffer,
+                                              MaximumLength,
+                                              (PVOID*)&CapturedString->Buffer);
+
+        /* If the string has data, copy it into the buffer */
+        if (StringLength)
+            RtlMoveMemory(CapturedString->Buffer, String, StringLength);
     }
 
-    /* Initialize this string */
-    CapturedString->Length = StringLength;
-    
-    /* Allocate a buffer and get its size */
-    ReturnedLength = CsrAllocateMessagePointer(CaptureBuffer,
-                                               MaximumLength,
-                                               (PVOID*)&CapturedString->Buffer);
-    CapturedString->MaximumLength = ReturnedLength;
-
-    /* If the string had data */
-    if (StringLength)
+    /* Null-terminate the string if we don't take up the whole space */
+    if (CapturedString->Length < CapturedString->MaximumLength)
+        CapturedString->Buffer[CapturedString->Length] = '\0';
+}
+
+static VOID
+CsrCaptureMessageUnicodeStringInPlace(IN OUT PCSR_CAPTURE_BUFFER CaptureBuffer,
+                                      IN PUNICODE_STRING String)
+{
+    ASSERT(String != NULL);
+
+    /* This is a way to capture the UNICODE string, since (Maximum)Length are also in bytes */
+    CsrCaptureMessageString(CaptureBuffer,
+                            (PCSTR)String->Buffer,
+                            String->Length,
+                            String->MaximumLength,
+                            (PSTRING)String);
+
+    /* Null-terminate the string */
+    if (String->MaximumLength >= String->Length + sizeof(WCHAR))
+    {
+        String->Buffer[String->Length / sizeof(WCHAR)] = L'\0';
+    }
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+CsrCaptureMessageMultiUnicodeStringsInPlace(OUT PCSR_CAPTURE_BUFFER* CaptureBuffer,
+                                            IN ULONG StringsCount,
+                                            IN PUNICODE_STRING* MessageStrings)
+{
+    ULONG Count;
+
+    if (!CaptureBuffer) return STATUS_INVALID_PARAMETER;
+
+    /* Allocate a new capture buffer if we don't have one already */
+    if (!*CaptureBuffer)
     {
-        /* Copy it into the capture buffer */
-        RtlMoveMemory(CapturedString->Buffer, String, MaximumLength);
+        /* Compute the required size for the capture buffer */
+        ULONG Size = 0;
 
-        /* If we don't take up the whole space */
-        if (CapturedString->Length < CapturedString->MaximumLength)
+        Count = 0;
+        while (Count < StringsCount)
         {
-            /* Null-terminate it */
-            CapturedString->Buffer[CapturedString->Length] = '\0';
+            if (MessageStrings[Count])
+                Size += MessageStrings[Count]->MaximumLength;
+
+            ++Count;
         }
+
+        /* Allocate the capture buffer */
+        *CaptureBuffer = CsrAllocateCaptureBuffer(StringsCount, Size);
+        if (!*CaptureBuffer) return STATUS_NO_MEMORY;
+    }
+
+    /* Now capture each UNICODE string */
+    Count = 0;
+    while (Count < StringsCount)
+    {
+        if (MessageStrings[Count])
+            CsrCaptureMessageUnicodeStringInPlace(*CaptureBuffer, MessageStrings[Count]);
+
+        ++Count;
     }
+
+    return STATUS_SUCCESS;
 }
 
 /*
@@ -254,14 +314,14 @@ CsrCaptureMessageString(PCSR_CAPTURE_BUFFER CaptureBuffer,
  */
 PLARGE_INTEGER
 NTAPI
-CsrCaptureTimeout(LONG Milliseconds,
-                  PLARGE_INTEGER Timeout)
+CsrCaptureTimeout(IN ULONG Milliseconds,
+                  OUT PLARGE_INTEGER Timeout)
 {
     /* Validate the time */
     if (Milliseconds == -1) return NULL;
 
     /* Convert to relative ticks */
-    Timeout->QuadPart = Milliseconds * -100000;
+    Timeout->QuadPart = Milliseconds * -10000LL;
     return Timeout;
 }