ReactOS  0.4.15-dev-1148-g8a4273b
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 
551  MultiByteToWideChar(CP_ACP, 0, pDevice, -1, pwszDeviceName, cch + 1);
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
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:487
struct _devicemodeW * LPDEVMODEW
LONG(WINAPI * DOCUMENTPROPERTYSHEETS)(PPROPSHEETUI_INFO, LPARAM)
Definition: printers.c:23
#define IDI_CPSUI_DOCUMENT
Definition: compstui.h:88
union _WINSPOOL_DOC_INFO_CONTAINER::@3401 DocInfo
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:479
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
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
DWORD _RpcStartDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, WINSPOOL_DOC_INFO_CONTAINER *pDocInfoContainer, DWORD *pJobId)
Definition: printers.c:319
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
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
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
smooth NULL
Definition: ftsmooth.c:416
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
union _WINSPOOL_PRINTER_CONTAINER::@3407 PrinterInfo
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:367
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
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:496
static LPSTR pName
Definition: security.c:75
GLsizeiptr size
Definition: glext.h:5919
struct _COMPUI_USERDATA * PCOMPUI_USERDATA
LPCSTR lpszOutput
Definition: wingdi.h:1677
#define GetProcessHeap()
Definition: compat.h:484
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
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:500
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
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
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
LPSTR pPortName
Definition: winspool.h:41
BOOL WINAPI DevQueryPrint(HANDLE hPrinter, LPDEVMODEW pDevMode, DWORD *pResID)
Definition: printers.c:614
BOOL WINAPI SetPrinterA(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
Definition: printers.c:3117
HMODULE hLibrary
Definition: odbccp32.c:12
BOOL WINAPI EndPagePrinter(HANDLE hPrinter)
Definition: printers.c:232
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
GLenum GLsizei len
Definition: glext.h:6722
BOOL WINAPI DeletePrinterIC(_In_ HANDLE hPrinterIC)
#define SP_APPABORT
Definition: wingdi.h:321
#define ERROR_INVALID_ACCESS
Definition: winerror.h:115
DWORD _RpcOpenPrinter(WINSPOOL_HANDLE pPrinterName, WINSPOOL_PRINTER_HANDLE *phPrinter, WCHAR *pDatatype, WINSPOOL_DEVMODE_CONTAINER *pDevModeContainer, DWORD AccessRequired)
Definition: printers.c:194
LPSTR pDescription
Definition: winspool.h:21
WINSPOOL_DOC_INFO_1 * pDocInfo1
Definition: winspool.idl:577
LONG(WINAPI * DEVICEPROPERTYSHEETS)(PPROPSHEETUI_INFO, LPARAM)
Definition: printers.c:21
HINSTANCE hinstWinSpool
Definition: