mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-03 04:13:31 +00:00
[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:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user