mirror of
https://github.com/reactos/reactos.git
synced 2024-11-02 04:37:32 +00:00
7bffb70353
WinSpool : Implement missing API. Sync/Port from wine. Setting it to fast track for needed testing of the later GDI code. Leaving Fix-me debug prints on. Local tree has WinSpool_winetest turned on. So no debug noise during normal ReactOS operation. SpoolSS : Reordered header types. Have more Spl function to be added while SpoolSV is being coded to forward to LocalSpl. Based on wine and old research from the GDI code.
552 lines
18 KiB
C
552 lines
18 KiB
C
/*
|
|
* PROJECT: ReactOS Spooler API
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: Functions for managing print jobs
|
|
* COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org)
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
#include <marshalling/jobs.h>
|
|
|
|
BOOL WINAPI
|
|
AddJobA(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded)
|
|
{
|
|
BOOL ret;
|
|
|
|
FIXME("AddJobA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pData, cbBuf, pcbNeeded);
|
|
|
|
if (Level != 1)
|
|
{
|
|
ERR("Level = %d, unsupported!\n", Level);
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
ret = AddJobW(hPrinter, Level, pData, cbBuf, pcbNeeded);
|
|
|
|
if (ret)
|
|
{
|
|
DWORD dwErrorCode;
|
|
ADDJOB_INFO_1W *addjobW = (ADDJOB_INFO_1W*)pData;
|
|
dwErrorCode = UnicodeToAnsiInPlace(addjobW->Path);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
ret = FALSE;
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
AddJobW(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNeeded)
|
|
{
|
|
DWORD dwErrorCode;
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
FIXME("AddJobW(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pData, cbBuf, pcbNeeded);
|
|
|
|
if (!pHandle)
|
|
{
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Do the RPC call
|
|
RpcTryExcept
|
|
{
|
|
dwErrorCode = _RpcAddJob(pHandle->hPrinter, Level, pData, cbBuf, pcbNeeded);
|
|
}
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
dwErrorCode = RpcExceptionCode();
|
|
ERR("_RpcAddJob failed with exception code %lu!\n", dwErrorCode);
|
|
}
|
|
RpcEndExcept;
|
|
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
|
{
|
|
// Replace relative offset addresses in the output by absolute pointers.
|
|
MarshallUpStructure(cbBuf, pData, AddJobInfo1Marshalling.pInfo, AddJobInfo1Marshalling.cbStructureSize, TRUE);
|
|
pHandle->bJob = TRUE;
|
|
FIXME("Notify Tray Icon\n");
|
|
}
|
|
|
|
Cleanup:
|
|
SetLastError(dwErrorCode);
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
}
|
|
|
|
BOOL WINAPI
|
|
EnumJobsA(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
|
{
|
|
DWORD dwErrorCode, i;
|
|
JOB_INFO_1W* pji1w = (JOB_INFO_1W*)pJob;
|
|
JOB_INFO_2A* pji2a = (JOB_INFO_2A*)pJob;
|
|
JOB_INFO_2W* pji2w = (JOB_INFO_2W*)pJob;
|
|
|
|
TRACE("EnumJobsA(%p, %lu, %lu, %lu, %p, %lu, %p, %p)\n", hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
if ( Level == 3 )
|
|
return EnumJobsW( hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned );
|
|
|
|
if ( EnumJobsW( hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned ) )
|
|
{
|
|
switch ( Level )
|
|
{
|
|
case 1:
|
|
{
|
|
for ( i = 0; i < *pcReturned; i++ )
|
|
{
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pPrinterName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pMachineName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pUserName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pDocument);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pDatatype);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w[i].pStatus);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
{
|
|
for ( i = 0; i < *pcReturned; i++ )
|
|
{
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pPrinterName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pMachineName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pUserName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pDocument);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pNotifyName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pDatatype);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pPrintProcessor);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pParameters);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w[i].pStatus);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
if ( pji2w[i].pDevMode )
|
|
{
|
|
RosConvertUnicodeDevModeToAnsiDevmode( pji2w[i].pDevMode, pji2a[i].pDevMode );
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
Cleanup:
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
EnumJobsW(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
|
{
|
|
DWORD dwErrorCode;
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
TRACE("EnumJobsW(%p, %lu, %lu, %lu, %p, %lu, %p, %p)\n", hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
if (!pHandle)
|
|
{
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Do the RPC call
|
|
RpcTryExcept
|
|
{
|
|
dwErrorCode = _RpcEnumJobs(pHandle->hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned);
|
|
}
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
dwErrorCode = RpcExceptionCode();
|
|
ERR("_RpcEnumJobs failed with exception code %lu!\n", dwErrorCode);
|
|
}
|
|
RpcEndExcept;
|
|
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
|
{
|
|
// Replace relative offset addresses in the output by absolute pointers for JOB_INFO_1W and JOB_INFO_2W.
|
|
if (Level <= 2)
|
|
{
|
|
ASSERT(Level >= 1);
|
|
MarshallUpStructuresArray(cbBuf, pJob, *pcReturned, pJobInfoMarshalling[Level]->pInfo, pJobInfoMarshalling[Level]->cbStructureSize, TRUE);
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
SetLastError(dwErrorCode);
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
}
|
|
|
|
BOOL WINAPI
|
|
GetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded)
|
|
{
|
|
DWORD dwErrorCode;
|
|
JOB_INFO_1W* pji1w = (JOB_INFO_1W*)pJob;
|
|
JOB_INFO_2A* pji2a = (JOB_INFO_2A*)pJob;
|
|
JOB_INFO_2W* pji2w = (JOB_INFO_2W*)pJob;
|
|
|
|
FIXME("GetJobA(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
|
|
|
|
if ( Level == 3 )
|
|
return GetJobW( hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded );
|
|
|
|
if ( GetJobW( hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded ) )
|
|
{
|
|
switch ( Level )
|
|
{
|
|
case 1:
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w->pPrinterName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w->pMachineName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w->pUserName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w->pDocument);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w->pDatatype);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji1w->pStatus);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w->pPrinterName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w->pMachineName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w->pUserName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w->pDocument);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w->pNotifyName);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w->pDatatype);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w->pPrintProcessor);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w->pParameters);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
dwErrorCode = UnicodeToAnsiInPlace(pji2w->pStatus);
|
|
if (dwErrorCode != ERROR_SUCCESS)
|
|
{
|
|
goto Cleanup;
|
|
}
|
|
if ( pji2w->pDevMode )
|
|
{
|
|
RosConvertUnicodeDevModeToAnsiDevmode( pji2w->pDevMode, pji2a->pDevMode );
|
|
}
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
Cleanup:
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJob, DWORD cbBuf, PDWORD pcbNeeded)
|
|
{
|
|
DWORD dwErrorCode;
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
FIXME("GetJobW(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
|
|
|
|
if (!pHandle)
|
|
{
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Do the RPC call
|
|
RpcTryExcept
|
|
{
|
|
dwErrorCode = _RpcGetJob(pHandle->hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
|
|
}
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
dwErrorCode = RpcExceptionCode();
|
|
ERR("_RpcGetJob failed with exception code %lu!\n", dwErrorCode);
|
|
}
|
|
RpcEndExcept;
|
|
|
|
if (dwErrorCode == ERROR_SUCCESS)
|
|
{
|
|
// Replace relative offset addresses in the output by absolute pointers.
|
|
ASSERT(Level >= 1 && Level <= 2);
|
|
MarshallUpStructure(cbBuf, pJob, pJobInfoMarshalling[Level]->pInfo, pJobInfoMarshalling[Level]->cbStructureSize, TRUE);
|
|
}
|
|
|
|
Cleanup:
|
|
SetLastError(dwErrorCode);
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
}
|
|
|
|
BOOL WINAPI
|
|
ScheduleJob(HANDLE hPrinter, DWORD dwJobID)
|
|
{
|
|
DWORD dwErrorCode;
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
|
|
TRACE("ScheduleJob(%p, %lu)\n", hPrinter, dwJobID);
|
|
|
|
if (!pHandle)
|
|
{
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// Do the RPC call
|
|
RpcTryExcept
|
|
{
|
|
dwErrorCode = _RpcScheduleJob(pHandle->hPrinter, dwJobID);
|
|
}
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
dwErrorCode = RpcExceptionCode();
|
|
ERR("_RpcScheduleJob failed with exception code %lu!\n", dwErrorCode);
|
|
}
|
|
RpcEndExcept;
|
|
|
|
if ( dwErrorCode == ERROR_SUCCESS )
|
|
pHandle->bJob = FALSE;
|
|
|
|
Cleanup:
|
|
SetLastError(dwErrorCode);
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
}
|
|
|
|
BOOL WINAPI
|
|
SetJobA(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command)
|
|
{
|
|
BOOL ret;
|
|
LPBYTE JobW;
|
|
UNICODE_STRING usBuffer;
|
|
|
|
TRACE("SetJobA(%p, %lu, %lu, %p, %lu)\n", hPrinter, JobId, Level, pJobInfo, Command);
|
|
|
|
/* JobId, pPrinterName, pMachineName, pDriverName, Size, Submitted, Time and TotalPages
|
|
are all ignored by SetJob, so we don't bother copying them */
|
|
switch(Level)
|
|
{
|
|
case 0:
|
|
JobW = NULL;
|
|
break;
|
|
case 1:
|
|
{
|
|
JOB_INFO_1W *info1W = HeapAlloc(GetProcessHeap(), 0, sizeof(*info1W));
|
|
ZeroMemory( info1W, sizeof(JOB_INFO_1W) );
|
|
JOB_INFO_1A *info1A = (JOB_INFO_1A*)pJobInfo;
|
|
|
|
JobW = (LPBYTE)info1W;
|
|
info1W->pUserName = AsciiToUnicode(&usBuffer, info1A->pUserName);
|
|
info1W->pDocument = AsciiToUnicode(&usBuffer, info1A->pDocument);
|
|
info1W->pDatatype = AsciiToUnicode(&usBuffer, info1A->pDatatype);
|
|
info1W->pStatus = AsciiToUnicode(&usBuffer, info1A->pStatus);
|
|
info1W->Status = info1A->Status;
|
|
info1W->Priority = info1A->Priority;
|
|
info1W->Position = info1A->Position;
|
|
info1W->PagesPrinted = info1A->PagesPrinted;
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
JOB_INFO_2W *info2W = HeapAlloc(GetProcessHeap(), 0, sizeof(*info2W));
|
|
ZeroMemory( info2W, sizeof(JOB_INFO_2W) );
|
|
JOB_INFO_2A *info2A = (JOB_INFO_2A*)pJobInfo;
|
|
|
|
JobW = (LPBYTE)info2W;
|
|
info2W->pUserName = AsciiToUnicode(&usBuffer, info2A->pUserName);
|
|
info2W->pDocument = AsciiToUnicode(&usBuffer, info2A->pDocument);
|
|
info2W->pNotifyName = AsciiToUnicode(&usBuffer, info2A->pNotifyName);
|
|
info2W->pDatatype = AsciiToUnicode(&usBuffer, info2A->pDatatype);
|
|
info2W->pPrintProcessor = AsciiToUnicode(&usBuffer, info2A->pPrintProcessor);
|
|
info2W->pParameters = AsciiToUnicode(&usBuffer, info2A->pParameters);
|
|
info2W->pDevMode = info2A->pDevMode ? GdiConvertToDevmodeW(info2A->pDevMode) : NULL;
|
|
info2W->pStatus = AsciiToUnicode(&usBuffer, info2A->pStatus);
|
|
info2W->pSecurityDescriptor = info2A->pSecurityDescriptor;
|
|
info2W->Status = info2A->Status;
|
|
info2W->Priority = info2A->Priority;
|
|
info2W->Position = info2A->Position;
|
|
info2W->StartTime = info2A->StartTime;
|
|
info2W->UntilTime = info2A->UntilTime;
|
|
info2W->PagesPrinted = info2A->PagesPrinted;
|
|
break;
|
|
}
|
|
case 3:
|
|
JobW = HeapAlloc(GetProcessHeap(), 0, sizeof(JOB_INFO_3));
|
|
memcpy(JobW, pJobInfo, sizeof(JOB_INFO_3));
|
|
break;
|
|
default:
|
|
ERR("Level = %d, unsupported!\n", Level);
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
return FALSE;
|
|
}
|
|
|
|
ret = SetJobW(hPrinter, JobId, Level, JobW, Command);
|
|
|
|
switch(Level)
|
|
{
|
|
case 1:
|
|
{
|
|
JOB_INFO_1W *info1W = (JOB_INFO_1W*)JobW;
|
|
HeapFree(GetProcessHeap(), 0, info1W->pUserName);
|
|
HeapFree(GetProcessHeap(), 0, info1W->pDocument);
|
|
HeapFree(GetProcessHeap(), 0, info1W->pDatatype);
|
|
HeapFree(GetProcessHeap(), 0, info1W->pStatus);
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
JOB_INFO_2W *info2W = (JOB_INFO_2W*)JobW;
|
|
HeapFree(GetProcessHeap(), 0, info2W->pUserName);
|
|
HeapFree(GetProcessHeap(), 0, info2W->pDocument);
|
|
HeapFree(GetProcessHeap(), 0, info2W->pNotifyName);
|
|
HeapFree(GetProcessHeap(), 0, info2W->pDatatype);
|
|
HeapFree(GetProcessHeap(), 0, info2W->pPrintProcessor);
|
|
HeapFree(GetProcessHeap(), 0, info2W->pParameters);
|
|
HeapFree(GetProcessHeap(), 0, info2W->pDevMode);
|
|
HeapFree(GetProcessHeap(), 0, info2W->pStatus);
|
|
break;
|
|
}
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, JobW);
|
|
|
|
return ret;
|
|
}
|
|
|
|
BOOL WINAPI
|
|
SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command)
|
|
{
|
|
DWORD dwErrorCode;
|
|
PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
|
|
WINSPOOL_JOB_CONTAINER JobContainer;
|
|
|
|
TRACE("SetJobW(%p, %lu, %lu, %p, %lu)\n", hPrinter, JobId, Level, pJobInfo, Command);
|
|
|
|
if (!pHandle)
|
|
{
|
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
|
goto Cleanup;
|
|
}
|
|
|
|
// pJobContainer->JobInfo is a union of pointers, so we can just set any element to our BYTE pointer.
|
|
JobContainer.Level = Level;
|
|
JobContainer.JobInfo.Level1 = (WINSPOOL_JOB_INFO_1*)pJobInfo;
|
|
|
|
// Do the RPC call
|
|
RpcTryExcept
|
|
{
|
|
dwErrorCode = _RpcSetJob(pHandle->hPrinter, JobId, &JobContainer, Command);
|
|
}
|
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
dwErrorCode = RpcExceptionCode();
|
|
ERR("_RpcSetJob failed with exception code %lu!\n", dwErrorCode);
|
|
}
|
|
RpcEndExcept;
|
|
|
|
Cleanup:
|
|
SetLastError(dwErrorCode);
|
|
return (dwErrorCode == ERROR_SUCCESS);
|
|
}
|