Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.

This commit is contained in:
Colin Finck 2017-10-03 07:45:34 +00:00
parent b94e2d8ca0
commit c2c66aff7d
24198 changed files with 0 additions and 37285 deletions

View file

@ -0,0 +1,27 @@
spec2def(spoolss.dll spoolss.spec ADD_IMPORTLIB)
list(APPEND SOURCE
context.c
jobs.c
main.c
memory.c
monitors.c
ports.c
precomp.h
printerdata.c
printers.c
printprocessors.c
tools.c)
add_library(spoolss SHARED
${SOURCE}
spoolss.rc
${CMAKE_CURRENT_BINARY_DIR}/spoolss_stubs.c
${CMAKE_CURRENT_BINARY_DIR}/spoolss.def)
set_module_type(spoolss win32dll UNICODE)
target_link_libraries(spoolss wine)
add_importlibs(spoolss advapi32 msvcrt kernel32 ntdll)
add_pch(spoolss precomp.h SOURCE)
add_cd_file(TARGET spoolss DESTINATION reactos/system32 FOR all)

View file

@ -0,0 +1,104 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions related to switching between security contexts
* COPYRIGHT: Copyright 2015 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
/**
* @see RevertToPrinterSelf
*/
BOOL WINAPI
ImpersonatePrinterClient(HANDLE hToken)
{
DWORD cbReturned;
DWORD dwErrorCode;
TOKEN_TYPE Type;
// Sanity check
if (!hToken)
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
// Get the type of the supplied token.
if (!GetTokenInformation(hToken, TokenType, &Type, sizeof(TOKEN_TYPE), &cbReturned))
{
dwErrorCode = GetLastError();
ERR("GetTokenInformation failed with error %lu!\n", dwErrorCode);
goto Cleanup;
}
// Check if this is an impersonation token and only set it as the thread token in this case.
// This is not always an impersonation token, see RevertToPrinterSelf.
if (Type == TokenImpersonation)
{
if (!SetThreadToken(NULL, hToken))
{
dwErrorCode = GetLastError();
ERR("SetThreadToken failed with error %lu!\n", dwErrorCode);
goto Cleanup;
}
}
Cleanup:
if (hToken)
CloseHandle(hToken);
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
/**
* RevertToPrinterSelf reverts the security context from the current user's context back to the process context.
* As spoolss.dll is used by spoolsv.exe, this is usually the SYSTEM security context.
*
* Unlike the traditional ImpersonateClient and then RevertToSelf approach, we do it the other way round here,
* because spoolss.dll is delay-loaded by spoolsv.exe in the current user's context. Use RevertToPrinterSelf then to
* return to the SYSTEM context for specific tasks.
*/
HANDLE WINAPI
RevertToPrinterSelf()
{
DWORD dwErrorCode;
HANDLE hReturnValue = NULL;
HANDLE hToken = NULL;
// All spoolss code is usually called after impersonating the client. In this case, we can retrieve our current thread impersonation token using OpenThreadToken.
// But in rare occasions, spoolss code is also called from a higher-privileged thread that doesn't impersonate the client. Then we don't get an impersonation token.
// Anyway, we can't just return nothing in this case, because this is being treated as failure by the caller. So we return the token of the current process.
// This behaviour is verified with Windows!
if (OpenThreadToken(GetCurrentThread(), TOKEN_IMPERSONATE, TRUE, &hToken))
{
// Tell the thread to stop impersonating.
if (!SetThreadToken(NULL, NULL))
{
dwErrorCode = GetLastError();
ERR("SetThreadToken failed with error %lu!\n", dwErrorCode);
goto Cleanup;
}
}
else if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
{
dwErrorCode = GetLastError();
ERR("OpenProcessToken failed with error %lu!\n", dwErrorCode);
goto Cleanup;
}
// We were successful, return a token!
dwErrorCode = ERROR_SUCCESS;
hReturnValue = hToken;
// Don't let the cleanup routine close this.
hToken = NULL;
Cleanup:
if (hToken)
CloseHandle(hToken);
SetLastError(dwErrorCode);
return hReturnValue;
}

View file

@ -0,0 +1,83 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions for managing print jobs
* COPYRIGHT: Copyright 2015 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
BOOL WINAPI
AddJobW(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpAddJob(pHandle->hPrinter, Level, pData, cbBuf, pcbNeeded);
}
BOOL WINAPI
EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpEnumJobs(pHandle->hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned);
}
BOOL WINAPI
GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpGetJob(pHandle->hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
}
BOOL WINAPI
ScheduleJob(HANDLE hPrinter, DWORD dwJobID)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpScheduleJob(pHandle->hPrinter, dwJobID);
}
BOOL WINAPI
SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpSetJob(pHandle->hPrinter, JobId, Level, pJobInfo, Command);
}

