mirror of
https://github.com/reactos/reactos.git
synced 2024-11-10 00:34:39 +00:00
62c4b828b4
More forwards to LocalSpl and LocalMon. At sometime will be merged together. Bug fixes. Printer Driver code is a wine hack. (WIP) Added information for shell tray icon notifications. Sync wine WinSpool driver tests. Unplugged from build.
499 lines
14 KiB
C
499 lines
14 KiB
C
/*
|
|
* PROJECT: ReactOS Local Spooler
|
|
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
|
|
* PURPOSE: Functions related to Ports of the Print Monitors
|
|
* COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
// Local Variables
|
|
static LIST_ENTRY _PortList;
|
|
|
|
|
|
PLOCAL_PORT
|
|
FindPort(PCWSTR pwszName)
|
|
{
|
|
PLIST_ENTRY pEntry;
|
|
PLOCAL_PORT pPort;
|
|
|
|
TRACE("FindPort(%S)\n", pwszName);
|
|
|
|
if (!pwszName)
|
|
return NULL;
|
|
|
|
for (pEntry = _PortList.Flink; pEntry != &_PortList; pEntry = pEntry->Flink)
|
|
{
|
|
pPort = CONTAINING_RECORD(pEntry, LOCAL_PORT, Entry);
|
|
|
|
if (_wcsicmp(pPort->pwszName, pwszName) == 0)
|
|
return pPort;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
BOOL
|
|
InitializePortList(void)
|
|
{
|
|
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;
|
|
|
|
TRACE("InitializePortList()\n");
|
|
|
|
// 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!\n");
|
|
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!\n");
|
|
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)
|
|
{
|
|
BOOL bReturnValue = TRUE;
|
|
DWORD cbCallBuffer;
|
|
DWORD cbNeeded;
|
|
DWORD dwReturned;
|
|
PBYTE pCallBuffer;
|
|
PLOCAL_PRINT_MONITOR pPrintMonitor;
|
|
PLIST_ENTRY pEntry;
|
|
|
|
TRACE("LocalEnumPorts(%S, %lu, %p, %lu, %p, %p)\n", pName, Level, pPorts, cbBuf, pcbNeeded, pcReturned);
|
|
|
|
// 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.
|
|
cbNeeded = 0;
|
|
dwReturned = 0;
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|