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 /** Internal ******************************************************************/
20 FontGetObject(PTEXTOBJ TFont
, INT Count
, PVOID Buffer
)
22 if( Buffer
== NULL
) return sizeof(LOGFONTW
);
26 case sizeof(ENUMLOGFONTEXDVW
):
27 RtlCopyMemory( (LPENUMLOGFONTEXDVW
) Buffer
,
29 sizeof(ENUMLOGFONTEXDVW
));
31 case sizeof(ENUMLOGFONTEXW
):
32 RtlCopyMemory( (LPENUMLOGFONTEXW
) Buffer
,
33 &TFont
->logfont
.elfEnumLogfontEx
,
34 sizeof(ENUMLOGFONTEXW
));
37 case sizeof(EXTLOGFONTW
):
38 case sizeof(ENUMLOGFONTW
):
39 RtlCopyMemory((LPENUMLOGFONTW
) Buffer
,
40 &TFont
->logfont
.elfEnumLogfontEx
.elfLogFont
,
41 sizeof(ENUMLOGFONTW
));
44 case sizeof(LOGFONTW
):
45 RtlCopyMemory((LPLOGFONTW
) Buffer
,
46 &TFont
->logfont
.elfEnumLogfontEx
.elfLogFont
,
51 SetLastWin32Error(ERROR_BUFFER_OVERFLOW
);
59 IntGetFontLanguageInfo(PDC Dc
)
62 FONTSIGNATURE fontsig
;
63 static const DWORD GCP_DBCS_MASK
=0x003F0000,
64 GCP_DIACRITIC_MASK
=0x00000000,
65 FLI_GLYPHS_MASK
=0x00000000,
66 GCP_GLYPHSHAPE_MASK
=0x00000040,
67 GCP_KASHIDA_MASK
=0x00000000,
68 GCP_LIGATE_MASK
=0x00000000,
69 GCP_USEKERNING_MASK
=0x00000000,
70 GCP_REORDER_MASK
=0x00000060;
74 ftGdiGetTextCharsetInfo( Dc
, &fontsig
, 0 );
76 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
77 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
80 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
81 result
|=GCP_DIACRITIC
;
83 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
86 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
87 result
|=GCP_GLYPHSHAPE
;
89 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
92 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
95 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
96 result
|=GCP_USEKERNING
;
98 Dc_Attr
= Dc
->pDc_Attr
;
99 if(!Dc_Attr
) Dc_Attr
= &Dc
->Dc_Attr
;
101 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
102 if ( Dc_Attr
->lTextAlign
& TA_RTLREADING
)
103 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
111 RealizeFontInit(HFONT hFont
)
113 NTSTATUS Status
= STATUS_SUCCESS
;
116 pTextObj
= TEXTOBJ_LockText(hFont
);
118 if ( pTextObj
&& !(pTextObj
->fl
& TEXTOBJECT_INIT
))
120 Status
= TextIntRealizeFont(hFont
, pTextObj
);
121 if (!NT_SUCCESS(Status
))
123 TEXTOBJ_UnlockText(pTextObj
);
130 /** Functions ******************************************************************/
134 NtGdiAddFontResourceW(
140 IN OPTIONAL DESIGNVECTOR
*pdv
)
142 UNICODE_STRING SafeFileName
;
147 /* FIXME - Protect with SEH? */
148 RtlInitUnicodeString(&SafeFileName
, pwszFiles
);
150 /* Reserve for prepending '\??\' */
151 SafeFileName
.Length
+= 4 * sizeof(WCHAR
);
152 SafeFileName
.MaximumLength
+= 4 * sizeof(WCHAR
);
154 src
= SafeFileName
.Buffer
;
155 SafeFileName
.Buffer
= (PWSTR
)ExAllocatePoolWithTag(PagedPool
, SafeFileName
.MaximumLength
, TAG_STRING
);
156 if(!SafeFileName
.Buffer
)
158 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
163 RtlCopyMemory(SafeFileName
.Buffer
, L
"\\??\\", 4 * sizeof(WCHAR
));
165 Status
= MmCopyFromCaller(SafeFileName
.Buffer
+ 4, src
, SafeFileName
.MaximumLength
- (4 * sizeof(WCHAR
)));
166 if(!NT_SUCCESS(Status
))
168 ExFreePoolWithTag(SafeFileName
.Buffer
, TAG_STRING
);
169 SetLastNtError(Status
);
173 Ret
= IntGdiAddFontResource(&SafeFileName
, (DWORD
)fl
);
175 ExFreePoolWithTag(SafeFileName
.Buffer
, TAG_STRING
);
193 DWORD Result
= GDI_ERROR
;
194 NTSTATUS Status
= STATUS_SUCCESS
;
200 ProbeForRead(Buffer
, Size
, 1);
202 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
204 Status
= _SEH2_GetExceptionCode();
209 if (!NT_SUCCESS(Status
)) return Result
;
214 SetLastWin32Error(ERROR_INVALID_HANDLE
);
217 Dc_Attr
= Dc
->pDc_Attr
;
218 if(!Dc_Attr
) Dc_Attr
= &Dc
->Dc_Attr
;
220 hFont
= Dc_Attr
->hlfntNew
;
221 TextObj
= RealizeFontInit(hFont
);
226 SetLastWin32Error(ERROR_INVALID_HANDLE
);
230 FontGdi
= ObjToGDI(TextObj
->Font
, FONT
);
232 Result
= ftGdiGetFontData(FontGdi
, Table
, Offset
, Buffer
, Size
);
234 TEXTOBJ_UnlockText(TextObj
);
244 NtGdiGetFontUnicodeRanges(
246 OUT OPTIONAL LPGLYPHSET pgs
)
255 NTSTATUS Status
= STATUS_SUCCESS
;
257 pDc
= DC_LockDc(hdc
);
260 SetLastWin32Error(ERROR_INVALID_HANDLE
);
264 Dc_Attr
= pDc
->pDc_Attr
;
265 if(!Dc_Attr
) Dc_Attr
= &pDc
->Dc_Attr
;
267 hFont
= Dc_Attr
->hlfntNew
;
268 TextObj
= RealizeFontInit(hFont
);
270 if ( TextObj
== NULL
)
272 SetLastWin32Error(ERROR_INVALID_HANDLE
);
275 FontGdi
= ObjToGDI(TextObj
->Font
, FONT
);
277 Size
= ftGetFontUnicodeRanges( FontGdi
, NULL
);
281 pgsSafe
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_GDITEXT
);
284 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
289 Size
= ftGetFontUnicodeRanges( FontGdi
, pgsSafe
);
295 ProbeForWrite(pgs
, Size
, 1);
296 RtlCopyMemory(pgs
, pgsSafe
, Size
);
298 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
300 Status
= _SEH2_GetExceptionCode();
304 if (!NT_SUCCESS(Status
)) Size
= 0;
306 ExFreePoolWithTag(pgsSafe
, TAG_GDITEXT
);
309 TEXTOBJ_UnlockText(TextObj
);
316 NtGdiGetGlyphOutline(
320 OUT LPGLYPHMETRICS pgm
,
322 OUT OPTIONAL PVOID UnsafeBuf
,
324 IN BOOL bIgnoreRotation
)
326 ULONG Ret
= GDI_ERROR
;
330 NTSTATUS Status
= STATUS_SUCCESS
;
335 SetLastWin32Error(ERROR_INVALID_HANDLE
);
339 if (UnsafeBuf
&& cjBuf
)
341 pvBuf
= ExAllocatePoolWithTag(PagedPool
, cjBuf
, TAG_GDITEXT
);
344 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
349 Ret
= ftGdiGetGlyphOutline( dc
,
362 ProbeForWrite(UnsafeBuf
, cjBuf
, 1);
363 RtlCopyMemory(UnsafeBuf
, pvBuf
, cjBuf
);
365 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
367 Status
= _SEH2_GetExceptionCode();
371 ExFreePoolWithTag(pvBuf
, TAG_GDITEXT
);
378 ProbeForWrite(pgm
, sizeof(GLYPHMETRICS
), 1);
379 RtlCopyMemory(pgm
, &gm
, sizeof(GLYPHMETRICS
));
381 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
383 Status
= _SEH2_GetExceptionCode();
388 if (! NT_SUCCESS(Status
))
390 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
401 NtGdiGetKerningPairs(HDC hDC
,
403 LPKERNINGPAIR krnpair
)
411 NTSTATUS Status
= STATUS_SUCCESS
;
416 SetLastWin32Error(ERROR_INVALID_HANDLE
);
420 Dc_Attr
= dc
->pDc_Attr
;
421 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
422 TextObj
= RealizeFontInit(Dc_Attr
->hlfntNew
);
427 SetLastWin32Error(ERROR_INVALID_HANDLE
);
431 FontGDI
= ObjToGDI(TextObj
->Font
, FONT
);
432 TEXTOBJ_UnlockText(TextObj
);
434 Count
= ftGdiGetKerningPairs(FontGDI
,0,NULL
);
436 if ( Count
&& krnpair
)
438 if (Count
> NumPairs
)
440 SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER
);
443 pKP
= ExAllocatePoolWithTag(PagedPool
, Count
* sizeof(KERNINGPAIR
), TAG_GDITEXT
);
446 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
449 ftGdiGetKerningPairs(FontGDI
,Count
,pKP
);
452 ProbeForWrite(krnpair
, Count
* sizeof(KERNINGPAIR
), 1);
453 RtlCopyMemory(krnpair
, pKP
, Count
* sizeof(KERNINGPAIR
));
455 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
457 Status
= _SEH2_GetExceptionCode();
460 if (!NT_SUCCESS(Status
))
462 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
465 ExFreePoolWithTag(pKP
,TAG_GDITEXT
);
471 From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page
472 472, this is NtGdiGetOutlineTextMetricsInternalW.
476 NtGdiGetOutlineTextMetricsInternalW (HDC hDC
,
478 OUTLINETEXTMETRICW
*otm
,
487 OUTLINETEXTMETRICW
*potm
;
488 NTSTATUS Status
= STATUS_SUCCESS
;
493 SetLastWin32Error(ERROR_INVALID_HANDLE
);
496 Dc_Attr
= dc
->pDc_Attr
;
497 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
498 hFont
= Dc_Attr
->hlfntNew
;
499 TextObj
= RealizeFontInit(hFont
);
503 SetLastWin32Error(ERROR_INVALID_HANDLE
);
506 FontGDI
= ObjToGDI(TextObj
->Font
, FONT
);
507 TEXTOBJ_UnlockText(TextObj
);
508 Size
= IntGetOutlineTextMetrics(FontGDI
, 0, NULL
);
509 if (!otm
) return Size
;
512 SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER
);
515 potm
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_GDITEXT
);
518 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
521 IntGetOutlineTextMetrics(FontGDI
, Size
, potm
);
526 ProbeForWrite(otm
, Size
, 1);
527 RtlCopyMemory(otm
, potm
, Size
);
529 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
531 Status
= _SEH2_GetExceptionCode();
535 if (!NT_SUCCESS(Status
))
537 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
541 ExFreePoolWithTag(potm
,TAG_GDITEXT
);
548 NtGdiGetFontResourceInfoInternalW(
553 OUT LPDWORD pdwBytes
,
557 NTSTATUS Status
= STATUS_SUCCESS
;
559 UNICODE_STRING SafeFileNames
;
566 WCHAR FullName
[LF_FULLFACESIZE
];
569 /* FIXME: handle cFiles > 0 */
571 /* Check for valid dwType values
572 dwType == 4 seems to be handled by gdi32 only */
573 if (dwType
== 4 || dwType
> 5)
575 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
579 /* Allocate a safe unicode string buffer */
580 cbStringSize
= cwc
* sizeof(WCHAR
);
581 SafeFileNames
.MaximumLength
= SafeFileNames
.Length
= cbStringSize
- sizeof(WCHAR
);
582 SafeFileNames
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
584 TAG('R','T','S','U'));
585 if (!SafeFileNames
.Buffer
)
587 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
591 /* Check buffers and copy pwszFiles to safe unicode string */
594 ProbeForRead(pwszFiles
, cbStringSize
, 1);
595 ProbeForWrite(pdwBytes
, sizeof(DWORD
), 1);
596 ProbeForWrite(pvBuf
, cjIn
, 1);
598 RtlCopyMemory(SafeFileNames
.Buffer
, pwszFiles
, cbStringSize
);
600 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
602 Status
= _SEH2_GetExceptionCode();
606 if(!NT_SUCCESS(Status
))
608 SetLastNtError(Status
);
609 /* Free the string buffer for the safe filename */
610 ExFreePoolWithTag(SafeFileNames
.Buffer
,TAG('R','T','S','U'));
614 /* Do the actual call */
615 bRet
= IntGdiGetFontResourceInfo(&SafeFileNames
, &Buffer
, &dwBytes
, dwType
);
617 /* Check if succeeded and the buffer is big enough */
618 if (bRet
&& cjIn
>= dwBytes
)
620 /* Copy the data back to caller */
623 /* Buffers are already probed */
624 RtlCopyMemory(pvBuf
, &Buffer
, dwBytes
);
627 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
629 Status
= _SEH2_GetExceptionCode();
633 if(!NT_SUCCESS(Status
))
635 SetLastNtError(Status
);
640 /* Free the string for the safe filenames */
641 ExFreePoolWithTag(SafeFileNames
.Buffer
,TAG('R','T','S','U'));
651 NtGdiGetRealizationInfo(
653 OUT PREALIZATION_INFO pri
,
664 pDc
= DC_LockDc(hdc
);
667 SetLastWin32Error(ERROR_INVALID_HANDLE
);
670 Dc_Attr
= pDc
->pDc_Attr
;
671 if(!Dc_Attr
) Dc_Attr
= &pDc
->Dc_Attr
;
672 pTextObj
= RealizeFontInit(Dc_Attr
->hlfntNew
);
673 pFontGdi
= ObjToGDI(pTextObj
->Font
, FONT
);
674 TEXTOBJ_UnlockText(pTextObj
);
677 Ret
= ftGdiRealizationInfo(pFontGdi
, &ri
);
682 NTSTATUS Status
= STATUS_SUCCESS
;
685 ProbeForWrite(pri
, sizeof(REALIZATION_INFO
), 1);
686 RtlCopyMemory(pri
, &ri
, sizeof(REALIZATION_INFO
));
688 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
690 Status
= _SEH2_GetExceptionCode();
694 if(!NT_SUCCESS(Status
))
696 SetLastNtError(Status
);
702 if (GdiHandleTable
->cfPublic
[i
].hf
== hf
)
704 GdiHandleTable
->cfPublic
[i
].iTechnology
= ri
.iTechnology
;
705 GdiHandleTable
->cfPublic
[i
].iUniq
= ri
.iUniq
;
706 GdiHandleTable
->cfPublic
[i
].dwUnknown
= ri
.dwUnknown
;
707 GdiHandleTable
->cfPublic
[i
].dwCFCount
= GdiHandleTable
->dwCFCount
;
708 GdiHandleTable
->cfPublic
[i
].fl
|= CFONT_REALIZATION
;
712 while ( i
< GDI_CFONT_MAX
);
720 IN PENUMLOGFONTEXDVW pelfw
,
726 ENUMLOGFONTEXDVW SafeLogfont
;
729 NTSTATUS Status
= STATUS_SUCCESS
;
731 /* Silence GCC warnings */
732 SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfEscapement
= 0;
733 SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfOrientation
= 0;
742 ProbeForRead(pelfw
, sizeof(ENUMLOGFONTEXDVW
), 1);
743 RtlCopyMemory(&SafeLogfont
, pelfw
, sizeof(ENUMLOGFONTEXDVW
));
745 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
747 Status
= _SEH2_GetExceptionCode();
751 if (!NT_SUCCESS(Status
))
756 TextObj
= TEXTOBJ_AllocTextWithHandle();
761 hNewFont
= TextObj
->BaseObject
.hHmgr
;
765 RtlCopyMemory (&TextObj
->logfont
, &SafeLogfont
, sizeof(ENUMLOGFONTEXDVW
));
767 if (SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfEscapement
!=
768 SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfOrientation
)
770 /* this should really depend on whether GM_ADVANCED is set */
771 TextObj
->logfont
.elfEnumLogfontEx
.elfLogFont
.lfOrientation
=
772 TextObj
->logfont
.elfEnumLogfontEx
.elfLogFont
.lfEscapement
;
774 TEXTOBJ_UnlockText(TextObj
);
790 HFONT hOrgFont
= NULL
;
792 if (hDC
== NULL
|| hFont
== NULL
) return NULL
;
794 pDC
= DC_LockDc(hDC
);
800 pDc_Attr
= pDC
->pDc_Attr
;
801 if(!pDc_Attr
) pDc_Attr
= &pDC
->Dc_Attr
;
803 /* FIXME: what if not successful? */
804 if(NT_SUCCESS(TextIntRealizeFont((HFONT
)hFont
,NULL
)))
806 hOrgFont
= pDc_Attr
->hlfntNew
;
807 pDc_Attr
->hlfntNew
= hFont
;