View file

@ -0,0 +1,259 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Main functions
* COPYRIGHT: Copyright 2015 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
// Global Variables
HANDLE hProcessHeap;
LIST_ENTRY PrintProviderList;
static DWORD
_AddPrintProviderToList(PCWSTR pwszFileName)
{
DWORD dwErrorCode;
HINSTANCE hinstPrintProvider;
PInitializePrintProvidor pfnInitializePrintProvidor;
PSPOOLSS_PRINT_PROVIDER pPrintProvider = NULL;
// Try to load it.
hinstPrintProvider = LoadLibraryW(pwszFileName);
if (!hinstPrintProvider)
{
dwErrorCode = GetLastError();
ERR("LoadLibraryW failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode);
goto Cleanup;
}
// Get the initialization routine.
pfnInitializePrintProvidor = (PInitializePrintProvidor)GetProcAddress(hinstPrintProvider, "InitializePrintProvidor");
if (!pfnInitializePrintProvidor)
{
dwErrorCode = GetLastError();
ERR("GetProcAddress failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode);
goto Cleanup;
}
// Create a new SPOOLSS_PRINT_PROVIDER structure for it.
pPrintProvider = DllAllocSplMem(sizeof(SPOOLSS_PRINT_PROVIDER));
if (!pPrintProvider)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
// Call the Print Provider initialization function.
if (!pfnInitializePrintProvidor(&pPrintProvider->PrintProvider, sizeof(PRINTPROVIDOR), NULL))
{
dwErrorCode = GetLastError();
ERR("InitializePrintProvidor failed for \"%S\" with error %lu!\n", pwszFileName, dwErrorCode);
goto Cleanup;
}
// Add this Print Provider to the list.
InsertTailList(&PrintProviderList, &pPrintProvider->Entry);
// Don't let the cleanup routine free this.
pPrintProvider = NULL;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
if (pPrintProvider)
DllFreeSplMem(pPrintProvider);
return dwErrorCode;
}
static BOOL
_InitializePrintProviderList()
{
DWORD cbFileName;
DWORD cchMaxSubKey;
DWORD cchPrintProviderName;
DWORD dwErrorCode;
DWORD dwSubKeys;
DWORD i;
HKEY hKey = NULL;
HKEY hSubKey = NULL;
PWSTR pwszPrintProviderName = NULL;
WCHAR wszFileName[MAX_PATH];
// Initialize an empty list for our Print Providers.
InitializeListHead(&PrintProviderList);
// First add the Local Spooler.
// This one must exist and must be the first one in the list.
dwErrorCode = _AddPrintProviderToList(L"localspl");
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("The Local Spooler could not be loaded!\n");
goto Cleanup;
}
// Now add additional Print Providers from the registry.
// First of all, open the key containing print providers.
dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\Print\\Providers", 0, KEY_READ, &hKey);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
// Get the number of Print Providers and maximum sub key length.
dwErrorCode = (DWORD)RegQueryInfoKeyW(hKey, NULL, NULL, NULL, &dwSubKeys, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
// Allocate a temporary buffer for the Print Provider names.
pwszPrintProviderName = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
if (!pwszPrintProviderName)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
// Loop through all available Print Providers.
for (i = 0; i < dwSubKeys; i++)
{
// Cleanup tasks from the previous run
if (hSubKey)
{
RegCloseKey(hSubKey);
hSubKey = NULL;
}
// Get the name of this Print Provider.
cchPrintProviderName = cchMaxSubKey + 1;
dwErrorCode = (DWORD)RegEnumKeyExW(hKey, i, pwszPrintProviderName, &cchPrintProviderName, NULL, NULL, NULL, NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegEnumKeyExW failed for iteration %lu with status %lu!\n", i, dwErrorCode);
continue;
}
// Open this Print Provider's registry key.
dwErrorCode = (DWORD)RegOpenKeyExW(hKey, pwszPrintProviderName, 0, KEY_READ, &hSubKey);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegOpenKeyExW failed for Print Provider \"%S\" with status %lu!\n", pwszPrintProviderName, dwErrorCode);
continue;
}
// Get the file name of the Print Provider.
cbFileName = MAX_PATH * sizeof(WCHAR);
dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Driver", NULL, NULL, (PBYTE)wszFileName, &cbFileName);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
continue;
}
// Load and add it to the list.
dwErrorCode = _AddPrintProviderToList(wszFileName);
if (dwErrorCode != ERROR_SUCCESS)
continue;
}
dwErrorCode = ERROR_SUCCESS;
Cleanup:
// Inside the loop
if (hSubKey)
RegCloseKey(hSubKey);
// Outside the loop
if (pwszPrintProviderName)
DllFreeSplMem(pwszPrintProviderName);
if (hKey)
RegCloseKey(hKey);
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
hProcessHeap = GetProcessHeap();
break;
}
return TRUE;
}
BOOL WINAPI
InitializeRouter(HANDLE SpoolerStatusHandle)
{
return _InitializePrintProviderList();
}
BOOL WINAPI
SplInitializeWinSpoolDrv(PVOID* pTable)
{
HINSTANCE hWinspool;
int i;
hWinspool = LoadLibraryW(L"winspool.drv");
if (!hWinspool)
{
ERR("Could not load winspool.drv, last error is %lu!\n", GetLastError());
return FALSE;
}
// Get the function pointers which are meant to be returned by this function.
pTable[0] = GetProcAddress(hWinspool, "OpenPrinterW");
pTable[1] = GetProcAddress(hWinspool, "ClosePrinter");
pTable[2] = GetProcAddress(hWinspool, "SpoolerDevQueryPrintW");
pTable[3] = GetProcAddress(hWinspool, "SpoolerPrinterEvent");
pTable[4] = GetProcAddress(hWinspool, "DocumentPropertiesW");
pTable[5] = GetProcAddress(hWinspool, (LPSTR)212);
pTable[6] = GetProcAddress(hWinspool, (LPSTR)213);
pTable[7] = GetProcAddress(hWinspool, (LPSTR)214);
pTable[8] = GetProcAddress(hWinspool, (LPSTR)215);
// Verify that all calls succeeded.
for (i = 0; i < 9; i++)
if (!pTable[i])
return FALSE;
return TRUE;
}
BOOL WINAPI
SplIsUpgrade()
{
return FALSE;
}
BOOL WINAPI
SpoolerInit()
{
// Nothing to do here yet
SetLastError(ERROR_SUCCESS);
return TRUE;
}
BOOL WINAPI
BuildOtherNamesFromMachineName(LPVOID * ptr1, LPVOID * ptr2)
{
FIXME("(%p, %p) stub\n", ptr1, ptr2);
*ptr1 = NULL;
*ptr2 = NULL;
return FALSE;
}

