ReactOS  0.4.15-dev-313-g8fde48b
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 #include <strsafe.h>
12 
13 // Local Constants
14 
17 static const WCHAR wszWindowsKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
18 static const WCHAR wszDeviceValue[] = L"Device";
19 
20 static DWORD
22 {
23  DWORD cbNeeded;
24  DWORD dwErrorCode;
25  PJOB_INFO_1W pJobInfo1 = NULL;
26 
27  // Create the spool file.
29  if (pHandle->hSPLFile == INVALID_HANDLE_VALUE)
30  {
31  dwErrorCode = GetLastError();
32  ERR("CreateFileW failed for \"%S\" with error %lu!\n", pAddJobInfo1->Path, dwErrorCode);
33  goto Cleanup;
34  }
35 
36  // Get the size of the job information.
37  GetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, NULL, 0, &cbNeeded);
39  {
40  dwErrorCode = GetLastError();
41  ERR("GetJobW failed with error %lu!\n", dwErrorCode);
42  goto Cleanup;
43  }
44 
45  // Allocate enough memory for the returned job information.
46  pJobInfo1 = HeapAlloc(hProcessHeap, 0, cbNeeded);
47  if (!pJobInfo1)
48  {
49  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
50  ERR("HeapAlloc failed!\n");
51  goto Cleanup;
52  }
53 
54  // Get the job information.
55  if (!GetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, (PBYTE)pJobInfo1, cbNeeded, &cbNeeded))
56  {
57  dwErrorCode = GetLastError();
58  ERR("GetJobW failed with error %lu!\n", dwErrorCode);
59  goto Cleanup;
60  }
61 
62  // Add our document information.
63  if (pDocInfo1->pDatatype)
64  pJobInfo1->pDatatype = pDocInfo1->pDatatype;
65 
66  pJobInfo1->pDocument = pDocInfo1->pDocName;
67 
68  // Set the new job information.
69  if (!SetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, (PBYTE)pJobInfo1, 0))
70  {
71  dwErrorCode = GetLastError();
72  ERR("SetJobW failed with error %lu!\n", dwErrorCode);
73  goto Cleanup;
74  }
75 
76  // We were successful!
77  pHandle->dwJobID = pAddJobInfo1->JobId;
78  dwErrorCode = ERROR_SUCCESS;
79 
80 Cleanup:
81  if (pJobInfo1)
82  HeapFree(hProcessHeap, 0, pJobInfo1);
83 
84  return dwErrorCode;
85 }
86 
87 static DWORD
89 {
90  DWORD dwErrorCode;
91  WINSPOOL_DOC_INFO_CONTAINER DocInfoContainer;
92 
93  DocInfoContainer.Level = 1;
94  DocInfoContainer.DocInfo.pDocInfo1 = (WINSPOOL_DOC_INFO_1*)pDocInfo1;
95 
97  {
98  dwErrorCode = _RpcStartDocPrinter(pHandle->hPrinter, &DocInfoContainer, &pHandle->dwJobID);
99  }
101  {
102  dwErrorCode = RpcExceptionCode();
103  ERR("_RpcStartDocPrinter failed with exception code %lu!\n", dwErrorCode);
104  }
105  RpcEndExcept;
106 
107  return dwErrorCode;
108 }
109 
110 BOOL WINAPI
112 {
113  TRACE("AbortPrinter(%p)\n", hPrinter);
115  return FALSE;
116 }
117 
120 {
121  TRACE("AddPrinterA(%s, %lu, %p)\n", pName, Level, pPrinter);
123  return NULL;
124 }
125 
128 {
129  TRACE("AddPrinterW(%S, %lu, %p)\n", pName, Level, pPrinter);
131  return NULL;
132 }
133 
134 BOOL WINAPI
136 {
137  DWORD dwErrorCode;
138  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
139 
140  TRACE("ClosePrinter(%p)\n", hPrinter);
141 
142  // Sanity checks.
143  if (!pHandle)
144  {
145  dwErrorCode = ERROR_INVALID_HANDLE;
146  goto Cleanup;
147  }
148 
149  // Do the RPC call.
151  {
152  dwErrorCode = _RpcClosePrinter(&pHandle->hPrinter);
153  }
155  {
156  dwErrorCode = RpcExceptionCode();
157  ERR("_RpcClosePrinter failed with exception code %lu!\n", dwErrorCode);
158  }
159  RpcEndExcept;
160 
161  // Close any open file handle.
162  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
163  CloseHandle(pHandle->hSPLFile);
164 
165  // Free the memory for the handle.
166  HeapFree(hProcessHeap, 0, pHandle);
167 
168 Cleanup:
169  SetLastError(dwErrorCode);
170  return (dwErrorCode == ERROR_SUCCESS);
171 }
172 
173 BOOL WINAPI
175 {
176  TRACE("DeletePrinter(%p)\n", hPrinter);
178  return FALSE;
179 }
180 
182 DeviceCapabilitiesA(LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA* pDevMode)
183 {
184  TRACE("DeviceCapabilitiesA(%s, %s, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode);
186  return 0;
187 }
188 
190 DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, WORD fwCapability, LPWSTR pOutput, const DEVMODEW* pDevMode)
191 {
192  TRACE("DeviceCapabilitiesW(%S, %S, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode);
194  return 0;
195 }
196 
197 INT WINAPI
198 DocumentEvent( HANDLE hPrinter, HDC hdc, int iEsc, ULONG cbIn, PVOID pvIn, ULONG cbOut, PVOID pvOut)
199 {
200  TRACE("DocumentEvent(%p, %p, %lu, %lu, %p, %lu, %p)\n", hPrinter, hdc, iEsc, cbIn, pvIn, cbOut, pvOut);
203 }
204 
205 LONG WINAPI
206 DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode)
207 {
209  PDEVMODEW pdmwInput = NULL;
210  PDEVMODEW pdmwOutput = NULL;
211  BOOL bReturnValue = -1;
212  DWORD cch;
213 
214  TRACE("DocumentPropertiesA(%p, %p, %s, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
215 
216  if (pDeviceName)
217  {
218  // Convert pName to a Unicode string pwszDeviceName.
219  cch = strlen(pDeviceName);
220 
221  pwszDeviceName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
222  if (!pwszDeviceName)
223  {
225  ERR("HeapAlloc failed!\n");
226  goto Cleanup;
227  }
228 
229  MultiByteToWideChar(CP_ACP, 0, pDeviceName, -1, pwszDeviceName, cch + 1);
230  }
231 
232  if (pDevModeInput)
233  {
234  // Create working buffer for input to DocumentPropertiesW.
235  pdmwInput = HeapAlloc(hProcessHeap, 0, sizeof(DEVMODEW));
236  if (!pdmwInput)
237  {
239  ERR("HeapAlloc failed!\n");
240  goto Cleanup;
241  }
242  RosConvertAnsiDevModeToUnicodeDevmode(pDevModeInput, pdmwInput);
243  }
244 
245  if (pDevModeOutput)
246  {
247  // Create working buffer for output from DocumentPropertiesW.
248  pdmwOutput = HeapAlloc(hProcessHeap, 0, sizeof(DEVMODEW));
249  if (!pdmwOutput)
250  {
252  ERR("HeapAlloc failed!\n");
253  goto Cleanup;
254  }
255  }
256 
257  bReturnValue = DocumentPropertiesW(hWnd, hPrinter, pwszDeviceName, pdmwOutput, pdmwInput, fMode);
258  TRACE("bReturnValue from DocumentPropertiesW is '%ld'.\n", bReturnValue);
259 
260  if (pwszDeviceName)
261  {
263  }
264 
265  if (bReturnValue < 0)
266  {
267  TRACE("DocumentPropertiesW failed!\n");
268  goto Cleanup;
269  }
270 
271  if (pdmwOutput)
272  {
273  RosConvertUnicodeDevModeToAnsiDevmode(pdmwOutput, pDevModeOutput);
274  }
275 
276 Cleanup:
277  if(pwszDeviceName)
279 
280  if (pdmwInput)
281  HeapFree(hProcessHeap, 0, pdmwInput);
282 
283  if (pdmwOutput)
284  HeapFree(hProcessHeap, 0, pdmwOutput);
285 
286  return bReturnValue;
287 }
288 
290 {
291  PRINTER_INFO_9W *pi9 = NULL;
292  DWORD needed = 0;
293  BOOL res;
294 
295  res = GetPrinterW(hprn, 9, NULL, 0, &needed);
297  {
298  pi9 = HeapAlloc(hProcessHeap, 0, needed);
299  res = GetPrinterW(hprn, 9, (LPBYTE)pi9, needed, &needed);
300  }
301 
302  if (res)
303  return pi9;
304 
305  ERR("GetPrinterW failed with %u\n", GetLastError());
306  HeapFree(hProcessHeap, 0, pi9);
307  return NULL;
308 }
309 
310 LONG WINAPI
311 DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode)
312 {
313  HANDLE hUseHandle = NULL;
314  PRINTER_INFO_9W *pi9 = NULL;
315  LONG Result = -1, Length;
316 
317  TRACE("DocumentPropertiesW(%p, %p, %S, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
318  if (hPrinter)
319  {
320  hUseHandle = hPrinter;
321  }
322  else if (!OpenPrinterW(pDeviceName, &hUseHandle, NULL))
323  {
324  ERR("No handle, and no usable printer name passed in\n");
325  return -1;
326  }
327 
328  pi9 = get_devmodeW(hUseHandle);
329 
330  if (pi9)
331  {
332  Length = pi9->pDevMode->dmSize + pi9->pDevMode->dmDriverExtra;
333  // See wineps.drv PSDRV_ExtDeviceMode
334  if (fMode)
335  {
336  Result = 1; /* IDOK */
337 
338  if (fMode & DM_IN_BUFFER)
339  {
340  FIXME("Merge pDevModeInput with pi9, write back to driver!\n");
341  // See wineps.drv PSDRV_MergeDevmodes
342  }
343 
344  if (fMode & DM_IN_PROMPT)
345  {
346  FIXME("Show property sheet!\n");
347  Result = 2; /* IDCANCEL */
348  }
349 
350  if (fMode & (DM_OUT_BUFFER | DM_OUT_DEFAULT))
351  {
352  if (pDevModeOutput)
353  {
354  memcpy(pDevModeOutput, pi9->pDevMode, pi9->pDevMode->dmSize + pi9->pDevMode->dmDriverExtra);
355  }
356  else
357  {
358  ERR("No pDevModeOutput\n");
359  Result = -1;
360  }
361  }
362  }
363  else
364  {
365  Result = Length;
366  }
367 
368  HeapFree(hProcessHeap, 0, pi9);
369  }
370 
371  if (hUseHandle && !hPrinter)
372  ClosePrinter(hUseHandle);
373  return Result;
374 }
375 
376 BOOL WINAPI
378 {
379  DWORD dwErrorCode;
380  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
381 
382  TRACE("EndDocPrinter(%p)\n", hPrinter);
383 
384  // Sanity checks.
385  if (!pHandle)
386  {
387  dwErrorCode = ERROR_INVALID_HANDLE;
388  goto Cleanup;
389  }
390 
391  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
392  {
393  // For spooled jobs, the document is finished by calling _RpcScheduleJob.
395  {
396  dwErrorCode = _RpcScheduleJob(pHandle->hPrinter, pHandle->dwJobID);
397  }
399  {
400  dwErrorCode = RpcExceptionCode();
401  ERR("_RpcScheduleJob failed with exception code %lu!\n", dwErrorCode);
402  }
403  RpcEndExcept;
404 
405  // Close the spool file handle.
406  CloseHandle(pHandle->hSPLFile);
407  }
408  else
409  {
410  // In all other cases, just call _RpcEndDocPrinter.
412  {
413  dwErrorCode = _RpcEndDocPrinter(pHandle->hPrinter);
414  }
416  {
417  dwErrorCode = RpcExceptionCode();
418  ERR("_RpcEndDocPrinter failed with exception code %lu!\n", dwErrorCode);
419  }
420  RpcEndExcept;
421  }
422 
423  // A new document can now be started again.
424  pHandle->bStartedDoc = FALSE;
425 
426 Cleanup:
427  SetLastError(dwErrorCode);
428  return (dwErrorCode == ERROR_SUCCESS);
429 }
430 
431 BOOL WINAPI
433 {
434  DWORD dwErrorCode;
435  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
436 
437  TRACE("EndPagePrinter(%p)\n", hPrinter);
438 
439  // Sanity checks.
440  if (!pHandle)
441  {
442  dwErrorCode = ERROR_INVALID_HANDLE;
443  goto Cleanup;
444  }
445 
446  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
447  {
448  // For spooled jobs, we don't need to do anything.
449  dwErrorCode = ERROR_SUCCESS;
450  }
451  else
452  {
453  // In all other cases, just call _RpcEndPagePrinter.
455  {
456  dwErrorCode = _RpcEndPagePrinter(pHandle->hPrinter);
457  }
459  {
460  dwErrorCode = RpcExceptionCode();
461  ERR("_RpcEndPagePrinter failed with exception code %lu!\n", dwErrorCode);
462  }
463  RpcEndExcept;
464  }
465 
466 Cleanup:
467  SetLastError(dwErrorCode);
468  return (dwErrorCode == ERROR_SUCCESS);
469 }
470 
471 BOOL WINAPI
473 {
474  DWORD dwErrorCode;
475  BOOL bResult;
476  DWORD cch;
477  PWSTR pwszName = NULL;
478  PSTR pszPrinterName = NULL;
479  PSTR pszServerName = NULL;
480  PSTR pszDescription = NULL;
481  PSTR pszName = NULL;
482  PSTR pszComment = NULL;
483  PSTR pszShareName = NULL;
484  PSTR pszPortName = NULL;
485  PSTR pszDriverName = NULL;
486  PSTR pszLocation = NULL;
487  PSTR pszSepFile = NULL;
488  PSTR pszPrintProcessor = NULL;
489  PSTR pszDatatype = NULL;
490  PSTR pszParameters = NULL;
491  DWORD i;
492  PPRINTER_INFO_1W ppi1w = NULL;
493  PPRINTER_INFO_1A ppi1a = NULL;
494  PPRINTER_INFO_2W ppi2w = NULL;
495  PPRINTER_INFO_2A ppi2a = NULL;
496  PPRINTER_INFO_4W ppi4w = NULL;
497  PPRINTER_INFO_4A ppi4a = NULL;
498  PPRINTER_INFO_5W ppi5w = NULL;
499  PPRINTER_INFO_5A ppi5a = NULL;
500 
501  TRACE("EnumPrintersA(%lu, %s, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
502 
503  // Check for invalid levels here for early error return. MSDN says that only 1, 2, 4, and 5 are allowable.
504  if (Level != 1 && Level != 2 && Level != 4 && Level != 5)
505  {
506  dwErrorCode = ERROR_INVALID_LEVEL;
507  ERR("Invalid Level!\n");
508  goto Cleanup;
509  }
510 
511  if (Name)
512  {
513  // Convert pName to a Unicode string pwszName.
514  cch = strlen(Name);
515 
516  pwszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
517  if (!pwszName)
518  {
519  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
520  ERR("HeapAlloc failed!\n");
521  goto Cleanup;
522  }
523 
524  MultiByteToWideChar(CP_ACP, 0, Name, -1, pwszName, cch + 1);
525  }
526 
527  /* Ref: https://stackoverflow.com/questions/41147180/why-enumprintersa-and-enumprintersw-request-the-same-amount-of-memory */
528  bResult = EnumPrintersW(Flags, pwszName, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
529  if (!bResult)
530  {
531  dwErrorCode = GetLastError();
532  goto Cleanup;
533  }
534 
535  /* We are mapping multiple different pointers to the same pPrinterEnum pointer here so that */
536  /* we can do in-place conversion. We read the Unicode response from the EnumPrintersW and */
537  /* then we write back the ANSI conversion into the same buffer for our EnumPrintersA output */
538 
539  /* mapping to pPrinterEnum for Unicode (w) characters for Levels 1, 2, 4, and 5 */
540  ppi1w = (PPRINTER_INFO_1W)pPrinterEnum;
541  ppi2w = (PPRINTER_INFO_2W)pPrinterEnum;
542  ppi4w = (PPRINTER_INFO_4W)pPrinterEnum;
543  ppi5w = (PPRINTER_INFO_5W)pPrinterEnum;
544  /* mapping to pPrinterEnum for ANSI (a) characters for Levels 1, 2, 4, and 5 */
545  ppi1a = (PPRINTER_INFO_1A)pPrinterEnum;
546  ppi2a = (PPRINTER_INFO_2A)pPrinterEnum;
547  ppi4a = (PPRINTER_INFO_4A)pPrinterEnum;
548  ppi5a = (PPRINTER_INFO_5A)pPrinterEnum;
549 
550  for (i = 0; i < *pcReturned; i++)
551  {
552  switch (Level)
553  {
554  case 1:
555  {
556  if (ppi1w[i].pDescription)
557  {
558  // Convert Unicode pDescription to a ANSI string pszDescription.
559  cch = wcslen(ppi1w[i].pDescription);
560 
561  pszDescription = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
562  if (!pszDescription)
563  {
564  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
565  ERR("HeapAlloc failed!\n");
566  goto Cleanup;
567  }
568 
569  WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pDescription, -1, pszDescription, cch + 1, NULL, NULL);
570  StringCchCopyA(ppi1a[i].pDescription, cch + 1, pszDescription);
571 
572  HeapFree(hProcessHeap, 0, pszDescription);
573  }
574 
575  if (ppi1w[i].pName)
576  {
577  // Convert Unicode pName to a ANSI string pszName.
578  cch = wcslen(ppi1w[i].pName);
579 
580  pszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
581  if (!pszName)
582  {
583  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
584  ERR("HeapAlloc failed!\n");
585  goto Cleanup;
586  }
587 
588  WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pName, -1, pszName, cch + 1, NULL, NULL);
589  StringCchCopyA(ppi1a[i].pName, cch + 1, pszName);
590 
591  HeapFree(hProcessHeap, 0, pszName);
592  }
593 
594  if (ppi1w[i].pComment)
595  {
596  // Convert Unicode pComment to a ANSI string pszComment.
597  cch = wcslen(ppi1w[i].pComment);
598 
599  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
600  if (!pszComment)
601  {
602  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
603  ERR("HeapAlloc failed!\n");
604  goto Cleanup;
605  }
606 
607  WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pComment, -1, pszComment, cch + 1, NULL, NULL);
608  StringCchCopyA(ppi1a[i].pComment, cch + 1, pszComment);
609 
610  HeapFree(hProcessHeap, 0, pszComment);
611  }
612  break;
613  }
614 
615 
616  case 2:
617  {
618  if (ppi2w[i].pServerName)
619  {
620  // Convert Unicode pServerName to a ANSI string pszServerName.
621  cch = wcslen(ppi2w[i].pServerName);
622 
623  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
624  if (!pszServerName)
625  {
626  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
627  ERR("HeapAlloc failed!\n");
628  goto Cleanup;
629  }
630 
631  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pServerName, -1, pszServerName, cch + 1, NULL, NULL);
632  StringCchCopyA(ppi2a[i].pServerName, cch + 1, pszServerName);
633 
634  HeapFree(hProcessHeap, 0, pszServerName);
635  }
636 
637  if (ppi2w[i].pPrinterName)
638  {
639  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
640  cch = wcslen(ppi2w[i].pPrinterName);
641 
642  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
643  if (!pszPrinterName)
644  {
645  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
646  ERR("HeapAlloc failed!\n");
647  goto Cleanup;
648  }
649 
650  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
651  StringCchCopyA(ppi2a[i].pPrinterName, cch + 1, pszPrinterName);
652 
653  HeapFree(hProcessHeap, 0, pszPrinterName);
654  }
655 
656  if (ppi2w[i].pShareName)
657  {
658  // Convert Unicode pShareName to a ANSI string pszShareName.
659  cch = wcslen(ppi2w[i].pShareName);
660 
661  pszShareName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
662  if (!pszShareName)
663  {
664  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
665  ERR("HeapAlloc failed!\n");
666  goto Cleanup;
667  }
668 
669  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pShareName, -1, pszShareName, cch + 1, NULL, NULL);
670  StringCchCopyA(ppi2a[i].pShareName, cch + 1, pszShareName);
671 
672  HeapFree(hProcessHeap, 0, pszShareName);
673  }
674 
675  if (ppi2w[i].pPortName)
676  {
677  // Convert Unicode pPortName to a ANSI string pszPortName.
678  cch = wcslen(ppi2w[i].pPortName);
679 
680  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
681  if (!pszPortName)
682  {
683  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
684  ERR("HeapAlloc failed!\n");
685  goto Cleanup;
686  }
687 
688  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPortName, -1, pszPortName, cch + 1, NULL, NULL);
689  StringCchCopyA(ppi2a[i].pPortName, cch + 1, pszPortName);
690 
691  HeapFree(hProcessHeap, 0, pszPortName);
692  }
693 
694  if (ppi2w[i].pDriverName)
695  {
696  // Convert Unicode pDriverName to a ANSI string pszDriverName.
697  cch = wcslen(ppi2w[i].pDriverName);
698 
699  pszDriverName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
700  if (!pszDriverName)
701  {
702  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
703  ERR("HeapAlloc failed!\n");
704  goto Cleanup;
705  }
706 
707  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pDriverName, -1, pszDriverName, cch + 1, NULL, NULL);
708  StringCchCopyA(ppi2a[i].pDriverName, cch + 1, pszDriverName);
709 
710  HeapFree(hProcessHeap, 0, pszDriverName);
711  }
712 
713  if (ppi2w[i].pComment)
714  {
715  // Convert Unicode pComment to a ANSI string pszComment.
716  cch = wcslen(ppi2w[i].pComment);
717 
718  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
719  if (!pszComment)
720  {
721  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
722  ERR("HeapAlloc failed!\n");
723  goto Cleanup;
724  }
725 
726  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pComment, -1, pszComment, cch + 1, NULL, NULL);
727  StringCchCopyA(ppi2a[i].pComment, cch + 1, pszComment);
728 
729  HeapFree(hProcessHeap, 0, pszComment);
730  }
731 
732  if (ppi2w[i].pLocation)
733  {
734  // Convert Unicode pLocation to a ANSI string pszLocation.
735  cch = wcslen(ppi2w[i].pLocation);
736 
737  pszLocation = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
738  if (!pszLocation)
739  {
740  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
741  ERR("HeapAlloc failed!\n");
742  goto Cleanup;
743  }
744 
745  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pLocation, -1, pszLocation, cch + 1, NULL, NULL);
746  StringCchCopyA(ppi2a[i].pLocation, cch + 1, pszLocation);
747 
748  HeapFree(hProcessHeap, 0, pszLocation);
749  }
750 
751 
752  if (ppi2w[i].pSepFile)
753  {
754  // Convert Unicode pSepFile to a ANSI string pszSepFile.
755  cch = wcslen(ppi2w[i].pSepFile);
756 
757  pszSepFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
758  if (!pszSepFile)
759  {
760  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
761  ERR("HeapAlloc failed!\n");
762  goto Cleanup;
763  }
764 
765  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pSepFile, -1, pszSepFile, cch + 1, NULL, NULL);
766  StringCchCopyA(ppi2a[i].pSepFile, cch + 1, pszSepFile);
767 
768  HeapFree(hProcessHeap, 0, pszSepFile);
769  }
770 
771  if (ppi2w[i].pPrintProcessor)
772  {
773  // Convert Unicode pPrintProcessor to a ANSI string pszPrintProcessor.
774  cch = wcslen(ppi2w[i].pPrintProcessor);
775 
776  pszPrintProcessor = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
777  if (!pszPrintProcessor)
778  {
779  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
780  ERR("HeapAlloc failed!\n");
781  goto Cleanup;
782  }
783 
784  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPrintProcessor, -1, pszPrintProcessor, cch + 1, NULL, NULL);
785  StringCchCopyA(ppi2a[i].pPrintProcessor, cch + 1, pszPrintProcessor);
786 
787  HeapFree(hProcessHeap, 0, pszPrintProcessor);
788  }
789 
790 
791  if (ppi2w[i].pDatatype)
792  {
793  // Convert Unicode pDatatype to a ANSI string pszDatatype.
794  cch = wcslen(ppi2w[i].pDatatype);
795 
796  pszDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
797  if (!pszDatatype)
798  {
799  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
800  ERR("HeapAlloc failed!\n");
801  goto Cleanup;
802  }
803 
804  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pDatatype, -1, pszDatatype, cch + 1, NULL, NULL);
805  StringCchCopyA(ppi2a[i].pDatatype, cch + 1, pszDatatype);
806 
807  HeapFree(hProcessHeap, 0, pszDatatype);
808  }
809 
810  if (ppi2w[i].pParameters)
811  {
812  // Convert Unicode pParameters to a ANSI string pszParameters.
813  cch = wcslen(ppi2w[i].pParameters);
814 
815  pszParameters = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
816  if (!pszParameters)
817  {
818  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
819  ERR("HeapAlloc failed!\n");
820  goto Cleanup;
821  }
822 
823  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pParameters, -1, pszParameters, cch + 1, NULL, NULL);
824  StringCchCopyA(ppi2a[i].pParameters, cch + 1, pszParameters);
825 
826  HeapFree(hProcessHeap, 0, pszParameters);
827  }
828  break;
829 
830  }
831 
832  case 4:
833  {
834  if (ppi4w[i].pPrinterName)
835  {
836  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
837  cch = wcslen(ppi4w[i].pPrinterName);
838 
839  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
840  if (!pszPrinterName)
841  {
842  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
843  ERR("HeapAlloc failed!\n");
844  goto Cleanup;
845  }
846 
847  WideCharToMultiByte(CP_ACP, 0, ppi4w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
848  StringCchCopyA(ppi4a[i].pPrinterName, cch + 1, pszPrinterName);
849 
850  HeapFree(hProcessHeap, 0, pszPrinterName);
851  }
852 
853  if (ppi4w[i].pServerName)
854  {
855  // Convert Unicode pServerName to a ANSI string pszServerName.
856  cch = wcslen(ppi4w[i].pServerName);
857 
858  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
859  if (!pszServerName)
860  {
861  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
862  ERR("HeapAlloc failed!\n");
863  goto Cleanup;
864  }
865 
866  WideCharToMultiByte(CP_ACP, 0, ppi4w[i].pServerName, -1, pszServerName, cch + 1, NULL, NULL);
867  StringCchCopyA(ppi4a[i].pServerName, cch + 1, pszServerName);
868 
869  HeapFree(hProcessHeap, 0, pszServerName);
870  }
871  break;
872  }
873 
874  case 5:
875  {
876  if (ppi5w[i].pPrinterName)
877  {
878  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
879  cch = wcslen(ppi5w[i].pPrinterName);
880 
881  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
882  if (!pszPrinterName)
883  {
884  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
885  ERR("HeapAlloc failed!\n");
886  goto Cleanup;
887  }
888 
889  WideCharToMultiByte(CP_ACP, 0, ppi5w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
890  StringCchCopyA(ppi5a[i].pPrinterName, cch + 1, pszPrinterName);
891 
892  HeapFree(hProcessHeap, 0, pszPrinterName);
893  }
894 
895  if (ppi5w[i].pPortName)
896  {
897  // Convert Unicode pPortName to a ANSI string pszPortName.
898  cch = wcslen(ppi5w[i].pPortName);
899 
900  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
901  if (!pszPortName)
902  {
903  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
904  ERR("HeapAlloc failed!\n");
905  goto Cleanup;
906  }
907 
908  WideCharToMultiByte(CP_ACP, 0, ppi5w[i].pPortName, -1, pszPortName, cch + 1, NULL, NULL);
909  StringCchCopyA(ppi5a[i].pPortName, cch + 1, pszPortName);
910 
911  HeapFree(hProcessHeap, 0, pszPortName);
912  }
913  break;
914  }
915 
916  } // switch
917  } // for
918 
919  dwErrorCode = ERROR_SUCCESS;
920 
921 Cleanup:
922  if (pwszName)
923  {
924  HeapFree(hProcessHeap, 0, pwszName);
925  }
926 
927  SetLastError(dwErrorCode);
928  return (dwErrorCode == ERROR_SUCCESS);
929 }
930 
931 BOOL WINAPI
933 {
934  DWORD dwErrorCode;
935 
936  TRACE("EnumPrintersW(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
937 
938  // Dismiss invalid levels already at this point.
939  if (Level == 3 || Level > 5)
940  {
941  dwErrorCode = ERROR_INVALID_LEVEL;
942  goto Cleanup;
943  }
944 
945  if (cbBuf && pPrinterEnum)
946  ZeroMemory(pPrinterEnum, cbBuf);
947 
948  // Do the RPC call
950  {
951  dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
952  }
954  {
955  dwErrorCode = RpcExceptionCode();
956  ERR("_RpcEnumPrinters failed with exception code %lu!\n", dwErrorCode);
957  }
958  RpcEndExcept;
959 
960  if (dwErrorCode == ERROR_SUCCESS)
961  {
962  // Replace relative offset addresses in the output by absolute pointers.
963  ASSERT(Level <= 9);
964  MarshallUpStructuresArray(cbBuf, pPrinterEnum, *pcReturned, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
965  }
966 
967 Cleanup:
968  SetLastError(dwErrorCode);
969  return (dwErrorCode == ERROR_SUCCESS);
970 }
971 
972 BOOL WINAPI
973 FlushPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten, DWORD cSleep)
974 {
975  TRACE("FlushPrinter(%p, %p, %lu, %p, %lu)\n", hPrinter, pBuf, cbBuf, pcWritten, cSleep);
977  return FALSE;
978 }
979 
980 BOOL WINAPI
981 GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
982 {
983  DWORD dwErrorCode;
984  PWSTR pwszBuffer = NULL;
985 
986  TRACE("GetDefaultPrinterA(%p, %p)\n", pszBuffer, pcchBuffer);
987 
988  // Sanity check.
989  if (!pcchBuffer)
990  {
991  dwErrorCode = ERROR_INVALID_PARAMETER;
992  goto Cleanup;
993  }
994 
995  // Check if an ANSI buffer was given and if so, allocate a Unicode buffer of the same size.
996  if (pszBuffer && *pcchBuffer)
997  {
998  pwszBuffer = HeapAlloc(hProcessHeap, 0, *pcchBuffer * sizeof(WCHAR));
999  if (!pwszBuffer)
1000  {
1001  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1002  ERR("HeapAlloc failed!\n");
1003  goto Cleanup;
1004  }
1005  }
1006 
1007  if (!GetDefaultPrinterW(pwszBuffer, pcchBuffer))
1008  {
1009  dwErrorCode = GetLastError();
1010  goto Cleanup;
1011  }
1012 
1013  // We successfully got a string in pwszBuffer, so convert the Unicode string to ANSI.
1014  WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszBuffer, *pcchBuffer, NULL, NULL);
1015 
1016  dwErrorCode = ERROR_SUCCESS;
1017 
1018 Cleanup:
1019  if (pwszBuffer)
1020  HeapFree(hProcessHeap, 0, pwszBuffer);
1021 
1022  SetLastError(dwErrorCode);
1023  return (dwErrorCode == ERROR_SUCCESS);
1024 }
1025 
1026 BOOL WINAPI
1027 GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
1028 {
1029  DWORD cbNeeded;
1030  DWORD cchInputBuffer;
1031  DWORD dwErrorCode;
1032  HKEY hWindowsKey = NULL;
1033  PWSTR pwszDevice = NULL;
1034  PWSTR pwszComma;
1035 
1036  TRACE("GetDefaultPrinterW(%p, %p)\n", pszBuffer, pcchBuffer);
1037 
1038  // Sanity check.
1039  if (!pcchBuffer)
1040  {
1041  dwErrorCode = ERROR_INVALID_PARAMETER;
1042  goto Cleanup;
1043  }
1044 
1045  cchInputBuffer = *pcchBuffer;
1046 
1047  // Open the registry key where the default printer for the current user is stored.
1048  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_READ, &hWindowsKey);
1049  if (dwErrorCode != ERROR_SUCCESS)
1050  {
1051  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
1052  goto Cleanup;
1053  }
1054 
1055  // Determine the size of the required buffer.
1056  dwErrorCode = (DWORD)RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, NULL, &cbNeeded);
1057  if (dwErrorCode != ERROR_SUCCESS)
1058  {
1059  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
1060  goto Cleanup;
1061  }
1062 
1063  // Allocate it.
1064  pwszDevice = HeapAlloc(hProcessHeap, 0, cbNeeded);
1065  if (!pwszDevice)
1066  {
1067  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1068  ERR("HeapAlloc failed!\n");
1069  goto Cleanup;
1070  }
1071 
1072  // Now get the actual value.
1073  dwErrorCode = RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, (PBYTE)pwszDevice, &cbNeeded);
1074  if (dwErrorCode != ERROR_SUCCESS)
1075  {
1076  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
1077  goto Cleanup;
1078  }
1079 
1080  // We get a string "<Printer Name>,winspool,<Port>:".
1081  // Extract the printer name from it.
1082  pwszComma = wcschr(pwszDevice, L',');
1083  if (!pwszComma)
1084  {
1085  ERR("Found no or invalid default printer: %S!\n", pwszDevice);
1086  dwErrorCode = ERROR_INVALID_NAME;
1087  goto Cleanup;
1088  }
1089 
1090  // Store the length of the Printer Name (including the terminating NUL character!) in *pcchBuffer.
1091  *pcchBuffer = pwszComma - pwszDevice + 1;
1092 
1093  // Check if the supplied buffer is large enough.
1094  if (cchInputBuffer < *pcchBuffer)
1095  {
1096  dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
1097  goto Cleanup;
1098  }
1099 
1100  // Copy the default printer.
1101  *pwszComma = 0;
1102  CopyMemory(pszBuffer, pwszDevice, *pcchBuffer * sizeof(WCHAR));
1103 
1104  dwErrorCode = ERROR_SUCCESS;
1105 
1106 Cleanup:
1107  if (hWindowsKey)
1108  RegCloseKey(hWindowsKey);
1109 
1110  if (pwszDevice)
1111  HeapFree(hProcessHeap, 0, pwszDevice);
1112 
1113  SetLastError(dwErrorCode);
1114  return (dwErrorCode == ERROR_SUCCESS);
1115 }
1116 
1117 BOOL WINAPI
1119 {
1120  DWORD dwErrorCode;
1121  BOOL bResult;
1122  PPRINTER_INFO_1A ppi1a = (PPRINTER_INFO_1A)pPrinter;
1123  PPRINTER_INFO_1W ppi1w = (PPRINTER_INFO_1W)pPrinter;
1124  PPRINTER_INFO_2A ppi2a = (PPRINTER_INFO_2A)pPrinter;
1125  PPRINTER_INFO_2W ppi2w = (PPRINTER_INFO_2W)pPrinter;
1126  PPRINTER_INFO_4A ppi4a = (PPRINTER_INFO_4A)pPrinter;
1127  PPRINTER_INFO_4W ppi4w = (PPRINTER_INFO_4W)pPrinter;
1128  PPRINTER_INFO_5A ppi5a = (PPRINTER_INFO_5A)pPrinter;
1129  PPRINTER_INFO_5W ppi5w = (PPRINTER_INFO_5W)pPrinter;
1130  PPRINTER_INFO_7A ppi7a = (PPRINTER_INFO_7A)pPrinter;
1131  PPRINTER_INFO_7W ppi7w = (PPRINTER_INFO_7W)pPrinter;
1132  DWORD cch;
1133 
1134  TRACE("GetPrinterA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
1135 
1136  // Check for invalid levels here for early error return. Should be 1-9.
1137  if (Level < 1 || Level > 9)
1138  {
1139  dwErrorCode = ERROR_INVALID_LEVEL;
1140  ERR("Invalid Level!\n");
1141  goto Cleanup;
1142  }
1143 
1144  bResult = GetPrinterW(hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
1145  if (!bResult)
1146  {
1147  dwErrorCode = GetLastError();
1148  goto Cleanup;
1149  }
1150 
1151  switch (Level)
1152  {
1153  case 1:
1154  {
1155  if (ppi1w->pDescription)
1156  {
1157  PSTR pszDescription;
1158 
1159  // Convert Unicode pDescription to a ANSI string pszDescription.
1160  cch = wcslen(ppi1w->pDescription);
1161 
1162  pszDescription = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1163  if (!pszDescription)
1164  {
1165  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1166  ERR("HeapAlloc failed!\n");
1167  goto Cleanup;
1168  }
1169 
1170  WideCharToMultiByte(CP_ACP, 0, ppi1w->pDescription, -1, pszDescription, cch + 1, NULL, NULL);
1171  StringCchCopyA(ppi1a->pDescription, cch + 1, pszDescription);
1172 
1173  HeapFree(hProcessHeap, 0, pszDescription);
1174  }
1175 
1176  if (ppi1w->pName)
1177  {
1178  PSTR pszName;
1179 
1180  // Convert Unicode pName to a ANSI string pszName.
1181  cch = wcslen(ppi1w->pName);
1182 
1183  pszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1184  if (!pszName)
1185  {
1186  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1187  ERR("HeapAlloc failed!\n");
1188  goto Cleanup;
1189  }
1190 
1191  WideCharToMultiByte(CP_ACP, 0, ppi1w->pName, -1, pszName, cch + 1, NULL, NULL);
1192  StringCchCopyA(ppi1a->pName, cch + 1, pszName);
1193 
1194  HeapFree(hProcessHeap, 0, pszName);
1195  }
1196 
1197  if (ppi1w->pComment)
1198  {
1199  PSTR pszComment;
1200 
1201  // Convert Unicode pComment to a ANSI string pszComment.
1202  cch = wcslen(ppi1w->pComment);
1203 
1204  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1205  if (!pszComment)
1206  {
1207  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1208  ERR("HeapAlloc failed!\n");
1209  goto Cleanup;
1210  }
1211 
1212  WideCharToMultiByte(CP_ACP, 0, ppi1w->pComment, -1, pszComment, cch + 1, NULL, NULL);
1213  StringCchCopyA(ppi1a->pComment, cch + 1, pszComment);
1214 
1215  HeapFree(hProcessHeap, 0, pszComment);
1216  }
1217  break;
1218  }
1219 
1220  case 2:
1221  {
1222  if (ppi2w->pServerName)
1223  {
1224  PSTR pszServerName;
1225 
1226  // Convert Unicode pServerName to a ANSI string pszServerName.
1227  cch = wcslen(ppi2w->pServerName);
1228 
1229  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1230  if (!pszServerName)
1231  {
1232  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1233  ERR("HeapAlloc failed!\n");
1234  goto Cleanup;
1235  }
1236 
1237  WideCharToMultiByte(CP_ACP, 0, ppi2w->pServerName, -1, pszServerName, cch + 1, NULL, NULL);
1238  StringCchCopyA(ppi2a->pServerName, cch + 1, pszServerName);
1239 
1240  HeapFree(hProcessHeap, 0, pszServerName);
1241  }
1242 
1243  if (ppi2w->pPrinterName)
1244  {
1245  PSTR pszPrinterName;
1246 
1247  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
1248  cch = wcslen(ppi2w->pPrinterName);
1249 
1250  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1251  if (!pszPrinterName)
1252  {
1253  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1254  ERR("HeapAlloc failed!\n");
1255  goto Cleanup;
1256  }
1257 
1258  WideCharToMultiByte(CP_ACP, 0, ppi2w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
1259  StringCchCopyA(ppi2a->pPrinterName, cch + 1, pszPrinterName);
1260 
1261  HeapFree(hProcessHeap, 0, pszPrinterName);
1262  }
1263 
1264  if (ppi2w->pShareName)
1265  {
1266  PSTR pszShareName;
1267 
1268  // Convert Unicode pShareName to a ANSI string pszShareName.
1269  cch = wcslen(ppi2w->pShareName);
1270 
1271  pszShareName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1272  if (!pszShareName)
1273  {
1274  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1275  ERR("HeapAlloc failed!\n");
1276  goto Cleanup;
1277  }
1278 
1279  WideCharToMultiByte(CP_ACP, 0, ppi2w->pShareName, -1, pszShareName, cch + 1, NULL, NULL);
1280  StringCchCopyA(ppi2a->pShareName, cch + 1, pszShareName);
1281 
1282  HeapFree(hProcessHeap, 0, pszShareName);
1283  }
1284 
1285  if (ppi2w->pPortName)
1286  {
1287  PSTR pszPortName;
1288 
1289  // Convert Unicode pPortName to a ANSI string pszPortName.
1290  cch = wcslen(ppi2w->pPortName);
1291 
1292  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1293  if (!pszPortName)
1294  {
1295  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1296  ERR("HeapAlloc failed!\n");
1297  goto Cleanup;
1298  }
1299 
1300  WideCharToMultiByte(CP_ACP, 0, ppi2w->pPortName, -1, pszPortName, cch + 1, NULL, NULL);
1301  StringCchCopyA(ppi2a->pPortName, cch + 1, pszPortName);
1302 
1303  HeapFree(hProcessHeap, 0, pszPortName);
1304  }
1305 
1306  if (ppi2w->pDriverName)
1307  {
1308  PSTR pszDriverName;
1309 
1310  // Convert Unicode pDriverName to a ANSI string pszDriverName.
1311  cch = wcslen(ppi2w->pDriverName);
1312 
1313  pszDriverName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1314  if (!pszDriverName)
1315  {
1316  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1317  ERR("HeapAlloc failed!\n");
1318  goto Cleanup;
1319  }
1320 
1321  WideCharToMultiByte(CP_ACP, 0, ppi2w->pDriverName, -1, pszDriverName, cch + 1, NULL, NULL);
1322  StringCchCopyA(ppi2a->pDriverName, cch + 1, pszDriverName);
1323 
1324  HeapFree(hProcessHeap, 0, pszDriverName);
1325  }
1326 
1327  if (ppi2w->pComment)
1328  {
1329  PSTR pszComment;
1330 
1331  // Convert Unicode pComment to a ANSI string pszComment.
1332  cch = wcslen(ppi2w->pComment);
1333 
1334  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1335  if (!pszComment)
1336  {
1337  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1338  ERR("HeapAlloc failed!\n");
1339  goto Cleanup;
1340  }
1341 
1342  WideCharToMultiByte(CP_ACP, 0, ppi2w->pComment, -1, pszComment, cch + 1, NULL, NULL);
1343  StringCchCopyA(ppi2a->pComment, cch + 1, pszComment);
1344 
1345  HeapFree(hProcessHeap, 0, pszComment);
1346  }
1347 
1348  if (ppi2w->pLocation)
1349  {
1350  PSTR pszLocation;
1351 
1352  // Convert Unicode pLocation to a ANSI string pszLocation.
1353  cch = wcslen(ppi2w->pLocation);
1354 
1355  pszLocation = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1356  if (!pszLocation)
1357  {
1358  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1359  ERR("HeapAlloc failed!\n");
1360  goto Cleanup;
1361  }
1362 
1363  WideCharToMultiByte(CP_ACP, 0, ppi2w->pLocation, -1, pszLocation, cch + 1, NULL, NULL);
1364  StringCchCopyA(ppi2a->pLocation, cch + 1, pszLocation);
1365 
1366  HeapFree(hProcessHeap, 0, pszLocation);
1367  }
1368 
1369  if (ppi2w->pSepFile)
1370  {
1371  PSTR pszSepFile;
1372 
1373  // Convert Unicode pSepFile to a ANSI string pszSepFile.
1374  cch = wcslen(ppi2w->pSepFile);
1375 
1376  pszSepFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1377  if (!pszSepFile)
1378  {
1379  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1380  ERR("HeapAlloc failed!\n");
1381  goto Cleanup;
1382  }
1383 
1384  WideCharToMultiByte(CP_ACP, 0, ppi2w->pSepFile, -1, pszSepFile, cch + 1, NULL, NULL);
1385  StringCchCopyA(ppi2a->pSepFile, cch + 1, pszSepFile);
1386 
1387  HeapFree(hProcessHeap, 0, pszSepFile);
1388  }
1389 
1390  if (ppi2w->pPrintProcessor)
1391  {
1392  PSTR pszPrintProcessor;
1393 
1394  // Convert Unicode pPrintProcessor to a ANSI string pszPrintProcessor.
1395  cch = wcslen(ppi2w->pPrintProcessor);
1396 
1397  pszPrintProcessor = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1398  if (!pszPrintProcessor)
1399  {
1400  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1401  ERR("HeapAlloc failed!\n");
1402  goto Cleanup;
1403  }
1404 
1405  WideCharToMultiByte(CP_ACP, 0, ppi2w->pPrintProcessor, -1, pszPrintProcessor, cch + 1, NULL, NULL);
1406  StringCchCopyA(ppi2a->pPrintProcessor, cch + 1, pszPrintProcessor);
1407 
1408  HeapFree(hProcessHeap, 0, pszPrintProcessor);
1409  }
1410 
1411  if (ppi2w->pDatatype)
1412  {
1413  PSTR pszDatatype;
1414 
1415  // Convert Unicode pDatatype to a ANSI string pszDatatype.
1416  cch = wcslen(ppi2w->pDatatype);
1417 
1418  pszDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1419  if (!pszDatatype)
1420  {
1421  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1422  ERR("HeapAlloc failed!\n");
1423  goto Cleanup;
1424  }
1425 
1426  WideCharToMultiByte(CP_ACP, 0, ppi2w->pDatatype, -1, pszDatatype, cch + 1, NULL, NULL);
1427  StringCchCopyA(ppi2a->pDatatype, cch + 1, pszDatatype);
1428 
1429  HeapFree(hProcessHeap, 0, pszDatatype);
1430  }
1431 
1432  if (ppi2w->pParameters)
1433  {
1434  PSTR pszParameters;
1435 
1436  // Convert Unicode pParameters to a ANSI string pszParameters.
1437  cch = wcslen(ppi2w->pParameters);
1438 
1439  pszParameters = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1440  if (!pszParameters)
1441  {
1442  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1443  ERR("HeapAlloc failed!\n");
1444  goto Cleanup;
1445  }
1446 
1447  WideCharToMultiByte(CP_ACP, 0, ppi2w->pParameters, -1, pszParameters, cch + 1, NULL, NULL);
1448  StringCchCopyA(ppi2a->pParameters, cch + 1, pszParameters);
1449 
1450  HeapFree(hProcessHeap, 0, pszParameters);
1451  }
1452  break;
1453  }
1454 
1455  case 4:
1456  {
1457  if (ppi4w->pPrinterName)
1458  {
1459  PSTR pszPrinterName;
1460 
1461  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
1462  cch = wcslen(ppi4w->pPrinterName);
1463 
1464  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1465  if (!pszPrinterName)
1466  {
1467  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1468  ERR("HeapAlloc failed!\n");
1469  goto Cleanup;
1470  }
1471 
1472  WideCharToMultiByte(CP_ACP, 0, ppi4w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
1473  StringCchCopyA(ppi4a->pPrinterName, cch + 1, pszPrinterName);
1474 
1475  HeapFree(hProcessHeap, 0, pszPrinterName);
1476  }
1477 
1478  if (ppi4w->pServerName)
1479  {
1480  PSTR pszServerName;
1481 
1482  // Convert Unicode pServerName to a ANSI string pszServerName.
1483  cch = wcslen(ppi4w->pServerName);
1484 
1485  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1486  if (!pszServerName)
1487  {
1488  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1489  ERR("HeapAlloc failed!\n");
1490  goto Cleanup;
1491  }
1492 
1493  WideCharToMultiByte(CP_ACP, 0, ppi4w->pServerName, -1, pszServerName, cch + 1, NULL, NULL);
1494  StringCchCopyA(ppi4a->pServerName, cch + 1, pszServerName);
1495 
1496  HeapFree(hProcessHeap, 0, pszServerName);
1497  }
1498  break;
1499  }
1500 
1501  case 5:
1502  {
1503  if (ppi5w->pPrinterName)
1504  {
1505  PSTR pszPrinterName;
1506 
1507  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
1508  cch = wcslen(ppi5w->pPrinterName);
1509 
1510  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1511  if (!pszPrinterName)
1512  {
1513  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1514  ERR("HeapAlloc failed!\n");
1515  goto Cleanup;
1516  }
1517 
1518  WideCharToMultiByte(CP_ACP, 0, ppi5w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
1519  StringCchCopyA(ppi5a->pPrinterName, cch + 1, pszPrinterName);
1520 
1521  HeapFree(hProcessHeap, 0, pszPrinterName);
1522  }
1523 
1524  if (ppi5w->pPortName)
1525  {
1526  PSTR pszPortName;
1527 
1528  // Convert Unicode pPortName to a ANSI string pszPortName.
1529  cch = wcslen(ppi5w->pPortName);
1530 
1531  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1532  if (!pszPortName)
1533  {
1534  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1535  ERR("HeapAlloc failed!\n");
1536  goto Cleanup;
1537  }
1538 
1539  WideCharToMultiByte(CP_ACP, 0, ppi5w->pPortName, -1, pszPortName, cch + 1, NULL, NULL);
1540  StringCchCopyA(ppi5a->pPortName, cch + 1, pszPortName);
1541 
1542  HeapFree(hProcessHeap, 0, pszPortName);
1543  }
1544  break;
1545  }
1546 
1547  case 7:
1548  {
1549  if (ppi7w->pszObjectGUID)
1550  {
1551  PSTR pszaObjectGUID;
1552 
1553  // Convert Unicode pszObjectGUID to a ANSI string pszaObjectGUID.
1554  cch = wcslen(ppi7w->pszObjectGUID);
1555 
1556  pszaObjectGUID = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1557  if (!pszaObjectGUID)
1558  {
1559  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1560  ERR("HeapAlloc failed!\n");
1561  goto Cleanup;
1562  }
1563 
1564  WideCharToMultiByte(CP_ACP, 0, ppi7w->pszObjectGUID, -1, pszaObjectGUID, cch + 1, NULL, NULL);
1565  StringCchCopyA(ppi7a->pszObjectGUID, cch + 1, pszaObjectGUID);
1566 
1567  HeapFree(hProcessHeap, 0, pszaObjectGUID);
1568  }
1569  break;
1570  }
1571  } // switch
1572 
1573  dwErrorCode = ERROR_SUCCESS;
1574 
1575 Cleanup:
1576  SetLastError(dwErrorCode);
1577  return (dwErrorCode == ERROR_SUCCESS);
1578 }
1579 
1580 BOOL WINAPI
1581 GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
1582 {
1583  /*
1584  * We are mapping multiple different pointers to the same pDriverInfo pointer here so that
1585  * we can use the same incoming pointer for different Levels
1586  */
1587  PDRIVER_INFO_1W pdi1w = (PDRIVER_INFO_1W)pDriverInfo;
1588  PDRIVER_INFO_2W pdi2w = (PDRIVER_INFO_2W)pDriverInfo;
1589  PDRIVER_INFO_3W pdi3w = (PDRIVER_INFO_3W)pDriverInfo;
1590  PDRIVER_INFO_4W pdi4w = (PDRIVER_INFO_4W)pDriverInfo;
1591  PDRIVER_INFO_5W pdi5w = (PDRIVER_INFO_5W)pDriverInfo;
1592  PDRIVER_INFO_6W pdi6w = (PDRIVER_INFO_6W)pDriverInfo;
1593 
1594  BOOL bReturnValue = FALSE;
1595  DWORD cch;
1596  PWSTR pwszEnvironment = NULL;
1597 
1598  TRACE("GetPrinterDriverA(%p, %s, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
1599 
1600  // Check for invalid levels here for early error return. Should be 1-6.
1601  if (Level < 1 || Level > 6)
1602  {
1604  ERR("Invalid Level!\n");
1605  goto Exit;
1606  }
1607 
1608  if (pEnvironment)
1609  {
1610  // Convert pEnvironment to a Unicode string pwszEnvironment.
1611  cch = strlen(pEnvironment);
1612 
1613  pwszEnvironment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
1614  if (!pwszEnvironment)
1615  {
1617  ERR("HeapAlloc failed!\n");
1618  goto Exit;
1619  }
1620 
1621  MultiByteToWideChar(CP_ACP, 0, pEnvironment, -1, pwszEnvironment, cch + 1);
1622  }
1623 
1624  bReturnValue = GetPrinterDriverW(hPrinter, pwszEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
1625  TRACE("*pcbNeeded is '%d' and bReturnValue is '%d' and GetLastError is '%ld'.\n", *pcbNeeded, bReturnValue, GetLastError());
1626 
1627  if (pwszEnvironment)
1628  {
1629  HeapFree(hProcessHeap, 0, pwszEnvironment);
1630  }
1631 
1632  if (!bReturnValue)
1633  {
1634  TRACE("GetPrinterDriverW failed!\n");
1635  goto Exit;
1636  }
1637 
1638  // Do Unicode to ANSI conversions for strings based on Level
1639  switch (Level)
1640  {
1641  case 1:
1642  {
1643  if (!UnicodeToAnsiInPlace(pdi1w->pName))
1644  goto Exit;
1645 
1646  break;
1647  }
1648 
1649  case 2:
1650  {
1651  if (!UnicodeToAnsiInPlace(pdi2w->pName))
1652  goto Exit;
1653 
1654  if (!UnicodeToAnsiInPlace(pdi2w->pEnvironment))
1655  goto Exit;
1656 
1657  if (!UnicodeToAnsiInPlace(pdi2w->pDriverPath))
1658  goto Exit;
1659 
1660  if (!UnicodeToAnsiInPlace(pdi2w->pDataFile))
1661  goto Exit;
1662 
1663  if (!UnicodeToAnsiInPlace(pdi2w->pConfigFile))
1664  goto Exit;
1665 
1666  break;
1667  }
1668 
1669  case 3:
1670  {
1671  if (!UnicodeToAnsiInPlace(pdi3w->pName))
1672  goto Exit;
1673 
1674  if (!UnicodeToAnsiInPlace(pdi3w->pEnvironment))
1675  goto Exit;
1676 
1677  if (!UnicodeToAnsiInPlace(pdi3w->pDriverPath))
1678  goto Exit;
1679 
1680  if (!UnicodeToAnsiInPlace(pdi3w->pDataFile))
1681  goto Exit;
1682 
1683  if (!UnicodeToAnsiInPlace(pdi3w->pConfigFile))
1684  goto Exit;
1685 
1686  if (!UnicodeToAnsiInPlace(pdi3w->pHelpFile))
1687  goto Exit;
1688 
1690  goto Exit;
1691 
1692  if (!UnicodeToAnsiInPlace(pdi3w->pMonitorName))
1693  goto Exit;
1694 
1696  goto Exit;
1697 
1698  break;
1699  }
1700 
1701  case 4:
1702  {
1703  if (!UnicodeToAnsiInPlace(pdi4w->pName))
1704  goto Exit;
1705 
1706  if (!UnicodeToAnsiInPlace(pdi4w->pEnvironment))
1707  goto Exit;
1708 
1709  if (!UnicodeToAnsiInPlace(pdi4w->pDriverPath))
1710  goto Exit;
1711 
1712  if (!UnicodeToAnsiInPlace(pdi4w->pDataFile))
1713  goto Exit;
1714 
1715  if (!UnicodeToAnsiInPlace(pdi4w->pConfigFile))
1716  goto Exit;
1717 
1718  if (!UnicodeToAnsiInPlace(pdi4w->pHelpFile))
1719  goto Exit;
1720 
1722  goto Exit;
1723 
1724  if (!UnicodeToAnsiInPlace(pdi4w->pMonitorName))
1725  goto Exit;
1726 
1728  goto Exit;
1729 
1731  goto Exit;
1732 
1733  break;
1734  }
1735 
1736  case 5:
1737  {
1738  if (!UnicodeToAnsiInPlace(pdi5w->pName))
1739  goto Exit;
1740 
1741  if (!UnicodeToAnsiInPlace(pdi5w->pEnvironment))
1742  goto Exit;
1743 
1744  if (!UnicodeToAnsiInPlace(pdi5w->pDriverPath))
1745  goto Exit;
1746 
1747  if (!UnicodeToAnsiInPlace(pdi5w->pDataFile))
1748  goto Exit;
1749 
1750  if (!UnicodeToAnsiInPlace(pdi5w->pConfigFile))
1751  goto Exit;
1752 
1753  break;
1754  }
1755 
1756  case 6:
1757  {
1758  if (!UnicodeToAnsiInPlace(pdi6w->pName))
1759  goto Exit;
1760 
1761  if (!UnicodeToAnsiInPlace(pdi6w->pEnvironment))
1762  goto Exit;
1763 
1764  if (!UnicodeToAnsiInPlace(pdi6w->pDriverPath))
1765  goto Exit;
1766 
1767  if (!UnicodeToAnsiInPlace(pdi6w->pDataFile))
1768  goto Exit;
1769 
1770  if (!UnicodeToAnsiInPlace(pdi6w->pConfigFile))
1771  goto Exit;
1772 
1773  if (!UnicodeToAnsiInPlace(pdi6w->pHelpFile))
1774  goto Exit;
1775 
1777  goto Exit;
1778 
1779  if (!UnicodeToAnsiInPlace(pdi6w->pMonitorName))
1780  goto Exit;
1781 
1783  goto Exit;
1784 
1786  goto Exit;
1787 
1788  if (!UnicodeToAnsiInPlace(pdi6w->pszMfgName))
1789  goto Exit;
1790 
1791  if (!UnicodeToAnsiInPlace(pdi6w->pszOEMUrl))
1792  goto Exit;
1793 
1794  if (!UnicodeToAnsiInPlace(pdi6w->pszHardwareID))
1795  goto Exit;
1796 
1797  if (!UnicodeToAnsiInPlace(pdi6w->pszProvider))
1798  goto Exit;
1799  }
1800  }
1801 
1802  bReturnValue = TRUE;
1803 
1804 Exit:
1805 
1806  return bReturnValue;
1807 }
1808 
1809 BOOL WINAPI
1810 GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
1811 {
1812  DWORD dwErrorCode;
1813  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
1814 
1815  TRACE("GetPrinterDriverW(%p, %S, %lu, %p, %lu, %p)\n", hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
1816 
1817  // Sanity checks.
1818  if (!pHandle)
1819  {
1820  dwErrorCode = ERROR_INVALID_HANDLE;
1821  goto Cleanup;
1822  }
1823 
1824  // Dismiss invalid levels already at this point.
1825  if (Level > 8 || Level < 1)
1826  {
1827  dwErrorCode = ERROR_INVALID_LEVEL;
1828  goto Cleanup;
1829  }
1830 
1831  if (cbBuf && pDriverInfo)
1832  ZeroMemory(pDriverInfo, cbBuf);
1833 
1834  // Do the RPC call
1835  RpcTryExcept
1836  {
1837  dwErrorCode = _RpcGetPrinterDriver(pHandle->hPrinter, pEnvironment, Level, pDriverInfo, cbBuf, pcbNeeded);
1838  }
1840  {
1841  dwErrorCode = RpcExceptionCode();
1842  ERR("_RpcGetPrinterDriver failed with exception code %lu!\n", dwErrorCode);
1843  }
1844  RpcEndExcept;
1845 
1846  if (dwErrorCode == ERROR_SUCCESS)
1847  {
1848  // Replace relative offset addresses in the output by absolute pointers.
1849  ASSERT(Level <= 5);
1850  MarshallUpStructure(cbBuf, pDriverInfo, pPrinterDriverMarshalling[Level]->pInfo, pPrinterDriverMarshalling[Level]->cbStructureSize, TRUE);
1851  }
1852 
1853 Cleanup:
1854  SetLastError(dwErrorCode);
1855  return (dwErrorCode == ERROR_SUCCESS);
1856 }
1857 
1858 BOOL WINAPI
1860 {
1861  DWORD dwErrorCode;
1862  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
1863 
1864  TRACE("GetPrinterW(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
1865 
1866  // Sanity checks.
1867  if (!pHandle)
1868  {
1869  dwErrorCode = ERROR_INVALID_HANDLE;
1870  goto Cleanup;
1871  }
1872 
1873  // Dismiss invalid levels already at this point.
1874  if (Level > 9)
1875  {
1876  dwErrorCode = ERROR_INVALID_LEVEL;
1877  goto Cleanup;
1878  }
1879 
1880  if (cbBuf && pPrinter)
1881  ZeroMemory(pPrinter, cbBuf);
1882 
1883  // Do the RPC call
1884  RpcTryExcept
1885  {
1886  dwErrorCode = _RpcGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
1887  }
1889  {
1890  dwErrorCode = RpcExceptionCode();
1891  ERR("_RpcGetPrinter failed with exception code %lu!\n", dwErrorCode);
1892  }
1893  RpcEndExcept;
1894 
1895  if (dwErrorCode == ERROR_SUCCESS)
1896  {
1897  // Replace relative offset addresses in the output by absolute pointers.
1898  ASSERT(Level <= 9);
1899  MarshallUpStructure(cbBuf, pPrinter, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
1900  }
1901 
1902 Cleanup:
1903  SetLastError(dwErrorCode);
1904  return (dwErrorCode == ERROR_SUCCESS);
1905 }
1906 
1907 BOOL WINAPI
1908 OpenPrinterA(LPSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSA pDefault)
1909 {
1910  BOOL bReturnValue = FALSE;
1911  DWORD cch;
1912  PWSTR pwszPrinterName = NULL;
1913  PRINTER_DEFAULTSW wDefault = { 0 };
1914 
1915  TRACE("OpenPrinterA(%s, %p, %p)\n", pPrinterName, phPrinter, pDefault);
1916 
1917  if (pPrinterName)
1918  {
1919  // Convert pPrinterName to a Unicode string pwszPrinterName
1920  cch = strlen(pPrinterName);
1921 
1922  pwszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
1923  if (!pwszPrinterName)
1924  {
1926  ERR("HeapAlloc failed!\n");
1927  goto Cleanup;
1928  }
1929 
1930  MultiByteToWideChar(CP_ACP, 0, pPrinterName, -1, pwszPrinterName, cch + 1);
1931  }
1932 
1933  if (pDefault)
1934  {
1935  wDefault.DesiredAccess = pDefault->DesiredAccess;
1936 
1937  if (pDefault->pDatatype)
1938  {
1939  // Convert pDefault->pDatatype to a Unicode string wDefault.pDatatype
1940  cch = strlen(pDefault->pDatatype);
1941 
1942  wDefault.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
1943  if (!wDefault.pDatatype)
1944  {
1946  ERR("HeapAlloc failed!\n");
1947  goto Cleanup;
1948  }
1949 
1950  MultiByteToWideChar(CP_ACP, 0, pDefault->pDatatype, -1, wDefault.pDatatype, cch + 1);
1951  }
1952 
1953  if (pDefault->pDevMode)
1954  wDefault.pDevMode = GdiConvertToDevmodeW(pDefault->pDevMode);
1955  }
1956 
1957  bReturnValue = OpenPrinterW(pwszPrinterName, phPrinter, &wDefault);
1958 
1959 Cleanup:
1960  if (wDefault.pDatatype)
1961  HeapFree(hProcessHeap, 0, wDefault.pDatatype);
1962 
1963  if (wDefault.pDevMode)
1964  HeapFree(hProcessHeap, 0, wDefault.pDevMode);
1965 
1966  if (pwszPrinterName)
1967  HeapFree(hProcessHeap, 0, pwszPrinterName);
1968 
1969  return bReturnValue;
1970 }
1971 
1972 BOOL WINAPI
1973 OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefault)
1974 {
1975  DWORD dwErrorCode;
1976  HANDLE hPrinter;
1977  PSPOOLER_HANDLE pHandle;
1978  PWSTR pDatatype = NULL;
1979  WINSPOOL_DEVMODE_CONTAINER DevModeContainer = { 0 };
1980  ACCESS_MASK AccessRequired = 0;
1981 
1982  TRACE("OpenPrinterW(%S, %p, %p)\n", pPrinterName, phPrinter, pDefault);
1983 
1984  // Sanity check
1985  if (!phPrinter)
1986  {
1987  dwErrorCode = ERROR_INVALID_PARAMETER;
1988  goto Cleanup;
1989  }
1990 
1991  // Prepare the additional parameters in the format required by _RpcOpenPrinter
1992  if (pDefault)
1993  {
1994  pDatatype = pDefault->pDatatype;
1995  DevModeContainer.cbBuf = sizeof(DEVMODEW);
1996  DevModeContainer.pDevMode = (BYTE*)pDefault->pDevMode;
1997  AccessRequired = pDefault->DesiredAccess;
1998  }
1999 
2000  // Do the RPC call
2001  RpcTryExcept
2002  {
2003  dwErrorCode = _RpcOpenPrinter(pPrinterName, &hPrinter, pDatatype, &DevModeContainer, AccessRequired);
2004  }
2006  {
2007  dwErrorCode = RpcExceptionCode();
2008  ERR("_RpcOpenPrinter failed with exception code %lu!\n", dwErrorCode);
2009  }
2010  RpcEndExcept;
2011 
2012  if (dwErrorCode == ERROR_SUCCESS)
2013  {
2014  // Create a new SPOOLER_HANDLE structure.
2016  if (!pHandle)
2017  {
2018  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2019  ERR("HeapAlloc failed!\n");
2020  goto Cleanup;
2021  }
2022 
2023  pHandle->hPrinter = hPrinter;
2024  pHandle->hSPLFile = INVALID_HANDLE_VALUE;
2025 
2026  // Return it as phPrinter.
2027  *phPrinter = (HANDLE)pHandle;
2028  }
2029 
2030 Cleanup:
2031  SetLastError(dwErrorCode);
2032  return (dwErrorCode == ERROR_SUCCESS);
2033 }
2034 
2035 BOOL WINAPI
2036 ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
2037 {
2038  DWORD dwErrorCode;
2039  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2040 
2041  TRACE("ReadPrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pNoBytesRead);
2042 
2043  // Sanity checks.
2044  if (!pHandle)
2045  {
2046  dwErrorCode = ERROR_INVALID_HANDLE;
2047  goto Cleanup;
2048  }
2049 
2050  // Do the RPC call
2051  RpcTryExcept
2052  {
2053  dwErrorCode = _RpcReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
2054  }
2056  {
2057  dwErrorCode = RpcExceptionCode();
2058  ERR("_RpcReadPrinter failed with exception code %lu!\n", dwErrorCode);
2059  }
2060  RpcEndExcept;
2061 
2062 Cleanup:
2063  SetLastError(dwErrorCode);
2064  return (dwErrorCode == ERROR_SUCCESS);
2065 }
2066 
2067 BOOL WINAPI
2069 {
2070  TRACE("ResetPrinterA(%p, %p)\n", hPrinter, pDefault);
2071  UNIMPLEMENTED;
2072  return FALSE;
2073 }
2074 
2075 BOOL WINAPI
2077 {
2078  TRACE("ResetPrinterW(%p, %p)\n", hPrinter, pDefault);
2079  UNIMPLEMENTED;
2080  return FALSE;
2081 }
2082 
2083 BOOL WINAPI
2085 {
2086  BOOL bReturnValue = FALSE;
2087  DWORD cch;
2088  PWSTR pwszPrinter = NULL;
2089 
2090  TRACE("SetDefaultPrinterA(%s)\n", pszPrinter);
2091 
2092  if (pszPrinter)
2093  {
2094  // Convert pszPrinter to a Unicode string pwszPrinter
2095  cch = strlen(pszPrinter);
2096 
2097  pwszPrinter = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
2098  if (!pwszPrinter)
2099  {
2101  ERR("HeapAlloc failed!\n");
2102  goto Cleanup;
2103  }
2104 
2105  MultiByteToWideChar(CP_ACP, 0, pszPrinter, -1, pwszPrinter, cch + 1);
2106  }
2107 
2108  bReturnValue = SetDefaultPrinterW(pwszPrinter);
2109 
2110 Cleanup:
2111  if (pwszPrinter)
2112  HeapFree(hProcessHeap, 0, pwszPrinter);
2113 
2114  return bReturnValue;
2115 }
2116 
2117 BOOL WINAPI
2119 {
2120  const WCHAR wszDevicesKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Devices";
2121 
2122  DWORD cbDeviceValueData;
2123  DWORD cbPrinterValueData = 0;
2124  DWORD cchPrinter;
2125  DWORD dwErrorCode;
2126  HKEY hDevicesKey = NULL;
2127  HKEY hWindowsKey = NULL;
2128  PWSTR pwszDeviceValueData = NULL;
2129  WCHAR wszPrinter[MAX_PRINTER_NAME + 1];
2130 
2131  TRACE("SetDefaultPrinterW(%S)\n", pszPrinter);
2132 
2133  // Open the Devices registry key.
2134  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszDevicesKey, 0, KEY_READ, &hDevicesKey);
2135  if (dwErrorCode != ERROR_SUCCESS)
2136  {
2137  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
2138  goto Cleanup;
2139  }
2140 
2141  // Did the caller give us a printer to set as default?
2142  if (pszPrinter && *pszPrinter)
2143  {
2144  // Check if the given printer exists and query the value data size.
2145  dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, NULL, &cbPrinterValueData);
2146  if (dwErrorCode == ERROR_FILE_NOT_FOUND)
2147  {
2148  dwErrorCode = ERROR_INVALID_PRINTER_NAME;
2149  goto Cleanup;
2150  }
2151  else if (dwErrorCode != ERROR_SUCCESS)
2152  {
2153  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
2154  goto Cleanup;
2155  }
2156 
2157  cchPrinter = wcslen(pszPrinter);
2158  }
2159  else
2160  {
2161  // If there is already a default printer, we're done!
2162  cchPrinter = _countof(wszPrinter);
2163  if (GetDefaultPrinterW(wszPrinter, &cchPrinter))
2164  {
2165  dwErrorCode = ERROR_SUCCESS;
2166  goto Cleanup;
2167  }
2168 
2169  // Otherwise, get us the first printer from the "Devices" key to later set it as default and query the value data size.
2170  cchPrinter = _countof(wszPrinter);
2171  dwErrorCode = (DWORD)RegEnumValueW(hDevicesKey, 0, wszPrinter, &cchPrinter, NULL, NULL, NULL, &cbPrinterValueData);
2172  if (dwErrorCode != ERROR_MORE_DATA)
2173  goto Cleanup;
2174 
2175  pszPrinter = wszPrinter;
2176  }
2177 
2178  // We now need to query the value data, which has the format "winspool,<Port>:"
2179  // and make "<Printer Name>,winspool,<Port>:" out of it.
2180  // Allocate a buffer large enough for the final data.
2181  cbDeviceValueData = (cchPrinter + 1) * sizeof(WCHAR) + cbPrinterValueData;
2182  pwszDeviceValueData = HeapAlloc(hProcessHeap, 0, cbDeviceValueData);
2183  if (!pwszDeviceValueData)
2184  {
2185  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2186  ERR("HeapAlloc failed!\n");
2187  goto Cleanup;
2188  }
2189 
2190  // Copy the Printer Name and a comma into it.
2191  CopyMemory(pwszDeviceValueData, pszPrinter, cchPrinter * sizeof(WCHAR));
2192  pwszDeviceValueData[cchPrinter] = L',';
2193 
2194  // Append the value data, which has the format "winspool,<Port>:"
2195  dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, (PBYTE)&pwszDeviceValueData[cchPrinter + 1], &cbPrinterValueData);
2196  if (dwErrorCode != ERROR_SUCCESS)
2197  goto Cleanup;
2198 
2199  // Open the Windows registry key.
2200  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_SET_VALUE, &hWindowsKey);
2201  if (dwErrorCode != ERROR_SUCCESS)
2202  {
2203  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
2204  goto Cleanup;
2205  }
2206 
2207  // Store our new default printer.
2208  dwErrorCode = (DWORD)RegSetValueExW(hWindowsKey, wszDeviceValue, 0, REG_SZ, (PBYTE)pwszDeviceValueData, cbDeviceValueData);
2209  if (dwErrorCode != ERROR_SUCCESS)
2210  {
2211  ERR("RegSetValueExW failed with status %lu!\n", dwErrorCode);
2212  goto Cleanup;
2213  }
2214 
2215 Cleanup:
2216  if (hDevicesKey)
2217  RegCloseKey(hDevicesKey);
2218 
2219  if (hWindowsKey)
2220  RegCloseKey(hWindowsKey);
2221 
2222  if (pwszDeviceValueData)
2223  HeapFree(hProcessHeap, 0, pwszDeviceValueData);
2224 
2225  SetLastError(dwErrorCode);
2226  return (dwErrorCode == ERROR_SUCCESS);
2227 }
2228 
2229 BOOL WINAPI
2231 {
2232  TRACE("SetPrinterA(%p, %lu, %p, %lu)\n", hPrinter, Level, pPrinter, Command);
2233  UNIMPLEMENTED;
2234  return FALSE;
2235 }
2236 
2237 BOOL WINAPI
2239 {
2240  TRACE("SetPrinterW(%p, %lu, %p, %lu)\n", hPrinter, Level, pPrinter, Command);
2241  UNIMPLEMENTED;
2242  return FALSE;
2243 }
2244 
2245 BOOL WINAPI
2247 {
2248  TRACE("DriverUnloadComplete(%S)\n", pDriverFile);
2249  UNIMPLEMENTED;
2250  return TRUE; // return true for now.
2251 }
2252 
2253 DWORD WINAPI
2255 {
2256  DOC_INFO_1W wDocInfo1 = { 0 };
2257  DWORD cch;
2258  DWORD dwErrorCode;
2259  DWORD dwReturnValue = 0;
2260  PDOC_INFO_1A pDocInfo1 = (PDOC_INFO_1A)pDocInfo;
2261 
2262  TRACE("StartDocPrinterA(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
2263 
2264  // Only check the minimum required for accessing pDocInfo.
2265  // Additional sanity checks are done in StartDocPrinterW.
2266  if (!pDocInfo1)
2267  {
2268  dwErrorCode = ERROR_INVALID_PARAMETER;
2269  goto Cleanup;
2270  }
2271 
2272  if (Level != 1)
2273  {
2274  dwErrorCode = ERROR_INVALID_LEVEL;
2275  goto Cleanup;
2276  }
2277 
2278  if (pDocInfo1->pDatatype)
2279  {
2280  // Convert pDocInfo1->pDatatype to a Unicode string wDocInfo1.pDatatype
2281  cch = strlen(pDocInfo1->pDatatype);
2282 
2283  wDocInfo1.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
2284  if (!wDocInfo1.pDatatype)
2285  {
2286  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2287  ERR("HeapAlloc failed!\n");
2288  goto Cleanup;
2289  }
2290 
2291  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDatatype, -1, wDocInfo1.pDatatype, cch + 1);
2292  }
2293 
2294  if (pDocInfo1->pDocName)
2295  {
2296  // Convert pDocInfo1->pDocName to a Unicode string wDocInfo1.pDocName
2297  cch = strlen(pDocInfo1->pDocName);
2298 
2299  wDocInfo1.pDocName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
2300  if (!wDocInfo1.pDocName)
2301  {
2302  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2303  ERR("HeapAlloc failed!\n");
2304  goto Cleanup;
2305  }
2306 
2307  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDocName, -1, wDocInfo1.pDocName, cch + 1);
2308  }
2309 
2310  if (pDocInfo1->pOutputFile)
2311  {
2312  // Convert pDocInfo1->pOutputFile to a Unicode string wDocInfo1.pOutputFile
2313  cch = strlen(pDocInfo1->pOutputFile);
2314 
2315  wDocInfo1.pOutputFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
2316  if (!wDocInfo1.pOutputFile)
2317  {
2318  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2319  ERR("HeapAlloc failed!\n");
2320  goto Cleanup;
2321  }
2322 
2323  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pOutputFile, -1, wDocInfo1.pOutputFile, cch + 1);
2324  }
2325 
2326  dwReturnValue = StartDocPrinterW(hPrinter, Level, (PBYTE)&wDocInfo1);
2327  dwErrorCode = GetLastError();
2328 
2329 Cleanup:
2330  if (wDocInfo1.pDatatype)
2331  HeapFree(hProcessHeap, 0, wDocInfo1.pDatatype);
2332 
2333  if (wDocInfo1.pDocName)
2334  HeapFree(hProcessHeap, 0, wDocInfo1.pDocName);
2335 
2336  if (wDocInfo1.pOutputFile)
2337  HeapFree(hProcessHeap, 0, wDocInfo1.pOutputFile);
2338 
2339  SetLastError(dwErrorCode);
2340  return dwReturnValue;
2341 }
2342 
2343 DWORD WINAPI
2345 {
2346  DWORD cbAddJobInfo1;
2347  DWORD cbNeeded;
2348  DWORD dwErrorCode;
2349  DWORD dwReturnValue = 0;
2350  PADDJOB_INFO_1W pAddJobInfo1 = NULL;
2351  PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo;
2352  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2353 
2354  TRACE("StartDocPrinterW(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
2355 
2356  // Sanity checks.
2357  if (!pHandle)
2358  {
2359  dwErrorCode = ERROR_INVALID_HANDLE;
2360  goto Cleanup;
2361  }
2362 
2363  if (!pDocInfo1)
2364  {
2365  dwErrorCode = ERROR_INVALID_PARAMETER;
2366  goto Cleanup;
2367  }
2368 
2369  if (Level != 1)
2370  {
2371  dwErrorCode = ERROR_INVALID_LEVEL;
2372  goto Cleanup;
2373  }
2374 
2375  if (pHandle->bStartedDoc)
2376  {
2377  dwErrorCode = ERROR_INVALID_PRINTER_STATE;
2378  goto Cleanup;
2379  }
2380 
2381  // Check if we want to redirect output into a file.
2382  if (pDocInfo1->pOutputFile)
2383  {
2384  // Do a StartDocPrinter RPC call in this case.
2385  dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1);
2386  }
2387  else
2388  {
2389  // Allocate memory for the ADDJOB_INFO_1W structure and a path.
2390  cbAddJobInfo1 = sizeof(ADDJOB_INFO_1W) + MAX_PATH * sizeof(WCHAR);
2391  pAddJobInfo1 = HeapAlloc(hProcessHeap, 0, cbAddJobInfo1);
2392  if (!pAddJobInfo1)
2393  {
2394  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2395  ERR("HeapAlloc failed!\n");
2396  goto Cleanup;
2397  }
2398 
2399  // Try to add a new job.
2400  // This only succeeds if the printer is set to do spooled printing.
2401  if (AddJobW((HANDLE)pHandle, 1, (PBYTE)pAddJobInfo1, cbAddJobInfo1, &cbNeeded))
2402  {
2403  // Do spooled printing.
2404  dwErrorCode = _StartDocPrinterSpooled(pHandle, pDocInfo1, pAddJobInfo1);
2405  }
2406  else if (GetLastError() == ERROR_INVALID_ACCESS)
2407  {
2408  // ERROR_INVALID_ACCESS is returned when the printer is set to do direct printing.
2409  // In this case, we do a StartDocPrinter RPC call.
2410  dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1);
2411  }
2412  else
2413  {
2414  dwErrorCode = GetLastError();
2415  ERR("AddJobW failed with error %lu!\n", dwErrorCode);
2416  goto Cleanup;
2417  }
2418  }
2419 
2420  if (dwErrorCode == ERROR_SUCCESS)
2421  {
2422  pHandle->bStartedDoc = TRUE;
2423  dwReturnValue = pHandle->dwJobID;
2424  }
2425 
2426 Cleanup:
2427  if (pAddJobInfo1)
2428  HeapFree(hProcessHeap, 0, pAddJobInfo1);
2429 
2430  SetLastError(dwErrorCode);
2431  return dwReturnValue;
2432 }
2433 
2434 BOOL WINAPI
2436 {
2437  DWORD dwErrorCode;
2438  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2439 
2440  TRACE("StartPagePrinter(%p)\n", hPrinter);
2441 
2442  // Sanity checks.
2443  if (!pHandle)
2444  {
2445  dwErrorCode = ERROR_INVALID_HANDLE;
2446  goto Cleanup;
2447  }
2448 
2449  // Do the RPC call
2450  RpcTryExcept
2451  {
2452  dwErrorCode = _RpcStartPagePrinter(pHandle->hPrinter);
2453  }
2455  {
2456  dwErrorCode = RpcExceptionCode();
2457  ERR("_RpcStartPagePrinter failed with exception code %lu!\n", dwErrorCode);
2458  }
2459  RpcEndExcept;
2460 
2461 Cleanup:
2462  SetLastError(dwErrorCode);
2463  return (dwErrorCode == ERROR_SUCCESS);
2464 }
2465 
2466 BOOL WINAPI
2467 WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
2468 {
2469  DWORD dwErrorCode;
2470  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2471 
2472  TRACE("WritePrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pcWritten);
2473 
2474  // Sanity checks.
2475  if (!pHandle)
2476  {
2477  dwErrorCode = ERROR_INVALID_HANDLE;
2478  goto Cleanup;
2479  }
2480 
2481  if (!pHandle->bStartedDoc)
2482  {
2483  dwErrorCode = ERROR_SPL_NO_STARTDOC;
2484  goto Cleanup;
2485  }
2486 
2487  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
2488  {
2489  // Write to the spool file. This doesn't need an RPC request.
2490  if (!WriteFile(pHandle->hSPLFile, pBuf, cbBuf, pcWritten, NULL))
2491  {
2492  dwErrorCode = GetLastError();
2493  ERR("WriteFile failed with error %lu!\n", dwErrorCode);
2494  goto Cleanup;
2495  }
2496 
2497  dwErrorCode = ERROR_SUCCESS;
2498  }
2499  else
2500  {
2501  // TODO: This case (for direct printing or remote printing) has bad performance if multiple small-sized WritePrinter calls are performed.
2502  // We may increase performance by writing into a buffer and only doing a single RPC call when the buffer is full.
2503 
2504  // Do the RPC call
2505  RpcTryExcept
2506  {
2507  dwErrorCode = _RpcWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten);
2508  }
2510  {
2511  dwErrorCode = RpcExceptionCode();
2512  ERR("_RpcWritePrinter failed with exception code %lu!\n", dwErrorCode);
2513  }
2514  RpcEndExcept;
2515  }
2516 
2517 Cleanup:
2518  SetLastError(dwErrorCode);
2519  return (dwErrorCode == ERROR_SUCCESS);
2520 }
2521 
2522 BOOL WINAPI
2523 XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
2524 {
2525  TRACE("XcvDataW(%p, %S, %p, %lu, %p, %lu, %p, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
2526  return FALSE;
2527 }
static PRINTER_INFO_9W * get_devmodeW(HANDLE hprn)
Definition: printers.c:289
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
struct _DRIVER_INFO_5W * PDRIVER_INFO_5W
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:56
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
struct _PRINTER_INFO_7A * PPRINTER_INFO_7A
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:407
LPWSTR pszProvider
Definition: winspool.h:529
LPSTR pPrinterName
Definition: winspool.h:110
LPWSTR pHelpFile
Definition: winspool.h:519
#define ERROR_SUCCESS
Definition: deptool.c:10
#define WideCharToMultiByte
Definition: compat.h:101
#define KEY_SET_VALUE
Definition: nt_native.h:1017
LPWSTR pDefaultDataType
Definition: winspool.h:425
LPWSTR pDependentFiles
Definition: winspool.h:454
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
struct _PRINTER_INFO_2W * PPRINTER_INFO_2W
#define DM_IN_PROMPT
Definition: windef.h:358
#define DM_OUT_DEFAULT
Definition: windef.h:360
BOOL WINAPI GetPrinterDriverA(HANDLE hPrinter, LPSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
Definition: printers.c:1581
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
LPWSTR pDriverPath
Definition: winspool.h:450
#define KEY_READ
Definition: nt_native.h:1023
LPWSTR pDatatype
Definition: winspool.h:72
uint16_t * PWSTR
Definition: typedefs.h:55
DWORD _RpcEndDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:61
BOOL WINAPI SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
Definition: printers.c:2238
#define CP_ACP
Definition: compat.h:99
struct _DRIVER_INFO_2W * PDRIVER_INFO_2W
DWORD WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, WORD fwCapability, LPWSTR pOutput, const DEVMODEW *pDevMode)
Definition: printers.c:190
#define HKEY_CURRENT_USER
Definition: winreg.h:11
LPSTR pServerName
Definition: winspool.h:38
char CHAR
Definition: xmlstorage.h:175
WINBOOL WINAPI GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded)
LPWSTR pDriverPath
Definition: winspool.h:480
#define ERROR_INVALID_HANDLE
Definition: compat.h:88
LPWSTR pOutputFile
Definition: winspool.h:557
static HDC
Definition: imagelist.c:92
LPWSTR pDataFile
Definition: winspool.h:394
BOOL WINAPI GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
Definition: printers.c:981
HWND hWnd
Definition: settings.c:17
struct _ADDJOB_INFO_1W ADDJOB_INFO_1W
WORD dmDriverExtra
Definition: wingdi.h:1620
LPWSTR pHelpFile
Definition: winspool.h:422
#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
LPWSTR pDataFile
Definition: winspool.h:517
#define INVALID_HANDLE_VALUE
Definition: compat.h:400
LPWSTR pConfigFile
Definition: winspool.h:452
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1648
struct _DRIVER_INFO_1W * PDRIVER_INFO_1W
DWORD WINAPI StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
Definition: printers.c:222
LPWSTR pName
Definition: winspool.h:514
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
LPDEVMODEW pDevMode
Definition: winspool.h:170
LPWSTR pMonitorName
Definition: winspool.h:521
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:969
BOOL bStartedDoc
Definition: precomp.h:34
BOOL WINAPI ResetPrinterA(HANDLE hPrinter, PPRINTER_DEFAULTSA pDefault)
Definition: printers.c:2068
#define DWORD
Definition: nt_native.h:44
LPWSTR pszOEMUrl
Definition: winspool.h:527
DWORD dwJobID
Definition: precomp.h:35
int32_t INT
Definition: typedefs.h:57
BOOL WINAPI DeletePrinter(HANDLE hPrinter)
Definition: printers.c:174
struct _PRINTER_INFO_5A * PPRINTER_INFO_5A
#define FILE_SHARE_READ
Definition: compat.h:125
LPWSTR pDependentFiles
Definition: winspool.h:520
LPSTR pSepFile
Definition: winspool.h:46
LPWSTR pDriverName
Definition: winspool.h:66
LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode)
Definition: printers.c:311
LPDEVMODEW pDevMode
Definition: winspool.h:769
LPSTR pShareName
Definition: winspool.h:40
LPWSTR pLocation
Definition: winspool.h:68
_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
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LPWSTR pMonitorName
Definition: winspool.h:424
LPSTR pComment
Definition: winspool.h:23
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
unsigned char * LPBYTE
Definition: typedefs.h:53
LPWSTR pPrinterName
Definition: winspool.h:100
LPWSTR pDataFile
Definition: winspool.h:420
LPWSTR pMonitorName
Definition: winspool.h:455
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL WINAPI GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
Definition: printers.c:1027
long LONG
Definition: pedump.c:60
#define DM_OUT_BUFFER
Definition: windef.h:359
BOOL WINAPI AbortPrinter(HANDLE hPrinter)
Definition: printers.c:111
LPWSTR pName
Definition: winspool.h:29
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FIXME(fmt,...)
Definition: debug.h:111
LPWSTR pShareName
Definition: winspool.h:64
#define RpcTryExcept
Definition: rpc.h:126
INT WINAPI DocumentEvent(HANDLE hPrinter, HDC hdc, int iEsc, ULONG cbIn, PVOID pvIn, ULONG cbOut, PVOID pvOut)
Definition: printers.c:198
LPSTR pServerName
Definition: winspool.h:95
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
LPWSTR pName
Definition: winspool.h:373
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:2853
BOOL WINAPI ResetPrinterW(HANDLE hPrinter, PPRINTER_DEFAULTSW pDefault)
Definition: printers.c:2076
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:201
smooth NULL
Definition: ftsmooth.c:416
LPSTR pDriverName
Definition: winspool.h:42
BOOL UnicodeToAnsiInPlace(PWSTR pwszField)
Definition: utils.c:10
_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
LPWSTR pszzPreviousNames
Definition: winspool.h:457
BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
Definition: printers.c:125
struct _PRINTER_INFO_2A * PPRINTER_INFO_2A
static DWORD _StartDocPrinterWithRPC(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1)
Definition: printers.c:88
struct _PRINTER_INFO_1W * PPRINTER_INFO_1W
LPWSTR pDataFile
Definition: winspool.h:481
const char * LPCSTR
Definition: xmlstorage.h:183
LPSTR pPrinterName
Definition: winspool.h:94
LPWSTR pszHardwareID
Definition: winspool.h:528
#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
LPSTR pPrinterName
Definition: winspool.h:39
HANDLE hSPLFile
Definition: precomp.h:37
LPWSTR pEnvironment
Definition: winspool.h:392
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:4895
#define DOCUMENTEVENT_UNSUPPORTED
Definition: winddiui.h:90
BOOL WINAPI ClosePrinter(HANDLE hPrinter)
Definition: printers.c:12
#define RpcExceptionCode()
Definition: rpc.h:132
void RosConvertUnicodeDevModeToAnsiDevmode(PDEVMODEW pDevModeInput, PDEVMODEA pDevModeOutput)
Definition: devmode.c:305
#define TRACE(s)
Definition: solgame.cpp:4
static LPSTR pName
Definition: security.c:75
void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW pDevModeOutput)
Definition: devmode.c:237
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:4116
__wchar_t WCHAR
Definition: xmlstorage.h:180
struct _PRINTER_INFO_1A * PPRINTER_INFO_1A
LPWSTR pDatatype
Definition: winspool.h:558
static void Exit(void)
Definition: sock.c:1331
LPWSTR pDataFile
Definition: winspool.h:451
#define _countof(array)
Definition: sndvol32.h:68
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:973
WORD dmSize
Definition: wingdi.h:1619
#define MAX_PATH
Definition: compat.h:26
DWORD _RpcWritePrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE *pBuf, DWORD cbBuf, DWORD *pcWritten)
Definition: printers.c:286
#define WINAPI
Definition: msvc.h:6
LPSTR pszObjectGUID
Definition: winspool.h:134
#define CopyMemory
Definition: winbase.h:1646
unsigned short WORD
Definition: ntddk_ex.h:93
PVOID HANDLE
Definition: typedefs.h:72
unsigned long DWORD
Definition: ntddk_ex.h:95
ACCESS_MASK DesiredAccess
Definition: winspool.h:770
LPWSTR pEnvironment
Definition: winspool.h:418
LPWSTR pDriverPath
Definition: winspool.h:393
#define SetLastError(x)
Definition: compat.h:418
DWORD _RpcReadPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE *pBuf, DWORD cbBuf, DWORD *pcNoBytesRead)
Definition: printers.c:201
LPWSTR pName
Definition: winspool.h:417
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
#define MAX_PRINTER_NAME
Definition: fpSetJob.c:25
LPWSTR pDriverPath
Definition: winspool.h:516
LPWSTR pEnvironment
Definition: winspool.h:515
LPSTR pLocation
Definition: winspool.h:44
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
LPWSTR pSepFile
Definition: winspool.h:70
LPWSTR pHelpFile
Definition: winspool.h:453
LPWSTR pDriverPath
Definition: winspool.h:419
static const WCHAR wszWindowsKey[]
Definition: printers.c:17
LPSTR pOutputFile
Definition: winspool.h:551
LPWSTR pDefaultDataType
Definition: winspool.h:456
static const WCHAR L[]
Definition: oid.c:1250
HDC hdc
Definition: main.c:9
LPSTR pDatatype
Definition: winspool.h:552
LPWSTR pServerName
Definition: winspool.h:62
LPWSTR pEnvironment
Definition: winspool.h:479
BOOL WINAPI OpenPrinterA(LPSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSA pDefault)
Definition: printers.c:1908
LPSTR pPortName
Definition: winspool.h:41
BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
Definition: printers.c:2230
BOOL WINAPI EndPagePrinter(HANDLE hPrinter)
Definition: printers.c:51
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#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
LPSTR pDescription
Definition: winspool.h:21
WINSPOOL_DOC_INFO_1 * pDocInfo1
Definition: winspool.idl:577
_In_ ULONG iEsc
Definition: winddi.h:3529
LPWSTR pPrinterName
Definition: winspool.h:118
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
LPWSTR pComment
Definition: winspool.h:30
#define ERROR_MORE_DATA
Definition: dderror.h:13
_In_ LPWSTR _In_ ULONG _In_ ULONG _In_ ULONG _Out_ DEVINFO _In_ HDEV _In_ LPWSTR pwszDeviceName
Definition: winddi.h:3553
#define ERROR_INVALID_PRINTER_NAME
Definition: winerror.h:1108
unsigned char BYTE
Definition: xxhash.c:193
BOOL WINAPI MarshallUpStructure(DWORD cbSize, PVOID pStructure, const MARSHALLING_INFO *pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
Definition: marshalling.c:137
struct _DRIVER_INFO_4W * PDRIVER_INFO_4W
HANDLE WINAPI AddPrinterA(PSTR pName, DWORD Level, PBYTE pPrinter)
Definition: printers.c:119
#define ERR(fmt,...)
Definition: debug.h:110
LPWSTR pDescription
Definition: winspool.h:28
LPWSTR pszObjectGUID
Definition: winspool.h:139
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
DWORD WINAPI DeviceCapabilitiesA(LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA *pDevMode)
Definition: printers.c:182
HANDLE WINAPI AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter)
Definition: printers.c:127
#define CREATE_ALWAYS
Definition: disk.h:72
LPWSTR pEnvironment
Definition: winspool.h:449
struct _PRINTER_INFO_4W * PPRINTER_INFO_4W
#define DM_IN_BUFFER
Definition: windef.h:357
LPWSTR pPortName
Definition: winspool.h:119
static const MARSHALLING * pPrinterInfoMarshalling[]
Definition: printers.h:146
_In_ DWORD _Out_ PDWORD pcbNeeded
Definition: winddi.h:3827
LPWSTR pName
Definition: winspool.h:448
BOOL WINAPI EnumPrintersA(DWORD Flags, PSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: printers.c:472
struct _DRIVER_INFO_6W * PDRIVER_INFO_6W
LPWSTR pDefaultDataType
Definition: winspool.h:522
LPWSTR pServerName
Definition: winspool.h:101
signed char * PSTR
Definition: retypes.h:7
struct _PRINTER_INFO_5W * PPRINTER_INFO_5W
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:409
LPSTR pComment
Definition: winspool.h:43
LPWSTR pPortName
Definition: winspool.h:65
LPSTR pParameters
Definition: winspool.h:49
LPWSTR pConfigFile
Definition: winspool.h:518
LPWSTR pszMfgName
Definition: winspool.h:526
BOOL WINAPI SetDefaultPrinterA(LPCSTR pszPrinter)
Definition: printers.c:2084
static const WCHAR wszDeviceValue[]
Definition: printers.c:18
BOOL WINAPI GetPrinterA(HANDLE hPrinter, DWORD Level, LPBYTE pPrinter, DWORD cbBuf, LPDWORD pcbNeeded)
Definition: printers.c:1118
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:58
LPWSTR pPrinterName
Definition: winspool.h:63
unsigned int ULONG
Definition: retypes.h:1
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3366
LPWSTR pszzPreviousNames
Definition: winspool.h:523
#define UNIMPLEMENTED
Definition: debug.h:115
LONG WINAPI DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode)
Definition: printers.c:206
#define ERROR_INVALID_NAME
Definition: compat.h:93
LPWSTR pComment
Definition: winspool.h:67
LPWSTR pName
Definition: winspool.h:478
LPWSTR pConfigFile
Definition: winspool.h:482
ACCESS_MASK DesiredAccess
Definition: winspool.h:764
struct _devicemodeW DEVMODEW
static HANDLE hXcv
Definition: localmon.c:73
#define ERROR_INVALID_PRINTER_STATE
Definition: winerror.h:1148
#define ERROR_INVALID_LEVEL
Definition: winerror.h:196
WCHAR * LPWSTR
Definition: xmlstorage.h:184
struct _PRINTER_INFO_7W * PPRINTER_INFO_7W
LPSTR pDatatype
Definition: winspool.h:48
LPWSTR pParameters
Definition: winspool.h:73
DWORD _RpcGetPrinterDriver(WINSPOOL_PRINTER_HANDLE hPrinter, WCHAR *pEnvironment, DWORD Level, BYTE *pDriver, DWORD cbBuf, DWORD *pcbNeeded)
struct _DOC_INFO_1A * PDOC_INFO_1A
LPWSTR pPrintProcessor
Definition: winspool.h:71
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:403
LPWSTR pName
Definition: winspool.h:391
struct _DRIVER_INFO_3W * PDRIVER_INFO_3W
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
LPWSTR pConfigFile
Definition: winspool.h:395
LPWSTR pConfigFile
Definition: winspool.h:421
union _WINSPOOL_DOC_INFO_CONTAINER::@3340 DocInfo
struct _PRINTER_INFO_4A * PPRINTER_INFO_4A
static DWORD _StartDocPrinterSpooled(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1, PADDJOB_INFO_1W pAddJobInfo1)
Definition: printers.c:21
BOOL WINAPI SetDefaultPrinterW(LPCWSTR pszPrinter)
Definition: printers.c:2118
#define RpcExcept(expr)
Definition: rpc.h:127
LPSTR pPrintProcessor
Definition: winspool.h:47
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:2254
HANDLE hPrinter
Definition: precomp.h:36
static const MARSHALLING * pPrinterDriverMarshalling[]
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define REG_SZ
Definition: layer.c:22
BOOL WINAPI SplDriverUnloadComplete(LPWSTR pDriverFile)
Definition: printers.c:2246
LPWSTR pDependentFiles
Definition: winspool.h:423