[SPOOLSS]
[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 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 dwReturned;
72 PBYTE pCallBuffer;
73 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
74 PLIST_ENTRY pEntry;
75
76 // Sanity checks.
77 if ((cbBuf && !pPrinterEnum) || !pcbNeeded || !pcReturned)
78 {
79 SetLastError(ERROR_INVALID_PARAMETER);
80 return FALSE;
81 }
82
83 // Begin counting.
84 *pcbNeeded = 0;
85 *pcReturned = 0;
86
87 // At the beginning, we have the full buffer available.
88 cbCallBuffer = cbBuf;
89 pCallBuffer = pPrinterEnum;
90
91 // Loop through all Print Provider.
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
114 return bReturnValue;
115 }
116
117 BOOL WINAPI
118 GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
119 {
120 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
121
122 // Sanity checks.
123 if (!pHandle)
124 {
125 SetLastError(ERROR_INVALID_PARAMETER);
126 return FALSE;
127 }
128
129 return pHandle->pPrintProvider->PrintProvider.fpGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
130 }
131
132 BOOL WINAPI
133 GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
134 {
135 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
136
137 // Sanity checks.
138 if (!pHandle)
139 {
140 SetLastError(ERROR_INVALID_PARAMETER);
141 return FALSE;
142 }
143
144 return pHandle->pPrintProvider->PrintProvider.fpGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
145 }
146
147 BOOL WINAPI
148 OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
149 {
150 BOOL bReturnValue;
151 HANDLE hPrinter;
152 PLIST_ENTRY pEntry;
153 PSPOOLSS_PRINTER_HANDLE pHandle;
154 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
155
156 // Sanity checks.
157 if (!pPrinterName || !phPrinter)
158 {
159 SetLastError(ERROR_INVALID_PARAMETER);
160 return FALSE;
161 }
162
163 // Loop through all Print Providers to find one able to open this Printer.
164 for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
165 {
166 pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
167
168 bReturnValue = pPrintProvider->PrintProvider.fpOpenPrinter(pPrinterName, &hPrinter, pDefault);
169 if (bReturnValue == ROUTER_SUCCESS)
170 {
171 // This Print Provider has opened this Printer.
172 // Store this information and return a handle.
173 pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
174 if (!pHandle)
175 {
176 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
177 ERR("DllAllocSplMem failed with error %lu!\n", GetLastError());
178 return FALSE;
179 }
180
181 pHandle->pPrintProvider = pPrintProvider;
182 pHandle->hPrinter = hPrinter;
183 *phPrinter = (HANDLE)pHandle;
184
185 SetLastError(ERROR_SUCCESS);
186 return TRUE;
187 }
188 else if (bReturnValue == ROUTER_STOP_ROUTING)
189 {
190 ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
191 return FALSE;
192 }
193 }
194
195 // We found no Print Provider able to open this Printer.
196 return FALSE;
197 }
198
199 BOOL WINAPI
200 ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
201 {
202 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
203
204 // Sanity checks.
205 if (!pHandle)
206 {
207 SetLastError(ERROR_INVALID_PARAMETER);
208 return FALSE;
209 }
210
211 return pHandle->pPrintProvider->PrintProvider.fpReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
212 }
213
214 DWORD WINAPI
215 StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
216 {
217 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
218
219 // Sanity checks.
220 if (!pHandle)
221 {
222 SetLastError(ERROR_INVALID_PARAMETER);
223 return FALSE;
224 }
225
226 return pHandle->pPrintProvider->PrintProvider.fpStartDocPrinter(pHandle->hPrinter, Level, pDocInfo);
227 }
228
229 BOOL WINAPI
230 StartPagePrinter(HANDLE hPrinter)
231 {
232 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
233
234 // Sanity checks.
235 if (!pHandle)
236 {
237 SetLastError(ERROR_INVALID_PARAMETER);
238 return FALSE;
239 }
240
241 return pHandle->pPrintProvider->PrintProvider.fpStartPagePrinter(pHandle->hPrinter);
242 }
243
244 BOOL WINAPI
245 WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
246 {
247 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hPrinter;
248
249 // Sanity checks.
250 if (!pHandle)
251 {
252 SetLastError(ERROR_INVALID_PARAMETER);
253 return FALSE;
254 }
255
256 return pHandle->pPrintProvider->PrintProvider.fpWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten);
257 }
258
259 BOOL WINAPI
260 XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
261 {
262 PSPOOLSS_PRINTER_HANDLE pHandle = (PSPOOLSS_PRINTER_HANDLE)hXcv;
263
264 // Sanity checks.
265 if (!pHandle)
266 {
267 SetLastError(ERROR_INVALID_PARAMETER);
268 return FALSE;
269 }
270
271 return pHandle->pPrintProvider->PrintProvider.fpXcvData(pHandle->hPrinter, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
272 }