ReactOS  0.4.15-dev-1033-gd7d716a
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 //
29 AddPrinterExW( PWSTR pName, DWORD Level, PBYTE pPrinter, PBYTE pClientInfo, DWORD ClientInfoLevel)
30 {
31  BOOL bReturnValue;
32  DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
33  HANDLE hPrinter = NULL;
34  PWSTR pPrinterName = NULL;
35  PLIST_ENTRY pEntry;
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.
52  for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
53  {
54  pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
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 
95 Cleanup:
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;
111  PLIST_ENTRY pEntry;
112  PSPOOLSS_PRINTER_HANDLE pHandle;
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.
132  for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
133  {
134  pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
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 
166 Cleanup:
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 
175 BOOL WINAPI
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 
201 BOOL WINAPI
203 {
205 
206  // Sanity checks.
207  if (!pHandle)
208  {
210  return FALSE;
211  }
212 
213  return pHandle->pPrintProvider->PrintProvider.fpDeletePrinter(pHandle->hPrinter);
214 }
215 
216 BOOL WINAPI
218 {
220 
221  // Sanity checks.
222  if (!pHandle)
223  {
225  return FALSE;
226  }
227 
228  return pHandle->pPrintProvider->PrintProvider.fpEndDocPrinter(pHandle->hPrinter);
229 }
230 
231 BOOL WINAPI
233 {
235 
236  // Sanity checks.
237  if (!pHandle)
238  {
240  return FALSE;
241  }
242 
243  return pHandle->pPrintProvider->PrintProvider.fpEndPagePrinter(pHandle->hPrinter);
244 }
245 
246 BOOL WINAPI
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;
256  PLIST_ENTRY pEntry;
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.
273  for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
274  {
275  pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
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 
306 Cleanup:
307  SetLastError(dwErrorCode);
308  return (dwErrorCode == ERROR_SUCCESS);
309 }
310 
311 BOOL WINAPI
312 GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
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 
344 BOOL WINAPI
345 OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
346 {
347  BOOL bReturnValue;
348  DWORD dwErrorCode = ERROR_INVALID_PRINTER_NAME;
349  HANDLE hPrinter;
350  PLIST_ENTRY pEntry;
351  PSPOOLSS_PRINTER_HANDLE pHandle;
352  PSPOOLSS_PRINT_PROVIDER pPrintProvider;
353 
354  // Loop through all Print Providers to find one able to open this Printer.
355  for (pEntry = PrintProviderList.Flink; pEntry != &PrintProviderList; pEntry = pEntry->Flink)
356  {
357  pPrintProvider = CONTAINING_RECORD(pEntry, SPOOLSS_PRINT_PROVIDER, Entry);
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 
387 Cleanup:
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 
396 BOOL WINAPI
397 ReadPrinter(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 
411 BOOL WINAPI
412 SeekPrinter( 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 
426 BOOL WINAPI
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 
456 BOOL WINAPI
458 {
460 
461  // Sanity checks.
462  if (!pHandle)
463  {
465  return FALSE;
466  }
467 
468  return pHandle->pPrintProvider->PrintProvider.fpStartPagePrinter(pHandle->hPrinter);
469 }
470 
471 BOOL WINAPI
472 WritePrinter(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 
486 BOOL WINAPI
487 XcvDataW(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 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
BOOL WINAPI EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: printers.c:247
const uint16_t * PCWSTR
Definition: typedefs.h:57
BOOL WINAPI ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
Definition: printers.c:397
LPCSTR pText
Definition: txtscale.cpp:79
#define ERROR_SUCCESS
Definition: deptool.c:10
struct _PRINTER_INFO_2W * PPRINTER_INFO_2W
uint16_t * PWSTR
Definition: typedefs.h:56
#define ROUTER_SUCCESS
Definition: winsplp.h:41
BOOL WINAPI DllFreeSplMem(PVOID pMem)
Definition: memory.c:112
HWND hWnd
Definition: settings.c:17
BOOL WINAPI AbortPrinter(HANDLE hPrinter)
Definition: printers.c:11
BOOL WINAPI SeekPrinter(HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite)
Definition: printers.c:412
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
DWORD WINAPI StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
Definition: printers.c:442
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
Definition: shell.h:41
struct _SPOOLSS_PRINTER_HANDLE * PSPOOLSS_PRINTER_HANDLE
BOOL WINAPI SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
Definition: printers.c:427
#define ERROR_INVALID_USER_BUFFER
Definition: winerror.h:1091
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define FALSE
Definition: types.h:117
HANDLE WINAPI AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter)
Definition: printers.c:105
unsigned int BOOL
Definition: ntddk_ex.h:94
#define FIXME(fmt,...)
Definition: debug.h:111
#define ROUTER_STOP_ROUTING
Definition: winsplp.h:42
smooth NULL
Definition: ftsmooth.c:416
#define MAXDWORD
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
BOOL WINAPI WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
Definition: printers.c:472
BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
Definition: printers.c:312
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
BOOL WINAPI ClosePrinter(HANDLE hPrinter)
Definition: printers.c:176
static LPSTR pName
Definition: security.c:75
#define WINAPI
Definition: msvc.h:6
LIST_ENTRY PrintProviderList
Definition: main.c:12
PVOID HANDLE
Definition: typedefs.h:73
unsigned long DWORD
Definition: ntddk_ex.h:95
BOOL Error
Definition: chkdsk.c:66
HANDLE WINAPI AddPrinterExW(PWSTR pName, DWORD Level, PBYTE pPrinter, PBYTE pClientInfo, DWORD ClientInfoLevel)
Definition: printers.c:29
#define SetLastError(x)
Definition: compat.h:500
DWORD WINAPI PrinterMessageBoxW(HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType)
Definition: printers.c:330
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:454
BOOL WINAPI EndPagePrinter(HANDLE hPrinter)
Definition: printers.c:232
Definition: typedefs.h:119
BOOL WINAPI XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
Definition: printers.c:487
static const WCHAR Cleanup[]
Definition: register.c:80
#define ERROR_INVALID_PRINTER_NAME
Definition: winerror.h:1108
#define ERR(fmt,...)
Definition: debug.h:110
_In_ DWORD _Out_ PDWORD pcbNeeded
Definition: winddi.h:3827
BOOL WINAPI DeletePrinter(HANDLE hPrinter)
Definition: printers.c:202
BOOL WINAPI StartPagePrinter(HANDLE hPrinter)
Definition: printers.c:457
BOOL WINAPI EndDocPrinter(HANDLE hPrinter)
Definition: printers.c:217
DWORD * PDWORD
Definition: pedump.c:68
BOOL WINAPI OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
Definition: printers.c:345
#define ERROR_NOT_SUPPORTED
Definition: compat.h:100
LPWSTR pPrinterName
Definition: winspool.h:63
#define ERROR_INVALID_NAME
Definition: compat.h:103
PRINTPROVIDOR PrintProvider
Definition: precomp.h:36
PVOID WINAPI DllAllocSplMem(DWORD dwBytes)
Definition: memory.c:95
static HANDLE hXcv
Definition: localmon.c:73
#define ERROR_INVALID_LEVEL
Definition: winerror.h:196
WCHAR * LPWSTR
Definition: xmlstorage.h:184
BYTE * PBYTE
Definition: pedump.c:66
base of all file and directory entries
Definition: entries.h:82
PSPOOLSS_PRINT_PROVIDER pPrintProvider
Definition: precomp.h:46