Author: cfinck
Date: Thu Jun 25 15:27:38 2015
New Revision: 68264
URL:
http://svn.reactos.org/svn/reactos?rev=68264&view=rev
Log:
[LOCALSPL]
Implement LocalEnumJobs the easy way by using the new Skiplist function
LookupNodeByIndexSkiplist and calling _LocalGetJobLevelX for each job.
This required changes in _LocalGetJobLevelX, so that the strings are now copied in reverse
to the end of the buffer while the structure is copied to the start. By preserving the
pointers after each call, the function can be called multiple times.
Modified:
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/jobs.c
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/main.c
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/precomp.h
Modified:
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/jobs.c
URL:
http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/rea…
==============================================================================
---
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/jobs.c [iso-8859-1]
(original)
+++
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/jobs.c [iso-8859-1]
Thu Jun 25 15:27:38 2015
@@ -359,7 +359,7 @@
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* ppStart,
PBYTE* ppEnd, DWORD cbBuf, PDWORD pcbNeeded)
{
DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
DWORD cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
@@ -369,58 +369,57 @@
DWORD cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
DWORD dwErrorCode;
JOB_INFO_1W JobInfo1 = { 0 };
- PBYTE pString;
// A Status Message is optional.
if (pJob->pwszStatus)
cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
// Check if the supplied buffer is large enough.
- *pcbNeeded = sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName +
cbPrinterName + cbStatus + cbUserName;
+ *pcbNeeded += sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName +
cbPrinterName + cbStatus + cbUserName;
if (cbBuf < *pcbNeeded)
{
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
- // Put the strings right after the JOB_INFO_1W structure.
- pString = pOutput + sizeof(JOB_INFO_1W);
-
- JobInfo1.pDatatype = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszDatatype, cbDatatype);
- pString += cbDatatype;
-
- JobInfo1.pDocument = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszDocumentName, cbDocumentName);
- pString += cbDocumentName;
-
- JobInfo1.pMachineName = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszMachineName, cbMachineName);
- pString += cbMachineName;
-
- JobInfo1.pPrinterName = (PWSTR)pString;
- CopyMemory(pString, pJob->pPrinter->pwszPrinterName, cbPrinterName);
- pString += cbPrinterName;
+ // Put the strings at the end of the buffer.
+ *ppEnd -= cbDatatype;
+ JobInfo1.pDatatype = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszDatatype, cbDatatype);
+
+ *ppEnd -= cbDocumentName;
+ JobInfo1.pDocument = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszDocumentName, cbDocumentName);
+
+ *ppEnd -= cbMachineName;
+ JobInfo1.pMachineName = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszMachineName, cbMachineName);
+
+ *ppEnd -= cbPrinterName;
+ JobInfo1.pPrinterName = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterName, cbPrinterName);
if (cbStatus)
{
- JobInfo1.pStatus = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszStatus, cbStatus);
- pString += cbStatus;
- }
-
- JobInfo1.pUserName = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszUserName, cbUserName);
- pString += cbUserName;
-
- // Fill the structure and copy it as well.
+ *ppEnd -= cbStatus;
+ JobInfo1.pStatus = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszStatus, cbStatus);
+ }
+
+ *ppEnd -= cbUserName;
+ JobInfo1.pUserName = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszUserName, cbUserName);
+
+ // Fill the rest of the structure.
JobInfo1.JobId = pJob->dwJobID;
JobInfo1.Priority = pJob->dwPriority;
JobInfo1.Status = pJob->dwStatus;
JobInfo1.TotalPages = pJob->dwTotalPages;
CopyMemory(&JobInfo1.Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
- CopyMemory(pOutput, &JobInfo1, sizeof(JOB_INFO_1W));
-
+
+ // Finally copy the structure to the output pointer.
+ CopyMemory(*ppStart, &JobInfo1, sizeof(JOB_INFO_1W));
+ *ppStart += sizeof(JOB_INFO_1W);
dwErrorCode = ERROR_SUCCESS;
Cleanup:
@@ -428,7 +427,7 @@
}
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* ppStart,
PBYTE* ppEnd, DWORD cbBuf, PDWORD pcbNeeded)
{
DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
DWORD cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
@@ -444,7 +443,6 @@
FILETIME ftNow;
FILETIME ftSubmitted;
JOB_INFO_2W JobInfo2 = { 0 };
- PBYTE pString;
ULARGE_INTEGER uliNow;
ULARGE_INTEGER uliSubmitted;
@@ -456,65 +454,63 @@
cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
// Check if the supplied buffer is large enough.
- *pcbNeeded = sizeof(JOB_INFO_2W) + cbDatatype + sizeof(DEVMODEW) + cbDocumentName +
cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor +
cbPrintProcessorParameters + cbStatus + cbUserName;
+ *pcbNeeded += sizeof(JOB_INFO_2W) + cbDatatype + sizeof(DEVMODEW) + cbDocumentName +
cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor +
cbPrintProcessorParameters + cbStatus + cbUserName;
if (cbBuf < *pcbNeeded)
{
dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
goto Cleanup;
}
- // Put the strings right after the JOB_INFO_2W structure.
- pString = pOutput + sizeof(JOB_INFO_2W);
-
- JobInfo2.pDatatype = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszDatatype, cbDatatype);
- pString += cbDatatype;
-
- JobInfo2.pDevMode = (PDEVMODEW)pString;
- CopyMemory(pString, &pJob->DevMode, sizeof(DEVMODEW));
- pString += sizeof(DEVMODEW);
-
- JobInfo2.pDocument = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszDocumentName, cbDocumentName);
- pString += cbDocumentName;
-
- JobInfo2.pDriverName = (PWSTR)pString;
- CopyMemory(pString, pJob->pPrinter->pwszPrinterDriver, cbDriverName);
- pString += cbDriverName;
-
- JobInfo2.pMachineName = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszMachineName, cbMachineName);
- pString += cbMachineName;
-
- JobInfo2.pNotifyName = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszNotifyName, cbNotifyName);
- pString += cbNotifyName;
-
- JobInfo2.pPrinterName = (PWSTR)pString;
- CopyMemory(pString, pJob->pPrinter->pwszPrinterName, cbPrinterName);
- pString += cbPrinterName;
-
- JobInfo2.pPrintProcessor = (PWSTR)pString;
- CopyMemory(pString, pJob->pPrintProcessor->pwszName, cbPrintProcessor);
- pString += cbPrintProcessor;
+ // Put the strings at the end of the buffer.
+ *ppEnd -= cbDatatype;
+ JobInfo2.pDatatype = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszDatatype, cbDatatype);
+
+ *ppEnd -= sizeof(DEVMODEW);
+ JobInfo2.pDevMode = (PDEVMODEW)*ppEnd;
+ CopyMemory(*ppEnd, &pJob->DevMode, sizeof(DEVMODEW));
+
+ *ppEnd -= cbDocumentName;
+ JobInfo2.pDocument = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszDocumentName, cbDocumentName);
+
+ *ppEnd -= cbDriverName;
+ JobInfo2.pDriverName = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterDriver, cbDriverName);
+
+ *ppEnd -= cbMachineName;
+ JobInfo2.pMachineName = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszMachineName, cbMachineName);
+
+ *ppEnd -= cbNotifyName;
+ JobInfo2.pNotifyName = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszNotifyName, cbNotifyName);
+
+ *ppEnd -= cbPrinterName;
+ JobInfo2.pPrinterName = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterName, cbPrinterName);
+
+ *ppEnd -= cbPrintProcessor;
+ JobInfo2.pPrintProcessor = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pPrintProcessor->pwszName, cbPrintProcessor);
if (cbPrintProcessorParameters)
{
- JobInfo2.pParameters = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszPrintProcessorParameters,
cbPrintProcessorParameters);
- pString += cbPrintProcessorParameters;
+ *ppEnd -= cbPrintProcessorParameters;
+ JobInfo2.pParameters = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszPrintProcessorParameters,
cbPrintProcessorParameters);
}
if (cbStatus)
{
- JobInfo2.pStatus = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszStatus, cbStatus);
- pString += cbStatus;
- }
-
- JobInfo2.pUserName = (PWSTR)pString;
- CopyMemory(pString, pJob->pwszUserName, cbUserName);
- pString += cbUserName;
+ *ppEnd -= cbStatus;
+ JobInfo2.pStatus = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszStatus, cbStatus);
+ }
+
+ *ppEnd -= cbUserName;
+ JobInfo2.pUserName = (PWSTR)*ppEnd;
+ CopyMemory(*ppEnd, pJob->pwszUserName, cbUserName);
// Time in JOB_INFO_2W is the number of milliseconds elapsed since the job was
submitted. Calculate this time.
if (!SystemTimeToFileTime(&pJob->stSubmitted, &ftSubmitted))
@@ -553,7 +549,8 @@
CopyMemory(&JobInfo2.Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
// Finally copy the structure to the output pointer.
- CopyMemory(pOutput, &JobInfo2, sizeof(JOB_INFO_2W));
+ CopyMemory(*ppStart, &JobInfo2, sizeof(JOB_INFO_2W));
+ *ppStart += sizeof(JOB_INFO_2W);
dwErrorCode = ERROR_SUCCESS;
Cleanup:
@@ -561,9 +558,10 @@
}
BOOL WINAPI
-LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pOutput, DWORD cbBuf,
LPDWORD pcbNeeded)
+LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf, LPDWORD
pcbNeeded)
{
DWORD dwErrorCode;
+ PBYTE pEnd = &pStart[cbBuf];
PLOCAL_HANDLE pHandle;
PLOCAL_JOB pJob;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
@@ -586,11 +584,14 @@
goto Cleanup;
}
+ // Begin counting.
+ *pcbNeeded = 0;
+
// The function behaves differently for each level.
if (Level == 1)
- dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, pOutput, cbBuf,
pcbNeeded);
+ dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, &pStart, &pEnd,
cbBuf, pcbNeeded);
else if (Level == 2)
- dwErrorCode = _LocalGetJobLevel2(pPrinterHandle, pJob, pOutput, cbBuf,
pcbNeeded);
+ dwErrorCode = _LocalGetJobLevel2(pPrinterHandle, pJob, &pStart, &pEnd,
cbBuf, pcbNeeded);
else
dwErrorCode = ERROR_INVALID_LEVEL;
@@ -871,6 +872,99 @@
if (Command)
{
// TODO
+ }
+
+ dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
+}
+
+BOOL WINAPI
+LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE pStart,
DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned)
+{
+ DWORD dwErrorCode;
+ PBYTE pEnd = &pStart[cbBuf];
+ PLOCAL_HANDLE pHandle;
+ PLOCAL_JOB pJob;
+ PSKIPLIST_NODE pFirstJobNode;
+ PSKIPLIST_NODE pNode;
+ PLOCAL_PRINTER_HANDLE pPrinterHandle;
+
+ // 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->pSpecificHandle;
+
+ // Check the level.
+ if (Level > 2)
+ {
+ dwErrorCode = ERROR_INVALID_LEVEL;
+ goto Cleanup;
+ }
+
+ // Begin counting.
+ *pcbNeeded = 0;
+ *pcReturned = 0;
+
+ // Lookup the node of the first job requested by the caller in the Printer's Job
List.
+ pFirstJobNode =
LookupNodeByIndexSkiplist(&pPrinterHandle->pPrinter->JobList, FirstJob);
+
+ // Count the required buffer size and the number of jobs.
+ pNode = pFirstJobNode;
+
+ while (*pcReturned < NoJobs && pNode)
+ {
+ pJob = (PLOCAL_JOB)pNode->Element;
+
+ // The function behaves differently for each level.
+ if (Level == 1)
+ _LocalGetJobLevel1(pPrinterHandle, pJob, NULL, NULL, 0, pcbNeeded);
+ else if (Level == 2)
+ _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++;
+ pNode = pNode->Next[0];
+ }
+
+ // Check if the supplied buffer is large enough.
+ if (cbBuf < *pcbNeeded)
+ {
+ dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
+ goto Cleanup;
+ }
+
+ // 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.
+ pNode = pFirstJobNode;
+
+ while (*pcReturned < NoJobs && pNode)
+ {
+ pJob = (PLOCAL_JOB)pNode->Element;
+
+ // The function behaves differently for each level.
+ if (Level == 1)
+ dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, &pStart,
&pEnd, cbBuf, pcbNeeded);
+ else if (Level == 2)
+ dwErrorCode = _LocalGetJobLevel2(pPrinterHandle, pJob, &pStart,
&pEnd, cbBuf, pcbNeeded);
+
+ if (dwErrorCode != ERROR_SUCCESS)
+ 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++;
+ pNode = pNode->Next[0];
}
dwErrorCode = ERROR_SUCCESS;
Modified:
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/main.c
URL:
http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/rea…
==============================================================================
---
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/main.c [iso-8859-1]
(original)
+++
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/main.c [iso-8859-1]
Thu Jun 25 15:27:38 2015
@@ -36,7 +36,7 @@
LocalOpenPrinter, // fpOpenPrinter
LocalSetJob, // fpSetJob
LocalGetJob, // fpGetJob
- NULL, // fpEnumJobs
+ LocalEnumJobs, // fpEnumJobs
NULL, // fpAddPrinter
NULL, // fpDeletePrinter
NULL, // fpSetPrinter
Modified:
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/precomp.h
URL:
http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/rea…
==============================================================================
---
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/precomp.h [iso-8859-1]
(original)
+++
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/precomp.h [iso-8859-1]
Thu Jun 25 15:27:38 2015
@@ -187,7 +187,8 @@
void InitializeGlobalJobList();
void InitializePrinterJobList(PLOCAL_PRINTER pPrinter);
BOOL WINAPI LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD
pcbNeeded);
-BOOL WINAPI LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pOutput, DWORD
cbBuf, LPDWORD pcbNeeded);
+BOOL WINAPI LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level,
PBYTE pStart, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
+BOOL WINAPI LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD
cbBuf, LPDWORD pcbNeeded);
BOOL WINAPI LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD
Command);
PLOCAL_JOB ReadJobShadowFile(PCWSTR pwszFilePath);
BOOL WriteJobShadowFile(PCWSTR pwszFilePath, const PLOCAL_JOB pJob);