[GDI32/WIN32K]
[reactos.git] / reactos / win32ss / gdi / 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 }
142 else
143 DriverU.Buffer = NULL;
144 if (NULL != lpszDevice)
145 {
146 RtlInitAnsiString(&DeviceA, (LPSTR)lpszDevice);
147 RtlAnsiStringToUnicodeString(&DeviceU, &DeviceA, TRUE);
148 }
149 else
150 DeviceU.Buffer = NULL;
151 if (NULL != lpszOutput)
152 {
153 RtlInitAnsiString(&OutputA, (LPSTR)lpszOutput);
154 RtlAnsiStringToUnicodeString(&OutputU, &OutputA, TRUE);
155 }
156 else
157 OutputU.Buffer = NULL;
158
159 if ( lpdvmInit )
160 dvmInitW = GdiConvertToDevmodeW((LPDEVMODEA)lpdvmInit);
161
162 hDC = IntCreateDICW ( DriverU.Buffer,
163 DeviceU.Buffer,
164 OutputU.Buffer,
165 lpdvmInit ? dvmInitW : NULL,
166 0 );
167 HEAP_free (dvmInitW);
168 /*
169 * Free Unicode parameters.
170 */
171 RtlFreeUnicodeString(&DriverU);
172 RtlFreeUnicodeString(&DeviceU);
173 RtlFreeUnicodeString(&OutputU);
174
175 /*
176 * Return the possible DC handle.
177 */
178 return hDC;
179 }
180
181
182 /*
183 * @implemented
184 */
185 HDC
186 WINAPI
187 CreateDCW (
188 LPCWSTR lpwszDriver,
189 LPCWSTR lpwszDevice,
190 LPCWSTR lpwszOutput,
191 CONST DEVMODEW *lpInitData
192 )
193 {
194
195 return IntCreateDICW ( lpwszDriver,
196 lpwszDevice,
197 lpwszOutput,
198 (PDEVMODEW) lpInitData,
199 0 );
200 }
201
202
203 /*
204 * @implemented
205 */
206 HDC
207 WINAPI
208 CreateICW(
209 LPCWSTR lpszDriver,
210 LPCWSTR lpszDevice,
211 LPCWSTR lpszOutput,
212 CONST DEVMODEW *lpdvmInit
213 )
214 {
215 return IntCreateDICW ( lpszDriver,
216 lpszDevice,
217 lpszOutput,
218 (PDEVMODEW) lpdvmInit,
219 1 );
220 }
221
222
223 /*
224 * @implemented
225 */
226 HDC
227 WINAPI
228 CreateICA(
229 LPCSTR lpszDriver,
230 LPCSTR lpszDevice,
231 LPCSTR lpszOutput,
232 CONST DEVMODEA *lpdvmInit
233 )
234 {
235 NTSTATUS Status;
236 LPWSTR lpszDriverW, lpszDeviceW, lpszOutputW;
237 LPDEVMODEW dvmInitW = NULL;
238 HDC rc = 0;
239
240 Status = HEAP_strdupA2W ( &lpszDriverW, lpszDriver );
241 if (!NT_SUCCESS (Status))
242 SetLastError (RtlNtStatusToDosError(Status));
243 else
244 {
245 Status = HEAP_strdupA2W ( &lpszDeviceW, lpszDevice );
246 if (!NT_SUCCESS (Status))
247 SetLastError (RtlNtStatusToDosError(Status));
248 else
249 {
250 Status = HEAP_strdupA2W ( &lpszOutputW, lpszOutput );
251 if (!NT_SUCCESS (Status))
252 SetLastError (RtlNtStatusToDosError(Status));
253 else
254 {
255 if ( lpdvmInit )
256 dvmInitW = GdiConvertToDevmodeW((LPDEVMODEA)lpdvmInit);
257
258 rc = IntCreateDICW ( lpszDriverW,
259 lpszDeviceW,
260 lpszOutputW,
261 lpdvmInit ? dvmInitW : NULL,
262 1 );
263 HEAP_free (dvmInitW);
264 HEAP_free ( lpszOutputW );
265 }
266 HEAP_free ( lpszDeviceW );
267 }
268 HEAP_free ( lpszDriverW );
269 }
270 return rc;
271 }
272
273
274 /*
275 * @implemented
276 */
277 BOOL
278 WINAPI
279 DeleteDC(HDC hDC)
280 {
281 BOOL Ret = TRUE;
282 PLDC pLDC = NULL;
283 HANDLE hPrinter = NULL;
284 ULONG hType = GDI_HANDLE_GET_TYPE(hDC);
285
286 pLDC = GdiGetLDC(hDC);
287
288 if (hType != GDILoObjType_LO_DC_TYPE)
289 {
290
291 if ( !pLDC || hType == GDILoObjType_LO_METADC16_TYPE)
292 {
293 SetLastError(ERROR_INVALID_HANDLE);
294 return FALSE;
295 }
296 if (pLDC->Flags & LDC_INIT_DOCUMENT) AbortDoc(hDC);
297 if (pLDC->hPrinter)
298 {
299 DocumentEventEx(NULL, pLDC->hPrinter, hDC, DOCUMENTEVENT_DELETEDC, 0, NULL, 0, NULL);
300 hPrinter = pLDC->hPrinter;
301 pLDC->hPrinter = NULL;
302 }
303 }
304
305 Ret = NtGdiDeleteObjectApp(hDC);
306
307 if (Ret && pLDC )
308 {
309 DPRINT1("Delete the Local DC structure\n");
310 LocalFree( pLDC );
311 }
312 if (hPrinter) fpClosePrinter(hPrinter);
313 return Ret;
314 }
315
316 /*
317 * @implemented
318 */
319 BOOL
320 WINAPI
321 DeleteObject(HGDIOBJ hObject)
322 {
323 UINT Type = 0;
324
325 /* From Wine: DeleteObject does not SetLastError() on a null object */
326 if(!hObject) return FALSE;
327
328 if (0 != ((DWORD) hObject & GDI_HANDLE_STOCK_MASK))
329 {
330 // Relax! This is a normal return!
331 DPRINT("Trying to delete system object 0x%x\n", hObject);
332 return TRUE;
333 }
334 // If you dont own it?! Get OUT!
335 if(!GdiIsHandleValid(hObject)) return FALSE;
336
337 Type = GDI_HANDLE_GET_TYPE(hObject);
338
339 if ((Type == GDI_OBJECT_TYPE_METAFILE) ||
340 (Type == GDI_OBJECT_TYPE_ENHMETAFILE))
341 return FALSE;
342
343 switch (Type)
344 {
345 case GDI_OBJECT_TYPE_DC:
346 return DeleteDC((HDC) hObject);
347 case GDI_OBJECT_TYPE_COLORSPACE:
348 return NtGdiDeleteColorSpace((HCOLORSPACE) hObject);
349 case GDI_OBJECT_TYPE_REGION:
350 return DeleteRegion((HRGN) hObject);
351 #if 0
352 case GDI_OBJECT_TYPE_METADC:
353 return MFDRV_DeleteObject( hObject );
354 case GDI_OBJECT_TYPE_EMF:
355 {
356 PLDC pLDC = GdiGetLDC(hObject);
357 if ( !pLDC ) return FALSE;
358 return EMFDRV_DeleteObject( hObject );
359 }
360 #endif
361 case GDI_OBJECT_TYPE_FONT:
362 break;
363
364 case GDI_OBJECT_TYPE_BRUSH:
365 case GDI_OBJECT_TYPE_EXTPEN:
366 case GDI_OBJECT_TYPE_PEN:
367 {
368 PBRUSH_ATTR Brh_Attr;
369 PTEB pTeb;
370
371 if ((!GdiGetHandleUserData(hObject, (DWORD)Type, (PVOID) &Brh_Attr)) ||
372 (Brh_Attr == NULL) ) break;
373
374 pTeb = NtCurrentTeb();
375
376 if (pTeb->Win32ThreadInfo == NULL) break;
377
378 if ((pTeb->GdiTebBatch.Offset + sizeof(GDIBSOBJECT)) <= GDIBATCHBUFSIZE)
379 {
380 PGDIBSOBJECT pgO = (PGDIBSOBJECT)(&pTeb->GdiTebBatch.Buffer[0] +
381 pTeb->GdiTebBatch.Offset);
382 pgO->gbHdr.Cmd = GdiBCDelObj;
383 pgO->gbHdr.Size = sizeof(GDIBSOBJECT);
384 pgO->hgdiobj = hObject;
385
386 pTeb->GdiTebBatch.Offset += sizeof(GDIBSOBJECT);
387 pTeb->GdiBatchCount++;
388 if (pTeb->GdiBatchCount >= GDI_BatchLimit) NtGdiFlush();
389 return TRUE;
390 }
391 break;
392 }
393 case GDI_OBJECT_TYPE_BITMAP:
394 default:
395 break;
396 }
397 return NtGdiDeleteObjectApp(hObject);
398 }
399
400 INT
401 WINAPI
402 GetArcDirection( HDC hdc )
403 {
404 return GetDCDWord( hdc, GdiGetArcDirection, 0);
405 }
406
407
408 INT
409 WINAPI
410 SetArcDirection( HDC hdc, INT nDirection )
411 {
412 return GetAndSetDCDWord( hdc, GdiGetSetArcDirection, nDirection, 0, 0, 0 );
413 }
414
415 /*
416 * @implemented
417 *
418 */
419 HGDIOBJ
420 WINAPI
421 GetCurrentObject(
422 _In_ HDC hdc,
423 _In_ UINT uObjectType)
424 {
425 PDC_ATTR pdcattr;
426
427 /* Check if this is a user mode object */
428 if ((uObjectType == OBJ_PEN) ||
429 (uObjectType == OBJ_EXTPEN) ||
430 (uObjectType == OBJ_BRUSH) ||
431 (uObjectType == OBJ_COLORSPACE))
432 {
433 /* Get the dc attribute */
434 pdcattr = GdiGetDcAttr(hdc);
435 if (!pdcattr) return NULL;
436 }
437
438 /* Check what object was requested */
439 switch (uObjectType)
440 {
441 case OBJ_EXTPEN:
442 case OBJ_PEN:
443 return pdcattr->hpen;
444
445 case OBJ_BRUSH:
446 return pdcattr->hbrush;
447
448 case OBJ_COLORSPACE:
449 return pdcattr->hColorSpace;
450
451 case OBJ_PAL:
452 uObjectType = GDI_OBJECT_TYPE_PALETTE;
453 break;
454
455 case OBJ_FONT:
456 uObjectType = GDI_OBJECT_TYPE_FONT;
457 break;
458
459 case OBJ_BITMAP:
460 uObjectType = GDI_OBJECT_TYPE_BITMAP;
461 break;
462
463 /* All others are invalid */
464 default:
465 SetLastError(ERROR_INVALID_PARAMETER);
466 return NULL;
467 }
468
469 /* Pass the request to win32k */
470 return NtGdiGetDCObject(hdc, uObjectType);
471 }
472
473 /*
474 * @implemented
475 *
476 */
477 int
478 WINAPI
479 GetDeviceCaps(HDC hDC,
480 int i)
481 {
482 PDC_ATTR Dc_Attr;
483 PLDC pLDC;
484 PDEVCAPS pDevCaps = GdiDevCaps; // Primary display device capabilities.
485 DPRINT("Device CAPS1\n");
486
487 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
488 {
489 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
490 {
491 if ( i == TECHNOLOGY) return DT_METAFILE;
492 return 0;
493 }
494 else
495 {
496 pLDC = GdiGetLDC(hDC);
497 if ( !pLDC )
498 {
499 SetLastError(ERROR_INVALID_HANDLE);
500 return 0;
501 }
502 if (!(pLDC->Flags & LDC_DEVCAPS))
503 {
504 if (!NtGdiGetDeviceCapsAll(hDC, &pLDC->DevCaps))
505 SetLastError(ERROR_INVALID_PARAMETER);
506 pLDC->Flags |= LDC_DEVCAPS;
507 }
508 pDevCaps = &pLDC->DevCaps;
509 }
510 }
511 else
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 WINAPI
647 GetRelAbs(
648 HDC hdc,
649 DWORD dwIgnore
650 )
651 {
652 return GetDCDWord( hdc, GdiGetRelAbs, 0);
653 }
654
655
656 /*
657 * @implemented
658 */
659 INT
660 WINAPI
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 WINAPI
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 WINAPI
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 WINAPI
727 GetAspectRatioFilterEx(
728 HDC hdc,
729 LPSIZE lpAspectRatio
730 )
731 {
732 return NtGdiGetDCPoint( hdc, GdiGetAspectRatioFilter, (PPOINTL) lpAspectRatio );
733 }
734
735
736 /*
737 * @implemented
738 */
739 BOOL
740 WINAPI
741 GetDCOrgEx(
742 HDC hdc,
743 LPPOINT lpPoint
744 )
745 {
746 return NtGdiGetDCPoint( hdc, GdiGetDCOrg, (PPOINTL)lpPoint );
747 }
748
749
750 /*
751 * @implemented
752 */
753 LONG
754 WINAPI
755 GetDCOrg(
756 HDC hdc)
757 {
758 // Officially obsolete by Microsoft
759 POINT Pt;
760 if (!GetDCOrgEx(hdc, &Pt))
761 return 0;
762 return(MAKELONG(Pt.x, Pt.y));
763 }
764
765 ULONG
766 WINAPI
767 GetFontObjectW(HGDIOBJ hfont, ULONG cbSize, LPVOID lpBuffer)
768 {
769 ENUMLOGFONTEXDVW elfedvW;
770 ULONG cbResult, cbMaxSize;
771
772 /* Check if size only is requested */
773 if (!lpBuffer) return sizeof(LOGFONTW);
774
775 /* Check for size 0 */
776 if (cbSize == 0)
777 {
778 /* Windows does not SetLastError() */
779 return 0;
780 }
781
782 /* Call win32k to get the logfont (widechar) */
783 cbResult = NtGdiExtGetObjectW(hfont, sizeof(ENUMLOGFONTEXDVW), &elfedvW);
784 if (cbResult == 0)
785 {
786 return 0;
787 }
788
789 /* Calculate the maximum size according to number of axes */
790 cbMaxSize = FIELD_OFFSET(ENUMLOGFONTEXDVW,
791 elfDesignVector.dvValues[elfedvW.elfDesignVector.dvNumAxes]);
792
793 /* Don't copy more than the maximum */
794 if (cbSize > cbMaxSize) cbSize = cbMaxSize;
795 if (cbSize > cbResult) cbSize = cbResult;
796
797 /* Copy the number of bytes requested */
798 memcpy(lpBuffer, &elfedvW, cbSize);
799
800 /* Return the number of bytes copied */
801 return cbSize;
802 }
803
804 ULONG
805 WINAPI
806 GetFontObjectA(HGDIOBJ hfont, ULONG cbSize, LPVOID lpBuffer)
807 {
808 ENUMLOGFONTEXDVW elfedvW;
809 ENUMLOGFONTEXDVA elfedvA;
810 ULONG cbResult;
811
812 /* Check if size only is requested */
813 if (!lpBuffer) return sizeof(LOGFONTA);
814
815 /* Check for size 0 */
816 if (cbSize == 0)
817 {
818 /* Windows does not SetLastError() */
819 return 0;
820 }
821
822 /* Windows does this ... */
823 if (cbSize == sizeof(LOGFONTW)) cbSize = sizeof(LOGFONTA);
824
825 /* Call win32k to get the logfont (widechar) */
826 cbResult = NtGdiExtGetObjectW(hfont, sizeof(ENUMLOGFONTEXDVW), &elfedvW);
827 if (cbResult == 0)
828 {
829 return 0;
830 }
831
832 /* Convert the logfont from widechar to ansi */
833 EnumLogFontExW2A(&elfedvA.elfEnumLogfontEx, &elfedvW.elfEnumLogfontEx);
834 elfedvA.elfDesignVector = elfedvW.elfDesignVector;
835
836 /* Don't copy more than maximum */
837 if (cbSize > sizeof(ENUMLOGFONTEXDVA)) cbSize = sizeof(ENUMLOGFONTEXDVA);
838
839 /* Copy the number of bytes requested */
840 memcpy(lpBuffer, &elfedvA, cbSize);
841
842 /* Return the number of bytes copied */
843 return cbSize;
844 }
845
846 /*
847 * @implemented
848 */
849 int
850 WINAPI
851 GetObjectW(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
852 {
853 DWORD dwType;
854 INT cbResult = 0;
855
856 hGdiObj = GdiFixUpHandle(hGdiObj);
857
858 /* Get the object type */
859 dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
860
861 /* Check what kind of object we have */
862 switch(dwType)
863 {
864 case GDI_OBJECT_TYPE_PEN:
865 if (!lpBuffer) return sizeof(LOGPEN);
866 cbResult = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
867 if (cbResult == 0)
868 SetLastError(ERROR_INVALID_PARAMETER);
869 return cbResult;
870
871 case GDI_OBJECT_TYPE_BRUSH:
872 if (!lpBuffer) return sizeof(LOGBRUSH);
873 cbResult = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
874 if (cbResult == 0)
875 SetLastError(ERROR_INVALID_PARAMETER);
876 return cbResult;
877
878 case GDI_OBJECT_TYPE_BITMAP:
879 if (!lpBuffer) return sizeof(BITMAP);
880 return NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
881
882 case GDI_OBJECT_TYPE_PALETTE:
883 if (!lpBuffer) return sizeof(WORD);
884 return NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
885
886 case GDI_OBJECT_TYPE_FONT:
887 return GetFontObjectW(hGdiObj, cbSize, lpBuffer);
888
889 case GDI_OBJECT_TYPE_EXTPEN:
890 /* we don't know the size, ask win32k */
891 cbResult = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
892 if (cbResult == 0)
893 {
894 if (!GdiIsHandleValid(hGdiObj))
895 SetLastError(ERROR_INVALID_PARAMETER);
896 else if (cbSize == 0)
897 SetLastError(ERROR_NOACCESS);
898 }
899 return cbResult;
900
901 case GDI_OBJECT_TYPE_COLORSPACE:
902 if ((cbSize < 328) || !lpBuffer)
903 {
904 SetLastError(ERROR_INSUFFICIENT_BUFFER);
905 return 0;
906 }
907 cbResult = NtGdiExtGetObjectW(hGdiObj, cbSize, lpBuffer);
908 if (cbResult == 0)
909 SetLastError(ERROR_INVALID_PARAMETER);
910 return cbResult;
911
912 case GDI_OBJECT_TYPE_METADC:
913 return 0;
914
915 case GDI_OBJECT_TYPE_DC:
916 case GDI_OBJECT_TYPE_REGION:
917 case GDI_OBJECT_TYPE_EMF:
918 case GDI_OBJECT_TYPE_METAFILE:
919 case GDI_OBJECT_TYPE_ENHMETAFILE:
920 SetLastError(ERROR_INVALID_HANDLE);
921 default:
922 return 0;
923 }
924
925 return 0;
926 }
927
928 /*
929 * @implemented
930 */
931 int
932 WINAPI
933 GetObjectA(HGDIOBJ hGdiObj, int cbSize, LPVOID lpBuffer)
934 {
935 DWORD dwType = GDI_HANDLE_GET_TYPE(hGdiObj);
936
937 /* Chjeck if this is anything else but a font */
938 if (dwType == GDI_OBJECT_TYPE_FONT)
939 {
940 return GetFontObjectA(hGdiObj, cbSize, lpBuffer);
941 }
942 else
943 {
944 /* Simply pass it to the widechar version */
945 return GetObjectW(hGdiObj, cbSize, lpBuffer);
946 }
947 }
948
949
950 /*
951 * @implemented
952 */
953 COLORREF
954 WINAPI
955 GetDCBrushColor(
956 HDC hdc
957 )
958 {
959 PDC_ATTR Dc_Attr;
960
961 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return CLR_INVALID;
962 return (COLORREF) Dc_Attr->ulBrushClr;
963 }
964
965 /*
966 * @implemented
967 */
968 COLORREF
969 WINAPI
970 GetDCPenColor(
971 HDC hdc
972 )
973 {
974 PDC_ATTR Dc_Attr;
975
976 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return CLR_INVALID;
977 return (COLORREF) Dc_Attr->ulPenClr;
978 }
979
980 /*
981 * @implemented
982 */
983 COLORREF
984 WINAPI
985 SetDCBrushColor(
986 HDC hdc,
987 COLORREF crColor
988 )
989 {
990 PDC_ATTR Dc_Attr;
991 COLORREF OldColor = CLR_INVALID;
992
993 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldColor;
994 else
995 {
996 OldColor = (COLORREF) Dc_Attr->ulBrushClr;
997 Dc_Attr->ulBrushClr = (ULONG) crColor;
998
999 if ( Dc_Attr->crBrushClr != crColor ) // if same, don't force a copy.
1000 {
1001 Dc_Attr->ulDirty_ |= DIRTY_FILL;
1002 Dc_Attr->crBrushClr = crColor;
1003 }
1004 }
1005 return OldColor;
1006 }
1007
1008 /*
1009 * @implemented
1010 */
1011 COLORREF
1012 WINAPI
1013 SetDCPenColor(
1014 HDC hdc,
1015 COLORREF crColor
1016 )
1017 {
1018 PDC_ATTR Dc_Attr;
1019 COLORREF OldColor = CLR_INVALID;
1020
1021 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldColor;
1022 else
1023 {
1024 OldColor = (COLORREF) Dc_Attr->ulPenClr;
1025 Dc_Attr->ulPenClr = (ULONG) crColor;
1026
1027 if ( Dc_Attr->crPenClr != crColor )
1028 {
1029 Dc_Attr->ulDirty_ |= DIRTY_LINE;
1030 Dc_Attr->crPenClr = crColor;
1031 }
1032 }
1033 return OldColor;
1034 }
1035
1036 /*
1037 * @implemented
1038 *
1039 */
1040 COLORREF
1041 WINAPI
1042 GetBkColor(HDC hdc)
1043 {
1044 PDC_ATTR Dc_Attr;
1045 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1046 return Dc_Attr->ulBackgroundClr;
1047 }
1048
1049 /*
1050 * @implemented
1051 */
1052 COLORREF
1053 WINAPI
1054 SetBkColor(
1055 HDC hdc,
1056 COLORREF crColor
1057 )
1058 {
1059 PDC_ATTR Dc_Attr;
1060 COLORREF OldColor = CLR_INVALID;
1061
1062 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldColor;
1063 #if 0
1064 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1065 {
1066 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1067 return MFDRV_SetBkColor( hDC, crColor );
1068 else
1069 {
1070 PLDC pLDC = Dc_Attr->pvLDC;
1071 if ( !pLDC )
1072 {
1073 SetLastError(ERROR_INVALID_HANDLE);
1074 return FALSE;
1075 }
1076 if (pLDC->iType == LDC_EMFLDC)
1077 {
1078 return EMFDRV_SetBkColor( hDC, crColor );
1079 }
1080 }
1081 }
1082 #endif
1083 OldColor = (COLORREF) Dc_Attr->ulBackgroundClr;
1084 Dc_Attr->ulBackgroundClr = (ULONG) crColor;
1085
1086 if ( Dc_Attr->crBackgroundClr != crColor )
1087 {
1088 Dc_Attr->ulDirty_ |= (DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL);
1089 Dc_Attr->crBackgroundClr = crColor;
1090 }
1091 return OldColor;
1092 }
1093
1094 /*
1095 * @implemented
1096 *
1097 */
1098 int
1099 WINAPI
1100 GetBkMode(HDC hdc)
1101 {
1102 PDC_ATTR Dc_Attr;
1103 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1104 return Dc_Attr->lBkMode;
1105 }
1106
1107 /*
1108 * @implemented
1109 *
1110 */
1111 int
1112 WINAPI
1113 SetBkMode(HDC hdc,
1114 int iBkMode)
1115 {
1116 PDC_ATTR Dc_Attr;
1117 INT OldMode = 0;
1118
1119 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return OldMode;
1120 #if 0
1121 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1122 {
1123 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1124 return MFDRV_SetBkMode( hdc, iBkMode )
1125 else
1126 {
1127 PLDC pLDC = Dc_Attr->pvLDC;
1128 if ( !pLDC )
1129 {
1130 SetLastError(ERROR_INVALID_HANDLE);
1131 return FALSE;
1132 }
1133 if (pLDC->iType == LDC_EMFLDC)
1134 {
1135 return EMFDRV_SetBkMode( hdc, iBkMode )
1136 }
1137 }
1138 }
1139 #endif
1140 OldMode = Dc_Attr->lBkMode;
1141 Dc_Attr->jBkMode = iBkMode; // Processed
1142 Dc_Attr->lBkMode = iBkMode; // Raw
1143 return OldMode;
1144 }
1145
1146 /*
1147 * @implemented
1148 *
1149 */
1150 int
1151 WINAPI
1152 GetPolyFillMode(HDC hdc)
1153 {
1154 PDC_ATTR Dc_Attr;
1155 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1156 return Dc_Attr->lFillMode;
1157 }
1158
1159 /*
1160 * @unimplemented
1161 */
1162 int
1163 WINAPI
1164 SetPolyFillMode(HDC hdc,
1165 int iPolyFillMode)
1166 {
1167 INT fmode;
1168 PDC_ATTR Dc_Attr;
1169 #if 0
1170 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1171 {
1172 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1173 return MFDRV_SetPolyFillMode( hdc, iPolyFillMode )
1174 else
1175 {
1176 PLDC pLDC = GdiGetLDC(hdc);
1177 if ( !pLDC )
1178 {
1179 SetLastError(ERROR_INVALID_HANDLE);
1180 return FALSE;
1181 }
1182 if (pLDC->iType == LDC_EMFLDC)
1183 {
1184 return EMFDRV_SetPolyFillMode( hdc, iPolyFillMode )
1185 }
1186 }
1187 }
1188 #endif
1189 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1190
1191 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
1192 {
1193 if (Dc_Attr->ulDirty_ & DC_MODE_DIRTY)
1194 {
1195 NtGdiFlush(); // Sync up Dc_Attr from Kernel space.
1196 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1197 }
1198 }
1199
1200 fmode = Dc_Attr->lFillMode;
1201 Dc_Attr->lFillMode = iPolyFillMode;
1202
1203 return fmode;
1204 }
1205
1206 /*
1207 * @implemented
1208 *
1209 */
1210 int
1211 WINAPI
1212 GetGraphicsMode(HDC hdc)
1213 {
1214 PDC_ATTR Dc_Attr;
1215 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1216 return Dc_Attr->iGraphicsMode;
1217 }
1218
1219 /*
1220 * @unimplemented
1221 */
1222 int
1223 WINAPI
1224 SetGraphicsMode(HDC hdc,
1225 int iMode)
1226 {
1227 INT oMode;
1228 PDC_ATTR Dc_Attr;
1229 if ((iMode < GM_COMPATIBLE) || (iMode > GM_ADVANCED))
1230 {
1231 SetLastError(ERROR_INVALID_PARAMETER);
1232 return 0;
1233 }
1234 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1235
1236 if (iMode == Dc_Attr->iGraphicsMode) return iMode;
1237
1238 if (NtCurrentTeb()->GdiTebBatch.HDC == hdc)
1239 {
1240 if (Dc_Attr->ulDirty_ & DC_MODE_DIRTY)
1241 {
1242 NtGdiFlush(); // Sync up Dc_Attr from Kernel space.
1243 Dc_Attr->ulDirty_ &= ~(DC_MODE_DIRTY|DC_FONTTEXT_DIRTY);
1244 }
1245 }
1246 /* One would think that setting the graphics mode to GM_COMPATIBLE
1247 * would also reset the world transformation matrix to the unity
1248 * matrix. However, in Windows, this is not the case. This doesn't
1249 * make a lot of sense to me, but that's the way it is.
1250 */
1251 oMode = Dc_Attr->iGraphicsMode;
1252 Dc_Attr->iGraphicsMode = iMode;
1253
1254 return oMode;
1255 }
1256
1257 /*
1258 * @implemented
1259 */
1260 HDC
1261 WINAPI
1262 ResetDCW(
1263 HDC hdc,
1264 CONST DEVMODEW *lpInitData
1265 )
1266 {
1267 NtGdiResetDC ( hdc, (PDEVMODEW)lpInitData, NULL, NULL, NULL);
1268 return hdc;
1269 }
1270
1271
1272 /*
1273 * @implemented
1274 */
1275 HDC
1276 WINAPI
1277 ResetDCA(
1278 HDC hdc,
1279 CONST DEVMODEA *lpInitData
1280 )
1281 {
1282 LPDEVMODEW InitDataW;
1283
1284 InitDataW = GdiConvertToDevmodeW((LPDEVMODEA)lpInitData);
1285
1286 NtGdiResetDC ( hdc, InitDataW, NULL, NULL, NULL);
1287 HEAP_free(InitDataW);
1288 return hdc;
1289 }
1290
1291
1292 /*
1293 * @implemented
1294 */
1295 DWORD
1296 WINAPI
1297 GetObjectType(
1298 HGDIOBJ h
1299 )
1300 {
1301 DWORD Ret = 0;
1302
1303 if(GdiIsHandleValid(h))
1304 {
1305 LONG Type = GDI_HANDLE_GET_TYPE(h);
1306 switch(Type)
1307 {
1308 case GDI_OBJECT_TYPE_PEN:
1309 Ret = OBJ_PEN;
1310 break;
1311 case GDI_OBJECT_TYPE_BRUSH:
1312 Ret = OBJ_BRUSH;
1313 break;
1314 case GDI_OBJECT_TYPE_BITMAP:
1315 Ret = OBJ_BITMAP;
1316 break;
1317 case GDI_OBJECT_TYPE_FONT:
1318 Ret = OBJ_FONT;
1319 break;
1320 case GDI_OBJECT_TYPE_PALETTE:
1321 Ret = OBJ_PAL;
1322 break;
1323 case GDI_OBJECT_TYPE_REGION:
1324 Ret = OBJ_REGION;
1325 break;
1326 case GDI_OBJECT_TYPE_DC:
1327 if ( GetDCDWord( h, GdiGetIsMemDc, 0))
1328 {
1329 Ret = OBJ_MEMDC;
1330 }
1331 else
1332 Ret = OBJ_DC;
1333 break;
1334 case GDI_OBJECT_TYPE_COLORSPACE:
1335 Ret = OBJ_COLORSPACE;
1336 break;
1337 case GDI_OBJECT_TYPE_METAFILE:
1338 Ret = OBJ_METAFILE;
1339 break;
1340 case GDI_OBJECT_TYPE_ENHMETAFILE:
1341 Ret = OBJ_ENHMETAFILE;
1342 break;
1343 case GDI_OBJECT_TYPE_METADC:
1344 Ret = OBJ_METADC;
1345 break;
1346 case GDI_OBJECT_TYPE_EXTPEN:
1347 Ret = OBJ_EXTPEN;
1348 break;
1349
1350 default:
1351 DPRINT1("GetObjectType: Magic 0x%08x not implemented\n", Type);
1352 break;
1353 }
1354 }
1355 else
1356 /* From Wine: GetObjectType does SetLastError() on a null object */
1357 SetLastError(ERROR_INVALID_HANDLE);
1358 return Ret;
1359 }
1360
1361
1362 /*
1363 * @implemented
1364 */
1365 HGDIOBJ
1366 WINAPI
1367 GetStockObject(
1368 INT h
1369 )
1370 {
1371 HGDIOBJ Ret = NULL;
1372 if ((h < 0) || (h >= NB_STOCK_OBJECTS)) return Ret;
1373 Ret = stock_objects[h];
1374 if (!Ret)
1375 {
1376 HGDIOBJ Obj = NtGdiGetStockObject( h );
1377
1378 if (GdiIsHandleValid(Obj))
1379 {
1380 stock_objects[h] = Obj;
1381 return Obj;
1382 }// Returns Null anyway.
1383 }
1384 return Ret;
1385 }
1386
1387 /* FIXME: include correct header */
1388 HPALETTE WINAPI NtUserSelectPalette(HDC hDC,
1389 HPALETTE hpal,
1390 BOOL ForceBackground);
1391
1392 HPALETTE
1393 WINAPI
1394 SelectPalette(
1395 HDC hDC,
1396 HPALETTE hPal,
1397 BOOL bForceBackground)
1398 {
1399 #if 0
1400 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1401 {
1402 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1403 return MFDRV_SelectPalette( hDC, hPal, bForceBackground);
1404 else
1405 {
1406 PLDC pLDC = GdiGetLDC(hDC);
1407 if ( !pLDC )
1408 {
1409 SetLastError(ERROR_INVALID_HANDLE);
1410 return NULL;
1411 }
1412 if (pLDC->iType == LDC_EMFLDC)
1413 {
1414 if return EMFDRV_SelectPalette( hDC, hPal, bForceBackground);
1415 }
1416 }
1417 }
1418 #endif
1419 return NtUserSelectPalette(hDC, hPal, bForceBackground);
1420 }
1421
1422 /*
1423 * @implemented
1424 *
1425 */
1426 int
1427 WINAPI
1428 GetMapMode(HDC hdc)
1429 {
1430 PDC_ATTR Dc_Attr;
1431 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1432 return Dc_Attr->iMapMode;
1433 }
1434
1435 /*
1436 * @implemented
1437 */
1438 INT
1439 WINAPI
1440 SetMapMode(
1441 HDC hdc,
1442 INT Mode
1443 )
1444 {
1445 PDC_ATTR Dc_Attr;
1446 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1447 #if 0
1448 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC)
1449 {
1450 if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC)
1451 return MFDRV_SetMapMode(hdc, Mode);
1452 else
1453 {
1454 SetLastError(ERROR_INVALID_HANDLE);
1455 return 0;
1456 }
1457 #endif
1458 // Force change if Isotropic is set for recompute.
1459 if ((Mode != Dc_Attr->iMapMode) || (Mode == MM_ISOTROPIC))
1460 {
1461 Dc_Attr->ulDirty_ &= ~SLOW_WIDTHS;
1462 return GetAndSetDCDWord( hdc, GdiGetSetMapMode, Mode, 0, 0, 0 );
1463 }
1464 return Dc_Attr->iMapMode;
1465 }
1466
1467 /*
1468 * @implemented
1469 *
1470 */
1471 int
1472 WINAPI
1473 GetStretchBltMode(HDC hdc)
1474 {
1475 PDC_ATTR Dc_Attr;
1476 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1477 return Dc_Attr->lStretchBltMode;
1478 }
1479
1480 /*
1481 * @implemented
1482 */
1483 int
1484 WINAPI
1485 SetStretchBltMode(HDC hdc, int iStretchMode)
1486 {
1487 INT oSMode;
1488 PDC_ATTR Dc_Attr;
1489 #if 0
1490 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
1491 {
1492 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
1493 return MFDRV_SetStretchBltMode( hdc, iStretchMode);
1494 else
1495 {
1496 PLDC pLDC = GdiGetLDC(hdc);
1497 if ( !pLDC )
1498 {
1499 SetLastError(ERROR_INVALID_HANDLE);
1500 return 0;
1501 }
1502 if (pLDC->iType == LDC_EMFLDC)
1503 {
1504 return EMFDRV_SetStretchBltMode( hdc, iStretchMode);
1505 }
1506 }
1507 }
1508 #endif
1509 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return 0;
1510
1511 oSMode = Dc_Attr->lStretchBltMode;
1512 Dc_Attr->lStretchBltMode = iStretchMode;
1513
1514 // Wine returns an error here. We set the default.
1515 if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK;
1516
1517 Dc_Attr->jStretchBltMode = iStretchMode;
1518
1519 return oSMode;
1520 }
1521
1522 /*
1523 * @implemented
1524 */
1525 HFONT
1526 WINAPI
1527 GetHFONT(HDC hdc)
1528 {
1529 PDC_ATTR Dc_Attr;
1530 if (!GdiGetHandleUserData((HGDIOBJ) hdc, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) return NULL;
1531 return Dc_Attr->hlfntNew;
1532 }
1533
1534
1535 /*
1536 * @implemented
1537 *
1538 */
1539 HGDIOBJ
1540 WINAPI
1541 SelectObject(HDC hDC,
1542 HGDIOBJ hGdiObj)
1543 {
1544 PDC_ATTR pDc_Attr;
1545 HGDIOBJ hOldObj = NULL;
1546 UINT uType;
1547
1548 if(!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
1549 {
1550 SetLastError(ERROR_INVALID_HANDLE);
1551 return NULL;
1552 }
1553
1554 hGdiObj = GdiFixUpHandle(hGdiObj);
1555 if (!GdiIsHandleValid(hGdiObj))
1556 {
1557 return NULL;
1558 }
1559
1560 uType = GDI_HANDLE_GET_TYPE(hGdiObj);
1561
1562 switch (uType)
1563 {
1564 case GDI_OBJECT_TYPE_REGION:
1565 return (HGDIOBJ)ExtSelectClipRgn(hDC, hGdiObj, RGN_COPY);
1566
1567 case GDI_OBJECT_TYPE_BITMAP:
1568 return NtGdiSelectBitmap(hDC, hGdiObj);
1569
1570 case GDI_OBJECT_TYPE_BRUSH:
1571 hOldObj = pDc_Attr->hbrush;
1572 pDc_Attr->ulDirty_ |= DC_BRUSH_DIRTY;
1573 pDc_Attr->hbrush = hGdiObj;
1574 return hOldObj;
1575 // return NtGdiSelectBrush(hDC, hGdiObj);
1576
1577 case GDI_OBJECT_TYPE_PEN:
1578 case GDI_OBJECT_TYPE_EXTPEN:
1579 hOldObj = pDc_Attr->hpen;
1580 pDc_Attr->ulDirty_ |= DC_PEN_DIRTY;
1581 pDc_Attr->hpen = hGdiObj;
1582 return hOldObj;
1583 // return NtGdiSelectPen(hDC, hGdiObj);
1584
1585 case GDI_OBJECT_TYPE_FONT:
1586 hOldObj = pDc_Attr->hlfntNew;
1587 if (hOldObj == hGdiObj) return hOldObj;
1588
1589 pDc_Attr->ulDirty_ &= ~SLOW_WIDTHS;
1590 pDc_Attr->ulDirty_ |= DIRTY_CHARSET;
1591 pDc_Attr->hlfntNew = hGdiObj;
1592
1593 if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION))
1594 {
1595 PGDIBSOBJECT pgO;
1596
1597 pgO = GdiAllocBatchCommand(hDC, GdiBCSelObj);
1598 if (pgO)
1599 {
1600 pgO->hgdiobj = hGdiObj;
1601 return hOldObj;
1602 }
1603 }
1604
1605 // default for select object font
1606 return NtGdiSelectFont(hDC, hGdiObj);
1607
1608 #if 0
1609 case GDI_OBJECT_TYPE_METADC:
1610 return MFDRV_SelectObject( hDC, hGdiObj);
1611 case GDI_OBJECT_TYPE_EMF:
1612 PLDC pLDC = GdiGetLDC(hDC);
1613 if ( !pLDC ) return NULL;
1614 return EMFDRV_SelectObject( hDC, hGdiObj);
1615 #endif
1616 case GDI_OBJECT_TYPE_COLORSPACE:
1617 SetColorSpace(hDC, (HCOLORSPACE) hGdiObj);
1618 return NULL;
1619
1620 case GDI_OBJECT_TYPE_PALETTE:
1621 default:
1622 SetLastError(ERROR_INVALID_FUNCTION);
1623 return NULL;
1624 }
1625
1626 return NULL;
1627 }