Fix build
[reactos.git] / reactos / dll / win32 / gdi32 / objects / printdrv.c
1 /*
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
6 * PROGRAMER:
7 *
8 */
9
10 // For the wine code:
11 /*
12 * Implementation of some printer driver bits
13 *
14 * Copyright 1996 John Harvey
15 * Copyright 1998 Huw Davies
16 * Copyright 1998 Andreas Mohr
17 * Copyright 1999 Klaas van Gend
18 *
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.
23 *
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.
28 *
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
32 */
33
34 #include "precomp.h"
35
36 #define NDEBUG
37 #include <debug.h>
38
39 /* GLOBALS *******************************************************************/
40 HANDLE ghSpooler = NULL;
41
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;
67
68 /* PRIVATE FUNCTIONS *********************************************************/
69
70 static
71 int
72 FASTCALL
73 IntEndPage(
74 HDC hdc,
75 BOOL Form
76 )
77 {
78 PLDC pldc;
79 int Ret = SP_ERROR;
80 ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
81
82 if (hType == GDILoObjType_LO_DC_TYPE || hType == GDILoObjType_LO_METADC16_TYPE)
83 {
84 SetLastError(ERROR_INVALID_HANDLE);
85 return SP_ERROR;
86 }
87
88 pldc = GdiGetLDC(hdc);
89 if ( !pldc )
90 {
91 SetLastError(ERROR_INVALID_HANDLE);
92 return SP_ERROR;
93 }
94
95 if (pldc->Flags & LDC_ATENDPAGE) return 1;
96
97 if (pldc->Flags & LDC_META_PRINT)
98 {
99 if ( Form )
100 {
101 // Do MF EndPageForm
102 }
103 else
104 {
105 // Do MF EndPage
106 }
107 return Ret;
108 }
109
110 if (pldc->Flags & LDC_KILL_DOCUMENT || pldc->Flags & LDC_INIT_PAGE)
111 {
112 SetLastError(ERROR_INVALID_PARAMETER);
113 return SP_ERROR;
114 }
115
116 if (pldc->Flags & LDC_SAPCALLBACK) GdiSAPCallback(pldc);
117
118 pldc->Flags &= ~LDC_INIT_PAGE;
119
120 DocumentEventEx(NULL, pldc->hPrinter, hdc, DOCUMENTEVENT_ENDPAGE, 0, NULL, 0, NULL);
121
122 ((PW32CLIENTINFO)NtCurrentTeb()->Win32ClientInfo)->cSpins = 0;
123
124 if ( NtGdiEndPage(hdc) )
125 {
126 BOOL Good;
127 // if (pldc->pUMPDev)
128 Good = EndPagePrinterEx(NULL,pldc->hPrinter);
129
130 if (Good) pldc->Flags |= LDC_STARTPAGE;
131 Ret = 1;
132 }
133 else
134 SetLastError(ERROR_INVALID_PARAMETER);
135 return Ret;
136 }
137
138 /* FUNCTIONS *****************************************************************/
139
140 BOOL
141 FASTCALL
142 AbortPrinterEx(
143 PVOID pvUMPDev,
144 HANDLE hPrinter
145 )
146 {
147 return fpAbortPrinter(hPrinter);
148 }
149
150 int
151 FASTCALL
152 DocumentEventEx(
153 PVOID pvUMPDev,
154 HANDLE hPrinter,
155 HDC hdc,
156 int iEsc,
157 ULONG cbIn,
158 PVOID pvIn,
159 ULONG cbOut,
160 PVOID pvOut
161 )
162 {
163 return fpDocumentEvent(hPrinter,hdc,iEsc,cbIn,pvIn,cbOut,pvOut);
164 }
165
166 BOOL
167 FASTCALL
168 EndDocPrinterEx(
169 PVOID pvUMPDev,
170 HANDLE hPrinter
171 )
172 {
173 return fpEndDocPrinter(hPrinter);
174 }
175
176 BOOL
177 FASTCALL
178 EndPagePrinterEx(
179 PVOID pvUMPDev,
180 HANDLE hPrinter
181 )
182 {
183 return fpEndPagePrinter(hPrinter);
184 }
185
186 BOOL
187 FASTCALL
188 LoadTheSpoolerDrv(VOID)
189 {
190 HMODULE hModWinSpoolDrv;
191
192 if ( !ghSpooler )
193 {
194 RtlEnterCriticalSection(&semLocal);
195
196 hModWinSpoolDrv = LoadLibraryW(L"WINSPOOL.DRV");
197
198 if (hModWinSpoolDrv)
199 {
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");
225
226 if ( !fpAbortPrinter ||
227 !fpClosePrinter ||
228 !fpCloseSpoolFileHandle ||
229 !fpCommitSpoolData ||
230 !fpDocumentEvent ||
231 !fpDocumentPropertiesW ||
232 !fpEndDocPrinter ||
233 !fpEndPagePrinter ||
234 !fpGetPrinterW ||
235 !fpGetPrinterDriverW ||
236 !fpGetSpoolFileHandle ||
237 !fpIsValidDevmodeW ||
238 !fpOpenPrinterW ||
239 !fpQueryColorProfile ||
240 !fpQueryRemoteFonts ||
241 !fpQuerySpoolMode ||
242 !fpReadPrinter ||
243 !fpResetPrinterW ||
244 !fpSeekPrinter ||
245 !fpSplDriverUnloadComplete ||
246 !fpSplReadPrinter ||
247 !fpStartDocDlgW ||
248 !fpStartDocPrinterW ||
249 !fpStartPagePrinter )
250 {
251 FreeLibrary(hModWinSpoolDrv);
252 hModWinSpoolDrv = NULL;
253 }
254 ghSpooler = hModWinSpoolDrv;
255 }
256 RtlLeaveCriticalSection(&semLocal);
257 }
258 else
259 return TRUE;
260
261 if ( !ghSpooler ) SetLastError(ERROR_NOT_ENOUGH_MEMORY);
262
263 return (ghSpooler != NULL);
264 }
265
266 /*
267 Note from msdn:
268
269 The sequence for a print job is as follows:
270
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.
277
278 */
279 DWORD
280 FASTCALL
281 StartDocPrinterWEx(
282 PVOID pvUMPDev,
283 HANDLE hPrinter,
284 DWORD Level,
285 LPBYTE pDocInfo
286 )
287 {
288 return fpStartDocPrinterW(hPrinter,Level,pDocInfo);
289 }
290
291 BOOL
292 FASTCALL
293 StartPagePrinterEx(
294 PVOID pvUMPDev,
295 HANDLE hPrinter
296 )
297 {
298 return fpStartPagePrinter(hPrinter);
299 }
300
301 /* SYSCALLS ******************************************************************/
302
303 /*
304 * @unimplemented
305 */
306 int
307 WINAPI
308 AbortDoc(
309 HDC hdc
310 )
311 {
312 PLDC pldc;
313 int Ret = SP_ERROR;
314 ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
315
316 if (hType == GDILoObjType_LO_DC_TYPE || hType == GDILoObjType_LO_METADC16_TYPE)
317 {
318 SetLastError(ERROR_INVALID_HANDLE);
319 return SP_ERROR;
320 }
321
322 pldc = GdiGetLDC(hdc);
323 if ( !pldc )
324 {
325 SetLastError(ERROR_INVALID_HANDLE);
326 return SP_ERROR;
327 }
328
329 if ( !(pldc->Flags & LDC_INIT_DOCUMENT) ) return 1;
330
331 DocumentEventEx(NULL, pldc->hPrinter, hdc, DOCUMENTEVENT_ABORTDOC, 0, NULL, 0, NULL);
332
333 ((PW32CLIENTINFO)NtCurrentTeb()->Win32ClientInfo)->cSpins = 0;
334
335 if ( pldc->Flags & LDC_META_PRINT)
336 {
337 UNIMPLEMENTED;
338 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
339 return Ret;
340 }
341
342 if (NtGdiAbortDoc(hdc))
343 {
344 if (fpAbortPrinter(pldc->hPrinter)) Ret = 1;
345 }
346 else
347 Ret = SP_ERROR;
348
349 pldc->Flags &= ~(LDC_ATENDPAGE|LDC_META_PRINT|LDC_STARTPAGE|LDC_INIT_PAGE|LDC_INIT_DOCUMENT|LDC_SAPCALLBACK);
350
351 return Ret;
352 }
353
354 /*
355 * @unimplemented
356 */
357 int
358 WINAPI
359 EndDoc(
360 HDC hdc
361 )
362 {
363 PLDC pldc;
364 int Ret = SP_ERROR;
365 ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
366
367 if (hType == GDILoObjType_LO_DC_TYPE || hType == GDILoObjType_LO_METADC16_TYPE)
368 {
369 SetLastError(ERROR_INVALID_HANDLE);
370 return SP_ERROR;
371 }
372
373 pldc = GdiGetLDC(hdc);
374 if ( !pldc )
375 {
376 SetLastError(ERROR_INVALID_HANDLE);
377 return SP_ERROR;
378 }
379
380 if (pldc->Flags & LDC_META_PRINT)
381 {
382 UNIMPLEMENTED;
383 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
384 return Ret;
385 }
386
387 if (pldc->Flags & LDC_INIT_DOCUMENT)
388 {
389 BOOL Good;
390 if (pldc->Flags & LDC_INIT_PAGE) EndPage(hdc);
391
392 DocumentEventEx(NULL, pldc->hPrinter, hdc, DOCUMENTEVENT_ENDDOC, 0, NULL, 0, NULL);
393
394 ((PW32CLIENTINFO)NtCurrentTeb()->Win32ClientInfo)->cSpins = 0;
395
396 Good = NtGdiEndDoc(hdc);
397
398 // if (pldc->pUMPDev)
399 Good = EndDocPrinterEx(NULL,pldc->hPrinter);
400
401 if (Good)
402 {
403 DocumentEventEx(NULL, pldc->hPrinter, hdc, DOCUMENTEVENT_ENDDOCPOST, 0, NULL, 0, NULL);
404 Ret = 1;
405 }
406 pldc->Flags &= ~(LDC_ATENDPAGE|LDC_STARTPAGE|LDC_INIT_DOCUMENT|LDC_SAPCALLBACK);
407 }
408 return Ret;
409 }
410
411 /*
412 * @implemented
413 */
414 int
415 WINAPI
416 EndFormPage(HDC hdc)
417 {
418 return IntEndPage(hdc,TRUE);
419 }
420
421 /*
422 * @implemented
423 */
424 int
425 WINAPI
426 EndPage(HDC hdc )
427 {
428 return IntEndPage(hdc,FALSE);
429 }
430
431 /*
432 * @unimplemented
433 */
434 HANDLE
435 WINAPI
436 GdiGetSpoolFileHandle(LPWSTR pwszPrinterName,
437 LPDEVMODEW pDevmode,
438 LPWSTR pwszDocName)
439 {
440 UNIMPLEMENTED;
441 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
442 return 0;
443 }
444
445 /*
446 * @unimplemented
447 */
448 BOOL
449 WINAPI
450 GdiDeleteSpoolFileHandle(HANDLE SpoolFileHandle)
451 {
452 UNIMPLEMENTED;
453 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
454 return 0;
455 }
456
457 /*
458 * @unimplemented
459 */
460 DWORD
461 WINAPI
462 GdiGetPageCount(HANDLE SpoolFileHandle)
463 {
464 UNIMPLEMENTED;
465 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
466 return 0;
467 }
468
469 /*
470 * @unimplemented
471 */
472 int
473 WINAPI
474 StartDocW(
475 HDC hdc,
476 CONST DOCINFOW *lpdi
477 )
478 {
479 PLDC pldc;
480 DOCINFOW diW;
481 DOC_INFO_1W di1W;
482 LPWSTR lpwstrRet = NULL;
483 BOOL Banding;
484 int PrnJobNo, Ret = SP_ERROR;
485 ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
486
487 if (hType == GDILoObjType_LO_DC_TYPE || hType == GDILoObjType_LO_METADC16_TYPE)
488 return SP_ERROR;
489
490 pldc = GdiGetLDC(hdc);
491 if ( !pldc || pldc->Flags & LDC_ATENDPAGE)
492 {
493 SetLastError(ERROR_INVALID_HANDLE);
494 return SP_ERROR;
495 }
496
497 if (!pldc->hPrinter) return SP_ERROR;
498
499 pldc->Flags &= ~LDC_KILL_DOCUMENT;
500
501 if (lpdi)
502 RtlCopyMemory(&diW, lpdi, sizeof(DOCINFOW));
503 else
504 {
505 diW.cbSize = sizeof(DOCINFOW);
506 diW.lpszDocName = NULL;
507 diW.lpszOutput = NULL;
508 diW.lpszDatatype = NULL;
509 diW.fwType = 0;
510 }
511
512 if (!diW.lpszOutput)
513 if (pldc->pwszPort) diW.lpszOutput = pldc->pwszPort;
514
515 lpwstrRet = fpStartDocDlgW(pldc->hPrinter, &diW);
516 if (lpwstrRet == (LPWSTR)SP_APPABORT)
517 {
518 pldc->Flags |= LDC_KILL_DOCUMENT;
519 return SP_ERROR;
520 }
521 if (lpwstrRet == (LPWSTR)SP_ERROR) return SP_ERROR;
522
523 if (lpwstrRet != 0) diW.lpszOutput = lpwstrRet;
524
525 Ret = DocumentEventEx( NULL,
526 pldc->hPrinter,
527 hdc,
528 DOCUMENTEVENT_STARTDOC,
529 sizeof(ULONG),
530 &diW,
531 0,
532 NULL);
533
534 if (Ret == SP_APPABORT)
535 {
536 pldc->Flags |= LDC_KILL_DOCUMENT;
537 Ret = SP_ERROR;
538 }
539 if (Ret == SP_ERROR)
540 {
541 if (lpwstrRet) LocalFree(lpwstrRet);
542 return Ret;
543 }
544
545 di1W.pDocName = (LPWSTR)diW.lpszDocName;
546 di1W.pOutputFile = (LPWSTR)diW.lpszOutput;
547 di1W.pDatatype = (LPWSTR)diW.lpszDatatype;
548
549 Ret = SP_ERROR;
550
551 PrnJobNo = StartDocPrinterWEx(NULL, pldc->hPrinter, 1, (LPBYTE)&di1W);
552 if (PrnJobNo <= 0)
553 {
554 Ret = NtGdiStartDoc( hdc, &diW, &Banding, PrnJobNo);
555 if (Ret)
556 {
557 if (pldc->pAbortProc)
558 {
559 GdiSAPCallback(pldc);
560 pldc->Flags |= LDC_SAPCALLBACK;
561 pldc->CallBackTick = GetTickCount();
562 }
563 pldc->Flags |= LDC_INIT_DOCUMENT;
564 if (!Banding) pldc->Flags |= LDC_STARTPAGE;
565 }
566 }
567 if (Ret == SP_ERROR)
568 {
569 //if ( pldc->pUMPDev )
570 AbortPrinterEx(NULL, pldc->hPrinter);
571 DPRINT1("StartDoc Died!!!\n");
572 }
573 else
574 {
575 if ( DocumentEventEx( NULL,
576 pldc->hPrinter,
577 hdc,
578 DOCUMENTEVENT_STARTDOCPOST,
579 sizeof(ULONG),
580 &Ret,
581 0,
582 NULL) == SP_ERROR)
583 {
584 AbortDoc(hdc);
585 Ret = SP_ERROR;
586 }
587 }
588 if (lpwstrRet) LocalFree(lpwstrRet);
589 return Ret;
590 }
591
592 /*
593 * @implemented
594 */
595 int
596 WINAPI
597 StartDocA(
598 HDC hdc,
599 CONST DOCINFOA *lpdi
600 )
601 {
602 LPWSTR szDocName = NULL, szOutput = NULL, szDatatype = NULL;
603 DOCINFOW docW;
604 INT ret, len;
605
606 docW.cbSize = lpdi->cbSize;
607 if (lpdi->lpszDocName)
608 {
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);
612 }
613 if (lpdi->lpszOutput)
614 {
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);
618 }
619 if (lpdi->lpszDatatype)
620 {
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);
624 }
625
626 docW.lpszDocName = szDocName;
627 docW.lpszOutput = szOutput;
628 docW.lpszDatatype = szDatatype;
629 docW.fwType = lpdi->fwType;
630
631 ret = StartDocW(hdc, &docW);
632
633 HeapFree( GetProcessHeap(), 0, szDocName );
634 HeapFree( GetProcessHeap(), 0, szOutput );
635 HeapFree( GetProcessHeap(), 0, szDatatype );
636
637 return ret;
638 }
639
640 /*
641 * @unimplemented
642 */
643 int
644 WINAPI
645 StartPage(
646 HDC hdc
647 )
648 {
649 PLDC pldc;
650 ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
651
652 if (hType == GDILoObjType_LO_DC_TYPE || hType == GDILoObjType_LO_METADC16_TYPE)
653 {
654 SetLastError(ERROR_INVALID_HANDLE);
655 return SP_ERROR;
656 }
657
658 pldc = GdiGetLDC(hdc);
659 if ( !pldc )
660 {
661 SetLastError(ERROR_INVALID_HANDLE);
662 return SP_ERROR;
663 }
664
665 if (pldc->Flags & LDC_META_PRINT)
666 {
667 UNIMPLEMENTED;
668 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
669 return SP_ERROR;
670 }
671
672 pldc->Flags &= ~(LDC_ATENDPAGE|LDC_STARTPAGE);
673
674 if (pldc->Flags & LDC_INIT_PAGE) return 1;
675
676 if (DocumentEventEx(NULL, pldc->hPrinter, hdc, DOCUMENTEVENT_STARTPAGE, 0, NULL, 0, NULL) != SP_ERROR)
677 {
678 pldc->Flags |= LDC_INIT_PAGE;
679
680 ((PW32CLIENTINFO)NtCurrentTeb()->Win32ClientInfo)->cSpins = 0;
681
682 if (StartPagePrinterEx(NULL, pldc->hPrinter))
683 {
684 if (NtGdiStartPage(hdc)) return 1;
685 }
686
687 pldc->Flags &= ~(LDC_INIT_PAGE);
688 EndDoc(hdc);
689 SetLastError(ERROR_INVALID_HANDLE);
690 }
691 return SP_ERROR;
692 }
693
694 /*
695 * @implemented
696 */
697 int
698 WINAPI
699 SetAbortProc(
700 HDC hdc,
701 ABORTPROC lpAbortProc)
702 {
703 PLDC pldc;
704 ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
705
706 if (hType == GDILoObjType_LO_DC_TYPE || hType == GDILoObjType_LO_METADC16_TYPE)
707 return SP_ERROR;
708
709 pldc = GdiGetLDC(hdc);
710 if ( pldc )
711 {
712 if ( lpAbortProc )
713 {
714 if ( pldc->Flags & LDC_INIT_DOCUMENT )
715 {
716 pldc->Flags |= LDC_SAPCALLBACK;
717 pldc->CallBackTick = GetTickCount();
718 }
719 }
720 else
721 {
722 pldc->Flags &= ~LDC_SAPCALLBACK;
723 }
724 pldc->pAbortProc = lpAbortProc;
725 return 1;
726 }
727 else
728 {
729 SetLastError(ERROR_INVALID_HANDLE);
730 }
731 return SP_ERROR;
732 }
733