[LOCALSPL]
[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 BOOL bReturnValue;
69 DWORD cbCallBuffer;
70 DWORD cbNeeded;
71 DWORD dwErrorCode = 0xFFFFFFFF;
72 DWORD dwReturned;
73 PBYTE pCallBuffer;
74 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
75 PLIST_ENTRY pEntry;
76
77 // Begin counting.
78 *pcbNeeded = 0;
79 *pcReturned = 0;
80
81 if (cbBuf && !pPrinterEnum)
82 {
83 dwErrorCode = ERROR_INVALID_USER_BUFFER;
84 goto Cleanup;
85 }
86
87 // At the beginning, we have the full buffer available.
88 cbCallBuffer = cbBuf;
89 pCallBuffer = pPrinterEnum;
90
91 // Loop through all Print Providers.
92 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
93 {
94 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
95
96 // Call the EnumPrinters function of this Print Provider.
97 bReturnValue = pPrintProvider->PrintProvider.fpEnumPrinters(Flags, Name, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
98
99 // Add the returned counts to the total values.
100 *pcbNeeded += cbNeeded;
101 *pcReturned += dwReturned;
102
103 // Reduce the available buffer size for the next call without risking an underflow.
104 if (cbNeeded < cbCallBuffer)
105 cbCallBuffer -= cbNeeded;
106 else
107 cbCallBuffer = 0;
108
109 // Advance the buffer if the caller provided it.
110 if (pCallBuffer)
111 pCallBuffer += cbNeeded;
112
113 // dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
114 if (dwErrorCode != ERROR_SUCCESS)
115 dwErrorCode = GetLastError();
116 }
117
118 Cleanup:
119 SetLastError(dwErrorCode);
120 return (dwErrorCode == ERROR_SUCCESS);
121 }
122
123 BOOL WINAPI
124 GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
125 {
126 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
127
128 // Sanity checks.
129 if (!pHandle)
130 {
131 SetLastError(ERROR_INVALID_PARAMETER);
132 return FALSE;
133 }
134
135 return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
136 }
137
138 BOOL WINAPI
139 GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
140 {
141 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
142
143 // Sanity checks.
144 if (!pHandle)
145 {
146 SetLastError(ERROR_INVALID_PARAMETER);
147 return FALSE;
148 }
149
150 return pHandle->pPrintProvider->PrintProvider.fpGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
151 }
152
153 BOOL WINAPI
154 OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
155 {
156 BOOL bReturnValue;
157 DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
158 HANDLE hPrinter;
159 PLIST_ENTRY pEntry;
160 PSPOOLSS_PRINTER_HANDLE pHandle;
161 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
162
163 // Sanity checks.
164 if (!pPrinterName || !phPrinter)
165 {
166 dwErrorCode = ERROR_INVALID_PARAMETER;
167 goto Cleanup;
168 }
169
170 // Loop through all Print Providers to find one able to open this Printer.
171 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
172 {
173 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
174
175 bReturnValue = pPrintProvider->PrintProvider.fpOpenPrinter(pPrinterName, &hPrinter, pDefault);
176 if (bReturnValue == ROUTER_SUCCESS)
177 {
178 // This Print Provider has opened this Printer.
179 // Store this information and return a handle.
180 pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
181 if (!pHandle)
182 {
183 ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
184 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
185 goto Cleanup;
186 }
187
188 pHandle->pPrintProvider = pPrintProvider;
189 pHandle->hPrinter = hPrinter;
190 *phPrinter = (HANDLE)pHandle;
191
192 dwErrorCode = ERROR_SUCCESS;
193 goto Cleanup;
194 }
195 else if (bReturnValue == ROUTER_STOP_ROUTING)
196 {
197 ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
198 dwErrorCode = GetLastError();
199 goto Cleanup;
200 }
201 }
202
203 // 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.
204 if (dwErrorCode == ERROR_INVALID_NAME)
205 dwErrorCode = ERROR_INVALID_PRINTER_NAME;
206
207 Cleanup:
208 SetLastError(dwErrorCode);
209 return (dwErrorCode == ERROR_SUCCESS);
210 }
211
212 BOOL WINAPI
213 ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
214 {
215 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
216
217 // Sanity checks.
218 if (!pHandle)
219 {
220 SetLastError(ERROR_INVALID_PARAMETER);
221 return FALSE;
222 }
223
224 return pHandle->pPrintProvider->PrintProvider.fpReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
225 }
226
227 DWORD WINAPI
228 StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
229 {
230 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
231
232 // Sanity checks.
233 if (!pHandle)
234 {
235 SetLastError(ERROR_INVALID_PARAMETER);
236 return FALSE;
237 }
238
239 return pHandle->pPrintProvider->PrintProvider.fpStartDocPrinter(pHandle->hPrinter, Level, pDocInfo);
240 }
241
242 BOOL WINAPI
243 StartPagePrinter(HANDLE hPrinter)
244 {
245 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
246
247 // Sanity checks.
248 if (!pHandle)
249 {
250 SetLastError(ERROR_INVALID_PARAMETER);
251 return FALSE;
252 }
253
254 return pHandle->pPrintProvider->PrintProvider.fpStartPagePrinter(pHandle->hPrinter);
255 }
256
257 BOOL WINAPI
258 WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
259 {
260 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
261
262 // Sanity checks.
263 if (!pHandle)
264 {
265 SetLastError(ERROR_INVALID_PARAMETER);
266 return FALSE;
267 }
268
269 return pHandle->pPrintProvider->PrintProvider.fpWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten);
270 }
271
272 BOOL WINAPI
273 XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
274 {
275 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hXcv;
276
277 // Sanity checks.
278 if (!pHandle)
279 {
280 SetLastError(ERROR_INVALID_PARAMETER);
281 return FALSE;
282 }
283
284 return pHandle->pPrintProvider->PrintProvider.fpXcvData(pHandle->hPrinter, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
285 }