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