[PRINTING]
authorColin Finck <colin@reactos.org>
Wed, 5 Jul 2017 15:29:13 +0000 (15:29 +0000)
committerColin Finck <colin@reactos.org>
Wed, 5 Jul 2017 15:29:13 +0000 (15:29 +0000)
Apply a consistent style to all similar functions:
- Spoolss functions don't necessarily set ERROR_SUCCESS. Check the boolean return value instead and only query the error code on failure.
- Use AlignRpcPtr and UndoAlignRpcPtr wherever feasible.
- Use one static function per level that can be called from both Get* and Enum* APIs.
- Use PackStrings in all functions that return structures with strings.
- Add TRACEs to all non-static functions in localspl.
- Pass a double pointer to all Marshalling functions and advance to the next structure there.
- Perform sanity checks and return the right error codes in a Windows-compatible way.
- Return TRUE when an Enum* API has no elements to enumerate.

Also fixes CORE-12793

svn path=/trunk/; revision=75287

19 files changed:
reactos/win32ss/printing/base/spoolss/monitors.c
reactos/win32ss/printing/base/spoolss/ports.c
reactos/win32ss/printing/base/spoolss/printers.c
reactos/win32ss/printing/base/spoolsv/init.c
reactos/win32ss/printing/base/spoolsv/jobs.c
reactos/win32ss/printing/base/spoolsv/monitors.c
reactos/win32ss/printing/base/spoolsv/ports.c
reactos/win32ss/printing/base/spoolsv/printers.c
reactos/win32ss/printing/base/spoolsv/printprocessors.c
reactos/win32ss/printing/monitors/localmon/ports.c
reactos/win32ss/printing/providers/localspl/jobs.c
reactos/win32ss/printing/providers/localspl/main.c
reactos/win32ss/printing/providers/localspl/monitors.c
reactos/win32ss/printing/providers/localspl/ports.c
reactos/win32ss/printing/providers/localspl/precomp.h
reactos/win32ss/printing/providers/localspl/printerdata.c
reactos/win32ss/printing/providers/localspl/printers.c
reactos/win32ss/printing/providers/localspl/printingthread.c
reactos/win32ss/printing/providers/localspl/printprocessors.c

index e9fbb82..7fcd7ff 100644 (file)
@@ -10,7 +10,7 @@
 BOOL WINAPI
 EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
 {
-    BOOL bReturnValue;
+    BOOL bReturnValue = TRUE;
     DWORD cbCallBuffer;
     DWORD cbNeeded;
     DWORD dwReturned;
@@ -19,9 +19,9 @@ EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcb
     PLIST_ENTRY pEntry;
 
     // Sanity checks.
-    if ((cbBuf && !pMonitors) || !pcbNeeded || !pcReturned)
+    if (cbBuf && !pMonitors)
     {
-        SetLastError(ERROR_INVALID_PARAMETER);
+        SetLastError(ERROR_INVALID_USER_BUFFER);
         return FALSE;
     }
 
index c5df5df..133c719 100644 (file)
@@ -10,7 +10,7 @@
 BOOL WINAPI
 EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
 {
-    BOOL bReturnValue;
+    BOOL bReturnValue = TRUE;
     DWORD cbCallBuffer;
     DWORD cbNeeded;
     DWORD dwReturned;
@@ -19,9 +19,9 @@ EnumPortsW(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded
     PLIST_ENTRY pEntry;
 
     // Sanity checks.
-    if ((cbBuf && !pPorts) || !pcbNeeded || !pcReturned)
+    if (cbBuf && !pPorts)
     {
-        SetLastError(ERROR_INVALID_PARAMETER);
+        SetLastError(ERROR_INVALID_USER_BUFFER);
         return FALSE;
     }
 
index 99d74d2..6d3da34 100644 (file)
@@ -67,7 +67,7 @@ EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cb
 {
     DWORD cbCallBuffer;
     DWORD cbNeeded;
-    DWORD dwErrorCode = 0xFFFFFFFF;
+    DWORD dwErrorCode = MAXDWORD;
     DWORD dwReturned;
     PBYTE pCallBuffer;
     PSPOOLSS_PRINT_PROVIDER pPrintProvider;
index 435b24e..f338efe 100644 (file)
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Print Spooler Service
  * LICENSE:     GNU GPLv2 or any later version as published by the Free Software Foundation
  * PURPOSE:     Various initialization functions
- * COPYRIGHT:   Copyright 2015 Colin Finck <colin@reactos.org>
+ * COPYRIGHT:   Copyright 2015-2017 Colin Finck <colin@reactos.org>
  */
 
 #include "precomp.h"
@@ -21,8 +21,8 @@ _RpcSpoolerInit()
         return dwErrorCode;
     }
 
-    SpoolerInit();
-    dwErrorCode = GetLastError();
+    if (!SpoolerInit())
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
index 1a2843a..c7c4978 100644 (file)
@@ -2,28 +2,29 @@
  * PROJECT:     ReactOS Print Spooler Service
  * LICENSE:     GNU GPLv2 or any later version as published by the Free Software Foundation
  * PURPOSE:     Functions for managing print jobs
- * COPYRIGHT:   Copyright 2015 Colin Finck <colin@reactos.org>
+ * COPYRIGHT:   Copyright 2015-2017 Colin Finck <colin@reactos.org>
  */
 
 #include "precomp.h"
 
 static void
-_MarshallDownAddJobInfo(PADDJOB_INFO_1W pAddJobInfo1)
+_MarshallDownAddJobInfo(PADDJOB_INFO_1W* ppAddJobInfo1)
 {
     // Replace absolute pointer addresses in the output by relative offsets.
+    PADDJOB_INFO_1W pAddJobInfo1 = *ppAddJobInfo1;
     pAddJobInfo1->Path = (PWSTR)((ULONG_PTR)pAddJobInfo1->Path - (ULONG_PTR)pAddJobInfo1);
+
+    *ppAddJobInfo1 += sizeof(ADDJOB_INFO_1W);
 }
 
 static void
-_MarshallDownJobInfo(PBYTE pJobInfo, DWORD Level)
+_MarshallDownJobInfo(PBYTE* ppJobInfo, DWORD Level)
 {
-    PJOB_INFO_1W pJobInfo1;
-    PJOB_INFO_2W pJobInfo2;
-
     // Replace absolute pointer addresses in the output by relative offsets.
     if (Level == 1)
     {
-        pJobInfo1 = (PJOB_INFO_1W)pJobInfo;
+        PJOB_INFO_1W pJobInfo1 = (PJOB_INFO_1W)(*ppJobInfo);
+
         pJobInfo1->pDatatype = (PWSTR)((ULONG_PTR)pJobInfo1->pDatatype - (ULONG_PTR)pJobInfo1);
         pJobInfo1->pDocument = (PWSTR)((ULONG_PTR)pJobInfo1->pDocument - (ULONG_PTR)pJobInfo1);
         pJobInfo1->pMachineName = (PWSTR)((ULONG_PTR)pJobInfo1->pMachineName - (ULONG_PTR)pJobInfo1);
@@ -33,10 +34,13 @@ _MarshallDownJobInfo(PBYTE pJobInfo, DWORD Level)
             pJobInfo1->pStatus = (PWSTR)((ULONG_PTR)pJobInfo1->pStatus - (ULONG_PTR)pJobInfo1);
 
         pJobInfo1->pUserName = (PWSTR)((ULONG_PTR)pJobInfo1->pUserName - (ULONG_PTR)pJobInfo1);
+
+        *ppJobInfo += sizeof(JOB_INFO_1W);
     }
     else if (Level == 2)
     {
-        pJobInfo2 = (PJOB_INFO_2W)pJobInfo;
+        PJOB_INFO_2W pJobInfo2 = (PJOB_INFO_2W)(*ppJobInfo);
+
         pJobInfo2->pDatatype = (PWSTR)((ULONG_PTR)pJobInfo2->pDatatype - (ULONG_PTR)pJobInfo2);
         pJobInfo2->pDevMode = (PDEVMODEW)((ULONG_PTR)pJobInfo2->pDevMode - (ULONG_PTR)pJobInfo2);
         pJobInfo2->pDocument = (PWSTR)((ULONG_PTR)pJobInfo2->pDocument - (ULONG_PTR)pJobInfo2);
@@ -53,6 +57,8 @@ _MarshallDownJobInfo(PBYTE pJobInfo, DWORD Level)
             pJobInfo2->pStatus = (PWSTR)((ULONG_PTR)pJobInfo2->pStatus - (ULONG_PTR)pJobInfo2);
 
         pJobInfo2->pUserName = (PWSTR)((ULONG_PTR)pJobInfo2->pUserName - (ULONG_PTR)pJobInfo2);
+
+        *ppJobInfo += sizeof(JOB_INFO_2W);
     }
 }
 
@@ -60,6 +66,7 @@ DWORD
 _RpcAddJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pAddJob, DWORD cbBuf, DWORD* pcbNeeded)
 {
     DWORD dwErrorCode;
+    PBYTE pAddJobAligned;
 
     dwErrorCode = RpcImpersonateClient(NULL);
     if (dwErrorCode != ERROR_SUCCESS)
@@ -68,13 +75,23 @@ _RpcAddJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pAddJob, DWORD c
         return dwErrorCode;
     }
 
-    AddJobW(hPrinter, Level, pAddJob, cbBuf, pcbNeeded);
-    dwErrorCode = GetLastError();
+    pAddJobAligned = AlignRpcPtr(pAddJob, &cbBuf);
 
-    if (dwErrorCode == ERROR_SUCCESS)
-        _MarshallDownAddJobInfo((PADDJOB_INFO_1W)pAddJob);
+    if (AddJobW(hPrinter, Level, pAddJobAligned, cbBuf, pcbNeeded))
+    {
+        PBYTE p = pAddJobAligned;
+
+        // Replace absolute pointer addresses in the output by relative offsets.
+        _MarshallDownAddJobInfo((PADDJOB_INFO_1W*)&p);
+    }
+    else
+    {
+        dwErrorCode = GetLastError();
+    }
 
     RpcRevertToSelf();
+    UndoAlignRpcPtr(pAddJob, pAddJobAligned, cbBuf, pcbNeeded);
+
     return dwErrorCode;
 }
 
@@ -82,8 +99,7 @@ DWORD
 _RpcEnumJobs(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, BYTE* pJob, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
 {
     DWORD dwErrorCode;
-    DWORD i;
-    PBYTE p = pJob;
+    PBYTE pJobAligned;
 
     dwErrorCode = RpcImpersonateClient(NULL);
     if (dwErrorCode != ERROR_SUCCESS)
@@ -92,24 +108,25 @@ _RpcEnumJobs(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWO
         return dwErrorCode;
     }
 
-    EnumJobsW(hPrinter, FirstJob, NoJobs, Level, pJob, cbBuf, pcbNeeded, pcReturned);
-    dwErrorCode = GetLastError();
+    pJobAligned = AlignRpcPtr(pJob, &cbBuf);
 
-    if (dwErrorCode == ERROR_SUCCESS)
+    if (EnumJobsW(hPrinter, FirstJob, NoJobs, Level, pJobAligned, cbBuf, pcbNeeded, pcReturned))
     {
+        DWORD i;
+        PBYTE p = pJobAligned;
+
         // Replace absolute pointer addresses in the output by relative offsets.
         for (i = 0; i < *pcReturned; i++)
-        {
-            _MarshallDownJobInfo(p, Level);
-
-            if (Level == 1)
-                p += sizeof(JOB_INFO_1W);
-            else if (Level == 2)
-                p += sizeof(JOB_INFO_2W);
-        }
+            _MarshallDownJobInfo(&p, Level);
+    }
+    else
+    {
+        dwErrorCode = GetLastError();
     }
 
     RpcRevertToSelf();
+    UndoAlignRpcPtr(pJob, pJobAligned, cbBuf, pcbNeeded);
+
     return dwErrorCode;
 }
 
@@ -117,6 +134,7 @@ DWORD
 _RpcGetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, DWORD Level, BYTE* pJob, DWORD cbBuf, DWORD* pcbNeeded)
 {
     DWORD dwErrorCode;
+    PBYTE pJobAligned;
 
     dwErrorCode = RpcImpersonateClient(NULL);
     if (dwErrorCode != ERROR_SUCCESS)
@@ -125,16 +143,23 @@ _RpcGetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, DWORD Level, BYTE* pJo
         return dwErrorCode;
     }
 
-    GetJobW(hPrinter, JobId, Level, pJob, cbBuf, pcbNeeded);
-    dwErrorCode = GetLastError();
+    pJobAligned = AlignRpcPtr(pJob, &cbBuf);
 
-    if (dwErrorCode == ERROR_SUCCESS)
+    if (GetJobW(hPrinter, JobId, Level, pJobAligned, cbBuf, pcbNeeded))
     {
+        PBYTE p = pJobAligned;
+
         // Replace absolute pointer addresses in the output by relative offsets.
-        _MarshallDownJobInfo(pJob, Level);
+        _MarshallDownJobInfo(&p, Level);
+    }
+    else
+    {
+        dwErrorCode = GetLastError();
     }
 
     RpcRevertToSelf();
+    UndoAlignRpcPtr(pJob, pJobAligned, cbBuf, pcbNeeded);
+
     return dwErrorCode;
 }
 
