ReactOS  0.4.15-dev-1638-gc0caa5c
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>
10 //#include <marshalling/printerdrivers.h>
11 #include <strsafe.h>
12 
14 //
15 // See winddiui.h, ReactOS version is limited.
16 // Loading from XyzUI.dll part of XyzDRV.dll set. example TTYUI.DLL or UniDrvUI.DLL.
17 //
20 
25 
28 
31 
34 
37 
40 
41 //
42 // PrintUI.dll
43 //
47 
48 //
49 // CompstUI User Data
50 //
51 typedef struct _COMPUI_USERDATA
52 {
56 
57 // Local Constants
58 
61 static const WCHAR wszWindowsKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows";
62 static const WCHAR wszDeviceValue[] = L"Device";
63 
64 static DWORD
66 {
67  DWORD cbNeeded;
68  DWORD dwErrorCode;
69  PJOB_INFO_1W pJobInfo1 = NULL;
70 
71  // Create the spool file.
73  if (pHandle->hSPLFile == INVALID_HANDLE_VALUE)
74  {
75  dwErrorCode = GetLastError();
76  ERR("CreateFileW failed for \"%S\" with error %lu!\n", pAddJobInfo1->Path, dwErrorCode);
77  goto Cleanup;
78  }
79 
80  // Get the size of the job information.
81  GetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, NULL, 0, &cbNeeded);
83  {
84  dwErrorCode = GetLastError();
85  ERR("GetJobW failed with error %lu!\n", dwErrorCode);
86  goto Cleanup;
87  }
88 
89  // Allocate enough memory for the returned job information.
90  pJobInfo1 = HeapAlloc(hProcessHeap, 0, cbNeeded);
91  if (!pJobInfo1)
92  {
93  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
94  ERR("HeapAlloc failed!\n");
95  goto Cleanup;
96  }
97 
98  // Get the job information.
99  if (!GetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, (PBYTE)pJobInfo1, cbNeeded, &cbNeeded))
100  {
101  dwErrorCode = GetLastError();
102  ERR("GetJobW failed with error %lu!\n", dwErrorCode);
103  goto Cleanup;
104  }
105 
106  // Add our document information.
107  if (pDocInfo1->pDatatype)
108  pJobInfo1->pDatatype = pDocInfo1->pDatatype;
109 
110  pJobInfo1->pDocument = pDocInfo1->pDocName;
111 
112  // Set the new job information.
113  if (!SetJobW((HANDLE)pHandle, pAddJobInfo1->JobId, 1, (PBYTE)pJobInfo1, 0))
114  {
115  dwErrorCode = GetLastError();
116  ERR("SetJobW failed with error %lu!\n", dwErrorCode);
117  goto Cleanup;
118  }
119 
120  // We were successful!
121  pHandle->dwJobID = pAddJobInfo1->JobId;
122  dwErrorCode = ERROR_SUCCESS;
123 
124 Cleanup:
125  if (pJobInfo1)
126  HeapFree(hProcessHeap, 0, pJobInfo1);
127 
128  return dwErrorCode;
129 }
130 
131 static DWORD
133 {
134  DWORD dwErrorCode;
135  WINSPOOL_DOC_INFO_CONTAINER DocInfoContainer;
136 
137  DocInfoContainer.Level = 1;
138  DocInfoContainer.DocInfo.pDocInfo1 = (WINSPOOL_DOC_INFO_1*)pDocInfo1;
139 
141  {
142  dwErrorCode = _RpcStartDocPrinter(pHandle->hPrinter, &DocInfoContainer, &pHandle->dwJobID);
143  }
145  {
146  dwErrorCode = RpcExceptionCode();
147  ERR("_RpcStartDocPrinter failed with exception code %lu!\n", dwErrorCode);
148  }
149  RpcEndExcept;
150 
151  return dwErrorCode;
152 }
153 
154 BOOL WINAPI
156 {
157  DWORD dwErrorCode;
158  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
159 
160  TRACE("AbortPrinter(%p)\n", hPrinter);
161 
162  // Sanity checks.
163  if (!pHandle)
164  {
165  dwErrorCode = ERROR_INVALID_HANDLE;
166  goto Cleanup;
167  }
168 
169  pHandle->bTrayIcon = pHandle->bStartedDoc = FALSE;
170 
171  if ( pHandle->hSPLFile != INVALID_HANDLE_VALUE && pHandle->bJob )
172  {
173  // Close any open file handle.
174  CloseHandle( pHandle->hSPLFile );
175  pHandle->hSPLFile = INVALID_HANDLE_VALUE;
176 
177  SetJobW( hPrinter, pHandle->dwJobID, 0, NULL, JOB_CONTROL_DELETE );
178 
179  return ScheduleJob( hPrinter, pHandle->dwJobID );
180  }
181 
182  // Do the RPC call.
184  {
185  dwErrorCode = _RpcAbortPrinter(&pHandle->hPrinter);
186  }
188  {
189  dwErrorCode = RpcExceptionCode();
190  ERR("_RpcAbortPrinter failed with exception code %lu!\n", dwErrorCode);
191  }
192  RpcEndExcept;
193 
194 Cleanup:
195  SetLastError(dwErrorCode);
196  return (dwErrorCode == ERROR_SUCCESS);
197 }
198 
201 {
202  UNICODE_STRING pNameW, usBuffer;
203  PWSTR pwstrNameW;
204  PRINTER_INFO_2W *ppi2w = (PRINTER_INFO_2W*)pPrinter;
205  PRINTER_INFO_2A *ppi2a = (PRINTER_INFO_2A*)pPrinter;
206  HANDLE ret = NULL;
207  PWSTR pwszPrinterName = NULL;
208  PWSTR pwszServerName = NULL;
209  PWSTR pwszShareName = NULL;
210  PWSTR pwszPortName = NULL;
211  PWSTR pwszDriverName = NULL;
212  PWSTR pwszComment = NULL;
213  PWSTR pwszLocation = NULL;
214  PWSTR pwszSepFile = NULL;
215  PWSTR pwszPrintProcessor = NULL;
216  PWSTR pwszDatatype = NULL;
217  PWSTR pwszParameters = NULL;
218  PDEVMODEW pdmw = NULL;
219 
220  TRACE("AddPrinterA(%s, %d, %p)\n", debugstr_a(pName), Level, pPrinter);
221 
222  if(Level != 2)
223  {
224  ERR("Level = %d, unsupported!\n", Level);
226  return NULL;
227  }
228 
229  pwstrNameW = AsciiToUnicode(&pNameW,pName);
230 
231  if (ppi2a->pShareName)
232  {
233  pwszShareName = AsciiToUnicode(&usBuffer, ppi2a->pShareName);
234  if (!(ppi2w->pShareName = pwszShareName)) goto Cleanup;
235  }
236  if (ppi2a->pPortName)
237  {
238  pwszPortName = AsciiToUnicode(&usBuffer, ppi2a->pPortName);
239  if (!(ppi2w->pPortName = pwszPortName)) goto Cleanup;
240  }
241  if (ppi2a->pDriverName)
242  {
243  pwszDriverName = AsciiToUnicode(&usBuffer, ppi2a->pDriverName);
244  if (!(ppi2w->pDriverName = pwszDriverName)) goto Cleanup;
245  }
246  if (ppi2a->pComment)
247  {
248  pwszComment = AsciiToUnicode(&usBuffer, ppi2a->pComment);
249  if (!(ppi2w->pComment = pwszComment)) goto Cleanup;
250  }
251  if (ppi2a->pLocation)
252  {
253  pwszLocation = AsciiToUnicode(&usBuffer, ppi2a->pLocation);
254  if (!(ppi2w->pLocation = pwszLocation)) goto Cleanup;
255  }
256  if (ppi2a->pSepFile)
257  {
258  pwszSepFile = AsciiToUnicode(&usBuffer, ppi2a->pSepFile);
259  if (!(ppi2w->pSepFile = pwszSepFile)) goto Cleanup;
260  }
261  if (ppi2a->pServerName)
262  {
263  pwszPrintProcessor = AsciiToUnicode(&usBuffer, ppi2a->pPrintProcessor);
264  if (!(ppi2w->pPrintProcessor = pwszPrintProcessor)) goto Cleanup;
265  }
266  if (ppi2a->pDatatype)
267  {
268  pwszDatatype = AsciiToUnicode(&usBuffer, ppi2a->pDatatype);
269  if (!(ppi2w->pDatatype = pwszDatatype)) goto Cleanup;
270  }
271  if (ppi2a->pParameters)
272  {
273  pwszParameters = AsciiToUnicode(&usBuffer, ppi2a->pParameters);
274  if (!(ppi2w->pParameters = pwszParameters)) goto Cleanup;
275  }
276  if ( ppi2a->pDevMode )
277  {
279  ppi2w->pDevMode = pdmw;
280  }
281  if (ppi2a->pServerName)
282  {
283  pwszServerName = AsciiToUnicode(&usBuffer, ppi2a->pServerName);
284  if (!(ppi2w->pPrinterName = pwszServerName)) goto Cleanup;
285  }
286  if (ppi2a->pPrinterName)
287  {
288  pwszPrinterName = AsciiToUnicode(&usBuffer, ppi2a->pPrinterName);
289  if (!(ppi2w->pPrinterName = pwszPrinterName)) goto Cleanup;
290  }
291 
292  ret = AddPrinterW(pwstrNameW, Level, (LPBYTE)ppi2w);
293 
294 Cleanup:
295  if (pdmw) HeapFree(hProcessHeap, 0, pdmw);
296  if (pwszPrinterName) HeapFree(hProcessHeap, 0, pwszPrinterName);
297  if (pwszServerName) HeapFree(hProcessHeap, 0, pwszServerName);
298  if (pwszShareName) HeapFree(hProcessHeap, 0, pwszShareName);
299  if (pwszPortName) HeapFree(hProcessHeap, 0, pwszPortName);
300  if (pwszDriverName) HeapFree(hProcessHeap, 0, pwszDriverName);
301  if (pwszComment) HeapFree(hProcessHeap, 0, pwszComment);
302  if (pwszLocation) HeapFree(hProcessHeap, 0, pwszLocation);
303  if (pwszSepFile) HeapFree(hProcessHeap, 0, pwszSepFile);
304  if (pwszPrintProcessor) HeapFree(hProcessHeap, 0, pwszPrintProcessor);
305  if (pwszDatatype) HeapFree(hProcessHeap, 0, pwszDatatype);
306  if (pwszParameters) HeapFree(hProcessHeap, 0, pwszParameters);
307 
308  RtlFreeUnicodeString(&pNameW);
309  return ret;
310 }
311 
314 {
315  DWORD dwErrorCode;
316  WINSPOOL_PRINTER_CONTAINER PrinterContainer;
317  WINSPOOL_DEVMODE_CONTAINER DevModeContainer;
318  WINSPOOL_SECURITY_CONTAINER SecurityContainer;
320  DWORD size;
321  HANDLE hPrinter = NULL, hHandle = NULL;
322  PSPOOLER_HANDLE pHandle = NULL;
323 
324  TRACE("AddPrinterW(%S, %lu, %p)\n", pName, Level, pPrinter);
325 
326  DevModeContainer.cbBuf = 0;
327  DevModeContainer.pDevMode = NULL;
328 
329  SecurityContainer.cbBuf = 0;
330  SecurityContainer.pSecurity = NULL;
331 
332  if ( Level != 2 )
333  {
334  FIXME( "Unsupported level %d\n", Level );
336  return hHandle;
337  }
338  else
339  {
340  PPRINTER_INFO_2W pi2w = (PPRINTER_INFO_2W)pPrinter;
341  if ( pi2w )
342  {
343  if ( pi2w->pDevMode )
344  {
345  if ( IsValidDevmodeNoSizeW( pi2w->pDevMode ) )
346  {
347  DevModeContainer.cbBuf = pi2w->pDevMode->dmSize + pi2w->pDevMode->dmDriverExtra;
348  DevModeContainer.pDevMode = (PBYTE)pi2w->pDevMode;
349  }
350  }
351 
352  if ( pi2w->pSecurityDescriptor )
353  {
354  sd = get_sd( pi2w->pSecurityDescriptor, &size );
355  if ( sd )
356  {
357  SecurityContainer.cbBuf = size;
358  SecurityContainer.pSecurity = (PBYTE)sd;
359  }
360  }
361  }
362  else
363  {
365  return hHandle;
366  }
367  }
368 
369  PrinterContainer.PrinterInfo.pPrinterInfo1 = (WINSPOOL_PRINTER_INFO_1*)pPrinter;
370  PrinterContainer.Level = Level;
371 
372  // Do the RPC call
374  {
375  dwErrorCode = _RpcAddPrinter( pName, &PrinterContainer, &DevModeContainer, &SecurityContainer, &hPrinter );
376  }
378  {
379  dwErrorCode = RpcExceptionCode();
380  }
381  RpcEndExcept;
382 
383  if (hPrinter)
384  {
385  // Create a new SPOOLER_HANDLE structure.
387  if (!pHandle)
388  {
389  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
390  ERR("HeapAlloc failed!\n");
391  _RpcDeletePrinter(hPrinter);
392  _RpcClosePrinter(hPrinter);
393  goto Cleanup;
394  }
395 
396  pHandle->Sig = SPOOLER_HANDLE_SIG;
397  pHandle->hPrinter = hPrinter;
398  pHandle->hSPLFile = INVALID_HANDLE_VALUE;
400  hHandle = (HANDLE)pHandle;
401  }
402 
403 Cleanup:
404  if ( sd ) HeapFree( GetProcessHeap(), 0, sd );
405 
406  SetLastError(dwErrorCode);
407  return hHandle;
408 }
409 
410 BOOL WINAPI
412 {
413  DWORD dwErrorCode;
414  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
415 
416  TRACE("ClosePrinter(%p)\n", hPrinter);
417 
418  // Sanity checks.
419  if ( IntProtectHandle( hPrinter, TRUE ) )
420  {
421  dwErrorCode = ERROR_INVALID_HANDLE;
422  goto Cleanup;
423  }
424 
425  // Do the RPC call.
427  {
428  dwErrorCode = _RpcClosePrinter(&pHandle->hPrinter);
429  }
431  {
432  dwErrorCode = RpcExceptionCode();
433  ERR("_RpcClosePrinter failed with exception code %lu!\n", dwErrorCode);
434  }
435  RpcEndExcept;
436 
437  // Close any open file handle.
438  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
439  CloseHandle(pHandle->hSPLFile);
440 
441  pHandle->Sig = -1;
442 
443  // Free the memory for the handle.
444  HeapFree(hProcessHeap, 0, pHandle);
445 
446 Cleanup:
447  SetLastError(dwErrorCode);
448  return (dwErrorCode == ERROR_SUCCESS);
449 }
450 
451 BOOL WINAPI
453 {
454  DWORD dwErrorCode;
455  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
456 
457  TRACE("DeletePrinter(%p)\n", hPrinter);
458 
459  // Sanity checks.
460  if (!pHandle)
461  {
462  dwErrorCode = ERROR_INVALID_HANDLE;
463  goto Cleanup;
464  }
465 
466  // Do the RPC call.
468  {
469  dwErrorCode = _RpcDeletePrinter(&pHandle->hPrinter);
470  }
472  {
473  dwErrorCode = RpcExceptionCode();
474  ERR("_RpcDeletePrinter failed with exception code %lu!\n", dwErrorCode);
475  }
476  RpcEndExcept;
477 
478 Cleanup:
479  SetLastError(dwErrorCode);
480  return (dwErrorCode == ERROR_SUCCESS);
481 }
482 
483 //
484 // Based on GDI32:printdrv.c:IntGetPrinterDriver.
485 //
486 HMODULE
487 WINAPI
489 {
490  INT iTries = 0;
491  DWORD Size = (sizeof(WCHAR) * MAX_PATH) * 2; // DRIVER_INFO_5W + plus strings.
494 
495  do
496  {
497  ++iTries;
498 
500 
501  if ( !pdi )
502  break;
503 
504  if ( GetPrinterDriverW(hspool, NULL, 5, (LPBYTE)pdi, Size, &Size) )
505  {
506  TRACE("Level 5 Size %d\n",Size);
507 
508  // Name and load configure library (for example, C:\DRIVERS\Pscrptui.dll). Not printui.dll!
509 
510  hLibrary = LoadLibrary(pdi->pConfigFile);
511 
512  FIXME("IGPD : Get Printer Driver Config File : %S\n",pdi->pConfigFile);
513 
515  return hLibrary;
516  }
517 
519  ++iTries;
520 
522  }
523  while ( iTries < 2 );
524  ERR("No Printer Driver Error %d\n",GetLastError());
525  return NULL;
526 }
527 
529 DeviceCapabilitiesA(LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA* pDevMode)
530 {
532  PDEVMODEW pdmwInput = NULL;
533  BOOL bReturnValue = GDI_ERROR;
534  DWORD cch;
535 
536  FIXME("DeviceCapabilitiesA(%s, %s, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode);
537 
538  if (pDevice)
539  {
540  // Convert pName to a Unicode string pwszDeviceName.
541  cch = strlen(pDevice);
542 
543  pwszDeviceName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
544  if (!pwszDeviceName)
545  {
547  ERR("HeapAlloc failed!\n");
548  goto Cleanup;
549  }
550 
552  }
553 
554  if (pDevMode)
555  {
556  RosConvertAnsiDevModeToUnicodeDevmode((PDEVMODEA)pDevMode, &pdmwInput);
557  }
558 
559  // pPort is ignored so no need to pass it.
560  bReturnValue = DeviceCapabilitiesW( pwszDeviceName, NULL, fwCapability, (LPWSTR)pOutput, (const DEVMODEW*) pdmwInput );
561 
562 Cleanup:
563  if(pwszDeviceName)
565 
566  if (pdmwInput)
567  HeapFree(hProcessHeap, 0, pdmwInput);
568 
569  return bReturnValue;
570 }
571 
573 DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, WORD fwCapability, LPWSTR pOutput, const DEVMODEW* pDevMode)
574 {
575  HANDLE hPrinter;
577  DWORD iDevCap = GDI_ERROR;
578 
579  FIXME("DeviceCapabilitiesW(%S, %S, %hu, %p, %p)\n", pDevice, pPort, fwCapability, pOutput, pDevMode);
580 
581  if ( pDevMode )
582  {
583  if (!IsValidDevmodeNoSizeW( (PDEVMODEW)pDevMode ) )
584  {
585  ERR("DeviceCapabilitiesW : Devode Invalid\n");
586  return -1;
587  }
588  }
589 
590  if ( OpenPrinterW( (LPWSTR)pDevice, &hPrinter, NULL ) )
591  {
592  hLibrary = LoadPrinterDriver( hPrinter );
593 
594  if ( hLibrary )
595  {
596  fpDeviceCapabilities = (PVOID)GetProcAddress( hLibrary, "DrvDeviceCapabilities" );
597 
598  if ( fpDeviceCapabilities )
599  {
600  iDevCap = fpDeviceCapabilities( hPrinter, (PWSTR)pDevice, fwCapability, pOutput, (PDEVMODE)pDevMode );
601  }
602 
604  }
605 
606  ClosePrinter( hPrinter );
607  }
608 
609  return iDevCap;
610 }
611 
612 BOOL
613 WINAPI
614 DevQueryPrint( HANDLE hPrinter, LPDEVMODEW pDevMode, DWORD *pResID)
615 {
617  BOOL Ret = FALSE;
618 
619  hLibrary = LoadPrinterDriver( hPrinter );
620 
621  if ( hLibrary )
622  {
623  fpDevQueryPrint = (PVOID)GetProcAddress( hLibrary, "DevQueryPrint" );
624 
625  if ( fpDevQueryPrint )
626  {
627  Ret = fpDevQueryPrint( hPrinter, pDevMode, pResID );
628  }
629 
631  }
632  return Ret;
633 }
634 
635 BOOL WINAPI
637 {
639  BOOL Ret = FALSE;
640 
641  hLibrary = LoadPrinterDriver( pDQPInfo->hPrinter );
642 
643  if ( hLibrary )
644  {
645  fpDevQueryPrintEx = (PVOID)GetProcAddress( hLibrary, "DevQueryPrintEx" );
646 
647  if ( fpDevQueryPrintEx )
648  {
649  Ret = fpDevQueryPrintEx( pDQPInfo );
650  }
651 
653  }
654  return Ret;
655 }
656 
657 INT WINAPI
658 DocumentEvent( HANDLE hPrinter, HDC hdc, int iEsc, ULONG cbIn, PVOID pvIn, ULONG cbOut, PVOID pvOut)
659 {
660  FIXME("DocumentEvent(%p, %p, %lu, %lu, %p, %lu, %p)\n", hPrinter, hdc, iEsc, cbIn, pvIn, cbOut, pvOut);
663 }
664 
665 LONG WINAPI
666 DocumentPropertiesA(HWND hWnd, HANDLE hPrinter, LPSTR pDeviceName, PDEVMODEA pDevModeOutput, PDEVMODEA pDevModeInput, DWORD fMode)
667 {
669  PDEVMODEW pdmwInput = NULL;
670  PDEVMODEW pdmwOutput = NULL;
671  LONG lReturnValue = -1;
672  DWORD cch;
673 
674  FIXME("DocumentPropertiesA(%p, %p, %s, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
675 
676  if (pDeviceName)
677  {
678  // Convert pName to a Unicode string pwszDeviceName.
679  cch = strlen(pDeviceName);
680 
681  pwszDeviceName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
682  if (!pwszDeviceName)
683  {
685  ERR("HeapAlloc failed!\n");
686  goto Cleanup;
687  }
688 
689  MultiByteToWideChar(CP_ACP, 0, pDeviceName, -1, pwszDeviceName, cch + 1);
690  }
691 
692  if (pDevModeInput)
693  {
694  // Create working buffer for input to DocumentPropertiesW.
695  RosConvertAnsiDevModeToUnicodeDevmode(pDevModeInput, &pdmwInput);
696  }
697 
698  if (pDevModeOutput)
699  {
700  // Create working buffer for output from DocumentPropertiesW.
701 
702  // Do it RIGHT! Get the F...ing Size!
704 
705  if ( Size < 0 )
706  {
707  goto Cleanup;
708  }
709 
710  pdmwOutput = HeapAlloc(hProcessHeap, 0, Size);
711  if (!pdmwOutput)
712  {
714  ERR("HeapAlloc failed!\n");
715  goto Cleanup;
716  }
717  }
718 
719  lReturnValue = DocumentPropertiesW(hWnd, hPrinter, pwszDeviceName, pdmwOutput, pdmwInput, fMode);
720  FIXME("lReturnValue from DocumentPropertiesW is '%ld'.\n", lReturnValue);
721 
722  if (lReturnValue < 0)
723  {
724  FIXME("DocumentPropertiesW failed!\n");
725  goto Cleanup;
726  }
727 
728  if (pdmwOutput)
729  {
730  RosConvertUnicodeDevModeToAnsiDevmode(pdmwOutput, pDevModeOutput);
731  }
732 
733 Cleanup:
734  if(pwszDeviceName)
736 
737  if (pdmwInput)
738  HeapFree(hProcessHeap, 0, pdmwInput);
739 
740  if (pdmwOutput)
741  HeapFree(hProcessHeap, 0, pdmwOutput);
742 
743  return lReturnValue;
744 }
745 
747 {
748  PRINTER_INFO_9W *pi9 = NULL;
749  DWORD needed = 0;
750  BOOL res;
751 
752  res = GetPrinterW(hprn, 9, NULL, 0, &needed);
754  {
755  pi9 = HeapAlloc(hProcessHeap, 0, needed);
756  res = GetPrinterW(hprn, 9, (LPBYTE)pi9, needed, &needed);
757  }
758 
759  if (res)
760  return pi9;
761 
762  ERR("GetPrinterW failed with %u\n", GetLastError());
763  HeapFree(hProcessHeap, 0, pi9);
764  return NULL;
765 }
766 
767 BOOL
768 FASTCALL
769 CreateUIUserData( ULONG_PTR *puserdata, HANDLE hPrinter )
770 {
771  PCOMPUI_USERDATA pcui_ud = DllAllocSplMem( sizeof(COMPUI_USERDATA) );
772 
773  *puserdata = (ULONG_PTR)pcui_ud;
774  FIXME("CreateUIUserData\n");
775  if ( pcui_ud )
776  {
777  pcui_ud->hModule = LoadPrinterDriver( hPrinter );
778 
779  if ( !pcui_ud->hModule )
780  {
781  DllFreeSplMem( pcui_ud );
782  *puserdata = 0;
783  }
784  }
785  return *puserdata != 0;
786 }
787 
788 VOID
789 FASTCALL
791 {
792  PCOMPUI_USERDATA pcui_ud = (PCOMPUI_USERDATA)*puserdata;
793  FIXME("DestroyUIUserData\n");
794  if ( pcui_ud )
795  {
796  if ( pcui_ud->hModule )
797  {
798  FreeLibrary( pcui_ud->hModule );
799  pcui_ud->hModule = NULL;
800  }
801 
802  if ( pcui_ud->pszPrinterName )
803  {
804  DllFreeSplMem( pcui_ud->pszPrinterName );
805  pcui_ud->pszPrinterName = NULL;
806  }
807 
808  DllFreeSplMem( pcui_ud );
809  *puserdata = 0;
810  }
811 }
812 
813 BOOL
814 FASTCALL
816 {
817  PRINTER_INFO_2W *pi2 = NULL;
818  DWORD needed = 0;
819  BOOL res;
820 
821  if (!(pdphdr->fMode & DM_OUT_BUFFER) ||
822  pdphdr->fMode & DM_NOPERMISSION || // Do not allow the user to modify properties on the displayed property sheet pages.
823  !pdphdr->pdmOut )
824  {
825  return FALSE;
826  }
827 
828  res = GetPrinterW( pdphdr->hPrinter, 2, NULL, 0, &needed);
830  {
831  pi2 = HeapAlloc(hProcessHeap, 0, needed);
832  res = GetPrinterW( pdphdr->hPrinter, 2, (LPBYTE)pi2, needed, &needed);
833  }
834 
835  if (res)
836  {
837  FIXME("IFUDMN : Get Printer Name %S\n",pi2->pPrinterName);
839  pdphdr->pdmOut->dmDeviceName[CCHDEVICENAME-1] = 0;
840  }
841  else
842  {
843  ERR("IFUDMN : GetPrinterW failed with %u\n", GetLastError());
844  }
845  HeapFree(hProcessHeap, 0, pi2);
846  return res;
847 }
848 
849 LONG
850 WINAPI
852 {
853  LONG Result = 0;
854  DWORD Size = 0;
856 
857  hLibrary = LoadLibraryA( "printui.dll" );
858 
859  if ( hLibrary )
860  {
861  fpConstructPrinterFriendlyName = (PVOID)GetProcAddress( hLibrary, "ConstructPrinterFriendlyName" );
862 
864  {
865  if ( !fpConstructPrinterFriendlyName( pszPrinterName, NULL, &Size ) )
866  {
868  {
869  PWSTR pwstr = DllAllocSplMem( (Size + 1) * sizeof(WCHAR) );
870 
871  pcui_ud->pszPrinterName = pwstr;
872 
873  if ( pwstr )
874  Result = fpConstructPrinterFriendlyName( pszPrinterName, pwstr, &Size );
875  }
876  }
877  }
879  }
880 
881  if ( !Result )
882  {
883  DllFreeSplMem( pcui_ud->pszPrinterName );
884  pcui_ud->pszPrinterName = AllocSplStr( pszPrinterName );
885  }
886 
887  return Result;
888 }
889 
890 //
891 // Tested with XP CompstUI as a callback and works. Fails perfectly.
892 //
893 LONG
894 WINAPI
896 {
897  LONG Result = -1;
899 
900  FIXME("DocumentPropertySheets(%p, 0x%lx)\n", pCPSUIInfo, lparam);
901 
902  // If pPSUIInfo is NULL, and if either lParam -> fMode is zero or lParam -> pdmOut is NULL,
903  // this function should return the size, in bytes, of the printer's DEVMODEW structure.
904  if ( !pCPSUIInfo && lparam )
905  {
907 
908  if ( pdphdr->cbSize >= sizeof(PDOCUMENTPROPERTYHEADER) &&
909  !(pdphdr->fMode & DM_PROMPT) )
910  {
912 
913  if ( hLibrary )
914  {
915  fpDocumentPropertySheets = (PVOID)GetProcAddress( hLibrary, "DrvDocumentPropertySheets" );
916 
918  {
919  FIXME("DPS : fpDocumentPropertySheets(%p, 0x%lx) pdmOut %p\n", pCPSUIInfo, lparam, pdphdr->pdmOut);
920  Result = fpDocumentPropertySheets( pCPSUIInfo, lparam );
921  FIXME("DPS : fpDocumentPropertySheets result %d cbOut %d\n",Result, pdphdr->cbOut);
922  }
923  else
924  {
925  //
926  // ReactOS backup!!! Currently no supporting UI driver.
927  //
928  PRINTER_INFO_9W * pi9 = get_devmodeW( pdphdr->hPrinter );
929  if ( pi9 )
930  {
931  Result = pi9->pDevMode->dmSize + pi9->pDevMode->dmDriverExtra;
932  FIXME("IDPS : Using ReactOS backup!!! DevMode Size %d\n",Result);
933  HeapFree(hProcessHeap, 0, pi9);
934  }
935  }
936 
938 
939  if ( Result > 0 )
940  {
941  IntFixUpDevModeNames( pdphdr );
942  }
943 
944  return Result;
945  }
946  else
947  {
949  }
950  }
951  else
952  {
954  }
955  return Result;
956  }
957 
958  Result = 0;
959 
960  if ( pCPSUIInfo )
961  {
962  PSETRESULT_INFO psri;
963  PPROPSHEETUI_INFO_HEADER ppsuiihdr;
964  PCOMPUI_USERDATA pcui_ud;
965  pdphdr = (PDOCUMENTPROPERTYHEADER)pCPSUIInfo->lParamInit;
966 
967  if ( pdphdr->cbSize < sizeof(PDOCUMENTPROPERTYHEADER) )
968  {
970  return Result;
971  }
972 
973  switch ( pCPSUIInfo->Reason )
974  {
976  {
977  FIXME("DocPS : PROPSHEETUI_REASON_INIT\n");
978  if ( CreateUIUserData( &pCPSUIInfo->UserData, pdphdr->hPrinter ) )
979  {
980  pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData;
981 
982  fpDocumentPropertySheets = (PVOID)GetProcAddress( pcui_ud->hModule, "DrvDocumentPropertySheets" );
983 
985  {
986  pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
988  -3, // What type of handle is this?
989  0 ); // Not used, must be zero.
990 
991  Result = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
994  pCPSUIInfo->lParamInit );
995  break;
996  }
997  FIXME("DocPS : PROPSHEETUI_REASON_INIT Fail\n");
998  DestroyUIUserData( &pCPSUIInfo->UserData );
999  }
1000  }
1001  break;
1002 
1004  FIXME("DocPS : PROPSHEETUI_REASON_GET_INFO_HEADER\n");
1005 
1006  ppsuiihdr = (PPROPSHEETUI_INFO_HEADER)lparam;
1007 
1008  pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData;
1009 
1010  CreatePrinterFriendlyName( pcui_ud, pdphdr->pszPrinterName );
1011 
1013  ppsuiihdr->pTitle = pcui_ud->pszPrinterName;
1014  ppsuiihdr->hInst = hinstWinSpool;
1015  ppsuiihdr->IconID = IDI_CPSUI_DOCUMENT;
1016 
1017  Result = CPSUI_OK;
1018  break;
1019 
1021  FIXME("DocPS : PROPSHEETUI_REASON_DESTROY\n");
1022  DestroyUIUserData( &pCPSUIInfo->UserData );
1023  Result = CPSUI_OK;
1024  break;
1025 
1027  FIXME("DocPS : PROPSHEETUI_REASON_SET_RESULT\n");
1028 
1029  psri = (PSETRESULT_INFO)lparam;
1030 
1031  pCPSUIInfo->Result = psri->Result;
1032  if ( pCPSUIInfo->Result > 0 )
1033  {
1034  IntFixUpDevModeNames( pdphdr );
1035  }
1036  Result = CPSUI_OK;
1037  break;
1038  }
1039  }
1040  return Result;
1041 }
1042 
1043 LONG
1044 WINAPI
1046 {
1047  LONG Result = 0;
1048  PDEVICEPROPERTYHEADER pdphdr;
1049 
1050  FIXME("DevicePropertySheets(%p, 0x%lx)\n", pCPSUIInfo, lparam);
1051 
1052  if ( pCPSUIInfo )
1053  {
1054  PSETRESULT_INFO psri;
1055  PPROPSHEETUI_INFO_HEADER ppsuiihdr;
1056  PCOMPUI_USERDATA pcui_ud;
1057  pdphdr = (PDEVICEPROPERTYHEADER)pCPSUIInfo->lParamInit;
1058 
1059  if ( pdphdr->cbSize < sizeof(DEVICEPROPERTYHEADER) )
1060  {
1062  return Result;
1063  }
1064 
1065  switch ( pCPSUIInfo->Reason )
1066  {
1068  {
1069  FIXME("DevPS : PROPSHEETUI_REASON_INIT\n");
1070  if ( CreateUIUserData( &pCPSUIInfo->UserData, pdphdr->hPrinter ) )
1071  {
1072  pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData;
1073 
1074  fpDevicePropertySheets = (PVOID)GetProcAddress( pcui_ud->hModule, "DrvDevicePropertySheets" );
1075 
1076  if ( fpDevicePropertySheets )
1077  {
1078  pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
1080  -3, // What type of handle is this?
1081  0 ); // Not used, must be zero.
1082 
1083  Result = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
1086  pCPSUIInfo->lParamInit );
1087  break;
1088  }
1089  FIXME("DevPS : PROPSHEETUI_REASON_INIT Fail\n");
1090  DestroyUIUserData( &pCPSUIInfo->UserData );
1091  }
1092  }
1093  break;
1094 
1096  FIXME("DevPS : PROPSHEETUI_REASON_GET_INFO_HEADER\n");
1097 
1098  ppsuiihdr = (PPROPSHEETUI_INFO_HEADER)lparam;
1099 
1100  pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData;
1101 
1102  CreatePrinterFriendlyName( pcui_ud, pdphdr->pszPrinterName );
1103 
1105  ppsuiihdr->pTitle = pcui_ud->pszPrinterName;
1106  ppsuiihdr->hInst = hinstWinSpool;
1107  ppsuiihdr->IconID = IDI_CPSUI_DOCUMENT;
1108 
1109  Result = CPSUI_OK;
1110  break;
1111 
1113  FIXME("DevPS : PROPSHEETUI_REASON_DESTROY\n");
1114  DestroyUIUserData( &pCPSUIInfo->UserData );
1115  Result = CPSUI_OK;
1116  break;
1117 
1119  FIXME("DevPS : PROPSHEETUI_REASON_SET_RESULT\n");
1120  psri = (PSETRESULT_INFO)lparam;
1121  pCPSUIInfo->Result = psri->Result;
1122  Result = CPSUI_OK;
1123  break;
1124  }
1125  }
1126  return Result;
1127 }
1128 
1129 LONG
1130 WINAPI
1132 {
1133  HMODULE hLibrary = NULL;
1135 
1136  FIXME("CallCommonPropertySheetUI(%p, %p, 0x%lx, %p)\n", hWnd, pfnPropSheetUI, lparam, pResult);
1137 
1138  if ( ( hLibrary = LoadLibraryA( "compstui.dll" ) ) )
1139  {
1140  fpCommonPropertySheetUIW = (PVOID) GetProcAddress(hLibrary, "CommonPropertySheetUIW");
1141 
1143  {
1144  Ret = fpCommonPropertySheetUIW( hWnd, pfnPropSheetUI, lparam, pResult );
1145  }
1146 
1148  }
1149  return Ret;
1150 }
1151 
1152 LONG WINAPI
1153 DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode)
1154 {
1155  HANDLE hUseHandle = NULL;
1156  DOCUMENTPROPERTYHEADER docprophdr;
1157  LONG Result = IDOK;
1158 
1159  FIXME("DocumentPropertiesW(%p, %p, %S, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
1160 
1161  if (hPrinter)
1162  {
1163  hUseHandle = hPrinter;
1164  }
1165  else if (!OpenPrinterW(pDeviceName, &hUseHandle, NULL))
1166  {
1167  ERR("No handle, and no usable printer name passed in\n");
1168  return -1;
1169  }
1170 
1171  if ( !(fMode & DM_IN_BUFFER ) ||
1172  ( ( pDevModeInput && !IsValidDevmodeNoSizeW( (PDEVMODEW)pDevModeInput ) ) ) )
1173  {
1174  pDevModeInput = NULL;
1175  fMode &= ~DM_IN_BUFFER;
1176  }
1177 
1178  docprophdr.cbSize = sizeof(DOCUMENTPROPERTYHEADER);
1179  docprophdr.Reserved = 0;
1180  docprophdr.hPrinter = hUseHandle;
1181  docprophdr.pszPrinterName = pDeviceName;
1182  docprophdr.cbOut = 0;
1183 
1184  if ( pDevModeOutput )
1185  {
1186  docprophdr.pdmIn = NULL;
1187  docprophdr.pdmOut = NULL;
1188  docprophdr.fMode = 0;
1189  FIXME("DPW : Call DocumentPropertySheets with pDevModeOutput %p\n",pDevModeOutput);
1190  docprophdr.cbOut = DocumentPropertySheets( NULL, (LPARAM)&docprophdr );
1191  }
1192 
1193  docprophdr.pdmIn = pDevModeInput;
1194  docprophdr.pdmOut = pDevModeOutput;
1195  docprophdr.fMode = fMode;
1196 
1197  if ( fMode & DM_IN_PROMPT )
1198  {
1199  Result = CPSUI_CANCEL;
1200 
1201  //
1202  // Now call the Property Sheet for Print > Properties.
1203  //
1205  {
1206  FIXME("CallCommonPropertySheetUI return error\n");
1208  }
1209  else
1210  Result = (Result == CPSUI_OK) ? IDOK : IDCANCEL;
1211  FIXME("CallCommonPropertySheetUI returned\n");
1212  }
1213  else
1214  {
1215  FIXME("DPW : CallDocumentPropertySheets\n");
1216  Result = DocumentPropertySheets( NULL, (LPARAM)&docprophdr );
1217  }
1218 
1220  {
1221  if ( pDevModeOutput )
1222  {
1223  if ( !IsValidDevmodeNoSizeW( pDevModeOutput ) )
1224  {
1225  ERR("DPW : Improper pDevModeOutput size.\n");
1226  Result = -1;
1227  }
1228  }
1229  else
1230  {
1231  ERR("No pDevModeOutput\n");
1232  }
1233  }
1234 
1235  if (hUseHandle && !hPrinter)
1236  ClosePrinter(hUseHandle);
1237  return Result;
1238 }
1239 
1240 BOOL
1241 WINAPI
1243 {
1244  PRINTER_INFO_2W *pi2 = NULL;
1245  DWORD needed = 0;
1246  LONG Ret, Result = 0;
1247  BOOL res;
1248  DEVICEPROPERTYHEADER devprophdr;
1249 
1250  FIXME("PrinterProperties(%p, %p)\n", hWnd, hPrinter);
1251 
1252  devprophdr.cbSize = sizeof(DEVICEPROPERTYHEADER);
1253  devprophdr.Flags = DPS_NOPERMISSION;
1254  devprophdr.hPrinter = hPrinter;
1255  devprophdr.pszPrinterName = NULL;
1256 
1257  res = GetPrinterW( hPrinter, 2, NULL, 0, &needed);
1259  {
1260  pi2 = HeapAlloc(hProcessHeap, 0, needed);
1261  res = GetPrinterW(hPrinter, 2, (LPBYTE)pi2, needed, &needed);
1262  }
1263 
1264  //
1265  // Above can fail, still process w/o printer name.
1266  //
1267  if ( res ) devprophdr.pszPrinterName = pi2->pPrinterName;
1268 
1269  needed = 1;
1270 
1271  if ( ( SetPrinterDataW( hPrinter, L"PrinterPropertiesPermission", REG_DWORD, (LPBYTE)&needed, sizeof(DWORD) ) == ERROR_SUCCESS ) )
1272  {
1273  devprophdr.Flags &= ~DPS_NOPERMISSION;
1274  }
1275 
1277 
1278  res = (Ret >= 0);
1279 
1280  if (!res)
1281  {
1282  FIXME("PrinterProperties fail ICPSUI\n");
1283  }
1284 
1285  if (pi2) HeapFree(hProcessHeap, 0, pi2);
1286 
1287  return res;
1288 }
1289 
1290 BOOL WINAPI
1292 {
1293  DWORD dwErrorCode;
1294  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
1295 
1296  TRACE("EndDocPrinter(%p)\n", hPrinter);
1297 
1298  // Sanity checks.
1299  if (!pHandle)
1300  {
1301  dwErrorCode = ERROR_INVALID_HANDLE;
1302  goto Cleanup;
1303  }
1304 
1305  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
1306  {
1307  // For spooled jobs, the document is finished by calling _RpcScheduleJob.
1308  RpcTryExcept
1309  {
1310  dwErrorCode = _RpcScheduleJob(pHandle->hPrinter, pHandle->dwJobID);
1311  }
1313  {
1314  dwErrorCode = RpcExceptionCode();
1315  ERR("_RpcScheduleJob failed with exception code %lu!\n", dwErrorCode);
1316  }
1317  RpcEndExcept;
1318 
1319  // Close the spool file handle.
1320  CloseHandle(pHandle->hSPLFile);
1321  }
1322  else
1323  {
1324  // In all other cases, just call _RpcEndDocPrinter.
1325  RpcTryExcept
1326  {
1327  dwErrorCode = _RpcEndDocPrinter(pHandle->hPrinter);
1328  }
1330  {
1331  dwErrorCode = RpcExceptionCode();
1332  ERR("_RpcEndDocPrinter failed with exception code %lu!\n", dwErrorCode);
1333  }
1334  RpcEndExcept;
1335  }
1336 
1337  // A new document can now be started again.
1338  pHandle->bTrayIcon = pHandle->bJob = pHandle->bStartedDoc = FALSE;
1339 
1340 Cleanup:
1341  SetLastError(dwErrorCode);
1342  return (dwErrorCode == ERROR_SUCCESS);
1343 }
1344 
1345 BOOL WINAPI
1347 {
1348  DWORD dwErrorCode;
1349  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
1350 
1351  TRACE("EndPagePrinter(%p)\n", hPrinter);
1352 
1353  // Sanity checks.
1354  if (!pHandle)
1355  {
1356  dwErrorCode = ERROR_INVALID_HANDLE;
1357  goto Cleanup;
1358  }
1359 
1360  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
1361  {
1362  // For spooled jobs, we don't need to do anything.
1363  dwErrorCode = ERROR_SUCCESS;
1364  }
1365  else
1366  {
1367  // In all other cases, just call _RpcEndPagePrinter.
1368  RpcTryExcept
1369  {
1370  dwErrorCode = _RpcEndPagePrinter(pHandle->hPrinter);
1371  }
1373  {
1374  dwErrorCode = RpcExceptionCode();
1375  ERR("_RpcEndPagePrinter failed with exception code %lu!\n", dwErrorCode);
1376  }
1377  RpcEndExcept;
1378  }
1379 
1380 Cleanup:
1381  SetLastError(dwErrorCode);
1382  return (dwErrorCode == ERROR_SUCCESS);
1383 }
1384 
1385 BOOL WINAPI
1387 {
1388  DWORD dwErrorCode;
1389  DWORD cch;
1390  PWSTR pwszName = NULL;
1391  PSTR pszPrinterName = NULL;
1392  PSTR pszServerName = NULL;
1393  PSTR pszDescription = NULL;
1394  PSTR pszName = NULL;
1395  PSTR pszComment = NULL;
1396  PSTR pszShareName = NULL;
1397  PSTR pszPortName = NULL;
1398  PSTR pszDriverName = NULL;
1399  PSTR pszLocation = NULL;
1400  PSTR pszSepFile = NULL;
1401  PSTR pszPrintProcessor = NULL;
1402  PSTR pszDatatype = NULL;
1403  PSTR pszParameters = NULL;
1404  DWORD i;
1405  PPRINTER_INFO_1W ppi1w = NULL;
1406  PPRINTER_INFO_1A ppi1a = NULL;
1407  PPRINTER_INFO_2W ppi2w = NULL;
1408  PPRINTER_INFO_2A ppi2a = NULL;
1409  PPRINTER_INFO_4W ppi4w = NULL;
1410  PPRINTER_INFO_4A ppi4a = NULL;
1411  PPRINTER_INFO_5W ppi5w = NULL;
1412  PPRINTER_INFO_5A ppi5a = NULL;
1413 
1414  TRACE("EnumPrintersA(%lu, %s, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
1415 
1416  // Check for invalid levels here for early error return. MSDN says that only 1, 2, 4, and 5 are allowable.
1417  if (Level != 1 && Level != 2 && Level != 4 && Level != 5)
1418  {
1419  dwErrorCode = ERROR_INVALID_LEVEL;
1420  ERR("Invalid Level!\n");
1421  goto Cleanup;
1422  }
1423 
1424  if (Name)
1425  {
1426  // Convert pName to a Unicode string pwszName.
1427  cch = strlen(Name);
1428 
1429  pwszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
1430  if (!pwszName)
1431  {
1432  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1433  ERR("HeapAlloc failed!\n");
1434  goto Cleanup;
1435  }
1436 
1437  MultiByteToWideChar(CP_ACP, 0, Name, -1, pwszName, cch + 1);
1438  }
1439 
1440  /* Ref: https://stackoverflow.com/questions/41147180/why-enumprintersa-and-enumprintersw-request-the-same-amount-of-memory */
1441  if (!EnumPrintersW(Flags, pwszName, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned))
1442  {
1443  dwErrorCode = GetLastError();
1444  goto Cleanup;
1445  }
1446 
1447  /* We are mapping multiple different pointers to the same pPrinterEnum pointer here so that */
1448  /* we can do in-place conversion. We read the Unicode response from the EnumPrintersW and */
1449  /* then we write back the ANSI conversion into the same buffer for our EnumPrintersA output */
1450 
1451  /* mapping to pPrinterEnum for Unicode (w) characters for Levels 1, 2, 4, and 5 */
1452  ppi1w = (PPRINTER_INFO_1W)pPrinterEnum;
1453  ppi2w = (PPRINTER_INFO_2W)pPrinterEnum;
1454  ppi4w = (PPRINTER_INFO_4W)pPrinterEnum;
1455  ppi5w = (PPRINTER_INFO_5W)pPrinterEnum;
1456  /* mapping to pPrinterEnum for ANSI (a) characters for Levels 1, 2, 4, and 5 */
1457  ppi1a = (PPRINTER_INFO_1A)pPrinterEnum;
1458  ppi2a = (PPRINTER_INFO_2A)pPrinterEnum;
1459  ppi4a = (PPRINTER_INFO_4A)pPrinterEnum;
1460  ppi5a = (PPRINTER_INFO_5A)pPrinterEnum;
1461 
1462  for (i = 0; i < *pcReturned; i++)
1463  {
1464  switch (Level)
1465  {
1466  case 1:
1467  {
1468  if (ppi1w[i].pDescription)
1469  {
1470  // Convert Unicode pDescription to a ANSI string pszDescription.
1471  cch = wcslen(ppi1w[i].pDescription);
1472 
1473  pszDescription = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1474  if (!pszDescription)
1475  {
1476  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1477  ERR("HeapAlloc failed!\n");
1478  goto Cleanup;
1479  }
1480 
1481  WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pDescription, -1, pszDescription, cch + 1, NULL, NULL);
1482  StringCchCopyA(ppi1a[i].pDescription, cch + 1, pszDescription);
1483 
1484  HeapFree(hProcessHeap, 0, pszDescription);
1485  }
1486 
1487  if (ppi1w[i].pName)
1488  {
1489  // Convert Unicode pName to a ANSI string pszName.
1490  cch = wcslen(ppi1w[i].pName);
1491 
1492  pszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1493  if (!pszName)
1494  {
1495  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1496  ERR("HeapAlloc failed!\n");
1497  goto Cleanup;
1498  }
1499 
1500  WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pName, -1, pszName, cch + 1, NULL, NULL);
1501  StringCchCopyA(ppi1a[i].pName, cch + 1, pszName);
1502 
1503  HeapFree(hProcessHeap, 0, pszName);
1504  }
1505 
1506  if (ppi1w[i].pComment)
1507  {
1508  // Convert Unicode pComment to a ANSI string pszComment.
1509  cch = wcslen(ppi1w[i].pComment);
1510 
1511  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1512  if (!pszComment)
1513  {
1514  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1515  ERR("HeapAlloc failed!\n");
1516  goto Cleanup;
1517  }
1518 
1519  WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pComment, -1, pszComment, cch + 1, NULL, NULL);
1520  StringCchCopyA(ppi1a[i].pComment, cch + 1, pszComment);
1521 
1522  HeapFree(hProcessHeap, 0, pszComment);
1523  }
1524  break;
1525  }
1526 
1527 
1528  case 2:
1529  {
1530  if (ppi2w[i].pServerName)
1531  {
1532  // Convert Unicode pServerName to a ANSI string pszServerName.
1533  cch = wcslen(ppi2w[i].pServerName);
1534 
1535  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1536  if (!pszServerName)
1537  {
1538  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1539  ERR("HeapAlloc failed!\n");
1540  goto Cleanup;
1541  }
1542 
1543  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pServerName, -1, pszServerName, cch + 1, NULL, NULL);
1544  StringCchCopyA(ppi2a[i].pServerName, cch + 1, pszServerName);
1545 
1546  HeapFree(hProcessHeap, 0, pszServerName);
1547  }
1548 
1549  if (ppi2w[i].pPrinterName)
1550  {
1551  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
1552  cch = wcslen(ppi2w[i].pPrinterName);
1553 
1554  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1555  if (!pszPrinterName)
1556  {
1557  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1558  ERR("HeapAlloc failed!\n");
1559  goto Cleanup;
1560  }
1561 
1562  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
1563  StringCchCopyA(ppi2a[i].pPrinterName, cch + 1, pszPrinterName);
1564 
1565  HeapFree(hProcessHeap, 0, pszPrinterName);
1566  }
1567 
1568  if (ppi2w[i].pShareName)
1569  {
1570  // Convert Unicode pShareName to a ANSI string pszShareName.
1571  cch = wcslen(ppi2w[i].pShareName);
1572 
1573  pszShareName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1574  if (!pszShareName)
1575  {
1576  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1577  ERR("HeapAlloc failed!\n");
1578  goto Cleanup;
1579  }
1580 
1581  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pShareName, -1, pszShareName, cch + 1, NULL, NULL);
1582  StringCchCopyA(ppi2a[i].pShareName, cch + 1, pszShareName);
1583 
1584  HeapFree(hProcessHeap, 0, pszShareName);
1585  }
1586 
1587  if (ppi2w[i].pPortName)
1588  {
1589  // Convert Unicode pPortName to a ANSI string pszPortName.
1590  cch = wcslen(ppi2w[i].pPortName);
1591 
1592  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1593  if (!pszPortName)
1594  {
1595  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1596  ERR("HeapAlloc failed!\n");
1597  goto Cleanup;
1598  }
1599 
1600  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPortName, -1, pszPortName, cch + 1, NULL, NULL);
1601  StringCchCopyA(ppi2a[i].pPortName, cch + 1, pszPortName);
1602 
1603  HeapFree(hProcessHeap, 0, pszPortName);
1604  }
1605 
1606  if (ppi2w[i].pDriverName)
1607  {
1608  // Convert Unicode pDriverName to a ANSI string pszDriverName.
1609  cch = wcslen(ppi2w[i].pDriverName);
1610 
1611  pszDriverName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1612  if (!pszDriverName)
1613  {
1614  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1615  ERR("HeapAlloc failed!\n");
1616  goto Cleanup;
1617  }
1618 
1619  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pDriverName, -1, pszDriverName, cch + 1, NULL, NULL);
1620  StringCchCopyA(ppi2a[i].pDriverName, cch + 1, pszDriverName);
1621 
1622  HeapFree(hProcessHeap, 0, pszDriverName);
1623  }
1624 
1625  if (ppi2w[i].pComment)
1626  {
1627  // Convert Unicode pComment to a ANSI string pszComment.
1628  cch = wcslen(ppi2w[i].pComment);
1629 
1630  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1631  if (!pszComment)
1632  {
1633  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1634  ERR("HeapAlloc failed!\n");
1635  goto Cleanup;
1636  }
1637 
1638  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pComment, -1, pszComment, cch + 1, NULL, NULL);
1639  StringCchCopyA(ppi2a[i].pComment, cch + 1, pszComment);
1640 
1641  HeapFree(hProcessHeap, 0, pszComment);
1642  }
1643 
1644  if (ppi2w[i].pLocation)
1645  {
1646  // Convert Unicode pLocation to a ANSI string pszLocation.
1647  cch = wcslen(ppi2w[i].pLocation);
1648 
1649  pszLocation = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1650  if (!pszLocation)
1651  {
1652  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1653  ERR("HeapAlloc failed!\n");
1654  goto Cleanup;
1655  }
1656 
1657  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pLocation, -1, pszLocation, cch + 1, NULL, NULL);
1658  StringCchCopyA(ppi2a[i].pLocation, cch + 1, pszLocation);
1659 
1660  HeapFree(hProcessHeap, 0, pszLocation);
1661  }
1662 
1663 
1664  if (ppi2w[i].pSepFile)
1665  {
1666  // Convert Unicode pSepFile to a ANSI string pszSepFile.
1667  cch = wcslen(ppi2w[i].pSepFile);
1668 
1669  pszSepFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1670  if (!pszSepFile)
1671  {
1672  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1673  ERR("HeapAlloc failed!\n");
1674  goto Cleanup;
1675  }
1676 
1677  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pSepFile, -1, pszSepFile, cch + 1, NULL, NULL);
1678  StringCchCopyA(ppi2a[i].pSepFile, cch + 1, pszSepFile);
1679 
1680  HeapFree(hProcessHeap, 0, pszSepFile);
1681  }
1682 
1683  if (ppi2w[i].pPrintProcessor)
1684  {
1685  // Convert Unicode pPrintProcessor to a ANSI string pszPrintProcessor.
1686  cch = wcslen(ppi2w[i].pPrintProcessor);
1687 
1688  pszPrintProcessor = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1689  if (!pszPrintProcessor)
1690  {
1691  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1692  ERR("HeapAlloc failed!\n");
1693  goto Cleanup;
1694  }
1695 
1696  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPrintProcessor, -1, pszPrintProcessor, cch + 1, NULL, NULL);
1697  StringCchCopyA(ppi2a[i].pPrintProcessor, cch + 1, pszPrintProcessor);
1698 
1699  HeapFree(hProcessHeap, 0, pszPrintProcessor);
1700  }
1701 
1702 
1703  if (ppi2w[i].pDatatype)
1704  {
1705  // Convert Unicode pDatatype to a ANSI string pszDatatype.
1706  cch = wcslen(ppi2w[i].pDatatype);
1707 
1708  pszDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1709  if (!pszDatatype)
1710  {
1711  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1712  ERR("HeapAlloc failed!\n");
1713  goto Cleanup;
1714  }
1715 
1716  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pDatatype, -1, pszDatatype, cch + 1, NULL, NULL);
1717  StringCchCopyA(ppi2a[i].pDatatype, cch + 1, pszDatatype);
1718 
1719  HeapFree(hProcessHeap, 0, pszDatatype);
1720  }
1721 
1722  if (ppi2w[i].pParameters)
1723  {
1724  // Convert Unicode pParameters to a ANSI string pszParameters.
1725  cch = wcslen(ppi2w[i].pParameters);
1726 
1727  pszParameters = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1728  if (!pszParameters)
1729  {
1730  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1731  ERR("HeapAlloc failed!\n");
1732  goto Cleanup;
1733  }
1734 
1735  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pParameters, -1, pszParameters, cch + 1, NULL, NULL);
1736  StringCchCopyA(ppi2a[i].pParameters, cch + 1, pszParameters);
1737 
1738  HeapFree(hProcessHeap, 0, pszParameters);
1739  }
1740  if ( ppi2w[i].pDevMode )
1741  {
1742  RosConvertUnicodeDevModeToAnsiDevmode( ppi2w[i].pDevMode, ppi2a[i].pDevMode );
1743  }
1744  break;
1745  }
1746 
1747  case 4:
1748  {
1749  if (ppi4w[i].pPrinterName)
1750  {
1751  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
1752  cch = wcslen(ppi4w[i].pPrinterName);
1753 
1754  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1755  if (!pszPrinterName)
1756  {
1757  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1758  ERR("HeapAlloc failed!\n");
1759  goto Cleanup;
1760  }
1761 
1762  WideCharToMultiByte(CP_ACP, 0, ppi4w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
1763  StringCchCopyA(ppi4a[i].pPrinterName, cch + 1, pszPrinterName);
1764 
1765  HeapFree(hProcessHeap, 0, pszPrinterName);
1766  }
1767 
1768  if (ppi4w[i].pServerName)
1769  {
1770  // Convert Unicode pServerName to a ANSI string pszServerName.
1771  cch = wcslen(ppi4w[i].pServerName);
1772 
1773  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1774  if (!pszServerName)
1775  {
1776  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1777  ERR("HeapAlloc failed!\n");
1778  goto Cleanup;
1779  }
1780 
1781  WideCharToMultiByte(CP_ACP, 0, ppi4w[i].pServerName, -1, pszServerName, cch + 1, NULL, NULL);
1782  StringCchCopyA(ppi4a[i].pServerName, cch + 1, pszServerName);
1783 
1784  HeapFree(hProcessHeap, 0, pszServerName);
1785  }
1786  break;
1787  }
1788 
1789  case 5:
1790  {
1791  if (ppi5w[i].pPrinterName)
1792  {
1793  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
1794  cch = wcslen(ppi5w[i].pPrinterName);
1795 
1796  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1797  if (!pszPrinterName)
1798  {
1799  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1800  ERR("HeapAlloc failed!\n");
1801  goto Cleanup;
1802  }
1803 
1804  WideCharToMultiByte(CP_ACP, 0, ppi5w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
1805  StringCchCopyA(ppi5a[i].pPrinterName, cch + 1, pszPrinterName);
1806 
1807  HeapFree(hProcessHeap, 0, pszPrinterName);
1808  }
1809 
1810  if (ppi5w[i].pPortName)
1811  {
1812  // Convert Unicode pPortName to a ANSI string pszPortName.
1813  cch = wcslen(ppi5w[i].pPortName);
1814 
1815  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1816  if (!pszPortName)
1817  {
1818  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1819  ERR("HeapAlloc failed!\n");
1820  goto Cleanup;
1821  }
1822 
1823  WideCharToMultiByte(CP_ACP, 0, ppi5w[i].pPortName, -1, pszPortName, cch + 1, NULL, NULL);
1824  StringCchCopyA(ppi5a[i].pPortName, cch + 1, pszPortName);
1825 
1826  HeapFree(hProcessHeap, 0, pszPortName);
1827  }
1828  break;
1829  }
1830 
1831  } // switch
1832  } // for
1833 
1834  dwErrorCode = ERROR_SUCCESS;
1835 
1836 Cleanup:
1837  if (pwszName)
1838  {
1839  HeapFree(hProcessHeap, 0, pwszName);
1840  }
1841 
1842  SetLastError(dwErrorCode);
1843  return (dwErrorCode == ERROR_SUCCESS);
1844 }
1845 
1846 BOOL WINAPI
1848 {
1849  DWORD dwErrorCode;
1850 
1851  TRACE("EnumPrintersW(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
1852 
1853  // Dismiss invalid levels already at this point.
1854  if (Level == 3 || Level > 5)
1855  {
1856  dwErrorCode = ERROR_INVALID_LEVEL;
1857  goto Cleanup;
1858  }
1859 
1860  if (cbBuf && pPrinterEnum)
1861  ZeroMemory(pPrinterEnum, cbBuf);
1862 
1863  // Do the RPC call
1864  RpcTryExcept
1865  {
1866  dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
1867  }
1869  {
1870  dwErrorCode = RpcExceptionCode();
1871  ERR("_RpcEnumPrinters failed with exception code %lu!\n", dwErrorCode);
1872  }
1873  RpcEndExcept;
1874 
1875  if (dwErrorCode == ERROR_SUCCESS)
1876  {
1877  // Replace relative offset addresses in the output by absolute pointers.
1878  ASSERT(Level <= 9);
1879  MarshallUpStructuresArray(cbBuf, pPrinterEnum, *pcReturned, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
1880  }
1881 
1882 Cleanup:
1883  SetLastError(dwErrorCode);
1884  return (dwErrorCode == ERROR_SUCCESS);
1885 }
1886 
1887 BOOL WINAPI
1888 FlushPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten, DWORD cSleep)
1889 {
1890  TRACE("FlushPrinter(%p, %p, %lu, %p, %lu)\n", hPrinter, pBuf, cbBuf, pcWritten, cSleep);
1891  UNIMPLEMENTED;
1892  return FALSE;
1893 }
1894 
1895 BOOL WINAPI
1896 GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
1897 {
1898  DWORD dwErrorCode;
1899  PWSTR pwszBuffer = NULL;
1900 
1901  TRACE("GetDefaultPrinterA(%p, %p)\n", pszBuffer, pcchBuffer);
1902 
1903  // Sanity check.
1904  if (!pcchBuffer)
1905  {
1906  dwErrorCode = ERROR_INVALID_PARAMETER;
1907  goto Cleanup;
1908  }
1909 
1910  // Check if an ANSI buffer was given and if so, allocate a Unicode buffer of the same size.
1911  if (pszBuffer && *pcchBuffer)
1912  {
1913  pwszBuffer = HeapAlloc(hProcessHeap, 0, *pcchBuffer * sizeof(WCHAR));
1914  if (!pwszBuffer)
1915  {
1916  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1917  ERR("HeapAlloc failed!\n");
1918  goto Cleanup;
1919  }
1920  }
1921 
1922  if (!GetDefaultPrinterW(pwszBuffer, pcchBuffer))
1923  {
1924  dwErrorCode = GetLastError();
1925  goto Cleanup;
1926  }
1927 
1928  // We successfully got a string in pwszBuffer, so convert the Unicode string to ANSI.
1929  WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszBuffer, *pcchBuffer, NULL, NULL);
1930 
1931  dwErrorCode = ERROR_SUCCESS;
1932 
1933 Cleanup:
1934  if (pwszBuffer)
1935  HeapFree(hProcessHeap, 0, pwszBuffer);
1936 
1937  SetLastError(dwErrorCode);
1938  return (dwErrorCode == ERROR_SUCCESS);
1939 }
1940 
1941 BOOL WINAPI
1942 GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
1943 {
1944  DWORD cbNeeded;
1945  DWORD cchInputBuffer;
1946  DWORD dwErrorCode;
1947  HKEY hWindowsKey = NULL;
1948  PWSTR pwszDevice = NULL;
1949  PWSTR pwszComma;
1950 
1951  TRACE("GetDefaultPrinterW(%p, %p)\n", pszBuffer, pcchBuffer);
1952 
1953  // Sanity check.
1954  if (!pcchBuffer)
1955  {
1956  dwErrorCode = ERROR_INVALID_PARAMETER;
1957  goto Cleanup;
1958  }
1959 
1960  cchInputBuffer = *pcchBuffer;
1961 
1962  // Open the registry key where the default printer for the current user is stored.
1963  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_READ, &hWindowsKey);
1964  if (dwErrorCode != ERROR_SUCCESS)
1965  {
1966  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
1967  goto Cleanup;
1968  }
1969 
1970  // Determine the size of the required buffer.
1971  dwErrorCode = (DWORD)RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, NULL, &cbNeeded);
1972  if (dwErrorCode != ERROR_SUCCESS)
1973  {
1974  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
1975  goto Cleanup;
1976  }
1977 
1978  // Allocate it.
1979  pwszDevice = HeapAlloc(hProcessHeap, 0, cbNeeded);
1980  if (!pwszDevice)
1981  {
1982  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1983  ERR("HeapAlloc failed!\n");
1984  goto Cleanup;
1985  }
1986 
1987  // Now get the actual value.
1988  dwErrorCode = RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, (PBYTE)pwszDevice, &cbNeeded);
1989  if (dwErrorCode != ERROR_SUCCESS)
1990  {
1991  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
1992  goto Cleanup;
1993  }
1994 
1995  // We get a string "<Printer Name>,winspool,<Port>:".
1996  // Extract the printer name from it.
1997  pwszComma = wcschr(pwszDevice, L',');
1998  if (!pwszComma)
1999  {
2000  ERR("Found no or invalid default printer: %S!\n", pwszDevice);
2001  dwErrorCode = ERROR_INVALID_NAME;
2002  goto Cleanup;
2003  }
2004 
2005  // Store the length of the Printer Name (including the terminating NUL character!) in *pcchBuffer.
2006  *pcchBuffer = pwszComma - pwszDevice + 1;
2007 
2008  // Check if the supplied buffer is large enough.
2009  if ( !pszBuffer || cchInputBuffer < *pcchBuffer)
2010  {
2011  dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
2012  goto Cleanup;
2013  }
2014 
2015  // Copy the default printer.
2016  *pwszComma = 0;
2017  CopyMemory(pszBuffer, pwszDevice, *pcchBuffer * sizeof(WCHAR));
2018 
2019  dwErrorCode = ERROR_SUCCESS;
2020 
2021 Cleanup:
2022  if (hWindowsKey)
2023  RegCloseKey(hWindowsKey);
2024 
2025  if (pwszDevice)
2026  HeapFree(hProcessHeap, 0, pwszDevice);
2027 
2028  SetLastError(dwErrorCode);
2029  return (dwErrorCode == ERROR_SUCCESS);
2030 }
2031 
2032 BOOL WINAPI
2034 {
2035  DWORD dwErrorCode;
2036  PPRINTER_INFO_1A ppi1a = (PPRINTER_INFO_1A)pPrinter;
2037  PPRINTER_INFO_1W ppi1w = (PPRINTER_INFO_1W)pPrinter;
2038  PPRINTER_INFO_2A ppi2a = (PPRINTER_INFO_2A)pPrinter;
2039  PPRINTER_INFO_2W ppi2w = (PPRINTER_INFO_2W)pPrinter;
2040  PPRINTER_INFO_4A ppi4a = (PPRINTER_INFO_4A)pPrinter;
2041  PPRINTER_INFO_4W ppi4w = (PPRINTER_INFO_4W)pPrinter;
2042  PPRINTER_INFO_5A ppi5a = (PPRINTER_INFO_5A)pPrinter;
2043  PPRINTER_INFO_5W ppi5w = (PPRINTER_INFO_5W)pPrinter;
2044  PPRINTER_INFO_7A ppi7a = (PPRINTER_INFO_7A)pPrinter;
2045  PPRINTER_INFO_7W ppi7w = (PPRINTER_INFO_7W)pPrinter;
2046  PPRINTER_INFO_9A ppi9a = (PPRINTER_INFO_9A)pPrinter;
2047  PPRINTER_INFO_9W ppi9w = (PPRINTER_INFO_9W)pPrinter;
2048  DWORD cch;
2049 
2050  TRACE("GetPrinterA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
2051 
2052  // Check for invalid levels here for early error return. Should be 1-9.
2053  if (Level < 1 || Level > 9)
2054  {
2055  dwErrorCode = ERROR_INVALID_LEVEL;
2056  ERR("Invalid Level!\n");
2057  goto Cleanup;
2058  }
2059 
2060  if (!GetPrinterW(hPrinter, Level, pPrinter, cbBuf, pcbNeeded))
2061  {
2062  dwErrorCode = GetLastError();
2063  goto Cleanup;
2064  }
2065 
2066  switch (Level)
2067  {
2068  case 1:
2069  {
2070  if (ppi1w->pDescription)
2071  {
2072  PSTR pszDescription;
2073 
2074  // Convert Unicode pDescription to a ANSI string pszDescription.
2075  cch = wcslen(ppi1w->pDescription);
2076 
2077  pszDescription = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2078  if (!pszDescription)
2079  {
2080  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2081  ERR("HeapAlloc failed!\n");
2082  goto Cleanup;
2083  }
2084 
2085  WideCharToMultiByte(CP_ACP, 0, ppi1w->pDescription, -1, pszDescription, cch + 1, NULL, NULL);
2086  StringCchCopyA(ppi1a->pDescription, cch + 1, pszDescription);
2087 
2088  HeapFree(hProcessHeap, 0, pszDescription);
2089  }
2090 
2091  if (ppi1w->pName)
2092  {
2093  PSTR pszName;
2094 
2095  // Convert Unicode pName to a ANSI string pszName.
2096  cch = wcslen(ppi1w->pName);
2097 
2098  pszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2099  if (!pszName)
2100  {
2101  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2102  ERR("HeapAlloc failed!\n");
2103  goto Cleanup;
2104  }
2105 
2106  WideCharToMultiByte(CP_ACP, 0, ppi1w->pName, -1, pszName, cch + 1, NULL, NULL);
2107  StringCchCopyA(ppi1a->pName, cch + 1, pszName);
2108 
2109  HeapFree(hProcessHeap, 0, pszName);
2110  }
2111 
2112  if (ppi1w->pComment)
2113  {
2114  PSTR pszComment;
2115 
2116  // Convert Unicode pComment to a ANSI string pszComment.
2117  cch = wcslen(ppi1w->pComment);
2118 
2119  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2120  if (!pszComment)
2121  {
2122  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2123  ERR("HeapAlloc failed!\n");
2124  goto Cleanup;
2125  }
2126 
2127  WideCharToMultiByte(CP_ACP, 0, ppi1w->pComment, -1, pszComment, cch + 1, NULL, NULL);
2128  StringCchCopyA(ppi1a->pComment, cch + 1, pszComment);
2129 
2130  HeapFree(hProcessHeap, 0, pszComment);
2131  }
2132  break;
2133  }
2134 
2135  case 2:
2136  {
2137  if (ppi2w->pServerName)
2138  {
2139  PSTR pszServerName;
2140 
2141  // Convert Unicode pServerName to a ANSI string pszServerName.
2142  cch = wcslen(ppi2w->pServerName);
2143 
2144  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2145  if (!pszServerName)
2146  {
2147  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2148  ERR("HeapAlloc failed!\n");
2149  goto Cleanup;
2150  }
2151 
2152  WideCharToMultiByte(CP_ACP, 0, ppi2w->pServerName, -1, pszServerName, cch + 1, NULL, NULL);
2153  StringCchCopyA(ppi2a->pServerName, cch + 1, pszServerName);
2154 
2155  HeapFree(hProcessHeap, 0, pszServerName);
2156  }
2157 
2158  if (ppi2w->pPrinterName)
2159  {
2160  PSTR pszPrinterName;
2161 
2162  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
2163  cch = wcslen(ppi2w->pPrinterName);
2164 
2165  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2166  if (!pszPrinterName)
2167  {
2168  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2169  ERR("HeapAlloc failed!\n");
2170  goto Cleanup;
2171  }
2172 
2173  WideCharToMultiByte(CP_ACP, 0, ppi2w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
2174  StringCchCopyA(ppi2a->pPrinterName, cch + 1, pszPrinterName);
2175 
2176  HeapFree(hProcessHeap, 0, pszPrinterName);
2177  }
2178 
2179  if (ppi2w->pShareName)
2180  {
2181  PSTR pszShareName;
2182 
2183  // Convert Unicode pShareName to a ANSI string pszShareName.
2184  cch = wcslen(ppi2w->pShareName);
2185 
2186  pszShareName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2187  if (!pszShareName)
2188  {
2189  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2190  ERR("HeapAlloc failed!\n");
2191  goto Cleanup;
2192  }
2193 
2194  WideCharToMultiByte(CP_ACP, 0, ppi2w->pShareName, -1, pszShareName, cch + 1, NULL, NULL);
2195  StringCchCopyA(ppi2a->pShareName, cch + 1, pszShareName);
2196 
2197  HeapFree(hProcessHeap, 0, pszShareName);
2198  }
2199 
2200  if (ppi2w->pPortName)
2201  {
2202  PSTR pszPortName;
2203 
2204  // Convert Unicode pPortName to a ANSI string pszPortName.
2205  cch = wcslen(ppi2w->pPortName);
2206 
2207  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2208  if (!pszPortName)
2209  {
2210  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2211  ERR("HeapAlloc failed!\n");
2212  goto Cleanup;
2213  }
2214 
2215  WideCharToMultiByte(CP_ACP, 0, ppi2w->pPortName, -1, pszPortName, cch + 1, NULL, NULL);
2216  StringCchCopyA(ppi2a->pPortName, cch + 1, pszPortName);
2217 
2218  HeapFree(hProcessHeap, 0, pszPortName);
2219  }
2220 
2221  if (ppi2w->pDriverName)
2222  {
2223  PSTR pszDriverName;
2224 
2225  // Convert Unicode pDriverName to a ANSI string pszDriverName.
2226  cch = wcslen(ppi2w->pDriverName);
2227 
2228  pszDriverName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2229  if (!pszDriverName)
2230  {
2231  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2232  ERR("HeapAlloc failed!\n");
2233  goto Cleanup;
2234  }
2235 
2236  WideCharToMultiByte(CP_ACP, 0, ppi2w->pDriverName, -1, pszDriverName, cch + 1, NULL, NULL);
2237  StringCchCopyA(ppi2a->pDriverName, cch + 1, pszDriverName);
2238 
2239  HeapFree(hProcessHeap, 0, pszDriverName);
2240  }
2241 
2242  if (ppi2w->pComment)
2243  {
2244  PSTR pszComment;
2245 
2246  // Convert Unicode pComment to a ANSI string pszComment.
2247  cch = wcslen(ppi2w->pComment);
2248 
2249  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2250  if (!pszComment)
2251  {
2252  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2253  ERR("HeapAlloc failed!\n");
2254  goto Cleanup;
2255  }
2256 
2257  WideCharToMultiByte(CP_ACP, 0, ppi2w->pComment, -1, pszComment, cch + 1, NULL, NULL);
2258  StringCchCopyA(ppi2a->pComment, cch + 1, pszComment);
2259 
2260  HeapFree(hProcessHeap, 0, pszComment);
2261  }
2262 
2263  if (ppi2w->pLocation)
2264  {
2265  PSTR pszLocation;
2266 
2267  // Convert Unicode pLocation to a ANSI string pszLocation.
2268  cch = wcslen(ppi2w->pLocation);
2269 
2270  pszLocation = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2271  if (!pszLocation)
2272  {
2273  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2274  ERR("HeapAlloc failed!\n");
2275  goto Cleanup;
2276  }
2277 
2278  WideCharToMultiByte(CP_ACP, 0, ppi2w->pLocation, -1, pszLocation, cch + 1, NULL, NULL);
2279  StringCchCopyA(ppi2a->pLocation, cch + 1, pszLocation);
2280 
2281  HeapFree(hProcessHeap, 0, pszLocation);
2282  }
2283 
2284  if (ppi2w->pSepFile)
2285  {
2286  PSTR pszSepFile;
2287 
2288  // Convert Unicode pSepFile to a ANSI string pszSepFile.
2289  cch = wcslen(ppi2w->pSepFile);
2290 
2291  pszSepFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2292  if (!pszSepFile)
2293  {
2294  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2295  ERR("HeapAlloc failed!\n");
2296  goto Cleanup;
2297  }
2298 
2299  WideCharToMultiByte(CP_ACP, 0, ppi2w->pSepFile, -1, pszSepFile, cch + 1, NULL, NULL);
2300  StringCchCopyA(ppi2a->pSepFile, cch + 1, pszSepFile);
2301 
2302  HeapFree(hProcessHeap, 0, pszSepFile);
2303  }
2304 
2305  if (ppi2w->pPrintProcessor)
2306  {
2307  PSTR pszPrintProcessor;
2308 
2309  // Convert Unicode pPrintProcessor to a ANSI string pszPrintProcessor.
2310  cch = wcslen(ppi2w->pPrintProcessor);
2311 
2312  pszPrintProcessor = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2313  if (!pszPrintProcessor)
2314  {
2315  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2316  ERR("HeapAlloc failed!\n");
2317  goto Cleanup;
2318  }
2319 
2320  WideCharToMultiByte(CP_ACP, 0, ppi2w->pPrintProcessor, -1, pszPrintProcessor, cch + 1, NULL, NULL);
2321  StringCchCopyA(ppi2a->pPrintProcessor, cch + 1, pszPrintProcessor);
2322 
2323  HeapFree(hProcessHeap, 0, pszPrintProcessor);
2324  }
2325 
2326  if (ppi2w->pDatatype)
2327  {
2328  PSTR pszDatatype;
2329 
2330  // Convert Unicode pDatatype to a ANSI string pszDatatype.
2331  cch = wcslen(ppi2w->pDatatype);
2332 
2333  pszDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2334  if (!pszDatatype)
2335  {
2336  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2337  ERR("HeapAlloc failed!\n");
2338  goto Cleanup;
2339  }
2340 
2341  WideCharToMultiByte(CP_ACP, 0, ppi2w->pDatatype, -1, pszDatatype, cch + 1, NULL, NULL);
2342  StringCchCopyA(ppi2a->pDatatype, cch + 1, pszDatatype);
2343 
2344  HeapFree(hProcessHeap, 0, pszDatatype);
2345  }
2346 
2347  if (ppi2w->pParameters)
2348  {
2349  PSTR pszParameters;
2350 
2351  // Convert Unicode pParameters to a ANSI string pszParameters.
2352  cch = wcslen(ppi2w->pParameters);
2353 
2354  pszParameters = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2355  if (!pszParameters)
2356  {
2357  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2358  ERR("HeapAlloc failed!\n");
2359  goto Cleanup;
2360  }
2361 
2362  WideCharToMultiByte(CP_ACP, 0, ppi2w->pParameters, -1, pszParameters, cch + 1, NULL, NULL);
2363  StringCchCopyA(ppi2a->pParameters, cch + 1, pszParameters);
2364 
2365  HeapFree(hProcessHeap, 0, pszParameters);
2366  }
2367  if ( ppi2w->pDevMode )
2368  {
2370  }
2371  break;
2372  }
2373 
2374  case 4:
2375  {
2376  if (ppi4w->pPrinterName)
2377  {
2378  PSTR pszPrinterName;
2379 
2380  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
2381  cch = wcslen(ppi4w->pPrinterName);
2382 
2383  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2384  if (!pszPrinterName)
2385  {
2386  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2387  ERR("HeapAlloc failed!\n");
2388  goto Cleanup;
2389  }
2390 
2391  WideCharToMultiByte(CP_ACP, 0, ppi4w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
2392  StringCchCopyA(ppi4a->pPrinterName, cch + 1, pszPrinterName);
2393 
2394  HeapFree(hProcessHeap, 0, pszPrinterName);
2395  }
2396 
2397  if (ppi4w->pServerName)
2398  {
2399  PSTR pszServerName;
2400 
2401  // Convert Unicode pServerName to a ANSI string pszServerName.
2402  cch = wcslen(ppi4w->pServerName);
2403 
2404  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2405  if (!pszServerName)
2406  {
2407  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2408  ERR("HeapAlloc failed!\n");
2409  goto Cleanup;
2410  }
2411 
2412  WideCharToMultiByte(CP_ACP, 0, ppi4w->pServerName, -1, pszServerName, cch + 1, NULL, NULL);
2413  StringCchCopyA(ppi4a->pServerName, cch + 1, pszServerName);
2414 
2415  HeapFree(hProcessHeap, 0, pszServerName);
2416  }
2417  break;
2418  }
2419 
2420  case 5:
2421  {
2422  if (ppi5w->pPrinterName)
2423  {
2424  PSTR pszPrinterName;
2425 
2426  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
2427  cch = wcslen(ppi5w->pPrinterName);
2428 
2429  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2430  if (!pszPrinterName)
2431  {
2432  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2433  ERR("HeapAlloc failed!\n");
2434  goto Cleanup;
2435  }
2436 
2437  WideCharToMultiByte(CP_ACP, 0, ppi5w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
2438  StringCchCopyA(ppi5a->pPrinterName, cch + 1, pszPrinterName);
2439 
2440  HeapFree(hProcessHeap, 0, pszPrinterName);
2441  }
2442 
2443  if (ppi5w->pPortName)
2444  {
2445  PSTR pszPortName;
2446 
2447  // Convert Unicode pPortName to a ANSI string pszPortName.
2448  cch = wcslen(ppi5w->pPortName);
2449 
2450  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2451  if (!pszPortName)
2452  {
2453  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2454  ERR("HeapAlloc failed!\n");
2455  goto Cleanup;
2456  }
2457 
2458  WideCharToMultiByte(CP_ACP, 0, ppi5w->pPortName, -1, pszPortName, cch + 1, NULL, NULL);
2459  StringCchCopyA(ppi5a->pPortName, cch + 1, pszPortName);
2460 
2461  HeapFree(hProcessHeap, 0, pszPortName);
2462  }
2463  break;
2464  }
2465 
2466  case 7:
2467  {
2468  if (ppi7w->pszObjectGUID)
2469  {
2470  PSTR pszaObjectGUID;
2471 
2472  // Convert Unicode pszObjectGUID to a ANSI string pszaObjectGUID.
2473  cch = wcslen(ppi7w->pszObjectGUID);
2474 
2475  pszaObjectGUID = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2476  if (!pszaObjectGUID)
2477  {
2478  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2479  ERR("HeapAlloc failed!\n");
2480  goto Cleanup;
2481  }
2482 
2483  WideCharToMultiByte(CP_ACP, 0, ppi7w->pszObjectGUID, -1, pszaObjectGUID, cch + 1, NULL, NULL);
2484  StringCchCopyA(ppi7a->pszObjectGUID, cch + 1, pszaObjectGUID);
2485 
2486  HeapFree(hProcessHeap, 0, pszaObjectGUID);
2487  }
2488  }
2489  break;
2490  case 8:
2491  case 9:
2493  break;
2494  } // switch
2495 
2496  dwErrorCode = ERROR_SUCCESS;
2497 
2498 Cleanup:
2499  SetLastError(dwErrorCode);
2500  return (dwErrorCode == ERROR_SUCCESS);
2501 }
2502 
2503 BOOL WINAPI
2505 {
2506  DWORD dwErrorCode;
2507  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2508 
2509  TRACE("GetPrinterW(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
2510 
2511  // Sanity checks.
2512  if (!pHandle)
2513  {
2514  dwErrorCode = ERROR_INVALID_HANDLE;
2515  goto Cleanup;
2516  }
2517 
2518  // Dismiss invalid levels already at this point.
2519  if (Level > 9)
2520  {
2521  dwErrorCode = ERROR_INVALID_LEVEL;
2522  goto Cleanup;
2523  }
2524 
2525  if (cbBuf && pPrinter)
2526  ZeroMemory(pPrinter, cbBuf);
2527 
2528  // Do the RPC call
2529  RpcTryExcept
2530  {
2531  dwErrorCode = _RpcGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
2532  }
2534  {
2535  dwErrorCode = RpcExceptionCode();
2536  ERR("_RpcGetPrinter failed with exception code %lu!\n", dwErrorCode);
2537  }
2538  RpcEndExcept;
2539 
2540  if (dwErrorCode == ERROR_SUCCESS)
2541  {
2542  // Replace relative offset addresses in the output by absolute pointers.
2543  ASSERT(Level <= 9);
2544  MarshallUpStructure(cbBuf, pPrinter, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
2545  }
2546 
2547 Cleanup:
2548  SetLastError(dwErrorCode);
2549  return (dwErrorCode == ERROR_SUCCESS);
2550 }
2551 
2552 BOOL WINAPI
2553 OpenPrinterA(LPSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSA pDefault)
2554 {
2555  BOOL bReturnValue = FALSE;
2556  DWORD cch;
2557  PWSTR pwszPrinterName = NULL;
2558  PRINTER_DEFAULTSW wDefault = { 0 };
2559 
2560  TRACE("OpenPrinterA(%s, %p, %p)\n", pPrinterName, phPrinter, pDefault);
2561 
2562  if (pPrinterName)
2563  {
2564  // Convert pPrinterName to a Unicode string pwszPrinterName
2565  cch = strlen(pPrinterName);
2566 
2567  pwszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
2568  if (!pwszPrinterName)
2569  {
2571  ERR("HeapAlloc failed!\n");
2572  goto Cleanup;
2573  }
2574 
2575  MultiByteToWideChar(CP_ACP, 0, pPrinterName, -1, pwszPrinterName, cch + 1);
2576  }
2577 
2578  if (pDefault)
2579  {
2580  wDefault.DesiredAccess = pDefault->DesiredAccess;
2581 
2582  if (pDefault->pDatatype)
2583  {
2584  // Convert pDefault->pDatatype to a Unicode string wDefault.pDatatype
2585  cch = strlen(pDefault->pDatatype);
2586 
2587  wDefault.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
2588  if (!wDefault.pDatatype)
2589  {
2591  ERR("HeapAlloc failed!\n");
2592  goto Cleanup;
2593  }
2594 
2595  MultiByteToWideChar(CP_ACP, 0, pDefault->pDatatype, -1, wDefault.pDatatype, cch + 1);
2596  }
2597 
2598  if (pDefault->pDevMode)
2599  wDefault.pDevMode = GdiConvertToDevmodeW(pDefault->pDevMode);
2600  }
2601 
2602  bReturnValue = OpenPrinterW(pwszPrinterName, phPrinter, &wDefault);
2603 
2604  if ( bReturnValue )
2605  {
2606  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)*phPrinter;
2607  pHandle->bAnsi = TRUE;
2608  }
2609 
2610 Cleanup:
2611  if (wDefault.pDatatype)
2612  HeapFree(hProcessHeap, 0, wDefault.pDatatype);
2613 
2614  if (wDefault.pDevMode)
2615  HeapFree(hProcessHeap, 0, wDefault.pDevMode);
2616 
2617  if (pwszPrinterName)
2618  HeapFree(hProcessHeap, 0, pwszPrinterName);
2619 
2620  return bReturnValue;
2621 }
2622 
2623 BOOL WINAPI
2624 OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefault)
2625 {
2626  DWORD dwErrorCode;
2627  HANDLE hPrinter;
2628  PSPOOLER_HANDLE pHandle;
2629  PWSTR pDatatype = NULL;
2630  WINSPOOL_DEVMODE_CONTAINER DevModeContainer = { 0 };
2631  ACCESS_MASK AccessRequired = 0;
2632 
2633  TRACE("OpenPrinterW(%S, %p, %p)\n", pPrinterName, phPrinter, pDefault);
2634 
2635  // Sanity check
2636  if (!phPrinter)
2637  {
2638  dwErrorCode = ERROR_INVALID_PARAMETER;
2639  goto Cleanup;
2640  }
2641 
2642  // Prepare the additional parameters in the format required by _RpcOpenPrinter
2643  if (pDefault)
2644  {
2645  pDatatype = pDefault->pDatatype;
2646  DevModeContainer.cbBuf = sizeof(DEVMODEW);
2647  DevModeContainer.pDevMode = (BYTE*)pDefault->pDevMode;
2648  AccessRequired = pDefault->DesiredAccess;
2649  }
2650 
2651  // Do the RPC call
2652  RpcTryExcept
2653  {
2654  dwErrorCode = _RpcOpenPrinter(pPrinterName, &hPrinter, pDatatype, &DevModeContainer, AccessRequired);
2655  }
2657  {
2658  dwErrorCode = RpcExceptionCode();
2659  ERR("_RpcOpenPrinter failed with exception code %lu!\n", dwErrorCode);
2660  }
2661  RpcEndExcept;
2662 
2663  if (dwErrorCode == ERROR_SUCCESS)
2664  {
2665  // Create a new SPOOLER_HANDLE structure.
2667  if (!pHandle)
2668  {
2669  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2670  ERR("HeapAlloc failed!\n");
2671  goto Cleanup;
2672  }
2673 
2674  pHandle->Sig = SPOOLER_HANDLE_SIG;
2675  pHandle->hPrinter = hPrinter;
2676  pHandle->hSPLFile = INVALID_HANDLE_VALUE;
2678 
2679  // Return it as phPrinter.
2680  *phPrinter = (HANDLE)pHandle;
2681  }
2682 
2683 Cleanup:
2684  SetLastError(dwErrorCode);
2685  return (dwErrorCode == ERROR_SUCCESS);
2686 }
2687 
2688 //
2689 // Dead API.
2690 //
2691 DWORD WINAPI
2693 {
2694  return 50;
2695 }
2696 
2697 DWORD WINAPI
2699 {
2700  return 50;
2701 }
2702 
2703 BOOL WINAPI
2705  HANDLE hPrinter,
2706  PDEVMODEW pdevmode,
2707  ULONG ulQueryMode,
2708  VOID *pvProfileData,
2709  ULONG *pcbProfileData,
2710  FLONG *pflProfileData )
2711 {
2712  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2713  BOOL Ret = FALSE;
2714  HMODULE hLibrary;
2715 
2716  FIXME("QueryColorProfile(%p, %p, %l, %p, %p, %p)\n", hPrinter, pdevmode, ulQueryMode, pvProfileData, pcbProfileData, pflProfileData);
2717 
2718  if ( pHandle->bNoColorProfile )
2719  {
2720  Ret = (BOOL)SP_ERROR;
2721  }
2722  else
2723  {
2724 
2725  if ( pdevmode )
2726  {
2727  if (!IsValidDevmodeNoSizeW( pdevmode ) )
2728  {
2729  ERR("DeviceCapabilitiesW : Devode Invalid");
2730  return FALSE;
2731  }
2732  }
2733 
2734  hLibrary = LoadPrinterDriver( hPrinter );
2735 
2736  if ( hLibrary )
2737  {
2738  fpQueryColorProfile = (PVOID)GetProcAddress( hLibrary, "DrvQueryColorProfile" );
2739 
2740  if ( fpQueryColorProfile )
2741  {
2742  Ret = fpQueryColorProfile( hPrinter, pdevmode, ulQueryMode, pvProfileData, pcbProfileData, pflProfileData );
2743  }
2744  else
2745  {
2746  pHandle->bNoColorProfile = TRUE;
2747  Ret = (BOOL)SP_ERROR;
2748  }
2749 
2751  }
2752  }
2753  return Ret;
2754 }
2755 
2756 // Note from GDI32:printdrv.c
2757 //
2758 // QuerySpoolMode :
2759 // BOOL return TRUE if successful.
2760 // dlFont 0x0001 for Downloading fonts. 0x0002 unknown XPS_PASS?.
2761 // dwVersion is version of EMFSPOOL. Must be 0x00010000. See [MS-EMFSPOOL] page 18.
2762 //
2763 
2764 #define QSM_DOWNLOADINGFONTS 0x0001
2765 
2766 /*
2767  Note from MSDN : "V4 print drivers using RAW mode to send PCL/Postscript have 0 byte spool file"
2768 
2769  Use XPS_PASS instead of RAW to pass information directly to the print filter pipeline in
2770  v4 and v3 XPSDrv drivers. Here's how to proceed with Windows 8:
2771 
2772  Call GetPrinterDriver to retrieve the DRIVER_INFO_8 structure.
2773  Check DRIVER_INFO_8::dwPrinterDriverAttributes for the PRINTER_DRIVER_XPS flag.
2774  Choose your datatype based on the presence or absence of the flag:
2775  If the flag is set, use XPS_PASS.
2776  If the flag isn't set, use RAW.
2777  */
2778 
2779 #define QSM_XPS_PASS 0x0002 // Guessing. PRINTER_DRIVER_XPS?
2780 
2781 BOOL WINAPI
2782 QuerySpoolMode( HANDLE hPrinter, PDWORD downloadFontsFlags, PDWORD dwVersion )
2783 {
2784  PRINTER_INFO_2W *pi2 = NULL;
2785  DWORD needed = 0;
2786  BOOL res;
2787 
2788  FIXME("QuerySpoolMode(%p, %p, %p)\n", hPrinter, downloadFontsFlags, dwVersion);
2789 
2790  res = GetPrinterW( hPrinter, 2, NULL, 0, &needed);
2792  {
2793  pi2 = HeapAlloc(hProcessHeap, 0, needed);
2794  res = GetPrinterW(hPrinter, 2, (LPBYTE)pi2, needed, &needed);
2795  }
2796 
2797  if ( res )
2798  {
2799  *dwVersion = 0x10000;
2800  *downloadFontsFlags = 0;
2801 
2802  if ( pi2->pServerName )
2803  {
2804  *downloadFontsFlags |= QSM_DOWNLOADINGFONTS;
2805  }
2806  }
2807 //
2808 // Guessing,,,
2809 // To do : Add GetPrinterDriver for DRIVER_INFO_8, test PRINTER_DRIVER_XPS flag,
2810 // to set *downloadFontsFlags |= QSM_XPS_PASS;
2811 //
2812 // Vista+ looks for QSM_XPS_PASS to be set in GDI32.
2813 //
2814  HeapFree(hProcessHeap, 0, pi2);
2815  return res;
2816 }
2817 
2818 //
2819 // This requires IC support.
2820 //
2821 DWORD WINAPI
2822 QueryRemoteFonts( HANDLE hPrinter, PUNIVERSAL_FONT_ID pufi, ULONG NumberOfUFIs )
2823 {
2824  HANDLE hIC;
2825  DWORD Result = -1, cOut, cIn = 0;
2826  PBYTE pOut;
2827 
2828  FIXME("QueryRemoteFonts(%p, %p, %lu)\n", hPrinter, pufi, NumberOfUFIs);
2829 
2830  hIC = CreatePrinterIC( hPrinter, NULL );
2831  if ( hIC )
2832  {
2833  cOut = (NumberOfUFIs * sizeof(UNIVERSAL_FONT_ID)) + sizeof(DWORD); // Include "DWORD" first part to return size.
2834 
2835  pOut = HeapAlloc( hProcessHeap, 0, cOut );
2836  if ( pOut )
2837  {
2838  if ( PlayGdiScriptOnPrinterIC( hIC, (LPBYTE)&cIn, sizeof(DWORD), pOut, cOut, 0 ) )
2839  {
2840  cIn = *((PDWORD)pOut); // Fisrt part is the size of the UFID object.
2841 
2842  Result = cIn; // Return the required size.
2843 
2844  if( NumberOfUFIs < cIn )
2845  {
2846  cIn = NumberOfUFIs;
2847  }
2848  // Copy whole object back to GDI32, exclude first DWORD part.
2849  memcpy( pufi, pOut + sizeof(DWORD), cIn * sizeof(UNIVERSAL_FONT_ID) );
2850  }
2851  HeapFree( hProcessHeap, 0, pOut );
2852  }
2853  DeletePrinterIC( hIC );
2854  }
2855  return Result;
2856 }
2857 
2858 BOOL WINAPI
2859 ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
2860 {
2861  DWORD dwErrorCode;
2862  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2863 
2864  TRACE("ReadPrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pNoBytesRead);
2865 
2866  // Sanity checks.
2867  if (!pHandle)
2868  {
2869  dwErrorCode = ERROR_INVALID_HANDLE;
2870  goto Cleanup;
2871  }
2872 
2873  // Do the RPC call
2874  RpcTryExcept
2875  {
2876  dwErrorCode = _RpcReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
2877  }
2879  {
2880  dwErrorCode = RpcExceptionCode();
2881  ERR("_RpcReadPrinter failed with exception code %lu!\n", dwErrorCode);
2882  }
2883  RpcEndExcept;
2884 
2885 Cleanup:
2886  SetLastError(dwErrorCode);
2887  return (dwErrorCode == ERROR_SUCCESS);
2888 }
2889 
2890 BOOL WINAPI
2892 {
2893  BOOL ret;
2894  UNICODE_STRING pNameW;
2895  PDEVMODEW pdmw = NULL;
2896  PPRINTER_DEFAULTSW pdw = (PPRINTER_DEFAULTSW)pDefault;
2897 
2898  TRACE("ResetPrinterA(%p, %p)\n", hPrinter, pDefault);
2899 
2900  if ( pDefault->pDatatype == (LPSTR)-1 )
2901  {
2902  pdw->pDatatype = (LPWSTR)-1;
2903  }
2904  else
2905  {
2906  pdw->pDatatype = AsciiToUnicode( &pNameW, pDefault->pDatatype );
2907  }
2908  if ( pDefault->pDevMode == (LPDEVMODEA)-1)
2909  {
2910  pdw->pDevMode = (LPDEVMODEW)-1;
2911  }
2912  else
2913  {
2914  if ( pDefault->pDevMode )//&& IsValidDevmodeNoSizeW( pDefault->pDevMode ) )
2915  {
2916  RosConvertAnsiDevModeToUnicodeDevmode( pDefault->pDevMode, &pdmw );
2917  pdw->pDevMode = pdmw;
2918  }
2919  }
2920 
2921  ret = ResetPrinterW( hPrinter, pdw );
2922 
2923  if (pdmw) HeapFree(hProcessHeap, 0, pdmw);
2924 
2925  RtlFreeUnicodeString( &pNameW );
2926 
2927  return ret;
2928 }
2929 
2930 BOOL WINAPI
2932 {
2933  TRACE("ResetPrinterW(%p, %p)\n", hPrinter, pDefault);
2934  UNIMPLEMENTED;
2935  return FALSE;
2936 }
2937 
2938 BOOL WINAPI
2939 SeekPrinter( HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite )
2940 {
2941  DWORD dwErrorCode;
2942  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2943 
2944  FIXME("SeekPrinter(%p, %I64u, %p, %lu, %d)\n", hPrinter, liDistanceToMove.QuadPart, pliNewPointer, dwMoveMethod, bWrite);
2945 
2946  // Sanity checks.
2947  if (!pHandle)
2948  {
2949  dwErrorCode = ERROR_INVALID_HANDLE;
2950  goto Cleanup;
2951  }
2952 
2953  // Do the RPC call
2954  RpcTryExcept
2955  {
2956  dwErrorCode = _RpcSeekPrinter(pHandle->hPrinter, liDistanceToMove, pliNewPointer, dwMoveMethod, bWrite);
2957  }
2959  {
2960  dwErrorCode = RpcExceptionCode();
2961  ERR("_RpcSeekPrinter failed with exception code %lu!\n", dwErrorCode);
2962  }
2963  RpcEndExcept;
2964 
2965 Cleanup:
2966  SetLastError(dwErrorCode);
2967  return (dwErrorCode == ERROR_SUCCESS);
2968 }
2969 
2970 BOOL WINAPI
2972 {
2973  BOOL bReturnValue = FALSE;
2974  DWORD cch;
2975  PWSTR pwszPrinter = NULL;
2976 
2977  TRACE("SetDefaultPrinterA(%s)\n", pszPrinter);
2978 
2979  if (pszPrinter)
2980  {
2981  // Convert pszPrinter to a Unicode string pwszPrinter
2982  cch = strlen(pszPrinter);
2983 
2984  pwszPrinter = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
2985  if (!pwszPrinter)
2986  {
2988  ERR("HeapAlloc failed!\n");
2989  goto Cleanup;
2990  }
2991 
2992  MultiByteToWideChar(CP_ACP, 0, pszPrinter, -1, pwszPrinter, cch + 1);
2993  }
2994 
2995  bReturnValue = SetDefaultPrinterW(pwszPrinter);
2996 
2997 Cleanup:
2998  if (pwszPrinter)
2999  HeapFree(hProcessHeap, 0, pwszPrinter);
3000 
3001  return bReturnValue;
3002 }
3003 
3004 BOOL WINAPI
3006 {
3007  const WCHAR wszDevicesKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Devices";
3008 
3009  DWORD cbDeviceValueData;
3010  DWORD cbPrinterValueData = 0;
3011  DWORD cchPrinter;
3012  DWORD dwErrorCode;
3013  HKEY hDevicesKey = NULL;
3014  HKEY hWindowsKey = NULL;
3015  PWSTR pwszDeviceValueData = NULL;
3016  WCHAR wszPrinter[MAX_PRINTER_NAME + 1];
3017 
3018  TRACE("SetDefaultPrinterW(%S)\n", pszPrinter);
3019 
3020  // Open the Devices registry key.
3021  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszDevicesKey, 0, KEY_READ, &hDevicesKey);
3022  if (dwErrorCode != ERROR_SUCCESS)
3023  {
3024  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
3025  goto Cleanup;
3026  }
3027 
3028  // Did the caller give us a printer to set as default?
3029  if (pszPrinter && *pszPrinter)
3030  {
3031  // Check if the given printer exists and query the value data size.
3032  dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, NULL, &cbPrinterValueData);
3033  if (dwErrorCode == ERROR_FILE_NOT_FOUND)
3034  {
3035  dwErrorCode = ERROR_INVALID_PRINTER_NAME;
3036  goto Cleanup;
3037  }
3038  else if (dwErrorCode != ERROR_SUCCESS)
3039  {
3040  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
3041  goto Cleanup;
3042  }
3043 
3044  cchPrinter = wcslen(pszPrinter);
3045  }
3046  else
3047  {
3048  // If there is already a default printer, we're done!
3049  cchPrinter = _countof(wszPrinter);
3050  if (GetDefaultPrinterW(wszPrinter, &cchPrinter))
3051  {
3052  dwErrorCode = ERROR_SUCCESS;
3053  goto Cleanup;
3054  }
3055 
3056  // Otherwise, get us the first printer from the "Devices" key to later set it as default and query the value data size.
3057  cchPrinter = _countof(wszPrinter);
3058  dwErrorCode = (DWORD)RegEnumValueW(hDevicesKey, 0, wszPrinter, &cchPrinter, NULL, NULL, NULL, &cbPrinterValueData);
3059  if (dwErrorCode != ERROR_MORE_DATA)
3060  goto Cleanup;
3061 
3062  pszPrinter = wszPrinter;
3063  }
3064 
3065  // We now need to query the value data, which has the format "winspool,<Port>:"
3066  // and make "<Printer Name>,winspool,<Port>:" out of it.
3067  // Allocate a buffer large enough for the final data.
3068  cbDeviceValueData = (cchPrinter + 1) * sizeof(WCHAR) + cbPrinterValueData;
3069  pwszDeviceValueData = HeapAlloc(hProcessHeap, 0, cbDeviceValueData);
3070  if (!pwszDeviceValueData)
3071  {
3072  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3073  ERR("HeapAlloc failed!\n");
3074  goto Cleanup;
3075  }
3076 
3077  // Copy the Printer Name and a comma into it.
3078  CopyMemory(pwszDeviceValueData, pszPrinter, cchPrinter * sizeof(WCHAR));
3079  pwszDeviceValueData[cchPrinter] = L',';
3080 
3081  // Append the value data, which has the format "winspool,<Port>:"
3082  dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, (PBYTE)&pwszDeviceValueData[cchPrinter + 1], &cbPrinterValueData);
3083  if (dwErrorCode != ERROR_SUCCESS)
3084  goto Cleanup;
3085 
3086  // Open the Windows registry key.
3087  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_SET_VALUE, &hWindowsKey);
3088  if (dwErrorCode != ERROR_SUCCESS)
3089  {
3090  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
3091  goto Cleanup;
3092  }
3093 
3094  // Store our new default printer.
3095  dwErrorCode = (DWORD)RegSetValueExW(hWindowsKey, wszDeviceValue, 0, REG_SZ, (PBYTE)pwszDeviceValueData, cbDeviceValueData);
3096  if (dwErrorCode != ERROR_SUCCESS)
3097  {
3098  ERR("RegSetValueExW failed with status %lu!\n", dwErrorCode);
3099  goto Cleanup;
3100  }
3101 
3102 Cleanup:
3103  if (hDevicesKey)
3104  RegCloseKey(hDevicesKey);
3105 
3106  if (hWindowsKey)
3107  RegCloseKey(hWindowsKey);
3108 
3109  if (pwszDeviceValueData)
3110  HeapFree(hProcessHeap, 0, pwszDeviceValueData);
3111 
3112  SetLastError(dwErrorCode);
3113  return (dwErrorCode == ERROR_SUCCESS);
3114 }
3115 
3116 BOOL WINAPI
3118 {
3119  BOOL Ret = FALSE;
3120  UNICODE_STRING usBuffer;
3121  PPRINTER_INFO_STRESS ppisa = (PPRINTER_INFO_STRESS)pPrinter;
3122  PPRINTER_INFO_STRESS ppisw = (PPRINTER_INFO_STRESS)pPrinter;
3123  PPRINTER_INFO_2A ppi2a = (PPRINTER_INFO_2A)pPrinter;
3124  PPRINTER_INFO_2W ppi2w = (PPRINTER_INFO_2W)pPrinter;
3125  PPRINTER_INFO_7A ppi7a = (PPRINTER_INFO_7A)pPrinter;
3126  PPRINTER_INFO_7W ppi7w = (PPRINTER_INFO_7W)pPrinter;
3127  PPRINTER_INFO_9A ppi9a = (PPRINTER_INFO_9A)pPrinter;
3128  PPRINTER_INFO_9W ppi9w = (PPRINTER_INFO_9W)pPrinter;
3129  PWSTR pwszPrinterName = NULL;
3130  PWSTR pwszServerName = NULL;
3131  PWSTR pwszShareName = NULL;
3132  PWSTR pwszPortName = NULL;
3133  PWSTR pwszDriverName = NULL;
3134  PWSTR pwszComment = NULL;
3135  PWSTR pwszLocation = NULL;
3136  PWSTR pwszSepFile = NULL;
3137  PWSTR pwszPrintProcessor = NULL;
3138  PWSTR pwszDatatype = NULL;
3139  PWSTR pwszParameters = NULL;
3140  PDEVMODEW pdmw = NULL;
3141 
3142  FIXME("SetPrinterA(%p, %lu, %p, %lu)\n", hPrinter, Level, pPrinter, Command);
3143 
3144  switch ( Level )
3145  {
3146  case 0:
3147  if ( Command == 0 )
3148  {
3149  if (ppisa->pPrinterName)
3150  {
3151  pwszPrinterName = AsciiToUnicode(&usBuffer, (LPCSTR)ppisa->pPrinterName);
3152  if (!(ppisw->pPrinterName = pwszPrinterName)) goto Cleanup;
3153  }
3154  if (ppisa->pServerName)
3155  {
3156  pwszServerName = AsciiToUnicode(&usBuffer, (LPCSTR)ppisa->pServerName);
3157  if (!(ppisw->pPrinterName = pwszServerName)) goto Cleanup;
3158  }
3159  }
3161  {
3162  // Set the pPrinter parameter to a pointer to a DWORD value that specifies the new printer status.
3163  PRINTER_INFO_6 pi6;
3164  pi6.dwStatus = (DWORD_PTR)pPrinter;
3165  pPrinter = (LPBYTE)&pi6;
3166  Level = 6;
3167  Command = 0;
3168  }
3169  break;
3170  case 2:
3171  {
3172  if (ppi2a->pShareName)
3173  {
3174  pwszShareName = AsciiToUnicode(&usBuffer, ppi2a->pShareName);
3175  if (!(ppi2w->pShareName = pwszShareName)) goto Cleanup;
3176  }
3177  if (ppi2a->pPortName)
3178  {
3179  pwszPortName = AsciiToUnicode(&usBuffer, ppi2a->pPortName);
3180  if (!(ppi2w->pPortName = pwszPortName)) goto Cleanup;
3181  }
3182  if (ppi2a->pDriverName)
3183  {
3184  pwszDriverName = AsciiToUnicode(&usBuffer, ppi2a->pDriverName);
3185  if (!(ppi2w->pDriverName = pwszDriverName)) goto Cleanup;
3186  }
3187  if (ppi2a->pComment)
3188  {
3189  pwszComment = AsciiToUnicode(&usBuffer, ppi2a->pComment);
3190  if (!(ppi2w->pComment = pwszComment)) goto Cleanup;
3191  }
3192  if (ppi2a->pLocation)
3193  {
3194  pwszLocation = AsciiToUnicode(&usBuffer, ppi2a->pLocation);
3195  if (!(ppi2w->pLocation = pwszLocation)) goto Cleanup;
3196  }
3197  if (ppi2a->pSepFile)
3198  {
3199  pwszSepFile = AsciiToUnicode(&usBuffer, ppi2a->pSepFile);
3200  if (!(ppi2w->pSepFile = pwszSepFile)) goto Cleanup;
3201  }
3202  if (ppi2a->pServerName)
3203  {
3204  pwszPrintProcessor = AsciiToUnicode(&usBuffer, ppi2a->pPrintProcessor);
3205  if (!(ppi2w->pPrintProcessor = pwszPrintProcessor)) goto Cleanup;
3206  }
3207  if (ppi2a->pDatatype)
3208  {
3209  pwszDatatype = AsciiToUnicode(&usBuffer, ppi2a->pDatatype);
3210  if (!(ppi2w->pDatatype = pwszDatatype)) goto Cleanup;
3211  }
3212  if (ppi2a->pParameters)
3213  {
3214  pwszParameters = AsciiToUnicode(&usBuffer, ppi2a->pParameters);
3215  if (!(ppi2w->pParameters = pwszParameters)) goto Cleanup;
3216  }
3217 
3218  if ( ppi2a->pDevMode )
3219  {
3221  ppi2w->pDevMode = pdmw;
3222  }
3223  }
3224  //
3225  // These two strings are relitive and common to these three Levels.
3226  // Fall through...
3227  //
3228  case 4:
3229  case 5:
3230  {
3231  if (ppi2a->pServerName) // 4 & 5 : pPrinterName.
3232  {
3233  pwszServerName = AsciiToUnicode(&usBuffer, ppi2a->pServerName);
3234  if (!(ppi2w->pPrinterName = pwszServerName)) goto Cleanup;
3235  }
3236  if (ppi2a->pPrinterName) // 4 : pServerName, 5 : pPortName.
3237  {
3238  pwszPrinterName = AsciiToUnicode(&usBuffer, ppi2a->pPrinterName);
3239  if (!(ppi2w->pPrinterName = pwszPrinterName)) goto Cleanup;
3240  }
3241  }
3242  break;
3243  case 3:
3244  case 6:
3245  break;
3246  case 7:
3247  {
3248  if (ppi7a->pszObjectGUID)
3249  {
3250  pwszPrinterName = AsciiToUnicode(&usBuffer, ppi7a->pszObjectGUID);
3251  if (!(ppi7w->pszObjectGUID = pwszPrinterName)) goto Cleanup;
3252  }
3253  }
3254  break;
3255 
3256  case 8:
3257  /* 8 is the global default printer info and 9 already sets it instead of the per-user one */
3258  /* still, PRINTER_INFO_8W is the same as PRINTER_INFO_9W */
3259  /* fall through */
3260  case 9:
3261  {
3263  ppi9w->pDevMode = pdmw;
3264  }
3265  break;
3266 
3267  default:
3268  FIXME( "Unsupported level %d\n", Level);
3270  }
3271 
3272  Ret = SetPrinterW( hPrinter, Level, pPrinter, Command );
3273 
3274 Cleanup:
3275  if (pdmw) HeapFree(hProcessHeap, 0, pdmw);
3276  if (pwszPrinterName) HeapFree(hProcessHeap, 0, pwszPrinterName);
3277  if (pwszServerName) HeapFree(hProcessHeap, 0, pwszServerName);
3278  if (pwszShareName) HeapFree(hProcessHeap, 0, pwszShareName);
3279  if (pwszPortName) HeapFree(hProcessHeap, 0, pwszPortName);
3280  if (pwszDriverName) HeapFree(hProcessHeap, 0, pwszDriverName);
3281  if (pwszComment) HeapFree(hProcessHeap, 0, pwszComment);
3282  if (pwszLocation) HeapFree(hProcessHeap, 0, pwszLocation);
3283  if (pwszSepFile) HeapFree(hProcessHeap, 0, pwszSepFile);
3284  if (pwszPrintProcessor) HeapFree(hProcessHeap, 0, pwszPrintProcessor);
3285  if (pwszDatatype) HeapFree(hProcessHeap, 0, pwszDatatype);
3286  if (pwszParameters) HeapFree(hProcessHeap, 0, pwszParameters);
3287  return Ret;
3288 }
3289 
3290 BOOL WINAPI
3292 {
3293  DWORD dwErrorCode;
3294  WINSPOOL_PRINTER_CONTAINER PrinterContainer;
3295  WINSPOOL_DEVMODE_CONTAINER DevModeContainer;
3296  WINSPOOL_SECURITY_CONTAINER SecurityContainer;
3298  DWORD size;
3299  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
3300 
3301  FIXME("SetPrinterW(%p, %lu, %p, %lu)\n", hPrinter, Level, pPrinter, Command);
3302 
3303  // Sanity checks
3304  if (!pHandle)
3305  return ERROR_INVALID_HANDLE;
3306 
3307  DevModeContainer.cbBuf = 0;
3308  DevModeContainer.pDevMode = NULL;
3309 
3310  SecurityContainer.cbBuf = 0;
3311  SecurityContainer.pSecurity = NULL;
3312 
3313  switch ( Level )
3314  {
3315  case 0:
3317  {
3318  // Set the pPrinter parameter to a pointer to a DWORD value that specifies the new printer status.
3319  PRINTER_INFO_6 pi6;
3320  pi6.dwStatus = (DWORD_PTR)pPrinter;
3321  pPrinter = (LPBYTE)&pi6;
3322  Level = 6;
3323  Command = 0;
3324  }
3325  break;
3326  case 2:
3327  {
3328  PPRINTER_INFO_2W pi2w = (PPRINTER_INFO_2W)pPrinter;
3329  if ( pi2w )
3330  {
3331  if ( pi2w->pDevMode )
3332  {
3333  if ( IsValidDevmodeNoSizeW( pi2w->pDevMode ) )
3334  {
3335  DevModeContainer.cbBuf = pi2w->pDevMode->dmSize + pi2w->pDevMode->dmDriverExtra;
3336  DevModeContainer.pDevMode = (PBYTE)pi2w->pDevMode;
3337  }
3338  }
3339 
3340  if ( pi2w->pSecurityDescriptor )
3341  {
3342  sd = get_sd( pi2w->pSecurityDescriptor, &size );
3343  if ( sd )
3344  {
3345  SecurityContainer.cbBuf = size;
3346  SecurityContainer.pSecurity = (PBYTE)sd;
3347  }
3348  }
3349  }
3350  else
3351  {
3353  return FALSE;
3354  }
3355  }
3356  break;
3357  case 3:
3358  {
3359  PPRINTER_INFO_3 pi3 = (PPRINTER_INFO_3)pPrinter;
3360  if ( pi3 )
3361  {
3362  if ( pi3->pSecurityDescriptor )
3363  {
3364  sd = get_sd( pi3->pSecurityDescriptor, &size );
3365  if ( sd )
3366  {
3367  SecurityContainer.cbBuf = size;
3368  SecurityContainer.pSecurity = (PBYTE)sd;
3369  }
3370  }
3371  }
3372  else
3373  {
3375  return FALSE;
3376  }
3377  }
3378  break;
3379 
3380  case 4:
3381  case 5:
3382  case 6:
3383  case 7:
3384  if ( pPrinter == NULL )
3385  {
3387  return FALSE;
3388  }
3389  break;
3390 
3391  case 8:
3392  /* 8 is the global default printer info and 9 already sets it instead of the per-user one */
3393  /* still, PRINTER_INFO_8W is the same as PRINTER_INFO_9W */
3394  /* fall through */
3395  case 9:
3396  {
3397  PPRINTER_INFO_9W pi9w = (PPRINTER_INFO_9W)pPrinter;
3398  if ( pi9w )
3399  {
3400  if ( pi9w->pDevMode )
3401  {
3402  if ( IsValidDevmodeNoSizeW( pi9w->pDevMode ) )
3403  {
3404  DevModeContainer.cbBuf = pi9w->pDevMode->dmSize + pi9w->pDevMode->dmDriverExtra;
3405  DevModeContainer.pDevMode = (LPBYTE)pi9w->pDevMode;
3406  }
3407  }
3408  }
3409  }
3410  break;
3411 
3412  default:
3413  FIXME( "Unsupported level %d\n", Level );
3415  return FALSE;
3416  }
3417 
3418  PrinterContainer.PrinterInfo.pPrinterInfo1 = (WINSPOOL_PRINTER_INFO_1*)pPrinter;
3419  PrinterContainer.Level = Level;
3420 
3421  // Do the RPC call
3422  RpcTryExcept
3423  {
3424  dwErrorCode = _RpcSetPrinter(pHandle->hPrinter, &PrinterContainer, &DevModeContainer, &SecurityContainer, Command);
3425  }
3427  {
3428  dwErrorCode = RpcExceptionCode();
3429  }
3430  RpcEndExcept;
3431 
3432  if ( sd ) HeapFree( GetProcessHeap(), 0, sd );
3433 
3434  SetLastError(dwErrorCode);
3435  return (dwErrorCode == ERROR_SUCCESS);
3436 }
3437 
3438 BOOL WINAPI
3440 {
3441  TRACE("DriverUnloadComplete(%S)\n", pDriverFile);
3442  UNIMPLEMENTED;
3443  return TRUE; // return true for now.
3444 }
3445 BOOL WINAPI
3446 
3447 SpoolerPrinterEvent( LPWSTR pPrinterName, INT DriverEvent, DWORD Flags, LPARAM lParam )
3448 {
3449  HMODULE hLibrary;
3450  HANDLE hPrinter;
3451  BOOL Ret = FALSE;
3452 
3453  if ( OpenPrinterW( pPrinterName, &hPrinter, NULL ) )
3454  {
3455  hLibrary = LoadPrinterDriver( hPrinter );
3456 
3457  if ( hLibrary )
3458  {
3459  fpPrinterEvent = (PVOID)GetProcAddress( hLibrary, "DrvPrinterEvent" );
3460 
3461  if ( fpPrinterEvent )
3462  {
3463  Ret = fpPrinterEvent( pPrinterName, DriverEvent, Flags, lParam );
3464  }
3465 
3467  }
3468 
3469  ClosePrinter( hPrinter );
3470  }
3471 
3472  return Ret;
3473 }
3474 
3476 {
3477  LPWSTR filename;
3478 
3479  switch(msg)
3480  {
3481  case WM_INITDIALOG:
3483  return TRUE;
3484 
3485  case WM_COMMAND:
3486  if(HIWORD(wparam) == BN_CLICKED)
3487  {
3488  if(LOWORD(wparam) == IDOK)
3489  {
3490  HANDLE hf;
3492  LPWSTR *output;
3493 
3494  filename = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
3496 
3498  {
3499  WCHAR caption[200], message[200];
3500  int mb_ret;
3501 
3502  LoadStringW(hinstWinSpool, IDS_CAPTION, caption, ARRAYSIZE(caption));
3504  mb_ret = MessageBoxW(hwnd, message, caption, MB_OKCANCEL | MB_ICONEXCLAMATION);
3505  if(mb_ret == IDCANCEL)
3506  {
3508  return TRUE;
3509  }
3510  }
3512  if(hf == INVALID_HANDLE_VALUE)
3513  {
3514  WCHAR caption[200], message[200];
3515 
3516  LoadStringW(hinstWinSpool, IDS_CAPTION, caption, ARRAYSIZE(caption));
3520  return TRUE;
3521  }
3522  CloseHandle(hf);
3525  *output = filename;
3526  EndDialog(hwnd, IDOK);
3527  return TRUE;
3528  }
3529  if(LOWORD(wparam) == IDCANCEL)
3530  {
3532  return TRUE;
3533  }
3534  }
3535  return FALSE;
3536  }
3537  return FALSE;
3538 }
3539 
3540 static const WCHAR FILE_Port[] = {'F','I','L','E',':',0};
3541 
3542 LPWSTR WINAPI
3543 StartDocDlgW( HANDLE hPrinter, DOCINFOW *doc )
3544 {
3545  LPWSTR ret = NULL;
3546  DWORD len, attr, retDlg;
3547 
3548  FIXME("StartDocDlgW(%p, %p)\n", hPrinter, doc);
3549 
3550  if (doc->lpszOutput == NULL) /* Check whether default port is FILE: */
3551  {
3552  PRINTER_INFO_5W *pi5;
3553  GetPrinterW(hPrinter, 5, NULL, 0, &len);
3555  return NULL;
3556  pi5 = HeapAlloc(GetProcessHeap(), 0, len);
3557  GetPrinterW(hPrinter, 5, (LPBYTE)pi5, len, &len);
3558  if (!pi5->pPortName || wcsicmp(pi5->pPortName, FILE_Port))
3559  {
3560  HeapFree(GetProcessHeap(), 0, pi5);
3561  return NULL;
3562  }
3563  HeapFree(GetProcessHeap(), 0, pi5);
3564  }
3565 
3566  if (doc->lpszOutput == NULL || !wcsicmp(doc->lpszOutput, FILE_Port))
3567  {
3568  LPWSTR name;
3569 
3570  retDlg = DialogBoxParamW( hinstWinSpool,
3573  file_dlg_proc,
3574  (LPARAM)&name );
3575 
3576  if ( retDlg == IDOK )
3577  {
3578  if (!(len = GetFullPathNameW(name, 0, NULL, NULL)))
3579  {
3580  HeapFree(GetProcessHeap(), 0, name);
3581  return NULL;
3582  }
3583  ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3585  HeapFree(GetProcessHeap(), 0, name);
3586  }
3587  else if ( retDlg == 0 ) // FALSE, some type of error occurred.
3588  {
3589  ret = (LPWSTR)SP_ERROR;
3590  }
3591  else if ( retDlg == IDCANCEL )
3592  {
3594  ret = (LPWSTR)SP_APPABORT;
3595  }
3596  return ret;
3597  }
3598 
3599  if (!(len = GetFullPathNameW(doc->lpszOutput, 0, NULL, NULL)))
3600  return NULL;
3601 
3602  ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3604 
3607  {
3608  HeapFree(GetProcessHeap(), 0, ret);
3609  ret = NULL;
3610  }
3611  return ret;
3612 }
3613 
3614 LPSTR WINAPI
3615 StartDocDlgA( HANDLE hPrinter, DOCINFOA *doc )
3616 {
3617  UNICODE_STRING usBuffer;
3618  DOCINFOW docW = { 0 };
3619  LPWSTR retW;
3620  LPWSTR docnameW = NULL, outputW = NULL, datatypeW = NULL;
3621  LPSTR ret = NULL;
3622 
3623  docW.cbSize = sizeof(docW);
3624  if (doc->lpszDocName)
3625  {
3626  docnameW = AsciiToUnicode(&usBuffer, doc->lpszDocName);
3627  if (!(docW.lpszDocName = docnameW)) goto failed;
3628  }
3629  if (doc->lpszOutput)
3630  {
3631  outputW = AsciiToUnicode(&usBuffer, doc->lpszOutput);
3632  if (!(docW.lpszOutput = outputW)) goto failed;
3633  }
3634  if (doc->lpszDatatype)
3635  {
3636  datatypeW = AsciiToUnicode(&usBuffer, doc->lpszDatatype);
3637  if (!(docW.lpszDatatype = datatypeW)) goto failed;
3638  }
3639  docW.fwType = doc->fwType;
3640 
3641  retW = StartDocDlgW(hPrinter, &docW);
3642 
3643  if (retW)
3644  {
3645  DWORD len = WideCharToMultiByte(CP_ACP, 0, retW, -1, NULL, 0, NULL, NULL);
3646  ret = HeapAlloc(GetProcessHeap(), 0, len);
3647  WideCharToMultiByte(CP_ACP, 0, retW, -1, ret, len, NULL, NULL);
3648  HeapFree(GetProcessHeap(), 0, retW);
3649  }
3650 
3651 failed:
3653  if (outputW) HeapFree(GetProcessHeap(), 0, outputW);
3654  if (docnameW) HeapFree(GetProcessHeap(), 0, docnameW);
3655 
3656  return ret;
3657 }
3658 
3659 DWORD WINAPI
3661 {
3662  DOC_INFO_1W wDocInfo1 = { 0 };
3663  DWORD cch;
3664  DWORD dwErrorCode;
3665  DWORD dwReturnValue = 0;
3666  PDOC_INFO_1A pDocInfo1 = (PDOC_INFO_1A)pDocInfo;
3667 
3668  TRACE("StartDocPrinterA(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
3669 
3670  // Only check the minimum required for accessing pDocInfo.
3671  // Additional sanity checks are done in StartDocPrinterW.
3672  if (!pDocInfo1)
3673  {
3674  dwErrorCode = ERROR_INVALID_PARAMETER;
3675  goto Cleanup;
3676  }
3677 
3678  if (Level != 1)
3679  {
3680  ERR("Level = %d, unsupported!\n", Level);
3681  dwErrorCode = ERROR_INVALID_LEVEL;
3682  goto Cleanup;
3683  }
3684 
3685  if (pDocInfo1->pDatatype)
3686  {
3687  // Convert pDocInfo1->pDatatype to a Unicode string wDocInfo1.pDatatype
3688  cch = strlen(pDocInfo1->pDatatype);
3689 
3690  wDocInfo1.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
3691  if (!wDocInfo1.pDatatype)
3692  {
3693  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3694  ERR("HeapAlloc failed!\n");
3695  goto Cleanup;
3696  }
3697 
3698  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDatatype, -1, wDocInfo1.pDatatype, cch + 1);
3699  }
3700 
3701  if (pDocInfo1->pDocName)
3702  {
3703  // Convert pDocInfo1->pDocName to a Unicode string wDocInfo1.pDocName
3704  cch = strlen(pDocInfo1->pDocName);
3705 
3706  wDocInfo1.pDocName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
3707  if (!wDocInfo1.pDocName)
3708  {
3709  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3710  ERR("HeapAlloc failed!\n");
3711  goto Cleanup;
3712  }
3713 
3714  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDocName, -1, wDocInfo1.pDocName, cch + 1);
3715  }
3716 
3717  if (pDocInfo1->pOutputFile)
3718  {
3719  // Convert pDocInfo1->pOutputFile to a Unicode string wDocInfo1.pOutputFile
3720  cch = strlen(pDocInfo1->pOutputFile);
3721 
3722  wDocInfo1.pOutputFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
3723  if (!wDocInfo1.pOutputFile)
3724  {
3725  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3726  ERR("HeapAlloc failed!\n");
3727  goto Cleanup;
3728  }
3729 
3730  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pOutputFile, -1, wDocInfo1.pOutputFile, cch + 1);
3731  }
3732 
3733  dwReturnValue = StartDocPrinterW(hPrinter, Level, (PBYTE)&wDocInfo1);
3734  dwErrorCode = GetLastError();
3735 
3736 Cleanup:
3737  if (wDocInfo1.pDatatype)
3738  HeapFree(hProcessHeap, 0, wDocInfo1.pDatatype);
3739 
3740  if (wDocInfo1.pDocName)
3741  HeapFree(hProcessHeap, 0, wDocInfo1.pDocName);
3742 
3743  if (wDocInfo1.pOutputFile)
3744  HeapFree(hProcessHeap, 0, wDocInfo1.pOutputFile);
3745 
3746  SetLastError(dwErrorCode);
3747  return dwReturnValue;
3748 }
3749 
3750 DWORD WINAPI
3752 {
3753  DWORD cbAddJobInfo1;
3754  DWORD cbNeeded;
3755  DWORD dwErrorCode;
3756  DWORD dwReturnValue = 0;
3757  PADDJOB_INFO_1W pAddJobInfo1 = NULL;
3758  PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo;
3759  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
3760 
3761  TRACE("StartDocPrinterW(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
3762 
3763  // Sanity checks.
3764  if (!pHandle)
3765  {
3766  dwErrorCode = ERROR_INVALID_HANDLE;
3767  goto Cleanup;
3768  }
3769 
3770  if (!pDocInfo1)
3771  {
3772  dwErrorCode = ERROR_INVALID_PARAMETER;
3773  goto Cleanup;
3774  }
3775 
3776  if (Level != 1)
3777  {
3778  ERR("Level = %d, unsupported!\n", Level);
3779  dwErrorCode = ERROR_INVALID_LEVEL;
3780  goto Cleanup;
3781  }
3782 
3783  if (pHandle->bStartedDoc)
3784  {
3785  dwErrorCode = ERROR_INVALID_PRINTER_STATE;
3786  goto Cleanup;
3787  }
3788 
3789  // Check if we want to redirect output into a file.
3790  if (pDocInfo1->pOutputFile)
3791  {
3792  // Do a StartDocPrinter RPC call in this case.
3793  dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1);
3794  }
3795  else
3796  {
3797  // Allocate memory for the ADDJOB_INFO_1W structure and a path.
3798  cbAddJobInfo1 = sizeof(ADDJOB_INFO_1W) + MAX_PATH * sizeof(WCHAR);
3799  pAddJobInfo1 = HeapAlloc(hProcessHeap, 0, cbAddJobInfo1);
3800  if (!pAddJobInfo1)
3801  {
3802  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3803  ERR("HeapAlloc failed!\n");
3804  goto Cleanup;
3805  }
3806 
3807  // Try to add a new job.
3808  // This only succeeds if the printer is set to do spooled printing.
3809  if (AddJobW((HANDLE)pHandle, 1, (PBYTE)pAddJobInfo1, cbAddJobInfo1, &cbNeeded))
3810  {
3811  // Do spooled printing.
3812  dwErrorCode = _StartDocPrinterSpooled(pHandle, pDocInfo1, pAddJobInfo1);
3813  }
3814  else if (GetLastError() == ERROR_INVALID_ACCESS)
3815  {
3816  // ERROR_INVALID_ACCESS is returned when the printer is set to do direct printing.
3817  // In this case, we do a StartDocPrinter RPC call.
3818  dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1);
3819  }
3820  else
3821  {
3822  dwErrorCode = GetLastError();
3823  ERR("AddJobW failed with error %lu!\n", dwErrorCode);
3824  goto Cleanup;
3825  }
3826  }
3827 
3828  if (dwErrorCode == ERROR_SUCCESS)
3829  {
3830  pHandle->bStartedDoc = TRUE;
3831  dwReturnValue = pHandle->dwJobID;
3832  if ( !pHandle->bTrayIcon )
3833  {
3834  UpdateTrayIcon( hPrinter, pHandle->dwJobID );
3835  }
3836  }
3837 
3838 Cleanup:
3839  if (pAddJobInfo1)
3840  HeapFree(hProcessHeap, 0, pAddJobInfo1);
3841 
3842  SetLastError(dwErrorCode);
3843  return dwReturnValue;
3844 }
3845 
3846 BOOL WINAPI
3848 {
3849  DWORD dwErrorCode;
3850  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
3851 
3852  TRACE("StartPagePrinter(%p)\n", hPrinter);
3853 
3854  // Sanity checks.
3855  if (!pHandle)
3856  {
3857  dwErrorCode = ERROR_INVALID_HANDLE;
3858  goto Cleanup;
3859  }
3860 
3861  // Do the RPC call
3862  RpcTryExcept
3863  {
3864  dwErrorCode = _RpcStartPagePrinter(pHandle->hPrinter);
3865  }
3867  {
3868  dwErrorCode = RpcExceptionCode();
3869  ERR("_RpcStartPagePrinter failed with exception code %lu!\n", dwErrorCode);
3870  }
3871  RpcEndExcept;
3872 
3873 Cleanup:
3874  SetLastError(dwErrorCode);
3875  return (dwErrorCode == ERROR_SUCCESS);
3876 }
3877 
3878 BOOL WINAPI
3879 WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
3880 {
3881  DWORD dwErrorCode;
3882  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
3883 
3884  TRACE("WritePrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pcWritten);
3885 
3886  // Sanity checks.
3887  if (!pHandle)
3888  {
3889  dwErrorCode = ERROR_INVALID_HANDLE;
3890  goto Cleanup;
3891  }
3892 
3893  if (!pHandle->bStartedDoc)
3894  {
3895  dwErrorCode = ERROR_SPL_NO_STARTDOC;
3896  goto Cleanup;
3897  }
3898 
3899  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
3900  {
3901  // Write to the spool file. This doesn't need an RPC request.
3902  if (!WriteFile(pHandle->hSPLFile, pBuf, cbBuf, pcWritten, NULL))
3903  {
3904  dwErrorCode = GetLastError();
3905  ERR("WriteFile failed with error %lu!\n", dwErrorCode);
3906  goto Cleanup;
3907  }
3908 
3909  dwErrorCode = ERROR_SUCCESS;
3910  }
3911  else
3912  {
3913  // TODO: This case (for direct printing or remote printing) has bad performance if multiple small-sized WritePrinter calls are performed.
3914  // We may increase performance by writing into a buffer and only doing a single RPC call when the buffer is full.
3915 
3916  // Do the RPC call
3917  RpcTryExcept
3918  {
3919  dwErrorCode = _RpcWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten);
3920  }
3922  {
3923  dwErrorCode = RpcExceptionCode();
3924  ERR("_RpcWritePrinter failed with exception code %lu!\n", dwErrorCode);
3925  }
3926  RpcEndExcept;
3927  }
3928 
3929 Cleanup:
3930  SetLastError(dwErrorCode);
3931  return (dwErrorCode == ERROR_SUCCESS);
3932 }
3933 
3934 BOOL WINAPI
3935 XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
3936 {
3937  DWORD dwErrorCode, Bogus = 0;
3939 
3940  TRACE("XcvDataW(%p, %S, %p, %lu, %p, %lu, %p, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
3941 
3942  if ( pcbOutputNeeded == NULL )
3943  {
3944  dwErrorCode = ERROR_INVALID_PARAMETER;
3945  goto Cleanup;
3946  }
3947 
3948  // Sanity checks.
3949  if (!pHandle) // ( IntProtectHandle( hXcv, FALSE ) )
3950  {
3951  dwErrorCode = ERROR_INVALID_HANDLE;
3952  goto Cleanup;
3953  }
3954 
3955  //
3956  // Do fixups.
3957  //
3958  if ( pInputData == NULL )
3959  {
3960  if ( !cbInputData )
3961  {
3962  pInputData = (PBYTE)&Bogus;
3963  }
3964  }
3965 
3966  if ( pOutputData == NULL )
3967  {
3968  if ( !cbOutputData )
3969  {
3970  pOutputData = (PBYTE)&Bogus;
3971  }
3972  }
3973 
3974  // Do the RPC call
3975  RpcTryExcept
3976  {
3977  dwErrorCode = _RpcXcvData( pHandle->hPrinter,
3978  pszDataName,
3979  pInputData,
3980  cbInputData,
3981  pOutputData,
3982  cbOutputData,
3983  pcbOutputNeeded,
3984  pdwStatus );
3985  }
3987  {
3988  dwErrorCode = RpcExceptionCode();
3989  ERR("_RpcXcvData failed with exception code %lu!\n", dwErrorCode);
3990  }
3991  RpcEndExcept;
3992 
3993  //IntUnprotectHandle( hXcv );
3994 
3995 Cleanup:
3996  SetLastError(dwErrorCode);
3997  return (dwErrorCode == ERROR_SUCCESS);
3998 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SP_ERROR
Definition: wingdi.h:317
DWORD _RpcSeekPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite)
Definition: printers.c:293
#define WM_GETTEXTLENGTH
Definition: winuser.h:1601
BOOL WINAPI EnumPrintersW(DWORD Flags, PWSTR Name, DWORD Level, PBYTE pPrinterEnum, DWORD cbBuf, PDWORD pcbNeeded, PDWORD pcReturned)
Definition: printers.c:247
DWORD _RpcStartPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:338
union _WINSPOOL_DOC_INFO_CONTAINER::@3395 DocInfo
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 DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
static HRESULT get_sd(SECURITY_DESCRIPTOR **sd, DWORD *size)
Definition: security.c:61
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define PRINTER_CONTROL_SET_STATUS
Definition: winspool.h:180
WINBOOL WINAPI ScheduleJob(HANDLE hPrinter, DWORD JobId)
Definition: jobs.c:56
LPWSTR pDocName
Definition: winspool.h:616
PWSTR WINAPI AllocSplStr(PCWSTR pwszInput)
Definition: memory.c:56
BOOL WINAPI ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
Definition: printers.c:397
#define RpcEndExcept
Definition: rpc.h:128
static QUERYCOLORPROFILE fpQueryColorProfile
Definition: printers.c:30
#define IDS_CANNOT_OPEN
Definition: resource.h:5
Definition: tftpd.h:59
struct _PRINTER_INFO_7A * PPRINTER_INFO_7A
UINT WINAPI GetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPWSTR lpString, int nMaxCount)
Definition: dialog.c:2271
static UCHAR ULONG UCHAR ULONG UCHAR * output
Definition: bcrypt.c:29
#define IDOK
Definition: winuser.h:824
#define CloseHandle
Definition: compat.h:598
struct _devicemodeW * LPDEVMODEW
LONG(WINAPI * DOCUMENTPROPERTYSHEETS)(PPROPSHEETUI_INFO, LPARAM)
Definition: printers.c:23
#define IDI_CPSUI_DOCUMENT
Definition: compstui.h:88
LPCSTR pText
Definition: txtscale.cpp:79
LPSTR pPrinterName
Definition: winspool.h:110
INT_PTR WINAPI DialogBoxParamW(_In_opt_ HINSTANCE, _In_ LPCWSTR, _In_opt_ HWND, _In_opt_ DLGPROC, _In_ LPARAM)
struct _devicemodeW * PDEVMODEW
LONG WINAPI CallCommonPropertySheetUI(HWND hWnd, PFNPROPSHEETUI pfnPropSheetUI, LPARAM lparam, LPDWORD pResult)
Definition: printers.c:1131
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
#define WideCharToMultiByte
Definition: compat.h:111
static const WCHAR datatypeW[]
#define LoadLibrary
Definition: winbase.h:3702
#define KEY_SET_VALUE
Definition: nt_native.h:1017
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
struct _PRINTER_INFO_2W * PPRINTER_INFO_2W
#define DM_IN_PROMPT
Definition: windef.h:358
BOOL(WINAPI * DEVQUERYPRINT)(HANDLE, LPDEVMODEW, DWORD *)
Definition: printers.c:35
struct _PROPSHEETUI_INFO_HEADER * PPROPSHEETUI_INFO_HEADER
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
struct _PROPSHEETUI_INFO * PPROPSHEETUI_INFO
#define KEY_READ
Definition: nt_native.h:1023
#define TRUE
Definition: types.h:120
LPWSTR pDatatype
Definition: winspool.h:72
HANDLE hComPropSheet
Definition: compstui.h:889
uint16_t * PWSTR
Definition: typedefs.h:56
DWORD _RpcEndDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:85
#define ERR_CPSUI_ALLOCMEM_FAILED
Definition: compstui.h:645
#define CP_ACP
Definition: compat.h:109
DWORD WINAPI DeviceCapabilitiesW(LPCWSTR pDevice, LPCWSTR pPort, WORD fwCapability, LPWSTR pOutput, const DEVMODEW *pDevMode)
Definition: printers.c:573
#define HKEY_CURRENT_USER
Definition: winreg.h:11
LPSTR pServerName
Definition: winspool.h:38
#define EDITBOX
Definition: wspool.h:30
char CHAR
Definition: xmlstorage.h:175
BOOL WINAPI PrinterProperties(HWND hWnd, HANDLE hPrinter)
Definition: printers.c:1242
DWORD _RpcDeletePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:66
WINBOOL WINAPI GetJobW(HANDLE hPrinter, DWORD JobId, DWORD Level, LPBYTE pJob, DWORD cbBuf, LPDWORD pcbNeeded)
BOOL WINAPI DllFreeSplMem(PVOID pMem)
Definition: memory.c:112
#define ERROR_INVALID_HANDLE
Definition: compat.h:98
LPWSTR pOutputFile
Definition: winspool.h:617
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define PSUIHDRF_PROPTITLE
Definition: compstui.h:693
static HDC
Definition: imagelist.c:92
#define CALLBACK
Definition: compat.h:35
BOOL WINAPI GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
Definition: printers.c:1896
#define QSM_DOWNLOADINGFONTS
Definition: printers.c:2764
HWND hWnd
Definition: settings.c:17
BOOL WINAPI AbortPrinter(HANDLE hPrinter)
Definition: printers.c:11
struct _ADDJOB_INFO_1W ADDJOB_INFO_1W
LPDEVMODEA pDevMode
Definition: winspool.h:166
HANDLE HWND
Definition: compat.h:19
WORD dmDriverExtra
Definition: wingdi.h:1620
struct _DEVICEPROPERTYHEADER DEVICEPROPERTYHEADER
#define FILENAME_DIALOG
Definition: wspool.h:29
BOOL WINAPI SeekPrinter(HANDLE hPrinter, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER pliNewPointer, DWORD dwMoveMethod, BOOL bWrite)
Definition: printers.c:412
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#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:123
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
static SPOOLERPRINTEREVENT fpPrinterEvent
Definition: printers.c:33
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
#define ZeroMemory
Definition: winbase.h:1648
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1105
#define CPSUI_OK
Definition: compstui.h:640
DWORD WINAPI StartDocPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pDocInfo)
Definition: printers.c:442
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:55
LPDEVMODEW pDevMode
Definition: winspool.h:170
UINT_PTR WPARAM
Definition: windef.h:207
#define GetWindowLongPtrW
Definition: winuser.h:4804
BOOL WINAPI DevQueryPrintEx(PDEVQUERYPRINT_INFO pDQPInfo)
Definition: printers.c:636
Definition: shell.h:41
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
WINBOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, LPWSTR pEnvironment, DWORD Level, LPBYTE pDriverInfo, DWORD cbBuf, LPDWORD pcbNeeded)
int32_t INT_PTR
Definition: typedefs.h:64
struct _DEVQUERYPRINT_INFO * PDEVQUERYPRINT_INFO
BOOL WINAPI SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
Definition: printers.c:427
#define JOB_CONTROL_DELETE
Definition: winspool.h:334
LONG WINAPI IntProtectHandle(HANDLE, BOOL)
Definition: utils.c:105
char * LPSTR
Definition: xmlstorage.h:182
struct _PRINTER_INFO_3 * PPRINTER_INFO_3
BOOL(WINAPI * DEVQUERYPRINTEX)(PDEVQUERYPRINT_INFO)
Definition: printers.c:38
const char * filename
Definition: ioapi.h:135
#define BOOL
Definition: nt_native.h:43
#define FASTCALL
Definition: nt_native.h:50
DEVMODEW *WINAPI GdiConvertToDevmodeW(const DEVMODEA *)
Definition: misc.c:969
BOOL bStartedDoc
Definition: precomp.h:41
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
BOOL WINAPI ResetPrinterA(HANDLE hPrinter, PPRINTER_DEFAULTSA pDefault)
Definition: printers.c:2891
#define DWORD
Definition: nt_native.h:44
DWORD dwJobID
Definition: precomp.h:49
int32_t INT
Definition: typedefs.h:58
BOOL WINAPI EndDialog(_In_ HWND, _In_ INT_PTR)
struct _PRINTER_INFO_9W * PPRINTER_INFO_9W
struct _PRINTER_INFO_5A * PPRINTER_INFO_5A
#define FILE_SHARE_READ
Definition: compat.h:136
LONG(WINAPI * CONSTRUCTPRINTERFRIENDLYNAME)(PWSTR, PVOID, LPDWORD)
Definition: printers.c:45
LPCWSTR lpszOutput
Definition: wingdi.h:1684
#define IDS_CAPTION
Definition: resource.h:93
LPSTR pSepFile
Definition: winspool.h:46
LPWSTR pDriverName
Definition: winspool.h:66
#define DPS_NOPERMISSION
Definition: winddiui.h:123
LONG WINAPI DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode)
Definition: printers.c:1153
void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW *pDevModeOutput)
Definition: devmode.c:285
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define MB_ICONEXCLAMATION
Definition: winuser.h:779
#define IDS_FILE_EXISTS
Definition: wspool.h:26
LPDEVMODEW pDevMode
Definition: winspool.h:862
#define SPOOLER_HANDLE_SIG
Definition: precomp.h:32
LPSTR pShareName
Definition: winspool.h:40
DWORD _RpcAddPrinter(WINSPOOL_HANDLE pName, WINSPOOL_PRINTER_CONTAINER *pPrinterContainer, WINSPOOL_DEVMODE_CONTAINER *pDevModeContainer, WINSPOOL_SECURITY_CONTAINER *pSecurityContainer, WINSPOOL_PRINTER_HANDLE *pHandle)
Definition: printers.c:31
LPWSTR pLocation
Definition: winspool.h:68
static COMMONPROPERTYSHEETUIW fpCommonPropertySheetUIW
Definition: printers.c:27
#define PROPSHEETUI_REASON_GET_INFO_HEADER
Definition: compstui.h:628
struct _PRINTER_INFO_9A * PPRINTER_INFO_9A
DWORD _RpcStartDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, WINSPOOL_DOC_INFO_CONTAINER *pDocInfoContainer, DWORD *pJobId)
Definition: printers.c:319
LPSTR pComment
Definition: winspool.h:23
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
BOOL FASTCALL IntFixUpDevModeNames(PDOCUMENTPROPERTYHEADER pdphdr)
Definition: printers.c:815
unsigned char * LPBYTE
Definition: typedefs.h:53
BOOL WINAPI SpoolerPrinterEvent(LPWSTR pPrinterName, INT DriverEvent, DWORD Flags, LPARAM lParam)
Definition: printers.c:3447
LPWSTR pPrinterName
Definition: winspool.h:100
#define FALSE
Definition: types.h:117
HANDLE WINAPI AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter)
Definition: printers.c:105
unsigned int BOOL
Definition: ntddk_ex.h:94
WINSPOOL_PRINTER_INFO_1 * pPrinterInfo1
Definition: winspool.idl:698
BOOL WINAPI GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
Definition: printers.c:1942
long LONG
Definition: pedump.c:60
LONG(WINAPI * COMMONPROPERTYSHEETUIW)(HWND, PFNPROPSHEETUI, LPARAM, LPDWORD)
Definition: printers.c:26
#define DM_OUT_BUFFER
Definition: windef.h:359
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
LPWSTR pName
Definition: winspool.h:29
static UINT WPARAM LPARAM lparam
Definition: combo.c:716
#define GENERIC_WRITE
Definition: nt_native.h:90
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
PRINTER_INFO_9W * get_devmodeW(HANDLE hprn)
Definition: printers.c:746
#define FIXME(fmt,...)
Definition: debug.h:111
LPWSTR pShareName
Definition: winspool.h:64
#define RpcTryExcept
Definition: rpc.h:126
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
INT WINAPI DocumentEvent(HANDLE hPrinter, HDC hdc, int iEsc, ULONG cbIn, PVOID pvIn, ULONG cbOut, PVOID pvOut)
Definition: printers.c:658
PFNCOMPROPSHEET pfnComPropSheet
Definition: compstui.h:890
union _WINSPOOL_PRINTER_CONTAINER::@3401 PrinterInfo
LPWSTR pszPrinterName
Definition: printers.c:54
LPSTR pServerName
Definition: winspool.h:95
DWORD _RpcEndPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:104
#define ERROR_SPL_NO_STARTDOC
Definition: winerror.h:1208
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
DWORD WINAPI PrinterMessageBoxA(HANDLE hPrinter, DWORD Error, HWND hWnd, LPSTR pText, LPSTR pCaption, DWORD dwType)
Definition: printers.c:2692
DWORD _RpcXcvData(WINSPOOL_PRINTER_HANDLE hXcv, const WCHAR *pszDataName, BYTE *pInputData, DWORD cbInputData, BYTE *pOutputData, DWORD cbOutputData, DWORD *pcbOutputNeeded, DWORD *pdwStatus)
Definition: xcv.c:11
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:2931
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:201
#define ERR_CPSUI_GETLASTERROR
Definition: compstui.h:644
LPSTR pDriverName
Definition: winspool.h:42
struct _DOCUMENTPROPERTYHEADER * PDOCUMENTPROPERTYHEADER
_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
static DEVQUERYPRINTEX fpDevQueryPrintEx
Definition: printers.c:39
static DEVQUERYPRINT fpDevQueryPrint
Definition: printers.c:36
LONG_PTR LPARAM
Definition: windef.h:208
#define MB_OKCANCEL
Definition: winuser.h:798
struct _PRINTER_INFO_2A * PPRINTER_INFO_2A
static DWORD _StartDocPrinterWithRPC(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1)
Definition: printers.c:132
DWORD dwStatus
Definition: winspool.h:130
BOOL WINAPI PlayGdiScriptOnPrinterIC(_In_ HANDLE hPrinterIC, _In_reads_bytes_(cIn) LPBYTE pIn, _In_ DWORD cIn, _Out_writes_bytes_(cOut) LPBYTE pOut, _In_ DWORD cOut, _In_ DWORD ul)
struct _PRINTER_INFO_1W * PPRINTER_INFO_1W
const char * LPCSTR
Definition: xmlstorage.h:183
#define DM_NOPERMISSION
Definition: winddiui.h:139
void * PVOID
Definition: retypes.h:9
LPSTR pPrinterName
Definition: winspool.h:94
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
struct _COMPUI_USERDATA COMPUI_USERDATA
unsigned long FLONG
Definition: ntbasedef.h:366
BOOL WINAPI WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
Definition: printers.c:472
wstring AsciiToUnicode(const char *AsciiString)
Definition: tools.cpp:220
BOOL WINAPI GetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD cbBuf, PDWORD pcbNeeded)
Definition: printers.c:312
ULONG_PTR Result
Definition: compstui.h:893
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
FxDevice * pDevice
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
LPSTR pPrinterName
Definition: winspool.h:39
HANDLE hSPLFile
Definition: precomp.h:51
DWORD(WINAPI * DEVICECAPABILITIES)(HANDLE, PWSTR, WORD, PVOID, PDEVMODEW)
Definition: printers.c:18
struct _DOCUMENTPROPERTYHEADER DOCUMENTPROPERTYHEADER
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:176
#define RpcExceptionCode()
Definition: rpc.h:132
DWORD fwType
Definition: wingdi.h:1679
void RosConvertUnicodeDevModeToAnsiDevmode(PDEVMODEW pDevModeInput, PDEVMODEA pDevModeOutput)
Definition: devmode.c:353
HMODULE hModule
Definition: printers.c:53
#define TRACE(s)
Definition: solgame.cpp:4
#define FreeLibrary(x)
Definition: compat.h:607
static LPSTR pName
Definition: security.c:75
GLsizeiptr size
Definition: glext.h:5919
struct _COMPUI_USERDATA * PCOMPUI_USERDATA
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
LPCSTR lpszOutput
Definition: wingdi.h:1677
#define GetProcessHeap()
Definition: compat.h:595
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
PSECURITY_DESCRIPTOR pSecurityDescriptor
Definition: winspool.h:90
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
DWORD_PTR Sig
Definition: precomp.h:40
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
#define ASSERT(a)
Definition: mode.c:45
HANDLE hSpoolFileHandle
Definition: precomp.h:53
int WINAPI MessageBoxW(_In_opt_ HWND, _In_opt_ LPCWSTR, _In_opt_ LPCWSTR, _In_ UINT)
if(!(yy_init))
Definition: macro.lex.yy.c:714
__wchar_t WCHAR
Definition: xmlstorage.h:180
struct _PRINTER_INFO_1A * PPRINTER_INFO_1A
LPWSTR pDatatype
Definition: winspool.h:618
#define debugstr_a
Definition: kernel32.h:31
struct _DEVICEPROPERTYHEADER * PDEVICEPROPERTYHEADER
#define _countof(array)
Definition: sndvol32.h:68
LPDEVMODEA pDevMode
Definition: winspool.h:856
HANDLE WINAPI CreatePrinterIC(_In_ HANDLE hPrinter, _In_opt_ LPDEVMODEW pDevMode)
DWORD _RpcScheduleJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId)
Definition: jobs.c:110
static VOID UpdateTrayIcon(HWND hwnd, LPTSTR szLCID, LPTSTR szName)
Definition: kbswitch.c:137
BOOL WINAPI FlushPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten, DWORD cSleep)
Definition: printers.c:1888
WORD dmSize
Definition: wingdi.h:1619
#define MAX_PATH
Definition: compat.h:34
DWORD _RpcWritePrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE *pBuf, DWORD cbBuf, DWORD *pcWritten)
Definition: printers.c:357
static DEVICEPROPERTYSHEETS fpDevicePropertySheets
Definition: printers.c:22
#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
#define BN_CLICKED
Definition: winuser.h:1907
unsigned long DWORD
Definition: ntddk_ex.h:95
PVOID HANDLE
Definition: typedefs.h:73
ACCESS_MASK DesiredAccess
Definition: winspool.h:863
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
BOOL Error
Definition: chkdsk.c:66
#define SetLastError(x)
Definition: compat.h:611
DWORD _RpcReadPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE *pBuf, DWORD cbBuf, DWORD *pcNoBytesRead)
Definition: printers.c:225
BOOL(WINAPI * SPOOLERPRINTEREVENT)(LPWSTR, int, DWORD, LPARAM)
Definition: printers.c:32
Definition: cookie.c:201
LRESULT WINAPI SendDlgItemMessageW(_In_ HWND, _In_ int, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define MAX_PRINTER_NAME
Definition: fpSetJob.c:25
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
DWORD WINAPI PrinterMessageBoxW(HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType)
Definition: printers.c:330
LPARAM lParamInit
Definition: compstui.h:891
LPSTR pLocation
Definition: winspool.h:44
LPWSTR pSepFile
Definition: winspool.h:70
#define wcsicmp
Definition: compat.h:15
static const WCHAR sd[]
Definition: suminfo.c:287
struct _PRINTER_INFO_STRESS * PPRINTER_INFO_STRESS
LPCSTR lpszDatatype
Definition: wingdi.h:1678
#define DM_PROMPT
Definition: windef.h:354
int ret
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
static const WCHAR wszWindowsKey[]
Definition: printers.c:61
LPSTR pOutputFile
Definition: winspool.h:611
#define LPDWORD
Definition: nt_native.h:46
HMODULE WINAPI LoadPrinterDriver(HANDLE hspool)
Definition: printers.c:488
__u8 attr
Definition: mkdosfs.c:359
static const WCHAR L[]
Definition: oid.c:1250
HDC hdc
Definition: main.c:9
LPSTR pDatatype
Definition: winspool.h:612
#define DWLP_USER
Definition: winuser.h:866
LPWSTR pServerName
Definition: winspool.h:62
BOOL WINAPI OpenPrinterA(LPSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSA pDefault)
Definition: printers.c:2553