modified include/reactos/probe.h
[reactos.git] / reactos / subsystems / win32 / win32k / objects / coord.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 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Coordinate systems
24 * FILE: subsys/win32k/objects/coord.c
25 * PROGRAMER: Unknown
26 */
27
28 /* INCLUDES ******************************************************************/
29
30 #include <w32k.h>
31
32 #define NDEBUG
33 #include <debug.h>
34
35 /* FUNCTIONS *****************************************************************/
36
37 void FASTCALL
38 IntFixIsotropicMapping(PDC dc)
39 {
40 ULONG xdim;
41 ULONG ydim;
42 PDC_ATTR Dc_Attr = dc->pDc_Attr;
43 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
44
45 xdim = EngMulDiv(Dc_Attr->szlViewportExt.cx,
46 ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize,
47 ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes) /
48 Dc_Attr->szlWindowExt.cx;
49 ydim = EngMulDiv(Dc_Attr->szlViewportExt.cy,
50 ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize,
51 ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes) /
52 Dc_Attr->szlWindowExt.cy;
53
54 if (xdim > ydim)
55 {
56 Dc_Attr->szlViewportExt.cx = Dc_Attr->szlViewportExt.cx * abs(ydim / xdim);
57 if (!Dc_Attr->szlViewportExt.cx) Dc_Attr->szlViewportExt.cx = 1;
58 }
59 else
60 {
61 Dc_Attr->szlViewportExt.cy = Dc_Attr->szlViewportExt.cy * abs(xdim / ydim);
62 if (!Dc_Attr->szlViewportExt.cy) Dc_Attr->szlViewportExt.cy = 1;
63 }
64 }
65
66 BOOL FASTCALL
67 IntGdiCombineTransform(LPXFORM XFormResult,
68 LPXFORM xform1,
69 LPXFORM xform2)
70 {
71 XFORM xformTemp;
72 /* Check for illegal parameters */
73 if (!XFormResult || !xform1 || !xform2)
74 {
75 return FALSE;
76 }
77
78 /* Create the result in a temporary XFORM, since xformResult may be
79 * equal to xform1 or xform2 */
80 xformTemp.eM11 = xform1->eM11 * xform2->eM11 + xform1->eM12 * xform2->eM21;
81 xformTemp.eM12 = xform1->eM11 * xform2->eM12 + xform1->eM12 * xform2->eM22;
82 xformTemp.eM21 = xform1->eM21 * xform2->eM11 + xform1->eM22 * xform2->eM21;
83 xformTemp.eM22 = xform1->eM21 * xform2->eM12 + xform1->eM22 * xform2->eM22;
84 xformTemp.eDx = xform1->eDx * xform2->eM11 + xform1->eDy * xform2->eM21 + xform2->eDx;
85 xformTemp.eDy = xform1->eDx * xform2->eM12 + xform1->eDy * xform2->eM22 + xform2->eDy;
86 *XFormResult = xformTemp;
87
88 return TRUE;
89 }
90
91 BOOL APIENTRY NtGdiCombineTransform(LPXFORM UnsafeXFormResult,
92 LPXFORM Unsafexform1,
93 LPXFORM Unsafexform2)
94 {
95 BOOL Ret;
96
97 _SEH2_TRY
98 {
99 ProbeForWrite(UnsafeXFormResult,
100 sizeof(XFORM),
101 1);
102 ProbeForRead(Unsafexform1,
103 sizeof(XFORM),
104 1);
105 ProbeForRead(Unsafexform2,
106 sizeof(XFORM),
107 1);
108 Ret = IntGdiCombineTransform(UnsafeXFormResult, Unsafexform1, Unsafexform2);
109 }
110 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
111 {
112 Ret = FALSE;
113 }
114 _SEH2_END;
115
116 return Ret;
117 }
118
119
120 int
121 FASTCALL
122 IntGetGraphicsMode ( PDC dc )
123 {
124 PDC_ATTR Dc_Attr;
125 ASSERT ( dc );
126 Dc_Attr = dc->pDc_Attr;
127 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
128 return Dc_Attr->iGraphicsMode;
129 }
130
131 BOOL
132 FASTCALL
133 IntGdiModifyWorldTransform(PDC pDc,
134 CONST LPXFORM lpXForm,
135 DWORD Mode)
136 {
137 ASSERT(pDc);
138 XFORM xformWorld2Wnd;
139
140 switch(Mode)
141 {
142 case MWT_IDENTITY:
143 xformWorld2Wnd.eM11 = 1.0f;
144 xformWorld2Wnd.eM12 = 0.0f;
145 xformWorld2Wnd.eM21 = 0.0f;
146 xformWorld2Wnd.eM22 = 1.0f;
147 xformWorld2Wnd.eDx = 0.0f;
148 xformWorld2Wnd.eDy = 0.0f;
149 XForm2MatrixS(&pDc->DcLevel.mxWorldToPage, &xformWorld2Wnd);
150 break;
151
152 case MWT_LEFTMULTIPLY:
153 MatrixS2XForm(&xformWorld2Wnd, &pDc->DcLevel.mxWorldToPage);
154 IntGdiCombineTransform(&xformWorld2Wnd, lpXForm, &xformWorld2Wnd);
155 XForm2MatrixS(&pDc->DcLevel.mxWorldToPage, &xformWorld2Wnd);
156 break;
157
158 case MWT_RIGHTMULTIPLY:
159 MatrixS2XForm(&xformWorld2Wnd, &pDc->DcLevel.mxWorldToPage);
160 IntGdiCombineTransform(&xformWorld2Wnd, &xformWorld2Wnd, lpXForm);
161 XForm2MatrixS(&pDc->DcLevel.mxWorldToPage, &xformWorld2Wnd);
162 break;
163
164 case MWT_MAX+1: // Must be MWT_SET????
165 XForm2MatrixS(&pDc->DcLevel.mxWorldToPage, lpXForm); // Do it like Wine.
166 break;
167
168 default:
169 return FALSE;
170 }
171 DC_UpdateXforms(pDc);
172 return TRUE;
173 }
174
175 BOOL
176 APIENTRY
177 NtGdiGetTransform(HDC hDC,
178 DWORD iXform,
179 LPXFORM XForm)
180 {
181 PDC dc;
182 NTSTATUS Status = STATUS_SUCCESS;
183
184 dc = DC_LockDc ( hDC );
185 if (!dc)
186 {
187 SetLastWin32Error(ERROR_INVALID_HANDLE);
188 return FALSE;
189 }
190 if (!XForm)
191 {
192 DC_UnlockDc(dc);
193 SetLastWin32Error(ERROR_INVALID_PARAMETER);
194 return FALSE;
195 }
196
197 _SEH2_TRY
198 {
199 ProbeForWrite(XForm,
200 sizeof(XFORM),
201 1);
202 switch(iXform)
203 {
204 case GdiWorldSpaceToPageSpace:
205 MatrixS2XForm(XForm, &dc->DcLevel.mxWorldToPage);
206 break;
207 default:
208 break;
209 }
210 }
211 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
212 {
213 Status = _SEH2_GetExceptionCode();
214 }
215 _SEH2_END;
216
217 DC_UnlockDc(dc);
218 return NT_SUCCESS(Status);
219 }
220
221
222 /*!
223 * Converts points from logical coordinates into device coordinates. Conversion depends on the mapping mode,
224 * world transfrom, viewport origin settings for the given device context.
225 * \param hDC device context.
226 * \param Points an array of POINT structures (in/out).
227 * \param Count number of elements in the array of POINT structures.
228 * \return TRUE if success.
229 */
230 BOOL
231 APIENTRY
232 NtGdiTransformPoints( HDC hDC,
233 PPOINT UnsafePtsIn,
234 PPOINT UnsafePtOut,
235 INT Count,
236 INT iMode )
237 {
238 PDC dc;
239 NTSTATUS Status = STATUS_SUCCESS;
240 LPPOINT Points;
241 ULONG Size;
242
243 dc = DC_LockDc(hDC);
244 if (!dc)
245 {
246 SetLastWin32Error(ERROR_INVALID_HANDLE);
247 return FALSE;
248 }
249
250 if (!UnsafePtsIn || !UnsafePtOut || Count <= 0)
251 {
252 DC_UnlockDc(dc);
253 SetLastWin32Error(ERROR_INVALID_PARAMETER);
254 return FALSE;
255 }
256
257 Size = Count * sizeof(POINT);
258
259 Points = (LPPOINT)ExAllocatePoolWithTag(PagedPool, Size, TAG_COORD);
260 if(!Points)
261 {
262 DC_UnlockDc(dc);
263 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
264 return FALSE;
265 }
266
267 _SEH2_TRY
268 {
269 ProbeForWrite(UnsafePtOut,
270 Size,
271 1);
272 ProbeForRead(UnsafePtsIn,
273 Size,
274 1);
275 RtlCopyMemory(Points,
276 UnsafePtsIn,
277 Size);
278 }
279 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
280 {
281 Status = _SEH2_GetExceptionCode();
282 }
283 _SEH2_END;
284
285 if(!NT_SUCCESS(Status))
286 {
287 DC_UnlockDc(dc);
288 ExFreePoolWithTag(Points, TAG_COORD);
289 SetLastNtError(Status);
290 return FALSE;
291 }
292
293 switch (iMode)
294 {
295 case GdiDpToLp:
296 IntDPtoLP(dc, Points, Count);
297 break;
298 case GdiLpToDp:
299 IntLPtoDP(dc, Points, Count);
300 break;
301 case 2: // Not supported yet. Need testing.
302 default:
303 {
304 DC_UnlockDc(dc);
305 ExFreePoolWithTag(Points, TAG_COORD);
306 SetLastWin32Error(ERROR_INVALID_PARAMETER);
307 return FALSE;
308 }
309 }
310
311 _SEH2_TRY
312 {
313 /* pointer was already probed! */
314 RtlCopyMemory(UnsafePtOut,
315 Points,
316 Size);
317 }
318 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
319 {
320 Status = _SEH2_GetExceptionCode();
321 }
322 _SEH2_END;
323
324 if(!NT_SUCCESS(Status))
325 {
326 DC_UnlockDc(dc);
327 ExFreePoolWithTag(Points, TAG_COORD);
328 SetLastNtError(Status);
329 return FALSE;
330 }
331 //
332 // If we are getting called that means User XForms is a mess!
333 //
334 DC_UnlockDc(dc);
335 ExFreePoolWithTag(Points, TAG_COORD);
336 return TRUE;
337 }
338
339 BOOL
340 APIENTRY
341 NtGdiModifyWorldTransform(HDC hDC,
342 LPXFORM UnsafeXForm,
343 DWORD Mode)
344 {
345 PDC dc;
346 XFORM SafeXForm;
347 BOOL Ret = TRUE;
348
349 dc = DC_LockDc(hDC);
350 if (!dc)
351 {
352 SetLastWin32Error(ERROR_INVALID_HANDLE);
353 return FALSE;
354 }
355
356 // The xform is permitted to be NULL for MWT_IDENTITY.
357 // However, if it is not NULL, then it must be valid even though it is not used.
358 if (UnsafeXForm != NULL || Mode != MWT_IDENTITY)
359 {
360 _SEH2_TRY
361 {
362 ProbeForRead(UnsafeXForm, sizeof(XFORM), 1);
363 RtlCopyMemory(&SafeXForm, UnsafeXForm, sizeof(XFORM));
364 }
365 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
366 {
367 Ret = FALSE;
368 }
369 _SEH2_END;
370 }
371
372 // Safe to handle kernel mode data.
373 if (Ret) Ret = IntGdiModifyWorldTransform(dc, &SafeXForm, Mode);
374 DC_UnlockDc(dc);
375 return Ret;
376 }
377
378 BOOL
379 APIENTRY
380 NtGdiOffsetViewportOrgEx(HDC hDC,
381 int XOffset,
382 int YOffset,
383 LPPOINT UnsafePoint)
384 {
385 PDC dc;
386 PDC_ATTR Dc_Attr;
387 NTSTATUS Status = STATUS_SUCCESS;
388
389 dc = DC_LockDc ( hDC );
390 if(!dc)
391 {
392 SetLastWin32Error(ERROR_INVALID_HANDLE);
393 return FALSE;
394 }
395 Dc_Attr = dc->pDc_Attr;
396 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
397
398 if (UnsafePoint)
399 {
400 _SEH2_TRY
401 {
402 ProbeForWrite(UnsafePoint,
403 sizeof(POINT),
404 1);
405 UnsafePoint->x = Dc_Attr->ptlViewportOrg.x;
406 UnsafePoint->y = Dc_Attr->ptlViewportOrg.y;
407 if ( Dc_Attr->dwLayout & LAYOUT_RTL ) UnsafePoint->x = -UnsafePoint->x;
408 }
409 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
410 {
411 Status = _SEH2_GetExceptionCode();
412 }
413 _SEH2_END;
414
415 if ( !NT_SUCCESS(Status) )
416 {
417 SetLastNtError(Status);
418 DC_UnlockDc(dc);
419 return FALSE;
420 }
421 }
422
423 if ( Dc_Attr->dwLayout & LAYOUT_RTL ) XOffset = -XOffset;
424 Dc_Attr->ptlViewportOrg.x += XOffset;
425 Dc_Attr->ptlViewportOrg.y += YOffset;
426 DC_UpdateXforms(dc);
427 DC_UnlockDc(dc);
428 return TRUE;
429 }
430
431 BOOL
432 APIENTRY
433 NtGdiOffsetWindowOrgEx(HDC hDC,
434 int XOffset,
435 int YOffset,
436 LPPOINT Point)
437 {
438 PDC dc;
439 PDC_ATTR Dc_Attr;
440
441 dc = DC_LockDc(hDC);
442 if (!dc)
443 {
444 SetLastWin32Error(ERROR_INVALID_HANDLE);
445 return FALSE;
446 }
447 Dc_Attr = dc->pDc_Attr;
448 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
449
450 if (Point)
451 {
452 NTSTATUS Status = STATUS_SUCCESS;
453
454 _SEH2_TRY
455 {
456 ProbeForWrite(Point,
457 sizeof(POINT),
458 1);
459 Point->x = Dc_Attr->ptlWindowOrg.x;
460 Point->y = Dc_Attr->ptlWindowOrg.y;
461 }
462 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
463 {
464 Status = _SEH2_GetExceptionCode();
465 }
466 _SEH2_END;
467
468 if(!NT_SUCCESS(Status))
469 {
470 SetLastNtError(Status);
471 DC_UnlockDc(dc);
472 return FALSE;
473 }
474 }
475
476 Dc_Attr->ptlWindowOrg.x += XOffset;
477 Dc_Attr->ptlWindowOrg.y += YOffset;
478
479 DC_UpdateXforms(dc);
480 DC_UnlockDc(dc);
481
482 return TRUE;
483 }
484
485 BOOL
486 APIENTRY
487 NtGdiScaleViewportExtEx(HDC hDC,
488 int Xnum,
489 int Xdenom,
490 int Ynum,
491 int Ydenom,
492 LPSIZE pSize)
493 {
494 PDC pDC;
495 PDC_ATTR pDc_Attr;
496 BOOL Ret = FALSE;
497 LONG X, Y;
498
499 pDC = DC_LockDc(hDC);
500 if (!pDC)
501 {
502 SetLastWin32Error(ERROR_INVALID_HANDLE);
503 return FALSE;
504 }
505 pDc_Attr = pDC->pDc_Attr;
506 if(!pDc_Attr) pDc_Attr = &pDC->Dc_Attr;
507
508 if ( pSize )
509 {
510 NTSTATUS Status = STATUS_SUCCESS;
511
512 _SEH2_TRY
513 {
514 ProbeForWrite(pSize,
515 sizeof(LPSIZE),
516 1);
517
518 pSize->cx = pDc_Attr->szlViewportExt.cx;
519 pSize->cy = pDc_Attr->szlViewportExt.cy;
520 }
521 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
522 {
523 Status = _SEH2_GetExceptionCode();
524 }
525 _SEH2_END;
526
527 if(!NT_SUCCESS(Status))
528 {
529 SetLastNtError(Status);
530 DC_UnlockDc(pDC);
531 return FALSE;
532 }
533 }
534
535 if (pDc_Attr->iMapMode > MM_TWIPS)
536 {
537 if ( ( Xdenom ) && ( Ydenom ) )
538 {
539 X = Xnum * pDc_Attr->szlViewportExt.cx / Xdenom;
540 if ( X )
541 {
542 Y = Ynum * pDc_Attr->szlViewportExt.cy / Ydenom;
543 if ( Y )
544 {
545 pDc_Attr->szlViewportExt.cx = X;
546 pDc_Attr->szlViewportExt.cy = Y;
547
548 IntMirrorWindowOrg(pDC);
549
550 pDc_Attr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
551
552 if (pDc_Attr->iMapMode == MM_ISOTROPIC) IntFixIsotropicMapping(pDC);
553 DC_UpdateXforms(pDC);
554
555 Ret = TRUE;
556 }
557 }
558 }
559 }
560 else
561 Ret = TRUE;
562
563 DC_UnlockDc(pDC);
564 return Ret;
565 }
566
567 BOOL
568 APIENTRY
569 NtGdiScaleWindowExtEx(HDC hDC,
570 int Xnum,
571 int Xdenom,
572 int Ynum,
573 int Ydenom,
574 LPSIZE pSize)
575 {
576 PDC pDC;
577 PDC_ATTR pDc_Attr;
578 BOOL Ret = FALSE;
579 LONG X, Y;
580
581 pDC = DC_LockDc(hDC);
582 if (!pDC)
583 {
584 SetLastWin32Error(ERROR_INVALID_HANDLE);
585 return FALSE;
586 }
587 pDc_Attr = pDC->pDc_Attr;
588 if(!pDc_Attr) pDc_Attr = &pDC->Dc_Attr;
589
590 if ( pSize )
591 {
592 NTSTATUS Status = STATUS_SUCCESS;
593
594 _SEH2_TRY
595 {
596 ProbeForWrite(pSize,
597 sizeof(LPSIZE),
598 1);
599
600 X = pDc_Attr->szlWindowExt.cx;
601 if (pDc_Attr->dwLayout & LAYOUT_RTL) X = -X;
602 pSize->cx = X;
603 pSize->cy = pDc_Attr->szlWindowExt.cy;
604 }
605 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
606 {
607 Status = _SEH2_GetExceptionCode();
608 }
609 _SEH2_END;
610
611 if(!NT_SUCCESS(Status))
612 {
613 SetLastNtError(Status);
614 DC_UnlockDc(pDC);
615 return FALSE;
616 }
617 }
618
619 if (pDc_Attr->iMapMode > MM_TWIPS)
620 {
621 if (( Xdenom ) && ( Ydenom ))
622 {
623 X = Xnum * pDc_Attr->szlWindowExt.cx / Xdenom;
624 if ( X )
625 {
626 Y = Ynum * pDc_Attr->szlWindowExt.cy / Ydenom;
627 if ( Y )
628 {
629 pDc_Attr->szlWindowExt.cx = X;
630 pDc_Attr->szlWindowExt.cy = Y;
631
632 IntMirrorWindowOrg(pDC);
633
634 pDc_Attr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
635
636 if (pDc_Attr->iMapMode == MM_ISOTROPIC) IntFixIsotropicMapping(pDC);
637 DC_UpdateXforms(pDC);
638
639 Ret = TRUE;
640 }
641 }
642 }
643 }
644 else
645 Ret = TRUE;
646
647 DC_UnlockDc(pDC);
648 return Ret;
649 }
650
651 int
652 APIENTRY
653 IntGdiSetMapMode(PDC dc,
654 int MapMode)
655 {
656 int PrevMapMode;
657 PDC_ATTR Dc_Attr = dc->pDc_Attr;
658 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
659
660 PrevMapMode = Dc_Attr->iMapMode;
661
662 Dc_Attr->iMapMode = MapMode;
663
664 switch (MapMode)
665 {
666 case MM_TEXT:
667 Dc_Attr->szlWindowExt.cx = 1;
668 Dc_Attr->szlWindowExt.cy = 1;
669 Dc_Attr->szlViewportExt.cx = 1;
670 Dc_Attr->szlViewportExt.cy = 1;
671 Dc_Attr->flXform &= ~(ISO_OR_ANISO_MAP_MODE|PTOD_EFM22_NEGATIVE|
672 PTOD_EFM11_NEGATIVE|POSITIVE_Y_IS_UP);
673 Dc_Attr->flXform |= (PAGE_XLATE_CHANGED|PAGE_TO_DEVICE_SCALE_IDENTITY|
674 INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
675 break;
676
677 case MM_ISOTROPIC:
678 Dc_Attr->szlWindowExt.cx = 3600;
679 Dc_Attr->szlWindowExt.cy = 2700;
680 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
681 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
682 break;
683
684 case MM_LOMETRIC:
685 Dc_Attr->szlWindowExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize * 10;
686 Dc_Attr->szlWindowExt.cy = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize * 10;
687 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
688 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
689 break;
690
691 case MM_HIMETRIC:
692 Dc_Attr->szlWindowExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize * 100;
693 Dc_Attr->szlWindowExt.cy = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize * 100;
694 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
695 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
696 break;
697
698 case MM_LOENGLISH:
699 Dc_Attr->szlWindowExt.cx = EngMulDiv(1000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize, 254);
700 Dc_Attr->szlWindowExt.cy = EngMulDiv(1000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize, 254);
701 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
702 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
703 break;
704
705 case MM_HIENGLISH:
706 Dc_Attr->szlWindowExt.cx = EngMulDiv(10000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize, 254);
707 Dc_Attr->szlWindowExt.cy = EngMulDiv(10000, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize, 254);
708 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
709 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
710 break;
711
712 case MM_TWIPS:
713 Dc_Attr->szlWindowExt.cx = EngMulDiv(14400, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzSize, 254);
714 Dc_Attr->szlWindowExt.cy = EngMulDiv(14400, ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertSize, 254);
715 Dc_Attr->szlViewportExt.cx = ((PGDIDEVICE)dc->pPDev)->GDIInfo.ulHorzRes;
716 Dc_Attr->szlViewportExt.cy = -((PGDIDEVICE)dc->pPDev)->GDIInfo.ulVertRes;
717 break;
718
719 case MM_ANISOTROPIC:
720 Dc_Attr->flXform &= ~(PAGE_TO_DEVICE_IDENTITY|POSITIVE_Y_IS_UP);
721 Dc_Attr->flXform |= ISO_OR_ANISO_MAP_MODE;
722 break;
723 default:
724 Dc_Attr->iMapMode = PrevMapMode;
725 PrevMapMode = 0;
726 }
727 DC_UpdateXforms(dc);
728
729 return PrevMapMode;
730 }
731
732 BOOL
733 APIENTRY
734 NtGdiSetViewportExtEx(HDC hDC,
735 int XExtent,
736 int YExtent,
737 LPSIZE Size)
738 {
739 PDC dc;
740 PDC_ATTR Dc_Attr;
741
742 dc = DC_LockDc(hDC);
743 if ( !dc )
744 {
745 SetLastWin32Error(ERROR_INVALID_HANDLE);
746 return FALSE;
747 }
748 Dc_Attr = dc->pDc_Attr;
749 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
750
751 switch (Dc_Attr->iMapMode)
752 {
753 case MM_HIENGLISH:
754 case MM_HIMETRIC:
755 case MM_LOENGLISH:
756 case MM_LOMETRIC:
757 case MM_TEXT:
758 case MM_TWIPS:
759 DC_UnlockDc(dc);
760 return FALSE;
761
762 case MM_ISOTROPIC:
763 // Here we should (probably) check that SetWindowExtEx *really* has
764 // been called
765 break;
766 }
767
768 if (Size)
769 {
770 NTSTATUS Status = STATUS_SUCCESS;
771
772 _SEH2_TRY
773 {
774 ProbeForWrite(Size,
775 sizeof(SIZE),
776 1);
777 Size->cx = Dc_Attr->szlViewportExt.cx;
778 Size->cy = Dc_Attr->szlViewportExt.cy;
779
780 Dc_Attr->szlViewportExt.cx = XExtent;
781 Dc_Attr->szlViewportExt.cy = YExtent;
782
783 if (Dc_Attr->iMapMode == MM_ISOTROPIC)
784 IntFixIsotropicMapping(dc);
785 }
786 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
787 {
788 Status = _SEH2_GetExceptionCode();
789 }
790 _SEH2_END;
791
792 if(!NT_SUCCESS(Status))
793 {
794 SetLastNtError(Status);
795 DC_UnlockDc(dc);
796 return FALSE;
797 }
798 }
799
800
801 DC_UpdateXforms(dc);
802 DC_UnlockDc(dc);
803
804 return TRUE;
805 }
806
807 BOOL
808 APIENTRY
809 NtGdiSetViewportOrgEx(HDC hDC,
810 int X,
811 int Y,
812 LPPOINT Point)
813 {
814 PDC dc;
815 PDC_ATTR Dc_Attr;
816
817 dc = DC_LockDc(hDC);
818 if (!dc)
819 {
820 SetLastWin32Error(ERROR_INVALID_HANDLE);
821 return FALSE;
822 }
823 Dc_Attr = dc->pDc_Attr;
824 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
825
826 if (Point)
827 {
828 NTSTATUS Status = STATUS_SUCCESS;
829
830 _SEH2_TRY
831 {
832 ProbeForWrite(Point,
833 sizeof(POINT),
834 1);
835 Point->x = Dc_Attr->ptlViewportOrg.x;
836 Point->y = Dc_Attr->ptlViewportOrg.y;
837 }
838 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
839 {
840 Status = _SEH2_GetExceptionCode();
841 }
842 _SEH2_END;
843
844 if(!NT_SUCCESS(Status))
845 {
846 SetLastNtError(Status);
847 DC_UnlockDc(dc);
848 return FALSE;
849 }
850 }
851
852 Dc_Attr->ptlViewportOrg.x = X;
853 Dc_Attr->ptlViewportOrg.y = Y;
854
855 DC_UpdateXforms(dc);
856 DC_UnlockDc(dc);
857
858 return TRUE;
859 }
860
861 BOOL
862 APIENTRY
863 NtGdiSetWindowExtEx(HDC hDC,
864 int XExtent,
865 int YExtent,
866 LPSIZE Size)
867 {
868 PDC dc;
869 PDC_ATTR Dc_Attr;
870
871 dc = DC_LockDc(hDC);
872 if (!dc)
873 {
874 SetLastWin32Error(ERROR_INVALID_HANDLE);
875 return FALSE;
876 }
877 Dc_Attr = dc->pDc_Attr;
878 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
879
880 switch (Dc_Attr->iMapMode)
881 {
882 case MM_HIENGLISH:
883 case MM_HIMETRIC:
884 case MM_LOENGLISH:
885 case MM_LOMETRIC:
886 case MM_TEXT:
887 case MM_TWIPS:
888 DC_UnlockDc(dc);
889 return FALSE;
890 }
891
892 if (Size)
893 {
894 NTSTATUS Status = STATUS_SUCCESS;
895
896 _SEH2_TRY
897 {
898 ProbeForWrite(Size,
899 sizeof(SIZE),
900 1);
901 Size->cx = Dc_Attr->szlWindowExt.cx;
902 Size->cy = Dc_Attr->szlWindowExt.cy;
903 }
904 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
905 {
906 Status = _SEH2_GetExceptionCode();
907 }
908 _SEH2_END;
909
910 if(!NT_SUCCESS(Status))
911 {
912 SetLastNtError(Status);
913 DC_UnlockDc(dc);
914 return FALSE;
915 }
916 }
917
918 Dc_Attr->szlWindowExt.cx = XExtent;
919 Dc_Attr->szlWindowExt.cy = YExtent;
920
921 DC_UpdateXforms(dc);
922 DC_UnlockDc(dc);
923
924 return TRUE;
925 }
926
927 BOOL
928 APIENTRY
929 NtGdiSetWindowOrgEx(HDC hDC,
930 int X,
931 int Y,
932 LPPOINT Point)
933 {
934 PDC dc;
935 PDC_ATTR Dc_Attr;
936
937 dc = DC_LockDc(hDC);
938 if (!dc)
939 {
940 SetLastWin32Error(ERROR_INVALID_HANDLE);
941 return FALSE;
942 }
943 Dc_Attr = dc->pDc_Attr;
944 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
945
946 if (Point)
947 {
948 NTSTATUS Status = STATUS_SUCCESS;
949
950 _SEH2_TRY
951 {
952 ProbeForWrite(Point,
953 sizeof(POINT),
954 1);
955 Point->x = Dc_Attr->ptlWindowOrg.x;
956 Point->y = Dc_Attr->ptlWindowOrg.y;
957 }
958 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
959 {
960 Status = _SEH2_GetExceptionCode();
961 }
962 _SEH2_END;
963
964 if(!NT_SUCCESS(Status))
965 {
966 SetLastNtError(Status);
967 DC_UnlockDc(dc);
968 return FALSE;
969 }
970 }
971
972 Dc_Attr->ptlWindowOrg.x = X;
973 Dc_Attr->ptlWindowOrg.y = Y;
974
975 DC_UpdateXforms(dc);
976 DC_UnlockDc(dc);
977
978 return TRUE;
979 }
980
981 //
982 // Mirror Window function.
983 //
984 VOID
985 FASTCALL
986 IntMirrorWindowOrg(PDC dc)
987 {
988 PDC_ATTR Dc_Attr;
989 LONG X;
990
991 Dc_Attr = dc->pDc_Attr;
992 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
993
994 if (!(Dc_Attr->dwLayout & LAYOUT_RTL))
995 {
996 Dc_Attr->ptlWindowOrg.x = Dc_Attr->lWindowOrgx; // Flip it back.
997 return;
998 }
999 if (!Dc_Attr->szlViewportExt.cx) return;
1000 //
1001 // WOrgx = wox - (Width - 1) * WExtx / VExtx
1002 //
1003 X = (dc->erclWindow.right - dc->erclWindow.left) - 1; // Get device width - 1
1004
1005 X = ( X * Dc_Attr->szlWindowExt.cx) / Dc_Attr->szlViewportExt.cx;
1006
1007 Dc_Attr->ptlWindowOrg.x = Dc_Attr->lWindowOrgx - X; // Now set the inverted win origion.
1008
1009 return;
1010 }
1011
1012 // NtGdiSetLayout
1013 //
1014 // The default is left to right. This function changes it to right to left, which
1015 // is the standard in Arabic and Hebrew cultures.
1016 //
1017 /*
1018 * @implemented
1019 */
1020 DWORD
1021 APIENTRY
1022 NtGdiSetLayout(
1023 IN HDC hdc,
1024 IN LONG wox,
1025 IN DWORD dwLayout)
1026 {
1027 PDC dc;
1028 PDC_ATTR Dc_Attr;
1029 DWORD oLayout;
1030
1031 dc = DC_LockDc(hdc);
1032 if (!dc)
1033 {
1034 SetLastWin32Error(ERROR_INVALID_HANDLE);
1035 return GDI_ERROR;
1036 }
1037 Dc_Attr = dc->pDc_Attr;
1038 if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
1039
1040 Dc_Attr->dwLayout = dwLayout;
1041 oLayout = Dc_Attr->dwLayout;
1042
1043 if (!(dwLayout & LAYOUT_ORIENTATIONMASK))
1044 {
1045 DC_UnlockDc(dc);
1046 return oLayout;
1047 }
1048
1049 if (dwLayout & LAYOUT_RTL) Dc_Attr->iMapMode = MM_ANISOTROPIC;
1050
1051 Dc_Attr->szlWindowExt.cy = -Dc_Attr->szlWindowExt.cy;
1052 Dc_Attr->ptlWindowOrg.x = -Dc_Attr->ptlWindowOrg.x;
1053
1054 if (wox == -1)
1055 IntMirrorWindowOrg(dc);
1056 else
1057 Dc_Attr->ptlWindowOrg.x = wox - Dc_Attr->ptlWindowOrg.x;
1058
1059 if (!(Dc_Attr->flTextAlign & TA_CENTER)) Dc_Attr->flTextAlign |= TA_RIGHT;
1060
1061 if (dc->DcLevel.flPath & DCPATH_CLOCKWISE)
1062 dc->DcLevel.flPath &= ~DCPATH_CLOCKWISE;
1063 else
1064 dc->DcLevel.flPath |= DCPATH_CLOCKWISE;
1065
1066 Dc_Attr->flXform |= (PAGE_EXTENTS_CHANGED|INVALIDATE_ATTRIBUTES|DEVICE_TO_WORLD_INVALID);
1067
1068 // DC_UpdateXforms(dc);
1069 DC_UnlockDc(dc);
1070 return oLayout;
1071 }
1072
1073 /*
1074 * @implemented
1075 */
1076 LONG
1077 APIENTRY
1078 NtGdiGetDeviceWidth(
1079 IN HDC hdc)
1080 {
1081 PDC dc;
1082 LONG Ret;
1083 dc = DC_LockDc(hdc);
1084 if (!dc)
1085 {
1086 SetLastWin32Error(ERROR_INVALID_HANDLE);
1087 return 0;
1088 }
1089 Ret = dc->erclWindow.right - dc->erclWindow.left;
1090 DC_UnlockDc(dc);
1091 return Ret;
1092 }
1093
1094 /*
1095 * @implemented
1096 */
1097 BOOL
1098 APIENTRY
1099 NtGdiMirrorWindowOrg(
1100 IN HDC hdc)
1101 {
1102 PDC dc;
1103 dc = DC_LockDc(hdc);
1104 if (!dc)
1105 {
1106 SetLastWin32Error(ERROR_INVALID_HANDLE);
1107 return FALSE;
1108 }
1109 IntMirrorWindowOrg(dc);
1110 DC_UnlockDc(dc);
1111 return TRUE;
1112 }
1113
1114 /*
1115 * @implemented
1116 */
1117 BOOL
1118 APIENTRY
1119 NtGdiSetSizeDevice(
1120 IN HDC hdc,
1121 IN INT cxVirtualDevice,
1122 IN INT cyVirtualDevice)
1123 {
1124 PDC dc;
1125 PDC_ATTR pDc_Attr;
1126
1127 if (!cxVirtualDevice ||
1128 !cyVirtualDevice ) return FALSE;
1129
1130 dc = DC_LockDc(hdc);
1131 if (!dc) return FALSE;
1132
1133 pDc_Attr = dc->pDc_Attr;
1134 if(!pDc_Attr) pDc_Attr = &dc->Dc_Attr;
1135
1136 pDc_Attr->szlVirtualDeviceSize.cx = cxVirtualDevice;
1137 pDc_Attr->szlVirtualDeviceSize.cy = cyVirtualDevice;
1138
1139 // DC_UpdateXforms(dc);
1140 DC_UnlockDc(dc);
1141
1142 return TRUE;
1143 }
1144
1145 /*
1146 * @implemented
1147 */
1148 BOOL
1149 APIENTRY
1150 NtGdiSetVirtualResolution(
1151 IN HDC hdc,
1152 IN INT cxVirtualDevicePixel,
1153 IN INT cyVirtualDevicePixel,
1154 IN INT cxVirtualDeviceMm,
1155 IN INT cyVirtualDeviceMm)
1156 {
1157 PDC dc;
1158 PDC_ATTR pDc_Attr;
1159
1160 // Need test types for zeros and non zeros
1161
1162 dc = DC_LockDc(hdc);
1163 if (!dc) return FALSE;
1164
1165 pDc_Attr = dc->pDc_Attr;
1166 if(!pDc_Attr) pDc_Attr = &dc->Dc_Attr;
1167
1168 pDc_Attr->szlVirtualDevicePixel.cx = cxVirtualDevicePixel;
1169 pDc_Attr->szlVirtualDevicePixel.cy = cyVirtualDevicePixel;
1170 pDc_Attr->szlVirtualDeviceMm.cx = cxVirtualDeviceMm;
1171 pDc_Attr->szlVirtualDeviceMm.cy = cyVirtualDeviceMm;
1172
1173 // DC_UpdateXforms(dc);
1174 DC_UnlockDc(dc);
1175 return TRUE;
1176 }
1177
1178 /* EOF */