Author: cfinck
Date: Fri Jun 19 15:21:30 2015
New Revision: 68195
URL:
http://svn.reactos.org/svn/reactos?rev=68195&view=rev
Log:
[LOCALSPL]
- Get rid of the Generic Tables entirely and make use of the new Skiplist for the Global
Job List, the Printer's Job List and the Printer List.
Use a doubly linked-list for the Print Processors (there won't be many) and just
save the information returned from the Print Processor's EnumPrintProcessorDatatypesW
instead of putting it in another structure.
- Implement LocalAddJob and LocalGetJob (with full JOB_INFO_1W and JOB_INFO_2W support)
This makes use of the element index in the new Skiplist implementation to retrieve the
position of the job in the list.
- Do some changes to LocalStartDocPrinter, though this will make use of LocalAddJob in the
future.
- Make some global variables static again.
Modified:
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/CMakeLists.txt
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
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printers.c
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printprocessors.c
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/tools.c
Modified:
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/rea…
==============================================================================
---
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/CMakeLists.txt [iso-8859-1]
(original)
+++
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/CMakeLists.txt [iso-8859-1]
Fri Jun 19 15:21:30 2015
@@ -1,5 +1,7 @@
spec2def(localspl.dll localspl.spec ADD_IMPORTLIB)
+
+include_directories(${REACTOS_SOURCE_DIR}/lib/skiplist)
list(APPEND SOURCE
jobs.c
@@ -16,7 +18,7 @@
${CMAKE_CURRENT_BINARY_DIR}/localspl.def)
set_module_type(localspl win32dll UNICODE)
-target_link_libraries(localspl wine)
-add_importlibs(localspl advapi32 spoolss msvcrt kernel32 ntdll)
+target_link_libraries(localspl skiplist16 wine)
+add_importlibs(localspl advapi32 rpcrt4 spoolss msvcrt kernel32 ntdll)
add_pch(localspl precomp.h SOURCE)
add_cd_file(TARGET localspl DESTINATION reactos/system32 FOR all)
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]
Fri Jun 19 15:21:30 2015
@@ -7,10 +7,103 @@
#include "precomp.h"
-LIST_ENTRY LocalJobQueue;
+// Global Variables
+SKIPLIST GlobalJobList;
+
+// Local Variables
+static DWORD _dwLastJobID;
+
+
+/**
+ * @name _GlobalJobListCompareRoutine
+ *
+ * SKIPLIST_COMPARE_ROUTINE for the Global Job List.
+ * We need the Global Job List to check whether a Job ID is already in use. Consequently,
this list is sorted by ID.
+ */
+static int WINAPI
+_GlobalJobListCompareRoutine(PVOID FirstStruct, PVOID SecondStruct)
+{
+ PLOCAL_JOB A = (PLOCAL_JOB)FirstStruct;
+ PLOCAL_JOB B = (PLOCAL_JOB)SecondStruct;
+
+ return A->dwJobID - B->dwJobID;
+}
+
+/**
+ * @name _PrinterJobListCompareRoutine
+ *
+ * SKIPLIST_COMPARE_ROUTINE for the each Printer's Job List.
+ * Jobs in this list are sorted in the desired order of processing.
+ */
+static int WINAPI
+_PrinterJobListCompareRoutine(PVOID FirstStruct, PVOID SecondStruct)
+{
+ PLOCAL_JOB A = (PLOCAL_JOB)FirstStruct;
+ PLOCAL_JOB B = (PLOCAL_JOB)SecondStruct;
+ int iComparison;
+ FILETIME ftSubmittedA;
+ FILETIME ftSubmittedB;
+ ULARGE_INTEGER uliSubmittedA;
+ ULARGE_INTEGER uliSubmittedB;
+ ULONGLONG ullResult;
+
+ // First compare the priorities to determine the order.
+ // The job with a higher priority shall come first.
+ iComparison = A->dwPriority - B->dwPriority;
+ if (iComparison != 0)
+ return iComparison;
+
+ // Both have the same priority, so go by creation time.
+ // Comparison is done using the MSDN-recommended way for comparing SYSTEMTIMEs.
+ if (!SystemTimeToFileTime(&A->stSubmitted, &ftSubmittedA))
+ {
+ ERR("SystemTimeToFileTime failed for A with error %lu!\n",
GetLastError());
+ return 0;
+ }
+
+ if (!SystemTimeToFileTime(&B->stSubmitted, &ftSubmittedB))
+ {
+ ERR("SystemTimeToFileTime failed for B with error %lu!\n",
GetLastError());
+ return 0;
+ }
+
+ uliSubmittedA.LowPart = ftSubmittedA.dwLowDateTime;
+ uliSubmittedA.HighPart = ftSubmittedA.dwHighDateTime;
+ uliSubmittedB.LowPart = ftSubmittedB.dwLowDateTime;
+ uliSubmittedB.HighPart = ftSubmittedB.dwHighDateTime;
+ ullResult = uliSubmittedA.QuadPart - uliSubmittedB.QuadPart;
+
+ if (ullResult < 0)
+ return -1;
+ else if (ullResult > 0)
+ return 1;
+
+ return 0;
+}
+
+BOOL
+GetNextJobID(PDWORD dwJobID)
+{
+ ++_dwLastJobID;
+
+ while (LookupElementSkiplist(&GlobalJobList, &_dwLastJobID, NULL))
+ {
+ // This ID is already taken. Try the next one.
+ ++_dwLastJobID;
+ }
+
+ if (!IS_VALID_JOB_ID(_dwLastJobID))
+ {
+ ERR("Job ID %lu isn't valid!\n", _dwLastJobID);
+ return FALSE;
+ }
+
+ *dwJobID = _dwLastJobID;
+ return TRUE;
+}
void
-InitializeJobQueue()
+InitializeGlobalJobList()
{
const WCHAR wszPath[] = L"\\PRINTERS\\?????.SHD";
const DWORD cchPath = _countof(wszPath) - 1;
@@ -19,11 +112,18 @@
DWORD dwJobID;
HANDLE hFind;
- PLOCAL_JOB pJob;
+ PLOCAL_JOB pJob = NULL;
PWSTR p;
WCHAR wszFullPath[MAX_PATH];
WIN32_FIND_DATAW FindData;
+ // This one is incremented in GetNextJobID.
+ _dwLastJobID = 0;
+
+ // Initialize an empty list for all jobs of all local printers.
+ // We will search it by Job ID (supply a pointer to a DWORD in
LookupElementSkiplist).
+ InitializeSkiplist(&GlobalJobList, DllAllocSplMem, _GlobalJobListCompareRoutine,
(PSKIPLIST_FREE_ROUTINE)DllFreeSplMem);
+
// Construct the full path search pattern.
CopyMemory(wszFullPath, wszSpoolDirectory, cchSpoolDirectory * sizeof(WCHAR));
CopyMemory(&wszFullPath[cchSpoolDirectory], wszPath, (cchPath + 1) *
sizeof(WCHAR));
@@ -33,7 +133,7 @@
if (hFind == INVALID_HANDLE_VALUE)
{
// No unfinished jobs found.
- return;
+ goto Cleanup;
}
do
@@ -56,12 +156,368 @@
if (!pJob)
continue;
- // Add it to the job queue of the respective printer.
- InsertTailList(&pJob->Printer->JobQueue, &pJob->Entry);
+ // Add it to the Global Job List.
+ if (!InsertElementSkiplist(&GlobalJobList, pJob))
+ {
+ ERR("InsertElementSkiplist failed for job %lu for the
GlobalJobList!\n", pJob->dwJobID);
+ goto Cleanup;
+ }
+
+ // Add it to the Printer's Job List.
+ if (!InsertElementSkiplist(&pJob->Printer->JobList, pJob))
+ {
+ ERR("InsertElementSkiplist failed for job %lu for the Printer's Job
List!\n", pJob->dwJobID);
+ goto Cleanup;
+ }
}
while (FindNextFileW(hFind, &FindData));
- FindClose(hFind);
+Cleanup:
+ // Outside the loop
+ if (hFind)
+ FindClose(hFind);
+}
+
+void
+InitializePrinterJobList(PLOCAL_PRINTER pPrinter)
+{
+ // Initialize an empty list for this printer's jobs.
+ // This one is only for sorting the jobs. If you need to lookup a job, search the
GlobalJobList by Job ID.
+ InitializeSkiplist(&pPrinter->JobList, DllAllocSplMem,
_PrinterJobListCompareRoutine, (PSKIPLIST_FREE_ROUTINE)DllFreeSplMem);
+}
+
+BOOL WINAPI
+LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeeded)
+{
+ const WCHAR wszDoubleBackslash[] = L"\\";
+ const DWORD cchDoubleBackslash = _countof(wszDoubleBackslash) - 1;
+ const WCHAR wszPrintersPath[] = L"\\PRINTERS\\";
+ const DWORD cchPrintersPath = _countof(wszPrintersPath) - 1;
+ const DWORD cchSpl = _countof("?????.SPL") - 1;
+
+ ADDJOB_INFO_1W AddJobInfo1;
+ BOOL bReturnValue = FALSE;
+ DWORD cchMachineName;
+ DWORD cchUserName;
+ PBYTE p;
+ PLOCAL_HANDLE pHandle;
+ PLOCAL_JOB pJob;
+ PLOCAL_PRINTER_HANDLE pPrinterHandle;
+ RPC_BINDING_HANDLE hServerBinding = NULL;
+ RPC_STATUS Status;
+ RPC_WSTR pwszBinding = NULL;
+ RPC_WSTR pwszMachineName = NULL;
+
+ // Check if this is a printer handle.
+ pHandle = (PLOCAL_HANDLE)hPrinter;
+ if (pHandle->HandleType != Printer)
+ goto Cleanup;
+
+ pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
+
+ // Check if this is the right structure level.
+ if (Level != 1)
+ goto Cleanup;
+
+ // FIXME: This needs to fail if the printer is set to do direct printing.
+
+ // Check if the supplied buffer is large enough.
+ *pcbNeeded = sizeof(ADDJOB_INFO_1W) + (cchSpoolDirectory + cchPrintersPath + cchSpl +
1) * sizeof(WCHAR);
+ if (cbBuf < *pcbNeeded)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ goto Cleanup;
+ }
+
+ // Create a new job.
+ pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
+ if (!pJob)
+ {
+ ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+
+ // Reserve an ID for this job.
+ if (!GetNextJobID(&pJob->dwJobID))
+ goto Cleanup;
+
+ // Copy over defaults to the LOCAL_JOB structure.
+ pJob->Printer = pPrinterHandle->Printer;
+ pJob->dwPriority = DEF_PRIORITY;
+ pJob->pwszDatatype = AllocSplStr(pPrinterHandle->pwszDatatype);
+ pJob->pwszDocumentName = AllocSplStr(wszDefaultDocumentName);
+ CopyMemory(&pJob->DevMode, &pPrinterHandle->DevMode,
sizeof(DEVMODEW));
+ GetSystemTime(&pJob->stSubmitted);
+
+ // Get the user name for the Job.
+ cchUserName = UNLEN + 1;
+ pJob->pwszUserName = DllAllocSplMem(cchUserName * sizeof(WCHAR));
+ if (!GetUserNameW(pJob->pwszUserName, &cchUserName))
+ {
+ ERR("GetUserNameW failed with error %lu!\n", GetLastError());
+ goto Cleanup;
+ }
+
+ // FIXME: For now, pwszNotifyName equals pwszUserName.
+ pJob->pwszNotifyName = AllocSplStr(pJob->pwszUserName);
+
+ // Get the name of the machine that submitted the Job over RPC.
+ Status = RpcBindingServerFromClient(NULL, &hServerBinding);
+ if (Status != RPC_S_OK)
+ {
+ ERR("RpcBindingServerFromClient failed with status %lu!\n", Status);
+ goto Cleanup;
+ }
+
+ Status = RpcBindingToStringBindingW(hServerBinding, &pwszBinding);
+ if (Status != RPC_S_OK)
+ {
+ ERR("RpcBindingToStringBindingW failed with status %lu!\n", Status);
+ goto Cleanup;
+ }
+
+ Status = RpcStringBindingParseW(pwszBinding, NULL, NULL, &pwszMachineName, NULL,
NULL);
+ if (Status != RPC_S_OK)
+ {
+ ERR("RpcStringBindingParseW failed with status %lu!\n", Status);
+ goto Cleanup;
+ }
+
+ cchMachineName = wcslen(pwszMachineName);
+ pJob->pwszMachineName = DllAllocSplMem((cchMachineName + cchDoubleBackslash + 1) *
sizeof(WCHAR));
+ CopyMemory(pJob->pwszMachineName, wszDoubleBackslash, cchDoubleBackslash *
sizeof(WCHAR));
+ CopyMemory(pJob->pwszMachineName + cchDoubleBackslash, pwszMachineName,
(cchMachineName + 1) * sizeof(WCHAR));
+
+ // Add the job to the Global Job List.
+ if (!InsertElementSkiplist(&GlobalJobList, pJob))
+ {
+ ERR("InsertElementSkiplist failed for job %lu for the
GlobalJobList!\n", pJob->dwJobID);
+ goto Cleanup;
+ }
+
+ // 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))
+ {
+ ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job
List!\n", pJob->dwJobID);
+ goto Cleanup;
+ }
+
+ // Return a proper ADDJOB_INFO_1W structure.
+ AddJobInfo1.JobId = pJob->dwJobID;
+ AddJobInfo1.Path = (PWSTR)(pData + sizeof(ADDJOB_INFO_1W));
+ p = pData;
+ CopyMemory(p, &AddJobInfo1, sizeof(ADDJOB_INFO_1W));
+ p += sizeof(ADDJOB_INFO_1W);
+ CopyMemory(p, wszSpoolDirectory, cchSpoolDirectory);
+ p += cchSpoolDirectory;
+ CopyMemory(p, wszPrintersPath, cchPrintersPath);
+ p += cchPrintersPath;
+ swprintf((PWSTR)p, L"%05lu.SPL", pJob->dwJobID);
+
+ bReturnValue = TRUE;
+
+Cleanup:
+ if (pwszMachineName)
+ RpcStringFreeW(&pwszMachineName);
+
+ if (pwszBinding)
+ RpcStringFreeW(&pwszBinding);
+
+ if (hServerBinding)
+ RpcBindingFree(&hServerBinding);
+
+ return bReturnValue;
+}
+
+
+static BOOL
+_LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE pOutput,
DWORD cbBuf, PDWORD pcbNeeded)
+{
+ 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 cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
+ JOB_INFO_1W JobInfo1 = { 0 };
+ PBYTE pString;
+
+ // Check if the supplied buffer is large enough.
+ *pcbNeeded = sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName +
cbPrinterName + cbUserName;
+ if (cbBuf < *pcbNeeded)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ // 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->Printer->pwszPrinterName, cbPrinterName);
+ pString += cbPrinterName;
+
+ JobInfo1.pUserName = (PWSTR)pString;
+ CopyMemory(pString, pJob->pwszUserName, cbUserName);
+ pString += cbUserName;
+
+ // Fill the structure and copy it as well.
+ 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));
+
+ return TRUE;
+}
+
+static BOOL
+_LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE pOutput,
DWORD cbBuf, PDWORD pcbNeeded)
+{
+ 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 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 cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
+ FILETIME ftNow;
+ FILETIME ftSubmitted;
+ JOB_INFO_2W JobInfo2 = { 0 };
+ PBYTE pString;
+ ULARGE_INTEGER uliNow;
+ ULARGE_INTEGER uliSubmitted;
+
+ // Check if the supplied buffer is large enough.
+ *pcbNeeded = sizeof(JOB_INFO_2W) + cbDatatype + sizeof(DEVMODEW) + cbDocumentName +
cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor +
cbUserName;
+ if (cbBuf < *pcbNeeded)
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ // 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->Printer->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->Printer->pwszPrinterName, cbPrinterName);
+ pString += cbPrinterName;
+
+ JobInfo2.pPrintProcessor = (PWSTR)pString;
+ CopyMemory(pString, pJob->Printer->pPrintProcessor->pwszName,
cbPrintProcessor);
+ pString += cbPrintProcessor;
+
+ JobInfo2.pUserName = (PWSTR)pString;
+ CopyMemory(pString, pJob->pwszUserName, cbUserName);
+ pString += 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))
+ {
+ ERR("SystemTimeToFileTime failed with error %lu!\n", GetLastError());
+ return FALSE;
+ }
+
+ GetSystemTimeAsFileTime(&ftNow);
+ uliSubmitted.LowPart = ftSubmitted.dwLowDateTime;
+ uliSubmitted.HighPart = ftSubmitted.dwHighDateTime;
+ uliNow.LowPart = ftNow.dwLowDateTime;
+ uliNow.HighPart = ftNow.dwHighDateTime;
+ JobInfo2.Time = (DWORD)((uliNow.QuadPart - uliSubmitted.QuadPart) / 10000);
+
+ // 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))
+ {
+ ERR("pJob could not be located in the Printer's Job List!\n");
+ return FALSE;
+ }
+
+ // Make the index 1-based.
+ ++JobInfo2.Position;
+
+ // Fill the rest of the structure.
+ JobInfo2.JobId = pJob->dwJobID;
+ JobInfo2.PagesPrinted = pJob->dwPagesPrinted;
+ JobInfo2.Priority = pJob->dwPriority;
+ JobInfo2.StartTime = pJob->dwStartTime;
+ JobInfo2.Status = pJob->dwStatus;
+ JobInfo2.TotalPages = pJob->dwTotalPages;
+ JobInfo2.UntilTime = pJob->dwUntilTime;
+ CopyMemory(&JobInfo2.Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
+
+ // Finally copy the structure to the output pointer.
+ CopyMemory(pOutput, &JobInfo2, sizeof(JOB_INFO_2W));
+ return TRUE;
+}
+
+BOOL WINAPI
+LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pOutput, DWORD cbBuf,
LPDWORD pcbNeeded)
+{
+ 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)
+ return FALSE;
+
+ pPrinterHandle = (PLOCAL_PRINTER_HANDLE)pHandle->SpecificHandle;
+
+ // Get the desired job.
+ pJob = LookupElementSkiplist(&GlobalJobList, &JobId, NULL);
+ if (!pJob || pJob->Printer != pPrinterHandle->Printer)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ // The function behaves differently for each level.
+ if (Level == 1)
+ return _LocalGetJobLevel1(pPrinterHandle, pJob, pOutput, cbBuf, pcbNeeded);
+ else if (Level == 2)
+ return _LocalGetJobLevel2(pPrinterHandle, pJob, pOutput, cbBuf, pcbNeeded);
+
+ return FALSE;
}
PLOCAL_JOB
@@ -80,7 +536,7 @@
hFile = CreateFileW(pwszFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
- ERR("CreateFileW failed with error %lu!\n", GetLastError());
+ ERR("CreateFileW failed with error %lu for file \"%S\"!\n",
GetLastError(), pwszFilePath);
goto Cleanup;
}
@@ -89,30 +545,30 @@
pShadowFile = DllAllocSplMem(cbFileSize);
if (!pShadowFile)
{
- ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
+ ERR("DllAllocSplMem failed with error %lufor file \"%S\"!\n",
GetLastError(), pwszFilePath);
goto Cleanup;
}
// Read the entire file.
if (!ReadFile(hFile, pShadowFile, cbFileSize, &cbRead, NULL))
{
- ERR("ReadFile failed with error %lu!\n", GetLastError());
+ ERR("ReadFile failed with error %lu for file \"%S\"!\n",
GetLastError(), pwszFilePath);
goto Cleanup;
}
// Check signature and header size.
if (pShadowFile->dwSignature != SHD_WIN2003_SIGNATURE || pShadowFile->cbHeader
!= sizeof(SHD_HEADER))
{
- ERR("Signature or Header Size mismatch!\n");
- goto Cleanup;
- }
-
- // Retrieve the associated printer from the table.
+ ERR("Signature or Header Size mismatch for file \"%S\"!\n",
pwszFilePath);
+ goto Cleanup;
+ }
+
+ // Retrieve the associated printer from the list.
pwszPrinterName = (PWSTR)((ULONG_PTR)pShadowFile + pShadowFile->offPrinterName);
- pPrinter = RtlLookupElementGenericTable(&PrinterTable, pwszPrinterName);
+ pPrinter = LookupElementSkiplist(&PrinterList, &pwszPrinterName, NULL);
if (!pPrinter)
{
- ERR("This shadow file references a non-existing printer!\n");
+ ERR("Shadow file \"%S\" references a non-existing
printer!\n", pwszFilePath);
goto Cleanup;
}
@@ -120,15 +576,18 @@
pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
if (!pJob)
{
- ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
+ ERR("DllAllocSplMem failed with error %lu for file
\"%S\"!\n", GetLastError(), pwszFilePath);
goto Cleanup;
}
pJob->dwJobID = pShadowFile->dwJobID;
+ pJob->dwTotalPages = pShadowFile->dwTotalPages;
+ pJob->dwPriority = pShadowFile->dwPriority;
pJob->Printer = pPrinter;
pJob->pwszDatatype = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile +
pShadowFile->offDatatype));
pJob->pwszDocumentName = AllocSplStr((PCWSTR)((ULONG_PTR)pShadowFile +
pShadowFile->offDocumentName));
pJob->pwszOutputFile = NULL;
+ CopyMemory(&pJob->stSubmitted, &pShadowFile->stSubmitted,
sizeof(SYSTEMTIME));
CopyMemory(&pJob->DevMode, (PDEVMODEW)((ULONG_PTR)pShadowFile +
pShadowFile->offDevMode), sizeof(DEVMODEW));
pReturnValue = pJob;
@@ -160,33 +619,42 @@
hFile = CreateFileW(pwszFilePath, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
- ERR("CreateFileW failed with error %lu!\n", GetLastError());
+ ERR("CreateFileW failed with error %lu for file \"%S\"!\n",
GetLastError(), pwszFilePath);
goto Cleanup;
}
// Compute the total size of the shadow file.
+ cbPrinterName = (wcslen(pJob->Printer->pwszPrinterName) + 1) * sizeof(WCHAR);
cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
- cbPrinterName = (wcslen(pJob->Printer->pwszPrinterName) + 1) * sizeof(WCHAR);
- cbFileSize = sizeof(SHD_HEADER) + cbDatatype + cbDocumentName + cbPrinterName;
+ cbFileSize = sizeof(SHD_HEADER) + cbPrinterName + cbDatatype + cbDocumentName +
sizeof(DEVMODEW);
// Allocate memory for it.
pShadowFile = DllAllocSplMem(cbFileSize);
if (!pShadowFile)
{
- ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
+ ERR("DllAllocSplMem failed with error %lu for file
\"%S\"!\n", GetLastError(), pwszFilePath);
goto Cleanup;
}
// Fill out the shadow file header information.
pShadowFile->dwSignature = SHD_WIN2003_SIGNATURE;
pShadowFile->cbHeader = sizeof(SHD_HEADER);
+
+ // Copy the values.
pShadowFile->dwJobID = pJob->dwJobID;
+ pShadowFile->dwTotalPages = pJob->dwTotalPages;
+ pShadowFile->dwPriority = pJob->dwPriority;
+ CopyMemory(&pShadowFile->stSubmitted, &pJob->stSubmitted,
sizeof(SYSTEMTIME));
// Add the extra values that are stored as offsets in the shadow file.
// The first value begins right after the shadow file header.
dwCurrentOffset = sizeof(SHD_HEADER);
+ CopyMemory((PBYTE)pShadowFile + dwCurrentOffset,
pJob->Printer->pwszPrinterName, cbPrinterName);
+ pShadowFile->offPrinterName = dwCurrentOffset;
+ dwCurrentOffset += cbPrinterName;
+
CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, pJob->pwszDatatype, cbDatatype);
pShadowFile->offDatatype = dwCurrentOffset;
dwCurrentOffset += cbDatatype;
@@ -195,14 +663,14 @@
pShadowFile->offDocumentName = dwCurrentOffset;
dwCurrentOffset += cbDocumentName;
- CopyMemory((PBYTE)pShadowFile + dwCurrentOffset,
pJob->Printer->pwszPrinterName, cbPrinterName);
- pShadowFile->offPrinterName = dwCurrentOffset;
- dwCurrentOffset += cbPrinterName;
+ CopyMemory((PBYTE)pShadowFile + dwCurrentOffset, &pJob->DevMode,
sizeof(DEVMODEW));
+ pShadowFile->offDevMode = dwCurrentOffset;
+ dwCurrentOffset += sizeof(DEVMODEW);
// Write the file.
if (!WriteFile(hFile, pShadowFile, cbFileSize, &cbWritten, NULL))
{
- ERR("WriteFile failed with error %lu!\n", GetLastError());
+ ERR("WriteFile failed with error %lu for file \"%S\"!\n",
GetLastError(), pwszFilePath);
goto Cleanup;
}
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]
Fri Jun 19 15:21:30 2015
@@ -11,7 +11,7 @@
WCHAR wszSpoolDirectory[MAX_PATH];
DWORD cchSpoolDirectory;
-// Constants
+// Global Constants
const WCHAR wszCurrentEnvironment[] =
#if defined(_X86_)
L"Windows NT x86";
@@ -23,16 +23,19 @@
#error Unsupported architecture
#endif
+const WCHAR wszDefaultDocumentName[] = L"Local Downlevel Document";
+
const WCHAR* wszPrintProviderInfo[3] = {
L"Windows NT Local Print Providor", // Name
L"Windows NT Local Printers", // Description
L"Locally connected Printers" // Comment
};
-static const PRINTPROVIDOR PrintProviderFunctions = {
+// Local Constants
+static const PRINTPROVIDOR _PrintProviderFunctions = {
LocalOpenPrinter, // fpOpenPrinter
NULL, // fpSetJob
- NULL, // fpGetJob
+ LocalGetJob, // fpGetJob
NULL, // fpEnumJobs
NULL, // fpAddPrinter
NULL, // fpDeletePrinter
@@ -56,7 +59,7 @@
NULL, // fpAbortPrinter
NULL, // fpReadPrinter
LocalEndDocPrinter, // fpEndDocPrinter
- NULL, // fpAddJob
+ LocalAddJob, // fpAddJob
NULL, // fpScheduleJob
NULL, // fpGetPrinterData
NULL, // fpSetPrinterData
@@ -139,8 +142,9 @@
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
_GetSpoolDirectory();
- InitializePrintProcessorTable();
- InitializePrinterTable();
+ InitializePrintProcessorList();
+ InitializePrinterList();
+ InitializeGlobalJobList();
break;
}
@@ -150,7 +154,7 @@
BOOL WINAPI
InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, LPWSTR
pFullRegistryPath)
{
- CopyMemory(pPrintProvidor, &PrintProviderFunctions, min(cbPrintProvidor,
sizeof(PRINTPROVIDOR)));
+ CopyMemory(pPrintProvidor, &_PrintProviderFunctions, min(cbPrintProvidor,
sizeof(PRINTPROVIDOR)));
return TRUE;
}
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]
Fri Jun 19 15:21:30 2015
@@ -13,6 +13,8 @@
#include <stdlib.h>
#include <wchar.h>
+#include <lmcons.h>
+#include <rpc.h>
#include <windef.h>
#include <winbase.h>
#include <wingdi.h>
@@ -21,6 +23,8 @@
#include <winsplp.h>
#include <ndk/rtlfuncs.h>
+#define SKIPLIST_LEVELS 16
+#include <skiplist.h>
#include <spoolss.h>
#include <wine/debug.h>
@@ -47,8 +51,10 @@
*/
typedef struct _LOCAL_PRINT_PROCESSOR
{
+ LIST_ENTRY Entry;
PWSTR pwszName;
- RTL_GENERIC_TABLE DatatypeTable;
+ PDATATYPES_INFO_1W pDatatypesInfo1;
+ DWORD dwDatatypeCount;
PClosePrintProcessor pfnClosePrintProcessor;
PControlPrintProcessor pfnControlPrintProcessor;
PEnumPrintProcessorDatatypesW pfnEnumPrintProcessorDatatypesW;
@@ -64,13 +70,15 @@
*/
typedef struct _LOCAL_PRINTER
{
+ // This sort key must be the first element for LookupElementSkiplist to work!
PWSTR pwszPrinterName;
+
PWSTR pwszPrinterDriver;
PWSTR pwszDescription;
PWSTR pwszDefaultDatatype;
DEVMODEW DefaultDevMode;
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
- LIST_ENTRY JobQueue;
+ SKIPLIST JobList;
}
LOCAL_PRINTER, *PLOCAL_PRINTER;
@@ -80,13 +88,24 @@
*/
typedef struct _LOCAL_JOB
{
- LIST_ENTRY Entry;
- PLOCAL_PRINTER Printer;
- DWORD dwJobID;
- PWSTR pwszDocumentName;
- PWSTR pwszDatatype;
- PWSTR pwszOutputFile;
- DEVMODEW DevMode;
+ // 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
}
LOCAL_JOB, *PLOCAL_JOB;
@@ -140,35 +159,42 @@
DWORD offPrintProcessor;
DWORD offDatatype;
DWORD dwUnknown2;
- SYSTEMTIME stSubmitTime;
+ SYSTEMTIME stSubmitted;
DWORD dwStartTime;
DWORD dwUntilTime;
DWORD dwUnknown6;
- DWORD dwPageCount;
+ DWORD dwTotalPages;
DWORD cbSecurityDescriptor;
DWORD offSecurityDescriptor;
DWORD dwUnknown3;
DWORD dwUnknown4;
DWORD dwUnknown5;
- DWORD offComputerName;
+ DWORD offMachineName;
DWORD dwSPLSize;
}
SHD_HEADER, *PSHD_HEADER;
// jobs.c
+extern SKIPLIST GlobalJobList;
+BOOL GetNextJobID(PDWORD dwJobID);
+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);
PLOCAL_JOB ReadJobShadowFile(PCWSTR pwszFilePath);
BOOL WriteJobShadowFile(PCWSTR pwszFilePath, const PLOCAL_JOB pJob);
// main.c
extern const WCHAR wszCurrentEnvironment[];
+extern const WCHAR wszDefaultDocumentName[];
extern const WCHAR* wszPrintProviderInfo[3];
extern WCHAR wszSpoolDirectory[MAX_PATH];
extern DWORD cchSpoolDirectory;
// printers.c
-extern RTL_GENERIC_TABLE PrinterTable;
-void InitializePrinterTable();
+extern SKIPLIST PrinterList;
+void InitializePrinterList();
BOOL WINAPI LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum,
DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW
pDefault);
DWORD WINAPI LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo);
@@ -179,15 +205,14 @@
BOOL WINAPI LocalClosePrinter(HANDLE hPrinter);
// printprocessors.c
-extern RTL_GENERIC_TABLE PrintProcessorTable;
-void InitializePrintProcessorTable();
+BOOL FindDatatype(PLOCAL_PRINT_PROCESSOR pPrintProcessor, PWSTR pwszDatatype);
+PLOCAL_PRINT_PROCESSOR FindPrintProcessor(PWSTR pwszName);
+void InitializePrintProcessorList();
BOOL WINAPI LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName,
DWORD Level, LPBYTE pDatatypes, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
BOOL WINAPI LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level,
LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
BOOL WINAPI LocalGetPrintProcessorDirectory(LPWSTR pName, LPWSTR pEnvironment, DWORD
Level, LPBYTE pPrintProcessorInfo, DWORD cbBuf, LPDWORD pcbNeeded);
// tools.c
PWSTR AllocAndRegQueryWSZ(HKEY hKey, PCWSTR pwszValueName);
-PVOID NTAPI GenericTableAllocateRoutine(PRTL_GENERIC_TABLE Table, CLONG ByteSize);
-VOID NTAPI GenericTableFreeRoutine(PRTL_GENERIC_TABLE Table, PVOID Buffer);
#endif
Modified:
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printers.c
URL:
http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/rea…
==============================================================================
---
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printers.c [iso-8859-1]
(original)
+++
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printers.c [iso-8859-1]
Fri Jun 19 15:21:30 2015
@@ -8,40 +8,33 @@
#include "precomp.h"
// Global Variables
-RTL_GENERIC_TABLE PrinterTable;
+SKIPLIST PrinterList;
/**
- * @name _PrinterTableCompareRoutine
+ * @name _PrinterListCompareRoutine
*
- * RTL_GENERIC_COMPARE_ROUTINE for the Printer Table.
+ * SKIPLIST_COMPARE_ROUTINE for the Printer List.
* Does a case-insensitive comparison, because e.g. LocalOpenPrinter doesn't match
the case when looking for Printers.
*/
-static RTL_GENERIC_COMPARE_RESULTS NTAPI
-_PrinterTableCompareRoutine(PRTL_GENERIC_TABLE Table, PVOID FirstStruct, PVOID
SecondStruct)
+static int WINAPI
+_PrinterListCompareRoutine(PVOID FirstStruct, PVOID SecondStruct)
{
PLOCAL_PRINTER A = (PLOCAL_PRINTER)FirstStruct;
PLOCAL_PRINTER B = (PLOCAL_PRINTER)SecondStruct;
- int iResult = wcsicmp(A->pwszPrinterName, B->pwszPrinterName);
-
- if (iResult < 0)
- return GenericLessThan;
- else if (iResult > 0)
- return GenericGreaterThan;
- else
- return GenericEqual;
+ return wcsicmp(A->pwszPrinterName, B->pwszPrinterName);
}
/**
- * @name InitializePrinterTable
+ * @name InitializePrinterList
*
- * Initializes a RTL_GENERIC_TABLE of locally available Printers.
- * The table is searchable by name and returns information about the printers, including
their job queues.
+ * Initializes a list of locally available Printers.
+ * The list is searchable by name and returns information about the printers, including
their job queues.
* During this process, the job queues are also initialized.
*/
void
-InitializePrinterTable()
+InitializePrinterList()
{
const WCHAR wszPrintersKey[] =
L"SYSTEM\\CurrentControlSet\\Control\\Print\\Printers";
@@ -52,14 +45,13 @@
HKEY hKey = NULL;
HKEY hSubKey = NULL;
LONG lStatus;
+ PLOCAL_PRINTER pPrinter = NULL;
PLOCAL_PRINT_PROCESSOR pPrintProcessor;
- PLOCAL_PRINTER pPrinter = NULL;
PWSTR pwszPrintProcessor = NULL;
WCHAR wszPrinterName[MAX_PRINTER_NAME + 1];
- // Initialize an empty table for our printers.
- // We will search it by printer name.
- RtlInitializeGenericTable(&PrinterTable, _PrinterTableCompareRoutine,
GenericTableAllocateRoutine, GenericTableFreeRoutine, NULL);
+ // Initialize an empty list for our printers.
+ InitializeSkiplist(&PrinterList, DllAllocSplMem, _PrinterListCompareRoutine,
(PSKIPLIST_FREE_ROUTINE)DllFreeSplMem);
// Open our printers registry key. Each subkey is a local printer there.
lStatus = RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszPrintersKey, 0, KEY_READ, &hKey);
@@ -91,6 +83,15 @@
{
if (pPrinter->pwszDefaultDatatype)
DllFreeSplStr(pPrinter->pwszDefaultDatatype);
+
+ if (pPrinter->pwszDescription)
+ DllFreeSplStr(pPrinter->pwszDescription);
+
+ if (pPrinter->pwszPrinterDriver)
+ DllFreeSplStr(pPrinter->pwszPrinterDriver);
+
+ if (pPrinter->pwszPrinterName)
+ DllFreeSplStr(pPrinter->pwszPrinterName);
DllFreeSplMem(pPrinter);
pPrinter = NULL;
@@ -129,8 +130,8 @@
if (!pwszPrintProcessor)
continue;
- // Try to find it in the Print Processor Table.
- pPrintProcessor = RtlLookupElementGenericTable(&PrintProcessorTable,
pwszPrintProcessor);
+ // Try to find it in the Print Processor List.
+ pPrintProcessor = FindPrintProcessor(pwszPrintProcessor);
if (!pPrintProcessor)
{
ERR("Invalid Print Processor \"%S\" for Printer
\"%S\"!\n", pwszPrintProcessor, wszPrinterName);
@@ -147,7 +148,7 @@
pPrinter->pwszPrinterName = AllocSplStr(wszPrinterName);
pPrinter->pPrintProcessor = pPrintProcessor;
- InitializeListHead(&pPrinter->JobQueue);
+ InitializePrinterJobList(pPrinter);
// Get the printer driver.
pPrinter->pwszPrinterDriver = AllocAndRegQueryWSZ(hSubKey, L"Printer
Driver");
@@ -165,7 +166,7 @@
continue;
// Verify that it's valid.
- if (!RtlLookupElementGenericTable(&pPrintProcessor->DatatypeTable,
pPrinter->pwszDefaultDatatype))
+ if (!FindDatatype(pPrintProcessor, pPrinter->pwszDefaultDatatype))
{
ERR("Invalid default datatype \"%S\" for Printer
\"%S\"!\n", pPrinter->pwszDefaultDatatype, wszPrinterName);
continue;
@@ -176,14 +177,14 @@
lStatus = RegQueryValueExW(hSubKey, L"Default DevMode", NULL, NULL,
(PBYTE)&pPrinter->DefaultDevMode, &cbDevMode);
if (lStatus != ERROR_SUCCESS || cbDevMode != sizeof(DEVMODEW))
{
- ERR("Couldn't query DevMode for Printer \"%S\", status is
%ld, cbDevMode is %lu!\n", wszPrinterName, lStatus, cbDevMode);
- continue;
- }
-
- // Add this printer to the printer table.
- if (!RtlInsertElementGenericTable(&PrinterTable, pPrinter,
sizeof(LOCAL_PRINTER), NULL))
- {
- ERR("RtlInsertElementGenericTable failed with error %lu!\n",
GetLastError());
+ ERR("Couldn't query a valid DevMode for Printer \"%S\",
status is %ld, cbDevMode is %lu!\n", wszPrinterName, lStatus, cbDevMode);
+ continue;
+ }
+
+ // Add this printer to the printer list.
+ if (!InsertElementSkiplist(&PrinterList, pPrinter))
+ {
+ ERR("InsertElementSkiplist failed for Printer \"%S\"!\n",
pPrinter->pwszPrinterName);
goto Cleanup;
}
@@ -192,20 +193,31 @@
}
Cleanup:
+ // Inside the loop
+ if (hSubKey)
+ RegCloseKey(hSubKey);
+
+ if (pPrinter)
+ {
+ if (pPrinter->pwszDefaultDatatype)
+ DllFreeSplStr(pPrinter->pwszDefaultDatatype);
+
+ if (pPrinter->pwszDescription)
+ DllFreeSplStr(pPrinter->pwszDescription);
+
+ if (pPrinter->pwszPrinterDriver)
+ DllFreeSplStr(pPrinter->pwszPrinterDriver);
+
+ if (pPrinter->pwszPrinterName)
+ DllFreeSplStr(pPrinter->pwszPrinterName);
+
+ DllFreeSplMem(pPrinter);
+ }
+
if (pwszPrintProcessor)
DllFreeSplStr(pwszPrintProcessor);
- if (pPrinter)
- {
- if (pPrinter->pwszDefaultDatatype)
- DllFreeSplStr(pPrinter->pwszDefaultDatatype);
-
- DllFreeSplMem(pPrinter);
- }
-
- if (hSubKey)
- RegCloseKey(hSubKey);
-
+ // Outside the loop
if (hKey)
RegCloseKey(hKey);
}
@@ -223,9 +235,9 @@
DWORD i;
PBYTE pPrinterInfo;
PBYTE pPrinterString;
+ PSKIPLIST_NODE pNode;
PLOCAL_PRINTER pPrinter;
PRINTER_INFO_1W PrinterInfo1;
- PVOID pRestartKey = NULL;
WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1];
DWORD dwOffsets[] = {
@@ -302,8 +314,10 @@
}
// Count the required buffer size and the number of printers.
- for (pPrinter = RtlEnumerateGenericTableWithoutSplaying(&PrinterTable,
&pRestartKey); pPrinter; pPrinter =
RtlEnumerateGenericTableWithoutSplaying(&PrinterTable, &pRestartKey))
- {
+ for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
+ {
+ pPrinter = (PLOCAL_PRINTER)pNode->Element;
+
// This looks wrong, but is totally right. PRINTER_INFO_1W has three members
pName, pComment and pDescription.
// But pComment equals the "Description" registry value while
pDescription is concatenated out of pName and pComment.
// On top of this, the computer name is prepended to the printer name if the user
supplied the local computer name during the query.
@@ -328,8 +342,10 @@
pPrinterString = pPrinterEnum + *pcReturned * sizeof(PRINTER_INFO_1W);
// Copy over the printer information.
- for (pPrinter = RtlEnumerateGenericTableWithoutSplaying(&PrinterTable,
&pRestartKey); pPrinter; pPrinter =
RtlEnumerateGenericTableWithoutSplaying(&PrinterTable, &pRestartKey))
- {
+ for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
+ {
+ pPrinter = (PLOCAL_PRINTER)pNode->Element;
+
// FIXME: As for now, the Flags member returns no information.
PrinterInfo1.Flags = 0;
@@ -409,7 +425,6 @@
PLOCAL_HANDLE pHandle;
PLOCAL_PRINTER pPrinter;
PLOCAL_PRINTER_HANDLE pPrinterHandle = NULL;
- PLIST_ENTRY pEntry;
WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
// Sanity checks
@@ -478,8 +493,8 @@
CopyMemory(pwszPrinterName, lpPrinterName, cchPrinterName * sizeof(WCHAR));
pwszPrinterName[cchPrinterName] = 0;
- // Retrieve the associated printer from the table.
- pPrinter = RtlLookupElementGenericTable(&PrinterTable, pwszPrinterName);
+ // Retrieve the associated printer from the list.
+ pPrinter = LookupElementSkiplist(&PrinterList, &pwszPrinterName, NULL);
if (!pPrinter)
{
// The printer does not exist.
@@ -495,7 +510,7 @@
if (pDefault && pDefault->pDatatype)
{
// Use the datatype if it's valid.
- if
(!RtlLookupElementGenericTable(&pPrinter->pPrintProcessor->DatatypeTable,
pDefault->pDatatype))
+ if (!FindDatatype(pPrinter->pPrintProcessor, pDefault->pDatatype))
{
SetLastError(ERROR_INVALID_DATATYPE);
goto Cleanup;
@@ -550,30 +565,16 @@
goto Cleanup;
}
- // Look for this job in the job queue of the printer.
- pEntry = pPrinter->JobQueue.Flink;
-
- for (;;)
+ // Look for this job in the Global Job List.
+ pJob = LookupElementSkiplist(&GlobalJobList, &dwJobID, NULL);
+ if (!pJob || pJob->Printer != pPrinter)
{
- if (pEntry == &pPrinter->JobQueue)
- {
- // We have reached the end of the list without finding the desired
Job ID.
- SetLastError(ERROR_INVALID_PRINTER_NAME);
- goto Cleanup;
- }
-
- // Get our job structure.
- pJob = CONTAINING_RECORD(pEntry, LOCAL_JOB, Entry);
-
- if (pJob->dwJobID == dwJobID)
- {
- // We have found the desired job. Give the caller a printer handle
referencing it.
- pPrinterHandle->StartedJob = pJob;
- break;
- }
-
- pEntry = pEntry->Flink;
+ // The user supplied a non-existing Job ID or the Job ID does not belong
to the supplied printer name.
+ SetLastError(ERROR_INVALID_PRINTER_NAME);
+ goto Cleanup;
}
+
+ pPrinterHandle->StartedJob = pJob;
}
// Create a new handle that references a printer.
@@ -647,11 +648,10 @@
DWORD WINAPI
LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
{
- DWORD dwReturnValue = 0;
PDOC_INFO_1W pDocumentInfo1;
PLOCAL_HANDLE pHandle;
+ PLOCAL_JOB pJob;
PLOCAL_PRINTER_HANDLE pPrinterHandle;
- PLOCAL_JOB pJob;
// Sanity checks
if (!pDocInfo)
@@ -688,15 +688,16 @@
// Create a new job.
pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
pJob->Printer = pPrinterHandle->Printer;
+ pJob->dwPriority = DEF_PRIORITY;
// Check if a datatype was given.
if (pDocumentInfo1->pDatatype)
{
// Use the datatype if it's valid.
- if
(!RtlLookupElementGenericTable(&pJob->Printer->pPrintProcessor->DatatypeTable,
pDocumentInfo1->pDatatype))
+ if (!FindDatatype(pJob->Printer->pPrintProcessor,
pDocumentInfo1->pDatatype))
{
SetLastError(ERROR_INVALID_DATATYPE);
- goto Cleanup;
+ return 0;
}
pJob->pwszDatatype = AllocSplStr(pDocumentInfo1->pDatatype);
@@ -717,14 +718,27 @@
if (pDocumentInfo1->pOutputFile)
pJob->pwszOutputFile = AllocSplStr(pDocumentInfo1->pOutputFile);
- // Enqueue the job.
- ///////////// TODO /////////////////////
-
-Cleanup:
- if (pJob)
- DllFreeSplMem(pJob);
-
- return dwReturnValue;
+ // Get an ID for the new job.
+ if (!GetNextJobID(&pJob->dwJobID))
+ return 0;
+
+ // Add the job to the Global Job List.
+ if (!InsertElementSkiplist(&GlobalJobList, pJob))
+ {
+ ERR("InsertElementSkiplist failed for job %lu for the
GlobalJobList!\n", pJob->dwJobID);
+ return 0;
+ }
+
+ // 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))
+ {
+ ERR("InsertTailElementSkiplist failed for job %lu for the Printer's Job
List!\n", pJob->dwJobID);
+ return 0;
+ }
+
+ pPrinterHandle->StartedJob = pJob;
+ return pJob->dwJobID;
}
BOOL WINAPI
Modified:
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printprocessors.c
URL:
http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/rea…
==============================================================================
---
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printprocessors.c [iso-8859-1]
(original)
+++
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/printprocessors.c [iso-8859-1]
Fri Jun 19 15:21:30 2015
@@ -8,8 +8,8 @@
#include "precomp.h"
-// Global Variables
-RTL_GENERIC_TABLE PrintProcessorTable;
+// Local Variables
+static LIST_ENTRY _PrintProcessorList;
/**
* @name _OpenEnvironment
@@ -76,83 +76,67 @@
return bReturnValue;
}
+BOOL
+FindDatatype(PLOCAL_PRINT_PROCESSOR pPrintProcessor, PWSTR pwszDatatype)
+{
+ DWORD i;
+ PDATATYPES_INFO_1W pCurrentDatatype = pPrintProcessor->pDatatypesInfo1;
+
+ for (i = 0; i < pPrintProcessor->dwDatatypeCount; i++)
+ {
+ if (wcsicmp(pCurrentDatatype->pName, pwszDatatype) == 0)
+ return TRUE;
+
+ ++pCurrentDatatype;
+ }
+
+ return FALSE;
+}
+
+PLOCAL_PRINT_PROCESSOR
+FindPrintProcessor(PWSTR pwszName)
+{
+ PLIST_ENTRY pEntry;
+ PLOCAL_PRINT_PROCESSOR pPrintProcessor;
+
+ for (pEntry = _PrintProcessorList.Flink; pEntry; pEntry = pEntry->Flink)
+ {
+ pPrintProcessor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_PROCESSOR, Entry);
+
+ if (wcsicmp(pPrintProcessor->pwszName, pwszName) == 0)
+ return pPrintProcessor;
+ }
+
+ return NULL;
+}
+
/**
- * @name _PrinterTableCompareRoutine
- *
- * RTL_GENERIC_COMPARE_ROUTINE for the Print Processor Table.
- * Does a case-insensitive comparison, because e.g. LocalEnumPrintProcessorDatatypes
doesn't match the case when looking for Print Processors.
- */
-static RTL_GENERIC_COMPARE_RESULTS NTAPI
-_PrintProcessorTableCompareRoutine(PRTL_GENERIC_TABLE Table, PVOID FirstStruct, PVOID
SecondStruct)
-{
- PLOCAL_PRINT_PROCESSOR A = (PLOCAL_PRINT_PROCESSOR)FirstStruct;
- PLOCAL_PRINT_PROCESSOR B = (PLOCAL_PRINT_PROCESSOR)SecondStruct;
-
- int iResult = wcsicmp(A->pwszName, B->pwszName);
-
- if (iResult < 0)
- return GenericLessThan;
- else if (iResult > 0)
- return GenericGreaterThan;
- else
- return GenericEqual;
-}
-
-/**
- * @name _DatatypeTableCompareRoutine
- *
- * RTL_GENERIC_COMPARE_ROUTINE for the Datatype Table.
- * Does a case-insensitive comparison, because e.g. LocalOpenPrinter doesn't match
the case when looking for Datatypes.
- */
-static RTL_GENERIC_COMPARE_RESULTS NTAPI
-_DatatypeTableCompareRoutine(PRTL_GENERIC_TABLE Table, PVOID FirstStruct, PVOID
SecondStruct)
-{
- PWSTR A = (PWSTR)FirstStruct;
- PWSTR B = (PWSTR)SecondStruct;
-
- int iResult = wcsicmp(A, B);
-
- if (iResult < 0)
- return GenericLessThan;
- else if (iResult > 0)
- return GenericGreaterThan;
- else
- return GenericEqual;
-}
-
-/**
- * @name InitializePrintProcessorTable
- *
- * Initializes a RTL_GENERIC_TABLE of locally available Print Processors.
- * The table is searchable by name and returns pointers to the functions of the loaded
Print Processor DLL.
+ * @name InitializePrintProcessorList
+ *
+ * Initializes a singly linked list of locally available Print Processors.
*/
void
-InitializePrintProcessorTable()
+InitializePrintProcessorList()
{
DWORD cbDatatypes;
DWORD cbFileName;
DWORD cchPrintProcessorPath;
DWORD cchMaxSubKey;
DWORD cchPrintProcessorName;
- DWORD dwDatatypes;
DWORD dwSubKeys;
DWORD i;
- DWORD j;
HINSTANCE hinstPrintProcessor;
HKEY hKey = NULL;
HKEY hSubKey = NULL;
HKEY hSubSubKey = NULL;
LONG lStatus;
- PDATATYPES_INFO_1W pDatatypesInfo1 = NULL;
PLOCAL_PRINT_PROCESSOR pPrintProcessor = NULL;
- PWSTR pwszDatatype = NULL;
PWSTR pwszPrintProcessorName = NULL;
WCHAR wszFileName[MAX_PATH];
WCHAR wszPrintProcessorPath[MAX_PATH];
- // Initialize an empty table for our Print Processors.
- // We will search it by Print Processor name.
- RtlInitializeGenericTable(&PrintProcessorTable,
_PrintProcessorTableCompareRoutine, GenericTableAllocateRoutine, GenericTableFreeRoutine,
NULL);
+ // Initialize an empty list for our Print Processors.
+ InitializeListHead(&_PrintProcessorList);
// Prepare the path to the Print Processor directory.
if (!LocalGetPrintProcessorDirectory(NULL, NULL, 1, (PBYTE)wszPrintProcessorPath,
sizeof(wszPrintProcessorPath), &cchPrintProcessorPath))
@@ -204,14 +188,11 @@
if (pPrintProcessor->pwszName)
DllFreeSplStr(pPrintProcessor->pwszName);
+ if (pPrintProcessor->pDatatypesInfo1)
+ DllFreeSplMem(pPrintProcessor->pDatatypesInfo1);
+
DllFreeSplMem(pPrintProcessor);
pPrintProcessor = NULL;
- }
-
- if (pDatatypesInfo1)
- {
- DllFreeSplMem(pDatatypesInfo1);
- pDatatypesInfo1 = NULL;
}
// Get the name of this Print Processor.
@@ -306,68 +287,46 @@
}
// Get all supported datatypes.
- pPrintProcessor->pfnEnumPrintProcessorDatatypesW(NULL, NULL, 1, NULL, 0,
&cbDatatypes, &dwDatatypes);
- pDatatypesInfo1 = DllAllocSplMem(cbDatatypes);
- if (!pDatatypesInfo1)
+ pPrintProcessor->pfnEnumPrintProcessorDatatypesW(NULL, NULL, 1, NULL, 0,
&cbDatatypes, &pPrintProcessor->dwDatatypeCount);
+ pPrintProcessor->pDatatypesInfo1 = DllAllocSplMem(cbDatatypes);
+ if (!pPrintProcessor->pDatatypesInfo1)
{
ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
goto Cleanup;
}
- if (!pPrintProcessor->pfnEnumPrintProcessorDatatypesW(NULL, NULL, 1,
(PBYTE)pDatatypesInfo1, cbDatatypes, &cbDatatypes, &dwDatatypes))
+ if (!pPrintProcessor->pfnEnumPrintProcessorDatatypesW(NULL, NULL, 1,
(PBYTE)pPrintProcessor->pDatatypesInfo1, cbDatatypes, &cbDatatypes,
&pPrintProcessor->dwDatatypeCount))
{
ERR("EnumPrintProcessorDatatypesW failed for Print Processor
\"%S\" with error %lu!\n", wszPrintProcessorPath, GetLastError());
continue;
}
- // Add the supported datatypes to the datatype table.
- RtlInitializeGenericTable(&pPrintProcessor->DatatypeTable,
_DatatypeTableCompareRoutine, GenericTableAllocateRoutine, GenericTableFreeRoutine,
NULL);
-
- for (j = 0; j < dwDatatypes; j++)
- {
- pwszDatatype = AllocSplStr(pDatatypesInfo1->pName);
-
- if (!RtlInsertElementGenericTable(&pPrintProcessor->DatatypeTable,
pDatatypesInfo1->pName, sizeof(PWSTR), NULL))
- {
- ERR("RtlInsertElementGenericTable failed for iteration %lu with
error %lu!\n", j, GetLastError());
- goto Cleanup;
- }
-
- ++pDatatypesInfo1;
- }
-
- // Add the Print Processor to the table.
- if (!RtlInsertElementGenericTable(&PrintProcessorTable, pPrintProcessor,
sizeof(LOCAL_PRINT_PROCESSOR), NULL))
- {
- ERR("RtlInsertElementGenericTable failed for iteration %lu with error
%lu!\n", i, GetLastError());
- goto Cleanup;
- }
+ // Add the Print Processor to the list.
+ InsertTailList(&_PrintProcessorList, &pPrintProcessor->Entry);
// Don't let the cleanup routines free this.
- pwszDatatype = NULL;
pPrintProcessor = NULL;
}
Cleanup:
- if (pwszDatatype)
- DllFreeSplStr(pwszDatatype);
-
- if (pDatatypesInfo1)
- DllFreeSplMem(pDatatypesInfo1);
+ // Inside the loop
+ if (hSubSubKey)
+ RegCloseKey(hSubSubKey);
if (pPrintProcessor)
{
if (pPrintProcessor->pwszName)
DllFreeSplStr(pPrintProcessor->pwszName);
+ if (pPrintProcessor->pDatatypesInfo1)
+ DllFreeSplMem(pPrintProcessor->pDatatypesInfo1);
+
DllFreeSplMem(pPrintProcessor);
}
+ // Outside the loop
if (pwszPrintProcessorName)
DllFreeSplStr(pwszPrintProcessorName);
-
- if (hSubSubKey)
- RegCloseKey(hSubSubKey);
if (hSubKey)
RegCloseKey(hSubKey);
@@ -423,7 +382,7 @@
}
// Try to find the Print Processor.
- pPrintProcessor = RtlLookupElementGenericTable(&PrintProcessorTable,
pPrintProcessorName);
+ pPrintProcessor = FindPrintProcessor(pPrintProcessorName);
if (!pPrintProcessor)
{
SetLastError(ERROR_UNKNOWN_PRINTPROCESSOR);
@@ -499,6 +458,7 @@
}
// Verify pEnvironment and open its registry key.
+ // We use the registry and not the PrintProcessorList here, because the caller may
request information about a different environment.
if (!_OpenEnvironment(pEnvironment, &hKey))
goto Cleanup;
Modified:
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/tools.c
URL:
http://svn.reactos.org/svn/reactos/branches/colins-printing-for-freedom/rea…
==============================================================================
---
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/tools.c [iso-8859-1]
(original)
+++
branches/colins-printing-for-freedom/reactos/win32ss/printing/providers/localspl/tools.c [iso-8859-1]
Fri Jun 19 15:21:30 2015
@@ -56,25 +56,3 @@
return pwszValue;
}
-
-/**
- * @name GenericTableAllocateRoutine
- *
- * RTL_GENERIC_ALLOCATE_ROUTINE for all our RTL_GENERIC_TABLEs, using DllAllocSplMem.
- */
-PVOID NTAPI
-GenericTableAllocateRoutine(PRTL_GENERIC_TABLE Table, CLONG ByteSize)
-{
- return DllAllocSplMem(ByteSize);
-}
-
-/**
- * @name GenericTableFreeRoutine
- *
- * RTL_GENERIC_FREE_ROUTINE for all our RTL_GENERIC_TABLEs, using DllFreeSplMem.
- */
-VOID NTAPI
-GenericTableFreeRoutine(PRTL_GENERIC_TABLE Table, PVOID Buffer)
-{
- DllFreeSplMem(Buffer);
-}