ecd64d0b2d4a75507dce8a306a9b7c9b51cf3a69
[reactos.git] / reactos / win32ss / printing / base / spoolss / printers.c
1 /*
2 * PROJECT: ReactOS Spooler Router
3 * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
4 * PURPOSE: Functions related to Printers and printing
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck <colin@reactos.org>
6 */
7
8 #include "precomp.h"
9
10
11 BOOL WINAPI
12 ClosePrinter(HANDLE hPrinter)
13 {
14 BOOL bReturnValue;
15 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
16
17 // Sanity checks.
18 if (!pHandle)
19 {
20 SetLastError(ERROR_INVALID_PARAMETER);
21 return FALSE;
22 }
23
24 // FIXME: Call FindClosePrinterChangeNotification for all created change notifications (according to MSDN).
25
26 // Call CloseHandle of the Print Provider.
27 bReturnValue = pHandle->pPrintProvider->PrintProvider.fpClosePrinter(pHandle->hPrinter);
28
29 // Free our handle information.
30 DllFreeSplMem(pHandle);
31
32 return bReturnValue;
33 }
34
35 BOOL WINAPI
36 EndDocPrinter(HANDLE hPrinter)
37 {
38 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
39
40 // Sanity checks.
41 if (!pHandle)
42 {
43 SetLastError(ERROR_INVALID_PARAMETER);
44 return FALSE;
45 }
46
47 return pHandle->pPrintProvider->PrintProvider.fpEndDocPrinter(pHandle->hPrinter);
48 }
49
50 BOOL WINAPI
51 EndPagePrinter(HANDLE hPrinter)
52 {
53 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
54
55 // Sanity checks.
56 if (!pHandle)
57 {
58 SetLastError(ERROR_INVALID_PARAMETER);
59 return FALSE;
60 }
61
62 return pHandle->pPrintProvider->PrintProvider.fpEndPagePrinter(pHandle->hPrinter);
63 }
64
65 BOOL WINAPI
66 EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
67 {
68 DWORD cbCallBuffer;
69 DWORD cbNeeded;
70 DWORD dwErrorCode = 0xFFFFFFFF;
71 DWORD dwReturned;
72 PBYTE pCallBuffer;
73 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
74 PLIST_ENTRY pEntry;
75
76 // Begin counting.
77 *pcbNeeded = 0;
78 *pcReturned = 0;
79
80 if (cbBuf && !pPrinterEnum)
81 {
82 dwErrorCode = ERROR_INVALID_USER_BUFFER;
83 goto Cleanup;
84 }
85
86 // At the beginning, we have the full buffer available.
87 cbCallBuffer = cbBuf;
88 pCallBuffer = pPrinterEnum;
89
90 // Loop through all Print Providers.
91 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
92 {
93 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
94
95 // Call the EnumPrinters function of this Print Provider.
96 pPrintProvider->PrintProvider.fpEnumPrinters(Flags, Name, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
97
98 // Add the returned counts to the total values.
99 *pcbNeeded += cbNeeded;
100 *pcReturned += dwReturned;
101
102 // Reduce the available buffer size for the next call without risking an underflow.
103 if (cbNeeded < cbCallBuffer)
104 cbCallBuffer -= cbNeeded;
105 else
106 cbCallBuffer = 0;
107
108 // Advance the buffer if the caller provided it.
109 if (pCallBuffer)
110 pCallBuffer += cbNeeded;
111
112 // dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
113 if (dwErrorCode != ERROR_SUCCESS)
114 dwErrorCode = GetLastError();
115 }
116
117 Cleanup:
118 SetLastError(dwErrorCode);
119 return (dwErrorCode == ERROR_SUCCESS);
120 }
121
122 BOOL WINAPI
123 GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
124 {
125 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
126
127 // Sanity checks.
128 if (!pHandle)
129 {
130 SetLastError(ERROR_INVALID_PARAMETER);
131 return FALSE;
132 }
133
134 return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
135 }
136
137 BOOL WINAPI
138 GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
139 {
140 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
141
142 // Sanity checks.
143 if (!pHandle)
144 {
145 SetLastError(ERROR_INVALID_PARAMETER);
146 return FALSE;
147 }
148
149 return pHandle->pPrintProvider->PrintProvider.fpGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
150 }
151
152 BOOL WINAPI
153 OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
154 {
155 BOOL bReturnValue;
156 DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
157 HANDLE hPrinter;
158 PLIST_ENTRY pEntry;
159 PSPOOLSS_PRINTER_HANDLE pHandle;
160 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
161
162 // Sanity checks.
163 if (!pPrinterName || !phPrinter)
164 {
165 dwErrorCode = ERROR_INVALID_PARAMETER;
166 goto Cleanup;
167 }
168
169 // Loop through all Print Providers to find one able to open this Printer.
170 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
171 {
172 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
173
174 bReturnValue = pPrintProvider->PrintProvider.fpOpenPrinter(pPrinterName, &hPrinter, pDefault);
175 if (bReturnValue == ROUTER_SUCCESS)
176 {
177 // This Print Provider has opened this Printer.
178 // Store this information and return a handle.
179 pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
180 if (!pHandle)
181 {
182 ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
183 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
184 goto Cleanup;
185 }
186
187 pHandle->pPrintProvider = pPrintProvider;
188 pHandle->hPrinter = hPrinter;
189 *phPrinter = (HANDLE)pHandle;
190
191 dwErrorCode = ERROR_SUCCESS;
192 goto Cleanup;
193 }
194 else if (bReturnValue == ROUTER_STOP_ROUTING)
195 {
196 ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
197 dwErrorCode = GetLastError();
198 goto Cleanup;
199 }
200 }
201
202 // ERROR_INVALID_NAME by the Print Provider is translated to ERROR_INVALID_PRINTER_NAME here, but not in other APIs as far as I know.
203 if (dwErrorCode == ERROR_INVALID_NAME)
204 dwErrorCode = ERROR_INVALID_PRINTER_NAME;
205
206 Cleanup:
207 SetLastError(dwErrorCode);
208 return (dwErrorCode == ERROR_SUCCESS);
209 }
210
211 BOOL WINAPI
212 ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
213 {
214 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
215
216 // Sanity checks.
217 if (!pHandle)
218 {
219 SetLastError(ERROR_INVALID_PARAMETER);
220 return FALSE;
221 }
222
223 return pHandle->pPrintProvider->PrintProvider.fpReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
224 }
225
226 DWORD WINAPI
227 StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
228 {
229 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
230
231 // Sanity checks.
232 if (!pHandle)
233 {
234 SetLastError(ERROR_INVALID_PARAMETER);
235 return FALSE;
236 }
237
238 return pHandle->pPrintProvider->PrintProvider.fpStartDocPrinter(pHandle->hPrinter, Level, pDocInfo);
239 }
240
241 BOOL WINAPI
242 StartPagePrinter(HANDLE hPrinter)
243 {
244 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
245
246 // Sanity checks.
247 if (!pHandle)
248 {
249 SetLastError(ERROR_INVALID_PARAMETER);
250 return FALSE;
251 }
252
253 return pHandle->pPrintProvider->PrintProvider.fpStartPagePrinter(pHandle->hPrinter);
254 }
255
256 BOOL WINAPI
257 WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
258 {
259 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
260
261 // Sanity checks.
262 if (!pHandle)
263 {
264 SetLastError(ERROR_INVALID_PARAMETER);
265 return FALSE;
266 }
267
268 return pHandle->pPrintProvider->PrintProvider.fpWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten);
269 }
270
271 BOOL WINAPI
272 XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
273 {
274 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hXcv;
275
276 // Sanity checks.
277 if (!pHandle)
278 {
279 SetLastError(ERROR_INVALID_PARAMETER);
280 return FALSE;
281 }
282
283 return pHandle->pPrintProvider->PrintProvider.fpXcvData(pHandle->hPrinter, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
284 }