View file

@ -0,0 +1,256 @@
/*
* 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)
{
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)
{
return HeapFree(hProcessHeap, 0, pwszString);
}
/**
* @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;
}

View file

@ -0,0 +1,70 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions related to Print Monitors
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
BOOL WINAPI
EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
BOOL bReturnValue = TRUE;
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwReturned;
PBYTE pCallBuffer;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
// Sanity checks.
if (cbBuf && !pMonitors)
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
// Begin counting.
*pcbNeeded = 0;
*pcReturned = 0;
// At the beginning, we have the full buffer available.
cbCallBuffer = cbBuf;
pCallBuffer = pMonitors;
// Loop through all Print Provider.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Check if this Print Provider provides an EnumMonitors function.
if (!pPrintProvider->PrintProvider.fpEnumMonitors)
continue;
// Call the EnumMonitors function of this Print Provider.
cbNeeded = 0;
dwReturned = 0;
bReturnValue = pPrintProvider->PrintProvider.fpEnumMonitors(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
// Add the returned counts to the total values.
*pcbNeeded += cbNeeded;
*pcReturned += dwReturned;
// Reduce the available buffer size for the next call without risking an underflow.
if (cbNeeded < cbCallBuffer)
cbCallBuffer -= cbNeeded;
else
cbCallBuffer = 0;
// Advance the buffer if the caller provided it.
if (pCallBuffer)
pCallBuffer += cbNeeded;
// Check if we shall not ask other Print Providers.
if (bReturnValue == ROUTER_STOP_ROUTING)
break;
}
return bReturnValue;
}

View file

@ -0,0 +1,66 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions related to Ports of the Print Monitors
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
BOOL WINAPI
EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
BOOL bReturnValue = TRUE;
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwReturned;
PBYTE pCallBuffer;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
// Sanity checks.
if (cbBuf && !pPorts)
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
// Begin counting.
*pcbNeeded = 0;
*pcReturned = 0;
// At the beginning, we have the full buffer available.
cbCallBuffer = cbBuf;
pCallBuffer = pPorts;
// Loop through all Print Provider.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Call the EnumPorts function of this Print Provider.
cbNeeded = 0;
dwReturned = 0;
bReturnValue = pPrintProvider->PrintProvider.fpEnumPorts(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
// Add the returned counts to the total values.
*pcbNeeded += cbNeeded;
*pcReturned += dwReturned;
// Reduce the available buffer size for the next call without risking an underflow.
if (cbNeeded < cbCallBuffer)
cbCallBuffer -= cbNeeded;
else
cbCallBuffer = 0;
// Advance the buffer if the caller provided it.
if (pCallBuffer)
pCallBuffer += cbNeeded;
// Check if we shall not ask other Print Providers.
if (bReturnValue == ROUTER_STOP_ROUTING)
break;
}
return bReturnValue;
}

View file

@ -0,0 +1,54 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Precompiled Header for all source files
* COPYRIGHT: Copyright 2015 Colin Finck (colin@reactos.org)
*/
#ifndef _PRECOMP_H
#define _PRECOMP_H
#define WIN32_NO_STATUS
#include <windef.h>
#include <winbase.h>
#include <wingdi.h>
#include <winreg.h>
#include <winspool.h>
#include <winsplp.h>
#include <ndk/rtlfuncs.h>
#include <spoolss.h>
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
// Function pointers
typedef BOOL (WINAPI *PInitializePrintProvidor)(LPPRINTPROVIDOR, DWORD, LPWSTR);
// Structures
/**
* Describes a Print Provider.
*/
typedef struct _SPOOLSS_PRINT_PROVIDER
{
LIST_ENTRY Entry;
PRINTPROVIDOR PrintProvider;
}
SPOOLSS_PRINT_PROVIDER, *PSPOOLSS_PRINT_PROVIDER;
/*
* Describes a handle returned by OpenPrinterW.
* We can't just pass the handle returned by the Print Provider, because spoolss has to remember which Print Provider opened this handle.
*/
typedef struct _SPOOLSS_PRINTER_HANDLE
{
PSPOOLSS_PRINT_PROVIDER pPrintProvider; /** Pointer to the Print Provider that opened this printer. */
HANDLE hPrinter; /** The handle returned by fpOpenPrinter of the Print Provider and passed to subsequent Print Provider functions. */
}
SPOOLSS_PRINTER_HANDLE, *PSPOOLSS_PRINTER_HANDLE;
// main.c
extern HANDLE hProcessHeap;
extern LIST_ENTRY PrintProviderList;
#endif

