mirror of
https://github.com/reactos/reactos.git
synced 2024-09-09 04:10:19 +00:00
192 lines
5.8 KiB
C
192 lines
5.8 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
|
|
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;
|
|
}
|