2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/objects/font.c
9 /** Includes ******************************************************************/
16 DWORD FASTCALL
GreGetGlyphIndicesW(HDC
,LPWSTR
,INT
,LPWORD
,DWORD
,DWORD
);
18 /** Internal ******************************************************************/
25 LPKERNINGPAIR krnpair
)
37 EngSetLastError(ERROR_INVALID_HANDLE
);
41 pdcattr
= dc
->pdcattr
;
42 TextObj
= RealizeFontInit(pdcattr
->hlfntNew
);
47 EngSetLastError(ERROR_INVALID_HANDLE
);
51 FontGDI
= ObjToGDI(TextObj
->Font
, FONT
);
52 TEXTOBJ_UnlockText(TextObj
);
54 Count
= ftGdiGetKerningPairs(FontGDI
,0,NULL
);
56 if ( Count
&& krnpair
)
60 EngSetLastError(ERROR_INSUFFICIENT_BUFFER
);
63 pKP
= ExAllocatePoolWithTag(PagedPool
, Count
* sizeof(KERNINGPAIR
), GDITAG_TEXT
);
66 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
69 ftGdiGetKerningPairs(FontGDI
,Count
,pKP
);
71 RtlCopyMemory(krnpair
, pKP
, Count
* sizeof(KERNINGPAIR
));
73 ExFreePoolWithTag(pKP
,GDITAG_TEXT
);
80 It is recommended that an application use the GetFontLanguageInfo function
81 to determine whether the GCP_DIACRITIC, GCP_DBCS, GCP_USEKERNING, GCP_LIGATE,
82 GCP_REORDER, GCP_GLYPHSHAPE, and GCP_KASHIDA values are valid for the
83 currently selected font. If not valid, GetCharacterPlacement ignores the
86 M$ must use a preset "compiled in" support for each language based releases.
87 ReactOS uses FreeType, this will need to be supported. ATM this is hard coded
94 GreGetCharacterPlacementW(
102 GCP_RESULTSW gcpwSave
;
108 DPRINT1("GreGCPW Start\n");
112 if (GreGetTextExtentW( hdc
, pwsz
, nCount
, &Size
, 1))
113 return MAKELONG(Size
.cx
, Size
.cy
);
117 DPRINT1("GreGCPW 1\n");
119 RtlCopyMemory(&gcpwSave
, pgcpw
, sizeof(GCP_RESULTSW
));
121 cSet
= nSet
= nCount
;
123 if ( nCount
> gcpwSave
.nGlyphs
) cSet
= gcpwSave
.nGlyphs
;
125 /* GCP_JUSTIFY may only be used in conjunction with GCP_MAXEXTENT. */
126 if ( dwFlags
& GCP_JUSTIFY
) dwFlags
|= GCP_MAXEXTENT
;
128 if ( !gcpwSave
.lpDx
&& gcpwSave
.lpCaretPos
)
129 tmpDxCaretPos
= gcpwSave
.lpCaretPos
;
131 tmpDxCaretPos
= gcpwSave
.lpDx
;
133 if ( !GreGetTextExtentExW( hdc
,
137 ((dwFlags
& GCP_MAXEXTENT
) ? (PULONG
) &cSet
: NULL
),
138 (PULONG
) tmpDxCaretPos
,
145 DPRINT1("GreGCPW 2\n");
149 if ( tmpDxCaretPos
&& nSet
> 0)
151 for (i
= (nSet
- 1); i
> 0; i
--)
153 tmpDxCaretPos
[i
] -= tmpDxCaretPos
[i
- 1];
157 if ( !(dwFlags
& GCP_MAXEXTENT
) || nSet
)
159 if ( (dwFlags
& GCP_USEKERNING
) &&
161 gcpwSave
.lpCaretPos
) &&
167 Count
= GreGetKerningPairs( hdc
, 0, NULL
);
170 pKP
= ExAllocatePoolWithTag(PagedPool
, Count
* sizeof(KERNINGPAIR
), GDITAG_TEXT
);
173 if ( GreGetKerningPairs( hdc
, Count
, pKP
) != Count
)
175 ExFreePoolWithTag( pKP
, GDITAG_TEXT
);
179 if ( (ULONG_PTR
)(pKP
) < ((ULONG_PTR
)(pKP
) + (ULONG_PTR
)(Count
* sizeof(KERNINGPAIR
))) )
181 DPRINT1("We Need to Do Something HERE!\n");
184 ExFreePoolWithTag( pKP
, GDITAG_TEXT
);
186 if ( dwFlags
& GCP_MAXEXTENT
)
188 if ( Size
.cx
> nMaxExtent
)
190 for (Cx
= Size
.cx
; nSet
> 0; nSet
--)
192 Cx
-= tmpDxCaretPos
[nSet
- 1];
194 if ( Cx
<= nMaxExtent
) break;
208 if ( (dwFlags
& GCP_JUSTIFY
) &&
210 gcpwSave
.lpCaretPos
) &&
213 DPRINT1("We Need to Do Something HERE 2!\n");
216 if ( gcpwSave
.lpDx
&& gcpwSave
.lpCaretPos
)
217 RtlCopyMemory( gcpwSave
.lpCaretPos
, gcpwSave
.lpDx
, nSet
* sizeof(LONG
));
219 if ( gcpwSave
.lpCaretPos
)
227 Cx
= gcpwSave
.lpCaretPos
[i
];
228 gcpwSave
.lpCaretPos
[i
] = pos
;
236 if ( gcpwSave
.lpOutString
)
237 RtlCopyMemory(gcpwSave
.lpOutString
, pwsz
, nSet
* sizeof(WCHAR
));
239 if ( gcpwSave
.lpClass
)
240 RtlFillMemory(gcpwSave
.lpClass
, nSet
, GCPCLASS_LATIN
);
242 if ( gcpwSave
.lpOrder
)
244 for (i
= 0; i
< nSet
; i
++)
245 gcpwSave
.lpOrder
[i
] = i
;
248 if ( gcpwSave
.lpGlyphs
)
250 if ( GreGetGlyphIndicesW( hdc
, pwsz
, nSet
, gcpwSave
.lpGlyphs
, 0, 0) == GDI_ERROR
)
257 pgcpw
->nGlyphs
= nSet
;
258 pgcpw
->nMaxFit
= nSet
;
260 DPRINT1("GreGCPW Exit\n");
261 return MAKELONG(Size
.cx
, Size
.cy
);
267 FontGetObject(PTEXTOBJ TFont
, INT Count
, PVOID Buffer
)
269 if( Buffer
== NULL
) return sizeof(LOGFONTW
);
273 case sizeof(ENUMLOGFONTEXDVW
):
274 RtlCopyMemory( (LPENUMLOGFONTEXDVW
) Buffer
,
276 sizeof(ENUMLOGFONTEXDVW
));
278 case sizeof(ENUMLOGFONTEXW
):
279 RtlCopyMemory( (LPENUMLOGFONTEXW
) Buffer
,
280 &TFont
->logfont
.elfEnumLogfontEx
,
281 sizeof(ENUMLOGFONTEXW
));
284 case sizeof(EXTLOGFONTW
):
285 case sizeof(ENUMLOGFONTW
):
286 RtlCopyMemory((LPENUMLOGFONTW
) Buffer
,
287 &TFont
->logfont
.elfEnumLogfontEx
.elfLogFont
,
288 sizeof(ENUMLOGFONTW
));
291 case sizeof(LOGFONTW
):
292 RtlCopyMemory((LPLOGFONTW
) Buffer
,
293 &TFont
->logfont
.elfEnumLogfontEx
.elfLogFont
,
298 EngSetLastError(ERROR_BUFFER_OVERFLOW
);
306 IntGetCharDimensions(HDC hdc
, PTEXTMETRICW ptm
, PDWORD height
)
315 static const WCHAR alphabet
[] = {
316 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
317 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
318 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
320 if(!ftGdiGetTextMetricsW(hdc
, &tmwi
)) return 0;
322 pdc
= DC_LockDc(hdc
);
326 pdcattr
= pdc
->pdcattr
;
328 TextObj
= RealizeFontInit(pdcattr
->hlfntNew
);
334 Good
= TextIntGetTextExtentPoint(pdc
, TextObj
, alphabet
, 52, 0, NULL
, 0, &sz
, 0);
335 TEXTOBJ_UnlockText(TextObj
);
339 if (ptm
) *ptm
= tmwi
.TextMetric
;
340 if (height
) *height
= tmwi
.TextMetric
.tmHeight
;
342 return (sz
.cx
/ 26 + 1) / 2;
348 IntGetFontLanguageInfo(PDC Dc
)
351 FONTSIGNATURE fontsig
;
352 static const DWORD GCP_DBCS_MASK
=0x003F0000,
353 GCP_DIACRITIC_MASK
=0x00000000,
354 FLI_GLYPHS_MASK
=0x00000000,
355 GCP_GLYPHSHAPE_MASK
=0x00000040,
356 GCP_KASHIDA_MASK
=0x00000000,
357 GCP_LIGATE_MASK
=0x00000000,
358 GCP_USEKERNING_MASK
=0x00000000,
359 GCP_REORDER_MASK
=0x00000060;
363 ftGdiGetTextCharsetInfo( Dc
, &fontsig
, 0 );
365 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
366 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
369 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
370 result
|=GCP_DIACRITIC
;
372 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
375 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
376 result
|=GCP_GLYPHSHAPE
;
378 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
381 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
384 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
385 result
|=GCP_USEKERNING
;
387 pdcattr
= Dc
->pdcattr
;
389 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
390 if ( pdcattr
->lTextAlign
& TA_RTLREADING
)
391 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
399 RealizeFontInit(HFONT hFont
)
401 NTSTATUS Status
= STATUS_SUCCESS
;
404 pTextObj
= TEXTOBJ_LockText(hFont
);
406 if ( pTextObj
&& !(pTextObj
->fl
& TEXTOBJECT_INIT
))
408 Status
= TextIntRealizeFont(hFont
, pTextObj
);
409 if (!NT_SUCCESS(Status
))
411 TEXTOBJ_UnlockText(pTextObj
);
420 GreSelectFont( HDC hDC
, HFONT hFont
)
424 PTEXTOBJ pOrgFnt
, pNewFnt
= NULL
;
425 HFONT hOrgFont
= NULL
;
427 if (!hDC
|| !hFont
) return NULL
;
429 pdc
= DC_LockDc(hDC
);
435 if (NT_SUCCESS(TextIntRealizeFont((HFONT
)hFont
,NULL
)))
437 /* LFONTOBJ use share and locking. */
438 pNewFnt
= TEXTOBJ_LockText(hFont
);
439 pdcattr
= pdc
->pdcattr
;
440 pOrgFnt
= pdc
->dclevel
.plfnt
;
443 hOrgFont
= pOrgFnt
->BaseObject
.hHmgr
;
447 hOrgFont
= pdcattr
->hlfntNew
;
449 pdc
->dclevel
.plfnt
= pNewFnt
;
450 pdc
->hlfntCur
= hFont
;
451 pdcattr
->hlfntNew
= hFont
;
452 pdcattr
->ulDirty_
|= DIRTY_CHARSET
;
453 pdcattr
->ulDirty_
&= ~SLOW_WIDTHS
;
456 if (pNewFnt
) TEXTOBJ_UnlockText(pNewFnt
);
461 /** Functions ******************************************************************/
465 NtGdiAddFontResourceW(
471 IN OPTIONAL DESIGNVECTOR
*pdv
)
473 UNICODE_STRING SafeFileName
;
478 /* FIXME - Protect with SEH? */
479 RtlInitUnicodeString(&SafeFileName
, pwszFiles
);
481 /* Reserve for prepending '\??\' */
482 SafeFileName
.Length
+= 4 * sizeof(WCHAR
);
483 SafeFileName
.MaximumLength
+= 4 * sizeof(WCHAR
);
485 src
= SafeFileName
.Buffer
;
486 SafeFileName
.Buffer
= (PWSTR
)ExAllocatePoolWithTag(PagedPool
, SafeFileName
.MaximumLength
, TAG_STRING
);
487 if(!SafeFileName
.Buffer
)
489 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
494 RtlCopyMemory(SafeFileName
.Buffer
, L
"\\??\\", 4 * sizeof(WCHAR
));
496 Status
= MmCopyFromCaller(SafeFileName
.Buffer
+ 4, src
, SafeFileName
.MaximumLength
- (4 * sizeof(WCHAR
)));
497 if(!NT_SUCCESS(Status
))
499 ExFreePoolWithTag(SafeFileName
.Buffer
, TAG_STRING
);
500 SetLastNtError(Status
);
504 Ret
= IntGdiAddFontResource(&SafeFileName
, (DWORD
)fl
);
506 ExFreePoolWithTag(SafeFileName
.Buffer
, TAG_STRING
);
515 NtGdiGetCharacterPlacementW(
520 IN OUT LPGCP_RESULTSW pgcpw
,
526 return GreGetCharacterPlacementW( hdc
,
549 DWORD Result
= GDI_ERROR
;
550 NTSTATUS Status
= STATUS_SUCCESS
;
556 ProbeForRead(Buffer
, Size
, 1);
558 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
560 Status
= _SEH2_GetExceptionCode();
565 if (!NT_SUCCESS(Status
)) return Result
;
570 EngSetLastError(ERROR_INVALID_HANDLE
);
573 pdcattr
= Dc
->pdcattr
;
575 hFont
= pdcattr
->hlfntNew
;
576 TextObj
= RealizeFontInit(hFont
);
581 EngSetLastError(ERROR_INVALID_HANDLE
);
585 FontGdi
= ObjToGDI(TextObj
->Font
, FONT
);
587 Result
= ftGdiGetFontData(FontGdi
, Table
, Offset
, Buffer
, Size
);
589 TEXTOBJ_UnlockText(TextObj
);
599 NtGdiGetFontUnicodeRanges(
601 OUT OPTIONAL LPGLYPHSET pgs
)
610 NTSTATUS Status
= STATUS_SUCCESS
;
612 pDc
= DC_LockDc(hdc
);
615 EngSetLastError(ERROR_INVALID_HANDLE
);
619 pdcattr
= pDc
->pdcattr
;
621 hFont
= pdcattr
->hlfntNew
;
622 TextObj
= RealizeFontInit(hFont
);
624 if ( TextObj
== NULL
)
626 EngSetLastError(ERROR_INVALID_HANDLE
);
629 FontGdi
= ObjToGDI(TextObj
->Font
, FONT
);
631 Size
= ftGetFontUnicodeRanges( FontGdi
, NULL
);
635 pgsSafe
= ExAllocatePoolWithTag(PagedPool
, Size
, GDITAG_TEXT
);
638 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
643 Size
= ftGetFontUnicodeRanges( FontGdi
, pgsSafe
);
649 ProbeForWrite(pgs
, Size
, 1);
650 RtlCopyMemory(pgs
, pgsSafe
, Size
);
652 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
654 Status
= _SEH2_GetExceptionCode();
658 if (!NT_SUCCESS(Status
)) Size
= 0;
660 ExFreePoolWithTag(pgsSafe
, GDITAG_TEXT
);
663 TEXTOBJ_UnlockText(TextObj
);
670 NtGdiGetGlyphOutline(
674 OUT LPGLYPHMETRICS pgm
,
676 OUT OPTIONAL PVOID UnsafeBuf
,
678 IN BOOL bIgnoreRotation
)
680 ULONG Ret
= GDI_ERROR
;
684 NTSTATUS Status
= STATUS_SUCCESS
;
689 EngSetLastError(ERROR_INVALID_HANDLE
);
693 if (UnsafeBuf
&& cjBuf
)
695 pvBuf
= ExAllocatePoolWithTag(PagedPool
, cjBuf
, GDITAG_TEXT
);
698 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
703 Ret
= ftGdiGetGlyphOutline( dc
,
716 ProbeForWrite(UnsafeBuf
, cjBuf
, 1);
717 RtlCopyMemory(UnsafeBuf
, pvBuf
, cjBuf
);
719 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
721 Status
= _SEH2_GetExceptionCode();
725 ExFreePoolWithTag(pvBuf
, GDITAG_TEXT
);
732 ProbeForWrite(pgm
, sizeof(GLYPHMETRICS
), 1);
733 RtlCopyMemory(pgm
, &gm
, sizeof(GLYPHMETRICS
));
735 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
737 Status
= _SEH2_GetExceptionCode();
742 if (! NT_SUCCESS(Status
))
744 EngSetLastError(ERROR_INVALID_PARAMETER
);
755 NtGdiGetKerningPairs(HDC hDC
,
757 LPKERNINGPAIR krnpair
)
765 NTSTATUS Status
= STATUS_SUCCESS
;
770 EngSetLastError(ERROR_INVALID_HANDLE
);
774 pdcattr
= dc
->pdcattr
;
775 TextObj
= RealizeFontInit(pdcattr
->hlfntNew
);
780 EngSetLastError(ERROR_INVALID_HANDLE
);
784 FontGDI
= ObjToGDI(TextObj
->Font
, FONT
);
785 TEXTOBJ_UnlockText(TextObj
);
787 Count
= ftGdiGetKerningPairs(FontGDI
,0,NULL
);
789 if ( Count
&& krnpair
)
791 if (Count
> NumPairs
)
793 EngSetLastError(ERROR_INSUFFICIENT_BUFFER
);
796 pKP
= ExAllocatePoolWithTag(PagedPool
, Count
* sizeof(KERNINGPAIR
), GDITAG_TEXT
);
799 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
802 ftGdiGetKerningPairs(FontGDI
,Count
,pKP
);
805 ProbeForWrite(krnpair
, Count
* sizeof(KERNINGPAIR
), 1);
806 RtlCopyMemory(krnpair
, pKP
, Count
* sizeof(KERNINGPAIR
));
808 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
810 Status
= _SEH2_GetExceptionCode();
813 if (!NT_SUCCESS(Status
))
815 EngSetLastError(ERROR_INVALID_PARAMETER
);
818 ExFreePoolWithTag(pKP
,GDITAG_TEXT
);
824 From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page
825 472, this is NtGdiGetOutlineTextMetricsInternalW.
829 NtGdiGetOutlineTextMetricsInternalW (HDC hDC
,
831 OUTLINETEXTMETRICW
*otm
,
840 OUTLINETEXTMETRICW
*potm
;
841 NTSTATUS Status
= STATUS_SUCCESS
;
846 EngSetLastError(ERROR_INVALID_HANDLE
);
849 pdcattr
= dc
->pdcattr
;
850 hFont
= pdcattr
->hlfntNew
;
851 TextObj
= RealizeFontInit(hFont
);
855 EngSetLastError(ERROR_INVALID_HANDLE
);
858 FontGDI
= ObjToGDI(TextObj
->Font
, FONT
);
859 TEXTOBJ_UnlockText(TextObj
);
860 Size
= IntGetOutlineTextMetrics(FontGDI
, 0, NULL
);
861 if (!otm
) return Size
;
864 EngSetLastError(ERROR_INSUFFICIENT_BUFFER
);
867 potm
= ExAllocatePoolWithTag(PagedPool
, Size
, GDITAG_TEXT
);
870 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
873 IntGetOutlineTextMetrics(FontGDI
, Size
, potm
);
878 ProbeForWrite(otm
, Size
, 1);
879 RtlCopyMemory(otm
, potm
, Size
);
881 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
883 Status
= _SEH2_GetExceptionCode();
887 if (!NT_SUCCESS(Status
))
889 EngSetLastError(ERROR_INVALID_PARAMETER
);
893 ExFreePoolWithTag(potm
,GDITAG_TEXT
);
900 NtGdiGetFontResourceInfoInternalW(
905 OUT LPDWORD pdwBytes
,
909 NTSTATUS Status
= STATUS_SUCCESS
;
911 UNICODE_STRING SafeFileNames
;
918 WCHAR FullName
[LF_FULLFACESIZE
];
921 /* FIXME: handle cFiles > 0 */
923 /* Check for valid dwType values
924 dwType == 4 seems to be handled by gdi32 only */
925 if (dwType
== 4 || dwType
> 5)
927 EngSetLastError(ERROR_INVALID_PARAMETER
);
931 /* Allocate a safe unicode string buffer */
932 cbStringSize
= cwc
* sizeof(WCHAR
);
933 SafeFileNames
.MaximumLength
= SafeFileNames
.Length
= cbStringSize
- sizeof(WCHAR
);
934 SafeFileNames
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
937 if (!SafeFileNames
.Buffer
)
939 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
943 /* Check buffers and copy pwszFiles to safe unicode string */
946 ProbeForRead(pwszFiles
, cbStringSize
, 1);
947 ProbeForWrite(pdwBytes
, sizeof(DWORD
), 1);
948 ProbeForWrite(pvBuf
, cjIn
, 1);
950 RtlCopyMemory(SafeFileNames
.Buffer
, pwszFiles
, cbStringSize
);
952 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
954 Status
= _SEH2_GetExceptionCode();
958 if(!NT_SUCCESS(Status
))
960 SetLastNtError(Status
);
961 /* Free the string buffer for the safe filename */
962 ExFreePoolWithTag(SafeFileNames
.Buffer
,'RTSU');
966 /* Do the actual call */
967 bRet
= IntGdiGetFontResourceInfo(&SafeFileNames
, &Buffer
, &dwBytes
, dwType
);
969 /* Check if succeeded and the buffer is big enough */
970 if (bRet
&& cjIn
>= dwBytes
)
972 /* Copy the data back to caller */
975 /* Buffers are already probed */
976 RtlCopyMemory(pvBuf
, &Buffer
, dwBytes
);
979 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
981 Status
= _SEH2_GetExceptionCode();
985 if(!NT_SUCCESS(Status
))
987 SetLastNtError(Status
);
992 /* Free the string for the safe filenames */
993 ExFreePoolWithTag(SafeFileNames
.Buffer
,'RTSU');
1003 NtGdiGetRealizationInfo(
1005 OUT PREALIZATION_INFO pri
,
1014 REALIZATION_INFO ri
;
1016 pDc
= DC_LockDc(hdc
);
1019 EngSetLastError(ERROR_INVALID_HANDLE
);
1022 pdcattr
= pDc
->pdcattr
;
1023 pTextObj
= RealizeFontInit(pdcattr
->hlfntNew
);
1024 pFontGdi
= ObjToGDI(pTextObj
->Font
, FONT
);
1025 TEXTOBJ_UnlockText(pTextObj
);
1028 Ret
= ftGdiRealizationInfo(pFontGdi
, &ri
);
1033 NTSTATUS Status
= STATUS_SUCCESS
;
1036 ProbeForWrite(pri
, sizeof(REALIZATION_INFO
), 1);
1037 RtlCopyMemory(pri
, &ri
, sizeof(REALIZATION_INFO
));
1039 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1041 Status
= _SEH2_GetExceptionCode();
1045 if(!NT_SUCCESS(Status
))
1047 SetLastNtError(Status
);
1053 if (GdiHandleTable
->cfPublic
[i
].hf
== hf
)
1055 GdiHandleTable
->cfPublic
[i
].iTechnology
= ri
.iTechnology
;
1056 GdiHandleTable
->cfPublic
[i
].iUniq
= ri
.iUniq
;
1057 GdiHandleTable
->cfPublic
[i
].dwUnknown
= ri
.dwUnknown
;
1058 GdiHandleTable
->cfPublic
[i
].dwCFCount
= GdiHandleTable
->dwCFCount
;
1059 GdiHandleTable
->cfPublic
[i
].fl
|= CFONT_REALIZATION
;
1063 while ( i
< GDI_CFONT_MAX
);
1071 IN PENUMLOGFONTEXDVW pelfw
,
1075 IN PVOID pvCliData
)
1077 ENUMLOGFONTEXDVW SafeLogfont
;
1080 NTSTATUS Status
= STATUS_SUCCESS
;
1082 /* Silence GCC warnings */
1083 SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfEscapement
= 0;
1084 SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfOrientation
= 0;
1093 ProbeForRead(pelfw
, sizeof(ENUMLOGFONTEXDVW
), 1);
1094 RtlCopyMemory(&SafeLogfont
, pelfw
, sizeof(ENUMLOGFONTEXDVW
));
1096 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1098 Status
= _SEH2_GetExceptionCode();
1102 if (!NT_SUCCESS(Status
))
1107 TextObj
= TEXTOBJ_AllocTextWithHandle();
1112 hNewFont
= TextObj
->BaseObject
.hHmgr
;
1116 RtlCopyMemory (&TextObj
->logfont
, &SafeLogfont
, sizeof(ENUMLOGFONTEXDVW
));
1118 if (SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfEscapement
!=
1119 SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfOrientation
)
1121 /* this should really depend on whether GM_ADVANCED is set */
1122 TextObj
->logfont
.elfEnumLogfontEx
.elfLogFont
.lfOrientation
=
1123 TextObj
->logfont
.elfEnumLogfontEx
.elfLogFont
.lfEscapement
;
1125 TEXTOBJ_UnlockText(TextObj
);
1127 if (pvCliData
&& hNewFont
)
1129 // FIXME: use GDIOBJ_InsertUserData
1130 KeEnterCriticalRegion();
1132 INT Index
= GDI_HANDLE_GET_INDEX((HGDIOBJ
)hNewFont
);
1133 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
1134 Entry
->UserData
= pvCliData
;
1136 KeLeaveCriticalRegion();
1151 return GreSelectFont(hDC
, hFont
);