[SPOOLSS]

Implement the undocumented AlignRpcPtr and UndoAlignRpcPtr functions used by many Rpc* functions in spoolsv according to traced callchains.
I could reverse engineer them entirely using rohitab.com's API Monitor and black-box testing.
I also add documented tests covering all cases I found out. We now pass 17/17 tests on Windows Server 2003 and ReactOS.

Also const-ify a parameter in PackStrings.

svn path=/trunk/; revision=74297
This commit is contained in:
Colin Finck
2017-04-13 16:48:40 +00:00
parent 6790e320bd
commit a737c007e8
7 changed files with 180 additions and 8 deletions
+85 -2
View 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 <[email protected]>
* COPYRIGHT: Copyright 2015-2017 Colin Finck <[email protected]>
*/
#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;
}
@@ -16,7 +16,7 @@
@ stub AdjustPointers
@ stub AdjustPointersInStructuresArray
@ stub AlignKMPtr
@ stub AlignRpcPtr
@ stdcall AlignRpcPtr(ptr ptr)
@ stdcall AllocSplStr(ptr)
@ stub AllowRemoteCalls
@ stub AppendPrinterNotifyInfoData
@@ -165,7 +165,7 @@
@ stdcall StartDocPrinterW(long long ptr)
@ stdcall StartPagePrinter(long)
@ stub UndoAlignKMPtr
@ stub UndoAlignRpcPtr
@ stdcall UndoAlignRpcPtr(ptr ptr long ptr)
@ stub UnloadDriver
@ stub UnloadDriverFile
@ stub UpdateBufferSize
@@ -86,7 +86,7 @@ MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters, DWORD c
* The strings are copied in reverse order, so this pointer will point to the last copied string of pSource.
*/
PBYTE WINAPI
PackStrings(PCWSTR* pSource, PBYTE pDest, PDWORD DestOffsets, PBYTE pEnd)
PackStrings(PCWSTR* pSource, PBYTE pDest, const DWORD* DestOffsets, PBYTE pEnd)
{
DWORD cbString;
ULONG_PTR StringAddress;
+4 -2
View File
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Printing Include files
* LICENSE: GNU LGPLv2 or any later version as published by the Free Software Foundation
* PURPOSE: Undocumented APIs of the Spooler Router "spoolss.dll"
* COPYRIGHT: Copyright 2015 Colin Finck <[email protected]>
* COPYRIGHT: Copyright 2015-2017 Colin Finck <[email protected]>
*/
#ifndef _REACTOS_SPOOLSS_H
@@ -19,14 +19,16 @@ typedef struct _MARSHALL_DOWN_INFO
}
MARSHALL_DOWN_INFO, *PMARSHALL_DOWN_INFO;
PVOID WINAPI AlignRpcPtr(PVOID pBuffer, PDWORD pcbBuffer);
PWSTR WINAPI AllocSplStr(PCWSTR pwszInput);
PVOID WINAPI DllAllocSplMem(DWORD dwBytes);
BOOL WINAPI DllFreeSplMem(PVOID pMem);
BOOL WINAPI DllFreeSplStr(PWSTR pwszString);
BOOL WINAPI MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters, DWORD cbStructureSize, BOOL bSomeBoolean);
PBYTE WINAPI PackStrings(PCWSTR* pSource, PBYTE pDest, PDWORD DestOffsets, PBYTE pEnd);
PBYTE WINAPI PackStrings(PCWSTR* pSource, PBYTE pDest, const DWORD* DestOffsets, PBYTE pEnd);
PVOID WINAPI ReallocSplMem(PVOID pOldMem, DWORD cbOld, DWORD cbNew);
BOOL WINAPI ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput);
BOOL WINAPI SplInitializeWinSpoolDrv(PVOID* pTable);
PDWORD WINAPI UndoAlignRpcPtr(PVOID pDestinationBuffer, PVOID pSourceBuffer, DWORD cbBuffer, PDWORD pcbNeeded);
#endif