2015-06-22 14:31:47 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Spooler API
|
2017-09-29 17:18:19 +00:00
|
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
2015-06-22 14:31:47 +00:00
|
|
|
* PURPOSE: Functions related to Printers and printing
|
2018-01-17 11:52:12 +00:00
|
|
|
* COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org)
|
2015-06-22 14:31:47 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
2018-01-17 11:52:12 +00:00
|
|
|
#include <marshalling/printers.h>
|
2015-06-22 14:31:47 +00:00
|
|
|
|
2017-05-09 15:44:42 +00:00
|
|
|
// Local Constants
|
|
|
|
|
|
|
|
/** And the award for the most confusingly named setting goes to "Device", for storing the default printer of the current user.
|
|
|
|
Ok, I admit that this has historical reasons. It's still not straightforward in any way though! */
|
|
|
|
static const WCHAR wszWindowsKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
|
|
|
|
static const WCHAR wszDeviceValue[] = L"Device";
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
static DWORD
|
|
|
|
_StartDocPrinterSpooled(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1, PADDJOB_INFO_1W pAddJobInfo1)
|
|
|
|
{
|
|
|
|
DWORD cbNeeded;
|
|
|
|
DWORD dwErrorCode;
|
|
|
|
PJOB_INFO_1W pJobInfo1 = NULL;
|
|
|
|
|
|
|
|
// Create the spool file.
|
|
|
|
pHandle->hSPLFile = CreateFileW(pAddJobInfo1->Path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, 0, NULL);
|
|
|
|
if (pHandle->hSPLFile == INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
ERR("CreateFileW failed for \"%S\" with error %lu!\n", pAddJobInfo1->Path, dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the size of the job information.
|
2015-07-17 15:11:34 +00:00
|
|
|
GetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, NULL, 0, &cbNeeded);
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
|
|
|
|
{
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
ERR("GetJobW failed with error %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate enough memory for the returned job information.
|
|
|
|
pJobInfo1 = HeapAlloc(hProcessHeap, 0, cbNeeded);
|
|
|
|
if (!pJobInfo1)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
ERR("HeapAlloc failed!\n");
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the job information.
|
2015-07-17 15:11:34 +00:00
|
|
|
if (!GetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, (PBYTE)pJobInfo1, cbNeeded, &cbNeeded))
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
{
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
ERR("GetJobW failed with error %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add our document information.
|
2015-07-20 15:21:03 +00:00
|
|
|
if (pDocInfo1->pDatatype)
|
|
|
|
pJobInfo1->pDatatype = pDocInfo1->pDatatype;
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
pJobInfo1->pDocument = pDocInfo1->pDocName;
|
|
|
|
|
|
|
|
// Set the new job information.
|
2015-07-17 15:11:34 +00:00
|
|
|
if (!SetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, (PBYTE)pJobInfo1, 0))
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
{
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
ERR("SetJobW failed with error %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We were successful!
|
|
|
|
pHandle->dwJobID = pAddJobInfo1->JobId;
|
|
|
|
dwErrorCode = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (pJobInfo1)
|
|
|
|
HeapFree(hProcessHeap, 0, pJobInfo1);
|
|
|
|
|
|
|
|
return dwErrorCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DWORD
|
|
|
|
_StartDocPrinterWithRPC(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1)
|
|
|
|
{
|
|
|
|
DWORD dwErrorCode;
|
|
|
|
WINSPOOL_DOC_INFO_CONTAINER DocInfoContainer;
|
|
|
|
|
|
|
|
DocInfoContainer.Level = 1;
|
|
|
|
DocInfoContainer.DocInfo.pDocInfo1 = (WINSPOOL_DOC_INFO_1*)pDocInfo1;
|
|
|
|
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcStartDocPrinter(pHandle->hPrinter, &DocInfoContainer, &pHandle->dwJobID);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcStartDocPrinter failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
return dwErrorCode;
|
|
|
|
}
|
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
AbortPrinter(HANDLE hPrinter)
|
|
|
|
{
|
|
|
|
TRACE("AbortPrinter(%p)\n", hPrinter);
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
HANDLE WINAPI
|
|
|
|
AddPrinterA(PSTR pName, DWORD Level, PBYTE pPrinter)
|
|
|
|
{
|
|
|
|
TRACE("AddPrinterA(%s, %lu, %p)\n", pName, Level, pPrinter);
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:59:46 +00:00
|
|
|
HANDLE WINAPI
|
|
|
|
AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("AddPrinterW(%S, %lu, %p)\n", pName, Level, pPrinter);
|
2015-07-22 17:59:46 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-06-22 14:31:47 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
ClosePrinter(HANDLE hPrinter)
|
|
|
|
{
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
DWORD dwErrorCode;
|
|
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("ClosePrinter(%p)\n", hPrinter);
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
// Sanity checks.
|
|
|
|
if (!pHandle)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the RPC call.
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
2017-06-26 15:16:46 +00:00
|
|
|
dwErrorCode = _RpcClosePrinter(&pHandle->hPrinter);
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcClosePrinter failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
// Close any open file handle.
|
|
|
|
if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
|
|
|
|
CloseHandle(pHandle->hSPLFile);
|
|
|
|
|
|
|
|
// Free the memory for the handle.
|
|
|
|
HeapFree(hProcessHeap, 0, pHandle);
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
DeletePrinter(HANDLE hPrinter)
|
|
|
|
{
|
|
|
|
TRACE("DeletePrinter(%p)\n", hPrinter);
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2015-06-22 14:31:47 +00:00
|
|
|
DWORD WINAPI
|
|
|
|
DeviceCapabilitiesA(LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA* pDevMode)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("DeviceCapabilitiesA(%s, %s, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode);
|
2017-12-09 12:35:42 +00:00
|
|
|
UNIMPLEMENTED;
|
2015-06-22 14:31:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD WINAPI
|
|
|
|
DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, WORD fwCapability, LPWSTR pOutput, const DEVMODEW* pDevMode)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("DeviceCapabilitiesW(%S, %S, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode);
|
2017-12-09 12:35:42 +00:00
|
|
|
UNIMPLEMENTED;
|
2015-06-22 14:31:47 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
LONG WINAPI
|
|
|
|
DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("DocumentPropertiesA(%p, %p, %s, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
|
2017-12-09 12:35:42 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return -1;
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LONG WINAPI
|
|
|
|
DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("DocumentPropertiesW(%p, %p, %S, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
|
2017-12-09 12:35:42 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return -1;
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
EndDocPrinter(HANDLE hPrinter)
|
|
|
|
{
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
DWORD dwErrorCode;
|
|
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("EndDocPrinter(%p)\n", hPrinter);
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
// Sanity checks.
|
|
|
|
if (!pHandle)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
// For spooled jobs, the document is finished by calling _RpcScheduleJob.
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcScheduleJob(pHandle->hPrinter, pHandle->dwJobID);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcScheduleJob failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
// Close the spool file handle.
|
|
|
|
CloseHandle(pHandle->hSPLFile);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// In all other cases, just call _RpcEndDocPrinter.
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcEndDocPrinter(pHandle->hPrinter);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcEndDocPrinter failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
}
|
|
|
|
|
|
|
|
// A new document can now be started again.
|
|
|
|
pHandle->bStartedDoc = FALSE;
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
EndPagePrinter(HANDLE hPrinter)
|
|
|
|
{
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
DWORD dwErrorCode;
|
|
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("EndPagePrinter(%p)\n", hPrinter);
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
// Sanity checks.
|
|
|
|
if (!pHandle)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
// For spooled jobs, we don't need to do anything.
|
|
|
|
dwErrorCode = ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// In all other cases, just call _RpcEndPagePrinter.
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcEndPagePrinter(pHandle->hPrinter);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcEndPagePrinter failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
}
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
2015-07-17 10:57:10 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
EnumPrintersA(DWORD Flags, PSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("EnumPrintersA(%lu, %s, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
2015-07-17 10:57:10 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
|
|
|
{
|
|
|
|
DWORD dwErrorCode;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("EnumPrintersW(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
|
2017-04-16 14:12:01 +00:00
|
|
|
// Dismiss invalid levels already at this point.
|
|
|
|
if (Level == 3 || Level > 5)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cbBuf && pPrinterEnum)
|
|
|
|
ZeroMemory(pPrinterEnum, cbBuf);
|
|
|
|
|
2015-07-17 10:57:10 +00:00
|
|
|
// Do the RPC call
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcEnumPrinters failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
|
|
|
{
|
2018-01-17 11:52:12 +00:00
|
|
|
// Replace relative offset addresses in the output by absolute pointers.
|
|
|
|
ASSERT(Level <= 9);
|
|
|
|
MarshallUpStructuresArray(cbBuf, pPrinterEnum, *pcReturned, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
|
2015-07-17 10:57:10 +00:00
|
|
|
}
|
|
|
|
|
2017-04-16 14:12:01 +00:00
|
|
|
Cleanup:
|
2015-07-17 10:57:10 +00:00
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
FlushPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten, DWORD cSleep)
|
|
|
|
{
|
|
|
|
TRACE("FlushPrinter(%p, %p, %lu, %p, %lu)\n", hPrinter, pBuf, cbBuf, pcWritten, cSleep);
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2015-06-22 14:31:47 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
|
|
|
|
{
|
2017-05-09 15:44:42 +00:00
|
|
|
DWORD dwErrorCode;
|
|
|
|
PWSTR pwszBuffer = NULL;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("GetDefaultPrinterA(%p, %p)\n", pszBuffer, pcchBuffer);
|
|
|
|
|
2017-05-09 15:44:42 +00:00
|
|
|
// Sanity check.
|
|
|
|
if (!pcchBuffer)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if an ANSI buffer was given and if so, allocate a Unicode buffer of the same size.
|
|
|
|
if (pszBuffer && *pcchBuffer)
|
|
|
|
{
|
|
|
|
pwszBuffer = HeapAlloc(hProcessHeap, 0, *pcchBuffer * sizeof(WCHAR));
|
|
|
|
if (!pwszBuffer)
|
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
ERR("HeapAlloc failed!\n");
|
2017-05-09 15:44:42 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!GetDefaultPrinterW(pwszBuffer, pcchBuffer))
|
|
|
|
{
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
2017-12-09 09:59:40 +00:00
|
|
|
// We successfully got a string in pwszBuffer, so convert the Unicode string to ANSI.
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszBuffer, *pcchBuffer, NULL, NULL);
|
|
|
|
|
2017-05-09 15:44:42 +00:00
|
|
|
dwErrorCode = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (pwszBuffer)
|
|
|
|
HeapFree(hProcessHeap, 0, pwszBuffer);
|
|
|
|
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
|
|
|
|
{
|
2017-05-09 15:44:42 +00:00
|
|
|
DWORD cbNeeded;
|
|
|
|
DWORD cchInputBuffer;
|
|
|
|
DWORD dwErrorCode;
|
|
|
|
HKEY hWindowsKey = NULL;
|
|
|
|
PWSTR pwszDevice = NULL;
|
|
|
|
PWSTR pwszComma;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("GetDefaultPrinterW(%p, %p)\n", pszBuffer, pcchBuffer);
|
|
|
|
|
2017-05-09 15:44:42 +00:00
|
|
|
// Sanity check.
|
|
|
|
if (!pcchBuffer)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cchInputBuffer = *pcchBuffer;
|
|
|
|
|
|
|
|
// Open the registry key where the default printer for the current user is stored.
|
|
|
|
dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_READ, &hWindowsKey);
|
|
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Determine the size of the required buffer.
|
|
|
|
dwErrorCode = (DWORD)RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, NULL, &cbNeeded);
|
|
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate it.
|
|
|
|
pwszDevice = HeapAlloc(hProcessHeap, 0, cbNeeded);
|
|
|
|
if (!pwszDevice)
|
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
ERR("HeapAlloc failed!\n");
|
2017-05-09 15:44:42 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now get the actual value.
|
|
|
|
dwErrorCode = RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, (PBYTE)pwszDevice, &cbNeeded);
|
|
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We get a string "<Printer Name>,winspool,<Port>:".
|
|
|
|
// Extract the printer name from it.
|
|
|
|
pwszComma = wcschr(pwszDevice, L',');
|
|
|
|
if (!pwszComma)
|
|
|
|
{
|
|
|
|
ERR("Found no or invalid default printer: %S!\n", pwszDevice);
|
|
|
|
dwErrorCode = ERROR_INVALID_NAME;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store the length of the Printer Name (including the terminating NUL character!) in *pcchBuffer.
|
|
|
|
*pcchBuffer = pwszComma - pwszDevice + 1;
|
|
|
|
|
|
|
|
// Check if the supplied buffer is large enough.
|
|
|
|
if (cchInputBuffer < *pcchBuffer)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy the default printer.
|
|
|
|
*pwszComma = 0;
|
|
|
|
CopyMemory(pszBuffer, pwszDevice, *pcchBuffer * sizeof(WCHAR));
|
|
|
|
|
|
|
|
dwErrorCode = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (hWindowsKey)
|
|
|
|
RegCloseKey(hWindowsKey);
|
|
|
|
|
|
|
|
if (pwszDevice)
|
|
|
|
HeapFree(hProcessHeap, 0, pwszDevice);
|
|
|
|
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("GetPrinterA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
|
2015-06-22 14:31:47 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("GetPrinterDriverA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
|
2015-06-22 14:31:47 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("GetPrinterDriverW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
|
2015-06-22 14:31:47 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
GetPrinterW(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
|
|
|
|
{
|
2017-04-30 15:12:53 +00:00
|
|
|
DWORD dwErrorCode;
|
2017-12-10 11:28:08 +00:00
|
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
2017-04-30 15:12:53 +00:00
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("GetPrinterW(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
|
|
|
|
|
2017-12-10 11:28:08 +00:00
|
|
|
// Sanity checks.
|
|
|
|
if (!pHandle)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
2017-04-30 15:12:53 +00:00
|
|
|
// Dismiss invalid levels already at this point.
|
|
|
|
if (Level > 9)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cbBuf && pPrinter)
|
|
|
|
ZeroMemory(pPrinter, cbBuf);
|
|
|
|
|
|
|
|
// Do the RPC call
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
2017-12-10 11:28:08 +00:00
|
|
|
dwErrorCode = _RpcGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
|
2017-04-30 15:12:53 +00:00
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcGetPrinter failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
|
|
|
{
|
2018-01-17 11:52:12 +00:00
|
|
|
// Replace relative offset addresses in the output by absolute pointers.
|
|
|
|
ASSERT(Level <= 9);
|
|
|
|
MarshallUpStructure(cbBuf, pPrinter, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
|
2017-04-30 15:12:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
OpenPrinterA(LPSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSA pDefault)
|
|
|
|
{
|
|
|
|
BOOL bReturnValue = FALSE;
|
2016-01-06 05:15:44 +00:00
|
|
|
DWORD cch;
|
2015-06-22 14:31:47 +00:00
|
|
|
PWSTR pwszPrinterName = NULL;
|
|
|
|
PRINTER_DEFAULTSW wDefault = { 0 };
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("OpenPrinterA(%s, %p, %p)\n", pPrinterName, phPrinter, pDefault);
|
|
|
|
|
2015-06-22 14:31:47 +00:00
|
|
|
if (pPrinterName)
|
|
|
|
{
|
|
|
|
// Convert pPrinterName to a Unicode string pwszPrinterName
|
2016-01-06 05:15:44 +00:00
|
|
|
cch = strlen(pPrinterName);
|
2015-06-22 14:31:47 +00:00
|
|
|
|
2016-01-06 05:15:44 +00:00
|
|
|
pwszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
2015-06-22 14:31:47 +00:00
|
|
|
if (!pwszPrinterName)
|
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
ERR("HeapAlloc failed!\n");
|
2015-06-22 14:31:47 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
2016-01-06 05:15:44 +00:00
|
|
|
MultiByteToWideChar(CP_ACP, 0, pPrinterName, -1, pwszPrinterName, cch + 1);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pDefault)
|
|
|
|
{
|
|
|
|
wDefault.DesiredAccess = pDefault->DesiredAccess;
|
|
|
|
|
|
|
|
if (pDefault->pDatatype)
|
|
|
|
{
|
2016-01-06 05:15:44 +00:00
|
|
|
// Convert pDefault->pDatatype to a Unicode string wDefault.pDatatype
|
|
|
|
cch = strlen(pDefault->pDatatype);
|
2015-06-22 14:31:47 +00:00
|
|
|
|
2016-01-06 05:15:44 +00:00
|
|
|
wDefault.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
|
|
|
if (!wDefault.pDatatype)
|
2015-06-22 14:31:47 +00:00
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
ERR("HeapAlloc failed!\n");
|
2015-06-22 14:31:47 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
2016-01-06 05:15:44 +00:00
|
|
|
MultiByteToWideChar(CP_ACP, 0, pDefault->pDatatype, -1, wDefault.pDatatype, cch + 1);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pDefault->pDevMode)
|
|
|
|
wDefault.pDevMode = GdiConvertToDevmodeW(pDefault->pDevMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
bReturnValue = OpenPrinterW(pwszPrinterName, phPrinter, &wDefault);
|
|
|
|
|
|
|
|
Cleanup:
|
2016-01-06 05:15:44 +00:00
|
|
|
if (wDefault.pDatatype)
|
|
|
|
HeapFree(hProcessHeap, 0, wDefault.pDatatype);
|
|
|
|
|
2015-06-22 14:31:47 +00:00
|
|
|
if (wDefault.pDevMode)
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
HeapFree(hProcessHeap, 0, wDefault.pDevMode);
|
2015-06-22 14:31:47 +00:00
|
|
|
|
|
|
|
if (pwszPrinterName)
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
HeapFree(hProcessHeap, 0, pwszPrinterName);
|
2015-06-22 14:31:47 +00:00
|
|
|
|
|
|
|
return bReturnValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefault)
|
|
|
|
{
|
|
|
|
DWORD dwErrorCode;
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
HANDLE hPrinter;
|
|
|
|
PSPOOLER_HANDLE pHandle;
|
2015-06-22 14:31:47 +00:00
|
|
|
PWSTR pDatatype = NULL;
|
2015-07-17 14:34:23 +00:00
|
|
|
WINSPOOL_DEVMODE_CONTAINER DevModeContainer = { 0 };
|
2015-06-22 14:31:47 +00:00
|
|
|
ACCESS_MASK AccessRequired = 0;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("OpenPrinterW(%S, %p, %p)\n", pPrinterName, phPrinter, pDefault);
|
|
|
|
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
// Sanity check
|
|
|
|
if (!phPrinter)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
2015-06-22 14:31:47 +00:00
|
|
|
// Prepare the additional parameters in the format required by _RpcOpenPrinter
|
|
|
|
if (pDefault)
|
|
|
|
{
|
|
|
|
pDatatype = pDefault->pDatatype;
|
|
|
|
DevModeContainer.cbBuf = sizeof(DEVMODEW);
|
|
|
|
DevModeContainer.pDevMode = (BYTE*)pDefault->pDevMode;
|
|
|
|
AccessRequired = pDefault->DesiredAccess;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the RPC call
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
2015-07-17 14:34:23 +00:00
|
|
|
dwErrorCode = _RpcOpenPrinter(pPrinterName, &hPrinter, pDatatype, &DevModeContainer, AccessRequired);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcOpenPrinter failed with exception code %lu!\n", dwErrorCode);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
// Create a new SPOOLER_HANDLE structure.
|
|
|
|
pHandle = HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, sizeof(SPOOLER_HANDLE));
|
|
|
|
if (!pHandle)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
ERR("HeapAlloc failed!\n");
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
pHandle->hPrinter = hPrinter;
|
|
|
|
pHandle->hSPLFile = INVALID_HANDLE_VALUE;
|
|
|
|
|
|
|
|
// Return it as phPrinter.
|
|
|
|
*phPrinter = (HANDLE)pHandle;
|
|
|
|
}
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
2015-06-28 15:51:32 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
|
|
|
|
{
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
DWORD dwErrorCode;
|
|
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("ReadPrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pNoBytesRead);
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
// Sanity checks.
|
|
|
|
if (!pHandle)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the RPC call
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcReadPrinter failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2015-06-28 15:51:32 +00:00
|
|
|
}
|
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
ResetPrinterA(HANDLE hPrinter, PPRINTER_DEFAULTSA pDefault)
|
|
|
|
{
|
|
|
|
TRACE("ResetPrinterA(%p, %p)\n", hPrinter, pDefault);
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:59:46 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
ResetPrinterW(HANDLE hPrinter, PPRINTER_DEFAULTSW pDefault)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("ResetPrinterW(%p, %p)\n", hPrinter, pDefault);
|
2015-07-22 17:59:46 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-05-09 15:44:42 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
SetDefaultPrinterA(LPCSTR pszPrinter)
|
|
|
|
{
|
|
|
|
BOOL bReturnValue = FALSE;
|
|
|
|
DWORD cch;
|
|
|
|
PWSTR pwszPrinter = NULL;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("SetDefaultPrinterA(%s)\n", pszPrinter);
|
|
|
|
|
2017-05-09 15:44:42 +00:00
|
|
|
if (pszPrinter)
|
|
|
|
{
|
|
|
|
// Convert pszPrinter to a Unicode string pwszPrinter
|
|
|
|
cch = strlen(pszPrinter);
|
|
|
|
|
|
|
|
pwszPrinter = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
|
|
|
if (!pwszPrinter)
|
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
ERR("HeapAlloc failed!\n");
|
2017-05-09 15:44:42 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pszPrinter, -1, pwszPrinter, cch + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
bReturnValue = SetDefaultPrinterW(pwszPrinter);
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (pwszPrinter)
|
|
|
|
HeapFree(hProcessHeap, 0, pwszPrinter);
|
|
|
|
|
|
|
|
return bReturnValue;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
SetDefaultPrinterW(LPCWSTR pszPrinter)
|
|
|
|
{
|
|
|
|
const WCHAR wszDevicesKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Devices";
|
|
|
|
|
|
|
|
DWORD cbDeviceValueData;
|
|
|
|
DWORD cbPrinterValueData = 0;
|
|
|
|
DWORD cchPrinter;
|
|
|
|
DWORD dwErrorCode;
|
|
|
|
HKEY hDevicesKey = NULL;
|
|
|
|
HKEY hWindowsKey = NULL;
|
|
|
|
PWSTR pwszDeviceValueData = NULL;
|
|
|
|
WCHAR wszPrinter[MAX_PRINTER_NAME + 1];
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("SetDefaultPrinterW(%S)\n", pszPrinter);
|
|
|
|
|
2017-05-09 15:44:42 +00:00
|
|
|
// Open the Devices registry key.
|
|
|
|
dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszDevicesKey, 0, KEY_READ, &hDevicesKey);
|
|
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Did the caller give us a printer to set as default?
|
|
|
|
if (pszPrinter && *pszPrinter)
|
|
|
|
{
|
|
|
|
// Check if the given printer exists and query the value data size.
|
|
|
|
dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, NULL, &cbPrinterValueData);
|
|
|
|
if (dwErrorCode == ERROR_FILE_NOT_FOUND)
|
|
|
|
{
|
2017-05-10 13:03:08 +00:00
|
|
|
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
|
2017-05-09 15:44:42 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
else if (dwErrorCode != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
cchPrinter = wcslen(pszPrinter);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If there is already a default printer, we're done!
|
|
|
|
cchPrinter = _countof(wszPrinter);
|
|
|
|
if (GetDefaultPrinterW(wszPrinter, &cchPrinter))
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_SUCCESS;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, get us the first printer from the "Devices" key to later set it as default and query the value data size.
|
|
|
|
cchPrinter = _countof(wszPrinter);
|
|
|
|
dwErrorCode = (DWORD)RegEnumValueW(hDevicesKey, 0, wszPrinter, &cchPrinter, NULL, NULL, NULL, &cbPrinterValueData);
|
|
|
|
if (dwErrorCode != ERROR_MORE_DATA)
|
|
|
|
goto Cleanup;
|
|
|
|
|
|
|
|
pszPrinter = wszPrinter;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We now need to query the value data, which has the format "winspool,<Port>:"
|
|
|
|
// and make "<Printer Name>,winspool,<Port>:" out of it.
|
|
|
|
// Allocate a buffer large enough for the final data.
|
|
|
|
cbDeviceValueData = (cchPrinter + 1) * sizeof(WCHAR) + cbPrinterValueData;
|
|
|
|
pwszDeviceValueData = HeapAlloc(hProcessHeap, 0, cbDeviceValueData);
|
|
|
|
if (!pwszDeviceValueData)
|
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
ERR("HeapAlloc failed!\n");
|
2017-05-09 15:44:42 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy the Printer Name and a comma into it.
|
|
|
|
CopyMemory(pwszDeviceValueData, pszPrinter, cchPrinter * sizeof(WCHAR));
|
|
|
|
pwszDeviceValueData[cchPrinter] = L',';
|
|
|
|
|
|
|
|
// Append the value data, which has the format "winspool,<Port>:"
|
|
|
|
dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, (PBYTE)&pwszDeviceValueData[cchPrinter + 1], &cbPrinterValueData);
|
|
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
|
|
goto Cleanup;
|
|
|
|
|
|
|
|
// Open the Windows registry key.
|
|
|
|
dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_SET_VALUE, &hWindowsKey);
|
|
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store our new default printer.
|
|
|
|
dwErrorCode = (DWORD)RegSetValueExW(hWindowsKey, wszDeviceValue, 0, REG_SZ, (PBYTE)pwszDeviceValueData, cbDeviceValueData);
|
|
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ERR("RegSetValueExW failed with status %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (hDevicesKey)
|
|
|
|
RegCloseKey(hDevicesKey);
|
|
|
|
|
|
|
|
if (hWindowsKey)
|
|
|
|
RegCloseKey(hWindowsKey);
|
|
|
|
|
|
|
|
if (pwszDeviceValueData)
|
|
|
|
HeapFree(hProcessHeap, 0, pwszDeviceValueData);
|
|
|
|
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
|
|
}
|
|
|
|
|
2017-12-09 12:35:42 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
SetPrinterA(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
|
|
|
|
{
|
|
|
|
TRACE("SetPrinterA(%p, %lu, %p, %lu)\n", hPrinter, Level, pPrinter, Command);
|
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2015-07-22 17:59:46 +00:00
|
|
|
BOOL WINAPI
|
|
|
|
SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("SetPrinterW(%p, %lu, %p, %lu)\n", hPrinter, Level, pPrinter, Command);
|
2015-07-22 17:59:46 +00:00
|
|
|
UNIMPLEMENTED;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2016-01-06 05:15:44 +00:00
|
|
|
DWORD WINAPI
|
|
|
|
StartDocPrinterA(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
|
|
|
|
{
|
|
|
|
DOC_INFO_1W wDocInfo1 = { 0 };
|
|
|
|
DWORD cch;
|
|
|
|
DWORD dwErrorCode;
|
|
|
|
DWORD dwReturnValue = 0;
|
|
|
|
PDOC_INFO_1A pDocInfo1 = (PDOC_INFO_1A)pDocInfo;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("StartDocPrinterA(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
|
|
|
|
|
2016-01-06 05:15:44 +00:00
|
|
|
// Only check the minimum required for accessing pDocInfo.
|
|
|
|
// Additional sanity checks are done in StartDocPrinterW.
|
|
|
|
if (!pDocInfo1)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Level != 1)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pDocInfo1->pDatatype)
|
|
|
|
{
|
|
|
|
// Convert pDocInfo1->pDatatype to a Unicode string wDocInfo1.pDatatype
|
|
|
|
cch = strlen(pDocInfo1->pDatatype);
|
|
|
|
|
|
|
|
wDocInfo1.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
|
|
|
if (!wDocInfo1.pDatatype)
|
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
ERR("HeapAlloc failed!\n");
|
2016-01-06 05:15:44 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDatatype, -1, wDocInfo1.pDatatype, cch + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pDocInfo1->pDocName)
|
|
|
|
{
|
|
|
|
// Convert pDocInfo1->pDocName to a Unicode string wDocInfo1.pDocName
|
|
|
|
cch = strlen(pDocInfo1->pDocName);
|
|
|
|
|
|
|
|
wDocInfo1.pDocName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
|
|
|
if (!wDocInfo1.pDocName)
|
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
ERR("HeapAlloc failed!\n");
|
2016-01-06 05:15:44 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDocName, -1, wDocInfo1.pDocName, cch + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pDocInfo1->pOutputFile)
|
|
|
|
{
|
|
|
|
// Convert pDocInfo1->pOutputFile to a Unicode string wDocInfo1.pOutputFile
|
|
|
|
cch = strlen(pDocInfo1->pOutputFile);
|
|
|
|
|
|
|
|
wDocInfo1.pOutputFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
|
|
|
|
if (!wDocInfo1.pOutputFile)
|
|
|
|
{
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
ERR("HeapAlloc failed!\n");
|
2016-01-06 05:15:44 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pOutputFile, -1, wDocInfo1.pOutputFile, cch + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
dwReturnValue = StartDocPrinterW(hPrinter, Level, (PBYTE)&wDocInfo1);
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (wDocInfo1.pDatatype)
|
|
|
|
HeapFree(hProcessHeap, 0, wDocInfo1.pDatatype);
|
|
|
|
|
|
|
|
if (wDocInfo1.pDocName)
|
|
|
|
HeapFree(hProcessHeap, 0, wDocInfo1.pDocName);
|
|
|
|
|
|
|
|
if (wDocInfo1.pOutputFile)
|
|
|
|
HeapFree(hProcessHeap, 0, wDocInfo1.pOutputFile);
|
|
|
|
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return dwReturnValue;
|
|
|
|
}
|
|
|
|
|
2015-06-22 14:31:47 +00:00
|
|
|
DWORD WINAPI
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
|
2015-06-22 14:31:47 +00:00
|
|
|
{
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
DWORD cbAddJobInfo1;
|
|
|
|
DWORD cbNeeded;
|
|
|
|
DWORD dwErrorCode;
|
2016-01-06 05:15:44 +00:00
|
|
|
DWORD dwReturnValue = 0;
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
PADDJOB_INFO_1W pAddJobInfo1 = NULL;
|
|
|
|
PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo;
|
|
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("StartDocPrinterW(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
// Sanity checks.
|
|
|
|
if (!pHandle)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pDocInfo1)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Level != 1)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pHandle->bStartedDoc)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_PRINTER_STATE;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if we want to redirect output into a file.
|
|
|
|
if (pDocInfo1->pOutputFile)
|
|
|
|
{
|
|
|
|
// Do a StartDocPrinter RPC call in this case.
|
|
|
|
dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Allocate memory for the ADDJOB_INFO_1W structure and a path.
|
|
|
|
cbAddJobInfo1 = sizeof(ADDJOB_INFO_1W) + MAX_PATH * sizeof(WCHAR);
|
|
|
|
pAddJobInfo1 = HeapAlloc(hProcessHeap, 0, cbAddJobInfo1);
|
|
|
|
if (!pAddJobInfo1)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
ERR("HeapAlloc failed!\n");
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to add a new job.
|
|
|
|
// This only succeeds if the printer is set to do spooled printing.
|
2015-07-17 15:11:34 +00:00
|
|
|
if (AddJobW((HANDLE)pHandle, 1, (PBYTE)pAddJobInfo1, cbAddJobInfo1, &cbNeeded))
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
{
|
|
|
|
// Do spooled printing.
|
|
|
|
dwErrorCode = _StartDocPrinterSpooled(pHandle, pDocInfo1, pAddJobInfo1);
|
|
|
|
}
|
|
|
|
else if (GetLastError() == ERROR_INVALID_ACCESS)
|
|
|
|
{
|
|
|
|
// ERROR_INVALID_ACCESS is returned when the printer is set to do direct printing.
|
|
|
|
// In this case, we do a StartDocPrinter RPC call.
|
|
|
|
dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
ERR("AddJobW failed with error %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
2016-01-06 05:15:44 +00:00
|
|
|
{
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
pHandle->bStartedDoc = TRUE;
|
2016-01-06 05:15:44 +00:00
|
|
|
dwReturnValue = pHandle->dwJobID;
|
|
|
|
}
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
if (pAddJobInfo1)
|
|
|
|
HeapFree(hProcessHeap, 0, pAddJobInfo1);
|
|
|
|
|
|
|
|
SetLastError(dwErrorCode);
|
2016-01-06 05:15:44 +00:00
|
|
|
return dwReturnValue;
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
StartPagePrinter(HANDLE hPrinter)
|
|
|
|
{
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
DWORD dwErrorCode;
|
|
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("StartPagePrinter(%p)\n", hPrinter);
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
// Sanity checks.
|
|
|
|
if (!pHandle)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the RPC call
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcStartPagePrinter(pHandle->hPrinter);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcStartPagePrinter failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
|
2015-06-22 14:31:47 +00:00
|
|
|
{
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
DWORD dwErrorCode;
|
|
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("WritePrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pcWritten);
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
// Sanity checks.
|
|
|
|
if (!pHandle)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pHandle->bStartedDoc)
|
|
|
|
{
|
|
|
|
dwErrorCode = ERROR_SPL_NO_STARTDOC;
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
|
|
|
|
{
|
|
|
|
// Write to the spool file. This doesn't need an RPC request.
|
|
|
|
if (!WriteFile(pHandle->hSPLFile, pBuf, cbBuf, pcWritten, NULL))
|
|
|
|
{
|
|
|
|
dwErrorCode = GetLastError();
|
|
|
|
ERR("WriteFile failed with error %lu!\n", dwErrorCode);
|
|
|
|
goto Cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
dwErrorCode = ERROR_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// TODO: This case (for direct printing or remote printing) has bad performance if multiple small-sized WritePrinter calls are performed.
|
|
|
|
// We may increase performance by writing into a buffer and only doing a single RPC call when the buffer is full.
|
|
|
|
|
|
|
|
// Do the RPC call
|
|
|
|
RpcTryExcept
|
|
|
|
{
|
|
|
|
dwErrorCode = _RpcWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten);
|
|
|
|
}
|
|
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
|
|
{
|
|
|
|
dwErrorCode = RpcExceptionCode();
|
|
|
|
ERR("_RpcWritePrinter failed with exception code %lu!\n", dwErrorCode);
|
|
|
|
}
|
|
|
|
RpcEndExcept;
|
|
|
|
}
|
|
|
|
|
|
|
|
Cleanup:
|
|
|
|
SetLastError(dwErrorCode);
|
|
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
2015-06-22 14:31:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
|
|
|
|
{
|
2017-12-09 11:00:09 +00:00
|
|
|
TRACE("XcvDataW(%p, %S, %p, %lu, %p, %lu, %p, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
|
2015-06-22 14:31:47 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|