@@ -150,8 +175,8 @@ _RpcScheduleJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId)
         return dwErrorCode;
     }
 
-    ScheduleJob(hPrinter, JobId);
-    dwErrorCode = GetLastError();
+    if (!ScheduleJob(hPrinter, JobId))
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
@@ -170,8 +195,8 @@ _RpcSetJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId, WINSPOOL_JOB_CONTAINER
     }
 
     // pJobContainer->JobInfo is a union of pointers, so we can just convert any element to our BYTE pointer.
-    SetJobW(hPrinter, JobId, pJobContainer->Level, (PBYTE)pJobContainer->JobInfo.Level1, Command);
-    dwErrorCode = GetLastError();
+    if (!SetJobW(hPrinter, JobId, pJobContainer->Level, (PBYTE)pJobContainer->JobInfo.Level1, Command))
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
index 1f2bc72..cb90e2e 100644 (file)
@@ -2,23 +2,28 @@
  * PROJECT:     ReactOS Print Spooler Service
  * LICENSE:     GNU GPLv2 or any later version as published by the Free Software Foundation
  * PURPOSE:     Functions related to Print Monitors
- * COPYRIGHT:   Copyright 2015 Colin Finck <colin@reactos.org>
+ * COPYRIGHT:   Copyright 2015-2017 Colin Finck <colin@reactos.org>
  */
 
 #include "precomp.h"
 
 static void
-_MarshallDownMonitorInfo(PBYTE pMonitorInfo, DWORD Level)
+_MarshallDownMonitorInfo(PBYTE* ppMonitorInfo, DWORD Level)
 {
-    PMONITOR_INFO_2W pMonitorInfo2 = (PMONITOR_INFO_2W)pMonitorInfo;        // MONITOR_INFO_1W is a subset of MONITOR_INFO_2W
+    PMONITOR_INFO_2W pMonitorInfo2 = (PMONITOR_INFO_2W)(*ppMonitorInfo);        // MONITOR_INFO_1W is a subset of MONITOR_INFO_2W
 
     // Replace absolute pointer addresses in the output by relative offsets.
     pMonitorInfo2->pName = (PWSTR)((ULONG_PTR)pMonitorInfo2->pName - (ULONG_PTR)pMonitorInfo2);
 
-    if (Level == 2)
+    if (Level == 1)
+    {
+        *ppMonitorInfo += sizeof(MONITOR_INFO_1W);
+    }
+    else
     {
         pMonitorInfo2->pDLLName = (PWSTR)((ULONG_PTR)pMonitorInfo2->pDLLName - (ULONG_PTR)pMonitorInfo2);
         pMonitorInfo2->pEnvironment = (PWSTR)((ULONG_PTR)pMonitorInfo2->pEnvironment - (ULONG_PTR)pMonitorInfo2);
+        *ppMonitorInfo += sizeof(MONITOR_INFO_2W);
     }
 }
 
@@ -40,8 +45,7 @@ DWORD
 _RpcEnumMonitors(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pMonitor, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
 {
     DWORD dwErrorCode;
-    DWORD i;
-    PBYTE p = pMonitor;
+    PBYTE pMonitorAligned;
 
     dwErrorCode = RpcImpersonateClient(NULL);
     if (dwErrorCode != ERROR_SUCCESS)
@@ -50,23 +54,24 @@ _RpcEnumMonitors(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pMonitor, DWORD cbBuf
         return dwErrorCode;
     }
 
-    EnumMonitorsW(pName, Level, pMonitor, cbBuf, pcbNeeded, pcReturned);
-    dwErrorCode = GetLastError();
+    pMonitorAligned = AlignRpcPtr(pMonitor, &cbBuf);
 
-    if (dwErrorCode == ERROR_SUCCESS)
+    if(EnumMonitorsW(pName, Level, pMonitorAligned, cbBuf, pcbNeeded, pcReturned))
     {
         // Replace absolute pointer addresses in the output by relative offsets.
-        for (i = 0; i < *pcReturned; i++)
-        {
-            _MarshallDownMonitorInfo(p, Level);
+        DWORD i;
+        PBYTE p = pMonitorAligned;
 
-            if (Level == 1)
-                p += sizeof(MONITOR_INFO_1W);
-            else if (Level == 2)
-                p += sizeof(MONITOR_INFO_2W);
-        }
+        for (i = 0; i < *pcReturned; i++)
+            _MarshallDownMonitorInfo(&p, Level);
+    }
+    else
+    {
+        dwErrorCode = GetLastError();
     }
 
     RpcRevertToSelf();
+    UndoAlignRpcPtr(pMonitor, pMonitorAligned, cbBuf, pcbNeeded);
+
     return dwErrorCode;
 }
index cb3d993..6e2fbd2 100644 (file)
@@ -2,23 +2,40 @@
  * PROJECT:     ReactOS Print Spooler Service
  * LICENSE:     GNU GPLv2 or any later version as published by the Free Software Foundation
  * PURPOSE:     Functions related to Ports
- * COPYRIGHT:   Copyright 2015 Colin Finck <colin@reactos.org>
+ * COPYRIGHT:   Copyright 2015-2017 Colin Finck <colin@reactos.org>
  */
 
 #include "precomp.h"
 
 static void
-_MarshallDownPortInfo(PBYTE pPortInfo, DWORD Level)
+_MarshallDownPortInfo(PBYTE* ppPortInfo, DWORD Level)
 {
-    PPORT_INFO_2W pPortInfo2 = (PPORT_INFO_2W)pPortInfo;         // PORT_INFO_1W is a subset of PORT_INFO_2W
-
     // Replace absolute pointer addresses in the output by relative offsets.
-    pPortInfo2->pPortName = (PWSTR)((ULONG_PTR)pPortInfo2->pPortName - (ULONG_PTR)pPortInfo2);
+    if (Level == 1)
+    {
+        PPORT_INFO_1W pPortInfo1 = (PPORT_INFO_1W)(*ppPortInfo);
 
-    if (Level == 2)
+        pPortInfo1->pName = (PWSTR)((ULONG_PTR)pPortInfo1->pName - (ULONG_PTR)pPortInfo1);
+
+        *ppPortInfo += sizeof(PORT_INFO_1W);
+    }
+    else if (Level == 2)
     {
+        PPORT_INFO_2W pPortInfo2 = (PPORT_INFO_2W)(*ppPortInfo);
+
+        pPortInfo2->pPortName = (PWSTR)((ULONG_PTR)pPortInfo2->pPortName - (ULONG_PTR)pPortInfo2);
         pPortInfo2->pDescription = (PWSTR)((ULONG_PTR)pPortInfo2->pDescription - (ULONG_PTR)pPortInfo2);
         pPortInfo2->pMonitorName = (PWSTR)((ULONG_PTR)pPortInfo2->pMonitorName - (ULONG_PTR)pPortInfo2);
+
+        *ppPortInfo += sizeof(PORT_INFO_2W);
+    }
+    else if (Level == 3)
+    {
+        PPORT_INFO_3W pPortInfo3 = (PPORT_INFO_3W)(*ppPortInfo);
+
+        pPortInfo3->pszStatus = (PWSTR)((ULONG_PTR)pPortInfo3->pszStatus - (ULONG_PTR)pPortInfo3);
+
+        *ppPortInfo += sizeof(PORT_INFO_3W);
     }
 }
 
@@ -54,8 +71,7 @@ DWORD
 _RpcEnumPorts(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pPort, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
 {
     DWORD dwErrorCode;
-    DWORD i;
-    PBYTE p = pPort;
+    PBYTE pPortAligned;
 
     dwErrorCode = RpcImpersonateClient(NULL);
     if (dwErrorCode != ERROR_SUCCESS)
@@ -64,24 +80,25 @@ _RpcEnumPorts(WINSPOOL_HANDLE pName, DWORD Level, BYTE* pPort, DWORD cbBuf, DWOR
         return dwErrorCode;
     }
 
-    EnumPortsW(pName, Level, pPort, cbBuf, pcbNeeded, pcReturned);
-    dwErrorCode = GetLastError();
+    pPortAligned = AlignRpcPtr(pPort, &cbBuf);
 
-    if (dwErrorCode == ERROR_SUCCESS)
+    if (EnumPortsW(pName, Level, pPortAligned, cbBuf, pcbNeeded, pcReturned))
     {
         // Replace absolute pointer addresses in the output by relative offsets.
+        DWORD i;
+        PBYTE p = pPortAligned;
+
         for (i = 0; i < *pcReturned; i++)
-        {
-            _MarshallDownPortInfo(p, Level);
-
-            if (Level == 1)
-                p += sizeof(PORT_INFO_1W);
-            else if (Level == 2)
-                p += sizeof(PORT_INFO_2W);
-        }
+            _MarshallDownPortInfo(&p, Level);
+    }
+    else
+    {
+        dwErrorCode = GetLastError();
     }
 
     RpcRevertToSelf();
+    UndoAlignRpcPtr(pPort, pPortAligned, cbBuf, pcbNeeded);
+
     return dwErrorCode;
 }
 
index 75872d2..78f25df 100644 (file)
@@ -150,8 +150,8 @@ _RpcClosePrinter(WINSPOOL_PRINTER_HANDLE* phPrinter)
 
     if (ClosePrinter(*phPrinter))
         *phPrinter = NULL;
-
-    dwErrorCode = GetLastError();
+    else
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
@@ -176,8 +176,8 @@ _RpcEndDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
         return dwErrorCode;
     }
 
-    EndDocPrinter(hPrinter);
-    dwErrorCode = GetLastError();
+    if (!EndDocPrinter(hPrinter))
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
@@ -195,8 +195,8 @@ _RpcEndPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
         return dwErrorCode;
     }
 
