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);
204 Status
= _SEH_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(pgsSafe
, Size
, 1);
296 RtlCopyMemory(pgs
, pgsSafe
, Size
);
300 Status
= _SEH_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
);
367 Status
= _SEH_GetExceptionCode();
371 ExFreePoolWithTag(pvBuf
, TAG_GDITEXT
);
378 ProbeForWrite(pgm
, sizeof(GLYPHMETRICS
), 1);
379 RtlCopyMemory(pgm
, &gm
, sizeof(GLYPHMETRICS
));
383 Status
= _SEH_GetExceptionCode();
388 if (! NT_SUCCESS(Status
))
390 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
401 NtGdiGetKerningPairs(HDC hDC
,
403 LPKERNINGPAIR krnpair
)
410 From "Undocumented Windows 2000 Secrets" Appendix B, Table B-2, page
411 472, this is NtGdiGetOutlineTextMetricsInternalW.
415 NtGdiGetOutlineTextMetricsInternalW (HDC hDC
,
417 OUTLINETEXTMETRICW
*otm
,
426 OUTLINETEXTMETRICW
*potm
;
432 SetLastWin32Error(ERROR_INVALID_HANDLE
);
435 Dc_Attr
= dc
->pDc_Attr
;
436 if(!Dc_Attr
) Dc_Attr
= &dc
->Dc_Attr
;
437 hFont
= Dc_Attr
->hlfntNew
;
438 TextObj
= RealizeFontInit(hFont
);
442 SetLastWin32Error(ERROR_INVALID_HANDLE
);
445 FontGDI
= ObjToGDI(TextObj
->Font
, FONT
);
446 TEXTOBJ_UnlockText(TextObj
);
447 Size
= IntGetOutlineTextMetrics(FontGDI
, 0, NULL
);
448 if (!otm
) return Size
;
451 SetLastWin32Error(ERROR_INSUFFICIENT_BUFFER
);
454 potm
= ExAllocatePoolWithTag(PagedPool
, Size
, TAG_GDITEXT
);
457 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
460 IntGetOutlineTextMetrics(FontGDI
, Size
, potm
);
463 Status
= MmCopyToCaller(otm
, potm
, Size
);
464 if (! NT_SUCCESS(Status
))
466 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
467 ExFreePoolWithTag(potm
,TAG_GDITEXT
);
471 ExFreePoolWithTag(potm
,TAG_GDITEXT
);
478 NtGdiGetFontResourceInfoInternalW(
483 OUT LPDWORD pdwBytes
,
487 NTSTATUS Status
= STATUS_SUCCESS
;
489 UNICODE_STRING SafeFileNames
;
496 WCHAR FullName
[LF_FULLFACESIZE
];
499 /* FIXME: handle cFiles > 0 */
501 /* Check for valid dwType values
502 dwType == 4 seems to be handled by gdi32 only */
503 if (dwType
== 4 || dwType
> 5)
505 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
509 /* Allocate a safe unicode string buffer */
510 cbStringSize
= cwc
* sizeof(WCHAR
);
511 SafeFileNames
.MaximumLength
= SafeFileNames
.Length
= cbStringSize
- sizeof(WCHAR
);
512 SafeFileNames
.Buffer
= ExAllocatePoolWithTag(PagedPool
,
514 TAG('R','T','S','U'));
515 if (!SafeFileNames
.Buffer
)
517 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY
);
521 /* Check buffers and copy pwszFiles to safe unicode string */
524 ProbeForRead(pwszFiles
, cbStringSize
, 1);
525 ProbeForWrite(pdwBytes
, sizeof(DWORD
), 1);
526 ProbeForWrite(pvBuf
, cjIn
, 1);
528 RtlCopyMemory(SafeFileNames
.Buffer
, pwszFiles
, cbStringSize
);
532 Status
= _SEH_GetExceptionCode();
536 if(!NT_SUCCESS(Status
))
538 SetLastNtError(Status
);
539 /* Free the string buffer for the safe filename */
540 ExFreePoolWithTag(SafeFileNames
.Buffer
,TAG('R','T','S','U'));
544 /* Do the actual call */
545 bRet
= IntGdiGetFontResourceInfo(&SafeFileNames
, &Buffer
, &dwBytes
, dwType
);
547 /* Check if succeeded and the buffer is big enough */
548 if (bRet
&& cjIn
>= dwBytes
)
550 /* Copy the data back to caller */
553 /* Buffers are already probed */
554 RtlCopyMemory(pvBuf
, &Buffer
, dwBytes
);
559 Status
= _SEH_GetExceptionCode();
563 if(!NT_SUCCESS(Status
))
565 SetLastNtError(Status
);
570 /* Free the string for the safe filenames */
571 ExFreePoolWithTag(SafeFileNames
.Buffer
,TAG('R','T','S','U'));
581 NtGdiGetRealizationInfo(
583 OUT PREALIZATION_INFO pri
,
594 pDc
= DC_LockDc(hdc
);
597 SetLastWin32Error(ERROR_INVALID_HANDLE
);
600 Dc_Attr
= pDc
->pDc_Attr
;
601 if(!Dc_Attr
) Dc_Attr
= &pDc
->Dc_Attr
;
602 pTextObj
= RealizeFontInit(Dc_Attr
->hlfntNew
);
603 pFontGdi
= ObjToGDI(pTextObj
->Font
, FONT
);
604 TEXTOBJ_UnlockText(pTextObj
);
607 Ret
= ftGdiRealizationInfo(pFontGdi
, &ri
);
612 NTSTATUS Status
= STATUS_SUCCESS
;
615 ProbeForWrite(pri
, sizeof(REALIZATION_INFO
), 1);
616 RtlCopyMemory(pri
, &ri
, sizeof(REALIZATION_INFO
));
620 Status
= _SEH_GetExceptionCode();
624 if(!NT_SUCCESS(Status
))
626 SetLastNtError(Status
);
632 if (GdiHandleTable
->cfPublic
[i
].hf
== hf
)
634 GdiHandleTable
->cfPublic
[i
].iTechnology
= ri
.iTechnology
;
635 GdiHandleTable
->cfPublic
[i
].iUniq
= ri
.iUniq
;
636 GdiHandleTable
->cfPublic
[i
].dwUnknown
= ri
.dwUnknown
;
637 GdiHandleTable
->cfPublic
[i
].dwCFCount
= GdiHandleTable
->dwCFCount
;
638 GdiHandleTable
->cfPublic
[i
].fl
|= CFONT_REALIZATION
;
642 while ( i
< GDI_CFONT_MAX
);
650 IN PENUMLOGFONTEXDVW pelfw
,
656 ENUMLOGFONTEXDVW SafeLogfont
;
659 NTSTATUS Status
= STATUS_SUCCESS
;
668 ProbeForRead(pelfw
, sizeof(ENUMLOGFONTEXDVW
), 1);
669 RtlCopyMemory(&SafeLogfont
, pelfw
, sizeof(ENUMLOGFONTEXDVW
));
673 Status
= _SEH_GetExceptionCode();
677 if (!NT_SUCCESS(Status
))
682 TextObj
= TEXTOBJ_AllocTextWithHandle();
687 hNewFont
= TextObj
->BaseObject
.hHmgr
;
691 RtlCopyMemory (&TextObj
->logfont
, &SafeLogfont
, sizeof(ENUMLOGFONTEXDVW
));
693 if (SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfEscapement
!=
694 SafeLogfont
.elfEnumLogfontEx
.elfLogFont
.lfOrientation
)
696 /* this should really depend on whether GM_ADVANCED is set */
697 TextObj
->logfont
.elfEnumLogfontEx
.elfLogFont
.lfOrientation
=
698 TextObj
->logfont
.elfEnumLogfontEx
.elfLogFont
.lfEscapement
;
700 TEXTOBJ_UnlockText(TextObj
);