[PRINTING]

Apply a consistent style to all similar functions:
- Spoolss functions don't necessarily set ERROR_SUCCESS. Check the boolean return value instead and only query the error code on failure.
- Use AlignRpcPtr and UndoAlignRpcPtr wherever feasible.
- Use one static function per level that can be called from both Get* and Enum* APIs.
- Use PackStrings in all functions that return structures with strings.
- Add TRACEs to all non-static functions in localspl.
- Pass a double pointer to all Marshalling functions and advance to the next structure there.
- Perform sanity checks and return the right error codes in a Windows-compatible way.
- Return TRUE when an Enum* API has no elements to enumerate.

Also fixes CORE-12793

svn path=/trunk/; revision=75287
This commit is contained in:
Colin Finck
2017-07-05 15:29:13 +00:00
parent f93ac7e964
commit 4c022adf19
19 changed files with 627 additions and 491 deletions
@@ -10,7 +10,7 @@
BOOL WINAPI
EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
BOOL bReturnValue;
BOOL bReturnValue = TRUE;
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwReturned;
@@ -19,9 +19,9 @@ EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcb
PLIST_ENTRY pEntry;
// Sanity checks.
if ((cbBuf && !pMonitors) || !pcbNeeded || !pcReturned)
if (cbBuf && !pMonitors)
{
SetLastError(ERROR_INVALID_PARAMETER);
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
@@ -10,7 +10,7 @@
BOOL WINAPI
EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
BOOL bReturnValue;
BOOL bReturnValue = TRUE;
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwReturned;
@@ -19,9 +19,9 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded
PLIST_ENTRY pEntry;
// Sanity checks.
if ((cbBuf && !pPorts) || !pcbNeeded || !pcReturned)
if (cbBuf && !pPorts)
{
SetLastError(ERROR_INVALID_PARAMETER);
SetLastError(ERROR_INVALID_USER_BUFFER);
return FALSE;
}
@@ -67,7 +67,7 @@ EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cb
{
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwErrorCode = 0xFFFFFFFF;
DWORD dwErrorCode = MAXDWORD;
DWORD dwReturned;
PBYTE pCallBuffer;
PSPOOLSS_PRINT_PROVIDER pPrintProvider;
+3 -3
View File
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Print Spooler Service
* LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
* PURPOSE: Various initialization functions
* COPYRIGHT: Copyright 2015 Colin Finck <[email protected]>
* COPYRIGHT: Copyright 2015-2017 Colin Finck <[email protected]>
*/
#include "precomp.h"
@@ -21,8 +21,8 @@ _RpcSpoolerInit()
return dwErrorCode;
}
SpoolerInit();
dwErrorCode = GetLastError();
if (!SpoolerInit())
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
+58 -33
View File
@@ -2,28 +2,29 @@
* PROJECT: ReactOS Print Spooler Service
* LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
* PURPOSE: Functions for managing print jobs
* COPYRIGHT: Copyright 2015 Colin Finck <[email protected]>
* COPYRIGHT: Copyright 2015-2017 Colin Finck <[email protected]>
*/
#include "precomp.h"
static void
_MarshallDownAddJobInfo(PADDJOB_INFO_1W pAddJobInfo1)
_MarshallDownAddJobInfo(PADDJOB_INFO_1W* ppAddJobInfo1)
{
// Replace absolute pointer addresses in the output by relative offsets.
PADDJOB_INFO_1W pAddJobInfo1 = *ppAddJobInfo1;
pAddJobInfo1->Path = (PWSTR)((ULONG_PTR)pAddJobInfo1->Path - (ULONG_PTR)pAddJobInfo1);
*ppAddJobInfo1 += sizeof(ADDJOB_INFO_1W);
}
static void
_MarshallDownJobInfo(PBYTE pJobInfo, DWORD Level)
_MarshallDownJobInfo(PBYTE* ppJobInfo, DWORD Level)
{
PJOB_INFO_1W pJobInfo1;
PJOB_INFO_2W pJobInfo2;
// Replace absolute pointer addresses in the output by relative offsets.
if (Level == 1)
{
pJobInfo1 = (PJOB_INFO_1W)pJobInfo;
PJOB_INFO_1W pJobInfo1 = (PJOB_INFO_1W)(*ppJobInfo);
pJobInfo1->pDatatype = (PWSTR)((ULONG_PTR)pJobInfo1->pDatatype - (ULONG_PTR)pJobInfo1);
pJobInfo1->pDocument = (PWSTR)((ULONG_PTR)pJobInfo1->pDocument - (ULONG_PTR)pJobInfo1);
pJobInfo1->pMachineName = (PWSTR)((ULONG_PTR)pJobInfo1->pMachineName - (ULONG_PTR)pJobInfo1);
@@ -33,10 +34,13 @@ _MarshallDownJobInfo(PBYTE pJobInfo, DWORD Level)
pJobInfo1->pStatus = (PWSTR)((ULONG_PTR)pJobInfo1->pStatus - (ULONG_PTR)pJobInfo1);
pJobInfo1->pUserName = (PWSTR)((ULONG_PTR)pJobInfo1->pUserName - (ULONG_PTR)pJobInfo1);
*ppJobInfo += sizeof(JOB_INFO_1W);
}
else if (Level == 2)
{
pJobInfo2 = (PJOB_INFO_2W)pJobInfo;
PJOB_INFO_2W pJobInfo2 = (PJOB_INFO_2W)(*ppJobInfo);
pJobInfo2->pDatatype = (PWSTR)((ULONG_PTR)pJobInfo2->pDatatype - (ULONG_PTR)pJobInfo2);
pJobInfo2->pDevMode = (PDEVMODEW)((ULONG_PTR)pJobInfo2->pDevMode - (ULONG_PTR)pJobInfo2);
pJobInfo2->pDocument = (PWSTR)((ULONG_PTR)pJobInfo2->pDocument - (ULONG_PTR)pJobInfo2);
@@ -53,6 +57,8 @@ _MarshallDownJobInfo(PBYTE pJobInfo, DWORD Level)
pJobInfo2->pStatus = (PWSTR)((ULONG_PTR)pJobInfo2->pStatus - (ULONG_PTR)pJobInfo2);
pJobInfo2->pUserName = (PWSTR)((ULONG_PTR)pJobInfo2->pUserName - (ULONG_PTR)pJobInfo2);
*ppJobInfo += sizeof(JOB_INFO_2W);
}
}
@@ -60,6 +66,7 @@ DWORD
_RpcAddJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pAddJob, DWORD cbBuf, DWORD* pcbNeeded)
{
DWORD dwErrorCode;
PBYTE pAddJobAligned;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
@@ -68,13 +75,23 @@ _RpcAddJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pAddJob, DWORD c
return dwErrorCode;
}
AddJobW(hPrinter, Level, pAddJob, cbBuf, pcbNeeded);
dwErrorCode = GetLastError();
pAddJobAligned = AlignRpcPtr(pAddJob, &cbBuf);
if (dwErrorCode == ERROR_SUCCESS)
_MarshallDownAddJobInfo((PADDJOB_INFO_1W)pAddJob);
if (AddJobW(hPrinter, Level, pAddJobAligned, cbBuf, pcbNeeded))
{
PBYTE p = pAddJobAligned;
// Replace absolute pointer addresses in the output by relative offsets.
_MarshallDownAddJobInfo((PADDJOB_INFO_1W*)&p);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pAddJob, pAddJobAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
@@ -82,8 +99,7 @@ DWORD
_RpcEnumJobs(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, BYTE* pJob, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
{
DWORD dwErrorCode;
DWORD i;
PBYTE p = pJob;
PBYTE pJobAligned;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
@@ -92,24 +108,25 @@ _RpcEnumJobs(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWO
return dwErrorCode;
}
EnumJobsW(hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned);
dwErrorCode = GetLastError();
pJobAligned = AlignRpcPtr(pJob, &cbBuf);
if (dwErrorCode == ERROR_SUCCESS)
if (EnumJobsW(hPrinter, FirstJob, NoJobs, Level, pJobAligned, cbBuf, pcbNeeded, pcReturned))
{
DWORD i;
PBYTE p = pJobAligned;
// Replace absolute pointer addresses in the output by relative offsets.
for (i = 0; i < *pcReturned; i++)
{
_MarshallDownJobInfo(p, Level);
if (Level == 1)
p += sizeof(JOB_INFO_1W);
else if (Level == 2)
p += sizeof(JOB_INFO_2W);
}
_MarshallDownJobInfo(&p, Level);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pJob, pJobAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
@@ -117,6 +134,7 @@ DWORD
_RpcGetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, DWORD Level, BYTE* pJob, DWORD cbBuf, DWORD* pcbNeeded)
{
DWORD dwErrorCode;
PBYTE pJobAligned;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
@@ -125,16 +143,23 @@ _RpcGetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, DWORD Level, BYTE* pJo
return dwErrorCode;
}
GetJobW(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
dwErrorCode = GetLastError();
pJobAligned = AlignRpcPtr(pJob, &cbBuf);
if (dwErrorCode == ERROR_SUCCESS)
if (GetJobW(hPrinter, JobId, Level, pJobAligned, cbBuf, pcbNeeded))
{
PBYTE p = pJobAligned;
// Replace absolute pointer addresses in the output by relative offsets.
_MarshallDownJobInfo(pJob, Level);
_MarshallDownJobInfo(&p, Level);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pJob, pJobAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
@@ -150,8 +175,8 @@ _RpcScheduleJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId)
return dwErrorCode;
}
ScheduleJob(hPrinter, JobId);
dwErrorCode = GetLastError();
if (!ScheduleJob(hPrinter, JobId))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
@@ -170,8 +195,8 @@ _RpcSetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, WINSPOOL_JOB_CONTAINER
}
// pJobContainer->JobInfo is a union of pointers, so we can just convert any element to our BYTE pointer.
SetJobW(hPrinter, JobId, pJobContainer->Level, (PBYTE)pJobContainer->JobInfo.Level1, Command);
dwErrorCode = GetLastError();
if (!SetJobW(hPrinter, JobId, pJobContainer->Level, (PBYTE)pJobContainer->JobInfo.Level1, Command))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
@@ -2,23 +2,28 @@
* PROJECT: ReactOS Print Spooler Service
* LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
* PURPOSE: Functions related to Print Monitors
* COPYRIGHT: Copyright 2015 Colin Finck <[email protected]>
* COPYRIGHT: Copyright 2015-2017 Colin Finck <[email protected]>
*/
#include "precomp.h"
static void
_MarshallDownMonitorInfo(PBYTE pMonitorInfo, DWORD Level)
_MarshallDownMonitorInfo(PBYTE* ppMonitorInfo, DWORD Level)
{
PMONITOR_INFO_2W pMonitorInfo2 = (PMONITOR_INFO_2W)pMonitorInfo; // MONITOR_INFO_1W is a subset of MONITOR_INFO_2W
PMONITOR_INFO_2W pMonitorInfo2 = (PMONITOR_INFO_2W)(*ppMonitorInfo); // MONITOR_INFO_1W is a subset of MONITOR_INFO_2W
// Replace absolute pointer addresses in the output by relative offsets.
pMonitorInfo2->pName = (PWSTR)((ULONG_PTR)pMonitorInfo2->pName - (ULONG_PTR)pMonitorInfo2);
if (Level == 2)
if (Level == 1)
{
*ppMonitorInfo += sizeof(MONITOR_INFO_1W);
}
else
{
pMonitorInfo2->pDLLName = (PWSTR)((ULONG_PTR)pMonitorInfo2->pDLLName - (ULONG_PTR)pMonitorInfo2);
pMonitorInfo2->pEnvironment = (PWSTR)((ULONG_PTR)pMonitorInfo2->pEnvironment - (ULONG_PTR)pMonitorInfo2);
*ppMonitorInfo += sizeof(MONITOR_INFO_2W);
}
}
@@ -40,8 +45,7 @@ DWORD
_RpcEnumMonitors(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pMonitor, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
{
DWORD dwErrorCode;
DWORD i;
PBYTE p = pMonitor;
PBYTE pMonitorAligned;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
@@ -50,23 +54,24 @@ _RpcEnumMonitors(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pMonitor, DWORD cbBuf
return dwErrorCode;
}
EnumMonitorsW(pName, Level, pMonitor, cbBuf, pcbNeeded, pcReturned);
dwErrorCode = GetLastError();
pMonitorAligned = AlignRpcPtr(pMonitor, &cbBuf);
if (dwErrorCode == ERROR_SUCCESS)
if(EnumMonitorsW(pName, Level, pMonitorAligned, cbBuf, pcbNeeded, pcReturned))
{
// Replace absolute pointer addresses in the output by relative offsets.
for (i = 0; i < *pcReturned; i++)
{
_MarshallDownMonitorInfo(p, Level);
DWORD i;
PBYTE p = pMonitorAligned;
if (Level == 1)
p += sizeof(MONITOR_INFO_1W);
else if (Level == 2)
p += sizeof(MONITOR_INFO_2W);
}
for (i = 0; i < *pcReturned; i++)
_MarshallDownMonitorInfo(&p, Level);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pMonitor, pMonitorAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
+37 -20
View File
@@ -2,23 +2,40 @@
* PROJECT: ReactOS Print Spooler Service
* LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
* PURPOSE: Functions related to Ports
* COPYRIGHT: Copyright 2015 Colin Finck <[email protected]>
* COPYRIGHT: Copyright 2015-2017 Colin Finck <[email protected]>
*/
#include "precomp.h"
static void
_MarshallDownPortInfo(PBYTE pPortInfo, DWORD Level)
_MarshallDownPortInfo(PBYTE* ppPortInfo, DWORD Level)
{
PPORT_INFO_2W pPortInfo2 = (PPORT_INFO_2W)pPortInfo; // PORT_INFO_1W is a subset of PORT_INFO_2W
// Replace absolute pointer addresses in the output by relative offsets.
pPortInfo2->pPortName = (PWSTR)((ULONG_PTR)pPortInfo2->pPortName - (ULONG_PTR)pPortInfo2);
if (Level == 2)
if (Level == 1)
{
PPORT_INFO_1W pPortInfo1 = (PPORT_INFO_1W)(*ppPortInfo);
pPortInfo1->pName = (PWSTR)((ULONG_PTR)pPortInfo1->pName - (ULONG_PTR)pPortInfo1);
*ppPortInfo += sizeof(PORT_INFO_1W);
}
else if (Level == 2)
{
PPORT_INFO_2W pPortInfo2 = (PPORT_INFO_2W)(*ppPortInfo);
pPortInfo2->pPortName = (PWSTR)((ULONG_PTR)pPortInfo2->pPortName - (ULONG_PTR)pPortInfo2);
pPortInfo2->pDescription = (PWSTR)((ULONG_PTR)pPortInfo2->pDescription - (ULONG_PTR)pPortInfo2);
pPortInfo2->pMonitorName = (PWSTR)((ULONG_PTR)pPortInfo2->pMonitorName - (ULONG_PTR)pPortInfo2);
*ppPortInfo += sizeof(PORT_INFO_2W);
}
else if (Level == 3)
{
PPORT_INFO_3W pPortInfo3 = (PPORT_INFO_3W)(*ppPortInfo);
pPortInfo3->pszStatus = (PWSTR)((ULONG_PTR)pPortInfo3->pszStatus - (ULONG_PTR)pPortInfo3);
*ppPortInfo += sizeof(PORT_INFO_3W);
}
}
@@ -54,8 +71,7 @@ DWORD
_RpcEnumPorts(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pPort, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
{
DWORD dwErrorCode;
DWORD i;
PBYTE p = pPort;
PBYTE pPortAligned;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
@@ -64,24 +80,25 @@ _RpcEnumPorts(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pPort, DWORD cbBuf, DWOR
return dwErrorCode;
}
EnumPortsW(pName, Level, pPort, cbBuf, pcbNeeded, pcReturned);
dwErrorCode = GetLastError();
pPortAligned = AlignRpcPtr(pPort, &cbBuf);
if (dwErrorCode == ERROR_SUCCESS)
if (EnumPortsW(pName, Level, pPortAligned, cbBuf, pcbNeeded, pcReturned))
{
// Replace absolute pointer addresses in the output by relative offsets.
for (i = 0; i < *pcReturned; i++)
{
_MarshallDownPortInfo(p, Level);
DWORD i;
PBYTE p = pPortAligned;
if (Level == 1)
p += sizeof(PORT_INFO_1W);
else if (Level == 2)
p += sizeof(PORT_INFO_2W);
}
for (i = 0; i < *pcReturned; i++)
_MarshallDownPortInfo(&p, Level);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pPort, pPortAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
@@ -150,8 +150,8 @@ _RpcClosePrinter(WINSPOOL_PRINTER_HANDLE* phPrinter)
if (ClosePrinter(*phPrinter))
*phPrinter = NULL;
dwErrorCode = GetLastError();
else
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
@@ -176,8 +176,8 @@ _RpcEndDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
return dwErrorCode;
}
EndDocPrinter(hPrinter);
dwErrorCode = GetLastError();
if (!EndDocPrinter(hPrinter))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
@@ -195,8 +195,8 @@ _RpcEndPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
return dwErrorCode;
}
EndPagePrinter(hPrinter);
dwErrorCode = GetLastError();
if (!EndPagePrinter(hPrinter))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
@@ -216,10 +216,8 @@ _RpcEnumPrinters(DWORD Flags, WINSPOOL_HANDLE Name, DWORD Level, BYTE* pPrinterE
}
pPrinterEnumAligned = AlignRpcPtr(pPrinterEnum, &cbBuf);
EnumPrintersW(Flags, Name, Level, pPrinterEnumAligned, cbBuf, pcbNeeded, pcReturned);
dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_SUCCESS)
if (EnumPrintersW(Flags, Name, Level, pPrinterEnumAligned, cbBuf, pcbNeeded, pcReturned))
{
DWORD i;
PBYTE p = pPrinterEnumAligned;
@@ -227,6 +225,10 @@ _RpcEnumPrinters(DWORD Flags, WINSPOOL_HANDLE Name, DWORD Level, BYTE* pPrinterE
for (i = 0; i < *pcReturned; i++)
_MarshallDownPrinterInfo(&p, Level);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pPrinterEnum, pPrinterEnumAligned, cbBuf, pcbNeeded);
@@ -255,14 +257,16 @@ _RpcGetPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pPrinter, DW
}
pPrinterAligned = AlignRpcPtr(pPrinter, &cbBuf);
GetPrinterW(hPrinter, Level, pPrinterAligned, cbBuf, pcbNeeded);
dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_SUCCESS)
if (GetPrinterW(hPrinter, Level, pPrinterAligned, cbBuf, pcbNeeded))
{
PBYTE p = pPrinterAligned;
_MarshallDownPrinterInfo(&p, Level);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pPrinter, pPrinterAligned, cbBuf, pcbNeeded);
@@ -287,8 +291,8 @@ _RpcOpenPrinter(WINSPOOL_HANDLE pPrinterName, WINSPOOL_PRINTER_HANDLE* phPrinter
Default.pDatatype = pDatatype;
Default.pDevMode = (PDEVMODEW)pDevModeContainer->pDevMode;
OpenPrinterW(pPrinterName, phPrinter, &Default);
dwErrorCode = GetLastError();
if (!OpenPrinterW(pPrinterName, phPrinter, &Default))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
@@ -313,8 +317,8 @@ _RpcReadPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE* pBuf, DWORD cbBuf, DWORD
return dwErrorCode;
}
ReadPrinter(hPrinter, pBuf, cbBuf, pcNoBytesRead);
dwErrorCode = GetLastError();
if (!ReadPrinter(hPrinter, pBuf, cbBuf, pcNoBytesRead))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
@@ -379,8 +383,8 @@ _RpcStartPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
return dwErrorCode;
}
StartPagePrinter(hPrinter);
dwErrorCode = GetLastError();
if (!StartPagePrinter(hPrinter))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
@@ -398,8 +402,8 @@ _RpcWritePrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE* pBuf, DWORD cbBuf, DWOR
return dwErrorCode;
}
WritePrinter(hPrinter, pBuf, cbBuf, pcWritten);
dwErrorCode = GetLastError();
if (!WritePrinter(hPrinter, pBuf, cbBuf, pcWritten))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Print Spooler Service
* LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
* PURPOSE: Functions related to Print Processors
* COPYRIGHT: Copyright 2015 Colin Finck <[email protected]>
* COPYRIGHT: Copyright 2015-2017 Colin Finck <[email protected]>
*/
#include "precomp.h"
@@ -78,6 +78,7 @@ DWORD
_RpcEnumPrintProcessors(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pPrintProcessorInfo, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
{
DWORD dwErrorCode;
PBYTE pPrintProcessorInfoAligned;
dwErrorCode = RpcImpersonateClient(NULL);
if (dwErrorCode != ERROR_SUCCESS)
@@ -86,20 +87,25 @@ _RpcEnumPrintProcessors(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level,
return dwErrorCode;
}
EnumPrintProcessorsW(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
dwErrorCode = GetLastError();
pPrintProcessorInfoAligned = AlignRpcPtr(pPrintProcessorInfo, &cbBuf);
if (dwErrorCode == ERROR_SUCCESS)
if (EnumPrintProcessorsW(pName, pEnvironment, Level, pPrintProcessorInfoAligned, cbBuf, pcbNeeded, pcReturned))
{
// Replace absolute pointer addresses in the output by relative offsets.
DWORD i;
PPRINTPROCESSOR_INFO_1W p = (PPRINTPROCESSOR_INFO_1W)pPrintProcessorInfo;
PPRINTPROCESSOR_INFO_1W p = (PPRINTPROCESSOR_INFO_1W)pPrintProcessorInfoAligned;
for (i = 0; i < *pcReturned; i++)
_MarshallDownPrintProcessorInfo(&p);
}
else
{
dwErrorCode = GetLastError();
}
RpcRevertToSelf();
UndoAlignRpcPtr(pPrintProcessorInfo, pPrintProcessorInfoAligned, cbBuf, pcbNeeded);
return dwErrorCode;
}
@@ -115,8 +121,8 @@ _RpcGetPrintProcessorDirectory(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD
return dwErrorCode;
}
GetPrintProcessorDirectoryW(pName, pEnvironment, Level, pPrintProcessorDirectory, cbBuf, pcbNeeded);
dwErrorCode = GetLastError();
if (!GetPrintProcessorDirectoryW(pName, pEnvironment, Level, pPrintProcessorDirectory, cbBuf, pcbNeeded))
dwErrorCode = GetLastError();
RpcRevertToSelf();
return dwErrorCode;
@@ -2,16 +2,27 @@
* PROJECT: ReactOS Local Port Monitor
* LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
* PURPOSE: Functions related to ports
* COPYRIGHT: Copyright 2015 Colin Finck <[email protected]>
* COPYRIGHT: Copyright 2015-2017 Colin Finck <[email protected]>
*/
#include "precomp.h"
// Local Constants
static const WCHAR wszNonspooledPrefix[] = L"NONSPOOLED_";
static const DWORD cchNonspooledPrefix = _countof(wszNonspooledPrefix) - 1;
static DWORD dwPortInfo1Offsets[] = {
FIELD_OFFSET(PORT_INFO_1W, pName),
MAXDWORD
};
static DWORD dwPortInfo2Offsets[] = {
FIELD_OFFSET(PORT_INFO_2W, pPortName),
FIELD_OFFSET(PORT_INFO_2W, pMonitorName),
FIELD_OFFSET(PORT_INFO_2W, pDescription),
MAXDWORD
};
/**
* @name _GetNonspooledPortName
@@ -359,130 +370,60 @@ _FindPort(PLOCALMON_HANDLE pLocalmon, PCWSTR pwszPortName)
return NULL;
}
static DWORD
_LocalmonEnumPortsLevel1(PLOCALMON_HANDLE pLocalmon, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
static void
_LocalmonGetPortLevel1(PLOCALMON_PORT pPort, PPORT_INFO_1W* ppPortInfo, PBYTE* ppPortInfoEnd, PDWORD pcbNeeded)
{
DWORD cbPortName;
DWORD dwErrorCode;
DWORD dwPortCount = 0;
PBYTE pPortInfo;
PBYTE pPortString;
PLIST_ENTRY pEntry;
PLOCALMON_PORT pPort;
PORT_INFO_1W PortInfo1;
PWSTR pwszStrings[1];
// Count the required buffer size and the number of datatypes.
for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
// Calculate the string lengths.
if (!ppPortInfo)
{
pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR);
*pcbNeeded += sizeof(PORT_INFO_1W) + cbPortName;
dwPortCount++;
return;
}
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// Set the pName field.
pwszStrings[0] = pPort->pwszPortName;
// Put the strings right after the last PORT_INFO_1W structure.
pPortInfo = pPorts;
pPortString = pPorts + dwPortCount * sizeof(PORT_INFO_1W);
// Copy over all ports.
for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
{
pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
// Copy the port name.
PortInfo1.pName = (PWSTR)pPortString;
cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR);
CopyMemory(pPortString, pPort->pwszPortName, cbPortName);
pPortString += cbPortName;
// Copy the structure and advance to the next one in the output buffer.
CopyMemory(pPortInfo, &PortInfo1, sizeof(PORT_INFO_1W));
pPortInfo += sizeof(PORT_INFO_1W);
}
*pcReturned = dwPortCount;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
return dwErrorCode;
// Copy the structure and advance to the next one in the output buffer.
*ppPortInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPortInfo), dwPortInfo1Offsets, *ppPortInfoEnd);
(*ppPortInfo)++;
}
static DWORD
_LocalmonEnumPortsLevel2(PLOCALMON_HANDLE pLocalmon, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
static void
_LocalmonGetPortLevel2(PLOCALMON_PORT pPort, PPORT_INFO_2W* ppPortInfo, PBYTE* ppPortInfoEnd, PDWORD pcbNeeded)
{
DWORD cbPortName;
DWORD dwErrorCode;
DWORD dwPortCount = 0;
PBYTE pPortInfo;
PBYTE pPortString;
PLIST_ENTRY pEntry;
PLOCALMON_PORT pPort;
PORT_INFO_2W PortInfo2;
PWSTR pwszStrings[3];
// Count the required buffer size and the number of datatypes.
for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
// Calculate the string lengths.
if (!ppPortInfo)
{
pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR);
*pcbNeeded += sizeof(PORT_INFO_2W) + cbPortName + cbLocalMonitor + cbLocalPort;
dwPortCount++;
return;
}
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// All local ports are writable and readable.
(*ppPortInfo)->fPortType = PORT_TYPE_WRITE | PORT_TYPE_READ;
(*ppPortInfo)->Reserved = 0;
// Put the strings right after the last PORT_INFO_2W structure.
pPortInfo = pPorts;
pPortString = pPorts + dwPortCount * sizeof(PORT_INFO_2W);
// Set the pPortName field.
pwszStrings[0] = pPort->pwszPortName;
// Copy over all ports.
for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
{
pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
// Set the pMonitorName field.
pwszStrings[1] = (PWSTR)pwszLocalMonitor;
// All local ports are writable and readable.
PortInfo2.fPortType = PORT_TYPE_WRITE | PORT_TYPE_READ;
PortInfo2.Reserved = 0;
// Set the pDescription field.
pwszStrings[2] = (PWSTR)pwszLocalPort;
// Copy the port name.
PortInfo2.pPortName = (PWSTR)pPortString;
cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR);
CopyMemory(pPortString, pPort->pwszPortName, cbPortName);
pPortString += cbPortName;
// Copy the monitor name.
PortInfo2.pMonitorName = (PWSTR)pPortString;
CopyMemory(pPortString, pwszLocalMonitor, cbLocalMonitor);
pPortString += cbLocalMonitor;
// Copy the description.
PortInfo2.pDescription = (PWSTR)pPortString;
CopyMemory(pPortString, pwszLocalPort, cbLocalPort);
pPortString += cbLocalPort;
// Copy the structure and advance to the next one in the output buffer.
CopyMemory(pPortInfo, &PortInfo2, sizeof(PORT_INFO_2W));
pPortInfo += sizeof(PORT_INFO_2W);
}
*pcReturned = dwPortCount;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
return dwErrorCode;
// Copy the structure and advance to the next one in the output buffer.
*ppPortInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPortInfo), dwPortInfo2Offsets, *ppPortInfoEnd);
(*ppPortInfo)++;
}
/**
@@ -590,20 +531,18 @@ BOOL WINAPI
LocalmonEnumPorts(HANDLE hMonitor, PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
DWORD dwErrorCode;
PBYTE pPortInfoEnd;
PLIST_ENTRY pEntry;
PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor;
PLOCALMON_PORT pPort;
TRACE("LocalmonEnumPorts(%p, %S, %lu, %p, %lu, %p, %p)\n", hMonitor, pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
// Sanity checks
if (!pLocalmon || (cbBuf && !pPorts) || !pcbNeeded || !pcReturned)
// Windows Server 2003's Local Port Monitor does absolutely no sanity checks here, not even for the Level parameter.
// As we implement a more modern MONITOR2-based Port Monitor, check at least our hMonitor.
if (!pLocalmon)
{
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if (Level > 2)
{
dwErrorCode = ERROR_INVALID_LEVEL;
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
@@ -613,13 +552,42 @@ LocalmonEnumPorts(HANDLE hMonitor, PWSTR pName, DWORD Level, PBYTE pPorts, DWORD
EnterCriticalSection(&pLocalmon->Section);
// The function behaves differently for each level.
if (Level == 1)
dwErrorCode = _LocalmonEnumPortsLevel1(pLocalmon, pPorts, cbBuf, pcbNeeded, pcReturned);
else if (Level == 2)
dwErrorCode = _LocalmonEnumPortsLevel2(pLocalmon, pPorts, cbBuf, pcbNeeded, pcReturned);
// Count the required buffer size and the number of ports.
for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
{
pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
if (Level == 1)
_LocalmonGetPortLevel1(pPort, NULL, NULL, pcbNeeded);
else if (Level == 2)
_LocalmonGetPortLevel2(pPort, NULL, NULL, pcbNeeded);
}
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
LeaveCriticalSection(&pLocalmon->Section);
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// Copy over the Port information.
pPortInfoEnd = &pPorts[*pcbNeeded];
for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
{
pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
if (Level == 1)
_LocalmonGetPortLevel1(pPort, (PPORT_INFO_1W*)&pPorts, &pPortInfoEnd, NULL);
else if (Level == 2)
_LocalmonGetPortLevel2(pPort, (PPORT_INFO_2W*)&pPorts, &pPortInfoEnd, NULL);
(*pcReturned)++;
}
LeaveCriticalSection(&pLocalmon->Section);
dwErrorCode = ERROR_SUCCESS;
Cleanup:
SetLastError(dwErrorCode);
@@ -729,6 +697,8 @@ LocalmonOpenPort(HANDLE hMonitor, PWSTR pName, PHANDLE pHandle)
goto Cleanup;
}
EnterCriticalSection(&pLocalmon->Section);
// Check if this is a FILE: port.
if (_wcsicmp(pName, L"FILE:") == 0)
{
@@ -739,13 +709,10 @@ LocalmonOpenPort(HANDLE hMonitor, PWSTR pName, PHANDLE pHandle)
pPort->hFile = INVALID_HANDLE_VALUE;
// Add it to the list of file ports.
EnterCriticalSection(&pLocalmon->Section);
InsertTailList(&pLocalmon->FilePorts, &pPort->Entry);
}
else
{
EnterCriticalSection(&pLocalmon->Section);
// Check if the port name is valid.
pPort = _FindPort(pLocalmon, pName);
if (!pPort)
+233 -198
View File
@@ -13,6 +13,31 @@ SKIPLIST GlobalJobList;
// Local Variables
static DWORD _dwLastJobID;
// Local Constants
static DWORD dwJobInfo1Offsets[] = {
FIELD_OFFSET(JOB_INFO_1W, pPrinterName),
FIELD_OFFSET(JOB_INFO_1W, pMachineName),
FIELD_OFFSET(JOB_INFO_1W, pUserName),
FIELD_OFFSET(JOB_INFO_1W, pDocument),
FIELD_OFFSET(JOB_INFO_1W, pDatatype),
FIELD_OFFSET(JOB_INFO_1W, pStatus),
MAXDWORD
};
static DWORD dwJobInfo2Offsets[] = {
FIELD_OFFSET(JOB_INFO_2W, pPrinterName),
FIELD_OFFSET(JOB_INFO_2W, pMachineName),
FIELD_OFFSET(JOB_INFO_2W, pUserName),
FIELD_OFFSET(JOB_INFO_2W, pDocument),
FIELD_OFFSET(JOB_INFO_2W, pNotifyName),
FIELD_OFFSET(JOB_INFO_2W, pDatatype),
FIELD_OFFSET(JOB_INFO_2W, pPrintProcessor),
FIELD_OFFSET(JOB_INFO_2W, pParameters),
FIELD_OFFSET(JOB_INFO_2W, pDriverName),
FIELD_OFFSET(JOB_INFO_2W, pStatus),
MAXDWORD
};
/**
* @name _EqualStrings
@@ -135,6 +160,8 @@ _PrinterJobListCompareRoutine(PVOID FirstStruct, PVOID SecondStruct)
DWORD
GetJobFilePath(PCWSTR pwszExtension, DWORD dwJobID, PWSTR pwszOutput)
{
TRACE("GetJobFilePath(%S, %lu, %p)\n", pwszExtension, dwJobID, pwszOutput);
if (pwszOutput)
{
CopyMemory(pwszOutput, wszJobDirectory, cchJobDirectory * sizeof(WCHAR));
@@ -146,7 +173,7 @@ GetJobFilePath(PCWSTR pwszExtension, DWORD dwJobID, PWSTR pwszOutput)
}
BOOL
InitializeGlobalJobList()
InitializeGlobalJobList(void)
{
const WCHAR wszPath[] = L"\\?????.SHD";
const DWORD cchPath = _countof(wszPath) - 1;
@@ -159,6 +186,8 @@ InitializeGlobalJobList()
WCHAR wszFullPath[MAX_PATH];
WIN32_FIND_DATAW FindData;
TRACE("InitializeGlobalJobList()\n");
// This one is incremented in _GetNextJobID.
_dwLastJobID = 0;
@@ -232,6 +261,8 @@ Cleanup:
void
InitializePrinterJobList(PLOCAL_PRINTER pPrinter)
{
TRACE("InitializePrinterJobList(%p)\n", pPrinter);
// Initialize an empty list for this printer's jobs.
// This one is only for sorting the jobs. If you need to lookup a job, search the GlobalJobList by Job ID.
InitializeSkiplist(&pPrinter->JobList, DllAllocSplMem, _PrinterJobListCompareRoutine, (PSKIPLIST_FREE_ROUTINE)DllFreeSplMem);
@@ -251,6 +282,8 @@ CreateJob(PLOCAL_PRINTER_HANDLE pPrinterHandle)
RPC_WSTR pwszBinding = NULL;
RPC_WSTR pwszMachineName = NULL;
TRACE("CreateJob(%p)\n", pPrinterHandle);
// Create a new job.
pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
if (!pJob)
@@ -366,6 +399,8 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNe
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
TRACE("LocalAddJob(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pData, cbBuf, pcbNeeded);
// Check if this is a printer handle.
if (pHandle->HandleType != HandleType_Printer)
{
@@ -426,198 +461,146 @@ Cleanup:
}
static DWORD
_LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE* ppStart, PBYTE* ppEnd, DWORD cbBuf, PDWORD pcbNeeded)
static void
_LocalGetJobLevel1(PLOCAL_JOB pJob, PJOB_INFO_1W* ppJobInfo, PBYTE* ppJobInfoEnd, PDWORD pcbNeeded)
{
DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
DWORD cbDocumentName = 0;
DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
DWORD cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
DWORD cbDatatype;
DWORD cbDocumentName = 0;
DWORD cbMachineName;
DWORD cbPrinterName;
DWORD cbStatus = 0;
DWORD cbUserName = 0;
DWORD dwErrorCode;
JOB_INFO_1W JobInfo1 = { 0 };
PWSTR pwszStrings[6];
// Calculate the lengths of the optional values.
if (pJob->pwszDocumentName)
cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
if (pJob->pwszStatus)
cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
if (pJob->pwszUserName)
cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
// Check if the supplied buffer is large enough.
*pcbNeeded += sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName + cbPrinterName + cbStatus + cbUserName;
if (cbBuf < *pcbNeeded)
// Calculate the string lengths.
if (!ppJobInfo)
{
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
// These values are optional.
if (pJob->pwszDocumentName)
cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
if (pJob->pwszStatus)
cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
if (pJob->pwszUserName)
cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
*pcbNeeded += sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName + cbPrinterName + cbStatus + cbUserName;
return;
}
// Put the strings at the end of the buffer.
*ppEnd -= cbDatatype;
JobInfo1.pDatatype = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszDatatype, cbDatatype);
// Set the general fields.
(*ppJobInfo)->JobId = pJob->dwJobID;
(*ppJobInfo)->Status = pJob->dwStatus;
(*ppJobInfo)->Priority = pJob->dwPriority;
(*ppJobInfo)->TotalPages = pJob->dwTotalPages;
(*ppJobInfo)->PagesPrinted = pJob->dwPagesPrinted;
CopyMemory(&(*ppJobInfo)->Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
*ppEnd -= cbMachineName;
JobInfo1.pMachineName = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszMachineName, cbMachineName);
*ppEnd -= cbPrinterName;
JobInfo1.pPrinterName = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterName, cbPrinterName);
// Copy the optional values.
if (cbDocumentName)
// Position in JOB_INFO_1W is the 1-based index of the job in the processing queue.
// Retrieve this through the element index of the job in the Printer's Job List.
if (!LookupElementSkiplist(&pJob->pPrinter->JobList, pJob, &(*ppJobInfo)->Position))
{
*ppEnd -= cbDocumentName;
JobInfo1.pDocument = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszDocumentName, cbDocumentName);
ERR("pJob could not be located in the Printer's Job List!\n");
return;
}
if (cbStatus)
{
*ppEnd -= cbStatus;
JobInfo1.pStatus = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszStatus, cbStatus);
}
// Make the index 1-based.
++(*ppJobInfo)->Position;
if (cbUserName)
{
*ppEnd -= cbUserName;
JobInfo1.pUserName = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszUserName, cbUserName);
}
// Set the pPrinterName field.
pwszStrings[0] = pJob->pPrinter->pwszPrinterName;
// Fill the rest of the structure.
JobInfo1.JobId = pJob->dwJobID;
JobInfo1.Priority = pJob->dwPriority;
JobInfo1.Status = pJob->dwStatus;
JobInfo1.TotalPages = pJob->dwTotalPages;
CopyMemory(&JobInfo1.Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
// Set the pMachineName field.
pwszStrings[1] = pJob->pwszMachineName;
// Finally copy the structure to the output pointer.
CopyMemory(*ppStart, &JobInfo1, sizeof(JOB_INFO_1W));
*ppStart += sizeof(JOB_INFO_1W);
dwErrorCode = ERROR_SUCCESS;
// Set the pUserName field.
pwszStrings[2] = pJob->pwszUserName;
Cleanup:
return dwErrorCode;
// Set the pDocument field.
pwszStrings[3] = pJob->pwszDocumentName;
// Set the pDatatype field.
pwszStrings[4] = pJob->pwszDatatype;
// Set the pStatus field.
pwszStrings[5] = pJob->pwszStatus;
// Finally copy the structure and advance to the next one in the output buffer.
*ppJobInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppJobInfo), dwJobInfo1Offsets, *ppJobInfoEnd);
(*ppJobInfo)++;
}
static DWORD
_LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE* ppStart, PBYTE* ppEnd, DWORD cbBuf, PDWORD pcbNeeded)
static void
_LocalGetJobLevel2(PLOCAL_JOB pJob, PJOB_INFO_2W* ppJobInfo, PBYTE* ppJobInfoEnd, PDWORD pcbNeeded)
{
DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
DWORD cbDevMode = pJob->pDevMode->dmSize + pJob->pDevMode->dmDriverExtra;
DWORD cbDatatype;
DWORD cbDevMode;
DWORD cbDocumentName = 0;
DWORD cbDriverName = (wcslen(pJob->pPrinter->pwszPrinterDriver) + 1) * sizeof(WCHAR);
DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
DWORD cbDriverName;
DWORD cbMachineName;
DWORD cbNotifyName = 0;
DWORD cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
DWORD cbPrintProcessor = (wcslen(pJob->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
DWORD cbPrinterName;
DWORD cbPrintProcessor;
DWORD cbPrintProcessorParameters = 0;
DWORD cbStatus = 0;
DWORD cbUserName = 0;
DWORD dwErrorCode;
FILETIME ftNow;
FILETIME ftSubmitted;
JOB_INFO_2W JobInfo2 = { 0 };
PWSTR pwszStrings[10];
ULARGE_INTEGER uliNow;
ULARGE_INTEGER uliSubmitted;
// Calculate the lengths of the optional values.
if (pJob->pwszDocumentName)
cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
// Calculate the string lengths.
cbDevMode = pJob->pDevMode->dmSize + pJob->pDevMode->dmDriverExtra;
if (pJob->pwszNotifyName)
cbNotifyName = (wcslen(pJob->pwszNotifyName) + 1) * sizeof(WCHAR);
if (pJob->pwszPrintProcessorParameters)
cbPrintProcessorParameters = (wcslen(pJob->pwszPrintProcessorParameters) + 1) * sizeof(WCHAR);
if (pJob->pwszStatus)
cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
if (pJob->pwszUserName)
cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
// Check if the supplied buffer is large enough.
*pcbNeeded += sizeof(JOB_INFO_2W) + cbDatatype + cbDevMode + cbDocumentName + cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor + cbPrintProcessorParameters + cbStatus + cbUserName;
if (cbBuf < *pcbNeeded)
if (!ppJobInfo)
{
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
cbDriverName = (wcslen(pJob->pPrinter->pwszPrinterDriver) + 1) * sizeof(WCHAR);
cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
cbPrintProcessor = (wcslen(pJob->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
// These values are optional.
if (pJob->pwszDocumentName)
cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
if (pJob->pwszNotifyName)
cbNotifyName = (wcslen(pJob->pwszNotifyName) + 1) * sizeof(WCHAR);
if (pJob->pwszPrintProcessorParameters)
cbPrintProcessorParameters = (wcslen(pJob->pwszPrintProcessorParameters) + 1) * sizeof(WCHAR);
if (pJob->pwszStatus)
cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
if (pJob->pwszUserName)
cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
*pcbNeeded += sizeof(JOB_INFO_2W) + cbDatatype + cbDevMode + cbDocumentName + cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor + cbPrintProcessorParameters + cbStatus + cbUserName;
return;
}
// Put the strings at the end of the buffer.
*ppEnd -= cbDatatype;
JobInfo2.pDatatype = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszDatatype, cbDatatype);
*ppEnd -= cbDevMode;
JobInfo2.pDevMode = (PDEVMODEW)*ppEnd;
CopyMemory(*ppEnd, pJob->pDevMode, cbDevMode);
*ppEnd -= cbDriverName;
JobInfo2.pDriverName = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterDriver, cbDriverName);
*ppEnd -= cbMachineName;
JobInfo2.pMachineName = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszMachineName, cbMachineName);
*ppEnd -= cbPrinterName;
JobInfo2.pPrinterName = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterName, cbPrinterName);
*ppEnd -= cbPrintProcessor;
JobInfo2.pPrintProcessor = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pPrintProcessor->pwszName, cbPrintProcessor);
// Copy the optional values.
if (cbDocumentName)
{
*ppEnd -= cbDocumentName;
JobInfo2.pDocument = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszDocumentName, cbDocumentName);
}
if (cbNotifyName)
{
*ppEnd -= cbNotifyName;
JobInfo2.pNotifyName = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszNotifyName, cbNotifyName);
}
if (cbPrintProcessorParameters)
{
*ppEnd -= cbPrintProcessorParameters;
JobInfo2.pParameters = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszPrintProcessorParameters, cbPrintProcessorParameters);
}
if (cbStatus)
{
*ppEnd -= cbStatus;
JobInfo2.pStatus = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszStatus, cbStatus);
}
if (cbUserName)
{
*ppEnd -= cbUserName;
JobInfo2.pUserName = (PWSTR)*ppEnd;
CopyMemory(*ppEnd, pJob->pwszUserName, cbUserName);
}
// Set the general fields.
(*ppJobInfo)->JobId = pJob->dwJobID;
(*ppJobInfo)->Status = pJob->dwStatus;
(*ppJobInfo)->Priority = pJob->dwPriority;
(*ppJobInfo)->StartTime = pJob->dwStartTime;
(*ppJobInfo)->UntilTime = pJob->dwUntilTime;
(*ppJobInfo)->TotalPages = pJob->dwTotalPages;
(*ppJobInfo)->PagesPrinted = pJob->dwPagesPrinted;
CopyMemory(&(*ppJobInfo)->Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
// Time in JOB_INFO_2W is the number of milliseconds elapsed since the job was submitted. Calculate this time.
if (!SystemTimeToFileTime(&pJob->stSubmitted, &ftSubmitted))
{
ERR("SystemTimeToFileTime failed with error %lu!\n", GetLastError());
return FALSE;
return;
}
GetSystemTimeAsFileTime(&ftNow);
@@ -625,37 +608,62 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE*
uliSubmitted.HighPart = ftSubmitted.dwHighDateTime;
uliNow.LowPart = ftNow.dwLowDateTime;
uliNow.HighPart = ftNow.dwHighDateTime;
JobInfo2.Time = (DWORD)((uliNow.QuadPart - uliSubmitted.QuadPart) / 10000);
(*ppJobInfo)->Time = (DWORD)((uliNow.QuadPart - uliSubmitted.QuadPart) / 10000);
// Position in JOB_INFO_2W is the 1-based index of the job in the processing queue.
// Retrieve this through the element index of the job in the Printer's Job List.
if (!LookupElementSkiplist(&pJob->pPrinter->JobList, pJob, &JobInfo2.Position))
if (!LookupElementSkiplist(&pJob->pPrinter->JobList, pJob, &(*ppJobInfo)->Position))
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("pJob could not be located in the Printer's Job List!\n");
goto Cleanup;
return;
}
// Make the index 1-based.
++JobInfo2.Position;
++(*ppJobInfo)->Position;
// Fill the rest of the structure.
JobInfo2.JobId = pJob->dwJobID;
JobInfo2.PagesPrinted = pJob->dwPagesPrinted;
JobInfo2.Priority = pJob->dwPriority;
JobInfo2.StartTime = pJob->dwStartTime;
JobInfo2.Status = pJob->dwStatus;
JobInfo2.TotalPages = pJob->dwTotalPages;
JobInfo2.UntilTime = pJob->dwUntilTime;
CopyMemory(&JobInfo2.Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
// FIXME!
FIXME("Setting pSecurityDescriptor and Size to 0 for now!\n");
(*ppJobInfo)->pSecurityDescriptor = NULL;
(*ppJobInfo)->Size = 0;
// Finally copy the structure to the output pointer.
CopyMemory(*ppStart, &JobInfo2, sizeof(JOB_INFO_2W));
*ppStart += sizeof(JOB_INFO_2W);
dwErrorCode = ERROR_SUCCESS;
// Set the pDevMode field (and copy the DevMode).
*ppJobInfoEnd -= cbDevMode;
CopyMemory(*ppJobInfoEnd, pJob->pDevMode, cbDevMode);
(*ppJobInfo)->pDevMode = (PDEVMODEW)(*ppJobInfoEnd);
Cleanup:
return dwErrorCode;
// Set the pPrinterName field.
pwszStrings[0] = pJob->pPrinter->pwszPrinterName;
// Set the pMachineName field.
pwszStrings[1] = pJob->pwszMachineName;
// Set the pUserName field.
pwszStrings[2] = pJob->pwszUserName;
// Set the pDocument field.
pwszStrings[3] = pJob->pwszDocumentName;
// Set the pNotifyName field.
pwszStrings[4] = pJob->pwszNotifyName;
// Set the pDatatype field.
pwszStrings[5] = pJob->pwszDatatype;
// Set the pPrintProcessor field.
pwszStrings[6] = pJob->pPrintProcessor->pwszName;
// Set the pParameters field.
pwszStrings[7] = pJob->pwszPrintProcessorParameters;
// Set the pDriverName field.
pwszStrings[8] = pJob->pPrinter->pwszPrinterDriver;
// Set the pStatus field.
pwszStrings[9] = pJob->pwszStatus;
// Finally copy the structure and advance to the next one in the output buffer.
*ppJobInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppJobInfo), dwJobInfo2Offsets, *ppJobInfoEnd);
(*ppJobInfo)++;
}
BOOL WINAPI
@@ -667,6 +675,8 @@ LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf
PLOCAL_JOB pJob;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
TRACE("LocalGetJob(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, JobId, Level, pStart, cbBuf, pcbNeeded);
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != HandleType_Printer)
@@ -685,16 +695,37 @@ LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf
goto Cleanup;
}
// Begin counting.
if (Level > 2)
{
// The caller supplied an invalid level for GetJob.
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
// Count the required buffer size.
*pcbNeeded = 0;
// The function behaves differently for each level.
if (Level == 1)
dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded);
_LocalGetJobLevel1(pJob, NULL, NULL, pcbNeeded);
else if (Level == 2)
dwErrorCode = _LocalGetJobLevel2(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded);
else
dwErrorCode = ERROR_INVALID_LEVEL;
_LocalGetJobLevel2(pJob, NULL, NULL, pcbNeeded);
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// Copy over the Job information.
pEnd = &pStart[*pcbNeeded];
if (Level == 1)
_LocalGetJobLevel1(pJob, (PJOB_INFO_1W*)&pStart, &pEnd, NULL);
else if (Level == 2)
_LocalGetJobLevel2(pJob, (PJOB_INFO_2W*)&pStart, &pEnd, NULL);
dwErrorCode = ERROR_SUCCESS;
Cleanup:
SetLastError(dwErrorCode);
@@ -938,6 +969,8 @@ LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Com
PLOCAL_PRINTER_HANDLE pPrinterHandle;
WCHAR wszFullPath[MAX_PATH];
TRACE("LocalSetJob(%p, %lu, %lu, %p, %lu)\n", hPrinter, JobId, Level, pJobInfo, Command);
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != HandleType_Printer)
@@ -1012,13 +1045,15 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
{
DWORD dwErrorCode;
DWORD i;
PBYTE pEnd = &pStart[cbBuf];
PBYTE pEnd;
PLOCAL_HANDLE pHandle;
PLOCAL_JOB pJob;
PSKIPLIST_NODE pFirstJobNode;
PSKIPLIST_NODE pNode;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
TRACE("LocalEnumJobs(%p, %lu, %lu, %lu, %p, %lu, %p, %p)\n", hPrinter, FirstJob, NoJobs, Level, pStart, cbBuf, pcbNeeded, pcReturned);
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != HandleType_Printer)
@@ -1051,11 +1086,10 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
{
pJob = (PLOCAL_JOB)pNode->Element;
// The function behaves differently for each level.
if (Level == 1)
_LocalGetJobLevel1(pPrinterHandle, pJob, NULL, NULL, 0, pcbNeeded);
_LocalGetJobLevel1(pJob, NULL, NULL, pcbNeeded);
else if (Level == 2)
_LocalGetJobLevel2(pPrinterHandle, pJob, NULL, NULL, 0, pcbNeeded);
_LocalGetJobLevel2(pJob, NULL, NULL, pcbNeeded);
// We stop either when there are no more jobs in the list or when the caller didn't request more, whatever comes first.
i++;
@@ -1069,26 +1103,19 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
goto Cleanup;
}
// Begin counting again and also empty the given buffer.
*pcbNeeded = 0;
ZeroMemory(pStart, cbBuf);
// Now call the same functions again to copy the actual data for each job into the buffer.
// Copy over the Job information.
i = 0;
pNode = pFirstJobNode;
pEnd = &pStart[*pcbNeeded];
while (i < NoJobs && pNode)
{
pJob = (PLOCAL_JOB)pNode->Element;
// The function behaves differently for each level.
if (Level == 1)
dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded);
_LocalGetJobLevel1(pJob, (PJOB_INFO_1W*)&pStart, &pEnd, NULL);
else if (Level == 2)
dwErrorCode = _LocalGetJobLevel2(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded);
if (dwErrorCode != ERROR_SUCCESS)
goto Cleanup;
_LocalGetJobLevel2(pJob, (PJOB_INFO_2W*)&pStart, &pEnd, NULL);
// We stop either when there are no more jobs in the list or when the caller didn't request more, whatever comes first.
i++;
@@ -1114,6 +1141,8 @@ LocalScheduleJob(HANDLE hPrinter, DWORD dwJobID)
PLOCAL_PRINTER_HANDLE pPrinterHandle;
WCHAR wszFullPath[MAX_PATH];
TRACE("LocalScheduleJob(%p, %lu)\n", hPrinter, dwJobID);
// Check if this is a printer handle.
if (pHandle->HandleType != HandleType_Printer)
{
@@ -1190,6 +1219,8 @@ ReadJobShadowFile(PCWSTR pwszFilePath)
PWSTR pwszPrinterName;
PWSTR pwszPrintProcessor;
TRACE("ReadJobShadowFile(%S)\n", pwszFilePath);
// Try to open the file.
hFile = CreateFileW(pwszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
@@ -1308,6 +1339,8 @@ WriteJobShadowFile(PWSTR pwszFilePath, const PLOCAL_JOB pJob)
HANDLE hSPLFile = INVALID_HANDLE_VALUE;
PSHD_HEADER pShadowFile = NULL;
TRACE("WriteJobShadowFile(%S, %p)\n", pwszFilePath, pJob);
// Try to open the SHD file.
hSHDFile = CreateFileW(pwszFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if (hSHDFile == INVALID_HANDLE_VALUE)
@@ -1441,7 +1474,9 @@ void
FreeJob(PLOCAL_JOB pJob)
{
PWSTR pwszSHDFile;
TRACE("FreeJob(%p)\n", pJob);
// Remove the Job from both Job Lists.
DeleteElementSkiplist(&pJob->pPrinter->JobList, pJob);
DeleteElementSkiplist(&GlobalJobList, pJob);
@@ -245,6 +245,8 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
BOOL WINAPI
InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, LPWSTR pFullRegistryPath)
{
TRACE("InitializePrintProvidor(%p, %lu, %S)\n", pPrintProvidor, cbPrintProvidor, pFullRegistryPath);
CopyMemory(pPrintProvidor, &_PrintProviderFunctions, min(cbPrintProvidor, sizeof(PRINTPROVIDOR)));
SetLastError(ERROR_SUCCESS);
@@ -10,6 +10,19 @@
// Global Variables
LIST_ENTRY PrintMonitorList;
// Local Constants
static DWORD dwMonitorInfo1Offsets[] = {
FIELD_OFFSET(MONITOR_INFO_1W, pName),
MAXDWORD
};
static DWORD dwMonitorInfo2Offsets[] = {
FIELD_OFFSET(MONITOR_INFO_2W, pName),
FIELD_OFFSET(MONITOR_INFO_2W, pEnvironment),
FIELD_OFFSET(MONITOR_INFO_2W, pDLLName),
MAXDWORD
};
PLOCAL_PRINT_MONITOR
FindPrintMonitor(PCWSTR pwszName)
@@ -17,6 +30,8 @@ FindPrintMonitor(PCWSTR pwszName)
PLIST_ENTRY pEntry;
PLOCAL_PRINT_MONITOR pPrintMonitor;
TRACE("FindPrintMonitor(%S)\n", pwszName);
if (!pwszName)
return NULL;
@@ -32,7 +47,7 @@ FindPrintMonitor(PCWSTR pwszName)
}
BOOL
InitializePrintMonitorList()
InitializePrintMonitorList(void)
{
const WCHAR wszMonitorsPath[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors";
const DWORD cchMonitorsPath = _countof(wszMonitorsPath) - 1;
@@ -51,6 +66,8 @@ InitializePrintMonitorList()
PLOCAL_PRINT_MONITOR pPrintMonitor = NULL;
PWSTR pwszRegistryPath = NULL;
TRACE("InitializePrintMonitorList()\n");
// Initialize an empty list for our Print Monitors.
InitializeListHead(&PrintMonitorList);
@@ -236,17 +253,69 @@ Cleanup:
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
static void
_LocalGetMonitorLevel1(PLOCAL_PRINT_MONITOR pPrintMonitor, PMONITOR_INFO_1W* ppMonitorInfo, PBYTE* ppMonitorInfoEnd, PDWORD pcbNeeded)
{
DWORD cbMonitorName;
PWSTR pwszStrings[1];
// Calculate the string lengths.
if (!ppMonitorInfo)
{
cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR);
*pcbNeeded += sizeof(MONITOR_INFO_1W) + cbMonitorName;
return;
}
// Set the pName field.
pwszStrings[0] = pPrintMonitor->pwszName;
// Copy the structure and advance to the next one in the output buffer.
*ppMonitorInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppMonitorInfo), dwMonitorInfo1Offsets, *ppMonitorInfoEnd);
(*ppMonitorInfo)++;
}
static void
_LocalGetMonitorLevel2(PLOCAL_PRINT_MONITOR pPrintMonitor, PMONITOR_INFO_2W* ppMonitorInfo, PBYTE* ppMonitorInfoEnd, PDWORD pcbNeeded)
{
DWORD cbFileName;
DWORD cbMonitorName;
PWSTR pwszStrings[3];
// Calculate the string lengths.
if (!ppMonitorInfo)
{
cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR);
cbFileName = (wcslen(pPrintMonitor->pwszFileName) + 1) * sizeof(WCHAR);
*pcbNeeded += sizeof(MONITOR_INFO_2W) + cbMonitorName + cbCurrentEnvironment + cbFileName;
return;
}
// Set the pName field.
pwszStrings[0] = pPrintMonitor->pwszName;
// Set the pEnvironment field.
pwszStrings[1] = (PWSTR)wszCurrentEnvironment;
// Set the pDLLName field.
pwszStrings[2] = pPrintMonitor->pwszFileName;
// Copy the structure and advance to the next one in the output buffer.
*ppMonitorInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppMonitorInfo), dwMonitorInfo2Offsets, *ppMonitorInfoEnd);
(*ppMonitorInfo)++;
}
BOOL WINAPI
LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
DWORD dwErrorCode;
PBYTE pStart;
PBYTE pEnd;
PBYTE pMonitorInfoEnd;
PLIST_ENTRY pEntry;
PLOCAL_PRINT_MONITOR pPrintMonitor;
MONITOR_INFO_2W MonitorInfo2; // MONITOR_INFO_1W is a subset of MONITOR_INFO_2W, so we can handle both in one function here.
TRACE("LocalEnumMonitors(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
// Sanity checks.
if (Level > 2)
@@ -255,12 +324,6 @@ LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD
goto Cleanup;
}
if ((cbBuf && !pMonitors) || !pcbNeeded || !pcReturned)
{
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// Begin counting.
*pcbNeeded = 0;
*pcReturned = 0;
@@ -270,13 +333,10 @@ LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD
{
pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry);
cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR);
cbFileName = (wcslen(pPrintMonitor->pwszFileName) + 1) * sizeof(WCHAR);
if (Level == 1)
*pcbNeeded += sizeof(MONITOR_INFO_1W) + cbMonitorName;
else
*pcbNeeded += sizeof(MONITOR_INFO_2W) + cbMonitorName + cbCurrentEnvironment + cbFileName;
_LocalGetMonitorLevel1(pPrintMonitor, NULL, NULL, pcbNeeded);
else if (Level == 2)
_LocalGetMonitorLevel2(pPrintMonitor, NULL, NULL, pcbNeeded);
}
// Check if the supplied buffer is large enough.
@@ -286,43 +346,17 @@ LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD
goto Cleanup;
}
// Put the strings at the end of the buffer.
pStart = pMonitors;
pEnd = &pMonitors[cbBuf];
// Copy over the Monitor information.
pMonitorInfoEnd = &pMonitors[*pcbNeeded];
for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink)
{
pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry);
// Copy the monitor name.
cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR);
pEnd -= cbMonitorName;
MonitorInfo2.pName = (PWSTR)pEnd;
CopyMemory(pEnd, pPrintMonitor->pwszName, cbMonitorName);
if (Level == 1)
{
// Finally copy the structure.
CopyMemory(pStart, &MonitorInfo2, sizeof(MONITOR_INFO_1W));
pStart += sizeof(MONITOR_INFO_1W);
}
else
{
// Copy the environment.
pEnd -= cbCurrentEnvironment;
MonitorInfo2.pEnvironment = (PWSTR)pEnd;
CopyMemory(pEnd, wszCurrentEnvironment, cbCurrentEnvironment);
// Copy the file name.
cbFileName = (wcslen(pPrintMonitor->pwszFileName) + 1) * sizeof(WCHAR);
pEnd -= cbFileName;
MonitorInfo2.pDLLName = (PWSTR)pEnd;
CopyMemory(pEnd, pPrintMonitor->pwszFileName, cbFileName);
// Finally copy the structure.
CopyMemory(pStart, &MonitorInfo2, sizeof(MONITOR_INFO_2W));
pStart += sizeof(MONITOR_INFO_2W);
}
_LocalGetMonitorLevel1(pPrintMonitor, (PMONITOR_INFO_1W*)&pMonitors, &pMonitorInfoEnd, NULL);
else if (Level == 2)
_LocalGetMonitorLevel2(pPrintMonitor, (PMONITOR_INFO_2W*)&pMonitors, &pMonitorInfoEnd, NULL);
(*pcReturned)++;
}
@@ -17,6 +17,8 @@ FindPort(PCWSTR pwszName)
PLIST_ENTRY pEntry;
PLOCAL_PORT pPort;
TRACE("FindPort(%S)\n", pwszName);
if (!pwszName)
return NULL;
@@ -32,7 +34,7 @@ FindPort(PCWSTR pwszName)
}
BOOL
InitializePortList()
InitializePortList(void)
{
BOOL bReturnValue;
DWORD cbNeeded;
@@ -46,6 +48,8 @@ InitializePortList()
PPORT_INFO_1W p;
PPORT_INFO_1W pPortInfo1 = NULL;
TRACE("InitializePortList()\n");
// Initialize an empty list for our Ports.
InitializeListHead(&_PortList);
@@ -136,7 +140,7 @@ Cleanup:
BOOL WINAPI
LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
{
BOOL bReturnValue;
BOOL bReturnValue = TRUE;
DWORD cbCallBuffer;
DWORD cbNeeded;
DWORD dwReturned;
@@ -144,12 +148,7 @@ LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNe
PLOCAL_PRINT_MONITOR pPrintMonitor;
PLIST_ENTRY pEntry;
// Sanity checks.
if ((cbBuf && !pPorts) || !pcbNeeded || !pcReturned)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
TRACE("LocalEnumPorts(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
// Begin counting.
*pcbNeeded = 0;
@@ -273,12 +273,12 @@ extern DWORD cchSpoolDirectory;
// monitors.c
extern LIST_ENTRY PrintMonitorList;
PLOCAL_PRINT_MONITOR FindPrintMonitor(PCWSTR pwszName);
BOOL InitializePrintMonitorList();
BOOL InitializePrintMonitorList(void);
BOOL WINAPI LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
// ports.c
PLOCAL_PORT FindPort(PCWSTR pwszName);
BOOL InitializePortList();
BOOL InitializePortList(void);
BOOL WINAPI LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
// printerdata.c
@@ -289,7 +289,7 @@ DWORD WINAPI LocalSetPrinterDataEx(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pV
// printers.c
extern SKIPLIST PrinterList;
BOOL InitializePrinterList();
BOOL InitializePrinterList(void);
BOOL WINAPI LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
BOOL WINAPI LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded);
BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault);
@@ -307,7 +307,7 @@ DWORD WINAPI PrintingThreadProc(PLOCAL_JOB pJob);
// printprocessors.c
BOOL FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype);
PLOCAL_PRINT_PROCESSOR FindPrintProcessor(PCWSTR pwszName);
BOOL InitializePrintProcessorList();
BOOL InitializePrintProcessorList(void);
BOOL WINAPI LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
BOOL WINAPI LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
BOOL WINAPI LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded);
@@ -10,6 +10,8 @@
DWORD WINAPI
LocalGetPrinterData(HANDLE hPrinter, PWSTR pValueName, PDWORD pType, PBYTE pData, DWORD nSize, PDWORD pcbNeeded)
{
TRACE("LocalGetPrinterData(%p, %S, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
// The ReactOS Printing Stack forwards all GetPrinterData calls to GetPrinterDataEx as soon as possible.
// This function may only be called if localspl.dll is used together with Windows Printing Stack components.
WARN("This function should never be called!\n");
@@ -316,6 +318,8 @@ LocalGetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName, PDWOR
DWORD dwTemp;
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
TRACE("LocalGetPrinterDataEx(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
// Even if GetPrinterDataExW in winspool ensures that the RPC function is never called without a valid pointer for pType,
// it's officially optional. Windows' fpGetPrinterDataEx also works with NULL for pType!
// Ensure here that it is always set to simplify the code later.
@@ -356,6 +360,8 @@ LocalGetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName, PDWOR
DWORD WINAPI
LocalSetPrinterData(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
{
TRACE("LocalSetPrinterData(%p, %S, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
// The ReactOS Printing Stack forwards all SetPrinterData calls to SetPrinterDataEx as soon as possible.
// This function may only be called if localspl.dll is used together with Windows Printing Stack components.
WARN("This function should never be called!\n");
@@ -446,6 +452,8 @@ LocalSetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName, DWORD
DWORD dwErrorCode;
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
TRACE("LocalSetPrinterDataEx(%p, %S, %S, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
if (!pHandle)
{
dwErrorCode = ERROR_INVALID_HANDLE;
@@ -119,6 +119,8 @@ InitializePrinterList()
PWSTR pwszPrintProcessor = NULL;
WCHAR wszPrinterName[MAX_PRINTER_NAME + 1];
TRACE("InitializePrinterList()\n");
// Initialize an empty list for our printers.
InitializeSkiplist(&PrinterList, DllAllocSplMem, _PrinterListCompareRoutine, (PSKIPLIST_FREE_ROUTINE)DllFreeSplMem);
@@ -864,12 +866,13 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
{
DWORD cchComputerName = 0;
DWORD dwErrorCode;
DWORD i;
PBYTE pPrinterInfoEnd;
PSKIPLIST_NODE pNode;
WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1] = { 0 };
PLOCAL_PRINTER pPrinter;
TRACE("LocalEnumPrinters(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
// Do no sanity checks or assertions for pcbNeeded and pcReturned here.
// This is verified and required by localspl_apitest!
@@ -916,7 +919,6 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
goto Cleanup;
// Count the required buffer size and the number of printers.
i = 0;
for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
{
pPrinter = (PLOCAL_PRINTER)pNode->Element;
@@ -929,7 +931,6 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
}
pfnGetPrinterLevels[Level](pPrinter, NULL, NULL, pcbNeeded, cchComputerName, wszComputerName);
i++;
}
// Check if the supplied buffer is large enough.
@@ -951,9 +952,9 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
continue;
pfnGetPrinterLevels[Level](pPrinter, &pPrinterEnum, &pPrinterInfoEnd, NULL, cchComputerName, wszComputerName);
(*pcReturned)++;
}
*pcReturned = i;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
@@ -969,6 +970,8 @@ LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDW
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
TRACE("LocalGetPrinter(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
// Sanity checks.
if (!pHandle)
{
@@ -993,6 +996,7 @@ LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDW
}
// Count the required buffer size.
*pcbNeeded = 0;
pfnGetPrinterLevels[Level](pPrinterHandle->pPrinter, NULL, NULL, pcbNeeded, 0, NULL);
// Check if the supplied buffer is large enough.
@@ -1363,6 +1367,8 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
PWSTR pwszSecondParameter;
WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
TRACE("LocalOpenPrinter(%S, %p, %p)\n", lpPrinterName, phPrinter, pDefault);
ASSERT(phPrinter);
*phPrinter = NULL;
@@ -1494,6 +1500,8 @@ LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
PLOCAL_PORT_HANDLE pPortHandle;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
TRACE("LocalReadPrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pNoBytesRead);
// Sanity checks.
if (!pHandle)
{
@@ -1568,6 +1576,8 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
PLOCAL_PORT_HANDLE pPortHandle;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
TRACE("LocalStartDocPrinter(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
// Sanity checks.
if (!pHandle)
{
@@ -1678,6 +1688,8 @@ LocalStartPagePrinter(HANDLE hPrinter)
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
TRACE("LocalStartPagePrinter(%p)\n", hPrinter);
// Sanity checks.
if (!pHandle || pHandle->HandleType != HandleType_Printer)
{
@@ -1712,6 +1724,8 @@ LocalWritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
PLOCAL_PORT_HANDLE pPortHandle;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
TRACE("LocalWritePrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pcWritten);
// Sanity checks.
if (!pHandle)
{
@@ -1783,6 +1797,8 @@ LocalEndPagePrinter(HANDLE hPrinter)
DWORD dwErrorCode;
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
TRACE("LocalEndPagePrinter(%p)\n", hPrinter);
// Sanity checks.
if (!pHandle || pHandle->HandleType != HandleType_Printer)
{
@@ -1807,6 +1823,8 @@ LocalEndDocPrinter(HANDLE hPrinter)
PLOCAL_PORT_HANDLE pPortHandle;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
TRACE("LocalEndDocPrinter(%p)\n", hPrinter);
// Sanity checks.
if (!pHandle)
{
@@ -1902,6 +1920,8 @@ LocalClosePrinter(HANDLE hPrinter)
{
PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
TRACE("LocalClosePrinter(%p)\n", hPrinter);
if (!pHandle)
{
SetLastError(ERROR_INVALID_HANDLE);
@@ -25,6 +25,8 @@ PrintingThreadProc(PLOCAL_JOB pJob)
PWSTR pwszPrinterPort = NULL;
PWSTR pwszSPLFile = NULL;
TRACE("PrintingThreadProc(%p)\n", pJob);
// Prepare the pPrinterName parameter.
// This is the string for LocalOpenPrinter to open a port (e.g. "LPT1:, Port").
cchPortName = wcslen(pJob->pPrinter->pPort->pwszName);
@@ -82,6 +82,8 @@ FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype)
DWORD i;
PDATATYPES_INFO_1W pCurrentDatatype = pPrintProcessor->pDatatypesInfo1;
TRACE("FindDatatype(%p, %S)\n", pPrintProcessor, pwszDatatype);
if (!pwszDatatype)
return FALSE;
@@ -102,6 +104,8 @@ FindPrintProcessor(PCWSTR pwszName)
PLIST_ENTRY pEntry;
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
TRACE("FindPrintProcessor(%S)\n", pwszName);
if (!pwszName)
return NULL;
@@ -122,7 +126,7 @@ FindPrintProcessor(PCWSTR pwszName)
* Initializes a singly linked list of locally available Print Processors.
*/
BOOL
InitializePrintProcessorList()
InitializePrintProcessorList(void)
{
DWORD cbDatatypes;
DWORD cbFileName;
@@ -140,6 +144,8 @@ InitializePrintProcessorList()
WCHAR wszFileName[MAX_PATH];
WCHAR wszPrintProcessorPath[MAX_PATH];
TRACE("InitializePrintProcessorList()\n");
// Initialize an empty list for our Print Processors.
InitializeListHead(&_PrintProcessorList);
@@ -398,6 +404,8 @@ LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD
DWORD dwErrorCode;
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
TRACE("LocalEnumPrintProcessorDatatypes(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
// Sanity checks
if (Level != 1)
{
@@ -474,6 +482,8 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
PRINTPROCESSOR_INFO_1W PrintProcessorInfo1;
PWSTR pwszTemp = NULL;
TRACE("LocalEnumPrintProcessors(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
// Sanity checks
if (Level != 1)
{
@@ -630,6 +640,8 @@ LocalGetPrintProcessorDirectory(PWSTR pName, PWSTR pEnvironment, DWORD Level, PB
HKEY hKey = NULL;
PWSTR pwszDirectory = (PWSTR)pPrintProcessorInfo;
TRACE("LocalGetPrintProcessorDirectory(%S, %S, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded);
// Verify pEnvironment and open its registry key.
dwErrorCode = _OpenEnvironment(pEnvironment, &hKey);
if (dwErrorCode != ERROR_SUCCESS)