[LOCALSPL]
authorColin Finck <colin@reactos.org>
Thu, 25 Jun 2015 12:29:18 +0000 (12:29 +0000)
committerColin Finck <colin@reactos.org>
Thu, 25 Jun 2015 12:29:18 +0000 (12:29 +0000)
- Implement LocalSetJob for Level 1 and 2.
- Add pPrintProcessor, pwszPrintProcessorParameters and pwszStatus members to the LOCAL_JOB structure and use them in LocalAddJob, LocalGetJob and LocalSetJob.
- Fix naming of some LOCAL_JOB members.

svn path=/branches/colins-printing-for-freedom/; revision=68259

reactos/win32ss/printing/providers/localspl/jobs.c
reactos/win32ss/printing/providers/localspl/main.c
reactos/win32ss/printing/providers/localspl/precomp.h
reactos/win32ss/printing/providers/localspl/printers.c

index aa81e3a..81806b4 100644 (file)
@@ -164,7 +164,7 @@ InitializeGlobalJobList()
         }
 
         // Add it to the Printer's Job List.
         }
 
         // Add it to the Printer's Job List.
-        if (!InsertElementSkiplist(&pJob->Printer->JobList, pJob))
+        if (!InsertElementSkiplist(&pJob->pPrinter->JobList, pJob))
         {
             ERR("InsertElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
             goto Cleanup;
         {
             ERR("InsertElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
             goto Cleanup;
@@ -215,10 +215,10 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
         goto Cleanup;
     }
 
         goto Cleanup;
     }
 
-    pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
+    pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
 
     // This handle must not have started a job yet!
 
     // This handle must not have started a job yet!
-    if (pPrinterHandle->StartedJob)
+    if (pPrinterHandle->pStartedJob)
     {
         dwErrorCode = ERROR_INVALID_HANDLE;
         goto Cleanup;
     {
         dwErrorCode = ERROR_INVALID_HANDLE;
         goto Cleanup;
@@ -233,7 +233,7 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
 
     // Check if the printer is set to do direct printing.
     // The Job List isn't used in this case.
 
     // 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)
+    if (pPrinterHandle->pPrinter->dwAttributes & PRINTER_ATTRIBUTE_DIRECT)
     {
         dwErrorCode = ERROR_INVALID_ACCESS;
         goto Cleanup;
     {
         dwErrorCode = ERROR_INVALID_ACCESS;
         goto Cleanup;
@@ -264,7 +264,8 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
     }
 
     // Copy over defaults to the LOCAL_JOB structure.
     }
 
     // Copy over defaults to the LOCAL_JOB structure.
-    pJob->Printer = pPrinterHandle->Printer;
+    pJob->pPrinter = pPrinterHandle->pPrinter;
+    pJob->pPrintProcessor = pPrinterHandle->pPrinter->pPrintProcessor;
     pJob->dwPriority = DEF_PRIORITY;
     pJob->pwszDatatype = AllocSplStr(pPrinterHandle->pwszDatatype);
     pJob->pwszDocumentName = AllocSplStr(wszDefaultDocumentName);
     pJob->dwPriority = DEF_PRIORITY;
     pJob->pwszDatatype = AllocSplStr(pPrinterHandle->pwszDatatype);
     pJob->pwszDocumentName = AllocSplStr(wszDefaultDocumentName);
@@ -321,7 +322,7 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
 
     // 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.
 
     // 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))
+    if (!InsertTailElementSkiplist(&pJob->pPrinter->JobList, pJob))
     {
         dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
         ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
     {
         dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
         ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
@@ -363,14 +364,19 @@ _LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
     DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
     DWORD cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
     DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
     DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
     DWORD cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
     DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
-    DWORD cbPrinterName = (wcslen(pJob->Printer->pwszPrinterName) + 1) * sizeof(WCHAR);
+    DWORD cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
+    DWORD cbStatus = 0;
     DWORD cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
     DWORD dwErrorCode;
     JOB_INFO_1W JobInfo1 = { 0 };
     PBYTE pString;
 
     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.
     // Check if the supplied buffer is large enough.
-    *pcbNeeded = sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName + cbPrinterName + cbUserName;
+    *pcbNeeded = sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName + cbPrinterName + cbStatus + cbUserName;
     if (cbBuf < *pcbNeeded)
     {
         dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
     if (cbBuf < *pcbNeeded)
     {
         dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
@@ -393,9 +399,16 @@ _LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
     pString += cbMachineName;
 
     JobInfo1.pPrinterName = (PWSTR)pString;
     pString += cbMachineName;
 
     JobInfo1.pPrinterName = (PWSTR)pString;
-    CopyMemory(pString, pJob->Printer->pwszPrinterName, cbPrinterName);
+    CopyMemory(pString, pJob->pPrinter->pwszPrinterName, cbPrinterName);
     pString += cbPrinterName;
 
     pString += 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;
     JobInfo1.pUserName = (PWSTR)pString;
     CopyMemory(pString, pJob->pwszUserName, cbUserName);
     pString += cbUserName;
@@ -419,11 +432,13 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
 {
     DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
     DWORD cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
 {
     DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
     DWORD cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
-    DWORD cbDriverName = (wcslen(pJob->Printer->pwszPrinterDriver) + 1) * sizeof(WCHAR);
+    DWORD cbDriverName = (wcslen(pJob->pPrinter->pwszPrinterDriver) + 1) * sizeof(WCHAR);
     DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
     DWORD cbNotifyName = (wcslen(pJob->pwszNotifyName) + 1) * sizeof(WCHAR);
     DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
     DWORD cbNotifyName = (wcslen(pJob->pwszNotifyName) + 1) * sizeof(WCHAR);
-    DWORD cbPrinterName = (wcslen(pJob->Printer->pwszPrinterName) + 1) * sizeof(WCHAR);
-    DWORD cbPrintProcessor = (wcslen(pJob->Printer->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
+    DWORD cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
+    DWORD cbPrintProcessor = (wcslen(pJob->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
+    DWORD cbPrintProcessorParameters = 0;
+    DWORD cbStatus = 0;
     DWORD cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
     DWORD dwErrorCode;
     FILETIME ftNow;
     DWORD cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
     DWORD dwErrorCode;
     FILETIME ftNow;
@@ -433,8 +448,15 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
     ULARGE_INTEGER uliNow;
     ULARGE_INTEGER uliSubmitted;
 
     ULARGE_INTEGER uliNow;
     ULARGE_INTEGER uliSubmitted;
 
+    // Print Processor Parameters and Status Message are optional.
+    if (pJob->pwszPrintProcessorParameters)
+        cbPrintProcessorParameters = (wcslen(pJob->pwszPrintProcessorParameters) + 1) * sizeof(WCHAR);
+
+    if (pJob->pwszStatus)
+        cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
+
     // Check if the supplied buffer is large enough.
     // Check if the supplied buffer is large enough.
-    *pcbNeeded = sizeof(JOB_INFO_2W) + cbDatatype + sizeof(DEVMODEW) + cbDocumentName + cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor + 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;
     if (cbBuf < *pcbNeeded)
     {
         dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
@@ -457,7 +479,7 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
     pString += cbDocumentName;
 
     JobInfo2.pDriverName = (PWSTR)pString;
     pString += cbDocumentName;
 
     JobInfo2.pDriverName = (PWSTR)pString;
-    CopyMemory(pString, pJob->Printer->pwszPrinterDriver, cbDriverName);
+    CopyMemory(pString, pJob->pPrinter->pwszPrinterDriver, cbDriverName);
     pString += cbDriverName;
 
     JobInfo2.pMachineName = (PWSTR)pString;
     pString += cbDriverName;
 
     JobInfo2.pMachineName = (PWSTR)pString;
@@ -469,13 +491,27 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
     pString += cbNotifyName;
 
     JobInfo2.pPrinterName = (PWSTR)pString;
     pString += cbNotifyName;
 
     JobInfo2.pPrinterName = (PWSTR)pString;
-    CopyMemory(pString, pJob->Printer->pwszPrinterName, cbPrinterName);
+    CopyMemory(pString, pJob->pPrinter->pwszPrinterName, cbPrinterName);
     pString += cbPrinterName;
 
     JobInfo2.pPrintProcessor = (PWSTR)pString;
     pString += cbPrinterName;
 
     JobInfo2.pPrintProcessor = (PWSTR)pString;
-    CopyMemory(pString, pJob->Printer->pPrintProcessor->pwszName, cbPrintProcessor);
+    CopyMemory(pString, pJob->pPrintProcessor->pwszName, cbPrintProcessor);
     pString += cbPrintProcessor;
 
     pString += cbPrintProcessor;
 
+    if (cbPrintProcessorParameters)
+    {
+        JobInfo2.pParameters = (PWSTR)pString;
+        CopyMemory(pString, pJob->pwszPrintProcessorParameters, cbPrintProcessorParameters);
+        pString += 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;
     JobInfo2.pUserName = (PWSTR)pString;
     CopyMemory(pString, pJob->pwszUserName, cbUserName);
     pString += cbUserName;
@@ -496,7 +532,7 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE
 
     // Position in JOB_INFO_2W is the 1-based index of the job in the processing queue.
     // Retrieve this through the element index of the job in the Printer's Job List.
 
     // Position in JOB_INFO_2W is the 1-based index of the job in the processing queue.
     // Retrieve this through the element index of the job in the Printer's Job List.
-    if (!LookupElementSkiplist(&pJob->Printer->JobList, pJob, &JobInfo2.Position))
+    if (!LookupElementSkiplist(&pJob->pPrinter->JobList, pJob, &JobInfo2.Position))
     {
         dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
         ERR("pJob could not be located in the Printer's Job List!\n");
     {
         dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
         ERR("pJob could not be located in the Printer's Job List!\n");
@@ -525,7 +561,7 @@ Cleanup:
 }
 
 BOOL WINAPI
 }
 
 BOOL WINAPI
-LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pOutput, DWORD cbBuf, LPDWORD pcbNeeded)
+LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pOutput, DWORD cbBuf, LPDWORD pcbNeeded)
 {
     DWORD dwErrorCode;
     PLOCAL_HANDLE pHandle;
 {
     DWORD dwErrorCode;
     PLOCAL_HANDLE pHandle;
@@ -540,11 +576,11 @@ LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pOutput, DWORD cbB
         goto Cleanup;
     }
 
         goto Cleanup;
     }
 
-    pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
+    pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
 
     // Get the desired job.
     pJob = LookupElementSkiplist(&GlobalJobList, &JobId, NULL);
 
     // Get the desired job.
     pJob = LookupElementSkiplist(&GlobalJobList, &JobId, NULL);
-    if (!pJob || pJob->Printer != pPrinterHandle->Printer)
+    if (!pJob || pJob->pPrinter != pPrinterHandle->pPrinter)
     {
         dwErrorCode = ERROR_INVALID_PARAMETER;
         goto Cleanup;
     {
         dwErrorCode = ERROR_INVALID_PARAMETER;
         goto Cleanup;
@@ -563,6 +599,287 @@ Cleanup:
     return (dwErrorCode == ERROR_SUCCESS);
 }
 
     return (dwErrorCode == ERROR_SUCCESS);
 }
 
+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);
+}
+
 PLOCAL_JOB
 ReadJobShadowFile(PCWSTR pwszFilePath)
 {
 PLOCAL_JOB
 ReadJobShadowFile(PCWSTR pwszFilePath)
 {
@@ -626,7 +943,7 @@ ReadJobShadowFile(PCWSTR pwszFilePath)
     pJob->dwJobID = pShadowFile->dwJobID;
     pJob->dwTotalPages = pShadowFile->dwTotalPages;
     pJob->dwPriority = pShadowFile->dwPriority;
     pJob->dwJobID = pShadowFile->dwJobID;
     pJob->dwTotalPages = pShadowFile->dwTotalPages;
     pJob->dwPriority = pShadowFile->dwPriority;
-    pJob->Printer = pPrinter;
+    pJob->pPrinter = pPrinter;
     pJob->pwszDatatype = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDatatype));
     pJob->pwszDocumentName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDocumentName));
     pJob->pwszOutputFile = NULL;
     pJob->pwszDatatype = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDatatype));
     pJob->pwszDocumentName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offDocumentName));
     pJob->pwszOutputFile = NULL;
@@ -667,7 +984,7 @@ WriteJobShadowFile(PCWSTR pwszFilePath, const PLOCAL_JOB pJob)
     }
 
     // Compute the total size of the shadow file.
     }
 
     // Compute the total size of the shadow file.
-    cbPrinterName = (wcslen(pJob->Printer->pwszPrinterName) + 1) * sizeof(WCHAR);
+    cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
     cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
     cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
     cbFileSize = sizeof(SHD_HEADER) + cbPrinterName + cbDatatype + cbDocumentName + sizeof(DEVMODEW);
     cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
     cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
     cbFileSize = sizeof(SHD_HEADER) + cbPrinterName + cbDatatype + cbDocumentName + sizeof(DEVMODEW);
@@ -694,7 +1011,7 @@ WriteJobShadowFile(PCWSTR pwszFilePath, const PLOCAL_JOB pJob)
     // The first value begins right after the shadow file header.
     dwCurrentOffset = sizeof(SHD_HEADER);
 
     // The first value begins right after the shadow file header.
     dwCurrentOffset = sizeof(SHD_HEADER);
 
-    CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->Printer->pwszPrinterName, cbPrinterName);
+    CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pPrinter->pwszPrinterName, cbPrinterName);
     pShadowFile->offPrinterName = dwCurrentOffset;
     dwCurrentOffset += cbPrinterName;
 
     pShadowFile->offPrinterName = dwCurrentOffset;
     dwCurrentOffset += cbPrinterName;
 
index 602029c..0602f79 100644 (file)
@@ -34,7 +34,7 @@ const WCHAR* wszPrintProviderInfo[3] = {
 // Local Constants
 static const PRINTPROVIDOR _PrintProviderFunctions = {
     LocalOpenPrinter,                           // fpOpenPrinter
 // Local Constants
 static const PRINTPROVIDOR _PrintProviderFunctions = {
     LocalOpenPrinter,                           // fpOpenPrinter
-    NULL,                                       // fpSetJob
+    LocalSetJob,                                // fpSetJob
     LocalGetJob,                                // fpGetJob
     NULL,                                       // fpEnumJobs
     NULL,                                       // fpAddPrinter
     LocalGetJob,                                // fpGetJob
     NULL,                                       // fpEnumJobs
     NULL,                                       // fpAddPrinter
index 0d8e726..61f4338 100644 (file)
@@ -32,6 +32,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(localspl);
 
 // Macros
 #define IS_VALID_JOB_ID(ID)     (ID >= 1 && ID <= 99999)
 
 // Macros
 #define IS_VALID_JOB_ID(ID)     (ID >= 1 && ID <= 99999)
+#define IS_VALID_PRIORITY(P)    (P >= MIN_PRIORITY && P <= MAX_PRIORITY)
 
 // Constants
 #define MAX_PRINTER_NAME        220
 
 // Constants
 #define MAX_PRINTER_NAME        220
@@ -91,23 +92,26 @@ LOCAL_PRINTER, *PLOCAL_PRINTER;
 typedef struct _LOCAL_JOB
 {
     // This sort key must be the first element for LookupElementSkiplist to work!
 typedef struct _LOCAL_JOB
 {
     // This sort key must be the first element for LookupElementSkiplist to work!
-    DWORD dwJobID;                      // Internal and external ID of this Job
-
-    PLOCAL_PRINTER Printer;             // Associated Printer to this Job
-    DWORD dwPriority;                   // Priority of this Job from MIN_PRIORITY to MAX_PRIORITY, default being DEF_PRIORITY
-    SYSTEMTIME stSubmitted;             // Time of the submission of this Job
-    PWSTR pwszUserName;                 // User that submitted the Job
-    PWSTR pwszNotifyName;               // User that shall be notified about the status of the Job
-    PWSTR pwszDocumentName;             // Name of the Document that is printed
-    PWSTR pwszDatatype;                 // Datatype of the Document
-    PWSTR pwszOutputFile;               // Output File to spool the Job to
-    DWORD dwTotalPages;                 // Total pages of the Document
-    DWORD dwPagesPrinted;               // Number of pages that have already been printed
-    DWORD dwStartTime;                  // Earliest time in minutes since 12:00 AM UTC when this document can be printed
-    DWORD dwUntilTime;                  // Latest time in minutes since 12:00 AM UTC when this document can be printed
-    DWORD dwStatus;                     // JOB_STATUS_* flags of the Job
-    PWSTR pwszMachineName;              // Name of the machine that submitted the Job (prepended with two backslashes)
-    DEVMODEW DevMode;                   // Associated Device Mode to this Job
+    DWORD dwJobID;                              // Internal and external ID of this Job
+
+    PLOCAL_PRINTER pPrinter;                    // Associated Printer to this Job
+    PLOCAL_PRINT_PROCESSOR pPrintProcessor;     // Associated Print Processor to this Job
+    DWORD dwPriority;                           // Priority of this Job from MIN_PRIORITY to MAX_PRIORITY, default being DEF_PRIORITY
+    SYSTEMTIME stSubmitted;                     // Time of the submission of this Job
+    PWSTR pwszUserName;                         // User that submitted the Job
+    PWSTR pwszNotifyName;                       // User that shall be notified about the status of the Job
+    PWSTR pwszDocumentName;                     // Name of the Document that is printed
+    PWSTR pwszDatatype;                         // Datatype of the Document
+    PWSTR pwszOutputFile;                       // Output File to spool the Job to
+    PWSTR pwszPrintProcessorParameters;         // Optional; Parameters for the chosen Print Processor
+    PWSTR pwszStatus;                           // Optional; a Status Message for the Job
+    DWORD dwTotalPages;                         // Total pages of the Document
+    DWORD dwPagesPrinted;                       // Number of pages that have already been printed
+    DWORD dwStartTime;                          // Earliest time in minutes since 12:00 AM UTC when this document can be printed
+    DWORD dwUntilTime;                          // Latest time in minutes since 12:00 AM UTC when this document can be printed
+    DWORD dwStatus;                             // JOB_STATUS_* flags of the Job
+    PWSTR pwszMachineName;                      // Name of the machine that submitted the Job (prepended with two backslashes)
+    DEVMODEW DevMode;                           // Associated Device Mode to this Job
 }
 LOCAL_JOB, *PLOCAL_JOB;
 
 }
 LOCAL_JOB, *PLOCAL_JOB;
 
@@ -120,8 +124,8 @@ LOCAL_JOB, *PLOCAL_JOB;
  */
 typedef struct _LOCAL_PRINTER_HANDLE
 {
  */
 typedef struct _LOCAL_PRINTER_HANDLE
 {
-    PLOCAL_PRINTER Printer;
-    PLOCAL_JOB StartedJob;
+    PLOCAL_PRINTER pPrinter;
+    PLOCAL_JOB pStartedJob;
     PWSTR pwszDatatype;
     DEVMODEW DevMode;
 }
     PWSTR pwszDatatype;
     DEVMODEW DevMode;
 }
@@ -134,7 +138,7 @@ LOCAL_PRINTER_HANDLE, *PLOCAL_PRINTER_HANDLE;
 typedef struct _LOCAL_HANDLE
 {
     enum { Printer, Monitor, Port } HandleType;
 typedef struct _LOCAL_HANDLE
 {
     enum { Printer, Monitor, Port } HandleType;
-    PVOID SpecificHandle;
+    PVOID pSpecificHandle;
 }
 LOCAL_HANDLE, *PLOCAL_HANDLE;
 
 }
 LOCAL_HANDLE, *PLOCAL_HANDLE;
 
@@ -184,6 +188,7 @@ 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);
 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 LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Command);
 PLOCAL_JOB ReadJobShadowFile(PCWSTR pwszFilePath);
 BOOL WriteJobShadowFile(PCWSTR pwszFilePath, const PLOCAL_JOB pJob);
 
 PLOCAL_JOB ReadJobShadowFile(PCWSTR pwszFilePath);
 BOOL WriteJobShadowFile(PCWSTR pwszFilePath, const PLOCAL_JOB pJob);
 
index b923b24..b3a3880 100644 (file)
@@ -537,7 +537,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
 
         // Create a new printer handle.
         pPrinterHandle = DllAllocSplMem(sizeof(LOCAL_PRINTER_HANDLE));
 
         // Create a new printer handle.
         pPrinterHandle = DllAllocSplMem(sizeof(LOCAL_PRINTER_HANDLE));
-        pPrinterHandle->Printer = pPrinter;
+        pPrinterHandle->pPrinter = pPrinter;
 
         // Check if a datatype was given.
         if (pDefault && pDefault->pDatatype)
 
         // Check if a datatype was given.
         if (pDefault && pDefault->pDatatype)
@@ -600,20 +600,20 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
 
             // Look for this job in the Global Job List.
             pJob = LookupElementSkiplist(&GlobalJobList, &dwJobID, NULL);
 
             // Look for this job in the Global Job List.
             pJob = LookupElementSkiplist(&GlobalJobList, &dwJobID, NULL);
-            if (!pJob || pJob->Printer != pPrinter)
+            if (!pJob || pJob->pPrinter != pPrinter)
             {
                 // The user supplied a non-existing Job ID or the Job ID does not belong to the supplied printer name.
                 dwErrorCode = ERROR_INVALID_PRINTER_NAME;
                 goto Cleanup;
             }
 
             {
                 // The user supplied a non-existing Job ID or the Job ID does not belong to the supplied printer name.
                 dwErrorCode = ERROR_INVALID_PRINTER_NAME;
                 goto Cleanup;
             }
 
-            pPrinterHandle->StartedJob = pJob;
+            pPrinterHandle->pStartedJob = pJob;
         }
 
         // Create a new handle that references a printer.
         pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
         pHandle->HandleType = Printer;
         }
 
         // Create a new handle that references a printer.
         pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
         pHandle->HandleType = Printer;
-        pHandle->SpecificHandle = pPrinterHandle;
+        pHandle->pSpecificHandle = pPrinterHandle;
     }
     else
     {
     }
     else
     {
@@ -637,7 +637,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
             ///////////// TODO /////////////////////
             pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
             pHandle->HandleType = Monitor;
             ///////////// TODO /////////////////////
             pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
             pHandle->HandleType = Monitor;
-            //pHandle->SpecificHandle = pMonitorHandle;
+            //pHandle->pSpecificHandle = pMonitorHandle;
         }
         else if (wcscmp(p, L"XcvPort ") == 0)
         {
         }
         else if (wcscmp(p, L"XcvPort ") == 0)
         {
@@ -647,7 +647,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
             //////////// TODO //////////////////////
             pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
             pHandle->HandleType = Port;
             //////////// TODO //////////////////////
             pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
             pHandle->HandleType = Port;
-            //pHandle->SpecificHandle = pPortHandle;
+            //pHandle->pSpecificHandle = pPortHandle;
         }
         else
         {
         }
         else
         {
@@ -710,7 +710,7 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
         goto Cleanup;
     }
 
         goto Cleanup;
     }
 
