[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:
Colin Finck 2015-06-23 13:46:14 +00:00
parent 5df5a009e2
commit 7e4bcf78c4
15 changed files with 303 additions and 261 deletions

View file

@ -94,9 +94,10 @@ SplIsUpgrade()
return FALSE;
}
DWORD WINAPI
BOOL WINAPI
SpoolerInit()
{
// Nothing to do here yet
return ERROR_SUCCESS;
SetLastError(ERROR_SUCCESS);
return TRUE;
}

View file

@ -21,13 +21,9 @@ _RpcSpoolerInit()
return dwErrorCode;
}
dwErrorCode = SpoolerInit();
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("SpoolerInit failed with error %lu!\n", dwErrorCode);
RpcRevertToSelf();
return dwErrorCode;
}
SpoolerInit();
dwErrorCode = GetLastError();
return RpcRevertToSelf();
RpcRevertToSelf();
return dwErrorCode;
}

View file

@ -19,15 +19,11 @@ _RpcAddJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pAddJob, DWORD c
return dwErrorCode;
}
dwErrorCode = AddJobW(hPrinter, Level, pAddJob, cbBuf, pcbNeeded);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("AddJobW failed with error %lu!\n", dwErrorCode);
RpcRevertToSelf();
return dwErrorCode;
}
AddJobW(hPrinter, Level, pAddJob, cbBuf, pcbNeeded);
dwErrorCode = GetLastError();
return RpcRevertToSelf();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
@ -42,15 +38,11 @@ _RpcGetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, DWORD Level, BYTE* pJo
return dwErrorCode;
}
dwErrorCode = GetJobW(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("GetJobW failed with error %lu!\n", dwErrorCode);
RpcRevertToSelf();
return dwErrorCode;
}
GetJobW(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
dwErrorCode = GetLastError();
return RpcRevertToSelf();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD

View file

@ -19,15 +19,11 @@ _RpcEnumPrinters(DWORD Flags, WINSPOOL_HANDLE Name, DWORD Level, BYTE* pPrinterE
return dwErrorCode;
}
dwErrorCode = EnumPrintersW(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("EnumPrintersW failed with error %lu!\n", dwErrorCode);
RpcRevertToSelf();
return dwErrorCode;
}
EnumPrintersW(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
dwErrorCode = GetLastError();
return RpcRevertToSelf();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
@ -47,13 +43,9 @@ _RpcOpenPrinter(WINSPOOL_HANDLE pPrinterName, WINSPOOL_PRINTER_HANDLE* phPrinter
Default.pDatatype = pDatatype;
Default.pDevMode = (PDEVMODEW)pDevModeContainer->pDevMode;
dwErrorCode = OpenPrinterW(pPrinterName, phPrinter, &Default);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("OpenPrinterW failed with error %lu!\n", dwErrorCode);
RpcRevertToSelf();
return dwErrorCode;
}
OpenPrinterW(pPrinterName, phPrinter, &Default);
dwErrorCode = GetLastError();
return RpcRevertToSelf();
RpcRevertToSelf();
return dwErrorCode;
}

View file

@ -26,15 +26,11 @@ _RpcEnumPrintProcessorDatatypes(WINSPOOL_HANDLE pName, WCHAR *pPrintProcessorNam
return dwErrorCode;
}
dwErrorCode = EnumPrintProcessorDatatypesW(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("EnumPrintProcessorDatatypesW failed with error %lu!\n", dwErrorCode);
RpcRevertToSelf();
return dwErrorCode;
}
EnumPrintProcessorDatatypesW(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
dwErrorCode = GetLastError();
return RpcRevertToSelf();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
@ -49,15 +45,11 @@ _RpcEnumPrintProcessors(WINSPOOL_HANDLE pName, WCHAR *pEnvironment, DWORD Level,
return dwErrorCode;
}
dwErrorCode = EnumPrintProcessorsW(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("EnumPrintProcessorsW failed with error %lu!\n", dwErrorCode);
RpcRevertToSelf();
return dwErrorCode;
}
EnumPrintProcessorsW(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
dwErrorCode = GetLastError();
return RpcRevertToSelf();
RpcRevertToSelf();
return dwErrorCode;
}
DWORD
@ -72,13 +64,9 @@ _RpcGetPrintProcessorDirectory(WINSPOOL_HANDLE pName, WCHAR *pEnvironment, DWORD
return dwErrorCode;
}
dwErrorCode = GetPrintProcessorDirectoryW(pName, pEnvironment, Level, pPrintProcessorDirectory, cbBuf, pcbNeeded);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("EnumPrintProcessorsW failed with error %lu!\n", dwErrorCode);
RpcRevertToSelf();
return dwErrorCode;
}
GetPrintProcessorDirectoryW(pName, pEnvironment, Level, pPrintProcessorDirectory, cbBuf, pcbNeeded);
dwErrorCode = GetLastError();
return RpcRevertToSelf();
RpcRevertToSelf();
return dwErrorCode;
}

