2015-06-09 13:22:25 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Spooler Router
|
2017-09-29 17:18:19 +00:00
|
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
2015-06-09 13:22:25 +00:00
|
|
|
* PURPOSE: Functions for allocating and freeing memory
|
2017-09-29 17:18:19 +00:00
|
|
|
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
|
2015-06-09 13:22:25 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
|
|
|
2017-04-13 16:48:40 +00:00
|
|
|
/**
|
|
|
|
* @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)
|
|
|
|
{
|
2017-04-16 10:36:16 +00:00
|
|
|
ASSERT(pcbBuffer);
|
|
|
|
|
2017-04-13 16:48:40 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2015-06-09 13:22:25 +00:00
|
|
|
/**
|
2015-07-07 17:06:48 +00:00
|
|
|
* @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.
|
|
|
|
*/
|
2015-06-09 13:22:25 +00:00
|
|
|
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)
|
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
ERR("HeapAlloc failed!\n");
|
2015-06-09 13:22:25 +00:00
|
|
|
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)
|
|
|
|
{
|
2020-08-04 02:07:58 +00:00
|
|
|
if ( !pMem ) return TRUE;
|
2015-06-09 13:22:25 +00:00
|
|
|
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)
|
|
|
|
{
|
2020-08-04 02:07:58 +00:00
|
|
|
if ( pwszString )
|
|
|
|
return HeapFree(hProcessHeap, 0, pwszString);
|
|
|
|
return FALSE;
|
2015-06-09 13:22:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @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)
|
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
ERR("DllAllocSplMem failed!\n");
|
2015-06-09 13:22:25 +00:00
|
|
|
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);
|
2017-04-13 16:48:40 +00:00
|
|
|
|
2015-06-09 13:22:25 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2017-04-13 16:48:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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.
|
2017-04-16 10:36:16 +00:00
|
|
|
* This parameter may be NULL if pSourceBuffer is NULL or cbBuffer is 0.
|
2017-04-13 16:48:40 +00:00
|
|
|
*
|
|
|
|
* @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)
|
|
|
|
{
|
2017-04-16 10:36:16 +00:00
|
|
|
// pDestinationBuffer is accessed unless pSourceBuffer equals pDestinationBuffer or cbBuffer is 0.
|
|
|
|
ASSERT(pDestinationBuffer || pSourceBuffer == pDestinationBuffer || cbBuffer == 0);
|
|
|
|
|
2017-04-13 16:48:40 +00:00
|
|
|
// 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;
|
|
|
|
}
|