-    EndPagePrinter(hPrinter);
-    dwErrorCode = GetLastError();
+    if (!EndPagePrinter(hPrinter))
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
@@ -216,10 +216,8 @@ _RpcEnumPrinters(DWORD Flags, WINSPOOL_HANDLE Name, DWORD Level, BYTE* pPrinterE
     }
 
     pPrinterEnumAligned = AlignRpcPtr(pPrinterEnum, &cbBuf);
-    EnumPrintersW(Flags, Name, Level, pPrinterEnumAligned, cbBuf, pcbNeeded, pcReturned);
-    dwErrorCode = GetLastError();
 
-    if (dwErrorCode == ERROR_SUCCESS)
+    if (EnumPrintersW(Flags, Name, Level, pPrinterEnumAligned, cbBuf, pcbNeeded, pcReturned))
     {
         DWORD i;
         PBYTE p = pPrinterEnumAligned;
@@ -227,6 +225,10 @@ _RpcEnumPrinters(DWORD Flags, WINSPOOL_HANDLE Name, DWORD Level, BYTE* pPrinterE
         for (i = 0; i < *pcReturned; i++)
             _MarshallDownPrinterInfo(&p, Level);
     }
+    else
+    {
+        dwErrorCode = GetLastError();
+    }
 
     RpcRevertToSelf();
     UndoAlignRpcPtr(pPrinterEnum, pPrinterEnumAligned, cbBuf, pcbNeeded);
@@ -255,14 +257,16 @@ _RpcGetPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE* pPrinter, DW
     }
 
     pPrinterAligned = AlignRpcPtr(pPrinter, &cbBuf);
-    GetPrinterW(hPrinter, Level, pPrinterAligned, cbBuf, pcbNeeded);
-    dwErrorCode = GetLastError();
 
-    if (dwErrorCode == ERROR_SUCCESS)
+    if (GetPrinterW(hPrinter, Level, pPrinterAligned, cbBuf, pcbNeeded))
     {
         PBYTE p = pPrinterAligned;
         _MarshallDownPrinterInfo(&p, Level);
     }
+    else
+    {
+        dwErrorCode = GetLastError();
+    }
 
     RpcRevertToSelf();
     UndoAlignRpcPtr(pPrinter, pPrinterAligned, cbBuf, pcbNeeded);
@@ -287,8 +291,8 @@ _RpcOpenPrinter(WINSPOOL_HANDLE pPrinterName, WINSPOOL_PRINTER_HANDLE* phPrinter
     Default.pDatatype = pDatatype;
     Default.pDevMode = (PDEVMODEW)pDevModeContainer->pDevMode;
 
-    OpenPrinterW(pPrinterName, phPrinter, &Default);
-    dwErrorCode = GetLastError();
+    if (!OpenPrinterW(pPrinterName, phPrinter, &Default))
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
@@ -313,8 +317,8 @@ _RpcReadPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE* pBuf, DWORD cbBuf, DWORD
         return dwErrorCode;
     }
 
-    ReadPrinter(hPrinter, pBuf, cbBuf, pcNoBytesRead);
-    dwErrorCode = GetLastError();
+    if (!ReadPrinter(hPrinter, pBuf, cbBuf, pcNoBytesRead))
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
@@ -379,8 +383,8 @@ _RpcStartPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
         return dwErrorCode;
     }
 
-    StartPagePrinter(hPrinter);
-    dwErrorCode = GetLastError();
+    if (!StartPagePrinter(hPrinter))
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
@@ -398,8 +402,8 @@ _RpcWritePrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE* pBuf, DWORD cbBuf, DWOR
         return dwErrorCode;
     }
 
-    WritePrinter(hPrinter, pBuf, cbBuf, pcWritten);
-    dwErrorCode = GetLastError();
+    if (!WritePrinter(hPrinter, pBuf, cbBuf, pcWritten))
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
index 4e709c5..d75d402 100644 (file)
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS Print Spooler Service
  * LICENSE:     GNU GPLv2 or any later version as published by the Free Software Foundation
  * PURPOSE:     Functions related to Print Processors
- * COPYRIGHT:   Copyright 2015 Colin Finck <colin@reactos.org>
+ * COPYRIGHT:   Copyright 2015-2017 Colin Finck <colin@reactos.org>
  */
 
 #include "precomp.h"