-    pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
+    pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->pSpecificHandle;
 
     // Check if this is the right document information level.
     if (Level != 1)
 
     // Check if this is the right document information level.
     if (Level != 1)
@@ -723,14 +723,14 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
 
     // Create a new job.
     pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
 
     // Create a new job.
     pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
-    pJob->Printer = pPrinterHandle->Printer;
+    pJob->pPrinter = pPrinterHandle->pPrinter;
     pJob->dwPriority = DEF_PRIORITY;
 
     // Check if a datatype was given.
     if (pDocumentInfo1->pDatatype)
     {
         // Use the datatype if it's valid.
     pJob->dwPriority = DEF_PRIORITY;
 
     // Check if a datatype was given.
     if (pDocumentInfo1->pDatatype)
     {
         // Use the datatype if it's valid.
-        if (!FindDatatype(pJob->Printer->pPrintProcessor, pDocumentInfo1->pDatatype))
+        if (!FindDatatype(pJob->pPrintProcessor, pDocumentInfo1->pDatatype))
         {
             dwErrorCode = ERROR_INVALID_DATATYPE;
             goto Cleanup;
         {
             dwErrorCode = ERROR_INVALID_DATATYPE;
             goto Cleanup;
@@ -771,14 +771,14 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
 
     // 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.
 
     // 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))
+    if (!InsertTailElementSkiplist(&pJob->pPrinter->JobList, pJob))
     {
         dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
         ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
         goto Cleanup;
     }
 
     {
         dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
         ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job List!\n", pJob->dwJobID);
         goto Cleanup;
     }
 
-    pPrinterHandle->StartedJob = pJob;
+    pPrinterHandle->pStartedJob = pJob;
     dwErrorCode = ERROR_SUCCESS;
     dwReturnValue = pJob->dwJobID;
 
     dwErrorCode = ERROR_SUCCESS;
     dwReturnValue = pJob->dwJobID;