2015-07-07 17:06:48 +00:00
|
|
|
/*
|
|
|
|
* PROJECT: ReactOS Local Spooler
|
2017-09-29 17:18:19 +00:00
|
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
2015-07-07 17:06:48 +00:00
|
|
|
* PURPOSE: Functions related to Ports of the Print Monitors
|
2017-09-29 17:18:19 +00:00
|
|
|
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
|
2015-07-07 17:06:48 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
2015-07-13 10:18:07 +00:00
|
|
|
// Local Variables
|
|
|
|
static LIST_ENTRY _PortList;
|
|
|
|
|
|
|
|
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
PLOCAL_PORT
|
|
|
|
FindPort(PCWSTR pwszName)
|
2015-07-13 10:18:07 +00:00
|
|
|
{
|
|
|
|
PLIST_ENTRY pEntry;
|
|
|
|
PLOCAL_PORT pPort;
|
|
|
|
|
2017-07-05 15:29:13 +00:00
|
|
|
TRACE("FindPort(%S)\n", pwszName);
|
|
|
|
|
2015-07-20 15:21:03 +00:00
|
|
|
if (!pwszName)
|
|
|
|
return NULL;
|
|
|
|
|
2015-07-13 10:18:07 +00:00
|
|
|
for (pEntry = _PortList.Flink; pEntry != &_PortList; pEntry = pEntry->Flink)
|
|
|
|
{
|
|
|
|
pPort = CONTAINING_RECORD(pEntry, LOCAL_PORT, Entry);
|
|
|
|
|
|
|
|
if (_wcsicmp(pPort->pwszName, pwszName) == 0)
|
[LOCALSPL, WINSPOOL]
Partially implement the whole StartDocPrinter, StartPagePrinter, ReadPrinter, WritePrinter, EndPagePrinter, EndDocPrinter, ClosePrinter group of functions.
They behave very differently based on whether spooled printing is enabled, whether it's a local or remote call, etc. Most information was gained by observing callchains under Windows.
So far, only the spooled path is implemented, the others need more investigation first.
Many other TODOs remain as well, see the comments.
Also make some more comments Doxygen-aware :)
svn path=/branches/colins-printing-for-freedom/; revision=68405
2015-07-16 15:03:47 +00:00
|
|
|
return pPort;
|
2015-07-13 10:18:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-08-26 22:12:20 +00:00
|
|
|
BOOL
|
|
|
|
CreatePortEntry( PCWSTR pwszName, PLOCAL_PRINT_MONITOR pPrintMonitor )
|
|
|
|
{
|
|
|
|
PLOCAL_PORT pPort;
|
|
|
|
DWORD cbPortName = (wcslen( pwszName ) + 1) * sizeof(WCHAR);
|
|
|
|
|
|
|
|
// Create a new LOCAL_PORT structure for it.
|
|
|
|
pPort = DllAllocSplMem(sizeof(LOCAL_PORT) + cbPortName);
|
|
|
|
if (!pPort)
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pPort->pPrintMonitor = pPrintMonitor;
|
|
|
|
pPort->pwszName = wcscpy( (PWSTR)(pPort+1), pwszName );
|
|
|
|
|
|
|
|
// Insert it into the list and advance to the next port.
|
|
|
|
InsertTailList(&_PortList, &pPort->Entry);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2015-07-13 10:18:07 +00:00
|
|
|
BOOL
|
2017-07-05 15:29:13 +00:00
|
|
|
InitializePortList(void)
|
2015-07-13 10:18:07 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2017-07-05 15:29:13 +00:00
|
|
|
TRACE("InitializePortList()\n");
|
|
|
|
|
2015-07-13 10:18:07 +00:00
|
|
|
// 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;
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
ERR("DllAllocSplMem failed!\n");
|
2015-07-13 10:18:07 +00:00
|
|
|
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;
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
ERR("DllAllocSplMem failed!\n");
|
2015-07-13 10:18:07 +00:00
|
|
|
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);
|
|
|
|
}
|
2015-07-07 17:06:48 +00:00
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
LocalEnumPorts(PWSTR pName, DWORD Level, PBYTE pPorts, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
|
|
|
|
{
|
2017-07-05 15:29:13 +00:00
|
|
|
BOOL bReturnValue = TRUE;
|
2015-07-07 17:06:48 +00:00
|
|
|
DWORD cbCallBuffer;
|
|
|
|
DWORD cbNeeded;
|
|
|
|
DWORD dwReturned;
|
|
|
|
PBYTE pCallBuffer;
|
|
|
|
PLOCAL_PRINT_MONITOR pPrintMonitor;
|
|
|
|
PLIST_ENTRY pEntry;
|
|
|
|
|
2017-07-05 15:29:13 +00:00
|
|
|
TRACE("LocalEnumPorts(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
|
2015-07-07 17:06:48 +00:00
|
|
|
|
|
|
|
// Begin counting.
|
|
|
|
*pcbNeeded = 0;
|
|
|
|
*pcReturned = 0;
|
|
|
|
|
|
|
|
// At the beginning, we have the full buffer available.
|
|
|
|
cbCallBuffer = cbBuf;
|
|
|
|
pCallBuffer = pPorts;
|
|
|
|
|
|
|
|
// Loop through all Print Monitors.
|
|
|
|
for (pEntry = PrintMonitorList.Flink; pEntry != &PrintMonitorList; pEntry = pEntry->Flink)
|
|
|
|
{
|
|
|
|
pPrintMonitor = CONTAINING_RECORD(pEntry, LOCAL_PRINT_MONITOR, Entry);
|
|
|
|
|
|
|
|
// Call the EnumPorts function of this Print Monitor.
|
[PRINTING]
- Implement GetPrinterDataA, GetPrinterDataExA, GetPrinterDataExW, GetPrinterDataW, SetPrinterDataA, SetPrinterDataExA, SetPrinterDataExW, SetPrinterDataW.
They support all features for Print Server and Printer Handles (minus security checks!)
I've also added tests for them.
- Store Printer data in SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers instead of SYSTEM\CurrentControlSet\Control\Print\Printers and create a registry symlink from the former path to the new one just like Windows does.
According to https://social.technet.microsoft.com/Forums/windowsserver/en-US/a683ab54-c43c-4ebe-af8f-1f7a65af2a51, this is needed when having >900 printers to work around a size limit of the SYSTEM registry hive. And if Windows has both locations, we need both for compatibility anyway.
- Add several settings which are queried by the new Printer Data APIs when working with Print Server Handles.
- Store the job directory in the Windows-compatible "DefaultSpoolDirectory" setting and make use of it.
- Revert the ASSERTs in LocalEnumPrinters again to let us verify the NULL pointer exceptions in localspl_apitest (thanks Serge! CORE-13433)
- Translate ERROR_INVALID_NAME to ERROR_INVALID_PRINTER_NAME in all cases in OpenPrinterW (thanks Victor! CORE-13412)
- Make EnumMonitorsW and EnumPortsW in spoolss more robust against failing Print Monitors.
- Remove the wrong !phPrinter check in OpenPrinterW to make Print Server Handles work for real.
- Fix error handling when memory allocation fails: HeapAlloc doesn't set last error, so it's just wrong to query or return it.
One more item done from https://reactos.org/wiki/Printing !
This is all still a big Work-in-Progress, with many subtle bugs deep down in ReactOS, for which I need to open additional tickets. But I didn't want to make this commit even bigger..
svn path=/trunk/; revision=75125
2017-06-19 14:18:19 +00:00
|
|
|
cbNeeded = 0;
|
|
|
|
dwReturned = 0;
|
|
|
|
|
2015-07-07 17:06:48 +00:00
|
|
|
if (pPrintMonitor->bIsLevel2)
|
|
|
|
bReturnValue = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnEnumPorts(pPrintMonitor->hMonitor, pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
|
|
|
|
else
|
|
|
|
bReturnValue = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnEnumPorts(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
|
|
|
|
|
|
|
|
// Add the returned counts to the total values.
|
|
|
|
*pcbNeeded += cbNeeded;
|
|
|
|
*pcReturned += dwReturned;
|
|
|
|
|
|
|
|
// Reduce the available buffer size for the next call without risking an underflow.
|
|
|
|
if (cbNeeded < cbCallBuffer)
|
|
|
|
cbCallBuffer -= cbNeeded;
|
|
|
|
else
|
|
|
|
cbCallBuffer = 0;
|
|
|
|
|
|
|
|
// Advance the buffer if the caller provided it.
|
|
|
|
if (pCallBuffer)
|
|
|
|
pCallBuffer += cbNeeded;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bReturnValue;
|
|
|
|
}
|
2020-08-26 22:12:20 +00:00
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
LocalAddPortEx(PWSTR pName, DWORD Level, PBYTE lpBuffer, PWSTR lpMonitorName)
|
|
|
|
{
|
|
|
|
DWORD lres;
|
|
|
|
BOOL res = FALSE;
|
|
|
|
PLOCAL_PORT pPort;
|
|
|
|
PLOCAL_PRINT_MONITOR pPrintMonitor;
|
|
|
|
PORT_INFO_1W * pi = (PORT_INFO_1W *) lpBuffer;
|
|
|
|
|
|
|
|
FIXME("LocalAddPortEx(%S, %lu, %p, %S)\n", pName, Level, lpBuffer, lpMonitorName);
|
|
|
|
|
|
|
|
lres = copy_servername_from_name(pName, NULL);
|
|
|
|
if ( lres )
|
|
|
|
{
|
|
|
|
FIXME("server %s not supported\n", debugstr_w(pName));
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( Level != 1 )
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((!pi) || (!lpMonitorName) || (!lpMonitorName[0]))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pPrintMonitor = FindPrintMonitor( lpMonitorName );
|
|
|
|
if (!pPrintMonitor )
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pPort = FindPort( pi->pName );
|
|
|
|
if ( pPort )
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPortEx )
|
|
|
|
{
|
|
|
|
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPortEx(pPrintMonitor->hMonitor, pName, Level, lpBuffer, lpMonitorName);
|
|
|
|
}
|
|
|
|
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPortEx )
|
|
|
|
{
|
|
|
|
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPortEx(pName, Level, lpBuffer, lpMonitorName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( res )
|
|
|
|
{
|
|
|
|
res = CreatePortEntry( pi->pName, pPrintMonitor );
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Local (AP, CP & DP) is still around, seems to be a backup if a failure was encountered.. New way, WinSpool->LocalUI->XcvDataW.
|
|
|
|
//
|
|
|
|
BOOL WINAPI
|
|
|
|
LocalAddPort(LPWSTR pName, HWND hWnd, LPWSTR pMonitorName)
|
|
|
|
{
|
|
|
|
DWORD lres;
|
|
|
|
BOOL res = FALSE;
|
|
|
|
PLOCAL_PRINT_MONITOR pPrintMonitor;
|
|
|
|
|
|
|
|
FIXME("LocalAddPort(%S, %p, %s)\n", pName, hWnd, debugstr_w(pMonitorName));
|
|
|
|
|
|
|
|
lres = copy_servername_from_name(pName, NULL);
|
|
|
|
if (lres)
|
|
|
|
{
|
|
|
|
FIXME("server %s not supported\n", debugstr_w(pName));
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* an empty Monitorname is Invalid */
|
|
|
|
if (!pMonitorName[0])
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pPrintMonitor = FindPrintMonitor( pMonitorName );
|
|
|
|
if (!pPrintMonitor )
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPort )
|
|
|
|
{
|
|
|
|
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnAddPort(pPrintMonitor->hMonitor, pName, hWnd, pMonitorName);
|
|
|
|
}
|
|
|
|
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPort )
|
|
|
|
{
|
|
|
|
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnAddPort(pName, hWnd, pMonitorName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( res )
|
|
|
|
{
|
|
|
|
DWORD cbNeeded, cReturned, i;
|
|
|
|
PPORT_INFO_1 pPorts;
|
|
|
|
|
|
|
|
//
|
|
|
|
// Play it safe,,, we know its Monitor2.... This is ReactOS.
|
|
|
|
//
|
|
|
|
if ( LocalEnumPorts( pName, 1, NULL, 0, &cbNeeded, &cReturned ) )
|
|
|
|
{
|
|
|
|
pPorts = DllAllocSplMem( cbNeeded );
|
|
|
|
if (pPorts)
|
|
|
|
{
|
|
|
|
if ( LocalEnumPorts( pName, 1, (PBYTE)pPorts, cbNeeded, &cbNeeded, &cReturned ) )
|
|
|
|
{
|
|
|
|
for ( i = 0; i < cReturned; i++ )
|
|
|
|
{
|
|
|
|
if ( !FindPort( pPorts[i].pName ) )
|
|
|
|
{
|
|
|
|
CreatePortEntry( pPorts[i].pName, pPrintMonitor );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DllFreeSplMem( pPorts );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
LocalConfigurePort(PWSTR pName, HWND hWnd, PWSTR pPortName)
|
|
|
|
{
|
|
|
|
LONG lres;
|
|
|
|
DWORD res;
|
|
|
|
PLOCAL_PORT pPrintPort;
|
|
|
|
PLOCAL_PRINT_MONITOR pPrintMonitor;
|
|
|
|
|
|
|
|
FIXME("LocalConfigurePort(%S, %p, %S)\n", pName, hWnd, pPortName);
|
|
|
|
|
|
|
|
lres = copy_servername_from_name(pName, NULL);
|
|
|
|
if (lres)
|
|
|
|
{
|
|
|
|
FIXME("server %s not supported\n", debugstr_w(pName));
|
|
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* an empty Portname is Invalid, but can popup a Dialog */
|
|
|
|
if (!pPortName[0])
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pPrintPort = FindPort(pPortName);
|
|
|
|
if (!pPrintPort )
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pPrintMonitor = pPrintPort->pPrintMonitor;
|
|
|
|
|
|
|
|
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnConfigurePort )
|
|
|
|
{
|
|
|
|
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnConfigurePort(pPrintMonitor->hMonitor, pName, hWnd, pPortName);
|
|
|
|
}
|
|
|
|
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnConfigurePort )
|
|
|
|
{
|
|
|
|
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnConfigurePort(pName, hWnd, pPortName);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
LocalDeletePort(PWSTR pName, HWND hWnd, PWSTR pPortName)
|
|
|
|
{
|
|
|
|
LONG lres;
|
|
|
|
DWORD res = FALSE;
|
|
|
|
PLOCAL_PORT pPrintPort;
|
|
|
|
PLOCAL_PRINT_MONITOR pPrintMonitor;
|
|
|
|
|
|
|
|
FIXME("LocalDeletePort(%S, %p, %S)\n", pName, hWnd, pPortName);
|
|
|
|
|
|
|
|
lres = copy_servername_from_name(pName, NULL);
|
|
|
|
if (lres)
|
|
|
|
{
|
|
|
|
FIXME("server %s not supported\n", debugstr_w(pName));
|
|
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pPortName[0])
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_NOT_SUPPORTED);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pPrintPort = FindPort(pPortName);
|
|
|
|
if (!pPrintPort )
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pPrintMonitor = pPrintPort->pPrintMonitor;
|
|
|
|
|
|
|
|
if ( pPrintMonitor->bIsLevel2 && ((PMONITOR2)pPrintMonitor->pMonitor)->pfnDeletePort )
|
|
|
|
{
|
|
|
|
res = ((PMONITOR2)pPrintMonitor->pMonitor)->pfnDeletePort(pPrintMonitor->hMonitor, pName, hWnd, pPortName);
|
|
|
|
}
|
|
|
|
else if ( !pPrintMonitor->bIsLevel2 && ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnDeletePort )
|
|
|
|
{
|
|
|
|
res = ((LPMONITOREX)pPrintMonitor->pMonitor)->Monitor.pfnDeletePort(pName, hWnd, pPortName);
|
|
|
|
}
|
|
|
|
|
|
|
|
RemoveEntryList(&pPrintPort->Entry);
|
|
|
|
|
|
|
|
DllFreeSplMem(pPrintPort);
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOL WINAPI
|
|
|
|
LocalSetPort(PWSTR pName, PWSTR pPortName, DWORD dwLevel, PBYTE pPortInfo)
|
|
|
|
{
|
|
|
|
LONG lres;
|
|
|
|
DWORD res = 0;
|
|
|
|
PPORT_INFO_3W ppi3w = (PPORT_INFO_3W)pPortInfo;
|
|
|
|
PLOCAL_PORT pPrintPort;
|
|
|
|
|
|
|
|
TRACE("LocalSetPort(%S, %S, %lu, %p)\n", pName, pPortName, dwLevel, pPortInfo);
|
|
|
|
|
|
|
|
lres = copy_servername_from_name(pName, NULL);
|
|
|
|
if (lres)
|
|
|
|
{
|
|
|
|
FIXME("server %s not supported\n", debugstr_w(pName));
|
|
|
|
SetLastError(ERROR_INVALID_NAME);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((dwLevel < 1) || (dwLevel > 2))
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_LEVEL);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !ppi3w )
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
pPrintPort = FindPort(pPortName);
|
|
|
|
if ( !pPrintPort )
|
|
|
|
{
|
|
|
|
SetLastError(ERROR_UNKNOWN_PORT);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
FIXME("Add Status Support to Local Ports!\n");
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|