View file

@ -0,0 +1,62 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions related to Printer Configuration Data
* COPYRIGHT: Copyright 2017 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
DWORD WINAPI
GetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity check.
if (!pHandle)
{
// Yes, Windows checks for the handle here and sets the last error to ERROR_INVALID_HANDLE,
// but returns FALSE and not the error code.
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
// Call GetPrinterDataEx of the Print Provider.
return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
}
DWORD WINAPI
GetPrinterDataW(HANDLE hPrinter, LPWSTR pValueName, LPDWORD pType, LPBYTE pData, DWORD nSize, LPDWORD pcbNeeded)
{
// The ReactOS Printing Stack forwards all GetPrinterData calls to GetPrinterDataEx as soon as possible.
// This function may only be called if spoolss.dll is used together with Windows Printing Stack components.
WARN("This function should never be called!\n");
return GetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, pType, pData, nSize, pcbNeeded);
}
DWORD WINAPI
SetPrinterDataExW(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pValueName, DWORD Type, LPBYTE pData, DWORD cbData)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity check.
if (!pHandle)
{
// Yes, Windows checks for the handle here and sets the last error to ERROR_INVALID_HANDLE,
// but returns FALSE and not the error code.
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
// Call SetPrinterDataEx of the Print Provider.
return pHandle->pPrintProvider->PrintProvider.fpSetPrinterDataEx(pHandle->hPrinter, pKeyName, pValueName, Type, pData, cbData);
}
DWORD WINAPI
SetPrinterDataW(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
{
// The ReactOS Printing Stack forwards all SetPrinterData calls to SetPrinterDataEx as soon as possible.
// This function may only be called if spoolss.dll is used together with Windows Printing Stack components.
WARN("This function should never be called!\n");
return SetPrinterDataExW(hPrinter, L"PrinterDriverData", pValueName, Type, pData, cbData);
}

View file

@ -0,0 +1,279 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions related to Printers and printing
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
BOOL WINAPI
ClosePrinter(HANDLE hPrinter)
{
BOOL bReturnValue;
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
// FIXME: Call FindClosePrinterChangeNotification for all created change notifications (according to MSDN).
// Call CloseHandle of the Print Provider.
bReturnValue = pHandle->pPrintProvider->PrintProvider.fpClosePrinter(pHandle->hPrinter);
// Free our handle information.
DllFreeSplMem(pHandle);
return bReturnValue;
}
BOOL WINAPI
EndDocPrinter(HANDLE hPrinter)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpEndDocPrinter(pHandle->hPrinter);
}
BOOL WINAPI
EndPagePrinter(HANDLE hPrinter)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpEndPagePrinter(pHandle->hPrinter);
}
BOOL WINAPI
EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwErrorCode = MAXDWORD;
DWORD dwReturned;
PBYTE pCallBuffer;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
PLIST_ENTRY pEntry;
// Begin counting.
*pcbNeeded = 0;
*pcReturned = 0;
if (cbBuf && !pPrinterEnum)
{
dwErrorCode = ERROR_INVALID_USER_BUFFER;
goto Cleanup;
}
// At the beginning, we have the full buffer available.
cbCallBuffer = cbBuf;
pCallBuffer = pPrinterEnum;
// Loop through all Print Providers.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
// Call the EnumPrinters function of this Print Provider.
cbNeeded = 0;
dwReturned = 0;
pPrintProvider->PrintProvider.fpEnumPrinters(Flags, Name, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
// Add the returned counts to the total values.
*pcbNeeded += cbNeeded;
*pcReturned += dwReturned;
// Reduce the available buffer size for the next call without risking an underflow.
if (cbNeeded < cbCallBuffer)
cbCallBuffer -= cbNeeded;
else
cbCallBuffer = 0;
// Advance the buffer if the caller provided it.
if (pCallBuffer)
pCallBuffer += cbNeeded;
// dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
if (dwErrorCode != ERROR_SUCCESS)
dwErrorCode = GetLastError();
}
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
}
BOOL WINAPI
GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
}
BOOL WINAPI
OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
{
BOOL bReturnValue;
DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
HANDLE hPrinter;
PLIST_ENTRY pEntry;
PSPOOLSS_PRINTER_HANDLE pHandle;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
// Loop through all Print Providers to find one able to open this Printer.
for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
{
pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
bReturnValue = pPrintProvider->PrintProvider.fpOpenPrinter(pPrinterName, &hPrinter, pDefault);
if (bReturnValue == ROUTER_SUCCESS)
{
// This Print Provider has opened this Printer.
// Store this information and return a handle.
pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
if (!pHandle)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed!\n");
goto Cleanup;
}
pHandle->pPrintProvider = pPrintProvider;
pHandle->hPrinter = hPrinter;
*phPrinter = (HANDLE)pHandle;
dwErrorCode = ERROR_SUCCESS;
goto Cleanup;
}
else if (bReturnValue == ROUTER_STOP_ROUTING)
{
ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
dwErrorCode = GetLastError();
goto Cleanup;
}
}
Cleanup:
// ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
if (dwErrorCode == ERROR_INVALID_NAME)
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
}
DWORD WINAPI
StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpStartDocPrinter(pHandle->hPrinter, Level, pDocInfo);
}
BOOL WINAPI
StartPagePrinter(HANDLE hPrinter)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpStartPagePrinter(pHandle->hPrinter);
}
BOOL WINAPI
WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten);
}
BOOL WINAPI
XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
{
PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hXcv;
// Sanity checks.
if (!pHandle)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return pHandle->pPrintProvider->PrintProvider.fpXcvData(pHandle->hPrinter, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
}

View file

@ -0,0 +1,50 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Functions related to Print Processors
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
BOOL WINAPI
EnumPrintProcessorDatatypesW(PWSTR pName, PWSTR pPrintProcessorName, DWORD Level, PBYTE pDatatypes, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
// Sanity checks
if (cbBuf && !pDatatypes)
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
// Always call this function on the Local Spooler.
pPrintProvider = CONTAINING_RECORD(PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry);
return pPrintProvider->PrintProvider.fpEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
}
BOOL WINAPI
EnumPrintProcessorsW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
// Always call this function on the Local Spooler.
PSPOOLSS_PRINT_PROVIDER pPrintProvider = CONTAINING_RECORD(PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry);
return pPrintProvider->PrintProvider.fpEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
}
BOOL WINAPI
GetPrintProcessorDirectoryW(PWSTR pName, PWSTR pEnvironment, DWORD Level, PBYTE pPrintProcessorInfo, DWORD cbBuf, PDWORD pcbNeeded)
{
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
// Sanity checks
if (cbBuf && !pPrintProcessorInfo)
{
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
// Always call this function on the Local Spooler.
pPrintProvider = CONTAINING_RECORD(PrintProviderList.Flink, SPOOLSS_PRINT_PROVIDER, Entry);
return pPrintProvider->PrintProvider.fpGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded);
}

