mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 23:03:00 +00:00
[WINSPOOL]
Don't rely on pure magic to transmit the error code of the RPC call to the calling application. Instead use SetLastError on the return value of the call (this is what all these DWORD return values are for!) [SPOOLSV] For every RPC function, return the error code of the called Spooler Router function instead of the error code of RpcRevertToSelf. [LOCALSPL, WINPRINT] - Change the code structure in every function called from the Spooler Router to always set an error code, especially ERROR_SUCCESS on success. - Store Attributes and Status values for a local printer. - Fail in LocalAddJob if an invalid handle has been supplied or the printer is set to do direct printing. svn path=/branches/colins-printing-for-freedom/; revision=68247
This commit is contained in:
parent
5df5a009e2
commit
7e4bcf78c4
15 changed files with 303 additions and 261 deletions
|
@ -94,9 +94,10 @@ SplIsUpgrade()
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI
|
BOOL WINAPI
|
||||||
SpoolerInit()
|
SpoolerInit()
|
||||||
{
|
{
|
||||||
// Nothing to do here yet
|
// Nothing to do here yet
|
||||||
return ERROR_SUCCESS;
|
SetLastError(ERROR_SUCCESS);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,13 +21,9 @@ _RpcSpoolerInit()
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwErrorCode = SpoolerInit();
|
SpoolerInit();
|
||||||
if (dwErrorCode != ERROR_SUCCESS)
|
dwErrorCode = GetLastError();
|
||||||
{
|
|
||||||
ERR("SpoolerInit failed with error %lu!\n", dwErrorCode);
|
|
||||||
RpcRevertToSelf();
|
RpcRevertToSelf();
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
|
||||||
|
|
||||||
return RpcRevertToSelf();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,15 +19,11 @@ _RpcAddJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pAddJob, DWORD c
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwErrorCode = AddJobW(hPrinter, Level, pAddJob, cbBuf, pcbNeeded);
|
AddJobW(hPrinter, Level, pAddJob, cbBuf, pcbNeeded);
|
||||||
if (dwErrorCode != ERROR_SUCCESS)
|
dwErrorCode = GetLastError();
|
||||||
{
|
|
||||||
ERR("AddJobW failed with error %lu!\n", dwErrorCode);
|
|
||||||
RpcRevertToSelf();
|
RpcRevertToSelf();
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
|
||||||
|
|
||||||
return RpcRevertToSelf();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
|
@ -42,15 +38,11 @@ _RpcGetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, DWORD Level, BYTE* pJo
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwErrorCode = GetJobW(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
|
GetJobW(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
|
||||||
if (dwErrorCode != ERROR_SUCCESS)
|
dwErrorCode = GetLastError();
|
||||||
{
|
|
||||||
ERR("GetJobW failed with error %lu!\n", dwErrorCode);
|
|
||||||
RpcRevertToSelf();
|
RpcRevertToSelf();
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
|
||||||
|
|
||||||
return RpcRevertToSelf();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
|
|
|
@ -19,15 +19,11 @@ _RpcEnumPrinters(DWORD Flags, WINSPOOL_HANDLE Name, DWORD Level, BYTE* pPrinterE
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwErrorCode = EnumPrintersW(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
EnumPrintersW(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
||||||
if (dwErrorCode != ERROR_SUCCESS)
|
dwErrorCode = GetLastError();
|
||||||
{
|
|
||||||
ERR("EnumPrintersW failed with error %lu!\n", dwErrorCode);
|
|
||||||
RpcRevertToSelf();
|
RpcRevertToSelf();
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
|
||||||
|
|
||||||
return RpcRevertToSelf();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
|
@ -47,13 +43,9 @@ _RpcOpenPrinter(WINSPOOL_HANDLE pPrinterName, WINSPOOL_PRINTER_HANDLE* phPrinter
|
||||||
Default.pDatatype = pDatatype;
|
Default.pDatatype = pDatatype;
|
||||||
Default.pDevMode = (PDEVMODEW)pDevModeContainer->pDevMode;
|
Default.pDevMode = (PDEVMODEW)pDevModeContainer->pDevMode;
|
||||||
|
|
||||||
dwErrorCode = OpenPrinterW(pPrinterName, phPrinter, &Default);
|
OpenPrinterW(pPrinterName, phPrinter, &Default);
|
||||||
if (dwErrorCode != ERROR_SUCCESS)
|
dwErrorCode = GetLastError();
|
||||||
{
|
|
||||||
ERR("OpenPrinterW failed with error %lu!\n", dwErrorCode);
|
|
||||||
RpcRevertToSelf();
|
RpcRevertToSelf();
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
|
||||||
|
|
||||||
return RpcRevertToSelf();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,15 +26,11 @@ _RpcEnumPrintProcessorDatatypes(WINSPOOL_HANDLE pName, WCHAR *pPrintProcessorNam
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwErrorCode = EnumPrintProcessorDatatypesW(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
|
EnumPrintProcessorDatatypesW(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
|
||||||
if (dwErrorCode != ERROR_SUCCESS)
|
dwErrorCode = GetLastError();
|
||||||
{
|
|
||||||
ERR("EnumPrintProcessorDatatypesW failed with error %lu!\n", dwErrorCode);
|
|
||||||
RpcRevertToSelf();
|
RpcRevertToSelf();
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
|
||||||
|
|
||||||
return RpcRevertToSelf();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
|
@ -49,15 +45,11 @@ _RpcEnumPrintProcessors(WINSPOOL_HANDLE pName, WCHAR *pEnvironment, DWORD Level,
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwErrorCode = EnumPrintProcessorsW(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
|
EnumPrintProcessorsW(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
|
||||||
if (dwErrorCode != ERROR_SUCCESS)
|
dwErrorCode = GetLastError();
|
||||||
{
|
|
||||||
ERR("EnumPrintProcessorsW failed with error %lu!\n", dwErrorCode);
|
|
||||||
RpcRevertToSelf();
|
RpcRevertToSelf();
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
|
||||||
|
|
||||||
return RpcRevertToSelf();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD
|
DWORD
|
||||||
|
@ -72,13 +64,9 @@ _RpcGetPrintProcessorDirectory(WINSPOOL_HANDLE pName, WCHAR *pEnvironment, DWORD
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
dwErrorCode = GetPrintProcessorDirectoryW(pName, pEnvironment, Level, pPrintProcessorDirectory, cbBuf, pcbNeeded);
|
GetPrintProcessorDirectoryW(pName, pEnvironment, Level, pPrintProcessorDirectory, cbBuf, pcbNeeded);
|
||||||
if (dwErrorCode != ERROR_SUCCESS)
|
dwErrorCode = GetLastError();
|
||||||
{
|
|
||||||
ERR("EnumPrintProcessorsW failed with error %lu!\n", dwErrorCode);
|
|
||||||
RpcRevertToSelf();
|
RpcRevertToSelf();
|
||||||
return dwErrorCode;
|
return dwErrorCode;
|
||||||
}
|
|
||||||
|
|
||||||
return RpcRevertToSelf();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,7 @@ AddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeede
|
||||||
RpcTryExcept
|
RpcTryExcept
|
||||||
{
|
{
|
||||||
dwErrorCode = _RpcAddJob(hPrinter, Level, pData, cbBuf, pcbNeeded);
|
dwErrorCode = _RpcAddJob(hPrinter, Level, pData, cbBuf, pcbNeeded);
|
||||||
if (dwErrorCode)
|
SetLastError(dwErrorCode);
|
||||||
{
|
|
||||||
ERR("_RpcAddJob failed with error %lu!\n", dwErrorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
@ -43,11 +39,7 @@ GetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDW
|
||||||
RpcTryExcept
|
RpcTryExcept
|
||||||
{
|
{
|
||||||
dwErrorCode = _RpcGetJob(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
|
dwErrorCode = _RpcGetJob(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
|
||||||
if (dwErrorCode)
|
SetLastError(dwErrorCode);
|
||||||
{
|
|
||||||
ERR("_RpcGetJob failed with error %lu!\n", dwErrorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
|
|
@ -68,19 +68,15 @@ midl_user_free(void __RPC_FAR* ptr)
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
SpoolerInit()
|
SpoolerInit()
|
||||||
{
|
{
|
||||||
BOOL ReturnValue = FALSE;
|
BOOL bReturnValue = FALSE;
|
||||||
DWORD ErrorCode;
|
DWORD dwErrorCode;
|
||||||
|
|
||||||
// Nothing to initialize here yet, but pass this call to the Spool Service as well.
|
// Nothing to initialize here yet, but pass this call to the Spool Service as well.
|
||||||
RpcTryExcept
|
RpcTryExcept
|
||||||
{
|
{
|
||||||
ErrorCode = _RpcSpoolerInit();
|
dwErrorCode = _RpcSpoolerInit();
|
||||||
if (ErrorCode)
|
SetLastError(dwErrorCode);
|
||||||
{
|
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
||||||
ERR("_RpcSpoolerInit failed with error %lu!\n", ErrorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue = (ErrorCode == ERROR_SUCCESS);
|
|
||||||
}
|
}
|
||||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||||
{
|
{
|
||||||
|
@ -88,5 +84,5 @@ SpoolerInit()
|
||||||
}
|
}
|
||||||
RpcEndExcept;
|
RpcEndExcept;
|
||||||
|
|
||||||
return ReturnValue;
|
return bReturnValue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,7 @@ EnumPrintersW(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD
|
||||||
RpcTryExcept
|
RpcTryExcept
|
||||||
{
|
{
|
||||||
dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
||||||
if (dwErrorCode)
|
SetLastError(dwErrorCode);
|
||||||
{
|
|
||||||
ERR("_RpcEnumPrinters failed with error %lu!\n", dwErrorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
@ -204,11 +200,7 @@ OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefau
|
||||||
RpcTryExcept
|
RpcTryExcept
|
||||||
{
|
{
|
||||||
dwErrorCode = _RpcOpenPrinter(pPrinterName, phPrinter, pDatatype, pDevModeContainer, AccessRequired);
|
dwErrorCode = _RpcOpenPrinter(pPrinterName, phPrinter, pDatatype, pDevModeContainer, AccessRequired);
|
||||||
if (dwErrorCode)
|
SetLastError(dwErrorCode);
|
||||||
{
|
|
||||||
ERR("_RpcOpenPrinter failed with error %lu!\n", dwErrorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
|
|
@ -23,11 +23,7 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
|
||||||
RpcTryExcept
|
RpcTryExcept
|
||||||
{
|
{
|
||||||
dwErrorCode = _RpcEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
|
dwErrorCode = _RpcEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
|
||||||
if (dwErrorCode)
|
SetLastError(dwErrorCode);
|
||||||
{
|
|
||||||
ERR("_RpcEnumPrintProcessorDatatypes failed with error %lu!\n", dwErrorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
@ -49,11 +45,7 @@ EnumPrintProcessorsW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPri
|
||||||
RpcTryExcept
|
RpcTryExcept
|
||||||
{
|
{
|
||||||
dwErrorCode = _RpcEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
|
dwErrorCode = _RpcEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
|
||||||
if (dwErrorCode)
|
SetLastError(dwErrorCode);
|
||||||
{
|
|
||||||
ERR("_RpcEnumPrintProcessors failed with error %lu!\n", dwErrorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
@ -75,11 +67,7 @@ GetPrintProcessorDirectoryW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBY
|
||||||
RpcTryExcept
|
RpcTryExcept
|
||||||
{
|
{
|
||||||
dwErrorCode = _RpcGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded);
|
dwErrorCode = _RpcGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded);
|
||||||
if (dwErrorCode)
|
SetLastError(dwErrorCode);
|
||||||
{
|
|
||||||
ERR("_RpcGetPrintProcessorDirectory failed with error %lu!\n", dwErrorCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
|
|
@ -49,13 +49,17 @@ BOOL WINAPI
|
||||||
EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
||||||
{
|
{
|
||||||
DWORD cbDatatype;
|
DWORD cbDatatype;
|
||||||
|
DWORD dwErrorCode;
|
||||||
DWORD dwOffsets[_countof(pwszDatatypes)];
|
DWORD dwOffsets[_countof(pwszDatatypes)];
|
||||||
PCWSTR* pCurrentDatatype;
|
PCWSTR* pCurrentDatatype;
|
||||||
PDWORD pCurrentOffset = dwOffsets;
|
PDWORD pCurrentOffset = dwOffsets;
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (Level != 1 || !pcbNeeded || !pcReturned)
|
if (Level != 1 || !pcbNeeded || !pcReturned)
|
||||||
return FALSE;
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
// Count the required buffer size and the number of datatypes.
|
// Count the required buffer size and the number of datatypes.
|
||||||
*pcbNeeded = 0;
|
*pcbNeeded = 0;
|
||||||
|
@ -76,20 +80,24 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
|
||||||
// Check if the supplied buffer is large enough.
|
// Check if the supplied buffer is large enough.
|
||||||
if (cbBuf < *pcbNeeded)
|
if (cbBuf < *pcbNeeded)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a buffer was supplied at all.
|
// Check if a buffer was supplied at all.
|
||||||
if (!pDatatypes)
|
if (!pDatatypes)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy over all datatypes.
|
// Copy over all datatypes.
|
||||||
*pCurrentOffset = MAXDWORD;
|
*pCurrentOffset = MAXDWORD;
|
||||||
PackStrings(pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]);
|
PackStrings(pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]);
|
||||||
|
|
||||||
return TRUE;
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
SetLastError(dwErrorCode);
|
||||||
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,36 +196,54 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
|
||||||
const DWORD cchSpl = _countof("?????.SPL") - 1;
|
const DWORD cchSpl = _countof("?????.SPL") - 1;
|
||||||
|
|
||||||
ADDJOB_INFO_1W AddJobInfo1;
|
ADDJOB_INFO_1W AddJobInfo1;
|
||||||
BOOL bReturnValue = FALSE;
|
|
||||||
DWORD cchMachineName;
|
DWORD cchMachineName;
|
||||||
DWORD cchUserName;
|
DWORD cchUserName;
|
||||||
|
DWORD dwErrorCode;
|
||||||
PBYTE p;
|
PBYTE p;
|
||||||
PLOCAL_HANDLE pHandle;
|
PLOCAL_HANDLE pHandle;
|
||||||
PLOCAL_JOB pJob;
|
PLOCAL_JOB pJob;
|
||||||
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
||||||
RPC_BINDING_HANDLE hServerBinding = NULL;
|
RPC_BINDING_HANDLE hServerBinding = NULL;
|
||||||
RPC_STATUS Status;
|
|
||||||
RPC_WSTR pwszBinding = NULL;
|
RPC_WSTR pwszBinding = NULL;
|
||||||
RPC_WSTR pwszMachineName = NULL;
|
RPC_WSTR pwszMachineName = NULL;
|
||||||
|
|
||||||
// Check if this is a printer handle.
|
// Check if this is a printer handle.
|
||||||
pHandle = (PLOCAL_HANDLE)hPrinter;
|
pHandle = (PLOCAL_HANDLE)hPrinter;
|
||||||
if (pHandle->HandleType != Printer)
|
if (pHandle->HandleType != Printer)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
|
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
|
||||||
|
|
||||||
|
// This handle must not have started a job yet!
|
||||||
|
if (pPrinterHandle->StartedJob)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if this is the right structure level.
|
// Check if this is the right structure level.
|
||||||
if (Level != 1)
|
if (Level != 1)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: This needs to fail if the printer is set to do direct printing.
|
// Check if the printer is set to do direct printing.
|
||||||
|
// The Job List isn't used in this case.
|
||||||
|
if (pPrinterHandle->Printer->dwAttributes & PRINTER_ATTRIBUTE_DIRECT)
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_ACCESS;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the supplied buffer is large enough.
|
// Check if the supplied buffer is large enough.
|
||||||
*pcbNeeded = sizeof(ADDJOB_INFO_1W) + (cchSpoolDirectory + cchPrintersPath + cchSpl + 1) * sizeof(WCHAR);
|
*pcbNeeded = sizeof(ADDJOB_INFO_1W) + (cchSpoolDirectory + cchPrintersPath + cchSpl + 1) * sizeof(WCHAR);
|
||||||
if (cbBuf < *pcbNeeded)
|
if (cbBuf < *pcbNeeded)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,13 +251,17 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
|
||||||
pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
|
pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
|
||||||
if (!pJob)
|
if (!pJob)
|
||||||
{
|
{
|
||||||
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
dwErrorCode = GetLastError();
|
||||||
|
ERR("DllAllocSplMem failed with error %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reserve an ID for this job.
|
// Reserve an ID for this job.
|
||||||
if (!GetNextJobID(&pJob->dwJobID))
|
if (!GetNextJobID(&pJob->dwJobID))
|
||||||
|
{
|
||||||
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
// Copy over defaults to the LOCAL_JOB structure.
|
// Copy over defaults to the LOCAL_JOB structure.
|
||||||
pJob->Printer = pPrinterHandle->Printer;
|
pJob->Printer = pPrinterHandle->Printer;
|
||||||
|
@ -254,7 +276,8 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
|
||||||
pJob->pwszUserName = DllAllocSplMem(cchUserName * sizeof(WCHAR));
|
pJob->pwszUserName = DllAllocSplMem(cchUserName * sizeof(WCHAR));
|
||||||
if (!GetUserNameW(pJob->pwszUserName, &cchUserName))
|
if (!GetUserNameW(pJob->pwszUserName, &cchUserName))
|
||||||
{
|
{
|
||||||
ERR("GetUserNameW failed with error %lu!\n", GetLastError());
|
dwErrorCode = GetLastError();
|
||||||
|
ERR("GetUserNameW failed with error %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,24 +285,24 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
|
||||||
pJob->pwszNotifyName = AllocSplStr(pJob->pwszUserName);
|
pJob->pwszNotifyName = AllocSplStr(pJob->pwszUserName);
|
||||||
|
|
||||||
// Get the name of the machine that submitted the Job over RPC.
|
// Get the name of the machine that submitted the Job over RPC.
|
||||||
Status = RpcBindingServerFromClient(NULL, &hServerBinding);
|
dwErrorCode = RpcBindingServerFromClient(NULL, &hServerBinding);
|
||||||
if (Status != RPC_S_OK)
|
if (dwErrorCode != RPC_S_OK)
|
||||||
{
|
{
|
||||||
ERR("RpcBindingServerFromClient failed with status %lu!\n", Status);
|
ERR("RpcBindingServerFromClient failed with status %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = RpcBindingToStringBindingW(hServerBinding, &pwszBinding);
|
dwErrorCode = RpcBindingToStringBindingW(hServerBinding, &pwszBinding);
|
||||||
if (Status != RPC_S_OK)
|
if (dwErrorCode != RPC_S_OK)
|
||||||
{
|
{
|
||||||
ERR("RpcBindingToStringBindingW failed with status %lu!\n", Status);
|
ERR("RpcBindingToStringBindingW failed with status %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = RpcStringBindingParseW(pwszBinding, NULL, NULL, &pwszMachineName, NULL, NULL);
|
dwErrorCode = RpcStringBindingParseW(pwszBinding, NULL, NULL, &pwszMachineName, NULL, NULL);
|
||||||
if (Status != RPC_S_OK)
|
if (dwErrorCode != RPC_S_OK)
|
||||||
{
|
{
|
||||||
ERR("RpcStringBindingParseW failed with status %lu!\n", Status);
|
ERR("RpcStringBindingParseW failed with status %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +314,7 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
|
||||||
// Add the job to the Global Job List.
|
// Add the job to the Global Job List.
|
||||||
if (!InsertElementSkiplist(&GlobalJobList, pJob))
|
if (!InsertElementSkiplist(&GlobalJobList, pJob))
|
||||||
{
|
{
|
||||||
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
ERR("InsertElementSkiplist failed for job %lu for the GlobalJobList!\n", pJob->dwJobID);
|
ERR("InsertElementSkiplist failed for job %lu for the GlobalJobList!\n", pJob->dwJobID);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
@ -299,6 +323,7 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
|
||||||
// As all new jobs are created with default priority, we can be sure that it would always be inserted at the end.
|
// As all new jobs are created with default priority, we can be sure that it would always be inserted at the end.
|
||||||
if (!InsertTailElementSkiplist(&pJob->Printer->JobList, pJob))
|
if (!InsertTailElementSkiplist(&pJob->Printer->JobList, pJob))
|
||||||
{
|
{
|
||||||
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
|
ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
@ -315,7 +340,7 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
|
||||||
p += cchPrintersPath;
|
p += cchPrintersPath;
|
||||||
swprintf((PWSTR)p, L"%05lu.SPL", pJob->dwJobID);
|
swprintf((PWSTR)p, L"%05lu.SPL", pJob->dwJobID);
|
||||||
|
|
||||||
bReturnValue = TRUE;
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pwszMachineName)
|
if (pwszMachineName)
|
||||||
|
@ -327,11 +352,12 @@ Cleanup:
|
||||||
if (hServerBinding)
|
if (hServerBinding)
|
||||||
RpcBindingFree(&hServerBinding);
|
RpcBindingFree(&hServerBinding);
|
||||||
|
|
||||||
return bReturnValue;
|
SetLastError(dwErrorCode);
|
||||||
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static BOOL
|
static DWORD
|
||||||
_LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE pOutput, DWORD cbBuf, PDWORD pcbNeeded)
|
_LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE pOutput, DWORD cbBuf, PDWORD pcbNeeded)
|
||||||
{
|
{
|
||||||
DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
|
DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
|
||||||
|
@ -339,6 +365,7 @@ _LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
|
||||||
DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
|
DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
|
||||||
DWORD cbPrinterName = (wcslen(pJob->Printer->pwszPrinterName) + 1) * sizeof(WCHAR);
|
DWORD cbPrinterName = (wcslen(pJob->Printer->pwszPrinterName) + 1) * sizeof(WCHAR);
|
||||||
DWORD cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
|
DWORD cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
|
||||||
|
DWORD dwErrorCode;
|
||||||
JOB_INFO_1W JobInfo1 = { 0 };
|
JOB_INFO_1W JobInfo1 = { 0 };
|
||||||
PBYTE pString;
|
PBYTE pString;
|
||||||
|
|
||||||
|
@ -346,8 +373,8 @@ _LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
|
||||||
*pcbNeeded = sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName + cbPrinterName + cbUserName;
|
*pcbNeeded = sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName + cbPrinterName + cbUserName;
|
||||||
if (cbBuf < *pcbNeeded)
|
if (cbBuf < *pcbNeeded)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the strings right after the JOB_INFO_1W structure.
|
// Put the strings right after the JOB_INFO_1W structure.
|
||||||
|
@ -381,10 +408,13 @@ _LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
|
||||||
CopyMemory(&JobInfo1.Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
|
CopyMemory(&JobInfo1.Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
|
||||||
CopyMemory(pOutput, &JobInfo1, sizeof(JOB_INFO_1W));
|
CopyMemory(pOutput, &JobInfo1, sizeof(JOB_INFO_1W));
|
||||||
|
|
||||||
return TRUE;
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL
|
static DWORD
|
||||||
_LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE pOutput, DWORD cbBuf, PDWORD pcbNeeded)
|
_LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE pOutput, DWORD cbBuf, PDWORD pcbNeeded)
|
||||||
{
|
{
|
||||||
DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
|
DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
|
||||||
|
@ -395,6 +425,7 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
|
||||||
DWORD cbPrinterName = (wcslen(pJob->Printer->pwszPrinterName) + 1) * sizeof(WCHAR);
|
DWORD cbPrinterName = (wcslen(pJob->Printer->pwszPrinterName) + 1) * sizeof(WCHAR);
|
||||||
DWORD cbPrintProcessor = (wcslen(pJob->Printer->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
|
DWORD cbPrintProcessor = (wcslen(pJob->Printer->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
|
||||||
DWORD cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
|
DWORD cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
|
||||||
|
DWORD dwErrorCode;
|
||||||
FILETIME ftNow;
|
FILETIME ftNow;
|
||||||
FILETIME ftSubmitted;
|
FILETIME ftSubmitted;
|
||||||
JOB_INFO_2W JobInfo2 = { 0 };
|
JOB_INFO_2W JobInfo2 = { 0 };
|
||||||
|
@ -406,8 +437,8 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
|
||||||
*pcbNeeded = sizeof(JOB_INFO_2W) + cbDatatype + sizeof(DEVMODEW) + cbDocumentName + cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor + cbUserName;
|
*pcbNeeded = sizeof(JOB_INFO_2W) + cbDatatype + sizeof(DEVMODEW) + cbDocumentName + cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor + cbUserName;
|
||||||
if (cbBuf < *pcbNeeded)
|
if (cbBuf < *pcbNeeded)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the strings right after the JOB_INFO_2W structure.
|
// Put the strings right after the JOB_INFO_2W structure.
|
||||||
|
@ -467,8 +498,9 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
|
||||||
// Retrieve this through the element index of the job in the Printer's Job List.
|
// Retrieve this through the element index of the job in the Printer's Job List.
|
||||||
if (!LookupElementSkiplist(&pJob->Printer->JobList, pJob, &JobInfo2.Position))
|
if (!LookupElementSkiplist(&pJob->Printer->JobList, pJob, &JobInfo2.Position))
|
||||||
{
|
{
|
||||||
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
ERR("pJob could not be located in the Printer's Job List!\n");
|
ERR("pJob could not be located in the Printer's Job List!\n");
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the index 1-based.
|
// Make the index 1-based.
|
||||||
|
@ -486,12 +518,16 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
|
||||||
|
|
||||||
// Finally copy the structure to the output pointer.
|
// Finally copy the structure to the output pointer.
|
||||||
CopyMemory(pOutput, &JobInfo2, sizeof(JOB_INFO_2W));
|
CopyMemory(pOutput, &JobInfo2, sizeof(JOB_INFO_2W));
|
||||||
return TRUE;
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pOutput, DWORD cbBuf, LPDWORD pcbNeeded)
|
LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pOutput, DWORD cbBuf, LPDWORD pcbNeeded)
|
||||||
{
|
{
|
||||||
|
DWORD dwErrorCode;
|
||||||
PLOCAL_HANDLE pHandle;
|
PLOCAL_HANDLE pHandle;
|
||||||
PLOCAL_JOB pJob;
|
PLOCAL_JOB pJob;
|
||||||
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
PLOCAL_PRINTER_HANDLE pPrinterHandle;
|
||||||
|
@ -499,7 +535,10 @@ LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pOutput, DWORD cbB
|
||||||
// Check if this is a printer handle.
|
// Check if this is a printer handle.
|
||||||
pHandle = (PLOCAL_HANDLE)hPrinter;
|
pHandle = (PLOCAL_HANDLE)hPrinter;
|
||||||
if (pHandle->HandleType != Printer)
|
if (pHandle->HandleType != Printer)
|
||||||
return FALSE;
|
{
|
||||||
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
|
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
|
||||||
|
|
||||||
|
@ -507,17 +546,21 @@ LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pOutput, DWORD cbB
|
||||||
pJob = LookupElementSkiplist(&GlobalJobList, &JobId, NULL);
|
pJob = LookupElementSkiplist(&GlobalJobList, &JobId, NULL);
|
||||||
if (!pJob || pJob->Printer != pPrinterHandle->Printer)
|
if (!pJob || pJob->Printer != pPrinterHandle->Printer)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The function behaves differently for each level.
|
// The function behaves differently for each level.
|
||||||
if (Level == 1)
|
if (Level == 1)
|
||||||
return _LocalGetJobLevel1(pPrinterHandle, pJob, pOutput, cbBuf, pcbNeeded);
|
dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, pOutput, cbBuf, pcbNeeded);
|
||||||
else if (Level == 2)
|
else if (Level == 2)
|
||||||
return _LocalGetJobLevel2(pPrinterHandle, pJob, pOutput, cbBuf, pcbNeeded);
|
dwErrorCode = _LocalGetJobLevel2(pPrinterHandle, pJob, pOutput, cbBuf, pcbNeeded);
|
||||||
|
else
|
||||||
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
||||||
|
|
||||||
return FALSE;
|
Cleanup:
|
||||||
|
SetLastError(dwErrorCode);
|
||||||
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
PLOCAL_JOB
|
PLOCAL_JOB
|
||||||
|
|
|
@ -156,5 +156,6 @@ InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, L
|
||||||
{
|
{
|
||||||
CopyMemory(pPrintProvidor, &_PrintProviderFunctions, min(cbPrintProvidor, sizeof(PRINTPROVIDOR)));
|
CopyMemory(pPrintProvidor, &_PrintProviderFunctions, min(cbPrintProvidor, sizeof(PRINTPROVIDOR)));
|
||||||
|
|
||||||
|
SetLastError(ERROR_SUCCESS);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,8 @@ typedef struct _LOCAL_PRINTER
|
||||||
// This sort key must be the first element for LookupElementSkiplist to work!
|
// This sort key must be the first element for LookupElementSkiplist to work!
|
||||||
PWSTR pwszPrinterName;
|
PWSTR pwszPrinterName;
|
||||||
|
|
||||||
|
DWORD dwAttributes;
|
||||||
|
DWORD dwStatus;
|
||||||
PWSTR pwszPrinterDriver;
|
PWSTR pwszPrinterDriver;
|
||||||
PWSTR pwszDescription;
|
PWSTR pwszDescription;
|
||||||
PWSTR pwszDefaultDatatype;
|
PWSTR pwszDefaultDatatype;
|
||||||
|
|
|
@ -38,7 +38,7 @@ InitializePrinterList()
|
||||||
{
|
{
|
||||||
const WCHAR wszPrintersKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers";
|
const WCHAR wszPrintersKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers";
|
||||||
|
|
||||||
DWORD cbDevMode;
|
DWORD cbData;
|
||||||
DWORD cchPrinterName;
|
DWORD cchPrinterName;
|
||||||
DWORD dwSubKeys;
|
DWORD dwSubKeys;
|
||||||
DWORD i;
|
DWORD i;
|
||||||
|
@ -173,11 +173,29 @@ InitializePrinterList()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the default DevMode.
|
// Get the default DevMode.
|
||||||
cbDevMode = sizeof(DEVMODEW);
|
cbData = sizeof(DEVMODEW);
|
||||||
lStatus = RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL, (PBYTE)&pPrinter->DefaultDevMode, &cbDevMode);
|
lStatus = RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL, (PBYTE)&pPrinter->DefaultDevMode, &cbData);
|
||||||
if (lStatus != ERROR_SUCCESS || cbDevMode != sizeof(DEVMODEW))
|
if (lStatus != ERROR_SUCCESS || cbData != sizeof(DEVMODEW))
|
||||||
{
|
{
|
||||||
ERR("Couldn't query a valid DevMode for Printer \"%S\", status is %ld, cbDevMode is %lu!\n", wszPrinterName, lStatus, cbDevMode);
|
ERR("Couldn't query a valid DevMode for Printer \"%S\", status is %ld, cbData is %lu!\n", wszPrinterName, lStatus, cbData);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the Attributes.
|
||||||
|
cbData = sizeof(DWORD);
|
||||||
|
lStatus = RegQueryValueExW(hSubKey, L"Attributes", NULL, NULL, (PBYTE)&pPrinter->dwAttributes, &cbData);
|
||||||
|
if (lStatus != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("Couldn't query Attributes for Printer \"%S\", status is %ld!\n", wszPrinterName, lStatus);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the Status.
|
||||||
|
cbData = sizeof(DWORD);
|
||||||
|
lStatus = RegQueryValueExW(hSubKey, L"Status", NULL, NULL, (PBYTE)&pPrinter->dwStatus, &cbData);
|
||||||
|
if (lStatus != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ERR("Couldn't query Status for Printer \"%S\", status is %ld!\n", wszPrinterName, lStatus);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +241,7 @@ Cleanup:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOL
|
DWORD
|
||||||
_LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
_LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
||||||
{
|
{
|
||||||
const WCHAR wszComma[] = L",";
|
const WCHAR wszComma[] = L",";
|
||||||
|
@ -232,6 +250,7 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
|
||||||
DWORD cbComment;
|
DWORD cbComment;
|
||||||
DWORD cbDescription;
|
DWORD cbDescription;
|
||||||
DWORD cchComputerName = 0;
|
DWORD cchComputerName = 0;
|
||||||
|
DWORD dwErrorCode;
|
||||||
DWORD i;
|
DWORD i;
|
||||||
PBYTE pPrinterInfo;
|
PBYTE pPrinterInfo;
|
||||||
PBYTE pPrinterString;
|
PBYTE pPrinterString;
|
||||||
|
@ -263,8 +282,9 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
|
||||||
cchComputerName = MAX_COMPUTERNAME_LENGTH + 1;
|
cchComputerName = MAX_COMPUTERNAME_LENGTH + 1;
|
||||||
if (!GetComputerNameW(&wszComputerName[2], &cchComputerName))
|
if (!GetComputerNameW(&wszComputerName[2], &cchComputerName))
|
||||||
{
|
{
|
||||||
ERR("GetComputerNameW failed with error %lu!\n", GetLastError());
|
dwErrorCode = GetLastError();
|
||||||
return FALSE;
|
ERR("GetComputerNameW failed with error %lu!\n", dwErrorCode);
|
||||||
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the leading slashes to the total length.
|
// Add the leading slashes to the total length.
|
||||||
|
@ -273,8 +293,8 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
|
||||||
// Now compare this with the local computer name and reject if it doesn't match.
|
// Now compare this with the local computer name and reject if it doesn't match.
|
||||||
if (wcsicmp(&Name[2], &wszComputerName[2]) != 0)
|
if (wcsicmp(&Name[2], &wszComputerName[2]) != 0)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_NAME);
|
dwErrorCode = ERROR_INVALID_NAME;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a trailing backslash to wszComputerName, which will later be prepended in front of the printer names.
|
// Add a trailing backslash to wszComputerName, which will later be prepended in front of the printer names.
|
||||||
|
@ -284,8 +304,8 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
|
||||||
else if (wcsicmp(Name, wszPrintProviderInfo[0]) != 0)
|
else if (wcsicmp(Name, wszPrintProviderInfo[0]) != 0)
|
||||||
{
|
{
|
||||||
// The user supplied a name that cannot be processed by the local print provider.
|
// The user supplied a name that cannot be processed by the local print provider.
|
||||||
SetLastError(ERROR_INVALID_NAME);
|
dwErrorCode = ERROR_INVALID_NAME;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -302,14 +322,15 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
|
||||||
// Check if the supplied buffer is large enough.
|
// Check if the supplied buffer is large enough.
|
||||||
if (cbBuf < *pcbNeeded)
|
if (cbBuf < *pcbNeeded)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy over the print processor information.
|
// Copy over the print processor information.
|
||||||
((PPRINTER_INFO_1W)pPrinterEnum)->Flags = 0;
|
((PPRINTER_INFO_1W)pPrinterEnum)->Flags = 0;
|
||||||
PackStrings(wszPrintProviderInfo, pPrinterEnum, dwOffsets, &pPrinterEnum[*pcbNeeded]);
|
PackStrings(wszPrintProviderInfo, pPrinterEnum, dwOffsets, &pPrinterEnum[*pcbNeeded]);
|
||||||
return TRUE;
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,8 +353,8 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
|
||||||
// Check if the supplied buffer is large enough.
|
// Check if the supplied buffer is large enough.
|
||||||
if (cbBuf < *pcbNeeded)
|
if (cbBuf < *pcbNeeded)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put the strings right after the last PRINTER_INFO_1W structure.
|
// Put the strings right after the last PRINTER_INFO_1W structure.
|
||||||
|
@ -381,12 +402,17 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
|
||||||
pPrinterInfo += sizeof(PRINTER_INFO_1W);
|
pPrinterInfo += sizeof(PRINTER_INFO_1W);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
||||||
{
|
{
|
||||||
|
DWORD dwErrorCode;
|
||||||
|
|
||||||
// Do no sanity checks here. This is verified by localspl_apitest!
|
// Do no sanity checks here. This is verified by localspl_apitest!
|
||||||
|
|
||||||
// Begin counting.
|
// Begin counting.
|
||||||
|
@ -394,30 +420,36 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
|
||||||
*pcReturned = 0;
|
*pcReturned = 0;
|
||||||
|
|
||||||
// Think positive :)
|
// Think positive :)
|
||||||
SetLastError(ERROR_SUCCESS);
|
// Treat it as success if the caller queried no information and we don't need to return any.
|
||||||
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
|
||||||
if (Flags & PRINTER_ENUM_LOCAL)
|
if (Flags & PRINTER_ENUM_LOCAL)
|
||||||
{
|
{
|
||||||
// The function behaves quite differently for each level.
|
// The function behaves quite differently for each level.
|
||||||
if (Level == 1)
|
if (Level == 1)
|
||||||
return _LocalEnumPrintersLevel1(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
{
|
||||||
|
dwErrorCode = _LocalEnumPrintersLevel1(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// TODO: Handle other levels.
|
// TODO: Handle other levels.
|
||||||
|
|
||||||
// The caller supplied an invalid level.
|
// The caller supplied an invalid level.
|
||||||
return FALSE;
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Treat it as success if the caller queried no information and we don't need to return any.
|
Cleanup:
|
||||||
return TRUE;
|
SetLastError(dwErrorCode);
|
||||||
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault)
|
LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault)
|
||||||
{
|
{
|
||||||
BOOL bReturnValue = ROUTER_UNKNOWN;
|
|
||||||
DWORD cchComputerName;
|
DWORD cchComputerName;
|
||||||
DWORD cchPrinterName;
|
DWORD cchPrinterName;
|
||||||
|
DWORD dwErrorCode;
|
||||||
DWORD dwJobID;
|
DWORD dwJobID;
|
||||||
PWSTR p = lpPrinterName;
|
PWSTR p = lpPrinterName;
|
||||||
PWSTR pwszPrinterName = NULL;
|
PWSTR pwszPrinterName = NULL;
|
||||||
|
@ -430,7 +462,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (!lpPrinterName || !phPrinter)
|
if (!lpPrinterName || !phPrinter)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,7 +477,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
if (!p)
|
if (!p)
|
||||||
{
|
{
|
||||||
// We didn't get a proper server name.
|
// We didn't get a proper server name.
|
||||||
SetLastError(ERROR_INVALID_PRINTER_NAME);
|
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,14 +488,15 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
cchComputerName = _countof(wszComputerName);
|
cchComputerName = _countof(wszComputerName);
|
||||||
if (!GetComputerNameW(wszComputerName, &cchComputerName))
|
if (!GetComputerNameW(wszComputerName, &cchComputerName))
|
||||||
{
|
{
|
||||||
ERR("GetComputerNameW failed with error %lu!\n", GetLastError());
|
dwErrorCode = GetLastError();
|
||||||
|
ERR("GetComputerNameW failed with error %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now compare this with the local computer name and reject if it doesn't match, because this print provider only supports local printers.
|
// Now compare this with the local computer name and reject if it doesn't match, because this print provider only supports local printers.
|
||||||
if (wcsicmp(lpPrinterName, wszComputerName) != 0)
|
if (wcsicmp(lpPrinterName, wszComputerName) != 0)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PRINTER_NAME);
|
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,7 +514,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
// No printer name and no comma? This is invalid!
|
// No printer name and no comma? This is invalid!
|
||||||
if (!cchPrinterName && !p)
|
if (!cchPrinterName && !p)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PRINTER_NAME);
|
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,7 +531,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
if (!pPrinter)
|
if (!pPrinter)
|
||||||
{
|
{
|
||||||
// The printer does not exist.
|
// The printer does not exist.
|
||||||
SetLastError(ERROR_INVALID_PRINTER_NAME);
|
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -512,7 +545,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
// Use the datatype if it's valid.
|
// Use the datatype if it's valid.
|
||||||
if (!FindDatatype(pPrinter->pPrintProcessor, pDefault->pDatatype))
|
if (!FindDatatype(pPrinter->pPrintProcessor, pDefault->pDatatype))
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_DATATYPE);
|
dwErrorCode = ERROR_INVALID_DATATYPE;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -545,7 +578,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
// The "Job " string has to follow now.
|
// The "Job " string has to follow now.
|
||||||
if (wcscmp(p, L"Job ") != 0)
|
if (wcscmp(p, L"Job ") != 0)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PRINTER_NAME);
|
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -561,7 +594,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
if (!IS_VALID_JOB_ID(dwJobID))
|
if (!IS_VALID_JOB_ID(dwJobID))
|
||||||
{
|
{
|
||||||
// The user supplied an invalid Job ID.
|
// The user supplied an invalid Job ID.
|
||||||
SetLastError(ERROR_INVALID_PRINTER_NAME);
|
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,7 +603,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
if (!pJob || pJob->Printer != pPrinter)
|
if (!pJob || pJob->Printer != pPrinter)
|
||||||
{
|
{
|
||||||
// The user supplied a non-existing Job ID or the Job ID does not belong to the supplied printer name.
|
// The user supplied a non-existing Job ID or the Job ID does not belong to the supplied printer name.
|
||||||
SetLastError(ERROR_INVALID_PRINTER_NAME);
|
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,13 +651,13 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PRINTER_NAME);
|
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*phPrinter = (HANDLE)pHandle;
|
*phPrinter = (HANDLE)pHandle;
|
||||||
bReturnValue = ROUTER_SUCCESS;
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
|
||||||
// Don't let the cleanup routines free this.
|
// Don't let the cleanup routines free this.
|
||||||
pPrinterHandle = NULL;
|
pPrinterHandle = NULL;
|
||||||
|
@ -642,12 +675,15 @@ Cleanup:
|
||||||
if (pwszPrinterName)
|
if (pwszPrinterName)
|
||||||
DllFreeSplMem(pwszPrinterName);
|
DllFreeSplMem(pwszPrinterName);
|
||||||
|
|
||||||
return bReturnValue;
|
SetLastError(dwErrorCode);
|
||||||
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD WINAPI
|
DWORD WINAPI
|
||||||
LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||||
{
|
{
|
||||||
|
DWORD dwErrorCode;
|
||||||
|
DWORD dwReturnValue = 0;
|
||||||
PDOC_INFO_1W pDocumentInfo1;
|
PDOC_INFO_1W pDocumentInfo1;
|
||||||
PLOCAL_HANDLE pHandle;
|
PLOCAL_HANDLE pHandle;
|
||||||
PLOCAL_JOB pJob;
|
PLOCAL_JOB pJob;
|
||||||
|
@ -656,22 +692,22 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (!pDocInfo)
|
if (!pDocInfo)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_PARAMETER);
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
||||||
return 0;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hPrinter)
|
if (!hPrinter)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
return 0;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this is a printer handle.
|
// Check if this is a printer handle.
|
||||||
pHandle = (PLOCAL_HANDLE)hPrinter;
|
pHandle = (PLOCAL_HANDLE)hPrinter;
|
||||||
if (pHandle->HandleType != Printer)
|
if (pHandle->HandleType != Printer)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
dwErrorCode = ERROR_INVALID_HANDLE;
|
||||||
return 0;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
|
pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
|
||||||
|
@ -679,8 +715,8 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||||
// Check if this is the right document information level.
|
// Check if this is the right document information level.
|
||||||
if (Level != 1)
|
if (Level != 1)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_LEVEL);
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
||||||
return 0;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
pDocumentInfo1 = (PDOC_INFO_1W)pDocInfo;
|
pDocumentInfo1 = (PDOC_INFO_1W)pDocInfo;
|
||||||
|
@ -696,8 +732,8 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||||
// Use the datatype if it's valid.
|
// Use the datatype if it's valid.
|
||||||
if (!FindDatatype(pJob->Printer->pPrintProcessor, pDocumentInfo1->pDatatype))
|
if (!FindDatatype(pJob->Printer->pPrintProcessor, pDocumentInfo1->pDatatype))
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_DATATYPE);
|
dwErrorCode = ERROR_INVALID_DATATYPE;
|
||||||
return 0;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
pJob->pwszDatatype = AllocSplStr(pDocumentInfo1->pDatatype);
|
pJob->pwszDatatype = AllocSplStr(pDocumentInfo1->pDatatype);
|
||||||
|
@ -720,25 +756,35 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
|
||||||
|
|
||||||
// Get an ID for the new job.
|
// Get an ID for the new job.
|
||||||
if (!GetNextJobID(&pJob->dwJobID))
|
if (!GetNextJobID(&pJob->dwJobID))
|
||||||
return 0;
|
{
|
||||||
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
goto Cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
// Add the job to the Global Job List.
|
// Add the job to the Global Job List.
|
||||||
if (!InsertElementSkiplist(&GlobalJobList, pJob))
|
if (!InsertElementSkiplist(&GlobalJobList, pJob))
|
||||||
{
|
{
|
||||||
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
ERR("InsertElementSkiplist failed for job %lu for the GlobalJobList!\n", pJob->dwJobID);
|
ERR("InsertElementSkiplist failed for job %lu for the GlobalJobList!\n", pJob->dwJobID);
|
||||||
return 0;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the job at the end of the Printer's Job List.
|
// Add the job at the end of the Printer's Job List.
|
||||||
// As all new jobs are created with default priority, we can be sure that it would always be inserted at the end.
|
// As all new jobs are created with default priority, we can be sure that it would always be inserted at the end.
|
||||||
if (!InsertTailElementSkiplist(&pJob->Printer->JobList, pJob))
|
if (!InsertTailElementSkiplist(&pJob->Printer->JobList, pJob))
|
||||||
{
|
{
|
||||||
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
|
ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
|
||||||
return 0;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
pPrinterHandle->StartedJob = pJob;
|
pPrinterHandle->StartedJob = pJob;
|
||||||
return pJob->dwJobID;
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
dwReturnValue = pJob->dwJobID;
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
SetLastError(dwErrorCode);
|
||||||
|
return dwReturnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
|
|
|
@ -24,18 +24,16 @@ static LIST_ENTRY _PrintProcessorList;
|
||||||
* You can use it for further tasks and have to close it with RegCloseKey.
|
* You can use it for further tasks and have to close it with RegCloseKey.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
* TRUE if the environment is valid and a registry key was opened, FALSE otherwise.
|
* A Windows Error Code indicating success or failure.
|
||||||
* In case of failure, Last Error will be set to ERROR_INVALID_ENVIRONMENT.
|
|
||||||
*/
|
*/
|
||||||
static BOOL
|
static DWORD
|
||||||
_OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey)
|
_OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey)
|
||||||
{
|
{
|
||||||
const WCHAR wszEnvironmentsKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Environments\\";
|
const WCHAR wszEnvironmentsKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Environments\\";
|
||||||
const DWORD cchEnvironmentsKey = _countof(wszEnvironmentsKey) - 1;
|
const DWORD cchEnvironmentsKey = _countof(wszEnvironmentsKey) - 1;
|
||||||
|
|
||||||
BOOL bReturnValue = FALSE;
|
|
||||||
DWORD cchEnvironment;
|
DWORD cchEnvironment;
|
||||||
LONG lStatus;
|
DWORD dwErrorCode;
|
||||||
PWSTR pwszEnvironmentKey = NULL;
|
PWSTR pwszEnvironmentKey = NULL;
|
||||||
|
|
||||||
// Use the current environment if none was supplied.
|
// Use the current environment if none was supplied.
|
||||||
|
@ -55,25 +53,23 @@ _OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey)
|
||||||
CopyMemory(&pwszEnvironmentKey[cchEnvironmentsKey], pEnvironment, (cchEnvironment + 1) * sizeof(WCHAR));
|
CopyMemory(&pwszEnvironmentKey[cchEnvironmentsKey], pEnvironment, (cchEnvironment + 1) * sizeof(WCHAR));
|
||||||
|
|
||||||
// Open the registry key.
|
// Open the registry key.
|
||||||
lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, pwszEnvironmentKey, 0, KEY_READ, hKey);
|
dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, pwszEnvironmentKey, 0, KEY_READ, hKey);
|
||||||
if (lStatus == ERROR_FILE_NOT_FOUND)
|
if (dwErrorCode == ERROR_FILE_NOT_FOUND)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_ENVIRONMENT);
|
dwErrorCode = ERROR_INVALID_ENVIRONMENT;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
else if (lStatus != ERROR_SUCCESS)
|
else if (dwErrorCode != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("RegOpenKeyExW failed with status %ld!\n", lStatus);
|
ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
bReturnValue = TRUE;
|
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pwszEnvironmentKey)
|
if (pwszEnvironmentKey)
|
||||||
DllFreeSplMem(pwszEnvironmentKey);
|
DllFreeSplMem(pwszEnvironmentKey);
|
||||||
|
|
||||||
return bReturnValue;
|
return dwErrorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
|
@ -146,7 +142,7 @@ InitializePrintProcessorList()
|
||||||
wszPrintProcessorPath[cchPrintProcessorPath++] = L'\\';
|
wszPrintProcessorPath[cchPrintProcessorPath++] = L'\\';
|
||||||
|
|
||||||
// Open the environment registry key.
|
// Open the environment registry key.
|
||||||
if (!_OpenEnvironment(NULL, &hKey))
|
if (_OpenEnvironment(NULL, &hKey) != ERROR_SUCCESS)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
|
||||||
// Open the "Print Processors" subkey.
|
// Open the "Print Processors" subkey.
|
||||||
|
@ -372,25 +368,33 @@ Cleanup:
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
||||||
{
|
{
|
||||||
|
DWORD dwErrorCode;
|
||||||
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
|
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (Level != 1)
|
if (Level != 1)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_LEVEL);
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to find the Print Processor.
|
// Try to find the Print Processor.
|
||||||
pPrintProcessor = FindPrintProcessor(pPrintProcessorName);
|
pPrintProcessor = FindPrintProcessor(pPrintProcessorName);
|
||||||
if (!pPrintProcessor)
|
if (!pPrintProcessor)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
|
dwErrorCode = ERROR_UNKNOWN_PRINTPROCESSOR;
|
||||||
return FALSE;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call its EnumPrintProcessorDatatypesW function.
|
// Call its EnumPrintProcessorDatatypesW function.
|
||||||
return pPrintProcessor->pfnEnumPrintProcessorDatatypesW(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
|
if (pPrintProcessor->pfnEnumPrintProcessorDatatypesW(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned))
|
||||||
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
|
else
|
||||||
|
dwErrorCode = GetLastError();
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
SetLastError(dwErrorCode);
|
||||||
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -431,13 +435,12 @@ LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD
|
||||||
BOOL WINAPI
|
BOOL WINAPI
|
||||||
LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
|
||||||
{
|
{
|
||||||
BOOL bReturnValue = FALSE;
|
|
||||||
DWORD cchMaxSubKey;
|
DWORD cchMaxSubKey;
|
||||||
DWORD cchPrintProcessor;
|
DWORD cchPrintProcessor;
|
||||||
|
DWORD dwErrorCode;
|
||||||
DWORD i;
|
DWORD i;
|
||||||
HKEY hKey = NULL;
|
HKEY hKey = NULL;
|
||||||
HKEY hSubKey = NULL;
|
HKEY hSubKey = NULL;
|
||||||
LONG lStatus;
|
|
||||||
PBYTE pCurrentOutputPrintProcessor;
|
PBYTE pCurrentOutputPrintProcessor;
|
||||||
PBYTE pCurrentOutputPrintProcessorInfo;
|
PBYTE pCurrentOutputPrintProcessorInfo;
|
||||||
PRINTPROCESSOR_INFO_1W PrintProcessorInfo1;
|
PRINTPROCESSOR_INFO_1W PrintProcessorInfo1;
|
||||||
|
@ -446,35 +449,36 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (Level != 1)
|
if (Level != 1)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_LEVEL);
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pcbNeeded || !pcReturned)
|
if (!pcbNeeded || !pcReturned)
|
||||||
{
|
{
|
||||||
// This error must be caught by RPC and returned as RPC_X_NULL_REF_POINTER.
|
// This error is also caught by RPC and returned as RPC_X_NULL_REF_POINTER.
|
||||||
ERR("pcbNeeded or pcReturned is NULL!\n");
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify pEnvironment and open its registry key.
|
// Verify pEnvironment and open its registry key.
|
||||||
// We use the registry and not the PrintProcessorList here, because the caller may request information about a different environment.
|
// We use the registry and not the PrintProcessorList here, because the caller may request information about a different environment.
|
||||||
if (!_OpenEnvironment(pEnvironment, &hKey))
|
dwErrorCode = _OpenEnvironment(pEnvironment, &hKey);
|
||||||
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
|
||||||
// Open the "Print Processors" subkey.
|
// Open the "Print Processors" subkey.
|
||||||
lStatus = RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey);
|
dwErrorCode = (DWORD)RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey);
|
||||||
if (lStatus != ERROR_SUCCESS)
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("RegOpenKeyExW failed with status %ld!\n", lStatus);
|
ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the number of Print Processors and maximum sub key length.
|
// Get the number of Print Processors and maximum sub key length.
|
||||||
lStatus = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, pcReturned, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL);
|
dwErrorCode = (DWORD)RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, pcReturned, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||||
if (lStatus != ERROR_SUCCESS)
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("RegQueryInfoKeyW failed with status %ld!\n", lStatus);
|
ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,6 +486,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
|
||||||
pwszTemp = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
|
pwszTemp = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
|
||||||
if (!pwszTemp)
|
if (!pwszTemp)
|
||||||
{
|
{
|
||||||
|
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
@ -494,10 +499,10 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
|
||||||
// RegEnumKeyExW sucks! Unlike similar API functions, it only returns the actual numbers of characters copied when you supply a buffer large enough.
|
// RegEnumKeyExW sucks! Unlike similar API functions, it only returns the actual numbers of characters copied when you supply a buffer large enough.
|
||||||
// So use pwszTemp with its size cchMaxSubKey for this.
|
// So use pwszTemp with its size cchMaxSubKey for this.
|
||||||
cchPrintProcessor = cchMaxSubKey;
|
cchPrintProcessor = cchMaxSubKey;
|
||||||
lStatus = RegEnumKeyExW(hSubKey, i, pwszTemp, &cchPrintProcessor, NULL, NULL, NULL, NULL);
|
dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, pwszTemp, &cchPrintProcessor, NULL, NULL, NULL, NULL);
|
||||||
if (lStatus != ERROR_SUCCESS)
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("RegEnumKeyExW failed with status %ld!\n", lStatus);
|
ERR("RegEnumKeyExW failed with status %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,7 +512,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
|
||||||
// Check if the supplied buffer is large enough.
|
// Check if the supplied buffer is large enough.
|
||||||
if (cbBuf < *pcbNeeded)
|
if (cbBuf < *pcbNeeded)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,10 +527,10 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
|
||||||
cchPrintProcessor = cchMaxSubKey;
|
cchPrintProcessor = cchMaxSubKey;
|
||||||
|
|
||||||
// Copy the Print Processor name.
|
// Copy the Print Processor name.
|
||||||
lStatus = RegEnumKeyExW(hSubKey, i, (PWSTR)pCurrentOutputPrintProcessor, &cchPrintProcessor, NULL, NULL, NULL, NULL);
|
dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, (PWSTR)pCurrentOutputPrintProcessor, &cchPrintProcessor, NULL, NULL, NULL, NULL);
|
||||||
if (lStatus != ERROR_SUCCESS)
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("RegEnumKeyExW failed with status %ld!\n", lStatus);
|
ERR("RegEnumKeyExW failed with status %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -539,8 +544,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
|
||||||
}
|
}
|
||||||
|
|
||||||
// We've finished successfully!
|
// We've finished successfully!
|
||||||
SetLastError(ERROR_SUCCESS);
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
bReturnValue = TRUE;
|
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (pwszTemp)
|
if (pwszTemp)
|
||||||
|
@ -552,7 +556,8 @@ Cleanup:
|
||||||
if (hKey)
|
if (hKey)
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
|
|
||||||
return bReturnValue;
|
SetLastError(dwErrorCode);
|
||||||
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -592,34 +597,34 @@ LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
|
||||||
const WCHAR wszPath[] = L"\\PRTPROCS\\";
|
const WCHAR wszPath[] = L"\\PRTPROCS\\";
|
||||||
const DWORD cchPath = _countof(wszPath) - 1;
|
const DWORD cchPath = _countof(wszPath) - 1;
|
||||||
|
|
||||||
BOOL bReturnValue = FALSE;
|
|
||||||
DWORD cbDataWritten;
|
DWORD cbDataWritten;
|
||||||
|
DWORD dwErrorCode;
|
||||||
HKEY hKey = NULL;
|
HKEY hKey = NULL;
|
||||||
LONG lStatus;
|
|
||||||
|
|
||||||
// Sanity checks
|
// Sanity checks
|
||||||
if (Level != 1)
|
if (Level != 1)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INVALID_LEVEL);
|
dwErrorCode = ERROR_INVALID_LEVEL;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pcbNeeded)
|
if (!pcbNeeded)
|
||||||
{
|
{
|
||||||
// This error must be caught by RPC and returned as RPC_X_NULL_REF_POINTER.
|
// This error is also caught by RPC and returned as RPC_X_NULL_REF_POINTER.
|
||||||
ERR("pcbNeeded is NULL!\n");
|
dwErrorCode = ERROR_INVALID_PARAMETER;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify pEnvironment and open its registry key.
|
// Verify pEnvironment and open its registry key.
|
||||||
if (!_OpenEnvironment(pEnvironment, &hKey))
|
dwErrorCode = _OpenEnvironment(pEnvironment, &hKey);
|
||||||
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
|
|
||||||
// Determine the size of the required buffer.
|
// Determine the size of the required buffer.
|
||||||
lStatus = RegQueryValueExW(hKey, L"Directory", NULL, NULL, NULL, pcbNeeded);
|
dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Directory", NULL, NULL, NULL, pcbNeeded);
|
||||||
if (lStatus != ERROR_SUCCESS)
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("RegQueryValueExW failed with status %ld!\n", lStatus);
|
ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,7 +634,7 @@ LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
|
||||||
// Is the supplied buffer large enough?
|
// Is the supplied buffer large enough?
|
||||||
if (cbBuf < *pcbNeeded)
|
if (cbBuf < *pcbNeeded)
|
||||||
{
|
{
|
||||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,20 +643,20 @@ LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
|
||||||
CopyMemory(&pPrintProcessorInfo[cchSpoolDirectory], wszPath, cchPath * sizeof(WCHAR));
|
CopyMemory(&pPrintProcessorInfo[cchSpoolDirectory], wszPath, cchPath * sizeof(WCHAR));
|
||||||
|
|
||||||
// Get the directory name from the registry.
|
// Get the directory name from the registry.
|
||||||
lStatus = RegQueryValueExW(hKey, L"Directory", NULL, NULL, &pPrintProcessorInfo[cchSpoolDirectory + cchPath], &cbDataWritten);
|
dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Directory", NULL, NULL, &pPrintProcessorInfo[cchSpoolDirectory + cchPath], &cbDataWritten);
|
||||||
if (lStatus != ERROR_SUCCESS)
|
if (dwErrorCode != ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
ERR("RegQueryValueExW failed with status %ld!\n", lStatus);
|
ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We've finished successfully!
|
// We've finished successfully!
|
||||||
SetLastError(ERROR_SUCCESS);
|
dwErrorCode = ERROR_SUCCESS;
|
||||||
bReturnValue = TRUE;
|
|
||||||
|
|
||||||
Cleanup:
|
Cleanup:
|
||||||
if (hKey)
|
if (hKey)
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
|
|
||||||
return bReturnValue;
|
SetLastError(dwErrorCode);
|
||||||
|
return (dwErrorCode == ERROR_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue