2 * PROJECT: ReactOS win32 kernel mode subsystem
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: win32ss/gdi/ntgdi/font.c
6 * PROGRAMMERS: James Tabor <james.tabor@reactos.org>
7 * Timo Kreuzer <timo.kreuzer@reactos.org>
8 * Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
11 /** Includes ******************************************************************/
18 HFONT APIENTRY
HfontCreate( IN PENUMLOGFONTEXDVW pelfw
,IN ULONG cjElfw
,IN LFTYPE lft
,IN FLONG fl
,IN PVOID pvCliData
);
20 /** Internal ******************************************************************/
23 GreCreateFontIndirectW( LOGFONTW
*lplf
)
27 ENUMLOGFONTEXDVW Logfont
;
29 RtlCopyMemory( &Logfont
.elfEnumLogfontEx
.elfLogFont
, lplf
, sizeof(LOGFONTW
));
30 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfFullName
,
31 sizeof(Logfont
.elfEnumLogfontEx
.elfFullName
));
32 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfStyle
,
33 sizeof(Logfont
.elfEnumLogfontEx
.elfStyle
));
34 RtlZeroMemory( &Logfont
.elfEnumLogfontEx
.elfScript
,
35 sizeof(Logfont
.elfEnumLogfontEx
.elfScript
));
37 Logfont
.elfDesignVector
.dvNumAxes
= 0;
39 RtlZeroMemory( &Logfont
.elfDesignVector
, sizeof(DESIGNVECTOR
));
41 return HfontCreate((PENUMLOGFONTEXDVW
)&Logfont
, 0, 0, 0, NULL
);
51 LPKERNINGPAIR krnpair
)
63 EngSetLastError(ERROR_INVALID_HANDLE
);
67 pdcattr
= dc
->pdcattr
;
68 TextObj
= RealizeFontInit(pdcattr
->hlfntNew
);
73 EngSetLastError(ERROR_INVALID_HANDLE
);
77 FontGDI
= ObjToGDI(TextObj
->Font
, FONT
);
78 TEXTOBJ_UnlockText(TextObj
);
80 Count
= ftGdiGetKerningPairs(FontGDI
,0,NULL
);
82 if ( Count
&& krnpair
)
86 EngSetLastError(ERROR_INSUFFICIENT_BUFFER
);
89 pKP
= ExAllocatePoolWithTag(PagedPool
, Count
* sizeof(KERNINGPAIR
), GDITAG_TEXT
);
92 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
95 ftGdiGetKerningPairs(FontGDI
,Count
,pKP
);
97 RtlCopyMemory(krnpair
, pKP
, Count
* sizeof(KERNINGPAIR
));
99 ExFreePoolWithTag(pKP
,GDITAG_TEXT
);
106 It is recommended that an application use the GetFontLanguageInfo function
107 to determine whether the GCP_DIACRITIC, GCP_DBCS, GCP_USEKERNING, GCP_LIGATE,
108 GCP_REORDER, GCP_GLYPHSHAPE, and GCP_KASHIDA values are valid for the
109 currently selected font. If not valid, GetCharacterPlacement ignores the
112 MS must use a preset "compiled in" support for each language based releases.
113 ReactOS uses FreeType, this will need to be supported. ATM this is hard coded
120 GreGetCharacterPlacementW(
125 LPGCP_RESULTSW pgcpw
,
128 GCP_RESULTSW gcpwSave
;
134 DPRINT1("GreGCPW Start\n");
138 if (GreGetTextExtentW( hdc
, pwsz
, nCount
, &Size
, 1))
139 return MAKELONG(Size
.cx
, Size
.cy
);
143 DPRINT1("GreGCPW 1\n");
145 RtlCopyMemory(&gcpwSave
, pgcpw
, sizeof(GCP_RESULTSW
));
147 cSet
= nSet
= nCount
;
149 if ( nCount
> gcpwSave
.nGlyphs
) cSet
= gcpwSave
.nGlyphs
;
151 /* GCP_JUSTIFY may only be used in conjunction with GCP_MAXEXTENT. */
152 if ( dwFlags
& GCP_JUSTIFY
) dwFlags
|= GCP_MAXEXTENT
;
154 if ( !gcpwSave
.lpDx
&& gcpwSave
.lpCaretPos
)
155 tmpDxCaretPos
= gcpwSave
.lpCaretPos
;
157 tmpDxCaretPos
= gcpwSave
.lpDx
;
159 if ( !GreGetTextExtentExW( hdc
,
163 ((dwFlags
& GCP_MAXEXTENT
) ? (PULONG
) &cSet
: NULL
),
164 (PULONG
) tmpDxCaretPos
,
171 DPRINT1("GreGCPW 2\n");
175 if ( tmpDxCaretPos
&& nSet
> 0)
177 for (i
= (nSet
- 1); i
> 0; i
--)
179 tmpDxCaretPos
[i
] -= tmpDxCaretPos
[i
- 1];
183 if ( !(dwFlags
& GCP_MAXEXTENT
) || nSet
)
185 if ( (dwFlags
& GCP_USEKERNING
) &&
187 gcpwSave
.lpCaretPos
) &&
193 Count
= GreGetKerningPairs( hdc
, 0, NULL
);
196 pKP
= ExAllocatePoolWithTag(PagedPool
, Count
* sizeof(KERNINGPAIR
), GDITAG_TEXT
);
199 if ( GreGetKerningPairs( hdc
, Count
, pKP
) != Count
)
201 ExFreePoolWithTag( pKP
, GDITAG_TEXT
);
205 if ( (ULONG_PTR
)(pKP
) < ((ULONG_PTR
)(pKP
) + (ULONG_PTR
)(Count
* sizeof(KERNINGPAIR
))) )
207 DPRINT1("We Need to Do Something HERE!\n");
210 ExFreePoolWithTag( pKP
, GDITAG_TEXT
);
212 if ( dwFlags
& GCP_MAXEXTENT
)
214 if ( Size
.cx
> nMaxExtent
)
216 for (Cx
= Size
.cx
; nSet
> 0; nSet
--)
218 Cx
-= tmpDxCaretPos
[nSet
- 1];
220 if ( Cx
<= nMaxExtent
) break;
234 if ( (dwFlags
& GCP_JUSTIFY
) &&
236 gcpwSave
.lpCaretPos
) &&
239 DPRINT1("We Need to Do Something HERE 2!\n");
242 if ( gcpwSave
.lpDx
&& gcpwSave
.lpCaretPos
)
243 RtlCopyMemory( gcpwSave
.lpCaretPos
, gcpwSave
.lpDx
, nSet
* sizeof(LONG
));
245 if ( gcpwSave
.lpCaretPos
)
253 Cx
= gcpwSave
.lpCaretPos
[i
];
254 gcpwSave
.lpCaretPos
[i
] = pos
;
262 if ( gcpwSave
.lpOutString
)
263 RtlCopyMemory(gcpwSave
.lpOutString
, pwsz
, nSet
* sizeof(WCHAR
));
265 if ( gcpwSave
.lpClass
)
266 RtlFillMemory(gcpwSave
.lpClass
, nSet
, GCPCLASS_LATIN
);
268 if ( gcpwSave
.lpOrder
)
270 for (i
= 0; i
< nSet
; i
++)
271 gcpwSave
.lpOrder
[i
] = i
;
274 if ( gcpwSave
.lpGlyphs
)
276 if ( GreGetGlyphIndicesW( hdc
, pwsz
, nSet
, gcpwSave
.lpGlyphs
, 0, 0) == GDI_ERROR
)
283 pgcpw
->nGlyphs
= nSet
;
284 pgcpw
->nMaxFit
= nSet
;
286 DPRINT1("GreGCPW Exit\n");
287 return MAKELONG(Size
.cx
, Size
.cy
);
293 FontGetObject(PTEXTOBJ plfont
, ULONG cjBuffer
, PVOID pvBuffer
)
296 ENUMLOGFONTEXDVW
*plf
;
299 plf
= &plfont
->logfont
;
301 if (!(plfont
->fl
& TEXTOBJECT_INIT
))
304 DPRINT1("FontGetObject font not initialized!\n");
306 Status
= TextIntRealizeFont(plfont
->BaseObject
.hHmgr
, plfont
);
307 if (!NT_SUCCESS(Status
))
309 DPRINT1("FontGetObject(TextIntRealizeFont) Status = 0x%lx\n", Status
);
313 /* If buffer is NULL, only the size is requested */
314 if (pvBuffer
== NULL
) return sizeof(LOGFONTW
);
316 /* Calculate the maximum size according to number of axes */
317 cjMaxSize
= FIELD_OFFSET(ENUMLOGFONTEXDVW
,
318 elfDesignVector
.dvValues
[plf
->elfDesignVector
.dvNumAxes
]);
320 if (cjBuffer
> cjMaxSize
) cjBuffer
= cjMaxSize
;
322 RtlCopyMemory(pvBuffer
, plf
, cjBuffer
);
329 IntGetCharDimensions(HDC hdc
, PTEXTMETRICW ptm
, PDWORD height
)
338 static const WCHAR alphabet
[] = {
339 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
340 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
341 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
343 if(!ftGdiGetTextMetricsW(hdc
, &tmwi
)) return 0;
345 pdc
= DC_LockDc(hdc
);
349 pdcattr
= pdc
->pdcattr
;
351 TextObj
= RealizeFontInit(pdcattr
->hlfntNew
);
357 Good
= TextIntGetTextExtentPoint(pdc
, TextObj
, alphabet
, 52, 0, NULL
, 0, &sz
, 0);
358 TEXTOBJ_UnlockText(TextObj
);
362 if (ptm
) *ptm
= tmwi
.TextMetric
;
363 if (height
) *height
= tmwi
.TextMetric
.tmHeight
;
365 return (sz
.cx
/ 26 + 1) / 2;
371 IntGetFontLanguageInfo(PDC Dc
)
374 FONTSIGNATURE fontsig
;
375 static const DWORD GCP_DBCS_MASK
=0x003F0000,
376 GCP_DIACRITIC_MASK
=0x00000000,
377 FLI_GLYPHS_MASK
=0x00000000,
378 GCP_GLYPHSHAPE_MASK
=0x00000040,
379 GCP_KASHIDA_MASK
=0x00000000,
380 GCP_LIGATE_MASK
=0x00000000,
381 GCP_USEKERNING_MASK
=0x00000000,
382 GCP_REORDER_MASK
=0x00000060;
386 ftGdiGetTextCharsetInfo( Dc
, &fontsig
, 0 );
388 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
389 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
392 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
393 result
|=GCP_DIACRITIC
;
395 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
398 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
399 result
|=GCP_GLYPHSHAPE
;
401 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
404 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
407 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
408 result
|=GCP_USEKERNING
;
410 pdcattr
= Dc
->pdcattr
;
412 /* This might need a test for a HEBREW- or ARABIC_CHARSET as well */
413 if ( pdcattr
->flTextAlign
& TA_RTLREADING
)
414 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
422 RealizeFontInit(HFONT hFont
)
424 NTSTATUS Status
= STATUS_SUCCESS
;
427 pTextObj
= TEXTOBJ_LockText(hFont
);
429 if ( pTextObj
&& !(pTextObj
->fl
& TEXTOBJECT_INIT
))
431 Status
= TextIntRealizeFont(hFont
, pTextObj
);
432 if (!NT_SUCCESS(Status
))
434 TEXTOBJ_UnlockText(pTextObj
);
442 /** Functions ******************************************************************/
446 NtGdiAddFontResourceW(
452 IN OPTIONAL DESIGNVECTOR
*pdv
)
454 UNICODE_STRING SafeFileName
;
457 DBG_UNREFERENCED_PARAMETER(cFiles
);
458 DBG_UNREFERENCED_PARAMETER(dwPidTid
);
459 DBG_UNREFERENCED_PARAMETER(pdv
);
461 DPRINT("NtGdiAddFontResourceW\n");
463 /* cwc = Length + trailing zero. */
464 if ((cwc
<= 1) || (cwc
> UNICODE_STRING_MAX_CHARS
))
467 SafeFileName
.MaximumLength
= (USHORT
)(cwc
* sizeof(WCHAR
));
468 SafeFileName
.Length
= SafeFileName
.MaximumLength
- sizeof(UNICODE_NULL
);
469 SafeFileName
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
470 SafeFileName
.MaximumLength
,
472 if (!SafeFileName
.Buffer
)
479 ProbeForRead(pwcFiles
, cwc
* sizeof(WCHAR
), sizeof(WCHAR
));
480 RtlCopyMemory(SafeFileName
.Buffer
, pwcFiles
, SafeFileName
.Length
);
482 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
484 ExFreePoolWithTag(SafeFileName
.Buffer
, TAG_STRING
);
485 _SEH2_YIELD(return 0);
489 SafeFileName
.Buffer
[SafeFileName
.Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
490 Ret
= IntGdiAddFontResource(&SafeFileName
, fl
);
492 ExFreePoolWithTag(SafeFileName
.Buffer
, TAG_STRING
);
498 NtGdiAddFontMemResourceEx(
501 IN DESIGNVECTOR
*pdv
,
503 OUT DWORD
*pNumFonts
)
505 _SEH2_VOLATILE PVOID Buffer
= NULL
;
509 DPRINT("NtGdiAddFontMemResourceEx\n");
510 DBG_UNREFERENCED_PARAMETER(pdv
);
511 DBG_UNREFERENCED_PARAMETER(cjDV
);
513 if (!pvBuffer
|| !cjBuffer
)
518 ProbeForRead(pvBuffer
, cjBuffer
, sizeof(BYTE
));
519 Buffer
= ExAllocatePoolWithQuotaTag(PagedPool
, cjBuffer
, TAG_FONT
);
520 RtlCopyMemory(Buffer
, pvBuffer
, cjBuffer
);
522 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
526 ExFreePoolWithTag(Buffer
, TAG_FONT
);
528 _SEH2_YIELD(return NULL
);
532 Ret
= IntGdiAddFontMemResource(Buffer
, cjBuffer
, &NumFonts
);
533 ExFreePoolWithTag(Buffer
, TAG_FONT
);
537 ProbeForWrite(pNumFonts
, sizeof(NumFonts
), 1);
538 *pNumFonts
= NumFonts
;
540 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
543 _SEH2_YIELD(return NULL
);
554 NtGdiRemoveFontMemResourceEx(
557 return IntGdiRemoveFontMemResource(hMMFont
);
566 NtGdiGetCharacterPlacementW(
571 IN OUT LPGCP_RESULTSW pgcpw
,
577 return GreGetCharacterPlacementW( hdc
,
600 DWORD Result
= GDI_ERROR
;
601 NTSTATUS Status
= STATUS_SUCCESS
;
607 ProbeForRead(Buffer
, Size
, 1);
609 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
611 Status
= _SEH2_GetExceptionCode();
616 if (!NT_SUCCESS(Status
)) return Result
;
621 EngSetLastError(ERROR_INVALID_HANDLE
);
624 pdcattr
= Dc
->pdcattr
;
626 hFont
= pdcattr
->hlfntNew
;
627 TextObj
= RealizeFontInit(hFont
);
632 EngSetLastError(ERROR_INVALID_HANDLE
);
636 FontGdi
= ObjToGDI(TextObj
->Font
, FONT
);
638 Result
= ftGdiGetFontData(FontGdi
, Table
, Offset
, Buffer
, Size
);
640 TEXTOBJ_UnlockText(TextObj
);
650 NtGdiGetFontUnicodeRanges(
652 OUT OPTIONAL LPGLYPHSET pgs
)
661 NTSTATUS Status
= STATUS_SUCCESS
;
663 pDc
= DC_LockDc(hdc
);
666 EngSetLastError(ERROR_INVALID_HANDLE
);
670 pdcattr
= pDc
->pdcattr
;
672 hFont
= pdcattr
->hlfntNew
;
673 TextObj
= RealizeFontInit(hFont
);
675 if ( TextObj
== NULL
)
677 EngSetLastError(ERROR_INVALID_HANDLE
);
680 FontGdi
= ObjToGDI(TextObj
->Font
, FONT
);
682 Size
= ftGetFontUnicodeRanges( FontGdi
, NULL
);
686 pgsSafe
= ExAllocatePoolWithTag(PagedPool
, Size
, GDITAG_TEXT
);
689 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
694 Size
= ftGetFontUnicodeRanges( FontGdi
, pgsSafe
);
700 ProbeForWrite(pgs
, Size
, 1);
701 RtlCopyMemory(pgs
, pgsSafe
, Size
);
703 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
705 Status
= _SEH2_GetExceptionCode();
709 if (!NT_SUCCESS(Status
)) Size
= 0;
711 ExFreePoolWithTag(pgsSafe
, GDITAG_TEXT
);
714 TEXTOBJ_UnlockText(TextObj
);
721 NtGdiGetGlyphOutline(
725 OUT LPGLYPHMETRICS pgm
,
727 OUT OPTIONAL PVOID UnsafeBuf
,
729 IN BOOL bIgnoreRotation
)
731 ULONG Ret
= GDI_ERROR
;
735 NTSTATUS Status
= STATUS_SUCCESS
;
740 EngSetLastError(ERROR_INVALID_HANDLE
);
744 if (UnsafeBuf
&& cjBuf
)
746 pvBuf
= ExAllocatePoolWithTag(PagedPool
, cjBuf
, GDITAG_TEXT
);
749 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
754 Ret
= ftGdiGetGlyphOutline( dc
,
767 ProbeForWrite(UnsafeBuf
, cjBuf
, 1);
768 RtlCopyMemory(UnsafeBuf
, pvBuf
, cjBuf
);
770 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
772 Status
= _SEH2_GetExceptionCode();
776 ExFreePoolWithTag(pvBuf
, GDITAG_TEXT
);
783 ProbeForWrite(pgm
, sizeof(GLYPHMETRICS
), 1);
784 RtlCopyMemory(pgm
, &gm
, sizeof(GLYPHMETRICS
));
786 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
788 Status
= _SEH2_GetExceptionCode();
793 if (! NT_SUCCESS(Status
))
795 EngSetLastError(ERROR_INVALID_PARAMETER
);
806 NtGdiGetKerningPairs(HDC hDC
,
808 LPKERNINGPAIR krnpair
)
816 NTSTATUS Status
= STATUS_SUCCESS
;
821 EngSetLastError(ERROR_INVALID_HANDLE
);
825 pdcattr
= dc
->pdcattr
;
826 TextObj
= RealizeFontInit(pdcattr
->hlfntNew
);
831 EngSetLastError(ERROR_INVALID_HANDLE
);
835 FontGDI
= ObjToGDI(TextObj
->Font
, FONT
);
836 TEXTOBJ_UnlockText(TextObj
);
838 Count
= ftGdiGetKerningPairs(FontGDI
,0,NULL
);
840 if ( Count
&& krnpair
)
842 if (Count
> NumPairs
)
844 EngSetLastError(ERROR_INSUFFICIENT_BUFFER
);
847 pKP
= ExAllocatePoolWithTag(PagedPool
, Count
* sizeof(KERNINGPAIR
), GDITAG_TEXT
);
850 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
853 ftGdiGetKerningPairs(FontGDI
,Count
,pKP
);
856 ProbeForWrite(krnpair
, Count
* sizeof(KERNINGPAIR
), 1);
857 RtlCopyMemory(krnpair
, pKP
, Count
* sizeof(KERNINGPAIR
));
859 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
861 Status
= _SEH2_GetExceptionCode();
864 if (!NT_SUCCESS(Status
))
866 EngSetLastError(ERROR_INVALID_PARAMETER
);
869 ExFreePoolWithTag(pKP
,GDITAG_TEXT
);
875 From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page
876 472, this is NtGdiGetOutlineTextMetricsInternalW.
880 NtGdiGetOutlineTextMetricsInternalW (HDC hDC
,
882 OUTLINETEXTMETRICW
*otm
,
891 OUTLINETEXTMETRICW
*potm
;
892 NTSTATUS Status
= STATUS_SUCCESS
;
897 EngSetLastError(ERROR_INVALID_HANDLE
);
900 pdcattr
= dc
->pdcattr
;
901 hFont
= pdcattr
->hlfntNew
;
902 TextObj
= RealizeFontInit(hFont
);
906 EngSetLastError(ERROR_INVALID_HANDLE
);
909 FontGDI
= ObjToGDI(TextObj
->Font
, FONT
);
910 TextIntUpdateSize(dc
, TextObj
, FontGDI
, TRUE
);
911 TEXTOBJ_UnlockText(TextObj
);
912 Size
= IntGetOutlineTextMetrics(FontGDI
, 0, NULL
);
913 if (!otm
) return Size
;
916 EngSetLastError(ERROR_INSUFFICIENT_BUFFER
);
919 potm
= ExAllocatePoolWithTag(PagedPool
, Size
, GDITAG_TEXT
);
922 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
925 IntGetOutlineTextMetrics(FontGDI
, Size
, potm
);
930 ProbeForWrite(otm
, Size
, 1);
931 RtlCopyMemory(otm
, potm
, Size
);
933 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
935 Status
= _SEH2_GetExceptionCode();
939 if (!NT_SUCCESS(Status
))
941 EngSetLastError(ERROR_INVALID_PARAMETER
);
945 ExFreePoolWithTag(potm
,GDITAG_TEXT
);
952 NtGdiGetFontResourceInfoInternalW(
957 IN OUT LPDWORD pdwBytes
,
961 NTSTATUS Status
= STATUS_SUCCESS
;
962 DWORD dwBytes
, dwBytesRequested
;
963 UNICODE_STRING SafeFileNames
;
968 /* FIXME: Handle cFiles > 0 */
970 /* Check for valid dwType values */
973 EngSetLastError(ERROR_INVALID_PARAMETER
);
977 /* Allocate a safe unicode string buffer */
978 cbStringSize
= cwc
* sizeof(WCHAR
);
979 SafeFileNames
.MaximumLength
= SafeFileNames
.Length
= (USHORT
)cbStringSize
- sizeof(WCHAR
);
980 SafeFileNames
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
983 if (!SafeFileNames
.Buffer
)
985 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
988 RtlZeroMemory(SafeFileNames
.Buffer
, SafeFileNames
.MaximumLength
);
990 /* Check buffers and copy pwszFiles to safe unicode string */
993 ProbeForRead(pwszFiles
, cbStringSize
, 1);
994 ProbeForWrite(pdwBytes
, sizeof(DWORD
), 1);
996 ProbeForWrite(pvBuf
, cjIn
, 1);
999 dwBytesRequested
= dwBytes
;
1001 RtlCopyMemory(SafeFileNames
.Buffer
, pwszFiles
, cbStringSize
);
1004 Buffer
= ExAllocatePoolWithTag(PagedPool
, dwBytes
, TAG_FINF
);
1008 Buffer
= ExAllocatePoolWithTag(PagedPool
, sizeof(DWORD
), TAG_FINF
);
1011 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1013 Status
= _SEH2_GetExceptionCode();
1017 if(!NT_SUCCESS(Status
))
1019 SetLastNtError(Status
);
1020 /* Free the string buffer for the safe filename */
1021 ExFreePoolWithTag(SafeFileNames
.Buffer
, TAG_USTR
);
1025 /* Do the actual call */
1026 bRet
= IntGdiGetFontResourceInfo(&SafeFileNames
,
1027 (pvBuf
? Buffer
: NULL
),
1030 /* Check if succeeded */
1033 /* Copy the data back to caller */
1036 /* Buffers are already probed */
1037 if (pvBuf
&& dwBytesRequested
> 0)
1038 RtlCopyMemory(pvBuf
, Buffer
, min(dwBytesRequested
, dwBytes
));
1039 *pdwBytes
= dwBytes
;
1041 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1043 Status
= _SEH2_GetExceptionCode();
1047 if(!NT_SUCCESS(Status
))
1049 SetLastNtError(Status
);
1054 ExFreePoolWithTag(Buffer
, TAG_FINF
);
1055 /* Free the string for the safe filenames */
1056 ExFreePoolWithTag(SafeFileNames
.Buffer
, TAG_USTR
);
1066 NtGdiGetRealizationInfo(
1068 OUT PREALIZATION_INFO pri
,
1077 REALIZATION_INFO ri
;
1079 pDc
= DC_LockDc(hdc
);
1082 EngSetLastError(ERROR_INVALID_HANDLE
);
1085 pdcattr
= pDc
->pdcattr
;
1086 pTextObj
= RealizeFontInit(pdcattr
->hlfntNew
);
1087 ASSERT(pTextObj
!= NULL
);
1088 pFontGdi
= ObjToGDI(pTextObj
->Font
, FONT
);
1089 TEXTOBJ_UnlockText(pTextObj
);
1092 Ret
= ftGdiRealizationInfo(pFontGdi
, &ri
);
1097 NTSTATUS Status
= STATUS_SUCCESS
;
1100 ProbeForWrite(pri
, sizeof(REALIZATION_INFO
), 1);
1101 RtlCopyMemory(pri
, &ri
, sizeof(REALIZATION_INFO
));
1103 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1105 Status
= _SEH2_GetExceptionCode();
1109 if(!NT_SUCCESS(Status
))
1111 SetLastNtError(Status
);
1117 if (GdiHandleTable
->cfPublic
[i
].hf
== hf
)
1119 GdiHandleTable
->cfPublic
[i
].iTechnology
= ri
.iTechnology
;
1120 GdiHandleTable
->cfPublic
[i
].iUniq
= ri
.iUniq
;
1121 GdiHandleTable
->cfPublic
[i
].dwUnknown
= ri
.dwUnknown
;
1122 GdiHandleTable
->cfPublic
[i
].dwCFCount
= GdiHandleTable
->dwCFCount
;
1123 GdiHandleTable
->cfPublic
[i
].fl
|= CFONT_REALIZATION
;
1127 while ( i
< GDI_CFONT_MAX
);
1136 IN PENUMLOGFONTEXDVW pelfw
,
1140 IN PVOID pvCliData
)
1150 plfont
= LFONT_AllocFontWithHandle();
1155 hNewFont
= plfont
->BaseObject
.hHmgr
;
1159 RtlCopyMemory (&plfont
->logfont
, pelfw
, sizeof(ENUMLOGFONTEXDVW
));
1160 ExInitializePushLock(&plfont
->lock
);
1162 if (pelfw
->elfEnumLogfontEx
.elfLogFont
.lfEscapement
!=
1163 pelfw
->elfEnumLogfontEx
.elfLogFont
.lfOrientation
)
1165 /* This should really depend on whether GM_ADVANCED is set */
1166 plfont
->logfont
.elfEnumLogfontEx
.elfLogFont
.lfOrientation
=
1167 plfont
->logfont
.elfEnumLogfontEx
.elfLogFont
.lfEscapement
;
1169 LFONT_UnlockFont(plfont
);
1171 if (pvCliData
&& hNewFont
)
1173 // FIXME: Use GDIOBJ_InsertUserData
1174 KeEnterCriticalRegion();
1176 INT Index
= GDI_HANDLE_GET_INDEX((HGDIOBJ
)hNewFont
);
1177 PGDI_TABLE_ENTRY Entry
= &GdiHandleTable
->Entries
[Index
];
1178 Entry
->UserData
= pvCliData
;
1180 KeLeaveCriticalRegion();
1190 IN PENUMLOGFONTEXDVW pelfw
,
1194 IN PVOID pvCliData
)
1196 ENUMLOGFONTEXDVW SafeLogfont
;
1197 NTSTATUS Status
= STATUS_SUCCESS
;
1199 /* Silence GCC warnings */
1200 SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfEscapement
= 0;
1201 SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfOrientation
= 0;
1210 ProbeForRead(pelfw
, sizeof(ENUMLOGFONTEXDVW
), 1);
1211 RtlCopyMemory(&SafeLogfont
, pelfw
, sizeof(ENUMLOGFONTEXDVW
));
1213 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1215 Status
= _SEH2_GetExceptionCode();
1219 if (!NT_SUCCESS(Status
))
1224 return HfontCreate(&SafeLogfont
, cjElfw
, lft
, fl
, pvCliData
);