View file

@ -0,0 +1,5 @@
#define REACTOS_VERSION_DLL
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Spooler Router"
#define REACTOS_STR_INTERNAL_NAME "spoolss"
#define REACTOS_STR_ORIGINAL_FILENAME "spoolss.dll"
#include <reactos/version.rc>

View file

@ -0,0 +1,178 @@
@ stub AbortPrinter
@ stub AddDriverCatalog
@ stub AddFormW
@ stdcall AddJobW(long long ptr long ptr)
@ stub AddMonitorW
@ stub AddPerMachineConnectionW
@ stub AddPortExW
@ stub AddPortW
@ stub AddPrinterConnectionW
@ stub AddPrinterDriverExW
@ stub AddPrinterDriverW
@ stub AddPrinterExW
@ stub AddPrinterW
@ stub AddPrintProcessorW
@ stub AddPrintProvidorW
@ stub AdjustPointers
@ stub AdjustPointersInStructuresArray
@ stub AlignKMPtr
@ stdcall AlignRpcPtr(ptr ptr)
@ stdcall AllocSplStr(ptr)
@ stub AllowRemoteCalls
@ stub AppendPrinterNotifyInfoData
@ stub bGetDevModePerUser
@ stub bSetDevModePerUser
@ stdcall BuildOtherNamesFromMachineName(ptr ptr)
@ stub CacheAddName
@ stub CacheCreateAndAddNode
@ stub CacheCreateAndAddNodeWithIPAddresses
@ stub CacheDeleteNode
@ stub CacheIsNameCluster
@ stub CacheIsNameInNodeList
@ stub CallDrvDevModeConversion
@ stub CallRouterFindFirstPrinterChangeNotification
@ stub CheckLocalCall
@ stdcall ClosePrinter(long)
@ stub ClusterSplClose
@ stub ClusterSplIsAlive
@ stub ClusterSplOpen
@ stub ConfigurePortW
@ stub CreatePrinterIC
@ stub DbgGetPointers
@ stub DeleteFormW
@ stub DeleteMonitorW
@ stub DeletePerMachineConnectionW
@ stub DeletePortW
@ stub DeletePrinter
@ stub DeletePrinterConnectionW
@ stub DeletePrinterDataExW
@ stub DeletePrinterDataW
@ stub DeletePrinterDriverExW
@ stub DeletePrinterDriverW
@ stub DeletePrinterIC
@ stub DeletePrinterKeyW
@ stub DeletePrintProcessorW
@ stub DeletePrintProvidorW
@ stdcall DllAllocSplMem(long)
@ stdcall DllFreeSplMem(ptr)
@ stdcall DllFreeSplStr(ptr)
@ stdcall EndDocPrinter(long)
@ stdcall EndPagePrinter(long)
@ stub EnumFormsW
@ stdcall EnumJobsW(long long long long ptr long ptr ptr)
@ stdcall EnumMonitorsW(wstr long ptr long ptr ptr)
@ stub EnumPerMachineConnectionsW
@ stdcall EnumPortsW(wstr long ptr long ptr ptr)
@ stub EnumPrinterDataExW
@ stub EnumPrinterDataW
@ stub EnumPrinterDriversW
@ stub EnumPrinterKeyW
@ stdcall EnumPrintersW(long wstr long ptr long ptr ptr)
@ stdcall EnumPrintProcessorDatatypesW(wstr wstr long ptr long ptr ptr)
@ stdcall EnumPrintProcessorsW(wstr wstr long ptr long ptr ptr)
@ stub FindClosePrinterChangeNotification
@ stub FlushPrinter
@ stub FormatPrinterForRegistryKey
@ stub FormatRegistryKeyForPrinter
@ stub FreeOtherNames
@ stub GetClientUserHandle
@ stub GetFormW
@ stub GetJobAttributes
@ stdcall GetJobW(long long long ptr long ptr)
@ stub GetNetworkId
@ stdcall GetPrinterDataExW(long wstr wstr ptr ptr long ptr)
@ stdcall GetPrinterDataW(long wstr ptr ptr long ptr)
@ stub GetPrinterDriverDirectoryW
@ stub GetPrinterDriverExW
@ stdcall GetPrinterDriverW(long wstr long ptr long ptr)
@ stdcall GetPrinterW(long long ptr long ptr)
@ stdcall GetPrintProcessorDirectoryW(wstr wstr long ptr long ptr)
@ stub GetServerPolicy
@ stub GetShrinkedSize
@ stdcall ImpersonatePrinterClient(long)
@ stdcall InitializeRouter(long)
@ stub IsNamedPipeRpcCall
@ stub LoadDriver
@ stub LoadDriverFiletoConvertDevmode
@ stub LoadDriverWithVersion
@ stub LogWmiTraceEvent
@ stdcall MarshallDownStructure(ptr ptr long long)
@ stub MarshallDownStructuresArray
@ stub MarshallUpStructure
@ stub MarshallUpStructuresArray
@ stub MIDL_user_allocate1
@ stub MIDL_user_free1
@ stub OldGetPrinterDriverW
@ stub OpenPrinterExW
@ stub OpenPrinterPortW
@ stdcall OpenPrinterW(wstr ptr ptr)
@ stdcall PackStrings(ptr ptr ptr ptr)
@ stub PartialReplyPrinterChangeNotification
@ stub PlayGdiScriptOnPrinterIC
@ stub PrinterHandleRundown
@ stub PrinterMessageBoxW
@ stub ProvidorFindClosePrinterChangeNotification
@ stub ProvidorFindFirstPrinterChangeNotification
@ stub pszDbgAllocMsgA
@ stdcall ReadPrinter(long ptr long ptr)
@ stdcall ReallocSplMem(ptr long long)
@ stdcall ReallocSplStr(ptr ptr)
@ stub RemoteFindFirstPrinterChangeNotification
@ stub ReplyClosePrinter
@ stub ReplyOpenPrinter
@ stub ReplyPrinterChangeNotification
@ stub ResetPrinterW
@ stdcall RevertToPrinterSelf()
@ stub RouterAllocBidiMem
@ stub RouterAllocBidiResponseContainer
@ stub RouterAllocPrinterNotifyInfo
@ stub RouterFindFirstPrinterChangeNotification
@ stub RouterFindNextPrinterChangeNotification
@ stub RouterFreeBidiMem
@ stub RouterFreePrinterNotifyInfo
@ stub RouterRefreshPrinterChangeNotification
@ stub RouterReplyPrinter
@ stdcall ScheduleJob(long long)
@ stub SeekPrinter
@ stub SendRecvBidiData
@ stub SetAllocFailCount
@ stub SetFormW
@ stdcall SetJobW(long long long ptr long)
@ stub SetPortW
@ stdcall SetPrinterDataExW(long wstr wstr long ptr long)
@ stdcall SetPrinterDataW(long wstr long ptr long)
@ stub SetPrinterW
@ stub SplCloseSpoolFileHandle
@ stub SplCommitSpoolData
@ stub SplDriverUnloadComplete
@ stub SplGetSpoolFileInfo
@ stdcall SplInitializeWinSpoolDrv(ptr)
@ stub SplIsSessionZero
@ stdcall SplIsUpgrade()
@ stub SplPowerEvent
@ stub SplProcessPnPEvent
@ stub SplPromptUIInUsersSession
@ stub SplReadPrinter
@ stub SplRegisterForDeviceEvents
@ stub SplShutDownRouter
@ stub SplUnregisterForDeviceEvents
@ stub SpoolerFindClosePrinterChangeNotification
@ stub SpoolerFindFirstPrinterChangeNotification
@ stub SpoolerFindNextPrinterChangeNotification
@ stub SpoolerFreePrinterNotifyInfo
@ stub SpoolerHasInitialized
@ stdcall SpoolerInit()
@ stdcall StartDocPrinterW(long long ptr)
@ stdcall StartPagePrinter(long)
@ stub UndoAlignKMPtr
@ stdcall UndoAlignRpcPtr(ptr ptr long ptr)
@ stub UnloadDriver
@ stub UnloadDriverFile
@ stub UpdateBufferSize
@ stub UpdatePrinterRegAll
@ stub UpdatePrinterRegUser
@ stub vDbgLogError
@ stub WaitForPrinterChange
@ stub WaitForSpoolerInitialization
@ stdcall WritePrinter(long ptr long ptr)
@ stdcall XcvDataW(long wstr ptr long ptr long ptr ptr)