@@ -78,6 +78,7 @@ DWORD
 _RpcEnumPrintProcessors(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level, BYTE* pPrintProcessorInfo, DWORD cbBuf, DWORD* pcbNeeded, DWORD* pcReturned)
 {
     DWORD dwErrorCode;
+    PBYTE pPrintProcessorInfoAligned;
 
     dwErrorCode = RpcImpersonateClient(NULL);
     if (dwErrorCode != ERROR_SUCCESS)
@@ -86,20 +87,25 @@ _RpcEnumPrintProcessors(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD Level,
         return dwErrorCode;
     }
 
-    EnumPrintProcessorsW(pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
-    dwErrorCode = GetLastError();
+    pPrintProcessorInfoAligned = AlignRpcPtr(pPrintProcessorInfo, &cbBuf);
 
-    if (dwErrorCode == ERROR_SUCCESS)
+    if (EnumPrintProcessorsW(pName, pEnvironment, Level, pPrintProcessorInfoAligned, cbBuf, pcbNeeded, pcReturned))
     {
         // Replace absolute pointer addresses in the output by relative offsets.
         DWORD i;
-        PPRINTPROCESSOR_INFO_1W p = (PPRINTPROCESSOR_INFO_1W)pPrintProcessorInfo;
+        PPRINTPROCESSOR_INFO_1W p = (PPRINTPROCESSOR_INFO_1W)pPrintProcessorInfoAligned;
 
         for (i = 0; i < *pcReturned; i++)
             _MarshallDownPrintProcessorInfo(&p);
     }
+    else
+    {
+        dwErrorCode = GetLastError();
+    }
 
     RpcRevertToSelf();
+    UndoAlignRpcPtr(pPrintProcessorInfo, pPrintProcessorInfoAligned, cbBuf, pcbNeeded);
+
     return dwErrorCode;
 }
 
@@ -115,8 +121,8 @@ _RpcGetPrintProcessorDirectory(WINSPOOL_HANDLE pName, WCHAR* pEnvironment, DWORD
         return dwErrorCode;
     }
 
-    GetPrintProcessorDirectoryW(pName, pEnvironment, Level, pPrintProcessorDirectory, cbBuf, pcbNeeded);
-    dwErrorCode = GetLastError();
+    if (!GetPrintProcessorDirectoryW(pName, pEnvironment, Level, pPrintProcessorDirectory, cbBuf, pcbNeeded))
+        dwErrorCode = GetLastError();
 
     RpcRevertToSelf();
     return dwErrorCode;
index ab146e3..4127e37 100644 (file)
@@ -2,16 +2,27 @@
  * PROJECT:     ReactOS Local Port Monitor
  * LICENSE:     GNU LGPL v2.1 or any later version as published by the Free Software Foundation
  * PURPOSE:     Functions related to ports
- * COPYRIGHT:   Copyright 2015 Colin Finck <colin@reactos.org>
+ * COPYRIGHT:   Copyright 2015-2017 Colin Finck <colin@reactos.org>
  */
 
 #include "precomp.h"
 
-
 // Local Constants
 static const WCHAR wszNonspooledPrefix[] = L"NONSPOOLED_";
 static const DWORD cchNonspooledPrefix = _countof(wszNonspooledPrefix) - 1;
 
+static DWORD dwPortInfo1Offsets[] = {
+    FIELD_OFFSET(PORT_INFO_1W, pName),
+    MAXDWORD
+};
+
+static DWORD dwPortInfo2Offsets[] = {
+    FIELD_OFFSET(PORT_INFO_2W, pPortName),
+    FIELD_OFFSET(PORT_INFO_2W, pMonitorName),
+    FIELD_OFFSET(PORT_INFO_2W, pDescription),
+    MAXDWORD
+};
+
 
 /**
  * @name _GetNonspooledPortName
@@ -359,130 +370,60 @@ _FindPort(PLOCALMON_HANDLE pLocalmon, PCWSTR pwszPortName)
     return NULL;
 }
 
-static DWORD
-_LocalmonEnumPortsLevel1(PLOCALMON_HANDLE pLocalmon, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
+static void
+_LocalmonGetPortLevel1(PLOCALMON_PORT pPort, PPORT_INFO_1W* ppPortInfo, PBYTE* ppPortInfoEnd, PDWORD pcbNeeded)
 {
     DWORD cbPortName;
-    DWORD dwErrorCode;
-    DWORD dwPortCount = 0;
-    PBYTE pPortInfo;
-    PBYTE pPortString;
-    PLIST_ENTRY pEntry;
-    PLOCALMON_PORT pPort;
-    PORT_INFO_1W PortInfo1;
+    PWSTR pwszStrings[1];
 
-    // Count the required buffer size and the number of datatypes.
-    for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
+    // Calculate the string lengths.
+    if (!ppPortInfo)
     {
-        pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
-
         cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR);
-        *pcbNeeded += sizeof(PORT_INFO_1W) + cbPortName;
-        dwPortCount++;
-    }
 
-    // Check if the supplied buffer is large enough.
-    if (cbBuf < *pcbNeeded)
-    {
-        dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
-        goto Cleanup;
-    }
-
-    // Put the strings right after the last PORT_INFO_1W structure.
-    pPortInfo = pPorts;
-    pPortString = pPorts + dwPortCount * sizeof(PORT_INFO_1W);
-
-    // Copy over all ports.
-    for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
-    {
-        pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
-
-        // Copy the port name.
-        PortInfo1.pName = (PWSTR)pPortString;
-        cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR);
-        CopyMemory(pPortString, pPort->pwszPortName, cbPortName);
-        pPortString += cbPortName;
-
-        // Copy the structure and advance to the next one in the output buffer.
-        CopyMemory(pPortInfo, &PortInfo1, sizeof(PORT_INFO_1W));
-        pPortInfo += sizeof(PORT_INFO_1W);
+        *pcbNeeded += sizeof(PORT_INFO_1W) + cbPortName;
+        return;
     }
 
-    *pcReturned = dwPortCount;
-    dwErrorCode = ERROR_SUCCESS;
+    // Set the pName field.
+    pwszStrings[0] = pPort->pwszPortName;
 
-Cleanup:
-    return dwErrorCode;
+    // Copy the structure and advance to the next one in the output buffer.
+    *ppPortInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPortInfo), dwPortInfo1Offsets, *ppPortInfoEnd);
+    (*ppPortInfo)++;
 }
 
-static DWORD
-_LocalmonEnumPortsLevel2(PLOCALMON_HANDLE pLocalmon, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
+static void
+_LocalmonGetPortLevel2(PLOCALMON_PORT pPort, PPORT_INFO_2W* ppPortInfo, PBYTE* ppPortInfoEnd, PDWORD pcbNeeded)
 {
     DWORD cbPortName;
-    DWORD dwErrorCode;
-    DWORD dwPortCount = 0;
-    PBYTE pPortInfo;
-    PBYTE pPortString;
-    PLIST_ENTRY pEntry;
-    PLOCALMON_PORT pPort;
-    PORT_INFO_2W PortInfo2;
+    PWSTR pwszStrings[3];
 
-    // Count the required buffer size and the number of datatypes.
-    for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
+    // Calculate the string lengths.
+    if (!ppPortInfo)
     {
-        pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
-
         cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR);
-        *pcbNeeded += sizeof(PORT_INFO_2W) + cbPortName + cbLocalMonitor + cbLocalPort;
-        dwPortCount++;
-    }
 
-    // Check if the supplied buffer is large enough.
-    if (cbBuf < *pcbNeeded)
-    {
-        dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
-        goto Cleanup;
+        *pcbNeeded += sizeof(PORT_INFO_2W) + cbPortName + cbLocalMonitor + cbLocalPort;
+        return;
     }
 
-    // Put the strings right after the last PORT_INFO_2W structure.
-    pPortInfo = pPorts;
-    pPortString = pPorts + dwPortCount * sizeof(PORT_INFO_2W);
+    // All local ports are writable and readable.
+    (*ppPortInfo)->fPortType = PORT_TYPE_WRITE | PORT_TYPE_READ;
+    (*ppPortInfo)->Reserved = 0;
 
-    // Copy over all ports.
-    for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
-    {
-        pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
+    // Set the pPortName field.
+    pwszStrings[0] = pPort->pwszPortName;
 
-        // All local ports are writable and readable.
-        PortInfo2.fPortType = PORT_TYPE_WRITE | PORT_TYPE_READ;
-        PortInfo2.Reserved = 0;
+    // Set the pMonitorName field.
+    pwszStrings[1] = (PWSTR)pwszLocalMonitor;
 
-        // Copy the port name.
-        PortInfo2.pPortName = (PWSTR)pPortString;
-        cbPortName = (wcslen(pPort->pwszPortName) + 1) * sizeof(WCHAR);
-        CopyMemory(pPortString, pPort->pwszPortName, cbPortName);
-        pPortString += cbPortName;
-
-        // Copy the monitor name.
-        PortInfo2.pMonitorName = (PWSTR)pPortString;
-        CopyMemory(pPortString, pwszLocalMonitor, cbLocalMonitor);
-        pPortString += cbLocalMonitor;
-
-        // Copy the description.
-        PortInfo2.pDescription = (PWSTR)pPortString;
-        CopyMemory(pPortString, pwszLocalPort, cbLocalPort);
-        pPortString += cbLocalPort;
-
-        // Copy the structure and advance to the next one in the output buffer.
-        CopyMemory(pPortInfo, &PortInfo2, sizeof(PORT_INFO_2W));
-        pPortInfo += sizeof(PORT_INFO_2W);
-    }
+    // Set the pDescription field.
+    pwszStrings[2] = (PWSTR)pwszLocalPort;
 
-    *pcReturned = dwPortCount;
-    dwErrorCode = ERROR_SUCCESS;
-
-Cleanup:
-    return dwErrorCode;
+    // Copy the structure and advance to the next one in the output buffer.
+    *ppPortInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppPortInfo), dwPortInfo2Offsets, *ppPortInfoEnd);
+    (*ppPortInfo)++;
 }
 
 /**
@@ -590,20 +531,18 @@ BOOL WINAPI
 LocalmonEnumPorts(HANDLE hMonitor, PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
 {
     DWORD dwErrorCode;
+    PBYTE pPortInfoEnd;
+    PLIST_ENTRY pEntry;
     PLOCALMON_HANDLE pLocalmon = (PLOCALMON_HANDLE)hMonitor;
+    PLOCALMON_PORT pPort;
 
     TRACE("LocalmonEnumPorts(%p, %S, %lu, %p, %lu, %p, %p)\n", hMonitor, pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
 
-    // Sanity checks
-    if (!pLocalmon || (cbBuf && !pPorts) || !pcbNeeded || !pcReturned)
+    // Windows Server 2003's Local Port Monitor does absolutely no sanity checks here, not even for the Level parameter.
+    // As we implement a more modern MONITOR2-based Port Monitor, check at least our hMonitor.
+    if (!pLocalmon)
     {
-        dwErrorCode = ERROR_INVALID_PARAMETER;
-        goto Cleanup;
-    }
-
-    if (Level > 2)
-    {
-        dwErrorCode = ERROR_INVALID_LEVEL;
+        dwErrorCode = ERROR_INVALID_HANDLE;
         goto Cleanup;
     }
 
@@ -613,13 +552,42 @@ LocalmonEnumPorts(HANDLE hMonitor, PWSTR pName, DWORD Level, PBYTE pPorts, DWORD
 
     EnterCriticalSection(&pLocalmon->Section);
 
-    // The function behaves differently for each level.
-    if (Level == 1)
-        dwErrorCode = _LocalmonEnumPortsLevel1(pLocalmon, pPorts, cbBuf, pcbNeeded, pcReturned);
-    else if (Level == 2)
-        dwErrorCode = _LocalmonEnumPortsLevel2(pLocalmon, pPorts, cbBuf, pcbNeeded, pcReturned);
+    // Count the required buffer size and the number of ports.
+    for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
+    {
+        pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
+
+        if (Level == 1)
+            _LocalmonGetPortLevel1(pPort, NULL, NULL, pcbNeeded);
+        else if (Level == 2)
+            _LocalmonGetPortLevel2(pPort, NULL, NULL, pcbNeeded);
+    }
+
+    // Check if the supplied buffer is large enough.
+    if (cbBuf < *pcbNeeded)
+    {
+        LeaveCriticalSection(&pLocalmon->Section);
+        dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
+        goto Cleanup;
+    }
+
+    // Copy over the Port information.
+    pPortInfoEnd = &pPorts[*pcbNeeded];
+
+    for (pEntry = pLocalmon->RegistryPorts.Flink; pEntry != &pLocalmon->RegistryPorts; pEntry = pEntry->Flink)
+    {
+        pPort = CONTAINING_RECORD(pEntry, LOCALMON_PORT, Entry);
+
+        if (Level == 1)
+            _LocalmonGetPortLevel1(pPort, (PPORT_INFO_1W*)&pPorts, &pPortInfoEnd, NULL);
+        else if (Level == 2)
+            _LocalmonGetPortLevel2(pPort, (PPORT_INFO_2W*)&pPorts, &pPortInfoEnd, NULL);
+
+        (*pcReturned)++;
+    }
 
     LeaveCriticalSection(&pLocalmon->Section);
+    dwErrorCode = ERROR_SUCCESS;
 
 Cleanup:
     SetLastError(dwErrorCode);
@@ -729,6 +697,8 @@ LocalmonOpenPort(HANDLE hMonitor, PWSTR pName, PHANDLE pHandle)
         goto Cleanup;
     }
 
+    EnterCriticalSection(&pLocalmon->Section);
+
     // Check if this is a FILE: port.
     if (_wcsicmp(pName, L"FILE:") == 0)
     {
@@ -739,13 +709,10 @@ LocalmonOpenPort(HANDLE hMonitor, PWSTR pName, PHANDLE pHandle)
         pPort->hFile = INVALID_HANDLE_VALUE;
 
         // Add it to the list of file ports.
-        EnterCriticalSection(&pLocalmon->Section);
         InsertTailList(&pLocalmon->FilePorts, &pPort->Entry);
     }
     else
     {
-        EnterCriticalSection(&pLocalmon->Section);
-
         // Check if the port name is valid.
         pPort = _FindPort(pLocalmon, pName);
         if (!pPort)
index 69b5982..a3d61a2 100644 (file)
@@ -13,6 +13,31 @@ SKIPLIST GlobalJobList;
 // Local Variables
 static DWORD _dwLastJobID;
 
+// Local Constants
+static DWORD dwJobInfo1Offsets[] = {
+    FIELD_OFFSET(JOB_INFO_1W, pPrinterName),
+    FIELD_OFFSET(JOB_INFO_1W, pMachineName),
+    FIELD_OFFSET(JOB_INFO_1W, pUserName),
+    FIELD_OFFSET(JOB_INFO_1W, pDocument),
+    FIELD_OFFSET(JOB_INFO_1W, pDatatype),
+    FIELD_OFFSET(JOB_INFO_1W, pStatus),
+    MAXDWORD
+};
+
+static DWORD dwJobInfo2Offsets[] = {
+    FIELD_OFFSET(JOB_INFO_2W, pPrinterName),
+    FIELD_OFFSET(JOB_INFO_2W, pMachineName),
+    FIELD_OFFSET(JOB_INFO_2W, pUserName),
+    FIELD_OFFSET(JOB_INFO_2W, pDocument),
+    FIELD_OFFSET(JOB_INFO_2W, pNotifyName),
+    FIELD_OFFSET(JOB_INFO_2W, pDatatype),
+    FIELD_OFFSET(JOB_INFO_2W, pPrintProcessor),
+    FIELD_OFFSET(JOB_INFO_2W, pParameters),
+    FIELD_OFFSET(JOB_INFO_2W, pDriverName),
+    FIELD_OFFSET(JOB_INFO_2W, pStatus),
+    MAXDWORD
+};
+
 
 /**
  * @name _EqualStrings
@@ -135,6 +160,8 @@ _PrinterJobListCompareRoutine(PVOID FirstStruct, PVOID SecondStruct)
 DWORD
 GetJobFilePath(PCWSTR pwszExtension, DWORD dwJobID, PWSTR pwszOutput)
 {
+    TRACE("GetJobFilePath(%S, %lu, %p)\n", pwszExtension, dwJobID, pwszOutput);
+
     if (pwszOutput)
     {
         CopyMemory(pwszOutput, wszJobDirectory, cchJobDirectory * sizeof(WCHAR));
@@ -146,7 +173,7 @@ GetJobFilePath(PCWSTR pwszExtension, DWORD dwJobID, PWSTR pwszOutput)
 }
 
 BOOL
-InitializeGlobalJobList()
+InitializeGlobalJobList(void)
 {
     const WCHAR wszPath[] = L"\\?????.SHD";
     const DWORD cchPath = _countof(wszPath) - 1;
@@ -159,6 +186,8 @@ InitializeGlobalJobList()
     WCHAR wszFullPath[MAX_PATH];
     WIN32_FIND_DATAW FindData;
 
+    TRACE("InitializeGlobalJobList()\n");
+
     // This one is incremented in _GetNextJobID.
     _dwLastJobID = 0;
 
@@ -232,6 +261,8 @@ Cleanup:
 void
 InitializePrinterJobList(PLOCAL_PRINTER pPrinter)
 {
+    TRACE("InitializePrinterJobList(%p)\n", 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);
@@ -251,6 +282,8 @@ CreateJob(PLOCAL_PRINTER_HANDLE pPrinterHandle)
     RPC_WSTR pwszBinding = NULL;
     RPC_WSTR pwszMachineName = NULL;
 
+    TRACE("CreateJob(%p)\n", pPrinterHandle);
+
     // Create a new job.
     pJob = DllAllocSplMem(sizeof(LOCAL_JOB));
     if (!pJob)
@@ -366,6 +399,8 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, PBYTE pData, DWORD cbBuf, PDWORD pcbNe
     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
 
+    TRACE("LocalAddJob(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pData, cbBuf, pcbNeeded);
+
     // Check if this is a printer handle.
     if (pHandle->HandleType != HandleType_Printer)
     {
@@ -426,198 +461,146 @@ Cleanup:
 }
 
 
-static DWORD
-_LocalGetJobLevel1(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE* ppStart, PBYTE* ppEnd, DWORD cbBuf, PDWORD pcbNeeded)
+static void
+_LocalGetJobLevel1(PLOCAL_JOB pJob, PJOB_INFO_1W* ppJobInfo, PBYTE* ppJobInfoEnd, PDWORD pcbNeeded)
 {
-    DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
-    DWORD cbDocumentName = 0;  
-    DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
-    DWORD cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
+    DWORD cbDatatype;
+    DWORD cbDocumentName = 0;
+    DWORD cbMachineName;
+    DWORD cbPrinterName;
     DWORD cbStatus = 0;
     DWORD cbUserName = 0;
-    DWORD dwErrorCode;
-    JOB_INFO_1W JobInfo1 = { 0 };
+    PWSTR pwszStrings[6];
 
-    // Calculate the lengths of the optional values.
-    if (pJob->pwszDocumentName)
-        cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
-
-    if (pJob->pwszStatus)
-        cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
-
-    if (pJob->pwszUserName)
-        cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
-
-    // Check if the supplied buffer is large enough.
-    *pcbNeeded += sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName + cbPrinterName + cbStatus + cbUserName;
-    if (cbBuf < *pcbNeeded)
+    // Calculate the string lengths.
+    if (!ppJobInfo)
     {
-        dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
-        goto Cleanup;
-    }
+        cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
+        cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
+        cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
 
-    // Put the strings at the end of the buffer.
-    *ppEnd -= cbDatatype;
-    JobInfo1.pDatatype = (PWSTR)*ppEnd;
-    CopyMemory(*ppEnd, pJob->pwszDatatype, cbDatatype);
+        // These values are optional.
+        if (pJob->pwszDocumentName)
+            cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
 
-    *ppEnd -= cbMachineName;
-    JobInfo1.pMachineName = (PWSTR)*ppEnd;
-    CopyMemory(*ppEnd, pJob->pwszMachineName, cbMachineName);
+        if (pJob->pwszStatus)
+            cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
 
-    *ppEnd -= cbPrinterName;
-    JobInfo1.pPrinterName = (PWSTR)*ppEnd;
-    CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterName, cbPrinterName);
+        if (pJob->pwszUserName)
+            cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
 
-    // Copy the optional values.
-    if (cbDocumentName)
-    {
-        *ppEnd -= cbDocumentName;
-        JobInfo1.pDocument = (PWSTR)*ppEnd;
-        CopyMemory(*ppEnd, pJob->pwszDocumentName, cbDocumentName);
+        *pcbNeeded += sizeof(JOB_INFO_1W) + cbDatatype + cbDocumentName + cbMachineName + cbPrinterName + cbStatus + cbUserName;
+        return;
     }
 
-    if (cbStatus)
-    {
-        *ppEnd -= cbStatus;
-        JobInfo1.pStatus = (PWSTR)*ppEnd;
-        CopyMemory(*ppEnd, pJob->pwszStatus, cbStatus);
-    }
+    // Set the general fields.
+    (*ppJobInfo)->JobId = pJob->dwJobID;
+    (*ppJobInfo)->Status = pJob->dwStatus;
+    (*ppJobInfo)->Priority = pJob->dwPriority;
+    (*ppJobInfo)->TotalPages = pJob->dwTotalPages;
+    (*ppJobInfo)->PagesPrinted = pJob->dwPagesPrinted;
+    CopyMemory(&(*ppJobInfo)->Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
 
-    if (cbUserName)
+    // Position in JOB_INFO_1W 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->pPrinter->JobList, pJob, &(*ppJobInfo)->Position))
     {
-        *ppEnd -= cbUserName;
-        JobInfo1.pUserName = (PWSTR)*ppEnd;
-        CopyMemory(*ppEnd, pJob->pwszUserName, cbUserName);
+        ERR("pJob could not be located in the Printer's Job List!\n");
+        return;
     }
 
-    // Fill the rest of the structure.
-    JobInfo1.JobId = pJob->dwJobID;
-    JobInfo1.Priority = pJob->dwPriority;
-    JobInfo1.Status = pJob->dwStatus;
-    JobInfo1.TotalPages = pJob->dwTotalPages;
-    CopyMemory(&JobInfo1.Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
+    // Make the index 1-based.
+    ++(*ppJobInfo)->Position;
 
-    // Finally copy the structure to the output pointer.
-    CopyMemory(*ppStart, &JobInfo1, sizeof(JOB_INFO_1W));
-    *ppStart += sizeof(JOB_INFO_1W);
-    dwErrorCode = ERROR_SUCCESS;
+    // Set the pPrinterName field.
+    pwszStrings[0] = pJob->pPrinter->pwszPrinterName;
 
-Cleanup:
-    return dwErrorCode;
+    // Set the pMachineName field.
+    pwszStrings[1] = pJob->pwszMachineName;
+
+    // Set the pUserName field.
+    pwszStrings[2] = pJob->pwszUserName;
+
+    // Set the pDocument field.
+    pwszStrings[3] = pJob->pwszDocumentName;
+
+    // Set the pDatatype field.
+    pwszStrings[4] = pJob->pwszDatatype;
+
+    // Set the pStatus field.
+    pwszStrings[5] = pJob->pwszStatus;
+
+    // Finally copy the structure and advance to the next one in the output buffer.
+    *ppJobInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppJobInfo), dwJobInfo1Offsets, *ppJobInfoEnd);
+    (*ppJobInfo)++;
 }
 
-static DWORD
-_LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE* ppStart, PBYTE* ppEnd, DWORD cbBuf, PDWORD pcbNeeded)
+static void
+_LocalGetJobLevel2(PLOCAL_JOB pJob, PJOB_INFO_2W* ppJobInfo, PBYTE* ppJobInfoEnd, PDWORD pcbNeeded)
 {
-    DWORD cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
-    DWORD cbDevMode = pJob->pDevMode->dmSize + pJob->pDevMode->dmDriverExtra;
+    DWORD cbDatatype;
+    DWORD cbDevMode;
     DWORD cbDocumentName = 0;
-    DWORD cbDriverName = (wcslen(pJob->pPrinter->pwszPrinterDriver) + 1) * sizeof(WCHAR);
-    DWORD cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
+    DWORD cbDriverName;
+    DWORD cbMachineName;
     DWORD cbNotifyName = 0;
-    DWORD cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
-    DWORD cbPrintProcessor = (wcslen(pJob->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
+    DWORD cbPrinterName;
+    DWORD cbPrintProcessor;
     DWORD cbPrintProcessorParameters = 0;
     DWORD cbStatus = 0;
     DWORD cbUserName = 0;
-    DWORD dwErrorCode;
     FILETIME ftNow;
     FILETIME ftSubmitted;
-    JOB_INFO_2W JobInfo2 = { 0 };
+    PWSTR pwszStrings[10];
     ULARGE_INTEGER uliNow;
     ULARGE_INTEGER uliSubmitted;
 
-    // Calculate the lengths of the optional values.
-    if (pJob->pwszDocumentName)
-        cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
-
-    if (pJob->pwszNotifyName)
-        cbNotifyName = (wcslen(pJob->pwszNotifyName) + 1) * sizeof(WCHAR);
-
-    if (pJob->pwszPrintProcessorParameters)
-        cbPrintProcessorParameters = (wcslen(pJob->pwszPrintProcessorParameters) + 1) * sizeof(WCHAR);
+    // Calculate the string lengths.
+    cbDevMode = pJob->pDevMode->dmSize + pJob->pDevMode->dmDriverExtra;
 
-    if (pJob->pwszStatus)
-        cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
-
-    if (pJob->pwszUserName)
-        cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
-
-    // Check if the supplied buffer is large enough.
-    *pcbNeeded += sizeof(JOB_INFO_2W) + cbDatatype + cbDevMode + cbDocumentName + cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor + cbPrintProcessorParameters + cbStatus + cbUserName;
-    if (cbBuf < *pcbNeeded)
+    if (!ppJobInfo)
     {
-        dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
-        goto Cleanup;
-    }
-
-    // Put the strings at the end of the buffer.
-    *ppEnd -= cbDatatype;
-    JobInfo2.pDatatype = (PWSTR)*ppEnd;
-    CopyMemory(*ppEnd, pJob->pwszDatatype, cbDatatype);
-
-    *ppEnd -= cbDevMode;
-    JobInfo2.pDevMode = (PDEVMODEW)*ppEnd;
-    CopyMemory(*ppEnd, pJob->pDevMode, cbDevMode);
+        cbDatatype = (wcslen(pJob->pwszDatatype) + 1) * sizeof(WCHAR);
+        cbDriverName = (wcslen(pJob->pPrinter->pwszPrinterDriver) + 1) * sizeof(WCHAR);
+        cbMachineName = (wcslen(pJob->pwszMachineName) + 1) * sizeof(WCHAR);
+        cbPrinterName = (wcslen(pJob->pPrinter->pwszPrinterName) + 1) * sizeof(WCHAR);
+        cbPrintProcessor = (wcslen(pJob->pPrintProcessor->pwszName) + 1) * sizeof(WCHAR);
 
-    *ppEnd -= cbDriverName;
-    JobInfo2.pDriverName = (PWSTR)*ppEnd;
-    CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterDriver, cbDriverName);
+        // These values are optional.
+        if (pJob->pwszDocumentName)
+            cbDocumentName = (wcslen(pJob->pwszDocumentName) + 1) * sizeof(WCHAR);
 
-    *ppEnd -= cbMachineName;
-    JobInfo2.pMachineName = (PWSTR)*ppEnd;
-    CopyMemory(*ppEnd, pJob->pwszMachineName, cbMachineName);
+        if (pJob->pwszNotifyName)
+            cbNotifyName = (wcslen(pJob->pwszNotifyName) + 1) * sizeof(WCHAR);
 
-    *ppEnd -= cbPrinterName;
-    JobInfo2.pPrinterName = (PWSTR)*ppEnd;
-    CopyMemory(*ppEnd, pJob->pPrinter->pwszPrinterName, cbPrinterName);
+        if (pJob->pwszPrintProcessorParameters)
+            cbPrintProcessorParameters = (wcslen(pJob->pwszPrintProcessorParameters) + 1) * sizeof(WCHAR);
 
-    *ppEnd -= cbPrintProcessor;
-    JobInfo2.pPrintProcessor = (PWSTR)*ppEnd;
-    CopyMemory(*ppEnd, pJob->pPrintProcessor->pwszName, cbPrintProcessor);
+        if (pJob->pwszStatus)
+            cbStatus = (wcslen(pJob->pwszStatus) + 1) * sizeof(WCHAR);
 
-    // Copy the optional values.
-    if (cbDocumentName)
-    {
-        *ppEnd -= cbDocumentName;
-        JobInfo2.pDocument = (PWSTR)*ppEnd;
-        CopyMemory(*ppEnd, pJob->pwszDocumentName, cbDocumentName);
-    }
-
-    if (cbNotifyName)
-    {
-        *ppEnd -= cbNotifyName;
-        JobInfo2.pNotifyName = (PWSTR)*ppEnd;
-        CopyMemory(*ppEnd, pJob->pwszNotifyName, cbNotifyName);
-    }
-
-    if (cbPrintProcessorParameters)
-    {
-        *ppEnd -= cbPrintProcessorParameters;
-        JobInfo2.pParameters = (PWSTR)*ppEnd;
-        CopyMemory(*ppEnd, pJob->pwszPrintProcessorParameters, cbPrintProcessorParameters);
-    }
+        if (pJob->pwszUserName)
+            cbUserName = (wcslen(pJob->pwszUserName) + 1) * sizeof(WCHAR);
 
-    if (cbStatus)
-    {
-        *ppEnd -= cbStatus;
-        JobInfo2.pStatus = (PWSTR)*ppEnd;
-        CopyMemory(*ppEnd, pJob->pwszStatus, cbStatus);
+        *pcbNeeded += sizeof(JOB_INFO_2W) + cbDatatype + cbDevMode + cbDocumentName + cbDriverName + cbMachineName + cbNotifyName + cbPrinterName + cbPrintProcessor + cbPrintProcessorParameters + cbStatus + cbUserName;
+        return;
     }
 
-    if (cbUserName)
-    {
-        *ppEnd -= cbUserName;
-        JobInfo2.pUserName = (PWSTR)*ppEnd;
-        CopyMemory(*ppEnd, pJob->pwszUserName, cbUserName);
-    }
+    // Set the general fields.
+    (*ppJobInfo)->JobId = pJob->dwJobID;
+    (*ppJobInfo)->Status = pJob->dwStatus;
+    (*ppJobInfo)->Priority = pJob->dwPriority;
+    (*ppJobInfo)->StartTime = pJob->dwStartTime;
+    (*ppJobInfo)->UntilTime = pJob->dwUntilTime;
+    (*ppJobInfo)->TotalPages = pJob->dwTotalPages;
+    (*ppJobInfo)->PagesPrinted = pJob->dwPagesPrinted;
+    CopyMemory(&(*ppJobInfo)->Submitted, &pJob->stSubmitted, sizeof(SYSTEMTIME));
 
     // 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;
+        return;
     }
 
     GetSystemTimeAsFileTime(&ftNow);
@@ -625,37 +608,62 @@ _LocalGetJobLevel2(PLOCAL_PRINTER_HANDLE pPrinterHandle, PLOCAL_JOB pJob, PBYTE*
     uliSubmitted.HighPart = ftSubmitted.dwHighDateTime;
     uliNow.LowPart = ftNow.dwLowDateTime;
     uliNow.HighPart = ftNow.dwHighDateTime;
-    JobInfo2.Time = (DWORD)((uliNow.QuadPart - uliSubmitted.QuadPart) / 10000);
+    (*ppJobInfo)->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->pPrinter->JobList, pJob, &JobInfo2.Position))
+    if (!LookupElementSkiplist(&pJob->pPrinter->JobList, pJob, &(*ppJobInfo)->Position))
     {
-        dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
         ERR("pJob could not be located in the Printer's Job List!\n");
-        goto Cleanup;
+        return;
     }
 
     // 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(*ppStart, &JobInfo2, sizeof(JOB_INFO_2W));
-    *ppStart += sizeof(JOB_INFO_2W);
-    dwErrorCode = ERROR_SUCCESS;
+    ++(*ppJobInfo)->Position;
 
-Cleanup:
-    return dwErrorCode;
+    // FIXME!
+    FIXME("Setting pSecurityDescriptor and Size to 0 for now!\n");
+    (*ppJobInfo)->pSecurityDescriptor = NULL;
+    (*ppJobInfo)->Size = 0;
+
+    // Set the pDevMode field (and copy the DevMode).
+    *ppJobInfoEnd -= cbDevMode;
+    CopyMemory(*ppJobInfoEnd, pJob->pDevMode, cbDevMode);
+    (*ppJobInfo)->pDevMode = (PDEVMODEW)(*ppJobInfoEnd);
+
+    // Set the pPrinterName field.
+    pwszStrings[0] = pJob->pPrinter->pwszPrinterName;
+
+    // Set the pMachineName field.
+    pwszStrings[1] = pJob->pwszMachineName;
+
+    // Set the pUserName field.
+    pwszStrings[2] = pJob->pwszUserName;
+
+    // Set the pDocument field.
+    pwszStrings[3] = pJob->pwszDocumentName;
+
+    // Set the pNotifyName field.
+    pwszStrings[4] = pJob->pwszNotifyName;
+
+    // Set the pDatatype field.
+    pwszStrings[5] = pJob->pwszDatatype;
+
+    // Set the pPrintProcessor field.
+    pwszStrings[6] = pJob->pPrintProcessor->pwszName;
+
+    // Set the pParameters field.
+    pwszStrings[7] = pJob->pwszPrintProcessorParameters;
+
+    // Set the pDriverName field.
+    pwszStrings[8] = pJob->pPrinter->pwszPrinterDriver;
+
+    // Set the pStatus field.
+    pwszStrings[9] = pJob->pwszStatus;
+
+    // Finally copy the structure and advance to the next one in the output buffer.
+    *ppJobInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppJobInfo), dwJobInfo2Offsets, *ppJobInfoEnd);
+    (*ppJobInfo)++;
 }
 
 BOOL WINAPI
@@ -667,6 +675,8 @@ LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf
     PLOCAL_JOB pJob;
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
 
+    TRACE("LocalGetJob(%p, %lu, %lu, %p, %lu, %p)\n", hPrinter, JobId, Level, pStart, cbBuf, pcbNeeded);
+
     // Check if this is a printer handle.
     pHandle = (PLOCAL_HANDLE)hPrinter;
     if (pHandle->HandleType != HandleType_Printer)
@@ -685,16 +695,37 @@ LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf
         goto Cleanup;
     }
 
-    // Begin counting.
+    if (Level > 2)
+    {
+        // The caller supplied an invalid level for GetJob.
+        dwErrorCode = ERROR_INVALID_LEVEL;
+        goto Cleanup;
+    }
+
+    // Count the required buffer size.
     *pcbNeeded = 0;
 
-    // The function behaves differently for each level.
     if (Level == 1)
-        dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded);
+        _LocalGetJobLevel1(pJob, NULL, NULL, pcbNeeded);
     else if (Level == 2)
-        dwErrorCode = _LocalGetJobLevel2(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded);
-    else
-        dwErrorCode = ERROR_INVALID_LEVEL;
+        _LocalGetJobLevel2(pJob, NULL, NULL, pcbNeeded);
+
+    // Check if the supplied buffer is large enough.
+    if (cbBuf < *pcbNeeded)
+    {
+        dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
+        goto Cleanup;
+    }
+
+    // Copy over the Job information.
+    pEnd = &pStart[*pcbNeeded];
+
+    if (Level == 1)
+        _LocalGetJobLevel1(pJob, (PJOB_INFO_1W*)&pStart, &pEnd, NULL);
+    else if (Level == 2)
+        _LocalGetJobLevel2(pJob, (PJOB_INFO_2W*)&pStart, &pEnd, NULL);
+
+    dwErrorCode = ERROR_SUCCESS;
 
 Cleanup:
     SetLastError(dwErrorCode);
@@ -938,6 +969,8 @@ LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Com
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
     WCHAR wszFullPath[MAX_PATH];
 
+    TRACE("LocalSetJob(%p, %lu, %lu, %p, %lu)\n", hPrinter, JobId, Level, pJobInfo, Command);
+
     // Check if this is a printer handle.
     pHandle = (PLOCAL_HANDLE)hPrinter;
     if (pHandle->HandleType != HandleType_Printer)
@@ -1012,13 +1045,15 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
 {
     DWORD dwErrorCode;
     DWORD i;
-    PBYTE pEnd = &pStart[cbBuf];
+    PBYTE pEnd;
     PLOCAL_HANDLE pHandle;
     PLOCAL_JOB pJob;
     PSKIPLIST_NODE pFirstJobNode;
     PSKIPLIST_NODE pNode;
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
 
+    TRACE("LocalEnumJobs(%p, %lu, %lu, %lu, %p, %lu, %p, %p)\n", hPrinter, FirstJob, NoJobs, Level, pStart, cbBuf, pcbNeeded, pcReturned);
+
     // Check if this is a printer handle.
     pHandle = (PLOCAL_HANDLE)hPrinter;
     if (pHandle->HandleType != HandleType_Printer)
@@ -1051,11 +1086,10 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
     {
         pJob = (PLOCAL_JOB)pNode->Element;
 
-        // The function behaves differently for each level.
         if (Level == 1)
-            _LocalGetJobLevel1(pPrinterHandle, pJob, NULL, NULL, 0, pcbNeeded);
+            _LocalGetJobLevel1(pJob, NULL, NULL, pcbNeeded);
         else if (Level == 2)
-            _LocalGetJobLevel2(pPrinterHandle, pJob, NULL, NULL, 0, pcbNeeded);
+            _LocalGetJobLevel2(pJob, NULL, NULL, pcbNeeded);
 
         // We stop either when there are no more jobs in the list or when the caller didn't request more, whatever comes first.
         i++;
@@ -1069,26 +1103,19 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
         goto Cleanup;
     }
 
-    // Begin counting again and also empty the given buffer.
-    *pcbNeeded = 0;
-    ZeroMemory(pStart, cbBuf);
-
-    // Now call the same functions again to copy the actual data for each job into the buffer.
+    // Copy over the Job information.
     i = 0;
     pNode = pFirstJobNode;
+    pEnd = &pStart[*pcbNeeded];
 
     while (i < NoJobs && pNode)
     {
         pJob = (PLOCAL_JOB)pNode->Element;
 
-        // The function behaves differently for each level.
         if (Level == 1)
-            dwErrorCode = _LocalGetJobLevel1(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded);
+            _LocalGetJobLevel1(pJob, (PJOB_INFO_1W*)&pStart, &pEnd, NULL);
         else if (Level == 2)
-            dwErrorCode = _LocalGetJobLevel2(pPrinterHandle, pJob, &pStart, &pEnd, cbBuf, pcbNeeded);
-
-        if (dwErrorCode != ERROR_SUCCESS)
-            goto Cleanup;
+            _LocalGetJobLevel2(pJob, (PJOB_INFO_2W*)&pStart, &pEnd, NULL);
 
         // We stop either when there are no more jobs in the list or when the caller didn't request more, whatever comes first.
         i++;
@@ -1114,6 +1141,8 @@ LocalScheduleJob(HANDLE hPrinter, DWORD dwJobID)
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
     WCHAR wszFullPath[MAX_PATH];
 
+    TRACE("LocalScheduleJob(%p, %lu)\n", hPrinter, dwJobID);
+
     // Check if this is a printer handle.
     if (pHandle->HandleType != HandleType_Printer)
     {
@@ -1190,6 +1219,8 @@ ReadJobShadowFile(PCWSTR pwszFilePath)
     PWSTR pwszPrinterName;
     PWSTR pwszPrintProcessor;
 
+    TRACE("ReadJobShadowFile(%S)\n", pwszFilePath);
+
     // Try to open the file.
     hFile = CreateFileW(pwszFilePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
     if (hFile == INVALID_HANDLE_VALUE)
@@ -1308,6 +1339,8 @@ WriteJobShadowFile(PWSTR pwszFilePath, const PLOCAL_JOB pJob)
     HANDLE hSPLFile = INVALID_HANDLE_VALUE;
     PSHD_HEADER pShadowFile = NULL;
 
+    TRACE("WriteJobShadowFile(%S, %p)\n", pwszFilePath, pJob);
+
     // Try to open the SHD file.
     hSHDFile = CreateFileW(pwszFilePath, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
     if (hSHDFile == INVALID_HANDLE_VALUE)
@@ -1441,7 +1474,9 @@ void
 FreeJob(PLOCAL_JOB pJob)
 {
     PWSTR pwszSHDFile;
-    
+
+    TRACE("FreeJob(%p)\n", pJob);
+
     // Remove the Job from both Job Lists.
     DeleteElementSkiplist(&pJob->pPrinter->JobList, pJob);
     DeleteElementSkiplist(&GlobalJobList, pJob);
index 5dd0436..16f2b9c 100644 (file)
@@ -245,6 +245,8 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 BOOL WINAPI
 InitializePrintProvidor(LPPRINTPROVIDOR pPrintProvidor, DWORD cbPrintProvidor, LPWSTR pFullRegistryPath)
 {
+    TRACE("InitializePrintProvidor(%p, %lu, %S)\n", pPrintProvidor, cbPrintProvidor, pFullRegistryPath);
+
     CopyMemory(pPrintProvidor, &_PrintProviderFunctions, min(cbPrintProvidor, sizeof(PRINTPROVIDOR)));
 
     SetLastError(ERROR_SUCCESS);
index d9222a0..1888dc4 100644 (file)
 // Global Variables
 LIST_ENTRY PrintMonitorList;
 
+// Local Constants
+static DWORD dwMonitorInfo1Offsets[] = {
+    FIELD_OFFSET(MONITOR_INFO_1W, pName),
+    MAXDWORD
+};
+
+static DWORD dwMonitorInfo2Offsets[] = {
+    FIELD_OFFSET(MONITOR_INFO_2W, pName),
+    FIELD_OFFSET(MONITOR_INFO_2W, pEnvironment),
+    FIELD_OFFSET(MONITOR_INFO_2W, pDLLName),
+    MAXDWORD
+};
+
 
 PLOCAL_PRINT_MONITOR
 FindPrintMonitor(PCWSTR pwszName)
@@ -17,6 +30,8 @@ FindPrintMonitor(PCWSTR pwszName)
     PLIST_ENTRY pEntry;
     PLOCAL_PRINT_MONITOR pPrintMonitor;
 
+    TRACE("FindPrintMonitor(%S)\n", pwszName);
+
     if (!pwszName)
         return NULL;
 
@@ -32,7 +47,7 @@ FindPrintMonitor(PCWSTR pwszName)
 }
 
 BOOL
-InitializePrintMonitorList()
+InitializePrintMonitorList(void)
 {
     const WCHAR wszMonitorsPath[] = L"SYSTEM\\CurrentControlSet\\Control\\Print\\Monitors";
     const DWORD cchMonitorsPath = _countof(wszMonitorsPath) - 1;
@@ -51,6 +66,8 @@ InitializePrintMonitorList()
     PLOCAL_PRINT_MONITOR pPrintMonitor = NULL;
     PWSTR pwszRegistryPath = NULL;
 
+    TRACE("InitializePrintMonitorList()\n");
+
     // Initialize an empty list for our Print Monitors.
     InitializeListHead(&PrintMonitorList);
 
@@ -236,17 +253,69 @@ Cleanup:
     return (dwErrorCode == ERROR_SUCCESS);
 }
 
-BOOL WINAPI
-LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
+static void
+_LocalGetMonitorLevel1(PLOCAL_PRINT_MONITOR pPrintMonitor, PMONITOR_INFO_1W* ppMonitorInfo, PBYTE* ppMonitorInfoEnd, PDWORD pcbNeeded)
+{
+    DWORD cbMonitorName;
+    PWSTR pwszStrings[1];
+
+    // Calculate the string lengths.
+    if (!ppMonitorInfo)
+    {
+        cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR);
+
+        *pcbNeeded += sizeof(MONITOR_INFO_1W) + cbMonitorName;
+        return;
+    }
+
+    // Set the pName field.
+    pwszStrings[0] = pPrintMonitor->pwszName;
+
+    // Copy the structure and advance to the next one in the output buffer.
+    *ppMonitorInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppMonitorInfo), dwMonitorInfo1Offsets, *ppMonitorInfoEnd);
+    (*ppMonitorInfo)++;
+}
+
+static void
+_LocalGetMonitorLevel2(PLOCAL_PRINT_MONITOR pPrintMonitor, PMONITOR_INFO_2W* ppMonitorInfo, PBYTE* ppMonitorInfoEnd, PDWORD pcbNeeded)
 {
     DWORD cbFileName;
     DWORD cbMonitorName;
+    PWSTR pwszStrings[3];
+
+    // Calculate the string lengths.
+    if (!ppMonitorInfo)
+    {
+        cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR);
+        cbFileName = (wcslen(pPrintMonitor->pwszFileName) + 1) * sizeof(WCHAR);
+
+        *pcbNeeded += sizeof(MONITOR_INFO_2W) + cbMonitorName + cbCurrentEnvironment + cbFileName;
+        return;
+    }
+
+    // Set the pName field.
+    pwszStrings[0] = pPrintMonitor->pwszName;
+
+    // Set the pEnvironment field.
+    pwszStrings[1] = (PWSTR)wszCurrentEnvironment;
+
+    // Set the pDLLName field.
+    pwszStrings[2] = pPrintMonitor->pwszFileName;
+
+    // Copy the structure and advance to the next one in the output buffer.
+    *ppMonitorInfoEnd = PackStrings(pwszStrings, (PBYTE)(*ppMonitorInfo), dwMonitorInfo2Offsets, *ppMonitorInfoEnd);
+    (*ppMonitorInfo)++;
+}
+
+BOOL WINAPI
+LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
+{
     DWORD dwErrorCode;
-    PBYTE pStart;
-    PBYTE pEnd;
+    PBYTE pMonitorInfoEnd;
     PLIST_ENTRY pEntry;
     PLOCAL_PRINT_MONITOR pPrintMonitor;
-    MONITOR_INFO_2W MonitorInfo2;               // MONITOR_INFO_1W is a subset of MONITOR_INFO_2W, so we can handle both in one function here.
+
+    TRACE("LocalEnumMonitors(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pMonitors, cbBuf, pcbNeeded, pcReturned);
 
     // Sanity checks.
     if (Level > 2)
@@ -255,12 +324,6 @@ LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD
         goto Cleanup;
     }
 
-    if ((cbBuf && !pMonitors) || !pcbNeeded || !pcReturned)
-    {
-        dwErrorCode = ERROR_INVALID_PARAMETER;
-        goto Cleanup;
-    }
-
     // Begin counting.
     *pcbNeeded = 0;
     *pcReturned = 0;
@@ -270,13 +333,10 @@ LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD
     {
         pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry);
 
-        cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR);
-        cbFileName = (wcslen(pPrintMonitor->pwszFileName) + 1) * sizeof(WCHAR);
-
         if (Level == 1)
-            *pcbNeeded += sizeof(MONITOR_INFO_1W) + cbMonitorName;
-        else
-            *pcbNeeded += sizeof(MONITOR_INFO_2W) + cbMonitorName + cbCurrentEnvironment + cbFileName;
+            _LocalGetMonitorLevel1(pPrintMonitor, NULL, NULL, pcbNeeded);
+        else if (Level == 2)
+            _LocalGetMonitorLevel2(pPrintMonitor, NULL, NULL, pcbNeeded);
     }
 
     // Check if the supplied buffer is large enough.
@@ -286,43 +346,17 @@ LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD
         goto Cleanup;
     }
 
-    // Put the strings at the end of the buffer.
-    pStart = pMonitors;
-    pEnd = &pMonitors[cbBuf];
+    // Copy over the Monitor information.
+    pMonitorInfoEnd = &pMonitors[*pcbNeeded];
 
     for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink)
     {
         pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry);
 
-        // Copy the monitor name.
-        cbMonitorName = (wcslen(pPrintMonitor->pwszName) + 1) * sizeof(WCHAR);
-        pEnd -= cbMonitorName;
-        MonitorInfo2.pName = (PWSTR)pEnd;
-        CopyMemory(pEnd, pPrintMonitor->pwszName, cbMonitorName);
-
         if (Level == 1)
-        {
-            // Finally copy the structure.
-            CopyMemory(pStart, &MonitorInfo2, sizeof(MONITOR_INFO_1W));
-            pStart += sizeof(MONITOR_INFO_1W);
-        }
-        else
-        {
-            // Copy the environment.
-            pEnd -= cbCurrentEnvironment;
-            MonitorInfo2.pEnvironment = (PWSTR)pEnd;
-            CopyMemory(pEnd, wszCurrentEnvironment, cbCurrentEnvironment);
-
-            // Copy the file name.
-            cbFileName = (wcslen(pPrintMonitor->pwszFileName) + 1) * sizeof(WCHAR);
-            pEnd -= cbFileName;
-            MonitorInfo2.pDLLName = (PWSTR)pEnd;
-            CopyMemory(pEnd, pPrintMonitor->pwszFileName, cbFileName);
-
-            // Finally copy the structure.
-            CopyMemory(pStart, &MonitorInfo2, sizeof(MONITOR_INFO_2W));
-            pStart += sizeof(MONITOR_INFO_2W);
-        }
+            _LocalGetMonitorLevel1(pPrintMonitor, (PMONITOR_INFO_1W*)&pMonitors, &pMonitorInfoEnd, NULL);
+        else if (Level == 2)
+            _LocalGetMonitorLevel2(pPrintMonitor, (PMONITOR_INFO_2W*)&pMonitors, &pMonitorInfoEnd, NULL);
 
         (*pcReturned)++;
     }
index bb51d9c..6ee8029 100644 (file)
@@ -17,6 +17,8 @@ FindPort(PCWSTR pwszName)
     PLIST_ENTRY pEntry;
     PLOCAL_PORT pPort;
 
+    TRACE("FindPort(%S)\n", pwszName);
+
     if (!pwszName)
         return NULL;
 
@@ -32,7 +34,7 @@ FindPort(PCWSTR pwszName)
 }
 
 BOOL
-InitializePortList()
+InitializePortList(void)
 {
     BOOL bReturnValue;
     DWORD cbNeeded;
@@ -46,6 +48,8 @@ InitializePortList()
     PPORT_INFO_1W p;
     PPORT_INFO_1W pPortInfo1 = NULL;
 
+    TRACE("InitializePortList()\n");
+
     // Initialize an empty list for our Ports.
     InitializeListHead(&_PortList);
 
@@ -136,7 +140,7 @@ Cleanup:
 BOOL WINAPI
 LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
 {
-    BOOL bReturnValue;
+    BOOL bReturnValue = TRUE;
     DWORD cbCallBuffer;
     DWORD cbNeeded;
     DWORD dwReturned;
@@ -144,12 +148,7 @@ LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNe
     PLOCAL_PRINT_MONITOR pPrintMonitor;
     PLIST_ENTRY pEntry;
 
-    // Sanity checks.
-    if ((cbBuf && !pPorts) || !pcbNeeded || !pcReturned)
-    {
-        SetLastError(ERROR_INVALID_PARAMETER);
-        return FALSE;
-    }
+    TRACE("LocalEnumPorts(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
 
     // Begin counting.
     *pcbNeeded = 0;
index 5241e43..93789c2 100644 (file)
@@ -273,12 +273,12 @@ extern DWORD cchSpoolDirectory;
 // monitors.c
 extern LIST_ENTRY PrintMonitorList;
 PLOCAL_PRINT_MONITOR FindPrintMonitor(PCWSTR pwszName);
-BOOL InitializePrintMonitorList();
+BOOL InitializePrintMonitorList(void);
 BOOL WINAPI LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
 
 // ports.c
 PLOCAL_PORT FindPort(PCWSTR pwszName);
-BOOL InitializePortList();
+BOOL InitializePortList(void);
 BOOL WINAPI LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
 
 // printerdata.c
@@ -289,7 +289,7 @@ DWORD WINAPI LocalSetPrinterDataEx(HANDLE hPrinter, LPCWSTR pKeyName, LPCWSTR pV
 
 // printers.c
 extern SKIPLIST PrinterList;
-BOOL InitializePrinterList();
+BOOL InitializePrinterList(void);
 BOOL WINAPI LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DWORD cbBuf, LPDWORD pcbNeeded, LPDWORD pcReturned);
 BOOL WINAPI LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded);
 BOOL WINAPI LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault);
@@ -307,7 +307,7 @@ DWORD WINAPI PrintingThreadProc(PLOCAL_JOB pJob);
 // printprocessors.c
 BOOL FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype);
 PLOCAL_PRINT_PROCESSOR FindPrintProcessor(PCWSTR pwszName);
-BOOL InitializePrintProcessorList();
+BOOL InitializePrintProcessorList(void);
 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);
index 491d432..b8ef863 100644 (file)
@@ -10,6 +10,8 @@
 DWORD WINAPI
 LocalGetPrinterData(HANDLE hPrinter, PWSTR pValueName, PDWORD pType, PBYTE pData, DWORD nSize, PDWORD pcbNeeded)
 {
+    TRACE("LocalGetPrinterData(%p, %S, %p, %p, %lu, %p)\n", hPrinter, pValueName, pType, pData, nSize, pcbNeeded);
+
     // The ReactOS Printing Stack forwards all GetPrinterData calls to GetPrinterDataEx as soon as possible.
     // This function may only be called if localspl.dll is used together with Windows Printing Stack components.
     WARN("This function should never be called!\n");
@@ -316,6 +318,8 @@ LocalGetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName, PDWOR
     DWORD dwTemp;
     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
 
+    TRACE("LocalGetPrinterDataEx(%p, %S, %S, %p, %p, %lu, %p)\n", hPrinter, pKeyName, pValueName, pType, pData, nSize, pcbNeeded);
+
     // Even if GetPrinterDataExW in winspool ensures that the RPC function is never called without a valid pointer for pType,
     // it's officially optional. Windows' fpGetPrinterDataEx also works with NULL for pType!
     // Ensure here that it is always set to simplify the code later.
@@ -356,6 +360,8 @@ LocalGetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName, PDWOR
 DWORD WINAPI
 LocalSetPrinterData(HANDLE hPrinter, PWSTR pValueName, DWORD Type, PBYTE pData, DWORD cbData)
 {
+    TRACE("LocalSetPrinterData(%p, %S, %lu, %p, %lu)\n", hPrinter, pValueName, Type, pData, cbData);
+
     // The ReactOS Printing Stack forwards all SetPrinterData calls to SetPrinterDataEx as soon as possible.
     // This function may only be called if localspl.dll is used together with Windows Printing Stack components.
     WARN("This function should never be called!\n");
@@ -446,6 +452,8 @@ LocalSetPrinterDataEx(HANDLE hPrinter, PCWSTR pKeyName, PCWSTR pValueName, DWORD
     DWORD dwErrorCode;
     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
 
+    TRACE("LocalSetPrinterDataEx(%p, %S, %S, %lu, %p, %lu)\n", hPrinter, pKeyName, pValueName, Type, pData, cbData);
+
     if (!pHandle)
     {
         dwErrorCode = ERROR_INVALID_HANDLE;
index e79cf63..8825e07 100644 (file)
@@ -119,6 +119,8 @@ InitializePrinterList()
     PWSTR pwszPrintProcessor = NULL;
     WCHAR wszPrinterName[MAX_PRINTER_NAME + 1];
 
+    TRACE("InitializePrinterList()\n");
+
     // Initialize an empty list for our printers.
     InitializeSkiplist(&PrinterList, DllAllocSplMem, _PrinterListCompareRoutine, (PSKIPLIST_FREE_ROUTINE)DllFreeSplMem);
 
@@ -864,12 +866,13 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
 {
     DWORD cchComputerName = 0;
     DWORD dwErrorCode;
-    DWORD i;
     PBYTE pPrinterInfoEnd;
     PSKIPLIST_NODE pNode;
     WCHAR wszComputerName[2 + MAX_COMPUTERNAME_LENGTH + 1 + 1] = { 0 };
     PLOCAL_PRINTER pPrinter;
 
+    TRACE("LocalEnumPrinters(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
+
     // Do no sanity checks or assertions for pcbNeeded and pcReturned here.
     // This is verified and required by localspl_apitest!
 
@@ -916,7 +919,6 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
         goto Cleanup;
 
     // Count the required buffer size and the number of printers.
-    i = 0;
     for (pNode = PrinterList.Head.Next[0]; pNode; pNode = pNode->Next[0])
     {
         pPrinter = (PLOCAL_PRINTER)pNode->Element;
@@ -929,7 +931,6 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
         }
 
         pfnGetPrinterLevels[Level](pPrinter, NULL, NULL, pcbNeeded, cchComputerName, wszComputerName);
-        i++;
     }
 
     // Check if the supplied buffer is large enough.
@@ -951,9 +952,9 @@ LocalEnumPrinters(DWORD Flags, LPWSTR Name, DWORD Level, LPBYTE pPrinterEnum, DW
             continue;
 
         pfnGetPrinterLevels[Level](pPrinter, &pPrinterEnum, &pPrinterInfoEnd, NULL, cchComputerName, wszComputerName);
+        (*pcReturned)++;
     }
 
-    *pcReturned = i;
     dwErrorCode = ERROR_SUCCESS;
 
 Cleanup:
@@ -969,6 +970,8 @@ LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDW
     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
 
+    TRACE("LocalGetPrinter(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
+
     // Sanity checks.
     if (!pHandle)
     {
@@ -993,6 +996,7 @@ LocalGetPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDW
     }
 
     // Count the required buffer size.
+    *pcbNeeded = 0;
     pfnGetPrinterLevels[Level](pPrinterHandle->pPrinter, NULL, NULL, pcbNeeded, 0, NULL);
 
     // Check if the supplied buffer is large enough.
@@ -1363,6 +1367,8 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
     PWSTR pwszSecondParameter;
     WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
 
+    TRACE("LocalOpenPrinter(%S, %p, %p)\n", lpPrinterName, phPrinter, pDefault);
+
     ASSERT(phPrinter);
     *phPrinter = NULL;
 
@@ -1494,6 +1500,8 @@ LocalReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
     PLOCAL_PORT_HANDLE pPortHandle;
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
 
+    TRACE("LocalReadPrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pNoBytesRead);
+
     // Sanity checks.
     if (!pHandle)
     {
@@ -1568,6 +1576,8 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
     PLOCAL_PORT_HANDLE pPortHandle;
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
 
+    TRACE("LocalStartDocPrinter(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
+
     // Sanity checks.
     if (!pHandle)
     {
@@ -1678,6 +1688,8 @@ LocalStartPagePrinter(HANDLE hPrinter)
     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
 
+    TRACE("LocalStartPagePrinter(%p)\n", hPrinter);
+
     // Sanity checks.
     if (!pHandle || pHandle->HandleType != HandleType_Printer)
     {
@@ -1712,6 +1724,8 @@ LocalWritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
     PLOCAL_PORT_HANDLE pPortHandle;
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
 
+    TRACE("LocalWritePrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pcWritten);
+
     // Sanity checks.
     if (!pHandle)
     {
@@ -1783,6 +1797,8 @@ LocalEndPagePrinter(HANDLE hPrinter)
     DWORD dwErrorCode;
     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
 
+    TRACE("LocalEndPagePrinter(%p)\n", hPrinter);
+
     // Sanity checks.
     if (!pHandle || pHandle->HandleType != HandleType_Printer)
     {
@@ -1807,6 +1823,8 @@ LocalEndDocPrinter(HANDLE hPrinter)
     PLOCAL_PORT_HANDLE pPortHandle;
     PLOCAL_PRINTER_HANDLE pPrinterHandle;
 
+    TRACE("LocalEndDocPrinter(%p)\n", hPrinter);
+
     // Sanity checks.
     if (!pHandle)
     {
@@ -1902,6 +1920,8 @@ LocalClosePrinter(HANDLE hPrinter)
 {
     PLOCAL_HANDLE pHandle = (PLOCAL_HANDLE)hPrinter;
 
+    TRACE("LocalClosePrinter(%p)\n", hPrinter);
+
     if (!pHandle)
     {
         SetLastError(ERROR_INVALID_HANDLE);
index 9197c4a..8da0297 100644 (file)
@@ -25,6 +25,8 @@ PrintingThreadProc(PLOCAL_JOB pJob)
     PWSTR pwszPrinterPort = NULL;
     PWSTR pwszSPLFile = NULL;
 
+    TRACE("PrintingThreadProc(%p)\n", pJob);
+
     // Prepare the pPrinterName parameter.
     // This is the string for LocalOpenPrinter to open a port (e.g. "LPT1:, Port").
     cchPortName = wcslen(pJob->pPrinter->pPort->pwszName);
index 1b948da..69276f6 100644 (file)
@@ -82,6 +82,8 @@ FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype)
     DWORD i;
     PDATATYPES_INFO_1W pCurrentDatatype = pPrintProcessor->pDatatypesInfo1;
 
+    TRACE("FindDatatype(%p, %S)\n", pPrintProcessor, pwszDatatype);
+
     if (!pwszDatatype)
         return FALSE;
 
@@ -102,6 +104,8 @@ FindPrintProcessor(PCWSTR pwszName)
     PLIST_ENTRY pEntry;
     PLOCAL_PRINT_PROCESSOR pPrintProcessor;
 
+    TRACE("FindPrintProcessor(%S)\n", pwszName);
+
     if (!pwszName)
         return NULL;
 
@@ -122,7 +126,7 @@ FindPrintProcessor(PCWSTR pwszName)
  * Initializes a singly linked list of locally available Print Processors.
  */
 BOOL
-InitializePrintProcessorList()
+InitializePrintProcessorList(void)
 {
     DWORD cbDatatypes;
     DWORD cbFileName;
@@ -140,6 +144,8 @@ InitializePrintProcessorList()
     WCHAR wszFileName[MAX_PATH];
     WCHAR wszPrintProcessorPath[MAX_PATH];
 
+    TRACE("InitializePrintProcessorList()\n");
+
     // Initialize an empty list for our Print Processors.
     InitializeListHead(&_PrintProcessorList);
     
@@ -398,6 +404,8 @@ LocalEnumPrintProcessorDatatypes(LPWSTR pName, LPWSTR pPrintProcessorName, DWORD
     DWORD dwErrorCode;
     PLOCAL_PRINT_PROCESSOR pPrintProcessor;
 
+    TRACE("LocalEnumPrintProcessorDatatypes(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pPrintProcessorName, Level, pDatatypes, cbBuf, pcbNeeded, pcReturned);
+
     // Sanity checks
     if (Level != 1)
     {
@@ -474,6 +482,8 @@ LocalEnumPrintProcessors(LPWSTR pName, LPWSTR pEnvironment, DWORD Level, LPBYTE
     PRINTPROCESSOR_INFO_1W PrintProcessorInfo1;
     PWSTR pwszTemp = NULL;
 
+    TRACE("LocalEnumPrintProcessors(%S, %S, %lu, %p, %lu, %p, %p)\n", pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded, pcReturned);
+
     // Sanity checks
     if (Level != 1)
     {
@@ -630,6 +640,8 @@ LocalGetPrintProcessorDirectory(PWSTR pName, PWSTR pEnvironment, DWORD Level, PB
     HKEY hKey = NULL;
     PWSTR pwszDirectory = (PWSTR)pPrintProcessorInfo;
 
+    TRACE("LocalGetPrintProcessorDirectory(%S, %S, %lu, %p, %lu, %p)\n", pName, pEnvironment, Level, pPrintProcessorInfo, cbBuf, pcbNeeded);
+
     // Verify pEnvironment and open its registry key.
     dwErrorCode = _OpenEnvironment(pEnvironment, &hKey);
     if (dwErrorCode != ERROR_SUCCESS)