3757 lines
79 KiB
C
3757 lines
79 KiB
C
/*++
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
yspool.c
|
|
|
|
Abstract:
|
|
|
|
This module provides all the public exported APIs relating to Printer
|
|
and Job management for the Print Providor Routing layer
|
|
|
|
Author:
|
|
|
|
Dave Snipp (DaveSn) 15-Mar-1991
|
|
|
|
[Notes:]
|
|
|
|
optional-notes
|
|
|
|
Revision History:
|
|
|
|
swilson 1-Jun-95 Converted winspool.c to yspool: the merging point of KM & RPC paths
|
|
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <rpc.h>
|
|
#include <winspool.h>
|
|
#include <winsprlp.h>
|
|
#include <winsplp.h>
|
|
#include <winspl.h>
|
|
#include <offsets.h>
|
|
#include "server.h"
|
|
#include "client.h"
|
|
#include "yspool.h"
|
|
#include "clusrout.h"
|
|
|
|
LPWSTR szNull = L"";
|
|
|
|
BOOL
|
|
OldGetPrinterDriverW(
|
|
HANDLE hPrinter,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pDriverInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded
|
|
);
|
|
|
|
|
|
|
|
#define YRevertToSelf(rpc) (rpc != NATIVE_CALL ? RpcRevertToSelf() : 0)
|
|
|
|
DWORD ServerHandleCount = 0;
|
|
|
|
BOOL
|
|
YImpersonateClient(CALL_ROUTE Route);
|
|
|
|
VOID
|
|
PrinterHandleRundown(
|
|
HANDLE hPrinter);
|
|
|
|
BOOL
|
|
GetPrinterDriverExW(
|
|
HANDLE hPrinter,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pDriverInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
DWORD dwClientMajorVersion,
|
|
DWORD dwClientMinorVersion,
|
|
PDWORD pdwServerMajorVersion,
|
|
PDWORD pdwServerMinorVersion);
|
|
|
|
BOOL
|
|
OpenPrinterExW(
|
|
LPWSTR pPrinterName,
|
|
HANDLE *pHandle,
|
|
LPPRINTER_DEFAULTS pDefault,
|
|
PSPLCLIENT_CONTAINER pSplClientContainer
|
|
);
|
|
|
|
HANDLE
|
|
AddPrinterExW(
|
|
LPWSTR pName,
|
|
DWORD Level,
|
|
LPBYTE pPrinter,
|
|
LPBYTE pClientInfo,
|
|
DWORD dwLevel
|
|
);
|
|
|
|
BOOL
|
|
SpoolerInit(
|
|
VOID);
|
|
|
|
|
|
BOOL
|
|
InvalidDevModeContainer(
|
|
LPDEVMODE_CONTAINER pDevModeContainer
|
|
)
|
|
{
|
|
DWORD dwSize = pDevModeContainer->cbBuf;
|
|
|
|
if(pDevModeContainer)
|
|
{
|
|
PDEVMODE pDevMode = (PDEVMODE) pDevModeContainer->pDevMode;
|
|
|
|
|
|
|
|
if (dwSize < MIN_DEVMODE_SIZEW)
|
|
return dwSize ? TRUE : !!pDevMode;
|
|
|
|
|
|
if (pDevMode && (pDevMode->dmSize + (DWORD) pDevMode->dmDriverExtra == pDevModeContainer->cbBuf))
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
InvalidSecurityContainer(
|
|
PSECURITY_CONTAINER pSecurityContainer
|
|
)
|
|
{
|
|
SECURITY_DESCRIPTOR_CONTROL SecurityDescriptorControl;
|
|
DWORD dwRevision;
|
|
|
|
if(!pSecurityContainer ||
|
|
(pSecurityContainer->pSecurity &&
|
|
!RtlValidRelativeSecurityDescriptor((SECURITY_DESCRIPTOR *)pSecurityContainer->pSecurity,
|
|
pSecurityContainer->cbBuf,
|
|
0)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
ValidatePortVarContainer(
|
|
PPORT_VAR_CONTAINER pPortVarContainer
|
|
)
|
|
{
|
|
return !!pPortVarContainer;
|
|
}
|
|
|
|
BOOL
|
|
ValidatePortContainer(
|
|
LPPORT_CONTAINER pPortContainer
|
|
)
|
|
{
|
|
return pPortContainer && pPortContainer->PortInfo.pPortInfo1;
|
|
}
|
|
|
|
BOOL
|
|
ValidatePrinterContainer(
|
|
PPRINTER_CONTAINER pPrinterContainer
|
|
)
|
|
{
|
|
return pPrinterContainer && pPrinterContainer->PrinterInfo.pPrinterInfo1;
|
|
}
|
|
|
|
BOOL
|
|
ValidateMonitorContainer(
|
|
LPMONITOR_CONTAINER pMonitorContainer
|
|
)
|
|
{
|
|
return pMonitorContainer && pMonitorContainer->MonitorInfo.pMonitorInfo2;
|
|
}
|
|
|
|
|
|
DWORD
|
|
YEnumPrinters(
|
|
DWORD Flags,
|
|
LPWSTR Name,
|
|
DWORD Level,
|
|
LPBYTE pPrinterEnum,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned,
|
|
CALL_ROUTE Route
|
|
)
|
|
{ FieldInfo* pFieldInfo;
|
|
DWORD cReturned, cbStruct;
|
|
DWORD Error=ERROR_INVALID_NAME;
|
|
DWORD BufferSize=cbBuf;
|
|
BOOL bRet;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case STRESSINFOLEVEL:
|
|
pFieldInfo = PrinterInfoStressFields;
|
|
cbStruct = sizeof(PRINTER_INFO_STRESS);
|
|
break;
|
|
|
|
case 1:
|
|
pFieldInfo = PrinterInfo1Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pFieldInfo = PrinterInfo2Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_2);
|
|
break;
|
|
|
|
case 4:
|
|
pFieldInfo = PrinterInfo4Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_4);
|
|
break;
|
|
|
|
case 5:
|
|
pFieldInfo = PrinterInfo5Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_5);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pPrinterEnum, &cbBuf);
|
|
|
|
if ( pPrinterEnum && !pAlignedBuff ){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = EnumPrinters(Flags, Name, Level, pAlignedBuff,
|
|
cbBuf, pcbNeeded, pcReturned);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructuresArray(pAlignedBuff, *pcReturned, pFieldInfo, cbStruct, Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pPrinterEnum, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
|
|
}
|
|
|
|
DWORD
|
|
YOpenPrinter(
|
|
LPWSTR pPrinterName,
|
|
HANDLE *phPrinter,
|
|
LPWSTR pDatatype,
|
|
LPDEVMODE_CONTAINER pDevModeContainer,
|
|
DWORD AccessRequired,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
PRINTER_DEFAULTS Defaults;
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
if ( InvalidDevModeContainer(pDevModeContainer) ) {
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
Defaults.pDatatype = pDatatype;
|
|
|
|
Defaults.pDevMode = (LPDEVMODE)pDevModeContainer->pDevMode;
|
|
|
|
Defaults.DesiredAccess = AccessRequired;
|
|
|
|
bRet = OpenPrinterW(pPrinterName, phPrinter, &Defaults);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
InterlockedIncrement ( &ServerHandleCount );
|
|
return ERROR_SUCCESS;
|
|
} else {
|
|
*phPrinter = NULL;
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
YOpenPrinterEx(
|
|
LPWSTR pPrinterName,
|
|
HANDLE *phPrinter,
|
|
LPWSTR pDatatype,
|
|
LPDEVMODE_CONTAINER pDevModeContainer,
|
|
DWORD AccessRequired,
|
|
CALL_ROUTE Route,
|
|
PSPLCLIENT_CONTAINER pSplClientContainer
|
|
)
|
|
{
|
|
PRINTER_DEFAULTS Defaults;
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
if ( InvalidDevModeContainer(pDevModeContainer) ) {
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
Defaults.pDatatype = pDatatype;
|
|
|
|
Defaults.pDevMode = (LPDEVMODE)pDevModeContainer->pDevMode;
|
|
|
|
Defaults.DesiredAccess = AccessRequired;
|
|
|
|
bRet = OpenPrinterExW(pPrinterName,
|
|
phPrinter,
|
|
&Defaults,
|
|
pSplClientContainer);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
InterlockedIncrement ( &ServerHandleCount );
|
|
return ERROR_SUCCESS;
|
|
} else {
|
|
*phPrinter = NULL;
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
YResetPrinter(
|
|
HANDLE hPrinter,
|
|
LPWSTR pDatatype,
|
|
LPDEVMODE_CONTAINER pDevModeContainer,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
PRINTER_DEFAULTS Defaults;
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
if ( InvalidDevModeContainer(pDevModeContainer) ) {
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
Defaults.pDatatype = pDatatype;
|
|
|
|
Defaults.pDevMode = (LPDEVMODE)pDevModeContainer->pDevMode;
|
|
|
|
//
|
|
// You cannot change the Access Mask on a Printer Spool Object
|
|
// We will always ignore this parameter and set it to zero
|
|
// We get some random garbage otherwise.
|
|
//
|
|
|
|
Defaults.DesiredAccess = 0;
|
|
|
|
bRet = ResetPrinter(hPrinter, &Defaults);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YSetJob(
|
|
HANDLE hPrinter,
|
|
DWORD JobId,
|
|
JOB_CONTAINER *pJobContainer,
|
|
DWORD Command,
|
|
CALL_ROUTE Route
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will modify the settings of the specified Print Job.
|
|
|
|
Arguments:
|
|
|
|
lpJob - Points to a valid JOB structure containing at least a valid
|
|
lpPrinter, and JobId.
|
|
|
|
Command - Specifies the operation to perform on the specified Job. A value
|
|
of FALSE indicates that only the elements of the JOB structure are to
|
|
be examined and set.
|
|
|
|
Return Value:
|
|
|
|
TRUE - The operation was successful.
|
|
|
|
FALSE/NULL - The operation failed. Extended error status is available
|
|
using GetLastError.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = SetJob(hPrinter, JobId, pJobContainer ? pJobContainer->Level : 0,
|
|
pJobContainer ? (LPBYTE)pJobContainer->JobInfo.Level1 : NULL,
|
|
Command);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YGetJob(
|
|
HANDLE hPrinter,
|
|
DWORD JobId,
|
|
DWORD Level,
|
|
LPBYTE pJob,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function will retrieve the settings of the specified Print Job.
|
|
|
|
Arguments:
|
|
|
|
lpJob - Points to a valid JOB structure containing at least a valid
|
|
lpPrinter, and JobId.
|
|
|
|
Return Value:
|
|
|
|
TRUE - The operation was successful.
|
|
|
|
FALSE/NULL - The operation failed. Extended error status is available
|
|
using GetLastError.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL bRet;
|
|
SIZE_T cbStruct;
|
|
FieldInfo *pFieldInfo;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = JobInfo1Fields;
|
|
cbStruct = sizeof(JOB_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pFieldInfo = JobInfo2Fields;
|
|
cbStruct = sizeof(JOB_INFO_2);
|
|
break;
|
|
|
|
case 3:
|
|
pFieldInfo = JobInfo3Fields;
|
|
cbStruct = sizeof(JOB_INFO_3);
|
|
break;
|
|
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
//
|
|
//
|
|
// HACK for 3.51: Catch bad parameters passed across the wire.
|
|
// If the buffer passed is > 1 MEG, fail the call.
|
|
//
|
|
if( cbBuf > 0x100000 ){
|
|
|
|
DBGMSG( DBG_ERROR,
|
|
( "** GetJob: cbBuf is 0x%x !! Contact VibhasC and AlbertT **\n", cbBuf ));
|
|
|
|
RaiseException( ERROR_INVALID_USER_BUFFER,
|
|
EXCEPTION_NONCONTINUABLE,
|
|
0,
|
|
NULL );
|
|
}
|
|
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pJob, &cbBuf);
|
|
|
|
if (pJob && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = GetJob(hPrinter, JobId, Level, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
if (Route) {
|
|
|
|
bRet = MarshallDownStructure(pAlignedBuff, pFieldInfo, cbStruct, Route);
|
|
}
|
|
}
|
|
|
|
UndoAlignRpcPtr(pJob, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YEnumJobs(
|
|
HANDLE hPrinter,
|
|
DWORD FirstJob,
|
|
DWORD NoJobs,
|
|
DWORD Level,
|
|
LPBYTE pJob,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
FieldInfo *pFieldInfo;
|
|
DWORD cReturned, cbStruct;
|
|
BOOL bRet;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = JobInfo1Fields;
|
|
cbStruct = sizeof(JOB_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pFieldInfo = JobInfo2Fields;
|
|
cbStruct = sizeof(JOB_INFO_2);
|
|
break;
|
|
|
|
case 3:
|
|
pFieldInfo = JobInfo3Fields;
|
|
cbStruct = sizeof(JOB_INFO_3);
|
|
break;
|
|
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pJob, &cbBuf);
|
|
|
|
if (pJob && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = EnumJobs(hPrinter, FirstJob, NoJobs, Level, pAlignedBuff,
|
|
cbBuf, pcbNeeded, pcReturned);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructuresArray(pAlignedBuff, *pcReturned, pFieldInfo, cbStruct, Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pJob, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YAddPrinter(
|
|
LPWSTR pName,
|
|
PPRINTER_CONTAINER pPrinterContainer,
|
|
PDEVMODE_CONTAINER pDevModeContainer,
|
|
PSECURITY_CONTAINER pSecurityContainer,
|
|
HANDLE *phPrinter,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
if(!ValidatePrinterContainer(pPrinterContainer) ||
|
|
InvalidDevModeContainer(pDevModeContainer))
|
|
{
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pPrinterContainer->Level == 2)
|
|
{
|
|
if(!pPrinterContainer->PrinterInfo.pPrinterInfo2 ||
|
|
(pSecurityContainer->pSecurity &&
|
|
InvalidSecurityContainer(pSecurityContainer)))
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
pPrinterContainer->PrinterInfo.pPrinterInfo2->pDevMode =
|
|
(LPDEVMODE)pDevModeContainer->pDevMode;
|
|
pPrinterContainer->PrinterInfo.pPrinterInfo2->pSecurityDescriptor =
|
|
(PSECURITY_DESCRIPTOR)pSecurityContainer->pSecurity;
|
|
}
|
|
|
|
*phPrinter = AddPrinter(pName, pPrinterContainer->Level,
|
|
(LPBYTE)pPrinterContainer->PrinterInfo.pPrinterInfo1);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (*phPrinter) {
|
|
InterlockedIncrement( &ServerHandleCount );
|
|
return ERROR_SUCCESS;
|
|
} else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YAddPrinterEx(
|
|
LPWSTR pName,
|
|
PPRINTER_CONTAINER pPrinterContainer,
|
|
PDEVMODE_CONTAINER pDevModeContainer,
|
|
PSECURITY_CONTAINER pSecurityContainer,
|
|
HANDLE *phPrinter,
|
|
CALL_ROUTE Route,
|
|
PSPLCLIENT_CONTAINER pSplClientContainer
|
|
)
|
|
{
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
if(!ValidatePrinterContainer(pPrinterContainer) ||
|
|
InvalidDevModeContainer(pDevModeContainer))
|
|
{
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pPrinterContainer->Level == 2)
|
|
{
|
|
if(!pPrinterContainer->PrinterInfo.pPrinterInfo2 ||
|
|
(pSecurityContainer->pSecurity &&
|
|
InvalidSecurityContainer(pSecurityContainer)))
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
pPrinterContainer->PrinterInfo.pPrinterInfo2->pDevMode =
|
|
(LPDEVMODE)pDevModeContainer->pDevMode;
|
|
pPrinterContainer->PrinterInfo.pPrinterInfo2->pSecurityDescriptor =
|
|
(PSECURITY_DESCRIPTOR)pSecurityContainer->pSecurity;
|
|
}
|
|
|
|
*phPrinter = AddPrinterExW(pName,
|
|
pPrinterContainer->Level,
|
|
(LPBYTE)pPrinterContainer->PrinterInfo.pPrinterInfo1,
|
|
(LPBYTE)pSplClientContainer->ClientInfo.pClientInfo1,
|
|
pSplClientContainer->Level);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (*phPrinter) {
|
|
InterlockedIncrement( &ServerHandleCount );
|
|
return ERROR_SUCCESS;
|
|
} else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YDeletePrinter(
|
|
HANDLE hPrinter,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeletePrinter(hPrinter);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YAddPrinterConnection(
|
|
LPWSTR pName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = AddPrinterConnection(pName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YDeletePrinterConnection(
|
|
LPWSTR pName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeletePrinterConnection(pName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YSetPrinter(
|
|
HANDLE hPrinter,
|
|
PPRINTER_CONTAINER pPrinterContainer,
|
|
PDEVMODE_CONTAINER pDevModeContainer,
|
|
PSECURITY_CONTAINER pSecurityContainer,
|
|
DWORD Command,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
if(!pPrinterContainer ||
|
|
(pPrinterContainer->Level && !ValidatePrinterContainer(pPrinterContainer)) ||
|
|
InvalidDevModeContainer(pDevModeContainer))
|
|
{
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (InvalidSecurityContainer(pSecurityContainer)) {
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
switch (pPrinterContainer->Level) {
|
|
|
|
case 2:
|
|
|
|
pPrinterContainer->PrinterInfo.pPrinterInfo2->pDevMode =
|
|
(LPDEVMODE)pDevModeContainer->pDevMode;
|
|
|
|
pPrinterContainer->PrinterInfo.pPrinterInfo2->pSecurityDescriptor =
|
|
(PSECURITY_DESCRIPTOR)pSecurityContainer->pSecurity;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
pPrinterContainer->PrinterInfo.pPrinterInfo3->pSecurityDescriptor =
|
|
(PSECURITY_DESCRIPTOR)pSecurityContainer->pSecurity;
|
|
break;
|
|
|
|
case 8:
|
|
|
|
pPrinterContainer->PrinterInfo.pPrinterInfo8->pDevMode =
|
|
(LPDEVMODE)pDevModeContainer->pDevMode;
|
|
break;
|
|
|
|
case 9:
|
|
|
|
pPrinterContainer->PrinterInfo.pPrinterInfo9->pDevMode =
|
|
(LPDEVMODE)pDevModeContainer->pDevMode;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
bRet = SetPrinter(hPrinter, pPrinterContainer->Level,
|
|
(LPBYTE)pPrinterContainer->PrinterInfo.pPrinterInfo1,
|
|
Command);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YGetPrinter(
|
|
HANDLE hPrinter,
|
|
DWORD Level,
|
|
LPBYTE pPrinter,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
FieldInfo *pFieldInfo;
|
|
BOOL ReturnValue;
|
|
DWORD *pOffsets;
|
|
SIZE_T cbStruct;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
*pcbNeeded = 0;
|
|
switch (Level) {
|
|
|
|
case STRESSINFOLEVEL:
|
|
pFieldInfo = PrinterInfoStressFields;
|
|
cbStruct = sizeof(PRINTER_INFO_STRESS);
|
|
break;
|
|
|
|
case 1:
|
|
pFieldInfo = PrinterInfo1Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pFieldInfo = PrinterInfo2Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_2);
|
|
break;
|
|
|
|
case 3:
|
|
pFieldInfo = PrinterInfo3Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_3);
|
|
break;
|
|
|
|
case 4:
|
|
pFieldInfo = PrinterInfo4Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_4);
|
|
break;
|
|
|
|
case 5:
|
|
pFieldInfo = PrinterInfo5Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_5);
|
|
break;
|
|
|
|
case 6:
|
|
pFieldInfo = PrinterInfo6Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_6);
|
|
break;
|
|
|
|
case 7:
|
|
pFieldInfo = PrinterInfo7Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_7);
|
|
break;
|
|
|
|
case 8:
|
|
pFieldInfo = PrinterInfo8Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_8);
|
|
break;
|
|
|
|
case 9:
|
|
pFieldInfo = PrinterInfo9Fields;
|
|
cbStruct = sizeof(PRINTER_INFO_9);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pPrinter, &cbBuf);
|
|
|
|
if (pPrinter && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
ReturnValue = GetPrinter(hPrinter, Level, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (ReturnValue) {
|
|
|
|
ReturnValue = MarshallDownStructure(pAlignedBuff, pFieldInfo, cbStruct, Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pPrinter, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return ReturnValue ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
|
|
DWORD
|
|
YAddPrinterDriver(
|
|
LPWSTR pName,
|
|
LPDRIVER_CONTAINER pDriverContainer,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
PDRIVER_INFO_4 pDriverInfo4 = NULL;
|
|
BOOL bRet = FALSE;
|
|
LPRPC_DRIVER_INFO_4W pRpcDriverInfo4;
|
|
|
|
if(!pDriverContainer)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
switch (pDriverContainer->Level) {
|
|
|
|
case 2:
|
|
bRet = AddPrinterDriver(pName,
|
|
pDriverContainer->Level,
|
|
(LPBYTE)pDriverContainer->DriverInfo.Level2);
|
|
break;
|
|
|
|
case 3:
|
|
case 4:
|
|
if(!pDriverContainer->DriverInfo.Level4)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
goto Error;
|
|
}
|
|
|
|
pDriverInfo4 = (PDRIVER_INFO_4) AllocSplMem(sizeof(DRIVER_INFO_4));
|
|
|
|
if ( !pDriverInfo4 ) {
|
|
|
|
goto Error;
|
|
}
|
|
|
|
pRpcDriverInfo4 = (LPRPC_DRIVER_INFO_4W) pDriverContainer->DriverInfo.Level4;
|
|
|
|
if (!pRpcDriverInfo4) {
|
|
FreeSplMem(pDriverInfo4);
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
goto Error;
|
|
}
|
|
|
|
pDriverInfo4->cVersion = pRpcDriverInfo4->cVersion;
|
|
pDriverInfo4->pName = pRpcDriverInfo4->pName;
|
|
pDriverInfo4->pEnvironment = pRpcDriverInfo4->pEnvironment;
|
|
pDriverInfo4->pDriverPath = pRpcDriverInfo4->pDriverPath;
|
|
pDriverInfo4->pDataFile = pRpcDriverInfo4->pDataFile;
|
|
pDriverInfo4->pConfigFile = pRpcDriverInfo4->pConfigFile;
|
|
pDriverInfo4->pHelpFile = pRpcDriverInfo4->pHelpFile;
|
|
pDriverInfo4->pMonitorName = pRpcDriverInfo4->pMonitorName;
|
|
pDriverInfo4->pDefaultDataType = pRpcDriverInfo4->pDefaultDataType;
|
|
|
|
//
|
|
// Use szNULL if the DependentFiles string contains nothing
|
|
//
|
|
if ((pRpcDriverInfo4->cchDependentFiles == 0) ||
|
|
(pRpcDriverInfo4->cchDependentFiles == 1)) {
|
|
|
|
pDriverInfo4->pDependentFiles = szNull;
|
|
} else {
|
|
pDriverInfo4->pDependentFiles = pRpcDriverInfo4->pDependentFiles
|
|
;
|
|
}
|
|
|
|
if ( pDriverContainer->Level == 4 ) {
|
|
|
|
if ( pRpcDriverInfo4->cchPreviousNames == 0 ||
|
|
pRpcDriverInfo4->cchPreviousNames == 1 )
|
|
pDriverInfo4->pszzPreviousNames = szNull;
|
|
else
|
|
pDriverInfo4->pszzPreviousNames
|
|
= pRpcDriverInfo4->pszzPreviousNames;
|
|
}
|
|
|
|
|
|
bRet = AddPrinterDriver(pName,
|
|
pDriverContainer->Level,
|
|
(LPBYTE) pDriverInfo4);
|
|
|
|
FreeSplMem(pDriverInfo4);
|
|
break;
|
|
|
|
default:
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
Error:
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YAddPrinterDriverEx(
|
|
LPWSTR pName,
|
|
LPDRIVER_CONTAINER pDriverContainer,
|
|
DWORD dwFileCopyFlags,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
PDRIVER_INFO_6 pDriverInfo6 = NULL;
|
|
LPRPC_DRIVER_INFO_6W pRpcDriverInfo6;
|
|
|
|
if(!pDriverContainer)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
switch (pDriverContainer->Level) {
|
|
|
|
case 2:
|
|
bRet = AddPrinterDriverEx(pName,
|
|
pDriverContainer->Level,
|
|
(LPBYTE)pDriverContainer->DriverInfo.Level2,
|
|
dwFileCopyFlags);
|
|
break;
|
|
|
|
case 3:
|
|
case 4:
|
|
case 6:
|
|
|
|
if(!pDriverContainer->DriverInfo.Level6)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
goto Error;
|
|
}
|
|
pDriverInfo6 = (PDRIVER_INFO_6) AllocSplMem(sizeof(DRIVER_INFO_6));
|
|
|
|
if ( !pDriverInfo6 ) {
|
|
|
|
bRet = FALSE;
|
|
goto Error;
|
|
}
|
|
|
|
pRpcDriverInfo6 = (LPRPC_DRIVER_INFO_6W) pDriverContainer->DriverInfo.Level6;
|
|
pDriverInfo6->cVersion = pRpcDriverInfo6->cVersion;
|
|
pDriverInfo6->pName = pRpcDriverInfo6->pName;
|
|
pDriverInfo6->pEnvironment = pRpcDriverInfo6->pEnvironment;
|
|
pDriverInfo6->pDriverPath = pRpcDriverInfo6->pDriverPath;
|
|
pDriverInfo6->pDataFile = pRpcDriverInfo6->pDataFile;
|
|
pDriverInfo6->pConfigFile = pRpcDriverInfo6->pConfigFile;
|
|
pDriverInfo6->pHelpFile = pRpcDriverInfo6->pHelpFile;
|
|
pDriverInfo6->pMonitorName = pRpcDriverInfo6->pMonitorName;
|
|
pDriverInfo6->pDefaultDataType = pRpcDriverInfo6->pDefaultDataType;
|
|
|
|
//
|
|
// Use szNULL if the DependentFiles string contains nothing
|
|
//
|
|
if ((pRpcDriverInfo6->cchDependentFiles == 0) ||
|
|
(pRpcDriverInfo6->cchDependentFiles == 1)) {
|
|
|
|
pDriverInfo6->pDependentFiles = szNull;
|
|
} else {
|
|
pDriverInfo6->pDependentFiles = pRpcDriverInfo6->pDependentFiles;
|
|
}
|
|
|
|
if ( pDriverContainer->Level == 4 || pDriverContainer->Level == 6 ) {
|
|
|
|
if ( pRpcDriverInfo6->cchPreviousNames == 0 ||
|
|
pRpcDriverInfo6->cchPreviousNames == 1 )
|
|
pDriverInfo6->pszzPreviousNames = szNull;
|
|
else
|
|
pDriverInfo6->pszzPreviousNames
|
|
= pRpcDriverInfo6->pszzPreviousNames;
|
|
}
|
|
|
|
if ( pDriverContainer->Level == 6 ) {
|
|
pDriverInfo6->ftDriverDate = pRpcDriverInfo6->ftDriverDate;
|
|
pDriverInfo6->dwlDriverVersion = pRpcDriverInfo6->dwlDriverVersion;
|
|
pDriverInfo6->pszMfgName = pRpcDriverInfo6->pMfgName;
|
|
pDriverInfo6->pszOEMUrl = pRpcDriverInfo6->pOEMUrl;
|
|
pDriverInfo6->pszHardwareID = pRpcDriverInfo6->pHardwareID;
|
|
pDriverInfo6->pszProvider = pRpcDriverInfo6->pProvider;
|
|
}
|
|
|
|
bRet = AddPrinterDriverEx(pName,
|
|
pDriverContainer->Level,
|
|
(LPBYTE) pDriverInfo6,
|
|
dwFileCopyFlags);
|
|
|
|
FreeSplMem(pDriverInfo6);
|
|
break;
|
|
|
|
default:
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
Error:
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YAddDriverCatalog(
|
|
HANDLE hPrinter,
|
|
DRIVER_INFCAT_CONTAINER *pDriverInfCatContainer,
|
|
DWORD dwCatalogCopyFlags,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
if (!pDriverInfCatContainer)
|
|
{
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
goto Cleanup;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
|
|
switch (pDriverInfCatContainer->dwLevel)
|
|
{
|
|
|
|
case 1:
|
|
bRet = AddDriverCatalog(hPrinter,
|
|
pDriverInfCatContainer->dwLevel,
|
|
pDriverInfCatContainer->DriverInfCatInfo.pDriverInfCatInfo1,
|
|
dwCatalogCopyFlags);
|
|
break;
|
|
|
|
case 2:
|
|
bRet = AddDriverCatalog(hPrinter,
|
|
pDriverInfCatContainer->dwLevel,
|
|
pDriverInfCatContainer->DriverInfCatInfo.pDriverInfCatInfo2,
|
|
dwCatalogCopyFlags);
|
|
break;
|
|
|
|
default:
|
|
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
break;
|
|
}
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
Cleanup:
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YEnumPrinterDrivers(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pDrivers,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD cReturned, cbStruct;
|
|
BOOL bRet;
|
|
FieldInfo *pFieldInfo;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = DriverInfo1Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pFieldInfo = DriverInfo2Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_2);
|
|
break;
|
|
|
|
case 3:
|
|
pFieldInfo = DriverInfo3Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_3);
|
|
break;
|
|
|
|
case 4:
|
|
pFieldInfo = DriverInfo4Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_4);
|
|
break;
|
|
|
|
case 5:
|
|
pFieldInfo = DriverInfo5Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_5);
|
|
break;
|
|
|
|
case 6:
|
|
pFieldInfo = DriverInfo6Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_6);
|
|
break;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pDrivers, &cbBuf);
|
|
|
|
if (pDrivers && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = EnumPrinterDrivers(pName, pEnvironment, Level, pAlignedBuff,
|
|
cbBuf, pcbNeeded, pcReturned);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructuresArray(pAlignedBuff, *pcReturned, pFieldInfo, cbStruct, Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pDrivers, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YGetPrinterDriver(
|
|
HANDLE hPrinter,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pDriverInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
FieldInfo *pFieldInfo;
|
|
BOOL bRet;
|
|
DWORD dwServerMajorVersion;
|
|
DWORD dwServerMinorVersion;
|
|
SIZE_T cbStruct;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = DriverInfo1Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pFieldInfo = DriverInfo2Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_2);
|
|
break;
|
|
|
|
case 3:
|
|
pFieldInfo = DriverInfo3Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_3);
|
|
break;
|
|
|
|
case 4:
|
|
pFieldInfo = DriverInfo4Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_4);
|
|
break;
|
|
|
|
case 6:
|
|
pFieldInfo = DriverInfo6Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_6);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pDriverInfo, &cbBuf);
|
|
|
|
if (pDriverInfo && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
if ( Route ) {
|
|
|
|
//
|
|
// If they are Remote using the old api the don't want versioning
|
|
//
|
|
|
|
bRet = OldGetPrinterDriverW(hPrinter, pEnvironment, Level, pAlignedBuff,
|
|
cbBuf, pcbNeeded);
|
|
} else {
|
|
|
|
bRet = GetPrinterDriverExW(hPrinter, pEnvironment, Level, pAlignedBuff,
|
|
cbBuf, pcbNeeded, (DWORD)-1, (DWORD)-1,
|
|
&dwServerMajorVersion, &dwServerMinorVersion);
|
|
}
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructure(pAlignedBuff, pFieldInfo, cbStruct, Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pDriverInfo, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YGetPrinterDriverDirectory(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pDriverInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = GetPrinterDriverDirectory(pName, pEnvironment, Level,
|
|
pDriverInfo, cbBuf, pcbNeeded);
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YDeletePrinterDriver(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
LPWSTR pDriverName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeletePrinterDriverW(pName, pEnvironment, pDriverName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
|
|
DWORD
|
|
YDeletePrinterDriverEx(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
LPWSTR pDriverName,
|
|
DWORD dwDeleteFlag,
|
|
DWORD dwVersionNum,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeletePrinterDriverExW(pName, pEnvironment, pDriverName,
|
|
dwDeleteFlag, dwVersionNum);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YAddPerMachineConnection(
|
|
LPWSTR pServer,
|
|
LPCWSTR pPrinterName,
|
|
LPCWSTR pPrintServer,
|
|
LPCWSTR pProvider,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = AddPerMachineConnection(pServer, pPrinterName, pPrintServer, pProvider);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YDeletePerMachineConnection(
|
|
LPWSTR pServer,
|
|
LPCWSTR pPrinterName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeletePerMachineConnection(pServer, pPrinterName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YEnumPerMachineConnections(
|
|
LPWSTR pServer,
|
|
LPBYTE pPrinterEnum,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD cReturned, cbStruct;
|
|
FieldInfo *pFieldInfo;
|
|
BOOL bRet;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
pFieldInfo = PrinterInfo4Fields;
|
|
|
|
cbStruct = sizeof(PRINTER_INFO_4);
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pPrinterEnum, &cbBuf);
|
|
|
|
if (pPrinterEnum && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = EnumPerMachineConnections(pServer,
|
|
pAlignedBuff,
|
|
cbBuf,
|
|
pcbNeeded,
|
|
pcReturned);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructuresArray(pAlignedBuff, *pcReturned, pFieldInfo, cbStruct, Route );
|
|
}
|
|
|
|
UndoAlignRpcPtr(pPrinterEnum, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
|
|
}
|
|
|
|
DWORD
|
|
YAddPrintProcessor(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
LPWSTR pPathName,
|
|
LPWSTR pPrintProcessorName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = AddPrintProcessor(pName, pEnvironment, pPathName,
|
|
pPrintProcessorName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else {
|
|
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
YEnumPrintProcessors(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pPrintProcessors,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD cReturned, cbStruct;
|
|
FieldInfo *pFieldInfo;
|
|
BOOL bRet;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = PrintProcessorInfo1Fields;
|
|
cbStruct = sizeof(PRINTPROCESSOR_INFO_1);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pPrintProcessors, &cbBuf);
|
|
|
|
if (pPrintProcessors && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = EnumPrintProcessors(pName, pEnvironment, Level,
|
|
pAlignedBuff, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructuresArray(pAlignedBuff, *pcReturned, pFieldInfo, cbStruct ,Route );
|
|
}
|
|
|
|
UndoAlignRpcPtr(pPrintProcessors, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YGetPrintProcessorDirectory(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pPrintProcessorInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = GetPrintProcessorDirectory(pName, pEnvironment, Level,
|
|
pPrintProcessorInfo, cbBuf, pcbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YEnumPrintProcessorDatatypes(
|
|
LPWSTR pName,
|
|
LPWSTR pPrintProcessorName,
|
|
DWORD Level,
|
|
LPBYTE pDatatypes,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD cReturned,cbStruct;
|
|
FieldInfo *pFieldInfo;
|
|
BOOL bRet;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = DatatypeInfo1Fields;
|
|
cbStruct = sizeof(DATATYPES_INFO_1);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pDatatypes, &cbBuf);
|
|
|
|
if (pDatatypes && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = EnumPrintProcessorDatatypes(pName, pPrintProcessorName,
|
|
Level, pAlignedBuff, cbBuf,
|
|
pcbNeeded, pcReturned);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructuresArray(pAlignedBuff, *pcReturned, pFieldInfo, cbStruct, Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pDatatypes, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YStartDocPrinter(
|
|
HANDLE hPrinter,
|
|
LPDOC_INFO_CONTAINER pDocInfoContainer,
|
|
LPDWORD pJobId,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
LPWSTR pChar;
|
|
|
|
if( !pDocInfoContainer || pDocInfoContainer->Level != 1 ){
|
|
RaiseException( ERROR_INVALID_USER_BUFFER,
|
|
EXCEPTION_NONCONTINUABLE,
|
|
0,
|
|
NULL );
|
|
}
|
|
|
|
try
|
|
{
|
|
if(pDocInfoContainer->DocInfo.pDocInfo1)
|
|
{
|
|
if( pDocInfoContainer->DocInfo.pDocInfo1->pDocName )
|
|
{
|
|
for( pChar = pDocInfoContainer->DocInfo.pDocInfo1->pDocName;
|
|
*pChar;
|
|
++pChar )
|
|
;
|
|
}
|
|
|
|
if( pDocInfoContainer->DocInfo.pDocInfo1->pOutputFile )
|
|
{
|
|
|
|
for( pChar = pDocInfoContainer->DocInfo.pDocInfo1->pOutputFile;
|
|
*pChar;
|
|
++pChar )
|
|
;
|
|
}
|
|
|
|
if( pDocInfoContainer->DocInfo.pDocInfo1->pDatatype )
|
|
{
|
|
|
|
for( pChar = pDocInfoContainer->DocInfo.pDocInfo1->pDatatype;
|
|
*pChar;
|
|
++pChar )
|
|
;
|
|
}
|
|
}
|
|
}
|
|
except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
|
|
RaiseException( ERROR_INVALID_USER_BUFFER,
|
|
EXCEPTION_NONCONTINUABLE,
|
|
0,
|
|
NULL );
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
*pJobId = StartDocPrinter(hPrinter, pDocInfoContainer->Level,
|
|
(LPBYTE)pDocInfoContainer->DocInfo.pDocInfo1);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (*pJobId)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YStartPagePrinter(
|
|
HANDLE hPrinter,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = StartPagePrinter(hPrinter);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YWritePrinter(
|
|
HANDLE hPrinter,
|
|
LPBYTE pBuf,
|
|
DWORD cbBuf,
|
|
LPDWORD pcWritten,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = WritePrinter(hPrinter, pBuf, cbBuf, pcWritten);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
|
|
DWORD
|
|
YSeekPrinter(
|
|
HANDLE hPrinter,
|
|
LARGE_INTEGER liDistanceToMove,
|
|
PLARGE_INTEGER pliNewPointer,
|
|
DWORD dwMoveMethod,
|
|
BOOL bWritePrinter,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = SeekPrinter( hPrinter,
|
|
liDistanceToMove,
|
|
pliNewPointer,
|
|
dwMoveMethod,
|
|
bWritePrinter );
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
|
|
DWORD
|
|
YFlushPrinter(
|
|
HANDLE hPrinter,
|
|
LPBYTE pBuf,
|
|
DWORD cbBuf,
|
|
LPDWORD pcWritten,
|
|
DWORD cSleep,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = FlushPrinter(hPrinter, pBuf, cbBuf, pcWritten, cSleep);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YEndPagePrinter(
|
|
HANDLE hPrinter,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = EndPagePrinter(hPrinter);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YAbortPrinter(
|
|
HANDLE hPrinter,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = AbortPrinter(hPrinter);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YReadPrinter(
|
|
HANDLE hPrinter,
|
|
LPBYTE pBuf,
|
|
DWORD cbBuf,
|
|
LPDWORD pRead,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = ReadPrinter(hPrinter, pBuf, cbBuf, pRead);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YSplReadPrinter(
|
|
HANDLE hPrinter,
|
|
LPBYTE *pBuf,
|
|
DWORD cbBuf,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
// Currently SplReadPrinter is internal and does not come thru RPC.
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = SplReadPrinter(hPrinter, pBuf, cbBuf);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
VOID StartDriverUnload( LPVOID pDriverFile )
|
|
{
|
|
|
|
SplDriverUnloadComplete((LPWSTR) pDriverFile);
|
|
|
|
if (pDriverFile) {
|
|
FreeSplMem(pDriverFile);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
YDriverUnloadComplete(
|
|
LPWSTR pDriverFile
|
|
)
|
|
{
|
|
HANDLE hThread;
|
|
DWORD dwThreadId;
|
|
LPWSTR pDriverFileCopy = NULL;
|
|
|
|
// Copy the string for passing it to another thread
|
|
if (pDriverFile && *pDriverFile) {
|
|
pDriverFileCopy = AllocSplStr(pDriverFile);
|
|
}
|
|
|
|
if (!pDriverFileCopy) {
|
|
return;
|
|
}
|
|
|
|
// Create a thread to process driver unload and return ASAP
|
|
hThread = CreateThread(NULL,
|
|
LARGE_INITIAL_STACK_COMMIT,
|
|
(LPTHREAD_START_ROUTINE) StartDriverUnload,
|
|
(LPVOID) pDriverFileCopy,
|
|
0,
|
|
&dwThreadId);
|
|
if (hThread) {
|
|
CloseHandle(hThread);
|
|
} else {
|
|
// thread did not spawn, free resources
|
|
FreeSplStr(pDriverFileCopy);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
DWORD
|
|
YEndDocPrinter(
|
|
HANDLE hPrinter,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = EndDocPrinter(hPrinter);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YAddJob(
|
|
HANDLE hPrinter,
|
|
DWORD Level,
|
|
LPBYTE pAddJob,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
LPBYTE pAlignedBuff;
|
|
DWORD cbStruct;
|
|
FieldInfo *pFieldInfo;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = AddJobFields;
|
|
cbStruct = sizeof(ADDJOB_INFO_1W);
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
pFieldInfo = AddJob2Fields;
|
|
cbStruct = sizeof(ADDJOB_INFO_2W);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pAddJob, &cbBuf);
|
|
|
|
if (pAddJob && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = AddJob(hPrinter, Level, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
if (Route) {
|
|
|
|
bRet = MarshallDownStructure(pAlignedBuff, pFieldInfo, sizeof(cbStruct), Route);
|
|
}
|
|
}
|
|
|
|
UndoAlignRpcPtr(pAddJob, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YScheduleJob(
|
|
HANDLE hPrinter,
|
|
DWORD JobId,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = ScheduleJob(hPrinter, JobId);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YGetPrinterData(
|
|
HANDLE hPrinter,
|
|
LPTSTR pValueName,
|
|
LPDWORD pType,
|
|
LPBYTE pData,
|
|
DWORD nSize,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
dwRet = GetPrinterData(hPrinter, pValueName, pType,
|
|
pData, nSize, pcbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD
|
|
YGetPrinterDataEx(
|
|
HANDLE hPrinter,
|
|
LPCTSTR pKeyName,
|
|
LPCTSTR pValueName,
|
|
LPDWORD pType,
|
|
LPBYTE pData,
|
|
DWORD nSize,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
dwRet = GetPrinterDataEx(hPrinter, pKeyName,pValueName, pType,
|
|
pData, nSize, pcbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
DWORD
|
|
YEnumPrinterData(
|
|
HANDLE hPrinter,
|
|
DWORD dwIndex, // index of value to query
|
|
LPWSTR pValueName, // address of buffer for value string
|
|
DWORD cbValueName, // size of value buffer
|
|
LPDWORD pcbValueName, // address for size of value buffer
|
|
LPDWORD pType, // address of buffer for type code
|
|
LPBYTE pData, // address of buffer for value data
|
|
DWORD cbData, // size of data buffer
|
|
LPDWORD pcbData, // address for size of data buffer
|
|
CALL_ROUTE Route // where this call comes from
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
dwRet = EnumPrinterData(hPrinter,
|
|
dwIndex,
|
|
pValueName,
|
|
cbValueName,
|
|
pcbValueName,
|
|
pType,
|
|
pData,
|
|
cbData,
|
|
pcbData);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD
|
|
YEnumPrinterDataEx(
|
|
HANDLE hPrinter,
|
|
LPCWSTR pKeyName, // address of key name
|
|
LPBYTE pEnumValues,
|
|
DWORD cbEnumValues,
|
|
LPDWORD pcbEnumValues,
|
|
LPDWORD pnEnumValues,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
DWORD cReturned;
|
|
PPRINTER_ENUM_VALUES pEnumValue = (PPRINTER_ENUM_VALUES) pEnumValues;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pEnumValues, &cbEnumValues);
|
|
|
|
if (pEnumValues && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
dwRet = EnumPrinterDataEx( hPrinter,
|
|
pKeyName,
|
|
pAlignedBuff,
|
|
cbEnumValues,
|
|
pcbEnumValues,
|
|
pnEnumValues);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (dwRet == ERROR_SUCCESS) {
|
|
|
|
if (!MarshallDownStructuresArray((LPBYTE) pAlignedBuff,
|
|
*pnEnumValues,
|
|
PrinterEnumValuesFields,
|
|
sizeof(PRINTER_ENUM_VALUES),
|
|
Route) ) {
|
|
dwRet = GetLastError();
|
|
}
|
|
|
|
}
|
|
|
|
UndoAlignRpcPtr(pEnumValues, pAlignedBuff, cbEnumValues, pcbEnumValues);
|
|
|
|
return dwRet;
|
|
|
|
}
|
|
|
|
DWORD
|
|
YEnumPrinterKey(
|
|
HANDLE hPrinter,
|
|
LPCWSTR pKeyName, // address of key name
|
|
LPWSTR pSubkey, // address of buffer for value string
|
|
DWORD cbSubkey, // size of value buffer
|
|
LPDWORD pcbSubkey, // address for size of value buffer
|
|
CALL_ROUTE Route // where this call comes from
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
dwRet = EnumPrinterKey( hPrinter,
|
|
pKeyName,
|
|
pSubkey,
|
|
cbSubkey,
|
|
pcbSubkey);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD
|
|
YDeletePrinterData(
|
|
HANDLE hPrinter,
|
|
LPWSTR pValueName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
dwRet = DeletePrinterData(hPrinter, pValueName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD
|
|
YDeletePrinterDataEx(
|
|
HANDLE hPrinter,
|
|
LPCWSTR pKeyName,
|
|
LPCWSTR pValueName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
dwRet = DeletePrinterDataEx(hPrinter, pKeyName, pValueName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD
|
|
YDeletePrinterKey(
|
|
HANDLE hPrinter,
|
|
LPCWSTR pKeyName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
dwRet = DeletePrinterKey(hPrinter, pKeyName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
DWORD
|
|
YSetPrinterData(
|
|
HANDLE hPrinter,
|
|
LPTSTR pValueName,
|
|
DWORD Type,
|
|
LPBYTE pData,
|
|
DWORD cbData,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
dwRet = SetPrinterData(hPrinter, pValueName, Type, pData, cbData);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
DWORD
|
|
YSetPrinterDataEx(
|
|
HANDLE hPrinter,
|
|
LPCTSTR pKeyName,
|
|
LPCTSTR pValueName,
|
|
DWORD Type,
|
|
LPBYTE pData,
|
|
DWORD cbData,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
dwRet = SetPrinterDataEx(hPrinter, pKeyName, pValueName, Type, pData, cbData);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
return dwRet;
|
|
}
|
|
|
|
|
|
DWORD
|
|
YWaitForPrinterChange(
|
|
HANDLE hPrinter,
|
|
DWORD Flags,
|
|
LPDWORD pFlags,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
*pFlags = WaitForPrinterChange(hPrinter, Flags);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (*pFlags) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YClosePrinter(
|
|
LPHANDLE phPrinter,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = ClosePrinter(*phPrinter);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
*phPrinter = NULL; // NULL out handle so Route knows to close it down.
|
|
|
|
if (bRet) {
|
|
|
|
InterlockedDecrement( &ServerHandleCount );
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
PRINTER_HANDLE_rundown(
|
|
HANDLE hPrinter
|
|
)
|
|
{
|
|
DBGMSG(DBG_INFO, ("Printer Handle rundown called\n"));
|
|
|
|
PrinterHandleRundown(hPrinter);
|
|
}
|
|
|
|
DWORD
|
|
YAddForm(
|
|
HANDLE hPrinter,
|
|
PFORM_CONTAINER pFormInfoContainer,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if(!pFormInfoContainer)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = AddForm(hPrinter, pFormInfoContainer->Level,
|
|
(LPBYTE)pFormInfoContainer->FormInfo.pFormInfo1);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YDeleteForm(
|
|
HANDLE hPrinter,
|
|
LPWSTR pFormName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeleteForm(hPrinter, pFormName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YGetForm(
|
|
PRINTER_HANDLE hPrinter,
|
|
LPWSTR pFormName,
|
|
DWORD Level,
|
|
LPBYTE pForm,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pForm, &cbBuf);
|
|
|
|
if (pForm && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = GetForm(hPrinter, pFormName, Level, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructure(pAlignedBuff, FormInfo1Fields, sizeof(FORM_INFO_1), Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pForm, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YSetForm(
|
|
PRINTER_HANDLE hPrinter,
|
|
LPWSTR pFormName,
|
|
PFORM_CONTAINER pFormInfoContainer,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = SetForm(hPrinter, pFormName, pFormInfoContainer->Level,
|
|
(LPBYTE)pFormInfoContainer->FormInfo.pFormInfo1);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YEnumForms(
|
|
PRINTER_HANDLE hPrinter,
|
|
DWORD Level,
|
|
LPBYTE pForm,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
DWORD cReturned, cbStruct;
|
|
FieldInfo *pFieldInfo;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = FormInfo1Fields;
|
|
cbStruct = sizeof(FORM_INFO_1);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pForm, &cbBuf);
|
|
|
|
if (pForm && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = EnumForms(hPrinter, Level, pAlignedBuff, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructuresArray(pAlignedBuff, *pcReturned, pFieldInfo, cbStruct, Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pForm, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YEnumPorts(
|
|
LPWSTR pName,
|
|
DWORD Level,
|
|
LPBYTE pPort,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
DWORD cReturned, cbStruct;
|
|
FieldInfo *pFieldInfo;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = PortInfo1Fields;
|
|
cbStruct = sizeof(PORT_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pFieldInfo = PortInfo2Fields;
|
|
cbStruct = sizeof(PORT_INFO_2);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pPort, &cbBuf);
|
|
|
|
if (pPort && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = EnumPorts(pName, Level, pAlignedBuff, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructuresArray(pAlignedBuff, *pcReturned, pFieldInfo, cbStruct, Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pPort, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YEnumMonitors(
|
|
LPWSTR pName,
|
|
DWORD Level,
|
|
LPBYTE pMonitor,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
LPDWORD pcReturned,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
DWORD cReturned, cbStruct;
|
|
FieldInfo *pFieldInfo;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = MonitorInfo1Fields;
|
|
cbStruct = sizeof(MONITOR_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pFieldInfo = MonitorInfo2Fields;
|
|
cbStruct = sizeof(MONITOR_INFO_2);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pMonitor, &cbBuf);
|
|
|
|
if (pMonitor && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = EnumMonitors(pName, Level, pAlignedBuff, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructuresArray(pAlignedBuff, *pcReturned, pFieldInfo, cbStruct, Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pMonitor, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
|
|
}
|
|
|
|
DWORD
|
|
YAddPort(
|
|
LPWSTR pName,
|
|
HWND hWnd,
|
|
LPWSTR pMonitorName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = AddPort(pName, hWnd, pMonitorName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YConfigurePort(
|
|
LPWSTR pName,
|
|
HWND hWnd,
|
|
LPWSTR pPortName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = ConfigurePort(pName, hWnd, pPortName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YDeletePort(
|
|
LPWSTR pName,
|
|
HWND hWnd,
|
|
LPWSTR pPortName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeletePort(pName, hWnd, pPortName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YXcvData(
|
|
HANDLE hXcv,
|
|
PCWSTR pszDataName,
|
|
PBYTE pInputData,
|
|
DWORD cbInputData,
|
|
PBYTE pOutputData,
|
|
DWORD cbOutputData,
|
|
PDWORD pcbOutputNeeded,
|
|
PDWORD pdwStatus,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = XcvData( hXcv,
|
|
pszDataName,
|
|
pInputData,
|
|
cbInputData,
|
|
pOutputData,
|
|
cbOutputData,
|
|
pcbOutputNeeded,
|
|
pdwStatus);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
|
|
DWORD
|
|
YCreatePrinterIC(
|
|
HANDLE hPrinter,
|
|
HANDLE *pHandle,
|
|
LPDEVMODE_CONTAINER pDevModeContainer,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
if ( InvalidDevModeContainer(pDevModeContainer) ) {
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
*pHandle = CreatePrinterIC(hPrinter,
|
|
(LPDEVMODEW)pDevModeContainer->pDevMode);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (*pHandle)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YPlayGdiScriptOnPrinterIC(
|
|
GDI_HANDLE hPrinterIC,
|
|
LPBYTE pIn,
|
|
DWORD cIn,
|
|
LPBYTE pOut,
|
|
DWORD cOut,
|
|
DWORD ul,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = PlayGdiScriptOnPrinterIC(hPrinterIC, pIn, cIn, pOut, cOut, ul);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YDeletePrinterIC(
|
|
GDI_HANDLE *phPrinterIC,
|
|
BOOL bImpersonate,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (bImpersonate && !YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeletePrinterIC(*phPrinterIC);
|
|
|
|
if (bImpersonate)
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
*phPrinterIC = NULL; // NULL out handle so Route knows to close it down.
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
|
|
DWORD
|
|
YPrinterMessageBox(
|
|
PRINTER_HANDLE hPrinter,
|
|
DWORD Error,
|
|
HWND hWnd,
|
|
LPWSTR pText,
|
|
LPWSTR pCaption,
|
|
DWORD dwType,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
return PrinterMessageBox(hPrinter, Error, hWnd, pText, pCaption, dwType);
|
|
}
|
|
|
|
DWORD
|
|
YAddMonitor(
|
|
LPWSTR pName,
|
|
PMONITOR_CONTAINER pMonitorContainer,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if(!ValidateMonitorContainer(pMonitorContainer))
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = AddMonitor(pName, pMonitorContainer->Level,
|
|
(LPBYTE)pMonitorContainer->MonitorInfo.pMonitorInfo1);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YDeleteMonitor(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
LPWSTR pMonitorName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeleteMonitor(pName, pEnvironment, pMonitorName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YDeletePrintProcessor(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
LPWSTR pPrintProcessorName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeletePrintProcessor(pName, pEnvironment, pPrintProcessorName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YAddPrintProvidor(
|
|
LPWSTR pName,
|
|
PPROVIDOR_CONTAINER pProvidorContainer,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
DWORD cchOrder;
|
|
LPBYTE pProvidorInfo;
|
|
|
|
PROVIDOR_INFO_2W ProvidorInfo2;
|
|
LPRPC_PROVIDOR_INFO_2W pRpcProvidorInfo;
|
|
|
|
if(!pProvidorContainer)
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
switch (pProvidorContainer->Level) {
|
|
case 1:
|
|
pProvidorInfo = (LPBYTE) pProvidorContainer->ProvidorInfo.pProvidorInfo1;
|
|
break;
|
|
|
|
case 2:
|
|
pRpcProvidorInfo = (LPRPC_PROVIDOR_INFO_2W)
|
|
pProvidorContainer->ProvidorInfo.pRpcProvidorInfo2;
|
|
cchOrder = pRpcProvidorInfo->cchOrder;
|
|
|
|
ProvidorInfo2.pOrder = (cchOrder == 0 || cchOrder == 1)
|
|
? szNull
|
|
: pRpcProvidorInfo->pOrder;
|
|
|
|
pProvidorInfo = (LPBYTE) &ProvidorInfo2;
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
bRet = AddPrintProvidor(pName, pProvidorContainer->Level,
|
|
pProvidorInfo);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YDeletePrintProvidor(
|
|
LPWSTR pName,
|
|
LPWSTR pEnvironment,
|
|
LPWSTR pPrintProvidorName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = DeletePrintProvidor(pName, pEnvironment, pPrintProvidorName);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
|
|
DWORD
|
|
YGetPrinterDriver2(
|
|
HANDLE hPrinter,
|
|
LPWSTR pEnvironment,
|
|
DWORD Level,
|
|
LPBYTE pDriverInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
DWORD dwClientMajorVersion,
|
|
DWORD dwClientMinorVersion,
|
|
PDWORD pdwServerMajorVersion,
|
|
PDWORD pdwServerMinorVersion,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
FieldInfo *pFieldInfo;
|
|
BOOL bRet;
|
|
SIZE_T cbStruct;
|
|
LPBYTE pAlignedBuff;
|
|
|
|
switch (Level) {
|
|
|
|
case 1:
|
|
pFieldInfo = DriverInfo1Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_1);
|
|
break;
|
|
|
|
case 2:
|
|
pFieldInfo = DriverInfo2Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_2);
|
|
break;
|
|
|
|
case 3:
|
|
pFieldInfo = DriverInfo3Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_3);
|
|
break;
|
|
|
|
case 4:
|
|
pFieldInfo = DriverInfo4Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_4);
|
|
break;
|
|
|
|
case 5:
|
|
pFieldInfo = DriverInfo5Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_5);
|
|
break;
|
|
|
|
case 6:
|
|
pFieldInfo = DriverInfo6Fields;
|
|
cbStruct = sizeof(DRIVER_INFO_6);
|
|
break;
|
|
|
|
case DRIVER_INFO_VERSION_LEVEL:
|
|
pFieldInfo = DriverInfoVersionFields;
|
|
cbStruct = sizeof(DRIVER_INFO_VERSION);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
//
|
|
// Hack-Hack-Hack to determine if we want the most recent driver
|
|
//
|
|
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
pAlignedBuff = AlignRpcPtr(pDriverInfo, &cbBuf);
|
|
|
|
if (pDriverInfo && !pAlignedBuff){
|
|
return GetLastError();
|
|
}
|
|
|
|
bRet = GetPrinterDriverExW(hPrinter, pEnvironment, Level, pAlignedBuff,
|
|
cbBuf, pcbNeeded, dwClientMajorVersion,
|
|
dwClientMinorVersion, pdwServerMajorVersion,
|
|
pdwServerMinorVersion);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
bRet = MarshallDownStructure(pAlignedBuff, pFieldInfo, cbStruct, Route);
|
|
}
|
|
|
|
UndoAlignRpcPtr(pDriverInfo, pAlignedBuff, cbBuf, pcbNeeded);
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YAddPortEx(
|
|
LPWSTR pName,
|
|
LPPORT_CONTAINER pPortContainer,
|
|
LPPORT_VAR_CONTAINER pPortVarContainer,
|
|
LPWSTR pMonitorName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
DWORD Level;
|
|
PPORT_INFO_FF pPortInfoFF;
|
|
PPORT_INFO_1 pPortInfo1;
|
|
|
|
if(!ValidatePortContainer(pPortContainer))
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
Level = pPortContainer->Level;
|
|
|
|
switch (Level){
|
|
case 1:
|
|
pPortInfo1 = pPortContainer->PortInfo.pPortInfo1;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
bRet = AddPortEx(pName, Level, (LPBYTE)pPortInfo1, pMonitorName);
|
|
YRevertToSelf(Route);
|
|
break;
|
|
|
|
case (DWORD)-1:
|
|
|
|
pPortInfoFF = pPortContainer->PortInfo.pPortInfoFF;
|
|
if(!ValidatePortVarContainer(pPortVarContainer))
|
|
{
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
pPortInfoFF->cbMonitorData = pPortVarContainer->cbMonitorData;
|
|
pPortInfoFF->pMonitorData = pPortVarContainer->pMonitorData;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
bRet = AddPortEx(pName, Level, (LPBYTE)pPortInfoFF, pMonitorName);
|
|
YRevertToSelf(Route);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
if (bRet) {
|
|
return ERROR_SUCCESS;
|
|
} else
|
|
return GetLastError();
|
|
}
|
|
|
|
|
|
DWORD
|
|
YSpoolerInit(
|
|
LPWSTR pName,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = SpoolerInit();
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
YResetPrinterEx(
|
|
HANDLE hPrinter,
|
|
LPWSTR pDatatype,
|
|
LPDEVMODE_CONTAINER pDevModeContainer,
|
|
DWORD dwFlag,
|
|
CALL_ROUTE Route
|
|
|
|
)
|
|
{
|
|
PRINTER_DEFAULTS Defaults;
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
if ( InvalidDevModeContainer(pDevModeContainer) ) {
|
|
YRevertToSelf(Route);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (pDatatype) {
|
|
Defaults.pDatatype = pDatatype;
|
|
}else {
|
|
if (dwFlag & RESET_PRINTER_DATATYPE) {
|
|
Defaults.pDatatype = (LPWSTR)-1;
|
|
}else {
|
|
Defaults.pDatatype = NULL;
|
|
}
|
|
}
|
|
|
|
if ((LPDEVMODE)pDevModeContainer->pDevMode) {
|
|
Defaults.pDevMode = (LPDEVMODE)pDevModeContainer->pDevMode;
|
|
}else {
|
|
if (dwFlag & RESET_PRINTER_DEVMODE) {
|
|
Defaults.pDevMode = (LPDEVMODE)-1;
|
|
}else{
|
|
Defaults.pDevMode = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// You cannot change the Access Mask on a Printer Spool Object
|
|
// We will always ignore this parameter and set it to zero
|
|
// We get some random garbage otherwise.
|
|
//
|
|
|
|
Defaults.DesiredAccess = 0;
|
|
|
|
bRet = ResetPrinter(hPrinter, &Defaults);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YSetAllocFailCount(
|
|
HANDLE hPrinter,
|
|
DWORD dwFailCount,
|
|
LPDWORD lpdwAllocCount,
|
|
LPDWORD lpdwFreeCount,
|
|
LPDWORD lpdwFailCountHit,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = SetAllocFailCount( hPrinter, dwFailCount, lpdwAllocCount, lpdwFreeCount, lpdwFailCountHit );
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet)
|
|
return ERROR_SUCCESS;
|
|
else
|
|
return GetLastError();
|
|
}
|
|
|
|
|
|
BOOL
|
|
YImpersonateClient(
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD Status;
|
|
|
|
if (Route != NATIVE_CALL) {
|
|
|
|
Status = RpcImpersonateClient(NULL);
|
|
SPLASSERT( Status == RPC_S_OK || Status == RPC_S_NO_CONTEXT_AVAILABLE );
|
|
|
|
if ( Status != RPC_S_OK ) {
|
|
SetLastError( Status );
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE; // If not RPC, then we should continue w/out doing anything
|
|
}
|
|
|
|
DWORD
|
|
YSetPort(
|
|
LPWSTR pName,
|
|
LPWSTR pPortName,
|
|
LPPORT_CONTAINER pPortContainer,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if(!ValidatePortContainer(pPortContainer))
|
|
{
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
switch (pPortContainer->Level) {
|
|
|
|
case 3:
|
|
if ( !YImpersonateClient(Route) )
|
|
return GetLastError();
|
|
|
|
bRet = SetPort(pName,
|
|
pPortName,
|
|
pPortContainer->Level,
|
|
(LPBYTE)pPortContainer->PortInfo.pPortInfo1);
|
|
YRevertToSelf(Route);
|
|
break;
|
|
|
|
default:
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
return bRet ? ERROR_SUCCESS : GetLastError();
|
|
}
|
|
|
|
|
|
DWORD
|
|
YClusterSplOpen(
|
|
LPCTSTR pszServer,
|
|
LPCTSTR pszResource,
|
|
PHANDLE phSpooler,
|
|
LPCTSTR pszName,
|
|
LPCTSTR pszAddress,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = ClusterSplOpen( pszServer,
|
|
pszResource,
|
|
phSpooler,
|
|
pszName,
|
|
pszAddress );
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YClusterSplClose(
|
|
PHANDLE phPrinter,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = ClusterSplClose( *phPrinter );
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
*phPrinter = NULL; // NULL out handle so Route knows to close it down.
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YClusterSplIsAlive(
|
|
HANDLE hSpooler,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
return GetLastError();
|
|
|
|
bRet = ClusterSplIsAlive( hSpooler );
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
if (bRet) {
|
|
|
|
return ERROR_SUCCESS;
|
|
|
|
} else
|
|
|
|
return GetLastError();
|
|
}
|
|
|
|
DWORD
|
|
YGetSpoolFileInfo(
|
|
HANDLE hPrinter,
|
|
DWORD dwAppProcessId,
|
|
DWORD dwLevel,
|
|
LPBYTE pSpoolFileInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
HANDLE hAppProcess;
|
|
BOOL bReturn = FALSE;
|
|
|
|
// Open the application before impersonating the user
|
|
hAppProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwAppProcessId);
|
|
|
|
if (!YImpersonateClient(Route)) {
|
|
goto CleanUp;
|
|
}
|
|
|
|
bReturn = SplGetSpoolFileInfo(hPrinter, hAppProcess, dwLevel,
|
|
pSpoolFileInfo, cbBuf, pcbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
CleanUp:
|
|
|
|
if (hAppProcess) {
|
|
CloseHandle(hAppProcess);
|
|
}
|
|
|
|
if (bReturn) {
|
|
return ERROR_SUCCESS;
|
|
} else {
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
YGetSpoolFileInfo2(
|
|
HANDLE hPrinter,
|
|
DWORD dwAppProcessId,
|
|
DWORD dwLevel,
|
|
LPFILE_INFO_CONTAINER pSplFileInfoContainer,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
HANDLE hAppProcess;
|
|
BOOL bReturn = FALSE;
|
|
DWORD cbNeeded = 0;
|
|
LPBYTE pSpoolFileInfo;
|
|
DWORD cbSize;
|
|
DWORD dwLastError = ERROR_SUCCESS;
|
|
|
|
switch (dwLevel){
|
|
case 1:
|
|
|
|
if(!pSplFileInfoContainer || !pSplFileInfoContainer->FileInfo.Level1)
|
|
{
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
pSpoolFileInfo = (LPBYTE)pSplFileInfoContainer->FileInfo.Level1;
|
|
cbSize = sizeof(SPOOL_FILE_INFO_1);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
// Open the application before impersonating the user
|
|
if ( hAppProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwAppProcessId) ) {
|
|
|
|
if (YImpersonateClient(Route)) {
|
|
|
|
bReturn = SplGetSpoolFileInfo(hPrinter, hAppProcess, dwLevel,
|
|
pSpoolFileInfo,
|
|
cbSize, &cbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
}
|
|
}
|
|
|
|
if ( !bReturn ) {
|
|
|
|
dwLastError = GetLastError();
|
|
|
|
//
|
|
// Ensure that if someone didn't set a last error, but failed the call,
|
|
// we still return an error.
|
|
//
|
|
if (dwLastError == ERROR_SUCCESS) {
|
|
|
|
dwLastError = ERROR_INVALID_HANDLE;
|
|
}
|
|
}
|
|
|
|
if (hAppProcess) {
|
|
CloseHandle(hAppProcess);
|
|
}
|
|
|
|
return dwLastError;
|
|
}
|
|
|
|
DWORD
|
|
YCommitSpoolData(
|
|
HANDLE hPrinter,
|
|
DWORD dwAppProcessId,
|
|
DWORD cbCommit,
|
|
DWORD dwLevel,
|
|
LPBYTE pSpoolFileInfo,
|
|
DWORD cbBuf,
|
|
LPDWORD pcbNeeded,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
HANDLE hAppProcess;
|
|
BOOL bReturn = FALSE;
|
|
|
|
// Open the application before impersonating the user
|
|
hAppProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwAppProcessId);
|
|
|
|
if (!YImpersonateClient(Route)) {
|
|
goto CleanUp;
|
|
}
|
|
|
|
bReturn = SplCommitSpoolData(hPrinter, hAppProcess, cbCommit,
|
|
dwLevel, pSpoolFileInfo, cbBuf, pcbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
CleanUp:
|
|
|
|
if (hAppProcess) {
|
|
CloseHandle(hAppProcess);
|
|
}
|
|
|
|
if (bReturn) {
|
|
return ERROR_SUCCESS;
|
|
} else {
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
DWORD
|
|
YCommitSpoolData2(
|
|
HANDLE hPrinter,
|
|
DWORD dwAppProcessId,
|
|
DWORD cbCommit,
|
|
DWORD dwLevel,
|
|
LPFILE_INFO_CONTAINER pSplFileInfoContainer,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
HANDLE hAppProcess;
|
|
BOOL bReturn = FALSE;
|
|
DWORD cbNeeded = 0;
|
|
LPBYTE pSpoolFileInfo;
|
|
DWORD cbSize;
|
|
DWORD dwLastError = ERROR_SUCCESS;
|
|
|
|
switch (dwLevel){
|
|
case 1:
|
|
|
|
if(!pSplFileInfoContainer || !pSplFileInfoContainer->FileInfo.Level1)
|
|
{
|
|
return ERROR_INVALID_HANDLE;
|
|
}
|
|
pSpoolFileInfo = (LPBYTE)pSplFileInfoContainer->FileInfo.Level1;
|
|
cbSize = sizeof(SPOOL_FILE_INFO_1);
|
|
break;
|
|
|
|
default:
|
|
return ERROR_INVALID_LEVEL;
|
|
}
|
|
|
|
// Open the application before impersonating the user
|
|
if ( hAppProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwAppProcessId) ) {
|
|
|
|
if (YImpersonateClient(Route)) {
|
|
|
|
bReturn = SplCommitSpoolData(hPrinter, hAppProcess, cbCommit,
|
|
dwLevel, pSpoolFileInfo,
|
|
cbSize, &cbNeeded);
|
|
|
|
YRevertToSelf(Route);
|
|
}
|
|
}
|
|
|
|
if ( !bReturn ) {
|
|
|
|
dwLastError = GetLastError();
|
|
|
|
//
|
|
// Make sure that there is a failure return if there is no last error.
|
|
//
|
|
if (dwLastError == ERROR_SUCCESS) {
|
|
|
|
dwLastError = ERROR_INVALID_HANDLE;
|
|
}
|
|
}
|
|
|
|
if (hAppProcess) {
|
|
CloseHandle(hAppProcess);
|
|
}
|
|
|
|
return dwLastError;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
YCloseSpoolFileHandle(
|
|
HANDLE hPrinter,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
if (!YImpersonateClient(Route)) {
|
|
goto CleanUp;
|
|
}
|
|
|
|
bReturn = SplCloseSpoolFileHandle(hPrinter);
|
|
|
|
YRevertToSelf(Route);
|
|
|
|
CleanUp:
|
|
|
|
if (bReturn) {
|
|
return ERROR_SUCCESS;
|
|
} else {
|
|
return GetLastError();
|
|
}
|
|
}
|
|
|
|
|
|
DWORD
|
|
YSendRecvBidiData(
|
|
IN HANDLE hPrinter,
|
|
IN LPCWSTR pAction,
|
|
IN PBIDI_REQUEST_CONTAINER pReqData,
|
|
OUT PBIDI_RESPONSE_CONTAINER* ppResData,
|
|
CALL_ROUTE Route
|
|
)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
if (!YImpersonateClient(Route))
|
|
{
|
|
dwRet = GetLastError();
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Do we need to verify the Data in pReqData ???
|
|
//
|
|
dwRet = SendRecvBidiData(hPrinter,
|
|
pAction,
|
|
pReqData,
|
|
ppResData);
|
|
YRevertToSelf(Route);
|
|
}
|
|
|
|
return (dwRet);
|
|
}
|
|
|