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