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