2 * PROJECT: ReactOS Local Spooler
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Functions related to Ports of the Print Monitors
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
11 static LIST_ENTRY _PortList
;
15 FindPort(PCWSTR pwszName
)
20 TRACE("FindPort(%S)\n", pwszName
);
25 for (pEntry
= _PortList
.Flink
; pEntry
!= &_PortList
; pEntry
= pEntry
->Flink
)
27 pPort
= CONTAINING_RECORD(pEntry
, LOCAL_PORT
, Entry
);
29 if (_wcsicmp(pPort
->pwszName
, pwszName
) == 0)
37 InitializePortList(void)
46 PLOCAL_PRINT_MONITOR pPrintMonitor
;
49 PPORT_INFO_1W pPortInfo1
= NULL
;
51 TRACE("InitializePortList()\n");
53 // Initialize an empty list for our Ports.
54 InitializeListHead(&_PortList
);
56 // Loop through all Print Monitors.
57 for (pEntry
= PrintMonitorList
.Flink
; pEntry
!= &PrintMonitorList
; pEntry
= pEntry
->Flink
)
59 // Cleanup from the previous run.
62 DllFreeSplMem(pPortInfo1
);
66 pPrintMonitor
= CONTAINING_RECORD(pEntry
, LOCAL_PRINT_MONITOR
, Entry
);
68 // Determine the required buffer size for EnumPorts.
69 if (pPrintMonitor
->bIsLevel2
)
70 bReturnValue
= ((PMONITOR2
)pPrintMonitor
->pMonitor
)->pfnEnumPorts(pPrintMonitor
->hMonitor
, NULL
, 1, NULL
, 0, &cbNeeded
, &dwReturned
);
72 bReturnValue
= ((LPMONITOREX
)pPrintMonitor
->pMonitor
)->Monitor
.pfnEnumPorts(NULL
, 1, NULL
, 0, &cbNeeded
, &dwReturned
);
74 // Check the returned error code.
75 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
77 ERR("Print Monitor \"%S\" failed with error %lu on EnumPorts!\n", pPrintMonitor
->pwszName
, GetLastError());
81 // Allocate a buffer large enough.
82 pPortInfo1
= DllAllocSplMem(cbNeeded
);
85 dwErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
86 ERR("DllAllocSplMem failed!\n");
90 // Get the ports handled by this monitor.
91 if (pPrintMonitor
->bIsLevel2
)
92 bReturnValue
= ((PMONITOR2
)pPrintMonitor
->pMonitor
)->pfnEnumPorts(pPrintMonitor
->hMonitor
, NULL
, 1, (PBYTE
)pPortInfo1
, cbNeeded
, &cbNeeded
, &dwReturned
);
94 bReturnValue
= ((LPMONITOREX
)pPrintMonitor
->pMonitor
)->Monitor
.pfnEnumPorts(NULL
, 1, (PBYTE
)pPortInfo1
, cbNeeded
, &cbNeeded
, &dwReturned
);
96 // Check the return value.
99 ERR("Print Monitor \"%S\" failed with error %lu on EnumPorts!\n", pPrintMonitor
->pwszName
, GetLastError());
103 // Loop through all returned ports.
106 for (i
= 0; i
< dwReturned
; i
++)
108 cbPortName
= (wcslen(p
->pName
) + 1) * sizeof(WCHAR
);
110 // Create a new LOCAL_PORT structure for it.
111 pPort
= DllAllocSplMem(sizeof(LOCAL_PORT
) + cbPortName
);
114 dwErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
115 ERR("DllAllocSplMem failed!\n");
119 pPort
->pPrintMonitor
= pPrintMonitor
;
120 pPort
->pwszName
= (PWSTR
)((PBYTE
)pPort
+ sizeof(LOCAL_PORT
));
121 CopyMemory(pPort
->pwszName
, p
->pName
, cbPortName
);
123 // Insert it into the list and advance to the next port.
124 InsertTailList(&_PortList
, &pPort
->Entry
);
129 dwErrorCode
= ERROR_SUCCESS
;
134 DllFreeSplMem(pPortInfo1
);
136 SetLastError(dwErrorCode
);
137 return (dwErrorCode
== ERROR_SUCCESS
);
141 LocalEnumPorts(PWSTR pName
, DWORD Level
, PBYTE pPorts
, DWORD cbBuf
, PDWORD pcbNeeded
, PDWORD pcReturned
)
143 BOOL bReturnValue
= TRUE
;
148 PLOCAL_PRINT_MONITOR pPrintMonitor
;
151 TRACE("LocalEnumPorts(%S, %lu, %p, %lu, %p, %p)\n", pName
, Level
, pPorts
, cbBuf
, pcbNeeded
, pcReturned
);
157 // At the beginning, we have the full buffer available.
158 cbCallBuffer
= cbBuf
;
159 pCallBuffer
= pPorts
;
161 // Loop through all Print Monitors.
162 for (pEntry
= PrintMonitorList
.Flink
; pEntry
!= &PrintMonitorList
; pEntry
= pEntry
->Flink
)
164 pPrintMonitor
= CONTAINING_RECORD(pEntry
, LOCAL_PRINT_MONITOR
, Entry
);
166 // Call the EnumPorts function of this Print Monitor.
170 if (pPrintMonitor
->bIsLevel2
)
171 bReturnValue
= ((PMONITOR2
)pPrintMonitor
->pMonitor
)->pfnEnumPorts(pPrintMonitor
->hMonitor
, pName
, Level
, pCallBuffer
, cbCallBuffer
, &cbNeeded
, &dwReturned
);
173 bReturnValue
= ((LPMONITOREX
)pPrintMonitor
->pMonitor
)->Monitor
.pfnEnumPorts(pName
, Level
, pCallBuffer
, cbCallBuffer
, &cbNeeded
, &dwReturned
);
175 // Add the returned counts to the total values.
176 *pcbNeeded
+= cbNeeded
;
177 *pcReturned
+= dwReturned
;
179 // Reduce the available buffer size for the next call without risking an underflow.
180 if (cbNeeded
< cbCallBuffer
)
181 cbCallBuffer
-= cbNeeded
;
185 // Advance the buffer if the caller provided it.
187 pCallBuffer
+= cbNeeded
;