ReactOS 0.4.15-dev-7918-g2a2556c
printers.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Spooler Router
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
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
12{
14
15 // Sanity checks.
16 if (!pHandle)
17 {
19 return FALSE;
20 }
21
22 return pHandle->pPrintProvider->PrintProvider.fpAbortPrinter(pHandle->hPrinter);
23}
24
25//
26// See [MS-RPRN] 2.2.1.11 SPLCLIENT_INFO, SPLCLIENT_INFO Level.
27//
29AddPrinterExW( PWSTR pName, DWORD Level, PBYTE pPrinter, PBYTE pClientInfo, DWORD ClientInfoLevel)
30{
31 BOOL bReturnValue;
33 HANDLE hPrinter = NULL;
34 PWSTR pPrinterName = NULL;
37 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
38
39 if ( Level != 2 )
40 {
41 FIXME( "Unsupported level %d\n", Level );
43 return hPrinter;
44 }
45 else
46 {
47 PPRINTER_INFO_2W pi2w = (PPRINTER_INFO_2W)pPrinter;
48 pPrinterName = pi2w->pPrinterName;
49 }
50
51 // Loop through all Print Providers to find one able to open this Printer.
53 {
55
56 hPrinter = pPrintProvider->PrintProvider.fpAddPrinterEx(pName, Level, pPrinter, pClientInfo, ClientInfoLevel);
57
58 bReturnValue = GetLastError();
59
60 // Fallback.... ?
61
62 if ( hPrinter == NULL && bReturnValue == ERROR_NOT_SUPPORTED )
63 {
64 hPrinter = pPrintProvider->PrintProvider.fpAddPrinter(pName, Level, pPrinter);
65 }
66
67 bReturnValue = GetLastError();
68
69 if ( bReturnValue == ROUTER_SUCCESS && hPrinter )
70 {
71 // This Print Provider has opened this Printer.
72 // Store this information and return a handle.
73 pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
74 if (!pHandle)
75 {
76 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
77 ERR("DllAllocSplMem failed!\n");
78 goto Cleanup;
79 }
80
81 pHandle->pPrintProvider = pPrintProvider;
82 pHandle->hPrinter = hPrinter;
83
84 dwErrorCode = ERROR_SUCCESS;
85 goto Cleanup;
86 }
87 else if (bReturnValue == ROUTER_STOP_ROUTING)
88 {
89 ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
90 dwErrorCode = GetLastError();
91 goto Cleanup;
92 }
93 }
94
96 // 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.
97 if (dwErrorCode == ERROR_INVALID_NAME)
98 dwErrorCode = ERROR_INVALID_PRINTER_NAME;
99
100 SetLastError(dwErrorCode);
101 return hPrinter;
102}
103
106{
107 BOOL bReturnValue;
108 DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
109 HANDLE hPrinter = NULL;
110 PWSTR pPrinterName = NULL;
113 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
114
115 FIXME("AddPrinterW(%S, %lu, %p)\n", pName, Level, pPrinter);
116
117 if ( Level != 2 )
118 {
119 FIXME( "Unsupported level %d\n", Level );
121 return hPrinter;
122 }
123 else
124 {
125 PPRINTER_INFO_2W pi2w = (PPRINTER_INFO_2W)pPrinter;
126 pPrinterName = pi2w->pPrinterName;
127 }
128
129 // Xp return AddPrinterExW( pName, Level, pPrinter, NULL, 0); but,,,, W7u just Forward Direct.
130
131 // Loop through all Print Providers to find one able to open this Printer.
133 {
135
136 hPrinter = pPrintProvider->PrintProvider.fpAddPrinter(pName, Level, pPrinter);
137
138 bReturnValue = GetLastError();
139
140 if ( bReturnValue == ROUTER_SUCCESS && hPrinter )
141 {
142 // This Print Provider has opened this Printer.
143 // Store this information and return a handle.
144 pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
145 if (!pHandle)
146 {
147 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
148 ERR("DllAllocSplMem failed!\n");
149 goto Cleanup;
150 }
151
152 pHandle->pPrintProvider = pPrintProvider;
153 pHandle->hPrinter = hPrinter;
154
155 dwErrorCode = ERROR_SUCCESS;
156 goto Cleanup;
157 }
158 else if (bReturnValue == ROUTER_STOP_ROUTING)
159 {
160 ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
161 dwErrorCode = GetLastError();
162 goto Cleanup;
163 }
164 }
165
166Cleanup:
167 // 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.
168 if (dwErrorCode == ERROR_INVALID_NAME)
169 dwErrorCode = ERROR_INVALID_PRINTER_NAME;
170
171 SetLastError(dwErrorCode);
172 return hPrinter;
173}
174
177{
178 BOOL bReturnValue;
180
181 FIXME("ClosePrinter %p\n",hPrinter);
182
183 // Sanity checks.
184 if (!pHandle)
185 {
187 return FALSE;
188 }
189
190 // FIXME: Call FindClosePrinterChangeNotification for all created change notifications (according to MSDN).
191
192 // Call CloseHandle of the Print Provider.
193 bReturnValue = pHandle->pPrintProvider->PrintProvider.fpClosePrinter(pHandle->hPrinter);
194 FIXME("ClosePrinter 2\n");
195 // Free our handle information.
196 DllFreeSplMem(pHandle);
197 FIXME("ClosePrinter 3\n");
198 return bReturnValue;
199}
200
203{
205
206 // Sanity checks.
207 if (!pHandle)
208 {
210 return FALSE;
211 }
212
213 return pHandle->pPrintProvider->PrintProvider.fpDeletePrinter(pHandle->hPrinter);
214}
215
218{
220
221 // Sanity checks.
222 if (!pHandle)
223 {
225 return FALSE;
226 }
227
228 return pHandle->pPrintProvider->PrintProvider.fpEndDocPrinter(pHandle->hPrinter);
229}
230
233{
235
236 // Sanity checks.
237 if (!pHandle)
238 {
240 return FALSE;
241 }
242
243 return pHandle->pPrintProvider->PrintProvider.fpEndPagePrinter(pHandle->hPrinter);
244}
245
248{
249 DWORD cbCallBuffer;
250 DWORD cbNeeded;
251 DWORD dwErrorCode = MAXDWORD;
252 DWORD dwReturned;
253 PBYTE pCallBuffer;
254 BOOL Ret = FALSE;
255 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
257
258 // Begin counting.
259 *pcbNeeded = 0;
260 *pcReturned = 0;
261
262 if (cbBuf && !pPrinterEnum)
263 {
264 dwErrorCode = ERROR_INVALID_USER_BUFFER;
265 goto Cleanup;
266 }
267
268 // At the beginning, we have the full buffer available.
269 cbCallBuffer = cbBuf;
270 pCallBuffer = pPrinterEnum;
271
272 // Loop through all Print Providers.
274 {
276
277 // Call the EnumPrinters function of this Print Provider.
278 cbNeeded = 0;
279 dwReturned = 0;
280 Ret = pPrintProvider->PrintProvider.fpEnumPrinters(Flags, Name, Level, pCallBuffer, cbCallBuffer, &cbNeeded, &dwReturned);
281
282 if ( !Ret )
283 {
284 dwErrorCode = GetLastError();
285 }
286
287 // Add the returned counts to the total values.
288 *pcbNeeded += cbNeeded;
289 *pcReturned += dwReturned;
290
291 // Reduce the available buffer size for the next call without risking an underflow.
292 if (cbNeeded < cbCallBuffer)
293 cbCallBuffer -= cbNeeded;
294 else
295 cbCallBuffer = 0;
296
297 // Advance the buffer if the caller provided it.
298 if (pCallBuffer)
299 pCallBuffer += cbNeeded;
300
301 // dwErrorCode shall not be overwritten if a previous EnumPrinters call already succeeded.
302 if (dwErrorCode != ERROR_SUCCESS)
303 dwErrorCode = GetLastError();
304 }
305
306Cleanup:
307 SetLastError(dwErrorCode);
308 return (dwErrorCode == ERROR_SUCCESS);
309}
310
313{
315
316 // Sanity checks.
317 if (!pHandle)
318 {
320 return FALSE;
321 }
322
323 return pHandle->pPrintProvider->PrintProvider.fpGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
324}
325
326//
327// Forward Dead API to Local/Remote....
328//
331{
333
334 // Sanity checks.
335 if (!pHandle)
336 {
338 return FALSE;
339 }
340
341 return pHandle->pPrintProvider->PrintProvider.fpPrinterMessageBox(pHandle->hPrinter, Error, hWnd, pText, pCaption, dwType);
342}
343
345OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
346{
347 BOOL bReturnValue;
348 DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
349 HANDLE hPrinter;
352 PSPOOLSS_PRINT_PROVIDER pPrintProvider;
353
354 // Loop through all Print Providers to find one able to open this Printer.
356 {
358
359 bReturnValue = pPrintProvider->PrintProvider.fpOpenPrinter(pPrinterName, &hPrinter, pDefault);
360 if (bReturnValue == ROUTER_SUCCESS)
361 {
362 // This Print Provider has opened this Printer.
363 // Store this information and return a handle.
364 pHandle = DllAllocSplMem(sizeof(SPOOLSS_PRINTER_HANDLE));
365 if (!pHandle)
366 {
367 dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
368 ERR("DllAllocSplMem failed!\n");
369 goto Cleanup;
370 }
371
372 pHandle->pPrintProvider = pPrintProvider;
373 pHandle->hPrinter = hPrinter;
374 *phPrinter = (HANDLE)pHandle;
375
376 dwErrorCode = ERROR_SUCCESS;
377 goto Cleanup;
378 }
379 else if (bReturnValue == ROUTER_STOP_ROUTING)
380 {
381 ERR("A Print Provider returned ROUTER_STOP_ROUTING for Printer \"%S\"!\n", pPrinterName);
382 dwErrorCode = GetLastError();
383 goto Cleanup;
384 }
385 }
386
387Cleanup:
388 // 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.
389 if (dwErrorCode == ERROR_INVALID_NAME)
390 dwErrorCode = ERROR_INVALID_PRINTER_NAME;
391
392 SetLastError(dwErrorCode);
393 return (dwErrorCode == ERROR_SUCCESS);
394}
395
397ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
398{
400
401 // Sanity checks.
402 if (!pHandle)
403 {
405 return FALSE;
406 }
407
408 return pHandle->pPrintProvider->PrintProvider.fpReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
409}
410
412SeekPrinter( HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite )
413{
415
416 // Sanity checks.
417 if (!pHandle)
418 {
420 return FALSE;
421 }
422
423 return pHandle->pPrintProvider->PrintProvider.fpSeekPrinter( pHandle->hPrinter, liDistanceToMove, pliNewPointer, dwMoveMethod, bWrite );
424}
425
428{
430
431 // Sanity checks.
432 if (!pHandle)
433 {
435 return FALSE;
436 }
437
438 return pHandle->pPrintProvider->PrintProvider.fpSetPrinter( pHandle->hPrinter, Level, pPrinter, Command );
439}
440
443{
445
446 // Sanity checks.
447 if (!pHandle)
448 {
450 return FALSE;
451 }
452
453 return pHandle->pPrintProvider->PrintProvider.fpStartDocPrinter(pHandle->hPrinter, Level, pDocInfo);
454}
455
458{
460
461 // Sanity checks.
462 if (!pHandle)
463 {
465 return FALSE;
466 }
467
468 return pHandle->pPrintProvider->PrintProvider.fpStartPagePrinter(pHandle->hPrinter);
469}
470
472WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
473{
475
476 // Sanity checks.
477 if (!pHandle)
478 {
480 return FALSE;
481 }
482
483 return pHandle->pPrintProvider->PrintProvider.fpWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten);
484}
485
487XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
488{
490
491 FIXME("XcvDataW( %p, %S,,,)\n",hXcv, pszDataName);
492
493 // Sanity checks.
494 if (!pHandle)
495 {
497 return FALSE;
498 }
499
500 return pHandle->pPrintProvider->PrintProvider.fpXcvData(pHandle->hPrinter, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
501}
HWND hWnd
Definition: settings.c:17
BOOL WINAPI XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
Definition: printers.c:487
DWORD WINAPI PrinterMessageBoxW(HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType)
Definition: printers.c:330
BOOL WINAPI DeletePrinter(HANDLE hPrinter)
Definition: printers.c:202
DWORD WINAPI StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
Definition: printers.c:442
BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
Definition: printers.c:312
BOOL WINAPI SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
Definition: printers.c:427
BOOL WINAPI EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: printers.c:247
HANDLE WINAPI AddPrinterExW(PWSTR pName, DWORD Level, PBYTE pPrinter, PBYTE pClientInfo, DWORD ClientInfoLevel)
Definition: printers.c:29
BOOL WINAPI EndDocPrinter(HANDLE hPrinter)
Definition: printers.c:217
BOOL WINAPI WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
Definition: printers.c:472
BOOL WINAPI ClosePrinter(HANDLE hPrinter)
Definition: printers.c:176
BOOL WINAPI AbortPrinter(HANDLE hPrinter)
Definition: printers.c:11
BOOL WINAPI ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
Definition: printers.c:397
BOOL WINAPI OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
Definition: printers.c:345
HANDLE WINAPI AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter)
Definition: printers.c:105
BOOL WINAPI EndPagePrinter(HANDLE hPrinter)
Definition: printers.c:232
BOOL WINAPI SeekPrinter(HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite)
Definition: printers.c:412
BOOL WINAPI StartPagePrinter(HANDLE hPrinter)
Definition: printers.c:457
BOOL Error
Definition: chkdsk.c:66
#define FIXME(fmt,...)
Definition: debug.h:111
#define ERR(fmt,...)
Definition: debug.h:110
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
#define ERROR_NOT_SUPPORTED
Definition: compat.h:100
#define ERROR_INVALID_NAME
Definition: compat.h:103
static const WCHAR Cleanup[]
Definition: register.c:80
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
PLIST_ENTRY pEntry
Definition: fxioqueue.cpp:4484
static HANDLE hXcv
Definition: localmon.c:73
static LPSTR pName
Definition: security.c:75
#define MAXDWORD
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
BYTE * PBYTE
Definition: pedump.c:66
DWORD * PDWORD
Definition: pedump.c:68
#define ROUTER_STOP_ROUTING
Definition: winsplp.h:42
#define ROUTER_SUCCESS
Definition: winsplp.h:41
Definition: shell.h:41
base of all file and directory entries
Definition: entries.h:83
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
LPWSTR pPrinterName
Definition: winspool.h:63
PSPOOLSS_PRINT_PROVIDER pPrintProvider
Definition: precomp.h:46
PRINTPROVIDOR PrintProvider
Definition: precomp.h:36
LPCSTR pText
Definition: txtscale.cpp:79
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
PVOID HANDLE
Definition: typedefs.h:73
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
LIST_ENTRY PrintProviderList
Definition: main.c:12
BOOL WINAPI DllFreeSplMem(PVOID pMem)
Definition: memory.c:112
PVOID WINAPI DllAllocSplMem(DWORD dwBytes)
Definition: memory.c:95
struct _SPOOLSS_PRINTER_HANDLE * PSPOOLSS_PRINTER_HANDLE
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_In_ DWORD _Out_ PDWORD pcbNeeded
Definition: winddi.h:3828
#define WINAPI
Definition: msvc.h:6
#define ERROR_INVALID_LEVEL
Definition: winerror.h:196
#define ERROR_INVALID_USER_BUFFER
Definition: winerror.h:1091
#define ERROR_INVALID_PRINTER_NAME
Definition: winerror.h:1108
struct _PRINTER_INFO_2W * PPRINTER_INFO_2W
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
WCHAR * LPWSTR
Definition: xmlstorage.h:184