[SPOOLSS]
[reactos.git] / reactos / win32ss / printing / base / spoolss / memory.c
index 96a7fd1..07be553 100644 (file)
@@ -2,12 +2,42 @@
  * PROJECT:     ReactOS Spooler Router
  * LICENSE:     GNU LGPL v2.1 or any later version as published by the Free Software Foundation
  * PURPOSE:     Functions for allocating and freeing memory
- * COPYRIGHT:   Copyright 2015 Colin Finck <colin@reactos.org>
+ * COPYRIGHT:   Copyright 2015-2017 Colin Finck <colin@reactos.org>
  */
 
 #include "precomp.h"
 
 
+/**
+ * @name AlignRpcPtr
+ *
+ * Checks if the input buffer and buffer size are 4-byte aligned.
+ * If the buffer size is not 4-byte aligned, it is aligned down.
+ * If the input buffer is not 4-byte aligned, a 4-byte aligned buffer of the aligned down buffer size is allocated and returned.
+ *
+ * @param pBuffer
+ * The buffer to check.
+ *
+ * @param pcbBuffer
+ * Pointer to the buffer size to check. Its value is aligned down if needed.
+ *
+ * @return
+ * pBuffer if pBuffer is already 4-byte aligned, or a newly allocated 4-byte aligned buffer of the aligned down buffer size otherwise.
+ * If a buffer was allocated, you have to free it using UndoAlignRpcPtr.
+ */
+PVOID WINAPI
+AlignRpcPtr(PVOID pBuffer, PDWORD pcbBuffer)
+{
+    // Align down the buffer size in pcbBuffer to a 4-byte boundary.
+    *pcbBuffer -= *pcbBuffer % sizeof(DWORD);
+
+    // Check if pBuffer is 4-byte aligned. If not, allocate a 4-byte aligned buffer.
+    if ((ULONG_PTR)pBuffer % sizeof(DWORD))
+        pBuffer = DllAllocSplMem(*pcbBuffer);
+
+    return pBuffer;
+}
+
 /**
  * @name AllocSplStr
  *
@@ -163,6 +193,59 @@ ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput)
         DllFreeSplStr(*ppwszString);
 
     *ppwszString = AllocSplStr(pwszInput);
-    
+
     return TRUE;
 }
+
+/**
+ * @name UndoAlignRpcPtr
+ *
+ * Copies the data from the aligned buffer previously allocated by AlignRpcPtr back to the original unaligned buffer.
+ * The aligned buffer is freed.
+ *
+ * Also aligns up the returned required buffer size of a function to a 4-byte boundary.
+ *
+ * @param pDestinationBuffer
+ * The original unaligned buffer, which you input as pBuffer to AlignRpcPtr.
+ * The data from pSourceBuffer is copied into this buffer before pSourceBuffer is freed.
+ * If AlignRpcPtr did not allocate a buffer, pDestinationBuffer equals pSourceBuffer and no memory is copied or freed.
+ * This parameter may be NULL if pSourceBuffer is NULL.
+ *
+ * @param pSourceBuffer
+ * The aligned buffer, which is returned by AlignRpcPtr.
+ * Its data is copied into pDestinationBuffer and then pSourceBuffer is freed.
+ * If AlignRpcPtr did not allocate a buffer, pDestinationBuffer equals pSourceBuffer and no memory is copied or freed.
+ * This parameter may be NULL.
+ *
+ * @param cbBuffer
+ * Number of bytes to copy.
+ * Set this to the size returned by AlignRpcPtr's pcbBuffer or less.
+ *
+ * @param pcbNeeded
+ * Let this parameter point to your variable calculating the needed bytes for a buffer and returning this value to the user.
+ * It is then aligned up to a 4-byte boundary, so that the user supplies a large enough buffer in the next call.
+ * Otherwise, AlignRpcPtr would align down the buffer size in the next call and your buffer would be smaller than intended.
+ * This parameter may be NULL.
+ *
+ * @return
+ * pcbNeeded
+ */
+PDWORD WINAPI
+UndoAlignRpcPtr(PVOID pDestinationBuffer, PVOID pSourceBuffer, DWORD cbBuffer, PDWORD pcbNeeded)
+{
+    // If pSourceBuffer is given, and source and destination pointers don't match,
+    // we assume that pSourceBuffer is the buffer allocated by AlignRpcPtr.
+    if (pSourceBuffer && pSourceBuffer != pDestinationBuffer)
+    {
+        // Copy back the buffer data to the (usually unaligned) destination buffer
+        // and free the buffer allocated by AlignRpcPtr.
+        CopyMemory(pDestinationBuffer, pSourceBuffer, cbBuffer);
+        DllFreeSplMem(pSourceBuffer);
+    }
+
+    // If pcbNeeded is given, align it up to a 4-byte boundary.
+    if (pcbNeeded && *pcbNeeded % sizeof(DWORD))
+        *pcbNeeded += sizeof(DWORD) - *pcbNeeded % sizeof(DWORD);
+
+    return pcbNeeded;
+}