ReactOS  0.4.15-dev-506-ga3ec01c
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 %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");
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  TRACE("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  BOOL bReturnValue = -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  bReturnValue = DocumentPropertiesW(hWnd, hPrinter, pwszDeviceName, pdmwOutput, pdmwInput, fMode);
720  FIXME("bReturnValue from DocumentPropertiesW is '%ld'.\n", bReturnValue);
721 
722  if (pwszDeviceName)
723  {
725  }
726 
727  if (bReturnValue < 0)
728  {
729  FIXME("DocumentPropertiesW failed!\n");
730  goto Cleanup;
731  }
732 
733  if (pdmwOutput)
734  {
735  RosConvertUnicodeDevModeToAnsiDevmode(pdmwOutput, pDevModeOutput);
736  }
737 
738 Cleanup:
739  if(pwszDeviceName)
741 
742  if (pdmwInput)
743  HeapFree(hProcessHeap, 0, pdmwInput);
744 
745  if (pdmwOutput)
746  HeapFree(hProcessHeap, 0, pdmwOutput);
747 
748  return bReturnValue;
749 }
750 
752 {
753  PRINTER_INFO_9W *pi9 = NULL;
754  DWORD needed = 0;
755  BOOL res;
756 
757  res = GetPrinterW(hprn, 9, NULL, 0, &needed);
759  {
760  pi9 = HeapAlloc(hProcessHeap, 0, needed);
761  res = GetPrinterW(hprn, 9, (LPBYTE)pi9, needed, &needed);
762  }
763 
764  if (res)
765  return pi9;
766 
767  ERR("GetPrinterW failed with %u\n", GetLastError());
768  HeapFree(hProcessHeap, 0, pi9);
769  return NULL;
770 }
771 
772 BOOL
773 FASTCALL
774 CreateUIUserData( ULONG_PTR *puserdata, HANDLE hPrinter )
775 {
776  PCOMPUI_USERDATA pcui_ud = DllAllocSplMem( sizeof(COMPUI_USERDATA) );
777 
778  *puserdata = (ULONG_PTR)pcui_ud;
779  FIXME("CreateUIUserData\n");
780  if ( pcui_ud )
781  {
782  pcui_ud->hModule = LoadPrinterDriver( hPrinter );
783 
784  if ( !pcui_ud->hModule )
785  {
786  DllFreeSplMem( pcui_ud );
787  *puserdata = 0;
788  }
789  }
790  return *puserdata != 0;
791 }
792 
793 VOID
794 FASTCALL
796 {
797  PCOMPUI_USERDATA pcui_ud = (PCOMPUI_USERDATA)*puserdata;
798  FIXME("DestroyUIUserData\n");
799  if ( pcui_ud )
800  {
801  if ( pcui_ud->hModule )
802  {
803  FreeLibrary( pcui_ud->hModule );
804  pcui_ud->hModule = NULL;
805  }
806 
807  if ( pcui_ud->pszPrinterName )
808  {
809  DllFreeSplMem( pcui_ud->pszPrinterName );
810  pcui_ud->pszPrinterName = NULL;
811  }
812 
813  DllFreeSplMem( pcui_ud );
814  *puserdata = 0;
815  }
816 }
817 
818 BOOL
819 FASTCALL
821 {
822  PRINTER_INFO_2W *pi2 = NULL;
823  DWORD needed = 0;
824  BOOL res;
825 
826  if (!(pdphdr->fMode & DM_OUT_BUFFER) ||
827  pdphdr->fMode & DM_NOPERMISSION || // Do not allow the user to modify properties on the displayed property sheet pages.
828  !pdphdr->pdmOut )
829  {
830  return FALSE;
831  }
832 
833  res = GetPrinterW( pdphdr->hPrinter, 2, NULL, 0, &needed);
835  {
836  pi2 = HeapAlloc(hProcessHeap, 0, needed);
837  res = GetPrinterW( pdphdr->hPrinter, 2, (LPBYTE)pi2, needed, &needed);
838  }
839 
840  if (res)
841  {
842  FIXME("IFUDMN : Get Printer Name %S\n",pi2->pPrinterName);
844  pdphdr->pdmOut->dmDeviceName[CCHDEVICENAME-1] = 0;
845  }
846  else
847  {
848  ERR("IFUDMN : GetPrinterW failed with %u\n", GetLastError());
849  }
850  HeapFree(hProcessHeap, 0, pi2);
851  return res;
852 }
853 
854 LONG
855 WINAPI
857 {
858  LONG Result = 0;
859  DWORD Size = 0;
861 
862  hLibrary = LoadLibraryA( "printui.dll" );
863 
864  if ( hLibrary )
865  {
866  fpConstructPrinterFriendlyName = (PVOID)GetProcAddress( hLibrary, "ConstructPrinterFriendlyName" );
867 
869  {
870  if ( !fpConstructPrinterFriendlyName( pszPrinterName, NULL, &Size ) )
871  {
873  {
874  PWSTR pwstr = DllAllocSplMem( (Size + 1) * sizeof(WCHAR) );
875 
876  pcui_ud->pszPrinterName = pwstr;
877 
878  if ( pwstr )
879  Result = fpConstructPrinterFriendlyName( pszPrinterName, pwstr, &Size );
880  }
881  }
882  }
884  }
885 
886  if ( !Result )
887  {
888  DllFreeSplMem( pcui_ud->pszPrinterName );
889  pcui_ud->pszPrinterName = AllocSplStr( pszPrinterName );
890  }
891 
892  return Result;
893 }
894 
895 //
896 // Tested with XP CompstUI as a callback and works. Fails perfectly.
897 //
898 LONG
899 WINAPI
901 {
902  LONG Result = -1;
904 
905  FIXME("DocumentPropertySheets(%p, 0x%lx)\n", pCPSUIInfo, lparam);
906 
907  // If pPSUIInfo is NULL, and if either lParam -> fMode is zero or lParam -> pdmOut is NULL,
908  // this function should return the size, in bytes, of the printer's DEVMODEW structure.
909  if ( !pCPSUIInfo && lparam )
910  {
912 
913  if ( pdphdr->cbSize >= sizeof(PDOCUMENTPROPERTYHEADER) &&
914  !(pdphdr->fMode & DM_PROMPT) )
915  {
917 
918  if ( hLibrary )
919  {
920  fpDocumentPropertySheets = (PVOID)GetProcAddress( hLibrary, "DrvDocumentPropertySheets" );
921 
923  {
924  Result = fpDocumentPropertySheets( pCPSUIInfo, lparam );
925  }
926  else
927  {
928  //
929  // ReactOS backup!!! Currently no supporting UI driver.
930  //
931  PRINTER_INFO_9W * pi9 = get_devmodeW( pdphdr->hPrinter );
932  if ( pi9 )
933  {
934  Result = pi9->pDevMode->dmSize + pi9->pDevMode->dmDriverExtra;
935  FIXME("IDPS : Using ReactOS backup!!! DevMode Size %d\n",Result);
936  HeapFree(hProcessHeap, 0, pi9);
937  }
938  }
939 
941 
942  if ( Result > 0 )
943  {
944  IntFixUpDevModeNames( pdphdr );
945  }
946 
947  return Result;
948  }
949  else
950  {
952  }
953  }
954  else
955  {
957  }
958  return Result;
959  }
960 
961  Result = 0;
962 
963  if ( pCPSUIInfo )
964  {
965  PSETRESULT_INFO psri;
966  PPROPSHEETUI_INFO_HEADER ppsuiihdr;
967  PCOMPUI_USERDATA pcui_ud;
968  pdphdr = (PDOCUMENTPROPERTYHEADER)pCPSUIInfo->lParamInit;
969 
970  if ( pdphdr->cbSize < sizeof(PDOCUMENTPROPERTYHEADER) )
971  {
973  return Result;
974  }
975 
976  switch ( pCPSUIInfo->Reason )
977  {
979  {
980  FIXME("DocPS : PROPSHEETUI_REASON_INIT\n");
981  if ( CreateUIUserData( &pCPSUIInfo->UserData, pdphdr->hPrinter ) )
982  {
983  pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData;
984 
985  fpDocumentPropertySheets = (PVOID)GetProcAddress( pcui_ud->hModule, "DrvDocumentPropertySheets" );
986 
988  {
989  pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
991  -3, // What type of handle is this?
992  0 ); // Not used, must be zero.
993 
994  Result = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
997  pCPSUIInfo->lParamInit );
998  break;
999  }
1000  FIXME("DocPS : PROPSHEETUI_REASON_INIT Fail\n");
1001  DestroyUIUserData( &pCPSUIInfo->UserData );
1002  }
1003  }
1004  break;
1005 
1007  FIXME("DocPS : PROPSHEETUI_REASON_GET_INFO_HEADER\n");
1008 
1009  ppsuiihdr = (PPROPSHEETUI_INFO_HEADER)lparam;
1010 
1011  pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData;
1012 
1013  CreatePrinterFriendlyName( pcui_ud, pdphdr->pszPrinterName );
1014 
1016  ppsuiihdr->pTitle = pcui_ud->pszPrinterName;
1017  ppsuiihdr->hInst = hinstWinSpool;
1018  ppsuiihdr->IconID = IDI_CPSUI_DOCUMENT;
1019 
1020  Result = CPSUI_OK;
1021  break;
1022 
1024  FIXME("DocPS : PROPSHEETUI_REASON_DESTROY\n");
1025  DestroyUIUserData( &pCPSUIInfo->UserData );
1026  Result = CPSUI_OK;
1027  break;
1028 
1030  FIXME("DocPS : PROPSHEETUI_REASON_SET_RESULT\n");
1031 
1032  psri = (PSETRESULT_INFO)lparam;
1033 
1034  pCPSUIInfo->Result = psri->Result;
1035  if ( pCPSUIInfo->Result > 0 )
1036  {
1037  IntFixUpDevModeNames( pdphdr );
1038  }
1039  Result = CPSUI_OK;
1040  break;
1041  }
1042  }
1043  return Result;
1044 }
1045 
1046 LONG
1047 WINAPI
1049 {
1050  LONG Result = 0;
1051  PDEVICEPROPERTYHEADER pdphdr;
1052 
1053  FIXME("DevicePropertySheets(%p, 0x%lx)\n", pCPSUIInfo, lparam);
1054 
1055  if ( pCPSUIInfo )
1056  {
1057  PSETRESULT_INFO psri;
1058  PPROPSHEETUI_INFO_HEADER ppsuiihdr;
1059  PCOMPUI_USERDATA pcui_ud;
1060  pdphdr = (PDEVICEPROPERTYHEADER)pCPSUIInfo->lParamInit;
1061 
1062  if ( pdphdr->cbSize < sizeof(DEVICEPROPERTYHEADER) )
1063  {
1065  return Result;
1066  }
1067 
1068  switch ( pCPSUIInfo->Reason )
1069  {
1071  {
1072  FIXME("DevPS : PROPSHEETUI_REASON_INIT\n");
1073  if ( CreateUIUserData( &pCPSUIInfo->UserData, pdphdr->hPrinter ) )
1074  {
1075  pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData;
1076 
1077  fpDevicePropertySheets = (PVOID)GetProcAddress( pcui_ud->hModule, "DrvDevicePropertySheets" );
1078 
1079  if ( fpDevicePropertySheets )
1080  {
1081  pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
1083  -3, // What type of handle is this?
1084  0 ); // Not used, must be zero.
1085 
1086  Result = pCPSUIInfo->pfnComPropSheet( pCPSUIInfo->hComPropSheet,
1089  pCPSUIInfo->lParamInit );
1090  break;
1091  }
1092  FIXME("DevPS : PROPSHEETUI_REASON_INIT Fail\n");
1093  DestroyUIUserData( &pCPSUIInfo->UserData );
1094  }
1095  }
1096  break;
1097 
1099  FIXME("DevPS : PROPSHEETUI_REASON_GET_INFO_HEADER\n");
1100 
1101  ppsuiihdr = (PPROPSHEETUI_INFO_HEADER)lparam;
1102 
1103  pcui_ud = (PCOMPUI_USERDATA)pCPSUIInfo->UserData;
1104 
1105  CreatePrinterFriendlyName( pcui_ud, pdphdr->pszPrinterName );
1106 
1108  ppsuiihdr->pTitle = pcui_ud->pszPrinterName;
1109  ppsuiihdr->hInst = hinstWinSpool;
1110  ppsuiihdr->IconID = IDI_CPSUI_DOCUMENT;
1111 
1112  Result = CPSUI_OK;
1113  break;
1114 
1116  FIXME("DevPS : PROPSHEETUI_REASON_DESTROY\n");
1117  DestroyUIUserData( &pCPSUIInfo->UserData );
1118  Result = CPSUI_OK;
1119  break;
1120 
1122  FIXME("DevPS : PROPSHEETUI_REASON_SET_RESULT\n");
1123  psri = (PSETRESULT_INFO)lparam;
1124  pCPSUIInfo->Result = psri->Result;
1125  Result = CPSUI_OK;
1126  break;
1127  }
1128  }
1129  return Result;
1130 }
1131 
1132 LONG
1133 WINAPI
1135 {
1136  HMODULE hLibrary = NULL;
1138 
1139  FIXME("CallCommonPropertySheetUI(%p, %p, 0x%lx, %p)\n", hWnd, pfnPropSheetUI, lparam, pResult);
1140 
1141  if ( ( hLibrary = LoadLibraryA( "compstui.dll" ) ) )
1142  {
1143  fpCommonPropertySheetUIW = (PVOID) GetProcAddress(hLibrary, "CommonPropertySheetUIW");
1144 
1146  {
1147  Ret = fpCommonPropertySheetUIW( hWnd, pfnPropSheetUI, lparam, pResult );
1148  }
1149 
1151  }
1152  return Ret;
1153 }
1154 
1155 LONG WINAPI
1156 DocumentPropertiesW(HWND hWnd, HANDLE hPrinter, LPWSTR pDeviceName, PDEVMODEW pDevModeOutput, PDEVMODEW pDevModeInput, DWORD fMode)
1157 {
1158  HANDLE hUseHandle = NULL;
1159  DOCUMENTPROPERTYHEADER docprophdr;
1160  LONG Result = IDOK;
1161 
1162  FIXME("DocumentPropertiesW(%p, %p, %S, %p, %p, %lu)\n", hWnd, hPrinter, pDeviceName, pDevModeOutput, pDevModeInput, fMode);
1163 
1164  if (hPrinter)
1165  {
1166  hUseHandle = hPrinter;
1167  }
1168  else if (!OpenPrinterW(pDeviceName, &hUseHandle, NULL))
1169  {
1170  ERR("No handle, and no usable printer name passed in\n");
1171  return -1;
1172  }
1173 
1174  if ( !(fMode & DM_IN_BUFFER ) ||
1175  ( ( pDevModeInput && !IsValidDevmodeNoSizeW( (PDEVMODEW)pDevModeInput ) ) ) )
1176  {
1177  pDevModeInput = NULL;
1178  fMode &= ~DM_IN_BUFFER;
1179  }
1180 
1181  docprophdr.cbSize = sizeof(DOCUMENTPROPERTYHEADER);
1182  docprophdr.Reserved = 0;
1183  docprophdr.hPrinter = hUseHandle;
1184  docprophdr.pszPrinterName = pDeviceName;
1185  docprophdr.cbOut = 0;
1186 
1187  if ( pDevModeOutput )
1188  {
1189  docprophdr.pdmIn = NULL;
1190  docprophdr.pdmOut = NULL;
1191  docprophdr.fMode = 0;
1192  FIXME("DPW : Call DocumentPropertySheets with pDevModeOutput %p\n",pDevModeOutput);
1193  docprophdr.cbOut = DocumentPropertySheets( NULL, (LPARAM)&docprophdr );
1194  }
1195 
1196  docprophdr.pdmIn = pDevModeInput;
1197  docprophdr.pdmOut = pDevModeOutput;
1198  docprophdr.fMode = fMode;
1199 
1200  if ( fMode & DM_IN_PROMPT )
1201  {
1202  Result = CPSUI_CANCEL;
1203 
1204  //
1205  // Now call the Property Sheet for Print > Properties.
1206  //
1208  {
1209  FIXME("CallCommonPropertySheetUI return error\n");
1211  }
1212  else
1213  Result = (Result == CPSUI_OK) ? IDOK : IDCANCEL;
1214  FIXME("CallCommonPropertySheetUI returned\n");
1215  }
1216  else
1217  {
1218  FIXME("DPW : CallDocumentPropertySheets\n");
1219  Result = DocumentPropertySheets( NULL, (LPARAM)&docprophdr );
1220  }
1221 
1223  {
1224  if ( pDevModeOutput )
1225  {
1226  if ( !IsValidDevmodeNoSizeW( pDevModeOutput ) )
1227  {
1228  ERR("DPW : Improper pDevModeOutput size.\n");
1229  Result = -1;
1230  }
1231  }
1232  else
1233  {
1234  ERR("No pDevModeOutput\n");
1235  }
1236  }
1237 
1238  if (hUseHandle && !hPrinter)
1239  ClosePrinter(hUseHandle);
1240  return Result;
1241 }
1242 
1243 BOOL
1244 WINAPI
1246 {
1247  PRINTER_INFO_2W *pi2 = NULL;
1248  DWORD needed = 0;
1249  LONG Ret, Result = 0;
1250  BOOL res;
1251  DEVICEPROPERTYHEADER devprophdr;
1252 
1253  FIXME("PrinterProperties(%p, %p)\n", hWnd, hPrinter);
1254 
1255  devprophdr.cbSize = sizeof(DEVICEPROPERTYHEADER);
1256  devprophdr.Flags = DPS_NOPERMISSION;
1257  devprophdr.hPrinter = hPrinter;
1258  devprophdr.pszPrinterName = NULL;
1259 
1260  res = GetPrinterW( hPrinter, 2, NULL, 0, &needed);
1262  {
1263  pi2 = HeapAlloc(hProcessHeap, 0, needed);
1264  res = GetPrinterW(hPrinter, 2, (LPBYTE)pi2, needed, &needed);
1265  }
1266 
1267  //
1268  // Above can fail, still process w/o printer name.
1269  //
1270  if ( res ) devprophdr.pszPrinterName = pi2->pPrinterName;
1271 
1272  needed = 1;
1273 
1274  if ( ( SetPrinterDataW( hPrinter, L"PrinterPropertiesPermission", REG_DWORD, (LPBYTE)&needed, sizeof(DWORD) ) == ERROR_SUCCESS ) )
1275  {
1276  devprophdr.Flags &= ~DPS_NOPERMISSION;
1277  }
1278 
1280 
1281  res = (Ret >= 0);
1282 
1283  if (!res)
1284  {
1285  FIXME("PrinterProperties fail ICPSUI\n");
1286  }
1287 
1288  if (pi2) HeapFree(hProcessHeap, 0, pi2);
1289 
1290  return res;
1291 }
1292 
1293 BOOL WINAPI
1295 {
1296  DWORD dwErrorCode;
1297  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
1298 
1299  TRACE("EndDocPrinter(%p)\n", hPrinter);
1300 
1301  // Sanity checks.
1302  if (!pHandle)
1303  {
1304  dwErrorCode = ERROR_INVALID_HANDLE;
1305  goto Cleanup;
1306  }
1307 
1308  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
1309  {
1310  // For spooled jobs, the document is finished by calling _RpcScheduleJob.
1311  RpcTryExcept
1312  {
1313  dwErrorCode = _RpcScheduleJob(pHandle->hPrinter, pHandle->dwJobID);
1314  }
1316  {
1317  dwErrorCode = RpcExceptionCode();
1318  ERR("_RpcScheduleJob failed with exception code %lu!\n", dwErrorCode);
1319  }
1320  RpcEndExcept;
1321 
1322  // Close the spool file handle.
1323  CloseHandle(pHandle->hSPLFile);
1324  }
1325  else
1326  {
1327  // In all other cases, just call _RpcEndDocPrinter.
1328  RpcTryExcept
1329  {
1330  dwErrorCode = _RpcEndDocPrinter(pHandle->hPrinter);
1331  }
1333  {
1334  dwErrorCode = RpcExceptionCode();
1335  ERR("_RpcEndDocPrinter failed with exception code %lu!\n", dwErrorCode);
1336  }
1337  RpcEndExcept;
1338  }
1339 
1340  // A new document can now be started again.
1341  pHandle->bTrayIcon = pHandle->bJob = pHandle->bStartedDoc = FALSE;
1342 
1343 Cleanup:
1344  SetLastError(dwErrorCode);
1345  return (dwErrorCode == ERROR_SUCCESS);
1346 }
1347 
1348 BOOL WINAPI
1350 {
1351  DWORD dwErrorCode;
1352  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
1353 
1354  TRACE("EndPagePrinter(%p)\n", hPrinter);
1355 
1356  // Sanity checks.
1357  if (!pHandle)
1358  {
1359  dwErrorCode = ERROR_INVALID_HANDLE;
1360  goto Cleanup;
1361  }
1362 
1363  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
1364  {
1365  // For spooled jobs, we don't need to do anything.
1366  dwErrorCode = ERROR_SUCCESS;
1367  }
1368  else
1369  {
1370  // In all other cases, just call _RpcEndPagePrinter.
1371  RpcTryExcept
1372  {
1373  dwErrorCode = _RpcEndPagePrinter(pHandle->hPrinter);
1374  }
1376  {
1377  dwErrorCode = RpcExceptionCode();
1378  ERR("_RpcEndPagePrinter failed with exception code %lu!\n", dwErrorCode);
1379  }
1380  RpcEndExcept;
1381  }
1382 
1383 Cleanup:
1384  SetLastError(dwErrorCode);
1385  return (dwErrorCode == ERROR_SUCCESS);
1386 }
1387 
1388 BOOL WINAPI
1390 {
1391  DWORD dwErrorCode;
1392  DWORD cch;
1393  PWSTR pwszName = NULL;
1394  PSTR pszPrinterName = NULL;
1395  PSTR pszServerName = NULL;
1396  PSTR pszDescription = NULL;
1397  PSTR pszName = NULL;
1398  PSTR pszComment = NULL;
1399  PSTR pszShareName = NULL;
1400  PSTR pszPortName = NULL;
1401  PSTR pszDriverName = NULL;
1402  PSTR pszLocation = NULL;
1403  PSTR pszSepFile = NULL;
1404  PSTR pszPrintProcessor = NULL;
1405  PSTR pszDatatype = NULL;
1406  PSTR pszParameters = NULL;
1407  DWORD i;
1408  PPRINTER_INFO_1W ppi1w = NULL;
1409  PPRINTER_INFO_1A ppi1a = NULL;
1410  PPRINTER_INFO_2W ppi2w = NULL;
1411  PPRINTER_INFO_2A ppi2a = NULL;
1412  PPRINTER_INFO_4W ppi4w = NULL;
1413  PPRINTER_INFO_4A ppi4a = NULL;
1414  PPRINTER_INFO_5W ppi5w = NULL;
1415  PPRINTER_INFO_5A ppi5a = NULL;
1416 
1417  TRACE("EnumPrintersA(%lu, %s, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
1418 
1419  // Check for invalid levels here for early error return. MSDN says that only 1, 2, 4, and 5 are allowable.
1420  if (Level != 1 && Level != 2 && Level != 4 && Level != 5)
1421  {
1422  dwErrorCode = ERROR_INVALID_LEVEL;
1423  ERR("Invalid Level!\n");
1424  goto Cleanup;
1425  }
1426 
1427  if (Name)
1428  {
1429  // Convert pName to a Unicode string pwszName.
1430  cch = strlen(Name);
1431 
1432  pwszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
1433  if (!pwszName)
1434  {
1435  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1436  ERR("HeapAlloc failed!\n");
1437  goto Cleanup;
1438  }
1439 
1440  MultiByteToWideChar(CP_ACP, 0, Name, -1, pwszName, cch + 1);
1441  }
1442 
1443  /* Ref: https://stackoverflow.com/questions/41147180/why-enumprintersa-and-enumprintersw-request-the-same-amount-of-memory */
1444  if (!EnumPrintersW(Flags, pwszName, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned))
1445  {
1446  dwErrorCode = GetLastError();
1447  goto Cleanup;
1448  }
1449 
1450  /* We are mapping multiple different pointers to the same pPrinterEnum pointer here so that */
1451  /* we can do in-place conversion. We read the Unicode response from the EnumPrintersW and */
1452  /* then we write back the ANSI conversion into the same buffer for our EnumPrintersA output */
1453 
1454  /* mapping to pPrinterEnum for Unicode (w) characters for Levels 1, 2, 4, and 5 */
1455  ppi1w = (PPRINTER_INFO_1W)pPrinterEnum;
1456  ppi2w = (PPRINTER_INFO_2W)pPrinterEnum;
1457  ppi4w = (PPRINTER_INFO_4W)pPrinterEnum;
1458  ppi5w = (PPRINTER_INFO_5W)pPrinterEnum;
1459  /* mapping to pPrinterEnum for ANSI (a) characters for Levels 1, 2, 4, and 5 */
1460  ppi1a = (PPRINTER_INFO_1A)pPrinterEnum;
1461  ppi2a = (PPRINTER_INFO_2A)pPrinterEnum;
1462  ppi4a = (PPRINTER_INFO_4A)pPrinterEnum;
1463  ppi5a = (PPRINTER_INFO_5A)pPrinterEnum;
1464 
1465  for (i = 0; i < *pcReturned; i++)
1466  {
1467  switch (Level)
1468  {
1469  case 1:
1470  {
1471  if (ppi1w[i].pDescription)
1472  {
1473  // Convert Unicode pDescription to a ANSI string pszDescription.
1474  cch = wcslen(ppi1w[i].pDescription);
1475 
1476  pszDescription = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1477  if (!pszDescription)
1478  {
1479  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1480  ERR("HeapAlloc failed!\n");
1481  goto Cleanup;
1482  }
1483 
1484  WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pDescription, -1, pszDescription, cch + 1, NULL, NULL);
1485  StringCchCopyA(ppi1a[i].pDescription, cch + 1, pszDescription);
1486 
1487  HeapFree(hProcessHeap, 0, pszDescription);
1488  }
1489 
1490  if (ppi1w[i].pName)
1491  {
1492  // Convert Unicode pName to a ANSI string pszName.
1493  cch = wcslen(ppi1w[i].pName);
1494 
1495  pszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1496  if (!pszName)
1497  {
1498  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1499  ERR("HeapAlloc failed!\n");
1500  goto Cleanup;
1501  }
1502 
1503  WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pName, -1, pszName, cch + 1, NULL, NULL);
1504  StringCchCopyA(ppi1a[i].pName, cch + 1, pszName);
1505 
1506  HeapFree(hProcessHeap, 0, pszName);
1507  }
1508 
1509  if (ppi1w[i].pComment)
1510  {
1511  // Convert Unicode pComment to a ANSI string pszComment.
1512  cch = wcslen(ppi1w[i].pComment);
1513 
1514  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1515  if (!pszComment)
1516  {
1517  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1518  ERR("HeapAlloc failed!\n");
1519  goto Cleanup;
1520  }
1521 
1522  WideCharToMultiByte(CP_ACP, 0, ppi1w[i].pComment, -1, pszComment, cch + 1, NULL, NULL);
1523  StringCchCopyA(ppi1a[i].pComment, cch + 1, pszComment);
1524 
1525  HeapFree(hProcessHeap, 0, pszComment);
1526  }
1527  break;
1528  }
1529 
1530 
1531  case 2:
1532  {
1533  if (ppi2w[i].pServerName)
1534  {
1535  // Convert Unicode pServerName to a ANSI string pszServerName.
1536  cch = wcslen(ppi2w[i].pServerName);
1537 
1538  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1539  if (!pszServerName)
1540  {
1541  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1542  ERR("HeapAlloc failed!\n");
1543  goto Cleanup;
1544  }
1545 
1546  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pServerName, -1, pszServerName, cch + 1, NULL, NULL);
1547  StringCchCopyA(ppi2a[i].pServerName, cch + 1, pszServerName);
1548 
1549  HeapFree(hProcessHeap, 0, pszServerName);
1550  }
1551 
1552  if (ppi2w[i].pPrinterName)
1553  {
1554  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
1555  cch = wcslen(ppi2w[i].pPrinterName);
1556 
1557  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1558  if (!pszPrinterName)
1559  {
1560  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1561  ERR("HeapAlloc failed!\n");
1562  goto Cleanup;
1563  }
1564 
1565  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
1566  StringCchCopyA(ppi2a[i].pPrinterName, cch + 1, pszPrinterName);
1567 
1568  HeapFree(hProcessHeap, 0, pszPrinterName);
1569  }
1570 
1571  if (ppi2w[i].pShareName)
1572  {
1573  // Convert Unicode pShareName to a ANSI string pszShareName.
1574  cch = wcslen(ppi2w[i].pShareName);
1575 
1576  pszShareName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1577  if (!pszShareName)
1578  {
1579  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1580  ERR("HeapAlloc failed!\n");
1581  goto Cleanup;
1582  }
1583 
1584  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pShareName, -1, pszShareName, cch + 1, NULL, NULL);
1585  StringCchCopyA(ppi2a[i].pShareName, cch + 1, pszShareName);
1586 
1587  HeapFree(hProcessHeap, 0, pszShareName);
1588  }
1589 
1590  if (ppi2w[i].pPortName)
1591  {
1592  // Convert Unicode pPortName to a ANSI string pszPortName.
1593  cch = wcslen(ppi2w[i].pPortName);
1594 
1595  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1596  if (!pszPortName)
1597  {
1598  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1599  ERR("HeapAlloc failed!\n");
1600  goto Cleanup;
1601  }
1602 
1603  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPortName, -1, pszPortName, cch + 1, NULL, NULL);
1604  StringCchCopyA(ppi2a[i].pPortName, cch + 1, pszPortName);
1605 
1606  HeapFree(hProcessHeap, 0, pszPortName);
1607  }
1608 
1609  if (ppi2w[i].pDriverName)
1610  {
1611  // Convert Unicode pDriverName to a ANSI string pszDriverName.
1612  cch = wcslen(ppi2w[i].pDriverName);
1613 
1614  pszDriverName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1615  if (!pszDriverName)
1616  {
1617  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1618  ERR("HeapAlloc failed!\n");
1619  goto Cleanup;
1620  }
1621 
1622  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pDriverName, -1, pszDriverName, cch + 1, NULL, NULL);
1623  StringCchCopyA(ppi2a[i].pDriverName, cch + 1, pszDriverName);
1624 
1625  HeapFree(hProcessHeap, 0, pszDriverName);
1626  }
1627 
1628  if (ppi2w[i].pComment)
1629  {
1630  // Convert Unicode pComment to a ANSI string pszComment.
1631  cch = wcslen(ppi2w[i].pComment);
1632 
1633  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1634  if (!pszComment)
1635  {
1636  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1637  ERR("HeapAlloc failed!\n");
1638  goto Cleanup;
1639  }
1640 
1641  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pComment, -1, pszComment, cch + 1, NULL, NULL);
1642  StringCchCopyA(ppi2a[i].pComment, cch + 1, pszComment);
1643 
1644  HeapFree(hProcessHeap, 0, pszComment);
1645  }
1646 
1647  if (ppi2w[i].pLocation)
1648  {
1649  // Convert Unicode pLocation to a ANSI string pszLocation.
1650  cch = wcslen(ppi2w[i].pLocation);
1651 
1652  pszLocation = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1653  if (!pszLocation)
1654  {
1655  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1656  ERR("HeapAlloc failed!\n");
1657  goto Cleanup;
1658  }
1659 
1660  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pLocation, -1, pszLocation, cch + 1, NULL, NULL);
1661  StringCchCopyA(ppi2a[i].pLocation, cch + 1, pszLocation);
1662 
1663  HeapFree(hProcessHeap, 0, pszLocation);
1664  }
1665 
1666 
1667  if (ppi2w[i].pSepFile)
1668  {
1669  // Convert Unicode pSepFile to a ANSI string pszSepFile.
1670  cch = wcslen(ppi2w[i].pSepFile);
1671 
1672  pszSepFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1673  if (!pszSepFile)
1674  {
1675  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1676  ERR("HeapAlloc failed!\n");
1677  goto Cleanup;
1678  }
1679 
1680  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pSepFile, -1, pszSepFile, cch + 1, NULL, NULL);
1681  StringCchCopyA(ppi2a[i].pSepFile, cch + 1, pszSepFile);
1682 
1683  HeapFree(hProcessHeap, 0, pszSepFile);
1684  }
1685 
1686  if (ppi2w[i].pPrintProcessor)
1687  {
1688  // Convert Unicode pPrintProcessor to a ANSI string pszPrintProcessor.
1689  cch = wcslen(ppi2w[i].pPrintProcessor);
1690 
1691  pszPrintProcessor = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1692  if (!pszPrintProcessor)
1693  {
1694  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1695  ERR("HeapAlloc failed!\n");
1696  goto Cleanup;
1697  }
1698 
1699  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pPrintProcessor, -1, pszPrintProcessor, cch + 1, NULL, NULL);
1700  StringCchCopyA(ppi2a[i].pPrintProcessor, cch + 1, pszPrintProcessor);
1701 
1702  HeapFree(hProcessHeap, 0, pszPrintProcessor);
1703  }
1704 
1705 
1706  if (ppi2w[i].pDatatype)
1707  {
1708  // Convert Unicode pDatatype to a ANSI string pszDatatype.
1709  cch = wcslen(ppi2w[i].pDatatype);
1710 
1711  pszDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1712  if (!pszDatatype)
1713  {
1714  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1715  ERR("HeapAlloc failed!\n");
1716  goto Cleanup;
1717  }
1718 
1719  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pDatatype, -1, pszDatatype, cch + 1, NULL, NULL);
1720  StringCchCopyA(ppi2a[i].pDatatype, cch + 1, pszDatatype);
1721 
1722  HeapFree(hProcessHeap, 0, pszDatatype);
1723  }
1724 
1725  if (ppi2w[i].pParameters)
1726  {
1727  // Convert Unicode pParameters to a ANSI string pszParameters.
1728  cch = wcslen(ppi2w[i].pParameters);
1729 
1730  pszParameters = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1731  if (!pszParameters)
1732  {
1733  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1734  ERR("HeapAlloc failed!\n");
1735  goto Cleanup;
1736  }
1737 
1738  WideCharToMultiByte(CP_ACP, 0, ppi2w[i].pParameters, -1, pszParameters, cch + 1, NULL, NULL);
1739  StringCchCopyA(ppi2a[i].pParameters, cch + 1, pszParameters);
1740 
1741  HeapFree(hProcessHeap, 0, pszParameters);
1742  }
1743  if ( ppi2w[i].pDevMode )
1744  {
1745  RosConvertUnicodeDevModeToAnsiDevmode( ppi2w[i].pDevMode, ppi2a[i].pDevMode );
1746  }
1747  break;
1748  }
1749 
1750  case 4:
1751  {
1752  if (ppi4w[i].pPrinterName)
1753  {
1754  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
1755  cch = wcslen(ppi4w[i].pPrinterName);
1756 
1757  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1758  if (!pszPrinterName)
1759  {
1760  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1761  ERR("HeapAlloc failed!\n");
1762  goto Cleanup;
1763  }
1764 
1765  WideCharToMultiByte(CP_ACP, 0, ppi4w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
1766  StringCchCopyA(ppi4a[i].pPrinterName, cch + 1, pszPrinterName);
1767 
1768  HeapFree(hProcessHeap, 0, pszPrinterName);
1769  }
1770 
1771  if (ppi4w[i].pServerName)
1772  {
1773  // Convert Unicode pServerName to a ANSI string pszServerName.
1774  cch = wcslen(ppi4w[i].pServerName);
1775 
1776  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1777  if (!pszServerName)
1778  {
1779  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1780  ERR("HeapAlloc failed!\n");
1781  goto Cleanup;
1782  }
1783 
1784  WideCharToMultiByte(CP_ACP, 0, ppi4w[i].pServerName, -1, pszServerName, cch + 1, NULL, NULL);
1785  StringCchCopyA(ppi4a[i].pServerName, cch + 1, pszServerName);
1786 
1787  HeapFree(hProcessHeap, 0, pszServerName);
1788  }
1789  break;
1790  }
1791 
1792  case 5:
1793  {
1794  if (ppi5w[i].pPrinterName)
1795  {
1796  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
1797  cch = wcslen(ppi5w[i].pPrinterName);
1798 
1799  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1800  if (!pszPrinterName)
1801  {
1802  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1803  ERR("HeapAlloc failed!\n");
1804  goto Cleanup;
1805  }
1806 
1807  WideCharToMultiByte(CP_ACP, 0, ppi5w[i].pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
1808  StringCchCopyA(ppi5a[i].pPrinterName, cch + 1, pszPrinterName);
1809 
1810  HeapFree(hProcessHeap, 0, pszPrinterName);
1811  }
1812 
1813  if (ppi5w[i].pPortName)
1814  {
1815  // Convert Unicode pPortName to a ANSI string pszPortName.
1816  cch = wcslen(ppi5w[i].pPortName);
1817 
1818  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
1819  if (!pszPortName)
1820  {
1821  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1822  ERR("HeapAlloc failed!\n");
1823  goto Cleanup;
1824  }
1825 
1826  WideCharToMultiByte(CP_ACP, 0, ppi5w[i].pPortName, -1, pszPortName, cch + 1, NULL, NULL);
1827  StringCchCopyA(ppi5a[i].pPortName, cch + 1, pszPortName);
1828 
1829  HeapFree(hProcessHeap, 0, pszPortName);
1830  }
1831  break;
1832  }
1833 
1834  } // switch
1835  } // for
1836 
1837  dwErrorCode = ERROR_SUCCESS;
1838 
1839 Cleanup:
1840  if (pwszName)
1841  {
1842  HeapFree(hProcessHeap, 0, pwszName);
1843  }
1844 
1845  SetLastError(dwErrorCode);
1846  return (dwErrorCode == ERROR_SUCCESS);
1847 }
1848 
1849 BOOL WINAPI
1851 {
1852  DWORD dwErrorCode;
1853 
1854  TRACE("EnumPrintersW(%lu, %S, %lu, %p, %lu, %p, %p)\n", Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
1855 
1856  // Dismiss invalid levels already at this point.
1857  if (Level == 3 || Level > 5)
1858  {
1859  dwErrorCode = ERROR_INVALID_LEVEL;
1860  goto Cleanup;
1861  }
1862 
1863  if (cbBuf && pPrinterEnum)
1864  ZeroMemory(pPrinterEnum, cbBuf);
1865 
1866  // Do the RPC call
1867  RpcTryExcept
1868  {
1869  dwErrorCode = _RpcEnumPrinters(Flags, Name, Level, pPrinterEnum, cbBuf, pcbNeeded, pcReturned);
1870  }
1872  {
1873  dwErrorCode = RpcExceptionCode();
1874  ERR("_RpcEnumPrinters failed with exception code %lu!\n", dwErrorCode);
1875  }
1876  RpcEndExcept;
1877 
1878  if (dwErrorCode == ERROR_SUCCESS)
1879  {
1880  // Replace relative offset addresses in the output by absolute pointers.
1881  ASSERT(Level <= 9);
1882  MarshallUpStructuresArray(cbBuf, pPrinterEnum, *pcReturned, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
1883  }
1884 
1885 Cleanup:
1886  SetLastError(dwErrorCode);
1887  return (dwErrorCode == ERROR_SUCCESS);
1888 }
1889 
1890 BOOL WINAPI
1891 FlushPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten, DWORD cSleep)
1892 {
1893  TRACE("FlushPrinter(%p, %p, %lu, %p, %lu)\n", hPrinter, pBuf, cbBuf, pcWritten, cSleep);
1894  UNIMPLEMENTED;
1895  return FALSE;
1896 }
1897 
1898 BOOL WINAPI
1899 GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
1900 {
1901  DWORD dwErrorCode;
1902  PWSTR pwszBuffer = NULL;
1903 
1904  TRACE("GetDefaultPrinterA(%p, %p)\n", pszBuffer, pcchBuffer);
1905 
1906  // Sanity check.
1907  if (!pcchBuffer)
1908  {
1909  dwErrorCode = ERROR_INVALID_PARAMETER;
1910  goto Cleanup;
1911  }
1912 
1913  // Check if an ANSI buffer was given and if so, allocate a Unicode buffer of the same size.
1914  if (pszBuffer && *pcchBuffer)
1915  {
1916  pwszBuffer = HeapAlloc(hProcessHeap, 0, *pcchBuffer * sizeof(WCHAR));
1917  if (!pwszBuffer)
1918  {
1919  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1920  ERR("HeapAlloc failed!\n");
1921  goto Cleanup;
1922  }
1923  }
1924 
1925  if (!GetDefaultPrinterW(pwszBuffer, pcchBuffer))
1926  {
1927  dwErrorCode = GetLastError();
1928  goto Cleanup;
1929  }
1930 
1931  // We successfully got a string in pwszBuffer, so convert the Unicode string to ANSI.
1932  WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszBuffer, *pcchBuffer, NULL, NULL);
1933 
1934  dwErrorCode = ERROR_SUCCESS;
1935 
1936 Cleanup:
1937  if (pwszBuffer)
1938  HeapFree(hProcessHeap, 0, pwszBuffer);
1939 
1940  SetLastError(dwErrorCode);
1941  return (dwErrorCode == ERROR_SUCCESS);
1942 }
1943 
1944 BOOL WINAPI
1945 GetDefaultPrinterW(LPWSTR pszBuffer, LPDWORD pcchBuffer)
1946 {
1947  DWORD cbNeeded;
1948  DWORD cchInputBuffer;
1949  DWORD dwErrorCode;
1950  HKEY hWindowsKey = NULL;
1951  PWSTR pwszDevice = NULL;
1952  PWSTR pwszComma;
1953 
1954  TRACE("GetDefaultPrinterW(%p, %p)\n", pszBuffer, pcchBuffer);
1955 
1956  // Sanity check.
1957  if (!pcchBuffer)
1958  {
1959  dwErrorCode = ERROR_INVALID_PARAMETER;
1960  goto Cleanup;
1961  }
1962 
1963  cchInputBuffer = *pcchBuffer;
1964 
1965  // Open the registry key where the default printer for the current user is stored.
1966  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_READ, &hWindowsKey);
1967  if (dwErrorCode != ERROR_SUCCESS)
1968  {
1969  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
1970  goto Cleanup;
1971  }
1972 
1973  // Determine the size of the required buffer.
1974  dwErrorCode = (DWORD)RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, NULL, &cbNeeded);
1975  if (dwErrorCode != ERROR_SUCCESS)
1976  {
1977  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
1978  goto Cleanup;
1979  }
1980 
1981  // Allocate it.
1982  pwszDevice = HeapAlloc(hProcessHeap, 0, cbNeeded);
1983  if (!pwszDevice)
1984  {
1985  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
1986  ERR("HeapAlloc failed!\n");
1987  goto Cleanup;
1988  }
1989 
1990  // Now get the actual value.
1991  dwErrorCode = RegQueryValueExW(hWindowsKey, wszDeviceValue, NULL, NULL, (PBYTE)pwszDevice, &cbNeeded);
1992  if (dwErrorCode != ERROR_SUCCESS)
1993  {
1994  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
1995  goto Cleanup;
1996  }
1997 
1998  // We get a string "<Printer Name>,winspool,<Port>:".
1999  // Extract the printer name from it.
2000  pwszComma = wcschr(pwszDevice, L',');
2001  if (!pwszComma)
2002  {
2003  ERR("Found no or invalid default printer: %S!\n", pwszDevice);
2004  dwErrorCode = ERROR_INVALID_NAME;
2005  goto Cleanup;
2006  }
2007 
2008  // Store the length of the Printer Name (including the terminating NUL character!) in *pcchBuffer.
2009  *pcchBuffer = pwszComma - pwszDevice + 1;
2010 
2011  // Check if the supplied buffer is large enough.
2012  if ( !pszBuffer || cchInputBuffer < *pcchBuffer)
2013  {
2014  dwErrorCode = ERROR_INSUFFICIENT_BUFFER;
2015  goto Cleanup;
2016  }
2017 
2018  // Copy the default printer.
2019  *pwszComma = 0;
2020  CopyMemory(pszBuffer, pwszDevice, *pcchBuffer * sizeof(WCHAR));
2021 
2022  dwErrorCode = ERROR_SUCCESS;
2023 
2024 Cleanup:
2025  if (hWindowsKey)
2026  RegCloseKey(hWindowsKey);
2027 
2028  if (pwszDevice)
2029  HeapFree(hProcessHeap, 0, pwszDevice);
2030 
2031  SetLastError(dwErrorCode);
2032  return (dwErrorCode == ERROR_SUCCESS);
2033 }
2034 
2035 BOOL WINAPI
2037 {
2038  DWORD dwErrorCode;
2039  PPRINTER_INFO_1A ppi1a = (PPRINTER_INFO_1A)pPrinter;
2040  PPRINTER_INFO_1W ppi1w = (PPRINTER_INFO_1W)pPrinter;
2041  PPRINTER_INFO_2A ppi2a = (PPRINTER_INFO_2A)pPrinter;
2042  PPRINTER_INFO_2W ppi2w = (PPRINTER_INFO_2W)pPrinter;
2043  PPRINTER_INFO_4A ppi4a = (PPRINTER_INFO_4A)pPrinter;
2044  PPRINTER_INFO_4W ppi4w = (PPRINTER_INFO_4W)pPrinter;
2045  PPRINTER_INFO_5A ppi5a = (PPRINTER_INFO_5A)pPrinter;
2046  PPRINTER_INFO_5W ppi5w = (PPRINTER_INFO_5W)pPrinter;
2047  PPRINTER_INFO_7A ppi7a = (PPRINTER_INFO_7A)pPrinter;
2048  PPRINTER_INFO_7W ppi7w = (PPRINTER_INFO_7W)pPrinter;
2049  PPRINTER_INFO_9A ppi9a = (PPRINTER_INFO_9A)pPrinter;
2050  PPRINTER_INFO_9W ppi9w = (PPRINTER_INFO_9W)pPrinter;
2051  DWORD cch;
2052 
2053  TRACE("GetPrinterA(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
2054 
2055  // Check for invalid levels here for early error return. Should be 1-9.
2056  if (Level < 1 || Level > 9)
2057  {
2058  dwErrorCode = ERROR_INVALID_LEVEL;
2059  ERR("Invalid Level!\n");
2060  goto Cleanup;
2061  }
2062 
2063  if (!GetPrinterW(hPrinter, Level, pPrinter, cbBuf, pcbNeeded))
2064  {
2065  dwErrorCode = GetLastError();
2066  goto Cleanup;
2067  }
2068 
2069  switch (Level)
2070  {
2071  case 1:
2072  {
2073  if (ppi1w->pDescription)
2074  {
2075  PSTR pszDescription;
2076 
2077  // Convert Unicode pDescription to a ANSI string pszDescription.
2078  cch = wcslen(ppi1w->pDescription);
2079 
2080  pszDescription = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2081  if (!pszDescription)
2082  {
2083  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2084  ERR("HeapAlloc failed!\n");
2085  goto Cleanup;
2086  }
2087 
2088  WideCharToMultiByte(CP_ACP, 0, ppi1w->pDescription, -1, pszDescription, cch + 1, NULL, NULL);
2089  StringCchCopyA(ppi1a->pDescription, cch + 1, pszDescription);
2090 
2091  HeapFree(hProcessHeap, 0, pszDescription);
2092  }
2093 
2094  if (ppi1w->pName)
2095  {
2096  PSTR pszName;
2097 
2098  // Convert Unicode pName to a ANSI string pszName.
2099  cch = wcslen(ppi1w->pName);
2100 
2101  pszName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2102  if (!pszName)
2103  {
2104  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2105  ERR("HeapAlloc failed!\n");
2106  goto Cleanup;
2107  }
2108 
2109  WideCharToMultiByte(CP_ACP, 0, ppi1w->pName, -1, pszName, cch + 1, NULL, NULL);
2110  StringCchCopyA(ppi1a->pName, cch + 1, pszName);
2111 
2112  HeapFree(hProcessHeap, 0, pszName);
2113  }
2114 
2115  if (ppi1w->pComment)
2116  {
2117  PSTR pszComment;
2118 
2119  // Convert Unicode pComment to a ANSI string pszComment.
2120  cch = wcslen(ppi1w->pComment);
2121 
2122  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2123  if (!pszComment)
2124  {
2125  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2126  ERR("HeapAlloc failed!\n");
2127  goto Cleanup;
2128  }
2129 
2130  WideCharToMultiByte(CP_ACP, 0, ppi1w->pComment, -1, pszComment, cch + 1, NULL, NULL);
2131  StringCchCopyA(ppi1a->pComment, cch + 1, pszComment);
2132 
2133  HeapFree(hProcessHeap, 0, pszComment);
2134  }
2135  break;
2136  }
2137 
2138  case 2:
2139  {
2140  if (ppi2w->pServerName)
2141  {
2142  PSTR pszServerName;
2143 
2144  // Convert Unicode pServerName to a ANSI string pszServerName.
2145  cch = wcslen(ppi2w->pServerName);
2146 
2147  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2148  if (!pszServerName)
2149  {
2150  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2151  ERR("HeapAlloc failed!\n");
2152  goto Cleanup;
2153  }
2154 
2155  WideCharToMultiByte(CP_ACP, 0, ppi2w->pServerName, -1, pszServerName, cch + 1, NULL, NULL);
2156  StringCchCopyA(ppi2a->pServerName, cch + 1, pszServerName);
2157 
2158  HeapFree(hProcessHeap, 0, pszServerName);
2159  }
2160 
2161  if (ppi2w->pPrinterName)
2162  {
2163  PSTR pszPrinterName;
2164 
2165  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
2166  cch = wcslen(ppi2w->pPrinterName);
2167 
2168  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2169  if (!pszPrinterName)
2170  {
2171  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2172  ERR("HeapAlloc failed!\n");
2173  goto Cleanup;
2174  }
2175 
2176  WideCharToMultiByte(CP_ACP, 0, ppi2w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
2177  StringCchCopyA(ppi2a->pPrinterName, cch + 1, pszPrinterName);
2178 
2179  HeapFree(hProcessHeap, 0, pszPrinterName);
2180  }
2181 
2182  if (ppi2w->pShareName)
2183  {
2184  PSTR pszShareName;
2185 
2186  // Convert Unicode pShareName to a ANSI string pszShareName.
2187  cch = wcslen(ppi2w->pShareName);
2188 
2189  pszShareName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2190  if (!pszShareName)
2191  {
2192  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2193  ERR("HeapAlloc failed!\n");
2194  goto Cleanup;
2195  }
2196 
2197  WideCharToMultiByte(CP_ACP, 0, ppi2w->pShareName, -1, pszShareName, cch + 1, NULL, NULL);
2198  StringCchCopyA(ppi2a->pShareName, cch + 1, pszShareName);
2199 
2200  HeapFree(hProcessHeap, 0, pszShareName);
2201  }
2202 
2203  if (ppi2w->pPortName)
2204  {
2205  PSTR pszPortName;
2206 
2207  // Convert Unicode pPortName to a ANSI string pszPortName.
2208  cch = wcslen(ppi2w->pPortName);
2209 
2210  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2211  if (!pszPortName)
2212  {
2213  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2214  ERR("HeapAlloc failed!\n");
2215  goto Cleanup;
2216  }
2217 
2218  WideCharToMultiByte(CP_ACP, 0, ppi2w->pPortName, -1, pszPortName, cch + 1, NULL, NULL);
2219  StringCchCopyA(ppi2a->pPortName, cch + 1, pszPortName);
2220 
2221  HeapFree(hProcessHeap, 0, pszPortName);
2222  }
2223 
2224  if (ppi2w->pDriverName)
2225  {
2226  PSTR pszDriverName;
2227 
2228  // Convert Unicode pDriverName to a ANSI string pszDriverName.
2229  cch = wcslen(ppi2w->pDriverName);
2230 
2231  pszDriverName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2232  if (!pszDriverName)
2233  {
2234  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2235  ERR("HeapAlloc failed!\n");
2236  goto Cleanup;
2237  }
2238 
2239  WideCharToMultiByte(CP_ACP, 0, ppi2w->pDriverName, -1, pszDriverName, cch + 1, NULL, NULL);
2240  StringCchCopyA(ppi2a->pDriverName, cch + 1, pszDriverName);
2241 
2242  HeapFree(hProcessHeap, 0, pszDriverName);
2243  }
2244 
2245  if (ppi2w->pComment)
2246  {
2247  PSTR pszComment;
2248 
2249  // Convert Unicode pComment to a ANSI string pszComment.
2250  cch = wcslen(ppi2w->pComment);
2251 
2252  pszComment = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2253  if (!pszComment)
2254  {
2255  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2256  ERR("HeapAlloc failed!\n");
2257  goto Cleanup;
2258  }
2259 
2260  WideCharToMultiByte(CP_ACP, 0, ppi2w->pComment, -1, pszComment, cch + 1, NULL, NULL);
2261  StringCchCopyA(ppi2a->pComment, cch + 1, pszComment);
2262 
2263  HeapFree(hProcessHeap, 0, pszComment);
2264  }
2265 
2266  if (ppi2w->pLocation)
2267  {
2268  PSTR pszLocation;
2269 
2270  // Convert Unicode pLocation to a ANSI string pszLocation.
2271  cch = wcslen(ppi2w->pLocation);
2272 
2273  pszLocation = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2274  if (!pszLocation)
2275  {
2276  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2277  ERR("HeapAlloc failed!\n");
2278  goto Cleanup;
2279  }
2280 
2281  WideCharToMultiByte(CP_ACP, 0, ppi2w->pLocation, -1, pszLocation, cch + 1, NULL, NULL);
2282  StringCchCopyA(ppi2a->pLocation, cch + 1, pszLocation);
2283 
2284  HeapFree(hProcessHeap, 0, pszLocation);
2285  }
2286 
2287  if (ppi2w->pSepFile)
2288  {
2289  PSTR pszSepFile;
2290 
2291  // Convert Unicode pSepFile to a ANSI string pszSepFile.
2292  cch = wcslen(ppi2w->pSepFile);
2293 
2294  pszSepFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2295  if (!pszSepFile)
2296  {
2297  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2298  ERR("HeapAlloc failed!\n");
2299  goto Cleanup;
2300  }
2301 
2302  WideCharToMultiByte(CP_ACP, 0, ppi2w->pSepFile, -1, pszSepFile, cch + 1, NULL, NULL);
2303  StringCchCopyA(ppi2a->pSepFile, cch + 1, pszSepFile);
2304 
2305  HeapFree(hProcessHeap, 0, pszSepFile);
2306  }
2307 
2308  if (ppi2w->pPrintProcessor)
2309  {
2310  PSTR pszPrintProcessor;
2311 
2312  // Convert Unicode pPrintProcessor to a ANSI string pszPrintProcessor.
2313  cch = wcslen(ppi2w->pPrintProcessor);
2314 
2315  pszPrintProcessor = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2316  if (!pszPrintProcessor)
2317  {
2318  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2319  ERR("HeapAlloc failed!\n");
2320  goto Cleanup;
2321  }
2322 
2323  WideCharToMultiByte(CP_ACP, 0, ppi2w->pPrintProcessor, -1, pszPrintProcessor, cch + 1, NULL, NULL);
2324  StringCchCopyA(ppi2a->pPrintProcessor, cch + 1, pszPrintProcessor);
2325 
2326  HeapFree(hProcessHeap, 0, pszPrintProcessor);
2327  }
2328 
2329  if (ppi2w->pDatatype)
2330  {
2331  PSTR pszDatatype;
2332 
2333  // Convert Unicode pDatatype to a ANSI string pszDatatype.
2334  cch = wcslen(ppi2w->pDatatype);
2335 
2336  pszDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2337  if (!pszDatatype)
2338  {
2339  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2340  ERR("HeapAlloc failed!\n");
2341  goto Cleanup;
2342  }
2343 
2344  WideCharToMultiByte(CP_ACP, 0, ppi2w->pDatatype, -1, pszDatatype, cch + 1, NULL, NULL);
2345  StringCchCopyA(ppi2a->pDatatype, cch + 1, pszDatatype);
2346 
2347  HeapFree(hProcessHeap, 0, pszDatatype);
2348  }
2349 
2350  if (ppi2w->pParameters)
2351  {
2352  PSTR pszParameters;
2353 
2354  // Convert Unicode pParameters to a ANSI string pszParameters.
2355  cch = wcslen(ppi2w->pParameters);
2356 
2357  pszParameters = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2358  if (!pszParameters)
2359  {
2360  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2361  ERR("HeapAlloc failed!\n");
2362  goto Cleanup;
2363  }
2364 
2365  WideCharToMultiByte(CP_ACP, 0, ppi2w->pParameters, -1, pszParameters, cch + 1, NULL, NULL);
2366  StringCchCopyA(ppi2a->pParameters, cch + 1, pszParameters);
2367 
2368  HeapFree(hProcessHeap, 0, pszParameters);
2369  }
2370  if ( ppi2w->pDevMode )
2371  {
2373  }
2374  break;
2375  }
2376 
2377  case 4:
2378  {
2379  if (ppi4w->pPrinterName)
2380  {
2381  PSTR pszPrinterName;
2382 
2383  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
2384  cch = wcslen(ppi4w->pPrinterName);
2385 
2386  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2387  if (!pszPrinterName)
2388  {
2389  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2390  ERR("HeapAlloc failed!\n");
2391  goto Cleanup;
2392  }
2393 
2394  WideCharToMultiByte(CP_ACP, 0, ppi4w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
2395  StringCchCopyA(ppi4a->pPrinterName, cch + 1, pszPrinterName);
2396 
2397  HeapFree(hProcessHeap, 0, pszPrinterName);
2398  }
2399 
2400  if (ppi4w->pServerName)
2401  {
2402  PSTR pszServerName;
2403 
2404  // Convert Unicode pServerName to a ANSI string pszServerName.
2405  cch = wcslen(ppi4w->pServerName);
2406 
2407  pszServerName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2408  if (!pszServerName)
2409  {
2410  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2411  ERR("HeapAlloc failed!\n");
2412  goto Cleanup;
2413  }
2414 
2415  WideCharToMultiByte(CP_ACP, 0, ppi4w->pServerName, -1, pszServerName, cch + 1, NULL, NULL);
2416  StringCchCopyA(ppi4a->pServerName, cch + 1, pszServerName);
2417 
2418  HeapFree(hProcessHeap, 0, pszServerName);
2419  }
2420  break;
2421  }
2422 
2423  case 5:
2424  {
2425  if (ppi5w->pPrinterName)
2426  {
2427  PSTR pszPrinterName;
2428 
2429  // Convert Unicode pPrinterName to a ANSI string pszPrinterName.
2430  cch = wcslen(ppi5w->pPrinterName);
2431 
2432  pszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2433  if (!pszPrinterName)
2434  {
2435  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2436  ERR("HeapAlloc failed!\n");
2437  goto Cleanup;
2438  }
2439 
2440  WideCharToMultiByte(CP_ACP, 0, ppi5w->pPrinterName, -1, pszPrinterName, cch + 1, NULL, NULL);
2441  StringCchCopyA(ppi5a->pPrinterName, cch + 1, pszPrinterName);
2442 
2443  HeapFree(hProcessHeap, 0, pszPrinterName);
2444  }
2445 
2446  if (ppi5w->pPortName)
2447  {
2448  PSTR pszPortName;
2449 
2450  // Convert Unicode pPortName to a ANSI string pszPortName.
2451  cch = wcslen(ppi5w->pPortName);
2452 
2453  pszPortName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2454  if (!pszPortName)
2455  {
2456  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2457  ERR("HeapAlloc failed!\n");
2458  goto Cleanup;
2459  }
2460 
2461  WideCharToMultiByte(CP_ACP, 0, ppi5w->pPortName, -1, pszPortName, cch + 1, NULL, NULL);
2462  StringCchCopyA(ppi5a->pPortName, cch + 1, pszPortName);
2463 
2464  HeapFree(hProcessHeap, 0, pszPortName);
2465  }
2466  break;
2467  }
2468 
2469  case 7:
2470  {
2471  if (ppi7w->pszObjectGUID)
2472  {
2473  PSTR pszaObjectGUID;
2474 
2475  // Convert Unicode pszObjectGUID to a ANSI string pszaObjectGUID.
2476  cch = wcslen(ppi7w->pszObjectGUID);
2477 
2478  pszaObjectGUID = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(CHAR));
2479  if (!pszaObjectGUID)
2480  {
2481  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2482  ERR("HeapAlloc failed!\n");
2483  goto Cleanup;
2484  }
2485 
2486  WideCharToMultiByte(CP_ACP, 0, ppi7w->pszObjectGUID, -1, pszaObjectGUID, cch + 1, NULL, NULL);
2487  StringCchCopyA(ppi7a->pszObjectGUID, cch + 1, pszaObjectGUID);
2488 
2489  HeapFree(hProcessHeap, 0, pszaObjectGUID);
2490  }
2491  }
2492  break;
2493  case 8:
2494  case 9:
2496  break;
2497  } // switch
2498 
2499  dwErrorCode = ERROR_SUCCESS;
2500 
2501 Cleanup:
2502  SetLastError(dwErrorCode);
2503  return (dwErrorCode == ERROR_SUCCESS);
2504 }
2505 
2506 BOOL WINAPI
2508 {
2509  DWORD dwErrorCode;
2510  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2511 
2512  TRACE("GetPrinterW(%p, %lu, %p, %lu, %p)\n", hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
2513 
2514  // Sanity checks.
2515  if (!pHandle)
2516  {
2517  dwErrorCode = ERROR_INVALID_HANDLE;
2518  goto Cleanup;
2519  }
2520 
2521  // Dismiss invalid levels already at this point.
2522  if (Level > 9)
2523  {
2524  dwErrorCode = ERROR_INVALID_LEVEL;
2525  goto Cleanup;
2526  }
2527 
2528  if (cbBuf && pPrinter)
2529  ZeroMemory(pPrinter, cbBuf);
2530 
2531  // Do the RPC call
2532  RpcTryExcept
2533  {
2534  dwErrorCode = _RpcGetPrinter(pHandle->hPrinter, Level, pPrinter, cbBuf, pcbNeeded);
2535  }
2537  {
2538  dwErrorCode = RpcExceptionCode();
2539  ERR("_RpcGetPrinter failed with exception code %lu!\n", dwErrorCode);
2540  }
2541  RpcEndExcept;
2542 
2543  if (dwErrorCode == ERROR_SUCCESS)
2544  {
2545  // Replace relative offset addresses in the output by absolute pointers.
2546  ASSERT(Level <= 9);
2547  MarshallUpStructure(cbBuf, pPrinter, pPrinterInfoMarshalling[Level]->pInfo, pPrinterInfoMarshalling[Level]->cbStructureSize, TRUE);
2548  }
2549 
2550 Cleanup:
2551  SetLastError(dwErrorCode);
2552  return (dwErrorCode == ERROR_SUCCESS);
2553 }
2554 
2555 BOOL WINAPI
2556 OpenPrinterA(LPSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSA pDefault)
2557 {
2558  BOOL bReturnValue = FALSE;
2559  DWORD cch;
2560  PWSTR pwszPrinterName = NULL;
2561  PRINTER_DEFAULTSW wDefault = { 0 };
2562 
2563  TRACE("OpenPrinterA(%s, %p, %p)\n", pPrinterName, phPrinter, pDefault);
2564 
2565  if (pPrinterName)
2566  {
2567  // Convert pPrinterName to a Unicode string pwszPrinterName
2568  cch = strlen(pPrinterName);
2569 
2570  pwszPrinterName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
2571  if (!pwszPrinterName)
2572  {
2574  ERR("HeapAlloc failed!\n");
2575  goto Cleanup;
2576  }
2577 
2578  MultiByteToWideChar(CP_ACP, 0, pPrinterName, -1, pwszPrinterName, cch + 1);
2579  }
2580 
2581  if (pDefault)
2582  {
2583  wDefault.DesiredAccess = pDefault->DesiredAccess;
2584 
2585  if (pDefault->pDatatype)
2586  {
2587  // Convert pDefault->pDatatype to a Unicode string wDefault.pDatatype
2588  cch = strlen(pDefault->pDatatype);
2589 
2590  wDefault.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
2591  if (!wDefault.pDatatype)
2592  {
2594  ERR("HeapAlloc failed!\n");
2595  goto Cleanup;
2596  }
2597 
2598  MultiByteToWideChar(CP_ACP, 0, pDefault->pDatatype, -1, wDefault.pDatatype, cch + 1);
2599  }
2600 
2601  if (pDefault->pDevMode)
2602  wDefault.pDevMode = GdiConvertToDevmodeW(pDefault->pDevMode);
2603  }
2604 
2605  bReturnValue = OpenPrinterW(pwszPrinterName, phPrinter, &wDefault);
2606 
2607  if ( bReturnValue )
2608  {
2609  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)*phPrinter;
2610  pHandle->bAnsi = TRUE;
2611  }
2612 
2613 Cleanup:
2614  if (wDefault.pDatatype)
2615  HeapFree(hProcessHeap, 0, wDefault.pDatatype);
2616 
2617  if (wDefault.pDevMode)
2618  HeapFree(hProcessHeap, 0, wDefault.pDevMode);
2619 
2620  if (pwszPrinterName)
2621  HeapFree(hProcessHeap, 0, pwszPrinterName);
2622 
2623  return bReturnValue;
2624 }
2625 
2626 BOOL WINAPI
2627 OpenPrinterW(LPWSTR pPrinterName, LPHANDLE phPrinter, LPPRINTER_DEFAULTSW pDefault)
2628 {
2629  DWORD dwErrorCode;
2630  HANDLE hPrinter;
2631  PSPOOLER_HANDLE pHandle;
2632  PWSTR pDatatype = NULL;
2633  WINSPOOL_DEVMODE_CONTAINER DevModeContainer = { 0 };
2634  ACCESS_MASK AccessRequired = 0;
2635 
2636  TRACE("OpenPrinterW(%S, %p, %p)\n", pPrinterName, phPrinter, pDefault);
2637 
2638  // Sanity check
2639  if (!phPrinter)
2640  {
2641  dwErrorCode = ERROR_INVALID_PARAMETER;
2642  goto Cleanup;
2643  }
2644 
2645  // Prepare the additional parameters in the format required by _RpcOpenPrinter
2646  if (pDefault)
2647  {
2648  pDatatype = pDefault->pDatatype;
2649  DevModeContainer.cbBuf = sizeof(DEVMODEW);
2650  DevModeContainer.pDevMode = (BYTE*)pDefault->pDevMode;
2651  AccessRequired = pDefault->DesiredAccess;
2652  }
2653 
2654  // Do the RPC call
2655  RpcTryExcept
2656  {
2657  dwErrorCode = _RpcOpenPrinter(pPrinterName, &hPrinter, pDatatype, &DevModeContainer, AccessRequired);
2658  }
2660  {
2661  dwErrorCode = RpcExceptionCode();
2662  ERR("_RpcOpenPrinter failed with exception code %lu!\n", dwErrorCode);
2663  }
2664  RpcEndExcept;
2665 
2666  if (dwErrorCode == ERROR_SUCCESS)
2667  {
2668  // Create a new SPOOLER_HANDLE structure.
2670  if (!pHandle)
2671  {
2672  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
2673  ERR("HeapAlloc failed!\n");
2674  goto Cleanup;
2675  }
2676 
2677  pHandle->Sig = SPOOLER_HANDLE_SIG;
2678  pHandle->hPrinter = hPrinter;
2679  pHandle->hSPLFile = INVALID_HANDLE_VALUE;
2681 
2682  // Return it as phPrinter.
2683  *phPrinter = (HANDLE)pHandle;
2684  }
2685 
2686 Cleanup:
2687  SetLastError(dwErrorCode);
2688  return (dwErrorCode == ERROR_SUCCESS);
2689 }
2690 
2691 //
2692 // Dead API.
2693 //
2694 DWORD WINAPI
2696 {
2697  return 50;
2698 }
2699 
2700 DWORD WINAPI
2702 {
2703  return 50;
2704 }
2705 
2706 BOOL WINAPI
2708  HANDLE hPrinter,
2709  PDEVMODEW pdevmode,
2710  ULONG ulQueryMode,
2711  VOID *pvProfileData,
2712  ULONG *pcbProfileData,
2713  FLONG *pflProfileData )
2714 {
2715  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2716  BOOL Ret = FALSE;
2717  HMODULE hLibrary;
2718 
2719  FIXME("QueryColorProfile(%p, %p, %l, %p, %p, %p)\n", hPrinter, pdevmode, ulQueryMode, pvProfileData, pcbProfileData, pflProfileData);
2720 
2721  if ( pHandle->bNoColorProfile )
2722  {
2723  Ret = (BOOL)SP_ERROR;
2724  }
2725  else
2726  {
2727 
2728  if ( pdevmode )
2729  {
2730  if (!IsValidDevmodeNoSizeW( pdevmode ) )
2731  {
2732  ERR("DeviceCapabilitiesW : Devode Invalid");
2733  return FALSE;
2734  }
2735  }
2736 
2737  hLibrary = LoadPrinterDriver( hPrinter );
2738 
2739  if ( hLibrary )
2740  {
2741  fpQueryColorProfile = (PVOID)GetProcAddress( hLibrary, "DrvQueryColorProfile" );
2742 
2743  if ( fpQueryColorProfile )
2744  {
2745  Ret = fpQueryColorProfile( hPrinter, pdevmode, ulQueryMode, pvProfileData, pcbProfileData, pflProfileData );
2746  }
2747  else
2748  {
2749  pHandle->bNoColorProfile = TRUE;
2750  Ret = (BOOL)SP_ERROR;
2751  }
2752 
2754  }
2755  }
2756  return Ret;
2757 }
2758 
2759 // Note from GDI32:printdrv.c
2760 //
2761 // QuerySpoolMode :
2762 // BOOL return TRUE if successful.
2763 // dlFont 0x0001 for Downloading fonts. 0x0002 unknown XPS_PASS?.
2764 // dwVersion is version of EMFSPOOL. Must be 0x00010000. See [MS-EMFSPOOL] page 18.
2765 //
2766 
2767 #define QSM_DOWNLOADINGFONTS 0x0001
2768 
2769 /*
2770  Note from MSDN : "V4 print drivers using RAW mode to send PCL/Postscript have 0 byte spool file"
2771 
2772  Use XPS_PASS instead of RAW to pass information directly to the print filter pipeline in
2773  v4 and v3 XPSDrv drivers. Here's how to proceed with Windows 8:
2774 
2775  Call GetPrinterDriver to retrieve the DRIVER_INFO_8 structure.
2776  Check DRIVER_INFO_8::dwPrinterDriverAttributes for the PRINTER_DRIVER_XPS flag.
2777  Choose your datatype based on the presence or absence of the flag:
2778  If the flag is set, use XPS_PASS.
2779  If the flag isn't set, use RAW.
2780  */
2781 
2782 #define QSM_XPS_PASS 0x0002 // Guessing. PRINTER_DRIVER_XPS?
2783 
2784 BOOL WINAPI
2785 QuerySpoolMode( HANDLE hPrinter, PDWORD downloadFontsFlags, PDWORD dwVersion )
2786 {
2787  PRINTER_INFO_2W *pi2 = NULL;
2788  DWORD needed = 0;
2789  BOOL res;
2790 
2791  FIXME("QuerySpoolMode(%p, %p, %p)\n", hPrinter, downloadFontsFlags, dwVersion);
2792 
2793  res = GetPrinterW( hPrinter, 2, NULL, 0, &needed);
2795  {
2796  pi2 = HeapAlloc(hProcessHeap, 0, needed);
2797  res = GetPrinterW(hPrinter, 2, (LPBYTE)pi2, needed, &needed);
2798  }
2799 
2800  if ( res )
2801  {
2802  *dwVersion = 0x10000;
2803  *downloadFontsFlags = 0;
2804 
2805  if ( pi2->pServerName )
2806  {
2807  *downloadFontsFlags |= QSM_DOWNLOADINGFONTS;
2808  }
2809  }
2810 //
2811 // Guessing,,,
2812 // To do : Add GetPrinterDriver for DRIVER_INFO_8, test PRINTER_DRIVER_XPS flag,
2813 // to set *downloadFontsFlags |= QSM_XPS_PASS;
2814 //
2815 // Vista+ looks for QSM_XPS_PASS to be set in GDI32.
2816 //
2817  HeapFree(hProcessHeap, 0, pi2);
2818  return res;
2819 }
2820 
2821 //
2822 // This requires IC support.
2823 //
2824 DWORD WINAPI
2825 QueryRemoteFonts( HANDLE hPrinter, PUNIVERSAL_FONT_ID pufi, ULONG NumberOfUFIs )
2826 {
2827  HANDLE hIC;
2828  DWORD Result = -1, cOut, cIn = 0;
2829  PBYTE pOut;
2830 
2831  FIXME("QueryRemoteFonts(%p, %p, %lu)\n", hPrinter, pufi, NumberOfUFIs);
2832 
2833  hIC = CreatePrinterIC( hPrinter, NULL );
2834  if ( hIC )
2835  {
2836  cOut = (NumberOfUFIs * sizeof(UNIVERSAL_FONT_ID)) + sizeof(DWORD); // Include "DWORD" first part to return size.
2837 
2838  pOut = HeapAlloc( hProcessHeap, 0, cOut );
2839  if ( pOut )
2840  {
2841  if ( PlayGdiScriptOnPrinterIC( hIC, (LPBYTE)&cIn, sizeof(DWORD), pOut, cOut, 0 ) )
2842  {
2843  cIn = *((PDWORD)pOut); // Fisrt part is the size of the UFID object.
2844 
2845  Result = cIn; // Return the required size.
2846 
2847  if( NumberOfUFIs < cIn )
2848  {
2849  cIn = NumberOfUFIs;
2850  }
2851  // Copy whole object back to GDI32, exclude first DWORD part.
2852  memcpy( pufi, pOut + sizeof(DWORD), cIn * sizeof(UNIVERSAL_FONT_ID) );
2853  }
2854  HeapFree( hProcessHeap, 0, pOut );
2855  }
2856  DeletePrinterIC( hIC );
2857  }
2858  return Result;
2859 }
2860 
2861 BOOL WINAPI
2862 ReadPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pNoBytesRead)
2863 {
2864  DWORD dwErrorCode;
2865  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
2866 
2867  TRACE("ReadPrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pNoBytesRead);
2868 
2869  // Sanity checks.
2870  if (!pHandle)
2871  {
2872  dwErrorCode = ERROR_INVALID_HANDLE;
2873  goto Cleanup;
2874  }
2875 
2876  // Do the RPC call
2877  RpcTryExcept
2878  {
2879  dwErrorCode = _RpcReadPrinter(pHandle->hPrinter, pBuf, cbBuf, pNoBytesRead);
2880  }
2882  {
2883  dwErrorCode = RpcExceptionCode();
2884  ERR("_RpcReadPrinter failed with exception code %lu!\n", dwErrorCode);
2885  }
2886  RpcEndExcept;
2887 
2888 Cleanup:
2889  SetLastError(dwErrorCode);
2890  return (dwErrorCode == ERROR_SUCCESS);
2891 }
2892 
2893 BOOL WINAPI
2895 {
2896  BOOL ret;
2897  UNICODE_STRING pNameW;
2898  PDEVMODEW pdmw = NULL;
2899  PPRINTER_DEFAULTSW pdw = (PPRINTER_DEFAULTSW)pDefault;
2900 
2901  TRACE("ResetPrinterA(%p, %p)\n", hPrinter, pDefault);
2902 
2903  if ( pDefault->pDatatype == (LPSTR)-1 )
2904  {
2905  pdw->pDatatype = (LPWSTR)-1;
2906  }
2907  else
2908  {
2909  pdw->pDatatype = AsciiToUnicode( &pNameW, pDefault->pDatatype );
2910  }
2911  if ( pDefault->pDevMode == (LPDEVMODEA)-1)
2912  {
2913  pdw->pDevMode = (LPDEVMODEW)-1;
2914  }
2915  else
2916  {
2917  if ( pDefault->pDevMode )//&& IsValidDevmodeNoSizeW( pDefault->pDevMode ) )
2918  {
2919  RosConvertAnsiDevModeToUnicodeDevmode( pDefault->pDevMode, &pdmw );
2920  pdw->pDevMode = pdmw;
2921  }
2922  }
2923 
2924  ret = ResetPrinterW( hPrinter, pdw );
2925 
2926  if (pdmw) HeapFree(hProcessHeap, 0, pdmw);
2927 
2928  RtlFreeUnicodeString( &pNameW );
2929 
2930  return ret;
2931 }
2932 
2933 BOOL WINAPI
2935 {
2936  TRACE("ResetPrinterW(%p, %p)\n", hPrinter, pDefault);
2937  UNIMPLEMENTED;
2938  return FALSE;
2939 }
2940 
2941 BOOL WINAPI
2943 {
2944  BOOL bReturnValue = FALSE;
2945  DWORD cch;
2946  PWSTR pwszPrinter = NULL;
2947 
2948  TRACE("SetDefaultPrinterA(%s)\n", pszPrinter);
2949 
2950  if (pszPrinter)
2951  {
2952  // Convert pszPrinter to a Unicode string pwszPrinter
2953  cch = strlen(pszPrinter);
2954 
2955  pwszPrinter = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
2956  if (!pwszPrinter)
2957  {
2959  ERR("HeapAlloc failed!\n");
2960  goto Cleanup;
2961  }
2962 
2963  MultiByteToWideChar(CP_ACP, 0, pszPrinter, -1, pwszPrinter, cch + 1);
2964  }
2965 
2966  bReturnValue = SetDefaultPrinterW(pwszPrinter);
2967 
2968 Cleanup:
2969  if (pwszPrinter)
2970  HeapFree(hProcessHeap, 0, pwszPrinter);
2971 
2972  return bReturnValue;
2973 }
2974 
2975 BOOL WINAPI
2977 {
2978  const WCHAR wszDevicesKey[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Devices";
2979 
2980  DWORD cbDeviceValueData;
2981  DWORD cbPrinterValueData = 0;
2982  DWORD cchPrinter;
2983  DWORD dwErrorCode;
2984  HKEY hDevicesKey = NULL;
2985  HKEY hWindowsKey = NULL;
2986  PWSTR pwszDeviceValueData = NULL;
2987  WCHAR wszPrinter[MAX_PRINTER_NAME + 1];
2988 
2989  TRACE("SetDefaultPrinterW(%S)\n", pszPrinter);
2990 
2991  // Open the Devices registry key.
2992  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszDevicesKey, 0, KEY_READ, &hDevicesKey);
2993  if (dwErrorCode != ERROR_SUCCESS)
2994  {
2995  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
2996  goto Cleanup;
2997  }
2998 
2999  // Did the caller give us a printer to set as default?
3000  if (pszPrinter && *pszPrinter)
3001  {
3002  // Check if the given printer exists and query the value data size.
3003  dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, NULL, &cbPrinterValueData);
3004  if (dwErrorCode == ERROR_FILE_NOT_FOUND)
3005  {
3006  dwErrorCode = ERROR_INVALID_PRINTER_NAME;
3007  goto Cleanup;
3008  }
3009  else if (dwErrorCode != ERROR_SUCCESS)
3010  {
3011  ERR("RegQueryValueExW failed with status %lu!\n", dwErrorCode);
3012  goto Cleanup;
3013  }
3014 
3015  cchPrinter = wcslen(pszPrinter);
3016  }
3017  else
3018  {
3019  // If there is already a default printer, we're done!
3020  cchPrinter = _countof(wszPrinter);
3021  if (GetDefaultPrinterW(wszPrinter, &cchPrinter))
3022  {
3023  dwErrorCode = ERROR_SUCCESS;
3024  goto Cleanup;
3025  }
3026 
3027  // Otherwise, get us the first printer from the "Devices" key to later set it as default and query the value data size.
3028  cchPrinter = _countof(wszPrinter);
3029  dwErrorCode = (DWORD)RegEnumValueW(hDevicesKey, 0, wszPrinter, &cchPrinter, NULL, NULL, NULL, &cbPrinterValueData);
3030  if (dwErrorCode != ERROR_MORE_DATA)
3031  goto Cleanup;
3032 
3033  pszPrinter = wszPrinter;
3034  }
3035 
3036  // We now need to query the value data, which has the format "winspool,<Port>:"
3037  // and make "<Printer Name>,winspool,<Port>:" out of it.
3038  // Allocate a buffer large enough for the final data.
3039  cbDeviceValueData = (cchPrinter + 1) * sizeof(WCHAR) + cbPrinterValueData;
3040  pwszDeviceValueData = HeapAlloc(hProcessHeap, 0, cbDeviceValueData);
3041  if (!pwszDeviceValueData)
3042  {
3043  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3044  ERR("HeapAlloc failed!\n");
3045  goto Cleanup;
3046  }
3047 
3048  // Copy the Printer Name and a comma into it.
3049  CopyMemory(pwszDeviceValueData, pszPrinter, cchPrinter * sizeof(WCHAR));
3050  pwszDeviceValueData[cchPrinter] = L',';
3051 
3052  // Append the value data, which has the format "winspool,<Port>:"
3053  dwErrorCode = (DWORD)RegQueryValueExW(hDevicesKey, pszPrinter, NULL, NULL, (PBYTE)&pwszDeviceValueData[cchPrinter + 1], &cbPrinterValueData);
3054  if (dwErrorCode != ERROR_SUCCESS)
3055  goto Cleanup;
3056 
3057  // Open the Windows registry key.
3058  dwErrorCode = (DWORD)RegOpenKeyExW(HKEY_CURRENT_USER, wszWindowsKey, 0, KEY_SET_VALUE, &hWindowsKey);
3059  if (dwErrorCode != ERROR_SUCCESS)
3060  {
3061  ERR("RegOpenKeyExW failed with status %lu!\n", dwErrorCode);
3062  goto Cleanup;
3063  }
3064 
3065  // Store our new default printer.
3066  dwErrorCode = (DWORD)RegSetValueExW(hWindowsKey, wszDeviceValue, 0, REG_SZ, (PBYTE)pwszDeviceValueData, cbDeviceValueData);
3067  if (dwErrorCode != ERROR_SUCCESS)
3068  {
3069  ERR("RegSetValueExW failed with status %lu!\n", dwErrorCode);
3070  goto Cleanup;
3071  }
3072 
3073 Cleanup:
3074  if (hDevicesKey)
3075  RegCloseKey(hDevicesKey);
3076 
3077  if (hWindowsKey)
3078  RegCloseKey(hWindowsKey);
3079 
3080  if (pwszDeviceValueData)
3081  HeapFree(hProcessHeap, 0, pwszDeviceValueData);
3082 
3083  SetLastError(dwErrorCode);
3084  return (dwErrorCode == ERROR_SUCCESS);
3085 }
3086 
3087 BOOL WINAPI
3089 {
3090  BOOL Ret = FALSE;
3091  UNICODE_STRING usBuffer;
3092  PPRINTER_INFO_STRESS ppisa = (PPRINTER_INFO_STRESS)pPrinter;
3093  PPRINTER_INFO_STRESS ppisw = (PPRINTER_INFO_STRESS)pPrinter;
3094  PPRINTER_INFO_2A ppi2a = (PPRINTER_INFO_2A)pPrinter;
3095  PPRINTER_INFO_2W ppi2w = (PPRINTER_INFO_2W)pPrinter;
3096  PPRINTER_INFO_7A ppi7a = (PPRINTER_INFO_7A)pPrinter;
3097  PPRINTER_INFO_7W ppi7w = (PPRINTER_INFO_7W)pPrinter;
3098  PPRINTER_INFO_9A ppi9a = (PPRINTER_INFO_9A)pPrinter;
3099  PPRINTER_INFO_9W ppi9w = (PPRINTER_INFO_9W)pPrinter;
3100  PWSTR pwszPrinterName = NULL;
3101  PWSTR pwszServerName = NULL;
3102  PWSTR pwszShareName = NULL;
3103  PWSTR pwszPortName = NULL;
3104  PWSTR pwszDriverName = NULL;
3105  PWSTR pwszComment = NULL;
3106  PWSTR pwszLocation = NULL;
3107  PWSTR pwszSepFile = NULL;
3108  PWSTR pwszPrintProcessor = NULL;
3109  PWSTR pwszDatatype = NULL;
3110  PWSTR pwszParameters = NULL;
3111  PDEVMODEW pdmw = NULL;
3112 
3113  FIXME("SetPrinterA(%p, %lu, %p, %lu)\n", hPrinter, Level, pPrinter, Command);
3114 
3115  switch ( Level )
3116  {
3117  case 0:
3118  if ( Command == 0 )
3119  {
3120  if (ppisa->pPrinterName)
3121  {
3122  pwszPrinterName = AsciiToUnicode(&usBuffer, (LPCSTR)ppisa->pPrinterName);
3123  if (!(ppisw->pPrinterName = pwszPrinterName)) goto Cleanup;
3124  }
3125  if (ppisa->pServerName)
3126  {
3127  pwszServerName = AsciiToUnicode(&usBuffer, (LPCSTR)ppisa->pServerName);
3128  if (!(ppisw->pPrinterName = pwszServerName)) goto Cleanup;
3129  }
3130  }
3132  {
3133  // Set the pPrinter parameter to a pointer to a DWORD value that specifies the new printer status.
3134  PRINTER_INFO_6 pi6;
3135  pi6.dwStatus = (DWORD_PTR)pPrinter;
3136  pPrinter = (LPBYTE)&pi6;
3137  Level = 6;
3138  Command = 0;
3139  }
3140  break;
3141  case 2:
3142  {
3143  if (ppi2a->pShareName)
3144  {
3145  pwszShareName = AsciiToUnicode(&usBuffer, ppi2a->pShareName);
3146  if (!(ppi2w->pShareName = pwszShareName)) goto Cleanup;
3147  }
3148  if (ppi2a->pPortName)
3149  {
3150  pwszPortName = AsciiToUnicode(&usBuffer, ppi2a->pPortName);
3151  if (!(ppi2w->pPortName = pwszPortName)) goto Cleanup;
3152  }
3153  if (ppi2a->pDriverName)
3154  {
3155  pwszDriverName = AsciiToUnicode(&usBuffer, ppi2a->pDriverName);
3156  if (!(ppi2w->pDriverName = pwszDriverName)) goto Cleanup;
3157  }
3158  if (ppi2a->pComment)
3159  {
3160  pwszComment = AsciiToUnicode(&usBuffer, ppi2a->pComment);
3161  if (!(ppi2w->pComment = pwszComment)) goto Cleanup;
3162  }
3163  if (ppi2a->pLocation)
3164  {
3165  pwszLocation = AsciiToUnicode(&usBuffer, ppi2a->pLocation);
3166  if (!(ppi2w->pLocation = pwszLocation)) goto Cleanup;
3167  }
3168  if (ppi2a->pSepFile)
3169  {
3170  pwszSepFile = AsciiToUnicode(&usBuffer, ppi2a->pSepFile);
3171  if (!(ppi2w->pSepFile = pwszSepFile)) goto Cleanup;
3172  }
3173  if (ppi2a->pServerName)
3174  {
3175  pwszPrintProcessor = AsciiToUnicode(&usBuffer, ppi2a->pPrintProcessor);
3176  if (!(ppi2w->pPrintProcessor = pwszPrintProcessor)) goto Cleanup;
3177  }
3178  if (ppi2a->pDatatype)
3179  {
3180  pwszDatatype = AsciiToUnicode(&usBuffer, ppi2a->pDatatype);
3181  if (!(ppi2w->pDatatype = pwszDatatype)) goto Cleanup;
3182  }
3183  if (ppi2a->pParameters)
3184  {
3185  pwszParameters = AsciiToUnicode(&usBuffer, ppi2a->pParameters);
3186  if (!(ppi2w->pParameters = pwszParameters)) goto Cleanup;
3187  }
3188 
3189  if ( ppi2a->pDevMode )
3190  {
3192  ppi2w->pDevMode = pdmw;
3193  }
3194  }
3195  //
3196  // These two strings are relitive and common to these three Levels.
3197  // Fall through...
3198  //
3199  case 4:
3200  case 5:
3201  {
3202  if (ppi2a->pServerName) // 4 & 5 : pPrinterName.
3203  {
3204  pwszServerName = AsciiToUnicode(&usBuffer, ppi2a->pServerName);
3205  if (!(ppi2w->pPrinterName = pwszServerName)) goto Cleanup;
3206  }
3207  if (ppi2a->pPrinterName) // 4 : pServerName, 5 : pPortName.
3208  {
3209  pwszPrinterName = AsciiToUnicode(&usBuffer, ppi2a->pPrinterName);
3210  if (!(ppi2w->pPrinterName = pwszPrinterName)) goto Cleanup;
3211  }
3212  }
3213  break;
3214  case 3:
3215  case 6:
3216  break;
3217  case 7:
3218  {
3219  if (ppi7a->pszObjectGUID)
3220  {
3221  pwszPrinterName = AsciiToUnicode(&usBuffer, ppi7a->pszObjectGUID);
3222  if (!(ppi7w->pszObjectGUID = pwszPrinterName)) goto Cleanup;
3223  }
3224  }
3225  break;
3226 
3227  case 8:
3228  /* 8 is the global default printer info and 9 already sets it instead of the per-user one */
3229  /* still, PRINTER_INFO_8W is the same as PRINTER_INFO_9W */
3230  /* fall through */
3231  case 9:
3232  {
3234  ppi9w->pDevMode = pdmw;
3235  }
3236  break;
3237 
3238  default:
3239  FIXME( "Unsupported level %d\n", Level);
3241  }
3242 
3243  Ret = SetPrinterW( hPrinter, Level, pPrinter, Command );
3244 
3245 Cleanup:
3246  if (pdmw) HeapFree(hProcessHeap, 0, pdmw);
3247  if (pwszPrinterName) HeapFree(hProcessHeap, 0, pwszPrinterName);
3248  if (pwszServerName) HeapFree(hProcessHeap, 0, pwszServerName);
3249  if (pwszShareName) HeapFree(hProcessHeap, 0, pwszShareName);
3250  if (pwszPortName) HeapFree(hProcessHeap, 0, pwszPortName);
3251  if (pwszDriverName) HeapFree(hProcessHeap, 0, pwszDriverName);
3252  if (pwszComment) HeapFree(hProcessHeap, 0, pwszComment);
3253  if (pwszLocation) HeapFree(hProcessHeap, 0, pwszLocation);
3254  if (pwszSepFile) HeapFree(hProcessHeap, 0, pwszSepFile);
3255  if (pwszPrintProcessor) HeapFree(hProcessHeap, 0, pwszPrintProcessor);
3256  if (pwszDatatype) HeapFree(hProcessHeap, 0, pwszDatatype);
3257  if (pwszParameters) HeapFree(hProcessHeap, 0, pwszParameters);
3258  return Ret;
3259 }
3260 
3261 BOOL WINAPI
3263 {
3264  DWORD dwErrorCode;
3265  WINSPOOL_PRINTER_CONTAINER PrinterContainer;
3266  WINSPOOL_DEVMODE_CONTAINER DevModeContainer;
3267  WINSPOOL_SECURITY_CONTAINER SecurityContainer;
3269  DWORD size;
3270  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
3271 
3272  FIXME("SetPrinterW(%p, %lu, %p, %lu)\n", hPrinter, Level, pPrinter, Command);
3273 
3274  // Sanity checks
3275  if (!pHandle)
3276  return ERROR_INVALID_HANDLE;
3277 
3278  DevModeContainer.cbBuf = 0;
3279  DevModeContainer.pDevMode = NULL;
3280 
3281  SecurityContainer.cbBuf = 0;
3282  SecurityContainer.pSecurity = NULL;
3283 
3284  switch ( Level )
3285  {
3286  case 0:
3288  {
3289  // Set the pPrinter parameter to a pointer to a DWORD value that specifies the new printer status.
3290  PRINTER_INFO_6 pi6;
3291  pi6.dwStatus = (DWORD_PTR)pPrinter;
3292  pPrinter = (LPBYTE)&pi6;
3293  Level = 6;
3294  Command = 0;
3295  }
3296  break;
3297  case 2:
3298  {
3299  PPRINTER_INFO_2W pi2w = (PPRINTER_INFO_2W)pPrinter;
3300  if ( pi2w )
3301  {
3302  if ( pi2w->pDevMode )
3303  {
3304  if ( IsValidDevmodeNoSizeW( pi2w->pDevMode ) )
3305  {
3306  DevModeContainer.cbBuf = pi2w->pDevMode->dmSize + pi2w->pDevMode->dmDriverExtra;
3307  DevModeContainer.pDevMode = (PBYTE)pi2w->pDevMode;
3308  }
3309  }
3310 
3311  if ( pi2w->pSecurityDescriptor )
3312  {
3313  sd = get_sd( pi2w->pSecurityDescriptor, &size );
3314  if ( sd )
3315  {
3316  SecurityContainer.cbBuf = size;
3317  SecurityContainer.pSecurity = (PBYTE)sd;
3318  }
3319  }
3320  }
3321  else
3322  {
3324  return FALSE;
3325  }
3326  }
3327  break;
3328  case 3:
3329  {
3330  PPRINTER_INFO_3 pi3 = (PPRINTER_INFO_3)pPrinter;
3331  if ( pi3 )
3332  {
3333  if ( pi3->pSecurityDescriptor )
3334  {
3335  sd = get_sd( pi3->pSecurityDescriptor, &size );
3336  if ( sd )
3337  {
3338  SecurityContainer.cbBuf = size;
3339  SecurityContainer.pSecurity = (PBYTE)sd;
3340  }
3341  }
3342  }
3343  else
3344  {
3346  return FALSE;
3347  }
3348  }
3349  break;
3350 
3351  case 4:
3352  case 5:
3353  case 6:
3354  case 7:
3355  if ( pPrinter == NULL )
3356  {
3358  return FALSE;
3359  }
3360  break;
3361 
3362  case 8:
3363  /* 8 is the global default printer info and 9 already sets it instead of the per-user one */
3364  /* still, PRINTER_INFO_8W is the same as PRINTER_INFO_9W */
3365  /* fall through */
3366  case 9:
3367  {
3368  PPRINTER_INFO_9W pi9w = (PPRINTER_INFO_9W)pPrinter;
3369  if ( pi9w )
3370  {
3371  if ( pi9w->pDevMode )
3372  {
3373  if ( IsValidDevmodeNoSizeW( pi9w->pDevMode ) )
3374  {
3375  DevModeContainer.cbBuf = pi9w->pDevMode->dmSize + pi9w->pDevMode->dmDriverExtra;
3376  DevModeContainer.pDevMode = (LPBYTE)pi9w->pDevMode;
3377  }
3378  }
3379  }
3380  }
3381  break;
3382 
3383  default:
3384  FIXME( "Unsupported level %d\n", Level );
3386  return FALSE;
3387  }
3388 
3389  PrinterContainer.PrinterInfo.pPrinterInfo1 = (WINSPOOL_PRINTER_INFO_1*)pPrinter;
3390  PrinterContainer.Level = Level;
3391 
3392  // Do the RPC call
3393  RpcTryExcept
3394  {
3395  dwErrorCode = _RpcSetPrinter(pHandle->hPrinter, &PrinterContainer, &DevModeContainer, &SecurityContainer, Command);
3396  }
3398  {
3399  dwErrorCode = RpcExceptionCode();
3400  }
3401  RpcEndExcept;
3402 
3403  if ( sd ) HeapFree( GetProcessHeap(), 0, sd );
3404 
3405  SetLastError(dwErrorCode);
3406  return (dwErrorCode == ERROR_SUCCESS);
3407 }
3408 
3409 BOOL WINAPI
3411 {
3412  TRACE("DriverUnloadComplete(%S)\n", pDriverFile);
3413  UNIMPLEMENTED;
3414  return TRUE; // return true for now.
3415 }
3416 BOOL WINAPI
3417 
3418 SpoolerPrinterEvent( LPWSTR pPrinterName, INT DriverEvent, DWORD Flags, LPARAM lParam )
3419 {
3420  HMODULE hLibrary;
3421  HANDLE hPrinter;
3422  BOOL Ret = FALSE;
3423 
3424  if ( OpenPrinterW( pPrinterName, &hPrinter, NULL ) )
3425  {
3426  hLibrary = LoadPrinterDriver( hPrinter );
3427 
3428  if ( hLibrary )
3429  {
3430  fpPrinterEvent = (PVOID)GetProcAddress( hLibrary, "DrvPrinterEvent" );
3431 
3432  if ( fpPrinterEvent )
3433  {
3434  Ret = fpPrinterEvent( pPrinterName, DriverEvent, Flags, lParam );
3435  }
3436 
3438  }
3439 
3440  ClosePrinter( hPrinter );
3441  }
3442 
3443  return Ret;
3444 }
3445 
3447 {
3448  LPWSTR filename;
3449 
3450  switch(msg)
3451  {
3452  case WM_INITDIALOG:
3454  return TRUE;
3455 
3456  case WM_COMMAND:
3457  if(HIWORD(wparam) == BN_CLICKED)
3458  {
3459  if(LOWORD(wparam) == IDOK)
3460  {
3461  HANDLE hf;
3463  LPWSTR *output;
3464 
3465  filename = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
3467 
3469  {
3470  WCHAR caption[200], message[200];
3471  int mb_ret;
3472 
3473  LoadStringW(hinstWinSpool, IDS_CAPTION, caption, ARRAYSIZE(caption));
3475  mb_ret = MessageBoxW(hwnd, message, caption, MB_OKCANCEL | MB_ICONEXCLAMATION);
3476  if(mb_ret == IDCANCEL)
3477  {
3479  return TRUE;
3480  }
3481  }
3483  if(hf == INVALID_HANDLE_VALUE)
3484  {
3485  WCHAR caption[200], message[200];
3486 
3487  LoadStringW(hinstWinSpool, IDS_CAPTION, caption, ARRAYSIZE(caption));
3491  return TRUE;
3492  }
3493  CloseHandle(hf);
3496  *output = filename;
3497  EndDialog(hwnd, IDOK);
3498  return TRUE;
3499  }
3500  if(LOWORD(wparam) == IDCANCEL)
3501  {
3503  return TRUE;
3504  }
3505  }
3506  return FALSE;
3507  }
3508  return FALSE;
3509 }
3510 
3511 static const WCHAR FILE_Port[] = {'F','I','L','E',':',0};
3512 
3513 LPWSTR WINAPI
3514 StartDocDlgW( HANDLE hPrinter, DOCINFOW *doc )
3515 {
3516  LPWSTR ret = NULL;
3517  DWORD len, attr, retDlg;
3518 
3519  FIXME("StartDocDlgW(%p, %p)\n", hPrinter, doc);
3520 
3521  if (doc->lpszOutput == NULL) /* Check whether default port is FILE: */
3522  {
3523  PRINTER_INFO_5W *pi5;
3524  GetPrinterW(hPrinter, 5, NULL, 0, &len);
3526  return NULL;
3527  pi5 = HeapAlloc(GetProcessHeap(), 0, len);
3528  GetPrinterW(hPrinter, 5, (LPBYTE)pi5, len, &len);
3529  if (!pi5->pPortName || wcsicmp(pi5->pPortName, FILE_Port))
3530  {
3531  HeapFree(GetProcessHeap(), 0, pi5);
3532  return NULL;
3533  }
3534  HeapFree(GetProcessHeap(), 0, pi5);
3535  }
3536 
3537  if (doc->lpszOutput == NULL || !wcsicmp(doc->lpszOutput, FILE_Port))
3538  {
3539  LPWSTR name;
3540 
3541  retDlg = DialogBoxParamW( hinstWinSpool,
3544  file_dlg_proc,
3545  (LPARAM)&name );
3546 
3547  if ( retDlg == IDOK )
3548  {
3549  if (!(len = GetFullPathNameW(name, 0, NULL, NULL)))
3550  {
3551  HeapFree(GetProcessHeap(), 0, name);
3552  return NULL;
3553  }
3554  ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3556  HeapFree(GetProcessHeap(), 0, name);
3557  }
3558  else if ( retDlg == 0 ) // FALSE, some type of error occurred.
3559  {
3560  ret = (LPWSTR)SP_ERROR;
3561  }
3562  else if ( retDlg == IDCANCEL )
3563  {
3565  ret = (LPWSTR)SP_APPABORT;
3566  }
3567  return ret;
3568  }
3569 
3570  if (!(len = GetFullPathNameW(doc->lpszOutput, 0, NULL, NULL)))
3571  return NULL;
3572 
3573  ret = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3575 
3578  {
3579  HeapFree(GetProcessHeap(), 0, ret);
3580  ret = NULL;
3581  }
3582  return ret;
3583 }
3584 
3585 LPSTR WINAPI
3586 StartDocDlgA( HANDLE hPrinter, DOCINFOA *doc )
3587 {
3588  UNICODE_STRING usBuffer;
3589  DOCINFOW docW = { 0 };
3590  LPWSTR retW;
3591  LPWSTR docnameW = NULL, outputW = NULL, datatypeW = NULL;
3592  LPSTR ret = NULL;
3593 
3594  docW.cbSize = sizeof(docW);
3595  if (doc->lpszDocName)
3596  {
3597  docnameW = AsciiToUnicode(&usBuffer, doc->lpszDocName);
3598  if (!(docW.lpszDocName = docnameW)) goto failed;
3599  }
3600  if (doc->lpszOutput)
3601  {
3602  outputW = AsciiToUnicode(&usBuffer, doc->lpszOutput);
3603  if (!(docW.lpszOutput = outputW)) goto failed;
3604  }
3605  if (doc->lpszDatatype)
3606  {
3607  datatypeW = AsciiToUnicode(&usBuffer, doc->lpszDatatype);
3608  if (!(docW.lpszDatatype = datatypeW)) goto failed;
3609  }
3610  docW.fwType = doc->fwType;
3611 
3612  retW = StartDocDlgW(hPrinter, &docW);
3613 
3614  if (retW)
3615  {
3616  DWORD len = WideCharToMultiByte(CP_ACP, 0, retW, -1, NULL, 0, NULL, NULL);
3617  ret = HeapAlloc(GetProcessHeap(), 0, len);
3618  WideCharToMultiByte(CP_ACP, 0, retW, -1, ret, len, NULL, NULL);
3619  HeapFree(GetProcessHeap(), 0, retW);
3620  }
3621 
3622 failed:
3623  if (datatypeW) HeapFree(GetProcessHeap(), 0, datatypeW);
3624  if (outputW) HeapFree(GetProcessHeap(), 0, outputW);
3625  if (docnameW) HeapFree(GetProcessHeap(), 0, docnameW);
3626 
3627  return ret;
3628 }
3629 
3630 DWORD WINAPI
3632 {
3633  DOC_INFO_1W wDocInfo1 = { 0 };
3634  DWORD cch;
3635  DWORD dwErrorCode;
3636  DWORD dwReturnValue = 0;
3637  PDOC_INFO_1A pDocInfo1 = (PDOC_INFO_1A)pDocInfo;
3638 
3639  TRACE("StartDocPrinterA(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
3640 
3641  // Only check the minimum required for accessing pDocInfo.
3642  // Additional sanity checks are done in StartDocPrinterW.
3643  if (!pDocInfo1)
3644  {
3645  dwErrorCode = ERROR_INVALID_PARAMETER;
3646  goto Cleanup;
3647  }
3648 
3649  if (Level != 1)
3650  {
3651  ERR("Level = %d, unsupported!\n", Level);
3652  dwErrorCode = ERROR_INVALID_LEVEL;
3653  goto Cleanup;
3654  }
3655 
3656  if (pDocInfo1->pDatatype)
3657  {
3658  // Convert pDocInfo1->pDatatype to a Unicode string wDocInfo1.pDatatype
3659  cch = strlen(pDocInfo1->pDatatype);
3660 
3661  wDocInfo1.pDatatype = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
3662  if (!wDocInfo1.pDatatype)
3663  {
3664  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3665  ERR("HeapAlloc failed!\n");
3666  goto Cleanup;
3667  }
3668 
3669  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDatatype, -1, wDocInfo1.pDatatype, cch + 1);
3670  }
3671 
3672  if (pDocInfo1->pDocName)
3673  {
3674  // Convert pDocInfo1->pDocName to a Unicode string wDocInfo1.pDocName
3675  cch = strlen(pDocInfo1->pDocName);
3676 
3677  wDocInfo1.pDocName = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
3678  if (!wDocInfo1.pDocName)
3679  {
3680  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3681  ERR("HeapAlloc failed!\n");
3682  goto Cleanup;
3683  }
3684 
3685  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pDocName, -1, wDocInfo1.pDocName, cch + 1);
3686  }
3687 
3688  if (pDocInfo1->pOutputFile)
3689  {
3690  // Convert pDocInfo1->pOutputFile to a Unicode string wDocInfo1.pOutputFile
3691  cch = strlen(pDocInfo1->pOutputFile);
3692 
3693  wDocInfo1.pOutputFile = HeapAlloc(hProcessHeap, 0, (cch + 1) * sizeof(WCHAR));
3694  if (!wDocInfo1.pOutputFile)
3695  {
3696  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3697  ERR("HeapAlloc failed!\n");
3698  goto Cleanup;
3699  }
3700 
3701  MultiByteToWideChar(CP_ACP, 0, pDocInfo1->pOutputFile, -1, wDocInfo1.pOutputFile, cch + 1);
3702  }
3703 
3704  dwReturnValue = StartDocPrinterW(hPrinter, Level, (PBYTE)&wDocInfo1);
3705  dwErrorCode = GetLastError();
3706 
3707 Cleanup:
3708  if (wDocInfo1.pDatatype)
3709  HeapFree(hProcessHeap, 0, wDocInfo1.pDatatype);
3710 
3711  if (wDocInfo1.pDocName)
3712  HeapFree(hProcessHeap, 0, wDocInfo1.pDocName);
3713 
3714  if (wDocInfo1.pOutputFile)
3715  HeapFree(hProcessHeap, 0, wDocInfo1.pOutputFile);
3716 
3717  SetLastError(dwErrorCode);
3718  return dwReturnValue;
3719 }
3720 
3721 DWORD WINAPI
3723 {
3724  DWORD cbAddJobInfo1;
3725  DWORD cbNeeded;
3726  DWORD dwErrorCode;
3727  DWORD dwReturnValue = 0;
3728  PADDJOB_INFO_1W pAddJobInfo1 = NULL;
3729  PDOC_INFO_1W pDocInfo1 = (PDOC_INFO_1W)pDocInfo;
3730  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
3731 
3732  TRACE("StartDocPrinterW(%p, %lu, %p)\n", hPrinter, Level, pDocInfo);
3733 
3734  // Sanity checks.
3735  if (!pHandle)
3736  {
3737  dwErrorCode = ERROR_INVALID_HANDLE;
3738  goto Cleanup;
3739  }
3740 
3741  if (!pDocInfo1)
3742  {
3743  dwErrorCode = ERROR_INVALID_PARAMETER;
3744  goto Cleanup;
3745  }
3746 
3747  if (Level != 1)
3748  {
3749  ERR("Level = %d, unsupported!\n", Level);
3750  dwErrorCode = ERROR_INVALID_LEVEL;
3751  goto Cleanup;
3752  }
3753 
3754  if (pHandle->bStartedDoc)
3755  {
3756  dwErrorCode = ERROR_INVALID_PRINTER_STATE;
3757  goto Cleanup;
3758  }
3759 
3760  // Check if we want to redirect output into a file.
3761  if (pDocInfo1->pOutputFile)
3762  {
3763  // Do a StartDocPrinter RPC call in this case.
3764  dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1);
3765  }
3766  else
3767  {
3768  // Allocate memory for the ADDJOB_INFO_1W structure and a path.
3769  cbAddJobInfo1 = sizeof(ADDJOB_INFO_1W) + MAX_PATH * sizeof(WCHAR);
3770  pAddJobInfo1 = HeapAlloc(hProcessHeap, 0, cbAddJobInfo1);
3771  if (!pAddJobInfo1)
3772  {
3773  dwErrorCode = ERROR_NOT_ENOUGH_MEMORY;
3774  ERR("HeapAlloc failed!\n");
3775  goto Cleanup;
3776  }
3777 
3778  // Try to add a new job.
3779  // This only succeeds if the printer is set to do spooled printing.
3780  if (AddJobW((HANDLE)pHandle, 1, (PBYTE)pAddJobInfo1, cbAddJobInfo1, &cbNeeded))
3781  {
3782  // Do spooled printing.
3783  dwErrorCode = _StartDocPrinterSpooled(pHandle, pDocInfo1, pAddJobInfo1);
3784  }
3785  else if (GetLastError() == ERROR_INVALID_ACCESS)
3786  {
3787  // ERROR_INVALID_ACCESS is returned when the printer is set to do direct printing.
3788  // In this case, we do a StartDocPrinter RPC call.
3789  dwErrorCode = _StartDocPrinterWithRPC(pHandle, pDocInfo1);
3790  }
3791  else
3792  {
3793  dwErrorCode = GetLastError();
3794  ERR("AddJobW failed with error %lu!\n", dwErrorCode);
3795  goto Cleanup;
3796  }
3797  }
3798 
3799  if (dwErrorCode == ERROR_SUCCESS)
3800  {
3801  pHandle->bStartedDoc = TRUE;
3802  dwReturnValue = pHandle->dwJobID;
3803  if ( !pHandle->bTrayIcon )
3804  {
3805  FIXME("Notify Tray Icon\n");
3806  }
3807  }
3808 
3809 Cleanup:
3810  if (pAddJobInfo1)
3811  HeapFree(hProcessHeap, 0, pAddJobInfo1);
3812 
3813  SetLastError(dwErrorCode);
3814  return dwReturnValue;
3815 }
3816 
3817 BOOL WINAPI
3819 {
3820  DWORD dwErrorCode;
3821  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
3822 
3823  TRACE("StartPagePrinter(%p)\n", hPrinter);
3824 
3825  // Sanity checks.
3826  if (!pHandle)
3827  {
3828  dwErrorCode = ERROR_INVALID_HANDLE;
3829  goto Cleanup;
3830  }
3831 
3832  // Do the RPC call
3833  RpcTryExcept
3834  {
3835  dwErrorCode = _RpcStartPagePrinter(pHandle->hPrinter);
3836  }
3838  {
3839  dwErrorCode = RpcExceptionCode();
3840  ERR("_RpcStartPagePrinter failed with exception code %lu!\n", dwErrorCode);
3841  }
3842  RpcEndExcept;
3843 
3844 Cleanup:
3845  SetLastError(dwErrorCode);
3846  return (dwErrorCode == ERROR_SUCCESS);
3847 }
3848 
3849 BOOL WINAPI
3850 WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
3851 {
3852  DWORD dwErrorCode;
3853  PSPOOLER_HANDLE pHandle = (PSPOOLER_HANDLE)hPrinter;
3854 
3855  TRACE("WritePrinter(%p, %p, %lu, %p)\n", hPrinter, pBuf, cbBuf, pcWritten);
3856 
3857  // Sanity checks.
3858  if (!pHandle)
3859  {
3860  dwErrorCode = ERROR_INVALID_HANDLE;
3861  goto Cleanup;
3862  }
3863 
3864  if (!pHandle->bStartedDoc)
3865  {
3866  dwErrorCode = ERROR_SPL_NO_STARTDOC;
3867  goto Cleanup;
3868  }
3869 
3870  if (pHandle->hSPLFile != INVALID_HANDLE_VALUE)
3871  {
3872  // Write to the spool file. This doesn't need an RPC request.
3873  if (!WriteFile(pHandle->hSPLFile, pBuf, cbBuf, pcWritten, NULL))
3874  {
3875  dwErrorCode = GetLastError();
3876  ERR("WriteFile failed with error %lu!\n", dwErrorCode);
3877  goto Cleanup;
3878  }
3879 
3880  dwErrorCode = ERROR_SUCCESS;
3881  }
3882  else
3883  {
3884  // TODO: This case (for direct printing or remote printing) has bad performance if multiple small-sized WritePrinter calls are performed.
3885  // We may increase performance by writing into a buffer and only doing a single RPC call when the buffer is full.
3886 
3887  // Do the RPC call
3888  RpcTryExcept
3889  {
3890  dwErrorCode = _RpcWritePrinter(pHandle->hPrinter, pBuf, cbBuf, pcWritten);
3891  }
3893  {
3894  dwErrorCode = RpcExceptionCode();
3895  ERR("_RpcWritePrinter failed with exception code %lu!\n", dwErrorCode);
3896  }
3897  RpcEndExcept;
3898  }
3899 
3900 Cleanup:
3901  SetLastError(dwErrorCode);
3902  return (dwErrorCode == ERROR_SUCCESS);
3903 }
3904 
3905 BOOL WINAPI
3906 XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
3907 {
3908  TRACE("XcvDataW(%p, %S, %p, %lu, %p, %lu, %p, %p)\n", hXcv, pszDataName, pInputData, cbInputData, pOutputData, cbOutputData, pcbOutputNeeded, pdwStatus);
3909  return FALSE;
3910 }
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
#define SP_ERROR
Definition: wingdi.h:317
#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:66
DWORD _RpcStartPagePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:267
union _WINSPOOL_PRINTER_CONTAINER::@3364 PrinterInfo
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:56
#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:207
#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
#define TRUE
Definition: types.h:120
static UCHAR ULONG UCHAR ULONG UCHAR * output
Definition: bcrypt.c:29
#define IDOK
Definition: winuser.h:824
#define CloseHandle
Definition: compat.h:407
struct _devicemodeW * LPDEVMODEW
LONG(WINAPI * DOCUMENTPROPERTYSHEETS)(PPROPSHEETUI_INFO, LPARAM)
Definition: printers.c:23
#define IDI_CPSUI_DOCUMENT
Definition: compstui.h:88
LPCSTR pText
Definition: txtscale.cpp:79
LPSTR pPrinterName
Definition: winspool.h:110
INT_PTR WINAPI DialogBoxParamW(_In_opt_ HINSTANCE, _In_ LPCWSTR, _In_opt_ HWND, _In_opt_ DLGPROC, _In_ LPARAM)
struct _devicemodeW * PDEVMODEW
LONG WINAPI CallCommonPropertySheetUI(HWND hWnd, PFNPROPSHEETUI pfnPropSheetUI, LPARAM lparam, LPDWORD pResult)
Definition: printers.c:1134
#define ERROR_SUCCESS
Definition: deptool.c:10
#define DWORD_PTR
Definition: treelist.c:76
#define WideCharToMultiByte
Definition: compat.h:101
#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
LPWSTR pDatatype
Definition: winspool.h:72
HANDLE hComPropSheet
Definition: compstui.h:889
uint16_t * PWSTR
Definition: typedefs.h:55
DWORD _RpcEndDocPrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:61
BOOL WINAPI SetPrinterW(HANDLE hPrinter, DWORD Level, PBYTE pPrinter, DWORD Command)
Definition: printers.c:3262
#define ERR_CPSUI_ALLOCMEM_FAILED
Definition: compstui.h:645
#define CP_ACP
Definition: compat.h:99
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:1245
DWORD _RpcDeletePrinter(WINSPOOL_PRINTER_HANDLE hPrinter)
Definition: printers.c:54
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:88
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:27
BOOL WINAPI GetDefaultPrinterA(LPSTR pszBuffer, LPDWORD pcchBuffer)
Definition: printers.c:1899
#define QSM_DOWNLOADINGFONTS
Definition: printers.c:2767
HWND hWnd
Definition: settings.c:17
struct _ADDJOB_INFO_1W ADDJOB_INFO_1W
LPDEVMODEA pDevMode
Definition: winspool.h:166
HANDLE HWND
Definition: compat.h:13
WORD dmDriverExtra
Definition: wingdi.h:1620
struct _DEVICEPROPERTYHEADER DEVICEPROPERTYHEADER
#define FILENAME_DIALOG
Definition: wspool.h:29
#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:99
#define INVALID_HANDLE_VALUE
Definition: compat.h:400
static SPOOLERPRINTEREVENT fpPrinterEvent
Definition: printers.c:33
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#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:222
_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
int32_t INT_PTR
Definition: typedefs.h:63
struct _DEVQUERYPRINT_INFO * PDEVQUERYPRINT_INFO
#define JOB_CONTROL_DELETE
Definition: winspool.h:334
LONG WINAPI IntProtectHandle(HANDLE, BOOL)
Definition: utils.c:97
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:2894
#define DWORD
Definition: nt_native.h:44
DWORD dwJobID
Definition: precomp.h:49
int32_t INT
Definition: typedefs.h:57
BOOL WINAPI DeletePrinter(HANDLE hPrinter)
Definition: printers.c:452
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:125
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:1156
void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW *pDevModeOutput)
Definition: devmode.c:285
uint32_t ULONG_PTR
Definition: typedefs.h:64
#define MB_ICONEXCLAMATION
Definition: winuser.h:779
#define IDS_FILE_EXISTS
Definition: wspool.h:26
LPDEVMODEW pDevMode
Definition: winspool.h:858
#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:19
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:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LPSTR pComment
Definition: winspool.h:23
LONG WINAPI RegCloseKey(HKEY hKey)
Definition: reg.c:423
BOOL FASTCALL IntFixUpDevModeNames(PDOCUMENTPROPERTYHEADER pdphdr)
Definition: printers.c:820
unsigned char * LPBYTE
Definition: typedefs.h:53
BOOL WINAPI SpoolerPrinterEvent(LPWSTR pPrinterName, INT DriverEvent, DWORD Flags, LPARAM lParam)
Definition: printers.c:3418
LPWSTR pPrinterName
Definition: winspool.h:100
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:1945
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
BOOL WINAPI AbortPrinter(HANDLE hPrinter)
Definition: printers.c:155
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:802
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:751
#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:80
#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:2695
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:2934
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
BOOL WINAPI GetPrinterDriverW(HANDLE hPrinter, PWSTR pEnvironment, DWORD Level, PBYTE pDriverInfo, DWORD cbBuf, PDWORD pcbNeeded)
Definition: printers.c:125
#define MB_OKCANCEL
Definition: winuser.h:798
struct _PRINTER_INFO_2A * PPRINTER_INFO_2A
static DWORD _StartDocPrinterWithRPC(PSPOOLER_HANDLE pHandle, PDOC_INFO_1W pDocInfo1)
Definition: printers.c:132
DWORD dwStatus
Definition: winspool.h:130
BOOL WINAPI PlayGdiScriptOnPrinterIC(_In_ HANDLE hPrinterIC, _In_reads_bytes_(cIn) LPBYTE pIn, _In_ DWORD cIn, _Out_writes_bytes_(cOut) LPBYTE pOut, _In_ DWORD cOut, _In_ DWORD ul)
struct _PRINTER_INFO_1W * PPRINTER_INFO_1W
const char * LPCSTR
Definition: xmlstorage.h:183
#define DM_NOPERMISSION
Definition: winddiui.h:139
void * PVOID
Definition: retypes.h:9
LPSTR pPrinterName
Definition: winspool.h:94
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
struct _COMPUI_USERDATA COMPUI_USERDATA
unsigned long FLONG
Definition: ntbasedef.h:373
BOOL WINAPI WritePrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten)
Definition: printers.c:252
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:140
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
DWORD WINAPI PrinterMessageBoxW(HANDLE hPrinter, DWORD Error, HWND hWnd, LPWSTR pText, LPWSTR pCaption, DWORD dwType)
Definition: printers.c:2701
BOOL WINAPI ClosePrinter(HANDLE hPrinter)
Definition: printers.c:12
#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:414
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:404
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:852
HANDLE WINAPI CreatePrinterIC(_In_ HANDLE hPrinter, _In_opt_ LPDEVMODEW pDevMode)
DWORD _RpcScheduleJob(WINSPOOL_PRINTER_HANDLE hPrinter, DWORD JobId)
Definition: jobs.c:110
union _WINSPOOL_DOC_INFO_CONTAINER::@3358 DocInfo
BOOL WINAPI FlushPrinter(HANDLE hPrinter, PVOID pBuf, DWORD cbBuf, PDWORD pcWritten, DWORD cSleep)
Definition: printers.c:1891
WORD dmSize
Definition: wingdi.h:1619
#define MAX_PATH
Definition: compat.h:26
DWORD _RpcWritePrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE *pBuf, DWORD cbBuf, DWORD *pcWritten)
Definition: printers.c:286
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:72
ACCESS_MASK DesiredAccess
Definition: winspool.h:859
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
BOOL Error
Definition: chkdsk.c:66
#define SetLastError(x)
Definition: compat.h:418
DWORD _RpcReadPrinter(WINSPOOL_PRINTER_HANDLE hPrinter, BYTE *pBuf, DWORD cbBuf, DWORD *pcNoBytesRead)
Definition: printers.c:201
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
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
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:126
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:2556
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:3088
HMODULE hLibrary
Definition: odbccp32.c:12
BOOL WINAPI EndPagePrinter(HANDLE hPrinter)
Definition: printers.c:51
#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:170
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: main.c:12
BOOL bNoColorProfile
Definition: precomp.h:46
_In_ ULONG iEsc
Definition: winddi.h:3529
LPWSTR pPrinterName
Definition: winspool.h:118
#define WM_COMMAND
Definition: winuser.h:1722
BOOL WINAPI XcvDataW(HANDLE hXcv, PCWSTR pszDataName, PBYTE pInputData, DWORD cbInputData, PBYTE pOutputData, DWORD cbOutputData, PDWORD pcbOutputNeeded, PDWORD pdwStatus)
Definition: printers.c:267
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
static const WCHAR Cleanup[]
Definition: register.c:80
LPWSTR pComment
Definition: winspool.h:30
#define ERROR_MORE_DATA
Definition: dderror.h:13
_In_ LPWSTR _In_ ULONG _In_ ULONG _In_ ULONG _Out_ DEVINFO _In_ HDEV _In_ LPWSTR pwszDeviceName
Definition: winddi.h:3553
#define ERROR_INVALID_PRINTER_NAME
Definition: winerror.h:1108
unsigned char BYTE
Definition: xxhash.c:193
#define wcsicmp
Definition: string.h:1152
#define PSUIHDRF_NOAPPLYNOW
Definition: compstui.h:692
BOOL WINAPI MarshallUpStructure(DWORD cbSize, PVOID pStructure, const MARSHALLING_INFO *pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
Definition: marshalling.c:137
LPDEVMODEW pDevMode
Definition: winspool.h:69
HANDLE WINAPI AddPrinterA(PSTR pName, DWORD Level, PBYTE pPrinter)
Definition: printers.c:200
struct _UNIVERSAL_FONT_ID UNIVERSAL_FONT_ID
LPDEVMODEA pDevMode
Definition: winspool.h:45
BOOL WINAPI QueryColorProfile(HANDLE hPrinter, PDEVMODEW pdevmode, ULONG ulQueryMode, VOID *pvProfileData, ULONG *pcbProfileData, FLONG *pflProfileData)
Definition: printers.c:2707
#define ERR(fmt,...)
Definition: debug.h:110
LPWSTR pDescription
Definition: winspool.h:28
LPWSTR pszObjectGUID
Definition: winspool.h:139
struct _SETRESULT_INFO * PSETRESULT_INFO
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
DWORD WINAPI DeviceCapabilitiesA(LPCSTR pDevice, LPCSTR pPort, WORD fwCapability, LPSTR pOutput, const DEVMODEA *pDevMode)
Definition: printers.c:529
HANDLE WINAPI AddPrinterW(PWSTR pName, DWORD Level, PBYTE pPrinter)
Definition: printers.c:313
#define PROPSHEETUI_REASON_INIT
Definition: compstui.h:627
#define CREATE_ALWAYS
Definition: disk.h:72
struct _PRINTER_INFO_4W * PPRINTER_INFO_4W
#define PROPSHEETUI_REASON_DESTROY
Definition: compstui.h:629
LONG(WINAPI * QUERYCOLORPROFILE)(HANDLE, PDEVMODEW, ULONG, PVOID, ULONG *, FLONG *)
Definition: printers.c:29
#define DM_IN_BUFFER
Definition: windef.h:357
LPWSTR pPortName
Definition: winspool.h:119
#define ERROR_CANCELLED
Definition: winerror.h:726
static const MARSHALLING * pPrinterInfoMarshalling[]
Definition: printers.h:146
#define CCHDEVICENAME
Definition: ddrawi.h:63
_In_ DWORD _Out_ PDWORD pcbNeeded
Definition: winddi.h:3827
struct _PRINTER_DEFAULTS