[LOCALSPL, WINPRINT]

Bugfix: All functions returning multiple elements must only set *pcReturned to the element count on success!
Currently, this was also done when querying the needed buffer size. But for this case, *pcReturned just has to be zeroed.

svn path=/branches/colins-printing-for-freedom/; revision=68335
This commit is contained in:
Colin Finck 2015-07-03 09:06:35 +00:00
parent 86dbf40cd1
commit 259a6572ae
4 changed files with 24 additions and 15 deletions

View file

@ -107,6 +107,7 @@ BOOL WINAPI
EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
{
DWORD cbDatatype;
DWORD dwDatatypeCount = 0;
DWORD dwErrorCode;
DWORD dwOffsets[_countof(_pwszDatatypes)];
PCWSTR* pCurrentDatatype;
@ -129,9 +130,9 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
*pcbNeeded += sizeof(DATATYPES_INFO_1W) + cbDatatype;
// Also calculate the offset in the output buffer of the pointer to this datatype string.
*pCurrentOffset = *pcReturned * sizeof(DATATYPES_INFO_1W) + FIELD_OFFSET(DATATYPES_INFO_1W, pName);
*pCurrentOffset = dwDatatypeCount * sizeof(DATATYPES_INFO_1W) + FIELD_OFFSET(DATATYPES_INFO_1W, pName);
(*pcReturned)++;
dwDatatypeCount++;
pCurrentOffset++;
}
@ -153,6 +154,7 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
*pCurrentOffset = MAXDWORD;
PackStrings(_pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]);
*pcReturned = dwDatatypeCount;
dwErrorCode = ERROR_SUCCESS;
Cleanup:

View file

@ -898,6 +898,7 @@ BOOL WINAPI
LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
{
DWORD dwErrorCode;
DWORD i;
PBYTE pEnd = &pStart[cbBuf];
PLOCAL_HANDLE pHandle;
PLOCAL_JOB pJob;
@ -930,9 +931,10 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
pFirstJobNode = LookupNodeByIndexSkiplist(&pPrinterHandle->pPrinter->JobList, FirstJob);
// Count the required buffer size and the number of jobs.
i = 0;
pNode = pFirstJobNode;
while (*pcReturned < NoJobs && pNode)
while (i < NoJobs && pNode)
{
pJob = (PLOCAL_JOB)pNode->Element;
@ -943,7 +945,7 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
_LocalGetJobLevel2(pPrinterHandle, pJob, NULL, NULL, 0, pcbNeeded);
// We stop either when there are no more jobs in the list or when the caller didn't request more, whatever comes first.
(*pcReturned)++;
i++;
pNode = pNode->Next[0];
}
@ -956,13 +958,13 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
// Begin counting again and also empty the given buffer.
*pcbNeeded = 0;
*pcReturned = 0;
ZeroMemory(pStart, cbBuf);
// Now call the same functions again to copy the actual data for each job into the buffer.
i = 0;
pNode = pFirstJobNode;
while (*pcReturned < NoJobs && pNode)
while (i < NoJobs && pNode)
{
pJob = (PLOCAL_JOB)pNode->Element;
@ -976,10 +978,11 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
goto Cleanup;
// We stop either when there are no more jobs in the list or when the caller didn't request more, whatever comes first.
(*pcReturned)++;
i++;
pNode = pNode->Next[0];
}
*pcReturned = i;
dwErrorCode = ERROR_SUCCESS;
Cleanup:

View file

@ -317,8 +317,6 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
for (i = 0; i < 3; i++)
*pcbNeeded += (wcslen(wszPrintProviderInfo[i]) + 1) * sizeof(WCHAR);
*pcReturned = 1;
// Check if the supplied buffer is large enough.
if (cbBuf < *pcbNeeded)
{
@ -329,12 +327,15 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
// Copy over the print processor information.
((PPRINTER_INFO_1W)pPrinterEnum)->Flags = 0;
PackStrings(wszPrintProviderInfo, pPrinterEnum, dwOffsets, &pPrinterEnum[*pcbNeeded]);
*pcReturned = 1;
dwErrorCode = ERROR_SUCCESS;
goto Cleanup;
}
}
// Count the required buffer size and the number of printers.
i = 0;
for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
{
pPrinter = (PLOCAL_PRINTER)pNode->Element;
@ -347,7 +348,7 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
cbDescription = cchComputerName * sizeof(WCHAR) + cbName + cbComment + sizeof(WCHAR);
*pcbNeeded += sizeof(PRINTER_INFO_1W) + cchComputerName * sizeof(WCHAR) + cbName + cbComment + cbDescription;
(*pcReturned)++;
i++;
}
// Check if the supplied buffer is large enough.
@ -360,7 +361,7 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
// Put the strings right after the last PRINTER_INFO_1W structure.
// Due to all the required string processing, we can't just use PackStrings here :(
pPrinterInfo = pPrinterEnum;
pPrinterString = pPrinterEnum + *pcReturned * sizeof(PRINTER_INFO_1W);
pPrinterString = pPrinterEnum + i * sizeof(PRINTER_INFO_1W);
// Copy over the printer information.
for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
@ -402,6 +403,7 @@ _LocalEnumPrintersLevel1(DWORD Flags, LPWSTR Name, LPBYTE pPrinterEnum, DWORD cb
pPrinterInfo += sizeof(PRINTER_INFO_1W);
}
*pcReturned = i;
dwErrorCode = ERROR_SUCCESS;
Cleanup:

View file

@ -438,6 +438,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
DWORD cchMaxSubKey;
DWORD cchPrintProcessor;
DWORD dwErrorCode;
DWORD dwPrintProcessorCount;
DWORD i;
HKEY hKey = NULL;
HKEY hSubKey = NULL;
@ -475,7 +476,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
}
// Get the number of Print Processors and maximum sub key length.
dwErrorCode = (DWORD)RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, pcReturned, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL);
dwErrorCode = (DWORD)RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, &dwPrintProcessorCount, &cchMaxSubKey, NULL, NULL, NULL, NULL, NULL, NULL);
if (dwErrorCode != ERROR_SUCCESS)
{
ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode);
@ -494,7 +495,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
// Determine the required size of the output buffer.
*pcbNeeded = 0;
for (i = 0; i < *pcReturned; i++)
for (i = 0; i < dwPrintProcessorCount; i++)
{
// 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.
@ -518,10 +519,10 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
// Put the Print Processor strings right after the last PRINTPROCESSOR_INFO_1W structure.
pCurrentOutputPrintProcessorInfo = pPrintProcessorInfo;
pCurrentOutputPrintProcessor = pPrintProcessorInfo + *pcReturned * sizeof(PRINTPROCESSOR_INFO_1W);
pCurrentOutputPrintProcessor = pPrintProcessorInfo + dwPrintProcessorCount * sizeof(PRINTPROCESSOR_INFO_1W);
// Copy over all Print Processors.
for (i = 0; i < *pcReturned; i++)
for (i = 0; i < dwPrintProcessorCount; i++)
{
// This isn't really correct, but doesn't cause any harm, because we've extensively checked the size of the supplied buffer above.
cchPrintProcessor = cchMaxSubKey + 1;
@ -544,6 +545,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
}
// We've finished successfully!
*pcReturned = dwPrintProcessorCount;
dwErrorCode = ERROR_SUCCESS;
Cleanup: