Merge from amd64-branch:
[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 WINAPI
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 WINAPI
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 WINAPI
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 WINAPI
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 WINAPI
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 WINAPI
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 WINAPI
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 WINAPI
376 GetArcDirection( HDC hdc )
377 {
378 return GetDCDWord( hdc, GdiGetArcDirection, 0);
379 }
380
381
382 INT
383 WINAPI
384 SetArcDirection( HDC hdc, INT nDirection )
385 {
386 return GetAndSetDCDWord( hdc, GdiGetSetArcDirection, nDirection, 0, 0, 0 );
387 }
388
389
390 HGDIOBJ
391 WINAPI
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 WINAPI
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 * @implemented
470 *
471 */
472 int
473 WINAPI
474 GetDeviceCaps(HDC hDC,
475 int i)
476 {
477 PDC_ATTR Dc_Attr;
478 PLDC pLDC;
479 PDEVCAPS pDevCaps = GdiDevCaps; // Primary display device capabilities.
480 DPRINT("Device CAPS1\n");
481
482 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
483 {
484 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
485 {
486 if ( i == TECHNOLOGY) return DT_METAFILE;
487 return 0;
488 }
489 else
490 {
491 pLDC = GdiGetLDC(hDC);
492 if ( !pLDC )
493 {
494 SetLastError(ERROR_INVALID_HANDLE);
495 return 0;
496 }
497 if (!(pLDC->Flags & LDC_DEVCAPS))
498 {
499 if (!NtGdiGetDeviceCapsAll(hDC, &pLDC->DevCaps))
500 SetLastError(ERROR_INVALID_PARAMETER);
501 pLDC->Flags |= LDC_DEVCAPS;
502 }
503 pDevCaps = &pLDC->DevCaps;
504 }
505 }
506 else
507 {
508 if (!GdiGetHandleUserData((HGDIOBJ) hDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr))
509 return 0;
510 if (!(Dc_Attr->ulDirty_ & DC_PRIMARY_DISPLAY) )
511 return NtGdiGetDeviceCaps(hDC,i);
512 }
513 DPRINT("Device CAPS2\n");
514
515 switch (i)
516 {
517 case DRIVERVERSION:
518 return pDevCaps->ulVersion;
519
520 case TECHNOLOGY:
521 return pDevCaps->ulTechnology;
522
523 case HORZSIZE:
524 return pDevCaps->ulHorzSize;
525
526 case VERTSIZE:
527 return pDevCaps->ulVertSize;
528
529 case HORZRES:
530 return pDevCaps->ulHorzRes;
531
532 case VERTRES:
533 return pDevCaps->ulVertRes;
534
535 case LOGPIXELSX:
536 return pDevCaps->ulLogPixelsX;
537
538 case LOGPIXELSY:
539 return pDevCaps->ulLogPixelsY;
540
541 case BITSPIXEL:
542 return pDevCaps->ulBitsPixel;
543
544 case PLANES:
545 return pDevCaps->ulPlanes;
546
547 case NUMBRUSHES:
548 return -1;
549
550 case NUMPENS:
551 return pDevCaps->ulNumPens;
552
553 case NUMFONTS:
554 return pDevCaps->ulNumFonts;
555
556 case NUMCOLORS:
557 return pDevCaps->ulNumColors;
558
559 case ASPECTX:
560 return pDevCaps->ulAspectX;
561
562 case ASPECTY:
563 return pDevCaps->ulAspectY;
564
565 case ASPECTXY:
566 return pDevCaps->ulAspectXY;
567
568 case CLIPCAPS:
569 return CP_RECTANGLE;
570
571 case SIZEPALETTE:
572 return pDevCaps->ulSizePalette;
573
574 case NUMRESERVED:
575 return 20;
576
577 case COLORRES:
578 return pDevCaps->ulColorRes;
579
580 case DESKTOPVERTRES:
581 return pDevCaps->ulVertRes;
582
583 case DESKTOPHORZRES:
584 return pDevCaps->ulHorzRes;
585
586 case BLTALIGNMENT:
587 return pDevCaps->ulBltAlignment;
588
589 case SHADEBLENDCAPS:
590 return pDevCaps->ulShadeBlend;
591
592 case COLORMGMTCAPS:
593 return pDevCaps->ulColorMgmtCaps;
594
595 case PHYSICALWIDTH:
596 return pDevCaps->ulPhysicalWidth;
597
598 case PHYSICALHEIGHT:
599 return pDevCaps->ulPhysicalHeight;
600
601 case PHYSICALOFFSETX:
602 return pDevCaps->ulPhysicalOffsetX;
603
604 case PHYSICALOFFSETY:
605 return pDevCaps->ulPhysicalOffsetY;
606
607 case VREFRESH:
608 return pDevCaps->ulVRefresh;
609
610 case RASTERCAPS:
611 return pDevCaps->ulRasterCaps;
612
613 case CURVECAPS:
614 return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
615 CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
616
617 case LINECAPS:
618 return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
619 LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
620
621 case POLYGONALCAPS:
622 return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
623 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
624
625 case TEXTCAPS:
626 return pDevCaps->ulTextCaps;
627
628 case PDEVICESIZE:
629 case SCALINGFACTORX:
630 case SCALINGFACTORY:
631 default:
632 return 0;
633 }
634 return 0;
635 }
636
637 /*
638 * @implemented
639 */
640 DWORD
641 WINAPI
642 GetRelAbs(
643 HDC hdc,
644 DWORD dwIgnore
645 )
646 {
647 return GetDCDWord( hdc, GdiGetRelAbs, 0);
648 }
649
650
651 /*
652 * @implemented
653 */
654 DWORD
655 WINAPI
656 SetRelAbs(
657 HDC hdc,
658 INT Mode
659 )
660 {
661 return GetAndSetDCDWord( hdc, GdiGetSetRelAbs, Mode, 0, 0, 0 );
662 }
663
664
665 /*
666 * @implemented
667 */
668 DWORD
669 WINAPI
670 GetAndSetDCDWord( HDC hDC, INT u, DWORD dwIn, DWORD Unk1, DWORD Unk2, DWORD Unk3 )
671 {
672 BOOL Ret = TRUE;
673 // Handle something other than a normal dc object.
674 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
675 {
676 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
677 return 0; //call MFDRV
678 else
679 {
680 PLDC pLDC = GdiGetLDC(hDC);
681 if ( !pLDC )
682 {
683 SetLastError(ERROR_INVALID_HANDLE);
684 return 0;
685 }
686 if (pLDC->iType == LDC_EMFLDC)
687 {
688 Ret = TRUE; //call EMFDRV
689 if (Ret)
690 return u;
691 return 0;
692 }
693 }
694 }
695 Ret = NtGdiGetAndSetDCDword( hDC, u, dwIn, (DWORD*) &u );
696 if (Ret)
697 return u;
698 else
699 SetLastError(ERROR_INVALID_HANDLE);
700 return 0;
701 }
702
703
704 /*
705 * @implemented
706 */
707 DWORD
708 WINAPI
709 GetDCDWord( HDC hDC, INT u, DWORD Result )
710 {
711 BOOL Ret = NtGdiGetDCDword( hDC, u, (DWORD*) &u );
712 if (!Ret) return Result;
713 else return u;
714 }
715
716
717 /*
718 * @implemented
719 */
720 BOOL
721 WINAPI
722 GetAspectRatioFilterEx(
723 HDC hdc,
724 LPSIZE lpAspectRatio
725 )
726 {
727 return NtGdiGetDCPoint( hdc, GdiGetAspectRatioFilter, (LPPOINT) lpAspectRatio );
728 }
729
730
731 /*
732 * @implemented
733 */
734 BOOL
735 WINAPI
736 GetDCOrgEx(
737 HDC hdc,
738 LPPOINT lpPoint
739 )
740 {
741 return NtGdiGetDCPoint( hdc, GdiGetDCOrg, lpPoint );
742 }
743
744
745 /*
746 * @implemented
747 */
748 LONG
749 WINAPI
750 GetDCOrg(
751 HDC hdc
752 )
753 {
754 // Officially obsolete by Microsoft
755 POINT Pt;
756 if (!GetDCOrgEx(hdc, &Pt))
757 return 0;
758 return(MAKELONG(Pt.x, Pt.y));
759 }
760
761
762 int
763 GetNonFontObject(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
764 {
765 INT dwType;
766
767 hGdiObj = (HANDLE)GdiFixUpHandle(hGdiObj);
768 dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
769
770 if (!lpBuffer) // Should pass it all to Win32k and let god sort it out. ;^)
771 {
772 switch(dwType)
773 {
774 case GDI_OBJECT_TYPE_PEN:
775 return sizeof(LOGPEN);
776 case GDI_OBJECT_TYPE_BRUSH:
777 return sizeof(LOGBRUSH);
778 case GDI_OBJECT_TYPE_BITMAP:
779 return sizeof(BITMAP);
780 case GDI_OBJECT_TYPE_PALETTE:
781 return sizeof(WORD);
782 case GDI_OBJECT_TYPE_EXTPEN: /* we don't know the size, ask win32k */
783 break;
784 }
785 }
786
787 switch(dwType)
788 {
789 case GDI_OBJECT_TYPE_PEN: //Check the structures and see if A & W are the same.
790 case GDI_OBJECT_TYPE_EXTPEN:
791 case GDI_OBJECT_TYPE_BRUSH: // Mixing Apples and Oranges?
792 case GDI_OBJECT_TYPE_BITMAP:
793 case GDI_OBJECT_TYPE_PALETTE:
794 return NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
795
796 case GDI_OBJECT_TYPE_DC:
797 case GDI_OBJECT_TYPE_REGION:
798 case GDI_OBJECT_TYPE_METAFILE:
799 case GDI_OBJECT_TYPE_ENHMETAFILE:
800 case GDI_OBJECT_TYPE_EMF:
801 SetLastError(ERROR_INVALID_HANDLE);
802 }
803 return 0;
804 }
805
806
807 /*
808 * @implemented
809 */
810 int
811 WINAPI
812 GetObjectA(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
813 {
814 ENUMLOGFONTEXDVW LogFont;
815 DWORD dwType;
816 INT Result = 0;
817
818 dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
819
820 if(dwType == GDI_OBJECT_TYPE_COLORSPACE) //Stays here, processes struct A
821 {
822 SetLastError(ERROR_NOT_SUPPORTED);
823 return 0;
824 }
825
826 if (dwType == GDI_OBJECT_TYPE_FONT)
827 {
828 if (!lpBuffer)
829 {
830 return sizeof(LOGFONTA);
831 }
832 if (cbSize == 0)
833 {
834 /* Windows does not SetLastError() */
835 return 0;
836 }
837 // ENUMLOGFONTEXDVW is the default size and should be the structure for
838 // Entry->KernelData for Font objects.
839 Result = NtGdiExtGetObjectW(hGdiObj, sizeof(ENUMLOGFONTEXDVW), &LogFont);
840
841 if (0 == Result)
842 {
843 return 0;
844 }
845
846 switch (cbSize)
847 {
848 case sizeof(ENUMLOGFONTEXDVA):
849 // need to move more here.
850 case sizeof(ENUMLOGFONTEXA):
851 EnumLogFontExW2A( (LPENUMLOGFONTEXA) lpBuffer, &LogFont.elfEnumLogfontEx );
852 break;
853
854 case sizeof(ENUMLOGFONTA):
855 // Same here, maybe? Check the structures.
856 case sizeof(EXTLOGFONTA):
857 // Same here
858 case sizeof(LOGFONTA):
859 LogFontW2A((LPLOGFONTA) lpBuffer, &LogFont.elfEnumLogfontEx.elfLogFont);
860 break;
861
862 default:
863 SetLastError(ERROR_BUFFER_OVERFLOW);
864 return 0;
865 }
866 return cbSize;
867 }
868
869 return GetNonFontObject(hGdiObj, cbSize, lpBuffer);
870 }
871
872
873 /*
874 * @implemented
875 */
876 int
877 WINAPI
878 GetObjectW(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
879 {
880 DWORD dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
881 INT Result = 0;
882
883 /*
884 Check List:
885 MSDN, "This can be a handle to one of the following: logical bitmap, a brush,
886 a font, a palette, a pen, or a device independent bitmap created by calling
887 the CreateDIBSection function."
888 */
889 if(dwType == GDI_OBJECT_TYPE_COLORSPACE) //Stays here, processes struct W
890 {
891 SetLastError(ERROR_NOT_SUPPORTED); // Not supported yet.
892 return 0;
893 }
894
895 if (dwType == GDI_OBJECT_TYPE_FONT)
896 {
897 if (!lpBuffer)
898 {
899 return sizeof(LOGFONTW);
900 }
901
902 if (cbSize == 0)
903 {
904 /* Windows does not SetLastError() */
905 return 0;
906 }
907 // Poorly written apps are not ReactOS problem!
908 // We fix it here if the size is larger than the default size.
909 if( cbSize > (int)sizeof(ENUMLOGFONTEXDVW) ) cbSize = sizeof(ENUMLOGFONTEXDVW);
910
911 Result = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer); // Should handle the copy.
912
913 if (0 == Result)
914 {
915 return 0;
916 }
917 return cbSize;
918 }
919
920 return GetNonFontObject(hGdiObj, cbSize, lpBuffer);
921 }
922
923
924 /*
925 * @implemented
926 */
927 COLORREF
928 WINAPI
929 GetDCBrushColor(
930 HDC hdc
931 )
932 {
933 PDC_ATTR Dc_Attr;
934
935 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return CLR_INVALID;
936 return (COLORREF) Dc_Attr->ulBrushClr;
937 }
938
939 /*
940 * @implemented
941 */
942 COLORREF
943 WINAPI
944 GetDCPenColor(
945 HDC hdc
946 )
947 {
948 PDC_ATTR Dc_Attr;
949
950 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return CLR_INVALID;
951 return (COLORREF) Dc_Attr->ulPenClr;
952 }
953
954 /*
955 * @implemented
956 */
957 COLORREF
958 WINAPI
959 SetDCBrushColor(
960 HDC hdc,
961 COLORREF crColor
962 )
963 {
964 PDC_ATTR Dc_Attr;
965 COLORREF OldColor = CLR_INVALID;
966
967 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldColor;
968 else
969 {
970 OldColor = (COLORREF) Dc_Attr->ulBrushClr;
971 Dc_Attr->ulBrushClr = (ULONG) crColor;
972
973 if ( Dc_Attr->crBrushClr != crColor ) // if same, don't force a copy.
974 {
975 Dc_Attr->ulDirty_ |= DIRTY_FILL;
976 Dc_Attr->crBrushClr = crColor;
977 }
978 }
979 return OldColor;
980 }
981
982 /*
983 * @implemented
984 */
985 COLORREF
986 WINAPI
987 SetDCPenColor(
988 HDC hdc,
989 COLORREF crColor
990 )
991 {
992 PDC_ATTR Dc_Attr;
993 COLORREF OldColor = CLR_INVALID;
994
995 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldColor;
996 else
997 {
998 OldColor = (COLORREF) Dc_Attr->ulPenClr;
999 Dc_Attr->ulPenClr = (ULONG) crColor;
1000
1001 if ( Dc_Attr->crPenClr != crColor )
1002 {
1003 Dc_Attr->ulDirty_ |= DIRTY_LINE;
1004 Dc_Attr->crPenClr = crColor;
1005 }
1006 }
1007 return OldColor;
1008 }
1009
1010 /*
1011 * @implemented
1012 *
1013 */
1014 COLORREF
1015 WINAPI
1016 GetBkColor(HDC hdc)
1017 {
1018 PDC_ATTR Dc_Attr;
1019 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1020 return Dc_Attr->ulBackgroundClr;
1021 }
1022
1023 /*
1024 * @implemented
1025 */
1026 COLORREF
1027 WINAPI
1028 SetBkColor(
1029 HDC hdc,
1030 COLORREF crColor
1031 )
1032 {
1033 PDC_ATTR Dc_Attr;
1034 COLORREF OldColor = CLR_INVALID;
1035
1036 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldColor;
1037 #if 0
1038 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1039 {
1040 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1041 return MFDRV_SetBkColor( hDC, crColor );
1042 else
1043 {
1044 PLDC pLDC = Dc_Attr->pvLDC;
1045 if ( !pLDC )
1046 {
1047 SetLastError(ERROR_INVALID_HANDLE);
1048 return FALSE;
1049 }
1050 if (pLDC->iType == LDC_EMFLDC)
1051 {
1052 return EMFDRV_SetBkColor( hDC, crColor );
1053 }
1054 }
1055 }
1056 #endif
1057 OldColor = (COLORREF) Dc_Attr->ulBackgroundClr;
1058 Dc_Attr->ulBackgroundClr = (ULONG) crColor;
1059
1060 if ( Dc_Attr->crBackgroundClr != crColor )
1061 {
1062 Dc_Attr->ulDirty_ |= (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL);
1063 Dc_Attr->crBackgroundClr = crColor;
1064 }
1065 return OldColor;
1066 }
1067
1068 /*
1069 * @implemented
1070 *
1071 */
1072 int
1073 WINAPI
1074 GetBkMode(HDC hdc)
1075 {
1076 PDC_ATTR Dc_Attr;
1077 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1078 return Dc_Attr->lBkMode;
1079 }
1080
1081 /*
1082 * @implemented
1083 *
1084 */
1085 int
1086 WINAPI
1087 SetBkMode(HDC hdc,
1088 int iBkMode)
1089 {
1090 PDC_ATTR Dc_Attr;
1091 INT OldMode = 0;
1092
1093 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldMode;
1094 #if 0
1095 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1096 {
1097 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1098 return MFDRV_SetBkMode( hdc, iBkMode )
1099 else
1100 {
1101 PLDC pLDC = Dc_Attr->pvLDC;
1102 if ( !pLDC )
1103 {
1104 SetLastError(ERROR_INVALID_HANDLE);
1105 return FALSE;
1106 }
1107 if (pLDC->iType == LDC_EMFLDC)
1108 {
1109 return EMFDRV_SetBkMode( hdc, iBkMode )
1110 }
1111 }
1112 }
1113 #endif
1114 OldMode = Dc_Attr->lBkMode;
1115 Dc_Attr->jBkMode = iBkMode; // Processed
1116 Dc_Attr->lBkMode = iBkMode; // Raw
1117 return OldMode;
1118 }
1119
1120 /*
1121 * @implemented
1122 *
1123 */
1124 int
1125 WINAPI
1126 GetPolyFillMode(HDC hdc)
1127 {
1128 PDC_ATTR Dc_Attr;
1129 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1130 return Dc_Attr->lFillMode;
1131 }
1132
1133 /*
1134 * @unimplemented
1135 */
1136 int
1137 WINAPI
1138 SetPolyFillMode(HDC hdc,
1139 int iPolyFillMode)
1140 {
1141 INT fmode;
1142 PDC_ATTR Dc_Attr;
1143 #if 0
1144 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1145 {
1146 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1147 return MFDRV_SetPolyFillMode( hdc, iPolyFillMode )
1148 else
1149 {
1150 PLDC pLDC = GdiGetLDC(hdc);
1151 if ( !pLDC )
1152 {
1153 SetLastError(ERROR_INVALID_HANDLE);
1154 return FALSE;
1155 }
1156 if (pLDC->iType == LDC_EMFLDC)
1157 {
1158 return EMFDRV_SetPolyFillMode( hdc, iPolyFillMode )
1159 }
1160 }
1161 }
1162 #endif
1163 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1164
1165 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
1166 {
1167 if (Dc_Attr->ulDirty_ & DC_MODE_DIRTY)
1168 {
1169 NtGdiFlush(); // Sync up Dc_Attr from Kernel space.
1170 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1171 }
1172 }
1173
1174 fmode = Dc_Attr->lFillMode;
1175 Dc_Attr->lFillMode = iPolyFillMode;
1176
1177 return fmode;
1178 }
1179
1180 /*
1181 * @implemented
1182 *
1183 */
1184 int
1185 WINAPI
1186 GetGraphicsMode(HDC hdc)
1187 {
1188 PDC_ATTR Dc_Attr;
1189 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1190 return Dc_Attr->iGraphicsMode;
1191 }
1192
1193 /*
1194 * @unimplemented
1195 */
1196 int
1197 WINAPI
1198 SetGraphicsMode(HDC hdc,
1199 int iMode)
1200 {
1201 INT oMode;
1202 PDC_ATTR Dc_Attr;
1203 if ((iMode < GM_COMPATIBLE) || (iMode > GM_ADVANCED))
1204 {
1205 SetLastError(ERROR_INVALID_PARAMETER);
1206 return 0;
1207 }
1208 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1209
1210 if (iMode == Dc_Attr->iGraphicsMode) return iMode;
1211
1212 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
1213 {
1214 if (Dc_Attr->ulDirty_ & DC_MODE_DIRTY)
1215 {
1216 NtGdiFlush(); // Sync up Dc_Attr from Kernel space.
1217 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1218 }
1219 }
1220 /* One would think that setting the graphics mode to GM_COMPATIBLE
1221 * would also reset the world transformation matrix to the unity
1222 * matrix. However, in Windows, this is not the case. This doesn't
1223 * make a lot of sense to me, but that's the way it is.
1224 */
1225 oMode = Dc_Attr->iGraphicsMode;
1226 Dc_Attr->iGraphicsMode = iMode;
1227
1228 return oMode;
1229 }
1230
1231 /*
1232 * @implemented
1233 */
1234 HDC
1235 WINAPI
1236 ResetDCW(
1237 HDC hdc,
1238 CONST DEVMODEW *lpInitData
1239 )
1240 {
1241 NtGdiResetDC ( hdc, (PDEVMODEW)lpInitData, NULL, NULL, NULL);
1242 return hdc;
1243 }
1244
1245
1246 /*
1247 * @implemented
1248 */
1249 HDC
1250 WINAPI
1251 ResetDCA(
1252 HDC hdc,
1253 CONST DEVMODEA *lpInitData
1254 )
1255 {
1256 LPDEVMODEW InitDataW;
1257
1258 InitDataW = GdiConvertToDevmodeW((LPDEVMODEA)lpInitData);
1259
1260 NtGdiResetDC ( hdc, InitDataW, NULL, NULL, NULL);
1261 HEAP_free(InitDataW);
1262 return hdc;
1263 }
1264
1265
1266 /*
1267 * @implemented
1268 */
1269 int
1270 WINAPI
1271 StartDocW(
1272 HDC hdc,
1273 CONST DOCINFOW *a1
1274 )
1275 {
1276 return NtGdiStartDoc ( hdc, (DOCINFOW *)a1, NULL, 0);
1277 }
1278
1279
1280 /*
1281 * @implemented
1282 */
1283 DWORD
1284 WINAPI
1285 GetObjectType(
1286 HGDIOBJ h
1287 )
1288 {
1289 DWORD Ret = 0;
1290
1291 if(GdiIsHandleValid(h))
1292 {
1293 LONG Type = GDI_HANDLE_GET_TYPE(h);
1294 switch(Type)
1295 {
1296 case GDI_OBJECT_TYPE_PEN:
1297 Ret = OBJ_PEN;
1298 break;
1299 case GDI_OBJECT_TYPE_BRUSH:
1300 Ret = OBJ_BRUSH;
1301 break;
1302 case GDI_OBJECT_TYPE_BITMAP:
1303 Ret = OBJ_BITMAP;
1304 break;
1305 case GDI_OBJECT_TYPE_FONT:
1306 Ret = OBJ_FONT;
1307 break;
1308 case GDI_OBJECT_TYPE_PALETTE:
1309 Ret = OBJ_PAL;
1310 break;
1311 case GDI_OBJECT_TYPE_REGION:
1312 Ret = OBJ_REGION;
1313 break;
1314 case GDI_OBJECT_TYPE_DC:
1315 if ( GetDCDWord( h, GdiGetIsMemDc, 0))
1316 {
1317 Ret = OBJ_MEMDC;
1318 }
1319 else
1320 Ret = OBJ_DC;
1321 break;
1322 case GDI_OBJECT_TYPE_COLORSPACE:
1323 Ret = OBJ_COLORSPACE;
1324 break;
1325 case GDI_OBJECT_TYPE_METAFILE:
1326 Ret = OBJ_METAFILE;
1327 break;
1328 case GDI_OBJECT_TYPE_ENHMETAFILE:
1329 Ret = OBJ_ENHMETAFILE;
1330 break;
1331 case GDI_OBJECT_TYPE_METADC:
1332 Ret = OBJ_METADC;
1333 break;
1334 case GDI_OBJECT_TYPE_EXTPEN:
1335 Ret = OBJ_EXTPEN;
1336 break;
1337
1338 default:
1339 DPRINT1("GetObjectType: Magic 0x%08x not implemented\n", Type);
1340 break;
1341 }
1342 }
1343 else
1344 /* From Wine: GetObjectType does SetLastError() on a null object */
1345 SetLastError(ERROR_INVALID_HANDLE);
1346 return Ret;
1347 }
1348
1349
1350 /*
1351 * @implemented
1352 */
1353 HGDIOBJ
1354 WINAPI
1355 GetStockObject(
1356 INT h
1357 )
1358 {
1359 HGDIOBJ Ret = NULL;
1360 if ((h < 0) || (h >= NB_STOCK_OBJECTS)) return Ret;
1361 Ret = stock_objects[h];
1362 if (!Ret)
1363 {
1364 HGDIOBJ Obj = NtGdiGetStockObject( h );
1365
1366 if (GdiIsHandleValid(Obj))
1367 {
1368 stock_objects[h] = Obj;
1369 return Obj;
1370 }// Returns Null anyway.
1371 }
1372 return Ret;
1373 }
1374
1375 /* FIXME: include correct header */
1376 HPALETTE WINAPI NtUserSelectPalette(HDC hDC,
1377 HPALETTE hpal,
1378 BOOL ForceBackground);
1379
1380 HPALETTE
1381 WINAPI
1382 SelectPalette(
1383 HDC hDC,
1384 HPALETTE hPal,
1385 BOOL bForceBackground)
1386 {
1387 #if 0
1388 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1389 {
1390 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1391 return MFDRV_SelectPalette( hDC, hPal, bForceBackground);
1392 else
1393 {
1394 PLDC pLDC = GdiGetLDC(hDC);
1395 if ( !pLDC )
1396 {
1397 SetLastError(ERROR_INVALID_HANDLE);
1398 return NULL;
1399 }
1400 if (pLDC->iType == LDC_EMFLDC)
1401 {
1402 if return EMFDRV_SelectPalette( hDC, hPal, bForceBackground);
1403 }
1404 }
1405 }
1406 #endif
1407 return NtUserSelectPalette(hDC, hPal, bForceBackground);
1408 }
1409
1410 /*
1411 * @implemented
1412 *
1413 */
1414 int
1415 WINAPI
1416 GetMapMode(HDC hdc)
1417 {
1418 PDC_ATTR Dc_Attr;
1419 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1420 return Dc_Attr->iMapMode;
1421 }
1422
1423 /*
1424 * @implemented
1425 */
1426 INT
1427 WINAPI
1428 SetMapMode(
1429 HDC hdc,
1430 INT Mode
1431 )
1432 {
1433 PDC_ATTR Dc_Attr;
1434 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1435 #if 0
1436 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1437 {
1438 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1439 return MFDRV_SetMapMode(hdc, Mode);
1440 else
1441 {
1442 SetLastError(ERROR_INVALID_HANDLE);
1443 return 0;
1444 }
1445 #endif
1446 // Force change if Isotropic is set for recompute.
1447 if ((Mode != Dc_Attr->iMapMode) || (Mode == MM_ISOTROPIC))
1448 {
1449 Dc_Attr->ulDirty_ &= ~SLOW_WIDTHS;
1450 return GetAndSetDCDWord( hdc, GdiGetSetMapMode, Mode, 0, 0, 0 );
1451 }
1452 return Dc_Attr->iMapMode;
1453 }
1454
1455 /*
1456 * @implemented
1457 *
1458 */
1459 int
1460 WINAPI
1461 GetStretchBltMode(HDC hdc)
1462 {
1463 PDC_ATTR Dc_Attr;
1464 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1465 return Dc_Attr->lStretchBltMode;
1466 }
1467
1468 /*
1469 * @implemented
1470 */
1471 int
1472 WINAPI
1473 SetStretchBltMode(HDC hdc, int iStretchMode)
1474 {
1475 INT oSMode;
1476 PDC_ATTR Dc_Attr;
1477 #if 0
1478 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1479 {
1480 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1481 return MFDRV_SetStretchBltMode( hdc, iStretchMode);
1482 else
1483 {
1484 PLDC pLDC = GdiGetLDC(hdc);
1485 if ( !pLDC )
1486 {
1487 SetLastError(ERROR_INVALID_HANDLE);
1488 return 0;
1489 }
1490 if (pLDC->iType == LDC_EMFLDC)
1491 {
1492 return EMFDRV_SetStretchBltMode( hdc, iStretchMode);
1493 }
1494 }
1495 }
1496 #endif
1497 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1498
1499 oSMode = Dc_Attr->lStretchBltMode;
1500 Dc_Attr->lStretchBltMode = iStretchMode;
1501
1502 // Wine returns an error here. We set the default.
1503 if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
1504
1505 Dc_Attr->jStretchBltMode = iStretchMode;
1506
1507 return oSMode;
1508 }
1509
1510 /*
1511 * @implemented
1512 */
1513 HFONT
1514 WINAPI
1515 GetHFONT(HDC hdc)
1516 {
1517 PDC_ATTR Dc_Attr;
1518 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return NULL;
1519 return Dc_Attr->hlfntNew;
1520 }
1521
1522
1523 /*
1524 * @implemented
1525 *
1526 */
1527 HGDIOBJ
1528 WINAPI
1529 SelectObject(HDC hDC,
1530 HGDIOBJ hGdiObj)
1531 {
1532 PDC_ATTR pDc_Attr;
1533 HGDIOBJ hOldObj = NULL;
1534 // PTEB pTeb;
1535
1536 if(!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
1537 {
1538 SetLastError(ERROR_INVALID_HANDLE);
1539 return NULL;
1540 }
1541
1542 hGdiObj = GdiFixUpHandle(hGdiObj);
1543 if (!GdiIsHandleValid(hGdiObj))
1544 {
1545 return NULL;
1546 }
1547
1548 UINT uType = GDI_HANDLE_GET_TYPE(hGdiObj);
1549
1550 switch (uType)
1551 {
1552 case GDI_OBJECT_TYPE_REGION:
1553 return (HGDIOBJ)ExtSelectClipRgn(hDC, hGdiObj, RGN_COPY);
1554
1555 case GDI_OBJECT_TYPE_BITMAP:
1556 return NtGdiSelectBitmap(hDC, hGdiObj);
1557
1558 case GDI_OBJECT_TYPE_BRUSH:
1559 hOldObj = pDc_Attr->hbrush;
1560 pDc_Attr->ulDirty_ |= DC_BRUSH_DIRTY;
1561 pDc_Attr->hbrush = hGdiObj;
1562 return hOldObj;
1563 // return NtGdiSelectBrush(hDC, hGdiObj);
1564
1565 case GDI_OBJECT_TYPE_PEN:
1566 case GDI_OBJECT_TYPE_EXTPEN:
1567 hOldObj = pDc_Attr->hpen;
1568 pDc_Attr->ulDirty_ |= DC_PEN_DIRTY;
1569 pDc_Attr->hpen = hGdiObj;
1570 return hOldObj;
1571 // return NtGdiSelectPen(hDC, hGdiObj);
1572
1573 case GDI_OBJECT_TYPE_FONT:
1574 hOldObj = pDc_Attr->hlfntNew;
1575 if (hOldObj == hGdiObj) return hOldObj;
1576 #if 0
1577 pDc_Attr->ulDirty_ &= ~SLOW_WIDTHS;
1578 pDc_Attr->ulDirty_ |= DIRTY_CHARSET;
1579 pDc_Attr->hlfntNew = hGdiObj;
1580 pTeb = NtCurrentTeb();
1581 if (((pTeb->GdiTebBatch.HDC == 0) ||
1582 (pTeb->GdiTebBatch.HDC == hDC)) &&
1583 ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSOBJECT)) <= GDIBATCHBUFSIZE) &&
1584 (!(pDc_Attr->ulDirty_ & DC_DIBSECTION)))
1585 {
1586 PGDIBSOBJECT pgO = (PGDIBSOBJECT)(&pTeb->GdiTebBatch.Buffer[0] +
1587 pTeb->GdiTebBatch.Offset);
1588 pgO->gbHdr.Cmd = GdiBCSelObj;
1589 pgO->gbHdr.Size = sizeof(GDIBSOBJECT);
1590 pgO->hgdiobj = hGdiObj;
1591
1592 pTeb->GdiTebBatch.Offset += sizeof(GDIBSOBJECT);
1593 pTeb->GdiTebBatch.HDC = hDC;
1594 pTeb->GdiBatchCount++;
1595 if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
1596 return hOldObj;
1597 }
1598 #endif
1599 // default for select object font
1600 return NtGdiSelectFont(hDC, hGdiObj);
1601
1602 #if 0
1603 case GDI_OBJECT_TYPE_METADC:
1604 return MFDRV_SelectObject( hDC, hGdiObj);
1605 case GDI_OBJECT_TYPE_EMF:
1606 PLDC pLDC = GdiGetLDC(hDC);
1607 if ( !pLDC ) return NULL;
1608 return EMFDRV_SelectObject( hDC, hGdiObj);
1609 #endif
1610 case GDI_OBJECT_TYPE_COLORSPACE:
1611 SetColorSpace(hDC, (HCOLORSPACE) hGdiObj);
1612 return NULL;
1613
1614 case GDI_OBJECT_TYPE_PALETTE:
1615 default:
1616 SetLastError(ERROR_INVALID_FUNCTION);
1617 return NULL;
1618 }
1619
1620 return NULL;
1621 }