mirror of
https://github.com/reactos/reactos.git
synced 2024-11-01 12:26:32 +00:00
7bffb70353
WinSpool : Implement missing API. Sync/Port from wine. Setting it to fast track for needed testing of the later GDI code. Leaving Fix-me debug prints on. Local tree has WinSpool_winetest turned on. So no debug noise during normal ReactOS operation. SpoolSS : Reordered header types. Have more Spl function to be added while SpoolSV is being coded to forward to LocalSpl. Based on wine and old research from the GDI code.
260 lines
7.4 KiB
C
260 lines
7.4 KiB
C
/*
|
|
* PROJECT: ReactOS Spooler Router
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: Functions for allocating and freeing memory
|
|
* 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)
|
|
{
|
|
ASSERT(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
|
|
*
|
|
* Allocates memory for a Unicode string and copies the input string into it.
|
|
* Equivalent of wcsdup, but the returned buffer is allocated from the spooler heap and must be freed with DllFreeSplStr.
|
|
*
|
|
* @param pwszInput
|
|
* The input string to copy
|
|
*
|
|
* @return
|
|
* Pointer to the copied string or NULL if no memory could be allocated.
|
|
*/
|
|
PWSTR WINAPI
|
|
AllocSplStr(PCWSTR pwszInput)
|
|
{
|
|
DWORD cbInput;
|
|
PWSTR pwszOutput;
|
|
|
|
// Sanity check
|
|
if (!pwszInput)
|
|
return NULL;
|
|
|
|
// Get the length of the input string.
|
|
cbInput = (wcslen(pwszInput) + 1) * sizeof(WCHAR);
|
|
|
|
// Allocate it. We don't use DllAllocSplMem here, because it unnecessarily zeroes the memory.
|
|
pwszOutput = HeapAlloc(hProcessHeap, 0, cbInput);
|
|
if (!pwszOutput)
|
|
{
|
|
ERR("HeapAlloc failed!\n");
|
|
return NULL;
|
|
}
|
|
|
|
// Copy the string and return it.
|
|
CopyMemory(pwszOutput, pwszInput, cbInput);
|
|
return pwszOutput;
|
|
}
|
|
|
|
/**
|
|
* @name DllAllocSplMem
|
|
*
|
|
* Allocate a block of zeroed memory.
|
|
* Windows allocates from a separate spooler heap here while we just use the process heap.
|
|
*
|
|
* @param dwBytes
|
|
* Number of bytes to allocate.
|
|
*
|
|
* @return
|
|
* A pointer to the allocated memory or NULL in case of an error.
|
|
* You have to free this memory using DllFreeSplMem.
|
|
*/
|
|
PVOID WINAPI
|
|
DllAllocSplMem(DWORD dwBytes)
|
|
{
|
|
return HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, dwBytes);
|
|
}
|
|
|
|
/**
|
|
* @name DllFreeSplMem
|
|
*
|
|
* Frees the memory allocated with DllAllocSplMem.
|
|
*
|
|
* @param pMem
|
|
* Pointer to the allocated memory.
|
|
*
|
|
* @return
|
|
* TRUE in case of success, FALSE otherwise.
|
|
*/
|
|
BOOL WINAPI
|
|
DllFreeSplMem(PVOID pMem)
|
|
{
|
|
if ( !pMem ) return TRUE;
|
|
return HeapFree(hProcessHeap, 0, pMem);
|
|
}
|
|
|
|
/**
|
|
* @name DllFreeSplStr
|
|
*
|
|
* Frees the string allocated with AllocSplStr.
|
|
*
|
|
* @param pwszString
|
|
* Pointer to the allocated string.
|
|
*
|
|
* @return
|
|
* TRUE in case of success, FALSE otherwise.
|
|
*/
|
|
BOOL WINAPI
|
|
DllFreeSplStr(PWSTR pwszString)
|
|
{
|
|
if ( pwszString )
|
|
return HeapFree(hProcessHeap, 0, pwszString);
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
* @name ReallocSplMem
|
|
*
|
|
* Allocates a new block of memory and copies the contents of the old block into the new one.
|
|
*
|
|
* @param pOldMem
|
|
* Pointer to the old block of memory.
|
|
* If this parameter is NULL, ReallocSplMem behaves exactly like DllAllocSplMem.
|
|
*
|
|
* @param cbOld
|
|
* Number of bytes to copy from the old block into the new one.
|
|
*
|
|
* @param cbNew
|
|
* Number of bytes to allocate for the new block.
|
|
*
|
|
* @return
|
|
* A pointer to the allocated new block or NULL in case of an error.
|
|
* You have to free this memory using DllFreeSplMem.
|
|
*/
|
|
PVOID WINAPI
|
|
ReallocSplMem(PVOID pOldMem, DWORD cbOld, DWORD cbNew)
|
|
{
|
|
PVOID pNewMem;
|
|
|
|
// Always allocate the new block of memory.
|
|
pNewMem = DllAllocSplMem(cbNew);
|
|
if (!pNewMem)
|
|
{
|
|
ERR("DllAllocSplMem failed!\n");
|
|
return NULL;
|
|
}
|
|
|
|
// Copy the old memory into the new block and free it.
|
|
if (pOldMem)
|
|
{
|
|
CopyMemory(pNewMem, pOldMem, min(cbOld, cbNew));
|
|
DllFreeSplMem(pOldMem);
|
|
}
|
|
|
|
return pNewMem;
|
|
}
|
|
|
|
/**
|
|
* @name ReallocSplStr
|
|
*
|
|
* Frees a string allocated by AllocSplStr and copies the given Unicode string into a newly allocated block of memory.
|
|
*
|
|
* @param ppwszString
|
|
* Pointer to the string pointer allocated by AllocSplStr.
|
|
* When the function returns, the variable receives the pointer to the copied string.
|
|
*
|
|
* @param pwszInput
|
|
* The Unicode string to copy into the new block of memory.
|
|
*
|
|
* @return
|
|
* Returns TRUE in any case.
|
|
*/
|
|
BOOL WINAPI
|
|
ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput)
|
|
{
|
|
if (*ppwszString)
|
|
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 or cbBuffer is 0.
|
|
*
|
|
* @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)
|
|
{
|
|
// pDestinationBuffer is accessed unless pSourceBuffer equals pDestinationBuffer or cbBuffer is 0.
|
|
ASSERT(pDestinationBuffer || pSourceBuffer == pDestinationBuffer || cbBuffer == 0);
|
|
|
|
// 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;
|
|
}
|