- Force a recompute when setting map modes.
[reactos.git] / reactos / dll / win32 / gdi32 / objects / dc.c
1 #include "precomp.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6 HGDIOBJ stock_objects[NB_STOCK_OBJECTS]; // temp location.
7
8 HDC
9 FASTCALL
10 IntCreateDICW ( LPCWSTR lpwszDriver,
11 LPCWSTR lpwszDevice,
12 LPCWSTR lpwszOutput,
13 PDEVMODEW lpInitData,
14 ULONG iType )
15 {
16 UNICODE_STRING Device, Output;
17 HDC hDC = NULL;
18 BOOL Display = FALSE, Default = TRUE;
19 ULONG UMdhpdev = 0;
20
21 HANDLE hspool = NULL;
22
23 if ((!lpwszDevice) && (!lpwszDriver))
24 {
25 Default = FALSE; // Ask Win32k to set Default device.
26 Display = TRUE; // Most likely to be DISPLAY.
27 }
28 else
29 {
30 if (lpwszDevice) // First
31 {
32 if (!_wcsnicmp(lpwszDevice, L"\\\\.\\DISPLAY",11)) Display = TRUE;
33 RtlInitUnicodeString(&Device, lpwszDevice);
34 }
35 else
36 {
37 if (lpwszDriver) // Second
38 {
39 if ((!_wcsnicmp(lpwszDriver, L"DISPLAY",7)) ||
40 (!_wcsnicmp(lpwszDriver, L"\\\\.\\DISPLAY",11))) Display = TRUE;
41 RtlInitUnicodeString(&Device, lpwszDriver);
42 }
43 }
44 }
45
46 if (lpwszOutput) RtlInitUnicodeString(&Output, lpwszOutput);
47
48 if (!Display)
49 {
50 //Handle Print device or something else.
51 DPRINT1("Not a DISPLAY device! %wZ\n", &Device);
52 }
53
54 hDC = NtGdiOpenDCW( (Default ? &Device : NULL),
55 (PDEVMODEW) lpInitData,
56 (lpwszOutput ? &Output : NULL),
57 iType, // DCW 0 and ICW 1.
58 hspool,
59 (PVOID) NULL, // NULL for now.
60 (PVOID) &UMdhpdev );
61 #if 0
62 // Handle something other than a normal dc object.
63 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
64 {
65 PDC_ATTR Dc_Attr;
66 PLDC pLDC;
67
68 GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr);
69
70 pLDC = LocalAlloc(LMEM_ZEROINIT, sizeof(LDC));
71
72 Dc_Attr->pvLDC = pLDC;
73 pLDC->hDC = hDC;
74 pLDC->iType = LDC_LDC; // 1 (init) local DC, 2 EMF LDC
75 DbgPrint("DC_ATTR Allocated -> 0x%x\n",Dc_Attr);
76 }
77 #endif
78 return hDC;
79 }
80
81
82 /*
83 * @implemented
84 */
85 HDC
86 STDCALL
87 CreateCompatibleDC ( HDC hdc)
88 {
89 HDC rhDC;
90 // PDC_ATTR Dc_Attr;
91
92 rhDC = NtGdiCreateCompatibleDC(hdc);
93 #if 0
94 if ( hdc && rhDC)
95 {
96 if (GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr))
97 {
98 if ( Dc_Attr->pvLIcm ) IcmCompatibleDC(rhDC, hdc, Dc_Attr);
99 }
100 }
101 #endif
102 return rhDC;
103 }
104
105 /*
106 * @implemented
107 */
108 HDC
109 STDCALL
110 CreateDCA (
111 LPCSTR lpszDriver,
112 LPCSTR lpszDevice,
113 LPCSTR lpszOutput,
114 CONST DEVMODEA * lpdvmInit
115 )
116 {
117 ANSI_STRING DriverA, DeviceA, OutputA;
118 UNICODE_STRING DriverU, DeviceU, OutputU;
119 LPDEVMODEW dvmInitW = NULL;
120 HDC hDC;
121
122 /*
123 * If needed, convert to Unicode
124 * any string parameter.
125 */
126
127 if (NULL != lpszDriver)
128 {
129 RtlInitAnsiString(&DriverA, (LPSTR)lpszDriver);
130 RtlAnsiStringToUnicodeString(&DriverU, &DriverA, TRUE);
131 } else
132 DriverU.Buffer = NULL;
133 if (NULL != lpszDevice)
134 {
135 RtlInitAnsiString(&DeviceA, (LPSTR)lpszDevice);
136 RtlAnsiStringToUnicodeString(&DeviceU, &DeviceA, TRUE);
137 } else
138 DeviceU.Buffer = NULL;
139 if (NULL != lpszOutput)
140 {
141 RtlInitAnsiString(&OutputA, (LPSTR)lpszOutput);
142 RtlAnsiStringToUnicodeString(&OutputU, &OutputA, TRUE);
143 } else
144 OutputU.Buffer = NULL;
145
146 if ( lpdvmInit )
147 dvmInitW = GdiConvertToDevmodeW((LPDEVMODEA)lpdvmInit);
148
149 hDC = IntCreateDICW ( DriverU.Buffer,
150 DeviceU.Buffer,
151 OutputU.Buffer,
152 lpdvmInit ? dvmInitW : NULL,
153 0 );
154 HEAP_free (dvmInitW);
155 /*
156 * Free Unicode parameters.
157 */
158 RtlFreeUnicodeString(&DriverU);
159 RtlFreeUnicodeString(&DeviceU);
160 RtlFreeUnicodeString(&OutputU);
161
162 /*
163 * Return the possible DC handle.
164 */
165 return hDC;
166 }
167
168
169 /*
170 * @implemented
171 */
172 HDC
173 STDCALL
174 CreateDCW (
175 LPCWSTR lpwszDriver,
176 LPCWSTR lpwszDevice,
177 LPCWSTR lpwszOutput,
178 CONST DEVMODEW *lpInitData
179 )
180 {
181
182 return IntCreateDICW ( lpwszDriver,
183 lpwszDevice,
184 lpwszOutput,
185 (PDEVMODEW) lpInitData,
186 0 );
187 }
188
189
190 /*
191 * @implemented
192 */
193 HDC
194 STDCALL
195 CreateICW(
196 LPCWSTR lpszDriver,
197 LPCWSTR lpszDevice,
198 LPCWSTR lpszOutput,
199 CONST DEVMODEW *lpdvmInit
200 )
201 {
202 return IntCreateDICW ( lpszDriver,
203 lpszDevice,
204 lpszOutput,
205 (PDEVMODEW) lpdvmInit,
206 1 );
207 }
208
209
210 /*
211 * @implemented
212 */
213 HDC
214 STDCALL
215 CreateICA(
216 LPCSTR lpszDriver,
217 LPCSTR lpszDevice,
218 LPCSTR lpszOutput,
219 CONST DEVMODEA *lpdvmInit
220 )
221 {
222 NTSTATUS Status;
223 LPWSTR lpszDriverW, lpszDeviceW, lpszOutputW;
224 LPDEVMODEW dvmInitW = NULL;
225 HDC rc = 0;
226
227 Status = HEAP_strdupA2W ( &lpszDriverW, lpszDriver );
228 if (!NT_SUCCESS (Status))
229 SetLastError (RtlNtStatusToDosError(Status));
230 else
231 {
232 Status = HEAP_strdupA2W ( &lpszDeviceW, lpszDevice );
233 if (!NT_SUCCESS (Status))
234 SetLastError (RtlNtStatusToDosError(Status));
235 else
236 {
237 Status = HEAP_strdupA2W ( &lpszOutputW, lpszOutput );
238 if (!NT_SUCCESS (Status))
239 SetLastError (RtlNtStatusToDosError(Status));
240 else
241 {
242 if ( lpdvmInit )
243 dvmInitW = GdiConvertToDevmodeW((LPDEVMODEA)lpdvmInit);
244
245 rc = IntCreateDICW ( lpszDriverW,
246 lpszDeviceW,
247 lpszOutputW,
248 lpdvmInit ? dvmInitW : NULL,
249 1 );
250 HEAP_free (dvmInitW);
251 HEAP_free ( lpszOutputW );
252 }
253 HEAP_free ( lpszDeviceW );
254 }
255 HEAP_free ( lpszDriverW );
256 }
257 return rc;
258 }
259
260
261 /*
262 * @implemented
263 */
264 BOOL
265 STDCALL
266 DeleteDC(HDC hDC)
267 {
268 BOOL Ret = TRUE;
269 #if 0
270 PDC_ATTR Dc_Attr;
271 PLDC pLDC;
272
273 if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return FALSE;
274
275 if ( Dc_Attr )
276 {
277 pLDC = Dc_Attr->pvLDC;
278
279 if ( pLDC )
280 {
281 DPRINT1("Delete the Local DC structure\n");
282 LocalFree( pLDC );
283 }
284 }
285 #endif
286 Ret = NtGdiDeleteObjectApp(hDC);
287
288 return Ret;
289 }
290
291 /*
292 * @implemented
293 */
294 BOOL
295 STDCALL
296 DeleteObject(HGDIOBJ hObject)
297 {
298 UINT Type = 0;
299
300 /* From Wine: DeleteObject does not SetLastError() on a null object */
301 if(!hObject) return FALSE;
302
303 if (0 != ((DWORD) hObject & GDI_HANDLE_STOCK_MASK))
304 { // Relax! This is a normal return!
305 DPRINT("Trying to delete system object 0x%x\n", hObject);
306 return TRUE;
307 }
308 // If you dont own it?! Get OUT!
309 if(!GdiIsHandleValid(hObject)) return FALSE;
310
311 Type = GDI_HANDLE_GET_TYPE(hObject);
312
313 if ((Type == GDI_OBJECT_TYPE_METAFILE) ||
314 (Type == GDI_OBJECT_TYPE_ENHMETAFILE))
315 return FALSE;
316
317 switch (Type)
318 {
319 case GDI_OBJECT_TYPE_DC:
320 return DeleteDC((HDC) hObject);
321 case GDI_OBJECT_TYPE_COLORSPACE:
322 return NtGdiDeleteColorSpace((HCOLORSPACE) hObject);
323 case GDI_OBJECT_TYPE_REGION:
324 return DeleteRegion((HRGN) hObject);
325 #if 0
326 case GDI_OBJECT_TYPE_METADC:
327 return MFDRV_DeleteObject( hObject );
328 case GDI_OBJECT_TYPE_EMF:
329 {
330 PLDC pLDC = GdiGetLDC(hObject);
331 if ( !pLDC ) return FALSE;
332 return EMFDRV_DeleteObject( hObject );
333 }
334 #endif
335 case GDI_OBJECT_TYPE_FONT:
336 break;
337
338 case GDI_OBJECT_TYPE_BRUSH:
339 case GDI_OBJECT_TYPE_EXTPEN:
340 case GDI_OBJECT_TYPE_PEN:
341 {
342 PBRUSH_ATTR Brh_Attr;
343 PTEB pTeb;
344
345 if ((!GdiGetHandleUserData(hObject, (DWORD)Type, (PVOID) &Brh_Attr)) ||
346 (Brh_Attr == NULL) ) break;
347
348 pTeb = NtCurrentTeb();
349
350 if (pTeb->Win32ThreadInfo == NULL) break;
351
352 if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSOBJECT)) <= GDIBATCHBUFSIZE)
353 {
354 PGDIBSOBJECT pgO = (PGDIBSOBJECT)(&pTeb->GdiTebBatch.Buffer[0] +
355 pTeb->GdiTebBatch.Offset);
356 pgO->gbHdr.Cmd = GdiBCDelObj;
357 pgO->gbHdr.Size = sizeof(GDIBSOBJECT);
358 pgO->hgdiobj = hObject;
359
360 pTeb->GdiTebBatch.Offset += sizeof(GDIBSOBJECT);
361 pTeb->GdiBatchCount++;
362 if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
363 return TRUE;
364 }
365 break;
366 }
367 case GDI_OBJECT_TYPE_BITMAP:
368 default:
369 break;
370 }
371 return NtGdiDeleteObjectApp(hObject);
372 }
373
374 INT
375 STDCALL
376 GetArcDirection( HDC hdc )
377 {
378 return GetDCDWord( hdc, GdiGetArcDirection, 0);
379 }
380
381
382 INT
383 STDCALL
384 SetArcDirection( HDC hdc, INT nDirection )
385 {
386 return GetAndSetDCDWord( hdc, GdiGetSetArcDirection, nDirection, 0, 0, 0 );
387 }
388
389
390 HGDIOBJ
391 STDCALL
392 GetDCObject( HDC hDC, INT iType)
393 {
394 if((iType == GDI_OBJECT_TYPE_BRUSH) ||
395 (iType == GDI_OBJECT_TYPE_EXTPEN)||
396 (iType == GDI_OBJECT_TYPE_PEN) ||
397 (iType == GDI_OBJECT_TYPE_COLORSPACE))
398 {
399 HGDIOBJ hGO = NULL;
400 PDC_ATTR Dc_Attr;
401
402 if (!hDC) return hGO;
403
404 if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return NULL;
405
406 switch (iType)
407 {
408 case GDI_OBJECT_TYPE_BRUSH:
409 hGO = Dc_Attr->hbrush;
410 break;
411
412 case GDI_OBJECT_TYPE_EXTPEN:
413 case GDI_OBJECT_TYPE_PEN:
414 hGO = Dc_Attr->hpen;
415 break;
416
417 case GDI_OBJECT_TYPE_COLORSPACE:
418 hGO = Dc_Attr->hColorSpace;
419 break;
420 }
421 return hGO;
422 }
423 return NtGdiGetDCObject( hDC, iType );
424 }
425
426
427 /*
428 * @implemented
429 *
430 */
431 HGDIOBJ
432 STDCALL
433 GetCurrentObject(HDC hdc,
434 UINT uObjectType)
435 {
436 switch(uObjectType)
437 {
438 case OBJ_EXTPEN:
439 case OBJ_PEN:
440 uObjectType = GDI_OBJECT_TYPE_PEN;
441 break;
442 case OBJ_BRUSH:
443 uObjectType = GDI_OBJECT_TYPE_BRUSH;
444 break;
445 case OBJ_PAL:
446 uObjectType = GDI_OBJECT_TYPE_PALETTE;
447 break;
448 case OBJ_FONT:
449 uObjectType = GDI_OBJECT_TYPE_FONT;
450 break;
451 case OBJ_BITMAP:
452 uObjectType = GDI_OBJECT_TYPE_BITMAP;
453 break;
454 case OBJ_COLORSPACE:
455 uObjectType = GDI_OBJECT_TYPE_COLORSPACE;
456 break;
457 /* tests show that OBJ_REGION is explicitly ignored */
458 case OBJ_REGION:
459 return NULL;
460 /* the SDK only mentions those above */
461 default:
462 SetLastError(ERROR_INVALID_PARAMETER);
463 return NULL;
464 }
465 return GetDCObject(hdc, uObjectType);
466 }
467
468
469 /*
470 * @implemented
471 */
472 DWORD
473 STDCALL
474 GetRelAbs(
475 HDC hdc,
476 DWORD dwIgnore
477 )
478 {
479 return GetDCDWord( hdc, GdiGetRelAbs, 0);
480 }
481
482
483 /*
484 * @implemented
485 */
486 DWORD
487 STDCALL
488 SetRelAbs(
489 HDC hdc,
490 INT Mode
491 )
492 {
493 return GetAndSetDCDWord( hdc, GdiGetSetRelAbs, Mode, 0, 0, 0 );
494 }
495
496
497 /*
498 * @implemented
499 */
500 DWORD
501 STDCALL
502 GetAndSetDCDWord( HDC hDC, INT u, DWORD dwIn, DWORD Unk1, DWORD Unk2, DWORD Unk3 )
503 {
504 BOOL Ret = TRUE;
505 // Handle something other than a normal dc object.
506 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
507 {
508 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
509 return 0; //call MFDRV
510 else
511 {
512 PLDC pLDC = GdiGetLDC(hDC);
513 if ( !pLDC )
514 {
515 SetLastError(ERROR_INVALID_HANDLE);
516 return 0;
517 }
518 if (pLDC->iType == LDC_EMFLDC)
519 {
520 Ret = TRUE; //call EMFDRV
521 if (Ret)
522 return u;
523 return 0;
524 }
525 }
526 }
527 Ret = NtGdiGetAndSetDCDword( hDC, u, dwIn, (DWORD*) &u );
528 if (Ret)
529 return u;
530 else
531 SetLastError(ERROR_INVALID_HANDLE);
532 return 0;
533 }
534
535
536 /*
537 * @implemented
538 */
539 DWORD
540 STDCALL
541 GetDCDWord( HDC hDC, INT u, DWORD Result )
542 {
543 BOOL Ret = NtGdiGetDCDword( hDC, u, (DWORD*) &u );
544 if (!Ret) return Result;
545 else return u;
546 }
547
548
549 /*
550 * @implemented
551 */
552 BOOL
553 STDCALL
554 GetAspectRatioFilterEx(
555 HDC hdc,
556 LPSIZE lpAspectRatio
557 )
558 {
559 return NtGdiGetDCPoint( hdc, GdiGetAspectRatioFilter, (LPPOINT) lpAspectRatio );
560 }
561
562
563 /*
564 * @implemented
565 */
566 BOOL
567 STDCALL
568 GetDCOrgEx(
569 HDC hdc,
570 LPPOINT lpPoint
571 )
572 {
573 return NtGdiGetDCPoint( hdc, GdiGetDCOrg, lpPoint );
574 }
575
576
577 /*
578 * @implemented
579 */
580 LONG
581 STDCALL
582 GetDCOrg(
583 HDC hdc
584 )
585 {
586 // Officially obsolete by Microsoft
587 POINT Pt;
588 if (!GetDCOrgEx(hdc, &Pt))
589 return 0;
590 return(MAKELONG(Pt.x, Pt.y));
591 }
592
593
594 int
595 GetNonFontObject(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
596 {
597 INT dwType;
598
599 hGdiObj = (HANDLE)GdiFixUpHandle(hGdiObj);
600 dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
601
602 if (!lpBuffer) // Should pass it all to Win32k and let god sort it out. ;^)
603 {
604 switch(dwType)
605 {
606 case GDI_OBJECT_TYPE_PEN:
607 return sizeof(LOGPEN);
608 case GDI_OBJECT_TYPE_BRUSH:
609 return sizeof(LOGBRUSH);
610 case GDI_OBJECT_TYPE_BITMAP:
611 return sizeof(BITMAP);
612 case GDI_OBJECT_TYPE_PALETTE:
613 return sizeof(WORD);
614 case GDI_OBJECT_TYPE_EXTPEN: /* we don't know the size, ask win32k */
615 break;
616 }
617 }
618
619 switch(dwType)
620 {
621 case GDI_OBJECT_TYPE_PEN: //Check the structures and see if A & W are the same.
622 case GDI_OBJECT_TYPE_EXTPEN:
623 case GDI_OBJECT_TYPE_BRUSH: // Mixing Apples and Oranges?
624 case GDI_OBJECT_TYPE_BITMAP:
625 case GDI_OBJECT_TYPE_PALETTE:
626 return NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
627
628 case GDI_OBJECT_TYPE_DC:
629 case GDI_OBJECT_TYPE_REGION:
630 case GDI_OBJECT_TYPE_METAFILE:
631 case GDI_OBJECT_TYPE_ENHMETAFILE:
632 case GDI_OBJECT_TYPE_EMF:
633 SetLastError(ERROR_INVALID_HANDLE);
634 }
635 return 0;
636 }
637
638
639 /*
640 * @implemented
641 */
642 int
643 STDCALL
644 GetObjectA(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
645 {
646 ENUMLOGFONTEXDVW LogFont;
647 DWORD dwType;
648 INT Result = 0;
649
650 dwType = GDI_HANDLE_GET_TYPE(hGdiObj);;
651
652 if(dwType == GDI_OBJECT_TYPE_COLORSPACE) //Stays here, processes struct A
653 {
654 SetLastError(ERROR_NOT_SUPPORTED);
655 return 0;
656 }
657
658 if (dwType == GDI_OBJECT_TYPE_FONT)
659 {
660 if (!lpBuffer)
661 {
662 return sizeof(LOGFONTA);
663 }
664 if (cbSize == 0)
665 {
666 /* Windows does not SetLastError() */
667 return 0;
668 }
669 // ENUMLOGFONTEXDVW is the default size and should be the structure for
670 // Entry->KernelData for Font objects.
671 Result = NtGdiExtGetObjectW(hGdiObj, sizeof(ENUMLOGFONTEXDVW), &LogFont);
672
673 if (0 == Result)
674 {
675 return 0;
676 }
677
678 switch (cbSize)
679 {
680 case sizeof(ENUMLOGFONTEXDVA):
681 // need to move more here.
682 case sizeof(ENUMLOGFONTEXA):
683 EnumLogFontExW2A( (LPENUMLOGFONTEXA) lpBuffer, &LogFont.elfEnumLogfontEx );
684 break;
685
686 case sizeof(ENUMLOGFONTA):
687 // Same here, maybe? Check the structures.
688 case sizeof(EXTLOGFONTA):
689 // Same here
690 case sizeof(LOGFONTA):
691 LogFontW2A((LPLOGFONTA) lpBuffer, &LogFont.elfEnumLogfontEx.elfLogFont);
692 break;
693
694 default:
695 SetLastError(ERROR_BUFFER_OVERFLOW);
696 return 0;
697 }
698 return cbSize;
699 }
700
701 return GetNonFontObject(hGdiObj, cbSize, lpBuffer);
702 }
703
704
705 /*
706 * @implemented
707 */
708 int
709 STDCALL
710 GetObjectW(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
711 {
712 DWORD dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
713 INT Result = 0;
714
715 /*
716 Check List:
717 MSDN, "This can be a handle to one of the following: logical bitmap, a brush,
718 a font, a palette, a pen, or a device independent bitmap created by calling
719 the CreateDIBSection function."
720 */
721 if(dwType == GDI_OBJECT_TYPE_COLORSPACE) //Stays here, processes struct W
722 {
723 SetLastError(ERROR_NOT_SUPPORTED); // Not supported yet.
724 return 0;
725 }
726
727 if (dwType == GDI_OBJECT_TYPE_FONT)
728 {
729 if (!lpBuffer)
730 {
731 return sizeof(LOGFONTW);
732 }
733
734 if (cbSize == 0)
735 {
736 /* Windows does not SetLastError() */
737 return 0;
738 }
739 // Poorly written apps are not ReactOS problem!
740 // We fix it here if the size is larger than the default size.
741 if( cbSize > sizeof(ENUMLOGFONTEXDVW) ) cbSize = sizeof(ENUMLOGFONTEXDVW);
742
743 Result = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer); // Should handle the copy.
744
745 if (0 == Result)
746 {
747 return 0;
748 }
749 return cbSize;
750 }
751
752 return GetNonFontObject(hGdiObj, cbSize, lpBuffer);
753 }
754
755
756 /*
757 * @implemented
758 */
759 COLORREF
760 STDCALL
761 GetDCBrushColor(
762 HDC hdc
763 )
764 {
765 PDC_ATTR Dc_Attr;
766
767 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return CLR_INVALID;
768 return (COLORREF) Dc_Attr->ulPenClr;
769 }
770
771 /*
772 * @implemented
773 */
774 COLORREF
775 STDCALL
776 GetDCPenColor(
777 HDC hdc
778 )
779 {
780 PDC_ATTR Dc_Attr;
781
782 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return CLR_INVALID;
783 return (COLORREF) Dc_Attr->ulPenClr;
784 }
785
786 /*
787 * @implemented
788 */
789 COLORREF
790 STDCALL
791 SetDCBrushColor(
792 HDC hdc,
793 COLORREF crColor
794 )
795 {
796 PDC_ATTR Dc_Attr;
797 COLORREF OldColor = CLR_INVALID;
798
799 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldColor;
800 else
801 {
802 OldColor = (COLORREF) Dc_Attr->ulBrushClr;
803 Dc_Attr->ulBrushClr = (ULONG) crColor;
804
805 if ( Dc_Attr->crBrushClr != crColor ) // if same, don't force a copy.
806 {
807 Dc_Attr->ulDirty_ |= DIRTY_FILL;
808 Dc_Attr->crBrushClr = crColor;
809 }
810 }
811 return OldColor;
812 }
813
814 /*
815 * @implemented
816 */
817 COLORREF
818 STDCALL
819 SetDCPenColor(
820 HDC hdc,
821 COLORREF crColor
822 )
823 {
824 PDC_ATTR Dc_Attr;
825 COLORREF OldColor = CLR_INVALID;
826
827 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldColor;
828 else
829 {
830 OldColor = (COLORREF) Dc_Attr->ulPenClr;
831 Dc_Attr->ulPenClr = (ULONG) crColor;
832
833 if ( Dc_Attr->crPenClr != crColor )
834 {
835 Dc_Attr->ulDirty_ |= DIRTY_LINE;
836 Dc_Attr->crPenClr = crColor;
837 }
838 }
839 return OldColor;
840 }
841
842 /*
843 * @implemented
844 *
845 */
846 COLORREF
847 STDCALL
848 GetBkColor(HDC hdc)
849 {
850 PDC_ATTR Dc_Attr;
851 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
852 return Dc_Attr->ulBackgroundClr;
853 }
854
855 /*
856 * @implemented
857 */
858 COLORREF
859 STDCALL
860 SetBkColor(
861 HDC hdc,
862 COLORREF crColor
863 )
864 {
865 PDC_ATTR Dc_Attr;
866 COLORREF OldColor = CLR_INVALID;
867
868 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldColor;
869 #if 0
870 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
871 {
872 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
873 return MFDRV_SetBkColor( hDC, crColor );
874 else
875 {
876 PLDC pLDC = Dc_Attr->pvLDC;
877 if ( !pLDC )
878 {
879 SetLastError(ERROR_INVALID_HANDLE);
880 return FALSE;
881 }
882 if (pLDC->iType == LDC_EMFLDC)
883 {
884 return EMFDRV_SetBkColor( hDC, crColor );
885 }
886 }
887 }
888 #endif
889 OldColor = (COLORREF) Dc_Attr->ulBackgroundClr;
890 Dc_Attr->ulBackgroundClr = (ULONG) crColor;
891
892 if ( Dc_Attr->crBackgroundClr != crColor )
893 {
894 Dc_Attr->ulDirty_ |= DIRTY_LINE;
895 Dc_Attr->crBackgroundClr = crColor;
896 }
897 return OldColor;
898 }
899
900 /*
901 * @implemented
902 *
903 */
904 int
905 STDCALL
906 GetBkMode(HDC hdc)
907 {
908 PDC_ATTR Dc_Attr;
909 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
910 return Dc_Attr->lBkMode;
911 }
912
913 /*
914 * @implemented
915 *
916 */
917 int
918 STDCALL
919 SetBkMode(HDC hdc,
920 int iBkMode)
921 {
922 PDC_ATTR Dc_Attr;
923 INT OldMode = 0;
924
925 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldMode;
926 #if 0
927 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
928 {
929 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
930 return MFDRV_SetBkMode( hdc, iBkMode )
931 else
932 {
933 PLDC pLDC = Dc_Attr->pvLDC;
934 if ( !pLDC )
935 {
936 SetLastError(ERROR_INVALID_HANDLE);
937 return FALSE;
938 }
939 if (pLDC->iType == LDC_EMFLDC)
940 {
941 return EMFDRV_SetBkMode( hdc, iBkMode )
942 }
943 }
944 }
945 #endif
946 OldMode = Dc_Attr->lBkMode;
947 Dc_Attr->jBkMode = iBkMode; // Processed
948 Dc_Attr->lBkMode = iBkMode; // Raw
949 return OldMode;
950 }
951
952 /*
953 * @implemented
954 *
955 */
956 int
957 STDCALL
958 GetPolyFillMode(HDC hdc)
959 {
960 PDC_ATTR Dc_Attr;
961 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
962 return Dc_Attr->lFillMode;
963 }
964
965 /*
966 * @unimplemented
967 */
968 int
969 STDCALL
970 SetPolyFillMode(HDC hdc,
971 int iPolyFillMode)
972 {
973 INT fmode;
974 PDC_ATTR Dc_Attr;
975 #if 0
976 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
977 {
978 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
979 return MFDRV_SetPolyFillMode( hdc, iPolyFillMode )
980 else
981 {
982 PLDC pLDC = GdiGetLDC(hdc);
983 if ( !pLDC )
984 {
985 SetLastError(ERROR_INVALID_HANDLE);
986 return FALSE;
987 }
988 if (pLDC->iType == LDC_EMFLDC)
989 {
990 return EMFDRV_SetPolyFillMode( hdc, iPolyFillMode )
991 }
992 }
993 }
994 #endif
995 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
996
997 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
998 {
999 if (Dc_Attr->ulDirty_ & DC_MODE_DIRTY)
1000 {
1001 NtGdiFlush(); // Sync up Dc_Attr from Kernel space.
1002 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1003 }
1004 }
1005
1006 fmode = Dc_Attr->lFillMode;
1007 Dc_Attr->lFillMode = iPolyFillMode;
1008
1009 return fmode;
1010 }
1011
1012 /*
1013 * @implemented
1014 *
1015 */
1016 int
1017 STDCALL
1018 GetGraphicsMode(HDC hdc)
1019 {
1020 PDC_ATTR Dc_Attr;
1021 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1022 return Dc_Attr->iGraphicsMode;
1023 }
1024
1025 /*
1026 * @unimplemented
1027 */
1028 int
1029 STDCALL
1030 SetGraphicsMode(HDC hdc,
1031 int iMode)
1032 {
1033 INT oMode;
1034 PDC_ATTR Dc_Attr;
1035 if ((iMode < GM_COMPATIBLE) || (iMode > GM_ADVANCED))
1036 {
1037 SetLastError(ERROR_INVALID_PARAMETER);
1038 return 0;
1039 }
1040 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1041
1042 if (iMode == Dc_Attr->iGraphicsMode) return iMode;
1043
1044 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
1045 {
1046 if (Dc_Attr->ulDirty_ & DC_MODE_DIRTY)
1047 {
1048 NtGdiFlush(); // Sync up Dc_Attr from Kernel space.
1049 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1050 }
1051 }
1052 /* One would think that setting the graphics mode to GM_COMPATIBLE
1053 * would also reset the world transformation matrix to the unity
1054 * matrix. However, in Windows, this is not the case. This doesn't
1055 * make a lot of sense to me, but that's the way it is.
1056 */
1057 oMode = Dc_Attr->iGraphicsMode;
1058 Dc_Attr->iGraphicsMode = iMode;
1059
1060 return oMode;
1061 }
1062
1063 /*
1064 * @implemented
1065 */
1066 HDC
1067 STDCALL
1068 ResetDCW(
1069 HDC hdc,
1070 CONST DEVMODEW *lpInitData
1071 )
1072 {
1073 NtGdiResetDC ( hdc, (PDEVMODEW)lpInitData, NULL, NULL, NULL);
1074 return hdc;
1075 }
1076
1077
1078 /*
1079 * @implemented
1080 */
1081 HDC
1082 STDCALL
1083 ResetDCA(
1084 HDC hdc,
1085 CONST DEVMODEA *lpInitData
1086 )
1087 {
1088 LPDEVMODEW InitDataW;
1089
1090 InitDataW = GdiConvertToDevmodeW((LPDEVMODEA)lpInitData);
1091
1092 NtGdiResetDC ( hdc, InitDataW, NULL, NULL, NULL);
1093 HEAP_free(InitDataW);
1094 return hdc;
1095 }
1096
1097
1098 /*
1099 * @implemented
1100 */
1101 int
1102 STDCALL
1103 StartDocW(
1104 HDC hdc,
1105 CONST DOCINFOW *a1
1106 )
1107 {
1108 return NtGdiStartDoc ( hdc, (DOCINFOW *)a1, NULL, 0);
1109 }
1110
1111
1112 /*
1113 * @implemented
1114 */
1115 DWORD
1116 STDCALL
1117 GetObjectType(
1118 HGDIOBJ h
1119 )
1120 {
1121 DWORD Ret = 0;
1122
1123 if(GdiIsHandleValid(h))
1124 {
1125 LONG Type = GDI_HANDLE_GET_TYPE(h);
1126 switch(Type)
1127 {
1128 case GDI_OBJECT_TYPE_PEN:
1129 Ret = OBJ_PEN;
1130 break;
1131 case GDI_OBJECT_TYPE_BRUSH:
1132 Ret = OBJ_BRUSH;
1133 break;
1134 case GDI_OBJECT_TYPE_BITMAP:
1135 Ret = OBJ_BITMAP;
1136 break;
1137 case GDI_OBJECT_TYPE_FONT:
1138 Ret = OBJ_FONT;
1139 break;
1140 case GDI_OBJECT_TYPE_PALETTE:
1141 Ret = OBJ_PAL;
1142 break;
1143 case GDI_OBJECT_TYPE_REGION:
1144 Ret = OBJ_REGION;
1145 break;
1146 case GDI_OBJECT_TYPE_DC:
1147 if ( GetDCDWord( h, GdiGetIsMemDc, 0))
1148 {
1149 Ret = OBJ_MEMDC;
1150 }
1151 else
1152 Ret = OBJ_DC;
1153 break;
1154 case GDI_OBJECT_TYPE_COLORSPACE:
1155 Ret = OBJ_COLORSPACE;
1156 break;
1157 case GDI_OBJECT_TYPE_METAFILE:
1158 Ret = OBJ_METAFILE;
1159 break;
1160 case GDI_OBJECT_TYPE_ENHMETAFILE:
1161 Ret = OBJ_ENHMETAFILE;
1162 break;
1163 case GDI_OBJECT_TYPE_METADC:
1164 Ret = OBJ_METADC;
1165 break;
1166 case GDI_OBJECT_TYPE_EXTPEN:
1167 Ret = OBJ_EXTPEN;
1168 break;
1169
1170 default:
1171 DPRINT1("GetObjectType: Magic 0x%08x not implemented\n", Type);
1172 break;
1173 }
1174 }
1175 else
1176 /* From Wine: GetObjectType does SetLastError() on a null object */
1177 SetLastError(ERROR_INVALID_HANDLE);
1178 return Ret;
1179 }
1180
1181
1182 /*
1183 * @implemented
1184 */
1185 HGDIOBJ
1186 WINAPI
1187 GetStockObject(
1188 INT h
1189 )
1190 {
1191 HGDIOBJ Ret = NULL;
1192 if ((h < 0) || (h >= NB_STOCK_OBJECTS)) return Ret;
1193 Ret = stock_objects[h];
1194 if (!Ret)
1195 {
1196 HGDIOBJ Obj = NtGdiGetStockObject( h );
1197
1198 if (GdiIsHandleValid(Obj))
1199 {
1200 stock_objects[h] = Obj;
1201 return Obj;
1202 }// Returns Null anyway.
1203 }
1204 return Ret;
1205 }
1206
1207 /* FIXME: include correct header */
1208 HPALETTE STDCALL NtUserSelectPalette(HDC hDC,
1209 HPALETTE hpal,
1210 BOOL ForceBackground);
1211
1212 HPALETTE
1213 STDCALL
1214 SelectPalette(
1215 HDC hDC,
1216 HPALETTE hPal,
1217 BOOL bForceBackground)
1218 {
1219 #if 0
1220 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1221 {
1222 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1223 return MFDRV_SelectPalette( hDC, hPal, bForceBackground);
1224 else
1225 {
1226 PLDC pLDC = GdiGetLDC(hDC);
1227 if ( !pLDC )
1228 {
1229 SetLastError(ERROR_INVALID_HANDLE);
1230 return NULL;
1231 }
1232 if (pLDC->iType == LDC_EMFLDC)
1233 {
1234 if return EMFDRV_SelectPalette( hDC, hPal, bForceBackground);
1235 }
1236 }
1237 }
1238 #endif
1239 return NtUserSelectPalette(hDC, hPal, bForceBackground);
1240 }
1241
1242 /*
1243 * @implemented
1244 *
1245 */
1246 int
1247 STDCALL
1248 GetMapMode(HDC hdc)
1249 {
1250 PDC_ATTR Dc_Attr;
1251 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1252 return Dc_Attr->iMapMode;
1253 }
1254
1255 /*
1256 * @implemented
1257 */
1258 INT
1259 STDCALL
1260 SetMapMode(
1261 HDC hdc,
1262 INT Mode
1263 )
1264 {
1265 PDC_ATTR Dc_Attr;
1266 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1267 #if 0
1268 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1269 {
1270 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1271 return MFDRV_SetMapMode(hdc, Mode);
1272 else
1273 {
1274 SetLastError(ERROR_INVALID_HANDLE);
1275 return 0;
1276 }
1277 #endif
1278 // Force change if Isotropic is set for recompute.
1279 if ((Mode != Dc_Attr->iMapMode) || (Mode == MM_ISOTROPIC))
1280 {
1281 Dc_Attr->ulDirty_ &= ~SLOW_WIDTHS;
1282 return GetAndSetDCDWord( hdc, GdiGetSetMapMode, Mode, 0, 0, 0 );
1283 }
1284 return Dc_Attr->iMapMode;
1285 }
1286
1287 /*
1288 * @implemented
1289 *
1290 */
1291 int
1292 STDCALL
1293 GetStretchBltMode(HDC hdc)
1294 {
1295 PDC_ATTR Dc_Attr;
1296 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1297 return Dc_Attr->lStretchBltMode;
1298 }
1299
1300 /*
1301 * @implemented
1302 */
1303 int
1304 STDCALL
1305 SetStretchBltMode(HDC hdc, int iStretchMode)
1306 {
1307 INT oSMode;
1308 PDC_ATTR Dc_Attr;
1309 #if 0
1310 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1311 {
1312 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1313 return MFDRV_SetStretchBltMode( hdc, iStretchMode);
1314 else
1315 {
1316 PLDC pLDC = GdiGetLDC(hdc);
1317 if ( !pLDC )
1318 {
1319 SetLastError(ERROR_INVALID_HANDLE);
1320 return 0;
1321 }
1322 if (pLDC->iType == LDC_EMFLDC)
1323 {
1324 return EMFDRV_SetStretchBltMode( hdc, iStretchMode);
1325 }
1326 }
1327 }
1328 #endif
1329 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1330
1331 oSMode = Dc_Attr->lStretchBltMode;
1332 Dc_Attr->lStretchBltMode = iStretchMode;
1333
1334 // Wine returns an error here. We set the default.
1335 if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
1336
1337 Dc_Attr->jStretchBltMode = iStretchMode;
1338
1339 return oSMode;
1340 }
1341
1342 /*
1343 * @implemented
1344 */
1345 HFONT
1346 STDCALL
1347 GetHFONT(HDC hdc)
1348 {
1349 PDC_ATTR Dc_Attr;
1350 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return NULL;
1351 return Dc_Attr->hlfntNew;
1352 }
1353
1354
1355 /*
1356 * @implemented
1357 *
1358 */
1359 HGDIOBJ
1360 STDCALL
1361 SelectObject(HDC hDC,
1362 HGDIOBJ hGdiObj)
1363 {
1364 PDC_ATTR pDc_Attr;
1365 // HGDIOBJ hOldObj = NULL;
1366 // PTEB pTeb;
1367
1368 if(!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
1369 {
1370 SetLastError(ERROR_INVALID_HANDLE);
1371 return NULL;
1372 }
1373
1374 hGdiObj = GdiFixUpHandle(hGdiObj);
1375 if (!GdiIsHandleValid(hGdiObj))
1376 {
1377 return NULL;
1378 }
1379
1380 UINT uType = GDI_HANDLE_GET_TYPE(hGdiObj);
1381
1382 switch (uType)
1383 {
1384 case GDI_OBJECT_TYPE_REGION:
1385 return (HGDIOBJ)ExtSelectClipRgn(hDC, hGdiObj, RGN_COPY);
1386
1387 case GDI_OBJECT_TYPE_BITMAP:
1388 return NtGdiSelectBitmap(hDC, hGdiObj);
1389
1390 case GDI_OBJECT_TYPE_BRUSH:
1391 #if 0 // enable this when support is ready in win32k
1392 hOldObj = pDc_Attr->hbrush;
1393 pDc_Attr->ulDirty_ |= DC_BRUSH_DIRTY;
1394 pDc_Attr->hbrush = hGdiObj;
1395 return hOldObj;
1396 #endif
1397 return NtGdiSelectBrush(hDC, hGdiObj);
1398
1399 case GDI_OBJECT_TYPE_PEN:
1400 case GDI_OBJECT_TYPE_EXTPEN:
1401 #if 0 // enable this when support is ready in win32k
1402 hOldObj = pDc_Attr->hpen;
1403 pDc_Attr->ulDirty_ |= DC_PEN_DIRTY;
1404 pDc_Attr->hpen = hGdiObj;
1405 return hOldObj;
1406 #endif
1407 return NtGdiSelectPen(hDC, hGdiObj);
1408
1409 case GDI_OBJECT_TYPE_FONT:
1410 #if 0
1411 pTeb = NtCurrentTeb();
1412 if (((pTeb->GdiTebBatch.HDC == 0) ||
1413 (pTeb->GdiTebBatch.HDC == (ULONG)hDC)) &&
1414 ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSOBJECT)) <= GDIBATCHBUFSIZE) &&
1415 (!(pDc_Attr->ulDirty_ & DC_DIBSECTION)))
1416 {
1417 PGDIBSOBJECT pgO = (PGDIBSOBJECT)(&pTeb->GdiTebBatch.Buffer[0] +
1418 pTeb->GdiTebBatch.Offset);
1419 pgO->gbHdr.Cmd = GdiBCSelObj;
1420 pgO->gbHdr.Size = sizeof(GDIBSOBJECT);
1421 pgO->hgdiobj = hGdiObj;
1422
1423 pTeb->GdiTebBatch.Offset += sizeof(GDIBSOBJECT);
1424 pTeb->GdiTebBatch.HDC = (ULONG)hDC;
1425 pTeb->GdiBatchCount++;
1426 if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
1427 return pDc_Attr->hlfntNew;
1428 }
1429 #endif
1430 // default for select object font
1431 return NtGdiSelectFont(hDC, hGdiObj);
1432 #if 0
1433 case GDI_OBJECT_TYPE_METADC:
1434 return MFDRV_SelectObject( hDC, hGdiObj);
1435 case GDI_OBJECT_TYPE_EMF:
1436 PLDC pLDC = GdiGetLDC(hDC);
1437 if ( !pLDC ) return NULL;
1438 return EMFDRV_SelectObject( hDC, hGdiObj);
1439 #endif
1440 case GDI_OBJECT_TYPE_COLORSPACE:
1441 SetColorSpace(hDC, (HCOLORSPACE) hGdiObj);
1442 return NULL;
1443
1444 case GDI_OBJECT_TYPE_PALETTE:
1445 default:
1446 SetLastError(ERROR_INVALID_FUNCTION);
1447 return NULL;
1448 }
1449
1450 return NULL;
1451 }