mirror of
https://github.com/reactos/reactos.git
synced 2025-08-07 05:52:57 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
27
win32ss/printing/base/spoolss/CMakeLists.txt
Normal file
27
win32ss/printing/base/spoolss/CMakeLists.txt
Normal 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)
|
104
win32ss/printing/base/spoolss/context.c
Normal file
104
win32ss/printing/base/spoolss/context.c
Normal 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;
|
||||
}
|
83
win32ss/printing/base/spoolss/jobs.c
Normal file
83
win32ss/printing/base/spoolss/jobs.c
Normal 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);
|
||||
}
|
259
win32ss/printing/base/spoolss/main.c
Normal file
259
win32ss/printing/base/spoolss/main.c
Normal 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;
|
||||
}
|
||||
|
256
win32ss/printing/base/spoolss/memory.c
Normal file
256
win32ss/printing/base/spoolss/memory.c
Normal 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;
|
||||
}
|
70
win32ss/printing/base/spoolss/monitors.c
Normal file
70
win32ss/printing/base/spoolss/monitors.c
Normal 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;
|
||||
}
|
66
win32ss/printing/base/spoolss/ports.c
Normal file
66
win32ss/printing/base/spoolss/ports.c
Normal 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;
|
||||
}
|
54
win32ss/printing/base/spoolss/precomp.h
Normal file
54
win32ss/printing/base/spoolss/precomp.h
Normal 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
|
62
win32ss/printing/base/spoolss/printerdata.c
Normal file
62
win32ss/printing/base/spoolss/printerdata.c
Normal 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);
|
||||
}
|
279
win32ss/printing/base/spoolss/printers.c
Normal file
279
win32ss/printing/base/spoolss/printers.c
Normal 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);
|
||||
}
|
50
win32ss/printing/base/spoolss/printprocessors.c
Normal file
50
win32ss/printing/base/spoolss/printprocessors.c
Normal 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);
|
||||
}
|
5
win32ss/printing/base/spoolss/spoolss.rc
Normal file
5
win32ss/printing/base/spoolss/spoolss.rc
Normal 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>
|
178
win32ss/printing/base/spoolss/spoolss.spec
Normal file
178
win32ss/printing/base/spoolss/spoolss.spec
Normal 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)
|
120
win32ss/printing/base/spoolss/tools.c
Normal file
120
win32ss/printing/base/spoolss/tools.c
Normal 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue