[LOCALSPL]
authorColin Finck <colin@reactos.org>
Mon, 13 Jul 2015 10:18:07 +0000 (10:18 +0000)
committerColin Finck <colin@reactos.org>
Mon, 13 Jul 2015 10:18:07 +0000 (10:18 +0000)
- Rewrite LocalOpenPrinter to also properly support opening Port and Xcv handles.
- Manage a list of Ports and their associated Print Monitors.
- const-ify some parameters.

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

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/printers.c
reactos/win32ss/printing/providers/localspl/printprocessors.c

index 47ca6af..b080bf9 100644 (file)
@@ -218,7 +218,7 @@ LocalAddJob(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcb
 
     // Check if this is a printer handle.
     pHandle = (PLOCAL_HANDLE)hPrinter;
-    if (pHandle->HandleType != Printer)
+    if (pHandle->HandleType != HandleType_Printer)
     {
         dwErrorCode = ERROR_INVALID_HANDLE;
         goto Cleanup;
@@ -579,7 +579,7 @@ LocalGetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pStart, DWORD cbBuf
 
     // Check if this is a printer handle.
     pHandle = (PLOCAL_HANDLE)hPrinter;
-    if (pHandle->HandleType != Printer)
+    if (pHandle->HandleType != HandleType_Printer)
     {
         dwErrorCode = ERROR_INVALID_HANDLE;
         goto Cleanup;
@@ -853,7 +853,7 @@ LocalSetJob(HANDLE hPrinter, DWORD JobId, DWORD Level, PBYTE pJobInfo, DWORD Com
 
     // Check if this is a printer handle.
     pHandle = (PLOCAL_HANDLE)hPrinter;
-    if (pHandle->HandleType != Printer)
+    if (pHandle->HandleType != HandleType_Printer)
     {
         dwErrorCode = ERROR_INVALID_HANDLE;
         goto Cleanup;
@@ -918,7 +918,7 @@ LocalEnumJobs(HANDLE hPrinter, DWORD FirstJob, DWORD NoJobs, DWORD Level, PBYTE
 
     // Check if this is a printer handle.
     pHandle = (PLOCAL_HANDLE)hPrinter;
-    if (pHandle->HandleType != Printer)
+    if (pHandle->HandleType != HandleType_Printer)
     {
         dwErrorCode = ERROR_INVALID_HANDLE;
         goto Cleanup;
@@ -1015,7 +1015,7 @@ LocalScheduleJob(HANDLE hPrinter, DWORD dwJobID)
 
     // Check if this is a printer handle.
     pHandle = (PLOCAL_HANDLE)hPrinter;
-    if (pHandle->HandleType != Printer)
+    if (pHandle->HandleType != HandleType_Printer)
     {
         dwErrorCode = ERROR_INVALID_HANDLE;
         goto Cleanup;
index 2e62069..ae0b16e 100644 (file)
@@ -146,6 +146,7 @@ DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
             _GetSpoolDirectory();
 
             return InitializePrintMonitorList() &&
+                   InitializePortList() &&
                    InitializePrintProcessorList() &&
                    InitializePrinterList() &&
                    InitializeGlobalJobList();
index 0dd2b70..3d1fc27 100644 (file)
@@ -7,9 +7,27 @@
 
 #include "precomp.h"
 
-// Local Variables
+// Global Variables
 LIST_ENTRY PrintMonitorList;
 
+
+PLOCAL_PRINT_MONITOR
+FindPrintMonitor(PCWSTR pwszName)
+{
+    PLIST_ENTRY pEntry;
+    PLOCAL_PRINT_MONITOR pPrintMonitor;
+
+    for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink)
+    {
+        pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry);
+
+        if (_wcsicmp(pPrintMonitor->pwszName, pwszName) == 0)
+            return pPrintMonitor;
+    }
+
+    return NULL;
+}
+
 BOOL
 InitializePrintMonitorList()
 {
index 6748368..1c5ed38 100644 (file)
@@ -7,6 +7,128 @@
 
 #include "precomp.h"
 
+// Local Variables
+static LIST_ENTRY _PortList;
+
+
+PLOCAL_PRINT_MONITOR
+FindPrintMonitorByPort(PCWSTR pwszName)
+{
+    PLIST_ENTRY pEntry;
+    PLOCAL_PORT pPort;
+
+    for (pEntry = _PortList.Flink; pEntry != &_PortList; pEntry = pEntry->Flink)
+    {
+        pPort = CONTAINING_RECORD(pEntry, LOCAL_PORT, Entry);
+
+        if (_wcsicmp(pPort->pwszName, pwszName) == 0)
+            return pPort->pPrintMonitor;
+    }
+
+    return NULL;
+}
+
+BOOL
+InitializePortList()
+{
+    BOOL bReturnValue;
+    DWORD cbNeeded;
+    DWORD cbPortName;
+    DWORD dwErrorCode;
+    DWORD dwReturned;
+    DWORD i;
+    PLOCAL_PORT pPort;
+    PLOCAL_PRINT_MONITOR pPrintMonitor;
+    PLIST_ENTRY pEntry;
+    PPORT_INFO_1W p;
+    PPORT_INFO_1W pPortInfo1 = NULL;
+
+    // Initialize an empty list for our Ports.
+    InitializeListHead(&_PortList);
+
+    // Loop through all Print Monitors.
+    for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink)
+    {
+        // Cleanup from the previous run.
+        if (pPortInfo1)
+        {
+            DllFreeSplMem(pPortInfo1);
+            pPortInfo1 = NULL;
+        }
+
+        pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry);
+
+        // Determine the required buffer size for EnumPorts.
+        if (pPrintMonitor->bIsLevel2)
+            bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnEnumPorts(pPrintMonitor->hMonitor, NULL, 1, NULL, 0, &cbNeeded, &dwReturned);
+        else
+            bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnEnumPorts(NULL, 1, NULL, 0, &cbNeeded, &dwReturned);
+
+        // Check the returned error code.
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
+        {
+            ERR("Print Monitor \"%S\" failed with error %lu on EnumPorts!\n", pPrintMonitor->pwszName, GetLastError());
+            continue;
+        }
+
+        // Allocate a buffer large enough.
+        pPortInfo1 = DllAllocSplMem(cbNeeded);
+        if (!pPortInfo1)
+        {
+            dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+            ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
+            goto Cleanup;
+        }
+
+        // Get the ports handled by this monitor.
+        if (pPrintMonitor->bIsLevel2)
+            bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnEnumPorts(pPrintMonitor->hMonitor, NULL, 1, (PBYTE)pPortInfo1, cbNeeded, &cbNeeded, &dwReturned);
+        else
+            bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnEnumPorts(NULL, 1, (PBYTE)pPortInfo1, cbNeeded, &cbNeeded, &dwReturned);
+
+        // Check the return value.
+        if (!bReturnValue)
+        {
+            ERR("Print Monitor \"%S\" failed with error %lu on EnumPorts!\n", pPrintMonitor->pwszName, GetLastError());
+            continue;
+        }
+
+        // Loop through all returned ports.
+        p = pPortInfo1;
+
+        for (i = 0; i < dwReturned; i++)
+        {
+            cbPortName = (wcslen(p->pName) + 1) * sizeof(WCHAR);
+
+            // Create a new LOCAL_PORT structure for it.
+            pPort = DllAllocSplMem(sizeof(LOCAL_PORT) + cbPortName);
+            if (!pPort)
+            {
+                dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+                ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
+                goto Cleanup;
+            }
+
+            pPort->pPrintMonitor = pPrintMonitor;
+            pPort->pwszName = (PWSTR)((PBYTE)pPort + sizeof(LOCAL_PORT));
+            CopyMemory(pPort->pwszName, p->pName, cbPortName);
+
+            // Insert it into the list and advance to the next port.
+            InsertTailList(&_PortList, &pPort->Entry);
+            p++;
+        }
+    }
+
+    dwErrorCode = ERROR_SUCCESS;
+
+Cleanup:
+    // Inside the loop
+    if (pPortInfo1)
+        DllFreeSplMem(pPortInfo1);
+
+    SetLastError(dwErrorCode);
+    return (dwErrorCode == ERROR_SUCCESS);
+}
 
 BOOL WINAPI
 LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
index 1153081..65b65d3 100644 (file)
@@ -139,7 +139,12 @@ LOCAL_PRINTER_HANDLE, *PLOCAL_PRINTER_HANDLE;
  */
 typedef struct _LOCAL_HANDLE
 {
-    enum { Printer, Monitor, Port } HandleType;
+    enum {
+        HandleType_Port,
+        HandleType_Printer,
+        HandleType_Xcv
+    }
+    HandleType;
     PVOID pSpecificHandle;
 }
 LOCAL_HANDLE, *PLOCAL_HANDLE;
@@ -159,6 +164,17 @@ typedef struct _LOCAL_PRINT_MONITOR
 }
 LOCAL_PRINT_MONITOR, *PLOCAL_PRINT_MONITOR;
 
+/**
+ * Describes a Port handled by a Print Monitor.
+ */
+typedef struct _LOCAL_PORT
+{
+    LIST_ENTRY Entry;
+    PWSTR pwszName;                         /** The name of the port (including the trailing colon). */
+    PLOCAL_PRINT_MONITOR pPrintMonitor;     /** The Print Monitor handling this port. */
+}
+LOCAL_PORT, *PLOCAL_PORT;
+
 /**
  * Describes the header of a print job serialized into a shadow file (.SHD)
  * Documented in http://www.undocprint.org/formats/winspool/shd
@@ -221,10 +237,13 @@ extern DWORD cchSpoolDirectory;
 
 // monitors.c
 extern LIST_ENTRY PrintMonitorList;
+PLOCAL_PRINT_MONITOR FindPrintMonitor(PCWSTR pwszName);
 BOOL InitializePrintMonitorList();
 BOOL WINAPI LocalEnumMonitors(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
 
 // ports.c
+PLOCAL_PRINT_MONITOR FindPrintMonitorByPort(PCWSTR pwszName);
+BOOL InitializePortList();
 BOOL WINAPI LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned);
 
 // printers.c
@@ -240,8 +259,8 @@ BOOL WINAPI LocalEndDocPrinter(HANDLE hPrinter);
 BOOL WINAPI LocalClosePrinter(HANDLE hPrinter);
 
 // printprocessors.c
-BOOL FindDatatype(PLOCAL_PRINT_PROCESSOR pPrintProcessor, PWSTR pwszDatatype);
-PLOCAL_PRINT_PROCESSOR FindPrintProcessor(PWSTR pwszName);
+BOOL FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype);
+PLOCAL_PRINT_PROCESSOR FindPrintProcessor(PCWSTR pwszName);
 BOOL 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);
index 0540735..cf3f36c 100644 (file)
@@ -477,18 +477,25 @@ Cleanup:
 BOOL WINAPI
 LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDefault)
 {
+    BOOL bReturnValue;
     DWORD cchComputerName;
-    DWORD cchPrinterName;
+    DWORD cchFirstParameter;
     DWORD dwErrorCode;
     DWORD dwJobID;
+    HANDLE hExternalHandle;
     PWSTR p = lpPrinterName;
-    PWSTR pwszPrinterName = NULL;
+    PWSTR pwszFirstParameter = NULL;
+    PWSTR pwszSecondParameter = NULL;
     PLOCAL_JOB pJob;
-    PLOCAL_HANDLE pHandle;
+    PLOCAL_HANDLE pHandle = NULL;
+    PLOCAL_PRINT_MONITOR pPrintMonitor;
     PLOCAL_PRINTER pPrinter;
     PLOCAL_PRINTER_HANDLE pPrinterHandle = NULL;
     WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
 
+    // TODO: lpPrinterName == NULL is supported and means access to the local printer server.
+    // Not sure yet if that is passed down to localspl.dll or processed in advance.
+
     // Sanity checks
     if (!lpPrinterName || !phPrinter)
     {
@@ -496,6 +503,7 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
         goto Cleanup;
     }
 
+    // Skip any server name in the first parameter.
     // Does lpPrinterName begin with two backslashes to indicate a server name?
     if (lpPrinterName[0] == L'\\' && lpPrinterName[1] == L'\\')
     {
@@ -511,9 +519,6 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
             goto Cleanup;
         }
 
-        // Null-terminate the string here to enable comparison.
-        *p = 0;
-
         // Get the local computer name for comparison.
         cchComputerName = _countof(wszComputerName);
         if (!GetComputerNameW(wszComputerName, &cchComputerName))
@@ -523,8 +528,10 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
             goto Cleanup;
         }
 
-        // Now compare this with the local computer name and reject if it doesn't match, because this print provider only supports local printers.
-        if (wcsicmp(lpPrinterName, wszComputerName) != 0)
+        // Now compare this string excerpt with the local computer name.
+        // The input parameter may not be writable, so we can't null-terminate the input string at this point.
+        // This print provider only supports local printers, so both strings have to match.
+        if (p - lpPrinterName != cchComputerName || _wcsnicmp(lpPrinterName, wszComputerName, cchComputerName) != 0)
         {
             dwErrorCode = ERROR_INVALID_PRINTER_NAME;
             goto Cleanup;
@@ -534,30 +541,155 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
         lpPrinterName = p + 1;
     }
 
-    // Look for a comma. If it exists, it indicates the end of the printer name.
-    p = wcschr(lpPrinterName, L',');
-    if (p)
-        cchPrinterName = p - lpPrinterName;
+    // Look for a comma. If it exists, it indicates the end of the first parameter.
+    pwszSecondParameter = wcschr(lpPrinterName, L',');
+    if (pwszSecondParameter)
+        cchFirstParameter = pwszSecondParameter - p;
     else
-        cchPrinterName = wcslen(lpPrinterName);
+        cchFirstParameter = wcslen(lpPrinterName);
 
-    // No printer name and no comma? This is invalid!
-    if (!cchPrinterName && !p)
+    // We must have at least one parameter.
+    if (!cchFirstParameter && !pwszSecondParameter)
     {
         dwErrorCode = ERROR_INVALID_PRINTER_NAME;
         goto Cleanup;
     }
 
-    // Do we have a printer name?
-    if (cchPrinterName)
+    // Do we have a first parameter?
+    if (cchFirstParameter)
     {
         // Yes, extract it.
-        pwszPrinterName = DllAllocSplMem((cchPrinterName + 1) * sizeof(WCHAR));
-        CopyMemory(pwszPrinterName, lpPrinterName, cchPrinterName * sizeof(WCHAR));
-        pwszPrinterName[cchPrinterName] = 0;
+        pwszFirstParameter = DllAllocSplMem((cchFirstParameter + 1) * sizeof(WCHAR));
+        CopyMemory(pwszFirstParameter, lpPrinterName, cchFirstParameter * sizeof(WCHAR));
+        pwszFirstParameter[cchFirstParameter] = 0;
+    }
+
+    // Do we have a second parameter?
+    if (pwszSecondParameter)
+    {
+        // Yes, skip the comma at the beginning.
+        ++pwszSecondParameter;
+
+        // Skip whitespace as well.
+        while (*pwszSecondParameter == L' ')
+            ++pwszSecondParameter;
+    }
+
+    // Create a new handle.
+    pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
+    if (!pHandle)
+    {
+        dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+        ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
+        goto Cleanup;
+    }
+
+    // Now we can finally check the type of handle actually requested.
+    if (pwszFirstParameter && pwszSecondParameter && wcsncmp(pwszSecondParameter, L"Port", 4) == 0)
+    {
+        // The caller wants a port handle and provided a string like:
+        //    "LPT1:, Port"
+        //    "\\COMPUTERNAME\LPT1:, Port"
+        
+        // Look for this port in our Print Monitor Port list.
+        pPrintMonitor = FindPrintMonitorByPort(pwszFirstParameter);
+        if (!pPrintMonitor)
+        {
+            // The supplied port is unknown to all our Print Monitors.
+            dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+            goto Cleanup;
+        }
+
+        // Call the monitor's OpenPort function.
+        if (pPrintMonitor->bIsLevel2)
+            bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnOpenPort(pPrintMonitor->hMonitor, pwszFirstParameter, &hExternalHandle);
+        else
+            bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnOpenPort(pwszFirstParameter, &hExternalHandle);
+
+        if (!bReturnValue)
+        {
+            // The OpenPort function failed. Return its last error.
+            dwErrorCode = GetLastError();
+            goto Cleanup;
+        }
+
+        // Return the Port handle through our general handle.
+        pHandle->HandleType = HandleType_Port;
+        pHandle->pSpecificHandle = hExternalHandle;
+    }
+    else if (!pwszFirstParameter && pwszSecondParameter && wcsncmp(pwszSecondParameter, L"Xcv", 3) == 0)
+    {
+        // The caller wants an Xcv handle and provided a string like:
+        //    ", XcvMonitor Local Port"
+        //    "\\COMPUTERNAME\, XcvMonitor Local Port"
+        //    ", XcvPort LPT1:"
+        //    "\\COMPUTERNAME\, XcvPort LPT1:"
+
+        // Skip the "Xcv" string.
+        pwszSecondParameter += 3;
+
+        // Is XcvMonitor or XcvPort requested?
+        if (wcsncmp(pwszSecondParameter, L"Monitor ", 8) == 0)
+        {
+            // Skip the "Monitor " string.
+            pwszSecondParameter += 8;
+
+            // Look for this monitor in our Print Monitor list.
+            pPrintMonitor = FindPrintMonitor(pwszSecondParameter);
+            if (!pPrintMonitor)
+            {
+                // The caller supplied a non-existing Monitor name.
+                dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+                goto Cleanup;
+            }
+        }
+        else if (wcsncmp(pwszSecondParameter, L"Port ", 5) == 0)
+        {
+            // Skip the "Port " string.
+            pwszSecondParameter += 5;
+
+            // Look for this port in our Print Monitor Port list.
+            pPrintMonitor = FindPrintMonitorByPort(pwszSecondParameter);
+            if (!pPrintMonitor)
+            {
+                // The supplied port is unknown to all our Print Monitors.
+                dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+                goto Cleanup;
+            }
+        }
+        else
+        {
+            dwErrorCode = ERROR_INVALID_PRINTER_NAME;
+            goto Cleanup;
+        }
 
-        // Retrieve the associated printer from the list.
-        pPrinter = LookupElementSkiplist(&PrinterList, &pwszPrinterName, NULL);
+        // Call the monitor's XcvOpenPort function.
+        if (pPrintMonitor->bIsLevel2)
+            bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnXcvOpenPort(pPrintMonitor->hMonitor, pwszSecondParameter, SERVER_EXECUTE, &hExternalHandle);
+        else
+            bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnXcvOpenPort(pwszSecondParameter, SERVER_EXECUTE, &hExternalHandle);
+
+        if (!bReturnValue)
+        {
+            // The XcvOpenPort function failed. Return its last error.
+            dwErrorCode = GetLastError();
+            goto Cleanup;
+        }
+
+        // Return the Xcv handle through our general handle.
+        pHandle->HandleType = HandleType_Xcv;
+        pHandle->pSpecificHandle = hExternalHandle;
+    }
+    else
+    {
+        // The caller wants a Printer or Printer Job handle and provided a string like:
+        //    "HP DeskJet"
+        //    "\\COMPUTERNAME\HP DeskJet"
+        //    "HP DeskJet, Job 5"
+        //    "\\COMPUTERNAME\HP DeskJet, Job 5"
+
+        // Retrieve the printer from the list.
+        pPrinter = LookupElementSkiplist(&PrinterList, &pwszFirstParameter, NULL);
         if (!pPrinter)
         {
             // The printer does not exist.
@@ -567,6 +699,13 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
 
         // Create a new printer handle.
         pPrinterHandle = DllAllocSplMem(sizeof(LOCAL_PRINTER_HANDLE));
+        if (!pPrinterHandle)
+        {
+            dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
+            ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
+            goto Cleanup;
+        }
+
         pPrinterHandle->pPrinter = pPrinter;
 
         // Check if a datatype was given.
@@ -593,34 +732,25 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
         else
             pPrinterHandle->pDevMode = DuplicateDevMode(pPrinter->pDefaultDevMode);
 
-        // Did we have a comma? Then the user may want a handle to an existing job instead of creating a new job.
-        if (p)
+        // Check if the caller wants a handle to an existing job.
+        if (pwszSecondParameter)
         {
-            ++p;
-            
-            // Skip whitespace.
-            do
-            {
-                ++p;
-            }
-            while (*p == ' ');
-
             // The "Job " string has to follow now.
-            if (wcscmp(p, L"Job ") != 0)
+            if (wcsncmp(pwszSecondParameter, L"Job ", 4) != 0)
             {
                 dwErrorCode = ERROR_INVALID_PRINTER_NAME;
                 goto Cleanup;
             }
 
             // Skip the "Job " string. 
-            p += sizeof("Job ") - 1;
+            pwszSecondParameter += 4;
 
             // Skip even more whitespace.
-            while (*p == ' ')
-                ++p;
+            while (*pwszSecondParameter == ' ')
+                ++pwszSecondParameter;
 
             // Finally extract the desired Job ID.
-            dwJobID = wcstoul(p, NULL, 10);
+            dwJobID = wcstoul(pwszSecondParameter, NULL, 10);
             if (!IS_VALID_JOB_ID(dwJobID))
             {
                 // The user supplied an invalid Job ID.
@@ -640,70 +770,36 @@ LocalOpenPrinter(PWSTR lpPrinterName, HANDLE* phPrinter, PPRINTER_DEFAULTSW pDef
             pPrinterHandle->pStartedJob = pJob;
         }
 
-        // Create a new handle that references a printer.
-        pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
-        pHandle->HandleType = Printer;
+        // Return the Printer handle through our general handle.
+        pHandle->HandleType = HandleType_Printer;
         pHandle->pSpecificHandle = pPrinterHandle;
     }
-    else
-    {
-        // No printer name, but we have a comma!
-        // This may be a request to a XcvMonitor or XcvPort handle.
-        ++p;
-
-        // Skip whitespace.
-        do
-        {
-            ++p;
-        }
-        while (*p == ' ');
-
-        // Check if this is a request to a XcvMonitor.
-        if (wcscmp(p, L"XcvMonitor ") == 0)
-        {
-            // Skip the "XcvMonitor " string. 
-            p += sizeof("XcvMonitor ") - 1;
-
-            ///////////// TODO /////////////////////
-            pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
-            pHandle->HandleType = Monitor;
-            //pHandle->pSpecificHandle = pMonitorHandle;
-        }
-        else if (wcscmp(p, L"XcvPort ") == 0)
-        {
-            // Skip the "XcvPort " string. 
-            p += sizeof("XcvPort ") - 1;
-
-            //////////// TODO //////////////////////
-            pHandle = DllAllocSplMem(sizeof(LOCAL_HANDLE));
-            pHandle->HandleType = Port;
-            //pHandle->pSpecificHandle = pPortHandle;
-        }
-        else
-        {
-            dwErrorCode = ERROR_INVALID_PRINTER_NAME;
-            goto Cleanup;
-        }
-    }
 
+    // We were successful! Return the handle.
     *phPrinter = (HANDLE)pHandle;
     dwErrorCode = ERROR_SUCCESS;
 
     // Don't let the cleanup routines free this.
+    pHandle = NULL;
     pPrinterHandle = NULL;
-    pwszPrinterName = NULL;
 
 Cleanup:
+    if (pHandle)
+        DllFreeSplMem(pHandle);
+
     if (pPrinterHandle)
     {
         if (pPrinterHandle->pwszDatatype)
             DllFreeSplStr(pPrinterHandle->pwszDatatype);
 
+        if (pPrinterHandle->pDevMode)
+            DllFreeSplMem(pPrinterHandle->pDevMode);
+
         DllFreeSplMem(pPrinterHandle);
     }
 
-    if (pwszPrinterName)
-        DllFreeSplMem(pwszPrinterName);
+    if (pwszFirstParameter)
+        DllFreeSplMem(pwszFirstParameter);
 
     SetLastError(dwErrorCode);
     return (dwErrorCode == ERROR_SUCCESS);
@@ -734,7 +830,7 @@ LocalStartDocPrinter(HANDLE hPrinter, DWORD Level, LPBYTE pDocInfo)
 
     // Check if this is a printer handle.
     pHandle = (PLOCAL_HANDLE)hPrinter;
-    if (pHandle->HandleType != Printer)
+    if (pHandle->HandleType != HandleType_Printer)
     {
         dwErrorCode = ERROR_INVALID_HANDLE;
         goto Cleanup;
index e4bd6b3..5d6c178 100644 (file)
@@ -73,7 +73,7 @@ Cleanup:
 }
 
 BOOL
-FindDatatype(PLOCAL_PRINT_PROCESSOR pPrintProcessor, PWSTR pwszDatatype)
+FindDatatype(const PLOCAL_PRINT_PROCESSOR pPrintProcessor, PCWSTR pwszDatatype)
 {
     DWORD i;
     PDATATYPES_INFO_1W pCurrentDatatype = pPrintProcessor->pDatatypesInfo1;
@@ -90,7 +90,7 @@ FindDatatype(PLOCAL_PRINT_PROCESSOR pPrintProcessor, PWSTR pwszDatatype)
 }
 
 PLOCAL_PRINT_PROCESSOR
-FindPrintProcessor(PWSTR pwszName)
+FindPrintProcessor(PCWSTR pwszName)
 {
     PLIST_ENTRY pEntry;
     PLOCAL_PRINT_PROCESSOR pPrintProcessor;