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