mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-26 19:33:31 +00:00
[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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user