View file

@ -17,11 +17,7 @@ AddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeede
RpcTryExcept
{
dwErrorCode = _RpcAddJob(hPrinter, Level, pData, cbBuf, pcbNeeded);
if (dwErrorCode)
{
ERR("_RpcAddJob failed with error %lu!\n", dwErrorCode);
}
SetLastError(dwErrorCode);
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@ -43,11 +39,7 @@ GetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDW
RpcTryExcept
{
dwErrorCode = _RpcGetJob(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
if (dwErrorCode)
{
ERR("_RpcGetJob failed with error %lu!\n", dwErrorCode);
}
SetLastError(dwErrorCode);
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)

View file

@ -68,19 +68,15 @@ midl_user_free(void __RPC_FAR* ptr)
BOOL WINAPI
SpoolerInit()
{
BOOL ReturnValue = FALSE;
DWORD ErrorCode;
BOOL bReturnValue = FALSE;
DWORD dwErrorCode;
// Nothing to initialize here yet, but pass this call to the Spool Service as well.
RpcTryExcept
{
ErrorCode = _RpcSpoolerInit();
if (ErrorCode)
{
ERR("_RpcSpoolerInit failed with error %lu!\n", ErrorCode);
}
ReturnValue = (ErrorCode == ERROR_SUCCESS);
dwErrorCode = _RpcSpoolerInit();
SetLastError(dwErrorCode);
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
{
@ -88,5 +84,5 @@ SpoolerInit()
}
RpcEndExcept;
return ReturnValue;
return bReturnValue;
}

View file

@ -23,11 +23,7 @@ EnumPrintersW(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD
RpcTryExcept
{
dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
if (dwErrorCode)
{
ERR("_RpcEnumPrinters failed with error %lu!\n", dwErrorCode);
}
SetLastError(dwErrorCode);
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@ -204,11 +200,7 @@ OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefau
RpcTryExcept
{
dwErrorCode = _RpcOpenPrinter(pPrinterName, phPrinter, pDatatype, pDevModeContainer, AccessRequired);
if (dwErrorCode)
{
ERR("_RpcOpenPrinter failed with error %lu!\n", dwErrorCode);
}
SetLastError(dwErrorCode);
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)

View file

@ -23,11 +23,7 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
RpcTryExcept
{
dwErrorCode = _RpcEnumPrintProcessorDatatypes(pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
if (dwErrorCode)
{
ERR("_RpcEnumPrintProcessorDatatypes failed with error %lu!\n", dwErrorCode);
}
SetLastError(dwErrorCode);
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@ -49,11 +45,7 @@ EnumPrintProcessorsW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPri
RpcTryExcept
{
dwErrorCode = _RpcEnumPrintProcessors(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
if (dwErrorCode)
{
ERR("_RpcEnumPrintProcessors failed with error %lu!\n", dwErrorCode);
}
SetLastError(dwErrorCode);
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)
@ -75,11 +67,7 @@ GetPrintProcessorDirectoryW(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBY
RpcTryExcept
{
dwErrorCode = _RpcGetPrintProcessorDirectory(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded);
if (dwErrorCode)
{
ERR("_RpcGetPrintProcessorDirectory failed with error %lu!\n", dwErrorCode);
}
SetLastError(dwErrorCode);
bReturnValue = (dwErrorCode == ERROR_SUCCESS);
}
RpcExcept(EXCEPTION_EXECUTE_HANDLER)

View file

@ -49,13 +49,17 @@ BOOL WINAPI
EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
{
DWORD cbDatatype;
DWORD dwErrorCode;
DWORD dwOffsets[_countof(pwszDatatypes)];
PCWSTR* pCurrentDatatype;
PDWORD pCurrentOffset = dwOffsets;
// Sanity checks
if (Level != 1 || !pcbNeeded || !pcReturned)
return FALSE;
{
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// Count the required buffer size and the number of datatypes.
*pcbNeeded = 0;
@ -76,20 +80,24 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// Check if a buffer was supplied at all.
if (!pDatatypes)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// Copy over all datatypes.
*pCurrentOffset = MAXDWORD;
PackStrings(pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]);
return TRUE;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}

View file

@ -196,36 +196,54 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
const DWORD cchSpl = _countof("?????.SPL") - 1;
ADDJOB_INFO_1W AddJobInfo1;
BOOL bReturnValue = FALSE;
DWORD cchMachineName;
DWORD cchUserName;
DWORD dwErrorCode;
PBYTE p;
PLOCAL_HANDLE pHandle;
PLOCAL_JOB pJob;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
RPC_BINDING_HANDLE hServerBinding = NULL;
RPC_STATUS Status;
RPC_WSTR pwszBinding = NULL;
RPC_WSTR pwszMachineName = NULL;
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != Printer)
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
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.
if (Level != 1)
{
dwErrorCode = ERROR_INVALID_LEVEL;
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.
*pcbNeeded = sizeof(ADDJOB_INFO_1W) + (cchSpoolDirectory + cchPrintersPath + cchSpl + 1) * sizeof(WCHAR);
if (cbBuf < *pcbNeeded)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
@ -233,13 +251,17 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
if (!pJob)
{
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
dwErrorCode = GetLastError();
ERR("DllAllocSplMem failed with error %lu!\n", dwErrorCode);
goto Cleanup;
}
// Reserve an ID for this job.
if (!GetNextJobID(&pJob->dwJobID))
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
// Copy over defaults to the LOCAL_JOB structure.
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));
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;
}
@ -262,24 +285,24 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
pJob->pwszNotifyName = AllocSplStr(pJob->pwszUserName);
// Get the name of the machine that submitted the Job over RPC.
Status = RpcBindingServerFromClient(NULL, &hServerBinding);
if (Status != RPC_S_OK)
dwErrorCode = RpcBindingServerFromClient(NULL, &hServerBinding);
if (dwErrorCode != RPC_S_OK)
{
ERR("RpcBindingServerFromClient failed with status %lu!\n", Status);
ERR("RpcBindingServerFromClient failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
Status = RpcBindingToStringBindingW(hServerBinding, &pwszBinding);
if (Status != RPC_S_OK)
dwErrorCode = RpcBindingToStringBindingW(hServerBinding, &pwszBinding);
if (dwErrorCode != RPC_S_OK)
{
ERR("RpcBindingToStringBindingW failed with status %lu!\n", Status);
ERR("RpcBindingToStringBindingW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
Status = RpcStringBindingParseW(pwszBinding, NULL, NULL, &pwszMachineName, NULL, NULL);
if (Status != RPC_S_OK)
dwErrorCode = RpcStringBindingParseW(pwszBinding, NULL, NULL, &pwszMachineName, NULL, NULL);
if (dwErrorCode != RPC_S_OK)
{
ERR("RpcStringBindingParseW failed with status %lu!\n", Status);
ERR("RpcStringBindingParseW failed with status %lu!\n", dwErrorCode);
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.
if (!InsertElementSkiplist(&GlobalJobList, pJob))
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("InsertElementSkiplist failed for job %lu for the GlobalJobList!\n", pJob->dwJobID);
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.
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);
goto Cleanup;
}
@ -315,7 +340,7 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
p += cchPrintersPath;
swprintf((PWSTR)p, L"%05lu.SPL", pJob->dwJobID);
bReturnValue = TRUE;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
if (pwszMachineName)
@ -327,11 +352,12 @@ Cleanup:
if (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)
{
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 cbPrinterName = (wcslen(pJob->Printer->pwszPrinterName) + 1) * sizeof(WCHAR);
DWORD cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
DWORD dwErrorCode;
JOB_INFO_1W JobInfo1 = { 0 };
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;
if (cbBuf < *pcbNeeded)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// 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(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)
{
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 cbPrintProcessor = (wcslen(pJob->Printer->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
DWORD cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
DWORD dwErrorCode;
FILETIME ftNow;
FILETIME ftSubmitted;
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;
if (cbBuf < *pcbNeeded)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// 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.
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");
return FALSE;
goto Cleanup;
}
// 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.
CopyMemory(pOutput, &JobInfo2, sizeof(JOB_INFO_2W));
return TRUE;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
return dwErrorCode;
}
BOOL WINAPI
LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pOutput, DWORD cbBuf, LPDWORD pcbNeeded)
{
DWORD dwErrorCode;
PLOCAL_HANDLE pHandle;
PLOCAL_JOB pJob;
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.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != Printer)
return FALSE;
{
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
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);
if (!pJob || pJob->Printer != pPrinterHandle->Printer)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// The function behaves differently for each level.
if (Level == 1)
return _LocalGetJobLevel1(pPrinterHandle, pJob, pOutput, cbBuf, pcbNeeded);
dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, pOutput, cbBuf, pcbNeeded);
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

View file

@ -156,5 +156,6 @@ InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, L
{
CopyMemory(pPrintProvidor, &_PrintProviderFunctions, min(cbPrintProvidor, sizeof(PRINTPROVIDOR)));
SetLastError(ERROR_SUCCESS);
return TRUE;
}

View file

@ -73,6 +73,8 @@ typedef struct _LOCAL_PRINTER
// This sort key must be the first element for LookupElementSkiplist to work!
PWSTR pwszPrinterName;
DWORD dwAttributes;
DWORD dwStatus;
PWSTR pwszPrinterDriver;
PWSTR pwszDescription;
PWSTR pwszDefaultDatatype;

View file

@ -38,7 +38,7 @@ InitializePrinterList()
{
const WCHAR wszPrintersKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers";
DWORD cbDevMode;
DWORD cbData;
DWORD cchPrinterName;
DWORD dwSubKeys;
DWORD i;
@ -173,11 +173,29 @@ InitializePrinterList()
}
// Get the default DevMode.
cbDevMode = sizeof(DEVMODEW);
lStatus = RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL, (PBYTE)&pPrinter->DefaultDevMode, &cbDevMode);
if (lStatus != ERROR_SUCCESS || cbDevMode != sizeof(DEVMODEW))
cbData = sizeof(DEVMODEW);
lStatus = RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL, (PBYTE)&pPrinter->DefaultDevMode, &cbData);
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;
}
@ -223,7 +241,7 @@ Cleanup:
}
BOOL
DWORD
_LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
{
const WCHAR wszComma[] = L",";
@ -232,6 +250,7 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
DWORD cbComment;
DWORD cbDescription;
DWORD cchComputerName = 0;
DWORD dwErrorCode;
DWORD i;
PBYTE pPrinterInfo;
PBYTE pPrinterString;
@ -263,8 +282,9 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
cchComputerName = MAX_COMPUTERNAME_LENGTH + 1;
if (!GetComputerNameW(&wszComputerName[2], &cchComputerName))
{
ERR("GetComputerNameW failed with error %lu!\n", GetLastError());
return FALSE;
dwErrorCode = GetLastError();
ERR("GetComputerNameW failed with error %lu!\n", dwErrorCode);
goto Cleanup;
}
// 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.
if (wcsicmp(&Name[2], &wszComputerName[2]) != 0)
{
SetLastError(ERROR_INVALID_NAME);
return FALSE;
dwErrorCode = ERROR_INVALID_NAME;
goto Cleanup;
}
// 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)
{
// The user supplied a name that cannot be processed by the local print provider.
SetLastError(ERROR_INVALID_NAME);
return FALSE;
dwErrorCode = ERROR_INVALID_NAME;
goto Cleanup;
}
}
else
@ -302,14 +322,15 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// Copy over the print processor information.
((PPRINTER_INFO_1W)pPrinterEnum)->Flags = 0;
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.
if (cbBuf < *pcbNeeded)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
// 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);
}
return TRUE;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
return dwErrorCode;
}
BOOL WINAPI
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!
// Begin counting.
@ -394,30 +420,36 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
*pcReturned = 0;
// 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)
{
// The function behaves quite differently for each level.
if (Level == 1)
return _LocalEnumPrintersLevel1(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
// TODO: Handle other levels.
// The caller supplied an invalid level.
return FALSE;
{
dwErrorCode = _LocalEnumPrintersLevel1(Flags, Name, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
}
else
{
// TODO: Handle other levels.
// The caller supplied an invalid level.
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
}
// Treat it as success if the caller queried no information and we don't need to return any.
return TRUE;
Cleanup:
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
BOOL WINAPI
LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault)
{
BOOL bReturnValue = ROUTER_UNKNOWN;
DWORD cchComputerName;
DWORD cchPrinterName;
DWORD dwErrorCode;
DWORD dwJobID;
PWSTR p = lpPrinterName;
PWSTR pwszPrinterName = NULL;
@ -430,7 +462,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
// Sanity checks
if (!lpPrinterName || !phPrinter)
{
SetLastError(ERROR_INVALID_PARAMETER);
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
@ -445,7 +477,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
if (!p)
{
// We didn't get a proper server name.
SetLastError(ERROR_INVALID_PRINTER_NAME);
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
goto Cleanup;
}
@ -456,14 +488,15 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
cchComputerName = _countof(wszComputerName);
if (!GetComputerNameW(wszComputerName, &cchComputerName))
{
ERR("GetComputerNameW failed with error %lu!\n", GetLastError());
dwErrorCode = GetLastError();
ERR("GetComputerNameW failed with error %lu!\n", dwErrorCode);
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.
if (wcsicmp(lpPrinterName, wszComputerName) != 0)
{
SetLastError(ERROR_INVALID_PRINTER_NAME);
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
goto Cleanup;
}
@ -481,7 +514,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
// No printer name and no comma? This is invalid!
if (!cchPrinterName && !p)
{
SetLastError(ERROR_INVALID_PRINTER_NAME);
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
goto Cleanup;
}
@ -498,7 +531,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
if (!pPrinter)
{
// The printer does not exist.
SetLastError(ERROR_INVALID_PRINTER_NAME);
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
goto Cleanup;
}
@ -512,7 +545,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
// Use the datatype if it's valid.
if (!FindDatatype(pPrinter->pPrintProcessor, pDefault->pDatatype))
{
SetLastError(ERROR_INVALID_DATATYPE);
dwErrorCode = ERROR_INVALID_DATATYPE;
goto Cleanup;
}
@ -545,7 +578,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
// The "Job " string has to follow now.
if (wcscmp(p, L"Job ") != 0)
{
SetLastError(ERROR_INVALID_PRINTER_NAME);
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
goto Cleanup;
}
@ -561,7 +594,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
if (!IS_VALID_JOB_ID(dwJobID))
{
// The user supplied an invalid Job ID.
SetLastError(ERROR_INVALID_PRINTER_NAME);
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
goto Cleanup;
}
@ -570,7 +603,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
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.
SetLastError(ERROR_INVALID_PRINTER_NAME);
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
goto Cleanup;
}
@ -618,13 +651,13 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
}
else
{
SetLastError(ERROR_INVALID_PRINTER_NAME);
dwErrorCode = ERROR_INVALID_PRINTER_NAME;
goto Cleanup;
}
}
*phPrinter = (HANDLE)pHandle;
bReturnValue = ROUTER_SUCCESS;
dwErrorCode = ERROR_SUCCESS;
// Don't let the cleanup routines free this.
pPrinterHandle = NULL;
@ -642,12 +675,15 @@ Cleanup:
if (pwszPrinterName)
DllFreeSplMem(pwszPrinterName);
return bReturnValue;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}
DWORD WINAPI
LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
{
DWORD dwErrorCode;
DWORD dwReturnValue = 0;
PDOC_INFO_1W pDocumentInfo1;
PLOCAL_HANDLE pHandle;
PLOCAL_JOB pJob;
@ -656,22 +692,22 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
// Sanity checks
if (!pDocInfo)
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
if (!hPrinter)
{
SetLastError(ERROR_INVALID_HANDLE);
return 0;
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
// Check if this is a printer handle.
pHandle = (PLOCAL_HANDLE)hPrinter;
if (pHandle->HandleType != Printer)
{
SetLastError(ERROR_INVALID_HANDLE);
return 0;
dwErrorCode = ERROR_INVALID_HANDLE;
goto Cleanup;
}
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.
if (Level != 1)
{
SetLastError(ERROR_INVALID_LEVEL);
return 0;
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
pDocumentInfo1 = (PDOC_INFO_1W)pDocInfo;
@ -696,8 +732,8 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
// Use the datatype if it's valid.
if (!FindDatatype(pJob->Printer->pPrintProcessor, pDocumentInfo1->pDatatype))
{
SetLastError(ERROR_INVALID_DATATYPE);
return 0;
dwErrorCode = ERROR_INVALID_DATATYPE;
goto Cleanup;
}
pJob->pwszDatatype = AllocSplStr(pDocumentInfo1->pDatatype);
@ -720,25 +756,35 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
// Get an ID for the new job.
if (!GetNextJobID(&pJob->dwJobID))
return 0;
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
goto Cleanup;
}
// Add the job to the Global Job List.
if (!InsertElementSkiplist(&GlobalJobList, pJob))
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
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.
// 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))
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
return 0;
goto Cleanup;
}
pPrinterHandle->StartedJob = pJob;
return pJob->dwJobID;
dwErrorCode = ERROR_SUCCESS;
dwReturnValue = pJob->dwJobID;
Cleanup:
SetLastError(dwErrorCode);
return dwReturnValue;
}
BOOL WINAPI

View file

@ -24,18 +24,16 @@ static LIST_ENTRY _PrintProcessorList;
* You can use it for further tasks and have to close it with RegCloseKey.
*
* @return
* TRUE if the environment is valid and a registry key was opened, FALSE otherwise.
* In case of failure, Last Error will be set to ERROR_INVALID_ENVIRONMENT.
* A Windows Error Code indicating success or failure.
*/
static BOOL
static DWORD
_OpenEnvironment(PCWSTR pEnvironment, PHKEY hKey)
{
const WCHAR wszEnvironmentsKey[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Environments\\";
const DWORD cchEnvironmentsKey = _countof(wszEnvironmentsKey) - 1;
BOOL bReturnValue = FALSE;
DWORD cchEnvironment;
LONG lStatus;
DWORD dwErrorCode;
PWSTR pwszEnvironmentKey = NULL;
// 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));
// Open the registry key.
lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, pwszEnvironmentKey, 0, KEY_READ, hKey);
if (lStatus == ERROR_FILE_NOT_FOUND)
dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_LOCAL_MACHINE, pwszEnvironmentKey, 0, KEY_READ, hKey);
if (dwErrorCode == ERROR_FILE_NOT_FOUND)
{
SetLastError(ERROR_INVALID_ENVIRONMENT);
dwErrorCode = ERROR_INVALID_ENVIRONMENT;
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;
}
bReturnValue = TRUE;
Cleanup:
if (pwszEnvironmentKey)
DllFreeSplMem(pwszEnvironmentKey);
return bReturnValue;
return dwErrorCode;
}
BOOL
@ -146,7 +142,7 @@ InitializePrintProcessorList()
wszPrintProcessorPath[cchPrintProcessorPath++] = L'\\';
// Open the environment registry key.
if (!_OpenEnvironment(NULL, &hKey))
if (_OpenEnvironment(NULL, &hKey) != ERROR_SUCCESS)
goto Cleanup;
// Open the "Print Processors" subkey.
@ -372,25 +368,33 @@ Cleanup:
BOOL WINAPI
LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
{
DWORD dwErrorCode;
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
// Sanity checks
if (Level != 1)
{
SetLastError(ERROR_INVALID_LEVEL);
return FALSE;
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
// Try to find the Print Processor.
pPrintProcessor = FindPrintProcessor(pPrintProcessorName);
if (!pPrintProcessor)
{
SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
return FALSE;
dwErrorCode = ERROR_UNKNOWN_PRINTPROCESSOR;
goto Cleanup;
}
// 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
LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
{
BOOL bReturnValue = FALSE;
DWORD cchMaxSubKey;
DWORD cchPrintProcessor;
DWORD dwErrorCode;
DWORD i;
HKEY hKey = NULL;
HKEY hSubKey = NULL;
LONG lStatus;
PBYTE pCurrentOutputPrintProcessor;
PBYTE pCurrentOutputPrintProcessorInfo;
PRINTPROCESSOR_INFO_1W PrintProcessorInfo1;
@ -446,35 +449,36 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
// Sanity checks
if (Level != 1)
{
SetLastError(ERROR_INVALID_LEVEL);
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
if (!pcbNeeded || !pcReturned)
{
// This error must be caught by RPC and returned as RPC_X_NULL_REF_POINTER.
ERR("pcbNeeded or pcReturned is NULL!\n");
// This error is also caught by RPC and returned as RPC_X_NULL_REF_POINTER.
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// 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.
if (!_OpenEnvironment(pEnvironment, &hKey))
dwErrorCode = _OpenEnvironment(pEnvironment, &hKey);
if (dwErrorCode != ERROR_SUCCESS)
goto Cleanup;
// Open the "Print Processors" subkey.
lStatus = RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey);
if (lStatus != ERROR_SUCCESS)
dwErrorCode = (DWORD)RegOpenKeyExW(hKey, L"Print Processors", 0, KEY_READ, &hSubKey);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegOpenKeyExW failed with status %ld!\n", lStatus);
ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
// 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);
if (lStatus != ERROR_SUCCESS)
dwErrorCode = (DWORD)RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, pcReturned, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegQueryInfoKeyW failed with status %ld!\n", lStatus);
ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
@ -482,6 +486,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
pwszTemp = DllAllocSplMem((cchMaxSubKey + 1) * sizeof(WCHAR));
if (!pwszTemp)
{
dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
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.
// So use pwszTemp with its size cchMaxSubKey for this.
cchPrintProcessor = cchMaxSubKey;
lStatus = RegEnumKeyExW(hSubKey, i, pwszTemp, &cchPrintProcessor, NULL, NULL, NULL, NULL);
if (lStatus != ERROR_SUCCESS)
dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, pwszTemp, &cchPrintProcessor, NULL, NULL, NULL, NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegEnumKeyExW failed with status %ld!\n", lStatus);
ERR("RegEnumKeyExW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
@ -507,7 +512,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
@ -522,10 +527,10 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
cchPrintProcessor = cchMaxSubKey;
// Copy the Print Processor name.
lStatus = RegEnumKeyExW(hSubKey, i, (PWSTR)pCurrentOutputPrintProcessor, &cchPrintProcessor, NULL, NULL, NULL, NULL);
if (lStatus != ERROR_SUCCESS)
dwErrorCode = (DWORD)RegEnumKeyExW(hSubKey, i, (PWSTR)pCurrentOutputPrintProcessor, &cchPrintProcessor, NULL, NULL, NULL, NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegEnumKeyExW failed with status %ld!\n", lStatus);
ERR("RegEnumKeyExW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
@ -539,8 +544,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
}
// We've finished successfully!
SetLastError(ERROR_SUCCESS);
bReturnValue = TRUE;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
if (pwszTemp)
@ -552,7 +556,8 @@ Cleanup:
if (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 DWORD cchPath = _countof(wszPath) - 1;
BOOL bReturnValue = FALSE;
DWORD cbDataWritten;
DWORD dwErrorCode;
HKEY hKey = NULL;
LONG lStatus;
// Sanity checks
if (Level != 1)
{
SetLastError(ERROR_INVALID_LEVEL);
dwErrorCode = ERROR_INVALID_LEVEL;
goto Cleanup;
}
if (!pcbNeeded)
{
// This error must be caught by RPC and returned as RPC_X_NULL_REF_POINTER.
ERR("pcbNeeded is NULL!\n");
// This error is also caught by RPC and returned as RPC_X_NULL_REF_POINTER.
dwErrorCode = ERROR_INVALID_PARAMETER;
goto Cleanup;
}
// Verify pEnvironment and open its registry key.
if (!_OpenEnvironment(pEnvironment, &hKey))
dwErrorCode = _OpenEnvironment(pEnvironment, &hKey);
if (dwErrorCode != ERROR_SUCCESS)
goto Cleanup;
// Determine the size of the required buffer.
lStatus = RegQueryValueExW(hKey, L"Directory", NULL, NULL, NULL, pcbNeeded);
if (lStatus != ERROR_SUCCESS)
dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Directory", NULL, NULL, NULL, pcbNeeded);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegQueryValueExW failed with status %ld!\n", lStatus);
ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
@ -629,7 +634,7 @@ LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
// Is the supplied buffer large enough?
if (cbBuf < *pcbNeeded)
{
SetLastError(ERROR_INSUFFICIENT_BUFFER);
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
@ -638,20 +643,20 @@ LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
CopyMemory(&pPrintProcessorInfo[cchSpoolDirectory], wszPath, cchPath * sizeof(WCHAR));
// Get the directory name from the registry.
lStatus = RegQueryValueExW(hKey, L"Directory", NULL, NULL, &pPrintProcessorInfo[cchSpoolDirectory + cchPath], &cbDataWritten);
if (lStatus != ERROR_SUCCESS)
dwErrorCode = (DWORD)RegQueryValueExW(hKey, L"Directory", NULL, NULL, &pPrintProcessorInfo[cchSpoolDirectory + cchPath], &cbDataWritten);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegQueryValueExW failed with status %ld!\n", lStatus);
ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
goto Cleanup;
}
// We've finished successfully!
SetLastError(ERROR_SUCCESS);
bReturnValue = TRUE;
dwErrorCode = ERROR_SUCCESS;
Cleanup:
if (hKey)
RegCloseKey(hKey);
return bReturnValue;
SetLastError(dwErrorCode);
return (dwErrorCode == ERROR_SUCCESS);
}