2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * PURPOSE: GDI Printing Support
5 * FILE: dll/win32/gdi32/objects/printdrv.c
12 * Implementation of some printer driver bits
14 * Copyright 1996 John Harvey
15 * Copyright 1998 Huw Davies
16 * Copyright 1998 Andreas Mohr
17 * Copyright 1999 Klaas van Gend
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Lesser General Public
21 * License as published by the Free Software Foundation; either
22 * version 2.1 of the License, or (at your option) any later version.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
39 /* GLOBALS *******************************************************************/
40 HANDLE ghSpooler
= NULL
;
42 static ABORTPRINTER fpAbortPrinter
;
43 CLOSEPRINTER fpClosePrinter
;
44 static CLOSESPOOLFILEHANDLE fpCloseSpoolFileHandle
;
45 static COMMITSPOOLDATA fpCommitSpoolData
;
46 //static fpConnectToLd64In32Server;
47 static DOCUMENTEVENT fpDocumentEvent
;
48 static DOCUMENTPROPERTIESW fpDocumentPropertiesW
;
49 static ENDDOCPRINTER fpEndDocPrinter
;
50 static ENDPAGEPRINTER fpEndPagePrinter
;
51 static GETSPOOLFILEHANDLE fpGetSpoolFileHandle
;
52 static GETPRINTERW fpGetPrinterW
;
53 static GETPRINTERDRIVERW fpGetPrinterDriverW
;
54 static ISVALIDDEVMODEW fpIsValidDevmodeW
;
55 OPENPRINTERW fpOpenPrinterW
;
56 static QUERYSPOOLMODE fpQuerySpoolMode
;
57 static QUERYREMOTEFONTS fpQueryRemoteFonts
;
58 static QUERYCOLORPROFILE fpQueryColorProfile
;
59 static READPRINTER fpReadPrinter
;
60 static RESETPRINTERW fpResetPrinterW
;
61 static SEEKPRINTER fpSeekPrinter
;
62 static SPLDRIVERUNLOADCOMPLETE fpSplDriverUnloadComplete
;
63 static SPLREADPRINTER fpSplReadPrinter
;
64 static STARTDOCDLGW fpStartDocDlgW
;
65 static STARTDOCPRINTERW fpStartDocPrinterW
;
66 static STARTPAGEPRINTER fpStartPagePrinter
;
68 /* PRIVATE FUNCTIONS *********************************************************/
80 ULONG hType
= GDI_HANDLE_GET_TYPE(hdc
);
82 if (hType
== GDILoObjType_LO_DC_TYPE
|| hType
== GDILoObjType_LO_METADC16_TYPE
)
84 SetLastError(ERROR_INVALID_HANDLE
);
88 pldc
= GdiGetLDC(hdc
);
91 SetLastError(ERROR_INVALID_HANDLE
);
95 if (pldc
->Flags
& LDC_ATENDPAGE
) return 1;
97 if (pldc
->Flags
& LDC_META_PRINT
)
110 if (pldc
->Flags
& LDC_KILL_DOCUMENT
|| pldc
->Flags
& LDC_INIT_PAGE
)
112 SetLastError(ERROR_INVALID_PARAMETER
);
116 if (pldc
->Flags
& LDC_SAPCALLBACK
) GdiSAPCallback(pldc
);
118 pldc
->Flags
&= ~LDC_INIT_PAGE
;
120 DocumentEventEx(NULL
, pldc
->hPrinter
, hdc
, DOCUMENTEVENT_ENDPAGE
, 0, NULL
, 0, NULL
);
122 ((PW32CLIENTINFO
)NtCurrentTeb()->Win32ClientInfo
)->cSpins
= 0;
124 if ( NtGdiEndPage(hdc
) )
127 // if (pldc->pUMPDev)
128 Good
= EndPagePrinterEx(NULL
,pldc
->hPrinter
);
130 if (Good
) pldc
->Flags
|= LDC_STARTPAGE
;
134 SetLastError(ERROR_INVALID_PARAMETER
);
138 /* FUNCTIONS *****************************************************************/
147 return fpAbortPrinter(hPrinter
);
163 return fpDocumentEvent(hPrinter
,hdc
,iEsc
,cbIn
,pvIn
,cbOut
,pvOut
);
173 return fpEndDocPrinter(hPrinter
);
183 return fpEndPagePrinter(hPrinter
);
188 LoadTheSpoolerDrv(VOID
)
190 HMODULE hModWinSpoolDrv
;
194 RtlEnterCriticalSection(&semLocal
);
196 hModWinSpoolDrv
= LoadLibraryW(L
"WINSPOOL.DRV");
200 fpAbortPrinter
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "AbortPrinter");
201 fpClosePrinter
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "ClosePrinter");
202 fpCloseSpoolFileHandle
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "CloseSpoolFileHandle");
203 fpCommitSpoolData
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "CommitSpoolData");
204 // fpConnectToLd64In32Server = (PVOID)GetProcAddress(hModWinSpoolDrv, (LPCSTR)224);
205 fpDocumentEvent
= (PVOID
)GetProcAddress(hModWinSpoolDrv
,"DocumentEvent");
206 fpDocumentPropertiesW
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "DocumentPropertiesW");
207 fpEndDocPrinter
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "EndDocPrinter");
208 fpEndPagePrinter
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "EndPagePrinter");
209 fpGetPrinterW
= (PVOID
)GetProcAddress( hModWinSpoolDrv
,"GetPrinterW");
210 fpGetPrinterDriverW
= (PVOID
)GetProcAddress(hModWinSpoolDrv
,"GetPrinterDriverW");
211 fpGetSpoolFileHandle
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "GetSpoolFileHandle");
212 fpIsValidDevmodeW
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "IsValidDevmodeW");
213 fpOpenPrinterW
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "OpenPrinterW");
214 fpQueryColorProfile
= (PVOID
)GetProcAddress(hModWinSpoolDrv
,"QueryColorProfile");
215 fpQueryRemoteFonts
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "QueryRemoteFonts");
216 fpQuerySpoolMode
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "QuerySpoolMode");
217 fpReadPrinter
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "ReadPrinter");
218 fpResetPrinterW
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "ResetPrinterW");
219 fpSeekPrinter
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "SeekPrinter");
220 fpSplDriverUnloadComplete
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "SplDriverUnloadComplete");
221 fpSplReadPrinter
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, (LPCSTR
)205);
222 fpStartDocDlgW
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "StartDocDlgW");
223 fpStartDocPrinterW
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "StartDocPrinterW");
224 fpStartPagePrinter
= (PVOID
)GetProcAddress(hModWinSpoolDrv
, "StartPagePrinter");
226 if ( !fpAbortPrinter
||
228 !fpCloseSpoolFileHandle
||
229 !fpCommitSpoolData
||
231 !fpDocumentPropertiesW
||
235 !fpGetPrinterDriverW
||
236 !fpGetSpoolFileHandle
||
237 !fpIsValidDevmodeW
||
239 !fpQueryColorProfile
||
240 !fpQueryRemoteFonts
||
245 !fpSplDriverUnloadComplete
||
248 !fpStartDocPrinterW
||
249 !fpStartPagePrinter
)
251 FreeLibrary(hModWinSpoolDrv
);
252 hModWinSpoolDrv
= NULL
;
254 ghSpooler
= hModWinSpoolDrv
;
256 RtlLeaveCriticalSection(&semLocal
);
261 if ( !ghSpooler
) SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
263 return (ghSpooler
!= NULL
);
269 The sequence for a print job is as follows:
271 1. To begin a print job, call StartDocPrinter.
272 2. To begin each page, call StartPagePrinter.
273 3. To write data to a page, call WritePrinter.
274 4. To end each page, call EndPagePrinter.
275 5. Repeat 2, 3, and 4 for as many pages as necessary.
276 6. To end the print job, call EndDocPrinter.
288 return fpStartDocPrinterW(hPrinter
,Level
,pDocInfo
);
298 return fpStartPagePrinter(hPrinter
);
301 /* SYSCALLS ******************************************************************/
314 ULONG hType
= GDI_HANDLE_GET_TYPE(hdc
);
316 if (hType
== GDILoObjType_LO_DC_TYPE
|| hType
== GDILoObjType_LO_METADC16_TYPE
)
318 SetLastError(ERROR_INVALID_HANDLE
);
322 pldc
= GdiGetLDC(hdc
);
325 SetLastError(ERROR_INVALID_HANDLE
);
329 if ( !(pldc
->Flags
& LDC_INIT_DOCUMENT
) ) return 1;
331 DocumentEventEx(NULL
, pldc
->hPrinter
, hdc
, DOCUMENTEVENT_ABORTDOC
, 0, NULL
, 0, NULL
);
333 ((PW32CLIENTINFO
)NtCurrentTeb()->Win32ClientInfo
)->cSpins
= 0;
335 if ( pldc
->Flags
& LDC_META_PRINT
)
338 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
342 if (NtGdiAbortDoc(hdc
))
344 if (fpAbortPrinter(pldc
->hPrinter
)) Ret
= 1;
349 pldc
->Flags
&= ~(LDC_ATENDPAGE
|LDC_META_PRINT
|LDC_STARTPAGE
|LDC_INIT_PAGE
|LDC_INIT_DOCUMENT
|LDC_SAPCALLBACK
);
365 ULONG hType
= GDI_HANDLE_GET_TYPE(hdc
);
367 if (hType
== GDILoObjType_LO_DC_TYPE
|| hType
== GDILoObjType_LO_METADC16_TYPE
)
369 SetLastError(ERROR_INVALID_HANDLE
);
373 pldc
= GdiGetLDC(hdc
);
376 SetLastError(ERROR_INVALID_HANDLE
);
380 if (pldc
->Flags
& LDC_META_PRINT
)
383 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
387 if (pldc
->Flags
& LDC_INIT_DOCUMENT
)
390 if (pldc
->Flags
& LDC_INIT_PAGE
) EndPage(hdc
);
392 DocumentEventEx(NULL
, pldc
->hPrinter
, hdc
, DOCUMENTEVENT_ENDDOC
, 0, NULL
, 0, NULL
);
394 ((PW32CLIENTINFO
)NtCurrentTeb()->Win32ClientInfo
)->cSpins
= 0;
396 Good
= NtGdiEndDoc(hdc
);
398 // if (pldc->pUMPDev)
399 Good
= EndDocPrinterEx(NULL
,pldc
->hPrinter
);
403 DocumentEventEx(NULL
, pldc
->hPrinter
, hdc
, DOCUMENTEVENT_ENDDOCPOST
, 0, NULL
, 0, NULL
);
406 pldc
->Flags
&= ~(LDC_ATENDPAGE
|LDC_STARTPAGE
|LDC_INIT_DOCUMENT
|LDC_SAPCALLBACK
);
418 return IntEndPage(hdc
,TRUE
);
428 return IntEndPage(hdc
,FALSE
);
436 GdiGetSpoolFileHandle(LPWSTR pwszPrinterName
,
441 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
450 GdiDeleteSpoolFileHandle(HANDLE SpoolFileHandle
)
453 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
462 GdiGetPageCount(HANDLE SpoolFileHandle
)
465 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
482 LPWSTR lpwstrRet
= NULL
;
484 int PrnJobNo
, Ret
= SP_ERROR
;
485 ULONG hType
= GDI_HANDLE_GET_TYPE(hdc
);
487 if (hType
== GDILoObjType_LO_DC_TYPE
|| hType
== GDILoObjType_LO_METADC16_TYPE
)
490 pldc
= GdiGetLDC(hdc
);
491 if ( !pldc
|| pldc
->Flags
& LDC_ATENDPAGE
)
493 SetLastError(ERROR_INVALID_HANDLE
);
497 if (!pldc
->hPrinter
) return SP_ERROR
;
499 pldc
->Flags
&= ~LDC_KILL_DOCUMENT
;
502 RtlCopyMemory(&diW
, lpdi
, sizeof(DOCINFOW
));
505 diW
.cbSize
= sizeof(DOCINFOW
);
506 diW
.lpszDocName
= NULL
;
507 diW
.lpszOutput
= NULL
;
508 diW
.lpszDatatype
= NULL
;
513 if (pldc
->pwszPort
) diW
.lpszOutput
= pldc
->pwszPort
;
515 lpwstrRet
= fpStartDocDlgW(pldc
->hPrinter
, &diW
);
516 if (lpwstrRet
== (LPWSTR
)SP_APPABORT
)
518 pldc
->Flags
|= LDC_KILL_DOCUMENT
;
521 if (lpwstrRet
== (LPWSTR
)SP_ERROR
) return SP_ERROR
;
523 if (lpwstrRet
!= 0) diW
.lpszOutput
= lpwstrRet
;
525 Ret
= DocumentEventEx( NULL
,
528 DOCUMENTEVENT_STARTDOC
,
534 if (Ret
== SP_APPABORT
)
536 pldc
->Flags
|= LDC_KILL_DOCUMENT
;
541 if (lpwstrRet
) LocalFree(lpwstrRet
);
545 di1W
.pDocName
= (LPWSTR
)diW
.lpszDocName
;
546 di1W
.pOutputFile
= (LPWSTR
)diW
.lpszOutput
;
547 di1W
.pDatatype
= (LPWSTR
)diW
.lpszDatatype
;
551 PrnJobNo
= StartDocPrinterWEx(NULL
, pldc
->hPrinter
, 1, (LPBYTE
)&di1W
);
554 Ret
= NtGdiStartDoc( hdc
, &diW
, &Banding
, PrnJobNo
);
557 if (pldc
->pAbortProc
)
559 GdiSAPCallback(pldc
);
560 pldc
->Flags
|= LDC_SAPCALLBACK
;
561 pldc
->CallBackTick
= GetTickCount();
563 pldc
->Flags
|= LDC_INIT_DOCUMENT
;
564 if (!Banding
) pldc
->Flags
|= LDC_STARTPAGE
;
569 //if ( pldc->pUMPDev )
570 AbortPrinterEx(NULL
, pldc
->hPrinter
);
571 DPRINT1("StartDoc Died!!!\n");
575 if ( DocumentEventEx( NULL
,
578 DOCUMENTEVENT_STARTDOCPOST
,
588 if (lpwstrRet
) LocalFree(lpwstrRet
);
602 LPWSTR szDocName
= NULL
, szOutput
= NULL
, szDatatype
= NULL
;
606 docW
.cbSize
= lpdi
->cbSize
;
607 if (lpdi
->lpszDocName
)
609 len
= MultiByteToWideChar(CP_ACP
,0,lpdi
->lpszDocName
,-1,NULL
,0);
610 szDocName
= HeapAlloc(GetProcessHeap(),0,len
*sizeof(WCHAR
));
611 MultiByteToWideChar(CP_ACP
,0,lpdi
->lpszDocName
,-1,szDocName
,len
);
613 if (lpdi
->lpszOutput
)
615 len
= MultiByteToWideChar(CP_ACP
,0,lpdi
->lpszOutput
,-1,NULL
,0);
616 szOutput
= HeapAlloc(GetProcessHeap(),0,len
*sizeof(WCHAR
));
617 MultiByteToWideChar(CP_ACP
,0,lpdi
->lpszOutput
,-1,szOutput
,len
);
619 if (lpdi
->lpszDatatype
)
621 len
= MultiByteToWideChar(CP_ACP
,0,lpdi
->lpszDatatype
,-1,NULL
,0);
622 szDatatype
= HeapAlloc(GetProcessHeap(),0,len
*sizeof(WCHAR
));
623 MultiByteToWideChar(CP_ACP
,0,lpdi
->lpszDatatype
,-1,szDatatype
,len
);
626 docW
.lpszDocName
= szDocName
;
627 docW
.lpszOutput
= szOutput
;
628 docW
.lpszDatatype
= szDatatype
;
629 docW
.fwType
= lpdi
->fwType
;
631 ret
= StartDocW(hdc
, &docW
);
633 HeapFree( GetProcessHeap(), 0, szDocName
);
634 HeapFree( GetProcessHeap(), 0, szOutput
);
635 HeapFree( GetProcessHeap(), 0, szDatatype
);
650 ULONG hType
= GDI_HANDLE_GET_TYPE(hdc
);
652 if (hType
== GDILoObjType_LO_DC_TYPE
|| hType
== GDILoObjType_LO_METADC16_TYPE
)
654 SetLastError(ERROR_INVALID_HANDLE
);
658 pldc
= GdiGetLDC(hdc
);
661 SetLastError(ERROR_INVALID_HANDLE
);
665 if (pldc
->Flags
& LDC_META_PRINT
)
668 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
672 pldc
->Flags
&= ~(LDC_ATENDPAGE
|LDC_STARTPAGE
);
674 if (pldc
->Flags
& LDC_INIT_PAGE
) return 1;
676 if (DocumentEventEx(NULL
, pldc
->hPrinter
, hdc
, DOCUMENTEVENT_STARTPAGE
, 0, NULL
, 0, NULL
) != SP_ERROR
)
678 pldc
->Flags
|= LDC_INIT_PAGE
;
680 ((PW32CLIENTINFO
)NtCurrentTeb()->Win32ClientInfo
)->cSpins
= 0;
682 if (StartPagePrinterEx(NULL
, pldc
->hPrinter
))
684 if (NtGdiStartPage(hdc
)) return 1;
687 pldc
->Flags
&= ~(LDC_INIT_PAGE
);
689 SetLastError(ERROR_INVALID_HANDLE
);
701 ABORTPROC lpAbortProc
)
704 ULONG hType
= GDI_HANDLE_GET_TYPE(hdc
);
706 if (hType
== GDILoObjType_LO_DC_TYPE
|| hType
== GDILoObjType_LO_METADC16_TYPE
)
709 pldc
= GdiGetLDC(hdc
);
714 if ( pldc
->Flags
& LDC_INIT_DOCUMENT
)
716 pldc
->Flags
|= LDC_SAPCALLBACK
;
717 pldc
->CallBackTick
= GetTickCount();
722 pldc
->Flags
&= ~LDC_SAPCALLBACK
;
724 pldc
->pAbortProc
= lpAbortProc
;
729 SetLastError(ERROR_INVALID_HANDLE
);