ReactOS  0.4.12-dev-712-ge6be187
printers.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Spooler API
3  * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE: Functions related to Printers and printing
5  * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org)
6  */
7 
8 #include "precomp.h"
9 #include <marshalling/printers.h>
11 
12 // Local Constants
13 
16 static const WCHAR wszWindowsKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
17 static const WCHAR wszDeviceValue[] = L"Device";
18 
19 static DWORD
21 {
22  DWORD cbNeeded;
23  DWORD dwErrorCode;
24  PJOB_INFO_1W pJobInfo1 = NULL;
25 
26  // Create the spool file.
28  if (pHandle->hSPLFile == INVALID_HANDLE_VALUE)
29  {
30  dwErrorCode = GetLastError();
31  ERR("CreateFileW failed for \"%S\" with error %lu!\n", pAddJobInfo1->Path, dwErrorCode);
32  goto Cleanup;
33  }
34 
35  // Get the size of the job information.
36  GetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, NULL, 0, &cbNeeded);
38  {
39  dwErrorCode = GetLastError();
40  ERR("GetJobW failed with error %lu!\n", dwErrorCode);
41  goto Cleanup;
42  }
43 
44  // Allocate enough memory for the returned job information.
45  pJobInfo1 = HeapAlloc(hProcessHeap, 0, cbNeeded);
46  if (!pJobInfo1)
47  {
48  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
49  ERR("HeapAlloc failed!\n");
50  goto Cleanup;
51  }
52 
53  // Get the job information.
54  if (!GetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, (PBYTE)pJobInfo1, cbNeeded, &cbNeeded))
55  {
56  dwErrorCode = GetLastError();
57  ERR("GetJobW failed with error %lu!\n", dwErrorCode);
58  goto Cleanup;
59  }
60 
61  // Add our document information.
62  if (pDocInfo1->pDatatype)
63  pJobInfo1->pDatatype = pDocInfo1->pDatatype;
64 
65  pJobInfo1->pDocument = pDocInfo1->pDocName;
66 
67  // Set the new job information.
68  if (!SetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, (PBYTE)pJobInfo1, 0))
69  {
70  dwErrorCode = GetLastError();
71  ERR("SetJobW failed with error %lu!\n", dwErrorCode);
72  goto Cleanup;
73  }
74 
75  // We were successful!
76  pHandle->dwJobID = pAddJobInfo1->JobId;
77  dwErrorCode = ERROR_SUCCESS;
78 
79 Cleanup:
80  if (pJobInfo1)
81  HeapFree(hProcessHeap, 0, pJobInfo1);
82 
83  return dwErrorCode;
84 }
85 
86 static DWORD
88 {
89  DWORD dwErrorCode;
90  WINSPOOL_DOC_INFO_CONTAINER DocInfoContainer;
91 
92  DocInfoContainer.Level = 1;
93  DocInfoContainer.DocInfo.pDocInfo1 = (WINSPOOL_DOC_INFO_1*)pDocInfo1;
94 
96  {
97  dwErrorCode = _RpcStartDocPrinter(pHandle->hPrinter, &DocInfoContainer, &pHandle->dwJobID);
98  }
100  {
101  dwErrorCode = RpcExceptionCode();
102  ERR("_RpcStartDocPrinter failed with exception code %lu!\n", dwErrorCode);
103  }
104  RpcEndExcept;
105 
106  return dwErrorCode;
107 }
108 
109 BOOL WINAPI
111 {
112  TRACE("AbortPrinter(%p)\n", hPrinter);
114  return FALSE;
115 }
116 
119 {
120  TRACE("AddPrinterA(%s, %lu, %p)\n", pName, Level, pPrinter);
122  return NULL;
123 }
124 
127 {
128  TRACE("AddPrinterW(%S, %lu, %p)\n", pName, Level, pPrinter);
130  return NULL;
131 }
132 
133 BOOL WINAPI
135 {
136  DWORD dwErrorCode;
137  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
138 
139  TRACE("ClosePrinter(%p)\n", hPrinter);
140 
141  // Sanity checks.
142  if (!pHandle)
143  {
144  dwErrorCode = ERROR_INVALID_HANDLE;
145  goto Cleanup;
146  }
147 
148  // Do the RPC call.
150  {
151  dwErrorCode = _RpcClosePrinter(&pHandle->hPrinter);
152  }
154  {
155  dwErrorCode = RpcExceptionCode();
156  ERR("_RpcClosePrinter failed with exception code %lu!\n", dwErrorCode);
157  }
158  RpcEndExcept;
159 
160  // Close any open file handle.
161  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
162  CloseHandle(pHandle->hSPLFile);
163 
164  // Free the memory for the handle.
165  HeapFree(hProcessHeap, 0, pHandle);
166 
167 Cleanup:
168  SetLastError(dwErrorCode);
169  return (dwErrorCode == ERROR_SUCCESS);
170 }
171 
172 BOOL WINAPI
174 {
175  TRACE("DeletePrinter(%p)\n", hPrinter);
177  return FALSE;
178 }
179 
181 DeviceCapabilitiesA(LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA* pDevMode)
182 {
183  TRACE("DeviceCapabilitiesA(%s, %s, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode);
185  return 0;
186 }
187 
189 DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, WORD fwCapability, LPWSTR pOutput, const DEVMODEW* pDevMode)
190 {
191  TRACE("DeviceCapabilitiesW(%S, %S, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode);
193  return 0;
194 }
195 
196 LONG WINAPI
197 DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode)
198 {
199  TRACE("DocumentPropertiesA(%p, %p, %s, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
201  return -1;
202 }
203 
205 {
206  PRINTER_INFO_9W *pi9 = NULL;
207  DWORD needed = 0;
208  BOOL res;
209 
210  res = GetPrinterW(hprn, 9, NULL, 0, &needed);
212  {
213  pi9 = HeapAlloc(hProcessHeap, 0, needed);
214  res = GetPrinterW(hprn, 9, (LPBYTE)pi9, needed, &needed);
215  }
216 
217  if (res)
218  return pi9;
219 
220  ERR("GetPrinterW failed with %u\n", GetLastError());
221  HeapFree(hProcessHeap, 0, pi9);
222  return NULL;
223 }
224 
225 LONG WINAPI
226 DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode)
227 {
228  HANDLE hUseHandle = NULL;
229  PRINTER_INFO_9W *pi9 = NULL;
230  LONG Result = -1, Length;
231 
232  TRACE("DocumentPropertiesW(%p, %p, %S, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
233  if (hPrinter)
234  {
235  hUseHandle = hPrinter;
236  }
237  else if (!OpenPrinterW(pDeviceName, &hUseHandle, NULL))
238  {
239  ERR("No handle, and no usable printer name passed in\n");
240  return -1;
241  }
242 
243  pi9 = get_devmodeW(hUseHandle);
244 
245  if (pi9)
246  {
247  Length = pi9->pDevMode->dmSize + pi9->pDevMode->dmDriverExtra;
248  // See wineps.drv PSDRV_ExtDeviceMode
249  if (fMode)
250  {
251  Result = 1; /* IDOK */
252 
253  if (fMode & DM_IN_BUFFER)
254  {
255  FIXME("Merge pDevModeInput with pi9, write back to driver!\n");
256  // See wineps.drv PSDRV_MergeDevmodes
257  }
258 
259  if (fMode & DM_IN_PROMPT)
260  {
261  FIXME("Show property sheet!\n");
262  Result = 2; /* IDCANCEL */
263  }
264 
266  {
267  if (pDevModeOutput)
268  {
269  memcpy(pDevModeOutput, pi9->pDevMode, pi9->pDevMode->dmSize + pi9->pDevMode->dmDriverExtra);
270  }
271  else
272  {
273  ERR("No pDevModeOutput\n");
274  Result = -1;
275  }
276  }
277  }
278  else
279  {
280  Result = Length;
281  }
282 
283  HeapFree(hProcessHeap, 0, pi9);
284  }
285 
286  if (hUseHandle && !hPrinter)
287  ClosePrinter(hUseHandle);
288  return Result;
289 }
290 
291 BOOL WINAPI
293 {
294  DWORD dwErrorCode;
295  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
296 
297  TRACE("EndDocPrinter(%p)\n", hPrinter);
298 
299  // Sanity checks.
300  if (!pHandle)
301  {
302  dwErrorCode = ERROR_INVALID_HANDLE;
303  goto Cleanup;
304  }
305 
306  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
307  {
308  // For spooled jobs, the document is finished by calling _RpcScheduleJob.
310  {
311  dwErrorCode = _RpcScheduleJob(pHandle->hPrinter, pHandle->dwJobID);
312  }
314  {
315  dwErrorCode = RpcExceptionCode();
316  ERR("_RpcScheduleJob failed with exception code %lu!\n", dwErrorCode);
317  }
318  RpcEndExcept;
319 
320  // Close the spool file handle.
321  CloseHandle(pHandle->hSPLFile);
322  }
323  else
324  {
325  // In all other cases, just call _RpcEndDocPrinter.
327  {
328  dwErrorCode = _RpcEndDocPrinter(pHandle->hPrinter);
329  }
331  {
332  dwErrorCode = RpcExceptionCode();
333  ERR("_RpcEndDocPrinter failed with exception code %lu!\n", dwErrorCode);
334  }
335  RpcEndExcept;
336  }
337 
338  // A new document can now be started again.
339  pHandle->bStartedDoc = FALSE;
340 
341 Cleanup:
342  SetLastError(dwErrorCode);
343  return (dwErrorCode == ERROR_SUCCESS);
344 }
345 
346 BOOL WINAPI
348 {
349  DWORD dwErrorCode;
350  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
351 
352  TRACE("EndPagePrinter(%p)\n", hPrinter);
353 
354  // Sanity checks.
355  if (!pHandle)
356  {
357  dwErrorCode = ERROR_INVALID_HANDLE;
358  goto Cleanup;
359  }
360 
361  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
362  {
363  // For spooled jobs, we don't need to do anything.
364  dwErrorCode = ERROR_SUCCESS;
365  }
366  else
367  {
368  // In all other cases, just call _RpcEndPagePrinter.
370  {
371  dwErrorCode = _RpcEndPagePrinter(pHandle->hPrinter);
372  }
374  {
375  dwErrorCode = RpcExceptionCode();
376  ERR("_RpcEndPagePrinter failed with exception code %lu!\n", dwErrorCode);
377  }
378  RpcEndExcept;
379  }
380 
381 Cleanup:
382  SetLastError(dwErrorCode);
383  return (dwErrorCode == ERROR_SUCCESS);
384 }
385 
386 BOOL WINAPI
388 {
389  TRACE("EnumPrintersA(%lu, %s, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
390  return FALSE;
391 }
392 
393 BOOL WINAPI
395 {
396  DWORD dwErrorCode;
397 
398  TRACE("EnumPrintersW(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
399 
400  // Dismiss invalid levels already at this point.
401  if (Level == 3 || Level > 5)
402  {
403  dwErrorCode = ERROR_INVALID_LEVEL;
404  goto Cleanup;
405  }
406 
407  if (cbBuf && pPrinterEnum)
408  ZeroMemory(pPrinterEnum, cbBuf);
409 
410  // Do the RPC call
412  {
413  dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
414  }
416  {
417  dwErrorCode = RpcExceptionCode();
418  ERR("_RpcEnumPrinters failed with exception code %lu!\n", dwErrorCode);
419  }
420  RpcEndExcept;
421 
422  if (dwErrorCode == ERROR_SUCCESS)
423  {
424  // Replace relative offset addresses in the output by absolute pointers.
425  ASSERT(Level <= 9);
426  MarshallUpStructuresArray(cbBuf, pPrinterEnum, *pcReturned, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
427  }
428 
429 Cleanup:
430  SetLastError(dwErrorCode);
431  return (dwErrorCode == ERROR_SUCCESS);
432 }
433 
434 BOOL WINAPI
435 FlushPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten, DWORD cSleep)
436 {
437  TRACE("FlushPrinter(%p, %p, %lu, %p, %lu)\n", hPrinter, pBuf, cbBuf, pcWritten, cSleep);
439  return FALSE;
440 }
441 
442 BOOL WINAPI
443 GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
444 {
445  DWORD dwErrorCode;
446  PWSTR pwszBuffer = NULL;
447 
448  TRACE("GetDefaultPrinterA(%p, %p)\n", pszBuffer, pcchBuffer);
449 
450  // Sanity check.
451  if (!pcchBuffer)
452  {
453  dwErrorCode = ERROR_INVALID_PARAMETER;
454  goto Cleanup;
455  }
456 
457  // Check if an ANSI buffer was given and if so, allocate a Unicode buffer of the same size.
458  if (pszBuffer && *pcchBuffer)
459  {
460  pwszBuffer = HeapAlloc(hProcessHeap, 0, *pcchBuffer * sizeof(WCHAR));
461  if (!pwszBuffer)
462  {
463  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
464  ERR("HeapAlloc failed!\n");
465  goto Cleanup;
466  }
467  }
468 
469  if (!GetDefaultPrinterW(pwszBuffer, pcchBuffer))
470  {
471  dwErrorCode = GetLastError();
472  goto Cleanup;
473  }
474 
475  // We successfully got a string in pwszBuffer, so convert the Unicode string to ANSI.
476  WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszBuffer, *pcchBuffer, NULL, NULL);
477 
478  dwErrorCode = ERROR_SUCCESS;
479 
480 Cleanup:
481  if (pwszBuffer)
482  HeapFree(hProcessHeap, 0, pwszBuffer);
483 
484  SetLastError(dwErrorCode);
485  return (dwErrorCode == ERROR_SUCCESS);
486 }
487 
488 BOOL WINAPI
489 GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
490 {
491  DWORD cbNeeded;
492  DWORD cchInputBuffer;
493  DWORD dwErrorCode;
494  HKEY hWindowsKey = NULL;
495  PWSTR pwszDevice = NULL;
496  PWSTR pwszComma;
497 
498  TRACE("GetDefaultPrinterW(%p, %p)\n", pszBuffer, pcchBuffer);
499 
500  // Sanity check.
501  if (!pcchBuffer)
502  {
503  dwErrorCode = ERROR_INVALID_PARAMETER;
504  goto Cleanup;
505  }
506 
507  cchInputBuffer = *pcchBuffer;
508 
509  // Open the registry key where the default printer for the current user is stored.
510  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_READ, &hWindowsKey);
511  if (dwErrorCode != ERROR_SUCCESS)
512  {
513  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
514  goto Cleanup;
515  }
516 
517  // Determine the size of the required buffer.
518  dwErrorCode = (DWORD)RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, NULL, &cbNeeded);
519  if (dwErrorCode != ERROR_SUCCESS)
520  {
521  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
522  goto Cleanup;
523  }
524 
525  // Allocate it.
526  pwszDevice = HeapAlloc(hProcessHeap, 0, cbNeeded);
527  if (!pwszDevice)
528  {
529  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
530  ERR("HeapAlloc failed!\n");
531  goto Cleanup;
532  }
533 
534  // Now get the actual value.
535  dwErrorCode = RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, (PBYTE)pwszDevice, &cbNeeded);
536  if (dwErrorCode != ERROR_SUCCESS)
537  {
538  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
539  goto Cleanup;
540  }
541 
542  // We get a string "<Printer Name>,winspool,<Port>:".
543  // Extract the printer name from it.
544  pwszComma = wcschr(pwszDevice, L',');
545  if (!pwszComma)
546  {
547  ERR("Found no or invalid default printer: %S!\n", pwszDevice);
548  dwErrorCode = ERROR_INVALID_NAME;
549  goto Cleanup;
550  }
551 
552  // Store the length of the Printer Name (including the terminating NUL character!) in *pcchBuffer.
553  *pcchBuffer = pwszComma - pwszDevice + 1;
554 
555  // Check if the supplied buffer is large enough.
556  if (cchInputBuffer < *pcchBuffer)
557  {
558  dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
559  goto Cleanup;
560  }
561 
562  // Copy the default printer.
563  *pwszComma = 0;
564  CopyMemory(pszBuffer, pwszDevice, *pcchBuffer * sizeof(WCHAR));
565 
566  dwErrorCode = ERROR_SUCCESS;
567 
568 Cleanup:
569  if (hWindowsKey)
570  RegCloseKey(hWindowsKey);
571 
572  if (pwszDevice)
573  HeapFree(hProcessHeap, 0, pwszDevice);
574 
575  SetLastError(dwErrorCode);
576  return (dwErrorCode == ERROR_SUCCESS);
577 }
578 
579 BOOL WINAPI
581 {
582  TRACE("GetPrinterA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
583  return FALSE;
584 }
585 
586 BOOL WINAPI
587 GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
588 {
589  TRACE("GetPrinterDriverA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
590  return FALSE;
591 }
592 
593 BOOL WINAPI
594 GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
595 {
596  DWORD dwErrorCode;
597  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
598 
599  TRACE("GetPrinterDriverW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
600 
601  // Sanity checks.
602  if (!pHandle)
603  {
604  dwErrorCode = ERROR_INVALID_HANDLE;
605  goto Cleanup;
606  }
607 
608  // Dismiss invalid levels already at this point.
609  if (Level > 8 || Level < 1)
610  {
611  dwErrorCode = ERROR_INVALID_LEVEL;
612  goto Cleanup;
613  }
614 
615  if (cbBuf && pDriverInfo)
616  ZeroMemory(pDriverInfo, cbBuf);
617 
618  // Do the RPC call
620  {
621  dwErrorCode = _RpcGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
622  }
624  {
625  dwErrorCode = RpcExceptionCode();
626  ERR("_RpcGetPrinter failed with exception code %lu!\n", dwErrorCode);
627  }
628  RpcEndExcept;
629 
630  if (dwErrorCode == ERROR_SUCCESS)
631  {
632  // Replace relative offset addresses in the output by absolute pointers.
633  ASSERT(Level <= 3);
634  MarshallUpStructure(cbBuf, pDriverInfo, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
635  }
636 
637 Cleanup:
638  SetLastError(dwErrorCode);
639  return (dwErrorCode == ERROR_SUCCESS);
640 }
641 
642 BOOL WINAPI
644 {
645  DWORD dwErrorCode;
646  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
647 
648  TRACE("GetPrinterW(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
649 
650  // Sanity checks.
651  if (!pHandle)
652  {
653  dwErrorCode = ERROR_INVALID_HANDLE;
654  goto Cleanup;
655  }
656 
657  // Dismiss invalid levels already at this point.
658  if (Level > 9)
659  {
660  dwErrorCode = ERROR_INVALID_LEVEL;
661  goto Cleanup;
662  }
663 
664  if (cbBuf && pPrinter)
665  ZeroMemory(pPrinter, cbBuf);
666 
667  // Do the RPC call
669  {
670  dwErrorCode = _RpcGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
671  }
673  {
674  dwErrorCode = RpcExceptionCode();
675  ERR("_RpcGetPrinter failed with exception code %lu!\n", dwErrorCode);
676  }
677  RpcEndExcept;
678 
679  if (dwErrorCode == ERROR_SUCCESS)
680  {
681  // Replace relative offset addresses in the output by absolute pointers.
682  ASSERT(Level <= 9);
683  MarshallUpStructure(cbBuf, pPrinter, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
684  }
685 
686 Cleanup:
687  SetLastError(dwErrorCode);
688  return (dwErrorCode == ERROR_SUCCESS);
689 }
690 
691 BOOL WINAPI
692 OpenPrinterA(LPSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSA pDefault)
693 {
694  BOOL bReturnValue = FALSE;
695  DWORD cch;
696  PWSTR pwszPrinterName = NULL;
697  PRINTER_DEFAULTSW wDefault = { 0 };
698 
699  TRACE("OpenPrinterA(%s, %p, %p)\n", pPrinterName, phPrinter, pDefault);
700 
701  if (pPrinterName)
702  {
703  // Convert pPrinterName to a Unicode string pwszPrinterName
704  cch = strlen(pPrinterName);
705 
706  pwszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
707  if (!pwszPrinterName)
708  {
710  ERR("HeapAlloc failed!\n");
711  goto Cleanup;
712  }
713 
714  MultiByteToWideChar(CP_ACP, 0, pPrinterName, -1, pwszPrinterName, cch + 1);
715  }
716 
717  if (pDefault)
718  {
719  wDefault.DesiredAccess = pDefault->DesiredAccess;
720 
721  if (pDefault->pDatatype)
722  {
723  // Convert pDefault->pDatatype to a Unicode string wDefault.pDatatype
724  cch = strlen(pDefault->pDatatype);
725 
726  wDefault.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
727  if (!wDefault.pDatatype)
728  {
730  ERR("HeapAlloc failed!\n");
731  goto Cleanup;
732  }
733 
734  MultiByteToWideChar(CP_ACP, 0, pDefault->pDatatype, -1, wDefault.pDatatype, cch + 1);
735  }
736 
737  if (pDefault->pDevMode)
738  wDefault.pDevMode = GdiConvertToDevmodeW(pDefault->pDevMode);
739  }
740 
741  bReturnValue = OpenPrinterW(pwszPrinterName, phPrinter, &wDefault);
742 
743 Cleanup:
744  if (wDefault.pDatatype)
745  HeapFree(hProcessHeap, 0, wDefault.pDatatype);
746 
747  if (wDefault.pDevMode)
748  HeapFree(hProcessHeap, 0, wDefault.pDevMode);
749 
750  if (pwszPrinterName)
751  HeapFree(hProcessHeap, 0, pwszPrinterName);
752 
753  return bReturnValue;
754 }
755 
756 BOOL WINAPI
757 OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefault)
758 {
759  DWORD dwErrorCode;
760  HANDLE hPrinter;
761  PSPOOLER_HANDLE pHandle;
762  PWSTR pDatatype = NULL;
763  WINSPOOL_DEVMODE_CONTAINER DevModeContainer = { 0 };
764  ACCESS_MASK AccessRequired = 0;
765 
766  TRACE("OpenPrinterW(%S, %p, %p)\n", pPrinterName, phPrinter, pDefault);
767 
768  // Sanity check
769  if (!phPrinter)
770  {
771  dwErrorCode = ERROR_INVALID_PARAMETER;
772  goto Cleanup;
773  }
774 
775  // Prepare the additional parameters in the format required by _RpcOpenPrinter
776  if (pDefault)
777  {
778  pDatatype = pDefault->pDatatype;
779  DevModeContainer.cbBuf = sizeof(DEVMODEW);
780  DevModeContainer.pDevMode = (BYTE*)pDefault->pDevMode;
781  AccessRequired = pDefault->DesiredAccess;
782  }
783 
784  // Do the RPC call
786  {
787  dwErrorCode = _RpcOpenPrinter(pPrinterName, &hPrinter, pDatatype, &DevModeContainer, AccessRequired);
788  }
790  {
791  dwErrorCode = RpcExceptionCode();
792  ERR("_RpcOpenPrinter failed with exception code %lu!\n", dwErrorCode);
793  }
794  RpcEndExcept;
795 
796  if (dwErrorCode == ERROR_SUCCESS)
797  {
798  // Create a new SPOOLER_HANDLE structure.
800  if (!pHandle)
801  {
802  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
803  ERR("HeapAlloc failed!\n");
804  goto Cleanup;
805  }
806 
807  pHandle->hPrinter = hPrinter;
808  pHandle->hSPLFile = INVALID_HANDLE_VALUE;
809 
810  // Return it as phPrinter.
811  *phPrinter = (HANDLE)pHandle;
812  }
813 
814 Cleanup:
815  SetLastError(dwErrorCode);
816  return (dwErrorCode == ERROR_SUCCESS);
817 }
818 
819 BOOL WINAPI
820 ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
821 {
822  DWORD dwErrorCode;
823  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
824 
825  TRACE("ReadPrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pNoBytesRead);
826 
827  // Sanity checks.
828  if (!pHandle)
829  {
830  dwErrorCode = ERROR_INVALID_HANDLE;
831  goto Cleanup;
832  }
833 
834  // Do the RPC call
836  {
837  dwErrorCode = _RpcReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
838  }
840  {
841  dwErrorCode = RpcExceptionCode();
842  ERR("_RpcReadPrinter failed with exception code %lu!\n", dwErrorCode);
843  }
844  RpcEndExcept;
845 
846 Cleanup:
847  SetLastError(dwErrorCode);
848  return (dwErrorCode == ERROR_SUCCESS);
849 }
850 
851 BOOL WINAPI
853 {
854  TRACE("ResetPrinterA(%p, %p)\n", hPrinter, pDefault);
856  return FALSE;
857 }
858 
859 BOOL WINAPI
861 {
862  TRACE("ResetPrinterW(%p, %p)\n", hPrinter, pDefault);
864  return FALSE;
865 }
866 
867 BOOL WINAPI
869 {
870  BOOL bReturnValue = FALSE;
871  DWORD cch;
872  PWSTR pwszPrinter = NULL;
873 
874  TRACE("SetDefaultPrinterA(%s)\n", pszPrinter);
875 
876  if (pszPrinter)
877  {
878  // Convert pszPrinter to a Unicode string pwszPrinter
879  cch = strlen(pszPrinter);
880 
881  pwszPrinter = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
882  if (!pwszPrinter)
883  {
885  ERR("HeapAlloc failed!\n");
886  goto Cleanup;
887  }
888 
889  MultiByteToWideChar(CP_ACP, 0, pszPrinter, -1, pwszPrinter, cch + 1);
890  }
891 
892  bReturnValue = SetDefaultPrinterW(pwszPrinter);
893 
894 Cleanup:
895  if (pwszPrinter)
896  HeapFree(hProcessHeap, 0, pwszPrinter);
897 
898  return bReturnValue;
899 }
900 
901 BOOL WINAPI
903 {
904  const WCHAR wszDevicesKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Devices";
905 
906  DWORD cbDeviceValueData;
907  DWORD cbPrinterValueData = 0;
908  DWORD cchPrinter;
909  DWORD dwErrorCode;
910  HKEY hDevicesKey = NULL;
911  HKEY hWindowsKey = NULL;
912  PWSTR pwszDeviceValueData = NULL;
913  WCHAR wszPrinter[MAX_PRINTER_NAME + 1];
914 
915  TRACE("SetDefaultPrinterW(%S)\n", pszPrinter);
916 
917  // Open the Devices registry key.
918  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszDevicesKey, 0, KEY_READ, &hDevicesKey);
919  if (dwErrorCode != ERROR_SUCCESS)
920  {
921  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
922  goto Cleanup;
923  }
924 
925  // Did the caller give us a printer to set as default?
926  if (pszPrinter && *pszPrinter)
927  {
928  // Check if the given printer exists and query the value data size.
929  dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, NULL, &cbPrinterValueData);
930  if (dwErrorCode == ERROR_FILE_NOT_FOUND)
931  {
932  dwErrorCode = ERROR_INVALID_PRINTER_NAME;
933  goto Cleanup;
934  }
935  else if (dwErrorCode != ERROR_SUCCESS)
936  {
937  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
938  goto Cleanup;
939  }
940 
941  cchPrinter = wcslen(pszPrinter);
942  }
943  else
944  {
945  // If there is already a default printer, we're done!
946  cchPrinter = _countof(wszPrinter);
947  if (GetDefaultPrinterW(wszPrinter, &cchPrinter))
948  {
949  dwErrorCode = ERROR_SUCCESS;
950  goto Cleanup;
951  }
952 
953  // Otherwise, get us the first printer from the "Devices" key to later set it as default and query the value data size.
954  cchPrinter = _countof(wszPrinter);
955  dwErrorCode = (DWORD)RegEnumValueW(hDevicesKey, 0, wszPrinter, &cchPrinter, NULL, NULL, NULL, &cbPrinterValueData);
956  if (dwErrorCode != ERROR_MORE_DATA)
957  goto Cleanup;
958 
959  pszPrinter = wszPrinter;
960  }
961 
962  // We now need to query the value data, which has the format "winspool,<Port>:"
963  // and make "<Printer Name>,winspool,<Port>:" out of it.
964  // Allocate a buffer large enough for the final data.
965  cbDeviceValueData = (cchPrinter + 1) * sizeof(WCHAR) + cbPrinterValueData;
966  pwszDeviceValueData = HeapAlloc(hProcessHeap, 0, cbDeviceValueData);
967  if (!pwszDeviceValueData)
968  {
969  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
970  ERR("HeapAlloc failed!\n");
971  goto Cleanup;
972  }
973 
974  // Copy the Printer Name and a comma into it.
975  CopyMemory(pwszDeviceValueData, pszPrinter, cchPrinter * sizeof(WCHAR));
976  pwszDeviceValueData[cchPrinter] = L',';
977 
978  // Append the value data, which has the format "winspool,<Port>:"
979  dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, (PBYTE)&pwszDeviceValueData[cchPrinter + 1], &cbPrinterValueData);
980  if (dwErrorCode != ERROR_SUCCESS)
981  goto Cleanup;
982 
983  // Open the Windows registry key.
984  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_SET_VALUE, &hWindowsKey);
985  if (dwErrorCode != ERROR_SUCCESS)
986  {
987  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
988  goto Cleanup;
989  }
990 
991  // Store our new default printer.
992  dwErrorCode = (DWORD)RegSetValueExW(hWindowsKey, wszDeviceValue, 0, REG_SZ, (PBYTE)pwszDeviceValueData, cbDeviceValueData);
993  if (dwErrorCode != ERROR_SUCCESS)
994  {
995  ERR("RegSetValueExW failed with status %lu!\n", dwErrorCode);
996  goto Cleanup;
997  }
998 
999 Cleanup:
1000  if (hDevicesKey)
1001  RegCloseKey(hDevicesKey);
1002 
1003  if (hWindowsKey)
1004  RegCloseKey(hWindowsKey);
1005 
1006  if (pwszDeviceValueData)
1007  HeapFree(hProcessHeap, 0, pwszDeviceValueData);
1008 
1009  SetLastError(dwErrorCode);
1010  return (dwErrorCode == ERROR_SUCCESS);
1011 }
1012 
1013 BOOL WINAPI
1015 {
1016  TRACE("SetPrinterA(%p, %lu, %p, %lu)\n", hPrinter, Level, pPrinter, Command);
1017  UNIMPLEMENTED;
1018  return FALSE;
1019 }
1020 
1021 BOOL WINAPI
1023 {
1024  TRACE("SetPrinterW(%p, %lu, %p, %lu)\n", hPrinter, Level, pPrinter, Command);
1025  UNIMPLEMENTED;
1026  return FALSE;
1027 }
1028 
1029 DWORD WINAPI
1031 {
1032  DOC_INFO_1W wDocInfo1 = { 0 };
1033  DWORD cch;
1034  DWORD dwErrorCode;
1035  DWORD dwReturnValue = 0;
1036  PDOC_INFO_1A pDocInfo1 = (PDOC_INFO_1A)pDocInfo;
1037 
1038  TRACE("StartDocPrinterA(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
1039 
1040  // Only check the minimum required for accessing pDocInfo.
1041  // Additional sanity checks are done in StartDocPrinterW.
1042  if (!pDocInfo1)
1043  {
1044  dwErrorCode = ERROR_INVALID_PARAMETER;
1045  goto Cleanup;
1046  }
1047 
1048  if (Level != 1)
1049  {
1050  dwErrorCode = ERROR_INVALID_LEVEL;
1051  goto Cleanup;
1052  }
1053 
1054  if (pDocInfo1->pDatatype)
1055  {
1056  // Convert pDocInfo1->pDatatype to a Unicode string wDocInfo1.pDatatype
1057  cch = strlen(pDocInfo1->pDatatype);
1058 
1059  wDocInfo1.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
1060  if (!wDocInfo1.pDatatype)
1061  {
1062  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1063  ERR("HeapAlloc failed!\n");
1064  goto Cleanup;
1065  }
1066 
1067  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDatatype, -1, wDocInfo1.pDatatype, cch + 1);
1068  }
1069 
1070  if (pDocInfo1->pDocName)
1071  {
1072  // Convert pDocInfo1->pDocName to a Unicode string wDocInfo1.pDocName
1073  cch = strlen(pDocInfo1->pDocName);
1074 
1075  wDocInfo1.pDocName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
1076  if (!wDocInfo1.pDocName)
1077  {
1078  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1079  ERR("HeapAlloc failed!\n");
1080  goto Cleanup;
1081  }
1082 
1083  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDocName, -1, wDocInfo1.pDocName, cch + 1);
1084  }
1085 
1086  if (pDocInfo1->pOutputFile)
1087  {
1088  // Convert pDocInfo1->pOutputFile to a Unicode string wDocInfo1.pOutputFile
1089  cch = strlen(pDocInfo1->pOutputFile);
1090 
1091  wDocInfo1.pOutputFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
1092  if (!wDocInfo1.pOutputFile)
1093  {
1094  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1095  ERR("HeapAlloc failed!\n");
1096  goto Cleanup;
1097  }
1098 
1099  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pOutputFile, -1, wDocInfo1.pOutputFile, cch + 1);
1100  }
1101 
1102  dwReturnValue = StartDocPrinterW(hPrinter, Level, (PBYTE)&wDocInfo1);
1103  dwErrorCode = GetLastError();
1104 
1105 Cleanup:
1106  if (wDocInfo1.pDatatype)
1107  HeapFree(hProcessHeap, 0, wDocInfo1.pDatatype);
1108 
1109  if (wDocInfo1.pDocName)
1110  HeapFree(hProcessHeap, 0, wDocInfo1.pDocName);
1111 
1112  if (wDocInfo1.pOutputFile)
1113  HeapFree(hProcessHeap, 0, wDocInfo1.pOutputFile);
1114 
1115  SetLastError(dwErrorCode);
1116  return dwReturnValue;
1117 }
1118 
1119 DWORD WINAPI
1121 {
1122  DWORD cbAddJobInfo1;
1123  DWORD cbNeeded;
1124  DWORD dwErrorCode;
1125  DWORD dwReturnValue = 0;
1126  PADDJOB_INFO_1W pAddJobInfo1 = NULL;
1127  PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo;
1128  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
1129 
1130  TRACE("StartDocPrinterW(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
1131 
1132  // Sanity checks.
1133  if (!pHandle)
1134  {
1135  dwErrorCode = ERROR_INVALID_HANDLE;
1136  goto Cleanup;
1137  }
1138 
1139  if (!pDocInfo1)
1140  {
1141  dwErrorCode = ERROR_INVALID_PARAMETER;
1142  goto Cleanup;
1143  }
1144 
1145  if (Level != 1)
1146  {
1147  dwErrorCode = ERROR_INVALID_LEVEL;
1148  goto Cleanup;
1149  }
1150 
1151  if (pHandle->bStartedDoc)
1152  {
1153  dwErrorCode = ERROR_INVALID_PRINTER_STATE;
1154  goto Cleanup;
1155  }
1156 
1157  // Check if we want to redirect output into a file.
1158  if (pDocInfo1->pOutputFile)
1159  {
1160  // Do a StartDocPrinter RPC call in this case.
1161  dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1);
1162  }
1163  else
1164  {
1165  // Allocate memory for the ADDJOB_INFO_1W structure and a path.
1166  cbAddJobInfo1 = sizeof(ADDJOB_INFO_1W) + MAX_PATH * sizeof(WCHAR);
1167  pAddJobInfo1 = HeapAlloc(hProcessHeap, 0, cbAddJobInfo1);
1168  if (!pAddJobInfo1)
1169  {
1170  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1171  ERR("HeapAlloc failed!\n");
1172  goto Cleanup;
1173  }
1174 
1175  // Try to add a new job.
1176  // This only succeeds if the printer is set to do spooled printing.
1177  if (AddJobW((HANDLE)pHandle, 1, (PBYTE)pAddJobInfo1, cbAddJobInfo1, &cbNeeded))
1178  {
1179  // Do spooled printing.
1180  dwErrorCode = _StartDocPrinterSpooled(pHandle, pDocInfo1, pAddJobInfo1);
1181  }
1182  else if (GetLastError() == ERROR_INVALID_ACCESS)
1183  {
1184  // ERROR_INVALID_ACCESS is returned when the printer is set to do direct printing.
1185  // In this case, we do a StartDocPrinter RPC call.
1186  dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1);
1187  }
1188  else
1189  {
1190  dwErrorCode = GetLastError();
1191  ERR("AddJobW failed with error %lu!\n", dwErrorCode);
1192  goto Cleanup;
1193  }
1194  }
1195 
1196  if (dwErrorCode == ERROR_SUCCESS)
1197  {
1198  pHandle->bStartedDoc = TRUE;
1199  dwReturnValue = pHandle->dwJobID;
1200  }
1201 
1202 Cleanup:
1203  if (pAddJobInfo1)
1204  HeapFree(hProcessHeap, 0, pAddJobInfo1);
1205 
1206  SetLastError(dwErrorCode);
1207  return dwReturnValue;
1208 }
1209 
1210 BOOL WINAPI
1212 {
1213  DWORD dwErrorCode;
1214  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
1215 
1216  TRACE("StartPagePrinter(%p)\n", hPrinter);
1217 
1218  // Sanity checks.
1219  if (!pHandle)
1220  {
1221  dwErrorCode = ERROR_INVALID_HANDLE;
1222  goto Cleanup;
1223  }
1224 
1225  // Do the RPC call
1226  RpcTryExcept
1227  {
1228  dwErrorCode = _RpcStartPagePrinter(pHandle->hPrinter);
1229  }
1231  {
1232  dwErrorCode = RpcExceptionCode();
1233  ERR("_RpcStartPagePrinter failed with exception code %lu!\n", dwErrorCode);
1234  }
1235  RpcEndExcept;
1236 
1237 Cleanup:
1238  SetLastError(dwErrorCode);
1239  return (dwErrorCode == ERROR_SUCCESS);
1240 }
1241 
1242 BOOL WINAPI
1243 WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
1244 {
1245  DWORD dwErrorCode;
1246  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
1247 
1248  TRACE("WritePrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pcWritten);
1249 
1250  // Sanity checks.
1251  if (!pHandle)
1252  {
1253  dwErrorCode = ERROR_INVALID_HANDLE;
1254  goto Cleanup;
1255  }
1256 
1257  if (!pHandle->bStartedDoc)
1258  {
1259  dwErrorCode = ERROR_SPL_NO_STARTDOC;
1260  goto Cleanup;
1261  }
1262 
1263  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
1264  {
1265  // Write to the spool file. This doesn't need an RPC request.
1266  if (!WriteFile(pHandle->hSPLFile, pBuf, cbBuf, pcWritten, NULL))
1267  {
1268  dwErrorCode = GetLastError();
1269  ERR("WriteFile failed with error %lu!\n", dwErrorCode);
1270  goto Cleanup;
1271  }
1272 
1273  dwErrorCode = ERROR_SUCCESS;
1274  }
1275  else
1276  {
1277  // TODO: This case (for direct printing or remote printing) has bad performance if multiple small-sized WritePrinter calls are performed.
1278  // We may increase performance by writing into a buffer and only doing a single RPC call when the buffer is full.
1279 
1280  // Do the RPC call
1281  RpcTryExcept
1282  {
1283  dwErrorCode = _RpcWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten);
1284  }
1286  {
1287  dwErrorCode = RpcExceptionCode();
1288  ERR("_RpcWritePrinter failed with exception code %lu!\n", dwErrorCode);
1289  }
1290  RpcEndExcept;
1291  }
1292 
1293 Cleanup:
1294  SetLastError(dwErrorCode);
1295  return (dwErrorCode == ERROR_SUCCESS);
1296 }
1297 
1298 BOOL WINAPI
1299 XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
1300 {
1301  TRACE("XcvDataW(%p, %S, %p, %lu, %p, %lu, %p, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
1302  return FALSE;
1303 }
static PRINTER_INFO_9W * get_devmodeW(HANDLE hprn)
Definition: printers.c:204
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
BOOL WINAPI EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: printers.c:66
DWORD _RpcStartPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:267
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
const uint16_t * PCWSTR
Definition: typedefs.h:55
LPWSTR pDocName
Definition: winspool.h:556
BOOL WINAPI ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
Definition: printers.c:207
#define RpcEndExcept
Definition: rpc.h:128
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
#define ERROR_SUCCESS
Definition: deptool.c:10
#define WideCharToMultiByte
Definition: compat.h:101
#define KEY_SET_VALUE
Definition: nt_native.h:1017
#define DM_IN_PROMPT
Definition: windef.h:343
#define DM_OUT_DEFAULT
Definition: windef.h:345
BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
Definition: printers.c:587
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define KEY_READ
Definition: nt_native.h:1023
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define DWORD
Definition: msvc.h:34
uint16_t * PWSTR
Definition: typedefs.h:54
DWORD _RpcEndDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:61
BOOL WINAPI SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
Definition: printers.c:1022
#define CP_ACP
Definition: compat.h:99
#define _countof(array)
Definition: fontsub.cpp:30
DWORD WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, WORD fwCapability, LPWSTR pOutput, const DEVMODEW *pDevMode)
Definition: printers.c:189
#define HKEY_CURRENT_USER
Definition: winreg.h:11
WINBOOL WINAPI GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded)
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
LPWSTR pOutputFile
Definition: winspool.h:557
BOOL WINAPI GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
Definition: printers.c:443
HWND hWnd
Definition: settings.c:17
struct _ADDJOB_INFO_1W ADDJOB_INFO_1W
WORD dmDriverExtra
Definition: wingdi.h:1599
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
DWORD _RpcEnumPrinters(DWORD Flags, WINSPOOL_HANDLE Name, DWORD Level, BYTE *pPrinterEnum, DWORD cbBuf, DWORD *pcbNeeded, DWORD *pcReturned)
Definition: printers.c:99
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
DWORD WINAPI StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
Definition: printers.c:222
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
LPDEVMODEW pDevMode
Definition: winspool.h:170
Definition: shell.h:41
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
char * LPSTR
Definition: xmlstorage.h:182
DEVMODEW *WINAPI GdiConvertToDevmodeW(const DEVMODEA *)
Definition: misc.c:968
BOOL bStartedDoc
Definition: precomp.h:32
BOOL WINAPI ResetPrinterA(HANDLE hPrinter, PPRINTER_DEFAULTSA pDefault)
Definition: printers.c:852
DWORD dwJobID
Definition: precomp.h:33
BOOL WINAPI DeletePrinter(HANDLE hPrinter)
Definition: printers.c:173
#define FILE_SHARE_READ
Definition: compat.h:125
LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode)
Definition: printers.c:226
LPDEVMODEW pDevMode
Definition: winspool.h:769
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
DWORD _RpcStartDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, WINSPOOL_DOC_INFO_CONTAINER *pDocInfoContainer, DWORD *pJobId)
Definition: printers.c:248
LPCRECT BOOL fMode
Definition: msvc.h:58
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:52
BOOL WINAPI GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
Definition: printers.c:489
long LONG
Definition: pedump.c:60
#define DM_OUT_BUFFER
Definition: windef.h:344
BOOL WINAPI AbortPrinter(HANDLE hPrinter)
Definition: printers.c:110
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FIXME(fmt,...)
Definition: debug.h:110
#define RpcTryExcept
Definition: rpc.h:126
DWORD _RpcEndPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:80
#define ERROR_SPL_NO_STARTDOC
Definition: winerror.h:1208
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
LONG WINAPI RegEnumValueW(_In_ HKEY hKey, _In_ DWORD index, _Out_ LPWSTR value, _Inout_ PDWORD val_count, _Reserved_ PDWORD reserved, _Out_opt_ PDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ PDWORD count)
Definition: reg.c:2867
BOOL WINAPI ResetPrinterW(HANDLE hPrinter, PPRINTER_DEFAULTSW pDefault)
Definition: printers.c:860
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:201
smooth NULL
Definition: ftsmooth.c:416
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
Definition: printers.c:125
static DWORD _StartDocPrinterWithRPC(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1)
Definition: printers.c:87
const char * LPCSTR
Definition: xmlstorage.h:183
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
BOOL WINAPI WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
Definition: printers.c:252
BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
Definition: printers.c:140
HANDLE hSPLFile
Definition: precomp.h:35
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4917
BOOL WINAPI ClosePrinter(HANDLE hPrinter)
Definition: printers.c:12
#define RpcExceptionCode()
Definition: rpc.h:132
#define TRACE(s)
Definition: solgame.cpp:4
static LPSTR pName
Definition: security.c:75
unsigned int BOOL
Definition: ntddk_ex.h:94
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4134
LPWSTR pDatatype
Definition: winspool.h:558
LPDEVMODEA pDevMode
Definition: winspool.h:763
DWORD _RpcScheduleJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId)
Definition: jobs.c:110
BOOL WINAPI FlushPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten, DWORD cSleep)
Definition: printers.c:435
WORD dmSize
Definition: wingdi.h:1598
#define MAX_PATH
Definition: compat.h:26
DWORD _RpcWritePrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE *pBuf, DWORD cbBuf, DWORD *pcWritten)
Definition: printers.c:286
#define CopyMemory
Definition: winbase.h:1633
unsigned short WORD
Definition: ntddk_ex.h:93
PVOID HANDLE
Definition: typedefs.h:71
unsigned long DWORD
Definition: ntddk_ex.h:95
ACCESS_MASK DesiredAccess
Definition: winspool.h:770
#define SetLastError(x)
Definition: compat.h:409
DWORD _RpcReadPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE *pBuf, DWORD cbBuf, DWORD *pcNoBytesRead)
Definition: printers.c:201
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define MAX_PRINTER_NAME
Definition: fpSetJob.c:25
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
static const WCHAR wszWindowsKey[]
Definition: printers.c:16
LPSTR pOutputFile
Definition: winspool.h:551
static const WCHAR L[]
Definition: oid.c:1250
LPSTR pDatatype
Definition: winspool.h:552
BOOL WINAPI OpenPrinterA(LPSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSA pDefault)
Definition: printers.c:692
BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
Definition: printers.c:1014
BOOL WINAPI EndPagePrinter(HANDLE hPrinter)
Definition: printers.c:51
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned char BYTE
Definition: mem.h:68
#define ERROR_INVALID_ACCESS
Definition: winerror.h:115
DWORD _RpcOpenPrinter(WINSPOOL_HANDLE pPrinterName, WINSPOOL_PRINTER_HANDLE *phPrinter, WCHAR *pDatatype, WINSPOOL_DEVMODE_CONTAINER *pDevModeContainer, DWORD AccessRequired)
Definition: printers.c:170
WINSPOOL_DOC_INFO_1 * pDocInfo1
Definition: winspool.idl:577
BOOL WINAPI XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
Definition: printers.c:267
static const WCHAR Cleanup[]
Definition: register.c:80
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define WINAPI
Definition: msvc.h:20
#define ERROR_INVALID_PRINTER_NAME
Definition: winerror.h:1108
BOOL WINAPI MarshallUpStructure(DWORD cbSize, PVOID pStructure, const MARSHALLING_INFO *pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
Definition: marshalling.c:137
HANDLE WINAPI AddPrinterA(PSTR pName, DWORD Level, PBYTE pPrinter)
Definition: printers.c:118
#define ERR(fmt,...)
Definition: debug.h:109
DWORD WINAPI DeviceCapabilitiesA(LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA *pDevMode)
Definition: printers.c:181
HANDLE WINAPI AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter)
Definition: printers.c:126
#define CREATE_ALWAYS
Definition: disk.h:72
#define DM_IN_BUFFER
Definition: windef.h:342
static const MARSHALLING * pPrinterInfoMarshalling[]
Definition: printers.h:146
_In_ DWORD _Out_ PDWORD pcbNeeded
Definition: winddi.h:3827
BOOL WINAPI EnumPrintersA(DWORD Flags, PSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: printers.c:387
signed char * PSTR
Definition: retypes.h:7
BOOL WINAPI StartPagePrinter(HANDLE hPrinter)
Definition: printers.c:237
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
BOOL WINAPI EndDocPrinter(HANDLE hPrinter)
Definition: printers.c:36
DWORD * PDWORD
Definition: pedump.c:68
#define MultiByteToWideChar
Definition: compat.h:100
DWORD _RpcClosePrinter(WINSPOOL_PRINTER_HANDLE *phPrinter)
Definition: printers.c:33
BOOL WINAPI OpenPrinterW(PWSTR pPrinterName, PHANDLE phPrinter, PPRINTER_DEFAULTSW pDefault)
Definition: printers.c:155
#define CreateFileW
Definition: compat.h:400
BOOL WINAPI SetDefaultPrinterA(LPCSTR pszPrinter)
Definition: printers.c:868
union _WINSPOOL_DOC_INFO_CONTAINER::@3270 DocInfo
static const WCHAR wszDeviceValue[]
Definition: printers.c:17
BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
Definition: printers.c:580
WINBOOL WINAPI AddJobW(HANDLE hPrinter, DWORD Level, LPBYTE pData, DWORD cbBuf, LPDWORD pcbNeeded)
GLuint res
Definition: glext.h:9613
struct _DOC_INFO_1W * PDOC_INFO_1W
uint32_t * LPDWORD
Definition: typedefs.h:57
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3381
#define UNIMPLEMENTED
Definition: debug.h:114
LONG WINAPI DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode)
Definition: printers.c:197
#define ERROR_INVALID_NAME
Definition: compat.h:93
ACCESS_MASK DesiredAccess
Definition: winspool.h:764
struct _devicemodeW DEVMODEW
static HANDLE hXcv
Definition: localmon.c:61
#define ERROR_INVALID_PRINTER_STATE
Definition: winerror.h:1148
#define ERROR_INVALID_LEVEL
Definition: winerror.h:196
WCHAR * LPWSTR
Definition: xmlstorage.h:184
DWORD _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR *pEnvironment, DWORD Level, BYTE *pDriver, DWORD cbBuf, DWORD *pcbNeeded)
struct _DOC_INFO_1A * PDOC_INFO_1A
WINBOOL WINAPI SetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD Command)
LPSTR pDocName
Definition: winspool.h:550
BYTE * PBYTE
Definition: pedump.c:66
struct _SPOOLER_HANDLE * PSPOOLER_HANDLE
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define HeapFree(x, y, z)
Definition: compat.h:394
ULONG ACCESS_MASK
Definition: nt_native.h:40
DWORD _RpcGetPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD Level, BYTE *pPrinter, DWORD cbBuf, DWORD *pcbNeeded)
Definition: printers.c:138
static DWORD _StartDocPrinterSpooled(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1, PADDJOB_INFO_1W pAddJobInfo1)
Definition: printers.c:20
BOOL WINAPI SetDefaultPrinterW(LPCWSTR pszPrinter)
Definition: printers.c:902
#define RpcExcept(expr)
Definition: rpc.h:127
BOOL WINAPI MarshallUpStructuresArray(DWORD cbSize, PVOID pStructuresArray, DWORD cElements, const MARSHALLING_INFO *pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
Definition: marshalling.c:202
HANDLE hProcessHeap
Definition: kbswitch.c:25
DWORD WINAPI StartDocPrinterA(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
Definition: printers.c:1030
HANDLE hPrinter
Definition: precomp.h:34
static const MARSHALLING * pPrinterDriverMarshalling[]
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define REG_SZ
Definition: layer.c:22