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