Revert r20367 and r20368 since they crash the GUI in second boot by hitting a assert...
[reactos.git] / reactos / subsys / win32k / objects / line.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <w32k.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25 // Some code from the WINE project source (www.winehq.com)
26
27
28 BOOL FASTCALL
29 IntGdiMoveToEx(DC *dc,
30 int X,
31 int Y,
32 LPPOINT Point)
33 {
34 BOOL PathIsOpen;
35
36 if ( Point )
37 {
38 Point->x = dc->w.CursPosX;
39 Point->y = dc->w.CursPosY;
40 }
41 dc->w.CursPosX = X;
42 dc->w.CursPosY = Y;
43
44 PathIsOpen = PATH_IsPathOpen(dc->w.path);
45
46 if ( PathIsOpen )
47 return PATH_MoveTo ( dc );
48
49 return TRUE;
50 }
51
52 BOOL FASTCALL
53 IntGdiLineTo(DC *dc,
54 int XEnd,
55 int YEnd)
56 {
57 BITMAPOBJ *BitmapObj;
58 BOOL Ret = TRUE;
59 PGDIBRUSHOBJ PenBrushObj;
60 GDIBRUSHINST PenBrushInst;
61 RECTL Bounds;
62 POINT Points[2];
63
64 if (PATH_IsPathOpen(dc->w.path))
65 {
66 Ret = PATH_LineTo(dc, XEnd, YEnd);
67 if (Ret)
68 {
69 // FIXME - PATH_LineTo should maybe do this...
70 dc->w.CursPosX = XEnd;
71 dc->w.CursPosY = YEnd;
72 }
73 return Ret;
74 }
75 else
76 {
77 BitmapObj = BITMAPOBJ_LockBitmap ( dc->w.hBitmap );
78 if (NULL == BitmapObj)
79 {
80 SetLastWin32Error(ERROR_INVALID_HANDLE);
81 return FALSE;
82 }
83
84 Points[0].x = dc->w.CursPosX;
85 Points[0].y = dc->w.CursPosY;
86 Points[1].x = XEnd;
87 Points[1].y = YEnd;
88
89 IntLPtoDP(dc, Points, 2);
90
91 /* FIXME: Is it correct to do this after the transformation? */
92 Points[0].x += dc->w.DCOrgX;
93 Points[0].y += dc->w.DCOrgY;
94 Points[1].x += dc->w.DCOrgX;
95 Points[1].y += dc->w.DCOrgY;
96
97 Bounds.left = min(Points[0].x, Points[1].x);
98 Bounds.top = min(Points[0].y, Points[1].y);
99 Bounds.right = max(Points[0].x, Points[1].x);
100 Bounds.bottom = max(Points[0].y, Points[1].y);
101
102 /* get BRUSHOBJ from current pen. */
103 PenBrushObj = PENOBJ_LockPen( dc->w.hPen );
104 /* FIXME - PenBrushObj can be NULL!!!! Don't assert here! */
105 ASSERT(PenBrushObj);
106
107 if (!(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
108 {
109 IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
110 Ret = IntEngLineTo(&BitmapObj->SurfObj,
111 dc->CombinedClip,
112 &PenBrushInst.BrushObject,
113 Points[0].x, Points[0].y,
114 Points[1].x, Points[1].y,
115 &Bounds,
116 ROP2_TO_MIX(dc->w.ROPmode));
117 }
118
119 BITMAPOBJ_UnlockBitmap ( BitmapObj );
120 PENOBJ_UnlockPen( PenBrushObj );
121 }
122
123 if (Ret)
124 {
125 dc->w.CursPosX = XEnd;
126 dc->w.CursPosY = YEnd;
127 }
128
129 return Ret;
130 }
131
132 BOOL FASTCALL
133 IntGdiPolyBezier(DC *dc,
134 LPPOINT pt,
135 DWORD Count)
136 {
137 BOOL ret = FALSE; // default to FAILURE
138
139 if ( PATH_IsPathOpen(dc->w.path) )
140 {
141 return PATH_PolyBezier ( dc, pt, Count );
142 }
143
144 /* We'll convert it into line segments and draw them using Polyline */
145 {
146 POINT *Pts;
147 INT nOut;
148
149 Pts = GDI_Bezier ( pt, Count, &nOut );
150 if ( Pts )
151 {
152 DbgPrint("Pts = %p, no = %d\n", Pts, nOut);
153 ret = IntGdiPolyline(dc, Pts, nOut);
154 ExFreePool(Pts);
155 }
156 }
157
158 return ret;
159 }
160
161 BOOL FASTCALL
162 IntGdiPolyBezierTo(DC *dc,
163 LPPOINT pt,
164 DWORD Count)
165 {
166 BOOL ret = FALSE; // default to failure
167
168 if ( PATH_IsPathOpen(dc->w.path) )
169 ret = PATH_PolyBezierTo ( dc, pt, Count );
170 else /* We'll do it using PolyBezier */
171 {
172 POINT *npt;
173 npt = ExAllocatePoolWithTag(PagedPool, sizeof(POINT) * (Count + 1), TAG_BEZIER);
174 if ( npt )
175 {
176 npt[0].x = dc->w.CursPosX;
177 npt[0].y = dc->w.CursPosY;
178 memcpy(npt + 1, pt, sizeof(POINT) * Count);
179 ret = IntGdiPolyBezier(dc, npt, Count+1);
180 ExFreePool(npt);
181 }
182 }
183 if ( ret )
184 {
185 dc->w.CursPosX = pt[Count-1].x;
186 dc->w.CursPosY = pt[Count-1].y;
187 }
188
189 return ret;
190 }
191
192 BOOL FASTCALL
193 IntGdiPolyline(DC *dc,
194 LPPOINT pt,
195 int Count)
196 {
197 BITMAPOBJ *BitmapObj;
198 GDIBRUSHOBJ *PenBrushObj;
199 GDIBRUSHINST PenBrushInst;
200 LPPOINT Points;
201 BOOL Ret = TRUE;
202 LONG i;
203
204 if (PATH_IsPathOpen(dc->w.path))
205 return PATH_Polyline(dc, pt, Count);
206
207 /* Get BRUSHOBJ from current pen. */
208 PenBrushObj = PENOBJ_LockPen(dc->w.hPen);
209 /* FIXME - PenBrushObj can be NULL! Don't assert here! */
210 ASSERT(PenBrushObj);
211
212 if (!(PenBrushObj->flAttrs & GDIBRUSH_IS_NULL))
213 {
214 Points = EngAllocMem(0, Count * sizeof(POINT), TAG_COORD);
215 if (Points != NULL)
216 {
217 BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
218 /* FIXME - BitmapObj can be NULL!!!! Don't assert but handle this case gracefully! */
219 ASSERT(BitmapObj);
220
221 RtlCopyMemory(Points, pt, Count * sizeof(POINT));
222 IntLPtoDP(dc, Points, Count);
223
224 /* Offset the array of point by the dc->w.DCOrg */
225 for (i = 0; i < Count; i++)
226 {
227 Points[i].x += dc->w.DCOrgX;
228 Points[i].y += dc->w.DCOrgY;
229 }
230
231 IntGdiInitBrushInstance(&PenBrushInst, PenBrushObj, dc->XlatePen);
232 Ret = IntEngPolyline(&BitmapObj->SurfObj, dc->CombinedClip,
233 &PenBrushInst.BrushObject, Points, Count,
234 ROP2_TO_MIX(dc->w.ROPmode));
235
236 BITMAPOBJ_UnlockBitmap(BitmapObj);
237 EngFreeMem(Points);
238 }
239 else
240 {
241 Ret = FALSE;
242 }
243 }
244
245 PENOBJ_UnlockPen(PenBrushObj);
246
247 return Ret;
248 }
249
250 BOOL FASTCALL
251 IntGdiPolylineTo(DC *dc,
252 LPPOINT pt,
253 DWORD Count)
254 {
255 BOOL ret = FALSE; // default to failure
256
257 if(PATH_IsPathOpen(dc->w.path))
258 {
259 ret = PATH_PolylineTo(dc, pt, Count);
260 }
261 else /* do it using Polyline */
262 {
263 POINT *pts = ExAllocatePoolWithTag(PagedPool, sizeof(POINT) * (Count + 1), TAG_SHAPE);
264 if ( pts )
265 {
266 pts[0].x = dc->w.CursPosX;
267 pts[0].y = dc->w.CursPosY;
268 memcpy( pts + 1, pt, sizeof(POINT) * Count);
269 ret = IntGdiPolyline(dc, pts, Count + 1);
270 ExFreePool(pts);
271 }
272 }
273 if ( ret )
274 {
275 dc->w.CursPosX = pt[Count-1].x;
276 dc->w.CursPosY = pt[Count-1].y;
277 }
278
279 return ret;
280 }
281
282 INT FASTCALL
283 IntGdiGetArcDirection(DC *dc)
284 {
285 return dc->w.ArcDirection;
286 }
287
288 BOOL FASTCALL
289 IntGdiArc(DC *dc,
290 int LeftRect,
291 int TopRect,
292 int RightRect,
293 int BottomRect,
294 int XStartArc,
295 int YStartArc,
296 int XEndArc,
297 int YEndArc)
298 {
299 if(PATH_IsPathOpen(dc->w.path))
300 {
301 return PATH_Arc(dc, LeftRect, TopRect, RightRect, BottomRect,
302 XStartArc, YStartArc, XEndArc, YEndArc);
303 }
304
305 // FIXME
306 // EngArc(dc, LeftRect, TopRect, RightRect, BottomRect, UNIMPLEMENTED
307 // XStartArc, YStartArc, XEndArc, YEndArc);
308
309 return TRUE;
310 }
311
312 BOOL FASTCALL
313 IntGdiPolyPolyline(DC *dc,
314 LPPOINT pt,
315 LPDWORD PolyPoints,
316 DWORD Count)
317 {
318 int i;
319 LPPOINT pts;
320 LPDWORD pc;
321 BOOL ret = FALSE; // default to failure
322 pts = pt;
323 pc = PolyPoints;
324
325 for (i = 0; i < Count; i++)
326 {
327 ret = IntGdiPolyline ( dc, pts, *pc );
328 if (ret == FALSE)
329 {
330 return ret;
331 }
332 pts+=*pc++;
333 }
334
335 return ret;
336 }
337
338 /******************************************************************************/
339
340 BOOL
341 STDCALL
342 NtGdiAngleArc(HDC hDC,
343 int X,
344 int Y,
345 DWORD Radius,
346 FLOAT StartAngle,
347 FLOAT SweepAngle)
348 {
349 UNIMPLEMENTED;
350 return FALSE;
351 }
352
353 BOOL
354 STDCALL
355 NtGdiArc(HDC hDC,
356 int LeftRect,
357 int TopRect,
358 int RightRect,
359 int BottomRect,
360 int XStartArc,
361 int YStartArc,
362 int XEndArc,
363 int YEndArc)
364 {
365 DC *dc;
366 BOOL Ret;
367
368 dc = DC_LockDc (hDC);
369 if(!dc)
370 {
371 SetLastWin32Error(ERROR_INVALID_HANDLE);
372 return FALSE;
373 }
374 if (dc->IsIC)
375 {
376 DC_UnlockDc(dc);
377 /* Yes, Windows really returns TRUE in this case */
378 return TRUE;
379 }
380
381 Ret = IntGdiArc(dc,
382 LeftRect,
383 TopRect,
384 RightRect,
385 BottomRect,
386 XStartArc,
387 YStartArc,
388 XEndArc,
389 YEndArc);
390
391 DC_UnlockDc( dc );
392 return Ret;
393 }
394
395 BOOL
396 STDCALL
397 NtGdiArcTo(HDC hDC,
398 int LeftRect,
399 int TopRect,
400 int RightRect,
401 int BottomRect,
402 int XRadial1,
403 int YRadial1,
404 int XRadial2,
405 int YRadial2)
406 {
407 BOOL result;
408 DC *dc;
409
410 dc = DC_LockDc (hDC);
411 if(!dc)
412 {
413 SetLastWin32Error(ERROR_INVALID_HANDLE);
414 return FALSE;
415 }
416 if (dc->IsIC)
417 {
418 DC_UnlockDc(dc);
419 /* Yes, Windows really returns TRUE in this case */
420 return TRUE;
421 }
422
423 // Line from current position to starting point of arc
424 if ( !IntGdiLineTo(dc, XRadial1, YRadial1) )
425 {
426 DC_UnlockDc(dc);
427 return FALSE;
428 }
429
430 //dc = DC_LockDc(hDC);
431
432 //if(!dc) return FALSE;
433
434 // Then the arc is drawn.
435 result = IntGdiArc(dc, LeftRect, TopRect, RightRect, BottomRect,
436 XRadial1, YRadial1, XRadial2, YRadial2);
437
438 //DC_UnlockDc(dc);
439
440 // If no error occured, the current position is moved to the ending point of the arc.
441 if(result)
442 IntGdiMoveToEx(dc, XRadial2, YRadial2, NULL);
443
444 DC_UnlockDc(dc);
445
446 return result;
447 }
448
449 INT
450 STDCALL
451 NtGdiGetArcDirection(HDC hDC)
452 {
453 PDC dc = DC_LockDc (hDC);
454 int ret = 0; // default to failure
455
456 if ( dc )
457 {
458 ret = IntGdiGetArcDirection ( dc );
459 DC_UnlockDc(dc);
460 }
461 else
462 {
463 SetLastWin32Error(ERROR_INVALID_HANDLE);
464 }
465
466 return ret;
467 }
468
469 BOOL
470 STDCALL
471 NtGdiLineTo(HDC hDC,
472 int XEnd,
473 int YEnd)
474 {
475 DC *dc;
476 BOOL Ret;
477
478 dc = DC_LockDc(hDC);
479 if(!dc)
480 {
481 SetLastWin32Error(ERROR_INVALID_HANDLE);
482 return FALSE;
483 }
484 if (dc->IsIC)
485 {
486 DC_UnlockDc(dc);
487 /* Yes, Windows really returns TRUE in this case */
488 return TRUE;
489 }
490
491 Ret = IntGdiLineTo(dc, XEnd, YEnd);
492
493 DC_UnlockDc(dc);
494 return Ret;
495 }
496
497 BOOL
498 STDCALL
499 NtGdiMoveToEx(HDC hDC,
500 int X,
501 int Y,
502 LPPOINT Point)
503 {
504 DC *dc;
505 POINT SafePoint;
506 NTSTATUS Status = STATUS_SUCCESS;
507 BOOL Ret;
508
509 dc = DC_LockDc(hDC);
510 if(!dc)
511 {
512 SetLastWin32Error(ERROR_INVALID_HANDLE);
513 return FALSE;
514 }
515 if (dc->IsIC)
516 {
517 DC_UnlockDc(dc);
518 /* Yes, Windows really returns TRUE in this case */
519 return TRUE;
520 }
521
522 if(Point)
523 {
524 _SEH_TRY
525 {
526 ProbeForRead(Point,
527 sizeof(POINT),
528 1);
529 SafePoint = *Point;
530 }
531 _SEH_HANDLE
532 {
533 Status = _SEH_GetExceptionCode();
534 }
535 _SEH_END;
536
537 if(!NT_SUCCESS(Status))
538 {
539 DC_UnlockDc(dc);
540 SetLastNtError(Status);
541 return FALSE;
542 }
543 }
544
545 Ret = IntGdiMoveToEx(dc, X, Y, (Point ? &SafePoint : NULL));
546
547 DC_UnlockDc(dc);
548 return Ret;
549 }
550
551 BOOL
552 STDCALL
553 NtGdiPolyBezier(HDC hDC,
554 CONST LPPOINT pt,
555 DWORD Count)
556 {
557 DC *dc;
558 LPPOINT Safept;
559 NTSTATUS Status = STATUS_SUCCESS;
560 BOOL Ret;
561
562 dc = DC_LockDc(hDC);
563 if(!dc)
564 {
565 SetLastWin32Error(ERROR_INVALID_HANDLE);
566 return FALSE;
567 }
568 if (dc->IsIC)
569 {
570 DC_UnlockDc(dc);
571 /* Yes, Windows really returns TRUE in this case */
572 return TRUE;
573 }
574
575 if(Count > 0)
576 {
577 _SEH_TRY
578 {
579 ProbeForRead(pt,
580 Count * sizeof(POINT),
581 1);
582 }
583 _SEH_HANDLE
584 {
585 Status = _SEH_GetExceptionCode();
586 }
587 _SEH_END;
588
589 if (!NT_SUCCESS(Status))
590 {
591 DC_UnlockDc(dc);
592 SetLastNtError(Status);
593 return FALSE;
594 }
595
596 Safept = ExAllocatePoolWithTag(PagedPool, sizeof(POINT) * Count, TAG_BEZIER);
597 if(!Safept)
598 {
599 DC_UnlockDc(dc);
600 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
601 return FALSE;
602 }
603
604 _SEH_TRY
605 {
606 /* pointers were already probed */
607 RtlCopyMemory(Safept,
608 pt,
609 Count * sizeof(POINT));
610 }
611 _SEH_HANDLE
612 {
613 Status = _SEH_GetExceptionCode();
614 }
615 _SEH_END;
616
617 if(!NT_SUCCESS(Status))
618 {
619 DC_UnlockDc(dc);
620 SetLastNtError(Status);
621 return FALSE;
622 }
623 }
624 else
625 {
626 DC_UnlockDc(dc);
627 SetLastWin32Error(ERROR_INVALID_PARAMETER);
628 return FALSE;
629 }
630
631 Ret = IntGdiPolyBezier(dc, Safept, Count);
632
633 ExFreePool(Safept);
634 DC_UnlockDc(dc);
635
636 return Ret;
637 }
638
639 BOOL
640 STDCALL
641 NtGdiPolyBezierTo(HDC hDC,
642 CONST LPPOINT pt,
643 DWORD Count)
644 {
645 DC *dc;
646 LPPOINT Safept;
647 NTSTATUS Status = STATUS_SUCCESS;
648 BOOL Ret;
649
650 dc = DC_LockDc(hDC);
651 if(!dc)
652 {
653 SetLastWin32Error(ERROR_INVALID_HANDLE);
654 return FALSE;
655 }
656 if (dc->IsIC)
657 {
658 DC_UnlockDc(dc);
659 /* Yes, Windows really returns TRUE in this case */
660 return TRUE;
661 }
662
663 if(Count > 0)
664 {
665 _SEH_TRY
666 {
667 ProbeForRead(pt,
668 Count * sizeof(POINT),
669 1);
670 }
671 _SEH_HANDLE
672 {
673 Status = _SEH_GetExceptionCode();
674 }
675 _SEH_END;
676
677 if (!NT_SUCCESS(Status))
678 {
679 DC_UnlockDc(dc);
680 SetLastNtError(Status);
681 return FALSE;
682 }
683
684 Safept = ExAllocatePoolWithTag(PagedPool, sizeof(POINT) * Count, TAG_BEZIER);
685 if(!Safept)
686 {
687 DC_UnlockDc(dc);
688 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
689 return FALSE;
690 }
691
692 _SEH_TRY
693 {
694 /* pointers were already probed */
695 RtlCopyMemory(Safept,
696 pt,
697 Count * sizeof(POINT));
698 }
699 _SEH_HANDLE
700 {
701 Status = _SEH_GetExceptionCode();
702 }
703 _SEH_END;
704
705 if(!NT_SUCCESS(Status))
706 {
707 DC_UnlockDc(dc);
708 SetLastNtError(Status);
709 return FALSE;
710 }
711 }
712 else
713 {
714 DC_UnlockDc(dc);
715 SetLastWin32Error(ERROR_INVALID_PARAMETER);
716 return FALSE;
717 }
718
719 Ret = IntGdiPolyBezierTo(dc, Safept, Count);
720
721 ExFreePool(Safept);
722 DC_UnlockDc(dc);
723
724 return Ret;
725 }
726
727 BOOL
728 STDCALL
729 NtGdiPolyDraw(HDC hDC,
730 CONST LPPOINT pt,
731 CONST LPBYTE Types,
732 int Count)
733 {
734 UNIMPLEMENTED;
735 return FALSE;
736 }
737
738 BOOL
739 STDCALL
740 NtGdiPolyline(HDC hDC,
741 CONST LPPOINT pt,
742 int Count)
743 {
744 DC *dc;
745 LPPOINT Safept;
746 NTSTATUS Status = STATUS_SUCCESS;
747 BOOL Ret;
748
749 dc = DC_LockDc(hDC);
750 if(!dc)
751 {
752 SetLastWin32Error(ERROR_INVALID_HANDLE);
753 return FALSE;
754 }
755 if (dc->IsIC)
756 {
757 DC_UnlockDc(dc);
758 /* Yes, Windows really returns TRUE in this case */
759 return TRUE;
760 }
761
762 if(Count >= 2)
763 {
764 _SEH_TRY
765 {
766 ProbeForRead(pt,
767 Count * sizeof(POINT),
768 1);
769 }
770 _SEH_HANDLE
771 {
772 Status = _SEH_GetExceptionCode();
773 }
774 _SEH_END;
775
776 if (!NT_SUCCESS(Status))
777 {
778 DC_UnlockDc(dc);
779 SetLastNtError(Status);
780 return FALSE;
781 }
782
783 Safept = ExAllocatePoolWithTag(PagedPool, sizeof(POINT) * Count, TAG_SHAPE);
784 if(!Safept)
785 {
786 DC_UnlockDc(dc);
787 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
788 return FALSE;
789 }
790
791 _SEH_TRY
792 {
793 /* pointers were already probed */
794 RtlCopyMemory(Safept,
795 pt,
796 Count * sizeof(POINT));
797 }
798 _SEH_HANDLE
799 {
800 Status = _SEH_GetExceptionCode();
801 }
802 _SEH_END;
803
804 if(!NT_SUCCESS(Status))
805 {
806 DC_UnlockDc(dc);
807 SetLastNtError(Status);
808 return FALSE;
809 }
810 }
811 else
812 {
813 DC_UnlockDc(dc);
814 SetLastWin32Error(ERROR_INVALID_PARAMETER);
815 return FALSE;
816 }
817
818 Ret = IntGdiPolyline(dc, Safept, Count);
819
820 ExFreePool(Safept);
821 DC_UnlockDc(dc);
822
823 return Ret;
824 }
825
826 BOOL
827 STDCALL
828 NtGdiPolylineTo(HDC hDC,
829 CONST LPPOINT pt,
830 DWORD Count)
831 {
832 DC *dc;
833 LPPOINT Safept;
834 NTSTATUS Status = STATUS_SUCCESS;
835 BOOL Ret;
836
837 dc = DC_LockDc(hDC);
838 if(!dc)
839 {
840 SetLastWin32Error(ERROR_INVALID_HANDLE);
841 return FALSE;
842 }
843 if (dc->IsIC)
844 {
845 DC_UnlockDc(dc);
846 /* Yes, Windows really returns TRUE in this case */
847 return TRUE;
848 }
849
850 if(Count > 0)
851 {
852 _SEH_TRY
853 {
854 ProbeForRead(pt,
855 Count * sizeof(POINT),
856 1);
857 }
858 _SEH_HANDLE
859 {
860 Status = _SEH_GetExceptionCode();
861 }
862 _SEH_END;
863
864 if (!NT_SUCCESS(Status))
865 {
866 DC_UnlockDc(dc);
867 SetLastNtError(Status);
868 return FALSE;
869 }
870
871 Safept = ExAllocatePoolWithTag(PagedPool, sizeof(POINT) * Count, TAG_SHAPE);
872 if(!Safept)
873 {
874 DC_UnlockDc(dc);
875 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
876 return FALSE;
877 }
878
879 _SEH_TRY
880 {
881 /* pointers were already probed */
882 RtlCopyMemory(Safept,
883 pt,
884 Count * sizeof(POINT));
885 }
886 _SEH_HANDLE
887 {
888 Status = _SEH_GetExceptionCode();
889 }
890 _SEH_END;
891
892 if(!NT_SUCCESS(Status))
893 {
894 DC_UnlockDc(dc);
895 SetLastNtError(Status);
896 return FALSE;
897 }
898 }
899 else
900 {
901 DC_UnlockDc(dc);
902 SetLastWin32Error(ERROR_INVALID_PARAMETER);
903 return FALSE;
904 }
905
906 Ret = IntGdiPolylineTo(dc, Safept, Count);
907
908 ExFreePool(Safept);
909 DC_UnlockDc(dc);
910
911 return Ret;
912 }
913
914 BOOL
915 STDCALL
916 NtGdiPolyPolyline(HDC hDC,
917 CONST LPPOINT pt,
918 CONST LPDWORD PolyPoints,
919 DWORD Count)
920 {
921 DC *dc;
922 LPPOINT Safept;
923 LPDWORD SafePolyPoints;
924 NTSTATUS Status = STATUS_SUCCESS;
925 BOOL Ret;
926
927 dc = DC_LockDc(hDC);
928 if(!dc)
929 {
930 SetLastWin32Error(ERROR_INVALID_HANDLE);
931 return FALSE;
932 }
933 if (dc->IsIC)
934 {
935 DC_UnlockDc(dc);
936 /* Yes, Windows really returns TRUE in this case */
937 return TRUE;
938 }
939
940 if(Count > 0)
941 {
942 _SEH_TRY
943 {
944 ProbeForRead(pt,
945 Count * sizeof(POINT),
946 1);
947 ProbeForRead(PolyPoints,
948 Count * sizeof(DWORD),
949 1);
950 }
951 _SEH_HANDLE
952 {
953 Status = _SEH_GetExceptionCode();
954 }
955 _SEH_END;
956
957 if (!NT_SUCCESS(Status))
958 {
959 DC_UnlockDc(dc);
960 SetLastNtError(Status);
961 return FALSE;
962 }
963
964 Safept = ExAllocatePoolWithTag(PagedPool, (sizeof(POINT) + sizeof(DWORD)) * Count, TAG_SHAPE);
965 if(!Safept)
966 {
967 DC_UnlockDc(dc);
968 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
969 return FALSE;
970 }
971
972 SafePolyPoints = (LPDWORD)&Safept[Count];
973
974 _SEH_TRY
975 {
976 /* pointers were already probed */
977 RtlCopyMemory(Safept,
978 pt,
979 Count * sizeof(POINT));
980 RtlCopyMemory(SafePolyPoints,
981 PolyPoints,
982 Count * sizeof(DWORD));
983 }
984 _SEH_HANDLE
985 {
986 Status = _SEH_GetExceptionCode();
987 }
988 _SEH_END;
989
990 if(!NT_SUCCESS(Status))
991 {
992 DC_UnlockDc(dc);
993 ExFreePool(Safept);
994 SetLastNtError(Status);
995 return FALSE;
996 }
997 }
998 else
999 {
1000 DC_UnlockDc(dc);
1001 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1002 return FALSE;
1003 }
1004
1005 Ret = IntGdiPolyPolyline(dc, Safept, SafePolyPoints, Count);
1006
1007 ExFreePool(Safept);
1008 DC_UnlockDc(dc);
1009
1010 return Ret;
1011 }
1012
1013 int
1014 STDCALL
1015 NtGdiSetArcDirection(HDC hDC,
1016 int ArcDirection)
1017 {
1018 PDC dc;
1019 INT nOldDirection = 0; // default to FAILURE
1020
1021 dc = DC_LockDc (hDC);
1022 if ( !dc ) return 0;
1023
1024 if ( ArcDirection == AD_COUNTERCLOCKWISE || ArcDirection == AD_CLOCKWISE )
1025 {
1026 nOldDirection = dc->w.ArcDirection;
1027 dc->w.ArcDirection = ArcDirection;
1028 }
1029
1030 DC_UnlockDc( dc );
1031 return nOldDirection;
1032 }
1033 /* EOF */