View file

@ -0,0 +1,120 @@
/*
* PROJECT: ReactOS Spooler Router
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Miscellaneous tool functions
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
*/
#include "precomp.h"
/**
* @name MarshallDownStructure
*
* Prepare a structure for marshalling/serialization by replacing absolute pointer addresses in its fields by relative offsets.
*
* @param pStructure
* Pointer to the structure to operate on.
*
* @param pParameters
* Array of MARSHALL_DOWN_INFO elements containing information about the fields of the structure as well as how to modify them.
* See the documentation on MARSHALL_DOWN_INFO for more information.
* You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
*
* @param cbStructureSize
* Apparently, this is the size in bytes of the structure given through pStructure under Windows.
* This parameter is unused in my implementation.
*
* @param bSomeBoolean
* Unknown boolean value
*
* @return
* TRUE if the structure was successfully adjusted, FALSE otherwise.
*/
BOOL WINAPI
MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters, DWORD cbStructureSize, BOOL bSomeBoolean)
{
// Sanity checks
if (!pStructure || !pParameters)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
// Loop until we reach an element with offset set to MAXDWORD.
while (pParameters->dwOffset != MAXDWORD)
{
if (pParameters->bAdjustAddress)
{
// Apply the byte offset on pStructure. There must be a pointer at this position, whose address we're adjusting
// by subtracting the address of pStructure from it.
*((PULONG_PTR)((PBYTE)pStructure + pParameters->dwOffset)) -= (ULONG_PTR)pStructure;
}
// Advance to the next element description.
pParameters++;
}
return TRUE;
}
/**
* @name PackStrings
*
* Takes an array of Unicode strings and fills an output buffer with these strings at the end and pointers to each string at specific offsets.
* Useful helper for functions that copy an information structure including strings into a given buffer (like PRINTER_INFO_1).
*
* @param pSource
* The array of Unicode strings to copy. Needs to have at least as many elements as the DestOffsets array.
*
* @param pDest
* Pointer to the beginning of the output buffer.
* The caller is responsible for verifying that this buffer is large enough to hold all strings and pointers.
*
* @param DestOffsets
* Array of byte offsets in the output buffer. For each element of DestOffsets, the function will copy the address of the corresponding copied
* string of pSource to this location in the output buffer. If a string in pSource is NULL, the function will set the pointer address to NULL
* in the output buffer.
* Use macros like FIELD_OFFSET to calculate the offsets for this array.
* The last element of the array must have the value MAXDWORD to let the function detect the end of the array.
*
* @param pEnd
* Pointer to the end of the output buffer. That means the first element outside of the buffer given in pDest.
*
* @return
* Returns a pointer to the beginning of the strings in pDest.
* The strings are copied in reverse order, so this pointer will point to the last copied string of pSource.
*/
PBYTE WINAPI
PackStrings(PWSTR* pSource, PBYTE pDest, const DWORD* DestOffsets, PBYTE pEnd)
{
DWORD cbString;
ULONG_PTR StringAddress;
// Loop until we reach an element with offset set to MAXDWORD.
while (*DestOffsets != MAXDWORD)
{
StringAddress = 0;
if (*pSource)
{
// Determine the length of the source string.
cbString = (wcslen(*pSource) + 1) * sizeof(WCHAR);
// Copy it before the last string.
pEnd -= cbString;
StringAddress = (ULONG_PTR)pEnd;
CopyMemory(pEnd, *pSource, cbString);
}
// Copy the address of the copied string to the location given by the offset.
CopyMemory(&pDest[*DestOffsets], &StringAddress, sizeof(ULONG_PTR));
// Advance to the next source string and destination offset.
pSource++;
DestOffsets++;
}
// pEnd is now at the last string we copied. Return this value as a pointer to the beginning of all strings in the output buffer.
return pEnd;
}