[Printing] Update and Add Functions
[reactos.git] / win32ss / printing / base / spoolss / monitors.c
1 /*
2 * PROJECT: ReactOS Spooler Router
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Functions related to Print Monitors
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
6 */
7
8 #include "precomp.h"
9
10 BOOL WINAPI
11 AddMonitorW(PWSTR pName, DWORD Level, PBYTE pMonitors)
12 {
13 BOOL bReturnValue = TRUE;
14 DWORD dwErrorCode = MAXDWORD;
15 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
16 PLIST_ENTRY pEntry;
17
18 // Loop through all Print Provider.
19 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
20 {
21 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
22
23 // Check if this Print Provider provides the function.
24 if (!pPrintProvider->PrintProvider.fpAddMonitor)
25 continue;
26
27 bReturnValue = pPrintProvider->PrintProvider.fpAddMonitor(pName, Level, pMonitors);
28
29 if ( !bReturnValue )
30 {
31 dwErrorCode = GetLastError();
32 }
33
34 // dwErrorCode shall not be overwritten if a previous call already succeeded.
35 if (dwErrorCode != ERROR_SUCCESS)
36 dwErrorCode = GetLastError();
37 }
38
39 SetLastError(dwErrorCode);
40 return (dwErrorCode == ERROR_SUCCESS);
41 }
42
43 BOOL WINAPI
44 DeleteMonitorW(PWSTR pName, PWSTR pEnvironment, PWSTR pMonitorName)
45 {
46 BOOL bReturnValue = TRUE;
47 DWORD dwErrorCode = MAXDWORD;
48 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
49 PLIST_ENTRY pEntry;
50
51 // Loop through all Print Provider.
52 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
53 {
54 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
55
56 // Check if this Print Provider provides the function.
57 if (!pPrintProvider->PrintProvider.fpDeleteMonitor)
58 continue;
59
60 bReturnValue = pPrintProvider->PrintProvider.fpDeleteMonitor(pName, pEnvironment, pMonitorName);
61
62 if ( !bReturnValue )
63 {
64 dwErrorCode = GetLastError();
65 }
66
67 // dwErrorCode shall not be overwritten if a previous call already succeeded.
68 if (dwErrorCode != ERROR_SUCCESS)
69 dwErrorCode = GetLastError();
70 }
71
72 SetLastError(dwErrorCode);
73 return (dwErrorCode == ERROR_SUCCESS);
74 }
75
76 BOOL WINAPI
77 EnumMonitorsW(PWSTR pName, DWORD Level, PBYTE pMonitors, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
78 {
79 BOOL bReturnValue = TRUE;
80 DWORD cbCallBuffer;
81 DWORD cbNeeded;
82 DWORD dwReturned;
83 DWORD dwErrorCode = MAXDWORD;
84 PBYTE pCallBuffer;
85 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
86 PLIST_ENTRY pEntry;
87
88 // Sanity checks.
89 if (cbBuf && !pMonitors)
90 {
91 SetLastError(ERROR_INVALID_USER_BUFFER);
92 return FALSE;
93 }
94
95 // Begin counting.
96 *pcbNeeded = 0;
97 *pcReturned = 0;
98
99 // At the beginning, we have the full buffer available.
100 cbCallBuffer = cbBuf;
101 pCallBuffer = pMonitors;
102
103 // Loop through all Print Provider.
104 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
105 {
106 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
107
108 // Check if this Print Provider provides an EnumMonitors function.
109 if (!pPrintProvider->PrintProvider.fpEnumMonitors)
110 continue;
111
112 // Call the EnumMonitors function of this Print Provider.
113 cbNeeded = 0;
114 dwReturned = 0;
115 bReturnValue = pPrintProvider->PrintProvider.fpEnumMonitors(pName, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
116
117 if ( !bReturnValue )
118 {
119 dwErrorCode = GetLastError();
120 }
121
122 // Add the returned counts to the total values.
123 *pcbNeeded += cbNeeded;
124 *pcReturned += dwReturned;
125
126 // Reduce the available buffer size for the next call without risking an underflow.
127 if (cbNeeded < cbCallBuffer)
128 cbCallBuffer -= cbNeeded;
129 else
130 cbCallBuffer = 0;
131
132 // Advance the buffer if the caller provided it.
133 if (pCallBuffer)
134 pCallBuffer += cbNeeded;
135
136 // dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
137 if (dwErrorCode != ERROR_SUCCESS)
138 dwErrorCode = GetLastError();
139 }
140
141 SetLastError(dwErrorCode);
142 return (dwErrorCode == ERROR_SUCCESS);
143 }