[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) EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
{ {
DWORD cbDatatype; DWORD cbDatatype;
DWORD dwDatatypeCount = 0;
DWORD dwErrorCode; DWORD dwErrorCode;
DWORD dwOffsets[_countof(_pwszDatatypes)]; DWORD dwOffsets[_countof(_pwszDatatypes)];
PCWSTR* pCurrentDatatype; PCWSTR* pCurrentDatatype;
@ -129,9 +130,9 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
*pcbNeeded += sizeof(DATATYPES_INFO_1W) + cbDatatype; *pcbNeeded += sizeof(DATATYPES_INFO_1W) + cbDatatype;
// Also calculate the offset in the output buffer of the pointer to this datatype string. // 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++; pCurrentOffset++;
} }
@ -153,6 +154,7 @@ EnumPrintProcessorDatatypesW(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD Lev
*pCurrentOffset = MAXDWORD; *pCurrentOffset = MAXDWORD;
PackStrings(_pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]); PackStrings(_pwszDatatypes, pDatatypes, dwOffsets, &pDatatypes[*pcbNeeded]);
*pcReturned = dwDatatypeCount;
dwErrorCode = ERROR_SUCCESS; dwErrorCode = ERROR_SUCCESS;
Cleanup: 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) LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
{ {
DWORD dwErrorCode; DWORD dwErrorCode;
DWORD i;
PBYTE pEnd = &pStart[cbBuf]; PBYTE pEnd = &pStart[cbBuf];
PLOCAL_HANDLE pHandle; PLOCAL_HANDLE pHandle;
PLOCAL_JOB pJob; PLOCAL_JOB pJob;
@ -930,9 +931,10 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
pFirstJobNode = LookupNodeByIndexSkiplist(&pPrinterHandle->pPrinter->JobList, FirstJob); pFirstJobNode = LookupNodeByIndexSkiplist(&pPrinterHandle->pPrinter->JobList, FirstJob);
// Count the required buffer size and the number of jobs. // Count the required buffer size and the number of jobs.
i = 0;
pNode = pFirstJobNode; pNode = pFirstJobNode;
while (*pcReturned < NoJobs && pNode) while (i < NoJobs && pNode)
{ {
pJob = (PLOCAL_JOB)pNode->Element; 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); _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. // 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]; 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. // Begin counting again and also empty the given buffer.
*pcbNeeded = 0; *pcbNeeded = 0;
*pcReturned = 0;
ZeroMemory(pStart, cbBuf); ZeroMemory(pStart, cbBuf);
// Now call the same functions again to copy the actual data for each job into the buffer. // Now call the same functions again to copy the actual data for each job into the buffer.
i = 0;
pNode = pFirstJobNode; pNode = pFirstJobNode;
while (*pcReturned < NoJobs && pNode) while (i < NoJobs && pNode)
{ {
pJob = (PLOCAL_JOB)pNode->Element; pJob = (PLOCAL_JOB)pNode->Element;
@ -976,10 +978,11 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
goto Cleanup; 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. // 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]; pNode = pNode->Next[0];
} }
*pcReturned = i;
dwErrorCode = ERROR_SUCCESS; dwErrorCode = ERROR_SUCCESS;
Cleanup: Cleanup:

View file

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

View file

@ -438,6 +438,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
DWORD cchMaxSubKey; DWORD cchMaxSubKey;
DWORD cchPrintProcessor; DWORD cchPrintProcessor;
DWORD dwErrorCode; DWORD dwErrorCode;
DWORD dwPrintProcessorCount;
DWORD i; DWORD i;
HKEY hKey = NULL; HKEY hKey = NULL;
HKEY hSubKey = 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. // 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) if (dwErrorCode != ERROR_SUCCESS)
{ {
ERR("RegQueryInfoKeyW failed with status %lu!\n", dwErrorCode); 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. // Determine the required size of the output buffer.
*pcbNeeded = 0; *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. // 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.
@ -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. // Put the Print Processor strings right after the last PRINTPROCESSOR_INFO_1W structure.
pCurrentOutputPrintProcessorInfo = pPrintProcessorInfo; pCurrentOutputPrintProcessorInfo = pPrintProcessorInfo;
pCurrentOutputPrintProcessor = pPrintProcessorInfo + *pcReturned * sizeof(PRINTPROCESSOR_INFO_1W); pCurrentOutputPrintProcessor = pPrintProcessorInfo + dwPrintProcessorCount * sizeof(PRINTPROCESSOR_INFO_1W);
// Copy over all Print Processors. // 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. // 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; cchPrintProcessor = cchMaxSubKey + 1;
@ -544,6 +545,7 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
} }
// We've finished successfully! // We've finished successfully!
*pcReturned = dwPrintProcessorCount;
dwErrorCode = ERROR_SUCCESS; dwErrorCode = ERROR_SUCCESS;
Cleanup: Cleanup: