+static DWORD
+_LocalSetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PJOB_INFO_1W pJobInfo)
+{
+ DWORD dwErrorCode;
+
+ // First check the validity of the input before changing anything.
+ if (!FindDatatype(pJob->pPrintProcessor, pJobInfo->pDatatype))
+ {
+ dwErrorCode = ERROR_INVALID_DATATYPE;
+ goto Cleanup;
+ }
+
+ // Check if the datatype has changed.
+ if (wcscmp(pJob->pwszDatatype, pJobInfo->pDatatype) != 0)
+ {
+ // Use the new value.
+ if (!ReallocSplStr(&pJob->pwszDatatype, pJobInfo->pDatatype))
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+ }
+
+ // Check if the document name has changed.
+ if (wcscmp(pJob->pwszDocumentName, pJobInfo->pDocument) != 0)
+ {
+ // Use the new value.
+ if (!ReallocSplStr(&pJob->pwszDocumentName, pJobInfo->pDocument))
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+ }
+
+ // Check if the status message has changed.
+ if ((!pJob->pwszStatus && pJobInfo->pStatus) || wcscmp(pJob->pwszStatus, pJobInfo->pStatus) != 0)
+ {
+ // Use the new value.
+ if (!ReallocSplStr(&pJob->pwszStatus, pJobInfo->pStatus))
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+ }
+
+ // Check if the user name has changed.
+ if (wcscmp(pJob->pwszUserName, pJobInfo->pUserName) != 0)
+ {
+ // The new user name doesn't need to exist, so no additional verification is required.
+
+ // Use the new value.
+ if (!ReallocSplStr(&pJob->pwszUserName, pJobInfo->pUserName))
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+ }
+
+ // Check if the priority has changed.
+ if (pJob->dwPriority != pJobInfo->Priority && IS_VALID_PRIORITY(pJobInfo->Priority))
+ {
+ // Set the new priority.
+ pJob->dwPriority = pJobInfo->Priority;
+
+ // Remove and reinsert the job in the Printer's Job List.
+ // The Compare function will be used to find the right position now considering the new priority.
+ DeleteElementSkiplist(&pJob->pPrinter->JobList, pJob);
+ InsertElementSkiplist(&pJob->pPrinter->JobList, pJob);
+ }
+
+ // Check if the status flags have changed.
+ if (pJob->dwStatus != pJobInfo->Status)
+ {
+ // Only add status flags that make sense.
+ if (pJobInfo->Status & JOB_STATUS_PAUSED)
+ pJob->dwStatus |= JOB_STATUS_PAUSED;
+
+ if (pJobInfo->Status & JOB_STATUS_ERROR)
+ pJob->dwStatus |= JOB_STATUS_ERROR;
+
+ if (pJobInfo->Status & JOB_STATUS_OFFLINE)
+ pJob->dwStatus |= JOB_STATUS_OFFLINE;
+
+ if (pJobInfo->Status & JOB_STATUS_PAPEROUT)
+ pJob->dwStatus |= JOB_STATUS_PAPEROUT;
+ }
+
+ dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+ return dwErrorCode;
+}
+
+static DWORD
+_LocalSetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PJOB_INFO_2W pJobInfo)
+{
+ DWORD dwErrorCode;
+ PLOCAL_PRINT_PROCESSOR pPrintProcessor;
+
+ // First check the validity of the input before changing anything.
+ pPrintProcessor = FindPrintProcessor(pJobInfo->pPrintProcessor);
+ if (!pPrintProcessor)
+ {
+ dwErrorCode = ERROR_UNKNOWN_PRINTPROCESSOR;
+ goto Cleanup;
+ }
+
+ if (!FindDatatype(pPrintProcessor, pJobInfo->pDatatype))
+ {
+ dwErrorCode = ERROR_INVALID_DATATYPE;
+ goto Cleanup;
+ }
+
+ // Check if the datatype has changed.
+ if (wcscmp(pJob->pwszDatatype, pJobInfo->pDatatype) != 0)
+ {
+ // Use the new value.
+ if (!ReallocSplStr(&pJob->pwszDatatype, pJobInfo->pDatatype))
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+ }
+
+ // Check if the document name has changed.
+ if (wcscmp(pJob->pwszDocumentName, pJobInfo->pDocument) != 0)
+ {
+ // Use the new value.
+ if (!ReallocSplStr(&pJob->pwszDocumentName, pJobInfo->pDocument))
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+ }
+
+ // Check if the notify name has changed.
+ if (wcscmp(pJob->pwszNotifyName, pJobInfo->pNotifyName) != 0)
+ {
+ // The new notify name doesn't need to exist, so no additional verification is required.
+
+ // Use the new value.
+ if (!ReallocSplStr(&pJob->pwszNotifyName, pJobInfo->pNotifyName))
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+ }
+
+ // Check if the (optional) Print Processor Parameters have changed.
+ if ((!pJob->pwszPrintProcessorParameters && pJobInfo->pParameters) || wcscmp(pJob->pwszPrintProcessorParameters, pJobInfo->pParameters) != 0)
+ {
+ // Use the new value.
+ if (!ReallocSplStr(&pJob->pwszPrintProcessorParameters, pJobInfo->pParameters))
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+ }
+
+ // Check if the (optional) Status Message has changed.
+ if ((!pJob->pwszStatus && pJobInfo->pStatus) || wcscmp(pJob->pwszStatus, pJobInfo->pStatus) != 0)
+ {
+ // Use the new value.
+ if (!ReallocSplStr(&pJob->pwszStatus, pJobInfo->pStatus))
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+ }
+
+ // Check if the user name has changed.
+ if (wcscmp(pJob->pwszUserName, pJobInfo->pUserName) != 0)
+ {
+ // The new user name doesn't need to exist, so no additional verification is required.
+
+ // Use the new value.
+ if (!ReallocSplStr(&pJob->pwszUserName, pJobInfo->pUserName))
+ {
+ dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+ ERR("ReallocSplStr failed, last error is %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+ }
+
+ // Check if the priority has changed.
+ if (pJob->dwPriority != pJobInfo->Priority && IS_VALID_PRIORITY(pJobInfo->Priority))
+ {
+ // Set the new priority.
+ pJob->dwPriority = pJobInfo->Priority;
+
+ // Remove and reinsert the job in the Printer's Job List.
+ // The Compare function will be used to find the right position now considering the new priority.
+ DeleteElementSkiplist(&pJob->pPrinter->JobList, pJob);
+ InsertElementSkiplist(&pJob->pPrinter->JobList, pJob);
+ }
+
+ // Check if the status flags have changed.
+ if (pJob->dwStatus != pJobInfo->Status)
+ {
+ // Only add status flags that make sense.
+ if (pJobInfo->Status & JOB_STATUS_PAUSED)
+ pJob->dwStatus |= JOB_STATUS_PAUSED;
+
+ if (pJobInfo->Status & JOB_STATUS_ERROR)
+ pJob->dwStatus |= JOB_STATUS_ERROR;
+
+ if (pJobInfo->Status & JOB_STATUS_OFFLINE)
+ pJob->dwStatus |= JOB_STATUS_OFFLINE;
+
+ if (pJobInfo->Status & JOB_STATUS_PAPEROUT)
+ pJob->dwStatus |= JOB_STATUS_PAPEROUT;
+ }
+
+ dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+ return dwErrorCode;
+}
+
+BOOL WINAPI
+LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command)
+{
+ DWORD dwErrorCode;
+ PLOCAL_HANDLE pHandle;
+ PLOCAL_JOB pJob;
+ 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;
+
+ // Get the desired job.
+ pJob = LookupElementSkiplist(&GlobalJobList, &JobId, NULL);
+ if (!pJob || pJob->pPrinter != pPrinterHandle->pPrinter)
+ {
+ dwErrorCode = ERROR_INVALID_PARAMETER;
+ goto Cleanup;
+ }
+
+ // Setting job information is handled differently for each level.
+ if (Level)
+ {
+ if (Level == 1)
+ dwErrorCode = _LocalSetJobLevel1(pPrinterHandle, pJob, (PJOB_INFO_1W)pJobInfo);
+ else if (Level == 2)
+ dwErrorCode = _LocalSetJobLevel2(pPrinterHandle, pJob, (PJOB_INFO_2W)pJobInfo);
+ else
+ dwErrorCode = ERROR_INVALID_LEVEL;
+ }
+
+ if (dwErrorCode != ERROR_SUCCESS)
+ goto Cleanup;
+
+ // Perform an additional command if desired.
+ if (Command)
+ {
+ // TODO
+ }
+
+ dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+ SetLastError(dwErrorCode);
+ return (dwErrorCode == ERROR_SUCCESS);
+}
+