2 * PROJECT: ReactOS Local Spooler
3 * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
4 * PURPOSE: Functions related to Ports of the Print Monitors
5 * COPYRIGHT: Copyright 2015 Colin Finck <colin@reactos.org>
11 static LIST_ENTRY _PortList
;
15 FindPort(PCWSTR pwszName
)
23 for (pEntry
= _PortList
.Flink
; pEntry
!= &_PortList
; pEntry
= pEntry
->Flink
)
25 pPort
= CONTAINING_RECORD(pEntry
, LOCAL_PORT
, Entry
);
27 if (_wcsicmp(pPort
->pwszName
, pwszName
) == 0)
44 PLOCAL_PRINT_MONITOR pPrintMonitor
;
47 PPORT_INFO_1W pPortInfo1
= NULL
;
49 // Initialize an empty list for our Ports.
50 InitializeListHead(&_PortList
);
52 // Loop through all Print Monitors.
53 for (pEntry
= PrintMonitorList
.Flink
; pEntry
!= &PrintMonitorList
; pEntry
= pEntry
->Flink
)
55 // Cleanup from the previous run.
58 DllFreeSplMem(pPortInfo1
);
62 pPrintMonitor
= CONTAINING_RECORD(pEntry
, LOCAL_PRINT_MONITOR
, Entry
);
64 // Determine the required buffer size for EnumPorts.
65 if (pPrintMonitor
->bIsLevel2
)
66 bReturnValue
= ((PMONITOR2
)pPrintMonitor
->pMonitor
)->pfnEnumPorts(pPrintMonitor
->hMonitor
, NULL
, 1, NULL
, 0, &cbNeeded
, &dwReturned
);
68 bReturnValue
= ((LPMONITOREX
)pPrintMonitor
->pMonitor
)->Monitor
.pfnEnumPorts(NULL
, 1, NULL
, 0, &cbNeeded
, &dwReturned
);
70 // Check the returned error code.
71 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER
)
73 ERR("Print Monitor \"%S\" failed with error %lu on EnumPorts!\n", pPrintMonitor
->pwszName
, GetLastError());
77 // Allocate a buffer large enough.
78 pPortInfo1
= DllAllocSplMem(cbNeeded
);
81 dwErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
82 ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
86 // Get the ports handled by this monitor.
87 if (pPrintMonitor
->bIsLevel2
)
88 bReturnValue
= ((PMONITOR2
)pPrintMonitor
->pMonitor
)->pfnEnumPorts(pPrintMonitor
->hMonitor
, NULL
, 1, (PBYTE
)pPortInfo1
, cbNeeded
, &cbNeeded
, &dwReturned
);
90 bReturnValue
= ((LPMONITOREX
)pPrintMonitor
->pMonitor
)->Monitor
.pfnEnumPorts(NULL
, 1, (PBYTE
)pPortInfo1
, cbNeeded
, &cbNeeded
, &dwReturned
);
92 // Check the return value.
95 ERR("Print Monitor \"%S\" failed with error %lu on EnumPorts!\n", pPrintMonitor
->pwszName
, GetLastError());
99 // Loop through all returned ports.
102 for (i
= 0; i
< dwReturned
; i
++)
104 cbPortName
= (wcslen(p
->pName
) + 1) * sizeof(WCHAR
);
106 // Create a new LOCAL_PORT structure for it.
107 pPort
= DllAllocSplMem(sizeof(LOCAL_PORT
) + cbPortName
);
110 dwErrorCode
= ERROR_NOT_ENOUGH_MEMORY
;
111 ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
115 pPort
->pPrintMonitor
= pPrintMonitor
;
116 pPort
->pwszName
= (PWSTR
)((PBYTE
)pPort
+ sizeof(LOCAL_PORT
));
117 CopyMemory(pPort
->pwszName
, p
->pName
, cbPortName
);
119 // Insert it into the list and advance to the next port.
120 InsertTailList(&_PortList
, &pPort
->Entry
);
125 dwErrorCode
= ERROR_SUCCESS
;
130 DllFreeSplMem(pPortInfo1
);
132 SetLastError(dwErrorCode
);
133 return (dwErrorCode
== ERROR_SUCCESS
);
137 LocalEnumPorts(PWSTR pName
, DWORD Level
, PBYTE pPorts
, DWORD cbBuf
, PDWORD pcbNeeded
, PDWORD pcReturned
)
144 PLOCAL_PRINT_MONITOR pPrintMonitor
;
148 if ((cbBuf
&& !pPorts
) || !pcbNeeded
|| !pcReturned
)
150 SetLastError(ERROR_INVALID_PARAMETER
);
158 // At the beginning, we have the full buffer available.
159 cbCallBuffer
= cbBuf
;
160 pCallBuffer
= pPorts
;
162 // Loop through all Print Monitors.
163 for (pEntry
= PrintMonitorList
.Flink
; pEntry
!= &PrintMonitorList
; pEntry
= pEntry
->Flink
)
165 pPrintMonitor
= CONTAINING_RECORD(pEntry
, LOCAL_PRINT_MONITOR
, Entry
);
167 // Call the EnumPorts function of this Print Monitor.
168 if (pPrintMonitor
->bIsLevel2
)
169 bReturnValue
= ((PMONITOR2
)pPrintMonitor
->pMonitor
)->pfnEnumPorts(pPrintMonitor
->hMonitor
, pName
, Level
, pCallBuffer
, cbCallBuffer
, &cbNeeded
, &dwReturned
);
171 bReturnValue
= ((LPMONITOREX
)pPrintMonitor
->pMonitor
)->Monitor
.pfnEnumPorts(pName
, Level
, pCallBuffer
, cbCallBuffer
, &cbNeeded
, &dwReturned
);
173 // Add the returned counts to the total values.
174 *pcbNeeded
+= cbNeeded
;
175 *pcReturned
+= dwReturned
;
177 // Reduce the available buffer size for the next call without risking an underflow.
178 if (cbNeeded
< cbCallBuffer
)
179 cbCallBuffer
-= cbNeeded
;
183 // Advance the buffer if the caller provided it.
185 pCallBuffer
+= cbNeeded
;